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

Side by Side Diff: src/parsing/parser.cc

Issue 2318263002: [parser] Refactor of Parse*Statement*, part 3 (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.h ('k') | src/parsing/parser-base.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 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "src/api.h" 9 #include "src/api.h"
10 #include "src/ast/ast-expression-rewriter.h" 10 #include "src/ast/ast-expression-rewriter.h"
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 Expression* prop = 499 Expression* prop =
500 factory()->NewProperty(iterable, iterator_symbol_literal, pos); 500 factory()->NewProperty(iterable, iterator_symbol_literal, pos);
501 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone()); 501 ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(0, zone());
502 return factory()->NewCall(prop, args, pos); 502 return factory()->NewCall(prop, args, pos);
503 } 503 }
504 504
505 void Parser::MarkTailPosition(Expression* expression) { 505 void Parser::MarkTailPosition(Expression* expression) {
506 expression->MarkTail(); 506 expression->MarkTail();
507 } 507 }
508 508
509 Expression* Parser::NewV8Intrinsic(const AstRawString* name,
510 ZoneList<Expression*>* args, int pos,
511 bool* ok) {
512 if (extension_ != nullptr) {
513 // The extension structures are only accessible while parsing the
514 // very first time, not when reparsing because of lazy compilation.
515 GetClosureScope()->ForceEagerCompilation();
516 }
517
518 const Runtime::Function* function = Runtime::FunctionForName(name->string());
519
520 if (function != nullptr) {
521 // Check for possible name clash.
522 DCHECK_EQ(Context::kNotFound,
523 Context::IntrinsicIndexForName(name->string()));
524 // Check for built-in IS_VAR macro.
525 if (function->function_id == Runtime::kIS_VAR) {
526 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
527 // %IS_VAR(x) evaluates to x if x is a variable,
528 // leads to a parse error otherwise. Could be implemented as an
529 // inline function %_IS_VAR(x) to eliminate this special case.
530 if (args->length() == 1 && args->at(0)->AsVariableProxy() != nullptr) {
531 return args->at(0);
532 } else {
533 ReportMessage(MessageTemplate::kNotIsvar);
534 *ok = false;
535 return nullptr;
536 }
537 }
538
539 // Check that the expected number of arguments are being passed.
540 if (function->nargs != -1 && function->nargs != args->length()) {
541 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
542 *ok = false;
543 return nullptr;
544 }
545
546 return factory()->NewCallRuntime(function, args, pos);
547 }
548
549 int context_index = Context::IntrinsicIndexForName(name->string());
550
551 // Check that the function is defined.
552 if (context_index == Context::kNotFound) {
553 ReportMessage(MessageTemplate::kNotDefined, name);
554 *ok = false;
555 return nullptr;
556 }
557
558 return factory()->NewCallRuntime(context_index, args, pos);
559 }
560
509 Parser::Parser(ParseInfo* info) 561 Parser::Parser(ParseInfo* info)
510 : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(), 562 : ParserBase<Parser>(info->zone(), &scanner_, info->stack_limit(),
511 info->extension(), info->ast_value_factory(), NULL), 563 info->extension(), info->ast_value_factory(), NULL),
512 scanner_(info->unicode_cache()), 564 scanner_(info->unicode_cache()),
513 reusable_preparser_(NULL), 565 reusable_preparser_(NULL),
514 original_scope_(NULL), 566 original_scope_(NULL),
515 target_stack_(NULL), 567 target_stack_(NULL),
516 compile_options_(info->compile_options()), 568 compile_options_(info->compile_options()),
517 cached_parse_data_(NULL), 569 cached_parse_data_(NULL),
518 total_preparse_skipped_(0), 570 total_preparse_skipped_(0),
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after
700 this->scope()->SetLanguageMode(info->language_mode()); 752 this->scope()->SetLanguageMode(info->language_mode());
701 ParseStatementList(body, Token::EOS, &ok); 753 ParseStatementList(body, Token::EOS, &ok);
702 } 754 }
703 755
704 // The parser will peek but not consume EOS. Our scope logically goes all 756 // The parser will peek but not consume EOS. Our scope logically goes all
705 // the way to the EOS, though. 757 // the way to the EOS, though.
706 scope->set_end_position(scanner()->peek_location().beg_pos); 758 scope->set_end_position(scanner()->peek_location().beg_pos);
707 759
708 if (ok && is_strict(language_mode())) { 760 if (ok && is_strict(language_mode())) {
709 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok); 761 CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
710 CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos, 762 CheckDecimalLiteralWithLeadingZero(beg_pos,
711 scanner()->location().end_pos); 763 scanner()->location().end_pos);
712 } 764 }
713 if (ok && is_sloppy(language_mode())) { 765 if (ok && is_sloppy(language_mode())) {
714 // TODO(littledan): Function bindings on the global object that modify 766 // TODO(littledan): Function bindings on the global object that modify
715 // pre-existing bindings should be made writable, enumerable and 767 // pre-existing bindings should be made writable, enumerable and
716 // nonconfigurable if possible, whereas this code will leave attributes 768 // nonconfigurable if possible, whereas this code will leave attributes
717 // unchanged if the property already exists. 769 // unchanged if the property already exists.
718 InsertSloppyBlockFunctionVarBindings(scope, &ok); 770 InsertSloppyBlockFunctionVarBindings(scope, &ok);
719 } 771 }
720 if (ok) { 772 if (ok) {
(...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after
1610 1662
1611 void Parser::DeclareAndInitializeVariables( 1663 void Parser::DeclareAndInitializeVariables(
1612 Block* block, const DeclarationDescriptor* declaration_descriptor, 1664 Block* block, const DeclarationDescriptor* declaration_descriptor,
1613 const DeclarationParsingResult::Declaration* declaration, 1665 const DeclarationParsingResult::Declaration* declaration,
1614 ZoneList<const AstRawString*>* names, bool* ok) { 1666 ZoneList<const AstRawString*>* names, bool* ok) {
1615 DCHECK_NOT_NULL(block); 1667 DCHECK_NOT_NULL(block);
1616 PatternRewriter::DeclareAndInitializeVariables( 1668 PatternRewriter::DeclareAndInitializeVariables(
1617 this, block, declaration_descriptor, declaration, names, ok); 1669 this, block, declaration_descriptor, declaration, names, ok);
1618 } 1670 }
1619 1671
1620 Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
1621 ZoneList<const AstRawString*>* names,
1622 bool* ok) {
1623 // VariableStatement ::
1624 // VariableDeclarations ';'
1625
1626 // The scope of a var declared variable anywhere inside a function
1627 // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
1628 // transform a source-level var declaration into a (Function) Scope
1629 // declaration, and rewrite the source-level initialization into an assignment
1630 // statement. We use a block to collect multiple assignments.
1631 //
1632 // We mark the block as initializer block because we don't want the
1633 // rewriter to add a '.result' assignment to such a block (to get compliant
1634 // behavior for code such as print(eval('var x = 7')), and for cosmetic
1635 // reasons when pretty-printing. Also, unless an assignment (initialization)
1636 // is inside an initializer block, it is ignored.
1637
1638 DeclarationParsingResult parsing_result;
1639 Block* result =
1640 ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
1641 ExpectSemicolon(CHECK_OK);
1642 return result;
1643 }
1644
1645 static bool ContainsLabel(ZoneList<const AstRawString*>* labels, 1672 static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
1646 const AstRawString* label) { 1673 const AstRawString* label) {
1647 DCHECK(label != NULL); 1674 DCHECK(label != NULL);
1648 if (labels != NULL) { 1675 if (labels != NULL) {
1649 for (int i = labels->length(); i-- > 0; ) { 1676 for (int i = labels->length(); i-- > 0; ) {
1650 if (labels->at(i) == label) { 1677 if (labels->at(i) == label) {
1651 return true; 1678 return true;
1652 } 1679 }
1653 } 1680 }
1654 } 1681 }
(...skipping 1105 matching lines...) Expand 10 before | Expand all | Expand 10 after
2760 } 2787 }
2761 2788
2762 inner_scope->set_end_position(scanner()->location().end_pos); 2789 inner_scope->set_end_position(scanner()->location().end_pos);
2763 inner_block->set_scope(inner_scope); 2790 inner_block->set_scope(inner_scope);
2764 } 2791 }
2765 2792
2766 outer_loop->Initialize(NULL, NULL, NULL, inner_block); 2793 outer_loop->Initialize(NULL, NULL, NULL, inner_block);
2767 return outer_block; 2794 return outer_block;
2768 } 2795 }
2769 2796
2770 Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
2771 bool legacy, bool* ok) {
2772 if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
2773 (legacy && allow_harmony_restrictive_declarations())) {
2774 return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
2775 } else {
2776 if (legacy) {
2777 ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
2778 }
2779 // Make a block around the statement for a lexical binding
2780 // is introduced by a FunctionDeclaration.
2781 BlockState block_state(&scope_state_);
2782 block_state.set_start_position(scanner()->location().beg_pos);
2783 Block* block = factory()->NewBlock(NULL, 1, false, kNoSourcePosition);
2784 Statement* body = ParseFunctionDeclaration(CHECK_OK);
2785 block->statements()->Add(body, zone());
2786 block_state.set_end_position(scanner()->location().end_pos);
2787 block->set_scope(block_state.FinalizedBlockScope());
2788 return block;
2789 }
2790 }
2791
2792 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels, 2797 Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
2793 bool* ok) { 2798 bool* ok) {
2794 int stmt_pos = peek_position(); 2799 int stmt_pos = peek_position();
2795 Statement* init = NULL; 2800 Statement* init = NULL;
2796 ZoneList<const AstRawString*> bound_names(1, zone()); 2801 ZoneList<const AstRawString*> bound_names(1, zone());
2797 bool bound_names_are_lexical = false; 2802 bool bound_names_are_lexical = false;
2798 2803
2799 // Create an in-between scope for let-bound iteration variables. 2804 // Create an in-between scope for let-bound iteration variables.
2800 BlockState for_state(&scope_state_); 2805 BlockState for_state(&scope_state_);
2801 Expect(Token::FOR, CHECK_OK); 2806 Expect(Token::FOR, CHECK_OK);
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after
3129 loop->Initialize(NULL, cond, next, body); 3134 loop->Initialize(NULL, cond, next, body);
3130 result = block; 3135 result = block;
3131 } else { 3136 } else {
3132 loop->Initialize(init, cond, next, body); 3137 loop->Initialize(init, cond, next, body);
3133 result = loop; 3138 result = loop;
3134 } 3139 }
3135 } 3140 }
3136 return result; 3141 return result;
3137 } 3142 }
3138 3143
3139
3140 DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
3141 // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
3142 // contexts this is used as a statement which invokes the debugger as i a
3143 // break point is present.
3144 // DebuggerStatement ::
3145 // 'debugger' ';'
3146
3147 int pos = peek_position();
3148 Expect(Token::DEBUGGER, CHECK_OK);
3149 ExpectSemicolon(CHECK_OK);
3150 return factory()->NewDebuggerStatement(pos);
3151 }
3152
3153
3154 void Parser::ParseArrowFunctionFormalParameters( 3144 void Parser::ParseArrowFunctionFormalParameters(
3155 ParserFormalParameters* parameters, Expression* expr, int end_pos, 3145 ParserFormalParameters* parameters, Expression* expr, int end_pos,
3156 bool* ok) { 3146 bool* ok) {
3157 // ArrowFunctionFormals :: 3147 // ArrowFunctionFormals ::
3158 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail) 3148 // Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
3159 // Tail 3149 // Tail
3160 // NonTailArrowFunctionFormals :: 3150 // NonTailArrowFunctionFormals ::
3161 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy) 3151 // Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
3162 // VariableProxy 3152 // VariableProxy
3163 // Tail :: 3153 // Tail ::
(...skipping 366 matching lines...) Expand 10 before | Expand all | Expand 10 after
3530 CheckFunctionName(language_mode, function_name, function_name_validity, 3520 CheckFunctionName(language_mode, function_name, function_name_validity,
3531 function_name_location, CHECK_OK); 3521 function_name_location, CHECK_OK);
3532 const bool allow_duplicate_parameters = 3522 const bool allow_duplicate_parameters =
3533 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind); 3523 is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
3534 ValidateFormalParameters(language_mode, allow_duplicate_parameters, 3524 ValidateFormalParameters(language_mode, allow_duplicate_parameters,
3535 CHECK_OK); 3525 CHECK_OK);
3536 3526
3537 if (is_strict(language_mode)) { 3527 if (is_strict(language_mode)) {
3538 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), 3528 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
3539 CHECK_OK); 3529 CHECK_OK);
3540 CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(), 3530 CheckDecimalLiteralWithLeadingZero(scope->start_position(),
3541 scope->end_position()); 3531 scope->end_position());
3542 } 3532 }
3543 CheckConflictingVarDeclarations(scope, CHECK_OK); 3533 CheckConflictingVarDeclarations(scope, CHECK_OK);
3544 3534
3545 if (body) { 3535 if (body) {
3546 // If body can be inspected, rewrite queued destructuring assignments 3536 // If body can be inspected, rewrite queued destructuring assignments
3547 RewriteDestructuringAssignments(); 3537 RewriteDestructuringAssignments();
3548 } 3538 }
3549 has_duplicate_parameters = 3539 has_duplicate_parameters =
3550 !classifier()->is_valid_formal_parameter_list_without_duplicates(); 3540 !classifier()->is_valid_formal_parameter_list_without_duplicates();
(...skipping 711 matching lines...) Expand 10 before | Expand all | Expand 10 after
4262 4252
4263 do_block->statements()->Add( 4253 do_block->statements()->Add(
4264 factory()->NewExpressionStatement(class_literal, pos), zone()); 4254 factory()->NewExpressionStatement(class_literal, pos), zone());
4265 do_expr->set_represented_function(constructor); 4255 do_expr->set_represented_function(constructor);
4266 Rewriter::Rewrite(this, GetClosureScope(), do_expr, ast_value_factory()); 4256 Rewriter::Rewrite(this, GetClosureScope(), do_expr, ast_value_factory());
4267 4257
4268 return do_expr; 4258 return do_expr;
4269 } 4259 }
4270 4260
4271 4261
4272 Expression* Parser::ParseV8Intrinsic(bool* ok) {
4273 // CallRuntime ::
4274 // '%' Identifier Arguments
4275
4276 int pos = peek_position();
4277 Expect(Token::MOD, CHECK_OK);
4278 // Allow "eval" or "arguments" for backward compatibility.
4279 const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers,
4280 CHECK_OK);
4281 Scanner::Location spread_pos;
4282 ExpressionClassifier classifier(this);
4283 ZoneList<Expression*>* args = ParseArguments(&spread_pos, CHECK_OK);
4284
4285 DCHECK(!spread_pos.IsValid());
4286
4287 if (extension_ != NULL) {
4288 // The extension structures are only accessible while parsing the
4289 // very first time not when reparsing because of lazy compilation.
4290 GetClosureScope()->ForceEagerCompilation();
4291 }
4292
4293 const Runtime::Function* function = Runtime::FunctionForName(name->string());
4294
4295 if (function != NULL) {
4296 // Check for possible name clash.
4297 DCHECK_EQ(Context::kNotFound,
4298 Context::IntrinsicIndexForName(name->string()));
4299 // Check for built-in IS_VAR macro.
4300 if (function->function_id == Runtime::kIS_VAR) {
4301 DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
4302 // %IS_VAR(x) evaluates to x if x is a variable,
4303 // leads to a parse error otherwise. Could be implemented as an
4304 // inline function %_IS_VAR(x) to eliminate this special case.
4305 if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
4306 return args->at(0);
4307 } else {
4308 ReportMessage(MessageTemplate::kNotIsvar);
4309 *ok = false;
4310 return NULL;
4311 }
4312 }
4313
4314 // Check that the expected number of arguments are being passed.
4315 if (function->nargs != -1 && function->nargs != args->length()) {
4316 ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
4317 *ok = false;
4318 return NULL;
4319 }
4320
4321 return factory()->NewCallRuntime(function, args, pos);
4322 }
4323
4324 int context_index = Context::IntrinsicIndexForName(name->string());
4325
4326 // Check that the function is defined.
4327 if (context_index == Context::kNotFound) {
4328 ReportMessage(MessageTemplate::kNotDefined, name);
4329 *ok = false;
4330 return NULL;
4331 }
4332
4333 return factory()->NewCallRuntime(context_index, args, pos);
4334 }
4335
4336
4337 Literal* Parser::GetLiteralUndefined(int position) { 4262 Literal* Parser::GetLiteralUndefined(int position) {
4338 return factory()->NewUndefinedLiteral(position); 4263 return factory()->NewUndefinedLiteral(position);
4339 } 4264 }
4340 4265
4341 4266
4342 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) { 4267 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4343 Declaration* decl = scope->CheckConflictingVarDeclarations(); 4268 Declaration* decl = scope->CheckConflictingVarDeclarations();
4344 if (decl != NULL) { 4269 if (decl != NULL) {
4345 // In ES6, conflicting variable bindings are early errors. 4270 // In ES6, conflicting variable bindings are early errors.
4346 const AstRawString* name = decl->proxy()->raw_name(); 4271 const AstRawString* name = decl->proxy()->raw_name();
(...skipping 1735 matching lines...) Expand 10 before | Expand all | Expand 10 after
6082 node->Print(Isolate::Current()); 6007 node->Print(Isolate::Current());
6083 } 6008 }
6084 #endif // DEBUG 6009 #endif // DEBUG
6085 6010
6086 #undef CHECK_OK 6011 #undef CHECK_OK
6087 #undef CHECK_OK_VOID 6012 #undef CHECK_OK_VOID
6088 #undef CHECK_FAILED 6013 #undef CHECK_FAILED
6089 6014
6090 } // namespace internal 6015 } // namespace internal
6091 } // namespace v8 6016 } // namespace v8
OLDNEW
« no previous file with comments | « src/parsing/parser.h ('k') | src/parsing/parser-base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698