Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 #ifndef V8_PARSING_PARSER_BASE_H | 5 #ifndef V8_PARSING_PARSER_BASE_H |
| 6 #define V8_PARSING_PARSER_BASE_H | 6 #define V8_PARSING_PARSER_BASE_H |
| 7 | 7 |
| 8 #include "src/ast/ast.h" | 8 #include "src/ast/ast.h" |
| 9 #include "src/ast/scopes.h" | 9 #include "src/ast/scopes.h" |
| 10 #include "src/bailout-reason.h" | 10 #include "src/bailout-reason.h" |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 217 stack_overflow_(false), | 217 stack_overflow_(false), |
| 218 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), | 218 default_eager_compile_hint_(FunctionLiteral::kShouldLazyCompile), |
| 219 function_literal_id_(0), | 219 function_literal_id_(0), |
| 220 allow_natives_(false), | 220 allow_natives_(false), |
| 221 allow_tailcalls_(false), | 221 allow_tailcalls_(false), |
| 222 allow_harmony_do_expressions_(false), | 222 allow_harmony_do_expressions_(false), |
| 223 allow_harmony_function_sent_(false), | 223 allow_harmony_function_sent_(false), |
| 224 allow_harmony_restrictive_generators_(false), | 224 allow_harmony_restrictive_generators_(false), |
| 225 allow_harmony_trailing_commas_(false), | 225 allow_harmony_trailing_commas_(false), |
| 226 allow_harmony_class_fields_(false), | 226 allow_harmony_class_fields_(false), |
| 227 allow_harmony_object_rest_spread_(false) {} | 227 allow_harmony_object_rest_spread_(false), |
| 228 allow_harmony_async_iteration_(false) {} | |
| 228 | 229 |
| 229 #define ALLOW_ACCESSORS(name) \ | 230 #define ALLOW_ACCESSORS(name) \ |
| 230 bool allow_##name() const { return allow_##name##_; } \ | 231 bool allow_##name() const { return allow_##name##_; } \ |
| 231 void set_allow_##name(bool allow) { allow_##name##_ = allow; } | 232 void set_allow_##name(bool allow) { allow_##name##_ = allow; } |
| 232 | 233 |
| 233 ALLOW_ACCESSORS(natives); | 234 ALLOW_ACCESSORS(natives); |
| 234 ALLOW_ACCESSORS(tailcalls); | 235 ALLOW_ACCESSORS(tailcalls); |
| 235 ALLOW_ACCESSORS(harmony_do_expressions); | 236 ALLOW_ACCESSORS(harmony_do_expressions); |
| 236 ALLOW_ACCESSORS(harmony_function_sent); | 237 ALLOW_ACCESSORS(harmony_function_sent); |
| 237 ALLOW_ACCESSORS(harmony_restrictive_generators); | 238 ALLOW_ACCESSORS(harmony_restrictive_generators); |
| 238 ALLOW_ACCESSORS(harmony_trailing_commas); | 239 ALLOW_ACCESSORS(harmony_trailing_commas); |
| 239 ALLOW_ACCESSORS(harmony_class_fields); | 240 ALLOW_ACCESSORS(harmony_class_fields); |
| 240 ALLOW_ACCESSORS(harmony_object_rest_spread); | 241 ALLOW_ACCESSORS(harmony_object_rest_spread); |
| 242 ALLOW_ACCESSORS(harmony_async_iteration); | |
| 241 | 243 |
| 242 #undef ALLOW_ACCESSORS | 244 #undef ALLOW_ACCESSORS |
| 243 | 245 |
| 244 uintptr_t stack_limit() const { return stack_limit_; } | 246 uintptr_t stack_limit() const { return stack_limit_; } |
| 245 | 247 |
| 246 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } | 248 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } |
| 247 | 249 |
| 248 void set_default_eager_compile_hint( | 250 void set_default_eager_compile_hint( |
| 249 FunctionLiteral::EagerCompileHint eager_compile_hint) { | 251 FunctionLiteral::EagerCompileHint eager_compile_hint) { |
| 250 default_eager_compile_hint_ = eager_compile_hint; | 252 default_eager_compile_hint_ = eager_compile_hint; |
| (...skipping 1044 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1295 bool* ok); | 1297 bool* ok); |
| 1296 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, | 1298 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, |
| 1297 bool* ok); | 1299 bool* ok); |
| 1298 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, | 1300 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, |
| 1299 bool* ok); | 1301 bool* ok); |
| 1300 StatementT ParseThrowStatement(bool* ok); | 1302 StatementT ParseThrowStatement(bool* ok); |
| 1301 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, | 1303 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, |
| 1302 bool* ok); | 1304 bool* ok); |
| 1303 StatementT ParseTryStatement(bool* ok); | 1305 StatementT ParseTryStatement(bool* ok); |
| 1304 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); | 1306 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); |
| 1307 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels, | |
| 1308 bool* ok); | |
| 1305 | 1309 |
| 1306 bool IsNextLetKeyword(); | 1310 bool IsNextLetKeyword(); |
| 1307 bool IsTrivialExpression(); | 1311 bool IsTrivialExpression(); |
| 1308 | 1312 |
| 1309 // Checks if the expression is a valid reference expression (e.g., on the | 1313 // Checks if the expression is a valid reference expression (e.g., on the |
| 1310 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1314 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| 1311 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1315 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 1312 ExpressionT CheckAndRewriteReferenceExpression( | 1316 ExpressionT CheckAndRewriteReferenceExpression( |
| 1313 ExpressionT expression, int beg_pos, int end_pos, | 1317 ExpressionT expression, int beg_pos, int end_pos, |
| 1314 MessageTemplate::Template message, bool* ok); | 1318 MessageTemplate::Template message, bool* ok); |
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1463 int function_literal_id_; | 1467 int function_literal_id_; |
| 1464 | 1468 |
| 1465 bool allow_natives_; | 1469 bool allow_natives_; |
| 1466 bool allow_tailcalls_; | 1470 bool allow_tailcalls_; |
| 1467 bool allow_harmony_do_expressions_; | 1471 bool allow_harmony_do_expressions_; |
| 1468 bool allow_harmony_function_sent_; | 1472 bool allow_harmony_function_sent_; |
| 1469 bool allow_harmony_restrictive_generators_; | 1473 bool allow_harmony_restrictive_generators_; |
| 1470 bool allow_harmony_trailing_commas_; | 1474 bool allow_harmony_trailing_commas_; |
| 1471 bool allow_harmony_class_fields_; | 1475 bool allow_harmony_class_fields_; |
| 1472 bool allow_harmony_object_rest_spread_; | 1476 bool allow_harmony_object_rest_spread_; |
| 1477 bool allow_harmony_async_iteration_; | |
| 1473 | 1478 |
| 1474 friend class DiscardableZoneScope; | 1479 friend class DiscardableZoneScope; |
| 1475 }; | 1480 }; |
| 1476 | 1481 |
| 1477 template <typename Impl> | 1482 template <typename Impl> |
| 1478 ParserBase<Impl>::FunctionState::FunctionState( | 1483 ParserBase<Impl>::FunctionState::FunctionState( |
| 1479 FunctionState** function_state_stack, ScopeState** scope_stack, | 1484 FunctionState** function_state_stack, ScopeState** scope_stack, |
| 1480 DeclarationScope* scope) | 1485 DeclarationScope* scope) |
| 1481 : ScopeState(scope_stack, scope), | 1486 : ScopeState(scope_stack, scope), |
| 1482 next_materialized_literal_index_(0), | 1487 next_materialized_literal_index_(0), |
| (...skipping 3262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4745 case Token::SEMICOLON: | 4750 case Token::SEMICOLON: |
| 4746 Next(); | 4751 Next(); |
| 4747 return factory()->NewEmptyStatement(kNoSourcePosition); | 4752 return factory()->NewEmptyStatement(kNoSourcePosition); |
| 4748 case Token::IF: | 4753 case Token::IF: |
| 4749 return ParseIfStatement(labels, ok); | 4754 return ParseIfStatement(labels, ok); |
| 4750 case Token::DO: | 4755 case Token::DO: |
| 4751 return ParseDoWhileStatement(labels, ok); | 4756 return ParseDoWhileStatement(labels, ok); |
| 4752 case Token::WHILE: | 4757 case Token::WHILE: |
| 4753 return ParseWhileStatement(labels, ok); | 4758 return ParseWhileStatement(labels, ok); |
| 4754 case Token::FOR: | 4759 case Token::FOR: |
| 4760 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() && | |
| 4761 PeekAhead() == Token::AWAIT)) { | |
| 4762 return ParseForAwaitStatement(labels, ok); | |
| 4763 } | |
| 4755 return ParseForStatement(labels, ok); | 4764 return ParseForStatement(labels, ok); |
| 4756 case Token::CONTINUE: | 4765 case Token::CONTINUE: |
| 4757 case Token::BREAK: | 4766 case Token::BREAK: |
| 4758 case Token::RETURN: | 4767 case Token::RETURN: |
| 4759 case Token::THROW: | 4768 case Token::THROW: |
| 4760 case Token::TRY: { | 4769 case Token::TRY: { |
| 4761 // These statements must have their labels preserved in an enclosing | 4770 // These statements must have their labels preserved in an enclosing |
| 4762 // block, as the corresponding AST nodes do not currently store their | 4771 // block, as the corresponding AST nodes do not currently store their |
| 4763 // labels. | 4772 // labels. |
| 4764 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4773 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
| (...skipping 857 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5622 block->set_scope(for_scope); | 5631 block->set_scope(for_scope); |
| 5623 loop->Initialize(init, cond, next, body); | 5632 loop->Initialize(init, cond, next, body); |
| 5624 return block; | 5633 return block; |
| 5625 } else { | 5634 } else { |
| 5626 loop->Initialize(init, cond, next, body); | 5635 loop->Initialize(init, cond, next, body); |
| 5627 return loop; | 5636 return loop; |
| 5628 } | 5637 } |
| 5629 } | 5638 } |
| 5630 } | 5639 } |
| 5631 | 5640 |
| 5641 template <typename Impl> | |
|
marja
2017/01/23 05:50:02
This is quite a lot of code duplication with Parse
caitp
2017/01/23 06:10:35
This is the main reason for the different function
| |
| 5642 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( | |
| 5643 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 5644 // for await '(' ForDeclaration of AssignmentExpression ')' | |
| 5645 DCHECK(is_async_function()); | |
| 5646 DCHECK(allow_harmony_async_iteration()); | |
| 5647 | |
| 5648 int stmt_pos = peek_position(); | |
| 5649 | |
| 5650 ForInfo for_info(this); | |
| 5651 for_info.mode = ForEachStatement::ITERATE; | |
| 5652 | |
| 5653 // Create an in-between scope for let-bound iteration variables. | |
| 5654 BlockState for_state(zone(), &scope_state_); | |
| 5655 Expect(Token::FOR, CHECK_OK); | |
| 5656 Expect(Token::AWAIT, CHECK_OK); | |
| 5657 Expect(Token::LPAREN, CHECK_OK); | |
| 5658 for_state.set_start_position(scanner()->location().beg_pos); | |
| 5659 for_state.set_is_hidden(); | |
| 5660 | |
| 5661 auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); | |
| 5662 typename Types::Target target(this, loop); | |
| 5663 | |
| 5664 ExpressionT each_variable = impl()->EmptyExpression(); | |
| 5665 | |
| 5666 bool has_declarations = false; | |
| 5667 | |
| 5668 switch (peek()) { | |
| 5669 case Token::LET: | |
| 5670 if (!IsNextLetKeyword()) goto parse_lhs; | |
| 5671 /* falls through */ | |
| 5672 case Token::VAR: | |
| 5673 case Token::CONST: { | |
| 5674 // The initializer contains declarations | |
| 5675 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')' | |
| 5676 // Statement | |
| 5677 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')' | |
| 5678 // Statement | |
| 5679 has_declarations = true; | |
| 5680 ParseVariableDeclarations(kForStatement, &for_info.parsing_result, | |
| 5681 nullptr, CHECK_OK); | |
| 5682 for_info.position = scanner()->location().beg_pos; | |
| 5683 | |
| 5684 // Only a single declaration is allowed in for-await-of loops | |
| 5685 if (for_info.parsing_result.declarations.length() != 1) { | |
| 5686 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc, | |
| 5687 MessageTemplate::kForInOfLoopMultiBindings, | |
| 5688 "for-await-of"); | |
| 5689 *ok = false; | |
| 5690 return impl()->NullStatement(); | |
| 5691 } | |
| 5692 | |
| 5693 // for-await-of's declarations do not permit initializers. | |
| 5694 if (for_info.parsing_result.first_initializer_loc.IsValid()) { | |
| 5695 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc, | |
| 5696 MessageTemplate::kForInOfLoopInitializer, | |
| 5697 "for-await-of"); | |
| 5698 *ok = false; | |
| 5699 return impl()->NullStatement(); | |
| 5700 } | |
| 5701 break; | |
| 5702 } | |
| 5703 | |
| 5704 default: | |
| 5705 parse_lhs : { | |
| 5706 // The initializer does not contain declarations. | |
| 5707 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')' | |
| 5708 // Statement | |
| 5709 int lhs_beg_pos = peek_position(); | |
| 5710 ExpressionClassifier classifier(this); | |
| 5711 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK); | |
| 5712 int lhs_end_pos = scanner()->location().end_pos; | |
| 5713 | |
| 5714 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) { | |
| 5715 ValidateAssignmentPattern(CHECK_OK); | |
| 5716 } else { | |
| 5717 impl()->RewriteNonPattern(CHECK_OK); | |
| 5718 each_variable = impl()->CheckAndRewriteReferenceExpression( | |
| 5719 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, | |
| 5720 kSyntaxError, CHECK_OK); | |
| 5721 } | |
| 5722 } break; | |
| 5723 } | |
| 5724 | |
| 5725 ExpectContextualKeyword(CStrVector("of"), CHECK_OK); | |
| 5726 int each_keyword_pos = scanner()->location().beg_pos; | |
| 5727 | |
| 5728 const bool kAllowIn = true; | |
| 5729 ExpressionT iterable = impl()->EmptyExpression(); | |
| 5730 | |
| 5731 { | |
| 5732 ExpressionClassifier classifier(this); | |
| 5733 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK); | |
| 5734 impl()->RewriteNonPattern(CHECK_OK); | |
| 5735 } | |
| 5736 | |
| 5737 Expect(Token::RPAREN, CHECK_OK); | |
| 5738 | |
| 5739 { | |
| 5740 ReturnExprScope no_tail_calls(function_state_, | |
| 5741 ReturnExprContext::kInsideForInOfBody); | |
| 5742 BlockState block_state(zone(), &scope_state_); | |
| 5743 block_state.set_start_position(scanner()->location().beg_pos); | |
| 5744 | |
| 5745 // For legacy compat reasons, give for loops similar treatment to | |
| 5746 // if statements in allowing a function declaration for a body | |
| 5747 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); | |
| 5748 block_state.set_end_position(scanner()->location().end_pos); | |
| 5749 | |
| 5750 if (has_declarations) { | |
| 5751 BlockT body_block = impl()->NullBlock(); | |
| 5752 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, | |
| 5753 &each_variable, CHECK_OK); | |
| 5754 body_block->statements()->Add(body, zone()); | |
| 5755 body_block->set_scope(block_state.FinalizedBlockScope()); | |
| 5756 for_state.set_end_position(scanner()->location().end_pos); | |
| 5757 | |
| 5758 const bool finalize = true; | |
| 5759 StatementT final_loop = impl()->InitializeForOfStatement( | |
| 5760 loop, each_variable, iterable, body_block, finalize, | |
| 5761 IteratorType::kAsync, each_keyword_pos); | |
| 5762 | |
| 5763 Scope* for_scope = for_state.FinalizedBlockScope(); | |
| 5764 DCHECK_NULL(for_scope); | |
| 5765 USE(for_scope); | |
| 5766 return final_loop; | |
| 5767 } else { | |
| 5768 const bool finalize = true; | |
| 5769 StatementT final_loop = impl()->InitializeForOfStatement( | |
| 5770 loop, each_variable, iterable, body, finalize, IteratorType::kAsync, | |
| 5771 each_keyword_pos); | |
| 5772 | |
| 5773 Scope* for_scope = for_state.FinalizedBlockScope(); | |
| 5774 DCHECK_NULL(for_scope); | |
| 5775 USE(for_scope); | |
| 5776 Scope* block_scope = block_state.FinalizedBlockScope(); | |
| 5777 DCHECK_NULL(block_scope); | |
| 5778 USE(block_scope); | |
| 5779 return final_loop; | |
| 5780 } | |
| 5781 | |
| 5782 UNREACHABLE(); | |
| 5783 return impl()->NullStatement(); | |
| 5784 } | |
| 5785 } | |
| 5786 | |
| 5632 #undef CHECK_OK | 5787 #undef CHECK_OK |
| 5633 #undef CHECK_OK_CUSTOM | 5788 #undef CHECK_OK_CUSTOM |
| 5634 | 5789 |
| 5635 template <typename Impl> | 5790 template <typename Impl> |
| 5636 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 5791 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
| 5637 Token::Value property) { | 5792 Token::Value property) { |
| 5638 if (property == Token::SMI || property == Token::NUMBER) return; | 5793 if (property == Token::SMI || property == Token::NUMBER) return; |
| 5639 | 5794 |
| 5640 if (IsProto()) { | 5795 if (IsProto()) { |
| 5641 if (has_seen_proto_) { | 5796 if (has_seen_proto_) { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5681 return; | 5836 return; |
| 5682 } | 5837 } |
| 5683 } | 5838 } |
| 5684 | 5839 |
| 5685 #undef CHECK_OK_VOID | 5840 #undef CHECK_OK_VOID |
| 5686 | 5841 |
| 5687 } // namespace internal | 5842 } // namespace internal |
| 5688 } // namespace v8 | 5843 } // namespace v8 |
| 5689 | 5844 |
| 5690 #endif // V8_PARSING_PARSER_BASE_H | 5845 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |