OLD | NEW |
---|---|
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 the V8 project authors. All rights reserved. |
2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
4 // met: | 4 // met: |
5 // | 5 // |
6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
(...skipping 1075 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1086 } | 1086 } |
1087 | 1087 |
1088 Isolate* isolate_; | 1088 Isolate* isolate_; |
1089 bool only_simple_this_property_assignments_; | 1089 bool only_simple_this_property_assignments_; |
1090 ZoneStringList* names_; | 1090 ZoneStringList* names_; |
1091 ZoneList<int>* assigned_arguments_; | 1091 ZoneList<int>* assigned_arguments_; |
1092 ZoneObjectList* assigned_constants_; | 1092 ZoneObjectList* assigned_constants_; |
1093 }; | 1093 }; |
1094 | 1094 |
1095 | 1095 |
1096 Statement* Parser::ParseSourceElement(ZoneStringList* labels, | |
1097 bool* ok) { | |
1098 if (peek() == Token::FUNCTION) { | |
1099 // FunctionDeclaration is only allowed in the context of SourceElements | |
1100 // (Ecma 262 5th Edition, clause 14): | |
1101 // SourceElement: | |
1102 // Statement | |
1103 // FunctionDeclaration | |
1104 // Common language extension is to allow function declaration in place | |
1105 // of any statement. This language extension is disabled in strict mode. | |
1106 return ParseFunctionDeclaration(ok); | |
1107 } else if (peek() == Token::LET && harmony_block_scoping_) { | |
1108 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
| |
1109 } else { | |
1110 return ParseStatement(labels, ok); | |
1111 } | |
1112 } | |
1113 | |
1114 | |
1096 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, | 1115 void* Parser::ParseSourceElements(ZoneList<Statement*>* processor, |
1097 int end_token, | 1116 int end_token, |
1098 bool* ok) { | 1117 bool* ok) { |
1099 // SourceElements :: | 1118 // SourceElements :: |
1100 // (Statement)* <end_token> | 1119 // (Statement)* <end_token> |
1101 | 1120 |
1102 // Allocate a target stack to use for this set of source | 1121 // Allocate a target stack to use for this set of source |
1103 // elements. This way, all scripts and functions get their own | 1122 // elements. This way, all scripts and functions get their own |
1104 // target stack thus avoiding illegal breaks and continues across | 1123 // target stack thus avoiding illegal breaks and continues across |
1105 // functions. | 1124 // functions. |
1106 TargetScope scope(&this->target_stack_); | 1125 TargetScope scope(&this->target_stack_); |
1107 | 1126 |
1108 ASSERT(processor != NULL); | 1127 ASSERT(processor != NULL); |
1109 InitializationBlockFinder block_finder(top_scope_, target_stack_); | 1128 InitializationBlockFinder block_finder(top_scope_, target_stack_); |
1110 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); | 1129 ThisNamedPropertyAssigmentFinder this_property_assignment_finder(isolate()); |
1111 bool directive_prologue = true; // Parsing directive prologue. | 1130 bool directive_prologue = true; // Parsing directive prologue. |
1112 | 1131 |
1113 while (peek() != end_token) { | 1132 while (peek() != end_token) { |
1114 if (directive_prologue && peek() != Token::STRING) { | 1133 if (directive_prologue && peek() != Token::STRING) { |
1115 directive_prologue = false; | 1134 directive_prologue = false; |
1116 } | 1135 } |
1117 | 1136 |
1118 Scanner::Location token_loc = scanner().peek_location(); | 1137 Scanner::Location token_loc = scanner().peek_location(); |
1119 | 1138 Statement* stat = ParseSourceElement(NULL, CHECK_OK); |
1120 Statement* stat; | |
1121 if (peek() == Token::FUNCTION) { | |
1122 // FunctionDeclaration is only allowed in the context of SourceElements | |
1123 // (Ecma 262 5th Edition, clause 14): | |
1124 // SourceElement: | |
1125 // Statement | |
1126 // FunctionDeclaration | |
1127 // Common language extension is to allow function declaration in place | |
1128 // of any statement. This language extension is disabled in strict mode. | |
1129 stat = ParseFunctionDeclaration(CHECK_OK); | |
1130 } else { | |
1131 stat = ParseStatement(NULL, CHECK_OK); | |
1132 } | |
1133 | |
1134 if (stat == NULL || stat->IsEmpty()) { | 1139 if (stat == NULL || stat->IsEmpty()) { |
1135 directive_prologue = false; // End of directive prologue. | 1140 directive_prologue = false; // End of directive prologue. |
1136 continue; | 1141 continue; |
1137 } | 1142 } |
1138 | 1143 |
1139 if (directive_prologue) { | 1144 if (directive_prologue) { |
1140 // A shot at a directive. | 1145 // A shot at a directive. |
1141 ExpressionStatement *e_stat; | 1146 ExpressionStatement *e_stat; |
1142 Literal *literal; | 1147 Literal *literal; |
1143 // Still processing directive prologue? | 1148 // Still processing directive prologue? |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1211 | 1216 |
1212 // Keep the source position of the statement | 1217 // Keep the source position of the statement |
1213 int statement_pos = scanner().peek_location().beg_pos; | 1218 int statement_pos = scanner().peek_location().beg_pos; |
1214 Statement* stmt = NULL; | 1219 Statement* stmt = NULL; |
1215 switch (peek()) { | 1220 switch (peek()) { |
1216 case Token::LBRACE: | 1221 case Token::LBRACE: |
1217 return ParseBlock(labels, ok); | 1222 return ParseBlock(labels, ok); |
1218 | 1223 |
1219 case Token::CONST: // fall through | 1224 case Token::CONST: // fall through |
1220 case Token::VAR: | 1225 case Token::VAR: |
1221 stmt = ParseVariableStatement(ok); | 1226 stmt = ParseVariableStatement(false, ok); |
1222 break; | 1227 break; |
1223 | 1228 |
1224 case Token::SEMICOLON: | 1229 case Token::SEMICOLON: |
1225 Next(); | 1230 Next(); |
1226 return EmptyStatement(); | 1231 return EmptyStatement(); |
1227 | 1232 |
1228 case Token::IF: | 1233 case Token::IF: |
1229 stmt = ParseIfStatement(labels, ok); | 1234 stmt = ParseIfStatement(labels, ok); |
1230 break; | 1235 break; |
1231 | 1236 |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1318 // is always the function scope. | 1323 // is always the function scope. |
1319 | 1324 |
1320 // If a function scope exists, then we can statically declare this | 1325 // If a function scope exists, then we can statically declare this |
1321 // variable and also set its mode. In any case, a Declaration node | 1326 // variable and also set its mode. In any case, a Declaration node |
1322 // will be added to the scope so that the declaration can be added | 1327 // will be added to the scope so that the declaration can be added |
1323 // to the corresponding activation frame at runtime if necessary. | 1328 // to the corresponding activation frame at runtime if necessary. |
1324 // For instance declarations inside an eval scope need to be added | 1329 // For instance declarations inside an eval scope need to be added |
1325 // to the calling function context. | 1330 // to the calling function context. |
1326 // Similarly, strict mode eval scope does not leak variable declarations to | 1331 // Similarly, strict mode eval scope does not leak variable declarations to |
1327 // the caller's scope so we declare all locals, too. | 1332 // the caller's scope so we declare all locals, too. |
1328 Scope* declaration_scope = top_scope_->DeclarationScope(); | 1333 |
1334 Scope* declaration_scope = mode == Variable::LET ? top_scope_ | |
1335 : top_scope_->DeclarationScope(); | |
1329 if (declaration_scope->is_function_scope() || | 1336 if (declaration_scope->is_function_scope() || |
1330 declaration_scope->is_strict_mode_eval_scope()) { | 1337 declaration_scope->is_strict_mode_eval_scope() || |
1338 declaration_scope->is_block_scope()) { | |
1331 // Declare the variable in the function scope. | 1339 // Declare the variable in the function scope. |
1332 var = declaration_scope->LocalLookup(name); | 1340 var = declaration_scope->LocalLookup(name); |
1333 if (var == NULL) { | 1341 if (var == NULL) { |
1334 // Declare the name. | 1342 // Declare the name. |
1335 var = declaration_scope->DeclareLocal(name, mode); | 1343 var = declaration_scope->DeclareLocal(name, mode); |
1336 } else { | 1344 } else { |
1337 // The name was declared before; check for conflicting | 1345 // The name was declared before; check for conflicting re-declarations. |
1338 // re-declarations. If the previous declaration was a const or the | 1346 // We have a conflict if either of the declarations is not a var. There |
1339 // current declaration is a const then we have a conflict. There is | 1347 // is similar code in runtime.cc in the Declare functions. |
1340 // similar code in runtime.cc in the Declare functions. | 1348 if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) { |
1341 if ((mode == Variable::CONST) || (var->mode() == Variable::CONST)) { | 1349 // We only have vars, consts and lets in declarations. |
1342 // We only have vars and consts in declarations. | |
1343 ASSERT(var->mode() == Variable::VAR || | 1350 ASSERT(var->mode() == Variable::VAR || |
1344 var->mode() == Variable::CONST); | 1351 var->mode() == Variable::CONST || |
1345 const char* type = (var->mode() == Variable::VAR) ? "var" : "const"; | 1352 var->mode() == Variable::LET); |
1353 const char* type = (var->mode() == Variable::VAR) ? "var" : | |
1354 (var->mode() == Variable::CONST) ? "const" : "let"; | |
1346 Handle<String> type_string = | 1355 Handle<String> type_string = |
1347 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); | 1356 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); |
1348 Expression* expression = | 1357 Expression* expression = |
1349 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), | 1358 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), |
1350 type_string, name); | 1359 type_string, name); |
1351 declaration_scope->SetIllegalRedeclaration(expression); | 1360 declaration_scope->SetIllegalRedeclaration(expression); |
1352 } | 1361 } |
1353 } | 1362 } |
1354 } | 1363 } |
1355 | 1364 |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1478 Handle<String> name = ParseIdentifierOrStrictReservedWord( | 1487 Handle<String> name = ParseIdentifierOrStrictReservedWord( |
1479 &is_strict_reserved, CHECK_OK); | 1488 &is_strict_reserved, CHECK_OK); |
1480 FunctionLiteral* fun = ParseFunctionLiteral(name, | 1489 FunctionLiteral* fun = ParseFunctionLiteral(name, |
1481 is_strict_reserved, | 1490 is_strict_reserved, |
1482 function_token_position, | 1491 function_token_position, |
1483 FunctionLiteral::DECLARATION, | 1492 FunctionLiteral::DECLARATION, |
1484 CHECK_OK); | 1493 CHECK_OK); |
1485 // Even if we're not at the top-level of the global or a function | 1494 // Even if we're not at the top-level of the global or a function |
1486 // scope, we treat is as such and introduce the function with it's | 1495 // scope, we treat is as such and introduce the function with it's |
1487 // initial value upon entering the corresponding scope. | 1496 // initial value upon entering the corresponding scope. |
1488 Declare(name, Variable::VAR, fun, true, CHECK_OK); | 1497 Variable::Mode mode = harmony_block_scoping_ ? Variable::LET : Variable::VAR; |
1498 Declare(name, mode, fun, true, CHECK_OK); | |
1489 return EmptyStatement(); | 1499 return EmptyStatement(); |
1490 } | 1500 } |
1491 | 1501 |
1492 | 1502 |
1493 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { | 1503 Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) { |
1494 if (harmony_block_scoping_) return ParseScopedBlock(labels, ok); | 1504 if (harmony_block_scoping_) return ParseScopedBlock(labels, ok); |
1495 | 1505 |
1496 // Block :: | 1506 // Block :: |
1497 // '{' Statement* '}' | 1507 // '{' Statement* '}' |
1498 | 1508 |
(...skipping 16 matching lines...) Expand all Loading... | |
1515 return result; | 1525 return result; |
1516 } | 1526 } |
1517 | 1527 |
1518 | 1528 |
1519 Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { | 1529 Block* Parser::ParseScopedBlock(ZoneStringList* labels, bool* ok) { |
1520 // Construct block expecting 16 statements. | 1530 // Construct block expecting 16 statements. |
1521 Block* body = new(zone()) Block(isolate(), labels, 16, false); | 1531 Block* body = new(zone()) Block(isolate(), labels, 16, false); |
1522 Scope* saved_scope = top_scope_; | 1532 Scope* saved_scope = top_scope_; |
1523 Scope* block_scope = NewScope(top_scope_, | 1533 Scope* block_scope = NewScope(top_scope_, |
1524 Scope::BLOCK_SCOPE, | 1534 Scope::BLOCK_SCOPE, |
1525 inside_with()); | 1535 inside_with()); |
Lasse Reichstein
2011/08/12 08:08:33
What baseline is this patch based on? I don't see
Steven
2011/08/16 09:05:32
It is based on a CL that was still in review. It's
| |
1526 body->set_block_scope(block_scope); | 1536 body->set_block_scope(block_scope); |
1527 block_scope->DeclareLocal(isolate()->factory()->block_scope_symbol(), | 1537 block_scope->DeclareLocal(isolate()->factory()->block_scope_symbol(), |
1528 Variable::VAR); | 1538 Variable::VAR); |
1529 if (top_scope_->is_strict_mode()) { | 1539 if (top_scope_->is_strict_mode()) { |
1530 block_scope->EnableStrictMode(); | 1540 block_scope->EnableStrictMode(); |
1531 } | 1541 } |
1532 top_scope_ = block_scope; | 1542 top_scope_ = block_scope; |
1533 | 1543 |
1534 // Parse the statements and collect escaping labels. | 1544 // Parse the statements and collect escaping labels. |
1535 TargetCollector collector; | 1545 TargetCollector collector; |
1536 Target target(&this->target_stack_, &collector); | 1546 Target target(&this->target_stack_, &collector); |
1537 Expect(Token::LBRACE, CHECK_OK); | 1547 Expect(Token::LBRACE, CHECK_OK); |
1538 { | 1548 { |
1539 Target target_body(&this->target_stack_, body); | 1549 Target target_body(&this->target_stack_, body); |
1540 InitializationBlockFinder block_finder(top_scope_, target_stack_); | 1550 InitializationBlockFinder block_finder(top_scope_, target_stack_); |
1541 | 1551 |
1542 while (peek() != Token::RBRACE) { | 1552 while (peek() != Token::RBRACE) { |
1543 Statement* stat = ParseStatement(NULL, CHECK_OK); | 1553 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
| |
1544 if (stat && !stat->IsEmpty()) { | 1554 if (stat && !stat->IsEmpty()) { |
1545 body->AddStatement(stat); | 1555 body->AddStatement(stat); |
1546 block_finder.Update(stat); | 1556 block_finder.Update(stat); |
1547 } | 1557 } |
1548 } | 1558 } |
1549 } | 1559 } |
1550 Expect(Token::RBRACE, CHECK_OK); | 1560 Expect(Token::RBRACE, CHECK_OK); |
1551 | 1561 |
1552 // Create exit block. | 1562 // Create exit block. |
1553 Block* exit = new(zone()) Block(isolate(), NULL, 1, false); | 1563 Block* exit = new(zone()) Block(isolate(), NULL, 1, false); |
1554 exit->AddStatement(new(zone()) ExitContextStatement()); | 1564 exit->AddStatement(new(zone()) ExitContextStatement()); |
1555 | 1565 |
1556 // Create a try-finally statement. | 1566 // Create a try-finally statement. |
1557 TryFinallyStatement* try_finally = | 1567 TryFinallyStatement* try_finally = |
1558 new(zone()) TryFinallyStatement(body, exit); | 1568 new(zone()) TryFinallyStatement(body, exit); |
1559 try_finally->set_escaping_targets(collector.targets()); | 1569 try_finally->set_escaping_targets(collector.targets()); |
1560 top_scope_ = saved_scope; | 1570 top_scope_ = saved_scope; |
1561 | 1571 |
1562 // Create a result block. | 1572 // Create a result block. |
1563 Block* result = new(zone()) Block(isolate(), NULL, 1, false); | 1573 Block* result = new(zone()) Block(isolate(), NULL, 1, false); |
1564 result->AddStatement(try_finally); | 1574 result->AddStatement(try_finally); |
1565 return result; | 1575 return result; |
1566 } | 1576 } |
1567 | 1577 |
1568 | 1578 |
1569 Block* Parser::ParseVariableStatement(bool* ok) { | 1579 Block* Parser::ParseVariableStatement(bool accept_LET, bool* ok) { |
1570 // VariableStatement :: | 1580 // VariableStatement :: |
1571 // VariableDeclarations ';' | 1581 // VariableDeclarations ';' |
1572 | 1582 |
1573 Handle<String> ignore; | 1583 Handle<String> ignore; |
1574 Block* result = ParseVariableDeclarations(true, &ignore, CHECK_OK); | 1584 Block* result = ParseVariableDeclarations(accept_LET, true, |
1585 &ignore, CHECK_OK); | |
1575 ExpectSemicolon(CHECK_OK); | 1586 ExpectSemicolon(CHECK_OK); |
1576 return result; | 1587 return result; |
1577 } | 1588 } |
1578 | 1589 |
1579 | 1590 |
1580 bool Parser::IsEvalOrArguments(Handle<String> string) { | 1591 bool Parser::IsEvalOrArguments(Handle<String> string) { |
1581 return string.is_identical_to(isolate()->factory()->eval_symbol()) || | 1592 return string.is_identical_to(isolate()->factory()->eval_symbol()) || |
1582 string.is_identical_to(isolate()->factory()->arguments_symbol()); | 1593 string.is_identical_to(isolate()->factory()->arguments_symbol()); |
1583 } | 1594 } |
1584 | 1595 |
1585 | 1596 |
1586 // If the variable declaration declares exactly one non-const | 1597 // If the variable declaration declares exactly one non-const |
1587 // variable, then *var is set to that variable. In all other cases, | 1598 // variable, then *var is set to that variable. In all other cases, |
1588 // *var is untouched; in particular, it is the caller's responsibility | 1599 // *var is untouched; in particular, it is the caller's responsibility |
1589 // to initialize it properly. This mechanism is used for the parsing | 1600 // to initialize it properly. This mechanism is used for the parsing |
1590 // of 'for-in' loops. | 1601 // of 'for-in' loops. |
1591 Block* Parser::ParseVariableDeclarations(bool accept_IN, | 1602 Block* Parser::ParseVariableDeclarations(bool accept_LET, |
1603 bool accept_IN, | |
1592 Handle<String>* out, | 1604 Handle<String>* out, |
1593 bool* ok) { | 1605 bool* ok) { |
1594 // VariableDeclarations :: | 1606 // VariableDeclarations :: |
1595 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | 1607 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] |
1596 | 1608 |
1597 Variable::Mode mode = Variable::VAR; | 1609 Variable::Mode mode = Variable::VAR; |
1598 bool is_const = false; | 1610 bool is_const = false; |
1599 Scope* declaration_scope = top_scope_->DeclarationScope(); | 1611 Scope* declaration_scope = top_scope_->DeclarationScope(); |
1600 if (peek() == Token::VAR) { | 1612 if (peek() == Token::VAR) { |
1601 Consume(Token::VAR); | 1613 Consume(Token::VAR); |
1602 } else if (peek() == Token::CONST) { | 1614 } else if (peek() == Token::CONST) { |
1603 Consume(Token::CONST); | 1615 Consume(Token::CONST); |
1604 if (declaration_scope->is_strict_mode()) { | 1616 if (declaration_scope->is_strict_mode()) { |
1605 ReportMessage("strict_const", Vector<const char*>::empty()); | 1617 ReportMessage("strict_const", Vector<const char*>::empty()); |
1606 *ok = false; | 1618 *ok = false; |
1607 return NULL; | 1619 return NULL; |
1608 } | 1620 } |
1609 mode = Variable::CONST; | 1621 mode = Variable::CONST; |
1610 is_const = true; | 1622 is_const = true; |
1623 } else if (peek() == Token::LET) { | |
1624 Consume(Token::LET); | |
1625 if (!accept_LET) { | |
1626 ReportMessage("unprotected_let", Vector<const char*>::empty()); | |
1627 *ok = false; | |
1628 return NULL; | |
1629 } | |
1630 mode = Variable::LET; | |
1611 } else { | 1631 } else { |
1612 UNREACHABLE(); // by current callers | 1632 UNREACHABLE(); // by current callers |
1613 } | 1633 } |
1614 | 1634 |
1615 // The scope of a variable/const declared anywhere inside a function | 1635 // The scope of a variable/const declared anywhere inside a function |
1616 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can | 1636 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can |
1617 // transform a source-level variable/const declaration into a (Function) | 1637 // transform a source-level variable/const declaration into a (Function) |
1618 // Scope declaration, and rewrite the source-level initialization into an | 1638 // Scope declaration, and rewrite the source-level initialization into an |
1619 // assignment statement. We use a block to collect multiple assignments. | 1639 // assignment statement. We use a block to collect multiple assignments. |
1620 // | 1640 // |
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2339 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement | 2359 // 'for' '(' Expression? ';' Expression? ';' Expression? ')' Statement |
2340 | 2360 |
2341 Statement* init = NULL; | 2361 Statement* init = NULL; |
2342 | 2362 |
2343 Expect(Token::FOR, CHECK_OK); | 2363 Expect(Token::FOR, CHECK_OK); |
2344 Expect(Token::LPAREN, CHECK_OK); | 2364 Expect(Token::LPAREN, CHECK_OK); |
2345 if (peek() != Token::SEMICOLON) { | 2365 if (peek() != Token::SEMICOLON) { |
2346 if (peek() == Token::VAR || peek() == Token::CONST) { | 2366 if (peek() == Token::VAR || peek() == Token::CONST) { |
2347 Handle<String> name; | 2367 Handle<String> name; |
2348 Block* variable_statement = | 2368 Block* variable_statement = |
2349 ParseVariableDeclarations(false, &name, CHECK_OK); | 2369 ParseVariableDeclarations(true, false, &name, CHECK_OK); |
2350 | 2370 |
2351 if (peek() == Token::IN && !name.is_null()) { | 2371 if (peek() == Token::IN && !name.is_null()) { |
2352 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with()); | 2372 VariableProxy* each = top_scope_->NewUnresolved(name, inside_with()); |
2353 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); | 2373 ForInStatement* loop = new(zone()) ForInStatement(isolate(), labels); |
2354 Target target(&this->target_stack_, loop); | 2374 Target target(&this->target_stack_, loop); |
2355 | 2375 |
2356 Expect(Token::IN, CHECK_OK); | 2376 Expect(Token::IN, CHECK_OK); |
2357 Expression* enumerable = ParseExpression(true, CHECK_OK); | 2377 Expression* enumerable = ParseExpression(true, CHECK_OK); |
2358 Expect(Token::RPAREN, CHECK_OK); | 2378 Expect(Token::RPAREN, CHECK_OK); |
2359 | 2379 |
(...skipping 626 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2986 Vector<const char*>::empty()); | 3006 Vector<const char*>::empty()); |
2987 case Token::STRING: | 3007 case Token::STRING: |
2988 return ReportMessage("unexpected_token_string", | 3008 return ReportMessage("unexpected_token_string", |
2989 Vector<const char*>::empty()); | 3009 Vector<const char*>::empty()); |
2990 case Token::IDENTIFIER: | 3010 case Token::IDENTIFIER: |
2991 return ReportMessage("unexpected_token_identifier", | 3011 return ReportMessage("unexpected_token_identifier", |
2992 Vector<const char*>::empty()); | 3012 Vector<const char*>::empty()); |
2993 case Token::FUTURE_RESERVED_WORD: | 3013 case Token::FUTURE_RESERVED_WORD: |
2994 return ReportMessage("unexpected_reserved", | 3014 return ReportMessage("unexpected_reserved", |
2995 Vector<const char*>::empty()); | 3015 Vector<const char*>::empty()); |
3016 case Token::LET: | |
3017 if (harmony_block_scoping_) { | |
3018 const char* name = Token::String(token); | |
3019 ASSERT(name != NULL); | |
3020 return ReportMessage("unexpected_token", | |
3021 Vector<const char*>(&name, 1)); | |
3022 } | |
3023 // FALLTHROUGH | |
2996 case Token::FUTURE_STRICT_RESERVED_WORD: | 3024 case Token::FUTURE_STRICT_RESERVED_WORD: |
2997 return ReportMessage(top_scope_->is_strict_mode() ? | 3025 return ReportMessage(top_scope_->is_strict_mode() ? |
2998 "unexpected_strict_reserved" : | 3026 "unexpected_strict_reserved" : |
2999 "unexpected_token_identifier", | 3027 "unexpected_token_identifier", |
3000 Vector<const char*>::empty()); | 3028 Vector<const char*>::empty()); |
3001 default: | 3029 default: |
3002 const char* name = Token::String(token); | 3030 const char* name = Token::String(token); |
3003 ASSERT(name != NULL); | 3031 ASSERT(name != NULL); |
3004 ReportMessage("unexpected_token", Vector<const char*>(&name, 1)); | 3032 ReportMessage("unexpected_token", Vector<const char*>(&name, 1)); |
3005 } | 3033 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3048 result = new(zone()) Literal( | 3076 result = new(zone()) Literal( |
3049 isolate(), isolate()->factory()->true_value()); | 3077 isolate(), isolate()->factory()->true_value()); |
3050 break; | 3078 break; |
3051 | 3079 |
3052 case Token::FALSE_LITERAL: | 3080 case Token::FALSE_LITERAL: |
3053 Consume(Token::FALSE_LITERAL); | 3081 Consume(Token::FALSE_LITERAL); |
3054 result = new(zone()) Literal( | 3082 result = new(zone()) Literal( |
3055 isolate(), isolate()->factory()->false_value()); | 3083 isolate(), isolate()->factory()->false_value()); |
3056 break; | 3084 break; |
3057 | 3085 |
3086 case Token::LET: | |
3087 if (harmony_block_scoping_) { | |
3088 Token::Value tok = Next(); | |
3089 ReportUnexpectedToken(tok); | |
3090 *ok = false; | |
3091 return NULL; | |
3092 } | |
3093 // FALLTHROUGH | |
3058 case Token::IDENTIFIER: | 3094 case Token::IDENTIFIER: |
3059 case Token::FUTURE_STRICT_RESERVED_WORD: { | 3095 case Token::FUTURE_STRICT_RESERVED_WORD: { |
3060 Handle<String> name = ParseIdentifier(CHECK_OK); | 3096 Handle<String> name = ParseIdentifier(CHECK_OK); |
3061 if (fni_ != NULL) fni_->PushVariableName(name); | 3097 if (fni_ != NULL) fni_->PushVariableName(name); |
3062 result = top_scope_->NewUnresolved(name, | 3098 result = top_scope_->NewUnresolved(name, |
3063 inside_with(), | 3099 inside_with(), |
3064 scanner().location().beg_pos); | 3100 scanner().location().beg_pos); |
3065 break; | 3101 break; |
3066 } | 3102 } |
3067 | 3103 |
(...skipping 444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3512 | 3548 |
3513 while (peek() != Token::RBRACE) { | 3549 while (peek() != Token::RBRACE) { |
3514 if (fni_ != NULL) fni_->Enter(); | 3550 if (fni_ != NULL) fni_->Enter(); |
3515 | 3551 |
3516 Literal* key = NULL; | 3552 Literal* key = NULL; |
3517 Token::Value next = peek(); | 3553 Token::Value next = peek(); |
3518 | 3554 |
3519 // Location of the property name token | 3555 // Location of the property name token |
3520 Scanner::Location loc = scanner().peek_location(); | 3556 Scanner::Location loc = scanner().peek_location(); |
3521 | 3557 |
3558 if (harmony_block_scoping_ && next == Token::LET) { | |
3559 // Go into FUTURE_STRICT_RESERVED_WORD case where | |
3560 // ParseIdentifierNameOrGetOrSet will handle the LET | |
3561 // token like a FUTURE_STRICT_RESERVED_WORD. | |
3562 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
| |
3563 } | |
3522 switch (next) { | 3564 switch (next) { |
3523 case Token::FUTURE_RESERVED_WORD: | 3565 case Token::FUTURE_RESERVED_WORD: |
3524 case Token::FUTURE_STRICT_RESERVED_WORD: | 3566 case Token::FUTURE_STRICT_RESERVED_WORD: |
3525 case Token::IDENTIFIER: { | 3567 case Token::IDENTIFIER: { |
3526 bool is_getter = false; | 3568 bool is_getter = false; |
3527 bool is_setter = false; | 3569 bool is_setter = false; |
3528 Handle<String> id = | 3570 Handle<String> id = |
3529 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); | 3571 ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK); |
3530 if (fni_ != NULL) fni_->PushLiteralName(id); | 3572 if (fni_ != NULL) fni_->PushLiteralName(id); |
3531 | 3573 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3699 // handle to decide whether to invoke function name inference. | 3741 // handle to decide whether to invoke function name inference. |
3700 bool should_infer_name = function_name.is_null(); | 3742 bool should_infer_name = function_name.is_null(); |
3701 | 3743 |
3702 // We want a non-null handle as the function name. | 3744 // We want a non-null handle as the function name. |
3703 if (should_infer_name) { | 3745 if (should_infer_name) { |
3704 function_name = isolate()->factory()->empty_symbol(); | 3746 function_name = isolate()->factory()->empty_symbol(); |
3705 } | 3747 } |
3706 | 3748 |
3707 int num_parameters = 0; | 3749 int num_parameters = 0; |
3708 // Function declarations are hoisted. | 3750 // Function declarations are hoisted. |
3709 Scope* scope = (type == FunctionLiteral::DECLARATION) | 3751 Scope* scope = (type == FunctionLiteral::DECLARATION && |
3752 !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
| |
3710 ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false) | 3753 ? NewScope(top_scope_->DeclarationScope(), Scope::FUNCTION_SCOPE, false) |
3711 : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); | 3754 : NewScope(top_scope_, Scope::FUNCTION_SCOPE, inside_with()); |
3712 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8); | 3755 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(8); |
3713 int materialized_literal_count; | 3756 int materialized_literal_count; |
3714 int expected_property_count; | 3757 int expected_property_count; |
3715 int start_pos; | 3758 int start_pos; |
3716 int end_pos; | 3759 int end_pos; |
3717 bool only_simple_this_property_assignments; | 3760 bool only_simple_this_property_assignments; |
3718 Handle<FixedArray> this_property_assignments; | 3761 Handle<FixedArray> this_property_assignments; |
3719 bool has_duplicate_parameters = false; | 3762 bool has_duplicate_parameters = false; |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3939 | 3982 |
3940 // We have a valid intrinsics call or a call to a builtin. | 3983 // We have a valid intrinsics call or a call to a builtin. |
3941 return new(zone()) CallRuntime(isolate(), name, function, args); | 3984 return new(zone()) CallRuntime(isolate(), name, function, args); |
3942 } | 3985 } |
3943 | 3986 |
3944 | 3987 |
3945 bool Parser::peek_any_identifier() { | 3988 bool Parser::peek_any_identifier() { |
3946 Token::Value next = peek(); | 3989 Token::Value next = peek(); |
3947 return next == Token::IDENTIFIER || | 3990 return next == Token::IDENTIFIER || |
3948 next == Token::FUTURE_RESERVED_WORD || | 3991 next == Token::FUTURE_RESERVED_WORD || |
3949 next == Token::FUTURE_STRICT_RESERVED_WORD; | 3992 next == Token::FUTURE_STRICT_RESERVED_WORD || |
3993 (next == Token::LET && !harmony_block_scoping_); | |
3950 } | 3994 } |
3951 | 3995 |
3952 | 3996 |
3953 void Parser::Consume(Token::Value token) { | 3997 void Parser::Consume(Token::Value token) { |
3954 Token::Value next = Next(); | 3998 Token::Value next = Next(); |
3955 USE(next); | 3999 USE(next); |
3956 USE(token); | 4000 USE(token); |
3957 ASSERT(next == token); | 4001 ASSERT(next == token); |
3958 } | 4002 } |
3959 | 4003 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4001 Literal* Parser::GetLiteralTheHole() { | 4045 Literal* Parser::GetLiteralTheHole() { |
4002 return NewLiteral(isolate()->factory()->the_hole_value()); | 4046 return NewLiteral(isolate()->factory()->the_hole_value()); |
4003 } | 4047 } |
4004 | 4048 |
4005 | 4049 |
4006 Literal* Parser::GetLiteralNumber(double value) { | 4050 Literal* Parser::GetLiteralNumber(double value) { |
4007 return NewNumberLiteral(value); | 4051 return NewNumberLiteral(value); |
4008 } | 4052 } |
4009 | 4053 |
4010 | 4054 |
4011 // Parses and identifier that is valid for the current scope, in particular it | 4055 // Parses and identifier that is valid for the current scope, in particular it |
Lasse Reichstein
2011/08/12 08:08:33
"and"->"an" while you are here :)
Steven
2011/08/16 09:05:32
Done.
| |
4012 // fails on strict mode future reserved keywords in a strict scope. | 4056 // fails on strict mode future reserved keywords in a strict scope. |
4013 Handle<String> Parser::ParseIdentifier(bool* ok) { | 4057 Handle<String> Parser::ParseIdentifier(bool* ok) { |
4014 if (top_scope_->is_strict_mode()) { | 4058 if (top_scope_->is_strict_mode()) { |
4015 Expect(Token::IDENTIFIER, ok); | 4059 Expect(Token::IDENTIFIER, ok); |
4016 } else if (!Check(Token::IDENTIFIER)) { | 4060 } else if (!Check(Token::IDENTIFIER)) { |
4017 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); | 4061 if (harmony_block_scoping_) { |
4062 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); | |
4063 } else if (!Check(Token::FUTURE_STRICT_RESERVED_WORD)) { | |
4064 Expect(Token::LET, ok); | |
4065 } | |
4018 } | 4066 } |
4019 if (!*ok) return Handle<String>(); | 4067 if (!*ok) return Handle<String>(); |
4020 return GetSymbol(ok); | 4068 return GetSymbol(ok); |
4021 } | 4069 } |
4022 | 4070 |
4023 | 4071 |
4024 // Parses and identifier or a strict mode future reserved word, and indicate | 4072 // Parses and identifier or a strict mode future reserved word, and indicate |
4025 // whether it is strict mode future reserved. | 4073 // whether it is strict mode future reserved. |
4026 Handle<String> Parser::ParseIdentifierOrStrictReservedWord( | 4074 Handle<String> Parser::ParseIdentifierOrStrictReservedWord( |
4027 bool* is_strict_reserved, bool* ok) { | 4075 bool* is_strict_reserved, bool* ok) { |
4028 *is_strict_reserved = false; | 4076 *is_strict_reserved = false; |
4029 if (!Check(Token::IDENTIFIER)) { | 4077 if (!Check(Token::IDENTIFIER)) { |
4030 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); | 4078 if (harmony_block_scoping_) { |
4079 Expect(Token::FUTURE_STRICT_RESERVED_WORD, ok); | |
4080 } else if (!Check(Token::FUTURE_STRICT_RESERVED_WORD)) { | |
4081 Expect(Token::LET, ok); | |
4082 } | |
4031 *is_strict_reserved = true; | 4083 *is_strict_reserved = true; |
4032 } | 4084 } |
4033 if (!*ok) return Handle<String>(); | 4085 if (!*ok) return Handle<String>(); |
4034 return GetSymbol(ok); | 4086 return GetSymbol(ok); |
4035 } | 4087 } |
4036 | 4088 |
4037 | 4089 |
4038 Handle<String> Parser::ParseIdentifierName(bool* ok) { | 4090 Handle<String> Parser::ParseIdentifierName(bool* ok) { |
4039 Token::Value next = Next(); | 4091 Token::Value next = Next(); |
4040 if (next != Token::IDENTIFIER && | 4092 if (next != Token::IDENTIFIER && |
(...skipping 1147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5188 result = parser.ParseProgram(source, | 5240 result = parser.ParseProgram(source, |
5189 info->is_global(), | 5241 info->is_global(), |
5190 info->StrictMode()); | 5242 info->StrictMode()); |
5191 } | 5243 } |
5192 } | 5244 } |
5193 info->SetFunction(result); | 5245 info->SetFunction(result); |
5194 return (result != NULL); | 5246 return (result != NULL); |
5195 } | 5247 } |
5196 | 5248 |
5197 } } // namespace v8::internal | 5249 } } // namespace v8::internal |
OLD | NEW |