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)) |
+ return false; |
} |
+ |
+ return true; |
} |