Chromium Code Reviews| Index: src/ast/ast.h |
| diff --git a/src/ast/ast.h b/src/ast/ast.h |
| index 0174a13478c458671a60bb0b0041e9c00acddf60..6cd77869ae35ec937d342ae01780d61f064b3764 100644 |
| --- a/src/ast/ast.h |
| +++ b/src/ast/ast.h |
| @@ -91,7 +91,7 @@ namespace internal { |
| V(CaseClause) \ |
| V(EmptyParentheses) \ |
| V(DoExpression) \ |
| - V(RewritableAssignmentExpression) |
| + V(RewritableExpression) |
| #define AST_NODE_LIST(V) \ |
| DECLARATION_NODE_LIST(V) \ |
| @@ -205,13 +205,9 @@ class AstNode: public ZoneObject { |
| // Type testing & conversion functions overridden by concrete subclasses. |
| #define DECLARE_NODE_FUNCTIONS(type) \ |
| - bool Is##type() const { return node_type() == AstNode::k##type; } \ |
| - type* As##type() { \ |
| - return Is##type() ? reinterpret_cast<type*>(this) : NULL; \ |
| - } \ |
| - const type* As##type() const { \ |
| - return Is##type() ? reinterpret_cast<const type*>(this) : NULL; \ |
| - } |
| + V8_INLINE bool Is##type() const; \ |
| + V8_INLINE type* As##type(); \ |
| + V8_INLINE const type* As##type() const; |
| AST_NODE_LIST(DECLARE_NODE_FUNCTIONS) |
| #undef DECLARE_NODE_FUNCTIONS |
| @@ -2509,18 +2505,32 @@ class Assignment final : public Expression { |
| }; |
| -class RewritableAssignmentExpression : public Expression { |
| +// The RewritableExpression class is a wrapper for AST nodes that wait |
| +// for some potential rewriting. However, even if such nodes are indeed |
| +// rewritten, the RewritableExpression wrapper nodes will survive in the |
| +// final AST and should be just ignored, i.e., they should be treated as |
| +// equivalent to the wrapped nodes. For this reason and to simplify later |
| +// phases, RewritableExpressions are considered as exceptions of AST nodes |
| +// in the following sense: |
| +// |
| +// 1. IsRewritableExpression and AsRewritableExpression behave as usual. |
| +// 2. All other Is* and As* methods are practically delegated to the |
| +// wrapped node, i.e. IsArrayLiteral() will return true iff the |
| +// wrapped node is an array literal. |
| +// |
| +// Furthermore, an invariant that should be respected is that the wrapped |
| +// node is not a RewritableExpression. |
| +class RewritableExpression : public Expression { |
| public: |
| - DECLARE_NODE_TYPE(RewritableAssignmentExpression) |
| + DECLARE_NODE_TYPE(RewritableExpression) |
| - Expression* expression() { return expr_; } |
| + Expression* expression() const { return expr_; } |
| bool is_rewritten() const { return is_rewritten_; } |
| - void set_expression(Expression* e) { expr_ = e; } |
| - |
| void Rewrite(Expression* new_expression) { |
| DCHECK(!is_rewritten()); |
| DCHECK_NOT_NULL(new_expression); |
| + DCHECK(!new_expression->IsRewritableExpression()); |
| expr_ = new_expression; |
| is_rewritten_ = true; |
| } |
| @@ -2528,10 +2538,12 @@ class RewritableAssignmentExpression : public Expression { |
| static int num_ids() { return parent_num_ids(); } |
| protected: |
| - RewritableAssignmentExpression(Zone* zone, Expression* expression) |
| + RewritableExpression(Zone* zone, Expression* expression) |
| : Expression(zone, expression->position()), |
| is_rewritten_(false), |
| - expr_(expression) {} |
| + expr_(expression) { |
| + DCHECK(!expression->IsRewritableExpression()); |
| + } |
| private: |
| int local_id(int n) const { return base_id() + parent_num_ids() + n; } |
| @@ -3387,12 +3399,9 @@ class AstNodeFactory final BASE_EMBEDDED { |
| local_zone_, condition, then_expression, else_expression, position); |
| } |
| - RewritableAssignmentExpression* NewRewritableAssignmentExpression( |
| - Expression* expression) { |
| + RewritableExpression* NewRewritableExpression(Expression* expression) { |
| DCHECK_NOT_NULL(expression); |
| - DCHECK(expression->IsAssignment()); |
| - return new (local_zone_) |
| - RewritableAssignmentExpression(local_zone_, expression); |
| + return new (local_zone_) RewritableExpression(local_zone_, expression); |
| } |
| Assignment* NewAssignment(Token::Value op, |
| @@ -3515,6 +3524,46 @@ class AstNodeFactory final BASE_EMBEDDED { |
| }; |
| +// Type testing & conversion functions overridden by concrete subclasses. |
| +// Inline functions for AstNode. |
| + |
| +#define DECLARE_NODE_FUNCTIONS(type) \ |
| + bool AstNode::Is##type() const { \ |
| + NodeType mine = node_type(); \ |
| + if (mine == AstNode::kRewritableExpression && \ |
| + AstNode::k##type != AstNode::kRewritableExpression) \ |
|
rossberg
2016/02/18 12:11:31
I assume compilers are smart enough to fold away t
nickie
2016/02/18 12:53:17
Yes, I also assumed this. If we have reason to be
|
| + mine = reinterpret_cast<const RewritableExpression*>(this) \ |
| + ->expression() \ |
| + ->node_type(); \ |
| + return mine == AstNode::k##type; \ |
| + } \ |
| + type* AstNode::As##type() { \ |
| + NodeType mine = node_type(); \ |
| + AstNode* result = this; \ |
| + if (mine == AstNode::kRewritableExpression && \ |
| + AstNode::k##type != AstNode::kRewritableExpression) { \ |
| + result = \ |
| + reinterpret_cast<const RewritableExpression*>(this)->expression(); \ |
|
rossberg
2016/02/18 12:11:32
I'm surprised C++ does not barf on the cast in lin
nickie
2016/02/18 12:53:17
I don't see why it should, but anyway. The const
|
| + mine = result->node_type(); \ |
| + } \ |
| + return mine == AstNode::k##type ? reinterpret_cast<type*>(result) : NULL; \ |
| + } \ |
| + const type* AstNode::As##type() const { \ |
| + NodeType mine = node_type(); \ |
| + const AstNode* result = this; \ |
| + if (mine == AstNode::kRewritableExpression && \ |
| + AstNode::k##type != AstNode::kRewritableExpression) { \ |
| + result = \ |
| + reinterpret_cast<const RewritableExpression*>(this)->expression(); \ |
| + mine = result->node_type(); \ |
| + } \ |
| + return mine == AstNode::k##type ? reinterpret_cast<const type*>(result) \ |
| + : NULL; \ |
| + } |
| +AST_NODE_LIST(DECLARE_NODE_FUNCTIONS) |
| +#undef DECLARE_NODE_FUNCTIONS |
| + |
| + |
| } // namespace internal |
| } // namespace v8 |