// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef VM_AST_H_
#define VM_AST_H_

#include "platform/assert.h"
#include "vm/allocation.h"
#include "vm/growable_array.h"
#include "vm/scopes.h"
#include "vm/object.h"
#include "vm/native_entry.h"
#include "vm/token.h"
#include "vm/token_position.h"

namespace dart {

#define FOR_EACH_NODE(V)                                                       \
  V(Await)                                                                     \
  V(AwaitMarker)                                                               \
  V(Return)                                                                    \
  V(Literal)                                                                   \
  V(Type)                                                                      \
  V(Assignable)                                                                \
  V(BinaryOp)                                                                  \
  V(BinaryOpWithMask32)                                                        \
  V(Comparison)                                                                \
  V(UnaryOp)                                                                   \
  V(ConditionalExpr)                                                           \
  V(If)                                                                        \
  V(Switch)                                                                    \
  V(Case)                                                                      \
  V(While)                                                                     \
  V(DoWhile)                                                                   \
  V(For)                                                                       \
  V(Jump)                                                                      \
  V(Stop)                                                                      \
  V(ArgumentList)                                                              \
  V(Array)                                                                     \
  V(Closure)                                                                   \
  V(InstanceCall)                                                              \
  V(StaticCall)                                                                \
  V(ClosureCall)                                                               \
  V(CloneContext)                                                              \
  V(ConstructorCall)                                                           \
  V(InstanceGetter)                                                            \
  V(InstanceSetter)                                                            \
  V(InitStaticField)                                                           \
  V(StaticGetter)                                                              \
  V(StaticSetter)                                                              \
  V(NativeBody)                                                                \
  V(Primary)                                                                   \
  V(LoadLocal)                                                                 \
  V(StoreLocal)                                                                \
  V(LoadInstanceField)                                                         \
  V(StoreInstanceField)                                                        \
  V(LoadStaticField)                                                           \
  V(StoreStaticField)                                                          \
  V(LoadIndexed)                                                               \
  V(StoreIndexed)                                                              \
  V(Sequence)                                                                  \
  V(Let)                                                                       \
  V(CatchClause)                                                               \
  V(TryCatch)                                                                  \
  V(Throw)                                                                     \
  V(InlinedFinally)                                                            \
  V(StringInterpolate)                                                         \


#define FORWARD_DECLARATION(BaseName) class BaseName##Node;
FOR_EACH_NODE(FORWARD_DECLARATION)
#undef FORWARD_DECLARATION


// Abstract class to implement an AST node visitor. An example is AstPrinter.
class AstNodeVisitor : public ValueObject {
 public:
  AstNodeVisitor() {}
  virtual ~AstNodeVisitor() {}

#define DEFINE_VISITOR_FUNCTION(BaseName)                                      \
  virtual void Visit##BaseName##Node(BaseName##Node* node) { }

  FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION)
#undef DEFINE_VISITOR_FUNCTION

 private:
  DISALLOW_COPY_AND_ASSIGN(AstNodeVisitor);
};


#define DECLARE_COMMON_NODE_FUNCTIONS(type)                                    \
  virtual void Visit(AstNodeVisitor* visitor);                                 \
  virtual const char* PrettyName() const;                                      \
  virtual type* As##type() { return this; }


class AstNode : public ZoneAllocated {
 public:
  explicit AstNode(TokenPosition token_pos)
      : token_pos_(token_pos) {
    ASSERT(!token_pos_.IsClassifying() ||
           (token_pos_ == TokenPosition::kMethodExtractor));
  }
  virtual ~AstNode() { }

  TokenPosition token_pos() const { return token_pos_; }

#define AST_TYPE_CHECK(BaseName)                                               \
  bool Is##BaseName##Node() { return As##BaseName##Node() != NULL; }           \
  virtual BaseName##Node* As##BaseName##Node() { return NULL; }

  FOR_EACH_NODE(AST_TYPE_CHECK)
#undef AST_TYPE_CHECK

  virtual void Visit(AstNodeVisitor* visitor) = 0;
  virtual void VisitChildren(AstNodeVisitor* visitor) const = 0;
  virtual const char* PrettyName() const = 0;

  // Convert the node into an assignment node using the rhs which is passed in,
  // this is typically used for converting nodes like LoadLocalNode,
  // LoadStaticFieldNode, InstanceGetterNode etc. which were created during
  // parsing as the assignment context was not known yet at that time.
  virtual AstNode* MakeAssignmentNode(AstNode* rhs) {
    return NULL;  // By default all nodes are not assignable.
  }

  // Return NULL if 'unary_op_kind' can't be applied.
  virtual AstNode* ApplyUnaryOp(Token::Kind unary_op_kind) {
    return NULL;
  }

  // Returns true if this node can be a compile-time constant, assuming
  // that all nodes it depends on are also compile-time constants of
  // the proper types and values.
  // See the concept of "potentially constant expression" in the language spec.
  // The purpose of IsPotentiallyConst is to detect cases where the node is
  // known NOT to be a constant expression, in which case false is returned and
  // a compile-time error is reported by the compiler. Otherwise, an error may
  // still be reported at run-time depending on actual values.
  virtual bool IsPotentiallyConst() const { return false; }

  // Analyzes an expression to determine whether it is a compile time
  // constant or not. Returns NULL if the expression is not a compile time
  // constant. Otherwise, the return value is an approximation of the
  // actual value of the const expression. The type of the returned value
  // corresponds to the type of the const expression and is either
  // Number, Integer, String, Bool, or anything else (not a subtype of
  // the former).
  virtual const Instance* EvalConstExpr() const { return NULL; }

 protected:
  friend class ParsedFunction;

 private:
  const TokenPosition token_pos_;
  DISALLOW_COPY_AND_ASSIGN(AstNode);
};


class AwaitNode : public AstNode {
 public:
  AwaitNode(TokenPosition token_pos,
            AstNode* expr,
            LocalVariable* saved_try_ctx,
            LocalVariable* async_saved_try_ctx,
            LocalVariable* outer_saved_try_ctx,
            LocalVariable* outer_async_saved_try_ctx,
            LocalScope* scope)
    : AstNode(token_pos),
      expr_(expr),
      saved_try_ctx_(saved_try_ctx),
      async_saved_try_ctx_(async_saved_try_ctx),
      outer_saved_try_ctx_(outer_saved_try_ctx),
      outer_async_saved_try_ctx_(outer_async_saved_try_ctx),
      scope_(scope) { }

  void VisitChildren(AstNodeVisitor* visitor) const {
    expr_->Visit(visitor);
  }

  AstNode* expr() const { return expr_; }
  LocalVariable* saved_try_ctx() const { return saved_try_ctx_; }
  LocalVariable* async_saved_try_ctx() const { return async_saved_try_ctx_; }
  LocalVariable* outer_saved_try_ctx() const { return outer_saved_try_ctx_; }
  LocalVariable* outer_async_saved_try_ctx() const {
    return outer_async_saved_try_ctx_;
  }
  LocalScope* scope() const { return scope_; }

  DECLARE_COMMON_NODE_FUNCTIONS(AwaitNode);

