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

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

Issue 2351233002: [parser] Refactor of Parse*Statement*, part 8 (Closed)
Patch Set: Change after reviewers' comments Created 4 years, 3 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
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 638 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/parsing/parser.cc ('k') | src/parsing/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698