Chromium Code Reviews| Index: src/scopes.cc |
| diff --git a/src/scopes.cc b/src/scopes.cc |
| index 8d71f8ae858d8b44937bea0e25dc69b379a60f7f..766e1ae5cccc7c5e42512cdaccdf2f634b1ca0aa 100644 |
| --- a/src/scopes.cc |
| +++ b/src/scopes.cc |
| @@ -67,7 +67,8 @@ Variable* VariableMap::Declare( |
| VariableMode mode, |
| bool is_valid_lhs, |
| Variable::Kind kind, |
| - InitializationFlag initialization_flag) { |
| + InitializationFlag initialization_flag, |
| + Interface* interface) { |
| Entry* p = ZoneHashMap::Lookup(name.location(), name->Hash(), true); |
| if (p->value == NULL) { |
| // The variable has not been declared yet -> insert it. |
| @@ -77,7 +78,8 @@ Variable* VariableMap::Declare( |
| mode, |
| is_valid_lhs, |
| kind, |
| - initialization_flag); |
| + initialization_flag, |
| + interface); |
| } |
| return reinterpret_cast<Variable*>(p->value); |
| } |
| @@ -105,6 +107,9 @@ Scope::Scope(Scope* outer_scope, ScopeType type) |
| params_(4), |
| unresolved_(16), |
| decls_(4), |
| + interface_(FLAG_harmony_modules && |
| + (type == MODULE_SCOPE || type == GLOBAL_SCOPE) |
| + ? Interface::NewModule() : NULL), |
| already_resolved_(false) { |
| SetDefaults(type, outer_scope, Handle<ScopeInfo>::null()); |
| // At some point we might want to provide outer scopes to |
| @@ -125,6 +130,7 @@ Scope::Scope(Scope* inner_scope, |
| params_(4), |
| unresolved_(16), |
| decls_(4), |
| + interface_(NULL), |
| already_resolved_(true) { |
| SetDefaults(type, NULL, scope_info); |
| if (!scope_info.is_null()) { |
| @@ -145,6 +151,7 @@ Scope::Scope(Scope* inner_scope, Handle<String> catch_variable_name) |
| params_(0), |
| unresolved_(0), |
| decls_(0), |
| + interface_(NULL), |
| already_resolved_(true) { |
| SetDefaults(CATCH_SCOPE, NULL, Handle<ScopeInfo>::null()); |
| AddInnerScope(inner_scope); |
| @@ -255,7 +262,7 @@ bool Scope::Analyze(CompilationInfo* info) { |
| // Allocate the variables. |
| { |
| AstNodeFactory<AstNullVisitor> ast_node_factory(info->isolate()); |
| - top->AllocateVariables(info->global_scope(), &ast_node_factory); |
| + if (!top->AllocateVariables(info, &ast_node_factory)) return false; |
| } |
| #ifdef DEBUG |
| @@ -264,6 +271,11 @@ bool Scope::Analyze(CompilationInfo* info) { |
| : FLAG_print_scopes) { |
| scope->Print(); |
| } |
| + |
| + if (FLAG_harmony_modules && FLAG_print_interfaces && top->is_global_scope()) { |
| + PrintF("global : "); |
| + top->interface()->Print(); |
| + } |
| #endif |
| if (FLAG_harmony_scoping) { |
| @@ -438,7 +450,8 @@ void Scope::DeclareParameter(Handle<String> name, VariableMode mode) { |
| Variable* Scope::DeclareLocal(Handle<String> name, |
| VariableMode mode, |
| - InitializationFlag init_flag) { |
| + InitializationFlag init_flag, |
| + Interface* interface) { |
| ASSERT(!already_resolved()); |
| // This function handles VAR and CONST modes. DYNAMIC variables are |
| // introduces during variable allocation, INTERNAL variables are allocated |
| @@ -448,8 +461,8 @@ Variable* Scope::DeclareLocal(Handle<String> name, |
| mode == CONST_HARMONY || |
| mode == LET); |
| ++num_var_or_const_; |
| - return |
| - variables_.Declare(this, name, mode, true, Variable::NORMAL, init_flag); |
| + return variables_.Declare( |
| + this, name, mode, true, Variable::NORMAL, init_flag, interface); |
| } |
| @@ -586,7 +599,7 @@ void Scope::CollectStackAndContextLocals(ZoneList<Variable*>* stack_locals, |
| } |
| -void Scope::AllocateVariables(Scope* global_scope, |
| +bool Scope::AllocateVariables(CompilationInfo* info, |
| AstNodeFactory<AstNullVisitor>* factory) { |
| // 1) Propagate scope information. |
| bool outer_scope_calls_non_strict_eval = false; |
| @@ -598,10 +611,12 @@ void Scope::AllocateVariables(Scope* global_scope, |
| PropagateScopeInfo(outer_scope_calls_non_strict_eval); |
| // 2) Resolve variables. |
| - ResolveVariablesRecursively(global_scope, factory); |
| + if (!ResolveVariablesRecursively(info, factory)) return false; |
| // 3) Allocate variables. |
| AllocateVariablesRecursively(); |
| + |
| + return true; |
| } |
| @@ -916,14 +931,14 @@ Variable* Scope::LookupRecursive(Handle<String> name, |
| } |
| -void Scope::ResolveVariable(Scope* global_scope, |
| +bool Scope::ResolveVariable(CompilationInfo* info, |
| VariableProxy* proxy, |
| AstNodeFactory<AstNullVisitor>* factory) { |
| - ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| + ASSERT(info->global_scope()->is_global_scope()); |
| // If the proxy is already resolved there's nothing to do |
| // (functions and consts may be resolved by the parser). |
| - if (proxy->var() != NULL) return; |
| + if (proxy->var() != NULL) return true; |
| // Otherwise, try to resolve the variable. |
| BindingKind binding_kind; |
| @@ -947,8 +962,7 @@ void Scope::ResolveVariable(Scope* global_scope, |
| case UNBOUND: |
| // No binding has been found. Declare a variable in global scope. |
| - ASSERT(global_scope != NULL); |
| - var = global_scope->DeclareGlobal(proxy->name()); |
| + var = info->global_scope()->DeclareGlobal(proxy->name()); |
| break; |
| case UNBOUND_EVAL_SHADOWED: |
| @@ -965,23 +979,62 @@ void Scope::ResolveVariable(Scope* global_scope, |
| ASSERT(var != NULL); |
| proxy->BindTo(var); |
| + |
| + if (FLAG_harmony_modules) { |
| + bool ok; |
| +#ifdef DEBUG |
| + if (FLAG_print_interface_details) |
| + PrintF("# Resolve %s:\n", var->name()->ToAsciiArray()); |
| +#endif |
| + proxy->interface()->Unify(var->interface(), &ok); |
| + if (!ok) { |
| +#ifdef DEBUG |
| + if (FLAG_print_interfaces) { |
| + PrintF("SCOPES TYPE ERROR\n"); |
| + PrintF("proxy: "); |
| + proxy->interface()->Print(); |
| + PrintF("var: "); |
| + var->interface()->Print(); |
| + } |
| +#endif |
| + |
| + // Inconsistent use of module. Throw a syntax error. |
| + // TODO(rossberg): generate more helpful error message. |
| + MessageLocation location(info->script(), |
| + proxy->position(), |
| + proxy->position()); |
| + Isolate* isolate = Isolate::Current(); |
| + Factory* factory = isolate->factory(); |
| + Handle<JSArray> array = factory->NewJSArray(1); |
| + array->SetElement(array, 0, var->name(), NONE, kStrictMode); |
| + Handle<Object> result = |
| + factory->NewSyntaxError("module_type_error", array); |
| + isolate->Throw(*result, &location); |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| } |
| -void Scope::ResolveVariablesRecursively( |
| - Scope* global_scope, |
| +bool Scope::ResolveVariablesRecursively( |
| + CompilationInfo* info, |
| AstNodeFactory<AstNullVisitor>* factory) { |
| - ASSERT(global_scope == NULL || global_scope->is_global_scope()); |
| + ASSERT(info->global_scope()->is_global_scope()); |
| // Resolve unresolved variables for this scope. |
| for (int i = 0; i < unresolved_.length(); i++) { |
| - ResolveVariable(global_scope, unresolved_[i], factory); |
| + if (!ResolveVariable(info, unresolved_[i], factory)) return false; |
| } |
| // Resolve unresolved variables for inner scopes. |
| for (int i = 0; i < inner_scopes_.length(); i++) { |
| - inner_scopes_[i]->ResolveVariablesRecursively(global_scope, factory); |
| + if (!inner_scopes_[i]->ResolveVariablesRecursively(info, factory)) |
|
Sven Panne
2012/03/08 08:55:00
I know that this recursive call has been there bef
rossberg
2012/03/08 10:47:06
See my respective comment in interface.cc.
|
| + return false; |
| } |
| + |
| + return true; |
| } |