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

Side by Side Diff: src/parser.cc

Issue 378303003: Make `let` usable as an identifier in ES6 sloppy mode. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Comments Created 6 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/messages.js ('k') | src/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/base/platform/platform.h" 9 #include "src/base/platform/platform.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 1140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1151 // LetDeclaration 1151 // LetDeclaration
1152 // ConstDeclaration 1152 // ConstDeclaration
1153 // ModuleDeclaration 1153 // ModuleDeclaration
1154 // ImportDeclaration 1154 // ImportDeclaration
1155 // ExportDeclaration 1155 // ExportDeclaration
1156 // GeneratorDeclaration 1156 // GeneratorDeclaration
1157 1157
1158 switch (peek()) { 1158 switch (peek()) {
1159 case Token::FUNCTION: 1159 case Token::FUNCTION:
1160 return ParseFunctionDeclaration(NULL, ok); 1160 return ParseFunctionDeclaration(NULL, ok);
1161 case Token::LET:
1162 case Token::CONST:
1163 return ParseVariableStatement(kModuleElement, NULL, ok);
1164 case Token::IMPORT: 1161 case Token::IMPORT:
1165 return ParseImportDeclaration(ok); 1162 return ParseImportDeclaration(ok);
1166 case Token::EXPORT: 1163 case Token::EXPORT:
1167 return ParseExportDeclaration(ok); 1164 return ParseExportDeclaration(ok);
1165 case Token::CONST:
1166 return ParseVariableStatement(kModuleElement, NULL, ok);
1167 case Token::LET:
1168 ASSERT(allow_harmony_scoping());
1169 if (strict_mode() == STRICT) {
1170 return ParseVariableStatement(kModuleElement, NULL, ok);
1171 }
1172 // Fall through.
1168 default: { 1173 default: {
1169 Statement* stmt = ParseStatement(labels, CHECK_OK); 1174 Statement* stmt = ParseStatement(labels, CHECK_OK);
1170 // Handle 'module' as a context-sensitive keyword. 1175 // Handle 'module' as a context-sensitive keyword.
1171 if (FLAG_harmony_modules && 1176 if (FLAG_harmony_modules &&
1172 peek() == Token::IDENTIFIER && 1177 peek() == Token::IDENTIFIER &&
1173 !scanner()->HasAnyLineTerminatorBeforeNext() && 1178 !scanner()->HasAnyLineTerminatorBeforeNext() &&
1174 stmt != NULL) { 1179 stmt != NULL) {
1175 ExpressionStatement* estmt = stmt->AsExpressionStatement(); 1180 ExpressionStatement* estmt = stmt->AsExpressionStatement();
1176 if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL && 1181 if (estmt != NULL && estmt->expression()->AsVariableProxy() != NULL &&
1177 estmt->expression()->AsVariableProxy()->raw_name() == 1182 estmt->expression()->AsVariableProxy()->raw_name() ==
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after
1456 Statement* Parser::ParseExportDeclaration(bool* ok) { 1461 Statement* Parser::ParseExportDeclaration(bool* ok) {
1457 // ExportDeclaration: 1462 // ExportDeclaration:
1458 // 'export' Identifier (',' Identifier)* ';' 1463 // 'export' Identifier (',' Identifier)* ';'
1459 // 'export' VariableDeclaration 1464 // 'export' VariableDeclaration
1460 // 'export' FunctionDeclaration 1465 // 'export' FunctionDeclaration
1461 // 'export' GeneratorDeclaration 1466 // 'export' GeneratorDeclaration
1462 // 'export' ModuleDeclaration 1467 // 'export' ModuleDeclaration
1463 // 1468 //
1464 // TODO(ES6): implement structuring ExportSpecifiers 1469 // TODO(ES6): implement structuring ExportSpecifiers
1465 1470
1471 ASSERT(strict_mode() == STRICT);
1472
1466 Expect(Token::EXPORT, CHECK_OK); 1473 Expect(Token::EXPORT, CHECK_OK);
1467 1474
1468 Statement* result = NULL; 1475 Statement* result = NULL;
1469 ZoneList<const AstRawString*> names(1, zone()); 1476 ZoneList<const AstRawString*> names(1, zone());
1470 switch (peek()) { 1477 switch (peek()) {
1471 case Token::IDENTIFIER: { 1478 case Token::IDENTIFIER: {
1472 int pos = position(); 1479 int pos = position();
1473 const AstRawString* name = 1480 const AstRawString* name =
1474 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK); 1481 ParseIdentifier(kDontAllowEvalOrArguments, CHECK_OK);
1475 // Handle 'module' as a context-sensitive keyword. 1482 // Handle 'module' as a context-sensitive keyword.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1538 // 1545 //
1539 // In harmony mode we allow additionally the following productions 1546 // In harmony mode we allow additionally the following productions
1540 // BlockElement (aka SourceElement): 1547 // BlockElement (aka SourceElement):
1541 // LetDeclaration 1548 // LetDeclaration
1542 // ConstDeclaration 1549 // ConstDeclaration
1543 // GeneratorDeclaration 1550 // GeneratorDeclaration
1544 1551
1545 switch (peek()) { 1552 switch (peek()) {
1546 case Token::FUNCTION: 1553 case Token::FUNCTION:
1547 return ParseFunctionDeclaration(NULL, ok); 1554 return ParseFunctionDeclaration(NULL, ok);
1548 case Token::LET:
1549 case Token::CONST: 1555 case Token::CONST:
1550 return ParseVariableStatement(kModuleElement, NULL, ok); 1556 return ParseVariableStatement(kModuleElement, NULL, ok);
1557 case Token::LET:
1558 ASSERT(allow_harmony_scoping());
1559 if (strict_mode() == STRICT) {
1560 return ParseVariableStatement(kModuleElement, NULL, ok);
1561 }
1562 // Fall through.
1551 default: 1563 default:
1552 return ParseStatement(labels, ok); 1564 return ParseStatement(labels, ok);
1553 } 1565 }
1554 } 1566 }
1555 1567
1556 1568
1557 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels, 1569 Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
1558 bool* ok) { 1570 bool* ok) {
1559 // Statement :: 1571 // Statement ::
1560 // Block 1572 // Block
(...skipping 15 matching lines...) Expand all
1576 // Note: Since labels can only be used by 'break' and 'continue' 1588 // Note: Since labels can only be used by 'break' and 'continue'
1577 // statements, which themselves are only valid within blocks, 1589 // statements, which themselves are only valid within blocks,
1578 // iterations or 'switch' statements (i.e., BreakableStatements), 1590 // iterations or 'switch' statements (i.e., BreakableStatements),
1579 // labels can be simply ignored in all other cases; except for 1591 // labels can be simply ignored in all other cases; except for
1580 // trivial labeled break statements 'label: break label' which is 1592 // trivial labeled break statements 'label: break label' which is
1581 // parsed into an empty statement. 1593 // parsed into an empty statement.
1582 switch (peek()) { 1594 switch (peek()) {
1583 case Token::LBRACE: 1595 case Token::LBRACE:
1584 return ParseBlock(labels, ok); 1596 return ParseBlock(labels, ok);
1585 1597
1586 case Token::CONST: // fall through
1587 case Token::LET:
1588 case Token::VAR:
1589 return ParseVariableStatement(kStatement, NULL, ok);
1590
1591 case Token::SEMICOLON: 1598 case Token::SEMICOLON:
1592 Next(); 1599 Next();
1593 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); 1600 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
1594 1601
1595 case Token::IF: 1602 case Token::IF:
1596 return ParseIfStatement(labels, ok); 1603 return ParseIfStatement(labels, ok);
1597 1604
1598 case Token::DO: 1605 case Token::DO:
1599 return ParseDoWhileStatement(labels, ok); 1606 return ParseDoWhileStatement(labels, ok);
1600 1607
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1652 ReportMessageAt(scanner()->peek_location(), "strict_function"); 1659 ReportMessageAt(scanner()->peek_location(), "strict_function");
1653 *ok = false; 1660 *ok = false;
1654 return NULL; 1661 return NULL;
1655 } 1662 }
1656 return ParseFunctionDeclaration(NULL, ok); 1663 return ParseFunctionDeclaration(NULL, ok);
1657 } 1664 }
1658 1665
1659 case Token::DEBUGGER: 1666 case Token::DEBUGGER:
1660 return ParseDebuggerStatement(ok); 1667 return ParseDebuggerStatement(ok);
1661 1668
1669 case Token::VAR:
1670 case Token::CONST:
1671 return ParseVariableStatement(kStatement, NULL, ok);
1672
1673 case Token::LET:
1674 ASSERT(allow_harmony_scoping());
1675 if (strict_mode() == STRICT) {
1676 return ParseVariableStatement(kStatement, NULL, ok);
1677 }
1678 // Fall through.
1662 default: 1679 default:
1663 return ParseExpressionOrLabelledStatement(labels, ok); 1680 return ParseExpressionOrLabelledStatement(labels, ok);
1664 } 1681 }
1665 } 1682 }
1666 1683
1667 1684
1668 VariableProxy* Parser::NewUnresolved(const AstRawString* name, 1685 VariableProxy* Parser::NewUnresolved(const AstRawString* name,
1669 VariableMode mode, Interface* interface) { 1686 VariableMode mode, Interface* interface) {
1670 // If we are inside a function, a declaration of a var/const variable is a 1687 // If we are inside a function, a declaration of a var/const variable is a
1671 // truly local variable, and the scope of the variable is always the function 1688 // truly local variable, and the scope of the variable is always the function
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
2055 mode = CONST; 2072 mode = CONST;
2056 init_op = Token::INIT_CONST; 2073 init_op = Token::INIT_CONST;
2057 } else { 2074 } else {
2058 ReportMessage("strict_const"); 2075 ReportMessage("strict_const");
2059 *ok = false; 2076 *ok = false;
2060 return NULL; 2077 return NULL;
2061 } 2078 }
2062 } 2079 }
2063 is_const = true; 2080 is_const = true;
2064 needs_init = true; 2081 needs_init = true;
2065 } else if (peek() == Token::LET) { 2082 } else if (peek() == Token::LET && strict_mode() == STRICT) {
marja 2014/07/10 14:05:28 Here you probably also want to ASSERT(allow_harmon
2066 // ES6 Draft Rev4 section 12.2.1:
2067 //
2068 // LetDeclaration : let LetBindingList ;
2069 //
2070 // * It is a Syntax Error if the code that matches this production is not
2071 // contained in extended code.
2072 //
2073 // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
2074 if (!allow_harmony_scoping() || strict_mode() == SLOPPY) {
2075 ReportMessage("illegal_let");
2076 *ok = false;
2077 return NULL;
2078 }
2079 Consume(Token::LET); 2083 Consume(Token::LET);
2080 if (var_context == kStatement) { 2084 if (var_context == kStatement) {
2081 // Let declarations are only allowed in source element positions. 2085 // Let declarations are only allowed in source element positions.
2082 ReportMessage("unprotected_let"); 2086 ReportMessage("unprotected_let");
2083 *ok = false; 2087 *ok = false;
2084 return NULL; 2088 return NULL;
2085 } 2089 }
2086 mode = LET; 2090 mode = LET;
2087 needs_init = true; 2091 needs_init = true;
2088 init_op = Token::INIT_LET; 2092 init_op = Token::INIT_LET;
(...skipping 1018 matching lines...) Expand 10 before | Expand all | Expand 10 after
3107 result->AddStatement(loop, zone()); 3111 result->AddStatement(loop, zone());
3108 scope_ = saved_scope; 3112 scope_ = saved_scope;
3109 for_scope->set_end_position(scanner()->location().end_pos); 3113 for_scope->set_end_position(scanner()->location().end_pos);
3110 for_scope = for_scope->FinalizeBlockScope(); 3114 for_scope = for_scope->FinalizeBlockScope();
3111 ASSERT(for_scope == NULL); 3115 ASSERT(for_scope == NULL);
3112 // Parsed for-in loop w/ variable/const declaration. 3116 // Parsed for-in loop w/ variable/const declaration.
3113 return result; 3117 return result;
3114 } else { 3118 } else {
3115 init = variable_statement; 3119 init = variable_statement;
3116 } 3120 }
3117 } else if (peek() == Token::LET) { 3121 } else if (peek() == Token::LET && strict_mode() == STRICT) {
marja 2014/07/10 14:05:28 Ditto
3118 const AstRawString* name = NULL; 3122 const AstRawString* name = NULL;
3119 VariableDeclarationProperties decl_props = kHasNoInitializers; 3123 VariableDeclarationProperties decl_props = kHasNoInitializers;
3120 Block* variable_statement = 3124 Block* variable_statement =
3121 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings, 3125 ParseVariableDeclarations(kForStatement, &decl_props, &let_bindings,
3122 &name, CHECK_OK); 3126 &name, CHECK_OK);
3123 bool accept_IN = name != NULL && decl_props != kHasInitializers; 3127 bool accept_IN = name != NULL && decl_props != kHasInitializers;
3124 bool accept_OF = decl_props == kHasNoInitializers; 3128 bool accept_OF = decl_props == kHasNoInitializers;
3125 ForEachStatement::VisitMode mode; 3129 ForEachStatement::VisitMode mode;
3126 3130
3127 if (accept_IN && CheckInOrOf(accept_OF, &mode)) { 3131 if (accept_IN && CheckInOrOf(accept_OF, &mode)) {
(...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after
3493 // NOTE: We create a proxy and resolve it here so that in the 3497 // NOTE: We create a proxy and resolve it here so that in the
3494 // future we can change the AST to only refer to VariableProxies 3498 // future we can change the AST to only refer to VariableProxies
3495 // instead of Variables and Proxis as is the case now. 3499 // instead of Variables and Proxis as is the case now.
3496 Variable* fvar = NULL; 3500 Variable* fvar = NULL;
3497 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; 3501 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
3498 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { 3502 if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
3499 if (allow_harmony_scoping() && strict_mode() == STRICT) { 3503 if (allow_harmony_scoping() && strict_mode() == STRICT) {
3500 fvar_init_op = Token::INIT_CONST; 3504 fvar_init_op = Token::INIT_CONST;
3501 } 3505 }
3502 VariableMode fvar_mode = 3506 VariableMode fvar_mode =
3503 allow_harmony_scoping() && strict_mode() == STRICT ? CONST 3507 allow_harmony_scoping() && strict_mode() == STRICT
3504 : CONST_LEGACY; 3508 ? CONST : CONST_LEGACY;
3505 ASSERT(function_name != NULL); 3509 ASSERT(function_name != NULL);
3506 fvar = new(zone()) Variable(scope_, 3510 fvar = new(zone()) Variable(scope_,
3507 function_name, fvar_mode, true /* is valid LHS */, 3511 function_name, fvar_mode, true /* is valid LHS */,
3508 Variable::NORMAL, kCreatedInitialized, Interface::NewConst()); 3512 Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
3509 VariableProxy* proxy = factory()->NewVariableProxy(fvar); 3513 VariableProxy* proxy = factory()->NewVariableProxy(fvar);
3510 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( 3514 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
3511 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); 3515 proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
3512 scope_->DeclareFunctionVar(fvar_declaration); 3516 scope_->DeclareFunctionVar(fvar_declaration);
3513 } 3517 }
3514 3518
(...skipping 1371 matching lines...) Expand 10 before | Expand all | Expand 10 after
4886 info()->SetAstValueFactory(ast_value_factory_); 4890 info()->SetAstValueFactory(ast_value_factory_);
4887 } 4891 }
4888 ast_value_factory_ = NULL; 4892 ast_value_factory_ = NULL;
4889 4893
4890 InternalizeUseCounts(); 4894 InternalizeUseCounts();
4891 4895
4892 return (result != NULL); 4896 return (result != NULL);
4893 } 4897 }
4894 4898
4895 } } // namespace v8::internal 4899 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/messages.js ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698