Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(982)

Unified Diff: src/parser.cc

Issue 7616009: Parse harmony let declarations. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 1167f43df519321d34a8a7efad9e085b2af7e548..6886340ef5f8b5612eb92575c6be7e2773d9f93a 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -1093,6 +1093,25 @@ class ThisNamedPropertyAssigmentFinder : public ParserFinder {
};
+Statement* Parser::ParseSourceElement(ZoneStringList* labels,
+ bool* ok) {
+ if (peek() == Token::FUNCTION) {
+ // FunctionDeclaration is only allowed in the context of SourceElements
+ // (Ecma 262 5th Edition, clause 14):
+ // SourceElement:
+ // Statement
+ // FunctionDeclaration
+ // Common language extension is to allow function declaration in place
+ // of any statement. This language extension is disabled in strict mode.
+ return ParseFunctionDeclaration(ok);
+ } else if (peek() == Token::LET && harmony_block_scoping_) {
+ return ParseVariableStatement(true, ok);
Lasse Reichstein 2011/08/12 08:08:33 Please use an enum with meaningful names for the f
Steven 2011/08/16 09:05:32 Done. See the VariableDeclarationContext enum. Als
+ } else {
+ return ParseStatement(labels, ok);
+ }
+}
+
+
void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
int end_token,
bool* ok) {
@@ -1116,21 +1135,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
}
Scanner::Location token_loc = scanner().peek_location();
-
- Statement* stat;
- if (peek() == Token::FUNCTION) {
- // FunctionDeclaration is only allowed in the context of SourceElements
- // (Ecma 262 5th Edition, clause 14):
- // SourceElement:
- // Statement
- // FunctionDeclaration
- // Common language extension is to allow function declaration in place
- // of any statement. This language extension is disabled in strict mode.
- stat = ParseFunctionDeclaration(CHECK_OK);
- } else {
- stat = ParseStatement(NULL, CHECK_OK);
- }
-
+ Statement* stat = ParseSourceElement(NULL, CHECK_OK);
if (stat == NULL || stat->IsEmpty()) {
directive_prologue = false; // End of directive prologue.
continue;
@@ -1218,7 +1223,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
case Token::CONST: // fall through
case Token::VAR:
- stmt = ParseVariableStatement(ok);
+ stmt = ParseVariableStatement(false, ok);
break;
case Token::SEMICOLON:
@@ -1325,24 +1330,28 @@ VariableProxy* Parser::Declare(Handle<String> name,
// to the calling function context.
// Similarly, strict mode eval scope does not leak variable declarations to
// the caller's scope so we declare all locals, too.
- Scope* declaration_scope = top_scope_->DeclarationScope();
+
+ Scope* declaration_scope = mode == Variable::LET ? top_scope_
+ : top_scope_->DeclarationScope();
if (declaration_scope->is_function_scope() ||
- declaration_scope->is_strict_mode_eval_scope()) {
+ declaration_scope->is_strict_mode_eval_scope() ||
+ declaration_scope->is_block_scope()) {
// Declare the variable in the function scope.
var = declaration_scope->LocalLookup(name);
if (var == NULL) {
// Declare the name.
var = declaration_scope->DeclareLocal(name, mode);
} else {
- // The name was declared before; check for conflicting
- // re-declarations. If the previous declaration was a const or the
- // current declaration is a const then we have a conflict. There is
- // similar code in runtime.cc in the Declare functions.
- if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) {
- // We only have vars and consts in declarations.
+ // The name was declared before; check for conflicting re-declarations.
+ // We have a conflict if either of the declarations is not a var. There
+ // is similar code in runtime.cc in the Declare functions.
+ if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) {
+ // We only have vars, consts and lets in declarations.
ASSERT(var->mode() == Variable::VAR ||
- var->mode() == Variable::CONST);
- const char* type = (var->mode() == Variable::VAR) ? "var" : "const";
+ var->mode() == Variable::CONST ||
+ var->mode() == Variable::LET);
+ const char* type = (var->mode() == Variable::VAR) ? "var" :
+ (var->mode() == Variable::CONST) ? "const" : "let";
Handle<String> type_string =
isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
Expression* expression =
@@ -1485,7 +1494,8 @@ Statement* Parser::ParseFunctionDeclaration(bool* ok) {
// Even if we're not at the top-level of the global or a function
// scope, we treat is as such and introduce the function with it's
// initial value upon entering the corresponding scope.
- Declare(name, Variable::VAR, fun, true, CHECK_OK);
+ Variable::Mode mode = harmony_block_scoping_ ? Variable::LET : Variable::VAR;
+ Declare(name, mode, fun, true, CHECK_OK);
return EmptyStatement();
}
@@ -1540,7 +1550,7 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
InitializationBlockFinder block_finder(top_scope_, target_stack_);
while (peek() != Token::RBRACE) {
- Statement* stat = ParseStatement(NULL, CHECK_OK);
+ Statement* stat = ParseSourceElement(NULL, CHECK_OK);
Lasse Reichstein 2011/08/12 08:08:33 Will this enable function declarations inside bloc
Steven 2011/08/16 09:05:32 The proposal allows local function declarations in
if (stat && !stat->IsEmpty()) {
body->AddStatement(stat);
block_finder.Update(stat);
@@ -1566,12 +1576,13 @@ Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) {
}
-Block* Parser::ParseVariableStatement(bool* ok) {
+Block* Parser::ParseVariableStatement(bool accept_LET, bool* ok) {
// VariableStatement ::
// VariableDeclarations ';'
Handle<String> ignore;
- Block* result = ParseVariableDeclarations(true, &ignore, CHECK_OK);
+ Block* result = ParseVariableDeclarations(accept_LET, true,
+ &ignore, CHECK_OK);
ExpectSemicolon(CHECK_OK);
return result;
}
@@ -1588,7 +1599,8 @@ bool Parser::IsEvalOrArguments(Handle<String> string) {
// *var is untouched; in particular, it is the caller's responsibility
// to initialize it properly. This mechanism is used for the parsing
// of 'for-in' loops.
-Block* Parser::ParseVariableDeclarations(bool accept_IN,
+Block* Parser::ParseVariableDeclarations(bool accept_LET,
+ bool accept_IN,
Handle<String>* out,
bool* ok) {
// VariableDeclarations ::
@@ -1608,6 +1620,14 @@ Block* Parser::ParseVariableDeclarations(bool accept_IN,
}
mode = Variable::CONST;
is_const = true;
+ } else if (peek() == Token::LET) {
+ Consume(Token::LET);
+ if (!accept_LET) {
+ ReportMessage("unprotected_let", Vector<const char*>::empty());
+ *ok = false;
+ return NULL;
+ }
+ mode = Variable::LET;
} else {
UNREACHABLE(); // by current callers
}
@@ -2346,7 +2366,7 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
if (peek() == Token::VAR || peek() == Token::CONST) {
Handle<String> name;
Block* variable_statement =
- ParseVariableDeclarations(false, &name, CHECK_OK);
+ ParseVariableDeclarations(true, false, &name, CHECK_OK);
if (peek() == Token::IN && !name.is_null()) {
VariableProxy* each = top_scope_->NewUnresolved(name, inside_with());
@@ -2993,6 +3013,14 @@ void Parser::ReportUnexpectedToken(Token::Value token) {
case Token::FUTURE_RESERVED_WORD:
return ReportMessage("unexpected_reserved",
Vector<const char*>::empty());
+ case Token::LET:
+ if (harmony_block_scoping_) {
+ const char* name = Token::String(token);
+ ASSERT(name != NULL);
+ return ReportMessage("unexpected_token",
+ Vector<const char*>(&name, 1));
+ }
+ // FALLTHROUGH
case Token::FUTURE_STRICT_RESERVED_WORD:
return ReportMessage(top_scope_->is_strict_mode() ?
"unexpected_strict_reserved" :
@@ -3055,6 +3083,14 @@ Expression* Parser::ParsePrimaryExpression(bool* ok) {
isolate(), isolate()->factory()->false_value());
break;
+ case Token::LET:
+ if (harmony_block_scoping_) {
+ Token::Value tok = Next();
+ ReportUnexpectedToken(tok);
+ *ok = false;
+ return NULL;
+ }
+ // FALLTHROUGH
case Token::IDENTIFIER:
case Token::FUTURE_STRICT_RESERVED_WORD: {
Handle<String> name = ParseIdentifier(CHECK_OK);
@@ -3519,6 +3555,12 @@ Expression* Parser::ParseObjectLiteral(bool* ok) {
// Location of the property name token
Scanner::Location loc = scanner().peek_location();
+ if (harmony_block_scoping_ && next == Token::LET) {
+ // Go into FUTURE_STRICT_RESERVED_WORD case where
+ // ParseIdentifierNameOrGetOrSet will handle the LET
+ // token like a FUTURE_STRICT_RESERVED_WORD.
+ next = Token::FUTURE_STRICT_RESERVED_WORD;
Lasse Reichstein 2011/08/12 08:08:33 Why not just add a case for Token::LET next to Tok
Steven 2011/08/16 09:05:32 Now obsolete, since the scanner now produces the c
+ }
switch (next) {
case Token::FUTURE_RESERVED_WORD:
case Token::FUTURE_STRICT_RESERVED_WORD:
@@ -3706,7 +3748,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(Handle<String> function_name,
int num_parameters = 0;
// Function declarations are hoisted.
- Scope* scope = (type == FunctionLiteral::DECLARATION)
+ Scope* scope = (type == FunctionLiteral::DECLARATION &&
+ !harmony_block_scoping_)
Lasse Reichstein 2011/08/12 08:08:33 If harmony_block_scoping_ is set, function declara
Steven 2011/08/16 09:05:32 Yes, function declarations are then also expected
? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false)
: NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8);
@@ -3946,7 +3989,8 @@ bool Parser::peek_any_identifier() {
Token::Value next = peek();
return next == Token::IDENTIFIER ||
next == Token::FUTURE_RESERVED_WORD ||
- next == Token::FUTURE_STRICT_RESERVED_WORD;
+ next == Token::FUTURE_STRICT_RESERVED_WORD ||
+ (next == Token::LET && !harmony_block_scoping_);
}
@@ -4014,7 +4058,11 @@ Handle<String> Parser::ParseIdentifier(bool* ok) {
if (top_scope_->is_strict_mode()) {
Expect(Token::IDENTIFIER, ok);
} else if (!Check(Token::IDENTIFIER)) {
- Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
+ if (harmony_block_scoping_) {
+ Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
+ } else if (!Check(Token::FUTURE_STRICT_RESERVED_WORD)) {
+ Expect(Token::LET, ok);
+ }
}
if (!*ok) return Handle<String>();
return GetSymbol(ok);
@@ -4027,7 +4075,11 @@ Handle<String> Parser::ParseIdentifierOrStrictReservedWord(
bool* is_strict_reserved, bool* ok) {
*is_strict_reserved = false;
if (!Check(Token::IDENTIFIER)) {
- Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
+ if (harmony_block_scoping_) {
+ Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok);
+ } else if (!Check(Token::FUTURE_STRICT_RESERVED_WORD)) {
+ Expect(Token::LET, ok);
+ }
*is_strict_reserved = true;
}
if (!*ok) return Handle<String>();

Powered by Google App Engine
This is Rietveld 408576698