 private:
  AstNode* expr_;
  LocalVariable* saved_try_ctx_;
  LocalVariable* async_saved_try_ctx_;
  LocalVariable* outer_saved_try_ctx_;
  LocalVariable* outer_async_saved_try_ctx_;
  LocalScope* scope_;

  DISALLOW_COPY_AND_ASSIGN(AwaitNode);
};


// AwaitMarker nodes are used to generate markers that the FlowGraphBuilder
// relies on. A marker indicates that a new await state needs to be
// added to a function preamble. This type also triggers storing of the
// current context.
//
// It is expected (ASSERT) that an AwaitMarker is followed by
// a return node of kind kContinuationTarget. That is:
//   <AwaitMarker> -> <other nodes> -> <kContinuationTarget> -> <other nodes> ->
//   <AwaitMarker> -> ...
class AwaitMarkerNode : public AstNode {
 public:
  AwaitMarkerNode(LocalScope* async_scope,
                  LocalScope* await_scope,
                  TokenPosition token_pos)
    : AstNode(token_pos),
      async_scope_(async_scope),
      await_scope_(await_scope) {
    ASSERT(async_scope != NULL);
    ASSERT(await_scope != NULL);
    await_scope->CaptureLocalVariables(async_scope);
  }

  void VisitChildren(AstNodeVisitor* visitor) const { }

  LocalScope* async_scope() const { return async_scope_; }
  LocalScope* await_scope() const { return await_scope_; }

  DECLARE_COMMON_NODE_FUNCTIONS(AwaitMarkerNode);

 private:
  LocalScope* async_scope_;
  LocalScope* await_scope_;

  DISALLOW_COPY_AND_ASSIGN(AwaitMarkerNode);
};


class SequenceNode : public AstNode {
 public:
  SequenceNode(TokenPosition token_pos, LocalScope* scope)
    : AstNode(token_pos),
      scope_(scope),
      nodes_(4),
      label_(NULL) {
  }

  LocalScope* scope() const { return scope_; }

  SourceLabel* label() const { return label_; }
  void set_label(SourceLabel* value) { label_ = value; }

  void VisitChildren(AstNodeVisitor* visitor) const;

  void Add(AstNode* node);
  intptr_t length() const { return nodes_.length(); }
  AstNode* NodeAt(intptr_t index) const { return nodes_[index]; }
  void ReplaceNodeAt(intptr_t index, AstNode* value) { nodes_[index] = value; }

  DECLARE_COMMON_NODE_FUNCTIONS(SequenceNode);

  // Collects all nodes accessible from this sequence node into array 'nodes'.
  void CollectAllNodes(GrowableArray<AstNode*>* nodes);

 private:
  LocalScope* scope_;
  GrowableArray<AstNode*> nodes_;
  SourceLabel* label_;

  DISALLOW_COPY_AND_ASSIGN(SequenceNode);
};


class CloneContextNode : public AstNode {
 public:
  explicit CloneContextNode(TokenPosition token_pos)
    : AstNode(token_pos) {
  }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  DECLARE_COMMON_NODE_FUNCTIONS(CloneContextNode);

 private:
  DISALLOW_COPY_AND_ASSIGN(CloneContextNode);
};


class ArgumentListNode : public AstNode {
 public:
  explicit ArgumentListNode(TokenPosition token_pos)
     : AstNode(token_pos),
       nodes_(4),
       names_(Array::ZoneHandle()) {
  }

  void VisitChildren(AstNodeVisitor* visitor) const;

  void Add(AstNode* node) {
    nodes_.Add(node);
  }
  intptr_t length() const { return nodes_.length(); }
  AstNode* NodeAt(intptr_t index) const { return nodes_[index]; }
  void SetNodeAt(intptr_t index, AstNode* node) { nodes_[index] = node; }
  const Array& names() const { return names_; }
  void set_names(const Array& names) {
    names_ = names.raw();
  }
  const GrowableArray<AstNode*>& nodes() const { return nodes_; }

  DECLARE_COMMON_NODE_FUNCTIONS(ArgumentListNode);

 private:
  GrowableArray<AstNode*> nodes_;
  Array& names_;

  DISALLOW_COPY_AND_ASSIGN(ArgumentListNode);
};


class LetNode : public AstNode {
 public:
  explicit LetNode(TokenPosition token_pos);

  LocalVariable* TempAt(intptr_t i) const { return vars_[i]; }
  AstNode* InitializerAt(intptr_t i) const { return initializers_[i]; }

  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  LocalVariable* AddInitializer(AstNode* node);

  const GrowableArray<AstNode*>& nodes() const { return nodes_; }

  void AddNode(AstNode* node) { nodes_.Add(node); }

  intptr_t num_temps() const {
    return vars_.length();
  }

  void VisitChildren(AstNodeVisitor* visitor) const;

  DECLARE_COMMON_NODE_FUNCTIONS(LetNode);

 private:
  GrowableArray<LocalVariable*> vars_;
  GrowableArray<AstNode*> initializers_;
  GrowableArray<AstNode*> nodes_;

  DISALLOW_COPY_AND_ASSIGN(LetNode);
};


class ArrayNode : public AstNode {
 public:
  ArrayNode(TokenPosition token_pos, const AbstractType& type)
      : AstNode(token_pos),
        type_(type),
        elements_() {
    CheckFields();
  }
  ArrayNode(TokenPosition token_pos,
            const AbstractType& type,
            const GrowableArray<AstNode*>& elements)
      : AstNode(token_pos),
        type_(type),
        elements_(elements.length()) {
    CheckFields();
    for (intptr_t i = 0; i < elements.length(); i++) {
      elements_.Add(elements[i]);
    }
  }

  void VisitChildren(AstNodeVisitor* visitor) const;

  intptr_t length() const { return elements_.length(); }

  AstNode* ElementAt(intptr_t index) const { return elements_[index]; }
  void SetElementAt(intptr_t index, AstNode* value) {
    elements_[index] = value;
  }
  void AddElement(AstNode* expr) { elements_.Add(expr); }

  const AbstractType& type() const { return type_; }

  DECLARE_COMMON_NODE_FUNCTIONS(ArrayNode);

 private:
  const AbstractType& type_;
  GrowableArray<AstNode*> elements_;

  void CheckFields() {
    ASSERT(type_.IsZoneHandle());
    ASSERT(!type_.IsNull());
    ASSERT(type_.IsFinalized());
    // Type may be uninstantiated when creating a generic list literal.
    ASSERT((type_.arguments() == TypeArguments::null()) ||
           ((TypeArguments::Handle(type_.arguments()).Length() == 1)));
  }

  DISALLOW_IMPLICIT_CONSTRUCTORS(ArrayNode);
};


class StringInterpolateNode : public AstNode {
 public:
  StringInterpolateNode(TokenPosition token_pos, ArrayNode* value)
      : AstNode(token_pos), value_(value) { }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    value_->Visit(visitor);
  }

  ArrayNode* value() const { return value_; }

  virtual bool IsPotentiallyConst() const;

  DECLARE_COMMON_NODE_FUNCTIONS(StringInterpolateNode);

 private:
  ArrayNode* value_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StringInterpolateNode);
};


class LiteralNode : public AstNode {
 public:
  LiteralNode(TokenPosition token_pos, const Instance& literal)
      : AstNode(token_pos), literal_(literal) {
    ASSERT(literal_.IsNotTemporaryScopedHandle());
    ASSERT(literal_.IsSmi() || literal_.IsOld());
#if defined(DEBUG)
    if (literal_.IsString()) {
      ASSERT(String::Cast(literal_).IsSymbol());
    }
#endif  // defined(DEBUG)
    ASSERT(literal_.IsNull() ||
           Class::Handle(literal_.clazz()).is_finalized() ||
           Class::Handle(literal_.clazz()).is_prefinalized());
  }

  const Instance& literal() const { return literal_; }

  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const {
    return &literal();
  }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  virtual AstNode* ApplyUnaryOp(Token::Kind unary_op_kind);

  DECLARE_COMMON_NODE_FUNCTIONS(LiteralNode);

 private:
  const Instance& literal_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(LiteralNode);
};


class TypeNode : public AstNode {
 public:
  TypeNode(TokenPosition token_pos, const AbstractType& type)
      : AstNode(token_pos), type_(type) {
    ASSERT(type_.IsZoneHandle());
    ASSERT(!type_.IsNull());
    ASSERT(type_.IsFinalized());
    // A wellformed literal Type must be canonical.
    ASSERT(!type_.IsType() ||
           type_.IsMalformedOrMalbounded() ||
           type_.IsCanonical());
  }

  const AbstractType& type() const { return type_; }

  const char* TypeName() const;

  virtual const Instance* EvalConstExpr() const {
    if (!type_.IsInstantiated() || type_.IsMalformedOrMalbounded()) {
      return NULL;
    }
    return &type();
  }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  DECLARE_COMMON_NODE_FUNCTIONS(TypeNode);

 private:
  const AbstractType& type_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(TypeNode);
};


class AssignableNode : public AstNode {
 public:
  AssignableNode(TokenPosition token_pos,
                 AstNode* expr,
                 const AbstractType& type,
                 const String& dst_name)
      : AstNode(token_pos), expr_(expr), type_(type), dst_name_(dst_name) {
    ASSERT(expr_ != NULL);
    ASSERT(type_.IsZoneHandle());
    ASSERT(!type_.IsNull());
    ASSERT(type_.IsFinalized());
    ASSERT(dst_name_.IsNotTemporaryScopedHandle());
  }

  AstNode* expr() const { return expr_; }
  const AbstractType& type() const { return type_; }
  const String& dst_name() const { return dst_name_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    expr()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(AssignableNode);

 private:
  AstNode* expr_;
  const AbstractType& type_;
  const String& dst_name_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(AssignableNode);
};


class ClosureNode : public AstNode {
 public:
  ClosureNode(TokenPosition token_pos,
              const Function& function,
              AstNode* receiver,  // Non-null for implicit instance closures.
              LocalScope* scope)  // Null for implicit closures.
      : AstNode(token_pos),
        function_(function),
        receiver_(receiver),
        scope_(scope),
        is_deferred_reference_(false) {
    ASSERT(function_.IsZoneHandle());
    ASSERT((function_.IsNonImplicitClosureFunction() &&
            (receiver_ == NULL) && (scope_ != NULL)) ||
           (function_.IsImplicitInstanceClosureFunction() &&
            (receiver_ != NULL) && (scope_ == NULL)) ||
           (function_.IsImplicitStaticClosureFunction() &&
            (receiver_ == NULL) && (scope_ == NULL)));
  }

  const Function& function() const { return function_; }
  AstNode* receiver() const { return receiver_; }
  LocalScope* scope() const { return scope_; }

  void set_is_deferred(bool value) { is_deferred_reference_ = value; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    if (receiver() != NULL) {
      receiver()->Visit(visitor);
    }
  }

  virtual AstNode* MakeAssignmentNode(AstNode* rhs);
  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  DECLARE_COMMON_NODE_FUNCTIONS(ClosureNode);

 private:
  const Function& function_;
  AstNode* receiver_;
  LocalScope* scope_;
  bool is_deferred_reference_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureNode);
};


// Primary nodes hold identifiers or values (library, class or function)
// resolved from an identifier. Primary nodes should not ever make it to the
// code generation phase as they will be transformed into the correct call or
// field access nodes.
class PrimaryNode : public AstNode {
 public:
  PrimaryNode(TokenPosition token_pos, const Object& primary)
      : AstNode(token_pos),
        primary_(primary),
        is_deferred_reference_(false) {
    ASSERT(primary_.IsNotTemporaryScopedHandle());
  }

  const Object& primary() const { return primary_; }

  void set_is_deferred(bool value) { is_deferred_reference_ = value; }
  bool is_deferred_reference() const { return is_deferred_reference_; }

  bool IsSuper() const {
    return primary().IsString() && (primary().raw() == Symbols::Super().raw());
  }

  virtual void VisitChildren(AstNodeVisitor* visitor) const;

  DECLARE_COMMON_NODE_FUNCTIONS(PrimaryNode);

 private:
  const Object& primary_;
  bool is_deferred_reference_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(PrimaryNode);
};

// In asynchronous code that gets suspeded and resumed, return nodes
// can be of different types:
// * A regular return node that in the case of async functions
//    gets replaced with appropriate completer calls. (kRegular)
// * A continuation return that just returns from a function, without
//   completing the Future. (kContinuation)
// * A continuation return followed by a continuation target, i.e. the
//   location at which the closure resumes the next time it gets invoked.
//   (kContinuationTarget).
// In synchronous functions, return nodes are always of type'kRegular'
class ReturnNode : public AstNode {
 public:
  enum ReturnType {
    kRegular,
    kContinuation,
    kContinuationTarget
  };

  // Return from a void function returns the null object.
  explicit ReturnNode(TokenPosition token_pos)
      : AstNode(token_pos),
        value_(new LiteralNode(token_pos, Instance::ZoneHandle())),
        inlined_finally_list_(),
        return_type_(kRegular) { }
  // Return from a non-void function.
  ReturnNode(TokenPosition token_pos,
             AstNode* value)
      : AstNode(token_pos),
        value_(value),
        inlined_finally_list_(),
        return_type_(kRegular) {
    ASSERT(value_ != NULL);
  }

  AstNode* value() const { return value_; }

  intptr_t inlined_finally_list_length() const {
    return inlined_finally_list_.length();
  }
  InlinedFinallyNode* InlinedFinallyNodeAt(intptr_t index) const {
    return inlined_finally_list_[index];
  }
  void AddInlinedFinallyNode(InlinedFinallyNode* finally_node) {
    inlined_finally_list_.Add(finally_node);
  }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    if (value() != NULL) {
      value()->Visit(visitor);
    }
  }

  void set_scope(LocalScope* scope) { scope_ = scope; }
  LocalScope* scope() const { return scope_; }

  ReturnType return_type() const { return return_type_; }
  void set_return_type(ReturnType type) { return_type_ = type; }

  DECLARE_COMMON_NODE_FUNCTIONS(ReturnNode);

 private:
  AstNode* value_;
  GrowableArray<InlinedFinallyNode*> inlined_finally_list_;
  LocalScope* scope_;
  ReturnType return_type_;

  DISALLOW_COPY_AND_ASSIGN(ReturnNode);
};


