Chromium Code Reviews| 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 |