// Copyright (c) 2011, 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.

#include "vm/ast.h"
#include "vm/compiler.h"
#include "vm/dart_entry.h"
#include "vm/isolate.h"
#include "vm/log.h"
#include "vm/object_store.h"
#include "vm/resolver.h"


namespace dart {

#define DEFINE_VISIT_FUNCTION(BaseName)                                        \
void BaseName##Node::Visit(AstNodeVisitor* visitor) {                          \
  visitor->Visit##BaseName##Node(this);                                        \
}

FOR_EACH_NODE(DEFINE_VISIT_FUNCTION)
#undef DEFINE_VISIT_FUNCTION


#define DEFINE_NAME_FUNCTION(BaseName)                                         \
const char* BaseName##Node::Name() const {                                     \
  return #BaseName;                                                            \
}

FOR_EACH_NODE(DEFINE_NAME_FUNCTION)
#undef DEFINE_NAME_FUNCTION


const Field* AstNode::MayCloneField(const Field& value) {
  if (Compiler::IsBackgroundCompilation() ||
      FLAG_force_clone_compiler_objects) {
    return &Field::ZoneHandle(value.CloneFromOriginal());
  } else {
    ASSERT(value.IsZoneHandle());
    return &value;
  }
}


// A visitor class to collect all the nodes (including children) into an
// array.
class AstNodeCollector : public AstNodeVisitor {
 public:
  explicit AstNodeCollector(GrowableArray<AstNode*>* nodes)
    : nodes_(nodes) { }

#define DEFINE_VISITOR_FUNCTION(BaseName)                                      \
  virtual void Visit##BaseName##Node(BaseName##Node* node) {                   \
    nodes_->Add(node);                                                         \
    node->VisitChildren(this);                                                 \
  }

FOR_EACH_NODE(DEFINE_VISITOR_FUNCTION)
#undef DEFINE_VISITOR_FUNCTION

 private:
  GrowableArray<AstNode*>* nodes_;
  DISALLOW_COPY_AND_ASSIGN(AstNodeCollector);
};


void SequenceNode::CollectAllNodes(GrowableArray<AstNode*>* nodes) {
  AstNodeCollector node_collector(nodes);
  this->Visit(&node_collector);
}


void SequenceNode::VisitChildren(AstNodeVisitor* visitor) const {
  for (intptr_t i = 0; i < this->length(); i++) {
    NodeAt(i)->Visit(visitor);
  }
}


void SequenceNode::Add(AstNode* node) {
  if (node->IsReturnNode()) {
    node->AsReturnNode()->set_scope(scope());
  }
  nodes_.Add(node);
}


void PrimaryNode::VisitChildren(AstNodeVisitor* visitor) const {
}


void ArgumentListNode::VisitChildren(AstNodeVisitor* visitor) const {
  for (intptr_t i = 0; i < this->length(); i++) {
    NodeAt(i)->Visit(visitor);
  }
}


LetNode::LetNode(TokenPosition token_pos)
  : AstNode(token_pos),
    vars_(1),
    initializers_(1),
    nodes_(1) { }


LocalVariable* LetNode::AddInitializer(AstNode* node) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  initializers_.Add(node);
  char name[64];
  OS::SNPrint(name, sizeof(name), ":lt%s_%" Pd "",
      token_pos().ToCString(), vars_.length());
  LocalVariable* temp_var =
      new LocalVariable(token_pos(),
                        String::ZoneHandle(zone, Symbols::New(thread, name)),
                        Object::dynamic_type());
  vars_.Add(temp_var);
  return temp_var;
}


void LetNode::VisitChildren(AstNodeVisitor* visitor) const {
  for (intptr_t i = 0; i < num_temps(); ++i) {
    initializers_[i]->Visit(visitor);
  }
  for (intptr_t i = 0; i < nodes_.length(); ++i) {
    nodes_[i]->Visit(visitor);
  }
}

bool LetNode::IsPotentiallyConst() const {
  for (intptr_t i = 0; i < num_temps(); i++) {
    if (!initializers_[i]->IsPotentiallyConst()) {
      return false;
    }
  }
  for (intptr_t i = 0; i < nodes_.length(); i++) {
    if (!nodes_[i]->IsPotentiallyConst()) {
      return false;
    }
  }
  return true;
}