class ComparisonNode : public AstNode {
 public:
  ComparisonNode(TokenPosition token_pos,
                 Token::Kind kind,
                 AstNode* left,
                 AstNode* right)
  : AstNode(token_pos), kind_(kind), left_(left), right_(right) {
    ASSERT(left_ != NULL);
    ASSERT(right_ != NULL);
    ASSERT(IsKindValid());
  }

  Token::Kind kind() const { return kind_; }
  AstNode* left() const { return left_; }
  AstNode* right() const { return right_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    left()->Visit(visitor);
    right()->Visit(visitor);
  }

  const char* TokenName() const;
  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  DECLARE_COMMON_NODE_FUNCTIONS(ComparisonNode);

 private:
  const Token::Kind kind_;
  AstNode* left_;
  AstNode* right_;

  bool IsKindValid() const;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ComparisonNode);
};


class BinaryOpNode : public AstNode {
 public:
  BinaryOpNode(TokenPosition token_pos,
               Token::Kind kind,
               AstNode* left,
               AstNode* right)
      : AstNode(token_pos), kind_(kind), left_(left), right_(right) {
    ASSERT(left_ != NULL);
    ASSERT(right_ != NULL);
    ASSERT(IsKindValid());
  }

  Token::Kind kind() const { return kind_; }
  AstNode* left() const { return left_; }
  AstNode* right() const { return right_; }

  virtual bool has_mask32() const { return false; }
  virtual int64_t mask32() const {
    UNREACHABLE();
    return 0;
  }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    left()->Visit(visitor);
    right()->Visit(visitor);
  }

  const char* TokenName() const;
  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  DECLARE_COMMON_NODE_FUNCTIONS(BinaryOpNode);

 private:
  const Token::Kind kind_;
  AstNode* left_;
  AstNode* right_;

  bool IsKindValid() const;

  DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryOpNode);
};


class BinaryOpWithMask32Node : public BinaryOpNode {
 public:
  BinaryOpWithMask32Node(TokenPosition token_pos,
                         Token::Kind kind_value,
                         AstNode* left,
                         AstNode* right,
                         int64_t mask32)
      : BinaryOpNode(token_pos, kind_value, left, right), mask32_(mask32) {
    ASSERT(mask32 >= 0 && Utils::IsUint(32, mask32));
    ASSERT((kind_value != Token::kAND) && (kind_value != Token::kOR));
  }

  // The optional 32-bit mask must be a an unsigned 32-bit value.
  virtual bool has_mask32() const { return true; }
  virtual int64_t mask32() const {
    ASSERT(has_mask32());
    return mask32_;
  }

  const char* TokenName() const;
  DECLARE_COMMON_NODE_FUNCTIONS(BinaryOpWithMask32Node);

 private:
  // Optional unsigned 32 bit mask applied on result. No mask: -1.
  const int64_t mask32_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(BinaryOpWithMask32Node);
};


class UnaryOpNode : public AstNode {
 public:
  // Returns optimized version, e.g., for ('-' '1') ('-1') literal is returned.
  static AstNode* UnaryOpOrLiteral(TokenPosition token_pos,
                                   Token::Kind kind,
                                   AstNode* operand);
  UnaryOpNode(TokenPosition token_pos,
              Token::Kind kind,
              AstNode* operand)
      : AstNode(token_pos), kind_(kind), operand_(operand) {
    ASSERT(operand_ != NULL);
    ASSERT(IsKindValid());
  }

  Token::Kind kind() const { return kind_; }
  AstNode* operand() const { return operand_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    operand()->Visit(visitor);
  }

  const char* TokenName() const;
  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  DECLARE_COMMON_NODE_FUNCTIONS(UnaryOpNode);

 private:
  const Token::Kind kind_;
  AstNode* operand_;

  bool IsKindValid() const;

  DISALLOW_IMPLICIT_CONSTRUCTORS(UnaryOpNode);
};


class ConditionalExprNode : public AstNode {
 public:
  ConditionalExprNode(TokenPosition token_pos,
                      AstNode* condition,
                      AstNode* true_expr,
                      AstNode* false_expr)
      : AstNode(token_pos),
        condition_(condition),
        true_expr_(true_expr),
        false_expr_(false_expr) {
      ASSERT(condition_ != NULL);
      ASSERT(true_expr_ != NULL);
      ASSERT(false_expr_ != NULL);
  }

  AstNode* condition() const { return condition_; }
  AstNode* true_expr() const { return true_expr_; }
  AstNode* false_expr() const { return false_expr_; }

  void set_true_expr(AstNode* true_expr) {
    ASSERT(true_expr != NULL);
    true_expr_ = true_expr;
  }
  void set_false_expr(AstNode* false_expr) {
    ASSERT(false_expr != NULL);
    false_expr_ = false_expr;
  }

  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    condition()->Visit(visitor);
    true_expr()->Visit(visitor);
    false_expr()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(ConditionalExprNode);

 private:
  AstNode* condition_;
  AstNode* true_expr_;
  AstNode* false_expr_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ConditionalExprNode);
};


class IfNode : public AstNode {
 public:
  IfNode(TokenPosition token_pos,
         AstNode* condition,
         SequenceNode* true_branch,
         SequenceNode* false_branch)
      : AstNode(token_pos),
        condition_(condition),
        true_branch_(true_branch),
        false_branch_(false_branch) {
      ASSERT(condition_ != NULL);
  }

  AstNode* condition() const { return condition_; }
  SequenceNode* true_branch() const { return true_branch_; }
  SequenceNode* false_branch() const { return false_branch_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    condition()->Visit(visitor);
    true_branch()->Visit(visitor);
    if (false_branch() != NULL) {
      false_branch()->Visit(visitor);
    }
  }

  DECLARE_COMMON_NODE_FUNCTIONS(IfNode);

 private:
  AstNode* condition_;
  SequenceNode* true_branch_;
  SequenceNode* false_branch_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(IfNode);
};


class CaseNode : public AstNode {
 public:
  CaseNode(TokenPosition token_pos,
           SourceLabel* label,
           SequenceNode* case_expressions,
           bool contains_default,
           LocalVariable* switch_expr_value,
           SequenceNode* statements)
    : AstNode(token_pos),
      label_(label),
      case_expressions_(case_expressions),
      contains_default_(contains_default),
      switch_expr_value_(switch_expr_value),
      statements_(statements) {
    // label may be NULL.
    ASSERT(case_expressions_ != NULL);
    ASSERT(switch_expr_value_ != NULL);
    ASSERT(statements_ != NULL);
  }

  SourceLabel* label() const { return label_; }
  SequenceNode* case_expressions() const { return case_expressions_; }
  bool contains_default() const { return contains_default_; }
  LocalVariable* switch_expr_value() const { return switch_expr_value_; }
  SequenceNode* statements() const { return statements_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    case_expressions()->Visit(visitor);
    statements()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(CaseNode);

 private:
  SourceLabel* label_;
  SequenceNode* case_expressions_;
  bool contains_default_;
  LocalVariable* switch_expr_value_;
  SequenceNode* statements_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(CaseNode);
};


class SwitchNode : public AstNode {
 public:
  SwitchNode(TokenPosition token_pos,
             SourceLabel* label,
             SequenceNode* body)
    : AstNode(token_pos),
      label_(label),
      body_(body) {
    ASSERT(label_ != NULL);
    ASSERT(body_ != NULL);
  }

