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 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
649 Variable* variable; | 649 Variable* variable; |
650 ExpressionT pattern; | 650 ExpressionT pattern; |
651 Scope* scope; | 651 Scope* scope; |
652 BlockT init_block; | 652 BlockT init_block; |
653 BlockT inner_block; | 653 BlockT inner_block; |
654 bool for_promise_reject; | 654 bool for_promise_reject; |
655 ZoneList<const AstRawString*> bound_names; | 655 ZoneList<const AstRawString*> bound_names; |
656 TailCallExpressionList tail_call_expressions; | 656 TailCallExpressionList tail_call_expressions; |
657 }; | 657 }; |
658 | 658 |
659 struct ForInfo { | |
660 public: | |
661 explicit ForInfo(ParserBase* parser) | |
662 : bound_names(1, parser->zone()), | |
663 bound_names_are_lexical(false), | |
664 mode(ForEachStatement::ENUMERATE), | |
665 each_loc(), | |
666 parsing_result() {} | |
667 ZoneList<const AstRawString*> bound_names; | |
668 bool bound_names_are_lexical; | |
669 ForEachStatement::VisitMode mode; | |
670 Scanner::Location each_loc; | |
671 DeclarationParsingResult parsing_result; | |
672 }; | |
673 | |
659 DeclarationScope* NewScriptScope() const { | 674 DeclarationScope* NewScriptScope() const { |
660 return new (zone()) DeclarationScope(zone(), ast_value_factory()); | 675 return new (zone()) DeclarationScope(zone(), ast_value_factory()); |
661 } | 676 } |
662 | 677 |
663 DeclarationScope* NewVarblockScope() const { | 678 DeclarationScope* NewVarblockScope() const { |
664 return new (zone()) DeclarationScope(zone(), scope(), BLOCK_SCOPE); | 679 return new (zone()) DeclarationScope(zone(), scope(), BLOCK_SCOPE); |
665 } | 680 } |
666 | 681 |
667 ModuleScope* NewModuleScope(DeclarationScope* parent) const { | 682 ModuleScope* NewModuleScope(DeclarationScope* parent) const { |
668 return new (zone()) ModuleScope(parent, ast_value_factory()); | 683 return new (zone()) ModuleScope(parent, ast_value_factory()); |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1243 StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels, | 1258 StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels, |
1244 bool* ok); | 1259 bool* ok); |
1245 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, | 1260 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, |
1246 bool* ok); | 1261 bool* ok); |
1247 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, | 1262 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, |
1248 bool* ok); | 1263 bool* ok); |
1249 StatementT ParseThrowStatement(bool* ok); | 1264 StatementT ParseThrowStatement(bool* ok); |
1250 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, | 1265 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, |
1251 bool* ok); | 1266 bool* ok); |
1252 StatementT ParseTryStatement(bool* ok); | 1267 StatementT ParseTryStatement(bool* ok); |
1253 Statement* ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); | 1268 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); |
1254 | 1269 |
1255 bool IsNextLetKeyword(); | 1270 bool IsNextLetKeyword(); |
1256 bool IsTrivialExpression(); | 1271 bool IsTrivialExpression(); |
1257 | 1272 |
1258 // Checks if the expression is a valid reference expression (e.g., on the | 1273 // Checks if the expression is a valid reference expression (e.g., on the |
1259 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1274 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
1260 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1275 // we allow calls for web compatibility and rewrite them to a runtime throw. |
1261 ExpressionT CheckAndRewriteReferenceExpression( | 1276 ExpressionT CheckAndRewriteReferenceExpression( |
1262 ExpressionT expression, int beg_pos, int end_pos, | 1277 ExpressionT expression, int beg_pos, int end_pos, |
1263 MessageTemplate::Template message, bool* ok); | 1278 MessageTemplate::Template message, bool* ok); |
(...skipping 3079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4343 case Token::SEMICOLON: | 4358 case Token::SEMICOLON: |
4344 Next(); | 4359 Next(); |
4345 return factory()->NewEmptyStatement(kNoSourcePosition); | 4360 return factory()->NewEmptyStatement(kNoSourcePosition); |
4346 case Token::IF: | 4361 case Token::IF: |
4347 return ParseIfStatement(labels, ok); | 4362 return ParseIfStatement(labels, ok); |
4348 case Token::DO: | 4363 case Token::DO: |
4349 return ParseDoWhileStatement(labels, ok); | 4364 return ParseDoWhileStatement(labels, ok); |
4350 case Token::WHILE: | 4365 case Token::WHILE: |
4351 return ParseWhileStatement(labels, ok); | 4366 return ParseWhileStatement(labels, ok); |
4352 case Token::FOR: | 4367 case Token::FOR: |
4353 return impl()->ParseForStatement(labels, ok); | 4368 return ParseForStatement(labels, ok); |
4354 case Token::CONTINUE: | 4369 case Token::CONTINUE: |
4355 case Token::BREAK: | 4370 case Token::BREAK: |
4356 case Token::RETURN: | 4371 case Token::RETURN: |
4357 case Token::THROW: | 4372 case Token::THROW: |
4358 case Token::TRY: { | 4373 case Token::TRY: { |
4359 // These statements must have their labels preserved in an enclosing | 4374 // These statements must have their labels preserved in an enclosing |
4360 // block, as the corresponding AST nodes do not currently store their | 4375 // block, as the corresponding AST nodes do not currently store their |
4361 // labels. | 4376 // labels. |
4362 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4377 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
4363 if (labels == nullptr) { | 4378 if (labels == nullptr) { |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4970 MessageTemplate::kUnexpectedTailCallInCatchBlock); | 4985 MessageTemplate::kUnexpectedTailCallInCatchBlock); |
4971 *ok = false; | 4986 *ok = false; |
4972 return impl()->NullStatement(); | 4987 return impl()->NullStatement(); |
4973 } | 4988 } |
4974 } | 4989 } |
4975 | 4990 |
4976 return impl()->RewriteTryStatement(try_block, catch_block, finally_block, | 4991 return impl()->RewriteTryStatement(try_block, catch_block, finally_block, |
4977 catch_info, pos); | 4992 catch_info, pos); |
4978 } | 4993 } |
4979 | 4994 |
4980 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, | 4995 template <typename Impl> |
4981 bool* ok) { | 4996 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( |
4997 ZoneList<const AstRawString*>* labels, bool* ok) { | |
4982 int stmt_pos = peek_position(); | 4998 int stmt_pos = peek_position(); |
4983 Statement* init = NULL; | 4999 ForInfo for_info(this); |
4984 ZoneList<const AstRawString*> bound_names(1, zone()); | |
4985 bool bound_names_are_lexical = false; | |
4986 | 5000 |
4987 // Create an in-between scope for let-bound iteration variables. | 5001 // Create an in-between scope for let-bound iteration variables. |
4988 BlockState for_state(&scope_state_); | 5002 BlockState for_state(&scope_state_); |
4989 Expect(Token::FOR, CHECK_OK); | 5003 Expect(Token::FOR, CHECK_OK); |
4990 Expect(Token::LPAREN, CHECK_OK); | 5004 Expect(Token::LPAREN, CHECK_OK); |
4991 for_state.set_start_position(scanner()->location().beg_pos); | 5005 for_state.set_start_position(scanner()->location().beg_pos); |
4992 for_state.set_is_hidden(); | 5006 for_state.set_is_hidden(); |
4993 DeclarationParsingResult parsing_result; | 5007 |
5008 StatementT init = impl()->NullStatement(); | |
4994 if (peek() != Token::SEMICOLON) { | 5009 if (peek() != Token::SEMICOLON) { |
5010 // An initializer is present. | |
4995 if (peek() == Token::VAR || peek() == Token::CONST || | 5011 if (peek() == Token::VAR || peek() == Token::CONST || |
4996 (peek() == Token::LET && IsNextLetKeyword())) { | 5012 (peek() == Token::LET && IsNextLetKeyword())) { |
4997 ParseVariableDeclarations(kForStatement, &parsing_result, nullptr, | 5013 // The initializer contains declarations. |
4998 CHECK_OK); | 5014 ParseVariableDeclarations(kForStatement, &for_info.parsing_result, |
5015 nullptr, CHECK_OK); | |
5016 for_info.bound_names_are_lexical = | |
marja
2016/09/20 19:36:30
bound_names_are_lexical is now redundant, right? M
nickie
2016/09/21 09:20:02
Yes. I'm removing it from ForInfo but I'm keeping
| |
5017 IsLexicalVariableMode(for_info.parsing_result.descriptor.mode); | |
5018 for_info.each_loc = scanner()->location(); | |
4999 | 5019 |
5000 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE; | 5020 if (CheckInOrOf(&for_info.mode)) { |
5001 int each_beg_pos = scanner()->location().beg_pos; | 5021 // Just one declaration followed by in/of. |
5002 int each_end_pos = scanner()->location().end_pos; | 5022 if (for_info.parsing_result.declarations.length() != 1) { |
5003 | 5023 impl()->ReportMessageAt( |
5004 if (CheckInOrOf(&mode)) { | 5024 for_info.parsing_result.bindings_loc, |
5005 if (parsing_result.declarations.length() != 1) { | 5025 MessageTemplate::kForInOfLoopMultiBindings, |
5006 ReportMessageAt(parsing_result.bindings_loc, | 5026 ForEachStatement::VisitModeString(for_info.mode)); |
5007 MessageTemplate::kForInOfLoopMultiBindings, | |
5008 ForEachStatement::VisitModeString(mode)); | |
5009 *ok = false; | 5027 *ok = false; |
5010 return nullptr; | 5028 return impl()->NullStatement(); |
5011 } | 5029 } |
5012 DeclarationParsingResult::Declaration& decl = | 5030 if (for_info.parsing_result.first_initializer_loc.IsValid() && |
5013 parsing_result.declarations[0]; | 5031 (is_strict(language_mode()) || |
5014 if (parsing_result.first_initializer_loc.IsValid() && | 5032 for_info.mode == ForEachStatement::ITERATE || |
marja
2016/09/21 08:23:21
Random whining unrelated to this CL: Why do we nee
nickie
2016/09/21 09:20:02
I agree. Also, it seems that this is used only lo
| |
5015 (is_strict(language_mode()) || mode == ForEachStatement::ITERATE || | 5033 IsLexicalVariableMode(for_info.parsing_result.descriptor.mode) || |
5016 IsLexicalVariableMode(parsing_result.descriptor.mode) || | 5034 !impl()->IsIdentifier( |
5017 !decl.pattern->IsVariableProxy() || allow_harmony_for_in())) { | 5035 for_info.parsing_result.declarations[0].pattern) || |
5036 allow_harmony_for_in())) { | |
5018 // Only increment the use count if we would have let this through | 5037 // Only increment the use count if we would have let this through |
5019 // without the flag. | 5038 // without the flag. |
5020 if (allow_harmony_for_in()) { | 5039 if (allow_harmony_for_in()) { |
5021 ++use_counts_[v8::Isolate::kForInInitializer]; | 5040 impl()->CountUsage(v8::Isolate::kForInInitializer); |
5022 } | 5041 } |
5023 ReportMessageAt(parsing_result.first_initializer_loc, | 5042 impl()->ReportMessageAt( |
5024 MessageTemplate::kForInOfLoopInitializer, | 5043 for_info.parsing_result.first_initializer_loc, |
5025 ForEachStatement::VisitModeString(mode)); | 5044 MessageTemplate::kForInOfLoopInitializer, |
5045 ForEachStatement::VisitModeString(for_info.mode)); | |
5026 *ok = false; | 5046 *ok = false; |
5027 return nullptr; | 5047 return impl()->NullStatement(); |
5028 } | 5048 } |
5029 | 5049 |
5030 Block* init_block = nullptr; | 5050 BlockT init_block = impl()->RewriteForVarInLegacy(&for_info); |
5031 bound_names_are_lexical = | |
5032 IsLexicalVariableMode(parsing_result.descriptor.mode); | |
5033 | 5051 |
5034 // special case for legacy for (var ... = ... in ...) | 5052 auto loop = |
marja
2016/09/20 19:36:30
I was thinking about the use of "auto" here (and b
nickie
2016/09/21 09:20:02
Yes, that's precisely what it does. (BTW, it's us
marja
2016/09/21 10:31:42
Ok, then it's fine.
| |
5035 if (!bound_names_are_lexical && decl.pattern->IsVariableProxy() && | 5053 factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); |
5036 decl.initializer != nullptr) { | 5054 typename Types::Target target(this, loop); |
5037 DCHECK(!allow_harmony_for_in()); | |
5038 ++use_counts_[v8::Isolate::kForInInitializer]; | |
5039 const AstRawString* name = | |
5040 decl.pattern->AsVariableProxy()->raw_name(); | |
5041 VariableProxy* single_var = NewUnresolved(name); | |
5042 init_block = factory()->NewBlock( | |
5043 nullptr, 2, true, parsing_result.descriptor.declaration_pos); | |
5044 init_block->statements()->Add( | |
5045 factory()->NewExpressionStatement( | |
5046 factory()->NewAssignment(Token::ASSIGN, single_var, | |
5047 decl.initializer, kNoSourcePosition), | |
5048 kNoSourcePosition), | |
5049 zone()); | |
5050 } | |
5051 | 5055 |
5052 // Rewrite a for-in/of statement of the form | 5056 int each_keyword_pos = scanner()->location().beg_pos; |
5053 // | |
5054 // for (let/const/var x in/of e) b | |
5055 // | |
5056 // into | |
5057 // | |
5058 // { | |
5059 // <let x' be a temporary variable> | |
5060 // for (x' in/of e) { | |
5061 // let/const/var x; | |
5062 // x = x'; | |
5063 // b; | |
5064 // } | |
5065 // let x; // for TDZ | |
5066 // } | |
5067 | 5057 |
5068 Variable* temp = NewTemporary(ast_value_factory()->dot_for_string()); | 5058 ExpressionT enumerable = impl()->EmptyExpression(); |
5069 ForEachStatement* loop = | 5059 if (for_info.mode == ForEachStatement::ITERATE) { |
5070 factory()->NewForEachStatement(mode, labels, stmt_pos); | |
5071 ParserTarget target(this, loop); | |
5072 | |
5073 int each_keyword_position = scanner()->location().beg_pos; | |
5074 | |
5075 Expression* enumerable; | |
5076 if (mode == ForEachStatement::ITERATE) { | |
5077 ExpressionClassifier classifier(this); | 5060 ExpressionClassifier classifier(this); |
5078 enumerable = ParseAssignmentExpression(true, CHECK_OK); | 5061 enumerable = ParseAssignmentExpression(true, CHECK_OK); |
5079 RewriteNonPattern(CHECK_OK); | 5062 impl()->RewriteNonPattern(CHECK_OK); |
5080 } else { | 5063 } else { |
5081 enumerable = ParseExpression(true, CHECK_OK); | 5064 enumerable = ParseExpression(true, CHECK_OK); |
5082 } | 5065 } |
5083 | 5066 |
5084 Expect(Token::RPAREN, CHECK_OK); | 5067 Expect(Token::RPAREN, CHECK_OK); |
5085 | 5068 |
5086 | 5069 StatementT final_loop = impl()->NullStatement(); |
5087 Block* body_block = | |
5088 factory()->NewBlock(NULL, 3, false, kNoSourcePosition); | |
5089 | |
5090 Statement* final_loop; | |
5091 { | 5070 { |
5092 ReturnExprScope no_tail_calls(function_state_, | 5071 ReturnExprScope no_tail_calls(function_state_, |
5093 ReturnExprContext::kInsideForInOfBody); | 5072 ReturnExprContext::kInsideForInOfBody); |
5094 BlockState block_state(&scope_state_); | 5073 BlockState block_state(&scope_state_); |
5095 block_state.set_start_position(scanner()->location().beg_pos); | 5074 block_state.set_start_position(scanner()->location().beg_pos); |
5096 | 5075 |
5097 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); | 5076 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
5098 | 5077 |
5099 auto each_initialization_block = | 5078 std::pair<BlockT, ExpressionT> body_block_and_each_variable = |
5100 factory()->NewBlock(nullptr, 1, true, kNoSourcePosition); | 5079 impl()->DesugarBindingInForEachStatement(&for_info, CHECK_OK); |
5101 { | 5080 body_block_and_each_variable.first->statements()->Add(body, zone()); |
adamk
2016/09/20 16:34:31
Please create a variable for body_block, it'll mak
marja
2016/09/21 08:23:21
Why do we need the pair anyway, it looks like we'r
nickie
2016/09/21 09:20:02
After offline discussion, I'm removing the pair an
nickie
2016/09/21 09:20:02
See comment below.
| |
5102 auto descriptor = parsing_result.descriptor; | 5081 final_loop = impl()->InitializeForEachStatement( |
5103 descriptor.declaration_pos = kNoSourcePosition; | 5082 loop, body_block_and_each_variable.second, enumerable, |
5104 descriptor.initialization_pos = kNoSourcePosition; | 5083 body_block_and_each_variable.first, each_keyword_pos); |
5105 decl.initializer = factory()->NewVariableProxy(temp); | |
5106 | 5084 |
5107 bool is_for_var_of = | |
5108 mode == ForEachStatement::ITERATE && | |
5109 parsing_result.descriptor.mode == VariableMode::VAR; | |
5110 | |
5111 PatternRewriter::DeclareAndInitializeVariables( | |
5112 this, each_initialization_block, &descriptor, &decl, | |
5113 bound_names_are_lexical || is_for_var_of ? &bound_names | |
5114 : nullptr, | |
5115 CHECK_OK); | |
5116 | |
5117 // Annex B.3.5 prohibits the form | |
5118 // `try {} catch(e) { for (var e of {}); }` | |
5119 // So if we are parsing a statement like `for (var ... of ...)` | |
5120 // we need to walk up the scope chain and look for catch scopes | |
5121 // which have a simple binding, then compare their binding against | |
5122 // all of the names declared in the init of the for-of we're | |
5123 // parsing. | |
5124 if (is_for_var_of) { | |
5125 Scope* catch_scope = scope(); | |
5126 while (catch_scope != nullptr && | |
5127 !catch_scope->is_declaration_scope()) { | |
5128 if (catch_scope->is_catch_scope()) { | |
5129 auto name = catch_scope->catch_variable_name(); | |
5130 if (name != | |
5131 ast_value_factory() | |
5132 ->dot_catch_string()) { // i.e. is a simple binding | |
5133 if (bound_names.Contains(name)) { | |
5134 ReportMessageAt(parsing_result.bindings_loc, | |
5135 MessageTemplate::kVarRedeclaration, name); | |
5136 *ok = false; | |
5137 return nullptr; | |
5138 } | |
5139 } | |
5140 } | |
5141 catch_scope = catch_scope->outer_scope(); | |
5142 } | |
5143 } | |
5144 } | |
5145 | |
5146 body_block->statements()->Add(each_initialization_block, zone()); | |
5147 body_block->statements()->Add(body, zone()); | |
5148 VariableProxy* temp_proxy = | |
5149 factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos); | |
5150 final_loop = InitializeForEachStatement( | |
5151 loop, temp_proxy, enumerable, body_block, each_keyword_position); | |
5152 block_state.set_end_position(scanner()->location().end_pos); | 5085 block_state.set_end_position(scanner()->location().end_pos); |
5153 body_block->set_scope(block_state.FinalizedBlockScope()); | 5086 body_block_and_each_variable.first->set_scope( |
5087 block_state.FinalizedBlockScope()); | |
5154 } | 5088 } |
5155 | 5089 |
5156 // Create a TDZ for any lexically-bound names. | 5090 init_block = |
5157 if (bound_names_are_lexical) { | 5091 impl()->CreateForEachStatementTDZ(init_block, &for_info, ok); |
5158 DCHECK_NULL(init_block); | |
5159 | |
5160 init_block = | |
5161 factory()->NewBlock(nullptr, 1, false, kNoSourcePosition); | |
5162 | |
5163 for (int i = 0; i < bound_names.length(); ++i) { | |
5164 // TODO(adamk): This needs to be some sort of special | |
5165 // INTERNAL variable that's invisible to the debugger | |
5166 // but visible to everything else. | |
5167 Declaration* tdz_decl = DeclareVariable( | |
5168 bound_names[i], LET, kNoSourcePosition, CHECK_OK); | |
5169 tdz_decl->proxy()->var()->set_initializer_position(position()); | |
5170 } | |
5171 } | |
5172 | 5092 |
5173 for_state.set_end_position(scanner()->location().end_pos); | 5093 for_state.set_end_position(scanner()->location().end_pos); |
5174 Scope* for_scope = for_state.FinalizedBlockScope(); | 5094 Scope* for_scope = for_state.FinalizedBlockScope(); |
5175 // Parsed for-in loop w/ variable declarations. | 5095 // Parsed for-in loop w/ variable declarations. |
5176 if (init_block != nullptr) { | 5096 if (!impl()->IsNullStatement(init_block)) { |
5177 init_block->statements()->Add(final_loop, zone()); | 5097 init_block->statements()->Add(final_loop, zone()); |
5178 init_block->set_scope(for_scope); | 5098 init_block->set_scope(for_scope); |
5179 return init_block; | 5099 return init_block; |
5180 } else { | 5100 } else { |
5181 DCHECK_NULL(for_scope); | 5101 DCHECK_NULL(for_scope); |
5182 return final_loop; | 5102 return final_loop; |
5183 } | 5103 } |
5184 } else { | 5104 } else { |
5185 bound_names_are_lexical = | 5105 // One or more declaration not followed by in/of. |
5186 IsLexicalVariableMode(parsing_result.descriptor.mode); | 5106 init = impl()->BuildInitializationBlock( |
5187 init = BuildInitializationBlock( | 5107 &for_info.parsing_result, |
5188 &parsing_result, bound_names_are_lexical ? &bound_names : nullptr, | 5108 for_info.bound_names_are_lexical ? &for_info.bound_names : nullptr, |
5189 CHECK_OK); | 5109 CHECK_OK); |
5190 } | 5110 } |
5191 } else { | 5111 } else { |
5112 // The initializer does not contain declarations. | |
5192 int lhs_beg_pos = peek_position(); | 5113 int lhs_beg_pos = peek_position(); |
5193 ExpressionClassifier classifier(this); | 5114 ExpressionClassifier classifier(this); |
5194 Expression* expression = ParseExpressionCoverGrammar(false, CHECK_OK); | 5115 ExpressionT expression = ParseExpressionCoverGrammar(false, CHECK_OK); |
5195 int lhs_end_pos = scanner()->location().end_pos; | 5116 int lhs_end_pos = scanner()->location().end_pos; |
5196 ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE; | |
5197 | 5117 |
5198 bool is_for_each = CheckInOrOf(&mode); | 5118 bool is_for_each = CheckInOrOf(&for_info.mode); |
5199 bool is_destructuring = is_for_each && (expression->IsArrayLiteral() || | 5119 bool is_destructuring = is_for_each && (expression->IsArrayLiteral() || |
5200 expression->IsObjectLiteral()); | 5120 expression->IsObjectLiteral()); |
5201 | 5121 |
5202 if (is_destructuring) { | 5122 if (is_destructuring) { |
5203 ValidateAssignmentPattern(CHECK_OK); | 5123 ValidateAssignmentPattern(CHECK_OK); |
5204 } else { | 5124 } else { |
5205 RewriteNonPattern(CHECK_OK); | 5125 impl()->RewriteNonPattern(CHECK_OK); |
5206 } | 5126 } |
5207 | 5127 |
5208 if (is_for_each) { | 5128 if (is_for_each) { |
5129 // Initializer is reference followed by in/of. | |
5209 if (!is_destructuring) { | 5130 if (!is_destructuring) { |
5210 expression = CheckAndRewriteReferenceExpression( | 5131 expression = impl()->CheckAndRewriteReferenceExpression( |
5211 expression, lhs_beg_pos, lhs_end_pos, | 5132 expression, lhs_beg_pos, lhs_end_pos, |
5212 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); | 5133 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); |
5213 } | 5134 } |
5214 | 5135 |
5215 ForEachStatement* loop = | 5136 auto loop = |
5216 factory()->NewForEachStatement(mode, labels, stmt_pos); | 5137 factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); |
5217 ParserTarget target(this, loop); | 5138 typename Types::Target target(this, loop); |
5218 | 5139 |
5219 int each_keyword_position = scanner()->location().beg_pos; | 5140 int each_keyword_pos = scanner()->location().beg_pos; |
5220 | 5141 |
5221 Expression* enumerable; | 5142 ExpressionT enumerable = impl()->EmptyExpression(); |
5222 if (mode == ForEachStatement::ITERATE) { | 5143 if (for_info.mode == ForEachStatement::ITERATE) { |
5223 ExpressionClassifier classifier(this); | 5144 ExpressionClassifier classifier(this); |
5224 enumerable = ParseAssignmentExpression(true, CHECK_OK); | 5145 enumerable = ParseAssignmentExpression(true, CHECK_OK); |
5225 RewriteNonPattern(CHECK_OK); | 5146 impl()->RewriteNonPattern(CHECK_OK); |
5226 } else { | 5147 } else { |
5227 enumerable = ParseExpression(true, CHECK_OK); | 5148 enumerable = ParseExpression(true, CHECK_OK); |
5228 } | 5149 } |
5229 | 5150 |
5230 Expect(Token::RPAREN, CHECK_OK); | 5151 Expect(Token::RPAREN, CHECK_OK); |
5231 | 5152 |
5232 { | 5153 { |
5233 ReturnExprScope no_tail_calls(function_state_, | 5154 ReturnExprScope no_tail_calls(function_state_, |
5234 ReturnExprContext::kInsideForInOfBody); | 5155 ReturnExprContext::kInsideForInOfBody); |
5235 BlockState block_state(&scope_state_); | 5156 BlockState block_state(&scope_state_); |
5236 block_state.set_start_position(scanner()->location().beg_pos); | 5157 block_state.set_start_position(scanner()->location().beg_pos); |
5237 | 5158 |
5238 // For legacy compat reasons, give for loops similar treatment to | 5159 // For legacy compat reasons, give for loops similar treatment to |
5239 // if statements in allowing a function declaration for a body | 5160 // if statements in allowing a function declaration for a body |
5240 Statement* body = ParseScopedStatement(NULL, true, CHECK_OK); | 5161 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
5241 block_state.set_end_position(scanner()->location().end_pos); | 5162 block_state.set_end_position(scanner()->location().end_pos); |
5242 Statement* final_loop = InitializeForEachStatement( | 5163 StatementT final_loop = impl()->InitializeForEachStatement( |
5243 loop, expression, enumerable, body, each_keyword_position); | 5164 loop, expression, enumerable, body, each_keyword_pos); |
5244 | 5165 |
5245 Scope* for_scope = for_state.FinalizedBlockScope(); | 5166 Scope* for_scope = for_state.FinalizedBlockScope(); |
5246 DCHECK_NULL(for_scope); | 5167 DCHECK_NULL(for_scope); |
5247 USE(for_scope); | 5168 USE(for_scope); |
5248 Scope* block_scope = block_state.FinalizedBlockScope(); | 5169 Scope* block_scope = block_state.FinalizedBlockScope(); |
5249 DCHECK_NULL(block_scope); | 5170 DCHECK_NULL(block_scope); |
5250 USE(block_scope); | 5171 USE(block_scope); |
5251 return final_loop; | 5172 return final_loop; |
5252 } | 5173 } |
5253 } else { | 5174 } else { |
5175 // Initializer is just an expression. | |
5254 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); | 5176 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); |
5255 } | 5177 } |
5256 } | 5178 } |
5257 } | 5179 } |
5258 | 5180 |
5259 // Standard 'for' loop | 5181 // Standard 'for' loop, we have parsed the initializer at this point. |
5260 ForStatement* loop = factory()->NewForStatement(labels, stmt_pos); | 5182 auto loop = factory()->NewForStatement(labels, stmt_pos); |
5261 ParserTarget target(this, loop); | 5183 typename Types::Target target(this, loop); |
5262 | 5184 |
5263 // Parsed initializer at this point. | |
5264 Expect(Token::SEMICOLON, CHECK_OK); | 5185 Expect(Token::SEMICOLON, CHECK_OK); |
5265 | 5186 |
5266 Expression* cond = NULL; | 5187 ExpressionT cond = impl()->EmptyExpression(); |
5267 Statement* next = NULL; | 5188 StatementT next = impl()->NullStatement(); |
5268 Statement* body = NULL; | 5189 StatementT body = impl()->NullStatement(); |
5269 | 5190 |
5270 // If there are let bindings, then condition and the next statement of the | 5191 // If there are let bindings, then condition and the next statement of the |
5271 // for loop must be parsed in a new scope. | 5192 // for loop must be parsed in a new scope. |
5272 Scope* inner_scope = scope(); | 5193 Scope* inner_scope = scope(); |
5273 // TODO(verwaest): Allocate this through a ScopeState as well. | 5194 // TODO(verwaest): Allocate this through a ScopeState as well. |
5274 if (bound_names_are_lexical && bound_names.length() > 0) { | 5195 if (for_info.bound_names_are_lexical && for_info.bound_names.length() > 0) { |
5275 inner_scope = NewScopeWithParent(inner_scope, BLOCK_SCOPE); | 5196 inner_scope = NewScopeWithParent(inner_scope, BLOCK_SCOPE); |
5276 inner_scope->set_start_position(scanner()->location().beg_pos); | 5197 inner_scope->set_start_position(scanner()->location().beg_pos); |
5277 } | 5198 } |
5278 { | 5199 { |
5279 BlockState block_state(&scope_state_, inner_scope); | 5200 BlockState block_state(&scope_state_, inner_scope); |
5280 | 5201 |
5281 if (peek() != Token::SEMICOLON) { | 5202 if (peek() != Token::SEMICOLON) { |
5282 cond = ParseExpression(true, CHECK_OK); | 5203 cond = ParseExpression(true, CHECK_OK); |
5283 } | 5204 } |
5284 Expect(Token::SEMICOLON, CHECK_OK); | 5205 Expect(Token::SEMICOLON, CHECK_OK); |
5285 | 5206 |
5286 if (peek() != Token::RPAREN) { | 5207 if (peek() != Token::RPAREN) { |
5287 Expression* exp = ParseExpression(true, CHECK_OK); | 5208 ExpressionT exp = ParseExpression(true, CHECK_OK); |
5288 next = factory()->NewExpressionStatement(exp, exp->position()); | 5209 next = factory()->NewExpressionStatement(exp, exp->position()); |
5289 } | 5210 } |
5290 Expect(Token::RPAREN, CHECK_OK); | 5211 Expect(Token::RPAREN, CHECK_OK); |
5291 | 5212 |
5292 body = ParseScopedStatement(NULL, true, CHECK_OK); | 5213 body = ParseScopedStatement(nullptr, true, CHECK_OK); |
5293 } | 5214 } |
5294 | 5215 |
5295 Statement* result = NULL; | 5216 if (for_info.bound_names_are_lexical && for_info.bound_names.length() > 0) { |
5296 if (bound_names_are_lexical && bound_names.length() > 0) { | 5217 auto result = impl()->DesugarLexicalBindingsInForStatement( |
5297 result = DesugarLexicalBindingsInForStatement( | 5218 loop, init, cond, next, body, inner_scope, &for_info, CHECK_OK); |
5298 inner_scope, parsing_result.descriptor.mode, &bound_names, loop, init, | |
5299 cond, next, body, CHECK_OK); | |
5300 for_state.set_end_position(scanner()->location().end_pos); | 5219 for_state.set_end_position(scanner()->location().end_pos); |
5220 return result; | |
5301 } else { | 5221 } else { |
5302 for_state.set_end_position(scanner()->location().end_pos); | 5222 for_state.set_end_position(scanner()->location().end_pos); |
5303 Scope* for_scope = for_state.FinalizedBlockScope(); | 5223 Scope* for_scope = for_state.FinalizedBlockScope(); |
5304 if (for_scope) { | 5224 if (for_scope != nullptr) { |
5305 // Rewrite a for statement of the form | 5225 // Rewrite a for statement of the form |
5306 // for (const x = i; c; n) b | 5226 // for (const x = i; c; n) b |
5307 // | 5227 // |
5308 // into | 5228 // into |
5309 // | 5229 // |
5310 // { | 5230 // { |
5311 // const x = i; | 5231 // const x = i; |
5312 // for (; c; n) b | 5232 // for (; c; n) b |
5313 // } | 5233 // } |
5314 // | 5234 // |
5315 // or, desugar | 5235 // or, desugar |
5316 // for (; c; n) b | 5236 // for (; c; n) b |
5317 // into | 5237 // into |
5318 // { | 5238 // { |
5319 // for (; c; n) b | 5239 // for (; c; n) b |
5320 // } | 5240 // } |
5321 // just in case b introduces a lexical binding some other way, e.g., if b | 5241 // just in case b introduces a lexical binding some other way, e.g., if b |
5322 // is a FunctionDeclaration. | 5242 // is a FunctionDeclaration. |
5323 Block* block = factory()->NewBlock(NULL, 2, false, kNoSourcePosition); | 5243 BlockT block = factory()->NewBlock(NULL, 2, false, kNoSourcePosition); |
5324 if (init != nullptr) { | 5244 if (!impl()->IsNullStatement(init)) { |
5325 block->statements()->Add(init, zone()); | 5245 block->statements()->Add(init, zone()); |
5326 } | 5246 } |
5327 block->statements()->Add(loop, zone()); | 5247 block->statements()->Add(loop, zone()); |
5328 block->set_scope(for_scope); | 5248 block->set_scope(for_scope); |
5329 loop->Initialize(NULL, cond, next, body); | 5249 loop->Initialize(init, cond, next, body); |
5330 result = block; | 5250 return block; |
5331 } else { | 5251 } else { |
5332 loop->Initialize(init, cond, next, body); | 5252 loop->Initialize(init, cond, next, body); |
5333 result = loop; | 5253 return loop; |
5334 } | 5254 } |
5335 } | 5255 } |
5336 return result; | |
5337 } | 5256 } |
5338 | 5257 |
5339 #undef CHECK_OK | 5258 #undef CHECK_OK |
5340 #undef CHECK_OK_CUSTOM | 5259 #undef CHECK_OK_CUSTOM |
5341 | 5260 |
5342 template <typename Impl> | 5261 template <typename Impl> |
5343 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 5262 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
5344 Token::Value property) { | 5263 Token::Value property) { |
5345 if (property == Token::SMI || property == Token::NUMBER) return; | 5264 if (property == Token::SMI || property == Token::NUMBER) return; |
5346 | 5265 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5387 has_seen_constructor_ = true; | 5306 has_seen_constructor_ = true; |
5388 return; | 5307 return; |
5389 } | 5308 } |
5390 } | 5309 } |
5391 | 5310 |
5392 | 5311 |
5393 } // namespace internal | 5312 } // namespace internal |
5394 } // namespace v8 | 5313 } // namespace v8 |
5395 | 5314 |
5396 #endif // V8_PARSING_PARSER_BASE_H | 5315 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |