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 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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_dynamic_import_(false) {} | 228 allow_harmony_dynamic_import_(false), |
| 229 allow_harmony_async_iteration_(false) {} | |
| 229 | 230 |
| 230 #define ALLOW_ACCESSORS(name) \ | 231 #define ALLOW_ACCESSORS(name) \ |
| 231 bool allow_##name() const { return allow_##name##_; } \ | 232 bool allow_##name() const { return allow_##name##_; } \ |
| 232 void set_allow_##name(bool allow) { allow_##name##_ = allow; } | 233 void set_allow_##name(bool allow) { allow_##name##_ = allow; } |
| 233 | 234 |
| 234 ALLOW_ACCESSORS(natives); | 235 ALLOW_ACCESSORS(natives); |
| 235 ALLOW_ACCESSORS(tailcalls); | 236 ALLOW_ACCESSORS(tailcalls); |
| 236 ALLOW_ACCESSORS(harmony_do_expressions); | 237 ALLOW_ACCESSORS(harmony_do_expressions); |
| 237 ALLOW_ACCESSORS(harmony_function_sent); | 238 ALLOW_ACCESSORS(harmony_function_sent); |
| 238 ALLOW_ACCESSORS(harmony_restrictive_generators); | 239 ALLOW_ACCESSORS(harmony_restrictive_generators); |
| 239 ALLOW_ACCESSORS(harmony_trailing_commas); | 240 ALLOW_ACCESSORS(harmony_trailing_commas); |
| 240 ALLOW_ACCESSORS(harmony_class_fields); | 241 ALLOW_ACCESSORS(harmony_class_fields); |
| 241 ALLOW_ACCESSORS(harmony_object_rest_spread); | 242 ALLOW_ACCESSORS(harmony_object_rest_spread); |
| 242 ALLOW_ACCESSORS(harmony_dynamic_import); | 243 ALLOW_ACCESSORS(harmony_dynamic_import); |
| 244 ALLOW_ACCESSORS(harmony_async_iteration); | |
| 243 | 245 |
| 244 #undef ALLOW_ACCESSORS | 246 #undef ALLOW_ACCESSORS |
| 245 | 247 |
| 246 uintptr_t stack_limit() const { return stack_limit_; } | 248 uintptr_t stack_limit() const { return stack_limit_; } |
| 247 | 249 |
| 248 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } | 250 void set_stack_limit(uintptr_t stack_limit) { stack_limit_ = stack_limit; } |
| 249 | 251 |
| 250 void set_default_eager_compile_hint( | 252 void set_default_eager_compile_hint( |
| 251 FunctionLiteral::EagerCompileHint eager_compile_hint) { | 253 FunctionLiteral::EagerCompileHint eager_compile_hint) { |
| 252 default_eager_compile_hint_ = eager_compile_hint; | 254 default_eager_compile_hint_ = eager_compile_hint; |
| (...skipping 1047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1300 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, | 1302 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, |
| 1301 ForInfo* for_info, BlockState* for_state, | 1303 ForInfo* for_info, BlockState* for_state, |
| 1302 ZoneList<const AstRawString*>* labels, bool* ok); | 1304 ZoneList<const AstRawString*>* labels, bool* ok); |
| 1303 | 1305 |
| 1304 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' | 1306 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' |
| 1305 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, | 1307 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, |
| 1306 bool bound_names_are_lexical, | 1308 bool bound_names_are_lexical, |
| 1307 ForInfo* for_info, BlockState* for_state, | 1309 ForInfo* for_info, BlockState* for_state, |
| 1308 ZoneList<const AstRawString*>* labels, | 1310 ZoneList<const AstRawString*>* labels, |
| 1309 bool* ok); | 1311 bool* ok); |
| 1312 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels, | |
| 1313 bool* ok); | |
| 1310 | 1314 |
| 1311 bool IsNextLetKeyword(); | 1315 bool IsNextLetKeyword(); |
| 1312 bool IsTrivialExpression(); | 1316 bool IsTrivialExpression(); |
| 1313 | 1317 |
| 1314 // Checks if the expression is a valid reference expression (e.g., on the | 1318 // Checks if the expression is a valid reference expression (e.g., on the |
| 1315 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1319 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
| 1316 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1320 // we allow calls for web compatibility and rewrite them to a runtime throw. |
| 1317 ExpressionT CheckAndRewriteReferenceExpression( | 1321 ExpressionT CheckAndRewriteReferenceExpression( |
| 1318 ExpressionT expression, int beg_pos, int end_pos, | 1322 ExpressionT expression, int beg_pos, int end_pos, |
| 1319 MessageTemplate::Template message, bool* ok); | 1323 MessageTemplate::Template message, bool* ok); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1496 | 1500 |
| 1497 bool allow_natives_; | 1501 bool allow_natives_; |
| 1498 bool allow_tailcalls_; | 1502 bool allow_tailcalls_; |
| 1499 bool allow_harmony_do_expressions_; | 1503 bool allow_harmony_do_expressions_; |
| 1500 bool allow_harmony_function_sent_; | 1504 bool allow_harmony_function_sent_; |
| 1501 bool allow_harmony_restrictive_generators_; | 1505 bool allow_harmony_restrictive_generators_; |
| 1502 bool allow_harmony_trailing_commas_; | 1506 bool allow_harmony_trailing_commas_; |
| 1503 bool allow_harmony_class_fields_; | 1507 bool allow_harmony_class_fields_; |
| 1504 bool allow_harmony_object_rest_spread_; | 1508 bool allow_harmony_object_rest_spread_; |
| 1505 bool allow_harmony_dynamic_import_; | 1509 bool allow_harmony_dynamic_import_; |
| 1510 bool allow_harmony_async_iteration_; | |
| 1506 | 1511 |
| 1507 friend class DiscardableZoneScope; | 1512 friend class DiscardableZoneScope; |
| 1508 }; | 1513 }; |
| 1509 | 1514 |
| 1510 template <typename Impl> | 1515 template <typename Impl> |
| 1511 ParserBase<Impl>::FunctionState::FunctionState( | 1516 ParserBase<Impl>::FunctionState::FunctionState( |
| 1512 FunctionState** function_state_stack, ScopeState** scope_stack, | 1517 FunctionState** function_state_stack, ScopeState** scope_stack, |
| 1513 DeclarationScope* scope) | 1518 DeclarationScope* scope) |
| 1514 : ScopeState(scope_stack, scope), | 1519 : ScopeState(scope_stack, scope), |
| 1515 next_materialized_literal_index_(0), | 1520 next_materialized_literal_index_(0), |
| (...skipping 3292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4808 case Token::SEMICOLON: | 4813 case Token::SEMICOLON: |
| 4809 Next(); | 4814 Next(); |
| 4810 return factory()->NewEmptyStatement(kNoSourcePosition); | 4815 return factory()->NewEmptyStatement(kNoSourcePosition); |
| 4811 case Token::IF: | 4816 case Token::IF: |
| 4812 return ParseIfStatement(labels, ok); | 4817 return ParseIfStatement(labels, ok); |
| 4813 case Token::DO: | 4818 case Token::DO: |
| 4814 return ParseDoWhileStatement(labels, ok); | 4819 return ParseDoWhileStatement(labels, ok); |
| 4815 case Token::WHILE: | 4820 case Token::WHILE: |
| 4816 return ParseWhileStatement(labels, ok); | 4821 return ParseWhileStatement(labels, ok); |
| 4817 case Token::FOR: | 4822 case Token::FOR: |
| 4823 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() && | |
| 4824 PeekAhead() == Token::AWAIT)) { | |
| 4825 return ParseForAwaitStatement(labels, ok); | |
| 4826 } | |
| 4818 return ParseForStatement(labels, ok); | 4827 return ParseForStatement(labels, ok); |
| 4819 case Token::CONTINUE: | 4828 case Token::CONTINUE: |
| 4820 case Token::BREAK: | 4829 case Token::BREAK: |
| 4821 case Token::RETURN: | 4830 case Token::RETURN: |
| 4822 case Token::THROW: | 4831 case Token::THROW: |
| 4823 case Token::TRY: { | 4832 case Token::TRY: { |
| 4824 // These statements must have their labels preserved in an enclosing | 4833 // These statements must have their labels preserved in an enclosing |
| 4825 // block, as the corresponding AST nodes do not currently store their | 4834 // block, as the corresponding AST nodes do not currently store their |
| 4826 // labels. | 4835 // labels. |
| 4827 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4836 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
| (...skipping 886 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5714 } | 5723 } |
| 5715 | 5724 |
| 5716 template <typename Impl> | 5725 template <typename Impl> |
| 5717 void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) { | 5726 void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) { |
| 5718 if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) { | 5727 if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) { |
| 5719 var->set_maybe_assigned(); | 5728 var->set_maybe_assigned(); |
| 5720 } | 5729 } |
| 5721 } | 5730 } |
| 5722 | 5731 |
| 5723 template <typename Impl> | 5732 template <typename Impl> |
| 5733 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement( | |
| 5734 ZoneList<const AstRawString*>* labels, bool* ok) { | |
| 5735 // for await '(' ForDeclaration of AssignmentExpression ')' | |
| 5736 DCHECK(is_async_function()); | |
| 5737 DCHECK(allow_harmony_async_iteration()); | |
| 5738 | |
| 5739 int stmt_pos = peek_position(); | |
| 5740 | |
| 5741 ForInfo for_info(this); | |
| 5742 for_info.mode = ForEachStatement::ITERATE; | |
| 5743 | |
| 5744 // Create an in-between scope for let-bound iteration variables. | |
| 5745 BlockState for_state(zone(), &scope_state_); | |
| 5746 Expect(Token::FOR, CHECK_OK); | |
| 5747 Expect(Token::AWAIT, CHECK_OK); | |
| 5748 Expect(Token::LPAREN, CHECK_OK); | |
| 5749 for_state.set_start_position(scanner()->location().beg_pos); | |
| 5750 for_state.set_is_hidden(); | |
| 5751 | |
| 5752 auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); | |
| 5753 typename Types::Target target(this, loop); | |
| 5754 | |
| 5755 ExpressionT each_variable = impl()->EmptyExpression(); | |
| 5756 | |
| 5757 bool has_declarations = false; | |
| 5758 | |
| 5759 switch (peek()) { | |
| 5760 case Token::LET: | |
| 5761 if (!IsNextLetKeyword()) goto parse_lhs; | |
|
adamk
2017/02/14 18:47:53
This is the first goto in the parser. Given that i
caitp
2017/02/14 20:27:29
Seems harder to read, to me, but alright
caitp
2017/02/14 21:40:58
Done.
| |
| 5762 /* falls through */ | |
| 5763 case Token::VAR: | |
| 5764 case Token::CONST: { | |
| 5765 // The initializer contains declarations | |
| 5766 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')' | |
| 5767 // Statement | |
| 5768 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')' | |
| 5769 // Statement | |
| 5770 has_declarations = true; | |
| 5771 ParseVariableDeclarations(kForStatement, &for_info.parsing_result, | |
| 5772 nullptr, CHECK_OK); | |
| 5773 for_info.position = scanner()->location().beg_pos; | |
| 5774 | |
| 5775 // Only a single declaration is allowed in for-await-of loops | |
| 5776 if (for_info.parsing_result.declarations.length() != 1) { | |
| 5777 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc, | |
| 5778 MessageTemplate::kForInOfLoopMultiBindings, | |
| 5779 "for-await-of"); | |
| 5780 *ok = false; | |
| 5781 return impl()->NullStatement(); | |
| 5782 } | |
| 5783 | |
| 5784 // for-await-of's declarations do not permit initializers. | |
| 5785 if (for_info.parsing_result.first_initializer_loc.IsValid()) { | |
| 5786 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc, | |
| 5787 MessageTemplate::kForInOfLoopInitializer, | |
| 5788 "for-await-of"); | |
| 5789 *ok = false; | |
| 5790 return impl()->NullStatement(); | |
| 5791 } | |
| 5792 break; | |
| 5793 } | |
| 5794 | |
| 5795 default: | |
| 5796 parse_lhs : { | |
| 5797 // The initializer does not contain declarations. | |
| 5798 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')' | |
| 5799 // Statement | |
| 5800 int lhs_beg_pos = peek_position(); | |
| 5801 ExpressionClassifier classifier(this); | |
| 5802 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK); | |
| 5803 int lhs_end_pos = scanner()->location().end_pos; | |
| 5804 | |
| 5805 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) { | |
| 5806 ValidateAssignmentPattern(CHECK_OK); | |
| 5807 } else { | |
| 5808 impl()->RewriteNonPattern(CHECK_OK); | |
| 5809 each_variable = impl()->CheckAndRewriteReferenceExpression( | |
| 5810 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor, | |
| 5811 kSyntaxError, CHECK_OK); | |
| 5812 } | |
| 5813 } break; | |
| 5814 } | |
| 5815 | |
| 5816 ExpectContextualKeyword(CStrVector("of"), CHECK_OK); | |
| 5817 int each_keyword_pos = scanner()->location().beg_pos; | |
| 5818 | |
| 5819 const bool kAllowIn = true; | |
| 5820 ExpressionT iterable = impl()->EmptyExpression(); | |
| 5821 | |
| 5822 { | |
| 5823 ExpressionClassifier classifier(this); | |
| 5824 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK); | |
| 5825 impl()->RewriteNonPattern(CHECK_OK); | |
| 5826 } | |
| 5827 | |
| 5828 Expect(Token::RPAREN, CHECK_OK); | |
| 5829 | |
| 5830 StatementT final_loop = impl()->NullStatement(); | |
| 5831 { | |
| 5832 ReturnExprScope no_tail_calls(function_state_, | |
| 5833 ReturnExprContext::kInsideForInOfBody); | |
| 5834 BlockState block_state(zone(), &scope_state_); | |
| 5835 block_state.set_start_position(scanner()->location().beg_pos); | |
| 5836 | |
| 5837 // For legacy compat reasons, give for loops similar treatment to | |
|
adamk
2017/02/14 18:47:53
Seems odd that new syntax still maintains this leg
caitp
2017/02/14 20:27:29
The spec doesn't say anything about any of this, b
| |
| 5838 // if statements in allowing a function declaration for a body | |
| 5839 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); | |
| 5840 block_state.set_end_position(scanner()->location().end_pos); | |
| 5841 | |
| 5842 if (has_declarations) { | |
| 5843 BlockT body_block = impl()->NullBlock(); | |
| 5844 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, | |
| 5845 &each_variable, CHECK_OK); | |
| 5846 body_block->statements()->Add(body, zone()); | |
| 5847 body_block->set_scope(block_state.FinalizedBlockScope()); | |
| 5848 for_state.set_end_position(scanner()->location().end_pos); | |
| 5849 | |
| 5850 const bool finalize = true; | |
| 5851 final_loop = impl()->InitializeForOfStatement( | |
| 5852 loop, each_variable, iterable, body_block, finalize, | |
| 5853 IteratorType::kAsync, each_keyword_pos); | |
| 5854 } else { | |
| 5855 const bool finalize = true; | |
| 5856 final_loop = impl()->InitializeForOfStatement( | |
| 5857 loop, each_variable, iterable, body, finalize, IteratorType::kAsync, | |
| 5858 each_keyword_pos); | |
| 5859 | |
| 5860 Scope* for_scope = for_state.FinalizedBlockScope(); | |
| 5861 DCHECK_NULL(for_scope); | |
| 5862 USE(for_scope); | |
| 5863 Scope* block_scope = block_state.FinalizedBlockScope(); | |
| 5864 DCHECK_NULL(block_scope); | |
| 5865 USE(block_scope); | |
| 5866 return final_loop; | |
| 5867 } | |
| 5868 } | |
| 5869 | |
| 5870 DCHECK(has_declarations); | |
| 5871 BlockT init_block = | |
| 5872 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok); | |
| 5873 | |
| 5874 for_state.set_end_position(scanner()->location().end_pos); | |
| 5875 Scope* for_scope = for_state.FinalizedBlockScope(); | |
| 5876 // Parsed for-in loop w/ variable declarations. | |
| 5877 if (!impl()->IsNullStatement(init_block)) { | |
| 5878 init_block->statements()->Add(final_loop, zone()); | |
| 5879 init_block->set_scope(for_scope); | |
| 5880 return init_block; | |
| 5881 } | |
| 5882 DCHECK_NULL(for_scope); | |
| 5883 return final_loop; | |
| 5884 } | |
| 5885 | |
| 5886 template <typename Impl> | |
| 5724 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 5887 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
| 5725 Token::Value property) { | 5888 Token::Value property) { |
| 5726 if (property == Token::SMI || property == Token::NUMBER) return; | 5889 if (property == Token::SMI || property == Token::NUMBER) return; |
| 5727 | 5890 |
| 5728 if (IsProto()) { | 5891 if (IsProto()) { |
| 5729 if (has_seen_proto_) { | 5892 if (has_seen_proto_) { |
| 5730 this->parser()->classifier()->RecordExpressionError( | 5893 this->parser()->classifier()->RecordExpressionError( |
| 5731 this->scanner()->location(), MessageTemplate::kDuplicateProto); | 5894 this->scanner()->location(), MessageTemplate::kDuplicateProto); |
| 5732 return; | 5895 return; |
| 5733 } | 5896 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5771 } | 5934 } |
| 5772 | 5935 |
| 5773 #undef CHECK_OK | 5936 #undef CHECK_OK |
| 5774 #undef CHECK_OK_CUSTOM | 5937 #undef CHECK_OK_CUSTOM |
| 5775 #undef CHECK_OK_VOID | 5938 #undef CHECK_OK_VOID |
| 5776 | 5939 |
| 5777 } // namespace internal | 5940 } // namespace internal |
| 5778 } // namespace v8 | 5941 } // namespace v8 |
| 5779 | 5942 |
| 5780 #endif // V8_PARSING_PARSER_BASE_H | 5943 #endif // V8_PARSING_PARSER_BASE_H |
| OLD | NEW |