OLD | NEW |
1 // Copyright 2011 the V8 project authors. All rights reserved. | 1 // Copyright 2011 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 <cmath> | 5 #include <cmath> |
6 | 6 |
7 #include "src/allocation.h" | 7 #include "src/allocation.h" |
8 #include "src/base/logging.h" | 8 #include "src/base/logging.h" |
9 #include "src/conversions-inl.h" | 9 #include "src/conversions-inl.h" |
10 #include "src/conversions.h" | 10 #include "src/conversions.h" |
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
424 return final; | 424 return final; |
425 } | 425 } |
426 | 426 |
427 | 427 |
428 PreParser::Statement PreParser::ParseVariableStatement( | 428 PreParser::Statement PreParser::ParseVariableStatement( |
429 VariableDeclarationContext var_context, | 429 VariableDeclarationContext var_context, |
430 bool* ok) { | 430 bool* ok) { |
431 // VariableStatement :: | 431 // VariableStatement :: |
432 // VariableDeclarations ';' | 432 // VariableDeclarations ';' |
433 | 433 |
434 Statement result = ParseVariableDeclarations( | 434 Statement result = |
435 var_context, nullptr, nullptr, nullptr, nullptr, nullptr, CHECK_OK); | 435 ParseVariableDeclarations(var_context, nullptr, nullptr, CHECK_OK); |
436 ExpectSemicolon(CHECK_OK); | 436 ExpectSemicolon(CHECK_OK); |
437 return result; | 437 return result; |
438 } | 438 } |
439 | 439 |
440 | |
441 // If the variable declaration declares exactly one non-const | |
442 // variable, then *var is set to that variable. In all other cases, | |
443 // *var is untouched; in particular, it is the caller's responsibility | |
444 // to initialize it properly. This mechanism is also used for the parsing | |
445 // of 'for-in' loops. | |
446 PreParser::Statement PreParser::ParseVariableDeclarations( | |
447 VariableDeclarationContext var_context, int* num_decl, bool* is_lexical, | |
448 bool* is_binding_pattern, Scanner::Location* first_initializer_loc, | |
449 Scanner::Location* bindings_loc, bool* ok) { | |
450 // VariableDeclarations :: | |
451 // ('var' | 'const') (Identifier ('=' AssignmentExpression)?)+[','] | |
452 // | |
453 // The ES6 Draft Rev3 specifies the following grammar for const declarations | |
454 // | |
455 // ConstDeclaration :: | |
456 // const ConstBinding (',' ConstBinding)* ';' | |
457 // ConstBinding :: | |
458 // Identifier '=' AssignmentExpression | |
459 // | |
460 // TODO(ES6): | |
461 // ConstBinding :: | |
462 // BindingPattern '=' AssignmentExpression | |
463 bool require_initializer = false; | |
464 bool lexical = false; | |
465 bool is_pattern = false; | |
466 if (peek() == Token::VAR) { | |
467 Consume(Token::VAR); | |
468 } else if (peek() == Token::CONST) { | |
469 // TODO(ES6): The ES6 Draft Rev4 section 12.2.2 reads: | |
470 // | |
471 // ConstDeclaration : const ConstBinding (',' ConstBinding)* ';' | |
472 // | |
473 // * It is a Syntax Error if the code that matches this production is not | |
474 // contained in extended code. | |
475 // | |
476 // However disallowing const in sloppy mode will break compatibility with | |
477 // existing pages. Therefore we keep allowing const with the old | |
478 // non-harmony semantics in sloppy mode. | |
479 Consume(Token::CONST); | |
480 DCHECK(var_context != kStatement); | |
481 require_initializer = true; | |
482 lexical = true; | |
483 } else if (peek() == Token::LET) { | |
484 Consume(Token::LET); | |
485 DCHECK(var_context != kStatement); | |
486 lexical = true; | |
487 } else { | |
488 *ok = false; | |
489 return Statement::Default(); | |
490 } | |
491 | |
492 // The scope of a var/const declared variable anywhere inside a function | |
493 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). The scope | |
494 // of a let declared variable is the scope of the immediately enclosing | |
495 // block. | |
496 int nvars = 0; // the number of variables declared | |
497 int bindings_start = peek_position(); | |
498 do { | |
499 // Parse binding pattern. | |
500 if (nvars > 0) Consume(Token::COMMA); | |
501 int decl_pos = peek_position(); | |
502 PreParserExpression pattern = PreParserExpression::Default(); | |
503 { | |
504 ExpressionClassifier pattern_classifier(this); | |
505 pattern = ParsePrimaryExpression(CHECK_OK); | |
506 | |
507 ValidateBindingPattern(CHECK_OK); | |
508 if (lexical) ValidateLetPattern(CHECK_OK); | |
509 } | |
510 | |
511 is_pattern = pattern.IsObjectLiteral() || pattern.IsArrayLiteral(); | |
512 | |
513 Scanner::Location variable_loc = scanner()->location(); | |
514 nvars++; | |
515 if (Check(Token::ASSIGN)) { | |
516 ExpressionClassifier classifier(this); | |
517 ParseAssignmentExpression(var_context != kForStatement, CHECK_OK); | |
518 ValidateExpression(CHECK_OK); | |
519 | |
520 variable_loc.end_pos = scanner()->location().end_pos; | |
521 if (first_initializer_loc && !first_initializer_loc->IsValid()) { | |
522 *first_initializer_loc = variable_loc; | |
523 } | |
524 } else if ((require_initializer || is_pattern) && | |
525 (var_context != kForStatement || !PeekInOrOf())) { | |
526 ReportMessageAt( | |
527 Scanner::Location(decl_pos, scanner()->location().end_pos), | |
528 MessageTemplate::kDeclarationMissingInitializer, | |
529 is_pattern ? "destructuring" : "const"); | |
530 *ok = false; | |
531 return Statement::Default(); | |
532 } | |
533 } while (peek() == Token::COMMA); | |
534 | |
535 if (bindings_loc) { | |
536 *bindings_loc = | |
537 Scanner::Location(bindings_start, scanner()->location().end_pos); | |
538 } | |
539 | |
540 if (num_decl != nullptr) *num_decl = nvars; | |
541 if (is_lexical != nullptr) *is_lexical = lexical; | |
542 if (is_binding_pattern != nullptr) *is_binding_pattern = is_pattern; | |
543 return Statement::Default(); | |
544 } | |
545 | |
546 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { | 440 PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { |
547 Consume(Token::FUNCTION); | 441 Consume(Token::FUNCTION); |
548 int pos = position(); | 442 int pos = position(); |
549 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; | 443 ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal; |
550 if (Check(Token::MUL)) { | 444 if (Check(Token::MUL)) { |
551 flags |= ParseFunctionFlags::kIsGenerator; | 445 flags |= ParseFunctionFlags::kIsGenerator; |
552 if (allow_harmony_restrictive_declarations()) { | 446 if (allow_harmony_restrictive_declarations()) { |
553 ReportMessageAt(scanner()->location(), | 447 ReportMessageAt(scanner()->location(), |
554 MessageTemplate::kGeneratorInLegacyContext); | 448 MessageTemplate::kGeneratorInLegacyContext); |
555 *ok = false; | 449 *ok = false; |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
799 // Create an in-between scope for let-bound iteration variables. | 693 // Create an in-between scope for let-bound iteration variables. |
800 bool has_lexical = false; | 694 bool has_lexical = false; |
801 | 695 |
802 BlockState block_state(&scope_state_); | 696 BlockState block_state(&scope_state_); |
803 Expect(Token::FOR, CHECK_OK); | 697 Expect(Token::FOR, CHECK_OK); |
804 Expect(Token::LPAREN, CHECK_OK); | 698 Expect(Token::LPAREN, CHECK_OK); |
805 if (peek() != Token::SEMICOLON) { | 699 if (peek() != Token::SEMICOLON) { |
806 ForEachStatement::VisitMode mode; | 700 ForEachStatement::VisitMode mode; |
807 if (peek() == Token::VAR || peek() == Token::CONST || | 701 if (peek() == Token::VAR || peek() == Token::CONST || |
808 (peek() == Token::LET && IsNextLetKeyword())) { | 702 (peek() == Token::LET && IsNextLetKeyword())) { |
809 int decl_count; | 703 DeclarationParsingResult parsing_result; |
810 bool is_lexical; | 704 |
811 bool is_binding_pattern; | 705 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr, |
812 Scanner::Location first_initializer_loc = Scanner::Location::invalid(); | 706 CHECK_OK); |
813 Scanner::Location bindings_loc = Scanner::Location::invalid(); | 707 if (parsing_result.descriptor.mode == CONST || |
814 ParseVariableDeclarations(kForStatement, &decl_count, &is_lexical, | 708 parsing_result.descriptor.mode == LET) { |
815 &is_binding_pattern, &first_initializer_loc, | 709 has_lexical = true; |
816 &bindings_loc, CHECK_OK); | 710 } |
817 if (is_lexical) has_lexical = true; | |
818 if (CheckInOrOf(&mode, ok)) { | 711 if (CheckInOrOf(&mode, ok)) { |
819 if (!*ok) return Statement::Default(); | 712 if (!*ok) return Statement::Default(); |
820 if (decl_count != 1) { | 713 if (parsing_result.declarations.length() != 1) { |
821 ReportMessageAt(bindings_loc, | 714 ReportMessageAt(parsing_result.bindings_loc, |
822 MessageTemplate::kForInOfLoopMultiBindings, | 715 MessageTemplate::kForInOfLoopMultiBindings, |
823 ForEachStatement::VisitModeString(mode)); | 716 ForEachStatement::VisitModeString(mode)); |
824 *ok = false; | 717 *ok = false; |
825 return Statement::Default(); | 718 return Statement::Default(); |
826 } | 719 } |
827 if (first_initializer_loc.IsValid() && | 720 bool is_binding_pattern = |
| 721 parsing_result.declarations[0].pattern.IsObjectLiteral() || |
| 722 parsing_result.declarations[0].pattern.IsArrayLiteral(); |
| 723 if (parsing_result.first_initializer_loc.IsValid() && |
828 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || | 724 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || |
829 is_lexical || is_binding_pattern || allow_harmony_for_in())) { | 725 has_lexical || is_binding_pattern || allow_harmony_for_in())) { |
830 // Only increment the use count if we would have let this through | 726 // Only increment the use count if we would have let this through |
831 // without the flag. | 727 // without the flag. |
832 if (use_counts_ != nullptr && allow_harmony_for_in()) { | 728 if (use_counts_ != nullptr && allow_harmony_for_in()) { |
833 ++use_counts_[v8::Isolate::kForInInitializer]; | 729 ++use_counts_[v8::Isolate::kForInInitializer]; |
834 } | 730 } |
835 ReportMessageAt(first_initializer_loc, | 731 ReportMessageAt(parsing_result.first_initializer_loc, |
836 MessageTemplate::kForInOfLoopInitializer, | 732 MessageTemplate::kForInOfLoopInitializer, |
837 ForEachStatement::VisitModeString(mode)); | 733 ForEachStatement::VisitModeString(mode)); |
838 *ok = false; | 734 *ok = false; |
839 return Statement::Default(); | 735 return Statement::Default(); |
840 } | 736 } |
841 | 737 |
842 if (mode == ForEachStatement::ITERATE) { | 738 if (mode == ForEachStatement::ITERATE) { |
843 ExpressionClassifier classifier(this); | 739 ExpressionClassifier classifier(this); |
844 ParseAssignmentExpression(true, CHECK_OK); | 740 ParseAssignmentExpression(true, CHECK_OK); |
845 RewriteNonPattern(CHECK_OK); | 741 RewriteNonPattern(CHECK_OK); |
(...skipping 386 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1232 | 1128 |
1233 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); | 1129 body->Add(PreParserStatement::ExpressionStatement(return_value), zone()); |
1234 } | 1130 } |
1235 | 1131 |
1236 #undef CHECK_OK | 1132 #undef CHECK_OK |
1237 #undef CHECK_OK_CUSTOM | 1133 #undef CHECK_OK_CUSTOM |
1238 | 1134 |
1239 | 1135 |
1240 } // namespace internal | 1136 } // namespace internal |
1241 } // namespace v8 | 1137 } // namespace v8 |
OLD | NEW |