const Instance* LetNode::EvalConstExpr() const {
  for (intptr_t i = 0; i < num_temps(); i++) {
    if (initializers_[i]->EvalConstExpr() == NULL) {
      return NULL;
    }
  }
  const Instance* last = NULL;
  for (intptr_t i = 0; i < nodes_.length(); i++) {
    last = nodes_[i]->EvalConstExpr();
    if (last == NULL) {
      return NULL;
    }
  }
  return last;
}


void ArrayNode::VisitChildren(AstNodeVisitor* visitor) const {
  for (intptr_t i = 0; i < this->length(); i++) {
    ElementAt(i)->Visit(visitor);
  }
}


bool StringInterpolateNode::IsPotentiallyConst() const {
  for (int i = 0; i < value_->length(); i++) {
    if (!value_->ElementAt(i)->IsPotentiallyConst()) {
      return false;
    }
  }
  return true;
}


bool LiteralNode::IsPotentiallyConst() const {
  return true;
}


AstNode* LiteralNode::ApplyUnaryOp(Token::Kind unary_op_kind) {
  if (unary_op_kind == Token::kNEGATE) {
    if (literal().IsSmi()) {
      const Smi& smi = Smi::Cast(literal());
      const Instance& literal =
          Instance::ZoneHandle(Integer::New(-smi.Value(), Heap::kOld));
      return new LiteralNode(this->token_pos(), literal);
    }
    if (literal().IsMint()) {
      const Mint& mint = Mint::Cast(literal());
      const Instance& literal =
          Instance::ZoneHandle(Integer::New(-mint.value(), Heap::kOld));
      return new LiteralNode(this->token_pos(), literal);
    }
    if (literal().IsDouble()) {
      const Double& dbl = Double::Cast(literal());
      // Preserve negative zero.
      double new_value = (dbl.value() == 0.0) ? -0.0 : (0.0 - dbl.value());
      const Double& double_instance =
          Double::ZoneHandle(Double::NewCanonical(new_value));
      return new LiteralNode(this->token_pos(), double_instance);
    }
  } else if (unary_op_kind == Token::kBIT_NOT) {
    if (literal().IsSmi()) {
      const Smi& smi = Smi::Cast(literal());
      const Instance& literal =
          Instance::ZoneHandle(Integer::New(~smi.Value(), Heap::kOld));
      return new LiteralNode(this->token_pos(), literal);
    }
    if (literal().IsMint()) {
      const Mint& mint = Mint::Cast(literal());
      const Instance& literal =
          Instance::ZoneHandle(Integer::New(~mint.value(), Heap::kOld));
      return new LiteralNode(this->token_pos(), literal);
    }
  } else if (unary_op_kind == Token::kNOT) {
    if (literal().IsBool()) {
      const Bool& boolean = Bool::Cast(literal());
      return new LiteralNode(this->token_pos(), Bool::Get(!boolean.value()));
    }
  }
  return NULL;
}


const char* TypeNode::TypeName() const {
  return String::Handle(type().UserVisibleName()).ToCString();
}


bool ComparisonNode::IsKindValid() const {
  return Token::IsRelationalOperator(kind_)
      || Token::IsEqualityOperator(kind_)
      || Token::IsTypeTestOperator(kind_)
      || Token::IsTypeCastOperator(kind_);
}


const char* ComparisonNode::TokenName() const {
  return (kind_ == Token::kAS) ? "as" : Token::Str(kind_);
}


bool ComparisonNode::IsPotentiallyConst() const {
  switch (kind_) {
    case Token::kLT:
    case Token::kGT:
    case Token::kLTE:
    case Token::kGTE:
    case Token::kEQ:
    case Token::kNE:
    case Token::kEQ_STRICT:
    case Token::kNE_STRICT:
      return this->left()->IsPotentiallyConst() &&
          this->right()->IsPotentiallyConst();
    default:
      return false;
  }
}


