Chromium Code Reviews| Index: src/pattern-rewriter.cc |
| diff --git a/src/pattern-rewriter.cc b/src/pattern-rewriter.cc |
| index 090f85dc9c533ad68fcdb0bff435c7440152194d..db114c91b5207eb8464d5ee807eafa20e45ea323 100644 |
| --- a/src/pattern-rewriter.cc |
| +++ b/src/pattern-rewriter.cc |
| @@ -17,19 +17,53 @@ void Parser::PatternRewriter::DeclareAndInitializeVariables( |
| ZoneList<const AstRawString*>* names, bool* ok) { |
| PatternRewriter rewriter; |
| + rewriter.parser_ = declaration_descriptor->parser; |
| + rewriter.context_ = BINDING; |
| rewriter.pattern_ = declaration->pattern; |
| rewriter.initializer_position_ = declaration->initializer_position; |
| rewriter.block_ = block; |
| rewriter.descriptor_ = declaration_descriptor; |
| rewriter.names_ = names; |
| rewriter.ok_ = ok; |
| + rewriter.rhs_ = nullptr; |
| rewriter.RecurseIntoSubpattern(rewriter.pattern_, declaration->initializer); |
| } |
| +Variable* Parser::PatternRewriter::RewriteDestructuringAssignment( |
| + Parser* parser, Block* block, Expression* pattern, Expression* value, |
| + Variable* result, bool* ok) { |
| + PatternRewriter rewriter; |
| + |
| + rewriter.parser_ = parser; |
| + rewriter.context_ = ASSIGNMENT; |
| + rewriter.pattern_ = pattern; |
| + rewriter.block_ = block; |
| + rewriter.descriptor_ = nullptr; |
| + rewriter.names_ = nullptr; |
| + rewriter.ok_ = ok; |
| + rewriter.rhs_ = result; |
| + |
| + rewriter.RecurseIntoSubpattern(rewriter.pattern_, value); |
| + DCHECK_NOT_NULL(rewriter.rhs_); |
| + return rewriter.rhs_; |
| +} |
| + |
| + |
| void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { |
| Expression* value = current_value_; |
| + |
| + if (context() == ASSIGNMENT) { |
| + // In an assignment context, simply perform the assignment |
| + Assignment* assignment = factory()->NewAssignment( |
| + Token::ASSIGN, pattern, value, pattern->position()); |
| + block_->statements()->Add( |
| + factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
| + zone()); |
| + return; |
| + } |
| + |
| descriptor_->scope->RemoveUnresolved(pattern); |
| // Declare variable. |
| @@ -47,7 +81,7 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { |
| // For let/const declarations in harmony mode, we can also immediately |
| // pre-resolve the proxy because it resides in the same scope as the |
| // declaration. |
| - Parser* parser = descriptor_->parser; |
| + Parser* parser = parser_; |
| const AstRawString* name = pattern->raw_name(); |
| VariableProxy* proxy = parser->NewUnresolved(name, descriptor_->mode); |
| Declaration* declaration = factory()->NewVariableDeclaration( |
| @@ -213,8 +247,14 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) { |
| Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { |
| - auto temp = descriptor_->parser->scope_->NewTemporary( |
| - ast_value_factory()->empty_string()); |
| + if (value && value->IsDoExpression()) { |
| + // Re-use completion values from |do-expressions| |
| + block_->statements()->Add( |
|
caitp (gmail)
2015/10/19 12:10:50
I was hoping this would help reduce the number of
|
| + factory()->NewExpressionStatement(value, RelocInfo::kNoPosition), |
| + zone()); |
| + return value->AsDoExpression()->result()->var(); |
| + } |
| + auto temp = parser_scope()->NewTemporary(ast_value_factory()->empty_string()); |
| if (value != nullptr) { |
| auto assignment = factory()->NewAssignment( |
| Token::ASSIGN, factory()->NewVariableProxy(temp), value, |
| @@ -230,9 +270,9 @@ Variable* Parser::PatternRewriter::CreateTempVar(Expression* value) { |
| void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { |
| auto temp = CreateTempVar(current_value_); |
| + if (rhs_ == nullptr) rhs_ = temp; |
| - block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), |
| - zone()); |
| + block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone()); |
| for (ObjectLiteralProperty* property : *pattern->properties()) { |
| RecurseIntoSubpattern( |
| @@ -245,12 +285,18 @@ void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern) { |
| void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { |
| auto temp = CreateTempVar(current_value_); |
| + if (rhs_ == nullptr) rhs_ = temp; |
| + |
| + Block* outer_block = block_; |
| - block_->statements()->Add(descriptor_->parser->BuildAssertIsCoercible(temp), |
| - zone()); |
| + if (context() == ASSIGNMENT) { |
| + block_ = factory()->NewBlock(nullptr, 4, false, node->position()); |
| + } |
| - auto iterator = CreateTempVar(descriptor_->parser->GetIterator( |
| - factory()->NewVariableProxy(temp), factory())); |
| + block_->statements()->Add(parser_->BuildAssertIsCoercible(temp), zone()); |
| + |
| + auto iterator = CreateTempVar( |
| + parser_->GetIterator(factory()->NewVariableProxy(temp), factory())); |
| auto done = CreateTempVar( |
| factory()->NewBooleanLiteral(false, RelocInfo::kNoPosition)); |
| auto result = CreateTempVar(); |
| @@ -269,13 +315,12 @@ void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { |
| // } |
| auto next_block = |
| factory()->NewBlock(nullptr, 2, true, RelocInfo::kNoPosition); |
| - next_block->statements()->Add( |
| - factory()->NewExpressionStatement( |
| - descriptor_->parser->BuildIteratorNextResult( |
| - factory()->NewVariableProxy(iterator), result, |
| - RelocInfo::kNoPosition), |
| - RelocInfo::kNoPosition), |
| - zone()); |
| + next_block->statements()->Add(factory()->NewExpressionStatement( |
| + parser_->BuildIteratorNextResult( |
| + factory()->NewVariableProxy(iterator), |
| + result, RelocInfo::kNoPosition), |
| + RelocInfo::kNoPosition), |
| + zone()); |
| auto assign_to_done = factory()->NewAssignment( |
| Token::ASSIGN, factory()->NewVariableProxy(done), |
| @@ -322,7 +367,7 @@ void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { |
| empty_exprs, |
| // Reuse pattern's literal index - it is unused since there is no |
| // actual literal allocated. |
| - node->literal_index(), is_strong(descriptor_->parser->language_mode()), |
| + node->literal_index(), is_strong(parser_->language_mode()), |
| RelocInfo::kNoPosition)); |
| auto arguments = new (zone()) ZoneList<Expression*>(2, zone()); |
| @@ -345,6 +390,14 @@ void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { |
| RecurseIntoSubpattern(spread->expression(), |
| factory()->NewVariableProxy(array)); |
| } |
| + |
| + if (outer_block != block_) { |
| + DoExpression* work = |
| + factory()->NewDoExpression(block_, temp, node->position()); |
| + block_ = outer_block; |
| + block_->statements()->Add( |
| + factory()->NewExpressionStatement(work, node->position()), zone()); |
| + } |
| } |
| @@ -353,6 +406,12 @@ void Parser::PatternRewriter::VisitAssignment(Assignment* node) { |
| // becomes |
| // temp = <value>; |
| // <pattern> = temp === undefined ? <init> : temp; |
| + PatternContext old_context = context(); |
| + if (old_context == INITIALIZER) { |
| + set_context(ASSIGNMENT); |
| + } else if (old_context == BINDING) { |
| + set_context(INITIALIZER); |
| + } |
| DCHECK(node->op() == Token::ASSIGN); |
| auto temp = CreateTempVar(current_value_); |
| Expression* is_undefined = factory()->NewCompareOperation( |
| @@ -363,6 +422,20 @@ void Parser::PatternRewriter::VisitAssignment(Assignment* node) { |
| is_undefined, node->value(), factory()->NewVariableProxy(temp), |
| RelocInfo::kNoPosition); |
| RecurseIntoSubpattern(node->target(), value); |
| + set_context(old_context); |
| +} |
| + |
| + |
| +// =============== ASSIGNMENT-ONLY ========================= |
| + |
| +void Parser::PatternRewriter::VisitProperty(v8::internal::Property* pattern) { |
| + DCHECK(context() == ASSIGNMENT); |
| + Expression* value = current_value_; |
| + Assignment* assignment = factory()->NewAssignment(Token::ASSIGN, pattern, |
| + value, pattern->position()); |
| + block_->statements()->Add( |
| + factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition), |
| + zone()); |
| } |
| @@ -403,7 +476,6 @@ NOT_A_PATTERN(IfStatement) |
| NOT_A_PATTERN(ImportDeclaration) |
| NOT_A_PATTERN(Literal) |
| NOT_A_PATTERN(NativeFunctionLiteral) |
| -NOT_A_PATTERN(Property) |
| NOT_A_PATTERN(RegExpLiteral) |
| NOT_A_PATTERN(ReturnStatement) |
| NOT_A_PATTERN(SloppyBlockFunctionStatement) |