  SourceLabel* label() const { return label_; }
  SequenceNode* body() const { return body_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    body()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(SwitchNode);

 private:
  SourceLabel* label_;
  SequenceNode* body_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(SwitchNode);
};


class WhileNode : public AstNode {
 public:
  WhileNode(TokenPosition token_pos,
            SourceLabel* label,
            AstNode* condition,
            SequenceNode* condition_preamble,
            SequenceNode* body)
    : AstNode(token_pos),
      label_(label),
      condition_(condition),
      condition_preamble_(condition_preamble),
      body_(body) {
    ASSERT(label_ != NULL);
    ASSERT(condition_ != NULL);
    ASSERT(body_ != NULL);
  }

  SourceLabel* label() const { return label_; }
  AstNode* condition() const { return condition_; }
  SequenceNode* body() const { return body_; }
  SequenceNode* condition_preamble() const { return condition_preamble_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    if (condition_preamble() != NULL) {
      condition_preamble()->Visit(visitor);
    }
    condition()->Visit(visitor);
    body()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(WhileNode);

 private:
  SourceLabel* label_;
  AstNode* condition_;
  SequenceNode* condition_preamble_;
  SequenceNode* body_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(WhileNode);
};


class DoWhileNode : public AstNode {
 public:
  DoWhileNode(TokenPosition token_pos,
              SourceLabel* label,
              AstNode* condition,
              SequenceNode* body)
    : AstNode(token_pos),
      label_(label),
      condition_(condition),
      body_(body) {
    ASSERT(label_ != NULL);
    ASSERT(condition_ != NULL);
    ASSERT(body_ != NULL);
  }

  SourceLabel* label() const { return label_; }
  AstNode* condition() const { return condition_; }
  SequenceNode* body() const { return body_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    body()->Visit(visitor);
    condition()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(DoWhileNode);

 private:
  SourceLabel* label_;
  AstNode* condition_;
  SequenceNode* body_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(DoWhileNode);
};


// The condition can be NULL.
class ForNode : public AstNode {
 public:
  ForNode(TokenPosition token_pos,
          SourceLabel* label,
          SequenceNode* initializer,
          AstNode* condition,
          SequenceNode* condition_preamble,
          SequenceNode* increment,
          SequenceNode* body)
    : AstNode(token_pos),
      label_(label),
      initializer_(initializer),
      condition_(condition),
      condition_preamble_(condition_preamble),
      increment_(increment),
      body_(body) {
    ASSERT(label_ != NULL);
    ASSERT(initializer_ != NULL);
    ASSERT(increment_ != NULL);
    ASSERT(body_ != NULL);
  }

  SourceLabel* label() const { return label_; }
  SequenceNode* initializer() const { return initializer_; }
  AstNode* condition() const { return condition_; }
  AstNode* condition_preamble() const { return condition_preamble_; }
  SequenceNode* increment() const { return increment_; }
  SequenceNode* body() const { return body_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    initializer()->Visit(visitor);
    if (condition_preamble() != NULL) {
      ASSERT(condition() != NULL);
      condition_preamble()->Visit(visitor);
    }
    if (condition() != NULL) {
      condition()->Visit(visitor);
    }
    increment()->Visit(visitor);
    body()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(ForNode);

 private:
  SourceLabel* label_;
  SequenceNode* initializer_;
  AstNode* condition_;
  AstNode* condition_preamble_;
  SequenceNode* increment_;
  SequenceNode* body_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ForNode);
};


class JumpNode : public AstNode {
 public:
  JumpNode(TokenPosition token_pos,
           Token::Kind kind,
           SourceLabel* label)
    : AstNode(token_pos),
      kind_(kind),
      label_(label),
      inlined_finally_list_() {
    ASSERT(label_ != NULL);
    ASSERT(kind_ == Token::kBREAK || kind_ == Token::kCONTINUE);
  }

  SourceLabel* label() const { return label_; }
  Token::Kind kind() const { return kind_; }

  intptr_t inlined_finally_list_length() const {
    return inlined_finally_list_.length();
  }
  InlinedFinallyNode* InlinedFinallyNodeAt(intptr_t index) const {
    return inlined_finally_list_[index];
  }
  void AddInlinedFinallyNode(InlinedFinallyNode* finally_node) {
    inlined_finally_list_.Add(finally_node);
  }

  const char* TokenName() const;

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  DECLARE_COMMON_NODE_FUNCTIONS(JumpNode);

 private:
  Token::Kind kind_;
  SourceLabel* label_;
  GrowableArray<InlinedFinallyNode*> inlined_finally_list_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(JumpNode);
};


class StopNode : public AstNode {
 public:
  StopNode(TokenPosition token_pos, const char* message)
      : AstNode(token_pos),
        message_(message) {
    ASSERT(message != NULL);
  }

  const char* message() const { return message_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  DECLARE_COMMON_NODE_FUNCTIONS(StopNode);

 private:
  const char* message_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StopNode);
};


class LoadLocalNode : public AstNode {
 public:
  LoadLocalNode(TokenPosition token_pos, const LocalVariable* local)
      : AstNode(token_pos), local_(*local) {
    ASSERT(local != NULL);
  }

  const LocalVariable& local() const { return local_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  virtual const Instance* EvalConstExpr() const;
  virtual bool IsPotentiallyConst() const;
  virtual AstNode* MakeAssignmentNode(AstNode* rhs);

  DECLARE_COMMON_NODE_FUNCTIONS(LoadLocalNode);

 private:
  const LocalVariable& local_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(LoadLocalNode);
};


class StoreLocalNode : public AstNode {
 public:
  StoreLocalNode(TokenPosition token_pos,
                 const LocalVariable* local,
                 AstNode* value)
      : AstNode(token_pos),  local_(*local), value_(value) {
    ASSERT(local != NULL);
    ASSERT(value_ != NULL);
  }

  const LocalVariable& local() const { return local_; }
  AstNode* value() const { return value_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    value()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(StoreLocalNode);

 private:
  const LocalVariable& local_;
  AstNode* value_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StoreLocalNode);
};


class LoadInstanceFieldNode : public AstNode {
 public:
  LoadInstanceFieldNode(TokenPosition token_pos,
                        AstNode* instance,
                        const Field& field)
      : AstNode(token_pos), instance_(instance), field_(field) {
    ASSERT(instance_ != NULL);
    ASSERT(field_.IsZoneHandle());
  }

  AstNode* instance() const { return instance_; }
  const Field& field() const { return field_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    instance()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(LoadInstanceFieldNode);

 private:
  AstNode* instance_;
  const Field& field_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(LoadInstanceFieldNode);
};


class StoreInstanceFieldNode : public AstNode {
 public:
  StoreInstanceFieldNode(TokenPosition token_pos,
                         AstNode* instance,
                         const Field& field,
                         AstNode* value)
      : AstNode(token_pos),
        instance_(instance),
        field_(field),
        value_(value) {
    ASSERT(instance_ != NULL);
    ASSERT(field_.IsZoneHandle());
    ASSERT(value_ != NULL);
  }

