Index: src/parser.h |
diff --git a/src/parser.h b/src/parser.h |
index 6c641721861146f7d53c9f9f31f322802276e6e6..ea3c7acf9faea7e92e88d08e75191abcf12278d5 100644 |
--- a/src/parser.h |
+++ b/src/parser.h |
@@ -888,6 +888,11 @@ class ParserTraits { |
ZoneList<v8::internal::Expression*>* args, |
int pos); |
+ // Rewrite all DestructuringAssignments in the current FunctionState. |
+ V8_INLINE void RewriteDestructuringAssignments(); |
+ |
+ V8_INLINE void ShouldRewriteDestructuringAssignment(Expression* assignment); |
+ |
private: |
Parser* parser_; |
}; |
@@ -1035,6 +1040,10 @@ class Parser : public ParserBase<ParserTraits> { |
const DeclarationParsingResult::Declaration* declaration, |
ZoneList<const AstRawString*>* names, bool* ok); |
+ static void RewriteDestructuringAssignment(Parser* parser, |
+ Assignment* assignment, |
+ Scope* Scope, bool* ok); |
+ |
void set_initializer_position(int pos) { initializer_position_ = pos; } |
private: |
@@ -1046,6 +1055,16 @@ class Parser : public ParserBase<ParserTraits> { |
#undef DECLARE_VISIT |
void Visit(AstNode* node) override; |
+ enum PatternContext { |
+ BINDING, |
+ INITIALIZER, |
+ ASSIGNMENT, |
+ ASSIGNMENT_INITIALIZER |
+ }; |
+ |
+ PatternContext context() const { return context_; } |
+ void set_context(PatternContext context) { context_ = context; } |
+ |
void RecurseIntoSubpattern(AstNode* pattern, Expression* value) { |
Expression* old_value = current_value_; |
current_value_ = value; |
@@ -1053,14 +1072,57 @@ class Parser : public ParserBase<ParserTraits> { |
current_value_ = old_value; |
} |
+ void VisitObjectLiteral(ObjectLiteral* node, Variable** temp_var); |
+ void VisitArrayLiteral(ArrayLiteral* node, Variable** temp_var); |
+ |
+ bool IsBindingContext() const { return IsBindingContext(context_); } |
+ bool IsInitializerContext() const { return context_ != ASSIGNMENT; } |
+ bool IsAssignmentContext() const { return IsAssignmentContext(context_); } |
+ bool IsAssignmentContext(PatternContext c) const { |
+ return c == ASSIGNMENT || c == ASSIGNMENT_INITIALIZER; |
+ } |
+ bool IsBindingContext(PatternContext c) const { |
+ return c == BINDING || c == INITIALIZER; |
+ } |
+ PatternContext SetAssignmentContextIfNeeded(Expression* node) { |
+ PatternContext old_context = context(); |
+ if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN) { |
+ set_context(ASSIGNMENT); |
+ } |
+ return old_context; |
+ } |
+ |
+ PatternContext SetInitializerContextIfNeeded(Expression* node) { |
adamk
2015/11/25 21:05:28
Any reason all of these functions need to be in th
caitp (gmail)
2015/11/25 21:41:51
No real reason, it was just convenient while writi
|
+ // Set appropriate initializer context for BindingElement and |
+ // AssignmentElement nodes |
+ PatternContext old_context = context(); |
+ if (node->IsAssignment() && node->AsAssignment()->op() == Token::ASSIGN) { |
+ switch (old_context) { |
+ case BINDING: |
+ set_context(INITIALIZER); |
+ break; |
+ case ASSIGNMENT: |
+ set_context(ASSIGNMENT_INITIALIZER); |
+ break; |
+ default: |
+ break; |
+ } |
+ } |
+ return old_context; |
+ } |
+ |
Variable* CreateTempVar(Expression* value = nullptr); |
- AstNodeFactory* factory() const { return descriptor_->parser->factory(); } |
+ AstNodeFactory* factory() const { return parser_->factory(); } |
AstValueFactory* ast_value_factory() const { |
- return descriptor_->parser->ast_value_factory(); |
+ return parser_->ast_value_factory(); |
} |
- Zone* zone() const { return descriptor_->parser->zone(); } |
+ Zone* zone() const { return parser_->zone(); } |
+ Scope* scope() const { return scope_; } |
+ Scope* scope_; |
+ Parser* parser_; |
+ PatternContext context_; |
Expression* pattern_; |
int initializer_position_; |
Block* block_; |
@@ -1210,6 +1272,11 @@ class Parser : public ParserBase<ParserTraits> { |
void SetLanguageMode(Scope* scope, LanguageMode mode); |
void RaiseLanguageMode(LanguageMode mode); |
+ V8_INLINE void RewriteDestructuringAssignments(); |
+ |
+ friend class InitializerRewriter; |
+ void RewriteParameterInitializer(Expression* expr, Scope* scope); |
+ |
Scanner scanner_; |
PreParser* reusable_preparser_; |
Scope* original_scope_; // for ES5 function declarations in sloppy eval |
@@ -1398,6 +1465,54 @@ DoExpression* ParserTraits::ParseDoExpression(bool* ok) { |
} |
+void ParserTraits::RewriteDestructuringAssignments() { |
+ parser_->RewriteDestructuringAssignments(); |
+} |
+ |
+ |
+void Parser::RewriteDestructuringAssignments() { |
adamk
2015/11/25 21:05:28
Another "why is this in the header?" question.
|
+ FunctionState* func = function_state_; |
+ if (!allow_harmony_destructuring_assignment()) return; |
+ typedef typename ParserBase<ParserTraits>::DestructuringAssignment Pair; |
+ const List<Pair>& assignments = func->destructuring_assignments_to_rewrite(); |
+ for (int i = assignments.length() - 1; i >= 0; --i) { |
+ // Rewrite list in reverse, so that nested assignment patterns are rewritten |
+ // correctly. |
+ Pair pair = assignments.at(i); |
+ Assignment* to_rewrite = pair.assignment->AsAssignment(); |
+ Scope* scope = pair.scope; |
+ DCHECK_NOT_NULL(to_rewrite); |
+ DCHECK(to_rewrite->is_destructuring_assignment()); |
+ if (!to_rewrite->destructuring_assignment()) { |
+ bool ok = true; |
+ PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope, |
+ &ok); |
+ DCHECK(ok); |
+ } |
+ } |
+} |
+ |
+ |
+void ParserTraits::ShouldRewriteDestructuringAssignment(Expression* expr) { |
adamk
2015/11/25 21:05:28
And here...
Also, as mentioned before, this name
caitp (gmail)
2015/11/25 21:41:51
Acknowledged.
|
+ DCHECK(expr->IsAssignment()); |
+ Assignment* assignment = expr->AsAssignment(); |
+ DCHECK(!assignment->is_destructuring_assignment()); |
+ DCHECK_EQ(Token::ASSIGN, assignment->op()); |
+ assignment->set_is_destructuring_assignment(); |
+ parser_->function_state_->AddDestructuringAssignment( |
+ Parser::DestructuringAssignment(assignment, parser_->scope_)); |
+} |
+ |
+inline void Parser::PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) { |
adamk
2015/11/25 21:05:28
And here and the below. parser.h is long enough as
|
+ Variable* temp_var = nullptr; |
+ VisitObjectLiteral(node, &temp_var); |
+} |
+ |
+inline void Parser::PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) { |
+ Variable* temp_var = nullptr; |
+ VisitArrayLiteral(node, &temp_var); |
+} |
+ |
} // namespace internal |
} // namespace v8 |