Index: src/parsing/parser.cc |
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc |
index a11a5d390e5eb6543892f61566dacb0e08639797..40aae0e69274df42546c0897fe6ab70d95ed5eee 100644 |
--- a/src/parsing/parser.cc |
+++ b/src/parsing/parser.cc |
@@ -6,6 +6,7 @@ |
#include "src/api.h" |
#include "src/ast/ast.h" |
+#include "src/ast/ast-expression-rewriter.h" |
#include "src/ast/ast-expression-visitor.h" |
#include "src/ast/ast-literal-reindexer.h" |
#include "src/ast/scopeinfo.h" |
@@ -6513,9 +6514,44 @@ ObjectLiteralProperty* ParserTraits::RewriteObjectLiteralProperty( |
} |
+class SpreadRewriter : public AstExpressionRewriter { |
nickie
2016/01/07 16:58:11
For the time being, this just rewrites spreads in
|
+ public: |
+ SpreadRewriter(uintptr_t stack_limit, Parser* parser) |
+ : AstExpressionRewriter(stack_limit), parser_(parser) {} |
+ ~SpreadRewriter() override {} |
+ |
+ private: |
+ bool RewriteExpression(Expression* expr) override { |
+ // Rewrite only what could have been a pattern. |
+ // The actual work is in array literals. |
+ if (expr->IsArrayLiteral()) { |
+ ArrayLiteral* lit = expr->AsArrayLiteral(); |
+ VisitExpressions(lit->values()); |
+ replacement_ = parser_->RewriteSpreads(lit); |
+ return false; |
+ } |
+ if (expr->IsObjectLiteral()) { |
+ return true; |
+ } |
+ if (expr->IsBinaryOperation() && |
+ expr->AsBinaryOperation()->op() == Token::COMMA) { |
+ return true; |
+ } |
+ // Everything else does not need rewriting. |
+ return false; |
+ } |
+ |
+ Parser* parser_; |
+}; |
+ |
+ |
Expression* Parser::RewriteExpression(Expression* expr) { |
- // TODO(nikolaos): For the time being, this does no rewriting at all. |
- return expr; |
+ SpreadRewriter rewriter(stack_limit_, this); |
+ AstNode* node = rewriter.Rewrite(expr); |
+ DCHECK_NOT_NULL(node); |
+ Expression* result = reinterpret_cast<Expression*>(node); |
+ DCHECK_NOT_NULL(result); |
+ return result; |
} |
@@ -6551,6 +6587,104 @@ void Parser::RewriteDestructuringAssignments() { |
} |
+Expression* Parser::RewriteSpreads(ArrayLiteral* lit) { |
+ ZoneList<Expression*>::iterator s = lit->FirstSpread(); |
+ if (s == lit->EndValue()) return nullptr; |
+ // TODO(nikolaos): Check and fix the positions for the generated AST. |
+ Variable* result = |
+ scope_->NewTemporary(ast_value_factory()->dot_result_string()); |
+ Expression* init_result = |
+ factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result), |
+ lit, RelocInfo::kNoPosition); |
+ Block* do_block = |
+ factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition); |
+ do_block->statements()->Add( |
+ factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition), |
+ zone()); |
+ while (s != lit->EndValue()) { |
+ Expression* value = *s++; |
+ Spread* spread = value->AsSpread(); |
+ if (spread == nullptr) { |
+ ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone()); |
+ append_element_args->Add(factory()->NewVariableProxy(result), zone()); |
+ append_element_args->Add(value, zone()); |
+ do_block->statements()->Add( |
+ factory()->NewExpressionStatement( |
+ factory()->NewCallRuntime(Runtime::kAppendElement, |
+ append_element_args, |
+ RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition), |
+ zone()); |
+ } else { |
+ Variable* each = |
+ scope_->NewTemporary(ast_value_factory()->dot_for_string()); |
+ Expression* subject = spread->expression(); |
+ Variable* iterator = |
+ scope_->NewTemporary(ast_value_factory()->dot_iterator_string()); |
+ Variable* element = |
+ scope_->NewTemporary(ast_value_factory()->dot_result_string()); |
+ // iterator = subject[Symbol.iterator]() |
+ Expression* assign_iterator = factory()->NewAssignment( |
+ Token::ASSIGN, factory()->NewVariableProxy(iterator), |
+ GetIterator(subject, factory(), spread->position()), |
+ spread->position()); |
+ // !%_IsJSReceiver(element = iterator.next()) && |
+ // %ThrowIteratorResultNotAnObject(element) |
+ Expression* next_element; |
+ { |
+ // element = iterator.next() |
+ Expression* iterator_proxy = factory()->NewVariableProxy(iterator); |
+ next_element = BuildIteratorNextResult(iterator_proxy, element, |
+ spread->position()); |
+ } |
+ // element.done |
+ Expression* element_done; |
+ { |
+ Expression* done_literal = factory()->NewStringLiteral( |
+ ast_value_factory()->done_string(), RelocInfo::kNoPosition); |
+ Expression* element_proxy = factory()->NewVariableProxy(element); |
+ element_done = factory()->NewProperty(element_proxy, done_literal, |
+ RelocInfo::kNoPosition); |
+ } |
+ // each = element.value |
+ Expression* assign_each; |
+ { |
+ Expression* value_literal = factory()->NewStringLiteral( |
+ ast_value_factory()->value_string(), RelocInfo::kNoPosition); |
+ Expression* element_proxy = factory()->NewVariableProxy(element); |
+ Expression* element_value = factory()->NewProperty( |
+ element_proxy, value_literal, RelocInfo::kNoPosition); |
+ assign_each = factory()->NewAssignment( |
+ Token::ASSIGN, factory()->NewVariableProxy(each), element_value, |
+ RelocInfo::kNoPosition); |
+ } |
+ // append each to the result |
+ Statement* append_body; |
+ { |
+ ZoneList<Expression*>* append_element_args = |
+ NewExpressionList(2, zone()); |
+ append_element_args->Add(factory()->NewVariableProxy(result), zone()); |
+ append_element_args->Add(factory()->NewVariableProxy(each), zone()); |
+ append_body = factory()->NewExpressionStatement( |
+ factory()->NewCallRuntime(Runtime::kAppendElement, |
+ append_element_args, |
+ RelocInfo::kNoPosition), |
+ RelocInfo::kNoPosition); |
+ } |
+ ForEachStatement* loop = factory()->NewForEachStatement( |
+ ForEachStatement::ITERATE, nullptr, spread->position()); |
+ ForOfStatement* for_of = loop->AsForOfStatement(); |
+ for_of->Initialize(factory()->NewVariableProxy(each), subject, |
+ append_body, assign_iterator, next_element, |
+ element_done, assign_each); |
+ do_block->statements()->Add(for_of, zone()); |
+ } |
+ } |
+ lit->RewindSpreads(); |
+ return factory()->NewDoExpression(do_block, result, lit->position()); |
+} |
+ |
+ |
void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) { |
DCHECK(expr->IsRewritableAssignmentExpression()); |
parser_->function_state_->AddDestructuringAssignment( |