const Instance* ComparisonNode::EvalConstExpr() const {
  const Instance* left_val = this->left()->EvalConstExpr();
  if (left_val == NULL) {
    return NULL;
  }
  const Instance* right_val = this->right()->EvalConstExpr();
  if (right_val == NULL) {
    return NULL;
  }
  switch (kind_) {
    case Token::kLT:
    case Token::kGT:
    case Token::kLTE:
    case Token::kGTE:
      if ((left_val->IsNumber() || left_val->IsNull()) &&
          (right_val->IsNumber() || right_val->IsNull())) {
        return &Bool::False();
      }
      return NULL;
    case Token::kEQ:
    case Token::kNE:
      // The comparison is a compile time const if both operands are either a
      // number, string, or boolean value (but not necessarily the same type).
      if ((left_val->IsNumber() ||
          left_val->IsString() ||
          left_val->IsBool() ||
          left_val->IsNull()) &&
          (right_val->IsNumber() ||
          right_val->IsString() ||
          right_val->IsBool() ||
          right_val->IsNull())) {
        return &Bool::False();
      }
      return NULL;
    case Token::kEQ_STRICT:
    case Token::kNE_STRICT:
      // identical(a, b) is a compile time const if both operands are
      // compile time constants, regardless of their type.
      return &Bool::True();
    default:
      return NULL;
  }
  return NULL;
}



bool BinaryOpNode::IsKindValid() const {
  switch (kind_) {
    case Token::kADD:
    case Token::kSUB:
    case Token::kMUL:
    case Token::kDIV:
    case Token::kTRUNCDIV:
    case Token::kMOD:
    case Token::kOR:
    case Token::kAND:
    case Token::kIFNULL:
    case Token::kBIT_OR:
    case Token::kBIT_XOR:
    case Token::kBIT_AND:
    case Token::kSHL:
    case Token::kSHR:
      return true;
    default:
      return false;
  }
}


const char* BinaryOpNode::TokenName() const {
  return Token::Str(kind_);
}


bool BinaryOpNode::IsPotentiallyConst() const {
  switch (kind_) {
    case Token::kOR:
    case Token::kAND:
      if (this->left()->IsLiteralNode() &&
          this->left()->AsLiteralNode()->literal().IsNull()) {
        return false;
      }
      if (this->right()->IsLiteralNode() &&
          this->right()->AsLiteralNode()->literal().IsNull()) {
        return false;
      }
      // Fall-through intentional.
    case Token::kADD:
    case Token::kSUB:
    case Token::kMUL:
    case Token::kDIV:
    case Token::kMOD:
    case Token::kTRUNCDIV:
    case Token::kBIT_OR:
    case Token::kBIT_XOR:
    case Token::kBIT_AND:
    case Token::kSHL:
    case Token::kSHR:
    case Token::kIFNULL:
      return this->left()->IsPotentiallyConst() &&
          this->right()->IsPotentiallyConst();
    default:
      UNREACHABLE();
      return false;
  }
}


const Instance* BinaryOpNode::EvalConstExpr() const {
  const Instance* left_val = this->left()->EvalConstExpr();
  if (left_val == NULL) {
    return NULL;
  }
  if (!left_val->IsNumber() && !left_val->IsBool() && !left_val->IsString() &&
      kind_ != Token::kIFNULL) {
    return NULL;
  }
  const Instance* right_val = this->right()->EvalConstExpr();
  if (right_val == NULL) {
    return NULL;
  }
  switch (kind_) {
    case Token::kADD:
      if (left_val->IsString()) {
        return right_val->IsString() ? left_val : NULL;
      }
      // Fall-through intentional.
    case Token::kSUB:
    case Token::kMUL:
    case Token::kDIV:
    case Token::kMOD:
    case Token::kTRUNCDIV:
      if (left_val->IsInteger()) {
        if (right_val->IsInteger()) {
          return left_val;
        } else if (right_val->IsNumber()) {
          return right_val;
        }
      } else if (left_val->IsNumber() &&
                 right_val->IsNumber()) {
        return left_val;
      }
      return NULL;
    case Token::kBIT_OR:
    case Token::kBIT_XOR:
    case Token::kBIT_AND:
    case Token::kSHL:
    case Token::kSHR:
      if (left_val->IsInteger() &&
          right_val->IsInteger()) {
        return right_val;
      }
      return NULL;
    case Token::kOR:
    case Token::kAND:
      if (left_val->IsBool() && right_val->IsBool()) {
        return left_val;
      }
      return NULL;
    case Token::kIFNULL:
      if (left_val->IsNull()) {
        return right_val;
      }
      return left_val;
    default:
      UNREACHABLE();
      return NULL;
  }
  return NULL;
}


