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) |