// 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_FLAG(bool, trace_ast_visitor, false,
            "Trace AstVisitor.");

#define DEFINE_VISIT_FUNCTION(BaseName)                                        \
void BaseName##Node::Visit(AstNodeVisitor* visitor) {                          \
  if (FLAG_trace_ast_visitor) {                                                \
    THR_Print("Visiting %s\n", PrettyName());                                  \
  }                                                                            \
  visitor->Visit##BaseName##Node(this);                                        \
}

FOR_EACH_NODE(DEFINE_VISIT_FUNCTION)
#undef DEFINE_VISIT_FUNCTION


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

FOR_EACH_NODE(DEFINE_NAME_FUNCTION)
#undef DEFINE_NAME_FUNCTION


// 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(intptr_t token_pos)
  : AstNode(token_pos),
    vars_(1),
    initializers_(1),
    nodes_(1) { }


LocalVariable* LetNode::AddInitializer(AstNode* node) {
  initializers_.Add(node);
  char name[64];
  OS::SNPrint(name, sizeof(name), ":lt%" Pd "_%" Pd "",
      token_pos(), vars_.length());
  LocalVariable* temp_var =
      new LocalVariable(token_pos(),
                        String::ZoneHandle(Symbols::New(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_);
}


const char* BinaryOpWithMask32Node::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(intptr_t 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()->flags().type_checks()) {
    rhs = new AssignableNode(
        field().token_pos(),
        rhs,
        AbstractType::ZoneHandle(field().type()),
        String::ZoneHandle(field().name()));
  }
  return new StoreStaticFieldNode(token_pos(), field(), 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(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->flags().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->flags().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->flags().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