  AstNode* instance() const { return instance_; }
  const Field& field() const { return field_; }
  AstNode* value() const { return value_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    instance()->Visit(visitor);
    value()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(StoreInstanceFieldNode);

 private:
  AstNode* instance_;
  const Field& field_;
  AstNode* value_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StoreInstanceFieldNode);
};


class LoadStaticFieldNode : public AstNode {
 public:
  LoadStaticFieldNode(TokenPosition token_pos, const Field& field)
      : AstNode(token_pos), field_(field), is_deferred_reference_(false) {
    ASSERT(field_.IsZoneHandle());
  }

  const Field& field() const { return field_; }
  void set_is_deferred(bool value) { is_deferred_reference_ = value; }
  bool is_deferred_reference() const { return is_deferred_reference_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  virtual AstNode* MakeAssignmentNode(AstNode* rhs);

  virtual bool IsPotentiallyConst() const {
    return field_.is_const();
  }

  virtual const Instance* EvalConstExpr() const {
    ASSERT(field_.is_static());
    return !is_deferred_reference_ && field_.is_const()
        ? &Instance::ZoneHandle(field_.StaticValue())
        : NULL;
  }

  DECLARE_COMMON_NODE_FUNCTIONS(LoadStaticFieldNode);

 private:
  const Field& field_;
  bool is_deferred_reference_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(LoadStaticFieldNode);
};


class StoreStaticFieldNode : public AstNode {
 public:
  StoreStaticFieldNode(TokenPosition token_pos,
                       const Field& field,
                       AstNode* value)
      : AstNode(token_pos), field_(field), value_(value) {
    ASSERT(field_.IsZoneHandle());
    ASSERT(value_ != NULL);
  }

  const Field& field() const { return field_; }
  AstNode* value() const { return value_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    value()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(StoreStaticFieldNode);

 private:
  const Field& field_;
  AstNode* value_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StoreStaticFieldNode);
};


class LoadIndexedNode : public AstNode {
 public:
  LoadIndexedNode(TokenPosition token_pos,
                  AstNode* array,
                  AstNode* index,
                  const Class& super_class)
      : AstNode(token_pos),
        array_(array),
        index_expr_(index),
        super_class_(super_class) {
    ASSERT(array_ != NULL);
    ASSERT(index_expr_ != NULL);
    ASSERT(super_class_.IsZoneHandle());
  }

  AstNode* array() const { return array_; }
  AstNode* index_expr() const { return index_expr_; }
  const Class& super_class() const { return super_class_; }
  bool IsSuperLoad() const { return !super_class_.IsNull(); }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    array()->Visit(visitor);
    index_expr()->Visit(visitor);
  }

  virtual AstNode* MakeAssignmentNode(AstNode* rhs);

  DECLARE_COMMON_NODE_FUNCTIONS(LoadIndexedNode);

 private:
  AstNode* array_;
  AstNode* index_expr_;
  const Class& super_class_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(LoadIndexedNode);
};


class StoreIndexedNode : public AstNode {
 public:
  StoreIndexedNode(TokenPosition token_pos,
                   AstNode* array,
                   AstNode* index,
                   AstNode* value,
                   const Class& super_class)
    : AstNode(token_pos),
      array_(array),
      index_expr_(index),
      value_(value),
      super_class_(super_class) {
    ASSERT(array_ != NULL);
    ASSERT(index_expr_ != NULL);
    ASSERT(value_ != NULL);
    ASSERT(super_class_.IsZoneHandle());
  }

  AstNode* array() const { return array_; }
  AstNode* index_expr() const { return index_expr_; }
  AstNode* value() const { return value_; }
  const Class& super_class() const { return super_class_; }
  bool IsSuperStore() const { return !super_class_.IsNull(); }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    array()->Visit(visitor);
    index_expr()->Visit(visitor);
    value()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(StoreIndexedNode);

 private:
  AstNode* array_;
  AstNode* index_expr_;
  AstNode* value_;
  const Class& super_class_;
  DISALLOW_IMPLICIT_CONSTRUCTORS(StoreIndexedNode);
};


class InstanceCallNode : public AstNode {
 public:
  InstanceCallNode(TokenPosition token_pos,
                   AstNode* receiver,
                   const String& function_name,
                   ArgumentListNode* arguments,
                   bool is_conditional = false)
      : AstNode(token_pos),
        receiver_(receiver),
        function_name_(function_name),
        arguments_(arguments),
        is_conditional_(is_conditional) {
    ASSERT(receiver_ != NULL);
    ASSERT(function_name_.IsNotTemporaryScopedHandle());
    ASSERT(function_name_.IsSymbol());
    ASSERT(arguments_ != NULL);
  }

  AstNode* receiver() const { return receiver_; }
  const String& function_name() const { return function_name_; }
  ArgumentListNode* arguments() const { return arguments_; }
  bool is_conditional() const { return is_conditional_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    receiver()->Visit(visitor);
    arguments()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(InstanceCallNode);

 private:
  AstNode* receiver_;
  const String& function_name_;
  ArgumentListNode* arguments_;
  const bool is_conditional_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceCallNode);
};


class InstanceGetterNode : public AstNode {
 public:
  InstanceGetterNode(TokenPosition token_pos,
                     AstNode* receiver,
                     const String& field_name,
                     bool is_conditional = false)
      : AstNode(token_pos),
        receiver_(receiver),
        field_name_(field_name),
        is_conditional_(is_conditional) {
    ASSERT(receiver_ != NULL);
    ASSERT(field_name_.IsNotTemporaryScopedHandle());
    ASSERT(field_name_.IsSymbol());
  }

  AstNode* receiver() const { return receiver_; }
  const String& field_name() const { return field_name_; }
  bool is_conditional() const { return is_conditional_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    receiver()->Visit(visitor);
  }

  virtual AstNode* MakeAssignmentNode(AstNode* rhs);

  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  DECLARE_COMMON_NODE_FUNCTIONS(InstanceGetterNode);

 private:
  AstNode* receiver_;
  const String& field_name_;
  const bool is_conditional_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceGetterNode);
};


class InstanceSetterNode : public AstNode {
 public:
  InstanceSetterNode(TokenPosition token_pos,
                     AstNode* receiver,
                     const String& field_name,
                     AstNode* value,
                     bool is_conditional = false)
      : AstNode(token_pos),
        receiver_(receiver),
        field_name_(field_name),
        value_(value),
        is_conditional_(is_conditional) {
    ASSERT(receiver_ != NULL);
    ASSERT(value_ != NULL);
    ASSERT(field_name_.IsZoneHandle());
    ASSERT(field_name_.IsSymbol());
  }

  AstNode* receiver() const { return receiver_; }
  const String& field_name() const { return field_name_; }
  AstNode* value() const { return value_; }
  bool is_conditional() const { return is_conditional_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    receiver()->Visit(visitor);
    value()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(InstanceSetterNode);

 private:
  AstNode* receiver_;
  const String& field_name_;
  AstNode* value_;
  const bool is_conditional_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(InstanceSetterNode);
};


class InitStaticFieldNode : public AstNode {
 public:
  InitStaticFieldNode(TokenPosition token_pos, const Field& field)
      : AstNode(token_pos), field_(field) {
    ASSERT(field_.IsZoneHandle());
  }

