Index: src/parser.cc |
diff --git a/src/parser.cc b/src/parser.cc |
index 5f04cabee3d81c3cd2779c0584870bfc2dd67fab..a253854d6e4a054c55e3f427a3840594f6a1e861 100644 |
--- a/src/parser.cc |
+++ b/src/parser.cc |
@@ -757,6 +757,12 @@ void Parser::ReportMessage(const char* type, Vector<const char*> args) { |
} |
+void Parser::ReportMessage(const char* type, Vector<Handle<String> > args) { |
+ Scanner::Location source_location = scanner().location(); |
+ ReportMessageAt(source_location, type, args); |
+} |
+ |
+ |
void Parser::ReportMessageAt(Scanner::Location source_location, |
const char* type, |
Vector<const char*> args) { |
@@ -1163,6 +1169,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
this_property_assignment_finder.GetThisPropertyAssignments()); |
} |
} |
+ |
return 0; |
} |
@@ -1221,12 +1228,28 @@ Block* Parser::ParseModuleDeclaration(ZoneStringList* names, bool* ok) { |
// Create new block with one expected declaration. |
Block* block = factory()->NewBlock(NULL, 1, true); |
Handle<String> name = ParseIdentifier(CHECK_OK); |
+ |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Module %s...\n", name->ToAsciiArray()); |
+#endif |
+ |
Module* module = ParseModule(CHECK_OK); |
- VariableProxy* proxy = NewUnresolved(name, LET); |
+ VariableProxy* proxy = NewUnresolved(name, LET, module->interface()); |
Declaration* declaration = |
factory()->NewModuleDeclaration(proxy, module, top_scope_); |
Declare(declaration, true, CHECK_OK); |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Module %s.\n", name->ToAsciiArray()); |
+ |
+ if (FLAG_print_interfaces) { |
+ PrintF("module %s : ", name->ToAsciiArray()); |
+ module->interface()->Print(); |
+ } |
+#endif |
+ |
// TODO(rossberg): Add initialization statement to block. |
if (names) names->Add(name); |
@@ -1267,6 +1290,9 @@ Module* Parser::ParseModuleLiteral(bool* ok) { |
// Construct block expecting 16 statements. |
Block* body = factory()->NewBlock(NULL, 16, false); |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) PrintF("# Literal "); |
+#endif |
Scope* scope = NewScope(top_scope_, MODULE_SCOPE); |
Expect(Token::LBRACE, CHECK_OK); |
@@ -1292,7 +1318,10 @@ Module* Parser::ParseModuleLiteral(bool* ok) { |
Expect(Token::RBRACE, CHECK_OK); |
scope->set_end_position(scanner().location().end_pos); |
body->set_block_scope(scope); |
- return factory()->NewModuleLiteral(body); |
+ |
+ scope->interface()->Freeze(ok); |
+ ASSERT(ok); |
+ return factory()->NewModuleLiteral(body, scope->interface()); |
} |
@@ -1302,10 +1331,28 @@ Module* Parser::ParseModulePath(bool* ok) { |
// ModulePath '.' Identifier |
Module* result = ParseModuleVariable(CHECK_OK); |
- |
while (Check(Token::PERIOD)) { |
Handle<String> name = ParseIdentifierName(CHECK_OK); |
- result = factory()->NewModulePath(result, name); |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Path .%s ", name->ToAsciiArray()); |
+#endif |
+ Module* member = factory()->NewModulePath(result, name); |
+ result->interface()->Add(name, member->interface(), ok); |
+ if (!*ok) { |
+#ifdef DEBUG |
+ if (FLAG_print_interfaces) { |
+ PrintF("PATH TYPE ERROR at '%s'\n", name->ToAsciiArray()); |
+ PrintF("result: "); |
+ result->interface()->Print(); |
+ PrintF("member: "); |
+ member->interface()->Print(); |
+ } |
+#endif |
+ ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1)); |
+ return NULL; |
+ } |
+ result = member; |
} |
return result; |
@@ -1317,8 +1364,13 @@ Module* Parser::ParseModuleVariable(bool* ok) { |
// Identifier |
Handle<String> name = ParseIdentifier(CHECK_OK); |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Module variable %s ", name->ToAsciiArray()); |
+#endif |
VariableProxy* proxy = top_scope_->NewUnresolved( |
- factory(), name, scanner().location().beg_pos); |
+ factory(), name, scanner().location().beg_pos, Interface::NewModule()); |
+ |
return factory()->NewModuleVariable(proxy); |
} |
@@ -1330,6 +1382,11 @@ Module* Parser::ParseModuleUrl(bool* ok) { |
Expect(Token::STRING, CHECK_OK); |
Handle<String> symbol = GetSymbol(CHECK_OK); |
+ // TODO(ES6): Request JS resource from environment... |
+ |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) PrintF("# Url "); |
+#endif |
return factory()->NewModuleUrl(symbol); |
} |
@@ -1357,6 +1414,7 @@ Block* Parser::ParseImportDeclaration(bool* ok) { |
ZoneStringList names(1); |
Handle<String> name = ParseIdentifierName(CHECK_OK); |
+ names.Add(name); |
while (peek() == Token::COMMA) { |
Consume(Token::COMMA); |
name = ParseIdentifierName(CHECK_OK); |
@@ -1371,14 +1429,30 @@ Block* Parser::ParseImportDeclaration(bool* ok) { |
// TODO(ES6): once we implement destructuring, make that one declaration. |
Block* block = factory()->NewBlock(NULL, 1, true); |
for (int i = 0; i < names.length(); ++i) { |
- VariableProxy* proxy = NewUnresolved(names[i], LET); |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Import %s ", names[i]->ToAsciiArray()); |
+#endif |
+ Interface* interface = Interface::NewUnknown(); |
+ module->interface()->Add(names[i], interface, ok); |
+ if (!*ok) { |
+#ifdef DEBUG |
+ if (FLAG_print_interfaces) { |
+ PrintF("IMPORT TYPE ERROR at '%s'\n", names[i]->ToAsciiArray()); |
+ PrintF("module: "); |
+ module->interface()->Print(); |
+ } |
+#endif |
+ ReportMessage("invalid_module_path", Vector<Handle<String> >(&name, 1)); |
+ return NULL; |
+ } |
+ VariableProxy* proxy = NewUnresolved(names[i], LET, interface); |
Declaration* declaration = |
factory()->NewImportDeclaration(proxy, module, top_scope_); |
Declare(declaration, true, CHECK_OK); |
// TODO(rossberg): Add initialization statement to block. |
} |
- |
return block; |
} |
@@ -1431,12 +1505,22 @@ Statement* Parser::ParseExportDeclaration(bool* ok) { |
return NULL; |
} |
- // Extract declared names into export declarations. |
+ // Extract declared names into export declarations and interface. |
+ Interface* interface = top_scope_->interface(); |
for (int i = 0; i < names.length(); ++i) { |
- VariableProxy* proxy = NewUnresolved(names[i], LET); |
- Declaration* declaration = |
- factory()->NewExportDeclaration(proxy, top_scope_); |
- top_scope_->AddDeclaration(declaration); |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Export %s ", names[i]->ToAsciiArray()); |
+#endif |
+ Interface* inner = Interface::NewUnknown(); |
+ interface->Add(names[i], inner, CHECK_OK); |
+ VariableProxy* proxy = NewUnresolved(names[i], LET, inner); |
+ USE(proxy); |
+ // TODO(rossberg): Rethink whether we actually need to store export |
+ // declarations (for compilation?). |
+ // ExportDeclaration* declaration = |
+ // factory()->NewExportDeclaration(proxy, top_scope_); |
+ // top_scope_->AddDeclaration(declaration); |
} |
ASSERT(result != NULL); |
@@ -1597,19 +1681,21 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) { |
} |
-VariableProxy* Parser::NewUnresolved(Handle<String> name, VariableMode mode) { |
+VariableProxy* Parser::NewUnresolved( |
+ Handle<String> name, VariableMode mode, Interface* interface) { |
// If we are inside a function, a declaration of a var/const variable is a |
// truly local variable, and the scope of the variable is always the function |
// scope. |
// Let/const variables in harmony mode are always added to the immediately |
// enclosing scope. |
return DeclarationScope(mode)->NewUnresolved( |
- factory(), name, scanner().location().beg_pos); |
+ factory(), name, scanner().location().beg_pos, interface); |
} |
void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
- Handle<String> name = declaration->proxy()->name(); |
+ VariableProxy* proxy = declaration->proxy(); |
+ Handle<String> name = proxy->name(); |
VariableMode mode = declaration->mode(); |
Scope* declaration_scope = DeclarationScope(mode); |
Variable* var = NULL; |
@@ -1627,13 +1713,14 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
if (declaration_scope->is_function_scope() || |
declaration_scope->is_strict_or_extended_eval_scope() || |
declaration_scope->is_block_scope() || |
- declaration_scope->is_module_scope()) { |
+ declaration_scope->is_module_scope() || |
+ declaration->AsModuleDeclaration() != NULL) { |
// Declare the variable in the function scope. |
var = declaration_scope->LocalLookup(name); |
if (var == NULL) { |
// Declare the name. |
var = declaration_scope->DeclareLocal( |
- name, mode, declaration->initialization()); |
+ name, mode, declaration->initialization(), proxy->interface()); |
} else { |
// The name was declared in this scope before; check for conflicting |
// re-declarations. We have a conflict if either of the declarations is |
@@ -1743,7 +1830,30 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) { |
// initialization code. Thus, inside the 'with' statement, we need |
// both access to the static and the dynamic context chain; the |
// runtime needs to provide both. |
- if (resolve && var != NULL) declaration->proxy()->BindTo(var); |
+ if (resolve && var != NULL) { |
+ proxy->BindTo(var); |
+ |
+ if (FLAG_harmony_modules) { |
+ bool ok; |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Declare %s\n", var->name()->ToAsciiArray()); |
+#endif |
+ proxy->interface()->Unify(var->interface(), &ok); |
+ if (!ok) { |
+#ifdef DEBUG |
+ if (FLAG_print_interfaces) { |
+ PrintF("DECLARE TYPE ERROR\n"); |
+ PrintF("proxy: "); |
+ proxy->interface()->Print(); |
+ PrintF("var: "); |
+ var->interface()->Print(); |
+ } |
+#endif |
+ ReportMessage("module_type_error", Vector<Handle<String> >(&name, 1)); |
+ } |
+ } |
+ } |
} |
@@ -3498,8 +3608,14 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) { |
case Token::FUTURE_STRICT_RESERVED_WORD: { |
Handle<String> name = ParseIdentifier(CHECK_OK); |
if (fni_ != NULL) fni_->PushVariableName(name); |
+ // The name may refer to a module instance object, so its type is unknown. |
+#ifdef DEBUG |
+ if (FLAG_print_interface_details) |
+ PrintF("# Variable %s ", name->ToAsciiArray()); |
+#endif |
+ Interface* interface = Interface::NewUnknown(); |
result = top_scope_->NewUnresolved( |
- factory(), name, scanner().location().beg_pos); |
+ factory(), name, scanner().location().beg_pos, interface); |
break; |
} |