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

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

Issue 1309813007: [es6] implement destructuring assignment (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add explicit placeholder RewritableExpression for rewriting Created 5 years 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 #include "src/parsing/parser.h" 5 #include "src/parsing/parser.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast/ast.h" 8 #include "src/ast/ast.h"
9 #include "src/ast/ast-expression-visitor.h"
9 #include "src/ast/ast-literal-reindexer.h" 10 #include "src/ast/ast-literal-reindexer.h"
10 #include "src/ast/scopeinfo.h" 11 #include "src/ast/scopeinfo.h"
11 #include "src/bailout-reason.h" 12 #include "src/bailout-reason.h"
12 #include "src/base/platform/platform.h" 13 #include "src/base/platform/platform.h"
13 #include "src/bootstrapper.h" 14 #include "src/bootstrapper.h"
14 #include "src/char-predicates-inl.h" 15 #include "src/char-predicates-inl.h"
15 #include "src/codegen.h" 16 #include "src/codegen.h"
16 #include "src/compiler.h" 17 #include "src/compiler.h"
17 #include "src/messages.h" 18 #include "src/messages.h"
18 #include "src/parsing/parameter-initializer-rewriter.h" 19 #include "src/parsing/parameter-initializer-rewriter.h"
(...skipping 894 matching lines...) Expand 10 before | Expand all | Expand 10 after
913 // ParseInfo during background parsing. 914 // ParseInfo during background parsing.
914 DCHECK(!info->script().is_null() || info->source_stream() != NULL); 915 DCHECK(!info->script().is_null() || info->source_stream() != NULL);
915 set_allow_lazy(info->allow_lazy_parsing()); 916 set_allow_lazy(info->allow_lazy_parsing());
916 set_allow_natives(FLAG_allow_natives_syntax || info->is_native()); 917 set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
917 set_allow_harmony_sloppy(FLAG_harmony_sloppy); 918 set_allow_harmony_sloppy(FLAG_harmony_sloppy);
918 set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function); 919 set_allow_harmony_sloppy_function(FLAG_harmony_sloppy_function);
919 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let); 920 set_allow_harmony_sloppy_let(FLAG_harmony_sloppy_let);
920 set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters); 921 set_allow_harmony_rest_parameters(FLAG_harmony_rest_parameters);
921 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters); 922 set_allow_harmony_default_parameters(FLAG_harmony_default_parameters);
922 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind); 923 set_allow_harmony_destructuring_bind(FLAG_harmony_destructuring_bind);
924 set_allow_harmony_destructuring_assignment(
925 FLAG_harmony_destructuring_assignment);
923 set_allow_strong_mode(FLAG_strong_mode); 926 set_allow_strong_mode(FLAG_strong_mode);
924 set_allow_legacy_const(FLAG_legacy_const); 927 set_allow_legacy_const(FLAG_legacy_const);
925 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions); 928 set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
926 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount; 929 for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
927 ++feature) { 930 ++feature) {
928 use_counts_[feature] = 0; 931 use_counts_[feature] = 0;
929 } 932 }
930 if (info->ast_value_factory() == NULL) { 933 if (info->ast_value_factory() == NULL) {
931 // info takes ownership of AstValueFactory. 934 // info takes ownership of AstValueFactory.
932 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed())); 935 info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 if (body->length() != 1 || 1086 if (body->length() != 1 ||
1084 !body->at(0)->IsExpressionStatement() || 1087 !body->at(0)->IsExpressionStatement() ||
1085 !body->at(0)->AsExpressionStatement()-> 1088 !body->at(0)->AsExpressionStatement()->
1086 expression()->IsFunctionLiteral()) { 1089 expression()->IsFunctionLiteral()) {
1087 ReportMessage(MessageTemplate::kSingleFunctionLiteral); 1090 ReportMessage(MessageTemplate::kSingleFunctionLiteral);
1088 ok = false; 1091 ok = false;
1089 } 1092 }
1090 } 1093 }
1091 1094
1092 if (ok) { 1095 if (ok) {
1096 ParserTraits::RewriteDestructuringAssignments();
1093 result = factory()->NewFunctionLiteral( 1097 result = factory()->NewFunctionLiteral(
1094 ast_value_factory()->empty_string(), ast_value_factory(), scope_, 1098 ast_value_factory()->empty_string(), ast_value_factory(), scope_,
1095 body, function_state.materialized_literal_count(), 1099 body, function_state.materialized_literal_count(),
1096 function_state.expected_property_count(), 0, 1100 function_state.expected_property_count(), 0,
1097 FunctionLiteral::kNoDuplicateParameters, 1101 FunctionLiteral::kNoDuplicateParameters,
1098 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval, 1102 FunctionLiteral::ANONYMOUS_EXPRESSION, FunctionLiteral::kGlobalOrEval,
1099 FunctionLiteral::kShouldLazyCompile, FunctionKind::kNormalFunction, 1103 FunctionLiteral::kShouldLazyCompile, FunctionKind::kNormalFunction,
1100 0); 1104 0);
1101 } 1105 }
1102 } 1106 }
(...skipping 3287 matching lines...) Expand 10 before | Expand all | Expand 10 after
4390 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(), 4394 CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
4391 CHECK_OK); 4395 CHECK_OK);
4392 } 4396 }
4393 if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) { 4397 if (is_sloppy(language_mode) && allow_harmony_sloppy_function()) {
4394 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK); 4398 InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
4395 } 4399 }
4396 if (is_strict(language_mode) || allow_harmony_sloppy() || 4400 if (is_strict(language_mode) || allow_harmony_sloppy() ||
4397 allow_harmony_destructuring_bind()) { 4401 allow_harmony_destructuring_bind()) {
4398 CheckConflictingVarDeclarations(scope, CHECK_OK); 4402 CheckConflictingVarDeclarations(scope, CHECK_OK);
4399 } 4403 }
4404
4405 if (body) {
4406 // If body can be inspected, rewrite queued destructuring assignments
4407 ParserTraits::RewriteDestructuringAssignments();
4408 }
4400 } 4409 }
4401 4410
4402 bool has_duplicate_parameters = 4411 bool has_duplicate_parameters =
4403 !formals_classifier.is_valid_formal_parameter_list_without_duplicates(); 4412 !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
4404 FunctionLiteral::ParameterFlag duplicate_parameters = 4413 FunctionLiteral::ParameterFlag duplicate_parameters =
4405 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters 4414 has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
4406 : FunctionLiteral::kNoDuplicateParameters; 4415 : FunctionLiteral::kNoDuplicateParameters;
4407 4416
4408 FunctionLiteral* function_literal = factory()->NewFunctionLiteral( 4417 FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
4409 function_name, ast_value_factory(), scope, body, 4418 function_name, ast_value_factory(), scope, body,
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
4518 RelocInfo::kNoPosition); 4527 RelocInfo::kNoPosition);
4519 IfStatement* if_statement = factory()->NewIfStatement( 4528 IfStatement* if_statement = factory()->NewIfStatement(
4520 condition, factory()->NewExpressionStatement(throw_type_error, 4529 condition, factory()->NewExpressionStatement(throw_type_error,
4521 RelocInfo::kNoPosition), 4530 RelocInfo::kNoPosition),
4522 factory()->NewEmptyStatement(RelocInfo::kNoPosition), 4531 factory()->NewEmptyStatement(RelocInfo::kNoPosition),
4523 RelocInfo::kNoPosition); 4532 RelocInfo::kNoPosition);
4524 return if_statement; 4533 return if_statement;
4525 } 4534 }
4526 4535
4527 4536
4537 class InitializerRewriter : public AstExpressionVisitor {
4538 public:
4539 InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser,
4540 Scope* scope)
4541 : AstExpressionVisitor(stack_limit, root),
4542 parser_(parser),
4543 scope_(scope) {}
4544
4545 private:
4546 void VisitExpression(Expression* expr) {
4547 RewritableExpression* rw = expr->AsRewritableExpression();
adamk 2015/12/01 22:42:56 Naming nit: I like "to_rewrite" better than "rw".
4548 if (!rw ||
adamk 2015/12/01 22:42:56 to_rewrite == nullptr
4549 !rw->IsRewritableAs(RewritableExpression::kDestructuringAssignment)) {
adamk 2015/12/01 22:42:56 It's checks like this that I don't see as terribly
caitp (gmail) 2015/12/01 22:51:00 the check is checking 2 things: 1, that it's "poss
adamk 2015/12/01 22:54:23 Right, sorry, there is that second case. Even so,
4550 return;
4551 }
4552
4553 bool ok = true;
4554 Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, rw, scope_,
4555 &ok);
4556 DCHECK(ok);
4557 }
4558
4559 private:
4560 Parser* parser_;
4561 Scope* scope_;
4562 };
4563
4564
4565 void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) {
4566 InitializerRewriter rewriter(stack_limit_, expr, this, scope);
4567 rewriter.Run();
4568 }
4569
4570
4528 Block* Parser::BuildParameterInitializationBlock( 4571 Block* Parser::BuildParameterInitializationBlock(
4529 const ParserFormalParameters& parameters, bool* ok) { 4572 const ParserFormalParameters& parameters, bool* ok) {
4530 DCHECK(!parameters.is_simple); 4573 DCHECK(!parameters.is_simple);
4531 DCHECK(scope_->is_function_scope()); 4574 DCHECK(scope_->is_function_scope());
4532 Block* init_block = 4575 Block* init_block =
4533 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition); 4576 factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
4534 for (int i = 0; i < parameters.params.length(); ++i) { 4577 for (int i = 0; i < parameters.params.length(); ++i) {
4535 auto parameter = parameters.params[i]; 4578 auto parameter = parameters.params[i];
4536 DeclarationDescriptor descriptor; 4579 DeclarationDescriptor descriptor;
4537 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER; 4580 descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
(...skipping 12 matching lines...) Expand all
4550 // it's just copying from a temp var to the real param var? 4593 // it's just copying from a temp var to the real param var?
4551 descriptor.initialization_pos = parameter.pattern->position(); 4594 descriptor.initialization_pos = parameter.pattern->position();
4552 // The initializer position which will end up in, 4595 // The initializer position which will end up in,
4553 // Variable::initializer_position(), used for hole check elimination. 4596 // Variable::initializer_position(), used for hole check elimination.
4554 int initializer_position = parameter.pattern->position(); 4597 int initializer_position = parameter.pattern->position();
4555 Expression* initial_value = 4598 Expression* initial_value =
4556 factory()->NewVariableProxy(parameters.scope->parameter(i)); 4599 factory()->NewVariableProxy(parameters.scope->parameter(i));
4557 if (parameter.initializer != nullptr) { 4600 if (parameter.initializer != nullptr) {
4558 // IS_UNDEFINED($param) ? initializer : $param 4601 // IS_UNDEFINED($param) ? initializer : $param
4559 DCHECK(!parameter.is_rest); 4602 DCHECK(!parameter.is_rest);
4603
4604 // Ensure initializer is rewritten
4605 RewriteParameterInitializer(parameter.initializer, scope_);
4606
4560 auto condition = factory()->NewCompareOperation( 4607 auto condition = factory()->NewCompareOperation(
4561 Token::EQ_STRICT, 4608 Token::EQ_STRICT,
4562 factory()->NewVariableProxy(parameters.scope->parameter(i)), 4609 factory()->NewVariableProxy(parameters.scope->parameter(i)),
4563 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), 4610 factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
4564 RelocInfo::kNoPosition); 4611 RelocInfo::kNoPosition);
4565 initial_value = factory()->NewConditional( 4612 initial_value = factory()->NewConditional(
4566 condition, parameter.initializer, initial_value, 4613 condition, parameter.initializer, initial_value,
4567 RelocInfo::kNoPosition); 4614 RelocInfo::kNoPosition);
4568 descriptor.initialization_pos = parameter.initializer->position(); 4615 descriptor.initialization_pos = parameter.initializer->position();
4569 initializer_position = parameter.initializer_end_position; 4616 initializer_position = parameter.initializer_end_position;
(...skipping 1883 matching lines...) Expand 10 before | Expand all | Expand 10 after
6453 ++use_counts_[feature]; 6500 ++use_counts_[feature];
6454 scope->SetLanguageMode(mode); 6501 scope->SetLanguageMode(mode);
6455 } 6502 }
6456 6503
6457 6504
6458 void Parser::RaiseLanguageMode(LanguageMode mode) { 6505 void Parser::RaiseLanguageMode(LanguageMode mode) {
6459 SetLanguageMode(scope_, 6506 SetLanguageMode(scope_,
6460 static_cast<LanguageMode>(scope_->language_mode() | mode)); 6507 static_cast<LanguageMode>(scope_->language_mode() | mode));
6461 } 6508 }
6462 6509
6510
6511 void ParserTraits::RewriteDestructuringAssignments() {
6512 parser_->RewriteDestructuringAssignments();
6513 }
6514
6515
6516 void Parser::RewriteDestructuringAssignments() {
6517 FunctionState* func = function_state_;
6518 if (!allow_harmony_destructuring_assignment()) return;
6519 const List<DestructuringAssignment>& assignments =
6520 func->destructuring_assignments_to_rewrite();
6521 for (int i = assignments.length() - 1; i >= 0; --i) {
6522 // Rewrite list in reverse, so that nested assignment patterns are rewritten
6523 // correctly.
6524 DestructuringAssignment pair = assignments.at(i);
6525 RewritableExpression* rw = pair.assignment->AsRewritableExpression();
adamk 2015/12/01 22:42:56 Like the old name better here too
6526 Scope* scope = pair.scope;
6527 DCHECK_NOT_NULL(rw);
6528 if (rw->IsRewritableAs(RewritableExpression::kDestructuringAssignment)) {
6529 bool ok = true;
6530 PatternRewriter::RewriteDestructuringAssignment(this, rw, scope, &ok);
6531 DCHECK(ok);
6532 }
6533 }
6534 }
6535
6536
6537 void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
6538 DCHECK(expr->IsRewritableExpression());
6539 DCHECK(expr->AsRewritableExpression()->expression()->IsAssignment());
adamk 2015/12/01 22:42:56 This, too, will go away if you just use the C++ ty
6540 DCHECK(expr->AsRewritableExpression()->hints() &
6541 RewritableExpression::kDestructuringAssignment);
6542 parser_->function_state_->AddDestructuringAssignment(
6543 Parser::DestructuringAssignment(expr, parser_->scope_));
6544 }
6545
6546
6463 } // namespace internal 6547 } // namespace internal
6464 } // namespace v8 6548 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698