  const Field& field() const { return field_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  DECLARE_COMMON_NODE_FUNCTIONS(InitStaticFieldNode);

 private:
  const Field& field_;

  DISALLOW_COPY_AND_ASSIGN(InitStaticFieldNode);
};


class StaticGetterNode : public AstNode {
 public:
  StaticGetterNode(TokenPosition token_pos,
                   AstNode* receiver,
                   const Class& cls,
                   const String& field_name)
      : AstNode(token_pos),
        receiver_(receiver),
        owner_(Object::ZoneHandle(cls.raw())),
        cls_(cls),
        field_name_(field_name),
        is_deferred_reference_(false) {
    ASSERT(cls_.IsZoneHandle());
    ASSERT(field_name_.IsZoneHandle());
    ASSERT(field_name_.IsSymbol());
  }

  // The receiver is required for a super getter (an instance method that
  // is resolved at compile time rather than at runtime).
  AstNode* receiver() const { return receiver_; }

  // The getter node needs to remmeber how the getter was referenced
  // so that it can resolve a corresponding setter if necessary.
  // The owner of this getter is either a class, the top-level library scope,
  // or a prefix (if the getter has been referenced throug a library prefix).
  void set_owner(const Object& value) {
    ASSERT(value.IsLibraryPrefix() || value.IsLibrary() || value.IsClass());
    owner_ = value.raw();
  }
  const Object& owner() const { return owner_; }

  const Class& cls() const { return cls_; }
  const String& field_name() const { return field_name_; }
  bool is_super_getter() const { return receiver_ != NULL; }
  void set_is_deferred(bool value) { is_deferred_reference_ = value; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  virtual AstNode* MakeAssignmentNode(AstNode* rhs);

  virtual bool IsPotentiallyConst() const;
  virtual const Instance* EvalConstExpr() const;

  DECLARE_COMMON_NODE_FUNCTIONS(StaticGetterNode);

 private:
  AstNode* receiver_;
  Object& owner_;
  const Class& cls_;
  const String& field_name_;
  bool is_deferred_reference_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticGetterNode);
};


class StaticSetterNode : public AstNode {
 public:
  // Static setter with resolved setter function.
  StaticSetterNode(TokenPosition token_pos,
                   AstNode* receiver,
                   const String& field_name,
                   const Function& function,
                   AstNode* value)
      : AstNode(token_pos),
        receiver_(receiver),
        cls_(Class::ZoneHandle(function.Owner())),
        field_name_(field_name),
        function_(function),
        value_(value) {
    ASSERT(function_.IsZoneHandle());
    ASSERT(function.is_static() || receiver != NULL);
    ASSERT(field_name_.IsZoneHandle());
    ASSERT(value_ != NULL);
  }

  // For unresolved setters.
  StaticSetterNode(TokenPosition token_pos,
                   AstNode* receiver,
                   const Class& cls,
                   const String& field_name,
                   AstNode* value)
  : AstNode(token_pos),
  receiver_(receiver),
  cls_(cls),
  field_name_(field_name),
  function_(Function::ZoneHandle()),
  value_(value) {
    ASSERT(cls_.IsZoneHandle());
    ASSERT(field_name_.IsZoneHandle());
    ASSERT(value_ != NULL);
  }

  // The receiver is required for a super setter (an instance method
  // that is resolved at compile time rather than at runtime).
  AstNode* receiver() const { return receiver_; }
  const Class& cls() const { return cls_; }
  const String& field_name() const { return field_name_; }
  // function() returns null for unresolved setters.
  const Function& function() const { return function_; }
  AstNode* value() const { return value_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    value()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(StaticSetterNode);

 private:
  AstNode* receiver_;
  const Class& cls_;
  const String& field_name_;
  const Function& function_;
  AstNode* value_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticSetterNode);
};


class StaticCallNode : public AstNode {
 public:
  StaticCallNode(TokenPosition token_pos,
                 const Function& function,
                 ArgumentListNode* arguments)
      : AstNode(token_pos),
        function_(function),
        arguments_(arguments) {
    ASSERT(function_.IsZoneHandle());
    ASSERT(arguments_ != NULL);
  }

  const Function& function() const { return function_; }
  ArgumentListNode* arguments() const { return arguments_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    arguments()->Visit(visitor);
  }

  virtual AstNode* MakeAssignmentNode(AstNode* rhs);

  DECLARE_COMMON_NODE_FUNCTIONS(StaticCallNode);

 private:
  const Function& function_;
  ArgumentListNode* arguments_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(StaticCallNode);
};


class ClosureCallNode : public AstNode {
 public:
  ClosureCallNode(TokenPosition token_pos,
                  AstNode* closure,
                  ArgumentListNode* arguments)
      : AstNode(token_pos),
        closure_(closure),
        arguments_(arguments) {
    ASSERT(closure_ != NULL);
    ASSERT(arguments_ != NULL);
  }

  AstNode* closure() const { return closure_; }
  ArgumentListNode* arguments() const { return arguments_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    closure()->Visit(visitor);
    arguments()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(ClosureCallNode);

 private:
  AstNode* closure_;
  ArgumentListNode* arguments_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ClosureCallNode);
};


// There are two kinds of constructor calls: factory calls and constructor
// calls, distinguishable by constructor.IsFactory().
//
// Constructor calls implicitly allocate an object of class constructor.owner(),
// possibly parameterized by type_arguments, which may still be uninstantiated.
// For example, if the type argument T in 'new A<T>()' is not known at compile
// time, it needs to be instantiated at run time. The instantiator and its
// instantiator_class are used to instantiate uninstantiated type arguments
// at run time, as explained below.
//
// Factory calls do not implicitly allocate an object, but receive an implicit
// type argument vector as first parameter, which may still be uninstantiated.
// As in constructor calls, the instantiator and its instantiator_class are used
// to instantiate uninstantiated type arguments at run time.
//
// If the caller to the constructor or to the factory is an instance function,
// the instantiator is the receiver of this function. In order to instantiate T
// in the example above (which could for example be the first type parameter of
// the class of the caller), the code at run time extracts the type arguments of
// the receiver at an offset in the receiver specified by the provided
// instantiator_class.
//
// If the caller to the constructor or to the factory is a factory, then the
// instantiator is the first parameter of this factory, which is already a
// type argument vector. This case is identified by a null and unneeded
// instantiator_class.
class ConstructorCallNode : public AstNode {
 public:
  ConstructorCallNode(TokenPosition token_pos,
                      const TypeArguments& type_arguments,
                      const Function& constructor,
                      ArgumentListNode* arguments)
      : AstNode(token_pos),
        type_arguments_(type_arguments),
        constructor_(constructor),
        arguments_(arguments) {
    ASSERT(type_arguments_.IsZoneHandle());
    ASSERT(constructor_.IsZoneHandle());
    ASSERT(arguments_ != NULL);
  }