AstNode* UnaryOpNode::UnaryOpOrLiteral(TokenPosition token_pos,
                                       Token::Kind kind,
                                       AstNode* operand) {
  AstNode* new_operand = operand->ApplyUnaryOp(kind);
  if (new_operand != NULL) {
    return new_operand;
  }
  return new UnaryOpNode(token_pos, kind, operand);
}


bool UnaryOpNode::IsKindValid() const {
  switch (kind_) {
    case Token::kNEGATE:
    case Token::kNOT:
    case Token::kBIT_NOT:
      return true;
    default:
      return false;
  }
}


bool UnaryOpNode::IsPotentiallyConst() const {
  if (this->operand()->IsLiteralNode() &&
      this->operand()->AsLiteralNode()->literal().IsNull()) {
    return false;
  }
  return this->operand()->IsPotentiallyConst();
}


const Instance* UnaryOpNode::EvalConstExpr() const {
  const Instance* val = this->operand()->EvalConstExpr();
  if (val == NULL) {
    return NULL;
  }
  switch (kind_) {
    case Token::kNEGATE:
      return val->IsNumber() ? val : NULL;
    case Token::kNOT:
      return val->IsBool() ? val : NULL;
    case Token::kBIT_NOT:
      return val->IsInteger() ? val : NULL;
    default:
      return NULL;
  }
}


bool ConditionalExprNode::IsPotentiallyConst() const {
  return this->condition()->IsPotentiallyConst() &&
    this->true_expr()->IsPotentiallyConst() &&
    this->false_expr()->IsPotentiallyConst();
}


const Instance* ConditionalExprNode::EvalConstExpr() const {
  const Instance* cond = this->condition()->EvalConstExpr();
  if ((cond != NULL) &&
      cond->IsBool() &&
      (this->true_expr()->EvalConstExpr() != NULL) &&
      (this->false_expr()->EvalConstExpr() != NULL)) {
    return cond;
  }
  return NULL;
}


bool ClosureNode::IsPotentiallyConst() const {
  if (function().IsImplicitStaticClosureFunction()) {
    return true;
  }
  return false;
}


const Instance* ClosureNode::EvalConstExpr() const {
  if (!is_deferred_reference_ &&
      function().IsImplicitStaticClosureFunction()) {
    // Return a value that represents an instance. Only the type is relevant.
    return &Instance::Handle();
  }
  return NULL;
}


AstNode* ClosureNode::MakeAssignmentNode(AstNode* rhs) {
  if (scope() == NULL) {
    // This is an implicit closure node created because a static getter was not
    // found. Change the getter into a setter. If it does not exist,
    // noSuchMethod will be called.
    return new StaticSetterNode(token_pos(),
                                receiver(),
                                Class::ZoneHandle(function().Owner()),
                                String::ZoneHandle(function().name()),
                                rhs);
  }
  return NULL;
}


const char* UnaryOpNode::TokenName() const {
  return Token::Str(kind_);
}


const char* JumpNode::TokenName() const {
  return Token::Str(kind_);
}


bool LoadLocalNode::IsPotentiallyConst() const {
  // Parameters of const constructors are implicitly final and can be
  // used in initializer expressions.
  // We can't check here whether the local variable is indeed a parameter,
  // but this code is executed before any other local variables are
  // added to the scope.
  return local().is_final();
}


const Instance* LoadLocalNode::EvalConstExpr() const {
  if (local().IsConst()) {
    return local().ConstValue();
  }
  return NULL;
}


AstNode* LoadLocalNode::MakeAssignmentNode(AstNode* rhs) {
  if (local().is_final()) {
    return NULL;
  }
  return new StoreLocalNode(token_pos(), &local(), rhs);
}


AstNode* LoadStaticFieldNode::MakeAssignmentNode(AstNode* rhs) {
  if (field().is_final()) {
    return NULL;
  }
  if (Isolate::Current()->type_checks()) {
    rhs = new AssignableNode(
        field().token_pos(),
        rhs,
        AbstractType::ZoneHandle(field().type()),
        String::ZoneHandle(field().name()));
  }
  return new StoreStaticFieldNode(
      token_pos(), Field::ZoneHandle(field().Original()), rhs);
}


