Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(71)

Side by Side Diff: src/parsing/parser-base.h

Issue 2637403008: [async-iteration] add support for for-await-of loops in Async Functions (Closed)
Patch Set: remove changes to ParserTarget / PreParserTarget Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 1058 matching lines...) Expand 10 before | Expand all | Expand 10 after
1309 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos, 1311 int stmt_pos, ExpressionT expression, int lhs_beg_pos, int lhs_end_pos,
1310 ForInfo* for_info, BlockState* for_state, 1312 ForInfo* for_info, BlockState* for_state,
1311 ZoneList<const AstRawString*>* labels, bool* ok); 1313 ZoneList<const AstRawString*>* labels, bool* ok);
1312 1314
1313 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }' 1315 // Parse a C-style for loop: 'for (<init>; <cond>; <step>) { ... }'
1314 StatementT ParseStandardForLoop(int stmt_pos, StatementT init, 1316 StatementT ParseStandardForLoop(int stmt_pos, StatementT init,
1315 bool bound_names_are_lexical, 1317 bool bound_names_are_lexical,
1316 ForInfo* for_info, BlockState* for_state, 1318 ForInfo* for_info, BlockState* for_state,
1317 ZoneList<const AstRawString*>* labels, 1319 ZoneList<const AstRawString*>* labels,
1318 bool* ok); 1320 bool* ok);
1321 StatementT ParseForAwaitStatement(ZoneList<const AstRawString*>* labels,
1322 bool* ok);
1319 1323
1320 bool IsNextLetKeyword(); 1324 bool IsNextLetKeyword();
1321 bool IsTrivialExpression(); 1325 bool IsTrivialExpression();
1322 1326
1323 // Checks if the expression is a valid reference expression (e.g., on the 1327 // Checks if the expression is a valid reference expression (e.g., on the
1324 // left-hand side of assignments). Although ruled out by ECMA as early errors, 1328 // left-hand side of assignments). Although ruled out by ECMA as early errors,
1325 // we allow calls for web compatibility and rewrite them to a runtime throw. 1329 // we allow calls for web compatibility and rewrite them to a runtime throw.
1326 ExpressionT CheckAndRewriteReferenceExpression( 1330 ExpressionT CheckAndRewriteReferenceExpression(
1327 ExpressionT expression, int beg_pos, int end_pos, 1331 ExpressionT expression, int beg_pos, int end_pos,
1328 MessageTemplate::Template message, bool* ok); 1332 MessageTemplate::Template message, bool* ok);
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 int function_literal_id_; 1481 int function_literal_id_;
1478 1482
1479 bool allow_natives_; 1483 bool allow_natives_;
1480 bool allow_tailcalls_; 1484 bool allow_tailcalls_;
1481 bool allow_harmony_do_expressions_; 1485 bool allow_harmony_do_expressions_;
1482 bool allow_harmony_function_sent_; 1486 bool allow_harmony_function_sent_;
1483 bool allow_harmony_restrictive_generators_; 1487 bool allow_harmony_restrictive_generators_;
1484 bool allow_harmony_trailing_commas_; 1488 bool allow_harmony_trailing_commas_;
1485 bool allow_harmony_class_fields_; 1489 bool allow_harmony_class_fields_;
1486 bool allow_harmony_object_rest_spread_; 1490 bool allow_harmony_object_rest_spread_;
1491 bool allow_harmony_async_iteration_;
1487 1492
1488 friend class DiscardableZoneScope; 1493 friend class DiscardableZoneScope;
1489 }; 1494 };
1490 1495
1491 template <typename Impl> 1496 template <typename Impl>
1492 ParserBase<Impl>::FunctionState::FunctionState( 1497 ParserBase<Impl>::FunctionState::FunctionState(
1493 FunctionState** function_state_stack, ScopeState** scope_stack, 1498 FunctionState** function_state_stack, ScopeState** scope_stack,
1494 DeclarationScope* scope) 1499 DeclarationScope* scope)
1495 : ScopeState(scope_stack, scope), 1500 : ScopeState(scope_stack, scope),
1496 next_materialized_literal_index_(0), 1501 next_materialized_literal_index_(0),
(...skipping 3273 matching lines...) Expand 10 before | Expand all | Expand 10 after
4770 case Token::SEMICOLON: 4775 case Token::SEMICOLON:
4771 Next(); 4776 Next();
4772 return factory()->NewEmptyStatement(kNoSourcePosition); 4777 return factory()->NewEmptyStatement(kNoSourcePosition);
4773 case Token::IF: 4778 case Token::IF:
4774 return ParseIfStatement(labels, ok); 4779 return ParseIfStatement(labels, ok);
4775 case Token::DO: 4780 case Token::DO:
4776 return ParseDoWhileStatement(labels, ok); 4781 return ParseDoWhileStatement(labels, ok);
4777 case Token::WHILE: 4782 case Token::WHILE:
4778 return ParseWhileStatement(labels, ok); 4783 return ParseWhileStatement(labels, ok);
4779 case Token::FOR: 4784 case Token::FOR:
4785 if (V8_UNLIKELY(allow_harmony_async_iteration() && is_async_function() &&
4786 PeekAhead() == Token::AWAIT)) {
4787 return ParseForAwaitStatement(labels, ok);
4788 }
4780 return ParseForStatement(labels, ok); 4789 return ParseForStatement(labels, ok);
4781 case Token::CONTINUE: 4790 case Token::CONTINUE:
4782 case Token::BREAK: 4791 case Token::BREAK:
4783 case Token::RETURN: 4792 case Token::RETURN:
4784 case Token::THROW: 4793 case Token::THROW:
4785 case Token::TRY: { 4794 case Token::TRY: {
4786 // These statements must have their labels preserved in an enclosing 4795 // These statements must have their labels preserved in an enclosing
4787 // block, as the corresponding AST nodes do not currently store their 4796 // block, as the corresponding AST nodes do not currently store their
4788 // labels. 4797 // labels.
4789 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. 4798 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes.
(...skipping 877 matching lines...) Expand 10 before | Expand all | Expand 10 after
5667 block->statements()->Add(loop, zone()); 5676 block->statements()->Add(loop, zone());
5668 block->set_scope(for_scope); 5677 block->set_scope(for_scope);
5669 loop->Initialize(init, cond, next, body); 5678 loop->Initialize(init, cond, next, body);
5670 return block; 5679 return block;
5671 } 5680 }
5672 5681
5673 loop->Initialize(init, cond, next, body); 5682 loop->Initialize(init, cond, next, body);
5674 return loop; 5683 return loop;
5675 } 5684 }
5676 5685
5686 template <typename Impl>
5687 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForAwaitStatement(
5688 ZoneList<const AstRawString*>* labels, bool* ok) {
5689 // for await '(' ForDeclaration of AssignmentExpression ')'
5690 DCHECK(is_async_function());
5691 DCHECK(allow_harmony_async_iteration());
5692
5693 int stmt_pos = peek_position();
5694
5695 ForInfo for_info(this);
5696 for_info.mode = ForEachStatement::ITERATE;
5697
5698 // Create an in-between scope for let-bound iteration variables.
5699 BlockState for_state(zone(), &scope_state_);
5700 Expect(Token::FOR, CHECK_OK);
5701 Expect(Token::AWAIT, CHECK_OK);
5702 Expect(Token::LPAREN, CHECK_OK);
5703 for_state.set_start_position(scanner()->location().beg_pos);
5704 for_state.set_is_hidden();
5705
5706 auto loop = factory()->NewForEachStatement(for_info.mode, labels, stmt_pos);
5707 typename Types::Target target(this, loop);
5708
5709 ExpressionT each_variable = impl()->EmptyExpression();
5710
5711 bool has_declarations = false;
5712
5713 switch (peek()) {
5714 case Token::LET:
5715 if (!IsNextLetKeyword()) goto parse_lhs;
5716 /* falls through */
5717 case Token::VAR:
5718 case Token::CONST: {
5719 // The initializer contains declarations
5720 // 'for' 'await' '(' ForDeclaration 'of' AssignmentExpression ')'
5721 // Statement
5722 // 'for' 'await' '(' 'var' ForBinding 'of' AssignmentExpression ')'
5723 // Statement
5724 has_declarations = true;
5725 ParseVariableDeclarations(kForStatement, &for_info.parsing_result,
5726 nullptr, CHECK_OK);
5727 for_info.position = scanner()->location().beg_pos;
5728
5729 // Only a single declaration is allowed in for-await-of loops
5730 if (for_info.parsing_result.declarations.length() != 1) {
5731 impl()->ReportMessageAt(for_info.parsing_result.bindings_loc,
5732 MessageTemplate::kForInOfLoopMultiBindings,
5733 "for-await-of");
5734 *ok = false;
5735 return impl()->NullStatement();
5736 }
5737
5738 // for-await-of's declarations do not permit initializers.
5739 if (for_info.parsing_result.first_initializer_loc.IsValid()) {
5740 impl()->ReportMessageAt(for_info.parsing_result.first_initializer_loc,
5741 MessageTemplate::kForInOfLoopInitializer,
5742 "for-await-of");
5743 *ok = false;
5744 return impl()->NullStatement();
5745 }
5746 break;
5747 }
5748
5749 default:
5750 parse_lhs : {
5751 // The initializer does not contain declarations.
5752 // 'for' 'await' '(' LeftHandSideExpression 'of' AssignmentExpression ')'
5753 // Statement
5754 int lhs_beg_pos = peek_position();
5755 ExpressionClassifier classifier(this);
5756 ExpressionT lhs = each_variable = ParseLeftHandSideExpression(CHECK_OK);
5757 int lhs_end_pos = scanner()->location().end_pos;
5758
5759 if (lhs->IsArrayLiteral() || lhs->IsObjectLiteral()) {
5760 ValidateAssignmentPattern(CHECK_OK);
5761 } else {
5762 impl()->RewriteNonPattern(CHECK_OK);
5763 each_variable = impl()->CheckAndRewriteReferenceExpression(
5764 lhs, lhs_beg_pos, lhs_end_pos, MessageTemplate::kInvalidLhsInFor,
5765 kSyntaxError, CHECK_OK);
5766 }
5767 } break;
5768 }
5769
5770 ExpectContextualKeyword(CStrVector("of"), CHECK_OK);
5771 int each_keyword_pos = scanner()->location().beg_pos;
5772
5773 const bool kAllowIn = true;
5774 ExpressionT iterable = impl()->EmptyExpression();
5775
5776 {
5777 ExpressionClassifier classifier(this);
5778 iterable = ParseAssignmentExpression(kAllowIn, CHECK_OK);
5779 impl()->RewriteNonPattern(CHECK_OK);
5780 }
5781
5782 Expect(Token::RPAREN, CHECK_OK);
5783
5784 StatementT final_loop = impl()->NullStatement();
5785 {
5786 ReturnExprScope no_tail_calls(function_state_,
5787 ReturnExprContext::kInsideForInOfBody);
5788 BlockState block_state(zone(), &scope_state_);
5789 block_state.set_start_position(scanner()->location().beg_pos);
5790
5791 // For legacy compat reasons, give for loops similar treatment to
5792 // if statements in allowing a function declaration for a body
5793 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK);
5794 block_state.set_end_position(scanner()->location().end_pos);
5795
5796 if (has_declarations) {
5797 BlockT body_block = impl()->NullBlock();
5798 impl()->DesugarBindingInForEachStatement(&for_info, &body_block,
5799 &each_variable, CHECK_OK);
5800 body_block->statements()->Add(body, zone());
5801 body_block->set_scope(block_state.FinalizedBlockScope());
5802 for_state.set_end_position(scanner()->location().end_pos);
5803
5804 const bool finalize = true;
5805 final_loop = impl()->InitializeForOfStatement(
5806 loop, each_variable, iterable, body_block, finalize,
5807 IteratorType::kAsync, each_keyword_pos);
5808 } else {
5809 const bool finalize = true;
5810 final_loop = impl()->InitializeForOfStatement(
5811 loop, each_variable, iterable, body, finalize, IteratorType::kAsync,
5812 each_keyword_pos);
5813
5814 Scope* for_scope = for_state.FinalizedBlockScope();
5815 DCHECK_NULL(for_scope);
5816 USE(for_scope);
5817 Scope* block_scope = block_state.FinalizedBlockScope();
5818 DCHECK_NULL(block_scope);
5819 USE(block_scope);
5820 return final_loop;
5821 }
5822 }
5823
5824 DCHECK(has_declarations);
5825 BlockT init_block =
5826 impl()->CreateForEachStatementTDZ(impl()->NullBlock(), for_info, ok);
5827
5828 for_state.set_end_position(scanner()->location().end_pos);
5829 Scope* for_scope = for_state.FinalizedBlockScope();
5830 // Parsed for-in loop w/ variable declarations.
5831 if (!impl()->IsNullStatement(init_block)) {
5832 init_block->statements()->Add(final_loop, zone());
5833 init_block->set_scope(for_scope);
5834 return init_block;
5835 }
5836 DCHECK_NULL(for_scope);
5837 return final_loop;
5838 }
5839
5677 #undef CHECK_OK 5840 #undef CHECK_OK
5678 #undef CHECK_OK_CUSTOM 5841 #undef CHECK_OK_CUSTOM
5679 5842
5680 template <typename Impl> 5843 template <typename Impl>
5681 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( 5844 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
5682 Token::Value property) { 5845 Token::Value property) {
5683 if (property == Token::SMI || property == Token::NUMBER) return; 5846 if (property == Token::SMI || property == Token::NUMBER) return;
5684 5847
5685 if (IsProto()) { 5848 if (IsProto()) {
5686 if (has_seen_proto_) { 5849 if (has_seen_proto_) {
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
5726 return; 5889 return;
5727 } 5890 }
5728 } 5891 }
5729 5892
5730 #undef CHECK_OK_VOID 5893 #undef CHECK_OK_VOID
5731 5894
5732 } // namespace internal 5895 } // namespace internal
5733 } // namespace v8 5896 } // namespace v8
5734 5897
5735 #endif // V8_PARSING_PARSER_BASE_H 5898 #endif // V8_PARSING_PARSER_BASE_H
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698