  const TypeArguments& type_arguments() const {
    return type_arguments_;
  }
  const Function& constructor() const { return constructor_; }
  ArgumentListNode* arguments() const { return arguments_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    arguments()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(ConstructorCallNode);

 private:
  const TypeArguments& type_arguments_;
  const Function& constructor_;
  ArgumentListNode* arguments_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ConstructorCallNode);
};


// The body of a Dart function marked as 'native' consists of this node.
class NativeBodyNode : public AstNode {
 public:
  NativeBodyNode(TokenPosition token_pos,
                 const Function& function,
                 const String& native_c_function_name,
                 LocalScope* scope,
                 bool link_lazily = false)
      : AstNode(token_pos),
        function_(function),
        native_c_function_name_(native_c_function_name),
        scope_(scope),
        link_lazily_(link_lazily) {
    ASSERT(function_.IsZoneHandle());
    ASSERT(native_c_function_name_.IsZoneHandle());
    ASSERT(native_c_function_name_.IsSymbol());
  }

  const Function& function() const { return function_; }
  const String& native_c_function_name() const {
    return native_c_function_name_;
  }
  LocalScope* scope() const { return scope_; }

  bool link_lazily() const { return link_lazily_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const { }

  DECLARE_COMMON_NODE_FUNCTIONS(NativeBodyNode);

 private:
  const Function& function_;  // Native Dart function.
  const String& native_c_function_name_;
  LocalScope* scope_;
  const bool link_lazily_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(NativeBodyNode);
};


class CatchClauseNode : public AstNode {
 public:
  static const intptr_t kInvalidTryIndex = -1;

  CatchClauseNode(TokenPosition token_pos,
                  SequenceNode* catch_block,
                  const Array& handler_types,
                  const LocalVariable* context_var,
                  const LocalVariable* exception_var,
                  const LocalVariable* stacktrace_var,
                  const LocalVariable* rethrow_exception_var,
                  const LocalVariable* rethrow_stacktrace_var,
                  intptr_t catch_handler_index,
                  bool needs_stacktrace)
      : AstNode(token_pos),
        catch_block_(catch_block),
        handler_types_(handler_types),
        context_var_(*context_var),
        exception_var_(*exception_var),
        stacktrace_var_(*stacktrace_var),
        rethrow_exception_var_(*rethrow_exception_var),
        rethrow_stacktrace_var_(*rethrow_stacktrace_var),
        catch_handler_index_(catch_handler_index),
        needs_stacktrace_(needs_stacktrace) {
    ASSERT(catch_block_ != NULL);
    ASSERT(handler_types.IsZoneHandle());
    ASSERT(context_var != NULL);
    ASSERT(exception_var != NULL);
    ASSERT(stacktrace_var != NULL);
  }

  const Array& handler_types() const { return handler_types_; }
  const LocalVariable& context_var() const { return context_var_; }
  const LocalVariable& exception_var() const { return exception_var_; }
  const LocalVariable& stacktrace_var() const { return stacktrace_var_; }
  const LocalVariable& rethrow_exception_var() const {
      return rethrow_exception_var_;
  }
  const LocalVariable& rethrow_stacktrace_var() const {
      return rethrow_stacktrace_var_;
  }
  intptr_t catch_handler_index() const { return catch_handler_index_; }
  bool needs_stacktrace() const { return needs_stacktrace_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    catch_block_->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(CatchClauseNode);

 private:
  SequenceNode* catch_block_;
  const Array& handler_types_;
  const LocalVariable& context_var_;
  const LocalVariable& exception_var_;
  const LocalVariable& stacktrace_var_;
  const LocalVariable& rethrow_exception_var_;
  const LocalVariable& rethrow_stacktrace_var_;
  const intptr_t catch_handler_index_;
  const bool needs_stacktrace_;

  DISALLOW_COPY_AND_ASSIGN(CatchClauseNode);
};


class TryCatchNode : public AstNode {
 public:
  TryCatchNode(TokenPosition token_pos,
               SequenceNode* try_block,
               const LocalVariable* context_var,
               CatchClauseNode* catch_block,
               SequenceNode* finally_block,
               intptr_t try_index,
               SequenceNode* rethrow_clause)
      : AstNode(token_pos),
        try_block_(try_block),
        context_var_(*context_var),
        catch_block_(catch_block),
        finally_block_(finally_block),
        try_index_(try_index),
        rethrow_clause_(rethrow_clause) {
    ASSERT(try_block_ != NULL);
    ASSERT(context_var != NULL);
    ASSERT(catch_block_ != NULL);
  }

  SequenceNode* try_block() const { return try_block_; }
  CatchClauseNode* catch_block() const { return catch_block_; }
  SequenceNode* finally_block() const { return finally_block_; }
  const LocalVariable& context_var() const { return context_var_; }
  intptr_t try_index() const { return try_index_; }

  SequenceNode* rethrow_clause() const { return rethrow_clause_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    try_block_->Visit(visitor);
    if (catch_block_ != NULL) {
      catch_block_->Visit(visitor);
    }
    if (finally_block_ != NULL) {
      finally_block_->Visit(visitor);
    }
  }

  DECLARE_COMMON_NODE_FUNCTIONS(TryCatchNode);

 private:
  SequenceNode* try_block_;
  const LocalVariable& context_var_;
  CatchClauseNode* catch_block_;
  SequenceNode* finally_block_;
  const intptr_t try_index_;
  SequenceNode* rethrow_clause_;

  DISALLOW_COPY_AND_ASSIGN(TryCatchNode);
};


class ThrowNode : public AstNode {
 public:
  ThrowNode(TokenPosition token_pos, AstNode* exception, AstNode* stacktrace)
      : AstNode(token_pos), exception_(exception), stacktrace_(stacktrace) {
    ASSERT(exception_ != NULL);
  }

  AstNode* exception() const { return exception_; }
  AstNode* stacktrace() const { return stacktrace_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    exception()->Visit(visitor);
    if (stacktrace() != NULL) {
      stacktrace()->Visit(visitor);
    }
  }

  DECLARE_COMMON_NODE_FUNCTIONS(ThrowNode);

 private:
  AstNode* exception_;
  AstNode* stacktrace_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(ThrowNode);
};


class InlinedFinallyNode : public AstNode {
 public:
  InlinedFinallyNode(TokenPosition token_pos,
                     SequenceNode* finally_block,
                     const LocalVariable* context_var,
                     intptr_t try_index)
      : AstNode(token_pos),
        finally_block_(finally_block),
        context_var_(*context_var),
        try_index_(try_index) {
    ASSERT(finally_block_ != NULL);
    ASSERT(context_var != NULL);
  }

  SequenceNode* finally_block() const { return finally_block_; }
  const LocalVariable& context_var() const { return context_var_; }
  intptr_t try_index() const { return try_index_; }

  virtual void VisitChildren(AstNodeVisitor* visitor) const {
    finally_block()->Visit(visitor);
  }

  DECLARE_COMMON_NODE_FUNCTIONS(InlinedFinallyNode);

 private:
  SequenceNode* finally_block_;
  const LocalVariable& context_var_;
  const intptr_t try_index_;

  DISALLOW_IMPLICIT_CONSTRUCTORS(InlinedFinallyNode);
};

}  // namespace dart

#undef DECLARE_COMMON_NODE_FUNCTIONS

#endif  // VM_AST_H_
