// 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.

#include "vm/parser.h"

#include "lib/invocation_mirror.h"
#include "vm/bigint_operations.h"
#include "vm/bootstrap.h"
#include "vm/class_finalizer.h"
#include "vm/compiler.h"
#include "vm/compiler_stats.h"
#include "vm/dart_api_impl.h"
#include "vm/dart_entry.h"
#include "vm/flags.h"
#include "vm/growable_array.h"
#include "vm/longjump.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/resolver.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"

namespace dart {

DEFINE_FLAG(bool, enable_asserts, false, "Enable assert statements.");
DEFINE_FLAG(bool, enable_type_checks, false, "Enable type checks.");
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
DECLARE_FLAG(bool, error_on_malformed_type);
DECLARE_FLAG(bool, throw_on_javascript_int_overflow);

static void CheckedModeHandler(bool value) {
  FLAG_enable_asserts = value;
  FLAG_enable_type_checks = value;
}

// --enable-checked-mode and --checked both enable checked mode which is
// equivalent to setting --enable-asserts and --enable-type-checks.
DEFINE_FLAG_HANDLER(CheckedModeHandler,
                    enable_checked_mode,
                    "Enable checked mode.");

DEFINE_FLAG_HANDLER(CheckedModeHandler,
                    checked,
                    "Enable checked mode.");

#if defined(DEBUG)
class TraceParser : public ValueObject {
 public:
  TraceParser(intptr_t token_pos, const Script& script, const char* msg) {
    if (FLAG_trace_parser) {
      // Skips tracing of bootstrap libraries.
      if (script.HasSource()) {
        intptr_t line, column;
        script.GetTokenLocation(token_pos, &line, &column);
        PrintIndent();
        OS::Print("%s (line %" Pd ", col %" Pd ", token %" Pd ")\n",
                  msg, line, column, token_pos);
      }
      indent_++;
    }
  }
  ~TraceParser() { indent_--; }
 private:
  void PrintIndent() {
    for (int i = 0; i < indent_; i++) { OS::Print(". "); }
  }
  static int indent_;
};

int TraceParser::indent_ = 0;

#define TRACE_PARSER(s) \
  TraceParser __p__(this->TokenPos(), this->script_, s)

#else  // not DEBUG
#define TRACE_PARSER(s)
#endif  // DEBUG


static RawTypeArguments* NewTypeArguments(const GrowableObjectArray& objs) {
  const TypeArguments& a =
      TypeArguments::Handle(TypeArguments::New(objs.Length()));
  AbstractType& type = AbstractType::Handle();
  for (int i = 0; i < objs.Length(); i++) {
    type ^= objs.At(i);
    a.SetTypeAt(i, type);
  }
  // Cannot canonicalize TypeArgument yet as its types may not have been
  // finalized yet.
  return a.raw();
}


static ThrowNode* GenerateRethrow(intptr_t token_pos, const Object& obj) {
  const UnhandledException& excp = UnhandledException::Cast(obj);
  Instance& exception = Instance::ZoneHandle(excp.exception());
  if (exception.IsNew()) {
    exception ^= Object::Clone(exception, Heap::kOld);
  }
  Instance& stack_trace = Instance::ZoneHandle(excp.stacktrace());
  if (stack_trace.IsNew()) {
    stack_trace ^= Object::Clone(stack_trace, Heap::kOld);
  }
  return new ThrowNode(token_pos,
                       new LiteralNode(token_pos, exception),
                       new LiteralNode(token_pos, stack_trace));
}


LocalVariable* ParsedFunction::EnsureExpressionTemp() {
  if (!has_expression_temp_var()) {
    LocalVariable* temp =
        new LocalVariable(function_.token_pos(),
                          Symbols::ExprTemp(),
                          Type::ZoneHandle(Type::DynamicType()));
    ASSERT(temp != NULL);
    set_expression_temp_var(temp);
  }
  ASSERT(has_expression_temp_var());
  return expression_temp_var();
}


void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) {
  ASSERT(node_sequence_ == NULL);
  ASSERT(node_sequence != NULL);
  node_sequence_ = node_sequence;
}


void ParsedFunction::AllocateVariables() {
  LocalScope* scope = node_sequence()->scope();
  const intptr_t num_fixed_params = function().num_fixed_parameters();
  const intptr_t num_opt_params = function().NumOptionalParameters();
  const intptr_t num_params = num_fixed_params + num_opt_params;
  // Compute start indices to parameters and locals, and the number of
  // parameters to copy.
  if (num_opt_params == 0) {
    // Parameter i will be at fp[kParamEndSlotFromFp + num_params - i] and
    // local variable j will be at fp[kFirstLocalSlotFromFp - j].
    first_parameter_index_ = kParamEndSlotFromFp + num_params;
    first_stack_local_index_ = kFirstLocalSlotFromFp;
    num_copied_params_ = 0;
  } else {
    // Parameter i will be at fp[kFirstLocalSlotFromFp - i] and local variable
    // j will be at fp[kFirstLocalSlotFromFp - num_params - j].
    first_parameter_index_ = kFirstLocalSlotFromFp;
    first_stack_local_index_ = first_parameter_index_ - num_params;
    num_copied_params_ = num_params;
  }

  // Allocate parameters and local variables, either in the local frame or
  // in the context(s).
  LocalScope* context_owner = NULL;  // No context needed yet.
  int next_free_frame_index =
      scope->AllocateVariables(first_parameter_index_,
                               num_params,
                               first_stack_local_index_,
                               scope,
                               &context_owner);

  // If this function allocates context variables, but none of its enclosing
  // functions do, the context on entry is not linked as parent of the allocated
  // context but saved on entry and restored on exit as to prevent memory leaks.
  // Add and allocate a local variable to this purpose.
  if (context_owner != NULL) {
    const ContextScope& context_scope =
        ContextScope::Handle(function().context_scope());
    if (context_scope.IsNull() || (context_scope.num_variables() == 0)) {
      LocalVariable* context_var =
          new LocalVariable(function().token_pos(),
                            Symbols::SavedEntryContextVar(),
                            Type::ZoneHandle(Type::DynamicType()));
      context_var->set_index(next_free_frame_index--);
      scope->AddVariable(context_var);
      set_saved_entry_context_var(context_var);
    }
  }

  // Frame indices are relative to the frame pointer and are decreasing.
  ASSERT(next_free_frame_index <= first_stack_local_index_);
  num_stack_locals_ = first_stack_local_index_ - next_free_frame_index;
}


struct Parser::Block : public ZoneAllocated {
  Block(Block* outer_block, LocalScope* local_scope, SequenceNode* seq)
    : parent(outer_block), scope(local_scope), statements(seq) {
    ASSERT(scope != NULL);
    ASSERT(statements != NULL);
  }
  Block* parent;  // Enclosing block, or NULL if outermost.
  LocalScope* scope;
  SequenceNode* statements;
};


// Class which describes an inlined finally block which is used to generate
// inlined code for the finally blocks when there is an exit from a try
// block using 'return', 'break' or 'continue'.
class Parser::TryBlocks : public ZoneAllocated {
 public:
  TryBlocks(Block* try_block, TryBlocks* outer_try_block, intptr_t try_index)
      : try_block_(try_block),
        inlined_finally_nodes_(),
        outer_try_block_(outer_try_block),
        try_index_(try_index) { }

  TryBlocks* outer_try_block() const { return outer_try_block_; }
  Block* try_block() const { return try_block_; }
  intptr_t try_index() const { return try_index_; }

  void AddNodeForFinallyInlining(AstNode* node);
  AstNode* GetNodeToInlineFinally(int index) {
    if (0 <= index && index < inlined_finally_nodes_.length()) {
      return inlined_finally_nodes_[index];
    }
    return NULL;
  }

 private:
  Block* try_block_;
  GrowableArray<AstNode*> inlined_finally_nodes_;
  TryBlocks* outer_try_block_;
  const intptr_t try_index_;

  DISALLOW_COPY_AND_ASSIGN(TryBlocks);
};


void Parser::TryBlocks::AddNodeForFinallyInlining(AstNode* node) {
  inlined_finally_nodes_.Add(node);
}


// For parsing a compilation unit.
Parser::Parser(const Script& script, const Library& library, intptr_t token_pos)
    : isolate_(Isolate::Current()),
      script_(Script::Handle(isolate_, script.raw())),
      tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()),
                       token_pos),
      token_kind_(Token::kILLEGAL),
      current_block_(NULL),
      is_top_level_(false),
      current_member_(NULL),
      allow_function_literals_(true),
      parsed_function_(NULL),
      innermost_function_(Function::Handle(isolate_)),
      literal_token_(LiteralToken::Handle(isolate_)),
      current_class_(Class::Handle(isolate_)),
      library_(Library::Handle(isolate_, library.raw())),
      try_blocks_list_(NULL),
      last_used_try_index_(0),
      unregister_pending_function_(false) {
  ASSERT(tokens_iterator_.IsValid());
  ASSERT(!library.IsNull());
}


// For parsing a function.
Parser::Parser(const Script& script,
               ParsedFunction* parsed_function,
               intptr_t token_position)
    : isolate_(Isolate::Current()),
      script_(Script::Handle(isolate_, script.raw())),
      tokens_iterator_(TokenStream::Handle(isolate_, script.tokens()),
                       token_position),
      token_kind_(Token::kILLEGAL),
      current_block_(NULL),
      is_top_level_(false),
      current_member_(NULL),
      allow_function_literals_(true),
      parsed_function_(parsed_function),
      innermost_function_(Function::Handle(isolate_,
                                           parsed_function->function().raw())),
      literal_token_(LiteralToken::Handle(isolate_)),
      current_class_(Class::Handle(isolate_,
                                   parsed_function->function().Owner())),
      library_(Library::Handle(Class::Handle(
          isolate_,
          parsed_function->function().origin()).library())),
      try_blocks_list_(NULL),
      last_used_try_index_(0),
      unregister_pending_function_(false) {
  ASSERT(tokens_iterator_.IsValid());
  ASSERT(!current_function().IsNull());
  if (FLAG_enable_type_checks) {
    EnsureExpressionTemp();
  }
}


Parser::~Parser() {
  if (unregister_pending_function_) {
    const GrowableObjectArray& pending_functions =
        GrowableObjectArray::Handle(
            isolate()->object_store()->pending_functions());
    ASSERT(pending_functions.Length() > 0);
    ASSERT(pending_functions.At(pending_functions.Length()-1) ==
        current_function().raw());
    pending_functions.RemoveLast();
  }
}


void Parser::SetScript(const Script & script, intptr_t token_pos) {
  script_ = script.raw();
  tokens_iterator_.SetStream(TokenStream::Handle(script.tokens()), token_pos);
  token_kind_ = Token::kILLEGAL;
}


bool Parser::SetAllowFunctionLiterals(bool value) {
  bool current_value = allow_function_literals_;
  allow_function_literals_ = value;
  return current_value;
}


const Function& Parser::current_function() const {
  ASSERT(parsed_function() != NULL);
  return parsed_function()->function();
}


const Function& Parser::innermost_function() const {
  return innermost_function_;
}


const Class& Parser::current_class() const {
  return current_class_;
}


void Parser::set_current_class(const Class& value) {
  current_class_ = value.raw();
}


void Parser::SetPosition(intptr_t position) {
  if (position < TokenPos() && position != 0) {
    CompilerStats::num_tokens_rewind += (TokenPos() - position);
  }
  tokens_iterator_.SetCurrentPosition(position);
  token_kind_ = Token::kILLEGAL;
}


void Parser::ParseCompilationUnit(const Library& library,
                                  const Script& script) {
  ASSERT(Isolate::Current()->long_jump_base()->IsSafeToJump());
  TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
  Parser parser(script, library, 0);
  parser.ParseTopLevel();
}


Token::Kind Parser::CurrentToken() {
  if (token_kind_ == Token::kILLEGAL) {
    token_kind_ = tokens_iterator_.CurrentTokenKind();
    if (token_kind_ == Token::kERROR) {
      ErrorMsg(TokenPos(), "%s", CurrentLiteral()->ToCString());
    }
  }
  CompilerStats::num_token_checks++;
  return token_kind_;
}


Token::Kind Parser::LookaheadToken(int num_tokens) {
  CompilerStats::num_tokens_lookahead++;
  CompilerStats::num_token_checks++;
  return tokens_iterator_.LookaheadTokenKind(num_tokens);
}


String* Parser::CurrentLiteral() const {
  String& result = String::ZoneHandle();
  result = tokens_iterator_.CurrentLiteral();
  return &result;
}


RawDouble* Parser::CurrentDoubleLiteral() const {
  literal_token_ ^= tokens_iterator_.CurrentToken();
  ASSERT(literal_token_.kind() == Token::kDOUBLE);
  return Double::RawCast(literal_token_.value());
}


RawInteger* Parser::CurrentIntegerLiteral() const {
  literal_token_ ^= tokens_iterator_.CurrentToken();
  ASSERT(literal_token_.kind() == Token::kINTEGER);
  RawInteger* ri = Integer::RawCast(literal_token_.value());
  if (FLAG_throw_on_javascript_int_overflow) {
    const Integer& i = Integer::Handle(ri);
    if (i.CheckJavascriptIntegerOverflow()) {
      ErrorMsg(TokenPos(),
          "Integer literal does not fit in a Javascript integer: %s.",
          i.ToCString());
    }
  }
  return ri;
}


// A QualIdent is an optionally qualified identifier.
struct QualIdent {
  QualIdent() {
    Clear();
  }
  void Clear() {
    lib_prefix = NULL;
    ident_pos = 0;
    ident = NULL;
  }
  LibraryPrefix* lib_prefix;
  intptr_t ident_pos;
  String* ident;
};


struct ParamDesc {
  ParamDesc()
      : type(NULL),
        name_pos(0),
        name(NULL),
        default_value(NULL),
        is_final(false),
        is_field_initializer(false) { }
  const AbstractType* type;
  intptr_t name_pos;
  const String* name;
  const Object* default_value;  // NULL if not an optional parameter.
  bool is_final;
  bool is_field_initializer;
};


struct ParamList {
  ParamList() {
    Clear();
  }

  void Clear() {
    num_fixed_parameters = 0;
    num_optional_parameters = 0;
    has_optional_positional_parameters = false;
    has_optional_named_parameters = false;
    has_field_initializer = false;
    implicitly_final = false;
    skipped = false;
    this->parameters = new ZoneGrowableArray<ParamDesc>();
  }

  void AddFinalParameter(intptr_t name_pos,
                         const String* name,
                         const AbstractType* type) {
    this->num_fixed_parameters++;
    ParamDesc param;
    param.name_pos = name_pos;
    param.name = name;
    param.is_final = true;
    param.type = type;
    this->parameters->Add(param);
  }

  void AddReceiver(const AbstractType* receiver_type, intptr_t token_pos) {
    ASSERT(this->parameters->is_empty());
    AddFinalParameter(token_pos, &Symbols::This(), receiver_type);
  }

  void SetImplicitlyFinal() {
    implicitly_final = true;
  }

  int num_fixed_parameters;
  int num_optional_parameters;
  bool has_optional_positional_parameters;
  bool has_optional_named_parameters;
  bool has_field_initializer;
  bool implicitly_final;
  bool skipped;
  ZoneGrowableArray<ParamDesc>* parameters;
};


struct MemberDesc {
  MemberDesc() {
    Clear();
  }
  void Clear() {
    has_abstract = false;
    has_external = false;
    has_final = false;
    has_const = false;
    has_static = false;
    has_var = false;
    has_factory = false;
    has_operator = false;
    metadata_pos = -1;
    operator_token = Token::kILLEGAL;
    type = NULL;
    name_pos = 0;
    name = NULL;
    redirect_name = NULL;
    constructor_name = NULL;
    params.Clear();
    kind = RawFunction::kRegularFunction;
  }
  bool IsConstructor() const {
    return (kind == RawFunction::kConstructor) && !has_static;
  }
  bool IsFactory() const {
    return (kind == RawFunction::kConstructor) && has_static;
  }
  bool IsFactoryOrConstructor() const {
    return (kind == RawFunction::kConstructor);
  }
  bool IsGetter() const {
    return kind == RawFunction::kGetterFunction;
  }
  bool IsSetter() const {
    return kind == RawFunction::kSetterFunction;
  }
  bool has_abstract;
  bool has_external;
  bool has_final;
  bool has_const;
  bool has_static;
  bool has_var;
  bool has_factory;
  bool has_operator;
  intptr_t metadata_pos;
  Token::Kind operator_token;
  const AbstractType* type;
  intptr_t name_pos;
  intptr_t decl_begin_pos;
  String* name;
  // For constructors: NULL or name of redirected to constructor.
  String* redirect_name;
  // For constructors: NULL for unnamed constructor,
  // identifier after classname for named constructors.
  String* constructor_name;
  ParamList params;
  RawFunction::Kind kind;
};


class ClassDesc : public ValueObject {
 public:
  ClassDesc(const Class& cls,
            const String& cls_name,
            bool is_interface,
            intptr_t token_pos)
      : clazz_(cls),
        class_name_(cls_name),
        token_pos_(token_pos),
        functions_(GrowableObjectArray::Handle(GrowableObjectArray::New())),
        fields_(GrowableObjectArray::Handle(GrowableObjectArray::New())) {
  }

  // Parameter 'name' is the unmangled name, i.e. without the setter
  // name mangling.
  bool FunctionNameExists(const String& name, RawFunction::Kind kind) const {
    // First check if a function or field of same name exists.
    if ((kind != RawFunction::kSetterFunction) && FunctionExists(name)) {
      return true;
    }
    // Now check whether there is a field and whether its implicit getter
    // or setter collides with the name.
    Field* field = LookupField(name);
    if (field != NULL) {
      if (kind == RawFunction::kSetterFunction) {
        // It's ok to have an implicit getter, it does not collide with
        // this setter function.
        if (!field->is_final()) {
          return true;
        }
      } else {
        // The implicit getter of the field collides with the name.
        return true;
      }
    }

    String& accessor_name = String::Handle();
    if (kind == RawFunction::kSetterFunction) {
      // Check if a setter function of same name exists.
      accessor_name = Field::SetterName(name);
      if (FunctionExists(accessor_name)) {
        return true;
      }
    } else {
      // Check if a getter function of same name exists.
      accessor_name = Field::GetterName(name);
      if (FunctionExists(accessor_name)) {
        return true;
      }
    }
    return false;
  }

  bool FieldNameExists(const String& name, bool check_setter) const {
    // First check if a function or field of same name exists.
    if (FunctionExists(name) || FieldExists(name)) {
      return true;
    }
    // Now check if a getter/setter function of same name exists.
    String& getter_name = String::Handle(Field::GetterName(name));
    if (FunctionExists(getter_name)) {
      return true;
    }
    if (check_setter) {
      String& setter_name = String::Handle(Field::SetterName(name));
      if (FunctionExists(setter_name)) {
        return true;
      }
    }
    return false;
  }

  void AddFunction(const Function& function) {
    ASSERT(!FunctionExists(String::Handle(function.name())));
    functions_.Add(function);
  }

  const GrowableObjectArray& functions() const {
    return functions_;
  }

  void AddField(const Field& field) {
    ASSERT(!FieldExists(String::Handle(field.name())));
    fields_.Add(field);
  }

  const GrowableObjectArray& fields() const {
    return fields_;
  }

  const Class& clazz() const {
    return clazz_;
  }

  const String& class_name() const {
    return class_name_;
  }

  bool has_constructor() const {
    Function& func = Function::Handle();
    for (int i = 0; i < functions_.Length(); i++) {
      func ^= functions_.At(i);
      if (func.kind() == RawFunction::kConstructor) {
        return true;
      }
    }
    return false;
  }

  intptr_t token_pos() const {
    return token_pos_;
  }

  void AddMember(const MemberDesc& member) {
    members_.Add(member);
  }

  const GrowableArray<MemberDesc>& members() const {
    return members_;
  }

  MemberDesc* LookupMember(const String& name) const {
    for (int i = 0; i < members_.length(); i++) {
      if (name.Equals(*members_[i].name)) {
        return &members_[i];
      }
    }
    return NULL;
  }

 private:
  Field* LookupField(const String& name) const {
    String& test_name = String::Handle();
    Field& field = Field::Handle();
    for (int i = 0; i < fields_.Length(); i++) {
      field ^= fields_.At(i);
      test_name = field.name();
      if (name.Equals(test_name)) {
        return &field;
      }
    }
    return NULL;
  }

  bool FieldExists(const String& name) const {
    return LookupField(name) != NULL;
  }

  Function* LookupFunction(const String& name) const {
    String& test_name = String::Handle();
    Function& func = Function::Handle();
    for (int i = 0; i < functions_.Length(); i++) {
      func ^= functions_.At(i);
      test_name = func.name();
      if (name.Equals(test_name)) {
        return &func;
      }
    }
    return NULL;
  }

  bool FunctionExists(const String& name) const {
    return LookupFunction(name) != NULL;
  }

  const Class& clazz_;
  const String& class_name_;
  intptr_t token_pos_;   // Token index of "class" keyword.
  GrowableObjectArray& functions_;
  GrowableObjectArray& fields_;
  GrowableArray<MemberDesc> members_;
};


struct TopLevel {
  TopLevel() :
      fields(GrowableObjectArray::Handle(GrowableObjectArray::New())),
      functions(GrowableObjectArray::Handle(GrowableObjectArray::New())) { }

  GrowableObjectArray& fields;
  GrowableObjectArray& functions;
};


static bool HasReturnNode(SequenceNode* seq) {
  if (seq->length() == 0) {
    return false;
  } else if ((seq->length()) == 1 &&
             (seq->NodeAt(seq->length() - 1)->IsSequenceNode())) {
    return HasReturnNode(seq->NodeAt(seq->length() - 1)->AsSequenceNode());
  } else {
    return seq->NodeAt(seq->length() - 1)->IsReturnNode();
  }
}


void Parser::ParseClass(const Class& cls) {
  if (!cls.is_synthesized_class()) {
    TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
    Isolate* isolate = Isolate::Current();
    ASSERT(isolate->long_jump_base()->IsSafeToJump());
    const Script& script = Script::Handle(isolate, cls.script());
    const Library& lib = Library::Handle(isolate, cls.library());
    Parser parser(script, lib, cls.token_pos());
    parser.ParseClassDefinition(cls);
  }
}


static bool IsInvisible(const Function& func) {
  if (!Library::IsPrivate(String::Handle(func.name()))) return false;
  // Check for private function in the core libraries.
  const Class& cls = Class::Handle(func.Owner());
  const Library& library = Library::Handle(cls.library());
  if (library.raw() == Library::CoreLibrary()) return true;
  if (library.raw() == Library::CollectionLibrary()) return true;
  if (library.raw() == Library::TypedDataLibrary()) return true;
  if (library.raw() == Library::MathLibrary()) return true;
  return false;
}


void Parser::ParseFunction(ParsedFunction* parsed_function) {
  TimerScope timer(FLAG_compiler_stats, &CompilerStats::parser_timer);
  Isolate* isolate = Isolate::Current();
  ASSERT(isolate->long_jump_base()->IsSafeToJump());
  ASSERT(parsed_function != NULL);
  const Function& func = parsed_function->function();
  // Mark private core library functions as invisible by default.
  if (IsInvisible(func)) func.set_is_visible(false);
  const Script& script = Script::Handle(isolate, func.script());
  Parser parser(script, parsed_function, func.token_pos());
  SequenceNode* node_sequence = NULL;
  Array& default_parameter_values = Array::ZoneHandle(isolate, Array::null());
  switch (func.kind()) {
    case RawFunction::kRegularFunction:
    case RawFunction::kClosureFunction:
    case RawFunction::kGetterFunction:
    case RawFunction::kSetterFunction:
    case RawFunction::kConstructor:
      // The call to a redirecting factory is redirected.
      ASSERT(!func.IsRedirectingFactory());
      if (!func.IsImplicitConstructor()) {
        parser.SkipFunctionPreamble();
      }
      node_sequence = parser.ParseFunc(func, default_parameter_values);
      break;
    case RawFunction::kImplicitGetter:
      ASSERT(!func.is_static());
      node_sequence = parser.ParseInstanceGetter(func);
      break;
    case RawFunction::kImplicitSetter:
      ASSERT(!func.is_static());
      node_sequence = parser.ParseInstanceSetter(func);
      break;
    case RawFunction::kImplicitStaticFinalGetter:
      node_sequence = parser.ParseStaticFinalGetter(func);
      break;
    case RawFunction::kMethodExtractor:
      node_sequence = parser.ParseMethodExtractor(func);
      break;
    case RawFunction::kNoSuchMethodDispatcher:
      node_sequence =
          parser.ParseNoSuchMethodDispatcher(func, default_parameter_values);
      break;
    case RawFunction::kInvokeFieldDispatcher:
      node_sequence =
          parser.ParseInvokeFieldDispatcher(func, default_parameter_values);
      break;
    default:
      UNREACHABLE();
  }

  if (!HasReturnNode(node_sequence)) {
    // Add implicit return node.
    node_sequence->Add(new ReturnNode(func.end_token_pos()));
  }
  if (parsed_function->has_expression_temp_var()) {
    node_sequence->scope()->AddVariable(parsed_function->expression_temp_var());
  }
  if (parsed_function->has_saved_current_context_var()) {
    node_sequence->scope()->AddVariable(
        parsed_function->saved_current_context_var());
  }
  parsed_function->SetNodeSequence(node_sequence);

  // The instantiator may be required at run time for generic type checks or
  // allocation of generic types.
  if (parser.IsInstantiatorRequired()) {
    // In the case of a local function, only set the instantiator if the
    // receiver (or type arguments parameter of a factory) was captured.
    LocalVariable* instantiator = NULL;
    const bool kTestOnly = true;
    if (parser.current_function().IsInFactoryScope()) {
      instantiator = parser.LookupTypeArgumentsParameter(node_sequence->scope(),
                                                         kTestOnly);
    } else {
      instantiator = parser.LookupReceiver(node_sequence->scope(), kTestOnly);
    }
    if (!parser.current_function().IsLocalFunction() ||
        ((instantiator != NULL) && instantiator->is_captured())) {
      parsed_function->set_instantiator(
          new LoadLocalNode(node_sequence->token_pos(), instantiator));
    }
  }

  parsed_function->set_default_parameter_values(default_parameter_values);
}


RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) {
  Isolate* isolate = Isolate::Current();
  StackZone zone(isolate);
  LongJump* base = isolate->long_jump_base();
  LongJump jump;
  isolate->set_long_jump_base(&jump);
  if (setjmp(*jump.Set()) == 0) {
    const Script& script = Script::Handle(cls.script());
    const Library& lib = Library::Handle(cls.library());
    Parser parser(script, lib, token_pos);
    parser.set_current_class(cls);
    return parser.EvaluateMetadata();
  } else {
    Error& error = Error::Handle();
    error = isolate->object_store()->sticky_error();
    isolate->object_store()->clear_sticky_error();
    isolate->set_long_jump_base(base);
    return error.raw();
  }
  UNREACHABLE();
  return Object::null();
}


RawArray* Parser::EvaluateMetadata() {
  if (CurrentToken() != Token::kAT) {
    ErrorMsg("Metadata character '@' expected");
  }
  GrowableObjectArray& meta_values =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  while (CurrentToken() == Token::kAT) {
    ConsumeToken();
    intptr_t expr_pos = TokenPos();
    if (!IsIdentifier()) {
      ExpectIdentifier("identifier expected");
    }
    AstNode* expr = NULL;
    if ((LookaheadToken(1) == Token::kLPAREN) ||
        ((LookaheadToken(1) == Token::kPERIOD) &&
            (LookaheadToken(3) == Token::kLPAREN)) ||
        ((LookaheadToken(1) == Token::kPERIOD) &&
            (LookaheadToken(3) == Token::kPERIOD) &&
            (LookaheadToken(5) == Token::kLPAREN))) {
      expr = ParseNewOperator(Token::kCONST);
    } else {
      expr = ParsePrimary();
    }
    if (expr->EvalConstExpr() == NULL) {
      ErrorMsg(expr_pos, "expression must be a compile-time constant");
    }
    const Instance& val = EvaluateConstExpr(expr);
    meta_values.Add(val);
  }
  return Array::MakeArray(meta_values);
}


SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) {
  TRACE_PARSER("ParseStaticFinalGetter");
  ParamList params;
  ASSERT(func.num_fixed_parameters() == 0);  // static.
  ASSERT(!func.HasOptionalParameters());
  ASSERT(AbstractType::Handle(func.result_type()).IsResolved());

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);

  intptr_t ident_pos = TokenPos();
  const String& field_name = *ExpectIdentifier("field name expected");
  const Class& field_class = Class::Handle(func.Owner());
  const Field& field =
      Field::ZoneHandle(field_class.LookupStaticField(field_name));

  if (!field.is_const() &&
      (field.value() != Object::transition_sentinel().raw()) &&
      (field.value() != Object::sentinel().raw())) {
    // The field has already been initialized at compile time (this can
    // happen, e.g., if we are recompiling for optimization).  There is no
    // need to check for initialization and compile the potentially very
    // large initialization code.  By skipping this code, the deoptimization
    // ids will not line up with the original code, but this is safe because
    // LoadStaticField does not deoptimize.
    LoadStaticFieldNode* load_node = new LoadStaticFieldNode(ident_pos, field);
    ReturnNode* return_node = new ReturnNode(ident_pos, load_node);
    current_block_->statements->Add(return_node);
    return CloseBlock();
  }

  // Static const fields must have an initializer.
  ExpectToken(Token::kASSIGN);

  // We don't want to use ParseConstExpr() here because we don't want
  // the constant folding code to create, compile and execute a code
  // fragment to evaluate the expression. Instead, we just make sure
  // the static const field initializer is a constant expression and
  // leave the evaluation to the getter function.
  const intptr_t expr_pos = TokenPos();
  AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);

  if (field.is_const()) {
    // This getter will only be called once at compile time.
    if (expr->EvalConstExpr() == NULL) {
      ErrorMsg(expr_pos, "initializer must be a compile-time constant");
    }
    ReturnNode* return_node = new ReturnNode(ident_pos, expr);
    current_block_->statements->Add(return_node);
  } else {
    // This getter may be called each time the static field is accessed.
    // The following generated code lazily initializes the field:
    // if (field.value === transition_sentinel) {
    //   field.value = null;
    //   throw("circular dependency in field initialization");
    // }
    // if (field.value === sentinel) {
    //   field.value = transition_sentinel;
    //   field.value = expr;
    // }
    // return field.value;  // Type check is executed here in checked mode.

    // Generate code checking for circular dependency in field initialization.
    AstNode* compare_circular = new ComparisonNode(
        ident_pos,
        Token::kEQ_STRICT,
        new LoadStaticFieldNode(ident_pos, field),
        new LiteralNode(ident_pos, Object::transition_sentinel()));
    // Set field to null prior to throwing exception, so that subsequent
    // accesses to the field do not throw again, since initializers should only
    // be executed once.
    SequenceNode* report_circular = new SequenceNode(ident_pos, NULL);
    report_circular->Add(
        new StoreStaticFieldNode(
            ident_pos,
            field,
            new LiteralNode(ident_pos, Instance::ZoneHandle())));
    // TODO(regis, 5802): Exception to throw is not specified by spec.
    const String& circular_error = String::ZoneHandle(
        Symbols::New("circular dependency in field initialization"));
    report_circular->Add(
        new ThrowNode(ident_pos,
                      new LiteralNode(ident_pos, circular_error),
                      NULL));
    AstNode* circular_check =
        new IfNode(ident_pos, compare_circular, report_circular, NULL);
    current_block_->statements->Add(circular_check);

    // Generate code checking for uninitialized field.
    AstNode* compare_uninitialized = new ComparisonNode(
        ident_pos,
        Token::kEQ_STRICT,
        new LoadStaticFieldNode(ident_pos, field),
        new LiteralNode(ident_pos, Object::sentinel()));
    SequenceNode* initialize_field = new SequenceNode(ident_pos, NULL);
    initialize_field->Add(
        new StoreStaticFieldNode(
            ident_pos,
            field,
            new LiteralNode(ident_pos, Object::transition_sentinel())));
    // TODO(hausner): If evaluation of the field value throws an exception,
    // we leave the field value as 'transition_sentinel', which is wrong.
    // A second reference to the field later throws a circular dependency
    // exception. The field should instead be set to null after an exception.
    initialize_field->Add(new StoreStaticFieldNode(ident_pos, field, expr));
    AstNode* uninitialized_check =
        new IfNode(ident_pos, compare_uninitialized, initialize_field, NULL);
    current_block_->statements->Add(uninitialized_check);

    // Generate code returning the field value.
    ReturnNode* return_node =
        new ReturnNode(ident_pos,
                       new LoadStaticFieldNode(ident_pos, field));
    current_block_->statements->Add(return_node);
  }
  return CloseBlock();
}


// Create AstNodes for an implicit instance getter method:
//   LoadLocalNode 0 ('this');
//   LoadInstanceFieldNode (field_name);
//   ReturnNode (field's value);
SequenceNode* Parser::ParseInstanceGetter(const Function& func) {
  TRACE_PARSER("ParseInstanceGetter");
  ParamList params;
  // func.token_pos() points to the name of the field.
  intptr_t ident_pos = func.token_pos();
  ASSERT(current_class().raw() == func.Owner());
  params.AddReceiver(ReceiverType(current_class()), ident_pos);
  ASSERT(func.num_fixed_parameters() == 1);  // receiver.
  ASSERT(!func.HasOptionalParameters());
  ASSERT(AbstractType::Handle(func.result_type()).IsResolved());

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);

  // Receiver is local 0.
  LocalVariable* receiver = current_block_->scope->VariableAt(0);
  LoadLocalNode* load_receiver = new LoadLocalNode(ident_pos, receiver);
  ASSERT(IsIdentifier());
  const String& field_name = *CurrentLiteral();
  const Class& field_class = Class::Handle(func.Owner());
  const Field& field =
      Field::ZoneHandle(field_class.LookupInstanceField(field_name));

  LoadInstanceFieldNode* load_field =
      new LoadInstanceFieldNode(ident_pos, load_receiver, field);

  ReturnNode* return_node = new ReturnNode(ident_pos, load_field);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


// Create AstNodes for an implicit instance setter method:
//   LoadLocalNode 0 ('this')
//   LoadLocalNode 1 ('value')
//   SetInstanceField (field_name);
//   ReturnNode (void);
SequenceNode* Parser::ParseInstanceSetter(const Function& func) {
  TRACE_PARSER("ParseInstanceSetter");
  // func.token_pos() points to the name of the field.
  intptr_t ident_pos = func.token_pos();
  const String& field_name = *CurrentLiteral();
  const Class& field_class = Class::ZoneHandle(func.Owner());
  const Field& field =
      Field::ZoneHandle(field_class.LookupInstanceField(field_name));
  const AbstractType& field_type = AbstractType::ZoneHandle(field.type());

  ParamList params;
  ASSERT(current_class().raw() == func.Owner());
  params.AddReceiver(ReceiverType(current_class()), ident_pos);
  params.AddFinalParameter(ident_pos,
                           &Symbols::Value(),
                           &field_type);
  ASSERT(func.num_fixed_parameters() == 2);  // receiver, value.
  ASSERT(!func.HasOptionalParameters());
  ASSERT(AbstractType::Handle(func.result_type()).IsVoidType());

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);

  LoadLocalNode* receiver =
      new LoadLocalNode(ident_pos, current_block_->scope->VariableAt(0));
  LoadLocalNode* value =
      new LoadLocalNode(ident_pos, current_block_->scope->VariableAt(1));

  EnsureExpressionTemp();
  StoreInstanceFieldNode* store_field =
      new StoreInstanceFieldNode(ident_pos, receiver, field, value);
  current_block_->statements->Add(store_field);
  current_block_->statements->Add(new ReturnNode(ident_pos));
  return CloseBlock();
}


SequenceNode* Parser::ParseMethodExtractor(const Function& func) {
  TRACE_PARSER("ParseMethodExtractor");
  ParamList params;

  const intptr_t ident_pos = func.token_pos();
  ASSERT(func.token_pos() == 0);
  ASSERT(current_class().raw() == func.Owner());
  params.AddReceiver(ReceiverType(current_class()), ident_pos);
  ASSERT(func.num_fixed_parameters() == 1);  // Receiver.
  ASSERT(!func.HasOptionalParameters());

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);

  // Receiver is local 0.
  LocalVariable* receiver = current_block_->scope->VariableAt(0);
  LoadLocalNode* load_receiver = new LoadLocalNode(ident_pos, receiver);

  ClosureNode* closure = new ClosureNode(
      ident_pos,
      Function::ZoneHandle(func.extracted_method_closure()),
      load_receiver,
      NULL);

  ReturnNode* return_node = new ReturnNode(ident_pos, closure);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


void Parser::BuildDispatcherScope(const Function& func,
                                  const ArgumentsDescriptor& desc,
                                  Array& default_values) {
  ParamList params;
  // Receiver first.
  intptr_t token_pos = func.token_pos();
  params.AddReceiver(ReceiverType(current_class()), token_pos);
  // Remaining positional parameters.
  intptr_t i = 1;
  for (; i < desc.PositionalCount(); ++i) {
    ParamDesc p;
    char name[64];
    OS::SNPrint(name, 64, ":p%" Pd, i);
    p.name = &String::ZoneHandle(Symbols::New(name));
    p.type = &Type::ZoneHandle(Type::DynamicType());
    params.parameters->Add(p);
    params.num_fixed_parameters++;
  }
  ASSERT(desc.PositionalCount() == params.num_fixed_parameters);

  // Named parameters.
  for (; i < desc.Count(); ++i) {
    ParamDesc p;
    intptr_t index = i - desc.PositionalCount();
    p.name = &String::ZoneHandle(desc.NameAt(index));
    p.type = &Type::ZoneHandle(Type::DynamicType());
    p.default_value = &Object::ZoneHandle();
    params.parameters->Add(p);
    params.num_optional_parameters++;
    params.has_optional_named_parameters = true;
  }
  ASSERT(desc.NamedCount() == params.num_optional_parameters);

  SetupDefaultsForOptionalParams(&params, default_values);

  // Build local scope for function and populate with the formal parameters.
  OpenFunctionBlock(func);
  AddFormalParamsToScope(&params, current_block_->scope);
}

SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func,
                                                  Array& default_values) {
  TRACE_PARSER("ParseNoSuchMethodDispatcher");

  ASSERT(func.IsNoSuchMethodDispatcher());
  intptr_t token_pos = func.token_pos();
  ASSERT(func.token_pos() == 0);
  ASSERT(current_class().raw() == func.Owner());

  ArgumentsDescriptor desc(Array::Handle(func.saved_args_desc()));
  ASSERT(desc.Count() > 0);

  // Set up scope for this function.
  BuildDispatcherScope(func, desc, default_values);

  // Receiver is local 0.
  LocalScope* scope = current_block_->scope;
  ArgumentListNode* func_args = new ArgumentListNode(token_pos);
  for (intptr_t i = 0; i < desc.Count(); ++i) {
    func_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i)));
  }

  if (desc.NamedCount() > 0) {
    const Array& arg_names =
        Array::ZoneHandle(Array::New(desc.NamedCount()));
    for (intptr_t i = 0; i < arg_names.Length(); ++i) {
      arg_names.SetAt(i, String::Handle(desc.NameAt(i)));
    }
    func_args->set_names(arg_names);
  }

  const String& func_name = String::ZoneHandle(func.name());
  ArgumentListNode* arguments = BuildNoSuchMethodArguments(token_pos,
                                                           func_name,
                                                           *func_args);
  const Function& no_such_method = Function::ZoneHandle(
        Resolver::ResolveDynamicAnyArgs(Class::Handle(func.Owner()),
                                        Symbols::NoSuchMethod()));
  StaticCallNode* call =
      new StaticCallNode(token_pos, no_such_method, arguments);


  ReturnNode* return_node = new ReturnNode(token_pos, call);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


SequenceNode* Parser::ParseInvokeFieldDispatcher(const Function& func,
                                                 Array& default_values) {
  TRACE_PARSER("ParseInvokeFieldDispatcher");

  ASSERT(func.IsInvokeFieldDispatcher());
  intptr_t token_pos = func.token_pos();
  ASSERT(func.token_pos() == 0);
  ASSERT(current_class().raw() == func.Owner());

  const Array& args_desc = Array::Handle(func.saved_args_desc());
  ArgumentsDescriptor desc(args_desc);
  ASSERT(desc.Count() > 0);

  // Set up scope for this function.
  BuildDispatcherScope(func, desc, default_values);

  // Receiver is local 0.
  LocalScope* scope = current_block_->scope;
  ArgumentListNode* no_args = new ArgumentListNode(token_pos);
  LoadLocalNode* receiver = new LoadLocalNode(token_pos, scope->VariableAt(0));

  const String& name = String::Handle(func.name());
  const String& getter_name =
      String::ZoneHandle(Symbols::New(String::Handle(Field::GetterName(name))));
  InstanceCallNode* getter_call = new InstanceCallNode(token_pos,
                                                       receiver,
                                                       getter_name,
                                                       no_args);

  // Pass arguments 1..n to the closure call.
  ArgumentListNode* closure_args = new ArgumentListNode(token_pos);
  const Array& names = Array::Handle(Array::New(desc.NamedCount(), Heap::kOld));
  // Positional parameters.
  intptr_t i = 1;
  for (; i < desc.PositionalCount(); ++i) {
    closure_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i)));
  }
  // Named parameters.
  for (; i < desc.Count(); i++) {
    closure_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i)));
    intptr_t index = i - desc.PositionalCount();
    names.SetAt(index, String::Handle(desc.NameAt(index)));
  }
  closure_args->set_names(names);

  EnsureSavedCurrentContext();
  ClosureCallNode* closure_call = new ClosureCallNode(token_pos,
                                                      getter_call,
                                                      closure_args);

  ReturnNode* return_node = new ReturnNode(token_pos, closure_call);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


void Parser::SkipBlock() {
  ASSERT(CurrentToken() == Token::kLBRACE);
  GrowableArray<Token::Kind> token_stack(8);
  const intptr_t block_start_pos = TokenPos();
  bool is_match = true;
  bool unexpected_token_found = false;
  Token::Kind token;
  intptr_t token_pos;
  do {
    token = CurrentToken();
    token_pos = TokenPos();
    switch (token) {
      case Token::kLBRACE:
      case Token::kLPAREN:
      case Token::kLBRACK:
        token_stack.Add(token);
        break;
      case Token::kRBRACE:
        is_match = token_stack.RemoveLast() == Token::kLBRACE;
        break;
      case Token::kRPAREN:
        is_match = token_stack.RemoveLast() == Token::kLPAREN;
        break;
      case Token::kRBRACK:
        is_match = token_stack.RemoveLast() == Token::kLBRACK;
        break;
      case Token::kEOS:
        unexpected_token_found = true;
        break;
      default:
        // nothing.
        break;
    }
    ConsumeToken();
  } while (!token_stack.is_empty() && is_match && !unexpected_token_found);
  if (!is_match) {
    ErrorMsg(token_pos, "unbalanced '%s'", Token::Str(token));
  } else if (unexpected_token_found) {
    ErrorMsg(block_start_pos, "unterminated block");
  }
}


void Parser::ParseFormalParameter(bool allow_explicit_default_value,
                                  ParamList* params) {
  TRACE_PARSER("ParseFormalParameter");
  ParamDesc parameter;
  bool var_seen = false;
  bool this_seen = false;

  SkipMetadata();
  if (CurrentToken() == Token::kFINAL) {
    ConsumeToken();
    parameter.is_final = true;
  } else if (CurrentToken() == Token::kVAR) {
    ConsumeToken();
    var_seen = true;
    // The parameter type is the 'dynamic' type.
    parameter.type = &Type::ZoneHandle(Type::DynamicType());
  }
  if (CurrentToken() == Token::kTHIS) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
    this_seen = true;
    parameter.is_field_initializer = true;
  }
  if (params->implicitly_final) {
    parameter.is_final = true;
  }
  if ((parameter.type == NULL) && (CurrentToken() == Token::kVOID)) {
    ConsumeToken();
    // This must later be changed to a closure type if we recognize
    // a closure/function type parameter. We check this at the end
    // of ParseFormalParameter.
    parameter.type = &Type::ZoneHandle(Type::VoidType());
  }
  if (parameter.type == NULL) {
    // At this point, we must see an identifier for the type or the
    // function parameter.
    if (!IsIdentifier()) {
      ErrorMsg("parameter name or type expected");
    }
    // We have not seen a parameter type yet, so we check if the next
    // identifier could represent a type before parsing it.
    Token::Kind follower = LookaheadToken(1);
    // We have an identifier followed by a 'follower' token.
    // We either parse a type or assume that no type is specified.
    if ((follower == Token::kLT) ||  // Parameterized type.
        (follower == Token::kPERIOD) ||  // Qualified class name of type.
        Token::IsIdentifier(follower) ||  // Parameter name following a type.
        (follower == Token::kTHIS)) {  // Field parameter following a type.
      // The types of formal parameters are never ignored, even in unchecked
      // mode, because they are part of the function type of closurized
      // functions appearing in type tests with typedefs.
      parameter.type = &AbstractType::ZoneHandle(
          ParseType(is_top_level_ ? ClassFinalizer::kResolveTypeParameters :
                                    ClassFinalizer::kCanonicalize));
    } else {
      parameter.type = &Type::ZoneHandle(Type::DynamicType());
    }
  }
  if (!this_seen && (CurrentToken() == Token::kTHIS)) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
    this_seen = true;
    parameter.is_field_initializer = true;
  }

  // At this point, we must see an identifier for the parameter name.
  parameter.name_pos = TokenPos();
  parameter.name = ExpectIdentifier("parameter name expected");
  if (parameter.is_field_initializer) {
    params->has_field_initializer = true;
  }

  // Check for duplicate formal parameters.
  const intptr_t num_existing_parameters =
      params->num_fixed_parameters + params->num_optional_parameters;
  for (intptr_t i = 0; i < num_existing_parameters; i++) {
    ParamDesc& existing_parameter = (*params->parameters)[i];
    if (existing_parameter.name->Equals(*parameter.name)) {
      ErrorMsg(parameter.name_pos, "duplicate formal parameter '%s'",
               parameter.name->ToCString());
    }
  }

  if (CurrentToken() == Token::kLPAREN) {
    // This parameter is probably a closure. If we saw the keyword 'var'
    // or 'final', a closure is not legal here and we ignore the
    // opening parens.
    if (!var_seen && !parameter.is_final) {
      // The parsed parameter type is actually the function result type.
      const AbstractType& result_type =
          AbstractType::Handle(parameter.type->raw());

      // Finish parsing the function type parameter.
      ParamList func_params;

      // Add implicit closure object parameter.
      func_params.AddFinalParameter(
          TokenPos(),
          &Symbols::ClosureParameter(),
          &Type::ZoneHandle(Type::DynamicType()));

      const bool no_explicit_default_values = false;
      ParseFormalParameterList(no_explicit_default_values, &func_params);

      // The field 'is_static' has no meaning for signature functions.
      const Function& signature_function = Function::Handle(
          Function::New(*parameter.name,
                        RawFunction::kSignatureFunction,
                        /* is_static = */ false,
                        /* is_const = */ false,
                        /* is_abstract = */ false,
                        /* is_external = */ false,
                        current_class(),
                        parameter.name_pos));
      signature_function.set_result_type(result_type);
      AddFormalParamsToFunction(&func_params, signature_function);
      const String& signature = String::Handle(signature_function.Signature());
      // Lookup the signature class, i.e. the class whose name is the signature.
      // We only lookup in the current library, but not in its imports, and only
      // create a new canonical signature class if it does not exist yet.
      Class& signature_class = Class::ZoneHandle(
          library_.LookupLocalClass(signature));
      if (signature_class.IsNull()) {
        signature_class = Class::NewSignatureClass(signature,
                                                   signature_function,
                                                   script_,
                                                   parameter.name_pos);
        // Record the function signature class in the current library, unless
        // we are currently skipping a formal parameter list, in which case
        // the signature class could remain unfinalized.
        if (!params->skipped) {
          library_.AddClass(signature_class);
        }
      } else {
        signature_function.set_signature_class(signature_class);
      }
      ASSERT(signature_function.signature_class() == signature_class.raw());
      Type& signature_type = Type::ZoneHandle(signature_class.SignatureType());
      if (!is_top_level_ && !signature_type.IsFinalized()) {
        signature_type ^= ClassFinalizer::FinalizeType(
            signature_class, signature_type, ClassFinalizer::kCanonicalize);
      }
      // The type of the parameter is now the signature type.
      parameter.type = &signature_type;
    }
  }

  if ((CurrentToken() == Token::kASSIGN) || (CurrentToken() == Token::kCOLON)) {
    if ((!params->has_optional_positional_parameters &&
         !params->has_optional_named_parameters) ||
        !allow_explicit_default_value) {
      ErrorMsg("parameter must not specify a default value");
    }
    if (params->has_optional_positional_parameters) {
      ExpectToken(Token::kASSIGN);
    } else {
      ExpectToken(Token::kCOLON);
    }
    params->num_optional_parameters++;
    if (is_top_level_) {
      // Skip default value parsing.
      SkipExpr();
    } else {
      const Object& const_value = ParseConstExpr()->literal();
      parameter.default_value = &const_value;
    }
  } else {
    if (params->has_optional_positional_parameters ||
        params->has_optional_named_parameters) {
      // Implicit default value is null.
      params->num_optional_parameters++;
      parameter.default_value = &Object::ZoneHandle();
    } else {
      params->num_fixed_parameters++;
      ASSERT(params->num_optional_parameters == 0);
    }
  }
  if (parameter.type->IsVoidType()) {
    ErrorMsg("parameter '%s' may not be 'void'", parameter.name->ToCString());
  }
  params->parameters->Add(parameter);
}


// Parses a sequence of normal or optional formal parameters.
void Parser::ParseFormalParameters(bool allow_explicit_default_values,
                                   ParamList* params) {
  TRACE_PARSER("ParseFormalParameters");
  do {
    ConsumeToken();
    if (!params->has_optional_positional_parameters &&
        !params->has_optional_named_parameters &&
        (CurrentToken() == Token::kLBRACK)) {
      // End of normal parameters, start of optional positional parameters.
      params->has_optional_positional_parameters = true;
      return;
    }
    if (!params->has_optional_positional_parameters &&
        !params->has_optional_named_parameters &&
        (CurrentToken() == Token::kLBRACE)) {
      // End of normal parameters, start of optional named parameters.
      params->has_optional_named_parameters = true;
      return;
    }
    ParseFormalParameter(allow_explicit_default_values, params);
  } while (CurrentToken() == Token::kCOMMA);
}


void Parser::ParseFormalParameterList(bool allow_explicit_default_values,
                                      ParamList* params) {
  TRACE_PARSER("ParseFormalParameterList");
  ASSERT(CurrentToken() == Token::kLPAREN);

  if (LookaheadToken(1) != Token::kRPAREN) {
    // Parse fixed parameters.
    ParseFormalParameters(allow_explicit_default_values, params);
    if (params->has_optional_positional_parameters ||
        params->has_optional_named_parameters) {
      // Parse optional parameters.
      ParseFormalParameters(allow_explicit_default_values, params);
      if (params->has_optional_positional_parameters) {
        if (CurrentToken() != Token::kRBRACK) {
          ErrorMsg("',' or ']' expected");
        }
      } else {
        if (CurrentToken() != Token::kRBRACE) {
          ErrorMsg("',' or '}' expected");
        }
      }
      ConsumeToken();  // ']' or '}'.
    }
    if ((CurrentToken() != Token::kRPAREN) &&
        !params->has_optional_positional_parameters &&
        !params->has_optional_named_parameters) {
      ErrorMsg("',' or ')' expected");
    }
  } else {
    ConsumeToken();
  }
  ExpectToken(Token::kRPAREN);
}


String& Parser::ParseNativeDeclaration() {
  TRACE_PARSER("ParseNativeDeclaration");
  ASSERT(IsLiteral("native"));
  ConsumeToken();
  if (CurrentToken() != Token::kSTRING) {
    ErrorMsg("string literal expected");
  }
  String& native_name = *CurrentLiteral();
  ConsumeToken();
  ExpectSemicolon();
  return native_name;
}


// Resolve and return the dynamic function of the given name in the superclass.
// If it is not found, and resolve_getter is true, try to resolve a getter of
// the same name. If it is still not found, return noSuchMethod and
// set is_no_such_method to true..
RawFunction* Parser::GetSuperFunction(intptr_t token_pos,
                                      const String& name,
                                      ArgumentListNode* arguments,
                                      bool resolve_getter,
                                      bool* is_no_such_method) {
  const Class& super_class = Class::Handle(current_class().SuperClass());
  if (super_class.IsNull()) {
    ErrorMsg(token_pos, "class '%s' does not have a superclass",
             String::Handle(current_class().Name()).ToCString());
  }
  Function& super_func = Function::Handle(
      Resolver::ResolveDynamicAnyArgs(super_class, name));
  if (!super_func.IsNull() &&
      !super_func.AreValidArguments(arguments->length(),
                                    arguments->names(),
                                    NULL)) {
    super_func = Function::null();
  } else if (super_func.IsNull() && resolve_getter) {
    const String& getter_name = String::ZoneHandle(Field::GetterName(name));
    super_func = Resolver::ResolveDynamicAnyArgs(super_class, getter_name);
    ASSERT(super_func.IsNull() ||
           (super_func.kind() != RawFunction::kImplicitStaticFinalGetter));
  }
  if (super_func.IsNull()) {
    super_func =
        Resolver::ResolveDynamicAnyArgs(super_class, Symbols::NoSuchMethod());
    ASSERT(!super_func.IsNull());
    *is_no_such_method = true;
  } else {
    *is_no_such_method = false;
  }
  return super_func.raw();
}


// Lookup class in the core lib which also contains various VM
// helper methods and classes. Allow look up of private classes.
static RawClass* LookupCoreClass(const String& class_name) {
  const Library& core_lib = Library::Handle(Library::CoreLibrary());
  String& name = String::Handle(class_name.raw());
  if (class_name.CharAt(0) == Scanner::kPrivateIdentifierStart) {
    // Private identifiers are mangled on a per script basis.
    name = String::Concat(name, String::Handle(core_lib.private_key()));
    name = Symbols::New(name);
  }
  return core_lib.LookupClass(name, NULL);  // No ambiguity error expected.
}


static const String& PrivateCoreLibName(const String& str) {
  const Library& core_lib = Library::Handle(Library::CoreLibrary());
  const String& private_name = String::ZoneHandle(core_lib.PrivateName(str));
  return private_name;
}


StaticCallNode* Parser::BuildInvocationMirrorAllocation(
    intptr_t call_pos,
    const String& function_name,
    const ArgumentListNode& function_args,
    const LocalVariable* temp_for_last_arg) {
  const intptr_t args_pos = function_args.token_pos();
  // Build arguments to the call to the static
  // InvocationMirror._allocateInvocationMirror method.
  ArgumentListNode* arguments = new ArgumentListNode(args_pos);
  // The first argument is the original function name.
  arguments->Add(new LiteralNode(args_pos, function_name));
  // The second argument is the arguments descriptor of the original function.
  const Array& args_descriptor =
      Array::ZoneHandle(ArgumentsDescriptor::New(function_args.length(),
                                                 function_args.names()));
  arguments->Add(new LiteralNode(args_pos, args_descriptor));
  // The third argument is an array containing the original function arguments,
  // including the receiver.
  ArrayNode* args_array =
      new ArrayNode(args_pos, Type::ZoneHandle(Type::ArrayType()));
  for (intptr_t i = 0; i < function_args.length(); i++) {
    AstNode* arg = function_args.NodeAt(i);
    if ((temp_for_last_arg != NULL) && (i == function_args.length() - 1)) {
      LetNode* store_arg = new LetNode(arg->token_pos());
      store_arg->AddNode(new StoreLocalNode(arg->token_pos(),
                                           temp_for_last_arg,
                                           arg));
      store_arg->AddNode(new LoadLocalNode(arg->token_pos(),
                                           temp_for_last_arg));
      args_array->AddElement(store_arg);
    } else {
      args_array->AddElement(arg);
    }
  }
  arguments->Add(args_array);
  // Lookup the static InvocationMirror._allocateInvocationMirror method.
  const Class& mirror_class =
      Class::Handle(LookupCoreClass(Symbols::InvocationMirror()));
  ASSERT(!mirror_class.IsNull());
  const Function& allocation_function = Function::ZoneHandle(
      mirror_class.LookupStaticFunction(
          PrivateCoreLibName(Symbols::AllocateInvocationMirror())));
  ASSERT(!allocation_function.IsNull());
  return new StaticCallNode(call_pos, allocation_function, arguments);
}


ArgumentListNode* Parser::BuildNoSuchMethodArguments(
    intptr_t call_pos,
    const String& function_name,
    const ArgumentListNode& function_args,
    const LocalVariable* temp_for_last_arg) {
  ASSERT(function_args.length() >= 1);  // The receiver is the first argument.
  const intptr_t args_pos = function_args.token_pos();
  ArgumentListNode* arguments = new ArgumentListNode(args_pos);
  arguments->Add(function_args.NodeAt(0));
  // The second argument is the invocation mirror.
  arguments->Add(BuildInvocationMirrorAllocation(
      call_pos, function_name, function_args, temp_for_last_arg));
  return arguments;
}


AstNode* Parser::ParseSuperCall(const String& function_name) {
  TRACE_PARSER("ParseSuperCall");
  ASSERT(CurrentToken() == Token::kLPAREN);
  const intptr_t supercall_pos = TokenPos();

  // 'this' parameter is the first argument to super call.
  ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
  AstNode* receiver = LoadReceiver(supercall_pos);
  arguments->Add(receiver);
  ParseActualParameters(arguments, kAllowConst);

  const bool kResolveGetter = true;
  bool is_no_such_method = false;
  const Function& super_function = Function::ZoneHandle(
      GetSuperFunction(supercall_pos,
                       function_name,
                       arguments,
                       kResolveGetter,
                       &is_no_such_method));
  if (super_function.IsGetterFunction() ||
      super_function.IsImplicitGetterFunction()) {
    const Class& super_class = Class::ZoneHandle(current_class().SuperClass());
    AstNode* closure = new StaticGetterNode(supercall_pos,
                                            LoadReceiver(supercall_pos),
                                            /* is_super_getter */ true,
                                            super_class,
                                            function_name);
    EnsureSavedCurrentContext();
    // 'this' is not passed as parameter to the closure.
    ArgumentListNode* closure_arguments = new ArgumentListNode(supercall_pos);
    for (int i = 1; i < arguments->length(); i++) {
      closure_arguments->Add(arguments->NodeAt(i));
    }
    return new ClosureCallNode(supercall_pos, closure, closure_arguments);
  }
  if (is_no_such_method) {
    arguments = BuildNoSuchMethodArguments(
        supercall_pos, function_name, *arguments);
  }
  return new StaticCallNode(supercall_pos, super_function, arguments);
}


// Simple test if a node is side effect free.
static bool IsSimpleLocalOrLiteralNode(AstNode* node) {
  return node->IsLiteralNode() || node->IsLoadLocalNode();
}


AstNode* Parser::BuildUnarySuperOperator(Token::Kind op, PrimaryNode* super) {
  ASSERT(super->IsSuper());
  AstNode* super_op = NULL;
  const intptr_t super_pos = super->token_pos();
  if ((op == Token::kNEGATE) ||
      (op == Token::kBIT_NOT)) {
    // Resolve the operator function in the superclass.
    const String& operator_function_name =
        String::ZoneHandle(Symbols::New(Token::Str(op)));
    ArgumentListNode* op_arguments = new ArgumentListNode(super_pos);
    AstNode* receiver = LoadReceiver(super_pos);
    op_arguments->Add(receiver);
    const bool kResolveGetter = false;
    bool is_no_such_method = false;
    const Function& super_operator = Function::ZoneHandle(
        GetSuperFunction(super_pos,
                         operator_function_name,
                         op_arguments,
                         kResolveGetter,
                         &is_no_such_method));
    if (is_no_such_method) {
      op_arguments = BuildNoSuchMethodArguments(
          super_pos, operator_function_name, *op_arguments);
    }
    super_op = new StaticCallNode(super_pos, super_operator, op_arguments);
  } else {
    ErrorMsg(super_pos, "illegal super operator call");
  }
  return super_op;
}


AstNode* Parser::ParseSuperOperator() {
  TRACE_PARSER("ParseSuperOperator");
  AstNode* super_op = NULL;
  const intptr_t operator_pos = TokenPos();

  if (CurrentToken() == Token::kLBRACK) {
    ConsumeToken();
    AstNode* index_expr = ParseExpr(kAllowConst, kConsumeCascades);
    ExpectToken(Token::kRBRACK);
    AstNode* receiver = LoadReceiver(operator_pos);
    const Class& super_class = Class::ZoneHandle(current_class().SuperClass());
    ASSERT(!super_class.IsNull());
    super_op =
        new LoadIndexedNode(operator_pos, receiver, index_expr, super_class);
  } else {
    ASSERT(Token::CanBeOverloaded(CurrentToken()) ||
           (CurrentToken() == Token::kNE));
    Token::Kind op = CurrentToken();
    ConsumeToken();

    bool negate_result = false;
    if (op == Token::kNE) {
      op = Token::kEQ;
      negate_result = true;
    }

    ASSERT(Token::Precedence(op) >= Token::Precedence(Token::kBIT_OR));
    AstNode* other_operand = ParseBinaryExpr(Token::Precedence(op) + 1);

    ArgumentListNode* op_arguments = new ArgumentListNode(operator_pos);
    AstNode* receiver = LoadReceiver(operator_pos);
    op_arguments->Add(receiver);
    op_arguments->Add(other_operand);

    // Resolve the operator function in the superclass.
    const String& operator_function_name =
        String::ZoneHandle(Symbols::New(Token::Str(op)));
    const bool kResolveGetter = false;
    bool is_no_such_method = false;
    const Function& super_operator = Function::ZoneHandle(
        GetSuperFunction(operator_pos,
                         operator_function_name,
                         op_arguments,
                         kResolveGetter,
                         &is_no_such_method));
    if (is_no_such_method) {
      op_arguments = BuildNoSuchMethodArguments(
          operator_pos, operator_function_name, *op_arguments);
    }
    super_op = new StaticCallNode(operator_pos, super_operator, op_arguments);
    if (negate_result) {
      super_op = new UnaryOpNode(operator_pos, Token::kNOT, super_op);
    }
  }
  return super_op;
}


AstNode* Parser::CreateImplicitClosureNode(const Function& func,
                                           intptr_t token_pos,
                                           AstNode* receiver) {
  Function& implicit_closure_function =
      Function::ZoneHandle(func.ImplicitClosureFunction());
  if (receiver != NULL) {
    // If we create an implicit instance closure from inside a closure of a
    // parameterized class, make sure that the receiver is captured as
    // instantiator.
    if (current_block_->scope->function_level() > 0) {
      const Class& signature_class = Class::Handle(
          implicit_closure_function.signature_class());
      if (signature_class.NumTypeParameters() > 0) {
        CaptureInstantiator();
      }
    }
  }
  return new ClosureNode(token_pos, implicit_closure_function, receiver, NULL);
}


AstNode* Parser::ParseSuperFieldAccess(const String& field_name) {
  TRACE_PARSER("ParseSuperFieldAccess");
  const intptr_t field_pos = TokenPos();
  const Class& super_class = Class::ZoneHandle(current_class().SuperClass());
  if (super_class.IsNull()) {
    ErrorMsg("class '%s' does not have a superclass",
             String::Handle(current_class().Name()).ToCString());
  }
  AstNode* implicit_argument = LoadReceiver(field_pos);

  const String& getter_name =
      String::ZoneHandle(Field::GetterName(field_name));
  const Function& super_getter = Function::ZoneHandle(
      Resolver::ResolveDynamicAnyArgs(super_class, getter_name));
  if (super_getter.IsNull()) {
    const String& setter_name =
        String::ZoneHandle(Field::SetterName(field_name));
    const Function& super_setter = Function::ZoneHandle(
        Resolver::ResolveDynamicAnyArgs(super_class, setter_name));
    if (super_setter.IsNull()) {
      // Check if this is an access to an implicit closure using 'super'.
      // If a function exists of the specified field_name then try
      // accessing it as a getter, at runtime we will handle this by
      // creating an implicit closure of the function and returning it.
      const Function& super_function = Function::ZoneHandle(
          Resolver::ResolveDynamicAnyArgs(super_class, field_name));
      if (!super_function.IsNull()) {
        // In case CreateAssignmentNode is called later on this
        // CreateImplicitClosureNode, it will be replaced by a StaticSetterNode.
        return CreateImplicitClosureNode(super_function,
                                         field_pos,
                                         implicit_argument);
      }
      // No function or field exists of the specified field_name.
      // Emit a StaticGetterNode anyway, so that noSuchMethod gets called.
    }
  }
  return new StaticGetterNode(
      field_pos, implicit_argument, true, super_class, field_name);
}


void Parser::GenerateSuperConstructorCall(const Class& cls,
                                          LocalVariable* receiver,
                                          ArgumentListNode* forwarding_args) {
  const intptr_t supercall_pos = TokenPos();
  const Class& super_class = Class::Handle(cls.SuperClass());
  // Omit the implicit super() if there is no super class (i.e.
  // we're not compiling class Object), or if the super class is an
  // artificially generated "wrapper class" that has no constructor.
  if (super_class.IsNull() ||
      (super_class.num_native_fields() > 0 &&
       Class::Handle(super_class.SuperClass()).IsObjectClass())) {
    return;
  }
  String& super_ctor_name = String::Handle(super_class.Name());
  super_ctor_name = String::Concat(super_ctor_name, Symbols::Dot());

  ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
  // Implicit 'this' parameter is the first argument.
  AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver);
  arguments->Add(implicit_argument);
  // Implicit construction phase parameter is second argument.
  AstNode* phase_parameter =
      new LiteralNode(supercall_pos,
                      Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll)));
  arguments->Add(phase_parameter);

  // If this is a super call in a forwarding constructor, add the user-
  // defined arguments to the super call and adjust the the super
  // constructor name to the respective named constructor if necessary.
  if (forwarding_args != NULL) {
    for (int i = 0; i < forwarding_args->length(); i++) {
      arguments->Add(forwarding_args->NodeAt(i));
    }
    String& ctor_name = String::Handle(current_function().name());
    String& class_name = String::Handle(cls.Name());
    if (ctor_name.Length() > class_name.Length() + 1) {
      // Generating a forwarding call to a named constructor 'C.n'.
      // Add the constructor name 'n' to the super constructor.
      ctor_name = String::SubString(ctor_name, class_name.Length() + 1);
      super_ctor_name = String::Concat(super_ctor_name, ctor_name);
    }
  }

  // Resolve super constructor function and check arguments.
  const Function& super_ctor = Function::ZoneHandle(
      super_class.LookupConstructor(super_ctor_name));
  if (super_ctor.IsNull()) {
      ErrorMsg(supercall_pos,
               "unresolved implicit call to super constructor '%s()'",
               String::Handle(super_class.Name()).ToCString());
  }
  if (current_function().is_const() && !super_ctor.is_const()) {
    ErrorMsg(supercall_pos, "implicit call to non-const super constructor");
  }

  String& error_message = String::Handle();
  if (!super_ctor.AreValidArguments(arguments->length(),
                                    arguments->names(),
                                    &error_message)) {
    ErrorMsg(supercall_pos,
             "invalid arguments passed to super constructor '%s()': %s",
             String::Handle(super_class.Name()).ToCString(),
             error_message.ToCString());
  }
  current_block_->statements->Add(
      new StaticCallNode(supercall_pos, super_ctor, arguments));
}


AstNode* Parser::ParseSuperInitializer(const Class& cls,
                                       LocalVariable* receiver) {
  TRACE_PARSER("ParseSuperInitializer");
  ASSERT(CurrentToken() == Token::kSUPER);
  const intptr_t supercall_pos = TokenPos();
  ConsumeToken();
  const Class& super_class = Class::Handle(cls.SuperClass());
  ASSERT(!super_class.IsNull());
  String& ctor_name = String::Handle(super_class.Name());
  ctor_name = String::Concat(ctor_name, Symbols::Dot());
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    ctor_name = String::Concat(ctor_name,
                               *ExpectIdentifier("constructor name expected"));
  }
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("parameter list expected");
  }

  ArgumentListNode* arguments = new ArgumentListNode(supercall_pos);
  // 'this' parameter is the first argument to super class constructor.
  AstNode* implicit_argument = new LoadLocalNode(supercall_pos, receiver);
  arguments->Add(implicit_argument);
  // Second implicit parameter is the construction phase. We optimistically
  // assume that we can execute both the super initializer and the super
  // constructor body. We may later change this to only execute the
  // super initializer.
  AstNode* phase_parameter =
      new LiteralNode(supercall_pos,
                      Smi::ZoneHandle(Smi::New(Function::kCtorPhaseAll)));
  arguments->Add(phase_parameter);
  // 'this' parameter must not be accessible to the other super call arguments.
  receiver->set_invisible(true);
  ParseActualParameters(arguments, kAllowConst);
  receiver->set_invisible(false);

  // Resolve the constructor.
  const Function& super_ctor = Function::ZoneHandle(
      super_class.LookupConstructor(ctor_name));
  if (super_ctor.IsNull()) {
    ErrorMsg(supercall_pos,
             "super class constructor '%s' not found",
             ctor_name.ToCString());
  }
  if (current_function().is_const() && !super_ctor.is_const()) {
    ErrorMsg(supercall_pos, "super constructor must be const");
  }
  String& error_message = String::Handle();
  if (!super_ctor.AreValidArguments(arguments->length(),
                                    arguments->names(),
                                    &error_message)) {
    ErrorMsg(supercall_pos,
             "invalid arguments passed to super class constructor '%s': %s",
             ctor_name.ToCString(),
             error_message.ToCString());
  }
  return new StaticCallNode(supercall_pos, super_ctor, arguments);
}


AstNode* Parser::ParseInitializer(const Class& cls,
                                  LocalVariable* receiver,
                                  GrowableArray<Field*>* initialized_fields) {
  TRACE_PARSER("ParseInitializer");
  const intptr_t field_pos = TokenPos();
  if (CurrentToken() == Token::kTHIS) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
  }
  const String& field_name = *ExpectIdentifier("field name expected");
  ExpectToken(Token::kASSIGN);

  const bool saved_mode = SetAllowFunctionLiterals(false);
  // "this" must not be accessible in initializer expressions.
  receiver->set_invisible(true);
  AstNode* init_expr = ParseConditionalExpr();
  if (CurrentToken() == Token::kCASCADE) {
    init_expr = ParseCascades(init_expr);
  }
  receiver->set_invisible(false);
  SetAllowFunctionLiterals(saved_mode);
  if (current_function().is_const() && !init_expr->IsPotentiallyConst()) {
    ErrorMsg(field_pos,
             "initializer expression must be compile time constant.");
  }
  Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
  if (field.IsNull()) {
    ErrorMsg(field_pos, "unresolved reference to instance field '%s'",
             field_name.ToCString());
  }
  CheckDuplicateFieldInit(field_pos, initialized_fields, &field);
  AstNode* instance = new LoadLocalNode(field_pos, receiver);
  EnsureExpressionTemp();
  return new StoreInstanceFieldNode(field_pos, instance, field, init_expr);
}


void Parser::CheckConstFieldsInitialized(const Class& cls) {
  const Array& fields = Array::Handle(cls.fields());
  Field& field = Field::Handle();
  SequenceNode* initializers = current_block_->statements;
  for (int field_num = 0; field_num < fields.Length(); field_num++) {
    field ^= fields.At(field_num);
    if (field.is_static()) {
      continue;
    }

    bool found = false;
    for (int i = 0; i < initializers->length(); i++) {
      found = false;
      if (initializers->NodeAt(i)->IsStoreInstanceFieldNode()) {
        StoreInstanceFieldNode* initializer =
            initializers->NodeAt(i)->AsStoreInstanceFieldNode();
        if (initializer->field().raw() == field.raw()) {
          found = true;
          break;
        }
      }
    }

    if (found) continue;

    if (field.is_final()) {
      ErrorMsg("final field '%s' not initialized",
               String::Handle(field.name()).ToCString());
    } else {
      field.UpdateCid(kNullCid);
      field.UpdateLength(Field::kNoFixedLength);
    }
  }
}


AstNode* Parser::ParseExternalInitializedField(const Field& field) {
  // Only use this function if the initialized field originates
  // from a different class. We need to save and restore current
  // class, library, and token stream (script).
  ASSERT(current_class().raw() != field.origin());
  const Class& saved_class = Class::Handle(current_class().raw());
  const Library& saved_library = Library::Handle(library().raw());
  const Script& saved_script = Script::Handle(script().raw());
  const intptr_t saved_token_pos = TokenPos();

  set_current_class(Class::Handle(field.origin()));
  set_library(Library::Handle(current_class().library()));
  SetScript(Script::Handle(current_class().script()), field.token_pos());

  ASSERT(IsIdentifier());
  ConsumeToken();
  ExpectToken(Token::kASSIGN);
  AstNode* init_expr = NULL;
  if (field.is_const()) {
    init_expr = ParseConstExpr();
  } else {
    init_expr = ParseExpr(kAllowConst, kConsumeCascades);
    if (init_expr->EvalConstExpr() != NULL) {
      init_expr =
          new LiteralNode(field.token_pos(), EvaluateConstExpr(init_expr));
    }
  }
  set_current_class(saved_class);
  set_library(saved_library);
  SetScript(saved_script, saved_token_pos);
  return init_expr;
}


void Parser::ParseInitializedInstanceFields(const Class& cls,
                 LocalVariable* receiver,
                 GrowableArray<Field*>* initialized_fields) {
  TRACE_PARSER("ParseInitializedInstanceFields");
  const Array& fields = Array::Handle(cls.fields());
  Field& f = Field::Handle();
  const intptr_t saved_pos = TokenPos();
  for (int i = 0; i < fields.Length(); i++) {
    f ^= fields.At(i);
    if (!f.is_static() && f.has_initializer()) {
      Field& field = Field::ZoneHandle();
      field ^= fields.At(i);
      if (field.is_final()) {
        // Final fields with initializer expression may not be initialized
        // again by constructors. Remember that this field is already
        // initialized.
        initialized_fields->Add(&field);
      }
      AstNode* init_expr = NULL;
      if (current_class().raw() != field.origin()) {
        init_expr = ParseExternalInitializedField(field);
      } else {
        SetPosition(field.token_pos());
        ASSERT(IsIdentifier());
        ConsumeToken();
        ExpectToken(Token::kASSIGN);
        if (field.is_const()) {
          init_expr = ParseConstExpr();
        } else {
          init_expr = ParseExpr(kAllowConst, kConsumeCascades);
          if (init_expr->EvalConstExpr() != NULL) {
            init_expr = new LiteralNode(field.token_pos(),
                                        EvaluateConstExpr(init_expr));
          }
        }
      }
      ASSERT(init_expr != NULL);
      AstNode* instance = new LoadLocalNode(field.token_pos(), receiver);
      EnsureExpressionTemp();
      AstNode* field_init =
          new StoreInstanceFieldNode(field.token_pos(),
                                     instance,
                                     field,
                                     init_expr);
      current_block_->statements->Add(field_init);
    }
  }
  SetPosition(saved_pos);
}


void Parser::CheckDuplicateFieldInit(intptr_t init_pos,
                                    GrowableArray<Field*>* initialized_fields,
                                    Field* field) {
  ASSERT(!field->is_static());
  for (int i = 0; i < initialized_fields->length(); i++) {
    Field* initialized_field = (*initialized_fields)[i];
    if (initialized_field->raw() == field->raw()) {
      ErrorMsg(init_pos,
               "duplicate initialization for field %s",
               String::Handle(field->name()).ToCString());
    }
  }
  initialized_fields->Add(field);
}


void Parser::ParseInitializers(const Class& cls,
                               LocalVariable* receiver,
                               GrowableArray<Field*>* initialized_fields) {
  TRACE_PARSER("ParseInitializers");
  bool super_init_seen = false;
  if (CurrentToken() == Token::kCOLON) {
    if ((LookaheadToken(1) == Token::kTHIS) &&
        ((LookaheadToken(2) == Token::kLPAREN) ||
        ((LookaheadToken(2) == Token::kPERIOD) &&
            (LookaheadToken(4) == Token::kLPAREN)))) {
      // Either we see this(...) or this.xxx(...) which is a
      // redirected constructor. We don't need to check whether
      // const fields are initialized. The other constructor will
      // guarantee that.
      ConsumeToken();  // Colon.
      ParseConstructorRedirection(cls, receiver);
      return;
    }
    do {
      ConsumeToken();  // Colon or comma.
      AstNode* init_statement;
      if (CurrentToken() == Token::kSUPER) {
        if (super_init_seen) {
          ErrorMsg("duplicate call to super constructor");
        }
        init_statement = ParseSuperInitializer(cls, receiver);
        super_init_seen = true;
      } else {
        init_statement = ParseInitializer(cls, receiver, initialized_fields);
      }
      current_block_->statements->Add(init_statement);
    } while (CurrentToken() == Token::kCOMMA);
  }
  if (!super_init_seen) {
    // Generate implicit super() if we haven't seen an explicit super call
    // or constructor redirection.
    GenerateSuperConstructorCall(cls, receiver, NULL);
  }
  CheckConstFieldsInitialized(cls);
}


void Parser::ParseConstructorRedirection(const Class& cls,
                                         LocalVariable* receiver) {
  TRACE_PARSER("ParseConstructorRedirection");
  ASSERT(CurrentToken() == Token::kTHIS);
  const intptr_t call_pos = TokenPos();
  ConsumeToken();
  String& ctor_name = String::Handle(cls.Name());

  ctor_name = String::Concat(ctor_name, Symbols::Dot());
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    ctor_name = String::Concat(ctor_name,
                               *ExpectIdentifier("constructor name expected"));
  }
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("parameter list expected");
  }

  ArgumentListNode* arguments = new ArgumentListNode(call_pos);
  // 'this' parameter is the first argument to constructor.
  AstNode* implicit_argument = new LoadLocalNode(call_pos, receiver);
  arguments->Add(implicit_argument);
  // Construction phase parameter is second argument.
  LocalVariable* phase_param = LookupPhaseParameter();
  ASSERT(phase_param != NULL);
  AstNode* phase_argument = new LoadLocalNode(call_pos, phase_param);
  arguments->Add(phase_argument);
  receiver->set_invisible(true);
  ParseActualParameters(arguments, kAllowConst);
  receiver->set_invisible(false);
  // Resolve the constructor.
  const Function& redirect_ctor = Function::ZoneHandle(
      cls.LookupConstructor(ctor_name));
  if (redirect_ctor.IsNull()) {
    ErrorMsg(call_pos, "constructor '%s' not found", ctor_name.ToCString());
  }
  String& error_message = String::Handle();
  if (!redirect_ctor.AreValidArguments(arguments->length(),
                                       arguments->names(),
                                       &error_message)) {
    ErrorMsg(call_pos,
             "invalid arguments passed to constructor '%s': %s",
             ctor_name.ToCString(),
             error_message.ToCString());
  }
  current_block_->statements->Add(
      new StaticCallNode(call_pos, redirect_ctor, arguments));
}


SequenceNode* Parser::MakeImplicitConstructor(const Function& func) {
  ASSERT(func.IsConstructor());
  ASSERT(func.Owner() == current_class().raw());
  const intptr_t ctor_pos = TokenPos();
  OpenFunctionBlock(func);

  LocalVariable* receiver = new LocalVariable(
      ctor_pos, Symbols::This(), *ReceiverType(current_class()));
  current_block_->scope->AddVariable(receiver);

  LocalVariable* phase_parameter = new LocalVariable(
      ctor_pos, Symbols::PhaseParameter(), Type::ZoneHandle(Type::SmiType()));
  current_block_->scope->AddVariable(phase_parameter);

  // Parse expressions of instance fields that have an explicit
  // initializer expression.
  // The receiver must not be visible to field initializer expressions.
  receiver->set_invisible(true);
  GrowableArray<Field*> initialized_fields;
  ParseInitializedInstanceFields(
      current_class(), receiver, &initialized_fields);
  receiver->set_invisible(false);

  // If the class of this implicit constructor is a mixin application class,
  // it is a forwarding constructor of the mixin. The forwarding
  // constructor initializes the instance fields that have initializer
  // expressions and then calls the respective super constructor with
  // the same name and number of parameters.
  ArgumentListNode* forwarding_args = NULL;
  if (current_class().mixin() != Type::null()) {
    // At this point we don't support forwarding constructors
    // that have optional parameters because we don't know the default
    // values of the optional parameters. We would have to compile the super
    // constructor to get the default values. Also, the spec is not clear
    // whether optional parameters are even allowed in this situation.
    // TODO(hausner): Remove this limitation if the language spec indeed
    // allows optional parameters.
    if (func.HasOptionalParameters()) {
      ErrorMsg(ctor_pos,
               "forwarding constructors must not have optional parameters");
    }

    // Prepare user-defined arguments to be forwarded to super call.
    // The first user-defined argument is at position 2.
    forwarding_args = new ArgumentListNode(ctor_pos);
    for (int i = 2; i < func.NumParameters(); i++) {
      LocalVariable* param = new LocalVariable(
          ctor_pos,
          String::ZoneHandle(func.ParameterNameAt(i)),
          Type::ZoneHandle(Type::DynamicType()));
      current_block_->scope->AddVariable(param);
      forwarding_args->Add(new LoadLocalNode(ctor_pos, param));
    }
  }

  GenerateSuperConstructorCall(current_class(), receiver, forwarding_args);
  CheckConstFieldsInitialized(current_class());

  // Empty constructor body.
  SequenceNode* statements = CloseBlock();
  return statements;
}


// Helper function to make the first num_variables variables in the
// given scope visible/invisible.
static void SetInvisible(LocalScope* scope, int num_variables, bool invisible) {
  ASSERT(num_variables <= scope->num_variables());
  for (int i = 0; i < num_variables; i++) {
    scope->VariableAt(i)->set_invisible(invisible);
  }
}


void Parser::CheckRecursiveInvocation() {
  const GrowableObjectArray& pending_functions =
      GrowableObjectArray::Handle(
          isolate()->object_store()->pending_functions());
  for (int i = 0; i < pending_functions.Length(); i++) {
    if (pending_functions.At(i) == current_function().raw()) {
      const String& fname =
          String::Handle(current_function().UserVisibleName());
      ErrorMsg("circular dependency for function %s", fname.ToCString());
    }
  }
  ASSERT(!unregister_pending_function_);
  pending_functions.Add(current_function());
  unregister_pending_function_ = true;
}


// Parser is at the opening parenthesis of the formal parameter declaration
// of function. Parse the formal parameters, initializers and code.
SequenceNode* Parser::ParseConstructor(const Function& func,
                                       Array& default_parameter_values) {
  TRACE_PARSER("ParseConstructor");
  ASSERT(func.IsConstructor());
  ASSERT(!func.IsFactory());
  ASSERT(!func.is_static());
  ASSERT(!func.IsLocalFunction());
  const Class& cls = Class::Handle(func.Owner());
  ASSERT(!cls.IsNull());

  CheckRecursiveInvocation();

  if (func.IsImplicitConstructor()) {
    // Special case: implicit constructor.
    // The parser adds an implicit default constructor when a class
    // does not have any explicit constructor or factory (see
    // Parser::AddImplicitConstructor).
    // There is no source text to parse. We just build the
    // sequence node by hand.
    return MakeImplicitConstructor(func);
  }

  OpenFunctionBlock(func);
  ParamList params;
  const bool allow_explicit_default_values = true;
  ASSERT(CurrentToken() == Token::kLPAREN);

  // Add implicit receiver parameter which is passed the allocated
  // but uninitialized instance to construct.
  ASSERT(current_class().raw() == func.Owner());
  params.AddReceiver(ReceiverType(current_class()), func.token_pos());

  // Add implicit parameter for construction phase.
  params.AddFinalParameter(
      TokenPos(),
      &Symbols::PhaseParameter(),
      &Type::ZoneHandle(Type::SmiType()));

  if (func.is_const()) {
    params.SetImplicitlyFinal();
  }
  ParseFormalParameterList(allow_explicit_default_values, &params);

  SetupDefaultsForOptionalParams(&params, default_parameter_values);
  ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
  ASSERT(func.NumParameters() == params.parameters->length());

  // Now populate function scope with the formal parameters.
  AddFormalParamsToScope(&params, current_block_->scope);

  // Initialize instance fields that have an explicit initializer expression.
  // The formal parameter names must not be visible to the instance
  // field initializer expressions, yet the parameters must be added to
  // the scope so the expressions use the correct offsets for 'this' when
  // storing values. We make the formal parameters temporarily invisible
  // while parsing the instance field initializer expressions.
  SetInvisible(current_block_->scope, params.parameters->length(), true);
  GrowableArray<Field*> initialized_fields;
  LocalVariable* receiver = current_block_->scope->VariableAt(0);
  OpenBlock();
  ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
  // Make the parameters (which are in the outer scope) visible again.
  SetInvisible(current_block_->scope->parent(),
               params.parameters->length(), false);

  // Turn formal field parameters into field initializers or report error
  // if the function is not a constructor.
  if (params.has_field_initializer) {
    for (int i = 0; i < params.parameters->length(); i++) {
      ParamDesc& param = (*params.parameters)[i];
      if (param.is_field_initializer) {
        const String& field_name = *param.name;
        Field& field = Field::ZoneHandle(cls.LookupInstanceField(field_name));
        if (field.IsNull()) {
          ErrorMsg(param.name_pos,
                   "unresolved reference to instance field '%s'",
                   field_name.ToCString());
        }
        CheckDuplicateFieldInit(param.name_pos, &initialized_fields, &field);
        AstNode* instance = new LoadLocalNode(param.name_pos, receiver);
        LocalVariable* p =
            current_block_->scope->LookupVariable(*param.name, false);
        ASSERT(p != NULL);
        // Initializing formals cannot be used in the explicit initializer
        // list, nor can they be used in the constructor body.
        // Thus, make the parameter invisible.
        p->set_invisible(true);
        AstNode* value = new LoadLocalNode(param.name_pos, p);
        EnsureExpressionTemp();
        AstNode* initializer = new StoreInstanceFieldNode(
            param.name_pos, instance, field, value);
        current_block_->statements->Add(initializer);
      }
    }
  }

  // Now parse the explicit initializer list or constructor redirection.
  ParseInitializers(cls, receiver, &initialized_fields);

  SequenceNode* init_statements = CloseBlock();
  if (init_statements->length() > 0) {
    // Generate guard around the initializer code.
    LocalVariable* phase_param = LookupPhaseParameter();
    AstNode* phase_value = new LoadLocalNode(TokenPos(), phase_param);
    AstNode* phase_check = new BinaryOpNode(
        TokenPos(), Token::kBIT_AND, phase_value,
        new LiteralNode(TokenPos(),
                        Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit))));
    AstNode* comparison =
        new ComparisonNode(TokenPos(), Token::kNE_STRICT,
                           phase_check,
                           new LiteralNode(TokenPos(),
                                           Smi::ZoneHandle(Smi::New(0))));
    AstNode* guarded_init_statements =
        new IfNode(TokenPos(), comparison, init_statements, NULL);
    current_block_->statements->Add(guarded_init_statements);
  }

  // Parsing of initializers done. Now we parse the constructor body
  // and add the implicit super call to the super constructor's body
  // if necessary.
  StaticCallNode* super_call = NULL;
  // Look for the super initializer call in the sequence of initializer
  // statements. If it exists and is not the last initializer statement,
  // we need to create an implicit super call to the super constructor's
  // body.
  // Thus, iterate over all but the last initializer to see whether
  // it's a super constructor call.
  for (int i = 0; i < init_statements->length() - 1; i++) {
    if (init_statements->NodeAt(i)->IsStaticCallNode()) {
      StaticCallNode* static_call =
      init_statements->NodeAt(i)->AsStaticCallNode();
      if (static_call->function().IsConstructor()) {
        super_call = static_call;
        break;
      }
    }
  }
  if (super_call != NULL) {
    // Generate an implicit call to the super constructor's body.
    // We need to patch the super _initializer_ call so that it
    // saves the evaluated actual arguments in temporary variables.
    // The temporary variables are necessary so that the argument
    // expressions are not evaluated twice.
    ArgumentListNode* ctor_args = super_call->arguments();
    // The super initializer call has at least 2 arguments: the
    // implicit receiver, and the hidden construction phase.
    ASSERT(ctor_args->length() >= 2);
    for (int i = 2; i < ctor_args->length(); i++) {
      AstNode* arg = ctor_args->NodeAt(i);
      if (!IsSimpleLocalOrLiteralNode(arg)) {
        LocalVariable* temp =
            CreateTempConstVariable(arg->token_pos(), "sca");
        AstNode* save_temp = new StoreLocalNode(arg->token_pos(), temp, arg);
        ctor_args->SetNodeAt(i, save_temp);
      }
    }
  }
  OpenBlock();  // Block to collect constructor body nodes.
  intptr_t body_pos = TokenPos();

  // Insert the implicit super call to the super constructor body.
  if (super_call != NULL) {
    ArgumentListNode* initializer_args = super_call->arguments();
    const Function& super_ctor = super_call->function();
    // Patch the initializer call so it only executes the super initializer.
    initializer_args->SetNodeAt(1,
        new LiteralNode(body_pos,
                        Smi::ZoneHandle(Smi::New(Function::kCtorPhaseInit))));

    ArgumentListNode* super_call_args = new ArgumentListNode(body_pos);
    // First argument is the receiver.
    super_call_args->Add(new LoadLocalNode(body_pos, receiver));
    // Second argument is the construction phase argument.
    AstNode* phase_parameter =
        new LiteralNode(body_pos,
                        Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody)));
    super_call_args->Add(phase_parameter);
    super_call_args->set_names(initializer_args->names());
    for (int i = 2; i < initializer_args->length(); i++) {
      AstNode* arg = initializer_args->NodeAt(i);
      if (arg->IsLiteralNode()) {
        LiteralNode* lit = arg->AsLiteralNode();
        super_call_args->Add(new LiteralNode(body_pos, lit->literal()));
      } else {
        ASSERT(arg->IsLoadLocalNode() || arg->IsStoreLocalNode());
        if (arg->IsLoadLocalNode()) {
          const LocalVariable& temp = arg->AsLoadLocalNode()->local();
          super_call_args->Add(new LoadLocalNode(body_pos, &temp));
        } else if (arg->IsStoreLocalNode()) {
          const LocalVariable& temp = arg->AsStoreLocalNode()->local();
          super_call_args->Add(new LoadLocalNode(body_pos, &temp));
        }
      }
    }
    ASSERT(super_ctor.AreValidArguments(super_call_args->length(),
                                        super_call_args->names(),
                                        NULL));
    current_block_->statements->Add(
        new StaticCallNode(body_pos, super_ctor, super_call_args));
  }

  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kARROW) {
    ErrorMsg("constructors may not return a value");
  } else if (IsLiteral("native")) {
    ErrorMsg("native constructors not supported");
  } else if (CurrentToken() == Token::kSEMICOLON) {
    // Some constructors have no function body.
    ConsumeToken();
  } else {
    UnexpectedToken();
  }

  SequenceNode* ctor_block = CloseBlock();
  if (ctor_block->length() > 0) {
    // Generate guard around the constructor body code.
    LocalVariable* phase_param = LookupPhaseParameter();
    AstNode* phase_value = new LoadLocalNode(body_pos, phase_param);
    AstNode* phase_check =
        new BinaryOpNode(body_pos, Token::kBIT_AND,
            phase_value,
            new LiteralNode(body_pos,
                Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))));
    AstNode* comparison =
       new ComparisonNode(body_pos, Token::kNE_STRICT,
                         phase_check,
                         new LiteralNode(body_pos,
                                         Smi::ZoneHandle(Smi::New(0))));
    AstNode* guarded_block_statements =
        new IfNode(body_pos, comparison, ctor_block, NULL);
    current_block_->statements->Add(guarded_block_statements);
  }

  SequenceNode* statements = CloseBlock();
  return statements;
}


// Parser is at the opening parenthesis of the formal parameter
// declaration of the function or constructor.
// Parse the formal parameters and code.
SequenceNode* Parser::ParseFunc(const Function& func,
                                Array& default_parameter_values) {
  TRACE_PARSER("ParseFunc");
  Function& saved_innermost_function =
      Function::Handle(innermost_function().raw());
  innermost_function_ = func.raw();

  // Save current try index. Try index starts at zero for each function.
  intptr_t saved_try_index = last_used_try_index_;
  last_used_try_index_ = 0;

  // TODO(12455) : Need better validation mechanism.

  if (func.IsConstructor()) {
    SequenceNode* statements = ParseConstructor(func, default_parameter_values);
    innermost_function_ = saved_innermost_function.raw();
    last_used_try_index_ = saved_try_index;
    return statements;
  }

  ASSERT(!func.IsConstructor());
  OpenFunctionBlock(func);  // Build local scope for function.

  ParamList params;
  // An instance closure function may capture and access the receiver, but via
  // the context and not via the first formal parameter.
  if (func.IsClosureFunction()) {
    // The first parameter of a closure function is the closure object.
    ASSERT(!func.is_const());  // Closure functions cannot be const.
    params.AddFinalParameter(
        TokenPos(),
        &Symbols::ClosureParameter(),
        &Type::ZoneHandle(Type::DynamicType()));
  } else if (!func.is_static()) {
    // Static functions do not have a receiver.
    ASSERT(current_class().raw() == func.Owner());
    params.AddReceiver(ReceiverType(current_class()), func.token_pos());
  } else if (func.IsFactory()) {
    // The first parameter of a factory is the AbstractTypeArguments vector of
    // the type of the instance to be allocated.
    params.AddFinalParameter(
        TokenPos(),
        &Symbols::TypeArgumentsParameter(),
        &Type::ZoneHandle(Type::DynamicType()));
  }
  ASSERT((CurrentToken() == Token::kLPAREN) || func.IsGetterFunction());
  const bool allow_explicit_default_values = true;
  if (!func.IsGetterFunction()) {
    ParseFormalParameterList(allow_explicit_default_values, &params);
  } else {
    // TODO(hausner): Remove this once we no longer support the old
    // getter syntax with explicit empty parameter list.
    if (CurrentToken() == Token::kLPAREN) {
      ConsumeToken();
      ExpectToken(Token::kRPAREN);
    }
  }

  // The number of parameters and their type are not yet set in local functions,
  // since they are not 'top-level' parsed.
  if (func.IsLocalFunction()) {
    AddFormalParamsToFunction(&params, func);
  }
  SetupDefaultsForOptionalParams(&params, default_parameter_values);
  ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
  ASSERT(func.NumParameters() == params.parameters->length());

  // Check whether the function has any field initializer formal parameters,
  // which are not allowed in non-constructor functions.
  if (params.has_field_initializer) {
    for (int i = 0; i < params.parameters->length(); i++) {
      ParamDesc& param = (*params.parameters)[i];
      if (param.is_field_initializer) {
        ErrorMsg(param.name_pos,
                 "field initializer only allowed in constructors");
      }
    }
  }
  // Populate function scope with the formal parameters.
  AddFormalParamsToScope(&params, current_block_->scope);

  if (FLAG_enable_type_checks &&
      (current_block_->scope->function_level() > 0)) {
    // We are parsing, but not compiling, a local function.
    // The instantiator may be required at run time for generic type checks.
    if (IsInstantiatorRequired()) {
      // Make sure that the receiver of the enclosing instance function
      // (or implicit first parameter of an enclosing factory) is marked as
      // captured if type checks are enabled, because they may access it to
      // instantiate types.
      CaptureInstantiator();
    }
  }

  OpenBlock();  // Open a nested scope for the outermost function block.
  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    const intptr_t expr_pos = TokenPos();
    AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
    ASSERT(expr != NULL);
    current_block_->statements->Add(new ReturnNode(expr_pos, expr));
  } else if (IsLiteral("native")) {
    ParseNativeFunctionBlock(&params, func);
  } else if (func.is_external()) {
    // Body of an external method contains a single throw.
    const String& function_name = String::ZoneHandle(func.name());
    // TODO(regis): For an instance function, pass the receiver to
    // NoSuchMethodError.
    current_block_->statements->Add(
        ThrowNoSuchMethodError(TokenPos(),
                               current_class(),
                               function_name,
                               func.is_static() ?
                                   InvocationMirror::kStatic :
                                   InvocationMirror::kDynamic,
                               InvocationMirror::kMethod));
  } else {
    UnexpectedToken();
  }
  SequenceNode* body = CloseBlock();
  current_block_->statements->Add(body);
  innermost_function_ = saved_innermost_function.raw();
  last_used_try_index_ = saved_try_index;
  return CloseBlock();
}


void Parser::SkipIf(Token::Kind token) {
  if (CurrentToken() == token) {
    ConsumeToken();
  }
}


// Skips tokens up to matching closing parenthesis.
void Parser::SkipToMatchingParenthesis() {
  ASSERT(CurrentToken() == Token::kLPAREN);
  int level = 0;
  do {
    if (CurrentToken() == Token::kLPAREN) {
      level++;
    } else if (CurrentToken() == Token::kRPAREN) {
      level--;
    }
    ConsumeToken();
  } while ((level > 0) && (CurrentToken() != Token::kEOS));
}


void Parser::SkipInitializers() {
  ASSERT(CurrentToken() == Token::kCOLON);
  do {
    ConsumeToken();  // Colon or comma.
    if (CurrentToken() == Token::kSUPER) {
      ConsumeToken();
      if (CurrentToken() == Token::kPERIOD) {
        ConsumeToken();
        ExpectIdentifier("identifier expected");
      }
      if (CurrentToken() != Token::kLPAREN) {
        ErrorMsg("'(' expected");
      }
      SkipToMatchingParenthesis();
    } else {
      SkipIf(Token::kTHIS);
      SkipIf(Token::kPERIOD);
      ExpectIdentifier("identifier expected");
      ExpectToken(Token::kASSIGN);
      SetAllowFunctionLiterals(false);
      SkipExpr();
      SetAllowFunctionLiterals(true);
    }
  } while (CurrentToken() == Token::kCOMMA);
}


void Parser::ParseQualIdent(QualIdent* qual_ident) {
  TRACE_PARSER("ParseQualIdent");
  ASSERT(IsIdentifier());
  ASSERT(!current_class().IsNull());
  qual_ident->ident_pos = TokenPos();
  qual_ident->ident = CurrentLiteral();
  qual_ident->lib_prefix = NULL;
  ConsumeToken();
  if (CurrentToken() == Token::kPERIOD) {
    // An identifier cannot be resolved in a local scope when top level parsing.
    if (is_top_level_ ||
        !ResolveIdentInLocalScope(qual_ident->ident_pos,
                                  *(qual_ident->ident),
                                  NULL)) {
      LibraryPrefix& lib_prefix = LibraryPrefix::ZoneHandle();
      if (current_class().mixin() == Type::null()) {
        lib_prefix = current_class().LookupLibraryPrefix(*(qual_ident->ident));
      } else {
        // TODO(hausner): Should we resolve the prefix via the library scope
        // rather than via the class?
        Class& cls = Class::Handle(parsed_function()->function().origin());
        lib_prefix = cls.LookupLibraryPrefix(*(qual_ident->ident));
      }
      if (!lib_prefix.IsNull()) {
        // We have a library prefix qualified identifier, unless the prefix is
        // shadowed by a type parameter in scope.
        if (current_class().IsNull() ||
            (current_class().LookupTypeParameter(*(qual_ident->ident)) ==
             TypeParameter::null())) {
          ConsumeToken();  // Consume the kPERIOD token.
          qual_ident->lib_prefix = &lib_prefix;
          qual_ident->ident_pos = TokenPos();
          qual_ident->ident =
              ExpectIdentifier("identifier expected after '.'");
        }
      }
    }
  }
}


void Parser::ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method) {
  TRACE_PARSER("ParseMethodOrConstructor");
  ASSERT(CurrentToken() == Token::kLPAREN || method->IsGetter());
  ASSERT(method->type != NULL);
  ASSERT(method->name_pos > 0);
  ASSERT(current_member_ == method);

  if (method->has_var) {
    ErrorMsg(method->name_pos, "keyword var not allowed for methods");
  }
  if (method->has_final) {
    ErrorMsg(method->name_pos, "'final' not allowed for methods");
  }
  if (method->has_abstract && method->has_static) {
    ErrorMsg(method->name_pos,
             "static method '%s' cannot be abstract",
             method->name->ToCString());
  }
  if (method->has_const && !method->IsFactoryOrConstructor()) {
    ErrorMsg(method->name_pos, "'const' not allowed for methods");
  }
  if (method->has_abstract && method->IsFactoryOrConstructor()) {
    ErrorMsg(method->name_pos, "constructor cannot be abstract");
  }
  if (method->has_const && method->IsConstructor()) {
    current_class().set_is_const();
  }

  // Parse the formal parameters.
  const bool are_implicitly_final = method->has_const;
  const bool allow_explicit_default_values = true;
  const intptr_t formal_param_pos = TokenPos();
  method->params.Clear();
  // Static functions do not have a receiver.
  // The first parameter of a factory is the AbstractTypeArguments vector of
  // the type of the instance to be allocated.
  if (!method->has_static || method->IsConstructor()) {
    method->params.AddReceiver(ReceiverType(current_class()), formal_param_pos);
  } else if (method->IsFactory()) {
    method->params.AddFinalParameter(
        formal_param_pos,
        &Symbols::TypeArgumentsParameter(),
        &Type::ZoneHandle(Type::DynamicType()));
  }
  // Constructors have an implicit parameter for the construction phase.
  if (method->IsConstructor()) {
    method->params.AddFinalParameter(
        TokenPos(),
        &Symbols::PhaseParameter(),
        &Type::ZoneHandle(Type::SmiType()));
  }
  if (are_implicitly_final) {
    method->params.SetImplicitlyFinal();
  }
  if (!method->IsGetter()) {
    ParseFormalParameterList(allow_explicit_default_values, &method->params);
  }

  // Now that we know the parameter list, we can distinguish between the
  // unary and binary operator -.
  if (method->has_operator) {
    if ((method->operator_token == Token::kSUB) &&
       (method->params.num_fixed_parameters == 1)) {
      // Patch up name for unary operator - so it does not clash with the
      // name for binary operator -.
      method->operator_token = Token::kNEGATE;
      *method->name = Symbols::New(Token::Str(Token::kNEGATE));
    }
    CheckOperatorArity(*method);
  }

  if (members->FunctionNameExists(*method->name, method->kind)) {
    ErrorMsg(method->name_pos,
             "field or method '%s' already defined", method->name->ToCString());
  }

  // Mangle the name for getter and setter functions and check function
  // arity.
  if (method->IsGetter() || method->IsSetter()) {
    int expected_num_parameters = 0;
    if (method->IsGetter()) {
      expected_num_parameters = (method->has_static) ? 0 : 1;
      method->name = &String::ZoneHandle(Field::GetterSymbol(*method->name));
    } else {
      ASSERT(method->IsSetter());
      expected_num_parameters = (method->has_static) ? 1 : 2;
      method->name = &String::ZoneHandle(Field::SetterSymbol(*method->name));
    }
    if ((method->params.num_fixed_parameters != expected_num_parameters) ||
        (method->params.num_optional_parameters != 0)) {
      ErrorMsg(method->name_pos, "illegal %s parameters",
               method->IsGetter() ? "getter" : "setter");
    }
  }

  // Parse redirecting factory constructor.
  Type& redirection_type = Type::Handle();
  String& redirection_identifier = String::Handle();
  if (method->IsFactory() && (CurrentToken() == Token::kASSIGN)) {
    ConsumeToken();
    const intptr_t type_pos = TokenPos();
    const AbstractType& type = AbstractType::Handle(
        ParseType(ClassFinalizer::kResolveTypeParameters));
    if (!type.IsMalformed() && type.IsTypeParameter()) {
      // Replace the type with a malformed type and compile a throw when called.
      redirection_type = ClassFinalizer::NewFinalizedMalformedType(
          Error::Handle(),  // No previous error.
          current_class(),
          type_pos,
          "factory '%s' may not redirect to type parameter '%s'",
          method->name->ToCString(),
          String::Handle(type.UserVisibleName()).ToCString());
    } else {
      redirection_type ^= type.raw();
    }
    if (CurrentToken() == Token::kPERIOD) {
      // Named constructor or factory.
      ConsumeToken();
      redirection_identifier = ExpectIdentifier("identifier expected")->raw();
    }
  } else if (CurrentToken() == Token::kCOLON) {
    // Parse initializers.
    if (!method->IsConstructor()) {
      ErrorMsg("initializers only allowed on constructors");
    }
    if ((LookaheadToken(1) == Token::kTHIS) &&
        ((LookaheadToken(2) == Token::kLPAREN) ||
         LookaheadToken(4) == Token::kLPAREN)) {
      // Redirected constructor: either this(...) or this.xxx(...).
      if (method->params.has_field_initializer) {
        // Constructors that redirect to another constructor must not
        // initialize any fields using field initializer parameters.
        ErrorMsg(formal_param_pos, "Redirecting constructor "
                 "may not use field initializer parameters");
      }
      ConsumeToken();  // Colon.
      ExpectToken(Token::kTHIS);
      String& redir_name = String::ZoneHandle(
          String::Concat(members->class_name(), Symbols::Dot()));
      if (CurrentToken() == Token::kPERIOD) {
        ConsumeToken();
        redir_name = String::Concat(redir_name,
            *ExpectIdentifier("constructor name expected"));
      }
      method->redirect_name = &redir_name;
      if (CurrentToken() != Token::kLPAREN) {
        ErrorMsg("'(' expected");
      }
      SkipToMatchingParenthesis();
    } else {
      SkipInitializers();
    }
  }

  // Only constructors can redirect to another method.
  ASSERT((method->redirect_name == NULL) || method->IsConstructor());

  intptr_t method_end_pos = TokenPos();
  if ((CurrentToken() == Token::kLBRACE) ||
      (CurrentToken() == Token::kARROW)) {
    if (method->has_abstract) {
      ErrorMsg(method->name_pos,
               "abstract method '%s' may not have a function body",
               method->name->ToCString());
    } else if (method->has_external) {
      ErrorMsg(method->name_pos,
               "external method '%s' may not have a function body",
               method->name->ToCString());
    } else if (method->IsFactoryOrConstructor() && method->has_const) {
      ErrorMsg(method->name_pos,
               "const constructor or factory '%s' may not have a function body",
               method->name->ToCString());
    }
    if (method->redirect_name != NULL) {
      ErrorMsg(method->name_pos,
               "Constructor with redirection may not have a function body");
    }
    if (CurrentToken() == Token::kLBRACE) {
      SkipBlock();
    } else {
      ConsumeToken();
      SkipExpr();
      ExpectSemicolon();
    }
    method_end_pos = TokenPos() - 1;
  } else if (IsLiteral("native")) {
    if (method->has_abstract) {
      ErrorMsg(method->name_pos,
               "abstract method '%s' may not have a function body",
               method->name->ToCString());
    } else if (method->IsFactoryOrConstructor() && method->has_const) {
      ErrorMsg(method->name_pos,
               "const constructor or factory '%s' may not be native",
               method->name->ToCString());
    }
    if (method->redirect_name != NULL) {
      ErrorMsg(method->name_pos,
               "Constructor with redirection may not have a function body");
    }
    ParseNativeDeclaration();
  } else {
    // We haven't found a method body. Issue error if one is required.
    const bool must_have_body =
        method->has_static &&
        !method->has_external &&
        redirection_type.IsNull();
    if (must_have_body) {
      ErrorMsg(method->name_pos,
               "function body expected for method '%s'",
               method->name->ToCString());
    }

    if (CurrentToken() == Token::kSEMICOLON) {
      ConsumeToken();
      if (!method->has_static &&
          !method->has_external &&
          !method->IsConstructor()) {
          // Methods, getters and setters without a body are
          // implicitly abstract.
        method->has_abstract = true;
      }
    } else {
      // Signature is not followed by semicolon or body. Issue an
      // appropriate error.
      const bool must_have_semicolon =
          (method->redirect_name != NULL) ||
          (method->IsConstructor() && method->has_const) ||
          method->has_external;
      if (must_have_semicolon) {
        ExpectSemicolon();
      } else {
        ErrorMsg(method->name_pos,
                 "function body or semicolon expected for method '%s'",
                 method->name->ToCString());
      }
    }
  }

  RawFunction::Kind function_kind;
  if (method->IsFactoryOrConstructor()) {
    function_kind = RawFunction::kConstructor;
  } else if (method->IsGetter()) {
    function_kind = RawFunction::kGetterFunction;
  } else if (method->IsSetter()) {
    function_kind = RawFunction::kSetterFunction;
  } else {
    function_kind = RawFunction::kRegularFunction;
  }
  Function& func = Function::Handle(
      Function::New(*method->name,
                    function_kind,
                    method->has_static,
                    method->has_const,
                    method->has_abstract,
                    method->has_external,
                    current_class(),
                    method->decl_begin_pos));
  func.set_result_type(*method->type);
  func.set_end_token_pos(method_end_pos);
  if (method->metadata_pos > 0) {
    library_.AddFunctionMetadata(func, method->metadata_pos);
  }

  // If this method is a redirecting factory, set the redirection information.
  if (!redirection_type.IsNull()) {
    ASSERT(func.IsFactory());
    func.SetRedirectionType(redirection_type);
    if (!redirection_identifier.IsNull()) {
      func.SetRedirectionIdentifier(redirection_identifier);
    }
  }

  // No need to resolve parameter types yet, or add parameters to local scope.
  ASSERT(is_top_level_);
  AddFormalParamsToFunction(&method->params, func);
  members->AddFunction(func);
}


void Parser::ParseFieldDefinition(ClassDesc* members, MemberDesc* field) {
  TRACE_PARSER("ParseFieldDefinition");
  // The parser has read the first field name and is now at the token
  // after the field name.
  ASSERT(CurrentToken() == Token::kSEMICOLON ||
         CurrentToken() == Token::kCOMMA ||
         CurrentToken() == Token::kASSIGN);
  ASSERT(field->type != NULL);
  ASSERT(field->name_pos > 0);
  ASSERT(current_member_ == field);
  // All const fields are also final.
  ASSERT(!field->has_const || field->has_final);

  if (field->has_abstract) {
    ErrorMsg("keyword 'abstract' not allowed in field declaration");
  }
  if (field->has_external) {
    ErrorMsg("keyword 'external' not allowed in field declaration");
  }
  if (field->has_factory) {
    ErrorMsg("keyword 'factory' not allowed in field declaration");
  }
  if (members->FieldNameExists(*field->name, !field->has_final)) {
    ErrorMsg(field->name_pos,
             "field or method '%s' already defined", field->name->ToCString());
  }
  Function& getter = Function::Handle();
  Function& setter = Function::Handle();
  Field& class_field = Field::Handle();
  Instance& init_value = Instance::Handle();
  while (true) {
    bool has_initializer = CurrentToken() == Token::kASSIGN;
    bool has_simple_literal = false;
    if (has_initializer) {
      ConsumeToken();
      init_value = Object::sentinel().raw();
      // For static const fields and static final non-const fields, the
      // initialization expression will be parsed through the
      // kImplicitStaticFinalGetter method invocation/compilation.
      // For instance fields, the expression is parsed when a constructor
      // is compiled.
      // For static const fields and static final non-const fields with very
      // simple initializer expressions (e.g. a literal number or string), we
      // optimize away the kImplicitStaticFinalGetter and initialize the field
      // here. However, the class finalizer will check the value type for
      // assignability once the declared field type can be resolved. If the
      // value is not assignable (assuming checked mode and disregarding actual
      // mode), the field value is reset and a kImplicitStaticFinalGetter is
      // created at finalization time.

      if (field->has_static && (field->has_const || field->has_final) &&
          (LookaheadToken(1) == Token::kSEMICOLON)) {
        has_simple_literal = IsSimpleLiteral(*field->type, &init_value);
      }
      SkipExpr();
    } else {
      if (field->has_const || (field->has_static && field->has_final)) {
        ErrorMsg(field->name_pos,
                 "%s%s field '%s' must have an initializer expression",
                 field->has_static ? "static " : "",
                 field->has_const ? "const" : "final",
                 field->name->ToCString());
      }
    }

    // Create the field object.
    class_field = Field::New(*field->name,
                             field->has_static,
                             field->has_final,
                             field->has_const,
                             current_class(),
                             field->name_pos);
    class_field.set_type(*field->type);
    class_field.set_has_initializer(has_initializer);
    members->AddField(class_field);
    if (field->metadata_pos >= 0) {
      library_.AddFieldMetadata(class_field, field->metadata_pos);
    }

    // For static final fields (this includes static const fields), set value to
    // "uninitialized" and create a kFinalImplicitGetter getter method.
    if (field->has_static && has_initializer) {
      class_field.set_value(init_value);
      if (!has_simple_literal) {
        String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
        getter = Function::New(getter_name,
                               RawFunction::kImplicitStaticFinalGetter,
                               field->has_static,
                               field->has_const,
                               /* is_abstract = */ false,
                               /* is_external = */ false,
                               current_class(),
                               field->name_pos);
        getter.set_result_type(*field->type);
        members->AddFunction(getter);
      }
    }

    // For instance fields, we create implicit getter and setter methods.
    if (!field->has_static) {
      String& getter_name = String::Handle(Field::GetterSymbol(*field->name));
      getter = Function::New(getter_name, RawFunction::kImplicitGetter,
                             field->has_static,
                             field->has_final,
                             /* is_abstract = */ false,
                             /* is_external = */ false,
                             current_class(),
                             field->name_pos);
      ParamList params;
      ASSERT(current_class().raw() == getter.Owner());
      params.AddReceiver(ReceiverType(current_class()), field->name_pos);
      getter.set_result_type(*field->type);
      AddFormalParamsToFunction(&params, getter);
      members->AddFunction(getter);
      if (!field->has_final) {
        // Build a setter accessor for non-const fields.
        String& setter_name = String::Handle(Field::SetterSymbol(*field->name));
        setter = Function::New(setter_name, RawFunction::kImplicitSetter,
                               field->has_static,
                               field->has_final,
                               /* is_abstract = */ false,
                               /* is_external = */ false,
                               current_class(),
                               field->name_pos);
        ParamList params;
        ASSERT(current_class().raw() == setter.Owner());
        params.AddReceiver(ReceiverType(current_class()), field->name_pos);
        params.AddFinalParameter(TokenPos(),
                                 &Symbols::Value(),
                                 field->type);
        setter.set_result_type(Type::Handle(Type::VoidType()));
        AddFormalParamsToFunction(&params, setter);
        members->AddFunction(setter);
      }
    }

    if (CurrentToken() != Token::kCOMMA) {
      break;
    }
    ConsumeToken();
    field->name_pos = this->TokenPos();
    field->name = ExpectIdentifier("field name expected");
  }
  ExpectSemicolon();
}


void Parser::CheckOperatorArity(const MemberDesc& member) {
  intptr_t expected_num_parameters;  // Includes receiver.
  Token::Kind op = member.operator_token;
  if (op == Token::kASSIGN_INDEX) {
    expected_num_parameters = 3;
  } else if ((op == Token::kBIT_NOT) || (op == Token::kNEGATE)) {
    expected_num_parameters = 1;
  } else {
    expected_num_parameters = 2;
  }
  if ((member.params.num_optional_parameters > 0) ||
      member.params.has_optional_positional_parameters ||
      member.params.has_optional_named_parameters ||
      (member.params.num_fixed_parameters != expected_num_parameters)) {
    // Subtract receiver when reporting number of expected arguments.
    ErrorMsg(member.name_pos, "operator %s expects %" Pd " argument(s)",
        member.name->ToCString(), (expected_num_parameters - 1));
  }
}


void Parser::ParseClassMemberDefinition(ClassDesc* members,
                                        intptr_t metadata_pos) {
  TRACE_PARSER("ParseClassMemberDefinition");
  MemberDesc member;
  current_member_ = &member;
  member.metadata_pos = metadata_pos;
  member.decl_begin_pos = TokenPos();
  if ((CurrentToken() == Token::kEXTERNAL) &&
      (LookaheadToken(1) != Token::kLPAREN)) {
    ConsumeToken();
    member.has_external = true;
  }
  if ((CurrentToken() == Token::kSTATIC) &&
      (LookaheadToken(1) != Token::kLPAREN)) {
    ConsumeToken();
    member.has_static = true;
  }
  if (CurrentToken() == Token::kCONST) {
    ConsumeToken();
    member.has_const = true;
  } else if (CurrentToken() == Token::kFINAL) {
    ConsumeToken();
    member.has_final = true;
  }
  if (CurrentToken() == Token::kVAR) {
    if (member.has_const) {
      ErrorMsg("identifier expected after 'const'");
    }
    if (member.has_final) {
      ErrorMsg("identifier expected after 'final'");
    }
    ConsumeToken();
    member.has_var = true;
    // The member type is the 'dynamic' type.
    member.type = &Type::ZoneHandle(Type::DynamicType());
  } else if (CurrentToken() == Token::kFACTORY) {
    ConsumeToken();
    if (member.has_static) {
      ErrorMsg("factory method cannot be explicitly marked static");
    }
    member.has_factory = true;
    member.has_static = true;
    // The result type depends on the name of the factory method.
  }
  // Optionally parse a type.
  if (CurrentToken() == Token::kVOID) {
    if (member.has_var || member.has_factory) {
      ErrorMsg("void not expected");
    }
    ConsumeToken();
    ASSERT(member.type == NULL);
    member.type = &Type::ZoneHandle(Type::VoidType());
  } else if (CurrentToken() == Token::kIDENT) {
    // This is either a type name or the name of a method/constructor/field.
    if ((member.type == NULL) && !member.has_factory) {
      // We have not seen a member type yet, so we check if the next
      // identifier could represent a type before parsing it.
      Token::Kind follower = LookaheadToken(1);
      // We have an identifier followed by a 'follower' token.
      // We either parse a type or assume that no type is specified.
      if ((follower == Token::kLT) ||  // Parameterized type.
          (follower == Token::kGET) ||  // Getter following a type.
          (follower == Token::kSET) ||  // Setter following a type.
          (follower == Token::kOPERATOR) ||  // Operator following a type.
          (Token::IsIdentifier(follower)) ||  // Member name following a type.
          ((follower == Token::kPERIOD) &&    // Qualified class name of type,
           (LookaheadToken(3) != Token::kLPAREN))) {  // but not a named constr.
        ASSERT(is_top_level_);
        // The declared type of fields is never ignored, even in unchecked mode,
        // because getters and setters could be closurized at some time (not
        // supported yet).
        member.type = &AbstractType::ZoneHandle(
            ParseType(ClassFinalizer::kResolveTypeParameters));
      }
    }
  }

  // Optionally parse a (possibly named) constructor name or factory.
  if (IsIdentifier() &&
      (CurrentLiteral()->Equals(members->class_name()) || member.has_factory)) {
    member.name_pos = TokenPos();
    member.name = CurrentLiteral();  // Unqualified identifier.
    ConsumeToken();
    if (member.has_factory) {
      // The factory name may be qualified, but the first identifier must match
      // the name of the immediately enclosing class.
      if (!member.name->Equals(members->class_name())) {
        ErrorMsg(member.name_pos, "factory name must be '%s'",
                 members->class_name().ToCString());
      }
    } else if (member.has_static) {
      ErrorMsg(member.name_pos, "constructor cannot be static");
    }
    if (member.type != NULL) {
      ErrorMsg(member.name_pos, "constructor must not specify return type");
    }
    // Do not bypass class resolution by using current_class() directly, since
    // it may be a patch class.
    const Object& result_type_class = Object::Handle(
        UnresolvedClass::New(LibraryPrefix::Handle(),
                             *member.name,
                             member.name_pos));
    // The type arguments of the result type are the type parameters of the
    // current class. Note that in the case of a patch class, they are copied
    // from the class being patched.
    member.type = &Type::ZoneHandle(Type::New(
        result_type_class,
        TypeArguments::Handle(current_class().type_parameters()),
        member.name_pos));

    // We must be dealing with a constructor or named constructor.
    member.kind = RawFunction::kConstructor;
    *member.name = String::Concat(*member.name, Symbols::Dot());
    if (CurrentToken() == Token::kPERIOD) {
      // Named constructor.
      ConsumeToken();
      member.constructor_name = ExpectIdentifier("identifier expected");
      *member.name = String::Concat(*member.name, *member.constructor_name);
    }
    // Ensure that names are symbols.
    *member.name = Symbols::New(*member.name);

    if (CurrentToken() != Token::kLPAREN) {
      ErrorMsg("left parenthesis expected");
    }
  } else if ((CurrentToken() == Token::kGET) && !member.has_var &&
             (LookaheadToken(1) != Token::kLPAREN) &&
             (LookaheadToken(1) != Token::kASSIGN) &&
             (LookaheadToken(1) != Token::kCOMMA)  &&
             (LookaheadToken(1) != Token::kSEMICOLON)) {
    ConsumeToken();
    member.kind = RawFunction::kGetterFunction;
    member.name_pos = this->TokenPos();
    member.name = ExpectIdentifier("identifier expected");
    // If the result type was not specified, it will be set to DynamicType.
  } else if ((CurrentToken() == Token::kSET) && !member.has_var &&
             (LookaheadToken(1) != Token::kLPAREN) &&
             (LookaheadToken(1) != Token::kASSIGN) &&
             (LookaheadToken(1) != Token::kCOMMA)  &&
             (LookaheadToken(1) != Token::kSEMICOLON))  {
    ConsumeToken();
    member.kind = RawFunction::kSetterFunction;
    member.name_pos = this->TokenPos();
    member.name = ExpectIdentifier("identifier expected");
    if (CurrentToken() != Token::kLPAREN) {
      ErrorMsg("'(' expected");
    }
    // The grammar allows a return type, so member.type is not always NULL here.
    // If no return type is specified, the return type of the setter is dynamic.
    if (member.type == NULL) {
      member.type = &Type::ZoneHandle(Type::DynamicType());
    }
  } else if ((CurrentToken() == Token::kOPERATOR) && !member.has_var &&
             (LookaheadToken(1) != Token::kLPAREN) &&
             (LookaheadToken(1) != Token::kASSIGN) &&
             (LookaheadToken(1) != Token::kCOMMA)  &&
             (LookaheadToken(1) != Token::kSEMICOLON)) {
    ConsumeToken();
    if (!Token::CanBeOverloaded(CurrentToken())) {
      ErrorMsg("invalid operator overloading");
    }
    if (member.has_static) {
      ErrorMsg("operator overloading functions cannot be static");
    }
    member.operator_token = CurrentToken();
    member.has_operator = true;
    member.kind = RawFunction::kRegularFunction;
    member.name_pos = this->TokenPos();
    member.name =
        &String::ZoneHandle(Symbols::New(Token::Str(member.operator_token)));
    ConsumeToken();
  } else if (IsIdentifier()) {
    member.name = CurrentLiteral();
    member.name_pos = TokenPos();
    ConsumeToken();
  } else {
    ErrorMsg("identifier expected");
  }

  ASSERT(member.name != NULL);
  if (CurrentToken() == Token::kLPAREN || member.IsGetter()) {
    // Constructor or method.
    if (member.type == NULL) {
      member.type = &Type::ZoneHandle(Type::DynamicType());
    }
    ASSERT(member.IsFactory() == member.has_factory);
    ParseMethodOrConstructor(members, &member);
  } else if (CurrentToken() ==  Token::kSEMICOLON ||
             CurrentToken() == Token::kCOMMA ||
             CurrentToken() == Token::kASSIGN) {
    // Field definition.
    if (member.has_const) {
      // const fields are implicitly final.
      member.has_final = true;
    }
    if (member.type == NULL) {
      if (member.has_final) {
        member.type = &Type::ZoneHandle(Type::DynamicType());
      } else {
        ErrorMsg("missing 'var', 'final', 'const' or type"
                 " in field declaration");
      }
    }
    ParseFieldDefinition(members, &member);
  } else {
    UnexpectedToken();
  }
  current_member_ = NULL;
  members->AddMember(member);
}


void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes,
                                   intptr_t metadata_pos) {
  TRACE_PARSER("ParseClassDeclaration");
  bool is_patch = false;
  bool is_abstract = false;
  if (is_patch_source() &&
      (CurrentToken() == Token::kIDENT) &&
      CurrentLiteral()->Equals("patch")) {
    ConsumeToken();
    is_patch = true;
  } else if (CurrentToken() == Token::kABSTRACT) {
    is_abstract = true;
    ConsumeToken();
  }
  ExpectToken(Token::kCLASS);
  const intptr_t classname_pos = TokenPos();
  String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected");
  if (FLAG_trace_parser) {
    OS::Print("TopLevel parsing class '%s'\n", class_name.ToCString());
  }
  Class& cls = Class::Handle();
  TypeArguments& orig_type_parameters = TypeArguments::Handle();
  Object& obj = Object::Handle(library_.LookupLocalObject(class_name));
  if (obj.IsNull()) {
    if (is_patch) {
      ErrorMsg(classname_pos, "missing class '%s' cannot be patched",
               class_name.ToCString());
    }
    cls = Class::New(class_name, script_, classname_pos);
    library_.AddClass(cls);
  } else {
    if (!obj.IsClass()) {
      ErrorMsg(classname_pos, "'%s' is already defined",
               class_name.ToCString());
    }
    cls ^= obj.raw();
    if (is_patch) {
      // Preserve and reuse the original type parameters and bounds since the
      // ones defined in the patch class will not be finalized.
      orig_type_parameters = cls.type_parameters();
      // A patch class must be given the same name as the class it is patching,
      // otherwise the generic signature classes it defines will not match the
      // patched generic signature classes. Therefore, new signature classes
      // will be introduced and the original ones will not get finalized.
      cls = Class::New(class_name, script_, classname_pos);
      cls.set_library(library_);
    } else {
      // Not patching a class, but it has been found. This must be one of the
      // pre-registered classes from object.cc or a duplicate definition.
      if (!(cls.is_prefinalized() ||
            RawObject::IsTypedDataViewClassId(cls.id()))) {
        ErrorMsg(classname_pos, "class '%s' is already defined",
                 class_name.ToCString());
      }
      // Pre-registered classes need their scripts connected at this time.
      cls.set_script(script_);
      cls.set_token_pos(classname_pos);
    }
  }
  ASSERT(!cls.IsNull());
  ASSERT(cls.functions() == Object::empty_array().raw());
  set_current_class(cls);
  ParseTypeParameters(cls);
  if (is_patch) {
    // Check that the new type parameters are identical to the original ones.
    const TypeArguments& new_type_parameters =
        TypeArguments::Handle(cls.type_parameters());
    const int new_type_params_count =
        new_type_parameters.IsNull() ? 0 : new_type_parameters.Length();
    const int orig_type_params_count =
        orig_type_parameters.IsNull() ? 0 : orig_type_parameters.Length();
    if (new_type_params_count != orig_type_params_count) {
      ErrorMsg(classname_pos,
               "class '%s' must be patched with identical type parameters",
               class_name.ToCString());
    }
    TypeParameter& new_type_param = TypeParameter::Handle();
    TypeParameter& orig_type_param = TypeParameter::Handle();
    String& new_name = String::Handle();
    String& orig_name = String::Handle();
    for (int i = 0; i < new_type_params_count; i++) {
      new_type_param ^= new_type_parameters.TypeAt(i);
      orig_type_param ^= orig_type_parameters.TypeAt(i);
      new_name = new_type_param.name();
      orig_name = orig_type_param.name();
      if (!new_name.Equals(orig_name)) {
        ErrorMsg(new_type_param.token_pos(),
                 "type parameter '%s' of patch class '%s' does not match "
                 "original type parameter '%s'",
                 new_name.ToCString(),
                 class_name.ToCString(),
                 orig_name.ToCString());
      }
      // We do not check that the bounds are repeated. We use the original ones.
      // TODO(regis): Should we check?
    }
    cls.set_type_parameters(orig_type_parameters);
  }
  AbstractType& super_type = Type::Handle();
  if (CurrentToken() == Token::kEXTENDS) {
    ConsumeToken();
    const intptr_t type_pos = TokenPos();
    super_type = ParseType(ClassFinalizer::kResolveTypeParameters);
    if (super_type.IsTypeParameter()) {
      ErrorMsg(type_pos,
               "class '%s' may not extend type parameter '%s'",
               class_name.ToCString(),
               String::Handle(super_type.UserVisibleName()).ToCString());
    }
    if (CurrentToken() == Token::kWITH) {
      super_type = ParseMixins(super_type);
    }
  } else {
    // No extends clause: implicitly extend Object, unless Object itself.
    if (!cls.IsObjectClass()) {
      super_type = Type::ObjectType();
    }
  }
  ASSERT(!super_type.IsNull() || cls.IsObjectClass());
  cls.set_super_type(super_type);

  if (CurrentToken() == Token::kIMPLEMENTS) {
    ParseInterfaceList(cls);
  }

  if (is_abstract) {
    cls.set_is_abstract();
  }
  if (is_patch) {
    // Apply the changes to the patched class looked up above.
    ASSERT(obj.raw() == library_.LookupLocalObject(class_name));
    // The patched class must not be finalized yet.
    const Class& orig_class = Class::Cast(obj);
    ASSERT(!orig_class.is_finalized());
    orig_class.set_patch_class(cls);
    cls.set_is_patch();
  }
  pending_classes.Add(cls, Heap::kOld);
  if (metadata_pos >= 0) {
    library_.AddClassMetadata(cls, metadata_pos);
  }

  if (CurrentToken() != Token::kLBRACE) {
    ErrorMsg("{ expected");
  }
  SkipBlock();
}


void Parser::ParseClassDefinition(const Class& cls) {
  TRACE_PARSER("ParseClassDefinition");
  set_current_class(cls);
  is_top_level_ = true;
  String& class_name = String::Handle(cls.Name());
  const intptr_t class_pos = TokenPos();
  ClassDesc members(cls, class_name, false, class_pos);
  while (CurrentToken() != Token::kLBRACE) {
    ConsumeToken();
  }
  ExpectToken(Token::kLBRACE);
  while (CurrentToken() != Token::kRBRACE) {
    intptr_t metadata_pos = SkipMetadata();
    ParseClassMemberDefinition(&members, metadata_pos);
  }
  ExpectToken(Token::kRBRACE);

  CheckConstructors(&members);

  // Need to compute this here since MakeArray() will clear the
  // functions array in members.
  const bool need_implicit_constructor =
      !members.has_constructor() && !cls.is_patch();

  Array& array = Array::Handle();
  array = Array::MakeArray(members.fields());
  cls.SetFields(array);

  // Creating a new array for functions marks the class as parsed.
  array = Array::MakeArray(members.functions());
  cls.SetFunctions(array);

  // Add an implicit constructor if no explicit constructor is present.
  // No implicit constructors are needed for patch classes.
  if (need_implicit_constructor) {
    AddImplicitConstructor(cls);
  }

  if (cls.is_patch()) {
    // Apply the changes to the patched class looked up above.
    Object& obj = Object::Handle(library_.LookupLocalObject(class_name));
    // The patched class must not be finalized yet.
    const Class& orig_class = Class::Cast(obj);
    ASSERT(!orig_class.is_finalized());
    Error& error = Error::Handle();
    if (!orig_class.ApplyPatch(cls, &error)) {
      AppendErrorMsg(error, class_pos, "applying patch failed");
    }
  }
}


// Add an implicit constructor to the given class.
void Parser::AddImplicitConstructor(const Class& cls) {
  // The implicit constructor is unnamed, has no explicit parameter.
  String& ctor_name = String::ZoneHandle(cls.Name());
  ctor_name = String::Concat(ctor_name, Symbols::Dot());
  ctor_name = Symbols::New(ctor_name);
  // To indicate that this is an implicit constructor, we set the
  // token position and end token position of the function
  // to the token position of the class.
  Function& ctor = Function::Handle(
      Function::New(ctor_name,
                    RawFunction::kConstructor,
                    /* is_static = */ false,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    /* is_external = */ false,
                    cls,
                    cls.token_pos()));
  ctor.set_end_token_pos(ctor.token_pos());

  ParamList params;
  // Add implicit 'this' parameter.
  const AbstractType* receiver_type = ReceiverType(cls);
  params.AddReceiver(receiver_type, cls.token_pos());
  // Add implicit parameter for construction phase.
  params.AddFinalParameter(cls.token_pos(),
                           &Symbols::PhaseParameter(),
                           &Type::ZoneHandle(Type::SmiType()));

  AddFormalParamsToFunction(&params, ctor);
  // The body of the constructor cannot modify the type of the constructed
  // instance, which is passed in as the receiver.
  ctor.set_result_type(*receiver_type);
  cls.AddFunction(ctor);
}


// Check for cycles in constructor redirection. Also check whether a
// named constructor collides with the name of another class member.
void Parser::CheckConstructors(ClassDesc* class_desc) {
  // Check for cycles in constructor redirection.
  const GrowableArray<MemberDesc>& members = class_desc->members();
  for (int i = 0; i < members.length(); i++) {
    MemberDesc* member = &members[i];

    if (member->constructor_name != NULL) {
      // Check whether constructor name conflicts with a member name.
      if (class_desc->FunctionNameExists(
          *member->constructor_name, member->kind)) {
        ErrorMsg(member->name_pos,
                 "Named constructor '%s' conflicts with method or field '%s'",
                 member->name->ToCString(),
                 member->constructor_name->ToCString());
      }
    }

    GrowableArray<MemberDesc*> ctors;
    while ((member != NULL) && (member->redirect_name != NULL)) {
      ASSERT(member->IsConstructor());
      // Check whether we have already seen this member.
      for (int i = 0; i < ctors.length(); i++) {
        if (ctors[i] == member) {
          ErrorMsg(member->name_pos,
                   "cyclic reference in constructor redirection");
        }
      }
      // We haven't seen this member. Add it to the list and follow
      // the next redirection. If we can't find the constructor to
      // which the current one redirects, we ignore the unresolved
      // reference. We'll catch it later when the constructor gets
      // compiled.
      ctors.Add(member);
      member = class_desc->LookupMember(*member->redirect_name);
    }
  }
}


void Parser::ParseMixinTypedef(const GrowableObjectArray& pending_classes) {
  TRACE_PARSER("ParseMixinTypedef");
  const intptr_t classname_pos = TokenPos();
  String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected");
  if (FLAG_trace_parser) {
    OS::Print("toplevel parsing typedef class '%s'\n", class_name.ToCString());
  }
  const Object& obj = Object::Handle(library_.LookupLocalObject(class_name));
  if (!obj.IsNull()) {
    ErrorMsg(classname_pos, "'%s' is already defined",
             class_name.ToCString());
  }
  const Class& mixin_application =
      Class::Handle(Class::New(class_name, script_, classname_pos));
  library_.AddClass(mixin_application);
  set_current_class(mixin_application);
  ParseTypeParameters(mixin_application);

  ExpectToken(Token::kASSIGN);

  if (CurrentToken() == Token::kABSTRACT) {
    mixin_application.set_is_abstract();
    ConsumeToken();
  }

  const intptr_t type_pos = TokenPos();
  AbstractType& type =
      AbstractType::Handle(ParseType(ClassFinalizer::kResolveTypeParameters));
  if (type.IsTypeParameter()) {
    ErrorMsg(type_pos,
             "class '%s' may not extend type parameter '%s'",
             class_name.ToCString(),
             String::Handle(type.UserVisibleName()).ToCString());
  }

  if (CurrentToken() != Token::kWITH) {
    ErrorMsg("mixin application 'with Type' expected");
  }
  type = ParseMixins(type);

  // TODO(hausner): treat the mixin application as an alias, not as a base
  // class whose super class is the mixin application!
  mixin_application.set_super_type(type);
  mixin_application.set_is_synthesized_class();

  // This mixin application typedef needs an implicit constructor, but it is
  // too early to call 'AddImplicitConstructor(mixin_application)' here,
  // because this class should be lazily compiled.
  if (CurrentToken() == Token::kIMPLEMENTS) {
    ParseInterfaceList(mixin_application);
  }
  ExpectSemicolon();
  pending_classes.Add(mixin_application, Heap::kOld);
}


// Look ahead to detect if we are seeing ident [ TypeParameters ] "(".
// We need this lookahead to distinguish between the optional return type
// and the alias name of a function type alias.
// Token position remains unchanged.
bool Parser::IsFunctionTypeAliasName() {
  if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) {
    return true;
  }
  const intptr_t saved_pos = TokenPos();
  bool is_alias_name = false;
  if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
    ConsumeToken();
    if (TryParseTypeParameter() && (CurrentToken() == Token::kLPAREN)) {
      is_alias_name = true;
    }
  }
  SetPosition(saved_pos);
  return is_alias_name;
}


// Look ahead to detect if we are seeing ident [ TypeParameters ] "=".
// Token position remains unchanged.
bool Parser::IsMixinTypedef() {
  if (IsIdentifier() && (LookaheadToken(1) == Token::kASSIGN)) {
    return true;
  }
  const intptr_t saved_pos = TokenPos();
  bool is_mixin_def = false;
  if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
    ConsumeToken();
    if (TryParseTypeParameter() && (CurrentToken() == Token::kASSIGN)) {
      is_mixin_def = true;
    }
  }
  SetPosition(saved_pos);
  return is_mixin_def;
}


void Parser::ParseTypedef(const GrowableObjectArray& pending_classes) {
  TRACE_PARSER("ParseTypedef");
  ExpectToken(Token::kTYPEDEF);

  if (IsMixinTypedef()) {
    ParseMixinTypedef(pending_classes);
    return;
  }

  // Parse the result type of the function type.
  AbstractType& result_type = Type::Handle(Type::DynamicType());
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    result_type = Type::VoidType();
  } else if (!IsFunctionTypeAliasName()) {
    // Type annotations in typedef are never ignored, even in unchecked mode.
    // Wait until we have an owner class before resolving the result type.
    result_type = ParseType(ClassFinalizer::kDoNotResolve);
  }

  const intptr_t alias_name_pos = TokenPos();
  const String* alias_name =
      ExpectUserDefinedTypeIdentifier("function alias name expected");

  // Lookup alias name and report an error if it is already defined in
  // the library scope.
  const Object& obj = Object::Handle(library_.LookupLocalObject(*alias_name));
  if (!obj.IsNull()) {
    ErrorMsg(alias_name_pos,
             "'%s' is already defined", alias_name->ToCString());
  }

  // Create the function type alias signature class. It will be linked to its
  // signature function after it has been parsed. The type parameters, in order
  // to be properly finalized, need to be associated to this signature class as
  // they are parsed.
  const Class& function_type_alias = Class::Handle(
      Class::NewSignatureClass(*alias_name,
                               Function::Handle(),
                               script_,
                               alias_name_pos));
  library_.AddClass(function_type_alias);
  set_current_class(function_type_alias);
  // Parse the type parameters of the function type.
  ParseTypeParameters(function_type_alias);
  // At this point, the type parameters have been parsed, so we can resolve the
  // result type.
  if (!result_type.IsNull()) {
    ResolveTypeFromClass(function_type_alias,
                         ClassFinalizer::kResolveTypeParameters,
                         &result_type);
  }
  // Parse the formal parameters of the function type.
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("formal parameter list expected");
  }
  ParamList func_params;

  // Add implicit closure object parameter.
  func_params.AddFinalParameter(
      TokenPos(),
      &Symbols::ClosureParameter(),
      &Type::ZoneHandle(Type::DynamicType()));

  const bool no_explicit_default_values = false;
  ParseFormalParameterList(no_explicit_default_values, &func_params);
  ExpectSemicolon();
  // The field 'is_static' has no meaning for signature functions.
  Function& signature_function = Function::Handle(
      Function::New(*alias_name,
                    RawFunction::kSignatureFunction,
                    /* is_static = */ false,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    /* is_external = */ false,
                    function_type_alias,
                    alias_name_pos));
  signature_function.set_result_type(result_type);
  AddFormalParamsToFunction(&func_params, signature_function);

  // Patch the signature function in the signature class.
  function_type_alias.PatchSignatureFunction(signature_function);

  const String& signature = String::Handle(signature_function.Signature());
  if (FLAG_trace_parser) {
    OS::Print("TopLevel parsing function type alias '%s'\n",
              signature.ToCString());
  }
  // Lookup the signature class, i.e. the class whose name is the signature.
  // We only lookup in the current library, but not in its imports, and only
  // create a new canonical signature class if it does not exist yet.
  Class& signature_class = Class::ZoneHandle(
      library_.LookupLocalClass(signature));
  if (signature_class.IsNull()) {
    signature_class = Class::NewSignatureClass(signature,
                                               signature_function,
                                               script_,
                                               alias_name_pos);
    // Record the function signature class in the current library.
    library_.AddClass(signature_class);
  } else {
    // Forget the just created signature function and use the existing one.
    signature_function = signature_class.signature_function();
    function_type_alias.PatchSignatureFunction(signature_function);
  }
  ASSERT(signature_function.signature_class() == signature_class.raw());

  // The alias should not be marked as finalized yet, since it needs to be
  // checked in the class finalizer for illegal self references.
  ASSERT(!function_type_alias.IsCanonicalSignatureClass());
  ASSERT(!function_type_alias.is_finalized());
  pending_classes.Add(function_type_alias, Heap::kOld);
}


// Consumes exactly one right angle bracket. If the current token is a single
// bracket token, it is consumed normally. However, if it is a double or triple
// bracket, it is replaced by a single or double bracket token without
// incrementing the token index.
void Parser::ConsumeRightAngleBracket() {
  if (token_kind_ == Token::kGT) {
    ConsumeToken();
  } else if (token_kind_ == Token::kSHR) {
    token_kind_ = Token::kGT;
  } else {
    UNREACHABLE();
  }
}


intptr_t Parser::SkipMetadata() {
  if (CurrentToken() != Token::kAT) {
    return -1;
  }
  intptr_t metadata_pos = TokenPos();
  while (CurrentToken() == Token::kAT) {
    ConsumeToken();
    ExpectIdentifier("identifier expected");
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kPERIOD) {
        ConsumeToken();
        ExpectIdentifier("identifier expected");
      }
    }
    if (CurrentToken() == Token::kLPAREN) {
      SkipToMatchingParenthesis();
    }
  }
  return metadata_pos;
}


void Parser::SkipTypeArguments() {
  if (CurrentToken() == Token::kLT) {
    do {
      ConsumeToken();
      SkipType(false);
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) || (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ErrorMsg("right angle bracket expected");
    }
  }
}


void Parser::SkipType(bool allow_void) {
  if (CurrentToken() == Token::kVOID) {
    if (!allow_void) {
      ErrorMsg("'void' not allowed here");
    }
    ConsumeToken();
  } else {
    ExpectIdentifier("type name expected");
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("name expected");
    }
    SkipTypeArguments();
  }
}


void Parser::ParseTypeParameters(const Class& cls) {
  TRACE_PARSER("ParseTypeParameters");
  if (CurrentToken() == Token::kLT) {
    const GrowableObjectArray& type_parameters_array =
        GrowableObjectArray::Handle(GrowableObjectArray::New());
    intptr_t index = 0;
    TypeParameter& type_parameter = TypeParameter::Handle();
    TypeParameter& existing_type_parameter = TypeParameter::Handle();
    String& existing_type_parameter_name = String::Handle();
    AbstractType& type_parameter_bound = Type::Handle();
    do {
      ConsumeToken();
      SkipMetadata();
      const intptr_t type_parameter_pos = TokenPos();
      String& type_parameter_name =
          *ExpectUserDefinedTypeIdentifier("type parameter expected");
      // Check for duplicate type parameters.
      for (intptr_t i = 0; i < index; i++) {
        existing_type_parameter ^= type_parameters_array.At(i);
        existing_type_parameter_name = existing_type_parameter.name();
        if (existing_type_parameter_name.Equals(type_parameter_name)) {
          ErrorMsg(type_parameter_pos, "duplicate type parameter '%s'",
                   type_parameter_name.ToCString());
        }
      }
      if (CurrentToken() == Token::kEXTENDS) {
        ConsumeToken();
        // A bound may refer to the owner of the type parameter it applies to,
        // i.e. to the class or interface currently being parsed.
        // Postpone resolution in order to avoid resolving the class and its
        // type parameters, as they are not fully parsed yet.
        type_parameter_bound = ParseType(ClassFinalizer::kDoNotResolve);
      } else {
        type_parameter_bound = isolate()->object_store()->object_type();
      }
      type_parameter = TypeParameter::New(cls,
                                          index,
                                          type_parameter_name,
                                          type_parameter_bound,
                                          type_parameter_pos);
      type_parameters_array.Add(type_parameter);
      index++;
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) || (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ErrorMsg("right angle bracket expected");
    }
    const TypeArguments& type_parameters =
        TypeArguments::Handle(NewTypeArguments(type_parameters_array));
    cls.set_type_parameters(type_parameters);
    // Try to resolve the upper bounds, which will at least resolve the
    // referenced type parameters.
    const intptr_t num_types = type_parameters.Length();
    for (intptr_t i = 0; i < num_types; i++) {
      type_parameter ^= type_parameters.TypeAt(i);
      type_parameter_bound = type_parameter.bound();
      ResolveTypeFromClass(cls,
                           ClassFinalizer::kResolveTypeParameters,
                           &type_parameter_bound);
      type_parameter.set_bound(type_parameter_bound);
    }
  }
}


RawAbstractTypeArguments* Parser::ParseTypeArguments(
    ClassFinalizer::FinalizationKind finalization) {
  TRACE_PARSER("ParseTypeArguments");
  if (CurrentToken() == Token::kLT) {
    const GrowableObjectArray& types =
        GrowableObjectArray::Handle(GrowableObjectArray::New());
    AbstractType& type = AbstractType::Handle();
    do {
      ConsumeToken();
      type = ParseType(finalization);
      // Map a malformed type argument to dynamic.
      if (type.IsMalformed()) {
        type = Type::DynamicType();
      }
      types.Add(type);
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) || (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ErrorMsg("right angle bracket expected");
    }
    if (finalization != ClassFinalizer::kIgnore) {
      return NewTypeArguments(types);
    }
  }
  return TypeArguments::null();
}


// Parse interface list and add to class cls.
void Parser::ParseInterfaceList(const Class& cls) {
  TRACE_PARSER("ParseInterfaceList");
  ASSERT(CurrentToken() == Token::kIMPLEMENTS);
  const GrowableObjectArray& all_interfaces =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  AbstractType& interface = AbstractType::Handle();
  // First get all the interfaces already implemented by class.
  Array& cls_interfaces = Array::Handle(cls.interfaces());
  for (intptr_t i = 0; i < cls_interfaces.Length(); i++) {
    interface ^= cls_interfaces.At(i);
    all_interfaces.Add(interface);
  }
  // Now parse and add the new interfaces.
  do {
    ConsumeToken();
    intptr_t interface_pos = TokenPos();
    interface = ParseType(ClassFinalizer::kResolveTypeParameters);
    if (interface.IsTypeParameter()) {
      ErrorMsg(interface_pos,
               "type parameter '%s' may not be used in interface list",
               String::Handle(interface.UserVisibleName()).ToCString());
    }
    all_interfaces.Add(interface);
  } while (CurrentToken() == Token::kCOMMA);
  cls_interfaces = Array::MakeArray(all_interfaces);
  cls.set_interfaces(cls_interfaces);
}


RawAbstractType* Parser::ParseMixins(const AbstractType& super_type) {
  TRACE_PARSER("ParseMixins");
  ASSERT(CurrentToken() == Token::kWITH);

  const GrowableObjectArray& mixin_apps =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  AbstractType& mixin_type = AbstractType::Handle();
  AbstractTypeArguments& mixin_type_arguments =
      AbstractTypeArguments::Handle();
  Class& mixin_application = Class::Handle();
  Type& mixin_application_type = Type::Handle();
  Type& mixin_super_type = Type::Handle();
  ASSERT(super_type.IsType());
  mixin_super_type ^= super_type.raw();
  Array& mixin_application_interfaces = Array::Handle();
  do {
    ConsumeToken();
    const intptr_t mixin_pos = TokenPos();
    mixin_type = ParseType(ClassFinalizer::kResolveTypeParameters);
    if (mixin_type.IsTypeParameter()) {
      ErrorMsg(mixin_pos,
               "mixin type '%s' may not be a type parameter",
               String::Handle(mixin_type.UserVisibleName()).ToCString());
    }

    // The name of the mixin application class is a combination of
    // the superclass and mixin class.
    String& mixin_app_name = String::Handle();
    mixin_app_name = mixin_super_type.ClassName();
    mixin_app_name = String::Concat(mixin_app_name, Symbols::Ampersand());
    mixin_app_name = String::Concat(mixin_app_name,
                                    String::Handle(mixin_type.ClassName()));
    mixin_app_name = Symbols::New(mixin_app_name);

    mixin_application = Class::New(mixin_app_name, script_, mixin_pos);
    mixin_application.set_super_type(mixin_super_type);
    mixin_application.set_mixin(Type::Cast(mixin_type));
    mixin_application.set_library(library_);
    mixin_application.set_is_synthesized_class();

    // Add the mixin type to the interfaces that the mixin application
    // class implements. This is necessary so that type tests work.
    mixin_application_interfaces = Array::New(1);
    mixin_application_interfaces.SetAt(0, mixin_type);
    mixin_application.set_interfaces(mixin_application_interfaces);

    // For the type arguments of the mixin application type, we need
    // a copy of the type arguments to the mixin type. The simplest way
    // to get the copy is to rewind the parser, parse the mixin type
    // again and steal its type arguments.
    SetPosition(mixin_pos);
    mixin_type = ParseType(ClassFinalizer::kResolveTypeParameters);
    mixin_type_arguments = mixin_type.arguments();

    mixin_application_type = Type::New(mixin_application,
                                       mixin_type_arguments,
                                       mixin_pos);
    mixin_super_type = mixin_application_type.raw();
    mixin_apps.Add(mixin_application_type);
  } while (CurrentToken() == Token::kCOMMA);
  return MixinAppType::New(super_type,
                           Array::Handle(Array::MakeArray(mixin_apps)));
}


void Parser::ParseTopLevelVariable(TopLevel* top_level,
                                   intptr_t metadata_pos) {
  TRACE_PARSER("ParseTopLevelVariable");
  const bool is_const = (CurrentToken() == Token::kCONST);
  // Const fields are implicitly final.
  const bool is_final = is_const || (CurrentToken() == Token::kFINAL);
  const bool is_static = true;
  const AbstractType& type = AbstractType::ZoneHandle(ParseConstFinalVarOrType(
      ClassFinalizer::kResolveTypeParameters));
  Field& field = Field::Handle();
  Function& getter = Function::Handle();
  while (true) {
    const intptr_t name_pos = TokenPos();
    String& var_name = *ExpectIdentifier("variable name expected");

    if (library_.LookupLocalObject(var_name) != Object::null()) {
      ErrorMsg(name_pos, "'%s' is already defined", var_name.ToCString());
    }
    String& accessor_name = String::Handle(Field::GetterName(var_name));
    if (library_.LookupLocalObject(accessor_name) != Object::null()) {
      ErrorMsg(name_pos, "getter for '%s' is already defined",
               var_name.ToCString());
    }
    // A const or final variable does not define an implicit setter,
    // so we only check setters for non-final variables.
    if (!is_final) {
      accessor_name = Field::SetterName(var_name);
      if (library_.LookupLocalObject(accessor_name) != Object::null()) {
        ErrorMsg(name_pos, "setter for '%s' is already defined",
                 var_name.ToCString());
      }
    }

    field = Field::New(var_name, is_static, is_final, is_const,
                       current_class(), name_pos);
    field.set_type(type);
    field.set_value(Instance::Handle(Instance::null()));
    top_level->fields.Add(field);
    library_.AddObject(field, var_name);
    if (metadata_pos >= 0) {
      library_.AddFieldMetadata(field, metadata_pos);
    }
    if (CurrentToken() == Token::kASSIGN) {
      ConsumeToken();
      Instance& field_value = Instance::Handle(Object::sentinel().raw());
      bool has_simple_literal = false;
      if ((is_const || is_final) && (LookaheadToken(1) == Token::kSEMICOLON)) {
        has_simple_literal = IsSimpleLiteral(type, &field_value);
      }
      SkipExpr();
      field.set_value(field_value);
      if (!has_simple_literal) {
        // Create a static final getter.
        String& getter_name = String::Handle(Field::GetterSymbol(var_name));
        getter = Function::New(getter_name,
                               RawFunction::kImplicitStaticFinalGetter,
                               is_static,
                               is_const,
                               /* is_abstract = */ false,
                               /* is_external = */ false,
                               current_class(),
                               name_pos);
        getter.set_result_type(type);
        top_level->functions.Add(getter);
      }
    } else if (is_final) {
      ErrorMsg(name_pos, "missing initializer for final or const variable");
    }

    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    } else if (CurrentToken() == Token::kSEMICOLON) {
      ConsumeToken();
      break;
    } else {
      ExpectSemicolon();  // Reports error.
    }
  }
}


void Parser::ParseTopLevelFunction(TopLevel* top_level,
                                   intptr_t metadata_pos) {
  TRACE_PARSER("ParseTopLevelFunction");
  const intptr_t decl_begin_pos = TokenPos();
  AbstractType& result_type = Type::Handle(Type::DynamicType());
  const bool is_static = true;
  bool is_external = false;
  bool is_patch = false;
  if (is_patch_source() &&
      (CurrentToken() == Token::kIDENT) &&
      CurrentLiteral()->Equals("patch") &&
      (LookaheadToken(1) != Token::kLPAREN)) {
    ConsumeToken();
    is_patch = true;
  } else if (CurrentToken() == Token::kEXTERNAL) {
    ConsumeToken();
    is_external = true;
  }
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    result_type = Type::VoidType();
  } else {
    // Parse optional type.
    if ((CurrentToken() == Token::kIDENT) &&
        (LookaheadToken(1) != Token::kLPAREN)) {
      result_type = ParseType(ClassFinalizer::kResolveTypeParameters);
    }
  }
  const intptr_t name_pos = TokenPos();
  const String& func_name = *ExpectIdentifier("function name expected");

  bool found = library_.LookupLocalObject(func_name) != Object::null();
  if (found && !is_patch) {
    ErrorMsg(name_pos, "'%s' is already defined", func_name.ToCString());
  } else if (!found && is_patch) {
    ErrorMsg(name_pos, "missing '%s' cannot be patched", func_name.ToCString());
  }
  String& accessor_name = String::Handle(Field::GetterName(func_name));
  if (library_.LookupLocalObject(accessor_name) != Object::null()) {
    ErrorMsg(name_pos, "'%s' is already defined as getter",
             func_name.ToCString());
  }
  // A setter named x= may co-exist with a function named x, thus we do
  // not need to check setters.

  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("'(' expected");
  }
  const intptr_t function_pos = TokenPos();
  ParamList params;
  const bool allow_explicit_default_values = true;
  ParseFormalParameterList(allow_explicit_default_values, &params);

  intptr_t function_end_pos = function_pos;
  if (is_external) {
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
    function_end_pos = TokenPos() - 1;
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    SkipExpr();
    ExpectSemicolon();
    function_end_pos = TokenPos() - 1;
  } else if (IsLiteral("native")) {
    ParseNativeDeclaration();
  } else {
    ErrorMsg("function block expected");
  }
  Function& func = Function::Handle(
      Function::New(func_name,
                    RawFunction::kRegularFunction,
                    is_static,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    is_external,
                    current_class(),
                    decl_begin_pos));
  func.set_result_type(result_type);
  func.set_end_token_pos(function_end_pos);
  AddFormalParamsToFunction(&params, func);
  top_level->functions.Add(func);
  if (!is_patch) {
    library_.AddObject(func, func_name);
  } else {
    library_.ReplaceObject(func, func_name);
  }
  if (metadata_pos >= 0) {
    library_.AddFunctionMetadata(func, metadata_pos);
  }
}


void Parser::ParseTopLevelAccessor(TopLevel* top_level,
                                   intptr_t metadata_pos) {
  TRACE_PARSER("ParseTopLevelAccessor");
  const intptr_t decl_begin_pos = TokenPos();
  const bool is_static = true;
  bool is_external = false;
  bool is_patch = false;
  AbstractType& result_type = AbstractType::Handle();
  if (is_patch_source() &&
      (CurrentToken() == Token::kIDENT) &&
      CurrentLiteral()->Equals("patch")) {
    ConsumeToken();
    is_patch = true;
  } else if (CurrentToken() == Token::kEXTERNAL) {
    ConsumeToken();
    is_external = true;
  }
  bool is_getter = (CurrentToken() == Token::kGET);
  if (CurrentToken() == Token::kGET ||
      CurrentToken() == Token::kSET) {
    ConsumeToken();
    result_type = Type::DynamicType();
  } else {
    if (CurrentToken() == Token::kVOID) {
      ConsumeToken();
      result_type = Type::VoidType();
    } else {
      result_type = ParseType(ClassFinalizer::kResolveTypeParameters);
    }
    is_getter = (CurrentToken() == Token::kGET);
    if (CurrentToken() == Token::kGET || CurrentToken() == Token::kSET) {
      ConsumeToken();
    } else {
      UnexpectedToken();
    }
  }
  const intptr_t name_pos = TokenPos();
  const String* field_name = ExpectIdentifier("accessor name expected");

  const intptr_t accessor_pos = TokenPos();
  ParamList params;

  if (!is_getter) {
    const bool allow_explicit_default_values = true;
    ParseFormalParameterList(allow_explicit_default_values, &params);
  }
  String& accessor_name = String::ZoneHandle();
  int expected_num_parameters = -1;
  if (is_getter) {
    expected_num_parameters = 0;
    accessor_name = Field::GetterSymbol(*field_name);
  } else {
    expected_num_parameters = 1;
    accessor_name = Field::SetterSymbol(*field_name);
  }
  if ((params.num_fixed_parameters != expected_num_parameters) ||
      (params.num_optional_parameters != 0)) {
    ErrorMsg(name_pos, "illegal %s parameters",
             is_getter ? "getter" : "setter");
  }

  if (is_getter && library_.LookupLocalObject(*field_name) != Object::null()) {
    ErrorMsg(name_pos, "'%s' is already defined in this library",
             field_name->ToCString());
  }
  if (!is_getter) {
    // Check whether there is a field with the same name that has an implicit
    // setter.
    const Field& field = Field::Handle(library_.LookupLocalField(*field_name));
    if (!field.IsNull() && !field.is_final()) {
      ErrorMsg(name_pos, "Variable '%s' is already defined in this library",
               field_name->ToCString());
    }
  }
  bool found = library_.LookupLocalObject(accessor_name) != Object::null();
  if (found && !is_patch) {
    ErrorMsg(name_pos, "%s for '%s' is already defined",
             is_getter ? "getter" : "setter",
             field_name->ToCString());
  } else if (!found && is_patch) {
    ErrorMsg(name_pos, "missing %s for '%s' cannot be patched",
             is_getter ? "getter" : "setter",
             field_name->ToCString());
  }

  intptr_t accessor_end_pos = accessor_pos;
  if (is_external) {
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
    accessor_end_pos = TokenPos() - 1;
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    SkipExpr();
    ExpectSemicolon();
    accessor_end_pos = TokenPos() - 1;
  } else if (IsLiteral("native")) {
    ParseNativeDeclaration();
  } else {
    ErrorMsg("function block expected");
  }
  Function& func = Function::Handle(
      Function::New(accessor_name,
                    is_getter? RawFunction::kGetterFunction :
                               RawFunction::kSetterFunction,
                    is_static,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    is_external,
                    current_class(),
                    decl_begin_pos));
  func.set_result_type(result_type);
  func.set_end_token_pos(accessor_end_pos);
  AddFormalParamsToFunction(&params, func);
  top_level->functions.Add(func);
  if (!is_patch) {
    library_.AddObject(func, accessor_name);
  } else {
    library_.ReplaceObject(func, accessor_name);
  }
  if (metadata_pos >= 0) {
    library_.AddFunctionMetadata(func, metadata_pos);
  }
}



RawObject* Parser::CallLibraryTagHandler(Dart_LibraryTag tag,
                                          intptr_t token_pos,
                                          const String& url) {
  Dart_LibraryTagHandler handler = isolate()->library_tag_handler();
  if (handler == NULL) {
    if (url.StartsWith(Symbols::DartScheme())) {
      if (tag == Dart_kCanonicalizeUrl) {
        return url.raw();
      }
      return Object::null();
    }
    ErrorMsg(token_pos, "no library handler registered");
  }
  // Block class finalization attempts when calling into the library
  // tag handler.
  isolate()->BlockClassFinalization();
  Dart_Handle result = handler(tag,
                               Api::NewHandle(isolate(), library_.raw()),
                               Api::NewHandle(isolate(), url.raw()));
  isolate()->UnblockClassFinalization();
  if (Dart_IsError(result)) {
    // In case of an error we append an explanatory error message to the
    // error obtained from the library tag handler.
    Error& prev_error = Error::Handle();
    prev_error ^= Api::UnwrapHandle(result);
    AppendErrorMsg(prev_error, token_pos, "library handler failed");
  }
  if (tag == Dart_kCanonicalizeUrl) {
    if (!Dart_IsString(result)) {
      ErrorMsg(token_pos, "library handler failed URI canonicalization");
    }
  }
  return Api::UnwrapHandle(result);
}


void Parser::ParseLibraryName() {
  ASSERT(CurrentToken() == Token::kLIBRARY);
  ConsumeToken();
  String& lib_name = *ExpectIdentifier("library name expected");
  if (CurrentToken() == Token::kPERIOD) {
    while (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      lib_name = String::Concat(lib_name, Symbols::Dot());
      lib_name = String::Concat(lib_name,
          *ExpectIdentifier("malformed library name"));
    }
    lib_name = Symbols::New(lib_name);
  }
  library_.SetName(lib_name);
  ExpectSemicolon();
}


void Parser::ParseIdentList(GrowableObjectArray* names) {
  if (!IsIdentifier()) {
    ErrorMsg("identifier expected");
  }
  while (IsIdentifier()) {
    names->Add(*CurrentLiteral());
    ConsumeToken();  // Identifier.
    if (CurrentToken() != Token::kCOMMA) {
      return;
    }
    ConsumeToken();  // Comma.
  }
}


void Parser::ParseLibraryImportExport() {
  bool is_import = (CurrentToken() == Token::kIMPORT);
  bool is_export = (CurrentToken() == Token::kEXPORT);
  ASSERT(is_import || is_export);
  const intptr_t import_pos = TokenPos();
  ConsumeToken();
  if (CurrentToken() != Token::kSTRING) {
    ErrorMsg("library url expected");
  }
  const String& url = *CurrentLiteral();
  if (url.Length() == 0) {
    ErrorMsg("library url expected");
  }
  ConsumeToken();
  String& prefix = String::Handle();
  if (is_import && IsLiteral("as")) {
    ConsumeToken();
    prefix = ExpectIdentifier("prefix identifier expected")->raw();
  }

  Array& show_names = Array::Handle();
  Array& hide_names = Array::Handle();
  if (IsLiteral("show") || IsLiteral("hide")) {
    GrowableObjectArray& show_list =
        GrowableObjectArray::Handle(GrowableObjectArray::New());
    GrowableObjectArray& hide_list =
        GrowableObjectArray::Handle(GrowableObjectArray::New());
    for (;;) {
      if (IsLiteral("show")) {
        ConsumeToken();
        ParseIdentList(&show_list);
      } else if (IsLiteral("hide")) {
        ConsumeToken();
        ParseIdentList(&hide_list);
      } else {
        break;
      }
    }
    if (show_list.Length() > 0) {
      show_names = Array::MakeArray(show_list);
    }
    if (hide_list.Length() > 0) {
      hide_names = Array::MakeArray(hide_list);
    }
  }
  ExpectSemicolon();

  // Canonicalize library URL.
  const String& canon_url = String::CheckedHandle(
      CallLibraryTagHandler(Dart_kCanonicalizeUrl, import_pos, url));
  // Lookup the library URL.
  Library& library = Library::Handle(Library::LookupLibrary(canon_url));
  if (library.IsNull()) {
    // Call the library tag handler to load the library.
    CallLibraryTagHandler(Dart_kImportTag, import_pos, canon_url);
    // If the library tag handler succeded without registering the
    // library we create an empty library to import.
    library = Library::LookupLibrary(canon_url);
    if (library.IsNull()) {
      library = Library::New(canon_url);
      library.Register();
    }
  }
  const Namespace& ns =
    Namespace::Handle(Namespace::New(library, show_names, hide_names));
  if (is_import) {
    // Ensure that private dart:_ libraries are only imported into dart:
    // libraries.
    const String& lib_url = String::Handle(library_.url());
    if (canon_url.StartsWith(Symbols::DartSchemePrivate()) &&
        !lib_url.StartsWith(Symbols::DartScheme())) {
      ErrorMsg(import_pos, "private library is not accessible");
    }
    if (prefix.IsNull() || (prefix.Length() == 0)) {
      library_.AddImport(ns);
    } else {
      LibraryPrefix& library_prefix = LibraryPrefix::Handle();
      library_prefix = library_.LookupLocalLibraryPrefix(prefix);
      if (!library_prefix.IsNull()) {
        library_prefix.AddImport(ns);
      } else {
        library_prefix = LibraryPrefix::New(prefix, ns);
        library_.AddObject(library_prefix, prefix);
      }
    }
  } else {
    ASSERT(is_export);
    library_.AddExport(ns);
  }
}


void Parser::ParseLibraryPart() {
  const intptr_t source_pos = TokenPos();
  ConsumeToken();  // Consume "part".
  if (CurrentToken() != Token::kSTRING) {
    ErrorMsg("url expected");
  }
  const String& url = *CurrentLiteral();
  ConsumeToken();
  ExpectSemicolon();
  const String& canon_url = String::CheckedHandle(
      CallLibraryTagHandler(Dart_kCanonicalizeUrl, source_pos, url));
  CallLibraryTagHandler(Dart_kSourceTag, source_pos, canon_url);
}


void Parser::ParseLibraryDefinition() {
  TRACE_PARSER("ParseLibraryDefinition");

  // Handle the script tag.
  if (CurrentToken() == Token::kSCRIPTTAG) {
    // Nothing to do for script tags except to skip them.
    ConsumeToken();
  }

  ASSERT(script_.kind() != RawScript::kSourceTag);

  // We may read metadata tokens that are part of the toplevel
  // declaration that follows the library definitions. Therefore, we
  // need to remember the position of the last token that was
  // successfully consumed.
  intptr_t rewind_pos = TokenPos();
  intptr_t metadata_pos = SkipMetadata();
  if (CurrentToken() == Token::kLIBRARY) {
    if (is_patch_source()) {
      ErrorMsg("patch cannot override library name");
    }
    ParseLibraryName();
    if (metadata_pos >= 0) {
      library_.AddLibraryMetadata(current_class(), metadata_pos);
    }
    rewind_pos = TokenPos();
    metadata_pos = SkipMetadata();
  }
  while ((CurrentToken() == Token::kIMPORT) ||
      (CurrentToken() == Token::kEXPORT)) {
    ParseLibraryImportExport();
    rewind_pos = TokenPos();
    metadata_pos = SkipMetadata();
  }
  // Core lib has not been explicitly imported, so we implicitly
  // import it here.
  if (!library_.ImportsCorelib()) {
    Library& core_lib = Library::Handle(Library::CoreLibrary());
    ASSERT(!core_lib.IsNull());
    const Namespace& core_ns = Namespace::Handle(
        Namespace::New(core_lib, Object::null_array(), Object::null_array()));
    library_.AddImport(core_ns);
  }
  while (CurrentToken() == Token::kPART) {
    ParseLibraryPart();
    rewind_pos = TokenPos();
    metadata_pos = SkipMetadata();
  }
  SetPosition(rewind_pos);
}


void Parser::ParsePartHeader() {
  SkipMetadata();
  if (CurrentToken() != Token::kPART) {
    ErrorMsg("'part of' expected");
  }
  ConsumeToken();
  if (!IsLiteral("of")) {
    ErrorMsg("'part of' expected");
  }
  ConsumeToken();
  // The VM is not required to check that the library name matches the
  // name of the current library, so we ignore it.
  ExpectIdentifier("library name expected");
  while (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    ExpectIdentifier("malformed library name");
  }
  ExpectSemicolon();
}


void Parser::ParseTopLevel() {
  TRACE_PARSER("ParseTopLevel");
  // Collect the classes found at the top level in this growable array.
  // They need to be registered with class finalization after parsing
  // has been completed.
  ObjectStore* object_store = isolate()->object_store();
  const GrowableObjectArray& pending_classes =
      GrowableObjectArray::Handle(isolate(), object_store->pending_classes());
  SetPosition(0);
  is_top_level_ = true;
  TopLevel top_level;
  Class& toplevel_class = Class::Handle(
      Class::New(Symbols::TopLevel(), script_, TokenPos()));
  toplevel_class.set_library(library_);

  if (is_library_source() || is_patch_source()) {
    set_current_class(toplevel_class);
    ParseLibraryDefinition();
  } else if (is_part_source()) {
    ParsePartHeader();
  }

  const Class& cls = Class::Handle(isolate());
  while (true) {
    set_current_class(cls);  // No current class.
    intptr_t metadata_pos = SkipMetadata();
    if (CurrentToken() == Token::kCLASS) {
      ParseClassDeclaration(pending_classes, metadata_pos);
    } else if ((CurrentToken() == Token::kTYPEDEF) &&
               (LookaheadToken(1) != Token::kLPAREN)) {
      set_current_class(toplevel_class);
      ParseTypedef(pending_classes);
    } else if ((CurrentToken() == Token::kABSTRACT) &&
        (LookaheadToken(1) == Token::kCLASS)) {
      ParseClassDeclaration(pending_classes, metadata_pos);
    } else if (is_patch_source() && IsLiteral("patch") &&
               (LookaheadToken(1) == Token::kCLASS)) {
      ParseClassDeclaration(pending_classes, metadata_pos);
    } else {
      set_current_class(toplevel_class);
      if (IsVariableDeclaration()) {
        ParseTopLevelVariable(&top_level, metadata_pos);
      } else if (IsFunctionDeclaration()) {
        ParseTopLevelFunction(&top_level, metadata_pos);
      } else if (IsTopLevelAccessor()) {
        ParseTopLevelAccessor(&top_level, metadata_pos);
      } else if (CurrentToken() == Token::kEOS) {
        break;
      } else {
        UnexpectedToken();
      }
    }
  }
  if ((top_level.fields.Length() > 0) || (top_level.functions.Length() > 0)) {
    Array& array = Array::Handle();

    array = Array::MakeArray(top_level.fields);
    toplevel_class.SetFields(array);

    array = Array::MakeArray(top_level.functions);
    toplevel_class.SetFunctions(array);

    library_.AddAnonymousClass(toplevel_class);
    pending_classes.Add(toplevel_class, Heap::kOld);
  }
}


void Parser::ChainNewBlock(LocalScope* outer_scope) {
  Block* block = new Block(current_block_,
                           outer_scope,
                           new SequenceNode(TokenPos(), outer_scope));
  current_block_ = block;
}


void Parser::OpenBlock() {
  ASSERT(current_block_ != NULL);
  LocalScope* outer_scope = current_block_->scope;
  ChainNewBlock(new LocalScope(outer_scope,
                               outer_scope->function_level(),
                               outer_scope->loop_level()));
}


void Parser::OpenLoopBlock() {
  ASSERT(current_block_ != NULL);
  LocalScope* outer_scope = current_block_->scope;
  ChainNewBlock(new LocalScope(outer_scope,
                               outer_scope->function_level(),
                               outer_scope->loop_level() + 1));
}


void Parser::OpenFunctionBlock(const Function& func) {
  LocalScope* outer_scope;
  if (current_block_ == NULL) {
    if (!func.IsLocalFunction()) {
      // We are compiling a non-nested function.
      outer_scope = new LocalScope(NULL, 0, 0);
    } else {
      // We are compiling the function of an invoked closure.
      // Restore the outer scope containing all captured variables.
      const ContextScope& context_scope =
          ContextScope::Handle(func.context_scope());
      ASSERT(!context_scope.IsNull());
      outer_scope =
          new LocalScope(LocalScope::RestoreOuterScope(context_scope), 0, 0);
    }
  } else {
    // We are parsing a nested function while compiling the enclosing function.
    outer_scope = new LocalScope(current_block_->scope,
                                 current_block_->scope->function_level() + 1,
                                 0);
  }
  ChainNewBlock(outer_scope);
}


SequenceNode* Parser::CloseBlock() {
  SequenceNode* statements = current_block_->statements;
  if (current_block_->scope != NULL) {
    // Record the begin and end token index of the scope.
    ASSERT(statements != NULL);
    current_block_->scope->set_begin_token_pos(statements->token_pos());
    current_block_->scope->set_end_token_pos(TokenPos());
  }
  current_block_ = current_block_->parent;
  return statements;
}


// Set up default values for all optional parameters to the function.
void Parser::SetupDefaultsForOptionalParams(const ParamList* params,
                                            Array& default_values) {
  if (params->num_optional_parameters > 0) {
    // Build array of default parameter values.
    ParamDesc* param =
      params->parameters->data() + params->num_fixed_parameters;
    default_values = Array::New(params->num_optional_parameters);
    for (int i = 0; i < params->num_optional_parameters; i++) {
      ASSERT(param->default_value != NULL);
      default_values.SetAt(i, *param->default_value);
      param++;
    }
  }
}


// Populate the parameter type array and parameter name array of the function
// with the formal parameter types and names.
void Parser::AddFormalParamsToFunction(const ParamList* params,
                                       const Function& func) {
  ASSERT((params != NULL) && (params->parameters != NULL));
  ASSERT((params->num_optional_parameters > 0) ==
         (params->has_optional_positional_parameters ||
          params->has_optional_named_parameters));
  if (!Utils::IsInt(16, params->num_fixed_parameters) ||
      !Utils::IsInt(16, params->num_optional_parameters)) {
    const Script& script = Script::Handle(Class::Handle(func.Owner()).script());
    const Error& error = Error::Handle(FormatErrorMsg(
        script, func.token_pos(), "Error", "too many formal parameters"));
    ErrorMsg(error);
  }
  func.set_num_fixed_parameters(params->num_fixed_parameters);
  func.SetNumOptionalParameters(params->num_optional_parameters,
                                params->has_optional_positional_parameters);
  const int num_parameters = params->parameters->length();
  ASSERT(num_parameters == func.NumParameters());
  func.set_parameter_types(Array::Handle(Array::New(num_parameters,
                                                    Heap::kOld)));
  func.set_parameter_names(Array::Handle(Array::New(num_parameters,
                                                    Heap::kOld)));
  for (int i = 0; i < num_parameters; i++) {
    ParamDesc& param_desc = (*params->parameters)[i];
    func.SetParameterTypeAt(i, *param_desc.type);
    func.SetParameterNameAt(i, *param_desc.name);
  }
}


// Populate local scope with the formal parameters.
void Parser::AddFormalParamsToScope(const ParamList* params,
                                    LocalScope* scope) {
  ASSERT((params != NULL) && (params->parameters != NULL));
  ASSERT(scope != NULL);
  const int num_parameters = params->parameters->length();
  for (int i = 0; i < num_parameters; i++) {
    ParamDesc& param_desc = (*params->parameters)[i];
    ASSERT(!is_top_level_ || param_desc.type->IsResolved());
    const String* name = param_desc.name;
    LocalVariable* parameter = new LocalVariable(
        param_desc.name_pos, *name, *param_desc.type);
    if (!scope->AddVariable(parameter)) {
      ErrorMsg(param_desc.name_pos,
               "name '%s' already exists in scope",
               param_desc.name->ToCString());
    }
    if (param_desc.is_final) {
      parameter->set_is_final();
    }
  }
}


// Builds ReturnNode/NativeBodyNode for a native function.
void Parser::ParseNativeFunctionBlock(const ParamList* params,
                                      const Function& func) {
  func.set_is_native(true);
  TRACE_PARSER("ParseNativeFunctionBlock");
  const Class& cls = Class::Handle(func.Owner());
  const Library& library = Library::Handle(cls.library());
  ASSERT(func.NumParameters() == params->parameters->length());

  // Parse the function name out.
  const intptr_t native_pos = TokenPos();
  const String& native_name = ParseNativeDeclaration();

  // Now resolve the native function to the corresponding native entrypoint.
  const int num_params = NativeArguments::ParameterCountForResolution(func);
  NativeFunction native_function = NativeEntry::ResolveNative(
      library, native_name, num_params);
  if (native_function == NULL) {
    ErrorMsg(native_pos, "native function '%s' cannot be found",
        native_name.ToCString());
  }

  // Now add the NativeBodyNode and return statement.
  Dart_NativeEntryResolver resolver = library.native_entry_resolver();
  bool is_bootstrap_native = Bootstrap::IsBootstapResolver(resolver);
  current_block_->statements->Add(
      new ReturnNode(TokenPos(),
                     new NativeBodyNode(TokenPos(),
                                        Function::ZoneHandle(func.raw()),
                                        native_name,
                                        native_function,
                                        current_block_->scope,
                                        is_bootstrap_native)));
}


LocalVariable* Parser::LookupReceiver(LocalScope* from_scope, bool test_only) {
  ASSERT(!current_function().is_static());
  return from_scope->LookupVariable(Symbols::This(), test_only);
}


LocalVariable* Parser::LookupTypeArgumentsParameter(LocalScope* from_scope,
                                                    bool test_only) {
  ASSERT(current_function().IsInFactoryScope());
  return from_scope->LookupVariable(Symbols::TypeArgumentsParameter(),
                                    test_only);
}


LocalVariable* Parser::LookupPhaseParameter() {
  const bool kTestOnly = false;
  return current_block_->scope->LookupVariable(Symbols::PhaseParameter(),
                                               kTestOnly);
}


void Parser::CaptureInstantiator() {
  ASSERT(current_block_->scope->function_level() > 0);
  bool found = false;
  if (current_function().IsInFactoryScope()) {
    found = current_block_->scope->CaptureVariable(
        Symbols::TypeArgumentsParameter());
  } else {
    found = current_block_->scope->CaptureVariable(Symbols::This());
  }
  ASSERT(found);
}


AstNode* Parser::LoadReceiver(intptr_t token_pos) {
  // A nested function may access 'this', referring to the receiver of the
  // outermost enclosing function.
  const bool kTestOnly = false;
  LocalVariable* receiver = LookupReceiver(current_block_->scope, kTestOnly);
  if (receiver == NULL) {
    ErrorMsg(token_pos, "illegal implicit access to receiver 'this'");
  }
  return new LoadLocalNode(TokenPos(), receiver);
}


AstNode* Parser::LoadTypeArgumentsParameter(intptr_t token_pos) {
  // A nested function may access ':type_arguments' to use as instantiator,
  // referring to the implicit first parameter of the outermost enclosing
  // factory function.
  const bool kTestOnly = false;
  LocalVariable* param = LookupTypeArgumentsParameter(current_block_->scope,
                                                      kTestOnly);
  ASSERT(param != NULL);
  return new LoadLocalNode(TokenPos(), param);
}


AstNode* Parser::CallGetter(intptr_t token_pos,
                            AstNode* object,
                            const String& name) {
  return new InstanceGetterNode(token_pos, object, name);
}


// Returns ast nodes of the variable initialization.
AstNode* Parser::ParseVariableDeclaration(const AbstractType& type,
                                          bool is_final,
                                          bool is_const) {
  TRACE_PARSER("ParseVariableDeclaration");
  ASSERT(IsIdentifier());
  const intptr_t ident_pos = TokenPos();
  LocalVariable* variable =
      new LocalVariable(ident_pos, *CurrentLiteral(), type);
  ASSERT(current_block_ != NULL);
  ASSERT(current_block_->scope != NULL);
  ConsumeToken();  // Variable identifier.
  AstNode* initialization = NULL;
  if (CurrentToken() == Token::kASSIGN) {
    // Variable initialization.
    const intptr_t assign_pos = TokenPos();
    ConsumeToken();
    AstNode* expr = ParseExpr(is_const, kConsumeCascades);
    initialization = new StoreLocalNode(assign_pos, variable, expr);
    if (is_const) {
      ASSERT(expr->IsLiteralNode());
      variable->SetConstValue(expr->AsLiteralNode()->literal());
    }
  } else if (is_final || is_const) {
    ErrorMsg(ident_pos,
    "missing initialization of 'final' or 'const' variable");
  } else {
    // Initialize variable with null.
    AstNode* null_expr = new LiteralNode(ident_pos, Instance::ZoneHandle());
    initialization = new StoreLocalNode(ident_pos, variable, null_expr);
  }
  // Add variable to scope after parsing the initalizer expression.
  // The expression must not be able to refer to the variable.
  if (!current_block_->scope->AddVariable(variable)) {
    LocalVariable* existing_var =
        current_block_->scope->LookupVariable(variable->name(), true);
    ASSERT(existing_var != NULL);
    if (existing_var->owner() == current_block_->scope) {
      ErrorMsg(ident_pos, "identifier '%s' already defined",
               variable->name().ToCString());
    } else {
      ErrorMsg(ident_pos,
               "'%s' from outer scope has already been used, cannot redefine",
               variable->name().ToCString());
    }
  }
  if (is_final || is_const) {
    variable->set_is_final();
  }
  return initialization;
}


// Parses ('var' | 'final' [type] | 'const' [type] | type).
// The presence of 'final' or 'const' must be detected and remembered
// before the call. If a type is parsed, it may be resolved and finalized
// according to the given type finalization mode.
RawAbstractType* Parser::ParseConstFinalVarOrType(
    ClassFinalizer::FinalizationKind finalization) {
  TRACE_PARSER("ParseConstFinalVarOrType");
  if (CurrentToken() == Token::kVAR) {
    ConsumeToken();
    return Type::DynamicType();
  }
  bool type_is_optional = false;
  if ((CurrentToken() == Token::kFINAL) || (CurrentToken() == Token::kCONST)) {
    ConsumeToken();
    type_is_optional = true;
  }
  if (CurrentToken() != Token::kIDENT) {
    if (type_is_optional) {
      return Type::DynamicType();
    } else {
      ErrorMsg("type name expected");
    }
  }
  if (type_is_optional) {
    Token::Kind follower = LookaheadToken(1);
    // We have an identifier followed by a 'follower' token.
    // We either parse a type or return now.
    if ((follower != Token::kLT) &&  // Parameterized type.
        (follower != Token::kPERIOD) &&  // Qualified class name of type.
        !Token::IsIdentifier(follower) &&  // Variable name following a type.
        (follower != Token::kTHIS)) {  // Field parameter following a type.
      return Type::DynamicType();
    }
  }
  return ParseType(finalization);
}


// Returns ast nodes of the variable initialization. Variables without an
// explicit initializer are initialized to null. If several variables are
// declared, the individual initializers are collected in a sequence node.
AstNode* Parser::ParseVariableDeclarationList() {
  TRACE_PARSER("ParseVariableDeclarationList");
  SkipMetadata();
  bool is_final = (CurrentToken() == Token::kFINAL);
  bool is_const = (CurrentToken() == Token::kCONST);
  const AbstractType& type = AbstractType::ZoneHandle(ParseConstFinalVarOrType(
      FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
                                ClassFinalizer::kIgnore));
  if (!IsIdentifier()) {
    ErrorMsg("identifier expected");
  }

  AstNode* initializers = ParseVariableDeclaration(type, is_final, is_const);
  ASSERT(initializers != NULL);
  while (CurrentToken() == Token::kCOMMA) {
    ConsumeToken();
    if (!IsIdentifier()) {
      ErrorMsg("identifier expected after comma");
    }
    // We have a second initializer. Allocate a sequence node now.
    // The sequence does not own the current scope. Set its own scope to NULL.
    SequenceNode* sequence = NodeAsSequenceNode(initializers->token_pos(),
                                                initializers,
                                                NULL);
    sequence->Add(ParseVariableDeclaration(type, is_final, is_const));
    initializers = sequence;
  }
  return initializers;
}


AstNode* Parser::ParseFunctionStatement(bool is_literal) {
  TRACE_PARSER("ParseFunctionStatement");
  AbstractType& result_type = AbstractType::Handle();
  const String* variable_name = NULL;
  const String* function_name = NULL;

  result_type = Type::DynamicType();

  intptr_t ident_pos = TokenPos();
  if (is_literal) {
    ASSERT(CurrentToken() == Token::kLPAREN);
    function_name = &Symbols::AnonymousClosure();
  } else {
    if (CurrentToken() == Token::kVOID) {
      ConsumeToken();
      result_type = Type::VoidType();
    } else if ((CurrentToken() == Token::kIDENT) &&
               (LookaheadToken(1) != Token::kLPAREN)) {
      result_type = ParseType(ClassFinalizer::kCanonicalize);
    }
    variable_name = ExpectIdentifier("function name expected");
    function_name = variable_name;
  }

  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("'(' expected");
  }
  intptr_t function_pos = TokenPos();

  // Check whether we have parsed this closure function before, in a previous
  // compilation. If so, reuse the function object, else create a new one
  // and register it in the current class.
  // Note that we cannot share the same closure function between the closurized
  // and non-closurized versions of the same parent function.
  Function& function = Function::ZoneHandle();
  bool is_new_closure = false;
  // TODO(hausner): There could be two different closures at the given
  // function_pos, one enclosed in a closurized function and one enclosed in the
  // non-closurized version of this same function.
  function = current_class().LookupClosureFunction(function_pos);
  if (function.IsNull() || (function.token_pos() != function_pos) ||
      (function.parent_function() != innermost_function().raw())) {
    is_new_closure = true;
    function = Function::NewClosureFunction(*function_name,
                                            innermost_function(),
                                            ident_pos);
    function.set_result_type(result_type);
    current_class().AddClosureFunction(function);
  }

  // The function type needs to be finalized at compile time, since the closure
  // may be type checked at run time when assigned to a function variable,
  // passed as a function argument, or returned as a function result.

  LocalVariable* function_variable = NULL;
  Type& function_type = Type::ZoneHandle();
  if (variable_name != NULL) {
    // Since the function type depends on the signature of the closure function,
    // it cannot be determined before the formal parameter list of the closure
    // function is parsed. Therefore, we set the function type to a new
    // parameterized type to be patched after the actual type is known.
    // We temporarily use the class of the Function interface.
    const Class& unknown_signature_class = Class::Handle(
        Type::Handle(Type::Function()).type_class());
    function_type = Type::New(
        unknown_signature_class, TypeArguments::Handle(), ident_pos);
    function_type.SetIsFinalized();  // No finalization needed.

    // Add the function variable to the scope before parsing the function in
    // order to allow self reference from inside the function.
    function_variable = new LocalVariable(ident_pos,
                                          *variable_name,
                                          function_type);
    function_variable->set_is_final();
    ASSERT(current_block_ != NULL);
    ASSERT(current_block_->scope != NULL);
    if (!current_block_->scope->AddVariable(function_variable)) {
      LocalVariable* existing_var =
          current_block_->scope->LookupVariable(function_variable->name(),
                                                true);
      ASSERT(existing_var != NULL);
      if (existing_var->owner() == current_block_->scope) {
        ErrorMsg(ident_pos, "identifier '%s' already defined",
                 function_variable->name().ToCString());
      } else {
        ErrorMsg(ident_pos,
                 "'%s' from outer scope has already been used, cannot redefine",
                 function_variable->name().ToCString());
      }
    }
  }

  // Parse the local function.
  Array& default_parameter_values = Array::Handle();
  SequenceNode* statements = Parser::ParseFunc(function,
                                               default_parameter_values);
  ASSERT(is_new_closure || (function.end_token_pos() == (TokenPos() - 1)));
  function.set_end_token_pos(TokenPos() - 1);

  // Now that the local function has formal parameters, lookup the signature
  // class in the current library (but not in its imports) and only create a new
  // canonical signature class if it does not exist yet.
  const String& signature = String::Handle(function.Signature());
  Class& signature_class = Class::ZoneHandle();
  if (!is_new_closure) {
    signature_class = function.signature_class();
  }
  if (signature_class.IsNull()) {
    signature_class = library_.LookupLocalClass(signature);
  }
  if (signature_class.IsNull()) {
    // If we don't have a signature class yet, this must be a closure we
    // have not parsed before.
    ASSERT(is_new_closure);
    signature_class = Class::NewSignatureClass(signature,
                                               function,
                                               script_,
                                               function.token_pos());
    // Record the function signature class in the current library.
    library_.AddClass(signature_class);
  } else if (is_new_closure) {
    function.set_signature_class(signature_class);
  }
  ASSERT(function.signature_class() == signature_class.raw());

  // Local functions are registered in the enclosing class, but
  // ignored during class finalization. The enclosing class has
  // already been finalized.
  ASSERT(current_class().is_finalized());

  // Make sure that the instantiator is captured.
  if ((signature_class.NumTypeParameters() > 0) &&
      (current_block_->scope->function_level() > 0)) {
    CaptureInstantiator();
  }

  // Since the signature type is cached by the signature class, it may have
  // been finalized already.
  Type& signature_type = Type::Handle(signature_class.SignatureType());
  AbstractTypeArguments& signature_type_arguments =
      AbstractTypeArguments::Handle(signature_type.arguments());

  if (!signature_type.IsFinalized()) {
    signature_type ^= ClassFinalizer::FinalizeType(
        signature_class, signature_type, ClassFinalizer::kCanonicalize);

    // The call to ClassFinalizer::FinalizeType may have
    // extended the vector of type arguments.
    signature_type_arguments = signature_type.arguments();
    ASSERT(signature_type.IsMalformed() ||
           signature_type_arguments.IsNull() ||
           (signature_type_arguments.Length() ==
            signature_class.NumTypeArguments()));

    // The signature_class should not have changed.
    ASSERT(signature_type.IsMalformed() ||
           (signature_type.type_class() == signature_class.raw()));
  }

  if (variable_name != NULL) {
    // Patch the function type of the variable now that the signature is known.
    function_type.set_type_class(signature_class);
    function_type.set_arguments(signature_type_arguments);

    // Mark the function type as malformed if the signature type is malformed.
    if (signature_type.IsMalformed()) {
      const Error& error = Error::Handle(signature_type.malformed_error());
      function_type.set_malformed_error(error);
    }

    // The function type was initially marked as instantiated, but it may
    // actually be uninstantiated.
    function_type.ResetIsFinalized();

    // The function variable type should have been patched above.
    ASSERT((function_variable == NULL) ||
           (function_variable->type().raw() == function_type.raw()));
  }

  // The code generator does not compile the closure function when visiting
  // a ClosureNode. The generated code allocates a new Closure object containing
  // the current context. The type of the Closure object refers to the closure
  // function, which will be compiled on first invocation of the closure object.
  // Therefore, we ignore the parsed default_parameter_values and the
  // node_sequence representing the body of the closure function, which will be
  // parsed again when compiled later.
  // The only purpose of parsing the function now (besides reporting obvious
  // errors) is to mark referenced variables of the enclosing scopes as
  // captured. The captured variables will be recorded along with their
  // allocation information in a Scope object stored in the function object.
  // This Scope object is then provided to the compiler when compiling the local
  // function. It would be too early to record the captured variables here,
  // since further closure functions may capture more variables.
  // This Scope object is constructed after all variables have been allocated.
  // The local scope of the parsed function can be pruned, since contained
  // variables are not relevant for the compilation of the enclosing function.
  // This pruning is done by omitting to hook the local scope in its parent
  // scope in the constructor of LocalScope.
  AstNode* closure =
      new ClosureNode(ident_pos, function, NULL, statements->scope());

  if (function_variable == NULL) {
    ASSERT(is_literal);
    return closure;
  } else {
    AstNode* initialization =
        new StoreLocalNode(ident_pos, function_variable, closure);
    return initialization;
  }
}


// Returns true if the current and next tokens can be parsed as type
// parameters. Current token position is not saved and restored.
bool Parser::TryParseTypeParameter() {
  if (CurrentToken() == Token::kLT) {
    // We are possibly looking at type parameters. Find closing ">".
    int nesting_level = 0;
    do {
      if (CurrentToken() == Token::kLT) {
        nesting_level++;
      } else if (CurrentToken() == Token::kGT) {
        nesting_level--;
      } else if (CurrentToken() == Token::kSHR) {
        nesting_level -= 2;
      } else if (CurrentToken() == Token::kIDENT) {
        // Check to see if it is a qualified identifier.
        if (LookaheadToken(1) == Token::kPERIOD) {
          // Consume the identifier, the period will be consumed below.
          ConsumeToken();
        }
      } else if (CurrentToken() != Token::kCOMMA &&
                 CurrentToken() != Token::kEXTENDS) {
        // We are looking at something other than type parameters.
        return false;
      }
      ConsumeToken();
    } while (nesting_level > 0);
    if (nesting_level < 0) {
      return false;
    }
  }
  return true;
}


bool Parser::IsSimpleLiteral(const AbstractType& type, Instance* value) {
  // Assigning null never causes a type error.
  if (CurrentToken() == Token::kNULL) {
    *value = Instance::null();
    return true;
  }
  // If the type of the const field is guaranteed to be instantiated once
  // resolved at class finalization time, and if the type of the literal is one
  // of int, double, String, or bool, then preset the field with the value and
  // perform the type check (in checked mode only) at finalization time.
  if (type.IsTypeParameter() ||
      (type.arguments() != AbstractTypeArguments::null())) {
    // Type parameters are always resolved eagerly by the parser and never
    // resolved later by the class finalizer. Therefore, we know here that if
    // 'type' is not a type parameter (an unresolved type will not get resolved
    // to a type parameter later) and if 'type' has no type arguments, then it
    // will be instantiated at class finalization time. Otherwise, we return
    // false, since the type test would not be possible at finalization time for
    // an uninstantiated type.
    return false;
  }
  if (CurrentToken() == Token::kINTEGER) {
    *value = CurrentIntegerLiteral();
    return true;
  } else if (CurrentToken() == Token::kDOUBLE) {
    *value = CurrentDoubleLiteral();
    return true;
  } else if (CurrentToken() == Token::kSTRING) {
    *value = CurrentLiteral()->raw();
    return true;
  } else if (CurrentToken() == Token::kTRUE) {
    *value = Bool::True().raw();
    return true;
  } else if (CurrentToken() == Token::kFALSE) {
    *value = Bool::False().raw();
    return true;
  }
  return false;
}


// Returns true if the current token is kIDENT or a pseudo-keyword.
bool Parser::IsIdentifier() {
  return Token::IsIdentifier(CurrentToken());
}


// Returns true if the next tokens can be parsed as a type with optional
// type parameters. Current token position is not restored.
bool Parser::TryParseOptionalType() {
  if (CurrentToken() == Token::kIDENT) {
    QualIdent type_name;
    ParseQualIdent(&type_name);
    if ((CurrentToken() == Token::kLT) && !TryParseTypeParameter()) {
      return false;
    }
  }
  return true;
}


// Returns true if the next tokens can be parsed as a type with optional
// type parameters, or keyword "void".
// Current token position is not restored.
bool Parser::TryParseReturnType() {
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    return true;
  } else if (CurrentToken() == Token::kIDENT) {
    return TryParseOptionalType();
  }
  return false;
}


// Look ahead to detect whether the next tokens should be parsed as
// a variable declaration. Ignores optional metadata.
// Returns true if we detect the token pattern:
//     'var'
//   | 'final'
//   | const [type] ident (';' | '=' | ',')
//   | type ident (';' | '=' | ',')
// Token position remains unchanged.
bool Parser::IsVariableDeclaration() {
  if ((CurrentToken() == Token::kVAR) ||
      (CurrentToken() == Token::kFINAL)) {
    return true;
  }
  // Skip optional metadata.
  if (CurrentToken() == Token::kAT) {
    const intptr_t saved_pos = TokenPos();
    SkipMetadata();
    const bool is_var_decl = IsVariableDeclaration();
    SetPosition(saved_pos);
    return is_var_decl;
  }
  if ((CurrentToken() != Token::kIDENT) && (CurrentToken() != Token::kCONST)) {
    // Not a legal type identifier or const keyword or metadata.
    return false;
  }
  const intptr_t saved_pos = TokenPos();
  bool is_var_decl = false;
  bool have_type = false;
  if (CurrentToken() == Token::kCONST) {
    ConsumeToken();
    have_type = true;  // Type is dynamic.
  }
  if (IsIdentifier()) {  // Type or variable name.
    Token::Kind follower = LookaheadToken(1);
    if ((follower == Token::kLT) ||  // Parameterized type.
        (follower == Token::kPERIOD) ||  // Qualified class name of type.
        Token::IsIdentifier(follower)) {  // Variable name following a type.
      // We see the beginning of something that could be a type.
      const intptr_t type_pos = TokenPos();
      if (TryParseOptionalType()) {
        have_type = true;
      } else {
        SetPosition(type_pos);
      }
    }
    if (have_type && IsIdentifier()) {
      ConsumeToken();
      if ((CurrentToken() == Token::kSEMICOLON) ||
          (CurrentToken() == Token::kCOMMA) ||
          (CurrentToken() == Token::kASSIGN)) {
        is_var_decl = true;
      }
    }
  }
  SetPosition(saved_pos);
  return is_var_decl;
}


// Look ahead to detect whether the next tokens should be parsed as
// a function declaration. Token position remains unchanged.
bool Parser::IsFunctionDeclaration() {
  const intptr_t saved_pos = TokenPos();
  bool is_external = false;
  if (is_top_level_) {
    if (is_patch_source() &&
        (CurrentToken() == Token::kIDENT) &&
        CurrentLiteral()->Equals("patch") &&
        (LookaheadToken(1) != Token::kLPAREN)) {
      // Skip over 'patch' for top-level function declarations in patch sources.
      ConsumeToken();
    } else if (CurrentToken() == Token::kEXTERNAL) {
      // Skip over 'external' for top-level function declarations.
      is_external = true;
      ConsumeToken();
    }
  }
  if (IsIdentifier() && (LookaheadToken(1) == Token::kLPAREN)) {
    // Possibly a function without explicit return type.
    ConsumeToken();  // Consume function identifier.
  } else if (TryParseReturnType()) {
    if (!IsIdentifier()) {
      SetPosition(saved_pos);
      return false;
    }
    ConsumeToken();  // Consume function identifier.
  } else {
    SetPosition(saved_pos);
    return false;
  }
  // Check parameter list and the following token.
  if (CurrentToken() == Token::kLPAREN) {
    SkipToMatchingParenthesis();
    if ((CurrentToken() == Token::kLBRACE) ||
        (CurrentToken() == Token::kARROW) ||
        (is_top_level_ && IsLiteral("native")) ||
        is_external) {
      SetPosition(saved_pos);
      return true;
    }
  }
  SetPosition(saved_pos);
  return false;
}


bool Parser::IsTopLevelAccessor() {
  const intptr_t saved_pos = TokenPos();
  if (is_patch_source() &&
      (CurrentToken() == Token::kIDENT) &&
      (CurrentLiteral()->Equals("patch"))) {
    ConsumeToken();
  } else if (CurrentToken() == Token::kEXTERNAL) {
    ConsumeToken();
  }
  if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
    SetPosition(saved_pos);
    return true;
  }
  if (TryParseReturnType()) {
    if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
      if (Token::IsIdentifier(LookaheadToken(1))) {  // Accessor name.
        SetPosition(saved_pos);
        return true;
      }
    }
  }
  SetPosition(saved_pos);
  return false;
}


bool Parser::IsFunctionLiteral() {
  if (CurrentToken() != Token::kLPAREN || !allow_function_literals_) {
    return false;
  }
  const intptr_t saved_pos = TokenPos();
  bool is_function_literal = false;
  SkipToMatchingParenthesis();
  if ((CurrentToken() == Token::kLBRACE) ||
      (CurrentToken() == Token::kARROW)) {
    is_function_literal = true;
  }
  SetPosition(saved_pos);
  return is_function_literal;
}


// Current token position is the token after the opening ( of the for
// statement. Returns true if we recognize a for ( .. in expr)
// statement.
bool Parser::IsForInStatement() {
  const intptr_t saved_pos = TokenPos();
  bool result = false;
  // Allow const modifier as well when recognizing a for-in statement
  // pattern. We will get an error later if the loop variable is
  // declared with const.
  if (CurrentToken() == Token::kVAR ||
      CurrentToken() == Token::kFINAL ||
      CurrentToken() == Token::kCONST) {
    ConsumeToken();
  }
  if (IsIdentifier()) {
    if (LookaheadToken(1) == Token::kIN) {
      result = true;
    } else if (TryParseOptionalType()) {
      if (IsIdentifier()) {
        ConsumeToken();
      }
      result = (CurrentToken() == Token::kIN);
    }
  }
  SetPosition(saved_pos);
  return result;
}


static bool ContainsAbruptCompletingStatement(SequenceNode* seq);

static bool IsAbruptCompleting(AstNode* statement) {
  return statement->IsReturnNode() ||
         statement->IsJumpNode()   ||
         statement->IsThrowNode()  ||
         (statement->IsSequenceNode() &&
             ContainsAbruptCompletingStatement(statement->AsSequenceNode()));
}


static bool ContainsAbruptCompletingStatement(SequenceNode* seq) {
  for (int i = 0; i < seq->length(); i++) {
    if (IsAbruptCompleting(seq->NodeAt(i))) {
      return true;
    }
  }
  return false;
}


void Parser::ParseStatementSequence() {
  TRACE_PARSER("ParseStatementSequence");
  const bool dead_code_allowed = true;
  bool abrupt_completing_seen = false;
  while (CurrentToken() != Token::kRBRACE) {
    const intptr_t statement_pos = TokenPos();
    AstNode* statement = ParseStatement();
    // Do not add statements with no effect (e.g., LoadLocalNode).
    if ((statement != NULL) && statement->IsLoadLocalNode()) {
      // Skip load local.
      continue;
    }
    if (statement != NULL) {
      if (!dead_code_allowed && abrupt_completing_seen) {
        ErrorMsg(statement_pos, "dead code after abrupt completing statement");
      }
      current_block_->statements->Add(statement);
      abrupt_completing_seen |= IsAbruptCompleting(statement);
    }
  }
}


// Parse nested statement of if, while, for, etc. We automatically generate
// a sequence of one statement if there are no curly braces.
// The argument 'parsing_loop_body' indicates the parsing of a loop statement.
SequenceNode* Parser::ParseNestedStatement(bool parsing_loop_body,
                                           SourceLabel* label) {
  TRACE_PARSER("ParseNestedStatement");
  if (parsing_loop_body) {
    OpenLoopBlock();
  } else {
    OpenBlock();
  }
  if (label != NULL) {
    current_block_->scope->AddLabel(label);
  }
  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else {
    AstNode* statement = ParseStatement();
    if (statement != NULL) {
      current_block_->statements->Add(statement);
    }
  }
  SequenceNode* sequence = CloseBlock();
  return sequence;
}


AstNode* Parser::ParseIfStatement(String* label_name) {
  TRACE_PARSER("ParseIfStatement");
  ASSERT(CurrentToken() == Token::kIF);
  const intptr_t if_pos = TokenPos();
  SourceLabel* label = NULL;
  if (label_name != NULL) {
    label = SourceLabel::New(if_pos, label_name, SourceLabel::kStatement);
    OpenBlock();
    current_block_->scope->AddLabel(label);
  }
  ConsumeToken();
  ExpectToken(Token::kLPAREN);
  AstNode* cond_expr = ParseExpr(kAllowConst, kConsumeCascades);
  ExpectToken(Token::kRPAREN);
  const bool parsing_loop_body = false;
  SequenceNode* true_branch = ParseNestedStatement(parsing_loop_body, NULL);
  SequenceNode* false_branch = NULL;
  if (CurrentToken() == Token::kELSE) {
    ConsumeToken();
    false_branch = ParseNestedStatement(parsing_loop_body, NULL);
  }
  AstNode* if_node = new IfNode(if_pos, cond_expr, true_branch, false_branch);
  if (label != NULL) {
    current_block_->statements->Add(if_node);
    SequenceNode* sequence = CloseBlock();
    sequence->set_label(label);
    if_node = sequence;
  }
  return if_node;
}


CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value,
                                  SourceLabel* case_label) {
  TRACE_PARSER("ParseCaseStatement");
  bool default_seen = false;
  const intptr_t case_pos = TokenPos();
  // The case expressions node sequence does not own the enclosing scope.
  SequenceNode* case_expressions = new SequenceNode(case_pos, NULL);
  while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) {
    if (CurrentToken() == Token::kCASE) {
      if (default_seen) {
        ErrorMsg("default clause must be last case");
      }
      ConsumeToken();  // Keyword case.
      const intptr_t expr_pos = TokenPos();
      AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
      AstNode* switch_expr_load = new LoadLocalNode(case_pos,
                                                    switch_expr_value);
      AstNode* case_comparison = new ComparisonNode(expr_pos,
                                                    Token::kEQ,
                                                    expr,
                                                    switch_expr_load);
      case_expressions->Add(case_comparison);
    } else {
      if (default_seen) {
        ErrorMsg("only one default clause is allowed");
      }
      ConsumeToken();  // Keyword default.
      default_seen = true;
      // The default case always succeeds.
    }
    ExpectToken(Token::kCOLON);
  }

  OpenBlock();
  bool abrupt_completing_seen = false;
  while (true) {
    // Check whether the next statement still belongs to the current case
    // clause. If we see 'case' or 'default', optionally preceeded by
    // a label, or closing brace, we stop parsing statements.
    Token::Kind next_token;
    if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) {
      next_token = LookaheadToken(2);
    } else {
      next_token = CurrentToken();
    }
    if (next_token == Token::kRBRACE) {
      // End of switch statement.
      break;
    }
    if ((next_token == Token::kCASE) || (next_token == Token::kDEFAULT)) {
      // End of this case clause. If there is a possible fall-through to
      // the next case clause, throw an implicit FallThroughError.
      if (!abrupt_completing_seen) {
        ArgumentListNode* arguments = new ArgumentListNode(TokenPos());
        arguments->Add(new LiteralNode(
            TokenPos(), Integer::ZoneHandle(Integer::New(TokenPos()))));
        current_block_->statements->Add(
            MakeStaticCall(Symbols::FallThroughError(),
                           PrivateCoreLibName(Symbols::ThrowNew()),
                           arguments));
      }
      break;
    }
    // The next statement still belongs to this case.
    AstNode* statement = ParseStatement();
    if (statement != NULL) {
      current_block_->statements->Add(statement);
      abrupt_completing_seen |= IsAbruptCompleting(statement);
    }
  }
  SequenceNode* statements = CloseBlock();
  return new CaseNode(case_pos, case_label,
      case_expressions, default_seen, switch_expr_value, statements);
}


AstNode* Parser::ParseSwitchStatement(String* label_name) {
  TRACE_PARSER("ParseSwitchStatement");
  ASSERT(CurrentToken() == Token::kSWITCH);
  const intptr_t switch_pos = TokenPos();
  SourceLabel* label =
      SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch);
  ConsumeToken();
  const bool parens_are_mandatory = false;
  bool paren_found = false;
  if (CurrentToken() == Token::kLPAREN) {
    paren_found = true;
    ConsumeToken();
  } else if (parens_are_mandatory) {
    ErrorMsg("'(' expected");
  }
  const intptr_t expr_pos = TokenPos();
  AstNode* switch_expr = ParseExpr(kAllowConst, kConsumeCascades);
  if (paren_found) {
    ExpectToken(Token::kRPAREN);
  }
  ExpectToken(Token::kLBRACE);
  OpenBlock();
  current_block_->scope->AddLabel(label);

  // Store switch expression in temporary local variable.
  LocalVariable* temp_variable =
      new LocalVariable(expr_pos,
                        Symbols::SwitchExpr(),
                        Type::ZoneHandle(Type::DynamicType()));
  current_block_->scope->AddVariable(temp_variable);
  AstNode* save_switch_expr =
      new StoreLocalNode(expr_pos, temp_variable, switch_expr);
  current_block_->statements->Add(save_switch_expr);

  // Parse case clauses
  bool default_seen = false;
  while (true) {
    // Check for statement label
    SourceLabel* case_label = NULL;
    if (IsIdentifier() && LookaheadToken(1) == Token::kCOLON) {
      // Case statements start with a label.
      String* label_name = CurrentLiteral();
      const intptr_t label_pos = TokenPos();
      ConsumeToken();  // Consume label identifier.
      ConsumeToken();  // Consume colon.
      case_label = current_block_->scope->LocalLookupLabel(*label_name);
      if (case_label == NULL) {
        // Label does not exist yet. Add it to scope of switch statement.
        case_label =
            new SourceLabel(label_pos, *label_name, SourceLabel::kCase);
        current_block_->scope->AddLabel(case_label);
      } else if (case_label->kind() == SourceLabel::kForward) {
        // We have seen a 'continue' with this label name. Resolve
        // the forward reference.
        case_label->ResolveForwardReference();
      } else {
        ErrorMsg(label_pos, "name '%s' already exists in scope",
                 label_name->ToCString());
      }
      ASSERT(case_label->kind() == SourceLabel::kCase);
    }
    if (CurrentToken() == Token::kCASE ||
        CurrentToken() == Token::kDEFAULT) {
      if (default_seen) {
        ErrorMsg("no case clauses allowed after default clause");
      }
      CaseNode* case_clause = ParseCaseClause(temp_variable, case_label);
      default_seen = case_clause->contains_default();
      current_block_->statements->Add(case_clause);
    } else if (CurrentToken() != Token::kRBRACE) {
      ErrorMsg("'case' or '}' expected");
    } else if (case_label != NULL) {
      ErrorMsg("expecting at least one case clause after label");
    } else {
      break;
    }
  }

  // Check for unresolved label references.
  SourceLabel* unresolved_label =
      current_block_->scope->CheckUnresolvedLabels();
  if (unresolved_label != NULL) {
    ErrorMsg("unresolved reference to label '%s'",
             unresolved_label->name().ToCString());
  }

  SequenceNode* switch_body = CloseBlock();
  ExpectToken(Token::kRBRACE);
  return new SwitchNode(switch_pos, label, switch_body);
}


AstNode* Parser::ParseWhileStatement(String* label_name) {
  TRACE_PARSER("ParseWhileStatement");
  const intptr_t while_pos = TokenPos();
  SourceLabel* label =
      SourceLabel::New(while_pos, label_name, SourceLabel::kWhile);
  ConsumeToken();
  ExpectToken(Token::kLPAREN);
  AstNode* cond_expr = ParseExpr(kAllowConst, kConsumeCascades);
  ExpectToken(Token::kRPAREN);
  const bool parsing_loop_body =  true;
  SequenceNode* while_body = ParseNestedStatement(parsing_loop_body, label);
  return new WhileNode(while_pos, label, cond_expr, while_body);
}


AstNode* Parser::ParseDoWhileStatement(String* label_name) {
  TRACE_PARSER("ParseDoWhileStatement");
  const intptr_t do_pos = TokenPos();
  SourceLabel* label =
      SourceLabel::New(do_pos, label_name, SourceLabel::kDoWhile);
  ConsumeToken();
  const bool parsing_loop_body =  true;
  SequenceNode* dowhile_body = ParseNestedStatement(parsing_loop_body, label);
  ExpectToken(Token::kWHILE);
  ExpectToken(Token::kLPAREN);
  AstNode* cond_expr = ParseExpr(kAllowConst, kConsumeCascades);
  ExpectToken(Token::kRPAREN);
  ExpectSemicolon();
  return new DoWhileNode(do_pos, label, cond_expr, dowhile_body);
}


AstNode* Parser::ParseForInStatement(intptr_t forin_pos,
                                     SourceLabel* label) {
  TRACE_PARSER("ParseForInStatement");
  bool is_final = (CurrentToken() == Token::kFINAL);
  if (CurrentToken() == Token::kCONST) {
    ErrorMsg("Loop variable cannot be 'const'");
  }
  const String* loop_var_name = NULL;
  LocalVariable* loop_var = NULL;
  intptr_t loop_var_pos = 0;
  if (LookaheadToken(1) == Token::kIN) {
    loop_var_pos = TokenPos();
    loop_var_name = ExpectIdentifier("variable name expected");
  } else {
    // The case without a type is handled above, so require a type here.
    const AbstractType& type =
        AbstractType::ZoneHandle(ParseConstFinalVarOrType(
            FLAG_enable_type_checks ? ClassFinalizer::kCanonicalize :
                                      ClassFinalizer::kIgnore));
    loop_var_pos = TokenPos();
    loop_var_name = ExpectIdentifier("variable name expected");
    loop_var = new LocalVariable(loop_var_pos, *loop_var_name, type);
    if (is_final) {
      loop_var->set_is_final();
    }
  }
  ExpectToken(Token::kIN);
  const intptr_t collection_pos = TokenPos();
  AstNode* collection_expr = ParseExpr(kAllowConst, kConsumeCascades);
  ExpectToken(Token::kRPAREN);

  OpenBlock();  // Implicit block around while loop.

  // Generate implicit iterator variable and add to scope.
  // We could set the type of the implicit iterator variable to Iterator<T>
  // where T is the type of the for loop variable. However, the type error
  // would refer to the compiler generated iterator and could confuse the user.
  // It is better to leave the iterator untyped and postpone the type error
  // until the loop variable is assigned to.
  const AbstractType& iterator_type = Type::ZoneHandle(Type::DynamicType());
  LocalVariable* iterator_var =
      new LocalVariable(collection_pos, Symbols::ForInIter(), iterator_type);
  current_block_->scope->AddVariable(iterator_var);

  // Generate initialization of iterator variable.
  ArgumentListNode* no_args = new ArgumentListNode(collection_pos);
  AstNode* get_iterator = new InstanceGetterNode(
      collection_pos, collection_expr, Symbols::GetIterator());
  AstNode* iterator_init =
      new StoreLocalNode(collection_pos, iterator_var, get_iterator);
  current_block_->statements->Add(iterator_init);

  // Generate while loop condition.
  AstNode* iterator_moveNext = new InstanceCallNode(
      collection_pos,
      new LoadLocalNode(collection_pos, iterator_var),
      Symbols::MoveNext(),
      no_args);

  // Parse the for loop body. Ideally, we would use ParseNestedStatement()
  // here, but that does not work well because we have to insert an implicit
  // variable assignment and potentially a variable declaration in the
  // loop body.
  OpenLoopBlock();
  current_block_->scope->AddLabel(label);

  AstNode* iterator_current = new InstanceGetterNode(
      collection_pos,
      new LoadLocalNode(collection_pos, iterator_var),
      Symbols::Current());

  // Generate assignment of next iterator value to loop variable.
  AstNode* loop_var_assignment = NULL;
  if (loop_var != NULL) {
    // The for loop declares a new variable. Add it to the loop body scope.
    current_block_->scope->AddVariable(loop_var);
    loop_var_assignment =
        new StoreLocalNode(loop_var_pos, loop_var, iterator_current);
  } else {
    AstNode* loop_var_primary =
        ResolveIdent(loop_var_pos, *loop_var_name, false);
    ASSERT(!loop_var_primary->IsPrimaryNode());
    loop_var_assignment = CreateAssignmentNode(
        loop_var_primary, iterator_current, loop_var_name, loop_var_pos);
    ASSERT(loop_var_assignment != NULL);
  }
  current_block_->statements->Add(loop_var_assignment);

  // Now parse the for-in loop statement or block.
  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else {
    AstNode* statement = ParseStatement();
    if (statement != NULL) {
      current_block_->statements->Add(statement);
    }
  }

  SequenceNode* for_loop_statement = CloseBlock();

  AstNode* while_statement =
      new WhileNode(forin_pos, label, iterator_moveNext, for_loop_statement);
  current_block_->statements->Add(while_statement);

  return CloseBlock();  // Implicit block around while loop.
}


AstNode* Parser::ParseForStatement(String* label_name) {
  TRACE_PARSER("ParseForStatement");
  const intptr_t for_pos = TokenPos();
  ConsumeToken();
  ExpectToken(Token::kLPAREN);
  SourceLabel* label = SourceLabel::New(for_pos, label_name, SourceLabel::kFor);
  if (IsForInStatement()) {
    return ParseForInStatement(for_pos, label);
  }
  // Open a block that contains the loop variable. Make it a loop block so
  // that we allocate a new context if the loop variable is captured.
  OpenLoopBlock();
  AstNode* initializer = NULL;
  const intptr_t init_pos = TokenPos();
  LocalScope* init_scope = current_block_->scope;
  if (CurrentToken() != Token::kSEMICOLON) {
    if (IsVariableDeclaration()) {
      initializer = ParseVariableDeclarationList();
    } else {
      initializer = ParseExpr(kAllowConst, kConsumeCascades);
    }
  }
  ExpectSemicolon();
  AstNode* condition = NULL;
  if (CurrentToken() != Token::kSEMICOLON) {
    condition = ParseExpr(kAllowConst, kConsumeCascades);
  }
  ExpectSemicolon();
  AstNode* increment = NULL;
  const intptr_t incr_pos = TokenPos();
  if (CurrentToken() != Token::kRPAREN) {
    increment = ParseExprList();
  }
  ExpectToken(Token::kRPAREN);
  const bool parsing_loop_body =  true;
  SequenceNode* body = ParseNestedStatement(parsing_loop_body, label);

  // Check whether any of the variables in the initializer part of
  // the for statement are captured by a closure. If so, we insert a
  // node that creates a new Context for the loop variable before
  // the increment expression is evaluated.
  for (int i = 0; i < init_scope->num_variables(); i++) {
    if (init_scope->VariableAt(i)->is_captured() &&
        (init_scope->VariableAt(i)->owner() == init_scope)) {
      SequenceNode* incr_sequence = new SequenceNode(incr_pos, NULL);
      incr_sequence->Add(new CloneContextNode(for_pos));
      if (increment != NULL) {
        incr_sequence->Add(increment);
      }
      increment = incr_sequence;
      break;
    }
  }
  AstNode* for_node =
      new ForNode(for_pos,
                  label,
                  NodeAsSequenceNode(init_pos, initializer, NULL),
                  condition,
                  NodeAsSequenceNode(incr_pos, increment, NULL),
                  body);
  current_block_->statements->Add(for_node);
  return CloseBlock();
}


// Calling VM-internal helpers, uses implementation core library.
AstNode* Parser::MakeStaticCall(const String& cls_name,
                                const String& func_name,
                                ArgumentListNode* arguments) {
  const Class& cls = Class::Handle(LookupCoreClass(cls_name));
  ASSERT(!cls.IsNull());
  const Function& func = Function::ZoneHandle(
      Resolver::ResolveStatic(cls,
                              func_name,
                              arguments->length(),
                              arguments->names(),
                              Resolver::kIsQualified));
  ASSERT(!func.IsNull());
  return new StaticCallNode(arguments->token_pos(), func, arguments);
}


AstNode* Parser::MakeAssertCall(intptr_t begin, intptr_t end) {
  ArgumentListNode* arguments = new ArgumentListNode(begin);
  arguments->Add(new LiteralNode(begin,
      Integer::ZoneHandle(Integer::New(begin))));
  arguments->Add(new LiteralNode(end,
      Integer::ZoneHandle(Integer::New(end))));
  return MakeStaticCall(Symbols::AssertionError(),
                        PrivateCoreLibName(Symbols::ThrowNew()),
                        arguments);
}


AstNode* Parser::InsertClosureCallNodes(AstNode* condition) {
  if (condition->IsClosureNode() ||
      (condition->IsStoreLocalNode() &&
       condition->AsStoreLocalNode()->value()->IsClosureNode())) {
    EnsureSavedCurrentContext();
    // Function literal in assert implies a call.
    const intptr_t pos = condition->token_pos();
    condition = new ClosureCallNode(pos, condition, new ArgumentListNode(pos));
  } else if (condition->IsConditionalExprNode()) {
    ConditionalExprNode* cond_expr = condition->AsConditionalExprNode();
    cond_expr->set_true_expr(InsertClosureCallNodes(cond_expr->true_expr()));
    cond_expr->set_false_expr(InsertClosureCallNodes(cond_expr->false_expr()));
  }
  return condition;
}


AstNode* Parser::ParseAssertStatement() {
  TRACE_PARSER("ParseAssertStatement");
  ConsumeToken();  // Consume assert keyword.
  ExpectToken(Token::kLPAREN);
  const intptr_t condition_pos = TokenPos();
  if (!FLAG_enable_asserts && !FLAG_enable_type_checks) {
    SkipExpr();
    ExpectToken(Token::kRPAREN);
    return NULL;
  }
  AstNode* condition = ParseExpr(kAllowConst, kConsumeCascades);
  const intptr_t condition_end = TokenPos();
  ExpectToken(Token::kRPAREN);
  condition = InsertClosureCallNodes(condition);
  condition = new UnaryOpNode(condition_pos, Token::kNOT, condition);
  AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end);
  return new IfNode(condition_pos,
                    condition,
                    NodeAsSequenceNode(condition_pos, assert_throw, NULL),
                    NULL);
}


struct CatchParamDesc {
  CatchParamDesc()
      : token_pos(0), type(NULL), var(NULL) { }
  intptr_t token_pos;
  const AbstractType* type;
  const String* var;
};


// Populate local scope of the catch block with the catch parameters.
void Parser::AddCatchParamsToScope(const CatchParamDesc& exception_param,
                                   const CatchParamDesc& stack_trace_param,
                                   LocalScope* scope) {
  if (exception_param.var != NULL) {
    LocalVariable* var = new LocalVariable(exception_param.token_pos,
                                           *exception_param.var,
                                           *exception_param.type);
    var->set_is_final();
    bool added_to_scope = scope->AddVariable(var);
    ASSERT(added_to_scope);
  }
  if (stack_trace_param.var != NULL) {
    LocalVariable* var = new LocalVariable(TokenPos(),
                                           *stack_trace_param.var,
                                           *stack_trace_param.type);
    var->set_is_final();
    bool added_to_scope = scope->AddVariable(var);
    if (!added_to_scope) {
      ErrorMsg(stack_trace_param.token_pos,
               "name '%s' already exists in scope",
               stack_trace_param.var->ToCString());
    }
  }
}


SequenceNode* Parser::ParseFinallyBlock() {
  TRACE_PARSER("ParseFinallyBlock");
  OpenBlock();
  ExpectToken(Token::kLBRACE);
  ParseStatementSequence();
  ExpectToken(Token::kRBRACE);
  SequenceNode* finally_block = CloseBlock();
  return finally_block;
}


void Parser::PushTryBlock(Block* try_block) {
  intptr_t try_index = AllocateTryIndex();
  TryBlocks* block = new TryBlocks(try_block, try_blocks_list_, try_index);
  try_blocks_list_ = block;
}


Parser::TryBlocks* Parser::PopTryBlock() {
  TryBlocks* innermost_try_block = try_blocks_list_;
  try_blocks_list_ = try_blocks_list_->outer_try_block();
  return innermost_try_block;
}


void Parser::AddNodeForFinallyInlining(AstNode* node) {
  if (node == NULL) {
    return;
  }
  ASSERT(node->IsReturnNode() || node->IsJumpNode());
  TryBlocks* iterator = try_blocks_list_;
  while (iterator != NULL) {
    // For continue and break node check if the target label is in scope.
    if (node->IsJumpNode()) {
      SourceLabel* label = node->AsJumpNode()->label();
      ASSERT(label != NULL);
      LocalScope* try_scope = iterator->try_block()->scope;
      // If the label is defined in a scope which is a child (nested scope)
      // of the try scope then we are not breaking out of this try block
      // so we do not need to inline the finally code. Otherwise we need
      // to inline the finally code of this try block and then move on to the
      // next outer try block.
      if (label->owner()->IsNestedWithin(try_scope)) {
        break;
      }
    }
    iterator->AddNodeForFinallyInlining(node);
    iterator = iterator->outer_try_block();
  }
}


// Add the inlined finally block to the specified node.
void Parser::AddFinallyBlockToNode(AstNode* node,
                                   InlinedFinallyNode* finally_node) {
  if (node->IsReturnNode()) {
    node->AsReturnNode()->AddInlinedFinallyNode(finally_node);
  } else {
    ASSERT(node->IsJumpNode());
    node->AsJumpNode()->AddInlinedFinallyNode(finally_node);
  }
}


AstNode* Parser::ParseTryStatement(String* label_name) {
  TRACE_PARSER("ParseTryStatement");

  // We create three stack slots for exceptions here:
  // ':saved_try_context_var' - Used to save the context before start of the try
  //                            block. The context register is restored from
  //                            this slot before processing the catch block
  //                            handler.
  // ':exception_var' - Used to save the current exception object that was
  //                    thrown.
  // ':stacktrace_var' - Used to save the current stack trace object into which
  //                     the stack trace was copied into when an exception was
  //                     thrown.
  // :exception_var and :stacktrace_var get set with the exception object
  // and the stacktrace object when an exception is thrown.
  // These three implicit variables can never be captured variables.
  LocalVariable* context_var =
      current_block_->scope->LocalLookupVariable(Symbols::SavedTryContextVar());
  if (context_var == NULL) {
    context_var = new LocalVariable(TokenPos(),
                                    Symbols::SavedTryContextVar(),
                                    Type::ZoneHandle(Type::DynamicType()));
    current_block_->scope->AddVariable(context_var);
  }
  LocalVariable* catch_excp_var =
      current_block_->scope->LocalLookupVariable(Symbols::ExceptionVar());
  if (catch_excp_var == NULL) {
    catch_excp_var = new LocalVariable(TokenPos(),
                                       Symbols::ExceptionVar(),
                                       Type::ZoneHandle(Type::DynamicType()));
    current_block_->scope->AddVariable(catch_excp_var);
  }
  LocalVariable* catch_trace_var =
      current_block_->scope->LocalLookupVariable(Symbols::StacktraceVar());
  if (catch_trace_var == NULL) {
    catch_trace_var = new LocalVariable(TokenPos(),
                                        Symbols::StacktraceVar(),
                                        Type::ZoneHandle(Type::DynamicType()));
    current_block_->scope->AddVariable(catch_trace_var);
  }

  const intptr_t try_pos = TokenPos();
  ConsumeToken();  // Consume the 'try'.

  SourceLabel* try_label = NULL;
  if (label_name != NULL) {
    try_label = SourceLabel::New(try_pos, label_name, SourceLabel::kStatement);
    OpenBlock();
    current_block_->scope->AddLabel(try_label);
  }

  // Now parse the 'try' block.
  OpenBlock();
  Block* current_try_block = current_block_;
  PushTryBlock(current_try_block);
  ExpectToken(Token::kLBRACE);
  ParseStatementSequence();
  ExpectToken(Token::kRBRACE);
  SequenceNode* try_block = CloseBlock();

  // Now create a label for the end of catch block processing so that we can
  // jump over the catch block code after executing the try block.
  SourceLabel* end_catch_label =
      SourceLabel::New(TokenPos(), NULL, SourceLabel::kCatch);

  // Now parse the 'catch' blocks if any and merge all of them into
  // an if-then sequence of the different types specified using the 'is'
  // operator.
  bool catch_seen = false;
  bool generic_catch_seen = false;
  SequenceNode* catch_handler_list = NULL;
  const intptr_t handler_pos = TokenPos();
  OpenBlock();  // Start the catch block sequence.
  current_block_->scope->AddLabel(end_catch_label);
  const GrowableObjectArray& handler_types =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  while ((CurrentToken() == Token::kCATCH) || IsLiteral("on")) {
    const intptr_t catch_pos = TokenPos();
    CatchParamDesc exception_param;
    CatchParamDesc stack_trace_param;
    catch_seen = true;
    if (IsLiteral("on")) {
      ConsumeToken();
      exception_param.type = &AbstractType::ZoneHandle(
          ParseType(ClassFinalizer::kCanonicalize));
    } else {
      exception_param.type =
          &AbstractType::ZoneHandle(Type::DynamicType());
    }
    if (CurrentToken() == Token::kCATCH) {
      ConsumeToken();  // Consume the 'catch'.
      ExpectToken(Token::kLPAREN);
      exception_param.token_pos = TokenPos();
      exception_param.var = ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kCOMMA) {
        ConsumeToken();
        // TODO(hausner): Make implicit type be StackTrace, not dynamic.
        stack_trace_param.type =
            &AbstractType::ZoneHandle(Type::DynamicType());
        stack_trace_param.token_pos = TokenPos();
        stack_trace_param.var = ExpectIdentifier("identifier expected");
      }
      ExpectToken(Token::kRPAREN);
    }

    // If a generic "catch all" statement has already been seen then all
    // subsequent catch statements are dead. We issue an error for now,
    // it might make sense to turn this into a warning.
    if (generic_catch_seen) {
      ErrorMsg("a generic 'catch all' statement already exists for this "
               "try block. All subsequent catch statements are dead code");
    }
    OpenBlock();
    AddCatchParamsToScope(exception_param,
                          stack_trace_param,
                          current_block_->scope);

    // Parse the individual catch handler code and add an unconditional
    // JUMP to the end of the try block.
    ExpectToken(Token::kLBRACE);
    OpenBlock();

    if (exception_param.var != NULL) {
      // Generate code to load the exception object (:exception_var) into
      // the exception variable specified in this block.
      LocalVariable* var = LookupLocalScope(*exception_param.var);
      ASSERT(var != NULL);
      ASSERT(catch_excp_var != NULL);
      current_block_->statements->Add(
          new StoreLocalNode(catch_pos, var,
                             new LoadLocalNode(catch_pos, catch_excp_var)));
    }
    if (stack_trace_param.var != NULL) {
      // A stack trace variable is specified in this block, so generate code
      // to load the stack trace object (:stacktrace_var) into the stack trace
      // variable specified in this block.
      ArgumentListNode* no_args = new ArgumentListNode(catch_pos);
      LocalVariable* trace = LookupLocalScope(*stack_trace_param.var);
      ASSERT(catch_trace_var != NULL);
      current_block_->statements->Add(
          new StoreLocalNode(catch_pos, trace,
                             new LoadLocalNode(catch_pos, catch_trace_var)));
      current_block_->statements->Add(
          new InstanceCallNode(
              catch_pos,
              new LoadLocalNode(catch_pos, trace),
              PrivateCoreLibName(Symbols::_setupFullStackTrace()),
              no_args));
    }

    ParseStatementSequence();  // Parse the catch handler code.
    current_block_->statements->Add(
        new JumpNode(catch_pos, Token::kCONTINUE, end_catch_label));
    SequenceNode* catch_handler = CloseBlock();
    ExpectToken(Token::kRBRACE);

    if (!exception_param.type->IsDynamicType()) {  // Has a type specification.
      // Now form an 'if type check' as an exception type exists in
      // the catch specifier.
      if (!exception_param.type->IsInstantiated() &&
          (current_block_->scope->function_level() > 0)) {
        // Make sure that the instantiator is captured.
        CaptureInstantiator();
      }
      TypeNode* exception_type = new TypeNode(catch_pos, *exception_param.type);
      AstNode* exception_var = new LoadLocalNode(catch_pos, catch_excp_var);
      if (!exception_type->type().IsInstantiated()) {
        EnsureExpressionTemp();
      }
      AstNode* type_cond_expr = new ComparisonNode(
          catch_pos, Token::kIS, exception_var, exception_type);
      current_block_->statements->Add(
          new IfNode(catch_pos, type_cond_expr, catch_handler, NULL));

      // Do not add uninstantiated types (e.g. type parameter T or
      // generic type List<T>), since the debugger won't be able to
      // instantiate it when walking the stack.
      // This means that the debugger is not able to determine whether
      // an exception is caught if the catch clause uses generic types.
      // It will report the exception as uncaught when in fact it might
      // be caught and handled when we unwind the stack.
      if (exception_param.type->IsInstantiated()) {
        handler_types.Add(*exception_param.type);
      }
    } else {
      // No exception type exists in the catch specifier so execute the
      // catch handler code unconditionally.
      current_block_->statements->Add(catch_handler);
      generic_catch_seen = true;
      // This catch clause will handle all exceptions. We can safely forget
      // all previous catch clause types.
      handler_types.SetLength(0);
      handler_types.Add(*exception_param.type);
    }
    SequenceNode* catch_clause = CloseBlock();

    // Add this individual catch handler to the catch handlers list.
    current_block_->statements->Add(catch_clause);
  }
  catch_handler_list = CloseBlock();
  TryBlocks* inner_try_block = PopTryBlock();
  intptr_t try_index = inner_try_block->try_index();
  TryBlocks* outer_try_block = try_blocks_list_;
  intptr_t outer_try_index = (outer_try_block != NULL)
      ? outer_try_block->try_index()
      : CatchClauseNode::kInvalidTryIndex;

  // Finally parse the 'finally' block.
  SequenceNode* finally_block = NULL;
  if (CurrentToken() == Token::kFINALLY) {
    current_function().set_has_finally(true);
    ConsumeToken();  // Consume the 'finally'.
    const intptr_t finally_pos = TokenPos();
    // Add the finally block to the exit points recorded so far.
    intptr_t node_index = 0;
    AstNode* node_to_inline =
        inner_try_block->GetNodeToInlineFinally(node_index);
    while (node_to_inline != NULL) {
      finally_block = ParseFinallyBlock();
      InlinedFinallyNode* node = new InlinedFinallyNode(finally_pos,
                                                        finally_block,
                                                        context_var,
                                                        outer_try_index);
      AddFinallyBlockToNode(node_to_inline, node);
      node_index += 1;
      node_to_inline = inner_try_block->GetNodeToInlineFinally(node_index);
      tokens_iterator_.SetCurrentPosition(finally_pos);
    }
    finally_block = ParseFinallyBlock();
  } else {
    if (!catch_seen) {
      ErrorMsg("catch or finally clause expected");
    }
  }

  if (!generic_catch_seen) {
    // No generic catch handler exists so rethrow the exception so that
    // the next catch handler can deal with it.
    catch_handler_list->Add(
        new ThrowNode(handler_pos,
                      new LoadLocalNode(handler_pos, catch_excp_var),
                      new LoadLocalNode(handler_pos, catch_trace_var)));
  }
  CatchClauseNode* catch_block =
      new CatchClauseNode(handler_pos,
                          catch_handler_list,
                          Array::ZoneHandle(Array::MakeArray(handler_types)),
                          context_var,
                          catch_excp_var,
                          catch_trace_var,
                          (finally_block != NULL)
                              ? AllocateTryIndex()
                              : CatchClauseNode::kInvalidTryIndex);

  // Now create the try/catch ast node and return it. If there is a label
  // on the try/catch, close the block that's embedding the try statement
  // and attach the label to it.
  AstNode* try_catch_node =
      new TryCatchNode(try_pos, try_block, end_catch_label,
                       context_var, catch_block, finally_block, try_index);

  if (try_label != NULL) {
    current_block_->statements->Add(try_catch_node);
    SequenceNode* sequence = CloseBlock();
    sequence->set_label(try_label);
    try_catch_node = sequence;
  }
  return try_catch_node;
}


AstNode* Parser::ParseJump(String* label_name) {
  TRACE_PARSER("ParseJump");
  ASSERT(CurrentToken() == Token::kBREAK || CurrentToken() == Token::kCONTINUE);
  Token::Kind jump_kind = CurrentToken();
  const intptr_t jump_pos = TokenPos();
  SourceLabel* target = NULL;
  ConsumeToken();
  if (IsIdentifier()) {
    // Explicit label after break/continue.
    const String& target_name = *CurrentLiteral();
    ConsumeToken();
    // Handle pathological cases first.
    if (label_name != NULL && target_name.Equals(*label_name)) {
      if (jump_kind == Token::kCONTINUE) {
        ErrorMsg(jump_pos, "'continue' jump to label '%s' is illegal",
                 target_name.ToCString());
      }
      // L: break L; is a no-op.
      return NULL;
    }
    target = current_block_->scope->LookupLabel(target_name);
    if (target == NULL && jump_kind == Token::kCONTINUE) {
      // Either a reference to a non-existent label, or a forward reference
      // to a case label that we haven't seen yet. If we are inside a switch
      // statement, create a "forward reference" label in the scope of
      // the switch statement.
      LocalScope* switch_scope = current_block_->scope->LookupSwitchScope();
      if (switch_scope != NULL) {
        // We found a switch scope. Enter a forward reference to the label.
        target = new SourceLabel(
            TokenPos(), target_name, SourceLabel::kForward);
        switch_scope->AddLabel(target);
      }
    }
    if (target == NULL) {
      ErrorMsg(jump_pos, "label '%s' not found", target_name.ToCString());
    }
  } else {
    target = current_block_->scope->LookupInnermostLabel(jump_kind);
    if (target == NULL) {
      ErrorMsg(jump_pos, "'%s' is illegal here", Token::Str(jump_kind));
    }
  }
  ASSERT(target != NULL);
  if (jump_kind == Token::kCONTINUE) {
    if (target->kind() == SourceLabel::kSwitch) {
      ErrorMsg(jump_pos, "'continue' jump to switch statement is illegal");
    } else if (target->kind() == SourceLabel::kStatement) {
      ErrorMsg(jump_pos, "'continue' jump to label '%s' is illegal",
               target->name().ToCString());
    }
  }
  if (jump_kind == Token::kBREAK && target->kind() == SourceLabel::kCase) {
    ErrorMsg(jump_pos, "'break' to case clause label is illegal");
  }
  if (target->FunctionLevel() != current_block_->scope->function_level()) {
    ErrorMsg(jump_pos, "'%s' target must be in same function context",
             Token::Str(jump_kind));
  }
  return new JumpNode(jump_pos, jump_kind, target);
}


AstNode* Parser::ParseStatement() {
  TRACE_PARSER("ParseStatement");
  AstNode* statement = NULL;
  intptr_t label_pos = 0;
  String* label_name = NULL;
  if (IsIdentifier()) {
    if (LookaheadToken(1) == Token::kCOLON) {
      // Statement starts with a label.
      label_name = CurrentLiteral();
      label_pos = TokenPos();
      ASSERT(label_pos > 0);
      ConsumeToken();  // Consume identifier.
      ConsumeToken();  // Consume colon.
    }
  }
  const intptr_t statement_pos = TokenPos();

  if (CurrentToken() == Token::kWHILE) {
    statement = ParseWhileStatement(label_name);
  } else if (CurrentToken() == Token::kFOR) {
    statement = ParseForStatement(label_name);
  } else if (CurrentToken() == Token::kDO) {
    statement = ParseDoWhileStatement(label_name);
  } else if (CurrentToken() == Token::kSWITCH) {
    statement = ParseSwitchStatement(label_name);
  } else if (CurrentToken() == Token::kTRY) {
    statement = ParseTryStatement(label_name);
  } else if (CurrentToken() == Token::kRETURN) {
    const intptr_t return_pos = TokenPos();
    ConsumeToken();
    if (CurrentToken() != Token::kSEMICOLON) {
      if (current_function().IsConstructor() &&
          (current_block_->scope->function_level() == 0)) {
        ErrorMsg(return_pos, "return of a value not allowed in constructors");
      }
      AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
      statement = new ReturnNode(statement_pos, expr);
    } else {
      statement = new ReturnNode(statement_pos);
    }
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kIF) {
    statement = ParseIfStatement(label_name);
  } else if (CurrentToken() == Token::kASSERT) {
    statement = ParseAssertStatement();
    ExpectSemicolon();
  } else if (IsVariableDeclaration()) {
    statement = ParseVariableDeclarationList();
    ExpectSemicolon();
  } else if (IsFunctionDeclaration()) {
    statement = ParseFunctionStatement(false);
  } else if (CurrentToken() == Token::kLBRACE) {
    SourceLabel* label = NULL;
    OpenBlock();
    if (label_name != NULL) {
      label = SourceLabel::New(label_pos, label_name, SourceLabel::kStatement);
      current_block_->scope->AddLabel(label);
    }
    ConsumeToken();
    ParseStatementSequence();
    statement = CloseBlock();
    if (label != NULL) {
      statement->AsSequenceNode()->set_label(label);
    }
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kBREAK) {
    statement = ParseJump(label_name);
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kCONTINUE) {
    statement = ParseJump(label_name);
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kSEMICOLON) {
    // Empty statement, nothing to do.
    ConsumeToken();
  } else if ((CurrentToken() == Token::kRETHROW) ||
            ((CurrentToken() == Token::kTHROW) &&
             (LookaheadToken(1) == Token::kSEMICOLON))) {
    // Rethrow of current exception. Throwing of an exception object
    // is an expression and is handled in ParseExpr().
    // TODO(hausner): remove support for 'throw;'.
    ConsumeToken();
    ExpectSemicolon();
    // Check if it is ok to do a rethrow.
    SourceLabel* label = current_block_->scope->LookupInnermostCatchLabel();
    if (label == NULL ||
        label->FunctionLevel() != current_block_->scope->function_level()) {
      ErrorMsg(statement_pos, "rethrow of an exception is not valid here");
    }
    ASSERT(label->owner() != NULL);
    LocalScope* scope = label->owner()->parent();
    ASSERT(scope != NULL);
    LocalVariable* excp_var =
        scope->LocalLookupVariable(Symbols::ExceptionVar());
    ASSERT(excp_var != NULL);
    LocalVariable* trace_var =
        scope->LocalLookupVariable(Symbols::StacktraceVar());
    ASSERT(trace_var != NULL);
    statement = new ThrowNode(statement_pos,
                              new LoadLocalNode(statement_pos, excp_var),
                              new LoadLocalNode(statement_pos, trace_var));
  } else {
    statement = ParseExpr(kAllowConst, kConsumeCascades);
    ExpectSemicolon();
  }
  return statement;
}


RawError* Parser::FormatErrorWithAppend(const Error& prev_error,
                                        const Script& script,
                                        intptr_t token_pos,
                                        const char* message_header,
                                        const char* format,
                                        va_list args) {
  const String& msg1 = String::Handle(String::New(prev_error.ToErrorCString()));
  const String& msg2 = String::Handle(
      FormatMessage(script, token_pos, message_header, format, args));
  return LanguageError::New(String::Handle(String::Concat(msg1, msg2)));
}


RawError* Parser::FormatError(const Script& script,
                              intptr_t token_pos,
                              const char* message_header,
                              const char* format,
                              va_list args) {
  const String& msg = String::Handle(
      FormatMessage(script, token_pos, message_header, format, args));
  return LanguageError::New(msg);
}


RawError* Parser::FormatErrorMsg(const Script& script,
                                 intptr_t token_pos,
                                 const char* message_header,
                                 const char* format, ...) {
  va_list args;
  va_start(args, format);
  const Error& error = Error::Handle(
      FormatError(script, token_pos, message_header, format, args));
  va_end(args);
  return error.raw();
}


RawString* Parser::FormatMessage(const Script& script,
                                 intptr_t token_pos,
                                 const char* message_header,
                                 const char* format, va_list args) {
  String& result = String::Handle();
  const String& msg = String::Handle(String::NewFormattedV(format, args));
  if (!script.IsNull()) {
    const String& script_url = String::Handle(script.url());
    if (token_pos >= 0) {
      intptr_t line, column;
      script.GetTokenLocation(token_pos, &line, &column);
      result = String::NewFormatted("'%s': %s: line %" Pd " pos %" Pd ": ",
                                    script_url.ToCString(),
                                    message_header,
                                    line,
                                    column);
      // Append the formatted error or warning message.
      result = String::Concat(result, msg);
      const String& new_line = String::Handle(String::New("\n"));
      // Append the source line.
      const String& script_line = String::Handle(script.GetLine(line));
      ASSERT(!script_line.IsNull());
      result = String::Concat(result, new_line);
      result = String::Concat(result, script_line);
      result = String::Concat(result, new_line);
      // Append the column marker.
      const String& column_line = String::Handle(
          String::NewFormatted("%*s\n", static_cast<int>(column), "^"));
      result = String::Concat(result, column_line);
    } else {
      // Token position is unknown.
      result = String::NewFormatted("'%s': %s: ",
                                    script_url.ToCString(),
                                    message_header);
      result = String::Concat(result, msg);
    }
  } else {
    // Script is unknown.
    // Append the formatted error or warning message.
    result = msg.raw();
  }
  return result.raw();
}


void Parser::PrintMessage(const Script& script,
                          intptr_t token_pos,
                          const char* message_header,
                          const char* format, ...) {
  va_list args;
  va_start(args, format);
  const String& buf = String::Handle(
      FormatMessage(script, token_pos, message_header, format, args));
  va_end(args);
  OS::Print("%s", buf.ToCString());
}


void Parser::ErrorMsg(intptr_t token_pos, const char* format, ...) const {
  va_list args;
  va_start(args, format);
  const Error& error = Error::Handle(
      FormatError(script_, token_pos, "Error", format, args));
  va_end(args);
  isolate()->long_jump_base()->Jump(1, error);
  UNREACHABLE();
}


void Parser::ErrorMsg(const char* format, ...) {
  va_list args;
  va_start(args, format);
  const Error& error = Error::Handle(
      FormatError(script_, TokenPos(), "Error", format, args));
  va_end(args);
  isolate()->long_jump_base()->Jump(1, error);
  UNREACHABLE();
}


void Parser::ErrorMsg(const Error& error) {
  Isolate::Current()->long_jump_base()->Jump(1, error);
  UNREACHABLE();
}


void Parser::AppendErrorMsg(
      const Error& prev_error, intptr_t token_pos, const char* format, ...) {
  va_list args;
  va_start(args, format);
  const Error& error = Error::Handle(FormatErrorWithAppend(
      prev_error, script_, token_pos, "Error", format, args));
  va_end(args);
  isolate()->long_jump_base()->Jump(1, error);
  UNREACHABLE();
}


void Parser::Warning(intptr_t token_pos, const char* format, ...) {
  if (FLAG_silent_warnings) return;
  va_list args;
  va_start(args, format);
  const Error& error = Error::Handle(
      FormatError(script_, token_pos, "Warning", format, args));
  va_end(args);
  if (FLAG_warning_as_error) {
    isolate()->long_jump_base()->Jump(1, error);
    UNREACHABLE();
  } else {
    OS::Print("%s", error.ToErrorCString());
  }
}


void Parser::Warning(const char* format, ...) {
  if (FLAG_silent_warnings) return;
  va_list args;
  va_start(args, format);
  const Error& error = Error::Handle(
      FormatError(script_, TokenPos(), "Warning", format, args));
  va_end(args);
  if (FLAG_warning_as_error) {
    isolate()->long_jump_base()->Jump(1, error);
    UNREACHABLE();
  } else {
    OS::Print("%s", error.ToErrorCString());
  }
}


void Parser::Unimplemented(const char* msg) {
  ErrorMsg(TokenPos(), "%s", msg);
}


void Parser::ExpectToken(Token::Kind token_expected) {
  if (CurrentToken() != token_expected) {
    ErrorMsg("'%s' expected", Token::Str(token_expected));
  }
  ConsumeToken();
}


void Parser::ExpectSemicolon() {
  if (CurrentToken() != Token::kSEMICOLON) {
    ErrorMsg("semicolon expected");
  }
  ConsumeToken();
}


void Parser::UnexpectedToken() {
  ErrorMsg("unexpected token '%s'",
           CurrentToken() == Token::kIDENT ?
               CurrentLiteral()->ToCString() : Token::Str(CurrentToken()));
}


String* Parser::ExpectUserDefinedTypeIdentifier(const char* msg) {
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("%s", msg);
  }
  String* ident = CurrentLiteral();
  if (ident->Equals("dynamic")) {
    ErrorMsg("%s", msg);
  }
  ConsumeToken();
  return ident;
}


// Check whether current token is an identifier or a built-in identifier.
String* Parser::ExpectIdentifier(const char* msg) {
  if (!IsIdentifier()) {
    ErrorMsg("%s", msg);
  }
  String* ident = CurrentLiteral();
  ConsumeToken();
  return ident;
}


bool Parser::IsLiteral(const char* literal) {
  return IsIdentifier() && CurrentLiteral()->Equals(literal);
}


static bool IsIncrementOperator(Token::Kind token) {
  return token == Token::kINCR || token == Token::kDECR;
}


static bool IsPrefixOperator(Token::Kind token) {
  return (token == Token::kSUB) ||
         (token == Token::kNOT) ||
         (token == Token::kBIT_NOT);
}


SequenceNode* Parser::NodeAsSequenceNode(intptr_t sequence_pos,
                                         AstNode* node,
                                         LocalScope* scope) {
  if ((node == NULL) || !node->IsSequenceNode()) {
    SequenceNode* sequence = new SequenceNode(sequence_pos, scope);
    if (node != NULL) {
      sequence->Add(node);
    }
    return sequence;
  }
  return node->AsSequenceNode();
}


AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type) {
  ASSERT(type.IsMalformed());
  ArgumentListNode* arguments = new ArgumentListNode(type_pos);
  // Location argument.
  arguments->Add(new LiteralNode(
      type_pos, Integer::ZoneHandle(Integer::New(type_pos))));
  // Src value argument.
  arguments->Add(new LiteralNode(type_pos, Instance::ZoneHandle()));
  // Dst type name argument.
  arguments->Add(new LiteralNode(type_pos, Symbols::Malformed()));
  // Dst name argument.
  arguments->Add(new LiteralNode(type_pos, Symbols::Empty()));
  // Malformed type error.
  const Error& error = Error::Handle(type.malformed_error());
  arguments->Add(new LiteralNode(type_pos, String::ZoneHandle(
      Symbols::New(error.ToErrorCString()))));
  return MakeStaticCall(Symbols::TypeError(),
                        PrivateCoreLibName(Symbols::ThrowNew()),
                        arguments);
}


// TODO(regis): Providing the argument values is not always feasible, since
// evaluating them could throw an error.
// Should NoSuchMethodError reflect the argument count and names instead of
// argument values? Or should the spec specify a different evaluation order?
AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos,
                                        const Class& cls,
                                        const String& function_name,
                                        InvocationMirror::Call im_call,
                                        InvocationMirror::Type im_type) {
  ArgumentListNode* arguments = new ArgumentListNode(call_pos);
  // Object receiver.
  // TODO(regis): For now, we pass a class literal of the unresolved
  // method's owner, but this is not specified and will probably change.
  Type& type = Type::ZoneHandle(
      Type::New(cls, TypeArguments::Handle(), call_pos, Heap::kOld));
  type ^= ClassFinalizer::FinalizeType(
      current_class(), type, ClassFinalizer::kCanonicalize);
  arguments->Add(new LiteralNode(call_pos, type));
  // String memberName.
  arguments->Add(new LiteralNode(
      call_pos, String::ZoneHandle(Symbols::New(function_name))));
  // Smi invocation_type.
  if (cls.IsTopLevel()) {
    ASSERT(im_call == InvocationMirror::kStatic ||
           im_call == InvocationMirror::kTopLevel);
    im_call = InvocationMirror::kTopLevel;
  }
  arguments->Add(new LiteralNode(call_pos, Smi::ZoneHandle(
      Smi::New(InvocationMirror::EncodeType(im_call, im_type)))));
  // List arguments.
  arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle()));
  // List argumentNames.
  arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle()));
  // List existingArgumentNames.
  // Check if there exists a function with the same name.
  Function& function =
     Function::Handle(cls.LookupStaticFunction(function_name));
  if (function.IsNull()) {
    // TODO(srdjan): Store argument values into the argument list.
    arguments->Add(new LiteralNode(call_pos, Array::ZoneHandle()));
  } else {
    const int total_num_parameters = function.NumParameters();
    Array& array =
        Array::ZoneHandle(Array::New(total_num_parameters, Heap::kOld));
    // Skip receiver.
    for (int i = 0; i < total_num_parameters; i++) {
      array.SetAt(i, String::Handle(function.ParameterNameAt(i)));
    }
    arguments->Add(new LiteralNode(call_pos, array));
  }
  return MakeStaticCall(Symbols::NoSuchMethodError(),
                        PrivateCoreLibName(Symbols::ThrowNew()),
                        arguments);
}


AstNode* Parser::ParseBinaryExpr(int min_preced) {
  TRACE_PARSER("ParseBinaryExpr");
  ASSERT(min_preced >= 4);
  AstNode* left_operand = ParseUnaryExpr();
  if (left_operand->IsPrimaryNode() &&
      (left_operand->AsPrimaryNode()->IsSuper())) {
    ErrorMsg(left_operand->token_pos(), "illegal use of 'super'");
  }
  if (IsLiteral("as")) {  // Not a reserved word.
    token_kind_ = Token::kAS;
  }
  int current_preced = Token::Precedence(CurrentToken());
  while (current_preced >= min_preced) {
    while (Token::Precedence(CurrentToken()) == current_preced) {
      Token::Kind op_kind = CurrentToken();
      const intptr_t op_pos = TokenPos();
      ConsumeToken();
      AstNode* right_operand = NULL;
      if ((op_kind != Token::kIS) && (op_kind != Token::kAS)) {
        right_operand = ParseBinaryExpr(current_preced + 1);
      } else {
        // For 'is' and 'as' we expect the right operand to be a type.
        if ((op_kind == Token::kIS) && (CurrentToken() == Token::kNOT)) {
          ConsumeToken();
          op_kind = Token::kISNOT;
        }
        const intptr_t type_pos = TokenPos();
        const AbstractType& type = AbstractType::ZoneHandle(
            ParseType(ClassFinalizer::kCanonicalize));
        if (!type.IsInstantiated() &&
            (current_block_->scope->function_level() > 0)) {
          // Make sure that the instantiator is captured.
          CaptureInstantiator();
        }
        right_operand = new TypeNode(type_pos, type);
        // If the type is malformed, it is actually malbounded in checked mode.
        ASSERT(!type.IsMalformed() || FLAG_enable_type_checks);
        if (((op_kind == Token::kIS) || (op_kind == Token::kISNOT)) &&
            type.IsMalformed()) {
          // Note that a type error is thrown even if the tested value is null
          // in a type test. However, no cast exception is thrown if the value
          // is null in a type cast.
          return ThrowTypeError(type_pos, type);
        }
      }
      if (Token::IsRelationalOperator(op_kind)
          || Token::IsTypeTestOperator(op_kind)
          || Token::IsTypeCastOperator(op_kind)
          || Token::IsEqualityOperator(op_kind)) {
        if (Token::IsTypeTestOperator(op_kind) ||
            Token::IsTypeCastOperator(op_kind)) {
          if (!right_operand->AsTypeNode()->type().IsInstantiated()) {
            EnsureExpressionTemp();
          }
        }
        left_operand = new ComparisonNode(
            op_pos, op_kind, left_operand, right_operand);
        break;  // Equality and relational operators cannot be chained.
      } else {
        left_operand = OptimizeBinaryOpNode(
            op_pos, op_kind, left_operand, right_operand);
      }
    }
    current_preced--;
  }
  return left_operand;
}


AstNode* Parser::ParseExprList() {
  TRACE_PARSER("ParseExprList");
  AstNode* expressions = ParseExpr(kAllowConst, kConsumeCascades);
  if (CurrentToken() == Token::kCOMMA) {
    // Collect comma-separated expressions in a non scope owning sequence node.
    SequenceNode* list = new SequenceNode(TokenPos(), NULL);
    list->Add(expressions);
    while (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
      AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
      list->Add(expr);
    }
    expressions = list;
  }
  return expressions;
}


void Parser::EnsureExpressionTemp() {
  // Temporary used later by the flow_graph_builder.
  parsed_function()->EnsureExpressionTemp();
}


void Parser::EnsureSavedCurrentContext() {
  // Used later by the flow_graph_builder to save current context.
  if (!parsed_function()->has_saved_current_context_var()) {
    LocalVariable* temp =
        new LocalVariable(current_function().token_pos(),
                          Symbols::SavedCurrentContextVar(),
                          Type::ZoneHandle(Type::DynamicType()));
    ASSERT(temp != NULL);
    parsed_function()->set_saved_current_context_var(temp);
  }
}


LocalVariable* Parser::CreateTempConstVariable(intptr_t token_pos,
                                               const char* s) {
  char name[64];
  OS::SNPrint(name, 64, ":%s%" Pd, s, token_pos);
  LocalVariable* temp =
      new LocalVariable(token_pos,
                        String::ZoneHandle(Symbols::New(name)),
                        Type::ZoneHandle(Type::DynamicType()));
  temp->set_is_final();
  current_block_->scope->AddVariable(temp);
  return temp;
}


// TODO(srdjan): Implement other optimizations.
AstNode* Parser::OptimizeBinaryOpNode(intptr_t op_pos,
                                      Token::Kind binary_op,
                                      AstNode* lhs,
                                      AstNode* rhs) {
  LiteralNode* lhs_literal = lhs->AsLiteralNode();
  LiteralNode* rhs_literal = rhs->AsLiteralNode();
  if ((lhs_literal != NULL) && (rhs_literal != NULL)) {
    if (lhs_literal->literal().IsDouble() &&
        rhs_literal->literal().IsDouble()) {
      double left_double = Double::Cast(lhs_literal->literal()).value();
      double right_double = Double::Cast(rhs_literal->literal()).value();
      if (binary_op == Token::kDIV) {
        const Double& dbl_obj = Double::ZoneHandle(
            Double::NewCanonical((left_double / right_double)));
        return new LiteralNode(op_pos, dbl_obj);
      }
    }
  }
  if ((binary_op == Token::kAND) || (binary_op == Token::kOR)) {
    EnsureExpressionTemp();
  }
  if (binary_op == Token::kBIT_AND) {
    // Normalize so that rhs is a literal if any is.
    if ((rhs_literal == NULL) && (lhs_literal != NULL)) {
      // Swap.
      LiteralNode* temp = rhs_literal;
      rhs_literal = lhs_literal;
      lhs_literal = temp;
    }
    if ((rhs_literal != NULL) &&
        (rhs_literal->literal().IsSmi() || rhs_literal->literal().IsMint())) {
      const int64_t val = Integer::Cast(rhs_literal->literal()).AsInt64Value();
      if ((0 <= val) && (Utils::IsUint(32, val))) {
        if (lhs->IsBinaryOpNode() &&
            (lhs->AsBinaryOpNode()->kind() == Token::kSHL)) {
          // Merge SHL and BIT_AND into one "SHL with mask" node.
          BinaryOpNode* old = lhs->AsBinaryOpNode();
          BinaryOpWithMask32Node* binop = new BinaryOpWithMask32Node(
              old->token_pos(), old->kind(), old->left(), old->right(), val);
          return binop;
        }
      }
    }
  }
  return new BinaryOpNode(op_pos, binary_op, lhs, rhs);
}


AstNode* Parser::ExpandAssignableOp(intptr_t op_pos,
                                    Token::Kind assignment_op,
                                    AstNode* lhs,
                                    AstNode* rhs) {
  TRACE_PARSER("ExpandAssignableOp");
  switch (assignment_op) {
    case Token::kASSIGN:
      return rhs;
    case Token::kASSIGN_ADD:
      return new BinaryOpNode(op_pos, Token::kADD, lhs, rhs);
    case Token::kASSIGN_SUB:
      return new BinaryOpNode(op_pos, Token::kSUB, lhs, rhs);
    case Token::kASSIGN_MUL:
      return new BinaryOpNode(op_pos, Token::kMUL, lhs, rhs);
    case Token::kASSIGN_TRUNCDIV:
      return new BinaryOpNode(op_pos, Token::kTRUNCDIV, lhs, rhs);
    case Token::kASSIGN_DIV:
      return new BinaryOpNode(op_pos, Token::kDIV, lhs, rhs);
    case Token::kASSIGN_MOD:
      return new BinaryOpNode(op_pos, Token::kMOD, lhs, rhs);
    case Token::kASSIGN_SHR:
      return new BinaryOpNode(op_pos, Token::kSHR, lhs, rhs);
    case Token::kASSIGN_SHL:
      return new BinaryOpNode(op_pos, Token::kSHL, lhs, rhs);
    case Token::kASSIGN_OR:
      return new BinaryOpNode(op_pos, Token::kBIT_OR, lhs, rhs);
    case Token::kASSIGN_AND:
      return new BinaryOpNode(op_pos, Token::kBIT_AND, lhs, rhs);
    case Token::kASSIGN_XOR:
      return new BinaryOpNode(op_pos, Token::kBIT_XOR, lhs, rhs);
    default:
      ErrorMsg(op_pos, "internal error: ExpandAssignableOp '%s' unimplemented",
          Token::Name(assignment_op));
      UNIMPLEMENTED();
      return NULL;
  }
}


// Evaluates the value of the compile time constant expression
// and returns a literal node for the value.
AstNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) {
  if (expr->IsLiteralNode()) {
    return expr;
  }
  if (expr->EvalConstExpr() == NULL) {
    ErrorMsg(expr_pos, "expression must be a compile-time constant");
  }
  return new LiteralNode(expr_pos, EvaluateConstExpr(expr));
}


LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
  AstNode* node = *expr;
  intptr_t token_pos = node->token_pos();
  LetNode* result = new LetNode(token_pos);
  if (node->IsLoadIndexedNode()) {
    LoadIndexedNode* load_indexed = node->AsLoadIndexedNode();
    AstNode* array = load_indexed->array();
    AstNode* index = load_indexed->index_expr();
    if (!IsSimpleLocalOrLiteralNode(load_indexed->array())) {
      LocalVariable* t0 = result->AddInitializer(load_indexed->array());
      array = new LoadLocalNode(token_pos, t0);
    }
    if (!IsSimpleLocalOrLiteralNode(load_indexed->index_expr())) {
      LocalVariable* t1 = result->AddInitializer(
          load_indexed->index_expr());
      index = new LoadLocalNode(token_pos, t1);
    }
    *expr = new LoadIndexedNode(token_pos,
                                array,
                                index,
                                load_indexed->super_class());
    return result;
  }
  if (node->IsInstanceGetterNode()) {
    InstanceGetterNode* getter = node->AsInstanceGetterNode();
    AstNode* receiver = getter->receiver();
    if (!IsSimpleLocalOrLiteralNode(getter->receiver())) {
      LocalVariable* t0 = result->AddInitializer(getter->receiver());
      receiver = new LoadLocalNode(token_pos, t0);
    }
    *expr = new InstanceGetterNode(token_pos,
                                   receiver,
                                   getter->field_name());
    return result;
  }
  return result;
}


AstNode* Parser::CreateAssignmentNode(AstNode* original,
                                      AstNode* rhs,
                                      const String* left_ident,
                                      intptr_t left_pos) {
  AstNode* result = original->MakeAssignmentNode(rhs);
  if (result == NULL) {
    String& name = String::ZoneHandle();
    if (original->IsTypeNode()) {
      name = Symbols::New(original->Name());
    } else if ((left_ident != NULL) &&
               (original->IsLiteralNode() ||
                original->IsLoadLocalNode() ||
                original->IsLoadStaticFieldNode())) {
      name = left_ident->raw();
    }
    if (name.IsNull()) {
      ErrorMsg(left_pos, "expression is not assignable");
    }
    result = ThrowNoSuchMethodError(original->token_pos(),
                                    current_class(),
                                    name,
                                    InvocationMirror::kStatic,
                                    InvocationMirror::kSetter);
  } else if (result->IsStoreIndexedNode() ||
             result->IsInstanceSetterNode() ||
             result->IsStaticSetterNode() ||
             result->IsStoreStaticFieldNode() ||
             result->IsStoreLocalNode()) {
    // Ensure that the expression temp is allocated for nodes that may need it.
    EnsureExpressionTemp();
  }
  return result;
}


AstNode* Parser::ParseCascades(AstNode* expr) {
  intptr_t cascade_pos = TokenPos();
  LetNode* cascade = new LetNode(cascade_pos);
  LocalVariable* cascade_receiver_var = cascade->AddInitializer(expr);
  while (CurrentToken() == Token::kCASCADE) {
    cascade_pos = TokenPos();
    LoadLocalNode* load_cascade_receiver =
        new LoadLocalNode(cascade_pos, cascade_receiver_var);
    if (Token::IsIdentifier(LookaheadToken(1))) {
      // Replace .. with . for ParseSelectors().
      token_kind_ = Token::kPERIOD;
    } else if (LookaheadToken(1) == Token::kLBRACK) {
      ConsumeToken();
    } else {
      ErrorMsg("identifier or [ expected after ..");
    }
    String* expr_ident =
        Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
    const intptr_t expr_pos = TokenPos();
    expr = ParseSelectors(load_cascade_receiver, true);

    // Assignments after a cascade are part of the cascade. The
    // assigned expression must not contain cascades.
    if (Token::IsAssignmentOperator(CurrentToken())) {
      Token::Kind assignment_op = CurrentToken();
      const intptr_t assignment_pos = TokenPos();
      ConsumeToken();
      AstNode* right_expr = ParseExpr(kAllowConst, kNoCascades);
      if (assignment_op != Token::kASSIGN) {
        // Compound assignment: store inputs with side effects into
        // temporary locals.
        LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
        right_expr =
            ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
        AstNode* assign_expr = CreateAssignmentNode(
            expr, right_expr, expr_ident, expr_pos);
        ASSERT(assign_expr != NULL);
        let_expr->AddNode(assign_expr);
        expr = let_expr;
      } else {
        right_expr =
            ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
        AstNode* assign_expr = CreateAssignmentNode(
            expr, right_expr, expr_ident, expr_pos);
        ASSERT(assign_expr != NULL);
        expr = assign_expr;
      }
    }
    cascade->AddNode(expr);
  }
  // The result is an expression with the (side effects of the) cascade
  // sequence followed by the (value of the) receiver temp variable load.
  cascade->AddNode(new LoadLocalNode(cascade_pos, cascade_receiver_var));
  return cascade;
}


AstNode* Parser::ParseExpr(bool require_compiletime_const,
                           bool consume_cascades) {
  TRACE_PARSER("ParseExpr");
  String* expr_ident =
      Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
  const intptr_t expr_pos = TokenPos();

  if (CurrentToken() == Token::kTHROW) {
    ConsumeToken();
    ASSERT(CurrentToken() != Token::kSEMICOLON);
    AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
    return new ThrowNode(expr_pos, expr, NULL);
  }
  AstNode* expr = ParseConditionalExpr();
  if (!Token::IsAssignmentOperator(CurrentToken())) {
    if ((CurrentToken() == Token::kCASCADE) && consume_cascades) {
      return ParseCascades(expr);
    }
    if (require_compiletime_const) {
      expr = FoldConstExpr(expr_pos, expr);
    }
    return expr;
  }
  // Assignment expressions.
  const Token::Kind assignment_op = CurrentToken();
  const intptr_t assignment_pos = TokenPos();
  ConsumeToken();
  const intptr_t right_expr_pos = TokenPos();
  if (require_compiletime_const && (assignment_op != Token::kASSIGN)) {
    ErrorMsg(right_expr_pos, "expression must be a compile-time constant");
  }
  AstNode* right_expr = ParseExpr(require_compiletime_const, consume_cascades);
  if (assignment_op != Token::kASSIGN) {
    // Compound assignment: store inputs with side effects into temp. locals.
    LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
    AstNode* assigned_value =
        ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
    AstNode* assign_expr = CreateAssignmentNode(
        expr, assigned_value, expr_ident, expr_pos);
    ASSERT(assign_expr != NULL);
    let_expr->AddNode(assign_expr);
    return let_expr;
  } else {
    AstNode* assigned_value =
        ExpandAssignableOp(assignment_pos, assignment_op, expr, right_expr);
    AstNode* assign_expr = CreateAssignmentNode(
        expr, assigned_value, expr_ident, expr_pos);
    ASSERT(assign_expr != NULL);
    return assign_expr;
  }
}


LiteralNode* Parser::ParseConstExpr() {
  TRACE_PARSER("ParseConstExpr");
  AstNode* expr = ParseExpr(kRequireConst, kNoCascades);
  ASSERT(expr->IsLiteralNode());
  return expr->AsLiteralNode();
}


AstNode* Parser::ParseConditionalExpr() {
  TRACE_PARSER("ParseConditionalExpr");
  const intptr_t expr_pos = TokenPos();
  AstNode* expr = ParseBinaryExpr(Token::Precedence(Token::kOR));
  if (CurrentToken() == Token::kCONDITIONAL) {
    EnsureExpressionTemp();
    ConsumeToken();
    AstNode* expr1 = ParseExpr(kAllowConst, kNoCascades);
    ExpectToken(Token::kCOLON);
    AstNode* expr2 = ParseExpr(kAllowConst, kNoCascades);
    expr = new ConditionalExprNode(expr_pos, expr, expr1, expr2);
  }
  return expr;
}


AstNode* Parser::ParseUnaryExpr() {
  TRACE_PARSER("ParseUnaryExpr");
  AstNode* expr = NULL;
  const intptr_t op_pos = TokenPos();
  if (IsPrefixOperator(CurrentToken())) {
    Token::Kind unary_op = CurrentToken();
    if (unary_op == Token::kSUB) {
      unary_op = Token::kNEGATE;
    }
    ConsumeToken();
    expr = ParseUnaryExpr();
    if (expr->IsPrimaryNode() && (expr->AsPrimaryNode()->IsSuper())) {
      expr = BuildUnarySuperOperator(unary_op, expr->AsPrimaryNode());
    } else {
      expr = UnaryOpNode::UnaryOpOrLiteral(op_pos, unary_op, expr);
    }
  } else if (IsIncrementOperator(CurrentToken())) {
    Token::Kind incr_op = CurrentToken();
    ConsumeToken();
    String* expr_ident =
        Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
    const intptr_t expr_pos = TokenPos();
    expr = ParseUnaryExpr();
    // Is prefix.
    LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
    Token::Kind binary_op =
        (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
    BinaryOpNode* add = new BinaryOpNode(
        op_pos,
        binary_op,
        expr,
        new LiteralNode(op_pos, Smi::ZoneHandle(Smi::New(1))));
    AstNode* store = CreateAssignmentNode(expr, add, expr_ident, expr_pos);
    ASSERT(store != NULL);
    let_expr->AddNode(store);
    expr = let_expr;
  } else {
    expr = ParsePostfixExpr();
  }
  return expr;
}


ArgumentListNode* Parser::ParseActualParameters(
                              ArgumentListNode* implicit_arguments,
                              bool require_const) {
  TRACE_PARSER("ParseActualParameters");
  ASSERT(CurrentToken() == Token::kLPAREN);
  const bool saved_mode = SetAllowFunctionLiterals(true);
  ArgumentListNode* arguments;
  if (implicit_arguments == NULL) {
    arguments = new ArgumentListNode(TokenPos());
  } else {
    arguments = implicit_arguments;
  }
  const GrowableObjectArray& names =
      GrowableObjectArray::Handle(GrowableObjectArray::New());
  bool named_argument_seen = false;
  if (LookaheadToken(1) != Token::kRPAREN) {
    String& arg_name = String::Handle();
    do {
      ASSERT((CurrentToken() == Token::kLPAREN) ||
             (CurrentToken() == Token::kCOMMA));
      ConsumeToken();
      if (IsIdentifier() && (LookaheadToken(1) == Token::kCOLON)) {
        named_argument_seen = true;
        // The canonicalization of the arguments descriptor array built in
        // the code generator requires that the names are symbols, i.e.
        // canonicalized strings.
        ASSERT(CurrentLiteral()->IsSymbol());
        for (int i = 0; i < names.Length(); i++) {
          arg_name ^= names.At(i);
          if (CurrentLiteral()->Equals(arg_name)) {
            ErrorMsg("duplicate named argument");
          }
        }
        names.Add(*CurrentLiteral());
        ConsumeToken();  // ident.
        ConsumeToken();  // colon.
      } else if (named_argument_seen) {
        ErrorMsg("named argument expected");
      }
      arguments->Add(ParseExpr(require_const, kConsumeCascades));
    } while (CurrentToken() == Token::kCOMMA);
  } else {
    ConsumeToken();
  }
  ExpectToken(Token::kRPAREN);
  SetAllowFunctionLiterals(saved_mode);
  if (named_argument_seen) {
    arguments->set_names(Array::Handle(Array::MakeArray(names)));
  }
  return arguments;
}


AstNode* Parser::ParseStaticCall(const Class& cls,
                                 const String& func_name,
                                 intptr_t ident_pos) {
  TRACE_PARSER("ParseStaticCall");
  const intptr_t call_pos = TokenPos();
  ASSERT(CurrentToken() == Token::kLPAREN);
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  const int num_arguments = arguments->length();
  const Function& func = Function::ZoneHandle(
      Resolver::ResolveStatic(cls,
                              func_name,
                              num_arguments,
                              arguments->names(),
                              Resolver::kIsQualified));
  if (func.IsNull()) {
    // Check if there is a static field of the same name, it could be a closure
    // and so we try and invoke the closure.
    AstNode* closure = NULL;
    const Field& field = Field::ZoneHandle(cls.LookupStaticField(func_name));
    Function& func = Function::ZoneHandle();
    if (field.IsNull()) {
      // No field, check if we have an explicit getter function.
      const String& getter_name =
          String::ZoneHandle(Field::GetterName(func_name));
      const int kNumArguments = 0;  // no arguments.
      func = Resolver::ResolveStatic(cls,
                                     getter_name,
                                     kNumArguments,
                                     Object::empty_array(),
                                     Resolver::kIsQualified);
      if (!func.IsNull()) {
        ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
        EnsureSavedCurrentContext();
        closure = new StaticGetterNode(call_pos,
                                       NULL,
                                       false,
                                       Class::ZoneHandle(cls.raw()),
                                       func_name);
        return new ClosureCallNode(call_pos, closure, arguments);
      }
    } else {
      EnsureSavedCurrentContext();
      closure = GenerateStaticFieldLookup(field, call_pos);
      return new ClosureCallNode(call_pos, closure, arguments);
    }
    // Could not resolve static method: throw a NoSuchMethodError.
    return ThrowNoSuchMethodError(ident_pos,
                                  cls,
                                  func_name,
                                  InvocationMirror::kStatic,
                                  InvocationMirror::kMethod);
  } else if (cls.IsTopLevel() &&
      (cls.library() == Library::CoreLibrary()) &&
      (func.name() == Symbols::Identical().raw())) {
    // This is the predefined toplevel function identical(a,b). Create
    // a comparison node instead.
    ASSERT(num_arguments == 2);
    return new ComparisonNode(ident_pos,
                              Token::kEQ_STRICT,
                              arguments->NodeAt(0),
                              arguments->NodeAt(1));
  }
  return new StaticCallNode(call_pos, func, arguments);
}


AstNode* Parser::ParseInstanceCall(AstNode* receiver, const String& func_name) {
  TRACE_PARSER("ParseInstanceCall");
  const intptr_t call_pos = TokenPos();
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg(call_pos, "left parenthesis expected");
  }
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  return new InstanceCallNode(call_pos, receiver, func_name, arguments);
}


AstNode* Parser::ParseClosureCall(AstNode* closure) {
  TRACE_PARSER("ParseClosureCall");
  const intptr_t call_pos = TokenPos();
  ASSERT(CurrentToken() == Token::kLPAREN);
  EnsureSavedCurrentContext();
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  return new ClosureCallNode(call_pos, closure, arguments);
}


AstNode* Parser::GenerateStaticFieldLookup(const Field& field,
                                           intptr_t ident_pos) {
  // If the static field has an initializer, initialize the field at compile
  // time, which is only possible if the field is const.
  AstNode* initializing_getter = RunStaticFieldInitializer(field);
  if (initializing_getter != NULL) {
    // The field is not yet initialized and could not be initialized at compile
    // time. The getter will initialize the field.
    return initializing_getter;
  }
  // The field is initialized.
  if (field.is_const()) {
    ASSERT(field.value() != Object::sentinel().raw());
    ASSERT(field.value() != Object::transition_sentinel().raw());
    return new LiteralNode(ident_pos, Instance::ZoneHandle(field.value()));
  }
  ASSERT(field.is_static());
  const Class& field_owner = Class::ZoneHandle(field.owner());
  const String& field_name = String::ZoneHandle(field.name());
  const String& getter_name = String::Handle(Field::GetterName(field_name));
  const Function& getter =
      Function::Handle(field_owner.LookupStaticFunction(getter_name));
  // Never load field directly if there is a getter (deterministic AST).
  if (getter.IsNull()) {
    return new LoadStaticFieldNode(ident_pos, Field::ZoneHandle(field.raw()));
  } else {
    ASSERT(getter.kind() == RawFunction::kImplicitStaticFinalGetter);
    return new StaticGetterNode(ident_pos,
                                NULL,  // Receiver.
                                false,  // is_super_getter.
                                field_owner,
                                field_name);
  }
}


AstNode* Parser::ParseStaticFieldAccess(const Class& cls,
                                        const String& field_name,
                                        intptr_t ident_pos,
                                        bool consume_cascades) {
  TRACE_PARSER("ParseStaticFieldAccess");
  AstNode* access = NULL;
  const intptr_t call_pos = TokenPos();
  const Field& field = Field::ZoneHandle(cls.LookupStaticField(field_name));
  Function& func = Function::ZoneHandle();
  if (Token::IsAssignmentOperator(CurrentToken())) {
    // Make sure an assignment is legal.
    if (field.IsNull()) {
      // No field, check if we have an explicit setter function.
      const String& setter_name =
          String::ZoneHandle(Field::SetterName(field_name));
      const int kNumArguments = 1;  // value.
      func = Resolver::ResolveStatic(cls,
                                     setter_name,
                                     kNumArguments,
                                     Object::empty_array(),
                                     Resolver::kIsQualified);
      if (func.IsNull()) {
        // No field or explicit setter function, throw a NoSuchMethodError.
        return ThrowNoSuchMethodError(ident_pos,
                                      cls,
                                      field_name,
                                      InvocationMirror::kStatic,
                                      InvocationMirror::kField);
      }

      // Explicit setter function for the field found, field does not exist.
      // Create a getter node first in case it is needed. If getter node
      // is used as part of, e.g., "+=", and the explicit getter does not
      // exist, and error will be reported by the code generator.
      access = new StaticGetterNode(call_pos,
                                    NULL,
                                    false,
                                    Class::ZoneHandle(cls.raw()),
                                    String::ZoneHandle(field_name.raw()));
    } else {
      // Field exists.
      if (field.is_final()) {
        // Field has been marked as final, report an error as the field
        // is not settable.
        ErrorMsg(ident_pos,
                 "field '%s' is const static, cannot assign to it",
                 field_name.ToCString());
      }
      access = GenerateStaticFieldLookup(field, TokenPos());
    }
  } else {  // Not Token::IsAssignmentOperator(CurrentToken()).
    if (field.IsNull()) {
      // No field, check if we have an explicit getter function.
      const String& getter_name =
          String::ZoneHandle(Field::GetterName(field_name));
      const int kNumArguments = 0;  // no arguments.
      func = Resolver::ResolveStatic(cls,
                                     getter_name,
                                     kNumArguments,
                                     Object::empty_array(),
                                     Resolver::kIsQualified);
      if (func.IsNull()) {
        // We might be referring to an implicit closure, check to see if
        // there is a function of the same name.
        func = cls.LookupStaticFunction(field_name);
        if (func.IsNull()) {
          // No field or explicit getter function, throw a NoSuchMethodError.
          return ThrowNoSuchMethodError(ident_pos,
                                        cls,
                                        field_name,
                                        InvocationMirror::kStatic,
                                        InvocationMirror::kGetter);
        }
        access = CreateImplicitClosureNode(func, call_pos, NULL);
      } else {
        ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
        access = new StaticGetterNode(call_pos,
                                      NULL,
                                      false,
                                      Class::ZoneHandle(cls.raw()),
                                      field_name);
      }
    } else {
      access = GenerateStaticFieldLookup(field, TokenPos());
    }
  }
  return access;
}


AstNode* Parser::LoadFieldIfUnresolved(AstNode* node) {
  if (!node->IsPrimaryNode()) {
    return node;
  }
  PrimaryNode* primary = node->AsPrimaryNode();
  if (primary->primary().IsString()) {
    if (primary->IsSuper()) {
      return primary;
    }
    // In a static method, evaluation of an unresolved identifier causes a
    // NoSuchMethodError to be thrown.
    // In an instance method, we convert this into a getter call
    // for a field (which may be defined in a subclass.)
    String& name = String::CheckedZoneHandle(primary->primary().raw());
    if (current_function().is_static() ||
        current_function().IsInFactoryScope()) {
      return ThrowNoSuchMethodError(primary->token_pos(),
                                    current_class(),
                                    name,
                                    InvocationMirror::kStatic,
                                    InvocationMirror::kField);
    } else {
      AstNode* receiver = LoadReceiver(primary->token_pos());
      return CallGetter(node->token_pos(), receiver, name);
    }
  }
  return primary;
}


AstNode* Parser::LoadClosure(PrimaryNode* primary) {
  ASSERT(primary->primary().IsFunction());
  AstNode* closure = NULL;
  const Function& func =
      Function::CheckedZoneHandle(primary->primary().raw());
  const String& funcname = String::ZoneHandle(func.name());
  if (func.is_static()) {
    // Static function access.
    closure = CreateImplicitClosureNode(func, primary->token_pos(), NULL);
  } else {
    // Instance function access.
    if (current_function().is_static() ||
        current_function().IsInFactoryScope()) {
      ErrorMsg(primary->token_pos(),
               "cannot access instance method '%s' from static method",
               funcname.ToCString());
    }
    AstNode* receiver = LoadReceiver(primary->token_pos());
    closure = CallGetter(primary->token_pos(), receiver, funcname);
  }
  return closure;
}


AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
  AstNode* left = primary;
  while (true) {
    AstNode* selector = NULL;
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      if (left->IsPrimaryNode()) {
        if (left->AsPrimaryNode()->primary().IsFunction()) {
          left = LoadClosure(left->AsPrimaryNode());
        } else if (left->AsPrimaryNode()->primary().IsTypeParameter()) {
          if (current_block_->scope->function_level() > 0) {
            // Make sure that the instantiator is captured.
            CaptureInstantiator();
          }
          TypeParameter& type_parameter = TypeParameter::ZoneHandle();
          type_parameter ^= ClassFinalizer::FinalizeType(
              current_class(),
              TypeParameter::Cast(left->AsPrimaryNode()->primary()),
              ClassFinalizer::kFinalize);
          ASSERT(!type_parameter.IsMalformed());
          left = new TypeNode(primary->token_pos(), type_parameter);
        } else {
          // Super field access handled in ParseSuperFieldAccess(),
          // super calls handled in ParseSuperCall().
          ASSERT(!left->AsPrimaryNode()->IsSuper());
          left = LoadFieldIfUnresolved(left);
        }
      }
      const intptr_t ident_pos = TokenPos();
      String* ident = ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kLPAREN) {
        // Identifier followed by a opening paren: method call.
        if (left->IsPrimaryNode() &&
            left->AsPrimaryNode()->primary().IsClass()) {
          // Static method call prefixed with class name.
          const Class& cls = Class::Cast(left->AsPrimaryNode()->primary());
          selector = ParseStaticCall(cls, *ident, ident_pos);
        } else {
          selector = ParseInstanceCall(left, *ident);
        }
      } else {
        // Field access.
        Class& cls = Class::Handle();
        if (left->IsPrimaryNode()) {
          PrimaryNode* primary_node = left->AsPrimaryNode();
          if (primary_node->primary().IsClass()) {
            // If the primary node referred to a class we are loading a
            // qualified static field.
            cls ^= primary_node->primary().raw();
          }
        }
        if (cls.IsNull()) {
          // Instance field access.
          selector = CallGetter(ident_pos, left, *ident);
        } else {
          // Static field access.
          selector =
              ParseStaticFieldAccess(cls, *ident, ident_pos, !is_cascade);
        }
      }
    } else if (CurrentToken() == Token::kLBRACK) {
      // Super index operator handled in ParseSuperOperator().
      ASSERT(!left->IsPrimaryNode() || !left->AsPrimaryNode()->IsSuper());

      const intptr_t bracket_pos = TokenPos();
      ConsumeToken();
      left = LoadFieldIfUnresolved(left);
      const bool saved_mode = SetAllowFunctionLiterals(true);
      AstNode* index = ParseExpr(kAllowConst, kConsumeCascades);
      SetAllowFunctionLiterals(saved_mode);
      ExpectToken(Token::kRBRACK);
      AstNode* array = left;
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary = left->AsPrimaryNode();
        if (primary->primary().IsFunction()) {
          array = LoadClosure(primary);
        } else if (primary->primary().IsClass()) {
          const Class& type_class = Class::Cast(primary->primary());
          Type& type = Type::ZoneHandle(
              Type::New(type_class, TypeArguments::Handle(),
                        primary->token_pos(), Heap::kOld));
          type ^= ClassFinalizer::FinalizeType(
              current_class(), type, ClassFinalizer::kCanonicalize);
          ASSERT(!type.IsMalformed());
          array = new TypeNode(primary->token_pos(), type);
        } else if (primary->primary().IsTypeParameter()) {
          if (current_block_->scope->function_level() > 0) {
            // Make sure that the instantiator is captured.
            CaptureInstantiator();
          }
          TypeParameter& type_parameter = TypeParameter::ZoneHandle();
          type_parameter ^= ClassFinalizer::FinalizeType(
              current_class(),
              TypeParameter::Cast(primary->primary()),
              ClassFinalizer::kFinalize);
          ASSERT(!type_parameter.IsMalformed());
          array = new TypeNode(primary->token_pos(), type_parameter);
        } else {
          UNREACHABLE();  // Internal parser error.
        }
      }
      selector =  new LoadIndexedNode(bracket_pos,
                                      array,
                                      index,
                                      Class::ZoneHandle());
    } else if (CurrentToken() == Token::kLPAREN) {
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary = left->AsPrimaryNode();
        const intptr_t primary_pos = primary->token_pos();
        if (primary->primary().IsFunction()) {
          const Function& func = Function::Cast(primary->primary());
          const String& func_name = String::ZoneHandle(func.name());
          if (func.is_static()) {
            // Parse static function call.
            Class& cls = Class::Handle(func.Owner());
            selector = ParseStaticCall(cls, func_name, primary_pos);
          } else {
            // Dynamic function call on implicit "this" parameter.
            if (current_function().is_static()) {
              ErrorMsg(primary_pos,
                       "cannot access instance method '%s' "
                       "from static function",
                       func_name.ToCString());
            }
            selector = ParseInstanceCall(LoadReceiver(primary_pos), func_name);
          }
        } else if (primary->primary().IsString()) {
          // Primary is an unresolved name.
          if (primary->IsSuper()) {
            ErrorMsg(primary->token_pos(), "illegal use of super");
          }
          String& name = String::CheckedZoneHandle(primary->primary().raw());
          if (current_function().is_static()) {
            selector = ThrowNoSuchMethodError(primary->token_pos(),
                                              current_class(),
                                              name,
                                              InvocationMirror::kStatic,
                                              InvocationMirror::kMethod);
          } else {
            // Treat as call to unresolved (instance) method.
            AstNode* receiver = LoadReceiver(primary->token_pos());
            selector = ParseInstanceCall(receiver, name);
          }
        } else if (primary->primary().IsTypeParameter()) {
          const String& name = String::ZoneHandle(
              Symbols::New(primary->Name()));
          selector = ThrowNoSuchMethodError(primary->token_pos(),
                                            current_class(),
                                            name,
                                            InvocationMirror::kStatic,
                                            InvocationMirror::kMethod);
        } else if (primary->primary().IsClass()) {
          const Class& type_class = Class::Cast(primary->primary());
          Type& type = Type::ZoneHandle(
              Type::New(type_class, TypeArguments::Handle(),
                        primary->token_pos(), Heap::kOld));
          type ^= ClassFinalizer::FinalizeType(
              current_class(), type, ClassFinalizer::kCanonicalize);
          ASSERT(!type.IsMalformed());
          selector = new TypeNode(primary->token_pos(), type);
        } else {
          UNREACHABLE();  // Internal parser error.
        }
      } else {
        // Left is not a primary node; this must be a closure call.
        AstNode* closure = left;
        selector = ParseClosureCall(closure);
      }
    } else {
      // No (more) selectors to parse.
      left = LoadFieldIfUnresolved(left);
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary = left->AsPrimaryNode();
        if (primary->primary().IsFunction()) {
          // Treat as implicit closure.
          left = LoadClosure(primary);
        } else if (primary->primary().IsClass()) {
          const Class& type_class = Class::Cast(primary->primary());
          Type& type = Type::ZoneHandle(
              Type::New(type_class, TypeArguments::Handle(),
                        primary->token_pos(), Heap::kOld));
          type ^= ClassFinalizer::FinalizeType(
              current_class(), type, ClassFinalizer::kCanonicalize);
          ASSERT(!type.IsMalformed());
          left = new TypeNode(primary->token_pos(), type);
        } else if (primary->primary().IsTypeParameter()) {
          if (current_block_->scope->function_level() > 0) {
            // Make sure that the instantiator is captured.
            CaptureInstantiator();
          }
          TypeParameter& type_parameter = TypeParameter::ZoneHandle();
          type_parameter ^= ClassFinalizer::FinalizeType(
              current_class(),
              TypeParameter::Cast(primary->primary()),
              ClassFinalizer::kFinalize);
          ASSERT(!type_parameter.IsMalformed());
          left = new TypeNode(primary->token_pos(), type_parameter);
        } else if (primary->IsSuper()) {
          // Return "super" to handle unary super operator calls,
          // or to report illegal use of "super" otherwise.
          left = primary;
        } else {
          UNREACHABLE();  // Internal parser error.
        }
      }
      // Done parsing selectors.
      return left;
    }
    ASSERT(selector != NULL);
    left = selector;
  }
}


AstNode* Parser::ParsePostfixExpr() {
  TRACE_PARSER("ParsePostfixExpr");
  String* expr_ident =
      Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
  const intptr_t expr_pos = TokenPos();
  AstNode* expr = ParsePrimary();
  expr = ParseSelectors(expr, false);
  if (IsIncrementOperator(CurrentToken())) {
    TRACE_PARSER("IncrementOperator");
    Token::Kind incr_op = CurrentToken();
    ConsumeToken();
    // Not prefix.
    LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
    LocalVariable* temp = let_expr->AddInitializer(expr);
    Token::Kind binary_op =
        (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
    BinaryOpNode* add = new BinaryOpNode(
        expr_pos,
        binary_op,
        new LoadLocalNode(expr_pos, temp),
        new LiteralNode(expr_pos, Smi::ZoneHandle(Smi::New(1))));
    AstNode* store = CreateAssignmentNode(expr, add, expr_ident, expr_pos);
    ASSERT(store != NULL);
    // The result is a pair of the (side effects of the) store followed by
    // the (value of the) initial value temp variable load.
    let_expr->AddNode(store);
    let_expr->AddNode(new LoadLocalNode(expr_pos, temp));
    return let_expr;
  }
  return expr;
}


// Resolve the given type and its type arguments from the given scope class
// according to the given type finalization mode.
// If the given scope class is null, use the current library, but do not try to
// resolve type parameters.
// Not all involved type classes may get resolved yet, but at least the type
// parameters of the given class will get resolved, thereby relieving the class
// finalizer from resolving type parameters out of context.
void Parser::ResolveTypeFromClass(const Class& scope_class,
                                  ClassFinalizer::FinalizationKind finalization,
                                  AbstractType* type) {
  ASSERT(finalization >= ClassFinalizer::kResolveTypeParameters);
  ASSERT(type != NULL);
  if (type->IsResolved()) {
    return;
  }
  // Resolve class.
  if (!type->HasResolvedTypeClass()) {
    const UnresolvedClass& unresolved_class =
        UnresolvedClass::Handle(type->unresolved_class());
    const String& unresolved_class_name =
        String::Handle(unresolved_class.ident());
    Class& resolved_type_class = Class::Handle();
    if (unresolved_class.library_prefix() == LibraryPrefix::null()) {
      if (!scope_class.IsNull()) {
        // First check if the type is a type parameter of the given scope class.
        const TypeParameter& type_parameter = TypeParameter::Handle(
            scope_class.LookupTypeParameter(unresolved_class_name));
        if (!type_parameter.IsNull()) {
          // A type parameter is considered to be a malformed type when
          // referenced by a static member.
          if (ParsingStaticMember()) {
            ASSERT(scope_class.raw() == current_class().raw());
            if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
                FLAG_error_on_malformed_type) {
              *type = ClassFinalizer::NewFinalizedMalformedType(
                  Error::Handle(),  // No previous error.
                  scope_class,
                  type->token_pos(),
                  "type parameter '%s' cannot be referenced "
                  "from static member",
                  String::Handle(type_parameter.name()).ToCString());
            } else {
              // Map the malformed type to dynamic and ignore type arguments.
              *type = Type::DynamicType();
            }
            return;
          }
          // A type parameter cannot be parameterized, so make the type
          // malformed if type arguments have previously been parsed.
          if (!AbstractTypeArguments::Handle(type->arguments()).IsNull()) {
            if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
                FLAG_error_on_malformed_type) {
              *type = ClassFinalizer::NewFinalizedMalformedType(
                  Error::Handle(),  // No previous error.
                  scope_class,
                  type_parameter.token_pos(),
                  "type parameter '%s' cannot be parameterized",
                  String::Handle(type_parameter.name()).ToCString());
            } else {
              // Map the malformed type to dynamic and ignore type arguments.
              *type = Type::DynamicType();
            }
            return;
          }
          *type = type_parameter.raw();
          return;
        }
      }
      // The referenced class may not have been parsed yet. It would be wrong
      // to resolve it too early to an imported class of the same name.
      if (finalization > ClassFinalizer::kResolveTypeParameters) {
        // Resolve classname in the scope of the current library.
        Error& error = Error::Handle();
        resolved_type_class = ResolveClassInCurrentLibraryScope(
            unresolved_class.token_pos(),
            unresolved_class_name,
            &error);
        if (!error.IsNull()) {
          if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
              FLAG_error_on_malformed_type) {
            *type = ClassFinalizer::NewFinalizedMalformedType(
                error,
                scope_class,
                unresolved_class.token_pos(),
                "cannot resolve class '%s'",
                unresolved_class_name.ToCString());
          } else {
            // Map the malformed type to dynamic and ignore type arguments.
            *type = Type::DynamicType();
          }
          return;
        }
      }
    } else {
      LibraryPrefix& lib_prefix =
          LibraryPrefix::Handle(unresolved_class.library_prefix());
      // Resolve class name in the scope of the library prefix.
      Error& error = Error::Handle();
      resolved_type_class = ResolveClassInPrefixScope(
          unresolved_class.token_pos(),
          lib_prefix,
          unresolved_class_name,
          &error);
      if (!error.IsNull()) {
        if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
            FLAG_error_on_malformed_type) {
          *type = ClassFinalizer::NewFinalizedMalformedType(
              error,
              scope_class,
              unresolved_class.token_pos(),
              "cannot resolve class '%s'",
              unresolved_class_name.ToCString());
        } else {
          // Map the malformed type to dynamic and ignore type arguments.
          *type = Type::DynamicType();
        }
        return;
      }
    }
    // At this point, we can only have a parameterized_type.
    const Type& parameterized_type = Type::Cast(*type);
    if (!resolved_type_class.IsNull()) {
      // Replace unresolved class with resolved type class.
      parameterized_type.set_type_class(resolved_type_class);
    } else if (finalization >= ClassFinalizer::kCanonicalize) {
      if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
          FLAG_error_on_malformed_type) {
        ClassFinalizer::FinalizeMalformedType(
            Error::Handle(),  // No previous error.
            scope_class,
            parameterized_type,
            "type '%s' is not loaded",
            String::Handle(parameterized_type.UserVisibleName()).ToCString());
      } else {
        // Map the malformed type to dynamic and ignore type arguments.
        *type = Type::DynamicType();
      }
      return;
    }
  }
  // Resolve type arguments, if any.
  const AbstractTypeArguments& arguments =
      AbstractTypeArguments::Handle(type->arguments());
  if (!arguments.IsNull()) {
    const intptr_t num_arguments = arguments.Length();
    for (intptr_t i = 0; i < num_arguments; i++) {
      AbstractType& type_argument = AbstractType::Handle(arguments.TypeAt(i));
      ResolveTypeFromClass(scope_class, finalization, &type_argument);
      arguments.SetTypeAt(i, type_argument);
    }
  }
}


LocalVariable* Parser::LookupLocalScope(const String& ident) {
  if (current_block_ == NULL) {
    return NULL;
  }
  // A found name is treated as accessed and possibly marked as captured.
  const bool kTestOnly = false;
  return current_block_->scope->LookupVariable(ident, kTestOnly);
}


void Parser::CheckInstanceFieldAccess(intptr_t field_pos,
                                      const String& field_name) {
  // Fields are not accessible from a static function, except from a
  // constructor, which is considered as non-static by the compiler.
  if (current_function().is_static()) {
    ErrorMsg(field_pos,
             "cannot access instance field '%s' from a static function",
             field_name.ToCString());
  }
}


bool Parser::ParsingStaticMember() const {
  if (is_top_level_) {
    return (current_member_ != NULL) &&
           current_member_->has_static && !current_member_->has_factory;
  }
  ASSERT(!current_function().IsNull());
  return
      current_function().is_static() && !current_function().IsInFactoryScope();
}


const AbstractType* Parser::ReceiverType(const Class& cls) {
  ASSERT(!cls.IsNull());
  TypeArguments& type_arguments = TypeArguments::Handle();
  if (cls.NumTypeParameters() > 0) {
    type_arguments = cls.type_parameters();
  }
  AbstractType& type = AbstractType::ZoneHandle(
      Type::New(cls, type_arguments, cls.token_pos()));
  if (cls.is_type_finalized()) {
    type ^= ClassFinalizer::FinalizeType(
        cls, type, ClassFinalizer::kCanonicalizeWellFormed);
    // Note that the receiver type may now be a malbounded type.
  }
  return &type;
}


bool Parser::IsInstantiatorRequired() const {
  ASSERT(!current_function().IsNull());
  if (current_function().is_static() &&
      !current_function().IsInFactoryScope()) {
    return false;
  }
  return current_class().NumTypeParameters() > 0;
}


RawInstance* Parser::TryCanonicalize(const Instance& instance,
                                     intptr_t token_pos) {
  if (instance.IsNull()) {
    return instance.raw();
  }
  const char* error_str = NULL;
  Instance& result =
      Instance::Handle(instance.CheckAndCanonicalize(&error_str));
  if (result.IsNull()) {
    ErrorMsg(token_pos, "Invalid const object %s", error_str);
  }
  return result.raw();
}


// If the field is already initialized, return no ast (NULL).
// Otherwise, if the field is constant, initialize the field and return no ast.
// If the field is not initialized and not const, return the ast for the getter.
AstNode* Parser::RunStaticFieldInitializer(const Field& field) {
  ASSERT(field.is_static());
  const Class& field_owner = Class::ZoneHandle(field.owner());
  const String& field_name = String::ZoneHandle(field.name());
  const String& getter_name = String::Handle(Field::GetterName(field_name));
  const Function& getter =
      Function::Handle(field_owner.LookupStaticFunction(getter_name));
  const Instance& value = Instance::Handle(field.value());
  if (value.raw() == Object::transition_sentinel().raw()) {
    if (field.is_const()) {
      ErrorMsg("circular dependency while initializing static field '%s'",
               field_name.ToCString());
    } else {
      // The implicit static getter will throw the exception if necessary.
      return new StaticGetterNode(TokenPos(),
                                  NULL,
                                  false,
                                  field_owner,
                                  field_name);
    }
  } else if (value.raw() == Object::sentinel().raw()) {
    // This field has not been referenced yet and thus the value has
    // not been evaluated. If the field is const, call the static getter method
    // to evaluate the expression and canonicalize the value.
    if (field.is_const()) {
      field.set_value(Object::transition_sentinel());
      const int kNumArguments = 0;  // no arguments.
      const Function& func =
          Function::Handle(Resolver::ResolveStatic(field_owner,
                                                   getter_name,
                                                   kNumArguments,
                                                   Object::empty_array(),
                                                   Resolver::kIsQualified));
      ASSERT(!func.IsNull());
      ASSERT(func.kind() == RawFunction::kImplicitStaticFinalGetter);
      Object& const_value = Object::Handle(
          DartEntry::InvokeFunction(func, Object::empty_array()));
      if (const_value.IsError()) {
        const Error& error = Error::Cast(const_value);
        if (error.IsUnhandledException()) {
          // An exception may not occur in every parse attempt, i.e., the
          // generated AST is not deterministic. Therefore mark the function as
          // not optimizable.
          current_function().set_is_optimizable(false);
          field.set_value(Object::null_instance());
          // It is a compile-time error if evaluation of a compile-time constant
          // would raise an exception.
          AppendErrorMsg(error, TokenPos(),
                         "error initializing const field '%s'",
                         String::Handle(field.name()).ToCString());
        } else {
          isolate()->long_jump_base()->Jump(1, error);
        }
      }
      ASSERT(const_value.IsNull() || const_value.IsInstance());
      Instance& instance = Instance::Handle();
      instance ^= const_value.raw();
      instance = TryCanonicalize(instance, TokenPos());
      field.set_value(instance);
      return NULL;   // Constant
    } else {
      return new StaticGetterNode(TokenPos(),
                                  NULL,
                                  false,
                                  field_owner,
                                  field_name);
    }
  }
  if (getter.IsNull() ||
      (getter.kind() == RawFunction::kImplicitStaticFinalGetter)) {
    return NULL;
  }
  ASSERT(getter.kind() == RawFunction::kImplicitGetter);
  return new StaticGetterNode(TokenPos(), NULL, false, field_owner, field_name);
}


RawObject* Parser::EvaluateConstConstructorCall(
    const Class& type_class,
    const AbstractTypeArguments& type_arguments,
    const Function& constructor,
    ArgumentListNode* arguments) {
  const int kNumExtraArgs = 2;  // implicit rcvr and construction phase args.
  const int num_arguments = arguments->length() + kNumExtraArgs;
  const Array& arg_values = Array::Handle(Array::New(num_arguments));
  Instance& instance = Instance::Handle();
  ASSERT(!constructor.IsFactory());
  instance = Instance::New(type_class, Heap::kOld);
  if (!type_arguments.IsNull()) {
    if (!type_arguments.IsInstantiated()) {
      ErrorMsg("type must be constant in const constructor");
    }
    instance.SetTypeArguments(
        AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
  }
  arg_values.SetAt(0, instance);
  arg_values.SetAt(1, Smi::Handle(Smi::New(Function::kCtorPhaseAll)));
  for (int i = 0; i < arguments->length(); i++) {
    AstNode* arg = arguments->NodeAt(i);
    // Arguments have been evaluated to a literal value already.
    ASSERT(arg->IsLiteralNode());
    arg_values.SetAt((i + kNumExtraArgs), arg->AsLiteralNode()->literal());
  }
  const Array& args_descriptor =
      Array::Handle(ArgumentsDescriptor::New(num_arguments,
                                             arguments->names()));
  const Object& result =
      Object::Handle(DartEntry::InvokeFunction(constructor,
                                               arg_values,
                                               args_descriptor));
  if (result.IsError()) {
      // An exception may not occur in every parse attempt, i.e., the
      // generated AST is not deterministic. Therefore mark the function as
      // not optimizable.
      current_function().set_is_optimizable(false);
      if (result.IsUnhandledException()) {
        return result.raw();
      } else {
        isolate()->long_jump_base()->Jump(1, Error::Cast(result));
        UNREACHABLE();
        return Object::null();
      }
  } else {
    return TryCanonicalize(instance, TokenPos());
  }
}


// Do a lookup for the identifier in the block scope and the class scope
// return true if the identifier is found, false otherwise.
// If node is non NULL return an AST node corresponding to the identifier.
bool Parser::ResolveIdentInLocalScope(intptr_t ident_pos,
                                      const String &ident,
                                      AstNode** node) {
  TRACE_PARSER("ResolveIdentInLocalScope");
  // First try to find the identifier in the nested local scopes.
  LocalVariable* local = LookupLocalScope(ident);
  if (local != NULL) {
    if (node != NULL) {
      if (local->IsConst()) {
        *node = new LiteralNode(ident_pos, *local->ConstValue());
      } else {
        *node = new LoadLocalNode(ident_pos, local);
      }
    }
    return true;
  }

  // Try to find the identifier in the class scope of the current class.
  // If the current class is the result of a mixin application, we must
  // use the class scope of the class from which the function originates.
  Class& cls = Class::Handle(isolate());
  if (current_class().mixin() == Type::null()) {
    cls = current_class().raw();
  } else {
    cls = parsed_function()->function().origin();
  }
  Function& func = Function::Handle(isolate(), Function::null());
  Field& field = Field::Handle(isolate(), Field::null());

  // First check if a field exists.
  field = cls.LookupField(ident);
  if (!field.IsNull()) {
    if (node != NULL) {
      if (!field.is_static()) {
        CheckInstanceFieldAccess(ident_pos, ident);
        *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
      } else {
        *node = GenerateStaticFieldLookup(field, ident_pos);
      }
    }
    return true;
  }

  // Check if an instance/static function exists.
  func = cls.LookupFunction(ident);
  if (!func.IsNull() &&
      (func.IsDynamicFunction() || func.IsStaticFunction())) {
    if (node != NULL) {
      *node = new PrimaryNode(ident_pos,
                              Function::ZoneHandle(isolate(), func.raw()));
    }
    return true;
  }

  // Now check if a getter/setter method exists for it in which case
  // it is still a field.
  func = cls.LookupGetterFunction(ident);
  if (!func.IsNull()) {
    if (func.IsDynamicFunction()) {
      if (node != NULL) {
        CheckInstanceFieldAccess(ident_pos, ident);
        ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
        *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
      }
      return true;
    } else if (func.IsStaticFunction()) {
      if (node != NULL) {
        ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
        // The static getter may later be changed into a dynamically
        // resolved instance setter if no static setter can
        // be found.
        AstNode* receiver = NULL;
        const bool kTestOnly = true;
        if (!current_function().is_static() &&
            (LookupReceiver(current_block_->scope, kTestOnly) != NULL)) {
          receiver = LoadReceiver(ident_pos);
        }
        *node = new StaticGetterNode(ident_pos,
                                     receiver,
                                     false,
                                     Class::ZoneHandle(isolate(), cls.raw()),
                                     ident);
      }
      return true;
    }
  }
  func = cls.LookupSetterFunction(ident);
  if (!func.IsNull()) {
    if (func.IsDynamicFunction()) {
      if (node != NULL) {
        // We create a getter node even though a getter doesn't exist as
        // it could be followed by an assignment which will convert it to
        // a setter node. If there is no assignment we will get an error
        // when we try to invoke the getter.
        CheckInstanceFieldAccess(ident_pos, ident);
        ASSERT(AbstractType::Handle(func.result_type()).IsResolved());
        *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
      }
      return true;
    } else if (func.IsStaticFunction()) {
      if (node != NULL) {
        // We create a getter node even though a getter doesn't exist as
        // it could be followed by an assignment which will convert it to
        // a setter node. If there is no assignment we will get an error
        // when we try to invoke the getter.
        *node = new StaticGetterNode(ident_pos,
                                     NULL,
                                     false,
                                     Class::ZoneHandle(isolate(), cls.raw()),
                                     ident);
      }
      return true;
    }
  }

  // Nothing found in scope of current class.
  if (node != NULL) {
    *node = NULL;
  }
  return false;  // Not an unqualified identifier.
}


static RawObject* LookupNameInLibrary(Isolate* isolate,
                                      const Library& lib,
                                      const String& name) {
  Object& obj = Object::Handle(isolate);
  obj = lib.LookupLocalObject(name);
  if (!obj.IsNull()) {
    return obj.raw();
  }
  String& accessor_name = String::Handle(isolate, Field::GetterName(name));
  obj = lib.LookupLocalObject(accessor_name);
  if (!obj.IsNull()) {
    return obj.raw();
  }
  accessor_name = Field::SetterName(name);
  obj = lib.LookupLocalObject(accessor_name);
  return obj.raw();
}


static RawObject* LookupNameInImport(Isolate* isolate,
                                     const Namespace& ns,
                                     const String& name) {
  // If the given name is filtered out by the import, don't look it up, nor its
  // getter and setter names.
  if (ns.HidesName(name)) {
    return Object::null();
  }
  Object& obj = Object::Handle(isolate);
  obj = ns.Lookup(name);
  if (!obj.IsNull()) {
    return obj.raw();
  }
  String& accessor_name = String::Handle(isolate, Field::GetterName(name));
  obj = ns.Lookup(accessor_name);
  if (!obj.IsNull()) {
    return obj.raw();
  }
  accessor_name = Field::SetterName(name);
  obj = ns.Lookup(accessor_name);
  return obj.raw();
}


// Resolve a name by checking the global scope of the current
// library. If not found in the current library, then look in the scopes
// of all libraries that are imported without a library prefix.
// Issue an error if the name is not found in the global scope
// of the current library, but is defined in more than one imported
// library, i.e. if the name cannot be resolved unambiguously.
RawObject* Parser::ResolveNameInCurrentLibraryScope(intptr_t ident_pos,
                                                    const String& name,
                                                    Error* error) {
  TRACE_PARSER("ResolveNameInCurrentLibraryScope");
  HANDLESCOPE(isolate());
  Object& obj = Object::Handle(isolate(),
                               LookupNameInLibrary(isolate(), library_, name));
  if (obj.IsNull()) {
    // Name is not found in current library. Check scope of all
    // imported libraries.
    String& first_lib_url = String::Handle(isolate());
    Namespace& import = Namespace::Handle(isolate());
    intptr_t num_imports = library_.num_imports();
    Object& imported_obj = Object::Handle(isolate());
    Library& lib = Library::Handle(isolate());
    for (int i = 0; i < num_imports; i++) {
      import = library_.ImportAt(i);
      imported_obj = LookupNameInImport(isolate(), import, name);
      if (!imported_obj.IsNull()) {
        lib ^= import.library();
        if (!first_lib_url.IsNull()) {
          // Found duplicate definition.
          Error& ambiguous_ref_error = Error::Handle();
          if (first_lib_url.raw() == lib.url()) {
            ambiguous_ref_error = FormatErrorMsg(
                script_, ident_pos, "Error",
                "ambiguous reference to '%s', "
                "as library '%s' is imported multiple times",
                name.ToCString(),
                first_lib_url.ToCString());
          } else {
            ambiguous_ref_error = FormatErrorMsg(
                script_, ident_pos, "Error",
                "ambiguous reference: "
                "'%s' is defined in library '%s' and also in '%s'",
                name.ToCString(),
                first_lib_url.ToCString(),
                String::Handle(lib.url()).ToCString());
          }
          if (error == NULL) {
            // Report a compile time error since the caller is not interested
            // in the error.
            ErrorMsg(ambiguous_ref_error);
          }
          *error = ambiguous_ref_error.raw();
          return Object::null();
        } else {
          first_lib_url = lib.url();
          obj = imported_obj.raw();
        }
      }
    }
  }
  return obj.raw();
}


RawClass* Parser::ResolveClassInCurrentLibraryScope(intptr_t ident_pos,
                                                    const String& name,
                                                    Error* error) {
  const Object& obj =
      Object::Handle(ResolveNameInCurrentLibraryScope(ident_pos, name, error));
  if (obj.IsClass()) {
    return Class::Cast(obj).raw();
  }
  return Class::null();
}


// Resolve an identifier by checking the global scope of the current
// library. If not found in the current library, then look in the scopes
// of all libraries that are imported without a library prefix.
// Issue an error if the identifier is not found in the global scope
// of the current library, but is defined in more than one imported
// library, i.e. if the identifier cannot be resolved unambiguously.
AstNode* Parser::ResolveIdentInCurrentLibraryScope(intptr_t ident_pos,
                                                   const String& ident) {
  TRACE_PARSER("ResolveIdentInCurrentLibraryScope");
  const Object& obj =
    Object::Handle(ResolveNameInCurrentLibraryScope(ident_pos, ident, NULL));
  if (obj.IsClass()) {
    const Class& cls = Class::Cast(obj);
    return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw()));
  } else if (obj.IsField()) {
    const Field& field = Field::Cast(obj);
    ASSERT(field.is_static());
    return GenerateStaticFieldLookup(field, ident_pos);
  } else if (obj.IsFunction()) {
    const Function& func = Function::Cast(obj);
    ASSERT(func.is_static());
    if (func.IsGetterFunction() || func.IsSetterFunction()) {
      return new StaticGetterNode(ident_pos,
                                  /* receiver */ NULL,
                                  /* is_super_getter */ false,
                                  Class::ZoneHandle(func.Owner()),
                                  ident);

    } else {
      return new PrimaryNode(ident_pos, Function::ZoneHandle(func.raw()));
    }
  } else {
    ASSERT(obj.IsNull() || obj.IsLibraryPrefix());
  }
  // Lexically unresolved primary identifiers are referenced by their name.
  return new PrimaryNode(ident_pos, ident);
}


RawObject* Parser::ResolveNameInPrefixScope(intptr_t ident_pos,
                                            const LibraryPrefix& prefix,
                                            const String& name,
                                            Error* error) {
  TRACE_PARSER("ResolveNameInPrefixScope");
  HANDLESCOPE(isolate());
  Namespace& import = Namespace::Handle(isolate());
  String& first_lib_url = String::Handle(isolate());
  Object& obj = Object::Handle(isolate());
  Object& resolved_obj = Object::Handle(isolate());
  const Array& imports = Array::Handle(isolate(), prefix.imports());
  Library& lib = Library::Handle(isolate());
  for (intptr_t i = 0; i < prefix.num_imports(); i++) {
    import ^= imports.At(i);
    resolved_obj = LookupNameInImport(isolate(), import, name);
    if (!resolved_obj.IsNull()) {
      obj = resolved_obj.raw();
      lib = import.library();
      if (first_lib_url.IsNull()) {
        first_lib_url = lib.url();
      } else {
        // Found duplicate definition.
        Error& ambiguous_ref_error = Error::Handle();
        if (first_lib_url.raw() == lib.url()) {
          ambiguous_ref_error = FormatErrorMsg(
              script_, ident_pos, "Error",
              "ambiguous reference: '%s.%s' is imported multiple times",
              String::Handle(prefix.name()).ToCString(),
              name.ToCString());
        } else {
          ambiguous_ref_error = FormatErrorMsg(
              script_, ident_pos, "Error",
              "ambiguous reference: '%s.%s' is defined in '%s' and '%s'",
              String::Handle(prefix.name()).ToCString(),
              name.ToCString(),
              first_lib_url.ToCString(),
              String::Handle(lib.url()).ToCString());
        }
        if (error == NULL) {
          // Report a compile time error since the caller is not interested
          // in the error.
          ErrorMsg(ambiguous_ref_error);
        }
        *error = ambiguous_ref_error.raw();
        return Object::null();
      }
    }
  }
  return obj.raw();
}


RawClass* Parser::ResolveClassInPrefixScope(intptr_t ident_pos,
                                            const LibraryPrefix& prefix,
                                            const String& name,
                                            Error* error) {
  const Object& obj =
      Object::Handle(ResolveNameInPrefixScope(ident_pos, prefix, name, error));
  if (obj.IsClass()) {
    return Class::Cast(obj).raw();
  }
  return Class::null();
}


// Do a lookup for the identifier in the scope of the specified
// library prefix. This means trying to resolve it locally in all of the
// libraries present in the library prefix. If there are multiple libraries
// with the name, issue an ambiguous reference error.
AstNode* Parser::ResolveIdentInPrefixScope(intptr_t ident_pos,
                                           const LibraryPrefix& prefix,
                                           const String& ident) {
  TRACE_PARSER("ResolveIdentInPrefixScope");
  Object& obj =
      Object::Handle(ResolveNameInPrefixScope(ident_pos, prefix, ident, NULL));
  if (obj.IsNull()) {
    // Unresolved prefixed primary identifier.
    ErrorMsg(ident_pos, "identifier '%s.%s' cannot be resolved",
             String::Handle(prefix.name()).ToCString(),
             ident.ToCString());
  }
  if (obj.IsClass()) {
    const Class& cls = Class::Cast(obj);
    return new PrimaryNode(ident_pos, Class::ZoneHandle(cls.raw()));
  } else if (obj.IsField()) {
    const Field& field = Field::Cast(obj);
    ASSERT(field.is_static());
    return GenerateStaticFieldLookup(field, ident_pos);
  } else if (obj.IsFunction()) {
    const Function& func = Function::Cast(obj);
    ASSERT(func.is_static());
    if (func.IsGetterFunction() || func.IsSetterFunction()) {
      return new StaticGetterNode(ident_pos,
                                  /* receiver */ NULL,
                                  /* is_super_getter */ false,
                                  Class::ZoneHandle(func.Owner()),
                                  ident);

    } else {
      return new PrimaryNode(ident_pos, Function::ZoneHandle(func.raw()));
    }
  } else {
    // TODO(hausner): Should this be an error? It is not meaningful to
    // reference a library prefix defined in an imported library.
    ASSERT(obj.IsLibraryPrefix());
  }
  // Lexically unresolved primary identifiers are referenced by their name.
  return new PrimaryNode(ident_pos, ident);
}


// Resolve identifier. Issue an error message if
// the ident refers to a method and allow_closure_names is false.
// If the name cannot be resolved, turn it into an instance field access
// if we're compiling an instance method, or issue an error message
// if we're compiling a static method.
AstNode* Parser::ResolveIdent(intptr_t ident_pos,
                              const String& ident,
                              bool allow_closure_names) {
  TRACE_PARSER("ResolveIdent");
  // First try to find the variable in the local scope (block scope or
  // class scope).
  AstNode* resolved = NULL;
  ResolveIdentInLocalScope(ident_pos, ident, &resolved);
  if (resolved == NULL) {
    // Check whether the identifier is a type parameter.
    if (!current_class().IsNull()) {
      TypeParameter& type_parameter = TypeParameter::ZoneHandle(
          current_class().LookupTypeParameter(ident));
      if (!type_parameter.IsNull()) {
        if (current_block_->scope->function_level() > 0) {
          // Make sure that the instantiator is captured.
          CaptureInstantiator();
        }
        type_parameter ^= ClassFinalizer::FinalizeType(
            current_class(), type_parameter, ClassFinalizer::kFinalize);
        ASSERT(!type_parameter.IsMalformed());
        return new TypeNode(ident_pos, type_parameter);
      }
    }
    // Not found in the local scope, and the name is not a type parameter.
    // Try finding the variable in the library scope (current library
    // and all libraries imported by it without a library prefix).
    resolved = ResolveIdentInCurrentLibraryScope(ident_pos, ident);
  }
  if (resolved->IsPrimaryNode()) {
    PrimaryNode* primary = resolved->AsPrimaryNode();
    if (primary->primary().IsString()) {
      // We got an unresolved name. If we are compiling a static
      // method, evaluation of an unresolved identifier causes a
      // NoSuchMethodError to be thrown. In an instance method, we convert
      // the unresolved name to an instance field access, since a
      // subclass might define a field with this name.
      if (current_function().is_static()) {
        resolved = ThrowNoSuchMethodError(ident_pos,
                                          current_class(),
                                          ident,
                                          InvocationMirror::kStatic,
                                          InvocationMirror::kField);
      } else {
        // Treat as call to unresolved instance field.
        resolved = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
      }
    } else if (primary->primary().IsFunction()) {
      if (allow_closure_names) {
        resolved = LoadClosure(primary);
      } else {
        ErrorMsg(ident_pos, "illegal reference to method '%s'",
                 ident.ToCString());
      }
    } else if (primary->primary().IsClass()) {
      const Class& type_class = Class::Cast(primary->primary());
      Type& type = Type::ZoneHandle(
          Type::New(type_class, TypeArguments::Handle(),
                    primary->token_pos(), Heap::kOld));
      type ^= ClassFinalizer::FinalizeType(
          current_class(), type, ClassFinalizer::kCanonicalize);
      ASSERT(!type.IsMalformed());
      resolved = new TypeNode(primary->token_pos(), type);
    }
  }
  return resolved;
}


// Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
// finalize it according to the given type finalization mode.
RawAbstractType* Parser::ParseType(
    ClassFinalizer::FinalizationKind finalization) {
  TRACE_PARSER("ParseType");
  if (CurrentToken() != Token::kIDENT) {
    ErrorMsg("type name expected");
  }
  QualIdent type_name;
  if (finalization == ClassFinalizer::kIgnore) {
    SkipQualIdent();
  } else {
    ParseQualIdent(&type_name);
    // An identifier cannot be resolved in a local scope when top level parsing.
    if (!is_top_level_ &&
        (type_name.lib_prefix == NULL) &&
        ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) {
      // The type is malformed. Skip over its type arguments.
      ParseTypeArguments(ClassFinalizer::kIgnore);
      if (finalization == ClassFinalizer::kCanonicalizeWellFormed) {
        return ClassFinalizer::NewFinalizedMalformedType(
            Error::Handle(),  // No previous error.
            current_class(),
            type_name.ident_pos,
            "using '%s' in this context is invalid",
            type_name.ident->ToCString());
      }
      return Type::DynamicType();
    }
  }
  Object& type_class = Object::Handle(isolate());
  // Leave type_class as null if type finalization mode is kIgnore.
  if (finalization != ClassFinalizer::kIgnore) {
    LibraryPrefix& lib_prefix = LibraryPrefix::Handle(isolate());
    if (type_name.lib_prefix != NULL) {
      lib_prefix = type_name.lib_prefix->raw();
    }
    type_class = UnresolvedClass::New(lib_prefix,
                                      *type_name.ident,
                                      type_name.ident_pos);
  }
  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
      isolate(), ParseTypeArguments(finalization));
  if (finalization == ClassFinalizer::kIgnore) {
    return Type::DynamicType();
  }
  AbstractType& type = AbstractType::Handle(
      isolate(), Type::New(type_class, type_arguments, type_name.ident_pos));
  if (finalization >= ClassFinalizer::kResolveTypeParameters) {
    ResolveTypeFromClass(current_class(), finalization, &type);
    if (finalization >= ClassFinalizer::kCanonicalize) {
      type ^= ClassFinalizer::FinalizeType(current_class(), type, finalization);
    }
  }
  return type.raw();
}


void Parser::CheckConstructorCallTypeArguments(
    intptr_t pos, Function& constructor,
    const AbstractTypeArguments& type_arguments) {
  if (!type_arguments.IsNull()) {
    const Class& constructor_class = Class::Handle(constructor.Owner());
    ASSERT(!constructor_class.IsNull());
    ASSERT(constructor_class.is_finalized());
    // Do not report the expected vs. actual number of type arguments, because
    // the type argument vector is flattened and raw types are allowed.
    if (type_arguments.Length() != constructor_class.NumTypeArguments()) {
      ErrorMsg(pos, "wrong number of type arguments passed to constructor");
    }
  }
}


// Parse "[" [ expr { "," expr } ["," ] "]".
// Note: if the list literal is empty and the brackets have no whitespace
// between them, the scanner recognizes the opening and closing bracket
// as one token of type Token::kINDEX.
AstNode* Parser::ParseListLiteral(intptr_t type_pos,
                                  bool is_const,
                                  const AbstractTypeArguments& type_arguments) {
  TRACE_PARSER("ParseListLiteral");
  ASSERT(type_pos >= 0);
  ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX);
  const intptr_t literal_pos = TokenPos();
  bool is_empty_literal = CurrentToken() == Token::kINDEX;
  ConsumeToken();

  AbstractType& element_type = Type::ZoneHandle(Type::DynamicType());
  AbstractTypeArguments& list_type_arguments =
      AbstractTypeArguments::ZoneHandle(type_arguments.raw());
  // If no type argument vector is provided, leave it as null, which is
  // equivalent to using dynamic as the type argument for the element type.
  if (!list_type_arguments.IsNull()) {
    ASSERT(list_type_arguments.Length() > 0);
    // List literals take a single type argument.
    if (list_type_arguments.Length() == 1) {
      element_type = list_type_arguments.TypeAt(0);
    } else {
      if (FLAG_error_on_malformed_type) {
        ErrorMsg(type_pos,
                 "a list literal takes one type argument specifying "
                 "the element type");
      }
      // Ignore type arguments.
      list_type_arguments = AbstractTypeArguments::null();
    }
    if (is_const && !element_type.IsInstantiated()) {
      ErrorMsg(type_pos,
               "the type argument of a constant list literal cannot include "
               "a type variable");
    }
  }
  ASSERT((list_type_arguments.IsNull() && element_type.IsDynamicType()) ||
         ((list_type_arguments.Length() == 1) && !element_type.IsNull()));
  const Class& array_class = Class::Handle(
      isolate()->object_store()->array_class());
  Type& type = Type::ZoneHandle(
      Type::New(array_class, list_type_arguments, type_pos));
  type ^= ClassFinalizer::FinalizeType(
      current_class(), type, ClassFinalizer::kCanonicalize);
  GrowableArray<AstNode*> element_list;
  // Parse the list elements. Note: there may be an optional extra
  // comma after the last element.
  if (!is_empty_literal) {
    const bool saved_mode = SetAllowFunctionLiterals(true);
    while (CurrentToken() != Token::kRBRACK) {
      const intptr_t element_pos = TokenPos();
      AstNode* element = ParseExpr(is_const, kConsumeCascades);
      if (FLAG_enable_type_checks &&
          !is_const &&
          !element_type.IsDynamicType()) {
        element = new AssignableNode(element_pos,
                                     element,
                                     element_type,
                                     Symbols::ListLiteralElement());
      }
      element_list.Add(element);
      if (CurrentToken() == Token::kCOMMA) {
        ConsumeToken();
      } else if (CurrentToken() != Token::kRBRACK) {
        ErrorMsg("comma or ']' expected");
      }
    }
    ExpectToken(Token::kRBRACK);
    SetAllowFunctionLiterals(saved_mode);
  }

  if (is_const) {
    // Allocate and initialize the const list at compile time.
    Array& const_list =
        Array::ZoneHandle(Array::New(element_list.length(), Heap::kOld));
    const_list.SetTypeArguments(
        AbstractTypeArguments::Handle(list_type_arguments.Canonicalize()));
    Error& malformed_error = Error::Handle();
    for (int i = 0; i < element_list.length(); i++) {
      AstNode* elem = element_list[i];
      // Arguments have been evaluated to a literal value already.
      ASSERT(elem->IsLiteralNode());
      ASSERT(!is_top_level_);  // We cannot check unresolved types.
      if (FLAG_enable_type_checks &&
          !element_type.IsDynamicType() &&
          (!elem->AsLiteralNode()->literal().IsNull() &&
           !elem->AsLiteralNode()->literal().IsInstanceOf(
               element_type, TypeArguments::Handle(), &malformed_error))) {
        // If the failure is due to a malformed type error, display it instead.
        if (!malformed_error.IsNull()) {
          ErrorMsg(malformed_error);
        } else {
          ErrorMsg(elem->AsLiteralNode()->token_pos(),
                   "list literal element at index %d must be "
                   "a constant of type '%s'",
                   i,
                   String::Handle(element_type.UserVisibleName()).ToCString());
        }
      }
      const_list.SetAt(i, elem->AsLiteralNode()->literal());
    }
    const_list ^= TryCanonicalize(const_list, literal_pos);
    const_list.MakeImmutable();
    return new LiteralNode(literal_pos, const_list);
  } else {
    // Factory call at runtime.
    const Class& factory_class =
        Class::Handle(LookupCoreClass(Symbols::List()));
    ASSERT(!factory_class.IsNull());
    const Function& factory_method = Function::ZoneHandle(
        factory_class.LookupFactory(
            PrivateCoreLibName(Symbols::ListLiteralFactory())));
    ASSERT(!factory_method.IsNull());
    if (!list_type_arguments.IsNull() &&
        !list_type_arguments.IsInstantiated() &&
        (current_block_->scope->function_level() > 0)) {
      // Make sure that the instantiator is captured.
      CaptureInstantiator();
    }
    AbstractTypeArguments& factory_type_args =
        AbstractTypeArguments::ZoneHandle(list_type_arguments.raw());
    // If the factory class extends other parameterized classes, adjust the
    // type argument vector.
    if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 1)) {
      ASSERT(factory_type_args.Length() == 1);
      Type& factory_type = Type::Handle(Type::New(
          factory_class, factory_type_args, type_pos, Heap::kNew));
      factory_type ^= ClassFinalizer::FinalizeType(
          current_class(), factory_type, ClassFinalizer::kFinalize);
      factory_type_args = factory_type.arguments();
      ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments());
    }
    factory_type_args = factory_type_args.Canonicalize();
    ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
    if (element_list.length() == 0) {
      // TODO(srdjan): Use Object::empty_array once issue 9871 has been fixed.
      Array& empty_array = Array::ZoneHandle(Object::empty_array().raw());
      LiteralNode* empty_array_literal =
          new LiteralNode(TokenPos(), empty_array);
      factory_param->Add(empty_array_literal);
    } else {
      ArrayNode* list = new ArrayNode(TokenPos(), type, element_list);
      factory_param->Add(list);
    }
    return CreateConstructorCallNode(literal_pos,
                                     factory_type_args,
                                     factory_method,
                                     factory_param);
  }
}


ConstructorCallNode* Parser::CreateConstructorCallNode(
    intptr_t token_pos,
    const AbstractTypeArguments& type_arguments,
    const Function& constructor,
    ArgumentListNode* arguments) {
  if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
    EnsureExpressionTemp();
  }
  return new ConstructorCallNode(token_pos,
                                 type_arguments,
                                 constructor,
                                 arguments);
}


static void AddKeyValuePair(GrowableArray<AstNode*>* pairs,
                            bool is_const,
                            AstNode* key,
                            AstNode* value) {
  if (is_const) {
    ASSERT(key->IsLiteralNode());
    const Instance& new_key = key->AsLiteralNode()->literal();
    for (int i = 0; i < pairs->length(); i += 2) {
      const Instance& key_i = (*pairs)[i]->AsLiteralNode()->literal();
      // The keys of a compile time constant map are compile time
      // constants, i.e. canonicalized values. Thus, we can compare
      // raw pointers to check for equality.
      if (new_key.raw() == key_i.raw()) {
        // Duplicate key found. The new value replaces the previously
        // defined value.
        (*pairs)[i + 1] = value;
        return;
      }
    }
  }
  pairs->Add(key);
  pairs->Add(value);
}


AstNode* Parser::ParseMapLiteral(intptr_t type_pos,
                                 bool is_const,
                                 const AbstractTypeArguments& type_arguments) {
  TRACE_PARSER("ParseMapLiteral");
  ASSERT(type_pos >= 0);
  ASSERT(CurrentToken() == Token::kLBRACE);
  const intptr_t literal_pos = TokenPos();
  ConsumeToken();

  AbstractType& key_type = Type::ZoneHandle(Type::DynamicType());
  AbstractType& value_type = Type::ZoneHandle(Type::DynamicType());
  AbstractTypeArguments& map_type_arguments =
      AbstractTypeArguments::ZoneHandle(type_arguments.raw());
  // If no type argument vector is provided, leave it as null, which is
  // equivalent to using dynamic as the type argument for the both key and value
  // types.
  if (!map_type_arguments.IsNull()) {
    ASSERT(map_type_arguments.Length() > 0);
    // Map literals take two type arguments.
    if (map_type_arguments.Length() == 2) {
      key_type = map_type_arguments.TypeAt(0);
      value_type = map_type_arguments.TypeAt(1);
      if (is_const && !type_arguments.IsInstantiated()) {
        ErrorMsg(type_pos,
                 "the type arguments of a constant map literal cannot include "
                 "a type variable");
      }
      if (key_type.IsMalformed()) {
        if (FLAG_error_on_malformed_type) {
          ErrorMsg(Error::Handle(key_type.malformed_error()));
        }
        // Map malformed key type to dynamic.
        key_type = Type::DynamicType();
        map_type_arguments.SetTypeAt(0, key_type);
      }
      if (value_type.IsMalformed()) {
        if (FLAG_error_on_malformed_type) {
          ErrorMsg(Error::Handle(value_type.malformed_error()));
        }
        // Map malformed value type to dynamic.
        value_type = Type::DynamicType();
        map_type_arguments.SetTypeAt(1, value_type);
      }
    } else {
      if (FLAG_error_on_malformed_type) {
        ErrorMsg(type_pos,
                 "a map literal takes two type arguments specifying "
                 "the key type and the value type");
      }
      // Ignore type arguments.
      map_type_arguments = AbstractTypeArguments::null();
    }
  }
  ASSERT((map_type_arguments.IsNull() &&
          key_type.IsDynamicType() && value_type.IsDynamicType()) ||
         ((map_type_arguments.Length() == 2) &&
          !key_type.IsMalformed() && !value_type.IsMalformed()));
  map_type_arguments ^= map_type_arguments.Canonicalize();

  GrowableArray<AstNode*> kv_pairs_list;
  // Parse the map entries. Note: there may be an optional extra
  // comma after the last entry.
  while (CurrentToken() != Token::kRBRACE) {
    const bool saved_mode = SetAllowFunctionLiterals(true);
    const intptr_t key_pos = TokenPos();
    AstNode* key = ParseExpr(is_const, kConsumeCascades);
    if (FLAG_enable_type_checks &&
        !is_const &&
        !key_type.IsDynamicType()) {
      key = new AssignableNode(key_pos,
                               key,
                               key_type,
                               Symbols::ListLiteralElement());
    }
    ExpectToken(Token::kCOLON);
    const intptr_t value_pos = TokenPos();
    AstNode* value = ParseExpr(is_const, kConsumeCascades);
    SetAllowFunctionLiterals(saved_mode);
    if (FLAG_enable_type_checks &&
        !is_const &&
        !value_type.IsDynamicType()) {
      value = new AssignableNode(value_pos,
                                 value,
                                 value_type,
                                 Symbols::ListLiteralElement());
    }
    AddKeyValuePair(&kv_pairs_list, is_const, key, value);

    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    } else if (CurrentToken() != Token::kRBRACE) {
      ErrorMsg("comma or '}' expected");
    }
  }
  ASSERT(kv_pairs_list.length() % 2 == 0);
  ExpectToken(Token::kRBRACE);

  if (is_const) {
    // Create the key-value pair array, canonicalize it and then create
    // the immutable map object with it. This all happens at compile time.
    // The resulting immutable map object is returned as a literal.

    // First, create the canonicalized key-value pair array.
    Array& key_value_array =
        Array::ZoneHandle(Array::New(kv_pairs_list.length(), Heap::kOld));
    AbstractType& arg_type = Type::Handle();
    Error& malformed_error = Error::Handle();
    for (int i = 0; i < kv_pairs_list.length(); i++) {
      AstNode* arg = kv_pairs_list[i];
      // Arguments have been evaluated to a literal value already.
      ASSERT(arg->IsLiteralNode());
      ASSERT(!is_top_level_);  // We cannot check unresolved types.
      if (FLAG_enable_type_checks) {
        if ((i % 2) == 0) {
          // Check key type.
          arg_type = key_type.raw();
        } else {
          // Check value type.
          arg_type = value_type.raw();
        }
        if (!arg_type.IsDynamicType() &&
            (!arg->AsLiteralNode()->literal().IsNull() &&
             !arg->AsLiteralNode()->literal().IsInstanceOf(
                 arg_type,
                 Object::null_abstract_type_arguments(),
                 &malformed_error))) {
          // If the failure is due to a malformed type error, display it.
          if (!malformed_error.IsNull()) {
            ErrorMsg(malformed_error);
          } else {
            ErrorMsg(arg->AsLiteralNode()->token_pos(),
                     "map literal %s at index %d must be "
                     "a constant of type '%s'",
                     ((i % 2) == 0) ? "key" : "value",
                     i >> 1,
                     String::Handle(arg_type.UserVisibleName()).ToCString());
          }
        }
      }
      key_value_array.SetAt(i, arg->AsLiteralNode()->literal());
    }
    key_value_array ^= TryCanonicalize(key_value_array, TokenPos());
    key_value_array.MakeImmutable();

    // Construct the map object.
    const Class& immutable_map_class =
        Class::Handle(LookupCoreClass(Symbols::ImmutableMap()));
    ASSERT(!immutable_map_class.IsNull());
    // If the immutable map class extends other parameterized classes, we need
    // to adjust the type argument vector. This is currently not the case.
    ASSERT(immutable_map_class.NumTypeArguments() == 2);
    ArgumentListNode* constr_args = new ArgumentListNode(TokenPos());
    constr_args->Add(new LiteralNode(literal_pos, key_value_array));
    const Function& map_constr =
        Function::ZoneHandle(immutable_map_class.LookupConstructor(
            PrivateCoreLibName(Symbols::ImmutableMapConstructor())));
    ASSERT(!map_constr.IsNull());
    const Object& constructor_result = Object::Handle(
        EvaluateConstConstructorCall(immutable_map_class,
                                     map_type_arguments,
                                     map_constr,
                                     constr_args));
    if (constructor_result.IsUnhandledException()) {
      return GenerateRethrow(literal_pos, constructor_result);
    } else {
      const Instance& const_instance = Instance::Cast(constructor_result);
      return new LiteralNode(literal_pos,
                             Instance::ZoneHandle(const_instance.raw()));
    }
  } else {
    // Factory call at runtime.
    const Class& factory_class =
        Class::Handle(LookupCoreClass(Symbols::Map()));
    ASSERT(!factory_class.IsNull());
    const Function& factory_method = Function::ZoneHandle(
        factory_class.LookupFactory(
            PrivateCoreLibName(Symbols::MapLiteralFactory())));
    ASSERT(!factory_method.IsNull());
    if (!map_type_arguments.IsNull() &&
        !map_type_arguments.IsInstantiated() &&
        (current_block_->scope->function_level() > 0)) {
      // Make sure that the instantiator is captured.
      CaptureInstantiator();
    }
    AbstractTypeArguments& factory_type_args =
        AbstractTypeArguments::ZoneHandle(map_type_arguments.raw());
    // If the factory class extends other parameterized classes, adjust the
    // type argument vector.
    if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 2)) {
      ASSERT(factory_type_args.Length() == 2);
      Type& factory_type = Type::Handle(Type::New(
          factory_class, factory_type_args, type_pos, Heap::kNew));
      factory_type ^= ClassFinalizer::FinalizeType(
          current_class(), factory_type, ClassFinalizer::kFinalize);
      factory_type_args = factory_type.arguments();
      ASSERT(factory_type_args.Length() == factory_class.NumTypeArguments());
    }
    factory_type_args = factory_type_args.Canonicalize();
    ArgumentListNode* factory_param = new ArgumentListNode(literal_pos);
    // The kv_pair array is temporary and of element type dynamic. It is passed
    // to the factory to initialize a properly typed map.
    ArrayNode* kv_pairs = new ArrayNode(
        TokenPos(),
        Type::ZoneHandle(Type::ArrayType()),
        kv_pairs_list);
    factory_param->Add(kv_pairs);
    return CreateConstructorCallNode(literal_pos,
                                     factory_type_args,
                                     factory_method,
                                     factory_param);
  }
}


AstNode* Parser::ParseCompoundLiteral() {
  TRACE_PARSER("ParseCompoundLiteral");
  bool is_const = false;
  if (CurrentToken() == Token::kCONST) {
    is_const = true;
    ConsumeToken();
  }
  const intptr_t type_pos = TokenPos();
  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
      ParseTypeArguments(ClassFinalizer::kCanonicalize));
  // Map and List interfaces do not declare bounds on their type parameters, so
  // we should never see a malformed type argument mapped to dynamic here.
  AstNode* primary = NULL;
  if ((CurrentToken() == Token::kLBRACK) ||
      (CurrentToken() == Token::kINDEX)) {
    primary = ParseListLiteral(type_pos, is_const, type_arguments);
  } else if (CurrentToken() == Token::kLBRACE) {
    primary = ParseMapLiteral(type_pos, is_const, type_arguments);
  } else {
    ErrorMsg("unexpected token %s", Token::Str(CurrentToken()));
  }
  return primary;
}


static const String& BuildConstructorName(const String& type_class_name,
                                          const String* named_constructor) {
  // By convention, the static function implementing a named constructor 'C'
  // for class 'A' is labeled 'A.C', and the static function implementing the
  // unnamed constructor for class 'A' is labeled 'A.'.
  // This convention prevents users from explicitly calling constructors.
  String& constructor_name =
      String::Handle(String::Concat(type_class_name, Symbols::Dot()));
  if (named_constructor != NULL) {
    constructor_name = String::Concat(constructor_name, *named_constructor);
  }
  return constructor_name;
}


AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
  TRACE_PARSER("ParseNewOperator");
  const intptr_t new_pos = TokenPos();
  ASSERT((op_kind == Token::kNEW) || (op_kind == Token::kCONST));
  bool is_const = (op_kind == Token::kCONST);
  if (!IsIdentifier()) {
    ErrorMsg("type name expected");
  }
  intptr_t type_pos = TokenPos();
  AbstractType& type = AbstractType::Handle(
      ParseType(ClassFinalizer::kCanonicalizeWellFormed));
  // In case the type is malformed, throw a dynamic type error after finishing
  // parsing the instance creation expression.
  if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) {
    // Replace the type with a malformed type.
    type = ClassFinalizer::NewFinalizedMalformedType(
        Error::Handle(),  // No previous error.
        current_class(),
        type_pos,
        "%s'%s' cannot be instantiated",
        type.IsTypeParameter() ? "type parameter " : "",
        type.IsTypeParameter() ?
            String::Handle(type.UserVisibleName()).ToCString() : "dynamic");
  }

  // The grammar allows for an optional ('.' identifier)? after the type, which
  // is a named constructor. Note that ParseType() above will not consume it as
  // part of a misinterpreted qualified identifier, because only a valid library
  // prefix is accepted as qualifier.
  String* named_constructor = NULL;
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    named_constructor = ExpectIdentifier("name of constructor expected");
  }

  // Parse constructor parameters.
  if (CurrentToken() != Token::kLPAREN) {
    ErrorMsg("'(' expected");
  }
  intptr_t call_pos = TokenPos();
  ArgumentListNode* arguments = ParseActualParameters(NULL, is_const);

  // Parsing is complete, so we can return a throw in case of a malformed type
  // or report a compile-time error if the constructor is const.
  if (type.IsMalformed()) {
    if (is_const) {
      const Error& error = Error::Handle(type.malformed_error());
      ErrorMsg(error);
    }
    return ThrowTypeError(type_pos, type);
  }

  // Resolve the type and optional identifier to a constructor or factory.
  Class& type_class = Class::Handle(type.type_class());
  const String& type_class_name = String::Handle(type_class.Name());
  AbstractTypeArguments& type_arguments =
      AbstractTypeArguments::ZoneHandle(type.arguments());

  // A constructor has an implicit 'this' parameter (instance to construct)
  // and a factory has an implicit 'this' parameter (type_arguments).
  // A constructor has a second implicit 'phase' parameter.
  intptr_t arguments_length = arguments->length() + 2;

  // An additional type check of the result of a redirecting factory may be
  // required.
  AbstractType& type_bound = AbstractType::ZoneHandle();

  // Make sure that an appropriate constructor exists.
  const String& constructor_name =
      BuildConstructorName(type_class_name, named_constructor);
  Function& constructor = Function::ZoneHandle(
      type_class.LookupConstructor(constructor_name));
  if (constructor.IsNull()) {
    constructor = type_class.LookupFactory(constructor_name);
    if (constructor.IsNull()) {
      const String& external_constructor_name =
          (named_constructor ? constructor_name : type_class_name);
      // Replace the type with a malformed type and compile a throw or report a
      // compile-time error if the constructor is const.
      if (is_const) {
        type = ClassFinalizer::NewFinalizedMalformedType(
            Error::Handle(),  // No previous error.
            current_class(),
            call_pos,
            "class '%s' has no constructor or factory named '%s'",
            String::Handle(type_class.Name()).ToCString(),
            external_constructor_name.ToCString());
        const Error& error = Error::Handle(type.malformed_error());
        ErrorMsg(error);
      }
      return ThrowNoSuchMethodError(call_pos,
                                    type_class,
                                    external_constructor_name,
                                    InvocationMirror::kConstructor,
                                    InvocationMirror::kMethod);
    } else if (constructor.IsRedirectingFactory()) {
      ClassFinalizer::ResolveRedirectingFactory(type_class, constructor);
      Type& redirect_type = Type::Handle(constructor.RedirectionType());
      if (!redirect_type.IsMalformed() && !redirect_type.IsInstantiated()) {
        // The type arguments of the redirection type are instantiated from the
        // type arguments of the parsed type of the 'new' or 'const' expression.
        Error& malformed_error = Error::Handle();
        redirect_type ^= redirect_type.InstantiateFrom(type_arguments,
                                                       &malformed_error);
        if (!malformed_error.IsNull()) {
          redirect_type.set_malformed_error(malformed_error);
        }
      }
      if (redirect_type.IsMalformed()) {
        if (is_const) {
          ErrorMsg(Error::Handle(redirect_type.malformed_error()));
        }
        return ThrowTypeError(redirect_type.token_pos(), redirect_type);
      }
      if (FLAG_enable_type_checks && !redirect_type.IsSubtypeOf(type, NULL)) {
        // Additional type checking of the result is necessary.
        type_bound = type.raw();
      }
      type = redirect_type.raw();
      type_class = type.type_class();
      type_arguments = type.arguments();
      constructor = constructor.RedirectionTarget();
      ASSERT(!constructor.IsNull());
    }
    if (constructor.IsFactory()) {
      // A factory does not have the implicit 'phase' parameter.
      arguments_length -= 1;
    }
  }

  // It is ok to call a factory method of an abstract class, but it is
  // a dynamic error to instantiate an abstract class.
  ASSERT(!constructor.IsNull());
  if (type_class.is_abstract() && !constructor.IsFactory()) {
    ArgumentListNode* arguments = new ArgumentListNode(type_pos);
    arguments->Add(new LiteralNode(
        TokenPos(), Integer::ZoneHandle(Integer::New(type_pos))));
    arguments->Add(new LiteralNode(
        TokenPos(), String::ZoneHandle(type_class_name.raw())));
    return MakeStaticCall(Symbols::AbstractClassInstantiationError(),
                          PrivateCoreLibName(Symbols::ThrowNew()),
                          arguments);
  }
  String& error_message = String::Handle();
  if (!constructor.AreValidArguments(arguments_length,
                                     arguments->names(),
                                     &error_message)) {
    const String& external_constructor_name =
        (named_constructor ? constructor_name : type_class_name);
    if (is_const) {
      ErrorMsg(call_pos,
               "invalid arguments passed to constructor '%s' "
               "for class '%s': %s",
               external_constructor_name.ToCString(),
               String::Handle(type_class.Name()).ToCString(),
               error_message.ToCString());
    }
    return ThrowNoSuchMethodError(call_pos,
                                  type_class,
                                  external_constructor_name,
                                  InvocationMirror::kConstructor,
                                  InvocationMirror::kMethod);
  }

  // Return a throw in case of a malformed type or report a compile-time error
  // if the constructor is const.
  if (type.IsMalformed()) {
    if (is_const) {
      const Error& error = Error::Handle(type.malformed_error());
      ErrorMsg(error);
    }
    return ThrowTypeError(type_pos, type);
  }
  type_arguments ^= type_arguments.Canonicalize();
  // Make the constructor call.
  AstNode* new_object = NULL;
  if (is_const) {
    if (!constructor.is_const()) {
      ErrorMsg("'const' requires const constructor: '%s'",
          String::Handle(constructor.name()).ToCString());
    }
    const Object& constructor_result = Object::Handle(
        EvaluateConstConstructorCall(type_class,
                                     type_arguments,
                                     constructor,
                                     arguments));
    if (constructor_result.IsUnhandledException()) {
      new_object = GenerateRethrow(new_pos, constructor_result);
    } else {
      const Instance& const_instance = Instance::Cast(constructor_result);
      new_object = new LiteralNode(new_pos,
                                   Instance::ZoneHandle(const_instance.raw()));
      if (!type_bound.IsNull()) {
        ASSERT(!type_bound.IsMalformed());
        Error& malformed_error = Error::Handle();
        ASSERT(!is_top_level_);  // We cannot check unresolved types.
        if (!const_instance.IsInstanceOf(type_bound,
                                         TypeArguments::Handle(),
                                         &malformed_error)) {
          type_bound = ClassFinalizer::NewFinalizedMalformedType(
              malformed_error,
              current_class(),
              new_pos,
              "const factory result is not an instance of '%s'",
              String::Handle(type_bound.UserVisibleName()).ToCString());
          new_object = ThrowTypeError(new_pos, type_bound);
        }
        type_bound = AbstractType::null();
      }
    }
  } else {
    CheckConstructorCallTypeArguments(new_pos, constructor, type_arguments);
    if (!type_arguments.IsNull() &&
        !type_arguments.IsInstantiated() &&
        (current_block_->scope->function_level() > 0)) {
      // Make sure that the instantiator is captured.
      CaptureInstantiator();
    }
    // If the type argument vector is not instantiated, we verify in checked
    // mode at runtime that it is within its declared bounds.
    new_object = CreateConstructorCallNode(
        new_pos, type_arguments, constructor, arguments);
  }
  if (!type_bound.IsNull()) {
    new_object = new AssignableNode(new_pos,
                                    new_object,
                                    type_bound,
                                    Symbols::FactoryResult());
  }
  return new_object;
}


String& Parser::Interpolate(const GrowableArray<AstNode*>& values) {
  const Class& cls = Class::Handle(LookupCoreClass(Symbols::StringBase()));
  ASSERT(!cls.IsNull());
  const Function& func =
      Function::Handle(cls.LookupStaticFunction(
          PrivateCoreLibName(Symbols::Interpolate())));
  ASSERT(!func.IsNull());

  // Build the array of literal values to interpolate.
  const Array& value_arr = Array::Handle(Array::New(values.length()));
  for (int i = 0; i < values.length(); i++) {
    ASSERT(values[i]->IsLiteralNode());
    value_arr.SetAt(i, values[i]->AsLiteralNode()->literal());
  }

  // Build argument array to pass to the interpolation function.
  const Array& interpolate_arg = Array::Handle(Array::New(1));
  interpolate_arg.SetAt(0, value_arr);

  // Call interpolation function.
  String& concatenated = String::ZoneHandle();
  concatenated ^= DartEntry::InvokeFunction(func, interpolate_arg);
  if (concatenated.IsUnhandledException()) {
    ErrorMsg("Exception thrown in Parser::Interpolate");
  }
  concatenated = Symbols::New(concatenated);
  return concatenated;
}


// A string literal consists of the concatenation of the next n tokens
// that satisfy the EBNF grammar:
// literal = kSTRING {{ interpol } kSTRING }
// interpol = kINTERPOL_VAR | (kINTERPOL_START expression kINTERPOL_END)
// In other words, the scanner breaks down interpolated strings so that
// a string literal always begins and ends with a kSTRING token.
AstNode* Parser::ParseStringLiteral() {
  TRACE_PARSER("ParseStringLiteral");
  AstNode* primary = NULL;
  const intptr_t literal_start = TokenPos();
  ASSERT(CurrentToken() == Token::kSTRING);
  Token::Kind l1_token = LookaheadToken(1);
  if ((l1_token != Token::kSTRING) &&
      (l1_token != Token::kINTERPOL_VAR) &&
      (l1_token != Token::kINTERPOL_START)) {
    // Common case: no interpolation.
    primary = new LiteralNode(literal_start, *CurrentLiteral());
    ConsumeToken();
    return primary;
  }
  // String interpolation needed.
  bool is_compiletime_const = true;
  GrowableArray<AstNode*> values_list;
  while (CurrentToken() == Token::kSTRING) {
    values_list.Add(new LiteralNode(TokenPos(), *CurrentLiteral()));
    ConsumeToken();
    while ((CurrentToken() == Token::kINTERPOL_VAR) ||
        (CurrentToken() == Token::kINTERPOL_START)) {
      AstNode* expr = NULL;
      const intptr_t expr_pos = TokenPos();
      if (CurrentToken() == Token::kINTERPOL_VAR) {
        expr = ResolveIdent(TokenPos(), *CurrentLiteral(), true);
        ConsumeToken();
      } else {
        ASSERT(CurrentToken() == Token::kINTERPOL_START);
        ConsumeToken();
        expr = ParseExpr(kAllowConst, kConsumeCascades);
        ExpectToken(Token::kINTERPOL_END);
      }
      // Check if this interpolated string is still considered a compile time
      // constant. If it is we need to evaluate if the current string part is
      // a constant or not. Only stings, numbers, booleans and null values
      // are allowed in compile time const interpolations.
      if (is_compiletime_const) {
        const Object* const_expr = expr->EvalConstExpr();
        if ((const_expr != NULL) &&
            (const_expr->IsNumber() ||
            const_expr->IsString() ||
            const_expr->IsBool() ||
            const_expr->IsNull())) {
          // Change expr into a literal.
          expr = new LiteralNode(expr_pos, EvaluateConstExpr(expr));
        } else {
          is_compiletime_const = false;
        }
      }
      values_list.Add(expr);
    }
  }
  if (is_compiletime_const) {
    primary = new LiteralNode(literal_start, Interpolate(values_list));
  } else {
    ArgumentListNode* interpolate_arg = new ArgumentListNode(TokenPos());
    ArrayNode* values = new ArrayNode(
        TokenPos(),
        Type::ZoneHandle(Type::ArrayType()),
        values_list);
    interpolate_arg->Add(values);
    primary = MakeStaticCall(Symbols::StringBase(),
                             PrivateCoreLibName(Symbols::Interpolate()),
                             interpolate_arg);
  }
  return primary;
}


AstNode* Parser::ParsePrimary() {
  TRACE_PARSER("ParsePrimary");
  ASSERT(!is_top_level_);
  AstNode* primary = NULL;
  if (IsFunctionLiteral()) {
    // The name of a literal function is visible from inside the function, but
    // must not collide with names in the scope declaring the literal.
    OpenBlock();
    primary = ParseFunctionStatement(true);
    CloseBlock();
  } else if (IsIdentifier()) {
    QualIdent qual_ident;
    ParseQualIdent(&qual_ident);
    if (qual_ident.lib_prefix == NULL) {
      if (!ResolveIdentInLocalScope(qual_ident.ident_pos,
                                    *qual_ident.ident,
                                    &primary)) {
        // Check whether the identifier is a type parameter.
        if (!current_class().IsNull()) {
          TypeParameter& type_param = TypeParameter::ZoneHandle(
              current_class().LookupTypeParameter(*(qual_ident.ident)));
          if (!type_param.IsNull()) {
            return new PrimaryNode(qual_ident.ident_pos, type_param);
          }
        }
        // This is a non-local unqualified identifier so resolve the
        // identifier locally in the main app library and all libraries
        // imported by it.
        primary = ResolveIdentInCurrentLibraryScope(qual_ident.ident_pos,
                                                    *qual_ident.ident);
      }
    } else {
      // This is a qualified identifier with a library prefix so resolve
      // the identifier locally in that library (we do not include the
      // libraries imported by that library).
      primary = ResolveIdentInPrefixScope(qual_ident.ident_pos,
                                          *qual_ident.lib_prefix,
                                          *qual_ident.ident);
    }
    ASSERT(primary != NULL);
  } else if (CurrentToken() == Token::kTHIS) {
    LocalVariable* local = LookupLocalScope(Symbols::This());
    if (local == NULL) {
      ErrorMsg("receiver 'this' is not in scope");
    }
    primary = new LoadLocalNode(TokenPos(), local);
    ConsumeToken();
  } else if (CurrentToken() == Token::kINTEGER) {
    const Integer& literal = Integer::ZoneHandle(CurrentIntegerLiteral());
    primary = new LiteralNode(TokenPos(), literal);
    ConsumeToken();
  } else if (CurrentToken() == Token::kTRUE) {
    primary = new LiteralNode(TokenPos(), Bool::True());
    ConsumeToken();
  } else if (CurrentToken() == Token::kFALSE) {
    primary = new LiteralNode(TokenPos(), Bool::False());
    ConsumeToken();
  } else if (CurrentToken() == Token::kNULL) {
    primary = new LiteralNode(TokenPos(), Instance::ZoneHandle());
    ConsumeToken();
  } else if (CurrentToken() == Token::kLPAREN) {
    ConsumeToken();
    const bool saved_mode = SetAllowFunctionLiterals(true);
    primary = ParseExpr(kAllowConst, kConsumeCascades);
    SetAllowFunctionLiterals(saved_mode);
    ExpectToken(Token::kRPAREN);
  } else if (CurrentToken() == Token::kDOUBLE) {
    Double& double_value = Double::ZoneHandle(CurrentDoubleLiteral());
    if (double_value.IsNull()) {
      ErrorMsg("invalid double literal");
    }
    primary = new LiteralNode(TokenPos(), double_value);
    ConsumeToken();
  } else if (CurrentToken() == Token::kSTRING) {
    primary = ParseStringLiteral();
  } else if (CurrentToken() == Token::kNEW) {
    ConsumeToken();
    primary = ParseNewOperator(Token::kNEW);
  } else if (CurrentToken() == Token::kCONST) {
    if ((LookaheadToken(1) == Token::kLT) ||
        (LookaheadToken(1) == Token::kLBRACK) ||
        (LookaheadToken(1) == Token::kINDEX) ||
        (LookaheadToken(1) == Token::kLBRACE)) {
      primary = ParseCompoundLiteral();
    } else {
      ConsumeToken();
      primary = ParseNewOperator(Token::kCONST);
    }
  } else if (CurrentToken() == Token::kLT ||
             CurrentToken() == Token::kLBRACK ||
             CurrentToken() == Token::kINDEX ||
             CurrentToken() == Token::kLBRACE) {
    primary = ParseCompoundLiteral();
  } else if (CurrentToken() == Token::kSUPER) {
    if (current_function().is_static()) {
      ErrorMsg("cannot access superclass from static method");
    }
    if (current_class().SuperClass() == Class::null()) {
      ErrorMsg("class '%s' does not have a superclass",
               String::Handle(current_class().Name()).ToCString());
    }
    if (current_class().mixin() != Type::null()) {
      const Type& mixin_type = Type::Handle(current_class().mixin());
      if (mixin_type.type_class() == current_function().origin()) {
        ErrorMsg("class '%s' may not use super "
                 "because it is used as mixin class",
                 String::Handle(current_class().Name()).ToCString());
      }
    }
    ConsumeToken();
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      const String& ident = *ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kLPAREN) {
        primary = ParseSuperCall(ident);
      } else {
        primary = ParseSuperFieldAccess(ident);
      }
    } else if ((CurrentToken() == Token::kLBRACK) ||
        Token::CanBeOverloaded(CurrentToken()) ||
        (CurrentToken() == Token::kNE)) {
      primary = ParseSuperOperator();
    } else {
      primary = new PrimaryNode(TokenPos(), Symbols::Super());
    }
  } else {
    UnexpectedToken();
  }
  return primary;
}


// Evaluate expression in expr and return the value. The expression must
// be a compile time constant.
const Instance& Parser::EvaluateConstExpr(AstNode* expr) {
  if (expr->IsLiteralNode()) {
    return expr->AsLiteralNode()->literal();
  } else if (expr->IsLoadLocalNode() &&
      expr->AsLoadLocalNode()->local().IsConst()) {
    return *expr->AsLoadLocalNode()->local().ConstValue();
  } else {
    ASSERT(expr->EvalConstExpr() != NULL);
    ReturnNode* ret = new ReturnNode(expr->token_pos(), expr);
    // Compile time constant expressions cannot reference anything from a
    // local scope.
    LocalScope* empty_scope = new LocalScope(NULL, 0, 0);
    SequenceNode* seq = new SequenceNode(expr->token_pos(), empty_scope);
    seq->Add(ret);

    Object& result = Object::Handle(Compiler::ExecuteOnce(seq));
    if (result.IsError()) {
      // Propagate the compilation error.
      isolate()->long_jump_base()->Jump(1, Error::Cast(result));
      UNREACHABLE();
    }
    ASSERT(result.IsInstance());
    Instance& value = Instance::ZoneHandle();
    value ^= result.raw();
    value = TryCanonicalize(value, TokenPos());
    return value;
  }
}


void Parser::SkipFunctionLiteral() {
  if (IsIdentifier()) {
    if (LookaheadToken(1) != Token::kLPAREN) {
      SkipType(true);
    }
    ExpectIdentifier("function name expected");
  }
  if (CurrentToken() == Token::kLPAREN) {
    const bool allow_explicit_default_values = true;
    ParamList params;
    params.skipped = true;
    ParseFormalParameterList(allow_explicit_default_values, &params);
  }
  if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
  } else if (CurrentToken() == Token::kARROW) {
    ConsumeToken();
    SkipExpr();
  }
}


// Skips function/method/constructor/getter/setter preambles until the formal
// parameter list. It is enough to skip the tokens, since we have already
// previously parsed the function.
void Parser::SkipFunctionPreamble() {
  while (true) {
    if (CurrentToken() == Token::kLPAREN ||
        CurrentToken() == Token::kARROW ||
        CurrentToken() == Token::kSEMICOLON ||
        CurrentToken() == Token::kLBRACE) {
      return;
    }
    // Case handles "native" keyword, but also return types of form
    // native.SomeType where native is the name of a library.
    if (CurrentToken() == Token::kIDENT &&
        LookaheadToken(1) != Token::kPERIOD) {
      if (CurrentLiteral()->raw() == Symbols::Native().raw()) {
        return;
      }
    }
    ConsumeToken();
  }
}


void Parser::SkipListLiteral() {
  if (CurrentToken() == Token::kINDEX) {
    // Empty list literal.
    ConsumeToken();
    return;
  }
  ExpectToken(Token::kLBRACK);
  while (CurrentToken() != Token::kRBRACK) {
    SkipNestedExpr();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    } else {
      break;
    }
  }
  ExpectToken(Token::kRBRACK);
}


void Parser::SkipMapLiteral() {
  ExpectToken(Token::kLBRACE);
  while (CurrentToken() != Token::kRBRACE) {
    SkipNestedExpr();
    ExpectToken(Token::kCOLON);
    SkipNestedExpr();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    } else {
      break;
    }
  }
  ExpectToken(Token::kRBRACE);
}


void Parser::SkipActualParameters() {
  ExpectToken(Token::kLPAREN);
  while (CurrentToken() != Token::kRPAREN) {
    if (IsIdentifier() && (LookaheadToken(1) == Token::kCOLON)) {
      // Named actual parameter.
      ConsumeToken();
      ConsumeToken();
    }
    SkipNestedExpr();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    }
  }
  ExpectToken(Token::kRPAREN);
}


void Parser::SkipCompoundLiteral() {
  if (CurrentToken() == Token::kLT) {
    SkipTypeArguments();
  }
  if ((CurrentToken() == Token::kLBRACK) ||
      (CurrentToken() == Token::kINDEX)) {
    SkipListLiteral();
  } else if (CurrentToken() == Token::kLBRACE) {
    SkipMapLiteral();
  }
}


void Parser::SkipNewOperator() {
  ConsumeToken();  // Skip new or const keyword.
  if (IsIdentifier()) {
    SkipType(false);
    if (CurrentToken() == Token::kLPAREN) {
      SkipActualParameters();
      return;
    }
  }
}


void Parser::SkipStringLiteral() {
  ASSERT(CurrentToken() == Token::kSTRING);
  while (CurrentToken() == Token::kSTRING) {
    ConsumeToken();
    while (true) {
      if (CurrentToken() == Token::kINTERPOL_VAR) {
        ConsumeToken();
      } else if (CurrentToken() == Token::kINTERPOL_START) {
        ConsumeToken();
        SkipExpr();
        ExpectToken(Token::kINTERPOL_END);
      } else {
        break;
      }
    }
  }
}


void Parser::SkipPrimary() {
  if (IsFunctionLiteral()) {
    SkipFunctionLiteral();
    return;
  }
  switch (CurrentToken()) {
    case Token::kTHIS:
    case Token::kSUPER:
    case Token::kNULL:
    case Token::kTRUE:
    case Token::kFALSE:
    case Token::kINTEGER:
    case Token::kDOUBLE:
      ConsumeToken();
      break;
    case Token::kIDENT:
      ConsumeToken();
      break;
    case Token::kSTRING:
      SkipStringLiteral();
      break;
    case Token::kLPAREN:
      ConsumeToken();
      SkipNestedExpr();
      ExpectToken(Token::kRPAREN);
      break;
    case Token::kNEW:
      SkipNewOperator();
      break;
    case Token::kCONST:
      if ((LookaheadToken(1) == Token::kLT) ||
          (LookaheadToken(1) == Token::kLBRACE) ||
          (LookaheadToken(1) == Token::kLBRACK) ||
          (LookaheadToken(1) == Token::kINDEX)) {
        ConsumeToken();
        SkipCompoundLiteral();
      } else {
        SkipNewOperator();
      }
      break;
    case Token::kLT:
    case Token::kLBRACE:
    case Token::kLBRACK:
    case Token::kINDEX:
      SkipCompoundLiteral();
      break;
    default:
      if (IsIdentifier()) {
        ConsumeToken();  // Handle pseudo-keyword identifiers.
      } else {
        UnexpectedToken();
        UNREACHABLE();
      }
      break;
  }
}


void Parser::SkipSelectors() {
  while (true) {
    if (CurrentToken() == Token::kCASCADE) {
      ConsumeToken();
      if (CurrentToken() == Token::kLBRACK) {
        continue;  // Consume [ in next loop iteration.
      } else {
        ExpectIdentifier("identifier or [ expected after ..");
      }
    } else if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("identifier expected");
    } else if (CurrentToken() == Token::kLBRACK) {
      ConsumeToken();
      SkipNestedExpr();
      ExpectToken(Token::kRBRACK);
    } else if (CurrentToken() == Token::kLPAREN) {
      SkipActualParameters();
    } else {
      break;
    }
  }
}

void Parser::SkipPostfixExpr() {
  SkipPrimary();
  SkipSelectors();
  if (IsIncrementOperator(CurrentToken())) {
    ConsumeToken();
  }
}


void Parser::SkipUnaryExpr() {
  if (IsPrefixOperator(CurrentToken()) ||
      IsIncrementOperator(CurrentToken())) {
    ConsumeToken();
    SkipUnaryExpr();
  } else {
    SkipPostfixExpr();
  }
}


void Parser::SkipBinaryExpr() {
  SkipUnaryExpr();
  const int min_prec = Token::Precedence(Token::kOR);
  const int max_prec = Token::Precedence(Token::kMUL);
  while (((min_prec <= Token::Precedence(CurrentToken())) &&
      (Token::Precedence(CurrentToken()) <= max_prec)) ||
      IsLiteral("as")) {
    Token::Kind last_token = IsLiteral("as") ? Token::kAS : CurrentToken();
    ConsumeToken();
    if (last_token == Token::kIS) {
      if (CurrentToken() == Token::kNOT) {
        ConsumeToken();
      }
      SkipType(false);
    } else if (last_token == Token::kAS) {
      SkipType(false);
    } else {
      SkipUnaryExpr();
    }
  }
}


void Parser::SkipConditionalExpr() {
  SkipBinaryExpr();
  if (CurrentToken() == Token::kCONDITIONAL) {
    ConsumeToken();
    SkipExpr();
    ExpectToken(Token::kCOLON);
    SkipExpr();
  }
}


void Parser::SkipExpr() {
  while (CurrentToken() == Token::kTHROW) {
    ConsumeToken();
  }
  SkipConditionalExpr();
  if (CurrentToken() == Token::kCASCADE) {
    SkipSelectors();
  }
  if (Token::IsAssignmentOperator(CurrentToken())) {
    ConsumeToken();
    SkipExpr();
  }
}


void Parser::SkipNestedExpr() {
  const bool saved_mode = SetAllowFunctionLiterals(true);
  SkipExpr();
  SetAllowFunctionLiterals(saved_mode);
}


void Parser::SkipQualIdent() {
  ASSERT(IsIdentifier());
  ConsumeToken();
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();  // Consume the kPERIOD token.
    ExpectIdentifier("identifier expected after '.'");
  }
}

}  // namespace dart
