// Copyright 2015 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/ast/ast-expression-rewriter.h" #include "src/ast/ast.h" #include "src/objects-inl.h" namespace v8 { namespace internal { // ---------------------------------------------------------------------------- // Implementation of AstExpressionRewriter // The AST is traversed but no actual rewriting takes place, unless the // Visit methods are overriden in subclasses. #define REWRITE_THIS(node) \ do { \ if (!RewriteExpression(node)) return; \ } while (false) #define NOTHING() DCHECK_NULL(replacement_) void AstExpressionRewriter::VisitDeclarations(Declaration::List* declarations) { for (Declaration::List::Iterator it = declarations->begin(); it != declarations->end(); ++it) { AST_REWRITE(Declaration, *it, it = replacement); } } void AstExpressionRewriter::VisitStatements(ZoneList* statements) { for (int i = 0; i < statements->length(); i++) { AST_REWRITE_LIST_ELEMENT(Statement, statements, i); // Not stopping when a jump statement is found. } } void AstExpressionRewriter::VisitExpressions( ZoneList* expressions) { for (int i = 0; i < expressions->length(); i++) { // The variable statement visiting code may pass NULL expressions // to this code. Maybe this should be handled by introducing an // undefined expression or literal? Revisit this code if this // changes if (expressions->at(i) != nullptr) { AST_REWRITE_LIST_ELEMENT(Expression, expressions, i); } } } void AstExpressionRewriter::VisitVariableDeclaration( VariableDeclaration* node) { // Not visiting `proxy_`. NOTHING(); } void AstExpressionRewriter::VisitFunctionDeclaration( FunctionDeclaration* node) { // Not visiting `proxy_`. AST_REWRITE_PROPERTY(FunctionLiteral, node, fun); } void AstExpressionRewriter::VisitBlock(Block* node) { VisitStatements(node->statements()); } void AstExpressionRewriter::VisitExpressionStatement( ExpressionStatement* node) { AST_REWRITE_PROPERTY(Expression, node, expression); } void AstExpressionRewriter::VisitEmptyStatement(EmptyStatement* node) { NOTHING(); } void AstExpressionRewriter::VisitSloppyBlockFunctionStatement( SloppyBlockFunctionStatement* node) { AST_REWRITE_PROPERTY(Statement, node, statement); } void AstExpressionRewriter::VisitIfStatement(IfStatement* node) { AST_REWRITE_PROPERTY(Expression, node, condition); AST_REWRITE_PROPERTY(Statement, node, then_statement); AST_REWRITE_PROPERTY(Statement, node, else_statement); } void AstExpressionRewriter::VisitContinueStatement(ContinueStatement* node) { NOTHING(); } void AstExpressionRewriter::VisitBreakStatement(BreakStatement* node) { NOTHING(); } void AstExpressionRewriter::VisitReturnStatement(ReturnStatement* node) { AST_REWRITE_PROPERTY(Expression, node, expression); } void AstExpressionRewriter::VisitWithStatement(WithStatement* node) { AST_REWRITE_PROPERTY(Expression, node, expression); AST_REWRITE_PROPERTY(Statement, node, statement); } void AstExpressionRewriter::VisitSwitchStatement(SwitchStatement* node) { AST_REWRITE_PROPERTY(Expression, node, tag); ZoneList* clauses = node->cases(); for (int i = 0; i < clauses->length(); i++) { AST_REWRITE_LIST_ELEMENT(CaseClause, clauses, i); } } void AstExpressionRewriter::VisitDoWhileStatement(DoWhileStatement* node) { AST_REWRITE_PROPERTY(Expression, node, cond); AST_REWRITE_PROPERTY(Statement, node, body); } void AstExpressionRewriter::VisitWhileStatement(WhileStatement* node) { AST_REWRITE_PROPERTY(Expression, node, cond); AST_REWRITE_PROPERTY(Statement, node, body); } void AstExpressionRewriter::VisitForStatement(ForStatement* node) { if (node->init() != nullptr) { AST_REWRITE_PROPERTY(Statement, node, init); } if (node->cond() != nullptr) { AST_REWRITE_PROPERTY(Expression, node, cond); } if (node->next() != nullptr) { AST_REWRITE_PROPERTY(Statement, node, next); } AST_REWRITE_PROPERTY(Statement, node, body); } void AstExpressionRewriter::VisitForInStatement(ForInStatement* node) { AST_REWRITE_PROPERTY(Expression, node, each); AST_REWRITE_PROPERTY(Expression, node, subject); AST_REWRITE_PROPERTY(Statement, node, body); } void AstExpressionRewriter::VisitForOfStatement(ForOfStatement* node) { AST_REWRITE_PROPERTY(Expression, node, assign_iterator); AST_REWRITE_PROPERTY(Expression, node, next_result); AST_REWRITE_PROPERTY(Expression, node, result_done); AST_REWRITE_PROPERTY(Expression, node, assign_each); AST_REWRITE_PROPERTY(Statement, node, body); } void AstExpressionRewriter::VisitTryCatchStatement(TryCatchStatement* node) { AST_REWRITE_PROPERTY(Block, node, try_block); // Not visiting the variable. AST_REWRITE_PROPERTY(Block, node, catch_block); } void AstExpressionRewriter::VisitTryFinallyStatement( TryFinallyStatement* node) { AST_REWRITE_PROPERTY(Block, node, try_block); AST_REWRITE_PROPERTY(Block, node, finally_block); } void AstExpressionRewriter::VisitDebuggerStatement(DebuggerStatement* node) { NOTHING(); } void AstExpressionRewriter::VisitFunctionLiteral(FunctionLiteral* node) { REWRITE_THIS(node); VisitDeclarations(node->scope()->declarations()); ZoneList* body = node->body(); if (body != nullptr) VisitStatements(body); } void AstExpressionRewriter::VisitClassLiteral(ClassLiteral* node) { REWRITE_THIS(node); // Not visiting `class_variable_proxy_`. if (node->extends() != nullptr) { AST_REWRITE_PROPERTY(Expression, node, extends); } AST_REWRITE_PROPERTY(FunctionLiteral, node, constructor); ZoneList* properties = node->properties(); for (int i = 0; i < properties->length(); i++) { VisitLiteralProperty(properties->at(i)); } } void AstExpressionRewriter::VisitNativeFunctionLiteral( NativeFunctionLiteral* node) { REWRITE_THIS(node); NOTHING(); } void AstExpressionRewriter::VisitConditional(Conditional* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, condition); AST_REWRITE_PROPERTY(Expression, node, then_expression); AST_REWRITE_PROPERTY(Expression, node, else_expression); } void AstExpressionRewriter::VisitVariableProxy(VariableProxy* node) { REWRITE_THIS(node); NOTHING(); } void AstExpressionRewriter::VisitLiteral(Literal* node) { REWRITE_THIS(node); NOTHING(); } void AstExpressionRewriter::VisitRegExpLiteral(RegExpLiteral* node) { REWRITE_THIS(node); NOTHING(); } void AstExpressionRewriter::VisitObjectLiteral(ObjectLiteral* node) { REWRITE_THIS(node); ZoneList* properties = node->properties(); for (int i = 0; i < properties->length(); i++) { VisitLiteralProperty(properties->at(i)); } } void AstExpressionRewriter::VisitLiteralProperty(LiteralProperty* property) { if (property == nullptr) return; AST_REWRITE_PROPERTY(Expression, property, key); AST_REWRITE_PROPERTY(Expression, property, value); } void AstExpressionRewriter::VisitArrayLiteral(ArrayLiteral* node) { REWRITE_THIS(node); VisitExpressions(node->values()); } void AstExpressionRewriter::VisitAssignment(Assignment* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, target); AST_REWRITE_PROPERTY(Expression, node, value); } void AstExpressionRewriter::VisitYield(Yield* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, generator_object); AST_REWRITE_PROPERTY(Expression, node, expression); } void AstExpressionRewriter::VisitThrow(Throw* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, exception); } void AstExpressionRewriter::VisitProperty(Property* node) { REWRITE_THIS(node); if (node == nullptr) return; AST_REWRITE_PROPERTY(Expression, node, obj); AST_REWRITE_PROPERTY(Expression, node, key); } void AstExpressionRewriter::VisitCall(Call* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, expression); VisitExpressions(node->arguments()); } void AstExpressionRewriter::VisitCallNew(CallNew* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, expression); VisitExpressions(node->arguments()); } void AstExpressionRewriter::VisitCallRuntime(CallRuntime* node) { REWRITE_THIS(node); VisitExpressions(node->arguments()); } void AstExpressionRewriter::VisitUnaryOperation(UnaryOperation* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, expression); } void AstExpressionRewriter::VisitCountOperation(CountOperation* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, expression); } void AstExpressionRewriter::VisitBinaryOperation(BinaryOperation* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, left); AST_REWRITE_PROPERTY(Expression, node, right); } void AstExpressionRewriter::VisitCompareOperation(CompareOperation* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, left); AST_REWRITE_PROPERTY(Expression, node, right); } void AstExpressionRewriter::VisitSpread(Spread* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Expression, node, expression); } void AstExpressionRewriter::VisitThisFunction(ThisFunction* node) { REWRITE_THIS(node); NOTHING(); } void AstExpressionRewriter::VisitSuperPropertyReference( SuperPropertyReference* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(VariableProxy, node, this_var); AST_REWRITE_PROPERTY(Expression, node, home_object); } void AstExpressionRewriter::VisitSuperCallReference(SuperCallReference* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(VariableProxy, node, this_var); AST_REWRITE_PROPERTY(VariableProxy, node, new_target_var); AST_REWRITE_PROPERTY(VariableProxy, node, this_function_var); } void AstExpressionRewriter::VisitCaseClause(CaseClause* node) { if (!node->is_default()) { AST_REWRITE_PROPERTY(Expression, node, label); } VisitStatements(node->statements()); } void AstExpressionRewriter::VisitEmptyParentheses(EmptyParentheses* node) { NOTHING(); } void AstExpressionRewriter::VisitGetIterator(GetIterator* node) { AST_REWRITE_PROPERTY(Expression, node, iterable); } void AstExpressionRewriter::VisitDoExpression(DoExpression* node) { REWRITE_THIS(node); AST_REWRITE_PROPERTY(Block, node, block); AST_REWRITE_PROPERTY(VariableProxy, node, result); } void AstExpressionRewriter::VisitRewritableExpression( RewritableExpression* node) { REWRITE_THIS(node); AST_REWRITE(Expression, node->expression(), node->Rewrite(replacement)); } } // namespace internal } // namespace v8