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 mode(ForEachStatement::ENUMERATE), |
| 664 each_loc(), |
| 665 parsing_result() {} |
| 666 ZoneList<const AstRawString*> bound_names; |
| 667 ForEachStatement::VisitMode mode; |
| 668 Scanner::Location each_loc; |
| 669 DeclarationParsingResult parsing_result; |
| 670 }; |
| 671 |
659 DeclarationScope* NewScriptScope() const { | 672 DeclarationScope* NewScriptScope() const { |
660 return new (zone()) DeclarationScope(zone(), ast_value_factory()); | 673 return new (zone()) DeclarationScope(zone(), ast_value_factory()); |
661 } | 674 } |
662 | 675 |
663 DeclarationScope* NewVarblockScope() const { | 676 DeclarationScope* NewVarblockScope() const { |
664 return new (zone()) DeclarationScope(zone(), scope(), BLOCK_SCOPE); | 677 return new (zone()) DeclarationScope(zone(), scope(), BLOCK_SCOPE); |
665 } | 678 } |
666 | 679 |
667 ModuleScope* NewModuleScope(DeclarationScope* parent) const { | 680 ModuleScope* NewModuleScope(DeclarationScope* parent) const { |
668 return new (zone()) ModuleScope(parent, ast_value_factory()); | 681 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, | 1256 StatementT ParseWithStatement(ZoneList<const AstRawString*>* labels, |
1244 bool* ok); | 1257 bool* ok); |
1245 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, | 1258 StatementT ParseDoWhileStatement(ZoneList<const AstRawString*>* labels, |
1246 bool* ok); | 1259 bool* ok); |
1247 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, | 1260 StatementT ParseWhileStatement(ZoneList<const AstRawString*>* labels, |
1248 bool* ok); | 1261 bool* ok); |
1249 StatementT ParseThrowStatement(bool* ok); | 1262 StatementT ParseThrowStatement(bool* ok); |
1250 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, | 1263 StatementT ParseSwitchStatement(ZoneList<const AstRawString*>* labels, |
1251 bool* ok); | 1264 bool* ok); |
1252 StatementT ParseTryStatement(bool* ok); | 1265 StatementT ParseTryStatement(bool* ok); |
| 1266 StatementT ParseForStatement(ZoneList<const AstRawString*>* labels, bool* ok); |
1253 | 1267 |
1254 bool IsNextLetKeyword(); | 1268 bool IsNextLetKeyword(); |
1255 bool IsTrivialExpression(); | 1269 bool IsTrivialExpression(); |
1256 | 1270 |
1257 // Checks if the expression is a valid reference expression (e.g., on the | 1271 // Checks if the expression is a valid reference expression (e.g., on the |
1258 // left-hand side of assignments). Although ruled out by ECMA as early errors, | 1272 // left-hand side of assignments). Although ruled out by ECMA as early errors, |
1259 // we allow calls for web compatibility and rewrite them to a runtime throw. | 1273 // we allow calls for web compatibility and rewrite them to a runtime throw. |
1260 ExpressionT CheckAndRewriteReferenceExpression( | 1274 ExpressionT CheckAndRewriteReferenceExpression( |
1261 ExpressionT expression, int beg_pos, int end_pos, | 1275 ExpressionT expression, int beg_pos, int end_pos, |
1262 MessageTemplate::Template message, bool* ok); | 1276 MessageTemplate::Template message, bool* ok); |
(...skipping 3079 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4342 case Token::SEMICOLON: | 4356 case Token::SEMICOLON: |
4343 Next(); | 4357 Next(); |
4344 return factory()->NewEmptyStatement(kNoSourcePosition); | 4358 return factory()->NewEmptyStatement(kNoSourcePosition); |
4345 case Token::IF: | 4359 case Token::IF: |
4346 return ParseIfStatement(labels, ok); | 4360 return ParseIfStatement(labels, ok); |
4347 case Token::DO: | 4361 case Token::DO: |
4348 return ParseDoWhileStatement(labels, ok); | 4362 return ParseDoWhileStatement(labels, ok); |
4349 case Token::WHILE: | 4363 case Token::WHILE: |
4350 return ParseWhileStatement(labels, ok); | 4364 return ParseWhileStatement(labels, ok); |
4351 case Token::FOR: | 4365 case Token::FOR: |
4352 return impl()->ParseForStatement(labels, ok); | 4366 return ParseForStatement(labels, ok); |
4353 case Token::CONTINUE: | 4367 case Token::CONTINUE: |
4354 case Token::BREAK: | 4368 case Token::BREAK: |
4355 case Token::RETURN: | 4369 case Token::RETURN: |
4356 case Token::THROW: | 4370 case Token::THROW: |
4357 case Token::TRY: { | 4371 case Token::TRY: { |
4358 // These statements must have their labels preserved in an enclosing | 4372 // These statements must have their labels preserved in an enclosing |
4359 // block, as the corresponding AST nodes do not currently store their | 4373 // block, as the corresponding AST nodes do not currently store their |
4360 // labels. | 4374 // labels. |
4361 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. | 4375 // TODO(nikolaos, marja): Consider adding the labels to the AST nodes. |
4362 if (labels == nullptr) { | 4376 if (labels == nullptr) { |
(...skipping 606 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4969 MessageTemplate::kUnexpectedTailCallInCatchBlock); | 4983 MessageTemplate::kUnexpectedTailCallInCatchBlock); |
4970 *ok = false; | 4984 *ok = false; |
4971 return impl()->NullStatement(); | 4985 return impl()->NullStatement(); |
4972 } | 4986 } |
4973 } | 4987 } |
4974 | 4988 |
4975 return impl()->RewriteTryStatement(try_block, catch_block, finally_block, | 4989 return impl()->RewriteTryStatement(try_block, catch_block, finally_block, |
4976 catch_info, pos); | 4990 catch_info, pos); |
4977 } | 4991 } |
4978 | 4992 |
| 4993 template <typename Impl> |
| 4994 typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseForStatement( |
| 4995 ZoneList<const AstRawString*>* labels, bool* ok) { |
| 4996 int stmt_pos = peek_position(); |
| 4997 ForInfo for_info(this); |
| 4998 bool bound_names_are_lexical = false; |
| 4999 |
| 5000 // Create an in-between scope for let-bound iteration variables. |
| 5001 BlockState for_state(&scope_state_); |
| 5002 Expect(Token::FOR, CHECK_OK); |
| 5003 Expect(Token::LPAREN, CHECK_OK); |
| 5004 for_state.set_start_position(scanner()->location().beg_pos); |
| 5005 for_state.set_is_hidden(); |
| 5006 |
| 5007 StatementT init = impl()->NullStatement(); |
| 5008 if (peek() != Token::SEMICOLON) { |
| 5009 // An initializer is present. |
| 5010 if (peek() == Token::VAR || peek() == Token::CONST || |
| 5011 (peek() == Token::LET && IsNextLetKeyword())) { |
| 5012 // The initializer contains declarations. |
| 5013 ParseVariableDeclarations(kForStatement, &for_info.parsing_result, |
| 5014 nullptr, CHECK_OK); |
| 5015 bound_names_are_lexical = |
| 5016 IsLexicalVariableMode(for_info.parsing_result.descriptor.mode); |
| 5017 for_info.each_loc = scanner()->location(); |
| 5018 |
| 5019 if (CheckInOrOf(&for_info.mode)) { |
| 5020 // Just one declaration followed by in/of. |
| 5021 if (for_info.parsing_result.declarations.length() != 1) { |
| 5022 impl()->ReportMessageAt( |
| 5023 for_info.parsing_result.bindings_loc, |
| 5024 MessageTemplate::kForInOfLoopMultiBindings, |
| 5025 ForEachStatement::VisitModeString(for_info.mode)); |
| 5026 *ok = false; |
| 5027 return impl()->NullStatement(); |
| 5028 } |
| 5029 if (for_info.parsing_result.first_initializer_loc.IsValid() && |
| 5030 (is_strict(language_mode()) || |
| 5031 for_info.mode == ForEachStatement::ITERATE || |
| 5032 bound_names_are_lexical || |
| 5033 !impl()->IsIdentifier( |
| 5034 for_info.parsing_result.declarations[0].pattern) || |
| 5035 allow_harmony_for_in())) { |
| 5036 // Only increment the use count if we would have let this through |
| 5037 // without the flag. |
| 5038 if (allow_harmony_for_in()) { |
| 5039 impl()->CountUsage(v8::Isolate::kForInInitializer); |
| 5040 } |
| 5041 impl()->ReportMessageAt( |
| 5042 for_info.parsing_result.first_initializer_loc, |
| 5043 MessageTemplate::kForInOfLoopInitializer, |
| 5044 ForEachStatement::VisitModeString(for_info.mode)); |
| 5045 *ok = false; |
| 5046 return impl()->NullStatement(); |
| 5047 } |
| 5048 |
| 5049 BlockT init_block = impl()->RewriteForVarInLegacy(for_info); |
| 5050 |
| 5051 auto loop = |
| 5052 factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); |
| 5053 typename Types::Target target(this, loop); |
| 5054 |
| 5055 int each_keyword_pos = scanner()->location().beg_pos; |
| 5056 |
| 5057 ExpressionT enumerable = impl()->EmptyExpression(); |
| 5058 if (for_info.mode == ForEachStatement::ITERATE) { |
| 5059 ExpressionClassifier classifier(this); |
| 5060 enumerable = ParseAssignmentExpression(true, CHECK_OK); |
| 5061 impl()->RewriteNonPattern(CHECK_OK); |
| 5062 } else { |
| 5063 enumerable = ParseExpression(true, CHECK_OK); |
| 5064 } |
| 5065 |
| 5066 Expect(Token::RPAREN, CHECK_OK); |
| 5067 |
| 5068 StatementT final_loop = impl()->NullStatement(); |
| 5069 { |
| 5070 ReturnExprScope no_tail_calls(function_state_, |
| 5071 ReturnExprContext::kInsideForInOfBody); |
| 5072 BlockState block_state(&scope_state_); |
| 5073 block_state.set_start_position(scanner()->location().beg_pos); |
| 5074 |
| 5075 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
| 5076 |
| 5077 BlockT body_block = impl()->NullBlock(); |
| 5078 ExpressionT each_variable = impl()->EmptyExpression(); |
| 5079 impl()->DesugarBindingInForEachStatement(&for_info, &body_block, |
| 5080 &each_variable, CHECK_OK); |
| 5081 body_block->statements()->Add(body, zone()); |
| 5082 final_loop = impl()->InitializeForEachStatement( |
| 5083 loop, each_variable, enumerable, body_block, each_keyword_pos); |
| 5084 |
| 5085 block_state.set_end_position(scanner()->location().end_pos); |
| 5086 body_block->set_scope(block_state.FinalizedBlockScope()); |
| 5087 } |
| 5088 |
| 5089 init_block = |
| 5090 impl()->CreateForEachStatementTDZ(init_block, for_info, ok); |
| 5091 |
| 5092 for_state.set_end_position(scanner()->location().end_pos); |
| 5093 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5094 // Parsed for-in loop w/ variable declarations. |
| 5095 if (!impl()->IsNullStatement(init_block)) { |
| 5096 init_block->statements()->Add(final_loop, zone()); |
| 5097 init_block->set_scope(for_scope); |
| 5098 return init_block; |
| 5099 } else { |
| 5100 DCHECK_NULL(for_scope); |
| 5101 return final_loop; |
| 5102 } |
| 5103 } else { |
| 5104 // One or more declaration not followed by in/of. |
| 5105 init = impl()->BuildInitializationBlock( |
| 5106 &for_info.parsing_result, |
| 5107 bound_names_are_lexical ? &for_info.bound_names : nullptr, |
| 5108 CHECK_OK); |
| 5109 } |
| 5110 } else { |
| 5111 // The initializer does not contain declarations. |
| 5112 int lhs_beg_pos = peek_position(); |
| 5113 ExpressionClassifier classifier(this); |
| 5114 ExpressionT expression = ParseExpressionCoverGrammar(false, CHECK_OK); |
| 5115 int lhs_end_pos = scanner()->location().end_pos; |
| 5116 |
| 5117 bool is_for_each = CheckInOrOf(&for_info.mode); |
| 5118 bool is_destructuring = is_for_each && (expression->IsArrayLiteral() || |
| 5119 expression->IsObjectLiteral()); |
| 5120 |
| 5121 if (is_destructuring) { |
| 5122 ValidateAssignmentPattern(CHECK_OK); |
| 5123 } else { |
| 5124 impl()->RewriteNonPattern(CHECK_OK); |
| 5125 } |
| 5126 |
| 5127 if (is_for_each) { |
| 5128 // Initializer is reference followed by in/of. |
| 5129 if (!is_destructuring) { |
| 5130 expression = impl()->CheckAndRewriteReferenceExpression( |
| 5131 expression, lhs_beg_pos, lhs_end_pos, |
| 5132 MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK); |
| 5133 } |
| 5134 |
| 5135 auto loop = |
| 5136 factory()->NewForEachStatement(for_info.mode, labels, stmt_pos); |
| 5137 typename Types::Target target(this, loop); |
| 5138 |
| 5139 int each_keyword_pos = scanner()->location().beg_pos; |
| 5140 |
| 5141 ExpressionT enumerable = impl()->EmptyExpression(); |
| 5142 if (for_info.mode == ForEachStatement::ITERATE) { |
| 5143 ExpressionClassifier classifier(this); |
| 5144 enumerable = ParseAssignmentExpression(true, CHECK_OK); |
| 5145 impl()->RewriteNonPattern(CHECK_OK); |
| 5146 } else { |
| 5147 enumerable = ParseExpression(true, CHECK_OK); |
| 5148 } |
| 5149 |
| 5150 Expect(Token::RPAREN, CHECK_OK); |
| 5151 |
| 5152 { |
| 5153 ReturnExprScope no_tail_calls(function_state_, |
| 5154 ReturnExprContext::kInsideForInOfBody); |
| 5155 BlockState block_state(&scope_state_); |
| 5156 block_state.set_start_position(scanner()->location().beg_pos); |
| 5157 |
| 5158 // For legacy compat reasons, give for loops similar treatment to |
| 5159 // if statements in allowing a function declaration for a body |
| 5160 StatementT body = ParseScopedStatement(nullptr, true, CHECK_OK); |
| 5161 block_state.set_end_position(scanner()->location().end_pos); |
| 5162 StatementT final_loop = impl()->InitializeForEachStatement( |
| 5163 loop, expression, enumerable, body, each_keyword_pos); |
| 5164 |
| 5165 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5166 DCHECK_NULL(for_scope); |
| 5167 USE(for_scope); |
| 5168 Scope* block_scope = block_state.FinalizedBlockScope(); |
| 5169 DCHECK_NULL(block_scope); |
| 5170 USE(block_scope); |
| 5171 return final_loop; |
| 5172 } |
| 5173 } else { |
| 5174 // Initializer is just an expression. |
| 5175 init = factory()->NewExpressionStatement(expression, lhs_beg_pos); |
| 5176 } |
| 5177 } |
| 5178 } |
| 5179 |
| 5180 // Standard 'for' loop, we have parsed the initializer at this point. |
| 5181 auto loop = factory()->NewForStatement(labels, stmt_pos); |
| 5182 typename Types::Target target(this, loop); |
| 5183 |
| 5184 Expect(Token::SEMICOLON, CHECK_OK); |
| 5185 |
| 5186 ExpressionT cond = impl()->EmptyExpression(); |
| 5187 StatementT next = impl()->NullStatement(); |
| 5188 StatementT body = impl()->NullStatement(); |
| 5189 |
| 5190 // If there are let bindings, then condition and the next statement of the |
| 5191 // for loop must be parsed in a new scope. |
| 5192 Scope* inner_scope = scope(); |
| 5193 // TODO(verwaest): Allocate this through a ScopeState as well. |
| 5194 if (bound_names_are_lexical && for_info.bound_names.length() > 0) { |
| 5195 inner_scope = NewScopeWithParent(inner_scope, BLOCK_SCOPE); |
| 5196 inner_scope->set_start_position(scanner()->location().beg_pos); |
| 5197 } |
| 5198 { |
| 5199 BlockState block_state(&scope_state_, inner_scope); |
| 5200 |
| 5201 if (peek() != Token::SEMICOLON) { |
| 5202 cond = ParseExpression(true, CHECK_OK); |
| 5203 } |
| 5204 Expect(Token::SEMICOLON, CHECK_OK); |
| 5205 |
| 5206 if (peek() != Token::RPAREN) { |
| 5207 ExpressionT exp = ParseExpression(true, CHECK_OK); |
| 5208 next = factory()->NewExpressionStatement(exp, exp->position()); |
| 5209 } |
| 5210 Expect(Token::RPAREN, CHECK_OK); |
| 5211 |
| 5212 body = ParseScopedStatement(nullptr, true, CHECK_OK); |
| 5213 } |
| 5214 |
| 5215 if (bound_names_are_lexical && for_info.bound_names.length() > 0) { |
| 5216 auto result = impl()->DesugarLexicalBindingsInForStatement( |
| 5217 loop, init, cond, next, body, inner_scope, for_info, CHECK_OK); |
| 5218 for_state.set_end_position(scanner()->location().end_pos); |
| 5219 return result; |
| 5220 } else { |
| 5221 for_state.set_end_position(scanner()->location().end_pos); |
| 5222 Scope* for_scope = for_state.FinalizedBlockScope(); |
| 5223 if (for_scope != nullptr) { |
| 5224 // Rewrite a for statement of the form |
| 5225 // for (const x = i; c; n) b |
| 5226 // |
| 5227 // into |
| 5228 // |
| 5229 // { |
| 5230 // const x = i; |
| 5231 // for (; c; n) b |
| 5232 // } |
| 5233 // |
| 5234 // or, desugar |
| 5235 // for (; c; n) b |
| 5236 // into |
| 5237 // { |
| 5238 // for (; c; n) b |
| 5239 // } |
| 5240 // just in case b introduces a lexical binding some other way, e.g., if b |
| 5241 // is a FunctionDeclaration. |
| 5242 BlockT block = factory()->NewBlock(nullptr, 2, false, kNoSourcePosition); |
| 5243 if (!impl()->IsNullStatement(init)) { |
| 5244 block->statements()->Add(init, zone()); |
| 5245 } |
| 5246 block->statements()->Add(loop, zone()); |
| 5247 block->set_scope(for_scope); |
| 5248 loop->Initialize(init, cond, next, body); |
| 5249 return block; |
| 5250 } else { |
| 5251 loop->Initialize(init, cond, next, body); |
| 5252 return loop; |
| 5253 } |
| 5254 } |
| 5255 } |
| 5256 |
4979 #undef CHECK_OK | 5257 #undef CHECK_OK |
4980 #undef CHECK_OK_CUSTOM | 5258 #undef CHECK_OK_CUSTOM |
4981 | 5259 |
4982 template <typename Impl> | 5260 template <typename Impl> |
4983 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( | 5261 void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto( |
4984 Token::Value property) { | 5262 Token::Value property) { |
4985 if (property == Token::SMI || property == Token::NUMBER) return; | 5263 if (property == Token::SMI || property == Token::NUMBER) return; |
4986 | 5264 |
4987 if (IsProto()) { | 5265 if (IsProto()) { |
4988 if (has_seen_proto_) { | 5266 if (has_seen_proto_) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5027 has_seen_constructor_ = true; | 5305 has_seen_constructor_ = true; |
5028 return; | 5306 return; |
5029 } | 5307 } |
5030 } | 5308 } |
5031 | 5309 |
5032 | 5310 |
5033 } // namespace internal | 5311 } // namespace internal |
5034 } // namespace v8 | 5312 } // namespace v8 |
5035 | 5313 |
5036 #endif // V8_PARSING_PARSER_BASE_H | 5314 #endif // V8_PARSING_PARSER_BASE_H |
OLD | NEW |