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 |