| Index: src/parser.cc
|
| diff --git a/src/parser.cc b/src/parser.cc
|
| index f0556cb35531f2e3feea74bf7a708356ccea6d73..1bab4a61797acd54807a10cd7baa9d15c4783e18 100644
|
| --- a/src/parser.cc
|
| +++ b/src/parser.cc
|
| @@ -1221,13 +1221,14 @@ Block* Parser::ParseModuleDeclaration(bool* ok) {
|
| // Create new block with one expected declaration.
|
| Block* block = factory()->NewBlock(NULL, 1, true);
|
| Handle<String> name = ParseIdentifier(CHECK_OK);
|
| - // top_scope_->AddDeclaration(
|
| - // factory()->NewModuleDeclaration(proxy, module, top_scope_));
|
| - VariableProxy* proxy = Declare(name, LET, NULL, true, CHECK_OK);
|
| - Module* module = ParseModule(ok);
|
| + Module* module = ParseModule(CHECK_OK);
|
| + VariableProxy* proxy = NewUnresolved(name, LET);
|
| + Declaration* declaration =
|
| + factory()->NewModuleDeclaration(proxy, module, top_scope_);
|
| + Declare(declaration, true, CHECK_OK);
|
| +
|
| // TODO(rossberg): Add initialization statement to block.
|
| - USE(proxy);
|
| - USE(module);
|
| +
|
| return block;
|
| }
|
|
|
| @@ -1497,21 +1498,22 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
|
| }
|
|
|
|
|
| -VariableProxy* Parser::Declare(Handle<String> name,
|
| - VariableMode mode,
|
| - FunctionLiteral* fun,
|
| - bool resolve,
|
| - bool* ok) {
|
| - Variable* var = NULL;
|
| +VariableProxy* Parser::NewUnresolved(Handle<String> name, VariableMode mode) {
|
| // 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.
|
| - Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
|
| - ? top_scope_ : top_scope_->DeclarationScope();
|
| - InitializationFlag init_flag = (fun != NULL || mode == VAR)
|
| - ? kCreatedInitialized : kNeedsInitialization;
|
| + return DeclarationScope(mode)->NewUnresolved(
|
| + factory(), name, scanner().location().beg_pos);
|
| +}
|
| +
|
| +
|
| +void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
|
| + Handle<String> name = declaration->proxy()->name();
|
| + VariableMode mode = declaration->mode();
|
| + Scope* declaration_scope = DeclarationScope(mode);
|
| + Variable* var = NULL;
|
|
|
| // If a function scope exists, then we can statically declare this
|
| // variable and also set its mode. In any case, a Declaration node
|
| @@ -1531,7 +1533,8 @@ VariableProxy* Parser::Declare(Handle<String> name,
|
| var = declaration_scope->LocalLookup(name);
|
| if (var == NULL) {
|
| // Declare the name.
|
| - var = declaration_scope->DeclareLocal(name, mode, init_flag);
|
| + var = declaration_scope->DeclareLocal(
|
| + name, mode, declaration->initialization());
|
| } else {
|
| // The name was declared in this scope before; check for conflicting
|
| // re-declarations. We have a conflict if either of the declarations is
|
| @@ -1558,7 +1561,7 @@ VariableProxy* Parser::Declare(Handle<String> name,
|
| Vector<const char*> args(elms, 2);
|
| ReportMessage("redeclaration", args);
|
| *ok = false;
|
| - return NULL;
|
| + return;
|
| }
|
| const char* type = (var->mode() == VAR)
|
| ? "var" : var->is_const_mode() ? "const" : "let";
|
| @@ -1588,10 +1591,7 @@ VariableProxy* Parser::Declare(Handle<String> name,
|
| // semantic issue as long as we keep the source order, but it may be
|
| // a performance issue since it may lead to repeated
|
| // Runtime::DeclareContextSlot() calls.
|
| - VariableProxy* proxy = declaration_scope->NewUnresolved(
|
| - factory(), name, scanner().location().beg_pos);
|
| - declaration_scope->AddDeclaration(
|
| - factory()->NewVariableDeclaration(proxy, mode, fun, top_scope_));
|
| + declaration_scope->AddDeclaration(declaration);
|
|
|
| if ((mode == CONST || mode == CONST_HARMONY) &&
|
| declaration_scope->is_global_scope()) {
|
| @@ -1615,7 +1615,7 @@ VariableProxy* Parser::Declare(Handle<String> name,
|
| mode,
|
| true,
|
| kind,
|
| - init_flag);
|
| + declaration->initialization());
|
| var->AllocateTo(Variable::LOOKUP, -1);
|
| resolve = true;
|
| }
|
| @@ -1644,9 +1644,7 @@ VariableProxy* Parser::Declare(Handle<String> name,
|
| // 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) proxy->BindTo(var);
|
| -
|
| - return proxy;
|
| + if (resolve && var != NULL) declaration->proxy()->BindTo(var);
|
| }
|
|
|
|
|
| @@ -1673,7 +1671,7 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
| // isn't lazily compiled. The extension structures are only
|
| // accessible while parsing the first time not when reparsing
|
| // because of lazy compilation.
|
| - top_scope_->DeclarationScope()->ForceEagerCompilation();
|
| + DeclarationScope(VAR)->ForceEagerCompilation();
|
|
|
| // Compute the function template for the native function.
|
| v8::Handle<v8::FunctionTemplate> fun_template =
|
| @@ -1698,12 +1696,15 @@ Statement* Parser::ParseNativeDeclaration(bool* ok) {
|
| // TODO(1240846): It's weird that native function declarations are
|
| // introduced dynamically when we meet their declarations, whereas
|
| // other functions are set up when entering the surrounding scope.
|
| + VariableProxy* proxy = NewUnresolved(name, VAR);
|
| + Declaration* declaration =
|
| + factory()->NewVariableDeclaration(proxy, VAR, top_scope_);
|
| + Declare(declaration, true, CHECK_OK);
|
| SharedFunctionInfoLiteral* lit =
|
| factory()->NewSharedFunctionInfoLiteral(shared);
|
| - VariableProxy* var = Declare(name, VAR, NULL, true, CHECK_OK);
|
| return factory()->NewExpressionStatement(
|
| factory()->NewAssignment(
|
| - Token::INIT_VAR, var, lit, RelocInfo::kNoPosition));
|
| + Token::INIT_VAR, proxy, lit, RelocInfo::kNoPosition));
|
| }
|
|
|
|
|
| @@ -1724,7 +1725,10 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) {
|
| // scope, we treat is as such and introduce the function with it's
|
| // initial value upon entering the corresponding scope.
|
| VariableMode mode = is_extended_mode() ? LET : VAR;
|
| - Declare(name, mode, fun, true, CHECK_OK);
|
| + VariableProxy* proxy = NewUnresolved(name, mode);
|
| + Declaration* declaration =
|
| + factory()->NewFunctionDeclaration(proxy, mode, fun, top_scope_);
|
| + Declare(declaration, true, CHECK_OK);
|
| return factory()->NewEmptyStatement();
|
| }
|
|
|
| @@ -1902,8 +1906,8 @@ Block* Parser::ParseVariableDeclarations(
|
| UNREACHABLE(); // by current callers
|
| }
|
|
|
| - Scope* declaration_scope = (mode == LET || mode == CONST_HARMONY)
|
| - ? top_scope_ : top_scope_->DeclarationScope();
|
| + Scope* declaration_scope = DeclarationScope(mode);
|
| +
|
| // The scope of a var/const declared variable anywhere inside a function
|
| // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
|
| // transform a source-level var/const declaration into a (Function)
|
| @@ -1950,7 +1954,10 @@ Block* Parser::ParseVariableDeclarations(
|
| // For let/const declarations in harmony mode, we can also immediately
|
| // pre-resolve the proxy because it resides in the same scope as the
|
| // declaration.
|
| - VariableProxy* proxy = Declare(name, mode, NULL, mode != VAR, CHECK_OK);
|
| + VariableProxy* proxy = NewUnresolved(name, mode);
|
| + Declaration* declaration =
|
| + factory()->NewVariableDeclaration(proxy, mode, top_scope_);
|
| + Declare(declaration, mode != VAR, CHECK_OK);
|
| nvars++;
|
| if (declaration_scope->num_var_or_const() > kMaxNumFunctionLocals) {
|
| ReportMessageAt(scanner().location(), "too_many_variables",
|
|
|