AstNode* InstanceGetterNode::MakeAssignmentNode(AstNode* rhs) {
  return new InstanceSetterNode(token_pos(),
                                receiver(),
                                field_name(),
                                rhs,
                                is_conditional());
}


bool InstanceGetterNode::IsPotentiallyConst() const {
  return field_name().Equals(Symbols::Length()) &&
    !is_conditional() &&
    receiver()->IsPotentiallyConst();
}


const Instance* InstanceGetterNode::EvalConstExpr() const {
  if (field_name().Equals(Symbols::Length()) && !is_conditional()) {
    const Instance* receiver_val = receiver()->EvalConstExpr();
    if ((receiver_val != NULL) && receiver_val->IsString()) {
      return &Instance::ZoneHandle(Smi::New(1));
    }
  }
  return NULL;
}


AstNode* LoadIndexedNode::MakeAssignmentNode(AstNode* rhs) {
  return new StoreIndexedNode(token_pos(), array(), index_expr(),
                              rhs, super_class());
}


AstNode* StaticGetterNode::MakeAssignmentNode(AstNode* rhs) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  Isolate* isolate = thread->isolate();
  if (is_super_getter()) {
    ASSERT(receiver() != NULL);
    const String& setter_name =
        String::ZoneHandle(zone, Field::LookupSetterSymbol(field_name_));
    Function& setter = Function::ZoneHandle(zone);
    if (!setter_name.IsNull()) {
      setter = Resolver::ResolveDynamicAnyArgs(zone, cls(), setter_name);
    }
    if (setter.IsNull() || setter.is_abstract()) {
      // No instance setter found in super class chain,
      // noSuchMethod will be called at runtime.
      return new StaticSetterNode(token_pos(),
                                  receiver(),
                                  cls(),
                                  field_name_,
                                  rhs);
    }
    return new StaticSetterNode(token_pos(),
                                receiver(),
                                field_name_,
                                setter,
                                rhs);
  }

  if (owner().IsLibraryPrefix()) {
    const LibraryPrefix& prefix = LibraryPrefix::Cast(owner_);
    // The parser has already dealt with the pathological case where a
    // library imports itself. See Parser::ResolveIdentInPrefixScope()
    ASSERT(field_name_.CharAt(0) != Library::kPrivateIdentifierStart);

    // If the prefix is not yet loaded, the getter doesn't exist. Return a
    // setter that will throw a NSME at runtime.
    if (!prefix.is_loaded()) {
      return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
    }

    Object& obj = Object::Handle(zone, prefix.LookupObject(field_name_));
    if (obj.IsField()) {
      const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw());
      if (!field.is_final()) {
        if (isolate->type_checks()) {
          rhs = new AssignableNode(field.token_pos(),
                                   rhs,
                                   AbstractType::ZoneHandle(zone, field.type()),
                                   field_name_);
        }
        return new StoreStaticFieldNode(token_pos(), field, rhs);
      }
    }

    // No field found in prefix. Look for a setter function.
    const String& setter_name =
         String::Handle(zone, Field::LookupSetterSymbol(field_name_));
    if (!setter_name.IsNull()) {
      obj = prefix.LookupObject(setter_name);
      if (obj.IsFunction()) {
        const Function& setter =
            Function::ZoneHandle(zone, Function::Cast(obj).raw());
        ASSERT(setter.is_static() && setter.IsSetterFunction());
        return new StaticSetterNode(
            token_pos(), NULL, field_name_, setter, rhs);
      }
    }

    // No writeable field and no setter found in the prefix. Return a
    // non-existing setter that will throw an NSM error.
    return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
  }

  if (owner().IsLibrary()) {
    const Library& library = Library::Cast(owner());
    Object& obj = Object::Handle(zone, library.ResolveName(field_name_));
    if (obj.IsField()) {
      const Field& field = Field::ZoneHandle(zone, Field::Cast(obj).raw());
      if (!field.is_final()) {
        if (isolate->type_checks()) {
          rhs = new AssignableNode(field.token_pos(),
                                   rhs,
                                   AbstractType::ZoneHandle(zone, field.type()),
                                   field_name_);
        }
        return new StoreStaticFieldNode(token_pos(), field, rhs);
      }
    }

    // No field found in library. Look for a setter function.
    const String& setter_name =
        String::Handle(zone, Field::LookupSetterSymbol(field_name_));
    if (!setter_name.IsNull()) {
      obj = library.ResolveName(setter_name);
      if (obj.IsFunction()) {
        const Function& setter =
            Function::ZoneHandle(zone, Function::Cast(obj).raw());
        ASSERT(setter.is_static() && setter.IsSetterFunction());
        return
            new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs);
      }
    }

    // No writeable field and no setter found in the library. Return a
    // non-existing setter that will throw an NSM error.
    return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
  }

  const Function& setter =
      Function::ZoneHandle(zone, cls().LookupSetterFunction(field_name_));
  if (!setter.IsNull() && setter.IsStaticFunction()) {
    return new StaticSetterNode(token_pos(), NULL, field_name_, setter, rhs);
  }
  // Could not find a static setter. Look for a field.
  // Access to a lazily initialized static field that has not yet been
  // initialized is compiled to a static implicit getter.
  // A setter may not exist for such a field.
  const Field& field = Field::ZoneHandle(zone,
                                         cls().LookupStaticField(field_name_));
  if (!field.IsNull()) {
    if (field.is_final()) {
      // Attempting to assign to a final variable will cause a NoSuchMethodError
      // to be thrown. Change static getter to non-existent static setter in
      // order to trigger the throw at runtime.
      return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
    }
#if defined(DEBUG)
    const String& getter_name =
        String::Handle(zone, Field::LookupGetterSymbol(field_name_));
    ASSERT(!getter_name.IsNull());
    const Function& getter =
        Function::Handle(zone, cls().LookupStaticFunction(getter_name));
    ASSERT(!getter.IsNull() &&
           (getter.kind() == RawFunction::kImplicitStaticFinalGetter));
#endif
    if (isolate->type_checks()) {
      rhs = new AssignableNode(
          field.token_pos(),
          rhs,
          AbstractType::ZoneHandle(zone, field.type()),
          String::ZoneHandle(zone, field.name()));
    }
    return new StoreStaticFieldNode(token_pos(), field, rhs);
  }
  // Didn't find a static setter or a static field. Make a call to
  // the non-existent setter to trigger a NoSuchMethodError at runtime.
  return new StaticSetterNode(token_pos(), NULL, cls(), field_name_, rhs);
}


AstNode* StaticCallNode::MakeAssignmentNode(AstNode* rhs) {
  // Return this node if it represents a 'throw NoSuchMethodError' indicating
  // that a getter was not found, otherwise return null.
  const Class& cls = Class::Handle(function().Owner());
  const String& cls_name = String::Handle(cls.Name());
  const String& func_name = String::Handle(function().name());
  if (cls_name.Equals(Symbols::NoSuchMethodError()) &&
      func_name.StartsWith(Symbols::ThrowNew())) {
    return this;
  }
  return NULL;
}


bool StaticGetterNode::IsPotentiallyConst() const {
  if (is_deferred_reference_) {
    return false;
  }
  const String& getter_name =
      String::Handle(Field::GetterName(this->field_name()));
  const Function& getter_func =
      Function::Handle(this->cls().LookupStaticFunction(getter_name));
  if (getter_func.IsNull() || !getter_func.is_const()) {
    return false;
  }
  return true;
}


const Instance* StaticGetterNode::EvalConstExpr() const {
  if (is_deferred_reference_) {
    return NULL;
  }
  const String& getter_name =
      String::Handle(Field::LookupGetterSymbol(this->field_name()));
  if (getter_name.IsNull()) {
    return NULL;
  }
  const Function& getter_func =
      Function::Handle(this->cls().LookupStaticFunction(getter_name));
  if (getter_func.IsNull() || !getter_func.is_const()) {
    return NULL;
  }
  const Object& result = Object::Handle(
      DartEntry::InvokeFunction(getter_func, Object::empty_array()));
  if (result.IsError() || result.IsNull()) {
    // TODO(turnidge): We could get better error messages by returning
    // the Error object directly to the parser.  This will involve
    // replumbing all of the EvalConstExpr methods.
    return NULL;
  }
  return &Instance::ZoneHandle(Instance::Cast(result).raw());
}

}  // namespace dart
