// 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 "platform/utils.h"
#include "vm/ast_transformer.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/handles.h"
#include "vm/hash_table.h"
#include "vm/heap.h"
#include "vm/isolate.h"
#include "vm/longjump.h"
#include "vm/native_arguments.h"
#include "vm/native_entry.h"
#include "vm/object.h"
#include "vm/object_store.h"
#include "vm/os.h"
#include "vm/regexp_assembler.h"
#include "vm/report.h"
#include "vm/resolver.h"
#include "vm/scanner.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/timer.h"
#include "vm/zone.h"

namespace dart {

DEFINE_FLAG(bool, enable_debug_break, false, "Allow use of break \"message\".");
DEFINE_FLAG(bool, enable_mirrors, true,
    "Disable to make importing dart:mirrors an error.");
DEFINE_FLAG(bool, load_deferred_eagerly, false,
    "Load deferred libraries eagerly.");
DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool, supermixin, false, "Allow super calls in mixins.");
DEFINE_FLAG(bool, warn_mixin_typedef, true, "Warning on legacy mixin typedef.");
DEFINE_FLAG(bool, link_natives_lazily, false, "Link native calls lazily");

DECLARE_FLAG(bool, lazy_dispatchers);
DECLARE_FLAG(bool, load_deferred_eagerly);
DECLARE_FLAG(bool, profile_vm);
DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
DECLARE_FLAG(bool, warn_on_javascript_compatibility);

// Quick access to the current thread, isolate and zone.
#define T (thread())
#define I (isolate())
#define Z (zone())


#if defined(DEBUG)
class TraceParser : public ValueObject {
 public:
  TraceParser(intptr_t token_pos,
              const Script& script,
              intptr_t* trace_indent,
              const char* msg) {
    indent_ = trace_indent;
    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() {
    if (FLAG_trace_parser) {
      (*indent_)--;
      ASSERT(*indent_ >= 0);
    }
  }

 private:
  void PrintIndent() {
    for (intptr_t i = 0; i < *indent_; i++) { OS::Print(". "); }
  }
  intptr_t* indent_;
};


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

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


class BoolScope : public ValueObject {
 public:
  BoolScope(bool* addr, bool new_value) : _addr(addr), _saved_value(*addr) {
    *_addr = new_value;
  }
  ~BoolScope() {
    *_addr = _saved_value;
  }

 private:
  bool* _addr;
  bool _saved_value;
};


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


LocalVariable* ParsedFunction::EnsureExpressionTemp() {
  if (!has_expression_temp_var()) {
    LocalVariable* temp =
        new (Z) 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::EnsureFinallyReturnTemp(bool is_async) {
  if (!has_finally_return_temp_var()) {
    LocalVariable* temp = new(Z) LocalVariable(
        function_.token_pos(),
        String::ZoneHandle(Z, Symbols::New(":finally_ret_val")),
        Type::ZoneHandle(Z, Type::DynamicType()));
    ASSERT(temp != NULL);
    temp->set_is_final();
    if (is_async) {
      temp->set_is_captured();
    }
    set_finally_return_temp_var(temp);
  }
  ASSERT(has_finally_return_temp_var());
}


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


void ParsedFunction::SetRegExpCompileData(
    RegExpCompileData* regexp_compile_data) {
  ASSERT(regexp_compile_data_ == NULL);
  ASSERT(regexp_compile_data != NULL);
  regexp_compile_data_ = regexp_compile_data;
}


void ParsedFunction::AddDeferredPrefix(const LibraryPrefix& prefix) {
  // 'deferred_prefixes_' are used to invalidate code, but no invalidation is
  // needed if --load_deferred_eagerly.
  ASSERT(!FLAG_load_deferred_eagerly);
  ASSERT(prefix.is_deferred_load());
  ASSERT(!prefix.is_loaded());
  for (intptr_t i = 0; i < deferred_prefixes_->length(); i++) {
    if ((*deferred_prefixes_)[i]->raw() == prefix.raw()) {
      return;
    }
  }
  deferred_prefixes_->Add(&LibraryPrefix::ZoneHandle(Z, prefix.raw()));
}


void ParsedFunction::AllocateVariables() {
  ASSERT(!function().IsIrregexpFunction());
  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).
  bool found_captured_variables = false;
  int next_free_frame_index =
      scope->AllocateVariables(first_parameter_index_,
                               num_params,
                               first_stack_local_index_,
                               NULL,
                               &found_captured_variables);

  // 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 CatchParamDesc {
  CatchParamDesc()
      : token_pos(0), type(NULL), name(NULL), var(NULL) { }
  intptr_t token_pos;
  const AbstractType* type;
  const String* name;
  LocalVariable* var;
};


void ParsedFunction::AllocateIrregexpVariables(intptr_t num_stack_locals) {
  ASSERT(function().IsIrregexpFunction());
  ASSERT(function().NumOptionalParameters() == 0);
  const intptr_t num_params = function().num_fixed_parameters();
  ASSERT(num_params == RegExpMacroAssembler::kParamCount);
  // Compute start indices to parameters and locals, and the number of
  // parameters to copy.
  // 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;

  // Frame indices are relative to the frame pointer and are decreasing.
  num_stack_locals_ = num_stack_locals;
}


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::TryStack : public ZoneAllocated {
 public:
  TryStack(Block* try_block, TryStack* outer_try, intptr_t try_index)
      : try_block_(try_block),
        inlined_finally_nodes_(),
        outer_try_(outer_try),
        try_index_(try_index),
        inside_catch_(false),
        inside_finally_(false) { }

  TryStack* outer_try() const { return outer_try_; }
  Block* try_block() const { return try_block_; }
  intptr_t try_index() const { return try_index_; }
  bool inside_catch() const { return inside_catch_; }
  void enter_catch() { inside_catch_ = true; }
  bool inside_finally() const { return inside_finally_; }
  void enter_finally() { inside_finally_ = true; }
  void exit_finally() { inside_finally_ = false; }

  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_;
  TryStack* outer_try_;
  const intptr_t try_index_;
  bool inside_catch_;  // True when parsing a catch clause of this try.
  bool inside_finally_;  // True when parsing a finally clause of an inner try
                         // of this try.

  DISALLOW_COPY_AND_ASSIGN(TryStack);
};


void Parser::TryStack::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_(Thread::Current()->isolate()),
      thread_(Thread::Current()),
      script_(Script::Handle(zone(), script.raw())),
      tokens_iterator_(TokenStream::Handle(zone(), script.tokens()),
                       token_pos),
      token_kind_(Token::kILLEGAL),
      current_block_(NULL),
      is_top_level_(false),
      await_is_keyword_(false),
      current_member_(NULL),
      allow_function_literals_(true),
      parsed_function_(NULL),
      innermost_function_(Function::Handle(zone())),
      literal_token_(LiteralToken::Handle(zone())),
      current_class_(Class::Handle(zone())),
      library_(Library::Handle(zone(), library.raw())),
      try_stack_(NULL),
      last_used_try_index_(0),
      unregister_pending_function_(false),
      async_temp_scope_(NULL),
      trace_indent_(0) {
  ASSERT(tokens_iterator_.IsValid());
  ASSERT(!library.IsNull());
}


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


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


// Each try in this function gets its own try index.
// See definition of RawPcDescriptors::PcDescriptor.
int16_t Parser::AllocateTryIndex() {
  if (!Utils::IsInt(16, last_used_try_index_ - 1)) {
    ReportError("too many nested try statements");
  }
  return last_used_try_index_++;
}


void Parser::SetScript(const Script& script, intptr_t token_pos) {
  script_ = script.raw();
  tokens_iterator_.SetStream(
      TokenStream::Handle(Z, 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) {
  tokens_iterator_.SetCurrentPosition(position);
  token_kind_ = Token::kILLEGAL;
}


void Parser::ParseCompilationUnit(const Library& library,
                                  const Script& script) {
  Thread* thread = Thread::Current();
  ASSERT(thread->long_jump_base()->IsSafeToJump());
  CSTAT_TIMER_SCOPE(thread, parser_timer);
  VMTagScope tagScope(thread, VMTag::kCompileTopLevelTagId);
  Parser parser(script, library, 0);
  parser.ParseTopLevel();
}


void Parser::ComputeCurrentToken() {
  ASSERT(token_kind_ == Token::kILLEGAL);
  token_kind_ = tokens_iterator_.CurrentTokenKind();
  if (token_kind_ == Token::kERROR) {
    ReportError(TokenPos(), "%s", CurrentLiteral()->ToCString());
  }
}


Token::Kind Parser::LookaheadToken(int num_tokens) {
  INC_STAT(I, num_tokens_lookahead, 1);
  INC_STAT(I, num_token_checks, 1);
  return tokens_iterator_.LookaheadTokenKind(num_tokens);
}


String* Parser::CurrentLiteral() const {
  String& result =
      String::ZoneHandle(Z, 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(Z, ri);
    if (i.CheckJavascriptIntegerOverflow()) {
      ReportError(TokenPos(),
                  "Integer literal does not fit in a Javascript integer: %s.",
                  i.ToCString());
    }
  }
  return ri;
}


struct ParamDesc {
  ParamDesc()
      : type(NULL),
        name_pos(0),
        name(NULL),
        default_value(NULL),
        metadata(NULL),
        var(NULL),
        is_final(false),
        is_field_initializer(false),
        has_explicit_type(false) { }
  const AbstractType* type;
  intptr_t name_pos;
  const String* name;
  const Instance* default_value;  // NULL if not an optional parameter.
  const Object* metadata;  // NULL if no metadata or metadata not evaluated.
  LocalVariable* var;  // Scope variable allocated for this parameter.
  bool is_final;
  bool is_field_initializer;
  bool has_explicit_type;
};


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_explicit_default_values = 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 EraseParameterTypes() {
    const Type& dynamic_type = Type::ZoneHandle(Type::DynamicType());
    const int num_parameters = parameters->length();
    for (int i = 0; i < num_parameters; i++) {
      (*parameters)[i].type = &dynamic_type;
    }
  }

  // Make the parameter variables visible/invisible.
  // Field initializer parameters are always invisible.
  void SetInvisible(bool invisible) {
    const intptr_t num_params = parameters->length();
    for (int i = 0; i < num_params; i++) {
      ParamDesc& param = (*parameters)[i];
      ASSERT(param.var != NULL);
      if (!param.is_field_initializer) {
        param.var->set_invisible(invisible);
      }
    }
  }

  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_explicit_default_values;
  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;
    has_native = false;
    metadata_pos = -1;
    operator_token = Token::kILLEGAL;
    type = NULL;
    name_pos = 0;
    name = NULL;
    redirect_name = NULL;
    dict_name = NULL;
    params.Clear();
    kind = RawFunction::kRegularFunction;
    field_ = NULL;
  }
  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;
  }
  const char* ToCString() const {
    if (field_ != NULL) {
      return "field";
    } else if (IsConstructor()) {
      return "constructor";
    } else if (IsFactory()) {
      return "factory";
    } else if (IsGetter()) {
      return "getter";
    } else if (IsSetter()) {
      return "setter";
    }
    return "method";
  }
  String* DictName() const {
    return (dict_name  != NULL) ? dict_name : name;
  }
  bool has_abstract;
  bool has_external;
  bool has_final;
  bool has_const;
  bool has_static;
  bool has_var;
  bool has_factory;
  bool has_operator;
  bool has_native;
  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;
  // dict_name is the name used for the class namespace, if it
  // differs from 'name'.
  // For constructors: NULL for unnamed constructor,
  // identifier after classname for named constructors.
  // For getters and setters: unmangled name.
  String* dict_name;
  ParamList params;
  RawFunction::Kind kind;
  // NULL for functions, field object for static or instance fields.
  Field* field_;
};


class ClassDesc : public ValueObject {
 public:
  ClassDesc(Zone* zone,
            const Class& cls,
            const String& cls_name,
            bool is_interface,
            intptr_t token_pos)
      : zone_(zone),
        clazz_(cls),
        class_name_(cls_name),
        token_pos_(token_pos),
        functions_(zone, 4),
        fields_(zone, 4) {
  }

  void AddFunction(const Function& function) {
    functions_.Add(&Function::ZoneHandle(zone_, function.raw()));
  }

  const GrowableArray<const Function*>& functions() const {
    return functions_;
  }

  void AddField(const Field& field) {
    fields_.Add(&Field::ZoneHandle(zone_, field.raw()));
  }

  const GrowableArray<const Field*>& fields() const {
    return fields_;
  }

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

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

  bool has_constructor() const {
    for (int i = 0; i < functions_.length(); i++) {
      const Function* 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;
  }

  RawArray* MakeFunctionsArray() {
    const intptr_t len = functions_.length();
    const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
    for (intptr_t i = 0; i < len; i++) {
      res.SetAt(i, *functions_[i]);
    }
    return res.raw();
  }

 private:
  Zone* zone_;
  const Class& clazz_;
  const String& class_name_;
  intptr_t token_pos_;   // Token index of "class" keyword.
  GrowableArray<const Function*> functions_;
  GrowableArray<const Field*> fields_;
  GrowableArray<MemberDesc> members_;
};


class TopLevel : public ValueObject {
 public:
  explicit TopLevel(Zone* zone) :
      zone_(zone),
      fields_(zone, 4),
      functions_(zone, 4) { }

  void AddField(const Field& field) {
    fields_.Add(&Field::ZoneHandle(zone_, field.raw()));
  }

  void AddFunction(const Function& function) {
    functions_.Add(&Function::ZoneHandle(zone_, function.raw()));
  }

  const GrowableArray<const Field*>& fields() const {
    return fields_;
  }

  const GrowableArray<const Function*>& functions() const {
    return functions_;
  }

 private:
  Zone* zone_;
  GrowableArray<const Field*> fields_;
  GrowableArray<const Function*> functions_;
};


void Parser::ParseClass(const Class& cls) {
  if (!cls.is_synthesized_class()) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();
    CSTAT_TIMER_SCOPE(thread, parser_timer);
    ASSERT(thread->long_jump_base()->IsSafeToJump());
    const Script& script = Script::Handle(zone, cls.script());
    const Library& lib = Library::Handle(zone, cls.library());
    Parser parser(script, lib, cls.token_pos());
    parser.ParseClassDefinition(cls);
  } else if (cls.is_enum_class()) {
    Thread* thread = Thread::Current();
    Zone* zone = thread->zone();
    CSTAT_TIMER_SCOPE(thread, parser_timer);
    ASSERT(thread->long_jump_base()->IsSafeToJump());
    const Script& script = Script::Handle(zone, cls.script());
    const Library& lib = Library::Handle(zone, cls.library());
    Parser parser(script, lib, cls.token_pos());
    parser.ParseEnumDefinition(cls);
  }
}


RawObject* Parser::ParseFunctionParameters(const Function& func) {
  ASSERT(!func.IsNull());
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  StackZone stack_zone(thread);
  Zone* zone = stack_zone.GetZone();
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    const Script& script = Script::Handle(zone, func.script());
    const Class& owner = Class::Handle(zone, func.Owner());
    ASSERT(!owner.IsNull());
    ParsedFunction* parsed_function = new ParsedFunction(
        thread, Function::ZoneHandle(zone, func.raw()));
    Parser parser(script, parsed_function, func.token_pos());
    parser.SkipFunctionPreamble();
    ParamList params;
    parser.ParseFormalParameterList(true, true, &params);
    ParamDesc* param = params.parameters->data();
    const int param_cnt = params.num_fixed_parameters +
                          params.num_optional_parameters;
    const Array& param_descriptor =
        Array::Handle(Array::New(param_cnt * kParameterEntrySize));
    for (int i = 0, j = 0; i < param_cnt; i++, j += kParameterEntrySize) {
      param_descriptor.SetAt(j + kParameterIsFinalOffset,
                             param[i].is_final ? Bool::True() : Bool::False());
      param_descriptor.SetAt(j + kParameterDefaultValueOffset,
          (param[i].default_value == NULL) ? Object::null_instance() :
                                             *(param[i].default_value));
      const Object* metadata = param[i].metadata;
      if ((metadata != NULL) && (*metadata).IsError()) {
        return metadata->raw();  // Error evaluating the metadata.
      }
      param_descriptor.SetAt(j + kParameterMetadataOffset,
          (param[i].metadata == NULL) ? Object::null_instance() :
                                        *(param[i].metadata));
    }
    return param_descriptor.raw();
  } else {
    Error& error = Error::Handle();
    error = isolate->object_store()->sticky_error();
    isolate->object_store()->clear_sticky_error();
    return error.raw();
  }
  UNREACHABLE();
  return Object::null();
}


bool Parser::ParseFormalParameters(const Function& func, ParamList* params) {
  ASSERT(!func.IsNull());
  // This is currently only used for constructors. To handle all kinds
  // of functions, special cases for getters and possibly other kinds
  // need to be added.
  ASSERT(func.kind() == RawFunction::kConstructor);
  ASSERT(!func.IsRedirectingFactory());
  // Implicit constructors have no source, no user-defined formal parameters.
  if (func.IsImplicitConstructor()) {
    return true;
  }
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    const Script& script = Script::Handle(func.script());
    const Class& owner = Class::Handle(func.Owner());
    ASSERT(!owner.IsNull());
    ParsedFunction* parsed_function =
        new ParsedFunction(Thread::Current(), Function::ZoneHandle(func.raw()));
    Parser parser(script, parsed_function, func.token_pos());
    parser.SkipFunctionPreamble();
    parser.ParseFormalParameterList(true, true, params);
    return true;
  } else {
    Thread::Current()->isolate()->object_store()->clear_sticky_error();
    params->Clear();
    return false;
  }
  UNREACHABLE();
  return false;
}


void Parser::ParseFunction(ParsedFunction* parsed_function) {
  Thread* thread = parsed_function->thread();
  ASSERT(thread == Thread::Current());
  Isolate* isolate = thread->isolate();
  Zone* zone = thread->zone();
  CSTAT_TIMER_SCOPE(thread, parser_timer);
  INC_STAT(isolate, num_functions_compiled, 1);
  VMTagScope tagScope(thread, VMTag::kCompileParseFunctionTagId,
                      FLAG_profile_vm);

  ASSERT(thread->long_jump_base()->IsSafeToJump());
  ASSERT(parsed_function != NULL);
  const Function& func = parsed_function->function();
  const Script& script = Script::Handle(zone, func.script());
  Parser parser(script, parsed_function, func.token_pos());
  SequenceNode* node_sequence = NULL;
  switch (func.kind()) {
    case RawFunction::kClosureFunction:
      if (func.IsImplicitClosureFunction()) {
        node_sequence =
            parser.ParseImplicitClosure(func);
        break;
      }
      if (func.IsConstructorClosureFunction()) {
        node_sequence =
            parser.ParseConstructorClosure(func);
        break;
      }
      // Fall-through: Handle non-implicit closures.
    case RawFunction::kRegularFunction:
    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);
      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);
      INC_STAT(isolate, num_implicit_final_getters, 1);
      break;
    case RawFunction::kMethodExtractor:
      node_sequence = parser.ParseMethodExtractor(func);
      break;
    case RawFunction::kNoSuchMethodDispatcher:
      node_sequence =
          parser.ParseNoSuchMethodDispatcher(func);
      break;
    case RawFunction::kInvokeFieldDispatcher:
      node_sequence =
          parser.ParseInvokeFieldDispatcher(func);
      break;
    case RawFunction::kIrregexpFunction:
      UNREACHABLE();  // Irregexp functions have their own parser.
    default:
      UNREACHABLE();
  }

  if (parsed_function->has_expression_temp_var()) {
    node_sequence->scope()->AddVariable(parsed_function->expression_temp_var());
  }
  node_sequence->scope()->AddVariable(
      parsed_function->current_context_var());
  if (parsed_function->has_finally_return_temp_var()) {
    node_sequence->scope()->AddVariable(
        parsed_function->finally_return_temp_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(instantiator);
    }
  }
}


RawObject* Parser::ParseMetadata(const Class& cls, intptr_t token_pos) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  StackZone stack_zone(thread);
  Zone* zone = stack_zone.GetZone();
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    const Script& script = Script::Handle(zone, cls.script());
    // Parsing metadata can involve following paths in the parser that are
    // normally used for expressions and assume current_function is non-null,
    // so we create a fake function to use as the current_function rather than
    // scattering special cases throughout the parser.
    const Function& fake_function = Function::ZoneHandle(zone, Function::New(
        Symbols::At(),
        RawFunction::kRegularFunction,
        true,  // is_static
        false,  // is_const
        false,  // is_abstract
        false,  // is_external
        false,  // is_native
        cls,
        token_pos));
    fake_function.set_is_debuggable(false);
    ParsedFunction* parsed_function =
        new ParsedFunction(thread, fake_function);
    Parser parser(script, parsed_function, token_pos);
    parser.set_current_class(cls);

    RawObject* metadata = parser.EvaluateMetadata();
    return metadata;
  } else {
    Error& error = Error::Handle(zone);
    error = isolate->object_store()->sticky_error();
    isolate->object_store()->clear_sticky_error();
    return error.raw();
  }
  UNREACHABLE();
  return Object::null();
}


RawArray* Parser::EvaluateMetadata() {
  CheckToken(Token::kAT, "Metadata character '@' expected");
  GrowableObjectArray& meta_values =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
  while (CurrentToken() == Token::kAT) {
    ConsumeToken();
    intptr_t expr_pos = TokenPos();
    if (!IsIdentifier()) {
      ExpectIdentifier("identifier expected");
    }
    // Reject expressions with deferred library prefix eagerly.
    Object& obj =
        Object::Handle(Z, library_.LookupLocalObject(*CurrentLiteral()));
    if (!obj.IsNull() && obj.IsLibraryPrefix()) {
      if (LibraryPrefix::Cast(obj).is_deferred_load()) {
        ReportError("Metadata must be compile-time constant");
      }
    }
    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 {
      // Can be x, C.x, or L.C.x.
      expr = ParsePrimary();  // Consumes x, C or L.C.
      Class& cls = Class::Handle(Z);
      if (expr->IsPrimaryNode()) {
        PrimaryNode* primary_node = expr->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();
        } else {
          ReportError(expr_pos,
                      "Metadata expressions must refer to a const field "
                      "or constructor");
        }
      }
      if (CurrentToken() == Token::kPERIOD) {
        // C.x or L.C.X.
        if (cls.IsNull()) {
          ReportError(expr_pos,
                      "Metadata expressions must refer to a const field "
                      "or constructor");
        }
        ConsumeToken();
        const intptr_t ident_pos = TokenPos();
        String* ident = ExpectIdentifier("identifier expected");
        const Field& field = Field::Handle(Z, cls.LookupStaticField(*ident));
        if (field.IsNull()) {
          ReportError(ident_pos,
                      "Class '%s' has no field '%s'",
                      cls.ToCString(),
                      ident->ToCString());
        }
        if (!field.is_const()) {
          ReportError(ident_pos,
                      "Field '%s' of class '%s' is not const",
                      ident->ToCString(),
                      cls.ToCString());
        }
        expr = GenerateStaticFieldLookup(field, ident_pos);
      }
    }
    if (expr->EvalConstExpr() == NULL) {
      ReportError(expr_pos, "expression must be a compile-time constant");
    }
    const Instance& val = EvaluateConstExpr(expr_pos, expr);
    meta_values.Add(val);
  }
  return Array::MakeArray(meta_values);
}


SequenceNode* Parser::ParseStaticInitializer() {
  ExpectIdentifier("field name expected");
  CheckToken(Token::kASSIGN, "field initialier expected");
  ConsumeToken();
  OpenFunctionBlock(parsed_function()->function());
  intptr_t expr_pos = TokenPos();
  AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
  ReturnNode* ret = new(Z) ReturnNode(expr_pos, expr);
  current_block_->statements->Add(ret);
  return CloseBlock();
}


ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) {
  ASSERT(field.is_static());
  Thread* thread = Thread::Current();
  // TODO(koda): Should there be a StackZone here?
  Zone* zone = thread->zone();

  const Class& script_cls = Class::Handle(zone, field.origin());
  const Script& script = Script::Handle(zone, script_cls.script());

  const String& field_name = String::Handle(zone, field.name());
  String& init_name = String::Handle(zone,
      Symbols::FromConcat(Symbols::InitPrefix(), field_name));

  const Function& initializer = Function::ZoneHandle(zone,
      Function::New(init_name,
                    RawFunction::kRegularFunction,
                    true,   // static
                    false,  // !const
                    false,  // !abstract
                    false,  // !external
                    false,  // !native
                    Class::Handle(field.owner()),
                    field.token_pos()));
  initializer.set_result_type(AbstractType::Handle(zone, field.type()));
  // Static initializer functions are hidden from the user.
  // Since they are only executed once, we avoid optimizing
  // and inlining them. After the field is initialized, the
  // compiler can eliminate the call to the static initializer.
  initializer.set_is_reflectable(false);
  initializer.set_is_debuggable(false);
  initializer.SetIsOptimizable(false);
  initializer.set_is_inlinable(false);

  ParsedFunction* parsed_function = new ParsedFunction(thread, initializer);
  Parser parser(script, parsed_function, field.token_pos());

  SequenceNode* body = parser.ParseStaticInitializer();
  parsed_function->SetNodeSequence(body);

  if (parsed_function->has_expression_temp_var()) {
    body->scope()->AddVariable(parsed_function->expression_temp_var());
  }
  body->scope()->AddVariable(parsed_function->current_context_var());
  if (parsed_function->has_finally_return_temp_var()) {
    body->scope()->AddVariable(parsed_function->finally_return_temp_var());
  }
  // The instantiator is not required in a static expression.
  ASSERT(!parser.IsInstantiatorRequired());

  return parsed_function;
}


RawObject* Parser::ParseFunctionFromSource(const Class& owning_class,
                                           const String& source) {
  Thread* thread = Thread::Current();
  Isolate* isolate = thread->isolate();
  StackZone stack_zone(thread);
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    const String& uri = String::Handle(Symbols::New("dynamically-added"));
    const Script& script = Script::Handle(
        Script::New(uri, source, RawScript::kSourceTag));
    const Library& owning_library = Library::Handle(owning_class.library());
    const String& private_key = String::Handle(owning_library.private_key());
    script.Tokenize(private_key);
    const intptr_t token_pos = 0;
    Parser parser(script, owning_library, token_pos);
    parser.is_top_level_ = true;
    parser.set_current_class(owning_class);
    const String& class_name = String::Handle(owning_class.Name());
    ClassDesc members(stack_zone.GetZone(),
                      owning_class,
                      class_name,
                      false,  /* is_interface */
                      token_pos);
    const intptr_t metadata_pos = parser.SkipMetadata();
    parser.ParseClassMemberDefinition(&members, metadata_pos);
    ASSERT(members.functions().length() == 1);
    const Function& func = *members.functions().At(0);
    func.set_eval_script(script);
    ParsedFunction* parsed_function = new ParsedFunction(thread, func);
    Parser::ParseFunction(parsed_function);
    return func.raw();
  } else {
    const Error& error = Error::Handle(isolate->object_store()->sticky_error());
    isolate->object_store()->clear_sticky_error();
    return error.raw();
  }
  UNREACHABLE();
  return Object::null();
}


SequenceNode* Parser::ParseStaticFinalGetter(const Function& func) {
  TRACE_PARSER("ParseStaticFinalGetter");
  ParamList params;
  ASSERT(func.num_fixed_parameters() == 0);  // static.
  ASSERT(!func.HasOptionalParameters());
  ASSERT(AbstractType::Handle(Z, 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(Z, func.Owner());
  const Field& field =
      Field::ZoneHandle(Z, field_class.LookupStaticField(field_name));

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

  const intptr_t expr_pos = TokenPos();
  if (field.is_const()) {
    // 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.
    AstNode* expr = ParseExpr(kAllowConst, kConsumeCascades);
    // This getter will only be called once at compile time.
    if (expr->EvalConstExpr() == NULL) {
      ReportError(expr_pos, "initializer is not a valid 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.
    // Call runtime support to parse and evaluate the initializer expression.
    // The runtime function will detect circular dependencies in expressions
    // and handle errors while evaluating the expression.
    current_block_->statements->Add(
        new (Z) InitStaticFieldNode(ident_pos, field));
    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.
  const 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(Z, 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);
  String& field_name = String::Handle(Z, func.name());
  field_name = Field::NameFromGetter(field_name);

  const Class& field_class = Class::Handle(Z, func.Owner());
  const Field& field =
      Field::ZoneHandle(Z, field_class.LookupInstanceField(field_name));
  ASSERT(!field.IsNull());

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

  ReturnNode* return_node = new ReturnNode(Scanner::kNoSourcePos, 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.
  const intptr_t ident_pos = func.token_pos();
  const String& field_name = *CurrentLiteral();
  const Class& field_class = Class::ZoneHandle(Z, func.Owner());
  const Field& field =
      Field::ZoneHandle(Z, field_class.LookupInstanceField(field_name));
  const AbstractType& field_type = AbstractType::ZoneHandle(Z, 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(Z, 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(Scanner::kNoSourcePos));
  return CloseBlock();
}


SequenceNode* Parser::ParseConstructorClosure(const Function& func) {
  TRACE_PARSER("ParseConstructorClosure");
  const intptr_t token_pos = func.token_pos();

  Function& constructor = Function::ZoneHandle(Z);
  TypeArguments& type_args = TypeArguments::ZoneHandle(Z);
  ParseConstructorClosurization(&constructor, &type_args);
  ASSERT(!constructor.IsNull());

  ParamList params;
  // The first parameter of the closure function is the implicit closure
  // argument.
  params.AddFinalParameter(token_pos,
                           &Symbols::ClosureParameter(),
                           &Type::ZoneHandle(Z, Type::DynamicType()));
  bool params_ok = ParseFormalParameters(constructor, &params);
  USE(params_ok);
  ASSERT(params_ok);
  // Per language spec, the type of the closure parameters is dynamic.
  // Replace the types parsed from the constructor.
  params.EraseParameterTypes();

  SetupDefaultsForOptionalParams(params);
  ASSERT(func.num_fixed_parameters() == params.num_fixed_parameters);
  ASSERT(func.NumOptionalParameters() == params.num_optional_parameters);

  OpenFunctionBlock(func);
  LocalScope* scope = current_block_->scope;
  AddFormalParamsToScope(&params, scope);

  ArgumentListNode* ctor_args = new ArgumentListNode(token_pos);
  // Skip implicit closure parameter at 0.
  for (intptr_t i = 1; i < func.NumParameters(); i++) {
    ctor_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i)));
  }

  if (func.HasOptionalNamedParameters()) {
    const Array& arg_names =
        Array::ZoneHandle(Array::New(func.NumOptionalParameters()));
    for (intptr_t i = 0; i < arg_names.Length(); i++) {
      intptr_t index = func.num_fixed_parameters() + i;
      arg_names.SetAt(i, String::Handle(func.ParameterNameAt(index)));
    }
    ctor_args->set_names(arg_names);
  }

  AstNode* new_object =
      CreateConstructorCallNode(token_pos, type_args, constructor, ctor_args);
  ReturnNode* return_node = new ReturnNode(token_pos, new_object);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


SequenceNode* Parser::ParseImplicitClosure(const Function& func) {
  TRACE_PARSER("ParseImplicitClosure");
  intptr_t token_pos = func.token_pos();

  OpenFunctionBlock(func);

  ParamList params;
  params.AddFinalParameter(
      token_pos,
      &Symbols::ClosureParameter(),
      &Type::ZoneHandle(Type::DynamicType()));

  const Function& parent = Function::ZoneHandle(func.parent_function());
  if (parent.IsImplicitSetterFunction()) {
    const intptr_t ident_pos = func.token_pos();
    ASSERT(IsIdentifier());
    const String& field_name = *CurrentLiteral();
    const Class& field_class = Class::ZoneHandle(Z, parent.Owner());
    const Field& field =
        Field::ZoneHandle(Z, field_class.LookupInstanceField(field_name));
    const AbstractType& field_type = AbstractType::ZoneHandle(Z, field.type());
    params.AddFinalParameter(ident_pos,
                             &Symbols::Value(),
                             &field_type);
    ASSERT(func.num_fixed_parameters() == 2);  // closure, value.
  } else if (!parent.IsGetterFunction() && !parent.IsImplicitGetterFunction()) {
    const bool allow_explicit_default_values = true;
    SkipFunctionPreamble();
    ParseFormalParameterList(allow_explicit_default_values, false, &params);
    SetupDefaultsForOptionalParams(params);
  }

  // Populate function scope with the formal parameters.
  LocalScope* scope = current_block_->scope;
  AddFormalParamsToScope(&params, scope);

  ArgumentListNode* func_args = new ArgumentListNode(token_pos);
  if (!func.is_static()) {
    func_args->Add(LoadReceiver(token_pos));
  }
  // Skip implicit parameter at 0.
  for (intptr_t i = 1; i < func.NumParameters(); ++i) {
    func_args->Add(new LoadLocalNode(token_pos, scope->VariableAt(i)));
  }

  if (func.HasOptionalNamedParameters()) {
    const Array& arg_names =
        Array::ZoneHandle(Array::New(func.NumOptionalParameters()));
    for (intptr_t i = 0; i < arg_names.Length(); ++i) {
      intptr_t index = func.num_fixed_parameters() + i;
      arg_names.SetAt(i, String::Handle(func.ParameterNameAt(index)));
    }
    func_args->set_names(arg_names);
  }
  StaticCallNode* call = new StaticCallNode(token_pos, parent, func_args);
  ReturnNode* return_node = new ReturnNode(token_pos, call);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


SequenceNode* Parser::ParseMethodExtractor(const Function& func) {
  TRACE_PARSER("ParseMethodExtractor");
  ASSERT(FLAG_lazy_dispatchers);

  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(Z, func.extracted_method_closure()),
      load_receiver,
      NULL);

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


void Parser::BuildDispatcherScope(const Function& func,
                                  const ArgumentsDescriptor& desc) {
  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(Z, Symbols::New(name));
    p.type = &Type::ZoneHandle(Z, 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(Z, desc.NameAt(index));
    p.type = &Type::ZoneHandle(Z, Type::DynamicType());
    p.default_value = &Object::null_instance();
    params.parameters->Add(p);
    params.num_optional_parameters++;
    params.has_optional_named_parameters = true;
  }
  ASSERT(desc.NamedCount() == params.num_optional_parameters);

  SetupDefaultsForOptionalParams(params);

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


SequenceNode* Parser::ParseNoSuchMethodDispatcher(const Function& func) {
  TRACE_PARSER("ParseNoSuchMethodDispatcher");
  ASSERT(FLAG_lazy_dispatchers);
  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(Z, func.saved_args_desc()));
  ASSERT(desc.Count() > 0);

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

  // 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(Z, Array::New(desc.NamedCount()));
    for (intptr_t i = 0; i < arg_names.Length(); ++i) {
      arg_names.SetAt(i, String::Handle(Z, desc.NameAt(i)));
    }
    func_args->set_names(arg_names);
  }

  const String& func_name = String::ZoneHandle(Z, func.name());
  ArgumentListNode* arguments = BuildNoSuchMethodArguments(
      token_pos, func_name, *func_args, NULL, false);
  const intptr_t kNumArguments = 2;  // Receiver, InvocationMirror.
  ArgumentsDescriptor args_desc(
      Array::Handle(Z, ArgumentsDescriptor::New(kNumArguments)));
  Function& no_such_method = Function::ZoneHandle(Z,
      Resolver::ResolveDynamicForReceiverClass(Class::Handle(Z, func.Owner()),
                                               Symbols::NoSuchMethod(),
                                               args_desc));
  if (no_such_method.IsNull()) {
    // If noSuchMethod(i) is not found, call Object:noSuchMethod.
    no_such_method ^= Resolver::ResolveDynamicForReceiverClass(
        Class::Handle(Z, I->object_store()->object_class()),
        Symbols::NoSuchMethod(),
        args_desc);
  }
  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) {
  TRACE_PARSER("ParseInvokeFieldDispatcher");
  ASSERT(FLAG_lazy_dispatchers);
  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(Z, func.saved_args_desc());
  ArgumentsDescriptor desc(args_desc);
  ASSERT(desc.Count() > 0);

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

  // 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 Class& function_impl = Class::Handle(Type::Handle(
      Isolate::Current()->object_store()->function_impl_type()).type_class());

  const Class& owner = Class::Handle(Z, func.Owner());
  ASSERT(!owner.IsNull());
  const String& name = String::Handle(Z, func.name());
  AstNode* function_object = NULL;
  if (owner.raw() == function_impl.raw() && name.Equals(Symbols::Call())) {
    function_object = receiver;
  } else {
    const String& getter_name = String::ZoneHandle(Z,
        Symbols::New(String::Handle(Z, Field::GetterName(name))));
    function_object = new(Z) InstanceCallNode(
        token_pos, receiver, getter_name, no_args);
  }

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

  AstNode* result = NULL;
  if (owner.raw() == function_impl.raw() && name.Equals(Symbols::Call())) {
    result = new ClosureCallNode(token_pos, function_object, args);
  } else {
    result = BuildClosureCall(token_pos, function_object, args);
  }

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


AstNode* Parser::BuildClosureCall(intptr_t token_pos,
                                  AstNode* closure,
                                  ArgumentListNode* arguments) {
  return new InstanceCallNode(token_pos,
                              closure,
                              Symbols::Call(),
                              arguments);
}


void Parser::SkipToMatching() {
  Token::Kind opening_token = CurrentToken();
  ASSERT((opening_token == Token::kLBRACE) ||
         (opening_token == Token::kLPAREN));
  GrowableArray<Token::Kind> token_stack(8);
  GrowableArray<intptr_t> token_pos_stack(8);
  // Adding the first opening brace here, because it will be consumed
  // in the loop right away.
  token_stack.Add(opening_token);
  const intptr_t start_pos =  TokenPos();
  intptr_t opening_pos = start_pos;
  token_pos_stack.Add(start_pos);
  bool is_match = true;
  bool unexpected_token_found = false;
  Token::Kind token = opening_token;
  intptr_t token_pos;
  do {
    ConsumeToken();
    token = CurrentToken();
    token_pos = TokenPos();
    switch (token) {
      case Token::kLBRACE:
      case Token::kLPAREN:
      case Token::kLBRACK:
        token_stack.Add(token);
        token_pos_stack.Add(token_pos);
        break;
      case Token::kRBRACE:
        opening_token = token_stack.RemoveLast();
        opening_pos = token_pos_stack.RemoveLast();
        is_match = opening_token == Token::kLBRACE;
        break;
      case Token::kRPAREN:
        opening_token = token_stack.RemoveLast();
        opening_pos = token_pos_stack.RemoveLast();
        is_match = opening_token == Token::kLPAREN;
        break;
      case Token::kRBRACK:
        opening_token = token_stack.RemoveLast();
        opening_pos = token_pos_stack.RemoveLast();
        is_match = opening_token == Token::kLBRACK;
        break;
      case Token::kEOS:
        unexpected_token_found = true;
        break;
      default:
        // nothing.
        break;
    }
  } while (!token_stack.is_empty() && is_match && !unexpected_token_found);
  if (!is_match) {
    const Error& error = Error::Handle(
        LanguageError::NewFormatted(Error::Handle(),
            script_, opening_pos, Report::kWarning, Heap::kNew,
            "unbalanced '%s' opens here", Token::Str(opening_token)));
    ReportErrors(error, script_, token_pos,
                 "unbalanced '%s'", Token::Str(token));
  } else if (unexpected_token_found) {
    ReportError(start_pos, "unterminated '%s'", Token::Str(opening_token));
  }
}



void Parser::SkipBlock() {
  ASSERT(CurrentToken() == Token::kLBRACE);
  SkipToMatching();
}


// Skips tokens up to and including matching closing parenthesis.
void Parser::SkipToMatchingParenthesis() {
  ASSERT(CurrentToken() == Token::kLPAREN);
  SkipToMatching();
  ASSERT(CurrentToken() == Token::kRPAREN);
  ConsumeToken();
}


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

  if (evaluate_metadata && (CurrentToken() == Token::kAT)) {
    parameter.metadata = &Array::ZoneHandle(Z, EvaluateMetadata());
  } else {
    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.
    // If this is an initializing formal, its type will be set to the type of
    // the respective field when the constructor is fully parsed.
    parameter.type = &Type::ZoneHandle(Z, Type::DynamicType());
  }
  if (CurrentToken() == Token::kTHIS) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
    this_seen = true;
    parameter.is_field_initializer = 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(Z, Type::VoidType());
  }
  if (parameter.type == NULL) {
    // At this point, we must see an identifier for the type or the
    // function parameter.
    if (!IsIdentifier()) {
      ReportError("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.has_explicit_type = true;
      parameter.type = &AbstractType::ZoneHandle(Z,
          ParseType(is_top_level_ ? ClassFinalizer::kResolveTypeParameters :
                                    ClassFinalizer::kCanonicalize));
    } else {
      // If this is an initializing formal, its type will be set to the type of
      // the respective field when the constructor is fully parsed.
      parameter.type = &Type::ZoneHandle(Z, 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;
  }

  if (params->has_optional_named_parameters &&
      (parameter.name->CharAt(0) == Library::kPrivateIdentifierStart)) {
    ReportError(parameter.name_pos, "named parameter must not be private");
  }

  // 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)) {
      ReportError(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(Z, 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(Z, Type::DynamicType()));

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

      // The field 'is_static' has no meaning for signature functions.
      const Function& signature_function = Function::Handle(Z,
          Function::New(*parameter.name,
                        RawFunction::kSignatureFunction,
                        /* is_static = */ false,
                        /* is_const = */ false,
                        /* is_abstract = */ false,
                        /* is_external = */ false,
                        /* is_native = */ false,
                        current_class(),
                        parameter.name_pos));
      signature_function.set_result_type(result_type);
      signature_function.set_is_debuggable(false);
      AddFormalParamsToFunction(&func_params, signature_function);
      const String& signature = String::Handle(Z,
                                               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(Z,
          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());
      if (!is_top_level_) {
        // Finalize types in signature class here, so that the
        // signature type is not computed twice.
        ClassFinalizer::FinalizeTypesInClass(signature_class);
      }
      const Type& signature_type =
          Type::ZoneHandle(Z, signature_class.SignatureType());
      ASSERT(is_top_level_ || signature_type.IsFinalized());
      // A signature type itself cannot be malformed or malbounded, only its
      // signature function's result type or parameter types may be.
      ASSERT(!signature_type.IsMalformed());
      ASSERT(!signature_type.IsMalbounded());
      // 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) {
      ReportError("parameter must not specify a default value");
    }
    if (params->has_optional_positional_parameters) {
      ExpectToken(Token::kASSIGN);
    } else {
      ExpectToken(Token::kCOLON);
    }
    params->num_optional_parameters++;
    params->has_explicit_default_values = true;  // Also if explicitly NULL.
    if (is_top_level_) {
      // Skip default value parsing.
      SkipExpr();
    } else {
      const Instance& 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::null_instance();
    } else {
      params->num_fixed_parameters++;
      ASSERT(params->num_optional_parameters == 0);
    }
  }
  if (parameter.type->IsVoidType()) {
    ReportError("parameter '%s' may not be 'void'",
                parameter.name->ToCString());
  }
  if (params->implicitly_final) {
    parameter.is_final = true;
  }
  params->parameters->Add(parameter);
}


// Parses a sequence of normal or optional formal parameters.
void Parser::ParseFormalParameters(bool allow_explicit_default_values,
                                   bool evaluate_metadata,
                                   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,
                         evaluate_metadata,
                         params);
  } while (CurrentToken() == Token::kCOMMA);
}


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

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


String& Parser::ParseNativeDeclaration() {
  TRACE_PARSER("ParseNativeDeclaration");
  ASSERT(IsSymbol(Symbols::Native()));
  ConsumeToken();
  CheckToken(Token::kSTRING, "string literal expected");
  String& native_name = *CurrentLiteral();
  ConsumeToken();
  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(Z, current_class().SuperClass());
  if (super_class.IsNull()) {
    ReportError(token_pos, "class '%s' does not have a superclass",
                String::Handle(Z, current_class().Name()).ToCString());
  }
  Function& super_func = Function::Handle(Z,
      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(Z, 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();
}


StaticCallNode* Parser::BuildInvocationMirrorAllocation(
    intptr_t call_pos,
    const String& function_name,
    const ArgumentListNode& function_args,
    const LocalVariable* temp_for_last_arg,
    bool is_super_invocation) {
  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);
  arguments->Add(new LiteralNode(args_pos, Bool::Get(is_super_invocation)));
  // Lookup the static InvocationMirror._allocateInvocationMirror method.
  const Class& mirror_class =
      Class::Handle(Library::LookupCoreClass(Symbols::InvocationMirror()));
  ASSERT(!mirror_class.IsNull());
  const Function& allocation_function = Function::ZoneHandle(
      mirror_class.LookupStaticFunction(
          Library::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,
    bool is_super_invocation) {
  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,
                                                 is_super_invocation));
  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(Z,
      GetSuperFunction(supercall_pos,
                       function_name,
                       arguments,
                       kResolveGetter,
                       &is_no_such_method));
  if (super_function.IsGetterFunction() ||
      super_function.IsImplicitGetterFunction()) {
    const Class& super_class =
        Class::ZoneHandle(Z, current_class().SuperClass());
    AstNode* closure = new StaticGetterNode(supercall_pos,
                                            LoadReceiver(supercall_pos),
                                            super_class,
                                            function_name);
    // '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 BuildClosureCall(supercall_pos, closure, closure_arguments);
  }
  if (is_no_such_method) {
    arguments = BuildNoSuchMethodArguments(
        supercall_pos, function_name, *arguments, NULL, true);
  }
  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(Z, 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(Z,
        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, NULL, true);
    }
    super_op = new StaticCallNode(super_pos, super_operator, op_arguments);
  } else {
    ReportError(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(Z, 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::kEQ));
    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(Z, Symbols::New(Token::Str(op)));
    const bool kResolveGetter = false;
    bool is_no_such_method = false;
    const Function& super_operator = Function::ZoneHandle(Z,
        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, NULL, true);
    }
    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;
}


ClosureNode* Parser::CreateImplicitClosureNode(const Function& func,
                                               intptr_t token_pos,
                                               AstNode* receiver) {
  Function& implicit_closure_function =
      Function::ZoneHandle(Z, 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(Z,
          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,
                                       intptr_t field_pos) {
  TRACE_PARSER("ParseSuperFieldAccess");
  const Class& super_class = Class::ZoneHandle(Z, current_class().SuperClass());
  if (super_class.IsNull()) {
    ReportError("class '%s' does not have a superclass",
                String::Handle(Z, current_class().Name()).ToCString());
  }
  AstNode* implicit_argument = LoadReceiver(field_pos);

  const String& getter_name =
      String::ZoneHandle(Z, Field::GetterName(field_name));
  const Function& super_getter = Function::ZoneHandle(Z,
      Resolver::ResolveDynamicAnyArgs(super_class, getter_name));
  if (super_getter.IsNull()) {
    const String& setter_name =
        String::ZoneHandle(Z, Field::SetterName(field_name));
    const Function& super_setter = Function::ZoneHandle(Z,
        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(Z,
          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(Z) StaticGetterNode(
      field_pos, implicit_argument, super_class, field_name);
}


void Parser::GenerateSuperConstructorCall(const Class& cls,
                                          intptr_t supercall_pos,
                                          LocalVariable* receiver,
                                          AstNode* phase_parameter,
                                          ArgumentListNode* forwarding_args) {
  const Class& super_class = Class::Handle(Z, 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(Z, super_class.SuperClass()).IsObjectClass())) {
    return;
  }
  String& super_ctor_name = String::Handle(Z, super_class.Name());
  super_ctor_name = Symbols::FromConcat(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.
  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(Z, current_function().name());
    String& class_name = String::Handle(Z, 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.
      const intptr_t kLen =  class_name.Length() + 1;
      ctor_name = Symbols::New(ctor_name, kLen, ctor_name.Length() - kLen);
      super_ctor_name = Symbols::FromConcat(super_ctor_name, ctor_name);
    }
  }

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

  String& error_message = String::Handle(Z);
  if (!super_ctor.AreValidArguments(arguments->length(),
                                    arguments->names(),
                                    &error_message)) {
    ReportError(supercall_pos,
                "invalid arguments passed to super constructor '%s()': %s",
                String::Handle(Z, 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(Z, cls.SuperClass());
  ASSERT(!super_class.IsNull());
  String& ctor_name = String::Handle(Z, super_class.Name());
  ctor_name = Symbols::FromConcat(ctor_name, Symbols::Dot());
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    ctor_name = Symbols::FromConcat(
        ctor_name, *ExpectIdentifier("constructor name expected"));
  }
  CheckToken(Token::kLPAREN, "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(Z, 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(Z,
      super_class.LookupConstructor(ctor_name));
  if (super_ctor.IsNull()) {
    ReportError(supercall_pos,
                "super class constructor '%s' not found",
                ctor_name.ToCString());
  }
  if (current_function().is_const() && !super_ctor.is_const()) {
    ReportError(supercall_pos, "super constructor must be const");
  }
  String& error_message = String::Handle(Z);
  if (!super_ctor.AreValidArguments(arguments->length(),
                                    arguments->names(),
                                    &error_message)) {
    ReportError(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()) {
    ReportError(field_pos,
                "initializer expression must be compile time constant.");
  }
  Field& field = Field::ZoneHandle(Z, cls.LookupInstanceField(field_name));
  if (field.IsNull()) {
    ReportError(field_pos, "unresolved reference to instance field '%s'",
                field_name.ToCString());
  }
  EnsureExpressionTemp();
  AstNode* instance = new(Z) LoadLocalNode(field_pos, receiver);
  AstNode* initializer = CheckDuplicateFieldInit(field_pos,
      initialized_fields, instance, &field, init_expr);
  if (initializer == NULL) {
    initializer =
        new(Z) StoreInstanceFieldNode(field_pos, instance, field, init_expr);
  }
  return initializer;
}


void Parser::CheckFieldsInitialized(const Class& cls) {
  const Array& fields = Array::Handle(Z, cls.fields());
  Field& field = Field::Handle(Z);
  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;

    field.RecordStore(Object::Handle(Z));
  }
}


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(Z, current_class().raw());
  const Library& saved_library = Library::Handle(Z, library().raw());
  const Script& saved_script = Script::Handle(Z, script().raw());
  const intptr_t saved_token_pos = TokenPos();

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

  ASSERT(IsIdentifier());
  ConsumeToken();
  ExpectToken(Token::kASSIGN);
  AstNode* init_expr = NULL;
  intptr_t expr_pos = TokenPos();
  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(expr_pos, 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(Z, cls.fields());
  Field& f = Field::Handle(Z);
  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(Z);
      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 (current_class().is_const()) {
          // If the class has a const contructor, the initializer
          // expression must be a compile-time constant.
          init_expr = ParseConstExpr();
        } else {
          intptr_t expr_pos = TokenPos();
          init_expr = ParseExpr(kAllowConst, kConsumeCascades);
          if (init_expr->EvalConstExpr() != NULL) {
            init_expr = new LiteralNode(field.token_pos(),
                                        EvaluateConstExpr(expr_pos, 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);
    }
  }
  initialized_fields->Add(NULL);  // End of inline initializers.
  SetPosition(saved_pos);
}


AstNode* Parser::CheckDuplicateFieldInit(
    intptr_t init_pos,
    GrowableArray<Field*>* initialized_fields,
    AstNode* instance,
    Field* field,
    AstNode* init_value) {
  ASSERT(!field->is_static());
  AstNode* result = NULL;

  // The initializer_list is divided into two sections. The sections
  // are separated by a NULL entry: [f0, ... fn, NULL, fn+1, ...]
  // The first fields f0 .. fn are final fields of the class that
  // have an initializer expression inlined in the class declaration.
  // The remaining fields are those initialized by the constructor's
  // initializing formals and initializer list
  int initializer_idx = 0;
  while (initializer_idx < initialized_fields->length()) {
    Field* initialized_field = (*initialized_fields)[initializer_idx];
    initializer_idx++;
    if (initialized_field == NULL) {
      break;
    }
    if (initialized_field->raw() == field->raw()) {
      // This final field has been initialized by an inlined
      // initializer expression. This is a runtime error.
      // Throw a NoSuchMethodError for the missing setter.
      ASSERT(field->is_final());

      // Build a call to NoSuchMethodError::_throwNew(
      //     Object receiver,
      //     String memberName,
      //     int invocation_type,
      //     List arguments,
      //     List argumentNames,
      //     List existingArgumentNames);

      ArgumentListNode* nsm_args = new(Z) ArgumentListNode(init_pos);
      // Object receiver.
      nsm_args->Add(instance);

      // String memberName.
      String& setter_name = String::ZoneHandle(field->name());
      setter_name = Field::SetterSymbol(setter_name);
      nsm_args->Add(new(Z) LiteralNode(init_pos, setter_name));

      // Smi invocation_type.
      const int invocation_type =
          InvocationMirror::EncodeType(InvocationMirror::kDynamic,
                                       InvocationMirror::kSetter);
      nsm_args->Add(new(Z) LiteralNode(
          init_pos, Smi::ZoneHandle(Z, Smi::New(invocation_type))));

      // List arguments.
      GrowableArray<AstNode*> setter_args;
      setter_args.Add(init_value);
      ArrayNode* setter_args_array = new(Z) ArrayNode(
          init_pos,
          Type::ZoneHandle(Z, Type::ArrayType()),
          setter_args);
      nsm_args->Add(setter_args_array);

      // List argumentNames.
      // The missing implicit setter of the field has no argument names.
      nsm_args->Add(new(Z) LiteralNode(init_pos, Array::ZoneHandle(Z)));

      // List existingArgumentNames.
      // There is no setter for the final field, thus there are
      // no existing names.
      nsm_args->Add(new(Z) LiteralNode(init_pos, Array::ZoneHandle(Z)));

      AstNode* nsm_call =
          MakeStaticCall(Symbols::NoSuchMethodError(),
          Library::PrivateCoreLibName(Symbols::ThrowNew()),
          nsm_args);

      LetNode* let = new(Z) LetNode(init_pos);
      let->AddNode(init_value);
      let->AddNode(nsm_call);
      result = let;
    }
  }
  // The remaining elements in initialized_fields are fields that
  // are initialized through initializing formal parameters, or
  // in the constructor's initializer list. If there is a duplicate,
  // it is a compile time error.
  while (initializer_idx < initialized_fields->length()) {
    Field* initialized_field = (*initialized_fields)[initializer_idx];
    initializer_idx++;
    if (initialized_field->raw() == field->raw()) {
      ReportError(init_pos,
                  "duplicate initializer for field %s",
                  String::Handle(Z, field->name()).ToCString());
    }
  }
  initialized_fields->Add(field);
  return result;
}


void Parser::ParseInitializers(const Class& cls,
                               LocalVariable* receiver,
                               GrowableArray<Field*>* initialized_fields) {
  TRACE_PARSER("ParseInitializers");
  bool super_init_seen = false;
  if (CurrentToken() == Token::kCOLON) {
    do {
      ConsumeToken();  // Colon or comma.
      AstNode* init_statement;
      if (CurrentToken() == Token::kSUPER) {
        if (super_init_seen) {
          ReportError("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.
    AstNode* phase_parameter = new LiteralNode(
        TokenPos(), Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseAll)));
    GenerateSuperConstructorCall(
        cls, TokenPos(), receiver, phase_parameter, NULL);
  }
  CheckFieldsInitialized(cls);
}


void Parser::ParseConstructorRedirection(const Class& cls,
                                         LocalVariable* receiver) {
  TRACE_PARSER("ParseConstructorRedirection");
  ExpectToken(Token::kCOLON);
  ASSERT(CurrentToken() == Token::kTHIS);
  const intptr_t call_pos = TokenPos();
  ConsumeToken();
  String& ctor_name = String::Handle(Z, cls.Name());
  GrowableHandlePtrArray<const String> pieces(Z, 3);
  pieces.Add(ctor_name);
  pieces.Add(Symbols::Dot());
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    pieces.Add(*ExpectIdentifier("constructor name expected"));
  }
  ctor_name = Symbols::FromConcatAll(pieces);
  CheckToken(Token::kLPAREN, "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(Z,
      cls.LookupConstructor(ctor_name));
  if (redirect_ctor.IsNull()) {
    ReportError(call_pos, "constructor '%s' not found", ctor_name.ToCString());
  }
  String& error_message = String::Handle(Z);
  if (!redirect_ctor.AreValidArguments(arguments->length(),
                                       arguments->names(),
                                       &error_message)) {
    ReportError(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.IsGenerativeConstructor());
  ASSERT(func.Owner() == current_class().raw());
  const intptr_t ctor_pos = TokenPos();
  OpenFunctionBlock(func);

  LocalVariable* receiver = new LocalVariable(
      Scanner::kNoSourcePos, Symbols::This(), *ReceiverType(current_class()));
  current_block_->scope->InsertParameterAt(0, receiver);

  LocalVariable* phase_parameter =
      new LocalVariable(Scanner::kNoSourcePos,
                        Symbols::PhaseParameter(),
                        Type::ZoneHandle(Z, Type::SmiType()));
  current_block_->scope->InsertParameterAt(1, 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 alias,
  // it is a forwarding constructor of the aliased mixin application class.
  // 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().is_mixin_app_alias() ||
      current_class().IsMixinApplication()) {
    // 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()) {
      const Class& super_class = Class::Handle(Z, current_class().SuperClass());
      ReportError(ctor_pos,
                  "cannot generate an implicit mixin application constructor "
                  "forwarding to a super class constructor with optional "
                  "parameters; add a constructor without optional parameters "
                  "to class '%s' that redirects to the constructor with "
                  "optional parameters and invoke it via super from a "
                  "constructor of the class extending the mixin application",
                  String::Handle(Z, super_class.Name()).ToCString());
    }

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

  GenerateSuperConstructorCall(
      current_class(),
      Scanner::kNoSourcePos,
      receiver,
      new LoadLocalNode(Scanner::kNoSourcePos, phase_parameter),
      forwarding_args);
  CheckFieldsInitialized(current_class());

  // Empty constructor body.
  current_block_->statements->Add(new ReturnNode(Scanner::kNoSourcePos));
  SequenceNode* statements = CloseBlock();
  return statements;
}


void Parser::CheckRecursiveInvocation() {
  const GrowableObjectArray& pending_functions =
      GrowableObjectArray::Handle(Z,
          I->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(Z, current_function().UserVisibleName());
      ReportError("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) {
  TRACE_PARSER("ParseConstructor");
  ASSERT(func.IsGenerativeConstructor());
  ASSERT(!func.IsFactory());
  ASSERT(!func.is_static());
  ASSERT(!func.IsLocalFunction());
  const Class& cls = Class::Handle(Z, 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(Z, Type::SmiType()));

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

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

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

  const bool is_redirecting_constructor =
      (CurrentToken() == Token::kCOLON) &&
          ((LookaheadToken(1) == Token::kTHIS) &&
              ((LookaheadToken(2) == Token::kLPAREN) ||
              ((LookaheadToken(2) == Token::kPERIOD) &&
              (LookaheadToken(4) == Token::kLPAREN))));

  GrowableArray<Field*> initialized_fields;
  LocalVariable* receiver = (*params.parameters)[0].var;
  OpenBlock();

  // If this is not a redirecting constructor, initialize
  // instance fields that have an explicit initializer expression.
  if (!is_redirecting_constructor) {
    // 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.
    params.SetInvisible(true);
    ParseInitializedInstanceFields(cls, receiver, &initialized_fields);
    // Make the parameters (which are in the outer scope) visible again.
    params.SetInvisible(false);
  }

  // Turn formal field parameters into field initializers.
  if (params.has_field_initializer) {
    // First two parameters are implicit receiver and phase.
    ASSERT(params.parameters->length() >= 2);
    for (int i = 2; 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(Z, cls.LookupInstanceField(field_name));
        if (field.IsNull()) {
          ReportError(param.name_pos,
                      "unresolved reference to instance field '%s'",
                      field_name.ToCString());
        }
        if (is_redirecting_constructor) {
          ReportError(param.name_pos,
                      "redirecting constructors may not have "
                      "initializing formal parameters");
        }

        if (!param.has_explicit_type) {
          const AbstractType& field_type =
              AbstractType::ZoneHandle(Z, field.type());
          param.type = &field_type;
          // Parameter type was already set to dynamic when parsing the class
          // declaration: fix it.
          func.SetParameterTypeAt(i, field_type);
        }

        AstNode* instance = new LoadLocalNode(param.name_pos, receiver);
        // Initializing formals cannot be used in the explicit initializer
        // list, nor can they be used in the constructor body.
        // Thus, they are set to be invisible when added to the scope.
        LocalVariable* p = param.var;
        ASSERT(p != NULL);
        ASSERT(p->is_invisible());
        AstNode* value = new LoadLocalNode(param.name_pos, p);
        EnsureExpressionTemp();
        AstNode* initializer =
            CheckDuplicateFieldInit(param.name_pos,
                                    &initialized_fields,
                                    instance,
                                    &field,
                                    value);
        if (initializer == NULL) {
          initializer = new(Z) StoreInstanceFieldNode(
              param.name_pos, instance, field, value);
        }
        current_block_->statements->Add(initializer);
      }
    }
  }

  if (is_redirecting_constructor) {
    ParseConstructorRedirection(cls, receiver);
  } else {
    ParseInitializers(cls, receiver, &initialized_fields);
  }

  SequenceNode* init_statements = CloseBlock();
  if (is_redirecting_constructor) {
    // A redirecting super constructor simply passes the phase parameter on to
    // the target which executes the corresponding phase.
    current_block_->statements->Add(init_statements);
  } else if (init_statements->length() > 0) {
    // Generate guard around the initializer code.
    LocalVariable* phase_param = LookupPhaseParameter();
    AstNode* phase_value = new
        LoadLocalNode(Scanner::kNoSourcePos, phase_param);
    AstNode* phase_check = new BinaryOpNode(
        Scanner::kNoSourcePos, Token::kBIT_AND, phase_value,
        new LiteralNode(Scanner::kNoSourcePos,
            Smi::ZoneHandle(Z, Smi::New(Function::kCtorPhaseInit))));
    AstNode* comparison =
        new ComparisonNode(Scanner::kNoSourcePos,
                           Token::kNE_STRICT,
                           phase_check,
                           new LiteralNode(TokenPos(),
                                           Smi::ZoneHandle(Z, Smi::New(0))));
    AstNode* guarded_init_statements =
        new IfNode(Scanner::kNoSourcePos,
                   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().IsGenerativeConstructor()) {
        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.
    // Note: we should never get here in the case of a redirecting
    // constructor. In that case, the call to the target constructor
    // is the "super call" and is implicitly at the end of the
    // initializer list.
    ASSERT(!is_redirecting_constructor);
    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(Z, 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(Z) LiteralNode(
        body_pos, Smi::ZoneHandle(Z, 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) {
    // We checked in the top-level parse phase that a redirecting
    // constructor does not have a body.
    ASSERT(!is_redirecting_constructor);
    ConsumeToken();
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kARROW) {
    ReportError("constructors may not return a value");
  } else if (IsSymbol(Symbols::Native())) {
    ReportError("native constructors not supported");
  } else if (CurrentToken() == Token::kSEMICOLON) {
    // Some constructors have no function body.
    ConsumeToken();
    if (func.is_external()) {
      // Body of an external method contains a single throw.
      const String& function_name = String::ZoneHandle(func.name());
      current_block_->statements->Add(
          ThrowNoSuchMethodError(TokenPos(),
                                 cls,
                                 function_name,
                                 NULL,   // No arguments.
                                 InvocationMirror::kStatic,
                                 InvocationMirror::kMethod,
                                 NULL));  // No existing function.
    }
  } 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(Scanner::kNoSourcePos, phase_param);
    AstNode* phase_check =
        new BinaryOpNode(Scanner::kNoSourcePos, Token::kBIT_AND,
            phase_value,
            new LiteralNode(Scanner::kNoSourcePos,
                Smi::ZoneHandle(Smi::New(Function::kCtorPhaseBody))));
    AstNode* comparison =
        new ComparisonNode(Scanner::kNoSourcePos,
                           Token::kNE_STRICT,
                           phase_check,
                           new LiteralNode(body_pos,
                                           Smi::ZoneHandle(Smi::New(0))));
    AstNode* guarded_block_statements =
        new IfNode(Scanner::kNoSourcePos, comparison, ctor_block, NULL);
    current_block_->statements->Add(guarded_block_statements);
  }
  current_block_->statements->Add(new ReturnNode(func.end_token_pos()));
  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) {
  TRACE_PARSER("ParseFunc");
  Function& saved_innermost_function =
      Function::Handle(Z, 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;

  // In case of nested async functions we also need to save the scope where
  // temporaries are added.
  LocalScope* saved_async_temp_scope = async_temp_scope_;

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

  ASSERT(!func.IsGenerativeConstructor());
  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(Z, 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 TypeArguments vector of
    // the type of the instance to be allocated.
    params.AddFinalParameter(
        TokenPos(),
        &Symbols::TypeArgumentsParameter(),
        &Type::ZoneHandle(Z, Type::DynamicType()));
  }
  // Expect the parameter list unless this is a getter function, or the
  // body closure of an async or generator getter function.
  ASSERT((CurrentToken() == Token::kLPAREN) ||
         func.IsGetterFunction() ||
         (func.is_generated_body() &&
             Function::Handle(func.parent_function()).IsGetterFunction()));
  const bool allow_explicit_default_values = true;
  if (func.IsGetterFunction()) {
    // Populate function scope with the formal parameters. Since in this case
    // we are compiling a getter this will at most populate the receiver.
    AddFormalParamsToScope(&params, current_block_->scope);
  } else if (func.IsAsyncClosure()) {
    AddAsyncClosureParameters(&params);
    SetupDefaultsForOptionalParams(params);
    AddFormalParamsToScope(&params, current_block_->scope);
    ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
    ASSERT(func.NumParameters() == params.parameters->length());
    if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
      // Parse and discard any formal parameters. They are accessed as
      // context variables.
      ParamList discarded_params;
      ParseFormalParameterList(allow_explicit_default_values,
                               false,
                               &discarded_params);
    }
  } else if (func.IsSyncGenClosure()) {
    AddSyncGenClosureParameters(&params);
    SetupDefaultsForOptionalParams(params);
    AddFormalParamsToScope(&params, current_block_->scope);
    ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
    if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
      // Parse and discard any formal parameters. They are accessed as
      // context variables.
      ParamList discarded_params;
      ParseFormalParameterList(allow_explicit_default_values,
                               false,
                               &discarded_params);
    }
  } else if (func.IsAsyncGenClosure()) {
    AddAsyncGenClosureParameters(&params);
    SetupDefaultsForOptionalParams(params);
    AddFormalParamsToScope(&params, current_block_->scope);
    ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
    ASSERT(func.NumParameters() == params.parameters->length());
    if (!Function::Handle(func.parent_function()).IsGetterFunction()) {
      // Parse and discard any formal parameters. They are accessed as
      // context variables.
      ParamList discarded_params;
      ParseFormalParameterList(allow_explicit_default_values,
                               false,
                               &discarded_params);
    }
  } else {
    ParseFormalParameterList(allow_explicit_default_values, false, &params);

    // 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);
    ASSERT(AbstractType::Handle(Z, 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) {
          ReportError(param.name_pos,
                      "field initializer only allowed in constructors");
        }
      }
    }
    // Populate function scope with the formal parameters.
    AddFormalParamsToScope(&params, current_block_->scope);

    if (I->flags().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();
      }
    }
  }

  const intptr_t modifier_pos = TokenPos();
  RawFunction::AsyncModifier func_modifier = ParseFunctionModifier();
  if (!func.is_generated_body()) {
    // Don't add a modifier to the closure representing the body of
    // the asynchronous function or generator.
    func.set_modifier(func_modifier);
  }

  OpenBlock();  // Open a nested scope for the outermost function block.

  Function& generated_body_closure = Function::ZoneHandle(Z);
  if (func.IsAsyncFunction()) {
    ASSERT(!func.is_generated_body());
    // The code of an async function is synthesized. Disable debugging.
    func.set_is_debuggable(false);
    generated_body_closure = OpenAsyncFunction(func.token_pos());
  } else if (func.IsAsyncClosure()) {
    // The closure containing the body of an async function is debuggable.
    ASSERT(func.is_debuggable());
    OpenAsyncClosure();
  } else if (func.IsSyncGenerator()) {
    // The code of a sync generator is synthesized. Disable debugging.
    func.set_is_debuggable(false);
    generated_body_closure = OpenSyncGeneratorFunction(func.token_pos());
  } else if (func.IsSyncGenClosure()) {
    // The closure containing the body of a sync generator is debuggable.
    ASSERT(func.is_debuggable());
    async_temp_scope_ = current_block_->scope;
  } else if (func.IsAsyncGenerator()) {
    func.set_is_debuggable(false);
    generated_body_closure = OpenAsyncGeneratorFunction(func.token_pos());
  } else if (func.IsAsyncGenClosure()) {
    // The closure containing the body of an async* function is debuggable.
    ASSERT(func.is_debuggable());
    OpenAsyncGeneratorClosure();
  }

  BoolScope allow_await(&this->await_is_keyword_,
                        func.IsAsyncOrGenerator() || func.is_generated_body());
  intptr_t end_token_pos = 0;
  if (CurrentToken() == Token::kLBRACE) {
    ConsumeToken();
    if (String::Handle(Z, func.name()).Equals(Symbols::EqualOperator())) {
      const Class& owner = Class::Handle(Z, func.Owner());
      if (!owner.IsObjectClass()) {
        AddEqualityNullCheck();
      }
    }
    ParseStatementSequence();
    end_token_pos = TokenPos();
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kARROW) {
    if (func.IsGenerator()) {
      ReportError(modifier_pos,
                  "=> style function may not be sync* or async* generator");
    }
    ConsumeToken();
    if (String::Handle(Z, func.name()).Equals(
        Symbols::EqualOperator())) {
      const Class& owner = Class::Handle(Z, func.Owner());
      if (!owner.IsObjectClass()) {
        AddEqualityNullCheck();
      }
    }
    const intptr_t expr_pos = TokenPos();
    AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
    ASSERT(expr != NULL);
    current_block_->statements->Add(new ReturnNode(expr_pos, expr));
    end_token_pos = TokenPos();
  } else if (IsSymbol(Symbols::Native())) {
    if (String::Handle(Z, func.name()).Equals(
        Symbols::EqualOperator())) {
      const Class& owner = Class::Handle(Z, func.Owner());
      if (!owner.IsObjectClass()) {
        AddEqualityNullCheck();
      }
    }
    ParseNativeFunctionBlock(&params, func);
    end_token_pos = TokenPos();
    ExpectSemicolon();
  } else if (func.is_external()) {
    // Body of an external method contains a single throw.
    const String& function_name = String::ZoneHandle(Z, func.name());
    current_block_->statements->Add(
        ThrowNoSuchMethodError(TokenPos(),
                               Class::Handle(func.Owner()),
                               function_name,
                               NULL,  // Ignore arguments.
                               func.is_static() ?
                                   InvocationMirror::kStatic :
                                   InvocationMirror::kDynamic,
                               InvocationMirror::kMethod,
                               &func));  // Unpatched external function.
    end_token_pos = TokenPos();
  } else {
    UnexpectedToken();
  }

  ASSERT(func.end_token_pos() == func.token_pos() ||
         func.end_token_pos() == end_token_pos);
  func.set_end_token_pos(end_token_pos);
  SequenceNode* body = CloseBlock();
  if (func.IsAsyncFunction()) {
    body = CloseAsyncFunction(generated_body_closure, body);
    generated_body_closure.set_end_token_pos(end_token_pos);
  } else if (func.IsAsyncClosure()) {
    body = CloseAsyncClosure(body);
  } else if (func.IsSyncGenerator()) {
    body = CloseSyncGenFunction(generated_body_closure, body);
    generated_body_closure.set_end_token_pos(end_token_pos);
  } else if (func.IsSyncGenClosure()) {
    // body is unchanged.
  } else if (func.IsAsyncGenerator()) {
    body = CloseAsyncGeneratorFunction(generated_body_closure, body);
    generated_body_closure.set_end_token_pos(end_token_pos);
  } else if (func.IsAsyncGenClosure()) {
    body = CloseAsyncGeneratorClosure(body);
  }
  EnsureHasReturnStatement(body, end_token_pos);
  current_block_->statements->Add(body);
  innermost_function_ = saved_innermost_function.raw();
  last_used_try_index_ = saved_try_index;
  async_temp_scope_ = saved_async_temp_scope;
  return CloseBlock();
}


void Parser::AddEqualityNullCheck() {
  AstNode* argument =
      new LoadLocalNode(Scanner::kNoSourcePos,
                        current_block_->scope->parent()->VariableAt(1));
  LiteralNode* null_operand =
      new LiteralNode(Scanner::kNoSourcePos, Instance::ZoneHandle(Z));
  ComparisonNode* check_arg =
      new ComparisonNode(Scanner::kNoSourcePos,
                         Token::kEQ_STRICT,
                         argument,
                         null_operand);
  ComparisonNode* result =
      new ComparisonNode(Scanner::kNoSourcePos,
                         Token::kEQ_STRICT,
                         LoadReceiver(Scanner::kNoSourcePos),
                         null_operand);
  SequenceNode* arg_is_null = new SequenceNode(Scanner::kNoSourcePos,
                                               current_block_->scope);
  arg_is_null->Add(new ReturnNode(Scanner::kNoSourcePos, result));
  IfNode* if_arg_null = new IfNode(Scanner::kNoSourcePos,
                                   check_arg,
                                   arg_is_null,
                                   NULL);
  current_block_->statements->Add(if_arg_null);
}


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


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");
      }
      CheckToken(Token::kLPAREN);
      SkipToMatchingParenthesis();
    } else {
      SkipIf(Token::kTHIS);
      SkipIf(Token::kPERIOD);
      ExpectIdentifier("identifier expected");
      ExpectToken(Token::kASSIGN);
      SetAllowFunctionLiterals(false);
      SkipExpr();
      SetAllowFunctionLiterals(true);
    }
  } while (CurrentToken() == Token::kCOMMA);
}


// If the current identifier is a library prefix followed by a period,
// consume the identifier and period, and return the resolved library
// prefix.
RawLibraryPrefix* Parser::ParsePrefix() {
  ASSERT(IsIdentifier());
  // A library prefix can never stand by itself. It must be followed by
  // a period or a hash mark (for closurization).
  Token::Kind next_token = LookaheadToken(1);
  if ((next_token != Token::kPERIOD) && (next_token != Token::kHASH)) {
    return LibraryPrefix::null();
  }
  const String& ident = *CurrentLiteral();

  // It is relatively fast to look up a name in the library dictionary,
  // compared to searching the nested local scopes. Look up the name
  // in the library scope and return in the common case where ident is
  // not a library prefix.
  LibraryPrefix& prefix =
      LibraryPrefix::Handle(Z, library_.LookupLocalLibraryPrefix(ident));
  if (prefix.IsNull()) {
    return LibraryPrefix::null();
  }

  // A library prefix with the name exists. Now check whether it is
  // shadowed by a local definition.
  if (!is_top_level_ &&
      ResolveIdentInLocalScope(TokenPos(), ident, NULL)) {
    return LibraryPrefix::null();
  }
  // Check whether the identifier is shadowed by a type parameter.
  ASSERT(!current_class().IsNull());
  if (current_class().LookupTypeParameter(ident) != TypeParameter::null()) {
    return LibraryPrefix::null();
  }

  // We have a name that is not shadowed, followed by a period or #.
  // Consume the identifier, let the caller consume the . or #.
  ConsumeToken();
  return prefix.raw();
}


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

  if (method->has_var) {
    ReportError(method->name_pos, "keyword var not allowed for methods");
  }
  if (method->has_final) {
    ReportError(method->name_pos, "'final' not allowed for methods");
  }
  if (method->has_abstract && method->has_static) {
    ReportError(method->name_pos,
                "static method '%s' cannot be abstract",
                method->name->ToCString());
     }
  if (method->has_const && !method->IsFactoryOrConstructor()) {
    ReportError(method->name_pos, "'const' not allowed for methods");
  }
  if (method->has_abstract && method->IsFactoryOrConstructor()) {
    ReportError(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 TypeArguments 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(Z, Type::DynamicType()));
  }
  // Constructors have an implicit parameter for the construction phase.
  if (method->IsConstructor()) {
    method->params.AddFinalParameter(
        TokenPos(),
        &Symbols::PhaseParameter(),
        &Type::ZoneHandle(Z, Type::SmiType()));
  }
  if (are_implicitly_final) {
    method->params.SetImplicitlyFinal();
  }
  if (!method->IsGetter()) {
    ParseFormalParameterList(allow_explicit_default_values,
                             false,
                             &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);
  }

  // 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->dict_name = method->name;
      method->name = &String::ZoneHandle(Z, Field::GetterSymbol(*method->name));
    } else {
      ASSERT(method->IsSetter());
      expected_num_parameters = (method->has_static) ? 1 : 2;
      method->dict_name = &String::ZoneHandle(Z,
          Symbols::FromConcat(*method->name, Symbols::Equals()));
      method->name = &String::ZoneHandle(Z, Field::SetterSymbol(*method->name));
    }
    if ((method->params.num_fixed_parameters != expected_num_parameters) ||
        (method->params.num_optional_parameters != 0)) {
      ReportError(method->name_pos, "illegal %s parameters",
                  method->IsGetter() ? "getter" : "setter");
    }
  }

  // Parse redirecting factory constructor.
  Type& redirection_type = Type::Handle(Z);
  String& redirection_identifier = String::Handle(Z);
  bool is_redirecting = false;
  if (method->IsFactory() && (CurrentToken() == Token::kASSIGN)) {
    // Default parameter values are disallowed in redirecting factories.
    if (method->params.has_explicit_default_values) {
      ReportError("redirecting factory '%s' may not specify default values "
                  "for optional parameters",
                  method->name->ToCString());
    }
    if (method->has_external) {
      ReportError(TokenPos(),
                  "external factory constructor '%s' may not have redirection",
                  method->name->ToCString());
    }
    ConsumeToken();
    const intptr_t type_pos = TokenPos();
    is_redirecting = true;
    const bool consume_unresolved_prefix =
        (LookaheadToken(3) == Token::kLT) ||
        (LookaheadToken(3) == Token::kPERIOD);
    const AbstractType& type = AbstractType::Handle(Z,
        ParseType(ClassFinalizer::kResolveTypeParameters,
                  true,
                  consume_unresolved_prefix));
    if (!type.IsMalformed() && type.IsTypeParameter()) {
      // Replace the type with a malformed type and compile a throw when called.
      redirection_type = ClassFinalizer::NewFinalizedMalformedType(
          Error::Handle(Z),  // No previous error.
          script_,
          type_pos,
          "factory '%s' may not redirect to type parameter '%s'",
          method->name->ToCString(),
          String::Handle(Z, type.UserVisibleName()).ToCString());
    } else {
      // We handle malformed and malbounded redirection type at run time.
      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()) {
      ReportError("initializers only allowed on constructors");
    }
    if (method->has_external) {
      ReportError(TokenPos(),
                  "external constructor '%s' may not have initializers",
                  method->name->ToCString());
    }
    if ((LookaheadToken(1) == Token::kTHIS) &&
        ((LookaheadToken(2) == Token::kLPAREN) ||
         LookaheadToken(4) == Token::kLPAREN)) {
      // Redirected constructor: either this(...) or this.xxx(...).
      is_redirecting = true;
      if (method->params.has_field_initializer) {
        // Constructors that redirect to another constructor must not
        // initialize any fields using field initializer parameters.
        ReportError(formal_param_pos, "Redirecting constructor "
                    "may not use field initializer parameters");
      }
      ConsumeToken();  // Colon.
      ExpectToken(Token::kTHIS);
      String& redir_name = String::ZoneHandle(Z,
          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;
      CheckToken(Token::kLPAREN);
      SkipToMatchingParenthesis();
    } else {
      SkipInitializers();
    }
  }

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

  if (method->IsConstructor() &&
      method->has_external &&
      method->params.has_field_initializer) {
    ReportError(method->name_pos,
                "external constructor '%s' may not have field initializers",
                method->name->ToCString());
  }

  const intptr_t modifier_pos = TokenPos();
  RawFunction::AsyncModifier async_modifier = ParseFunctionModifier();
  if ((method->IsFactoryOrConstructor() || method->IsSetter()) &&
      (async_modifier != RawFunction::kNoModifier)) {
    ReportError(modifier_pos,
                "%s '%s' may not be async, async* or sync*",
                (method->IsSetter()) ? "setter" : "constructor",
                method->name->ToCString());
  }

  intptr_t method_end_pos = TokenPos();
  if ((CurrentToken() == Token::kLBRACE) ||
      (CurrentToken() == Token::kARROW)) {
    if (method->has_abstract) {
      ReportError(TokenPos(),
                  "abstract method '%s' may not have a function body",
                  method->name->ToCString());
    } else if (method->has_external) {
      ReportError(TokenPos(),
                  "external %s '%s' may not have a function body",
                  method->IsFactoryOrConstructor() ? "constructor" : "method",
                  method->name->ToCString());
    } else if (method->IsConstructor() && method->has_const) {
      ReportError(TokenPos(),
                  "const constructor '%s' may not have a function body",
                  method->name->ToCString());
    } else if (method->IsFactory() && method->has_const) {
      ReportError(TokenPos(),
                  "const factory '%s' may not have a function body",
                  method->name->ToCString());
    }
    if (method->redirect_name != NULL) {
      ReportError(method->name_pos,
                  "Constructor with redirection may not have a function body");
    }
    if (CurrentToken() == Token::kLBRACE) {
      SkipBlock();
      method_end_pos = TokenPos();
      ExpectToken(Token::kRBRACE);
    } else {
      if ((async_modifier & RawFunction::kGeneratorBit) != 0) {
        ReportError(modifier_pos,
                    "=> style function may not be sync* or async* generator");
      }

      ConsumeToken();
      BoolScope allow_await(&this->await_is_keyword_,
                            async_modifier != RawFunction::kNoModifier);
      SkipExpr();
      method_end_pos = TokenPos();
      ExpectSemicolon();
    }
  } else if (IsSymbol(Symbols::Native())) {
    if (method->has_abstract) {
      ReportError(method->name_pos,
                  "abstract method '%s' may not have a function body",
                  method->name->ToCString());
    } else if (method->IsConstructor() && method->has_const) {
      ReportError(method->name_pos,
                  "const constructor '%s' may not be native",
                  method->name->ToCString());
    }
    if (method->redirect_name != NULL) {
      ReportError(method->name_pos,
                  "Constructor with redirection may not have a function body");
    }
    ParseNativeDeclaration();
    method_end_pos = TokenPos();
    ExpectSemicolon();
    method->has_native = true;
  } 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) {
      ReportError(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 {
        ReportError(method->name_pos,
                    "function body or semicolon expected for method '%s'",
                    method->name->ToCString());
      }
    }
  }

  if (method->has_abstract && (async_modifier != RawFunction::kNoModifier)) {
    ReportError(modifier_pos,
                "abstract function '%s' may not be async, async* or sync*",
                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(Z,
      Function::New(*method->name,
                    function_kind,
                    method->has_static,
                    method->has_const,
                    method->has_abstract,
                    method->has_external,
                    method->has_native,
                    current_class(),
                    method->decl_begin_pos));
  func.set_result_type(*method->type);
  func.set_end_token_pos(method_end_pos);
  func.set_is_redirecting(is_redirecting);
  func.set_modifier(async_modifier);
  if (library_.is_dart_scheme() && library_.IsPrivate(*method->name)) {
    func.set_is_reflectable(false);
  }
  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) {
    ReportError("keyword 'abstract' not allowed in field declaration");
  }
  if (field->has_external) {
    ReportError("keyword 'external' not allowed in field declaration");
  }
  if (field->has_factory) {
    ReportError("keyword 'factory' not allowed in field declaration");
  }
  if (!field->has_static && field->has_const) {
    ReportError(field->name_pos, "instance field may not be 'const'");
  }
  Function& getter = Function::Handle(Z);
  Function& setter = Function::Handle(Z);
  Field& class_field = Field::ZoneHandle(Z);
  Instance& init_value = Instance::Handle(Z);
  while (true) {
    bool has_initializer = CurrentToken() == Token::kASSIGN;
    bool has_simple_literal = false;
    if (has_initializer) {
      ConsumeToken();
      init_value = Object::sentinel().raw();
      // For static 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 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 ((LookaheadToken(1) == Token::kSEMICOLON) ||
          (LookaheadToken(1) == Token::kCOMMA)) {
        has_simple_literal = IsSimpleLiteral(*field->type, &init_value);
      }
      SkipExpr();
    } else {
      // Static const and static final fields must have an initializer.
      // Static const fields are implicitly final.
      if (field->has_static && field->has_final) {
        ReportError(field->name_pos,
                    "static %s field '%s' must have an initializer expression",
                    field->has_const ? "const" : "final",
                    field->name->ToCString());
      }
    }

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

    // Start tracking types for fields with simple initializers in their
    // definition. This avoids some of the overhead to track this at runtime
    // and rules out many fields from being unnecessary unboxing candidates.
    if (!field->has_static && has_initializer && has_simple_literal) {
      class_field.RecordStore(init_value);
      if (!init_value.IsNull() && init_value.IsDouble()) {
        class_field.set_is_double_initialized(true);
      }
    }

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

    // For instance fields, we create implicit getter and setter methods.
    if (!field->has_static) {
      String& getter_name =
          String::Handle(Z, Field::GetterSymbol(*field->name));
      getter = Function::New(getter_name, RawFunction::kImplicitGetter,
                             field->has_static,
                             field->has_final,
                             /* is_abstract = */ false,
                             /* is_external = */ false,
                             /* is_native = */ 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);
      getter.set_is_debuggable(false);
      AddFormalParamsToFunction(&params, getter);
      members->AddFunction(getter);
      if (!field->has_final) {
        // Build a setter accessor for non-const fields.
        String& setter_name =
            String::Handle(Z, Field::SetterSymbol(*field->name));
        setter = Function::New(setter_name, RawFunction::kImplicitSetter,
                               field->has_static,
                               field->has_final,
                               /* is_abstract = */ false,
                               /* is_external = */ false,
                               /* is_native = */ 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(Z, Type::VoidType()));
        setter.set_is_debuggable(false);
        if (library_.is_dart_scheme() && library_.IsPrivate(*field->name)) {
          setter.set_is_reflectable(false);
        }
        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.
    ReportError(member.name_pos, "operator %s expects %" Pd " argument(s)",
                member.name->ToCString(), (expected_num_parameters - 1));
  }
}


void Parser::CheckMemberNameConflict(ClassDesc* members,
                                     MemberDesc* member) {
  const String& name = *member->DictName();
  if (name.Equals(members->class_name())) {
    ReportError(member->name_pos,
                "%s '%s' conflicts with class name",
                member->ToCString(),
                name.ToCString());
  }
  if (members->clazz().LookupTypeParameter(name) != TypeParameter::null()) {
    ReportError(member->name_pos,
                "%s '%s' conflicts with type parameter",
                member->ToCString(),
                name.ToCString());
  }
  for (int i = 0; i < members->members().length(); i++) {
    MemberDesc* existing_member = &members->members()[i];
    if (name.Equals(*existing_member->DictName())) {
      ReportError(member->name_pos,
                  "%s '%s' conflicts with previously declared %s",
                  member->ToCString(),
                  name.ToCString(),
                  existing_member->ToCString());
    }
  }
}


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) {
      ReportError("identifier expected after 'const'");
    }
    if (member.has_final) {
      ReportError("identifier expected after 'final'");
    }
    ConsumeToken();
    member.has_var = true;
    // The member type is the 'dynamic' type.
    member.type = &Type::ZoneHandle(Z, Type::DynamicType());
  } else if (CurrentToken() == Token::kFACTORY) {
    ConsumeToken();
    if (member.has_static) {
      ReportError("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) {
      ReportError("void not expected");
    }
    ConsumeToken();
    ASSERT(member.type == NULL);
    member.type = &Type::ZoneHandle(Z, 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(Z,
            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())) {
        ReportError(member.name_pos, "factory name must be '%s'",
                    members->class_name().ToCString());
      }
    } else if (member.has_static) {
      ReportError(member.name_pos, "constructor cannot be static");
    }
    if (member.type != NULL) {
      ReportError(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(Z,
        UnresolvedClass::New(LibraryPrefix::Handle(Z),
                             *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(Z, Type::New(
        result_type_class,
        TypeArguments::Handle(Z, current_class().type_parameters()),
        member.name_pos));

    // We must be dealing with a constructor or named constructor.
    member.kind = RawFunction::kConstructor;
    GrowableHandlePtrArray<const String> to_concat(Z, 3);
    to_concat.Add(*member.name);
    to_concat.Add(Symbols::Dot());
    if (CurrentToken() == Token::kPERIOD) {
      // Named constructor.
      ConsumeToken();
      member.dict_name = ExpectIdentifier("identifier expected");
      to_concat.Add(*member.dict_name);
    }
    *member.name = Symbols::FromConcatAll(to_concat);
    CheckToken(Token::kLPAREN);
  } 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");
    CheckToken(Token::kLPAREN);
    // 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(Z, 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())) {
      ReportError("invalid operator overloading");
    }
    if (member.has_static) {
      ReportError("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(Z, Symbols::New(Token::Str(member.operator_token)));
    ConsumeToken();
  } else if (IsIdentifier()) {
    member.name = CurrentLiteral();
    member.name_pos = TokenPos();
    ConsumeToken();
  } else {
    ReportError("identifier expected");
  }

  ASSERT(member.name != NULL);
  if (CurrentToken() == Token::kLPAREN || member.IsGetter()) {
    // Constructor or method.
    if (member.type == NULL) {
      member.type = &Type::ZoneHandle(Z, 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(Z, Type::DynamicType());
      } else {
        ReportError("missing 'var', 'final', 'const' or type"
                    " in field declaration");
      }
    }
    ParseFieldDefinition(members, &member);
  } else {
    UnexpectedToken();
  }
  current_member_ = NULL;
  CheckMemberNameConflict(members, &member);
  members->AddMember(member);
}


void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes,
                                  const Class& toplevel_class,
                                  intptr_t metadata_pos) {
  TRACE_PARSER("ParseEnumDeclaration");
  const intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos
                                                      : TokenPos();
  ConsumeToken();
  const intptr_t name_pos = TokenPos();
  String* enum_name =
      ExpectUserDefinedTypeIdentifier("enum type name expected");
  if (FLAG_trace_parser) {
    OS::Print("TopLevel parsing enum '%s'\n", enum_name->ToCString());
  }
  ExpectToken(Token::kLBRACE);
  if (!IsIdentifier()) {
    ReportError("Enumeration must have at least one name");
  }
  while (IsIdentifier()) {
    ConsumeToken();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
      if (CurrentToken() == Token::kRBRACE) {
        break;
      }
    } else if (CurrentToken() == Token::kRBRACE) {
      break;
    } else {
      ReportError(", or } expected");
    }
  }
  ExpectToken(Token::kRBRACE);

  Object& obj = Object::Handle(Z, library_.LookupLocalObject(*enum_name));
  if (!obj.IsNull()) {
    ReportError(name_pos, "'%s' is already defined", enum_name->ToCString());
  }
  Class& cls = Class::Handle(Z);
  cls = Class::New(*enum_name, script_, declaration_pos);
  cls.set_library(library_);
  library_.AddClass(cls);
  cls.set_is_synthesized_class();
  cls.set_is_enum_class();
  if (metadata_pos >= 0) {
    library_.AddClassMetadata(cls, toplevel_class, metadata_pos);
  }
  cls.set_super_type(Type::Handle(Z, Type::ObjectType()));
  pending_classes.Add(cls, Heap::kOld);
}


void Parser::ParseClassDeclaration(const GrowableObjectArray& pending_classes,
                                   const Class& toplevel_class,
                                   intptr_t metadata_pos) {
  TRACE_PARSER("ParseClassDeclaration");
  bool is_patch = false;
  bool is_abstract = false;
  intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos : TokenPos();
  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(Z);
  TypeArguments& orig_type_parameters = TypeArguments::Handle(Z);
  Object& obj = Object::Handle(Z, library_.LookupLocalObject(class_name));
  if (obj.IsNull()) {
    if (is_patch) {
      ReportError(classname_pos, "missing class '%s' cannot be patched",
                  class_name.ToCString());
    }
    cls = Class::New(class_name, script_, declaration_pos);
    library_.AddClass(cls);
  } else {
    if (!obj.IsClass()) {
      ReportError(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_, declaration_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::IsImplicitFieldClassId(cls.id()))) {
        ReportError(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(declaration_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(Z, 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) {
      ReportError(classname_pos,
                  "class '%s' must be patched with identical type parameters",
                  class_name.ToCString());
    }
    TypeParameter& new_type_param = TypeParameter::Handle(Z);
    TypeParameter& orig_type_param = TypeParameter::Handle(Z);
    String& new_name = String::Handle(Z);
    String& orig_name = String::Handle(Z);
    AbstractType& new_bound = AbstractType::Handle(Z);
    AbstractType& orig_bound = AbstractType::Handle(Z);
    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)) {
        ReportError(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());
      }
      new_bound = new_type_param.bound();
      orig_bound = orig_type_param.bound();
      if (!new_bound.Equals(orig_bound)) {
        ReportError(new_type_param.token_pos(),
                    "bound '%s' of type parameter '%s' of patch class '%s' "
                    "does not match original type parameter bound '%s'",
                    String::Handle(new_bound.UserVisibleName()).ToCString(),
                    new_name.ToCString(),
                    class_name.ToCString(),
                    String::Handle(orig_bound.UserVisibleName()).ToCString());
      }
    }
    cls.set_type_parameters(orig_type_parameters);
  }

  if (is_abstract) {
    cls.set_is_abstract();
  }
  if (metadata_pos >= 0) {
    library_.AddClassMetadata(cls, toplevel_class, metadata_pos);
  }

  const bool is_mixin_declaration = (CurrentToken() == Token::kASSIGN);
  if (is_mixin_declaration && is_patch) {
    ReportError(classname_pos,
                "mixin application '%s' may not be a patch class",
                class_name.ToCString());
  }

  AbstractType& super_type = Type::Handle(Z);
  if ((CurrentToken() == Token::kEXTENDS) || is_mixin_declaration) {
    ConsumeToken();  // extends or =
    const intptr_t type_pos = TokenPos();
    super_type = ParseType(ClassFinalizer::kResolveTypeParameters);
    if (super_type.IsMalformedOrMalbounded()) {
      ReportError(Error::Handle(Z, super_type.error()));
    }
    if (super_type.IsDynamicType()) {
      // Unlikely here, since super type is not resolved yet.
      ReportError(type_pos,
                  "class '%s' may not extend 'dynamic'",
                  class_name.ToCString());
    }
    if (super_type.IsTypeParameter()) {
      ReportError(type_pos,
                  "class '%s' may not extend type parameter '%s'",
                  class_name.ToCString(),
                  String::Handle(Z,
                                 super_type.UserVisibleName()).ToCString());
    }
    // The class finalizer will check whether the super type is malbounded.
    if (is_mixin_declaration) {
      if (CurrentToken() != Token::kWITH) {
        ReportError("mixin application clause 'with type' expected");
      }
      cls.set_is_mixin_app_alias();
      cls.set_is_synthesized_class();
    }
    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_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 (is_mixin_declaration) {
    ExpectSemicolon();
  } else {
    CheckToken(Token::kLBRACE);
    SkipBlock();
    ExpectToken(Token::kRBRACE);
  }
}


void Parser::ParseClassDefinition(const Class& cls) {
  TRACE_PARSER("ParseClassDefinition");
  INC_STAT(I, num_classes_compiled, 1);
  set_current_class(cls);
  is_top_level_ = true;
  String& class_name = String::Handle(Z, cls.Name());
  SkipMetadata();
  if (is_patch_source() &&
      (CurrentToken() == Token::kIDENT) &&
      CurrentLiteral()->Equals("patch")) {
    ConsumeToken();
  } else if (CurrentToken() == Token::kABSTRACT) {
    ConsumeToken();
  }
  ExpectToken(Token::kCLASS);
  const intptr_t class_pos = TokenPos();
  ClassDesc members(Z, 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();

  cls.AddFields(members.fields());

  // Creating a new array for functions marks the class as parsed.
  Array& array = Array::Handle(Z, members.MakeFunctionsArray());
  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(Z, 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(Z);
    if (!orig_class.ApplyPatch(cls, &error)) {
      Report::LongJumpF(error, script_, class_pos, "applying patch failed");
    }
  }
}


void Parser::ParseEnumDefinition(const Class& cls) {
  TRACE_PARSER("ParseEnumDefinition");
  INC_STAT(I, num_classes_compiled, 1);

  SkipMetadata();
  ExpectToken(Token::kENUM);

  const String& enum_name = String::Handle(Z, cls.Name());
  ClassDesc enum_members(Z, cls, enum_name, false, cls.token_pos());

  // Add instance field 'final int index'.
  Field& index_field = Field::ZoneHandle(Z);
  const Type& int_type = Type::Handle(Z, Type::IntType());
  const Type& dynamic_type = Type::Handle(Type::DynamicType());
  index_field = Field::New(Symbols::Index(),
                           false,  // Not static.
                           true,  // Field is final.
                           false,  // Not const.
                           true,  // Is reflectable.
                           cls,
                           cls.token_pos());
  index_field.set_type(int_type);
  enum_members.AddField(index_field);

  // Add implicit getter for index field.
  const String& getter_name =
      String::Handle(Z, Field::GetterSymbol(Symbols::Index()));
  Function& getter = Function::Handle(Z);
  getter = Function::New(getter_name,
                         RawFunction::kImplicitGetter,
                         /* is_static = */ false,
                         /* is_const = */ true,
                         /* is_abstract = */ false,
                         /* is_external = */ false,
                         /* is_native = */ false,
                         cls,
                         cls.token_pos());
  getter.set_result_type(int_type);
  getter.set_is_debuggable(false);
  ParamList params;
  params.AddReceiver(&dynamic_type, cls.token_pos());
  AddFormalParamsToFunction(&params, getter);
  enum_members.AddFunction(getter);

  GrowableObjectArray& enum_names = GrowableObjectArray::Handle(Z,
      GrowableObjectArray::New(8, Heap::kOld));
  const String& name_prefix =
      String::Handle(String::Concat(enum_name, Symbols::Dot()));

  ASSERT(IsIdentifier());
  ASSERT(CurrentLiteral()->raw() == cls.Name());

  ConsumeToken();  // Enum type name.
  ExpectToken(Token::kLBRACE);
  Field& enum_value = Field::Handle(Z);
  String& enum_value_name = String::Handle(Z);
  intptr_t i = 0;
  GrowableArray<String*> declared_names(8);

  while (IsIdentifier()) {
    String* enum_ident = CurrentLiteral();

    // Check for name conflicts.
    if (enum_ident->raw() == cls.Name()) {
      ReportError("enum identifier '%s' cannot be equal to enum type name",
          CurrentLiteral()->ToCString());
    } else if (enum_ident->raw() == Symbols::Index().raw()) {
      ReportError("enum identifier conflicts with "
                  "implicit instance field 'index'");
    } else if (enum_ident->raw() == Symbols::Values().raw()) {
      ReportError("enum identifier conflicts with "
                  "implicit static field 'values'");
    } else if (enum_ident->raw() == Symbols::toString().raw()) {
      ReportError("enum identifier conflicts with "
                  "implicit instance method 'toString()'");
    }
    for (intptr_t n = 0; n < declared_names.length(); n++) {
      if (enum_ident->Equals(*declared_names[n])) {
        ReportError("Duplicate name '%s' in enum definition '%s'",
                    enum_ident->ToCString(),
                    enum_name.ToCString());
      }
    }
    declared_names.Add(enum_ident);

    // Create the static const field for the enumeration value.
    enum_value = Field::New(*enum_ident,
                            /* is_static = */ true,
                            /* is_final = */ true,
                            /* is_const = */ true,
                            /* is_reflectable = */ true,
                            cls,
                            cls.token_pos());
    enum_value.set_type(dynamic_type);
    enum_value.set_has_initializer(false);
    enum_members.AddField(enum_value);
    // Initialize the field with the ordinal value. It will be patched
    // later with the enum constant instance.
    const Smi& ordinal_value = Smi::Handle(Z, Smi::New(i));
    enum_value.set_value(ordinal_value);
    enum_value.RecordStore(ordinal_value);
    i++;

    // For the user-visible name of the enumeration value, we need to
    // unmangle private names.
    if (enum_ident->CharAt(0) == '_') {
      *enum_ident = String::IdentifierPrettyName(*enum_ident);
    }
    enum_value_name = Symbols::FromConcat(name_prefix, *enum_ident);
    enum_names.Add(enum_value_name, Heap::kOld);

    ConsumeToken();  // Enum value name.
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
    }
  }
  ExpectToken(Token::kRBRACE);

  const Class& helper_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::_EnumHelper()));
  ASSERT(!helper_class.IsNull());

  // Add static field 'const List values'.
  Field& values_field = Field::ZoneHandle(Z);
  values_field = Field::New(Symbols::Values(),
                            /* is_static = */ true,
                            /* is_final = */ true,
                            /* is_const = */ true,
                            /* is_reflectable = */ true,
                            cls,
                            cls.token_pos());
  values_field.set_type(Type::Handle(Z, Type::ArrayType()));
  enum_members.AddField(values_field);

  // Allocate the immutable array containing the enumeration values.
  // The actual enum instance values will be patched in later.
  const Array& values_array = Array::Handle(Z, Array::New(i, Heap::kOld));
  values_field.set_value(values_array);
  values_field.RecordStore(values_array);

  // Create a static field that contains the list of enumeration names.
  // Clone the _enum_names field from the helper class.
  Field& names_field = Field::Handle(Z,
      helper_class.LookupStaticField(Symbols::_EnumNames()));
  ASSERT(!names_field.IsNull());
  names_field = names_field.Clone(cls);
  enum_members.AddField(names_field);
  const Array& names_array = Array::Handle(Array::MakeArray(enum_names));
  names_field.set_value(names_array);
  names_field.RecordStore(names_array);

  // Clone the toString() function from the helper class.
  Function& to_string_func = Function::Handle(Z,
      helper_class.LookupDynamicFunctionAllowPrivate(Symbols::toString()));
  ASSERT(!to_string_func.IsNull());
  to_string_func = to_string_func.Clone(cls);
  enum_members.AddFunction(to_string_func);

  // Clone the hashCode getter function from the helper class.
  Function& hash_code_func = Function::Handle(I,
      helper_class.LookupDynamicFunctionAllowPrivate(Symbols::hashCode()));
  ASSERT(!hash_code_func.IsNull());
  hash_code_func = hash_code_func.Clone(cls);
  enum_members.AddFunction(hash_code_func);

  cls.AddFields(enum_members.fields());
  const Array& functions = Array::Handle(Z, enum_members.MakeFunctionsArray());
  cls.SetFunctions(functions);
}


// 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(Z, cls.Name());
  ctor_name = Symbols::FromConcat(ctor_name, Symbols::Dot());
  // 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(Z,
      Function::New(ctor_name,
                    RawFunction::kConstructor,
                    /* is_static = */ false,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    /* is_external = */ false,
                    /* is_native = */ false,
                    cls,
                    cls.token_pos()));
  ctor.set_end_token_pos(ctor.token_pos());
  ctor.set_is_debuggable(false);
  if (library_.is_dart_scheme() && library_.IsPrivate(ctor_name)) {
    ctor.set_is_reflectable(false);
  }

  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(Z, 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.
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->redirect_name == NULL) {
      continue;
    }
    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) {
          ReportError(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::ParseMixinAppAlias(
    const GrowableObjectArray& pending_classes,
    const Class& toplevel_class,
    intptr_t metadata_pos) {
  TRACE_PARSER("ParseMixinAppAlias");
  const intptr_t classname_pos = TokenPos();
  String& class_name = *ExpectUserDefinedTypeIdentifier("class name expected");
  if (FLAG_trace_parser) {
    OS::Print("toplevel parsing mixin application alias class '%s'\n",
              class_name.ToCString());
  }
  const Object& obj = Object::Handle(Z, library_.LookupLocalObject(class_name));
  if (!obj.IsNull()) {
    ReportError(classname_pos, "'%s' is already defined",
                class_name.ToCString());
  }
  const Class& mixin_application =
      Class::Handle(Z, Class::New(class_name, script_, classname_pos));
  mixin_application.set_is_mixin_app_alias();
  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(Z,
                           ParseType(ClassFinalizer::kResolveTypeParameters));
  if (type.IsTypeParameter()) {
    ReportError(type_pos,
                "class '%s' may not extend type parameter '%s'",
                class_name.ToCString(),
                String::Handle(Z, type.UserVisibleName()).ToCString());
  }

  CheckToken(Token::kWITH, "mixin application 'with Type' expected");
  type = ParseMixins(type);

  mixin_application.set_super_type(type);
  mixin_application.set_is_synthesized_class();

  // This mixin application alias 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);
  if (metadata_pos >= 0) {
    library_.AddClassMetadata(mixin_application, toplevel_class, metadata_pos);
  }
}


// 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 (TryParseTypeParameters() && (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::IsMixinAppAlias() {
  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 (TryParseTypeParameters() && (CurrentToken() == Token::kASSIGN)) {
      is_mixin_def = true;
    }
  }
  SetPosition(saved_pos);
  return is_mixin_def;
}


void Parser::ParseTypedef(const GrowableObjectArray& pending_classes,
                          const Class& toplevel_class,
                          intptr_t metadata_pos) {
  TRACE_PARSER("ParseTypedef");
  intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos : TokenPos();
  ExpectToken(Token::kTYPEDEF);

  if (IsMixinAppAlias()) {
    if (FLAG_warn_mixin_typedef) {
      ReportWarning(TokenPos(), "deprecated mixin application typedef");
    }
    ParseMixinAppAlias(pending_classes, toplevel_class, metadata_pos);
    return;
  }

  // Parse the result type of the function type.
  AbstractType& result_type = Type::Handle(Z, Type::DynamicType());
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    result_type = Type::VoidType();
  } else if (!IsFunctionTypeAliasName()) {
    // Type annotations in typedef are never ignored, even in production 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(Z, library_.LookupLocalObject(*alias_name));
  if (!obj.IsNull()) {
    ReportError(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(Z,
      Class::NewSignatureClass(*alias_name,
                               Function::Handle(Z),
                               script_,
                               declaration_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.
  CheckToken(Token::kLPAREN, "formal parameter list expected");
  ParamList func_params;

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

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

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

  const String& signature = String::Handle(Z,
                                           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(Z, 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);
  if (metadata_pos >= 0) {
    library_.AddClassMetadata(function_type_alias,
                              toplevel_class,
                              metadata_pos);
  }
}


// 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 {
      ReportError("right angle bracket expected");
    }
  }
}


void Parser::SkipType(bool allow_void) {
  if (CurrentToken() == Token::kVOID) {
    if (!allow_void) {
      ReportError("'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) {
    GrowableArray<AbstractType*> type_parameters_array(Z, 2);
    intptr_t index = 0;
    TypeParameter& type_parameter = TypeParameter::Handle(Z);
    TypeParameter& existing_type_parameter = TypeParameter::Handle(Z);
    String& existing_type_parameter_name = String::Handle(Z);
    AbstractType& type_parameter_bound = Type::Handle(Z);
    do {
      ConsumeToken();
      const intptr_t metadata_pos = SkipMetadata();
      const intptr_t type_parameter_pos = TokenPos();
      const intptr_t declaration_pos = (metadata_pos > 0) ? metadata_pos
                                                          : type_parameter_pos;
      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)->raw();
        existing_type_parameter_name = existing_type_parameter.name();
        if (existing_type_parameter_name.Equals(type_parameter_name)) {
          ReportError(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 = I->object_store()->object_type();
      }
      type_parameter = TypeParameter::New(cls,
                                          index,
                                          type_parameter_name,
                                          type_parameter_bound,
                                          declaration_pos);
      type_parameters_array.Add(
          &AbstractType::ZoneHandle(Z, type_parameter.raw()));
      if (metadata_pos >= 0) {
        library_.AddTypeParameterMetadata(type_parameter, metadata_pos);
      }
      index++;
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) || (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ReportError("right angle bracket expected");
    }
    const TypeArguments& type_parameters =
        TypeArguments::Handle(Z,
                              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);
    }
  }
}


RawTypeArguments* Parser::ParseTypeArguments(
    ClassFinalizer::FinalizationKind finalization) {
  TRACE_PARSER("ParseTypeArguments");
  if (CurrentToken() == Token::kLT) {
    GrowableArray<AbstractType*> types;
    AbstractType& type = AbstractType::Handle(Z);
    do {
      ConsumeToken();
      type = ParseType(finalization);
      // Map a malformed type argument to dynamic.
      if (type.IsMalformed()) {
        type = Type::DynamicType();
      }
      types.Add(&AbstractType::ZoneHandle(Z, type.raw()));
    } while (CurrentToken() == Token::kCOMMA);
    Token::Kind token = CurrentToken();
    if ((token == Token::kGT) || (token == Token::kSHR)) {
      ConsumeRightAngleBracket();
    } else {
      ReportError("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(Z, GrowableObjectArray::New());
  AbstractType& interface = AbstractType::Handle(Z);
  // First get all the interfaces already implemented by class.
  Array& cls_interfaces = Array::Handle(Z, 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()) {
      ReportError(interface_pos,
                  "type parameter '%s' may not be used in interface list",
                  String::Handle(Z, 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_types =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
  AbstractType& mixin_type = AbstractType::Handle(Z);
  do {
    ConsumeToken();
    mixin_type = ParseType(ClassFinalizer::kResolveTypeParameters);
    if (mixin_type.IsDynamicType()) {
      // The string 'dynamic' is not resolved yet at this point, but a malformed
      // type mapped to dynamic can be encountered here.
      ReportError(mixin_type.token_pos(), "illegal mixin of a malformed type");
    }
    if (mixin_type.IsTypeParameter()) {
      ReportError(mixin_type.token_pos(),
                  "mixin type '%s' may not be a type parameter",
                  String::Handle(Z, mixin_type.UserVisibleName()).ToCString());
    }
    mixin_types.Add(mixin_type);
  } while (CurrentToken() == Token::kCOMMA);
  return MixinAppType::New(super_type,
      Array::Handle(Z, Array::MakeArray(mixin_types)));
}


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(Z,
      ParseConstFinalVarOrType(ClassFinalizer::kResolveTypeParameters));
  Field& field = Field::Handle(Z);
  Function& getter = Function::Handle(Z);
  while (true) {
    const intptr_t name_pos = TokenPos();
    String& var_name = *ExpectIdentifier("variable name expected");

    if (library_.LookupLocalObject(var_name) != Object::null()) {
      ReportError(name_pos, "'%s' is already defined", var_name.ToCString());
    }

    // Check whether a getter or setter for this name exists. A const
    // or final field implies a setter which throws a NoSuchMethodError,
    // thus we need to check for conflicts with existing setters and
    // getters.
    String& accessor_name = String::Handle(Z, Field::GetterName(var_name));
    if (library_.LookupLocalObject(accessor_name) != Object::null()) {
      ReportError(name_pos, "getter for '%s' is already defined",
                  var_name.ToCString());
    }
    accessor_name = Field::SetterName(var_name);
    if (library_.LookupLocalObject(accessor_name) != Object::null()) {
      ReportError(name_pos, "setter for '%s' is already defined",
                  var_name.ToCString());
    }

    const bool is_reflectable =
        !(library_.is_dart_scheme() && library_.IsPrivate(var_name));
    field = Field::New(var_name, is_static, is_final, is_const, is_reflectable,
                       current_class(), name_pos);
    field.set_type(type);
    field.set_value(Object::null_instance());
    top_level->AddField(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(Z, Object::sentinel().raw());
      bool has_simple_literal = false;
      if (LookaheadToken(1) == Token::kSEMICOLON) {
        has_simple_literal = IsSimpleLiteral(type, &field_value);
      }
      SkipExpr();
      field.set_value(field_value);
      field.set_has_initializer(true);

      if (!has_simple_literal) {
        // Create a static final getter.
        String& getter_name = String::Handle(Z, Field::GetterSymbol(var_name));
        getter = Function::New(getter_name,
                               RawFunction::kImplicitStaticFinalGetter,
                               is_static,
                               is_const,
                               /* is_abstract = */ false,
                               /* is_external = */ false,
                               /* is_native = */ false,
                               current_class(),
                               name_pos);
        getter.set_result_type(type);
        getter.set_is_debuggable(false);
        if (library_.is_dart_scheme() && library_.IsPrivate(var_name)) {
          getter.set_is_reflectable(false);
        }
        top_level->AddFunction(getter);
      }
    } else if (is_final) {
      ReportError(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.
    }
  }
}


RawFunction::AsyncModifier Parser::ParseFunctionModifier() {
  if (IsSymbol(Symbols::Async())) {
    ConsumeToken();
    if (CurrentToken() == Token::kMUL) {
      const bool enableAsyncStar = true;
      if (!enableAsyncStar) {
        ReportError("async* generator functions are not yet supported");
      }
      ConsumeToken();
      return RawFunction::kAsyncGen;
    } else {
      return RawFunction::kAsync;
    }
  } else if (IsSymbol(Symbols::Sync()) &&
      (LookaheadToken(1) == Token::kMUL)) {
    const bool enableSyncStar = true;
    if (!enableSyncStar) {
      ReportError("sync* generator functions are not yet supported");
    }
    ConsumeToken();
    ConsumeToken();
    return RawFunction::kSyncGen;
  }
  return RawFunction::kNoModifier;
}


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(Z, 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) {
    ReportError(name_pos, "'%s' is already defined", func_name.ToCString());
  } else if (!found && is_patch) {
    ReportError(name_pos, "missing '%s' cannot be patched",
                func_name.ToCString());
  }
  String& accessor_name = String::Handle(Z, Field::GetterName(func_name));
  if (library_.LookupLocalObject(accessor_name) != Object::null()) {
    ReportError(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.

  CheckToken(Token::kLPAREN);
  const intptr_t function_pos = TokenPos();
  ParamList params;
  const bool allow_explicit_default_values = true;
  ParseFormalParameterList(allow_explicit_default_values, false, &params);

  const intptr_t modifier_pos = TokenPos();
  RawFunction::AsyncModifier func_modifier = ParseFunctionModifier();

  intptr_t function_end_pos = function_pos;
  bool is_native = false;
  if (is_external) {
    function_end_pos = TokenPos();
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
    function_end_pos = TokenPos();
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kARROW) {
    if ((func_modifier & RawFunction::kGeneratorBit) != 0) {
      ReportError(modifier_pos,
                  "=> style function may not be sync* or async* generator");
    }
    ConsumeToken();
    BoolScope allow_await(&this->await_is_keyword_,
                          func_modifier != RawFunction::kNoModifier);
    SkipExpr();
    function_end_pos = TokenPos();
    ExpectSemicolon();
  } else if (IsSymbol(Symbols::Native())) {
    ParseNativeDeclaration();
    function_end_pos = TokenPos();
    ExpectSemicolon();
    is_native = true;
  } else {
    ReportError("function block expected");
  }
  Function& func = Function::Handle(Z,
      Function::New(func_name,
                    RawFunction::kRegularFunction,
                    is_static,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    is_external,
                    is_native,
                    current_class(),
                    decl_begin_pos));
  func.set_result_type(result_type);
  func.set_end_token_pos(function_end_pos);
  func.set_modifier(func_modifier);
  if (library_.is_dart_scheme() && library_.IsPrivate(func_name)) {
    func.set_is_reflectable(false);
  }
  AddFormalParamsToFunction(&params, func);
  top_level->AddFunction(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(Z);
  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, false, &params);
  }
  String& accessor_name = String::ZoneHandle(Z);
  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)) {
    ReportError(name_pos, "illegal %s parameters",
                is_getter ? "getter" : "setter");
  }

  // Check whether this getter conflicts with a function or top-level variable
  // with the same name.
  if (is_getter &&
      (library_.LookupLocalObject(*field_name) != Object::null())) {
    ReportError(name_pos, "'%s' is already defined in this library",
                field_name->ToCString());
  }
  // Check whether this setter conflicts with the implicit setter
  // of a top-level variable with the same name.
  if (!is_getter &&
      (library_.LookupLocalField(*field_name) != Object::null())) {
    ReportError(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) {
    ReportError(name_pos, "%s for '%s' is already defined",
                is_getter ? "getter" : "setter",
                field_name->ToCString());
  } else if (!found && is_patch) {
    ReportError(name_pos, "missing %s for '%s' cannot be patched",
                is_getter ? "getter" : "setter",
                field_name->ToCString());
  }

  const intptr_t modifier_pos = TokenPos();
  RawFunction::AsyncModifier func_modifier = ParseFunctionModifier();
  if (!is_getter && (func_modifier != RawFunction::kNoModifier)) {
    ReportError(modifier_pos,
                "setter function cannot be async, async* or sync*");
  }

  intptr_t accessor_end_pos = accessor_pos;
  bool is_native = false;
  if (is_external) {
    accessor_end_pos = TokenPos();
    ExpectSemicolon();
  } else if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
    accessor_end_pos = TokenPos();
    ExpectToken(Token::kRBRACE);
  } else if (CurrentToken() == Token::kARROW) {
    if (is_getter && ((func_modifier & RawFunction::kGeneratorBit) != 0)) {
      ReportError(modifier_pos,
                  "=> style getter may not be sync* or async* generator");
    }
    ConsumeToken();
    BoolScope allow_await(&this->await_is_keyword_,
                          func_modifier != RawFunction::kNoModifier);
    SkipExpr();
    accessor_end_pos = TokenPos();
    ExpectSemicolon();
  } else if (IsSymbol(Symbols::Native())) {
    ParseNativeDeclaration();
    accessor_end_pos = TokenPos();
    ExpectSemicolon();
    is_native = true;
  } else {
    ReportError("function block expected");
  }
  Function& func = Function::Handle(Z,
      Function::New(accessor_name,
                    is_getter ? RawFunction::kGetterFunction :
                                RawFunction::kSetterFunction,
                    is_static,
                    /* is_const = */ false,
                    /* is_abstract = */ false,
                    is_external,
                    is_native,
                    current_class(),
                    decl_begin_pos));
  func.set_result_type(result_type);
  func.set_end_token_pos(accessor_end_pos);
  func.set_modifier(func_modifier);
  if (is_native) {
    func.set_is_debuggable(false);
  }
  if (library_.is_dart_scheme() && library_.IsPrivate(accessor_name)) {
    func.set_is_reflectable(false);
  }
  AddFormalParamsToFunction(&params, func);
  top_level->AddFunction(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 = I->library_tag_handler();
  if (handler == NULL) {
    if (url.StartsWith(Symbols::DartScheme())) {
      if (tag == Dart_kCanonicalizeUrl) {
        return url.raw();
      }
      return Object::null();
    }
    ReportError(token_pos, "no library handler registered");
  }
  // Block class finalization attempts when calling into the library
  // tag handler.
  I->BlockClassFinalization();
  Api::Scope api_scope(I);
  Dart_Handle result = handler(tag,
                               Api::NewHandle(I, library_.raw()),
                               Api::NewHandle(I, url.raw()));
  I->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(Z);
    prev_error ^= Api::UnwrapHandle(result);
    Report::LongJumpF(prev_error, script_, token_pos, "library handler failed");
  }
  if (tag == Dart_kCanonicalizeUrl) {
    if (!Dart_IsString(result)) {
      ReportError(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()) {
    ReportError("identifier expected");
  }
  while (IsIdentifier()) {
    names->Add(*CurrentLiteral());
    ConsumeToken();  // Identifier.
    if (CurrentToken() != Token::kCOMMA) {
      return;
    }
    ConsumeToken();  // Comma.
  }
}


void Parser::ParseLibraryImportExport(intptr_t metadata_pos) {
  bool is_import = (CurrentToken() == Token::kIMPORT);
  bool is_export = (CurrentToken() == Token::kEXPORT);
  ASSERT(is_import || is_export);
  const intptr_t import_pos = TokenPos();
  ConsumeToken();
  CheckToken(Token::kSTRING, "library url expected");
  AstNode* url_literal = ParseStringLiteral(false);
  ASSERT(url_literal->IsLiteralNode());
  ASSERT(url_literal->AsLiteralNode()->literal().IsString());
  const String& url = String::Cast(url_literal->AsLiteralNode()->literal());
  if (url.Length() == 0) {
    ReportError("library url expected");
  }
  bool is_deferred_import = false;
  if (is_import && (IsSymbol(Symbols::Deferred()))) {
    is_deferred_import = true;
    ConsumeToken();
    CheckToken(Token::kAS, "'as' expected");
  }
  String& prefix = String::Handle(Z);
  intptr_t prefix_pos = 0;
  if (is_import && (CurrentToken() == Token::kAS)) {
    ConsumeToken();
    prefix_pos = TokenPos();
    prefix = ExpectIdentifier("prefix identifier expected")->raw();
  }

  Array& show_names = Array::Handle(Z);
  Array& hide_names = Array::Handle(Z);
  if (is_deferred_import ||
      IsSymbol(Symbols::Show()) ||
      IsSymbol(Symbols::Hide())) {
    GrowableObjectArray& show_list =
        GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
    GrowableObjectArray& hide_list =
        GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
    // Libraries imported through deferred import automatically hide
    // the name 'loadLibrary'.
    if (is_deferred_import) {
      hide_list.Add(Symbols::LoadLibrary());
    }
    for (;;) {
      if (IsSymbol(Symbols::Show())) {
        ConsumeToken();
        ParseIdentList(&show_list);
      } else if (IsSymbol(Symbols::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));

  // Create a new library if it does not exist yet.
  Library& library = Library::Handle(Z, Library::LookupLibrary(canon_url));
  if (library.IsNull()) {
    library = Library::New(canon_url);
    library.Register();
  }

  // If loading hasn't been requested yet, and if this is not a deferred
  // library import, call the library tag handler to request loading
  // the library.
  if (library.LoadNotStarted() &&
      (!is_deferred_import || FLAG_load_deferred_eagerly)) {
    library.SetLoadRequested();
    CallLibraryTagHandler(Dart_kImportTag, import_pos, canon_url);
  }

  Namespace& ns = Namespace::Handle(Z,
      Namespace::New(library, show_names, hide_names));
  if (metadata_pos >= 0) {
    ns.AddMetadata(metadata_pos, current_class());
  }

  // Ensure that private dart:_ libraries are only imported into dart:
  // libraries, including indirectly through exports.
  const String& lib_url = String::Handle(Z, library_.url());
  if (canon_url.StartsWith(Symbols::DartSchemePrivate()) &&
      !lib_url.StartsWith(Symbols::DartScheme())) {
    ReportError(import_pos, "private library is not accessible");
  }

  if (!FLAG_enable_mirrors && Symbols::DartMirrors().Equals(canon_url)) {
    ReportError(import_pos,
                "import of dart:mirrors with --enable-mirrors=false");
  }

  if (is_import) {
    if (prefix.IsNull() || (prefix.Length() == 0)) {
      ASSERT(!is_deferred_import);
      library_.AddImport(ns);
    } else {
      LibraryPrefix& library_prefix = LibraryPrefix::Handle(Z);
      library_prefix = library_.LookupLocalLibraryPrefix(prefix);
      if (!library_prefix.IsNull()) {
        // Check that prefix names of deferred import clauses are
        // unique.
        if (!is_deferred_import && library_prefix.is_deferred_load()) {
          ReportError(prefix_pos,
                      "prefix '%s' already used in a deferred import clause",
                      prefix.ToCString());
        }
        if (is_deferred_import) {
          ReportError(prefix_pos, "prefix of deferred import must be unique");
        }
        library_prefix.AddImport(ns);
      } else {
        library_prefix =
            LibraryPrefix::New(prefix, ns, is_deferred_import, library_);
        library_.AddObject(library_prefix, prefix);
      }
    }
  } else {
    ASSERT(is_export);
    library_.AddExport(ns);
  }
}


void Parser::ParseLibraryPart() {
  const intptr_t source_pos = TokenPos();
  ConsumeToken();  // Consume "part".
  CheckToken(Token::kSTRING, "url expected");
  AstNode* url_literal = ParseStringLiteral(false);
  ASSERT(url_literal->IsLiteralNode());
  ASSERT(url_literal->AsLiteralNode()->literal().IsString());
  const String& url = String::Cast(url_literal->AsLiteralNode()->literal());
  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()) {
      ReportError("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(metadata_pos);
    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(Z, Library::CoreLibrary());
    ASSERT(!core_lib.IsNull());
    const Namespace& core_ns = Namespace::Handle(Z,
        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();
  CheckToken(Token::kPART, "'part of' expected");
  ConsumeToken();
  if (!IsSymbol(Symbols::Of())) {
    ReportError("'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 = I->object_store();
  const GrowableObjectArray& pending_classes =
      GrowableObjectArray::Handle(Z, object_store->pending_classes());
  SetPosition(0);
  is_top_level_ = true;
  TopLevel top_level(Z);
  Class& toplevel_class = Class::Handle(Z,
      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(Z);
  while (true) {
    set_current_class(cls);  // No current class.
    intptr_t metadata_pos = SkipMetadata();
    if (CurrentToken() == Token::kCLASS) {
      ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos);
    } else if (CurrentToken() == Token::kENUM) {
      ParseEnumDeclaration(pending_classes, toplevel_class, metadata_pos);
    } else if ((CurrentToken() == Token::kTYPEDEF) &&
               (LookaheadToken(1) != Token::kLPAREN)) {
      set_current_class(toplevel_class);
      ParseTypedef(pending_classes, toplevel_class, metadata_pos);
    } else if ((CurrentToken() == Token::kABSTRACT) &&
        (LookaheadToken(1) == Token::kCLASS)) {
      ParseClassDeclaration(pending_classes, toplevel_class, metadata_pos);
    } else if (is_patch_source() && IsSymbol(Symbols::Patch()) &&
               (LookaheadToken(1) == Token::kCLASS)) {
      ParseClassDeclaration(pending_classes, toplevel_class, 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 ((library_.num_anonymous_classes() == 0) ||
      (top_level.fields().length() > 0) ||
      (top_level.functions().length() > 0)) {
    toplevel_class.AddFields(top_level.fields());
    const intptr_t len = top_level.functions().length();
    const Array& array = Array::Handle(Z, Array::New(len, Heap::kOld));
    for (intptr_t i = 0; i < len; i++) {
      array.SetAt(i, *top_level.functions()[i]);
    }
    toplevel_class.SetFunctions(array);
    library_.AddAnonymousClass(toplevel_class);
    pending_classes.Add(toplevel_class, Heap::kOld);
  }
}


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


void Parser::OpenBlock() {
  ASSERT(current_block_ != NULL);
  LocalScope* outer_scope = current_block_->scope;
  ChainNewBlock(new(Z) 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(Z) 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(Z) 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(Z, func.context_scope());
      ASSERT(!context_scope.IsNull());
      outer_scope = new(Z) LocalScope(
          LocalScope::RestoreOuterScope(context_scope), 0, 0);
    }
  } else {
    // We are parsing a nested function while compiling the enclosing function.
    outer_scope =
        new(Z) LocalScope(current_block_->scope,
                                  current_block_->scope->function_level() + 1,
                                  0);
  }
  ChainNewBlock(outer_scope);
}


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

  async_temp_scope_ = current_block_->scope;

  OpenAsyncTryBlock();
}


SequenceNode* Parser::CloseAsyncGeneratorTryBlock(SequenceNode *body) {
  TRACE_PARSER("CloseAsyncGeneratorTryBlock");
  // The generated try-catch-finally that wraps the async generator function
  // body is the outermost try statement.
  ASSERT(try_stack_ != NULL);
  ASSERT(try_stack_->outer_try() == NULL);
  // We only get here when parsing an async generator body.
  ASSERT(innermost_function().IsAsyncGenClosure());

  const intptr_t try_end_pos = innermost_function().end_token_pos();

  // The try-block (closure body code) has been parsed. We are now
  // generating the code for the catch block.
  LocalScope* try_scope = current_block_->scope;
  try_stack_->enter_catch();
  OpenBlock();  // Catch handler list.
  OpenBlock();  // Catch block.

  // Add the exception and stack trace parameters to the scope.
  const AbstractType& dynamic_type =
      AbstractType::ZoneHandle(Z, Type::DynamicType());
  CatchParamDesc exception_param;
  CatchParamDesc stack_trace_param;
  exception_param.token_pos = Scanner::kNoSourcePos;
  exception_param.type = &dynamic_type;
  exception_param.name = &Symbols::ExceptionParameter();
  stack_trace_param.token_pos = Scanner::kNoSourcePos;
  stack_trace_param.type = &dynamic_type;
  stack_trace_param.name = &Symbols::StackTraceParameter();

  AddCatchParamsToScope(
      &exception_param, &stack_trace_param, current_block_->scope);

  // Generate code to save the exception object and stack trace
  // in local variables.
  LocalVariable* context_var = try_scope->LocalLookupVariable(
      Symbols::SavedTryContextVar());
  ASSERT(context_var != NULL);

  LocalVariable* exception_var = try_scope->LocalLookupVariable(
      Symbols::ExceptionVar());
  ASSERT(exception_var != NULL);
  if (exception_param.var != NULL) {
    // Generate code to load the exception object (:exception_var) into
    // the exception variable specified in this block.
    current_block_->statements->Add(new(Z) StoreLocalNode(
        Scanner::kNoSourcePos,
        exception_param.var,
        new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
  }

  LocalVariable* stack_trace_var =
      try_scope->LocalLookupVariable(Symbols::StackTraceVar());
  ASSERT(stack_trace_var != NULL);
  if (stack_trace_param.var != NULL) {
    // A stack trace variable is specified in this block, so generate code
    // to load the stack trace object (:stack_trace_var) into the stack
    // trace variable specified in this block.
    current_block_->statements->Add(new(Z) StoreLocalNode(
        Scanner::kNoSourcePos,
        stack_trace_param.var,
        new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
  }
  LocalVariable* saved_exception_var = try_scope->LocalLookupVariable(
      Symbols::SavedExceptionVar());
  LocalVariable* saved_stack_trace_var = try_scope->LocalLookupVariable(
      Symbols::SavedStackTraceVar());
  SaveExceptionAndStacktrace(current_block_->statements,
                             exception_var,
                             stack_trace_var,
                             saved_exception_var,
                             saved_stack_trace_var);

  // Catch block: add the error to the stream.
  // :controller.AddError(:exception, :stack_trace);
  // return;  // The finally block will close the stream.
  LocalVariable* controller =
      current_block_->scope->LookupVariable(Symbols::Controller(), false);
  ASSERT(controller != NULL);
  ArgumentListNode* args =
      new(Z) ArgumentListNode(Scanner::kNoSourcePos);
  args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
  args->Add(new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
  current_block_->statements->Add(
      new(Z) InstanceCallNode(try_end_pos,
          new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
          Symbols::AddError(),
          args));
  ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos);
  AddNodeForFinallyInlining(return_node);
  current_block_->statements->Add(return_node);
  AstNode* catch_block = CloseBlock();
  current_block_->statements->Add(catch_block);
  SequenceNode* catch_handler_list = CloseBlock();

  TryStack* try_statement = PopTry();
  ASSERT(try_stack_ == NULL);  // We popped the outermost try block.

  // Finally block: closing the stream and returning. Instead of simply
  // returning, create an await state and suspend. There may be outstanding
  // calls to schedule the generator body. This suspension ensures that we
  // do not repeat any code of the generator body.
  // :controller.close();
  // suspend;
  // We need to inline this code in all recorded exit points.
  intptr_t node_index = 0;
  SequenceNode* finally_clause = NULL;
  if (try_stack_ != NULL) {
    try_stack_->enter_finally();
  }
  do {
    OpenBlock();
    ArgumentListNode* no_args =
        new(Z) ArgumentListNode(Scanner::kNoSourcePos);
    current_block_->statements->Add(
        new(Z) InstanceCallNode(try_end_pos,
            new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller),
            Symbols::Close(),
            no_args));

    // Suspend after the close.
    AwaitMarkerNode* await_marker =
        new(Z) AwaitMarkerNode(async_temp_scope_, current_block_->scope);
    current_block_->statements->Add(await_marker);
    ReturnNode* continuation_ret = new(Z) ReturnNode(try_end_pos);
    continuation_ret->set_return_type(ReturnNode::kContinuationTarget);
    current_block_->statements->Add(continuation_ret);

    finally_clause = CloseBlock();
    AstNode* node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
    if (node_to_inline != NULL) {
      InlinedFinallyNode* node =
          new(Z) InlinedFinallyNode(try_end_pos,
                                    finally_clause,
                                    context_var,
                                    // No outer try statement
                                    CatchClauseNode::kInvalidTryIndex);
      finally_clause = NULL;
      AddFinallyClauseToNode(true, node_to_inline, node);
      node_index++;
    }
  } while (finally_clause == NULL);

  if (try_stack_ != NULL) {
    try_stack_->exit_finally();
  }

  const GrowableObjectArray& handler_types =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
  handler_types.Add(dynamic_type);  // Catch block handles all exceptions.

  CatchClauseNode* catch_clause = new(Z) CatchClauseNode(
      Scanner::kNoSourcePos,
      catch_handler_list,
      Array::ZoneHandle(Z, Array::MakeArray(handler_types)),
      context_var,
      exception_var,
      stack_trace_var,
      saved_exception_var,
      saved_stack_trace_var,
      AllocateTryIndex(),
      true);

  const intptr_t try_index = try_statement->try_index();

  AstNode* try_catch_node =
      new(Z) TryCatchNode(Scanner::kNoSourcePos,
                          body,
                          context_var,
                          catch_clause,
                          finally_clause,
                          try_index);
  current_block_->statements->Add(try_catch_node);
  return CloseBlock();
}


SequenceNode* Parser::CloseAsyncTryBlock(SequenceNode* try_block) {
  // This is the outermost try-catch of the function.
  ASSERT(try_stack_ != NULL);
  ASSERT(try_stack_->outer_try() == NULL);
  ASSERT(innermost_function().IsAsyncClosure());
  LocalScope* try_scope = current_block_->scope;

  try_stack_->enter_catch();

  OpenBlock();  // Catch handler list.
  OpenBlock();  // Catch block.
  const AbstractType& dynamic_type =
      AbstractType::ZoneHandle(Z, Type::DynamicType());
  CatchParamDesc exception_param;
  CatchParamDesc stack_trace_param;
  exception_param.token_pos = Scanner::kNoSourcePos;
  exception_param.type = &dynamic_type;
  exception_param.name = &Symbols::ExceptionParameter();
  stack_trace_param.token_pos = Scanner::kNoSourcePos;
  stack_trace_param.type = &dynamic_type;
  stack_trace_param.name = &Symbols::StackTraceParameter();

  AddCatchParamsToScope(
      &exception_param, &stack_trace_param, current_block_->scope);

  LocalVariable* context_var = try_scope->LocalLookupVariable(
      Symbols::SavedTryContextVar());
  ASSERT(context_var != NULL);

  LocalVariable* exception_var = try_scope->LocalLookupVariable(
      Symbols::ExceptionVar());
  if (exception_param.var != NULL) {
    // Generate code to load the exception object (:exception_var) into
    // the exception variable specified in this block.
    ASSERT(exception_var != NULL);
    current_block_->statements->Add(new(Z) StoreLocalNode(
        Scanner::kNoSourcePos,
        exception_param.var,
        new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));
  }

  LocalVariable* stack_trace_var =
      try_scope->LocalLookupVariable(Symbols::StackTraceVar());
  if (stack_trace_param.var != NULL) {
    // A stack trace variable is specified in this block, so generate code
    // to load the stack trace object (:stack_trace_var) into the stack
    // trace variable specified in this block.
    ASSERT(stack_trace_var != NULL);
    current_block_->statements->Add(new(Z) StoreLocalNode(
        Scanner::kNoSourcePos,
        stack_trace_param.var,
        new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
  }
  LocalVariable* saved_exception_var = try_scope->LocalLookupVariable(
      Symbols::SavedExceptionVar());
  LocalVariable* saved_stack_trace_var = try_scope->LocalLookupVariable(
      Symbols::SavedStackTraceVar());
  SaveExceptionAndStacktrace(current_block_->statements,
                             exception_var,
                             stack_trace_var,
                             saved_exception_var,
                             saved_stack_trace_var);

  // Complete the async future with an error. This catch block executes
  // unconditionally, there is no need to generate a type check for.
  LocalVariable* async_completer = current_block_->scope->LookupVariable(
      Symbols::AsyncCompleter(), false);
  ASSERT(async_completer != NULL);
  ArgumentListNode* completer_args =
      new (Z) ArgumentListNode(Scanner::kNoSourcePos);
  completer_args->Add(
      new (Z) LoadLocalNode(Scanner::kNoSourcePos, exception_param.var));
  completer_args->Add(
      new (Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_param.var));
  current_block_->statements->Add(new (Z) InstanceCallNode(
      TokenPos(),
      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_completer),
      Symbols::CompleterCompleteError(),
      completer_args));
  ReturnNode* return_node = new (Z) ReturnNode(Scanner::kNoSourcePos);
  // Behavior like a continuation return, i.e,. don't call a completer.
  return_node->set_return_type(ReturnNode::kContinuation);
  current_block_->statements->Add(return_node);
  AstNode* catch_block = CloseBlock();
  current_block_->statements->Add(catch_block);
  SequenceNode* catch_handler_list = CloseBlock();

  const GrowableObjectArray& handler_types =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
  handler_types.SetLength(0);
  handler_types.Add(*exception_param.type);

  TryStack* try_statement = PopTry();
  const intptr_t try_index = try_statement->try_index();

  CatchClauseNode* catch_clause = new (Z) CatchClauseNode(
      Scanner::kNoSourcePos,
      catch_handler_list,
      Array::ZoneHandle(Z, Array::MakeArray(handler_types)),
      context_var,
      exception_var,
      stack_trace_var,
      saved_exception_var,
      saved_stack_trace_var,
      CatchClauseNode::kInvalidTryIndex,
      true);
  AstNode* try_catch_node = new (Z) TryCatchNode(
      Scanner::kNoSourcePos,
      try_block,
      context_var,
      catch_clause,
      NULL,  // No finally clause.
      try_index);
  current_block_->statements->Add(try_catch_node);
  return CloseBlock();
}


// Wrap the body of the async or async* closure in a try/catch block.
void Parser::OpenAsyncTryBlock() {
  ASSERT(innermost_function().IsAsyncClosure() ||
         innermost_function().IsAsyncGenClosure());
  LocalVariable* context_var = NULL;
  LocalVariable* exception_var = NULL;
  LocalVariable* stack_trace_var = NULL;
  LocalVariable* saved_exception_var = NULL;
  LocalVariable* saved_stack_trace_var = NULL;
  SetupExceptionVariables(current_block_->scope,
                          true,
                          &context_var,
                          &exception_var,
                          &stack_trace_var,
                          &saved_exception_var,
                          &saved_stack_trace_var);

  // Open the try block.
  OpenBlock();
  // This is the outermost try-catch in the function.
  ASSERT(try_stack_ == NULL);
  PushTry(current_block_);

  SetupSavedTryContext(context_var);
}


void Parser::AddSyncGenClosureParameters(ParamList* params) {
  // Create the parameter list for the body closure of a sync generator:
  // 1) Implicit closure parameter;
  // 2) Iterator
  const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
  // Add implicit closure parameter if not already present.
  if (params->parameters->length() == 0) {
    params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type);
  }
  ParamDesc iterator_param;
  iterator_param.name = &Symbols::IteratorParameter();
  iterator_param.type = &dynamic_type;
  params->parameters->Add(iterator_param);
  params->num_fixed_parameters++;
}


void Parser::AddAsyncGenClosureParameters(ParamList* params) {
  // Create the parameter list for the body closure of an async generator.
  // The closure has the same parameters as an asynchronous non-generator.
  AddAsyncClosureParameters(params);
}


RawFunction* Parser::OpenSyncGeneratorFunction(intptr_t func_pos) {
  Function& body = Function::Handle(Z);
  String& body_closure_name = String::Handle(Z);
  bool is_new_closure = false;

  AddContinuationVariables();

  // Check whether a function for the body of this generator
  // function has already been created by a previous
  // compilation.
  const Function& found_func = Function::Handle(
      Z, current_class().LookupClosureFunction(func_pos));
  if (!found_func.IsNull() &&
      (found_func.token_pos() == func_pos) &&
      (found_func.script() == innermost_function().script()) &&
      (found_func.parent_function() == innermost_function().raw())) {
    ASSERT(found_func.IsSyncGenClosure());
    body = found_func.raw();
    body_closure_name = body.name();
  } else {
    // Create the closure containing the body of this generator function.
    String& generator_name = String::Handle(Z, innermost_function().name());
    body_closure_name =
        String::NewFormatted("<%s_sync_body>", generator_name.ToCString());
    body_closure_name = Symbols::New(body_closure_name);
    body = Function::NewClosureFunction(body_closure_name,
                                        innermost_function(),
                                        func_pos);
    body.set_is_generated_body(true);
    body.set_result_type(AbstractType::Handle(Type::DynamicType()));
    is_new_closure = true;
  }

  ParamList closure_params;
  AddSyncGenClosureParameters(&closure_params);

  if (is_new_closure) {
    // Add the parameters to the newly created closure.
    AddFormalParamsToFunction(&closure_params, body);

    // Create and set the signature class of the closure.
    const String& sig = String::Handle(Z, body.Signature());
    Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
    if (sig_cls.IsNull()) {
      sig_cls = Class::NewSignatureClass(sig, body, script_, body.token_pos());
      library_.AddClass(sig_cls);
    }
    body.set_signature_class(sig_cls);
    // Finalize types in signature class here, so that the
    // signature type is not computed twice.
    ClassFinalizer::FinalizeTypesInClass(sig_cls);
    const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
    ASSERT(sig_type.IsFinalized());
    ASSERT(AbstractType::Handle(Z, body.result_type()).IsResolved());
    ASSERT(body.NumParameters() == closure_params.parameters->length());
  }

  OpenFunctionBlock(body);
  AddFormalParamsToScope(&closure_params, current_block_->scope);
  async_temp_scope_ = current_block_->scope;
  return body.raw();
}

SequenceNode* Parser::CloseSyncGenFunction(const Function& closure,
                                           SequenceNode* closure_body) {
  // Explicitly reference variables of the sync generator function from the
  // closure body in order to mark them as captured.
  LocalVariable* existing_var =
      closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var =
      closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());

  // :await_jump_var = -1;
  LocalVariable* jump_var =
      current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
  LiteralNode* init_value =
      new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
  current_block_->statements->Add(
      new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));

  // return new SyncIterable(body_closure);
  const Class& iterable_class =
      Class::Handle(Z, Library::LookupCoreClass(Symbols::_SyncIterable()));
  ASSERT(!iterable_class.IsNull());
  const Function& iterable_constructor = Function::ZoneHandle(Z,
      iterable_class.LookupConstructorAllowPrivate(
          Symbols::_SyncIterableConstructor()));
  ASSERT(!iterable_constructor.IsNull());

  const String& closure_name = String::Handle(Z, closure.name());
  ASSERT(closure_name.IsSymbol());

  ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
  ClosureNode* closure_obj = new(Z) ClosureNode(
      Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
  arguments->Add(closure_obj);
  ConstructorCallNode* new_iterable =
      new(Z) ConstructorCallNode(Scanner::kNoSourcePos,
          TypeArguments::ZoneHandle(Z),
          iterable_constructor,
          arguments);
  ReturnNode* return_node =
      new (Z) ReturnNode(Scanner::kNoSourcePos, new_iterable);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


void Parser::AddAsyncClosureParameters(ParamList* params) {
  // Async closures have three optional parameters:
  // * A continuation result.
  // * A continuation error.
  // * A continuation stack trace.
  const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
  ASSERT(params->parameters->length() <= 1);
  // Add implicit closure parameter if not yet present.
  if (params->parameters->length() == 0) {
    params->AddFinalParameter(0, &Symbols::ClosureParameter(), &dynamic_type);
  }
  ParamDesc result_param;
  result_param.name = &Symbols::AsyncOperationParam();
  result_param.default_value = &Object::null_instance();
  result_param.type = &dynamic_type;
  params->parameters->Add(result_param);
  ParamDesc error_param;
  error_param.name = &Symbols::AsyncOperationErrorParam();
  error_param.default_value = &Object::null_instance();
  error_param.type = &dynamic_type;
  params->parameters->Add(error_param);
  ParamDesc stack_trace_param;
  stack_trace_param.name = &Symbols::AsyncOperationStackTraceParam();
  stack_trace_param.default_value = &Object::null_instance();
  stack_trace_param.type = &dynamic_type;
  params->parameters->Add(stack_trace_param);
  params->has_optional_positional_parameters = true;
  params->num_optional_parameters += 3;
}


RawFunction* Parser::OpenAsyncFunction(intptr_t async_func_pos) {
  TRACE_PARSER("OpenAsyncFunction");
  AddContinuationVariables();
  AddAsyncClosureVariables();
  Function& closure = Function::Handle(Z);
  bool is_new_closure = false;

  // Check whether a function for the asynchronous function body of
  // this async function has already been created by a previous
  // compilation of this function.
  const Function& found_func = Function::Handle(
      Z, current_class().LookupClosureFunction(async_func_pos));
  if (!found_func.IsNull() &&
      (found_func.token_pos() == async_func_pos) &&
      (found_func.script() == innermost_function().script()) &&
      (found_func.parent_function() == innermost_function().raw())) {
    ASSERT(found_func.IsAsyncClosure());
    closure = found_func.raw();
  } else {
    // Create the closure containing the body of this async function.
    const String& async_func_name =
        String::Handle(Z, innermost_function().name());
    String& closure_name = String::Handle(Z,
        String::NewFormatted("<%s_async_body>", async_func_name.ToCString()));
    closure = Function::NewClosureFunction(
        String::Handle(Z, Symbols::New(closure_name)),
        innermost_function(),
        async_func_pos);
    closure.set_is_generated_body(true);
    closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
    is_new_closure = true;
  }
  // Create the parameter list for the async body closure.
  ParamList closure_params;
  AddAsyncClosureParameters(&closure_params);
  if (is_new_closure) {
    // Add the parameters to the newly created closure.
    AddFormalParamsToFunction(&closure_params, closure);

    // Create and set the signature class of the closure.
    const String& sig = String::Handle(Z, closure.Signature());
    Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
    if (sig_cls.IsNull()) {
      sig_cls =
          Class::NewSignatureClass(sig, closure, script_, closure.token_pos());
      library_.AddClass(sig_cls);
    }
    closure.set_signature_class(sig_cls);
    // Finalize types in signature class here, so that the
    // signature type is not computed twice.
    ClassFinalizer::FinalizeTypesInClass(sig_cls);
    const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
    ASSERT(sig_type.IsFinalized());
    ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved());
    ASSERT(closure.NumParameters() == closure_params.parameters->length());
  }
  OpenFunctionBlock(closure);
  AddFormalParamsToScope(&closure_params, current_block_->scope);
  async_temp_scope_ = current_block_->scope;
  return closure.raw();
}


void Parser::AddContinuationVariables() {
  // Add to current block's scope:
  //   var :await_jump_var;
  //   var :await_ctx_var;
  const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
  LocalVariable* await_jump_var = new (Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AwaitJumpVar(), dynamic_type);
  current_block_->scope->AddVariable(await_jump_var);
  LocalVariable* await_ctx_var = new (Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AwaitContextVar(), dynamic_type);
  current_block_->scope->AddVariable(await_ctx_var);
}


void Parser::AddAsyncClosureVariables() {
  // Add to current block's scope:
  //   var :async_op;
  //   var :async_then_callback;
  //   var :async_catch_error_callback;
  //   var :async_completer;
  const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
  LocalVariable* async_op_var = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type);
  current_block_->scope->AddVariable(async_op_var);
  LocalVariable* async_then_callback_var = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AsyncThenCallback(), dynamic_type);
  current_block_->scope->AddVariable(async_then_callback_var);
  LocalVariable* async_catch_error_callback_var = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AsyncCatchErrorCallback(), dynamic_type);
  current_block_->scope->AddVariable(async_catch_error_callback_var);
  LocalVariable* async_completer = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AsyncCompleter(), dynamic_type);
  current_block_->scope->AddVariable(async_completer);
}


void Parser::AddAsyncGeneratorVariables() {
  // Add to current block's scope:
  //   var :controller;
  // The :controller variable is used by the async generator closure to
  // store the StreamController object to which the yielded expressions
  // are added.
  //   var :async_op;
  //   var :async_then_callback;
  //   var :async_catch_error_callback;
  // These variables are used to store the async generator closure containing
  // the body of the async* function. They are used by the await operator.
  const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
  LocalVariable* controller_var = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::Controller(), dynamic_type);
  current_block_->scope->AddVariable(controller_var);
  LocalVariable* async_op_var = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AsyncOperation(), dynamic_type);
  current_block_->scope->AddVariable(async_op_var);
  LocalVariable* async_then_callback_var = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AsyncThenCallback(), dynamic_type);
  current_block_->scope->AddVariable(async_then_callback_var);
  LocalVariable* async_catch_error_callback_var = new(Z) LocalVariable(
      Scanner::kNoSourcePos, Symbols::AsyncCatchErrorCallback(), dynamic_type);
  current_block_->scope->AddVariable(async_catch_error_callback_var);
}


RawFunction* Parser::OpenAsyncGeneratorFunction(intptr_t async_func_pos) {
  TRACE_PARSER("OpenAsyncGeneratorFunction");
  AddContinuationVariables();
  AddAsyncGeneratorVariables();

  Function& closure = Function::Handle(Z);
  bool is_new_closure = false;

  // Check whether a function for the asynchronous function body of
  // this async generator has already been created by a previous
  // compilation of this function.
  const Function& found_func = Function::Handle(
      Z, current_class().LookupClosureFunction(async_func_pos));
  if (!found_func.IsNull() &&
      (found_func.token_pos() == async_func_pos) &&
      (found_func.script() == innermost_function().script()) &&
      (found_func.parent_function() == innermost_function().raw())) {
    ASSERT(found_func.IsAsyncGenClosure());
    closure = found_func.raw();
  } else {
    // Create the closure containing the body of this async generator function.
    const String& async_generator_name =
        String::Handle(Z, innermost_function().name());
    String& closure_name = String::Handle(Z,
        String::NewFormatted("<%s_async_gen_body>",
                             async_generator_name.ToCString()));
    closure = Function::NewClosureFunction(
        String::Handle(Z, Symbols::New(closure_name)),
        innermost_function(),
        async_func_pos);
    closure.set_is_generated_body(true);
    closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
    is_new_closure = true;
  }

  ParamList closure_params;
  AddAsyncGenClosureParameters(&closure_params);

  if (is_new_closure) {
    // Add the parameters to the newly created closure.
    AddFormalParamsToFunction(&closure_params, closure);

    // Create and set the signature class of the closure.
    const String& sig = String::Handle(Z, closure.Signature());
    Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
    if (sig_cls.IsNull()) {
      sig_cls =
          Class::NewSignatureClass(sig, closure, script_, closure.token_pos());
      library_.AddClass(sig_cls);
    }
    closure.set_signature_class(sig_cls);
    // Finalize types in signature class here, so that the
    // signature type is not computed twice.
    ClassFinalizer::FinalizeTypesInClass(sig_cls);
    const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
    ASSERT(sig_type.IsFinalized());
    ASSERT(AbstractType::Handle(Z, closure.result_type()).IsResolved());
    ASSERT(closure.NumParameters() == closure_params.parameters->length());
  }

  OpenFunctionBlock(closure);
  AddFormalParamsToScope(&closure_params, current_block_->scope);
  async_temp_scope_ = current_block_->scope;
  return closure.raw();
}


// Generate the Ast nodes for the implicit code of the async* function.
//
// f(...) async* {
//   var :controller;
//   var :await_jump_var = -1;
//   var :await_context_var;
//   f_async_body() {
//     ... source code of f ...
//   }
//   var :async_op = f_async_body;
//   var :async_then_callback = _asyncThenWrapperHelper(:async_op);
//   var :async_catch_error_callback = _asyncCatchErrorWrapperHelper(:async_op);
//   :controller = new _AsyncStarStreamController(:async_op);
//   return :controller.stream;
// }
SequenceNode* Parser::CloseAsyncGeneratorFunction(const Function& closure_func,
                                                  SequenceNode* closure_body) {
  TRACE_PARSER("CloseAsyncGeneratorFunction");
  ASSERT(!closure_func.IsNull());
  ASSERT(closure_body != NULL);

  // Explicitly reference variables of the async genenerator function from the
  // closure body in order to mark them as captured.
  LocalVariable* existing_var = closure_body->scope()->LookupVariable(
      Symbols::AwaitJumpVar(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var = closure_body->scope()->LookupVariable(
      Symbols::AwaitContextVar(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var = closure_body->scope()->LookupVariable(
      Symbols::Controller(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var = closure_body->scope()->LookupVariable(
      Symbols::AsyncOperation(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var = closure_body->scope()->LookupVariable(
      Symbols::AsyncThenCallback(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var = closure_body->scope()->LookupVariable(
      Symbols::AsyncCatchErrorCallback(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());

  const Library& async_lib = Library::Handle(Library::AsyncLibrary());

  const Class& controller_class = Class::Handle(Z,
      async_lib.LookupClassAllowPrivate(
          Symbols::_AsyncStarStreamController()));
  ASSERT(!controller_class.IsNull());
  const Function& controller_constructor = Function::ZoneHandle(Z,
      controller_class.LookupConstructorAllowPrivate(
          Symbols::_AsyncStarStreamControllerConstructor()));

  // :await_jump_var = -1;
  LocalVariable* jump_var =
      current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
  LiteralNode* init_value =
      new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
  current_block_->statements->Add(
      new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));

  // Add to AST:
  //   :async_op = <closure>;  (containing the original body)
  LocalVariable* async_op_var =
      current_block_->scope->LookupVariable(Symbols::AsyncOperation(), false);
  ClosureNode* closure_obj = new(Z) ClosureNode(
      Scanner::kNoSourcePos, closure_func, NULL, closure_body->scope());
  StoreLocalNode* store_async_op = new (Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_op_var,
      closure_obj);

  current_block_->statements->Add(store_async_op);

  // :async_then_callback = _asyncThenWrapperHelper(:async_op)
  const Function& async_then_wrapper_helper = Function::ZoneHandle(
      Z, async_lib.LookupFunctionAllowPrivate(
          Symbols::AsyncThenWrapperHelper()));
  ASSERT(!async_then_wrapper_helper.IsNull());
  ArgumentListNode* async_then_wrapper_helper_args = new (Z) ArgumentListNode(
      Scanner::kNoSourcePos);
  async_then_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
  StaticCallNode* then_wrapper_call = new (Z) StaticCallNode(
      Scanner::kNoSourcePos,
      async_then_wrapper_helper,
      async_then_wrapper_helper_args);
  LocalVariable* async_then_callback_var =
      current_block_->scope->LookupVariable(
          Symbols::AsyncThenCallback(), false);
  StoreLocalNode* store_async_then_callback = new (Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_then_callback_var,
      then_wrapper_call);

  current_block_->statements->Add(store_async_then_callback);

  // :async_catch_error_callback = _asyncErrorWrapperHelper(:async_op)

  const Function& async_error_wrapper_helper = Function::ZoneHandle(
      Z, async_lib.LookupFunctionAllowPrivate(
          Symbols::AsyncErrorWrapperHelper()));
  ASSERT(!async_error_wrapper_helper.IsNull());
  ArgumentListNode* async_error_wrapper_helper_args = new (Z) ArgumentListNode(
      Scanner::kNoSourcePos);
  async_error_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
  StaticCallNode* error_wrapper_call = new (Z) StaticCallNode(
      Scanner::kNoSourcePos,
      async_error_wrapper_helper,
      async_error_wrapper_helper_args);
  LocalVariable* async_catch_error_callback_var =
      current_block_->scope->LookupVariable(
          Symbols::AsyncCatchErrorCallback(), false);
  StoreLocalNode* store_async_catch_error_callback = new (Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_catch_error_callback_var,
      error_wrapper_call);

  current_block_->statements->Add(store_async_catch_error_callback);

  // :controller = new _AsyncStarStreamController(body_closure);
  ArgumentListNode* arguments = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
  arguments->Add(new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
  ConstructorCallNode* controller_constructor_call =
      new(Z) ConstructorCallNode(Scanner::kNoSourcePos,
                                 TypeArguments::ZoneHandle(Z),
                                 controller_constructor,
                                 arguments);
  LocalVariable* controller_var =
     current_block_->scope->LookupVariable(Symbols::Controller(), false);
  StoreLocalNode* store_controller =
      new(Z) StoreLocalNode(Scanner::kNoSourcePos,
                            controller_var,
                            controller_constructor_call);
  current_block_->statements->Add(store_controller);

  // return :controller.stream;
  ReturnNode* return_node = new(Z) ReturnNode(Scanner::kNoSourcePos,
      new(Z) InstanceGetterNode(Scanner::kNoSourcePos,
          new(Z) LoadLocalNode(Scanner::kNoSourcePos,
              controller_var),
              Symbols::Stream()));
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


void Parser::OpenAsyncGeneratorClosure() {
  async_temp_scope_ = current_block_->scope;
  OpenAsyncTryBlock();
}


SequenceNode* Parser::CloseAsyncGeneratorClosure(SequenceNode* body) {
  // We need a temporary expression to store intermediate return values.
  parsed_function()->EnsureExpressionTemp();

  SequenceNode* new_body = CloseAsyncGeneratorTryBlock(body);
  ASSERT(new_body != NULL);
  ASSERT(new_body->scope() != NULL);
  return new_body;
}


// Add a return node to the sequence if necessary.
void Parser::EnsureHasReturnStatement(SequenceNode* seq, intptr_t return_pos) {
  if ((seq->length() == 0) ||
      !seq->NodeAt(seq->length() - 1)->IsReturnNode()) {
    const Function& func = innermost_function();
    // The implicit return value of synchronous generator closures is false,
    // to indicate that there are no more elements in the iterable.
    // In other cases the implicit return value is null.
    AstNode* return_value = func.IsSyncGenClosure()
        ? new LiteralNode(return_pos, Bool::False())
        : new LiteralNode(return_pos, Instance::ZoneHandle());
    seq->Add(new ReturnNode(return_pos, return_value));
  }
}


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;
}


SequenceNode* Parser::CloseAsyncFunction(const Function& closure,
                                         SequenceNode* closure_body) {
  TRACE_PARSER("CloseAsyncFunction");
  ASSERT(!closure.IsNull());
  ASSERT(closure_body != NULL);

  // Explicitly reference variables of the async function from the
  // closure body in order to mark them as captured.
  LocalVariable* existing_var =
      closure_body->scope()->LookupVariable(Symbols::AwaitJumpVar(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var =
      closure_body->scope()->LookupVariable(Symbols::AwaitContextVar(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());
  existing_var =
      closure_body->scope()->LookupVariable(Symbols::AsyncCompleter(), false);
  ASSERT((existing_var != NULL) && existing_var->is_captured());

  // Create and return a new future that executes a closure with the current
  // body.

  // No need to capture parameters or other variables, since they have already
  // been captured in the corresponding scope as the body has been parsed within
  // a nested block (contained in the async function's block).
  const Class& future =
      Class::ZoneHandle(Z, I->object_store()->future_class());
  ASSERT(!future.IsNull());
  const Function& constructor = Function::ZoneHandle(Z,
      future.LookupFunction(Symbols::FutureMicrotask()));
  ASSERT(!constructor.IsNull());
  const Class& completer =
      Class::ZoneHandle(Z, I->object_store()->completer_class());
  ASSERT(!completer.IsNull());
  const Function& completer_constructor = Function::ZoneHandle(Z,
      completer.LookupFunction(Symbols::CompleterSyncConstructor()));
  ASSERT(!completer_constructor.IsNull());

  LocalVariable* async_completer = current_block_->scope->LookupVariable(
      Symbols::AsyncCompleter(), false);

  // Add to AST:
  //   :async_completer = new Completer.sync();
  ArgumentListNode* empty_args =
      new (Z) ArgumentListNode(Scanner::kNoSourcePos);
  ConstructorCallNode* completer_constructor_node = new (Z) ConstructorCallNode(
      Scanner::kNoSourcePos,
      TypeArguments::ZoneHandle(Z),
      completer_constructor,
      empty_args);
  StoreLocalNode* store_completer = new (Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_completer,
      completer_constructor_node);
  current_block_->statements->Add(store_completer);

  // :await_jump_var = -1;
  LocalVariable* jump_var =
      current_block_->scope->LookupVariable(Symbols::AwaitJumpVar(), false);
  LiteralNode* init_value =
      new(Z) LiteralNode(Scanner::kNoSourcePos, Smi::ZoneHandle(Smi::New(-1)));
  current_block_->statements->Add(
      new(Z) StoreLocalNode(Scanner::kNoSourcePos, jump_var, init_value));

  // Add to AST:
  //   :async_op = <closure>;  (containing the original body)
  LocalVariable* async_op_var = current_block_->scope->LookupVariable(
      Symbols::AsyncOperation(), false);
  ClosureNode* cn = new(Z) ClosureNode(
      Scanner::kNoSourcePos, closure, NULL, closure_body->scope());
  StoreLocalNode* store_async_op = new (Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_op_var,
      cn);
  current_block_->statements->Add(store_async_op);

  const Library& async_lib = Library::Handle(Library::AsyncLibrary());
  // :async_then_callback = _asyncThenWrapperHelper(:async_op)
  const Function& async_then_wrapper_helper = Function::ZoneHandle(
      Z, async_lib.LookupFunctionAllowPrivate(
          Symbols::AsyncThenWrapperHelper()));
  ASSERT(!async_then_wrapper_helper.IsNull());
  ArgumentListNode* async_then_wrapper_helper_args = new (Z) ArgumentListNode(
      Scanner::kNoSourcePos);
  async_then_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
  StaticCallNode* then_wrapper_call = new (Z) StaticCallNode(
      Scanner::kNoSourcePos,
      async_then_wrapper_helper,
      async_then_wrapper_helper_args);
  LocalVariable* async_then_callback_var =
      current_block_->scope->LookupVariable(
          Symbols::AsyncThenCallback(), false);
  StoreLocalNode* store_async_then_callback = new (Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_then_callback_var,
      then_wrapper_call);

  current_block_->statements->Add(store_async_then_callback);

  // :async_catch_error_callback = _asyncErrorWrapperHelper(:async_op)

  const Function& async_error_wrapper_helper = Function::ZoneHandle(
      Z, async_lib.LookupFunctionAllowPrivate(
          Symbols::AsyncErrorWrapperHelper()));
  ASSERT(!async_error_wrapper_helper.IsNull());
  ArgumentListNode* async_error_wrapper_helper_args = new (Z) ArgumentListNode(
      Scanner::kNoSourcePos);
  async_error_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(Scanner::kNoSourcePos, async_op_var));
  StaticCallNode* error_wrapper_call = new (Z) StaticCallNode(
      Scanner::kNoSourcePos,
      async_error_wrapper_helper,
      async_error_wrapper_helper_args);
  LocalVariable* async_catch_error_callback_var =
      current_block_->scope->LookupVariable(
          Symbols::AsyncCatchErrorCallback(), false);
  StoreLocalNode* store_async_catch_error_callback = new (Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_catch_error_callback_var,
      error_wrapper_call);

  current_block_->statements->Add(store_async_catch_error_callback);

  // Add to AST:
  //   new Future.microtask(:async_op);
  ArgumentListNode* arguments = new (Z) ArgumentListNode(Scanner::kNoSourcePos);
  arguments->Add(new (Z) LoadLocalNode(
      Scanner::kNoSourcePos, async_op_var));
  ConstructorCallNode* future_node = new (Z) ConstructorCallNode(
      Scanner::kNoSourcePos, TypeArguments::ZoneHandle(Z), constructor,
      arguments);
  current_block_->statements->Add(future_node);

  // Add to AST:
  //   return :async_completer.future;
  ReturnNode* return_node = new (Z) ReturnNode(
      Scanner::kNoSourcePos,
      new (Z) InstanceGetterNode(
          Scanner::kNoSourcePos,
          new (Z) LoadLocalNode(
              Scanner::kNoSourcePos,
              async_completer),
          Symbols::CompleterFuture()));
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


SequenceNode* Parser::CloseAsyncClosure(SequenceNode* body) {
  // We need a temporary expression to store intermediate return values.
  parsed_function()->EnsureExpressionTemp();

  SequenceNode* new_body = CloseAsyncTryBlock(body);
  ASSERT(new_body != NULL);
  ASSERT(new_body->scope() != NULL);
  return new_body;
}


// Set up default values for all optional parameters to the function.
void Parser::SetupDefaultsForOptionalParams(const ParamList& params) {
  if ((current_function().raw() == innermost_function().raw()) &&
      (params.num_optional_parameters > 0)) {
    ZoneGrowableArray<const Instance*>* default_values =
        new ZoneGrowableArray<const Instance*>(zone(),
                                               params.num_optional_parameters);
    // Build array of default parameter values.
    const ZoneGrowableArray<ParamDesc>& parameters = *params.parameters;
    const int first_opt_param_offset = params.num_fixed_parameters;
    for (int i = 0; i < params.num_optional_parameters; i++) {
      const Instance* default_value =
          parameters[i + first_opt_param_offset].default_value;
      default_values->Add(default_value);
    }
    parsed_function()->set_default_parameter_values(default_values);
  }
}


// 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());
    Report::MessageF(Report::kError, script, func.token_pos(),
                     "too many formal parameters");
  }
  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(Z) LocalVariable(
        param_desc.name_pos, *name, *param_desc.type);
    if (!scope->InsertParameterAt(i, parameter)) {
      ReportError(param_desc.name_pos,
                  "name '%s' already exists in scope",
                  param_desc.name->ToCString());
    }
    param_desc.var = parameter;
    if (param_desc.is_final) {
      parameter->set_is_final();
    }
    if (param_desc.is_field_initializer) {
      parameter->set_invisible(true);
    }
  }
}


// Builds ReturnNode/NativeBodyNode for a native function.
void Parser::ParseNativeFunctionBlock(const ParamList* params,
                                      const Function& func) {
  ASSERT(func.is_native());
  TRACE_PARSER("ParseNativeFunctionBlock");
  const Class& cls = Class::Handle(Z, func.Owner());
  const Library& library = Library::Handle(Z, 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);
  bool auto_setup_scope = true;
  NativeFunction native_function = NativeEntry::ResolveNative(
      library, native_name, num_params, &auto_setup_scope);
  if (native_function == NULL) {
    ReportError(native_pos,
                "native function '%s' (%" Pd " arguments) cannot be found",
                native_name.ToCString(), func.NumParameters());
  }
  func.SetIsNativeAutoSetupScope(auto_setup_scope);

  // 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(Z) ReturnNode(
      TokenPos(),
      new(Z) NativeBodyNode(
          TokenPos(),
          Function::ZoneHandle(Z, func.raw()),
          native_name,
          native_function,
          current_block_->scope,
          is_bootstrap_native,
          FLAG_link_natives_lazily)));
}


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);
  const String* variable_name = current_function().IsInFactoryScope() ?
      &Symbols::TypeArgumentsParameter() : &Symbols::This();
  current_block_->scope->CaptureVariable(
      current_block_->scope->LookupVariable(*variable_name, true));
}


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) {
    ReportError(token_pos, "illegal implicit access to receiver 'this'");
  }
  return new(Z) LoadLocalNode(TokenPos(), receiver);
}


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


// Returns ast nodes of the variable initialization.
AstNode* Parser::ParseVariableDeclaration(const AbstractType& type,
                                          bool is_final,
                                          bool is_const,
                                          SequenceNode** await_preamble) {
  TRACE_PARSER("ParseVariableDeclaration");
  ASSERT(IsIdentifier());
  const intptr_t ident_pos = TokenPos();
  const String& ident = *CurrentLiteral();
  ConsumeToken();  // Variable identifier.
  const intptr_t assign_pos = TokenPos();
  AstNode* initialization = NULL;
  LocalVariable* variable = NULL;
  if (CurrentToken() == Token::kASSIGN) {
    // Variable initialization.
    ConsumeToken();
    AstNode* expr = ParseAwaitableExpr(
        is_const, kConsumeCascades, await_preamble);
    const intptr_t expr_end_pos = TokenPos();
    variable = new(Z) LocalVariable(
        expr_end_pos, ident, type);
    initialization = new(Z) StoreLocalNode(
        assign_pos, variable, expr);
    if (is_const) {
      ASSERT(expr->IsLiteralNode());
      variable->SetConstValue(expr->AsLiteralNode()->literal());
    }
  } else if (is_final || is_const) {
    ReportError(ident_pos,
                "missing initialization of 'final' or 'const' variable");
  } else {
    // Initialize variable with null.
    variable = new(Z) LocalVariable(
        assign_pos, ident, type);
    AstNode* null_expr = new(Z) LiteralNode(ident_pos, Instance::ZoneHandle(Z));
    initialization = new(Z) StoreLocalNode(
        ident_pos, variable, null_expr);
  }

  ASSERT(current_block_ != NULL);
  const intptr_t previous_pos =
      current_block_->scope->PreviousReferencePos(ident);
  if (previous_pos >= 0) {
    ASSERT(!script_.IsNull());
    if (previous_pos > ident_pos) {
      ReportError(ident_pos,
                  "initializer of '%s' may not refer to itself",
                  ident.ToCString());

    } else {
      intptr_t line_number;
      script_.GetTokenLocation(previous_pos, &line_number, NULL);
      ReportError(ident_pos,
                  "identifier '%s' previously used in line %" Pd "",
                  ident.ToCString(),
                  line_number);
    }
  }

  // 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);
    // Use before define cases have already been detected and reported above.
    ASSERT(existing_var->owner() == current_block_->scope);
    ReportError(ident_pos, "identifier '%s' already defined",
                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 {
      ReportError("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(Z,
      ParseConstFinalVarOrType(I->flags().type_checks() ?
          ClassFinalizer::kCanonicalize : ClassFinalizer::kIgnore));
  if (!IsIdentifier()) {
    ReportError("identifier expected");
  }

  SequenceNode* preamble = NULL;
  AstNode* initializers =
      ParseVariableDeclaration(type, is_final, is_const, &preamble);
  ASSERT(initializers != NULL);
  if (preamble != NULL) {
    preamble->Add(initializers);
    initializers = preamble;
  }
  while (CurrentToken() == Token::kCOMMA) {
    ConsumeToken();
    if (!IsIdentifier()) {
      ReportError("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);
    preamble = NULL;
    AstNode* declaration = ParseVariableDeclaration(
        type, is_final, is_const, &preamble);
    if (preamble != NULL) {
      sequence->Add(preamble);
    }
    sequence->Add(declaration);
    initializers = sequence;
  }
  return initializers;
}


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

  result_type = Type::DynamicType();

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

    // Check that the function name has not been referenced
    // before this declaration.
    ASSERT(current_block_ != NULL);
    const intptr_t previous_pos =
        current_block_->scope->PreviousReferencePos(*function_name);
    if (previous_pos >= 0) {
      ASSERT(!script_.IsNull());
      intptr_t line_number;
      script_.GetTokenLocation(previous_pos, &line_number, NULL);
      ReportError(name_pos,
                  "identifier '%s' previously used in line %" Pd "",
                  function_name->ToCString(),
                  line_number);
    }
  }
  CheckToken(Token::kLPAREN);

  // 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(Z);
  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())) {
    // The function will be registered in the lookup table by the
    // EffectGraphVisitor::VisitClosureNode when the newly allocated closure
    // function has been properly setup.
    is_new_closure = true;
    function = Function::NewClosureFunction(*function_name,
                                            innermost_function(),
                                            function_pos);
    function.set_result_type(result_type);
    if (metadata_pos >= 0) {
      library_.AddFunctionMetadata(function, metadata_pos);
    }
  }

  // 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(Z);
  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(Z,
        Type::Handle(Z, Type::Function()).type_class());
    function_type = Type::New(unknown_signature_class,
                              TypeArguments::Handle(Z), function_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(Z) LocalVariable(function_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);
      // Use before define cases have already been detected and reported above.
      ASSERT(existing_var->owner() == current_block_->scope);
      ReportError(function_pos, "identifier '%s' already defined",
                  function_variable->name().ToCString());
    }
  }

  // Parse the local function.
  SequenceNode* statements = Parser::ParseFunc(function);

  // 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(Z, function.Signature());
  Class& signature_class = Class::ZoneHandle(Z);
  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();
  }

  // Finalize types in signature class here, so that the
  // signature type is not computed twice.
  ClassFinalizer::FinalizeTypesInClass(signature_class);
  const Type& signature_type = Type::Handle(Z, signature_class.SignatureType());
  ASSERT(signature_type.IsFinalized());

  // A signature type itself cannot be malformed or malbounded, only its
  // signature function's result type or parameter types may be.
  ASSERT(!signature_type.IsMalformed());
  ASSERT(!signature_type.IsMalbounded());

  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(
        TypeArguments::Handle(Z, signature_type.arguments()));

    // 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(Z) ClosureNode(
      function_pos, function, NULL, statements->scope());

  if (function_variable == NULL) {
    ASSERT(is_literal);
    return closure;
  } else {
    AstNode* initialization = new(Z) StoreLocalNode(
        function_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::TryParseTypeParameters() {
  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() != TypeArguments::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()) &&
      !(await_is_keyword_ &&
       ((CurrentLiteral()->raw() == Symbols::Await().raw()) ||
       (CurrentLiteral()->raw() == Symbols::Async().raw()) ||
       (CurrentLiteral()->raw() == Symbols::YieldKw().raw())));
}


bool Parser::IsSymbol(const String& symbol) {
  return (CurrentLiteral()->raw() == symbol.raw()) &&
      (CurrentToken() == Token::kIDENT);
}


// Returns true if the next tokens can be parsed as a an optionally
// qualified identifier: [ident '.'] ident.
// Current token position is not restored.
bool Parser::TryParseQualIdent() {
  if (CurrentToken() != Token::kIDENT) {
    return false;
  }
  ConsumeToken();
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    if (CurrentToken() != Token::kIDENT) {
      return false;
    }
    ConsumeToken();
  }
  return true;
}


// 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) {
    if (!TryParseQualIdent()) {
      return false;
    }
    if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) {
      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;
  SkipMetadata();
  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_ && IsSymbol(Symbols::Native())) ||
        is_external ||
        IsSymbol(Symbols::Async()) ||
        IsSymbol(Symbols::Sync())) {
      SetPosition(saved_pos);
      return true;
    }
  }
  SetPosition(saved_pos);
  return false;
}


bool Parser::IsTopLevelAccessor() {
  const intptr_t saved_pos = TokenPos();
  if (is_patch_source() && IsSymbol(Symbols::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();
  ParseFunctionModifier();
  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) {
        ReportError(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 = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
  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(Z) 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;
}


// Return true if the type class of the given value implements the
// == operator.
static bool ImplementsEqualOperator(const Instance& value) {
  Class& cls = Class::Handle(value.clazz());
  const Function& equal_op = Function::Handle(
      Resolver::ResolveDynamicAnyArgs(cls, Symbols::EqualOperator()));
  ASSERT(!equal_op.IsNull());
  cls = equal_op.Owner();
  return !cls.IsObjectClass();
}


// Check that all case expressions are of the same type, either int, String,
// or any other class that does not override the == operator.
// The expressions are compile-time constants and are thus in the form
// of a LiteralNode.
RawClass* Parser::CheckCaseExpressions(
    const GrowableArray<LiteralNode*>& values) {
  const intptr_t num_expressions = values.length();
  if (num_expressions == 0) {
    return Object::dynamic_class();
  }
  const Instance& first_value = values[0]->literal();
  for (intptr_t i = 0; i < num_expressions; i++) {
    const Instance& val = values[i]->literal();
    const intptr_t val_pos = values[i]->token_pos();
    if (first_value.IsInteger()) {
      if (!val.IsInteger()) {
        ReportError(val_pos, "expected case expression of type int");
      }
      continue;
    }
    if (first_value.IsString()) {
      if (!val.IsString()) {
        ReportError(val_pos, "expected case expression of type String");
      }
      continue;
    }
    if (val.IsDouble()) {
      ReportError(val_pos, "case expression may not be of type double");
    }
    if (val.clazz() != first_value.clazz()) {
      ReportError(val_pos, "all case expressions must be of same type");
    }
    if (val.clazz() == I->object_store()->symbol_class()) {
      continue;
    }
    if (i == 0) {
      // The value is of some type other than int, String or double.
      // Check that the type class does not override the == operator.
      // Check this only in the first loop iteration since all values
      // are of the same type, which we check above.
      if (ImplementsEqualOperator(val)) {
        ReportError(val_pos,
                    "type class of case expression must not "
                    "implement operator ==");
      }
    }
  }
  if (first_value.IsInteger()) {
    return Type::Handle(Z, Type::IntType()).type_class();
  } else if (first_value.IsString()) {
    return Type::Handle(Z, Type::StringType()).type_class();
  }
  return first_value.clazz();
}


CaseNode* Parser::ParseCaseClause(LocalVariable* switch_expr_value,
                                  GrowableArray<LiteralNode*>* case_expr_values,
                                  SourceLabel* case_label) {
  TRACE_PARSER("ParseCaseClause");
  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(Z) SequenceNode(case_pos, NULL);
  while (CurrentToken() == Token::kCASE || CurrentToken() == Token::kDEFAULT) {
    if (CurrentToken() == Token::kCASE) {
      if (default_seen) {
        ReportError("default clause must be last case");
      }
      ConsumeToken();  // Keyword case.
      const intptr_t expr_pos = TokenPos();
      AstNode* expr = ParseExpr(kRequireConst, kConsumeCascades);
      ASSERT(expr->IsLiteralNode());
      case_expr_values->Add(expr->AsLiteralNode());

      AstNode* switch_expr_load = new(Z) LoadLocalNode(
          case_pos, switch_expr_value);
      AstNode* case_comparison = new(Z) ComparisonNode(
          expr_pos, Token::kEQ, expr, switch_expr_load);
      case_expressions->Add(case_comparison);
    } else {
      if (default_seen) {
        ReportError("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(Z) ArgumentListNode(TokenPos());
        arguments->Add(new(Z) LiteralNode(
            TokenPos(), Integer::ZoneHandle(Z, Integer::New(TokenPos()))));
        current_block_->statements->Add(
            MakeStaticCall(Symbols::FallThroughError(),
                           Library::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(Z) 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();
  ExpectToken(Token::kLPAREN);
  const intptr_t expr_pos = TokenPos();
  AstNode* switch_expr = ParseAwaitableExpr(
      kAllowConst, kConsumeCascades, NULL);
  ExpectToken(Token::kRPAREN);
  ExpectToken(Token::kLBRACE);
  OpenBlock();
  current_block_->scope->AddLabel(label);

  // Store switch expression in temporary local variable. The type of the
  // variable is set to dynamic. It will later be patched to match the
  // type of the case clause expressions. Therefore, we have to allocate
  // a new type representing dynamic and can't reuse the canonical
  // type object for dynamic.
  const Type& temp_var_type = Type::ZoneHandle(Z,
       Type::New(Class::Handle(Z, Object::dynamic_class()),
                 TypeArguments::Handle(Z),
                 expr_pos));
  temp_var_type.SetIsFinalized();
  LocalVariable* temp_variable = new(Z) LocalVariable(
      expr_pos,  Symbols::SwitchExpr(), temp_var_type);
  current_block_->scope->AddVariable(temp_variable);
  AstNode* save_switch_expr = new(Z) StoreLocalNode(
      expr_pos, temp_variable, switch_expr);
  current_block_->statements->Add(save_switch_expr);

  // Parse case clauses
  bool default_seen = false;
  GrowableArray<LiteralNode*> case_expr_values;
  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(Z) 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 {
        ReportError(label_pos, "label '%s' already exists in scope",
                    label_name->ToCString());
      }
      ASSERT(case_label->kind() == SourceLabel::kCase);
    }
    if (CurrentToken() == Token::kCASE ||
        CurrentToken() == Token::kDEFAULT) {
      if (default_seen) {
        ReportError("no case clauses allowed after default clause");
      }
      CaseNode* case_clause =
          ParseCaseClause(temp_variable, &case_expr_values, case_label);
      default_seen = case_clause->contains_default();
      current_block_->statements->Add(case_clause);
    } else if (CurrentToken() != Token::kRBRACE) {
      ReportError("'case' or '}' expected");
    } else if (case_label != NULL) {
      ReportError("expecting at least one case clause after label");
    } else {
      break;
    }
  }

  // Check that all expressions in case clauses are of the same class,
  // or implement int, double or String. Patch the type of the temporary
  // variable holding the switch expression to match the type of the
  // case clause constants.
  temp_var_type.set_type_class(
      Class::Handle(Z, CheckCaseExpressions(case_expr_values)));

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

  SequenceNode* switch_body = CloseBlock();
  ExpectToken(Token::kRBRACE);
  return new(Z) 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);
  SequenceNode* await_preamble = NULL;
  AstNode* cond_expr = ParseAwaitableExpr(
      kAllowConst, kConsumeCascades, &await_preamble);
  ExpectToken(Token::kRPAREN);
  const bool parsing_loop_body =  true;
  SequenceNode* while_body = ParseNestedStatement(parsing_loop_body, label);
  WhileNode* while_node = new (Z) WhileNode(while_pos,
                                            label,
                                            cond_expr,
                                            await_preamble,
                                            while_body);
  return while_node;
}


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);
  SequenceNode* await_preamble = NULL;
  intptr_t expr_pos = TokenPos();
  AstNode* cond_expr =
      ParseAwaitableExpr(kAllowConst, kConsumeCascades, &await_preamble);
  if (await_preamble != NULL) {
    // Prepend the preamble to the condition.
    LetNode* await_cond = new(Z) LetNode(expr_pos);
    await_cond->AddNode(await_preamble);
    await_cond->AddNode(cond_expr);
    cond_expr = await_cond;
  }
  ExpectToken(Token::kRPAREN);
  ExpectSemicolon();
  return new(Z) DoWhileNode(do_pos, label, cond_expr, dowhile_body);
}


static LocalVariable* LookupSavedTryContextVar(LocalScope* scope) {
  LocalVariable* var =
      scope->LocalLookupVariable(Symbols::SavedTryContextVar());
  ASSERT((var != NULL) && !var->is_captured());
  return var;
}


static LocalVariable* LookupAsyncSavedTryContextVar(LocalScope* scope,
                                                    uint16_t try_index) {
  const String& async_saved_try_ctx_name =
      String::ZoneHandle(Symbols::New(String::Handle(
          String::NewFormatted(
              "%s%d",
              Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
              try_index))));
  LocalVariable* var = scope->LocalLookupVariable(async_saved_try_ctx_name);
  ASSERT(var != NULL);
  return var;
}


// If the await or yield being parsed is in a try block, the continuation code
// needs to restore the corresponding stack-based variable :saved_try_ctx_var,
// and the stack-based variable :saved_try_ctx_var of the outer try block.
// The inner :saved_try_ctx_var is used by a finally clause handling an
// exception thrown by the continuation code in a try block or catch block.
// If no finally clause exists, the catch or finally clause of the outer try
// block, if any, uses the outer :saved_try_ctx_var to handle the exception.
//
// * Try blocks and catch blocks:
//     Set the context variable for this try block and for the outer try block.
// * Finally blocks:
//     Set the context variable for the outer try block. Note that the try
//     declaring the finally is popped before parsing the finally clause, so the
//     outer try block is at the top of the try block list.
void Parser::CheckAsyncOpInTryBlock(
    LocalVariable** saved_try_ctx,
    LocalVariable** async_saved_try_ctx,
    LocalVariable** outer_saved_try_ctx,
    LocalVariable** outer_async_saved_try_ctx) const {
  *saved_try_ctx = NULL;
  *async_saved_try_ctx = NULL;
  *outer_saved_try_ctx = NULL;
  *outer_async_saved_try_ctx = NULL;
  if (try_stack_ != NULL) {
    LocalScope* scope = try_stack_->try_block()->scope;
    uint16_t try_index = try_stack_->try_index();
    const int current_function_level = current_block_->scope->function_level();
    if (scope->function_level() == current_function_level) {
      // The block declaring :saved_try_ctx_var variable is the parent of the
      // pushed try block.
      *saved_try_ctx = LookupSavedTryContextVar(scope->parent());
      *async_saved_try_ctx = LookupAsyncSavedTryContextVar(async_temp_scope_,
                                                           try_index);
      if ((try_stack_->outer_try() != NULL) && !try_stack_->inside_finally()) {
        // Collecting the outer try scope is not necessary if we
        // are in a finally block.
        scope = try_stack_->outer_try()->try_block()->scope;
        try_index = try_stack_->outer_try()->try_index();
        if (scope->function_level() == current_function_level) {
          *outer_saved_try_ctx = LookupSavedTryContextVar(scope->parent());
          *outer_async_saved_try_ctx =
              LookupAsyncSavedTryContextVar(async_temp_scope_, try_index);
        }
      }
    }
  }
  // An async or async* has an implicitly created try-catch around the
  // function body, so the await or yield inside the async closure should always
  // be created with a try scope.
  ASSERT((*saved_try_ctx != NULL) ||
         innermost_function().IsAsyncFunction() ||
         innermost_function().IsAsyncGenerator() ||
         innermost_function().IsSyncGenClosure() ||
         innermost_function().IsSyncGenerator());
}


// Build an AST node for static call to Dart function print(str).
// Used during debugging to insert print in generated dart code.
AstNode* Parser::DartPrint(const char* str) {
  const Library& lib = Library::Handle(Library::CoreLibrary());
  const Function& print_fn = Function::ZoneHandle(
      Z, lib.LookupFunctionAllowPrivate(Symbols::print()));
  ASSERT(!print_fn.IsNull());
  ArgumentListNode* one_arg = new(Z) ArgumentListNode(Scanner::kNoSourcePos);
  String& msg = String::Handle(String::NewFormatted("%s", str));
  one_arg->Add(new(Z) LiteralNode(Scanner::kNoSourcePos,
               String::ZoneHandle(Symbols::New(msg))));
  AstNode* print_call =
      new(Z) StaticCallNode(Scanner::kNoSourcePos, print_fn, one_arg);
  return print_call;
}


AstNode* Parser::ParseAwaitForStatement(String* label_name) {
  TRACE_PARSER("ParseAwaitForStatement");
  ASSERT(IsAwaitKeyword());
  const intptr_t await_for_pos = TokenPos();
  ConsumeToken();  // await.
  ASSERT(CurrentToken() == Token::kFOR);
  ConsumeToken();  // for.
  ExpectToken(Token::kLPAREN);

  if (!innermost_function().IsAsyncFunction() &&
      !innermost_function().IsAsyncClosure() &&
      !innermost_function().IsAsyncGenerator() &&
      !innermost_function().IsAsyncGenClosure()) {
    ReportError(await_for_pos,
                "await for loop is only allowed in an asynchronous function");
  }

  // Parse loop variable.
  bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
  if (CurrentToken() == Token::kCONST) {
    ReportError("Loop variable cannot be 'const'");
  }
  bool new_loop_var = false;
  AbstractType& loop_var_type =  AbstractType::ZoneHandle(Z);
  if (LookaheadToken(1) != Token::kIN) {
    // Declaration of a new loop variable.
    // Delay creation of the local variable until we know its actual
    // position, which is inside the loop body.
    new_loop_var = true;
    loop_var_type = ParseConstFinalVarOrType(
       I->flags().type_checks() ? ClassFinalizer::kCanonicalize :
                                  ClassFinalizer::kIgnore);
  }
  intptr_t loop_var_pos = TokenPos();
  const String* loop_var_name = ExpectIdentifier("variable name expected");

  // Parse stream expression.
  ExpectToken(Token::kIN);
  const intptr_t stream_pos = TokenPos();
  AstNode* stream_expr =
      ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
  ExpectToken(Token::kRPAREN);

  // Open a block for the iterator variable and the try-finally
  // statement that contains the loop.
  OpenBlock();
  const Block* loop_block = current_block_;

  // Build creation of implicit StreamIterator.
  // var :for-in-iter = new StreamIterator(stream_expr).
  const Class& stream_iterator_cls =
      Class::ZoneHandle(Z, I->object_store()->stream_iterator_class());
  ASSERT(!stream_iterator_cls.IsNull());
  const Function& iterator_ctor =
      Function::ZoneHandle(Z, stream_iterator_cls.LookupFunction(
          Symbols::StreamIteratorConstructor()));
  ASSERT(!iterator_ctor.IsNull());
  ArgumentListNode* ctor_args = new (Z) ArgumentListNode(Scanner::kNoSourcePos);
  ctor_args->Add(stream_expr);
  ConstructorCallNode* ctor_call =
      new (Z) ConstructorCallNode(Scanner::kNoSourcePos,
                              TypeArguments::ZoneHandle(Z),
                              iterator_ctor,
                              ctor_args);
  const AbstractType& iterator_type = Type::ZoneHandle(Z, Type::DynamicType());
  LocalVariable* iterator_var = new(Z) LocalVariable(
      stream_pos, Symbols::ForInIter(), iterator_type);
  current_block_->scope->AddVariable(iterator_var);
  AstNode* iterator_init =
      new(Z) StoreLocalNode(stream_pos, iterator_var, ctor_call);
  current_block_->statements->Add(iterator_init);

  // We need to ensure that the stream is cancelled after the loop.
  // Thus, wrap the loop in a try-finally that calls :for-in-iter.close()
  // in the finally clause. It is harmless to call close() if the stream
  // is already cancelled (when moveNext() returns false).
  // Note: even though this is async code, we do not need to set up
  // the closurized saved_exception_var and saved_stack_trace_var because
  // there can not be a suspend/resume event before the exception is
  // rethrown in the catch clause. The catch block of the implicit
  // try-finally is empty.
  LocalVariable* context_var = NULL;
  LocalVariable* exception_var = NULL;
  LocalVariable* stack_trace_var = NULL;
  LocalVariable* saved_exception_var = NULL;
  LocalVariable* saved_stack_trace_var = NULL;
  SetupExceptionVariables(current_block_->scope,
                          false,  // Do not create the saved_ vars.
                          &context_var,
                          &exception_var,
                          &stack_trace_var,
                          &saved_exception_var,
                          &saved_stack_trace_var);
  OpenBlock();  // try block.
  PushTry(current_block_);
  SetupSavedTryContext(context_var);

  // Build while loop condition.
  // while (await :for-in-iter.moveNext())
  LocalVariable* saved_try_ctx;
  LocalVariable* async_saved_try_ctx;
  LocalVariable* outer_saved_try_ctx;
  LocalVariable* outer_async_saved_try_ctx;
  CheckAsyncOpInTryBlock(&saved_try_ctx,
                         &async_saved_try_ctx,
                         &outer_saved_try_ctx,
                         &outer_async_saved_try_ctx);
  ArgumentListNode* no_args = new(Z) ArgumentListNode(stream_pos);
  AstNode* iterator_moveNext = new(Z) InstanceCallNode(
      stream_pos,
      new(Z) LoadLocalNode(stream_pos, iterator_var),
                           Symbols::MoveNext(),
                           no_args);
  OpenBlock();
  AstNode* await_moveNext =
      new(Z) AwaitNode(stream_pos,
                       iterator_moveNext,
                       saved_try_ctx,
                       async_saved_try_ctx,
                       outer_saved_try_ctx,
                       outer_async_saved_try_ctx,
                       current_block_->scope);
  AwaitTransformer at(current_block_->statements, async_temp_scope_);
  await_moveNext = at.Transform(await_moveNext);
  SequenceNode* await_preamble = CloseBlock();

  // 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();

  SourceLabel* label =
      SourceLabel::New(await_for_pos, label_name, SourceLabel::kFor);
  current_block_->scope->AddLabel(label);
  const intptr_t loop_var_assignment_pos = TokenPos();

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

  // Generate assignment of next iterator value to loop variable.
  AstNode* loop_var_assignment = NULL;
  if (new_loop_var) {
    // The for loop variable is new for each iteration.
    // Create a variable and add it to the loop body scope.
    // Note that the variable token position needs to be inside the
    // loop block, so it gets put in the loop context level.
    LocalVariable* loop_var =
        new(Z) LocalVariable(loop_var_assignment_pos,
                             *loop_var_name,
                             loop_var_type);;
    if (loop_var_is_final) {
      loop_var->set_is_final();
    }
    current_block_->scope->AddVariable(loop_var);
    loop_var_assignment = new(Z) StoreLocalNode(
        loop_var_assignment_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_assignment_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_block = CloseBlock();

  WhileNode* while_node = new (Z) WhileNode(await_for_pos,
                                            label,
                                            await_moveNext,
                                            await_preamble,
                                            for_loop_block);
  // Add the while loop to the try block.
  current_block_->statements->Add(while_node);
  SequenceNode* try_block = CloseBlock();

  // Create an empty "catch all" block that rethrows the current
  // exception and stacktrace.
  try_stack_->enter_catch();
  SequenceNode* catch_block = new(Z) SequenceNode(await_for_pos, NULL);

  if (outer_saved_try_ctx != NULL) {
    catch_block->Add(new (Z) StoreLocalNode(
        Scanner::kNoSourcePos,
        outer_saved_try_ctx,
        new (Z) LoadLocalNode(Scanner::kNoSourcePos,
                              outer_async_saved_try_ctx)));
  }

  // We don't need to copy the current exception and stack trace variables
  // into :saved_exception_var and :saved_stack_trace_var here because there
  // is no code in the catch clause that could suspend the function.

  // Rethrow the exception.
  catch_block->Add(new(Z) ThrowNode(
      await_for_pos,
      new(Z) LoadLocalNode(await_for_pos, exception_var),
      new(Z) LoadLocalNode(await_for_pos, stack_trace_var)));

  TryStack* try_statement = PopTry();
  const intptr_t try_index = try_statement->try_index();
  TryStack* outer_try = try_stack_;
  const intptr_t outer_try_index = (outer_try != NULL) ?
      outer_try->try_index() : CatchClauseNode::kInvalidTryIndex;

  // The finally block contains a call to cancel the stream.
  // :for-in-iter.cancel()

  // Inline the finally block to the exit points in the try block.
  intptr_t node_index = 0;
  SequenceNode* finally_clause = NULL;
  if (try_stack_ != NULL) {
    try_stack_->enter_finally();
  }
  do {
    OpenBlock();
    ArgumentListNode* no_args =
        new(Z) ArgumentListNode(Scanner::kNoSourcePos);
    current_block_->statements->Add(
        new(Z) InstanceCallNode(Scanner::kNoSourcePos,
            new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_var),
            Symbols::Cancel(),
            no_args));
    finally_clause = CloseBlock();
    AstNode* node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
    if (node_to_inline != NULL) {
      InlinedFinallyNode* node =
          new(Z) InlinedFinallyNode(Scanner::kNoSourcePos,
                                    finally_clause,
                                    context_var,
                                    outer_try_index);
      finally_clause = NULL;
      AddFinallyClauseToNode(true, node_to_inline, node);
      node_index++;
    }
  } while (finally_clause == NULL);

  if (try_stack_ != NULL) {
    try_stack_->exit_finally();
  }

  // Create the try-statement and add to the current sequence, which is
  // the block around the loop statement.

  const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
  const Array& handler_types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld));
  handler_types.SetAt(0, dynamic_type);  // Catch block handles all exceptions.

  CatchClauseNode* catch_clause = new(Z) CatchClauseNode(await_for_pos,
      catch_block,
      handler_types,
      context_var,
      exception_var,
      stack_trace_var,
      exception_var,
      stack_trace_var,
      AllocateTryIndex(),
      true);  // Needs stack trace.

  AstNode* try_catch_node =
      new(Z) TryCatchNode(await_for_pos,
                         try_block,
                         context_var,
                         catch_clause,
                         finally_clause,
                         try_index);

  ASSERT(current_block_ == loop_block);
  loop_block->statements->Add(try_catch_node);

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


AstNode* Parser::ParseForInStatement(intptr_t forin_pos,
                                     SourceLabel* label) {
  TRACE_PARSER("ParseForInStatement");
  bool loop_var_is_final = (CurrentToken() == Token::kFINAL);
  if (CurrentToken() == Token::kCONST) {
    ReportError("Loop variable cannot be 'const'");
  }
  const String* loop_var_name = NULL;
  intptr_t loop_var_pos = 0;
  bool new_loop_var = false;
  AbstractType& loop_var_type =  AbstractType::ZoneHandle(Z);
  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.
    // Delay creation of the local variable until we know its actual
    // position, which is inside the loop body.
    new_loop_var = true;
    loop_var_type = ParseConstFinalVarOrType(
        I->flags().type_checks() ? ClassFinalizer::kCanonicalize :
                                   ClassFinalizer::kIgnore);
    loop_var_name = ExpectIdentifier("variable name expected");
  }
  ExpectToken(Token::kIN);
  const intptr_t collection_pos = TokenPos();
  AstNode* collection_expr =
      ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
  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(Z, Type::DynamicType());
  LocalVariable* iterator_var = new(Z) LocalVariable(
      collection_pos, Symbols::ForInIter(), iterator_type);
  current_block_->scope->AddVariable(iterator_var);

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

  // Generate while loop condition.
  AstNode* iterator_moveNext = new(Z) InstanceCallNode(
      collection_pos,
      new(Z) 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);
  const intptr_t loop_var_assignment_pos = TokenPos();

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

  // Generate assignment of next iterator value to loop variable.
  AstNode* loop_var_assignment = NULL;
  if (new_loop_var) {
    // The for loop variable is new for each iteration.
    // Create a variable and add it to the loop body scope.
    LocalVariable* loop_var =
       new(Z) LocalVariable(loop_var_assignment_pos,
                            *loop_var_name,
                            loop_var_type);;
    if (loop_var_is_final) {
      loop_var->set_is_final();
    }
    current_block_->scope->AddVariable(loop_var);
    loop_var_assignment = new(Z) StoreLocalNode(
        loop_var_assignment_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_assignment_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(Z) WhileNode(
      forin_pos, label, iterator_moveNext, NULL, 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 = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
    }
  }
  ExpectSemicolon();
  AstNode* condition = NULL;
  SequenceNode* condition_preamble = NULL;
  if (CurrentToken() != Token::kSEMICOLON) {
    condition = ParseAwaitableExpr(
        kAllowConst, kConsumeCascades, &condition_preamble);
  }
  ExpectSemicolon();
  AstNode* increment = NULL;
  const intptr_t incr_pos = TokenPos();
  if (CurrentToken() != Token::kRPAREN) {
    increment = ParseAwaitableExprList();
  }
  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(Z) SequenceNode(incr_pos, NULL);
      incr_sequence->Add(new(Z) CloneContextNode(for_pos));
      if (increment != NULL) {
        incr_sequence->Add(increment);
      }
      increment = incr_sequence;
      break;
    }
  }
  AstNode* for_node = new(Z) ForNode(
      for_pos,
      label,
      NodeAsSequenceNode(init_pos, initializer, NULL),
      condition,
      condition_preamble,
      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(Z, Library::LookupCoreClass(cls_name));
  ASSERT(!cls.IsNull());
  const Function& func = Function::ZoneHandle(Z,
      Resolver::ResolveStatic(cls,
                              func_name,
                              arguments->length(),
                              arguments->names()));
  ASSERT(!func.IsNull());
  return new(Z) StaticCallNode(arguments->token_pos(), func, arguments);
}


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


AstNode* Parser::InsertClosureCallNodes(AstNode* condition) {
  if (condition->IsClosureNode() ||
      (condition->IsStoreLocalNode() &&
       condition->AsStoreLocalNode()->value()->IsClosureNode())) {
    // Function literal in assert implies a call.
    const intptr_t pos = condition->token_pos();
    condition = BuildClosureCall(pos,
                                 condition,
                                 new(Z) 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 (!I->flags().asserts() && !I->flags().type_checks()) {
    SkipExpr();
    ExpectToken(Token::kRPAREN);
    return NULL;
  }
  AstNode* condition = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
  const intptr_t condition_end = TokenPos();
  ExpectToken(Token::kRPAREN);
  condition = InsertClosureCallNodes(condition);
  condition = new(Z) UnaryOpNode(condition_pos, Token::kNOT, condition);
  AstNode* assert_throw = MakeAssertCall(condition_pos, condition_end);
  return new(Z) IfNode(
      condition_pos,
      condition,
      NodeAsSequenceNode(condition_pos, assert_throw, NULL),
      NULL);
}


// Populate local scope of the catch block with the catch parameters.
void Parser::AddCatchParamsToScope(CatchParamDesc* exception_param,
                                   CatchParamDesc* stack_trace_param,
                                   LocalScope* scope) {
  if (exception_param->name != NULL) {
    LocalVariable* var = new(Z) LocalVariable(
        exception_param->token_pos,
        *exception_param->name,
        *exception_param->type);
    var->set_is_final();
    bool added_to_scope = scope->AddVariable(var);
    ASSERT(added_to_scope);
    exception_param->var = var;
  }
  if (stack_trace_param->name != NULL) {
    LocalVariable* var = new(Z) LocalVariable(
        stack_trace_param->token_pos,
        *stack_trace_param->name,
        *stack_trace_param->type);
    var->set_is_final();
    bool added_to_scope = scope->AddVariable(var);
    if (!added_to_scope) {
      // The name of the exception param is reused for the stack trace param.
      ReportError(stack_trace_param->token_pos,
                  "name '%s' already exists in scope",
                  stack_trace_param->name->ToCString());
    }
    stack_trace_param->var = var;
  }
}


// Generate code to load the exception object (:exception_var) into
// the saved exception variable (:saved_exception_var) used to rethrow.
// Generate code to load the stack trace object (:stack_trace_var) into
// the saved stacktrace variable (:saved_stack_trace_var) used to rethrow.
void Parser::SaveExceptionAndStacktrace(SequenceNode* statements,
                                        LocalVariable* exception_var,
                                        LocalVariable* stack_trace_var,
                                        LocalVariable* saved_exception_var,
                                        LocalVariable* saved_stack_trace_var) {
  ASSERT(innermost_function().IsAsyncClosure() ||
         innermost_function().IsAsyncFunction() ||
         innermost_function().IsSyncGenClosure() ||
         innermost_function().IsSyncGenerator() ||
         innermost_function().IsAsyncGenClosure() ||
         innermost_function().IsAsyncGenerator());

  ASSERT(saved_exception_var != NULL);
  ASSERT(exception_var != NULL);
  statements->Add(new(Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      saved_exception_var,
      new(Z) LoadLocalNode(Scanner::kNoSourcePos, exception_var)));

  ASSERT(saved_stack_trace_var != NULL);
  ASSERT(stack_trace_var != NULL);
  statements->Add(new(Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      saved_stack_trace_var,
      new(Z) LoadLocalNode(Scanner::kNoSourcePos, stack_trace_var)));
}


SequenceNode* Parser::EnsureFinallyClause(
    bool parse,
    bool is_async,
    LocalVariable* exception_var,
    LocalVariable* stack_trace_var,
    LocalVariable* rethrow_exception_var,
    LocalVariable* rethrow_stack_trace_var) {
  TRACE_PARSER("EnsureFinallyClause");
  ASSERT(parse || (is_async && (try_stack_ != NULL)));
  OpenBlock();
  if (parse) {
    ExpectToken(Token::kLBRACE);
  }

  if (try_stack_ != NULL) {
    try_stack_->enter_finally();
  }
  // In case of async closures we need to restore the saved try index of an
  // outer try block (if it exists).  The current try block has already been
  // removed from the stack of try blocks.
  if (is_async) {
    if (try_stack_ != NULL) {
      LocalScope* scope = try_stack_->try_block()->scope;
      if (scope->function_level() == current_block_->scope->function_level()) {
        LocalVariable* saved_try_ctx =
            LookupSavedTryContextVar(scope->parent());
        LocalVariable* async_saved_try_ctx =
            LookupAsyncSavedTryContextVar(async_temp_scope_,
                                          try_stack_->try_index());
        current_block_->statements->Add(
            new (Z) StoreLocalNode(
                Scanner::kNoSourcePos,
                saved_try_ctx,
                new (Z) LoadLocalNode(Scanner::kNoSourcePos,
                                      async_saved_try_ctx)));
      }
    }
    // We need to save the exception variables as in catch clauses, whether
    // there is an outer try or not. Note that this is only necessary if the
    // finally clause contains an await or yield.
    // TODO(hausner): Optimize.
    SaveExceptionAndStacktrace(current_block_->statements,
                               exception_var,
                               stack_trace_var,
                               rethrow_exception_var,
                               rethrow_stack_trace_var);
  }

  if (parse) {
    ParseStatementSequence();
    ExpectToken(Token::kRBRACE);
  }
  SequenceNode* finally_clause = CloseBlock();
  if (try_stack_ != NULL) {
    try_stack_->exit_finally();
  }
  return finally_clause;
}


void Parser::PushTry(Block* try_block) {
  intptr_t try_index = AllocateTryIndex();
  try_stack_ = new(Z) TryStack(try_block, try_stack_, try_index);
}


Parser::TryStack* Parser::PopTry() {
  TryStack* innermost_try = try_stack_;
  try_stack_ = try_stack_->outer_try();
  return innermost_try;
}


void Parser::AddNodeForFinallyInlining(AstNode* node) {
  if (node == NULL) {
    return;
  }
  ASSERT(node->IsReturnNode() || node->IsJumpNode());
  TryStack* iterator = try_stack_;
  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();
  }
}


// Add the inlined finally clause to the specified node.
void Parser::AddFinallyClauseToNode(bool is_async,
                                    AstNode* node,
                                    InlinedFinallyNode* finally_clause) {
  ReturnNode* return_node = node->AsReturnNode();
  if (return_node != NULL) {
    parsed_function()->EnsureFinallyReturnTemp(is_async);
    return_node->AddInlinedFinallyNode(finally_clause);
    return;
  }
  JumpNode* jump_node = node->AsJumpNode();
  ASSERT(jump_node != NULL);
  jump_node->AddInlinedFinallyNode(finally_clause);
}


SequenceNode* Parser::ParseCatchClauses(
    intptr_t handler_pos,
    bool is_async,
    LocalVariable* exception_var,
    LocalVariable* stack_trace_var,
    LocalVariable* rethrow_exception_var,
    LocalVariable* rethrow_stack_trace_var,
    const GrowableObjectArray& handler_types,
    bool* needs_stack_trace) {
  // All catch blocks are merged into an if-then-else sequence of the
  // different types specified using the 'is' operator.  While parsing
  // record the type tests (either a ComparisonNode or else the LiteralNode
  // true for a generic catch) and the catch bodies in a pair of parallel
  // lists.  Afterward, construct the nested if-then-else.
  bool generic_catch_seen = false;
  GrowableArray<AstNode*> type_tests;
  GrowableArray<SequenceNode*> catch_blocks;
  while ((CurrentToken() == Token::kCATCH) || IsSymbol(Symbols::On())) {
    // Open a block that contains the if or an unconditional body.  It's
    // closed in the loop that builds the if-then-else nest.
    OpenBlock();
    const intptr_t catch_pos = TokenPos();
    CatchParamDesc exception_param;
    CatchParamDesc stack_trace_param;
    if (IsSymbol(Symbols::On())) {
      ConsumeToken();
      exception_param.type = &AbstractType::ZoneHandle(Z,
          ParseType(ClassFinalizer::kCanonicalize));
    } else {
      exception_param.type = &AbstractType::ZoneHandle(Z, Type::DynamicType());
    }
    if (CurrentToken() == Token::kCATCH) {
      ConsumeToken();  // Consume the 'catch'.
      ExpectToken(Token::kLPAREN);
      exception_param.token_pos = TokenPos();
      exception_param.name = ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kCOMMA) {
        ConsumeToken();
        stack_trace_param.type =
            &AbstractType::ZoneHandle(Z, Type::DynamicType());
        stack_trace_param.token_pos = TokenPos();
        stack_trace_param.name = ExpectIdentifier("identifier expected");
      }
      ExpectToken(Token::kRPAREN);
    }

    // Create a block containing the catch clause parameters and the
    // following code:
    // 1) Store exception object and stack trace object into user-defined
    //    variables (as needed).
    // 2) In async code, save exception object and stack trace object into
    //    captured :saved_exception_var and :saved_stack_trace_var.
    // 3) Nested block with source code from catch clause block.
    OpenBlock();
    AddCatchParamsToScope(&exception_param, &stack_trace_param,
                          current_block_->scope);

    if (exception_param.var != NULL) {
      // Generate code to load the exception object (:exception_var) into
      // the exception variable specified in this block.
      ASSERT(exception_var != NULL);
      current_block_->statements->Add(new(Z) StoreLocalNode(
          catch_pos, exception_param.var, new(Z) LoadLocalNode(
              catch_pos, exception_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 (:stack_trace_var) into the stack
      // trace variable specified in this block.
      *needs_stack_trace = true;
      ASSERT(stack_trace_var != NULL);
      current_block_->statements->Add(new(Z) StoreLocalNode(
          catch_pos, stack_trace_param.var, new(Z) LoadLocalNode(
              catch_pos, stack_trace_var)));
    }

    // Add nested block with user-defined code.  This block allows
    // declarations in the body to shadow the catch parameters.
    CheckToken(Token::kLBRACE);

    current_block_->statements->Add(ParseNestedStatement(false, NULL));
    catch_blocks.Add(CloseBlock());

    const bool is_bad_type =
        exception_param.type->IsMalformed() ||
        exception_param.type->IsMalbounded();
    if (exception_param.type->IsDynamicType() || is_bad_type) {
      // There is no exception type or else it is malformed or malbounded.
      // In the first case, unconditionally execute the catch body.  In the
      // second case, unconditionally throw.
      generic_catch_seen = true;
      type_tests.Add(new(Z) LiteralNode(catch_pos, Bool::True()));
      if (is_bad_type) {
        // Replace the body with one that throws.
        SequenceNode* block = new(Z) SequenceNode(catch_pos, NULL);
        block->Add(ThrowTypeError(catch_pos, *exception_param.type));
        catch_blocks.Last() = block;
      }
      // 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);
    } else {
      // Has a type specification that is not malformed or malbounded.  Now
      // form an 'if type check' to guard the catch handler code.
      if (!exception_param.type->IsInstantiated() &&
          (current_block_->scope->function_level() > 0)) {
        // Make sure that the instantiator is captured.
        CaptureInstantiator();
      }
      TypeNode* exception_type = new(Z) TypeNode(
          catch_pos, *exception_param.type);
      AstNode* exception_value = new(Z) LoadLocalNode(
          catch_pos, exception_var);
      if (!exception_type->type().IsInstantiated()) {
        EnsureExpressionTemp();
      }
      type_tests.Add(new(Z) ComparisonNode(
          catch_pos, Token::kIS, exception_value, exception_type));

      // 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 (!generic_catch_seen && exception_param.type->IsInstantiated()) {
        handler_types.Add(*exception_param.type);
      }
    }

    ASSERT(type_tests.length() == catch_blocks.length());
  }

  // Build the if/then/else nest from the inside out.  Keep the AST simple
  // for the case of a single generic catch clause.  The initial value of
  // current is the last (innermost) else block if there were any catch
  // clauses.
  SequenceNode* current = NULL;
  if (!generic_catch_seen) {
    // There isn't a generic catch clause so create a clause body that
    // rethrows the exception.  This includes the case that there were no
    // catch clauses.
    // An await cannot possibly be executed inbetween the catch entry and here,
    // therefore, it is safe to rethrow the stack-based :exception_var instead
    // of the captured copy :saved_exception_var.
    current = new(Z) SequenceNode(handler_pos, NULL);
    current->Add(new(Z) ThrowNode(
        handler_pos,
        new(Z) LoadLocalNode(handler_pos, exception_var),
        new(Z) LoadLocalNode(handler_pos, stack_trace_var)));
  } else if (type_tests.Last()->IsLiteralNode()) {
    ASSERT(type_tests.Last()->AsLiteralNode()->literal().raw() ==
           Bool::True().raw());
    // The last body is entered unconditionally.  Start building the
    // if/then/else nest with that body as the innermost else block.
    // Note that it is nested inside an extra block which we opened
    // before we knew the body was entered unconditionally.
    type_tests.RemoveLast();
    current_block_->statements->Add(catch_blocks.RemoveLast());
    current = CloseBlock();
  }
  // If the last body was entered conditionally and there is no need to add
  // a rethrow, use an empty else body (current = NULL above).
  while (!type_tests.is_empty()) {
    AstNode* type_test = type_tests.RemoveLast();
    SequenceNode* catch_block = catch_blocks.RemoveLast();
    current_block_->statements->Add(new(Z) IfNode(
        type_test->token_pos(), type_test, catch_block, current));
    current = CloseBlock();
  }
  // In case of async closures, restore :saved_try_context_var before executing
  // the catch clauses.
  if (is_async && (current != NULL)) {
    ASSERT(try_stack_ != NULL);
    SequenceNode* async_code = new(Z) SequenceNode(handler_pos, NULL);
    const TryStack* try_block = try_stack_->outer_try();
    if (try_block != NULL) {
      LocalScope* scope = try_block->try_block()->scope;
      if (scope->function_level() == current_block_->scope->function_level()) {
        LocalVariable* saved_try_ctx =
            LookupSavedTryContextVar(scope->parent());
        LocalVariable* async_saved_try_ctx =
            LookupAsyncSavedTryContextVar(async_temp_scope_,
                                          try_block->try_index());
        async_code->Add(
            new (Z) StoreLocalNode(
                Scanner::kNoSourcePos,
                saved_try_ctx,
                new (Z) LoadLocalNode(Scanner::kNoSourcePos,
                                      async_saved_try_ctx)));
      }
    }
    SaveExceptionAndStacktrace(async_code,
                               exception_var,
                               stack_trace_var,
                               rethrow_exception_var,
                               rethrow_stack_trace_var);
    // The async_code node sequence contains code to restore the context (if
    // an outer try block is present) and code to save the exception and
    // stack trace variables.
    // This async code is inserted before the current node sequence containing
    // the chain of if/then/else handling all catch clauses.
    async_code->Add(current);
    current = async_code;
  }
  return current;
}


void Parser::SetupSavedTryContext(LocalVariable* saved_try_context) {
  const String& async_saved_try_ctx_name = String::ZoneHandle(Z,
      Symbols::New(String::Handle(Z,
          String::NewFormatted("%s%d",
                               Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
                               last_used_try_index_ - 1))));
  LocalVariable* async_saved_try_ctx = new (Z) LocalVariable(
      Scanner::kNoSourcePos,
      async_saved_try_ctx_name,
      Type::ZoneHandle(Z, Type::DynamicType()));
  ASSERT(async_temp_scope_ != NULL);
  async_temp_scope_->AddVariable(async_saved_try_ctx);
  ASSERT(saved_try_context != NULL);
  current_block_->statements->Add(new(Z) StoreLocalNode(
      Scanner::kNoSourcePos,
      async_saved_try_ctx,
      new(Z) LoadLocalNode(Scanner::kNoSourcePos, saved_try_context)));
}


// We create three variables for exceptions:
// ':saved_try_context_var' - Used to save the context before the start of
//                            the try block. The context register is
//                            restored from this variable before
//                            processing the catch block handler.
// ':exception_var' - Used to save the current exception object that was
//                    thrown.
// ':stack_trace_var' - Used to save the current stack trace object which
//                      the stack trace was copied into when an exception
//                      was thrown.
// :exception_var and :stack_trace_var get set with the exception object
// and the stack trace object when an exception is thrown.  These three
// implicit variables can never be captured.
//
// In case of async code, we create two additional variables:
// ':saved_exception_var' - Used to capture the exception object above.
// ':saved_stack_trace_var' - Used to capture the stack trace object above.
void Parser::SetupExceptionVariables(LocalScope* try_scope,
                                     bool is_async,
                                     LocalVariable** context_var,
                                     LocalVariable** exception_var,
                                     LocalVariable** stack_trace_var,
                                     LocalVariable** saved_exception_var,
                                     LocalVariable** saved_stack_trace_var) {
  const Type& dynamic_type = Type::ZoneHandle(Z, Type::DynamicType());
  // Consecutive try statements share the same set of variables.
  *context_var = try_scope->LocalLookupVariable(Symbols::SavedTryContextVar());
  if (*context_var == NULL) {
    *context_var = new(Z) LocalVariable(
        TokenPos(),
        Symbols::SavedTryContextVar(),
        dynamic_type);
    try_scope->AddVariable(*context_var);
  }
  *exception_var = try_scope->LocalLookupVariable(Symbols::ExceptionVar());
  if (*exception_var == NULL) {
    *exception_var = new(Z) LocalVariable(
        TokenPos(),
        Symbols::ExceptionVar(),
        dynamic_type);
    try_scope->AddVariable(*exception_var);
  }
  *stack_trace_var = try_scope->LocalLookupVariable(Symbols::StackTraceVar());
  if (*stack_trace_var == NULL) {
    *stack_trace_var = new(Z) LocalVariable(
        TokenPos(),
        Symbols::StackTraceVar(),
        dynamic_type);
    try_scope->AddVariable(*stack_trace_var);
  }
  if (is_async) {
    *saved_exception_var = try_scope->LocalLookupVariable(
        Symbols::SavedExceptionVar());
    if (*saved_exception_var == NULL) {
      *saved_exception_var = new(Z) LocalVariable(
          TokenPos(),
          Symbols::SavedExceptionVar(),
          dynamic_type);
      try_scope->AddVariable(*saved_exception_var);
    }
    *saved_stack_trace_var = try_scope->LocalLookupVariable(
        Symbols::SavedStackTraceVar());
    if (*saved_stack_trace_var == NULL) {
      *saved_stack_trace_var = new(Z) LocalVariable(
          TokenPos(),
          Symbols::SavedStackTraceVar(),
          dynamic_type);
      try_scope->AddVariable(*saved_stack_trace_var);
    }
  }
}


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

  const intptr_t try_pos = TokenPos();
  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);
  }

  const bool is_async = innermost_function().IsAsyncClosure() ||
                        innermost_function().IsAsyncFunction() ||
                        innermost_function().IsSyncGenClosure() ||
                        innermost_function().IsSyncGenerator() ||
                        innermost_function().IsAsyncGenClosure() ||
                        innermost_function().IsAsyncGenerator();
  LocalVariable* context_var = NULL;
  LocalVariable* exception_var = NULL;
  LocalVariable* stack_trace_var = NULL;
  LocalVariable* saved_exception_var = NULL;
  LocalVariable* saved_stack_trace_var = NULL;
  SetupExceptionVariables(current_block_->scope,
                          is_async,
                          &context_var,
                          &exception_var,
                          &stack_trace_var,
                          &saved_exception_var,
                          &saved_stack_trace_var);

  ConsumeToken();  // Consume the 'try'.

  // Now parse the 'try' block.
  OpenBlock();
  PushTry(current_block_);
  ExpectToken(Token::kLBRACE);

  if (is_async) {
    SetupSavedTryContext(context_var);
  }

  ParseStatementSequence();
  ExpectToken(Token::kRBRACE);
  SequenceNode* try_block = CloseBlock();

  if ((CurrentToken() != Token::kCATCH) && !IsSymbol(Symbols::On()) &&
      (CurrentToken() != Token::kFINALLY)) {
    ReportError("catch or finally clause expected");
  }

  // Now parse the 'catch' blocks if any.
  try_stack_->enter_catch();
  const intptr_t handler_pos = TokenPos();
  const GrowableObjectArray& handler_types =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
  bool needs_stack_trace = false;
  SequenceNode* catch_handler_list =
      ParseCatchClauses(handler_pos,
                        is_async,
                        exception_var,
                        stack_trace_var,
                        is_async ? saved_exception_var : exception_var,
                        is_async ? saved_stack_trace_var : stack_trace_var,
                        handler_types,
                        &needs_stack_trace);

  TryStack* try_statement = PopTry();
  const intptr_t try_index = try_statement->try_index();
  TryStack* outer_try = try_stack_;
  const intptr_t outer_try_index = (outer_try != NULL) ?
      outer_try->try_index() : CatchClauseNode::kInvalidTryIndex;

  // Finally, parse or generate the 'finally' clause.
  // A finally clause is required in async code to restore the saved try context
  // of an existing outer try. Generate a finally clause to this purpose if it
  // is not declared.
  SequenceNode* finally_clause = NULL;
  const bool parse = CurrentToken() == Token::kFINALLY;
  if (parse || (is_async && (try_stack_ != NULL))) {
    if (parse) {
      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 = try_statement->GetNodeToInlineFinally(node_index);
    while (node_to_inline != NULL) {
      finally_clause = EnsureFinallyClause(
          parse,
          is_async,
          exception_var,
          stack_trace_var,
          is_async ? saved_exception_var : exception_var,
          is_async ? saved_stack_trace_var : stack_trace_var);
      InlinedFinallyNode* node = new(Z) InlinedFinallyNode(finally_pos,
                                                           finally_clause,
                                                           context_var,
                                                           outer_try_index);
      AddFinallyClauseToNode(is_async, node_to_inline, node);
      node_index += 1;
      node_to_inline = try_statement->GetNodeToInlineFinally(node_index);
      tokens_iterator_.SetCurrentPosition(finally_pos);
    }
    finally_clause = EnsureFinallyClause(
        parse,
        is_async,
        exception_var,
        stack_trace_var,
        is_async ? saved_exception_var : exception_var,
        is_async ? saved_stack_trace_var : stack_trace_var);
  }

  CatchClauseNode* catch_clause = new(Z) CatchClauseNode(
      handler_pos,
      catch_handler_list,
      Array::ZoneHandle(Z, Array::MakeArray(handler_types)),
      context_var,
      exception_var,
      stack_trace_var,
      is_async ? saved_exception_var : exception_var,
      is_async ? saved_stack_trace_var : stack_trace_var,
      (finally_clause != NULL) ?
          AllocateTryIndex() : CatchClauseNode::kInvalidTryIndex,
      needs_stack_trace);

  // 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(Z) TryCatchNode(
      try_pos, try_block, context_var, catch_clause, finally_clause, 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) {
        ReportError(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(Z) SourceLabel(
            TokenPos(), target_name, SourceLabel::kForward);
        switch_scope->AddLabel(target);
      }
    }
    if (target == NULL) {
      ReportError(jump_pos, "label '%s' not found", target_name.ToCString());
    }
  } else if (FLAG_enable_debug_break && (CurrentToken() == Token::kSTRING)) {
    const char* message = strdup(CurrentLiteral()->ToCString());
    ConsumeToken();
    return new(Z) StopNode(jump_pos, message);
  } else {
    target = current_block_->scope->LookupInnermostLabel(jump_kind);
    if (target == NULL) {
      ReportError(jump_pos, "'%s' is illegal here", Token::Str(jump_kind));
    }
  }
  ASSERT(target != NULL);
  if (jump_kind == Token::kCONTINUE) {
    if (target->kind() == SourceLabel::kSwitch) {
      ReportError(jump_pos, "'continue' jump to switch statement is illegal");
    } else if (target->kind() == SourceLabel::kStatement) {
      ReportError(jump_pos, "'continue' jump to label '%s' is illegal",
                  target->name().ToCString());
    }
  }
  if (jump_kind == Token::kBREAK && target->kind() == SourceLabel::kCase) {
    ReportError(jump_pos, "'break' to case clause label is illegal");
  }
  if (target->FunctionLevel() != current_block_->scope->function_level()) {
    ReportError(jump_pos, "'%s' target must be in same function context",
                Token::Str(jump_kind));
  }
  return new(Z) JumpNode(jump_pos, jump_kind, target);
}


AstNode* Parser::ParseYieldStatement() {
  bool is_yield_each = false;
  const intptr_t yield_pos = TokenPos();
  ConsumeToken();  // yield reserved word.
  if (CurrentToken() == Token::kMUL) {
    is_yield_each = true;
    ConsumeToken();
  }
  if (!innermost_function().IsGenerator() &&
      !innermost_function().IsGeneratorClosure()) {
    ReportError(yield_pos,
                "yield%s statement only allowed in generator functions",
                is_yield_each ? "*" : "");
  }

  AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);

  LetNode* yield = new(Z) LetNode(yield_pos);
  if (innermost_function().IsSyncGenerator() ||
      innermost_function().IsSyncGenClosure()) {
    // Yield statement in sync* function.

    LocalVariable* iterator_param =
        LookupLocalScope(Symbols::IteratorParameter());
    ASSERT(iterator_param != NULL);
    // Generate :iterator.current = expr;
    AstNode* iterator =
        new(Z) LoadLocalNode(Scanner::kNoSourcePos, iterator_param);
    AstNode* store_current =
        new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
                                  iterator,
                                  String::ZoneHandle(Symbols::Current().raw()),
                                  expr);
    yield->AddNode(store_current);
    if (is_yield_each) {
      // Generate :iterator.isYieldEach = true;
      AstNode* set_is_yield_each =
          new(Z) InstanceSetterNode(Scanner::kNoSourcePos,
              iterator,
              String::ZoneHandle(Symbols::IsYieldEach().raw()),
              new(Z) LiteralNode(TokenPos(), Bool::True()));
      yield->AddNode(set_is_yield_each);
    }
    AwaitMarkerNode* await_marker =
        new(Z) AwaitMarkerNode(async_temp_scope_, current_block_->scope);
    yield->AddNode(await_marker);
    // Return true to indicate that a value has been generated.
    ReturnNode* return_true = new(Z) ReturnNode(yield_pos,
        new(Z) LiteralNode(TokenPos(), Bool::True()));
    return_true->set_return_type(ReturnNode::kContinuationTarget);
    yield->AddNode(return_true);

    // If this expression is part of a try block, also append the code for
    // restoring the saved try context that lives on the stack and possibly the
    // saved try context of the outer try block.
    LocalVariable* saved_try_ctx;
    LocalVariable* async_saved_try_ctx;
    LocalVariable* outer_saved_try_ctx;
    LocalVariable* outer_async_saved_try_ctx;
    CheckAsyncOpInTryBlock(&saved_try_ctx,
                           &async_saved_try_ctx,
                           &outer_saved_try_ctx,
                           &outer_async_saved_try_ctx);
    if (saved_try_ctx != NULL) {
      yield->AddNode(new (Z) StoreLocalNode(
          Scanner::kNoSourcePos,
          saved_try_ctx,
          new (Z) LoadLocalNode(Scanner::kNoSourcePos,
                                async_saved_try_ctx)));
      if (outer_saved_try_ctx != NULL) {
        yield->AddNode(new (Z) StoreLocalNode(
            Scanner::kNoSourcePos,
            outer_saved_try_ctx,
            new (Z) LoadLocalNode(Scanner::kNoSourcePos,
                                  outer_async_saved_try_ctx)));
      }
    } else {
      ASSERT(outer_saved_try_ctx == NULL);
    }
  } else {
    // yield statement in async* function.
    ASSERT(innermost_function().IsAsyncGenerator() ||
           innermost_function().IsAsyncGenClosure());

    LocalVariable* controller_var = LookupLocalScope(Symbols::Controller());
    ASSERT(controller_var != NULL);
    // :controller.add[Stream](expr);
    ArgumentListNode* add_args = new(Z) ArgumentListNode(yield_pos);
    add_args->Add(expr);
    AstNode* add_call =
        new(Z) InstanceCallNode(yield_pos,
            new(Z) LoadLocalNode(Scanner::kNoSourcePos, controller_var),
            is_yield_each ? Symbols::AddStream() : Symbols::add(),
            add_args);

    // if (:controller.add[Stream](expr)) {
    //   return;
    // }
    // await_marker;
    // continuation_return;
    // restore saved_try_context

    SequenceNode* true_branch =
        new(Z) SequenceNode(Scanner::kNoSourcePos, NULL);
    AstNode* return_from_generator = new(Z) ReturnNode(yield_pos);
    true_branch->Add(return_from_generator);
    AddNodeForFinallyInlining(return_from_generator);
    AstNode* if_is_cancelled =
       new(Z) IfNode(Scanner::kNoSourcePos, add_call, true_branch, NULL);
    yield->AddNode(if_is_cancelled);

    AwaitMarkerNode* await_marker =
        new(Z) AwaitMarkerNode(async_temp_scope_, current_block_->scope);
    yield->AddNode(await_marker);
    ReturnNode* continuation_return = new(Z) ReturnNode(yield_pos);
    continuation_return->set_return_type(ReturnNode::kContinuationTarget);
    yield->AddNode(continuation_return);

    // If this expression is part of a try block, also append the code for
    // restoring the saved try context that lives on the stack and possibly the
    // saved try context of the outer try block.
    LocalVariable* saved_try_ctx;
    LocalVariable* async_saved_try_ctx;
    LocalVariable* outer_saved_try_ctx;
    LocalVariable* outer_async_saved_try_ctx;
    CheckAsyncOpInTryBlock(&saved_try_ctx,
                           &async_saved_try_ctx,
                           &outer_saved_try_ctx,
                           &outer_async_saved_try_ctx);
    if (saved_try_ctx != NULL) {
      yield->AddNode(new (Z) StoreLocalNode(
          Scanner::kNoSourcePos,
          saved_try_ctx,
          new (Z) LoadLocalNode(Scanner::kNoSourcePos,
                                async_saved_try_ctx)));
      if (outer_saved_try_ctx != NULL) {
        yield->AddNode(new (Z) StoreLocalNode(
            Scanner::kNoSourcePos,
            outer_saved_try_ctx,
            new (Z) LoadLocalNode(Scanner::kNoSourcePos,
                                  outer_async_saved_try_ctx)));
      }
    } else {
      ASSERT(outer_saved_try_ctx == NULL);
    }
  }
  return yield;
}


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();
  const Token::Kind token = CurrentToken();

  if (token == Token::kWHILE) {
    statement = ParseWhileStatement(label_name);
  } else if (token == Token::kFOR) {
    statement = ParseForStatement(label_name);
  } else if (IsAwaitKeyword() && (LookaheadToken(1) == Token::kFOR)) {
    statement = ParseAwaitForStatement(label_name);
  } else if (token == Token::kDO) {
    statement = ParseDoWhileStatement(label_name);
  } else if (token == Token::kSWITCH) {
    statement = ParseSwitchStatement(label_name);
  } else if (token == Token::kTRY) {
    statement = ParseTryStatement(label_name);
  } else if (token == Token::kRETURN) {
    const intptr_t return_pos = TokenPos();
    ConsumeToken();
    if (CurrentToken() != Token::kSEMICOLON) {
      const intptr_t expr_pos = TokenPos();
      if (current_function().IsGenerativeConstructor() &&
          (current_block_->scope->function_level() == 0)) {
        ReportError(expr_pos,
                    "return of a value is not allowed in constructors");
      } else if (current_function().IsGeneratorClosure() &&
          (current_block_->scope->function_level() == 0)) {
        ReportError(expr_pos, "generator functions may not return a value");
      }
      AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
      statement = new(Z) ReturnNode(statement_pos, expr);
    } else {
      if (current_function().IsSyncGenClosure() &&
          (current_block_->scope->function_level() == 0)) {
        // In a synchronous generator, return without an expression
        // returns false, signaling that the iterator terminates and
        // did not yield a value.
        statement = new(Z) ReturnNode(statement_pos,
            new(Z) LiteralNode(return_pos, Bool::False()));
      } else {
        statement = new(Z) ReturnNode(statement_pos);
      }
    }
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (IsYieldKeyword()) {
    statement = ParseYieldStatement();
    ExpectSemicolon();
  } else if (token == Token::kIF) {
    statement = ParseIfStatement(label_name);
  } else if (token == Token::kASSERT) {
    statement = ParseAssertStatement();
    ExpectSemicolon();
  } else if (IsVariableDeclaration()) {
    statement = ParseVariableDeclarationList();
    ExpectSemicolon();
  } else if (IsFunctionDeclaration()) {
    statement = ParseFunctionStatement(false);
  } else if (token == 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 (token == Token::kBREAK) {
    statement = ParseJump(label_name);
    if ((statement != NULL) && !statement->IsStopNode()) {
      AddNodeForFinallyInlining(statement);
    }
    ExpectSemicolon();
  } else if (token == Token::kCONTINUE) {
    statement = ParseJump(label_name);
    AddNodeForFinallyInlining(statement);
    ExpectSemicolon();
  } else if (token == Token::kSEMICOLON) {
    // Empty statement, nothing to do.
    ConsumeToken();
  } else if (token == Token::kRETHROW) {
    // Rethrow of current exception.
    ConsumeToken();
    ExpectSemicolon();
    // Check if it is ok to do a rethrow.
    if ((try_stack_ == NULL) || !try_stack_->inside_catch()) {
      ReportError(statement_pos, "rethrow of an exception is not valid here");
    }

    // If in async code, use :saved_exception_var and :saved_stack_trace_var
    // instead of :exception_var and :stack_trace_var.
    // These variables are bound in the block containing the try.
    // Look in the try scope directly.
    LocalScope* scope = try_stack_->try_block()->scope->parent();
    ASSERT(scope != NULL);
    LocalVariable* excp_var;
    LocalVariable* trace_var;
    if (innermost_function().IsAsyncClosure() ||
        innermost_function().IsAsyncFunction() ||
        innermost_function().IsSyncGenClosure() ||
        innermost_function().IsSyncGenerator() ||
        innermost_function().IsAsyncGenClosure() ||
        innermost_function().IsAsyncGenerator()) {
      excp_var = scope->LocalLookupVariable(Symbols::SavedExceptionVar());
      trace_var = scope->LocalLookupVariable(Symbols::SavedStackTraceVar());
    } else {
      excp_var = scope->LocalLookupVariable(Symbols::ExceptionVar());
      trace_var = scope->LocalLookupVariable(Symbols::StackTraceVar());
    }
    ASSERT(excp_var != NULL);
    ASSERT(trace_var != NULL);

    statement = new(Z) ThrowNode(
        statement_pos,
        new(Z) LoadLocalNode(statement_pos, excp_var),
        new(Z) LoadLocalNode(statement_pos, trace_var));
  } else {
    statement = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
    ExpectSemicolon();
  }
  return statement;
}


void Parser::ReportError(const Error& error) {
  Report::LongJump(error);
  UNREACHABLE();
}


void Parser::ReportErrors(const Error& prev_error,
                          const Script& script, intptr_t token_pos,
                          const char* format, ...) {
  va_list args;
  va_start(args, format);
  Report::LongJumpV(prev_error, script, token_pos, format, args);
  va_end(args);
  UNREACHABLE();
}


void Parser::ReportError(intptr_t token_pos, const char* format, ...) const {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kError, script_, token_pos, format, args);
  va_end(args);
  UNREACHABLE();
}


void Parser::ReportError(const char* format, ...) const {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kError, script_, TokenPos(), format, args);
  va_end(args);
  UNREACHABLE();
}


void Parser::ReportWarning(intptr_t token_pos, const char* format, ...) const {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kWarning, script_, token_pos, format, args);
  va_end(args);
}


void Parser::ReportWarning(const char* format, ...) const {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kWarning, script_, TokenPos(), format, args);
  va_end(args);
}


void Parser::CheckToken(Token::Kind token_expected, const char* msg) {
  if (CurrentToken() != token_expected) {
    if (msg != NULL) {
      ReportError("%s", msg);
    } else {
      ReportError("'%s' expected", Token::Str(token_expected));
    }
  }
}


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


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


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


String* Parser::ExpectUserDefinedTypeIdentifier(const char* msg) {
  if (CurrentToken() != Token::kIDENT) {
    ReportError("%s", msg);
  }
  String* ident = CurrentLiteral();
  if (ident->Equals("dynamic")) {
    ReportError("%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()) {
    ReportError("%s", msg);
  }
  String* ident = CurrentLiteral();
  ConsumeToken();
  return ident;
}


bool Parser::IsAwaitKeyword() {
  return await_is_keyword_ && IsSymbol(Symbols::Await());
}


bool Parser::IsYieldKeyword() {
  return await_is_keyword_ && IsSymbol(Symbols::YieldKw());
}


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();
}


// Call _throwNewIfNotLoaded if prefix is not NULL, otherwise call _throwNew.
AstNode* Parser::ThrowTypeError(intptr_t type_pos, const AbstractType& type,
                                LibraryPrefix* prefix) {
  ArgumentListNode* arguments = new(Z) ArgumentListNode(type_pos);

  String& method_name = String::Handle(Z);
  if (prefix == NULL) {
    method_name = Library::PrivateCoreLibName(Symbols::ThrowNew()).raw();
  } else {
    arguments->Add(new(Z) LiteralNode(type_pos, *prefix));
    method_name = Library::PrivateCoreLibName(
        Symbols::ThrowNewIfNotLoaded()).raw();
  }
  // Location argument.
  arguments->Add(new(Z) LiteralNode(
      type_pos, Integer::ZoneHandle(Z, Integer::New(type_pos))));
  // Src value argument.
  arguments->Add(new(Z) LiteralNode(type_pos, Instance::ZoneHandle(Z)));
  // Dst type name argument.
  arguments->Add(new(Z) LiteralNode(type_pos, Symbols::Malformed()));
  // Dst name argument.
  arguments->Add(new(Z) LiteralNode(type_pos, Symbols::Empty()));
  // Malformed type error or malbounded type error.
  const Error& error = Error::Handle(Z, type.error());
  ASSERT(!error.IsNull());
  arguments->Add(new(Z) LiteralNode(type_pos, String::ZoneHandle(Z,
      Symbols::New(error.ToErrorCString()))));
  return MakeStaticCall(Symbols::TypeError(), method_name, arguments);
}


// Call _throwNewIfNotLoaded if prefix is not NULL, otherwise call _throwNew.
AstNode* Parser::ThrowNoSuchMethodError(intptr_t call_pos,
                                        const Class& cls,
                                        const String& function_name,
                                        ArgumentListNode* function_arguments,
                                        InvocationMirror::Call im_call,
                                        InvocationMirror::Type im_type,
                                        const Function* func,
                                        const LibraryPrefix* prefix) {
  ArgumentListNode* arguments = new(Z) ArgumentListNode(call_pos);

  String& method_name = String::Handle(Z);
  if (prefix == NULL) {
    method_name = Library::PrivateCoreLibName(Symbols::ThrowNew()).raw();
  } else {
    arguments->Add(new(Z) LiteralNode(call_pos, *prefix));
    method_name = Library::PrivateCoreLibName(
        Symbols::ThrowNewIfNotLoaded()).raw();
  }
  // Object receiver.
  // If the function is external and dynamic, pass the actual receiver,
  // otherwise, pass a class literal of the unresolved method's owner.
  if ((func != NULL) && !func->IsNull() &&
      func->is_external() && !func->is_static()) {
    arguments->Add(LoadReceiver(func->token_pos()));
  } else {
    Type& type = Type::ZoneHandle(Z,
        Type::New(cls, TypeArguments::Handle(Z), call_pos, Heap::kOld));
    type ^= ClassFinalizer::FinalizeType(
        current_class(), type, ClassFinalizer::kCanonicalize);
    arguments->Add(new(Z) LiteralNode(call_pos, type));
  }
  // String memberName.
  arguments->Add(new(Z) LiteralNode(
      call_pos, String::ZoneHandle(Z, 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(Z) LiteralNode(call_pos, Smi::ZoneHandle(Z,
      Smi::New(InvocationMirror::EncodeType(im_call, im_type)))));
  // List arguments.
  if (function_arguments == NULL) {
    arguments->Add(new(Z) LiteralNode(call_pos, Array::ZoneHandle(Z)));
  } else {
    ArrayNode* array = new(Z) ArrayNode(
        call_pos,
        Type::ZoneHandle(Z, Type::ArrayType()),
        function_arguments->nodes());
    arguments->Add(array);
  }
  // List argumentNames.
  if (function_arguments == NULL) {
    arguments->Add(new(Z) LiteralNode(call_pos, Array::ZoneHandle(Z)));
  } else {
    arguments->Add(new(Z) LiteralNode(call_pos, function_arguments->names()));
  }

  // List existingArgumentNames.
  // Check if there exists a function with the same name unless caller
  // has done the lookup already. If there is a function with the same
  // name but incompatible parameters, inform the NoSuchMethodError what the
  // expected parameters are.
  Function& function = Function::Handle(Z);
  if (func != NULL) {
    function = func->raw();
  } else {
    function = cls.LookupStaticFunction(function_name);
  }
  Array& array = Array::ZoneHandle(Z);
  // An unpatched external function is treated as an unresolved function.
  if (!function.IsNull() && !function.is_external()) {
    // The constructor for NoSuchMethodError takes a list of existing
    // parameter names to produce a descriptive error message explaining
    // the parameter mismatch. The problem is that the array of names
    // does not describe which parameters are optional positional or
    // named, which can lead to confusing error messages.
    // Since the NoSuchMethodError class only uses the list to produce
    // a string describing the expected parameters, we construct a more
    // descriptive string here and pass it as the only element of the
    // "existingArgumentNames" array of the NoSuchMethodError constructor.
    // TODO(13471): Separate the implementations of NoSuchMethodError
    // between dart2js and VM. Update the constructor to accept a string
    // describing the formal parameters of an incompatible call target.
    array = Array::New(1, Heap::kOld);
    array.SetAt(0, String::Handle(Z, function.UserVisibleFormalParameters()));
  }
  arguments->Add(new(Z) LiteralNode(call_pos, array));

  return MakeStaticCall(Symbols::NoSuchMethodError(), method_name, arguments);
}


AstNode* Parser::ParseBinaryExpr(int min_preced) {
  TRACE_PARSER("ParseBinaryExpr");
  ASSERT(min_preced >= Token::Precedence(Token::kIFNULL));
  AstNode* left_operand = ParseUnaryExpr();
  if (left_operand->IsPrimaryNode() &&
      (left_operand->AsPrimaryNode()->IsSuper())) {
    ReportError(left_operand->token_pos(), "illegal use of 'super'");
  }
  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(Z,
            ParseType(ClassFinalizer::kCanonicalize));
        if (!type.IsInstantiated() &&
            (current_block_->scope->function_level() > 0)) {
          // Make sure that the instantiator is captured.
          CaptureInstantiator();
        }
        right_operand = new(Z) TypeNode(type_pos, type);
        // In production mode, the type may be malformed.
        // In checked mode, the type may be malformed or malbounded.
        if (((op_kind == Token::kIS) || (op_kind == Token::kISNOT) ||
             (op_kind == Token::kAS)) &&
            type.IsMalformedOrMalbounded()) {
          // Note that a type error is thrown in a type test or in
          // a type cast even if the tested value is null.
          // We need to evaluate the left operand for potential
          // side effects.
          LetNode* let = new(Z) LetNode(left_operand->token_pos());
          let->AddNode(left_operand);
          let->AddNode(ThrowTypeError(type_pos, type));
          left_operand = let;
          break;  // Type checks and casts can't be chained.
        }
      }
      if (Token::IsRelationalOperator(op_kind)
          || Token::IsTypeTestOperator(op_kind)
          || Token::IsTypeCastOperator(op_kind)
          || Token::IsEqualityOperator(op_kind)) {
        left_operand = new(Z) 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::ParseAwaitableExprList() {
  TRACE_PARSER("ParseAwaitableExprList");
  SequenceNode* preamble = NULL;
  AstNode* expressions = ParseAwaitableExpr(
      kAllowConst, kConsumeCascades, &preamble);
  if (preamble != NULL) {
    preamble->Add(expressions);
    expressions = preamble;
  }
  if (CurrentToken() == Token::kCOMMA) {
    // Collect comma-separated expressions in a non scope owning sequence node.
    SequenceNode* list = new(Z) SequenceNode(TokenPos(), NULL);
    list->Add(expressions);
    while (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
      preamble = NULL;
      AstNode* expr = ParseAwaitableExpr(
          kAllowConst, kConsumeCascades, &preamble);
      if (preamble != NULL) {
        list->Add(preamble);
      }
      list->Add(expr);
    }
    expressions = list;
  }
  return expressions;
}


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


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(Z) LocalVariable(
      token_pos,
      String::ZoneHandle(Z, Symbols::New(name)),
      Type::ZoneHandle(Z, 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(Z,
            Double::NewCanonical((left_double / right_double)));
        return new(Z) LiteralNode(op_pos, dbl_obj);
      }
    }
  }
  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(Z) BinaryOpWithMask32Node(
              old->token_pos(), old->kind(), old->left(), old->right(), val);
          return binop;
        }
      }
    }
  }
  return new(Z) 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(Z) BinaryOpNode(op_pos, Token::kADD, lhs, rhs);
    case Token::kASSIGN_SUB:
      return new(Z) BinaryOpNode(op_pos, Token::kSUB, lhs, rhs);
    case Token::kASSIGN_MUL:
      return new(Z) BinaryOpNode(op_pos, Token::kMUL, lhs, rhs);
    case Token::kASSIGN_TRUNCDIV:
      return new(Z) BinaryOpNode(op_pos, Token::kTRUNCDIV, lhs, rhs);
    case Token::kASSIGN_DIV:
      return new(Z) BinaryOpNode(op_pos, Token::kDIV, lhs, rhs);
    case Token::kASSIGN_MOD:
      return new(Z) BinaryOpNode(op_pos, Token::kMOD, lhs, rhs);
    case Token::kASSIGN_SHR:
      return new(Z) BinaryOpNode(op_pos, Token::kSHR, lhs, rhs);
    case Token::kASSIGN_SHL:
      return new(Z) BinaryOpNode(op_pos, Token::kSHL, lhs, rhs);
    case Token::kASSIGN_OR:
      return new(Z) BinaryOpNode(op_pos, Token::kBIT_OR, lhs, rhs);
    case Token::kASSIGN_AND:
      return new(Z) BinaryOpNode(op_pos, Token::kBIT_AND, lhs, rhs);
    case Token::kASSIGN_XOR:
      return new(Z) BinaryOpNode(op_pos, Token::kBIT_XOR, lhs, rhs);
    case Token::kASSIGN_COND:
      return new(Z) BinaryOpNode(op_pos, Token::kIFNULL, lhs, rhs);
    default:
      ReportError(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.
LiteralNode* Parser::FoldConstExpr(intptr_t expr_pos, AstNode* expr) {
  if (expr->IsLiteralNode()) {
    return expr->AsLiteralNode();
  }
  if (expr->EvalConstExpr() == NULL) {
    ReportError(expr_pos, "expression is not a valid compile-time constant");
  }
  return new(Z) LiteralNode(
      expr_pos, EvaluateConstExpr(expr_pos, expr));
}


LetNode* Parser::PrepareCompoundAssignmentNodes(AstNode** expr) {
  AstNode* node = *expr;
  intptr_t token_pos = node->token_pos();
  LetNode* result = new(Z) 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(Z) LoadLocalNode(token_pos, t0);
    }
    if (!IsSimpleLocalOrLiteralNode(load_indexed->index_expr())) {
      LocalVariable* t1 = result->AddInitializer(
          load_indexed->index_expr());
      index = new(Z) LoadLocalNode(token_pos, t1);
    }
    *expr = new(Z) 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(Z) LoadLocalNode(token_pos, t0);
    }
    *expr = new(Z) InstanceGetterNode(
        token_pos, receiver, getter->field_name(), getter->is_conditional());
    return result;
  }
  return result;
}


// Check whether the syntax of expression expr is a grammatically legal
// assignable expression. This check is used to detect situations where
// the expression itself is assignable, but the source is grammatically
// wrong. The AST representation of an expression cannot distinguish
// between x = 0 and (x) = 0. The latter is illegal.
// A syntactically legal assignable expression always ends with an
// identifier token or a ] token. We rewind the token iterator and
// check whether the token before end_pos is an identifier or ].
bool Parser::IsLegalAssignableSyntax(AstNode* expr, intptr_t end_pos) {
  ASSERT(expr->token_pos() >= 0);
  ASSERT(expr->token_pos() < end_pos);
  SetPosition(expr->token_pos());
  Token::Kind token = Token::kILLEGAL;
  while (TokenPos() < end_pos) {
    token = CurrentToken();
    ConsumeToken();
  }
  ASSERT(TokenPos() == end_pos);
  return Token::IsIdentifier(token) || (token == Token::kRBRACK);
}


AstNode* Parser::CreateAssignmentNode(AstNode* original,
                                      AstNode* rhs,
                                      const String* left_ident,
                                      intptr_t left_pos,
                                      bool is_compound /* = false */) {
  AstNode* result = original->MakeAssignmentNode(rhs);
  if (result == NULL) {
    String& name = String::ZoneHandle(Z);
    const Class* target_cls = &current_class();
    if (original->IsTypeNode()) {
      name = Symbols::New(original->AsTypeNode()->TypeName());
    } else if (original->IsLoadStaticFieldNode()) {
      name = original->AsLoadStaticFieldNode()->field().name();
      target_cls = &Class::Handle(Z,
          original->AsLoadStaticFieldNode()->field().owner());
    } else if ((left_ident != NULL) &&
               (original->IsLiteralNode() ||
                original->IsLoadLocalNode())) {
      name = left_ident->raw();
    }
    if (name.IsNull()) {
      ReportError(left_pos, "expression is not assignable");
    }
    LetNode* let_node = new(Z) LetNode(left_pos);
    let_node->AddInitializer(rhs);
    let_node->AddNode(ThrowNoSuchMethodError(
         original->token_pos(),
         *target_cls,
         String::Handle(Z, Field::SetterName(name)),
         NULL,  // No arguments.
         InvocationMirror::kStatic,
         original->IsLoadLocalNode() ?
         InvocationMirror::kLocalVar : InvocationMirror::kSetter,
         NULL));  // No existing function.
    result = let_node;
  }
  // The compound assignment operator a ??= b is different from other
  // a op= b assignments. If a is non-null, the assignment to a must be
  // dropped:
  // normally: a op= b ==> a = a op b
  // however:  a ??= b ==> a ?? (a = b)
  // Therefore, we need to transform a = (a ?? b) into a ?? (a = b)
  if (is_compound &&
      rhs->IsBinaryOpNode() &&
      (rhs->AsBinaryOpNode()->kind() == Token::kIFNULL)) {
    BinaryOpNode* ifnull = rhs->AsBinaryOpNode();
    AstNode* modified_assign =
        CreateAssignmentNode(original,
                             ifnull->right(),
                             left_ident,
                             left_pos);
    result = new(Z) BinaryOpNode(rhs->token_pos(),
                                 Token::kIFNULL,
                                 ifnull->left(),
                                 modified_assign);
  }
  return result;
}


AstNode* Parser::ParseCascades(AstNode* expr) {
  intptr_t cascade_pos = TokenPos();
  LetNode* cascade = new(Z) LetNode(cascade_pos);
  LocalVariable* cascade_receiver_var = cascade->AddInitializer(expr);
  while (CurrentToken() == Token::kCASCADE) {
    cascade_pos = TokenPos();
    LoadLocalNode* load_cascade_receiver =
        new(Z) 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 {
      ReportError("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, true);
        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(Z) LoadLocalNode(cascade_pos, cascade_receiver_var));
  return cascade;
}


// Convert loading of a static const field into a literal node.
static AstNode* LiteralIfStaticConst(Zone* zone, AstNode* expr) {
  if (expr->IsLoadStaticFieldNode()) {
    const Field& field = expr->AsLoadStaticFieldNode()->field();
    if (field.is_const() &&
        !expr->AsLoadStaticFieldNode()->is_deferred_reference()) {
      ASSERT(field.value() != Object::sentinel().raw());
      ASSERT(field.value() != Object::transition_sentinel().raw());
      return new(zone) LiteralNode(expr->token_pos(),
                                   Instance::ZoneHandle(zone, field.value()));
    }
  }
  return expr;
}


AstNode* Parser::ParseAwaitableExpr(bool require_compiletime_const,
                                    bool consume_cascades,
                                    SequenceNode** await_preamble) {
  TRACE_PARSER("ParseAwaitableExpr");
  BoolScope saved_seen_await(&parsed_function()->have_seen_await_expr_, false);
  AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
  if (parsed_function()->have_seen_await()) {
    // Make sure we do not reuse the scope to avoid creating contexts that we
    // are unaware of, i.e, creating contexts that have already been covered.
    // See FlowGraphBuilder::VisitSequenceNode() for details on when contexts
    // are created.
    OpenBlock();
    AwaitTransformer at(current_block_->statements, async_temp_scope_);
    AstNode* result = at.Transform(expr);
    SequenceNode* preamble = CloseBlock();
    if (await_preamble == NULL) {
      current_block_->statements->Add(preamble);
    } else {
      *await_preamble = preamble;
    }
    return result;
  }
  return expr;
}


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) {
    if (require_compiletime_const) {
      ReportError("'throw expr' is not a valid compile-time constant");
    }
    ConsumeToken();
    if (CurrentToken() == Token::kSEMICOLON) {
      ReportError("expression expected after throw");
    }
    AstNode* expr = ParseExpr(require_compiletime_const, consume_cascades);
    return new(Z) ThrowNode(expr_pos, expr, NULL);
  }

  if (require_compiletime_const) {
    // Check whether we already have evaluated a compile-time constant
    // at this source location.
    Instance& existing_const = Instance::ZoneHandle(Z);
    if (GetCachedConstant(expr_pos, &existing_const)) {
      SkipConditionalExpr();
      return new(Z) LiteralNode(expr_pos, existing_const);
    }
  }

  AstNode* expr = ParseConditionalExpr();
  if (!Token::IsAssignmentOperator(CurrentToken())) {
    if ((CurrentToken() == Token::kCASCADE) && consume_cascades) {
      return ParseCascades(expr);
    }
    if (require_compiletime_const) {
      const bool use_cache = !expr->IsLiteralNode();
      LiteralNode* const_value = FoldConstExpr(expr_pos, expr);
      if (use_cache) CacheConstantValue(expr_pos, const_value->literal());
      expr = const_value;
    } else {
      expr = LiteralIfStaticConst(Z, expr);
    }
    return expr;
  }
  // Assignment expressions.
  if (!IsLegalAssignableSyntax(expr, TokenPos())) {
    ReportError(expr_pos, "expression is not assignable");
  }
  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)) {
    ReportError(right_expr_pos,
                "expression is not a valid 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, true);
    ASSERT(assign_expr != NULL);
    let_expr->AddNode(assign_expr);
    return let_expr;
  } else {
    AstNode* assigned_value = LiteralIfStaticConst(Z, 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");
  intptr_t expr_pos = TokenPos();
  AstNode* expr = ParseExpr(kRequireConst, kNoCascades);
  if (!expr->IsLiteralNode()) {
    ReportError(expr_pos, "expression must be a compile-time constant");
  }
  return expr->AsLiteralNode();
}


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


AstNode* Parser::ParseUnaryExpr() {
  TRACE_PARSER("ParseUnaryExpr");
  AstNode* expr = NULL;
  const intptr_t op_pos = TokenPos();
  if (IsAwaitKeyword()) {
    TRACE_PARSER("ParseAwaitExpr");
    if (!innermost_function().IsAsyncFunction() &&
        !innermost_function().IsAsyncClosure() &&
        !innermost_function().IsAsyncGenerator() &&
        !innermost_function().IsAsyncGenClosure()) {
      ReportError("await operator is only allowed in an asynchronous function");
    }
    ConsumeToken();
    parsed_function()->record_await();

    LocalVariable* saved_try_ctx;
    LocalVariable* async_saved_try_ctx;
    LocalVariable* outer_saved_try_ctx;
    LocalVariable* outer_async_saved_try_ctx;
    CheckAsyncOpInTryBlock(&saved_try_ctx,
                           &async_saved_try_ctx,
                           &outer_saved_try_ctx,
                           &outer_async_saved_try_ctx);
    expr = new (Z) AwaitNode(op_pos,
                             ParseUnaryExpr(),
                             saved_try_ctx,
                             async_saved_try_ctx,
                             outer_saved_try_ctx,
                             outer_async_saved_try_ctx,
                             current_block_->scope);
  } else 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();
    if (!IsLegalAssignableSyntax(expr, TokenPos())) {
      ReportError(expr_pos, "expression is not assignable");
    }
    // Is prefix.
    LetNode* let_expr = PrepareCompoundAssignmentNodes(&expr);
    Token::Kind binary_op =
        (incr_op == Token::kINCR) ? Token::kADD : Token::kSUB;
    BinaryOpNode* add = new(Z) BinaryOpNode(
        op_pos,
        binary_op,
        expr,
        new(Z) LiteralNode(op_pos, Smi::ZoneHandle(Z, Smi::New(1))));
    AstNode* store =
        CreateAssignmentNode(expr, add, expr_ident, expr_pos, true);
    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(Z) ArgumentListNode(TokenPos());
  } else {
    arguments = implicit_arguments;
  }
  const GrowableObjectArray& names =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New(Heap::kOld));
  bool named_argument_seen = false;
  if (LookaheadToken(1) != Token::kRPAREN) {
    String& arg_name = String::Handle(Z);
    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)) {
            ReportError("duplicate named argument");
          }
        }
        names.Add(*CurrentLiteral(), Heap::kOld);
        ConsumeToken();  // ident.
        ConsumeToken();  // colon.
      } else if (named_argument_seen) {
        ReportError("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(Z, 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(Z,
      Resolver::ResolveStatic(cls,
                              func_name,
                              num_arguments,
                              arguments->names()));
  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(Z, cls.LookupStaticField(func_name));
    Function& func = Function::ZoneHandle(Z);
    if (field.IsNull()) {
      // No field, check if we have an explicit getter function.
      const String& getter_name =
          String::ZoneHandle(Z, Field::GetterName(func_name));
      const int kNumArguments = 0;  // no arguments.
      func = Resolver::ResolveStatic(cls,
                                     getter_name,
                                     kNumArguments,
                                     Object::empty_array());
      if (!func.IsNull()) {
        ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
        closure = new(Z) StaticGetterNode(
            call_pos,
            NULL,
            Class::ZoneHandle(Z, cls.raw()),
            func_name);
        return BuildClosureCall(call_pos, closure, arguments);
      }
    } else {
      closure = GenerateStaticFieldLookup(field, call_pos);
      return BuildClosureCall(call_pos, closure, arguments);
    }
    // Could not resolve static method: throw a NoSuchMethodError.
    return ThrowNoSuchMethodError(ident_pos,
                                  cls,
                                  func_name,
                                  arguments,
                                  InvocationMirror::kStatic,
                                  InvocationMirror::kMethod,
                                  NULL);  // No existing function.
  } 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 of a static call to the function, unless
    // javascript warnings are desired and identical is not invoked from a patch
    // source.
    if (!FLAG_warn_on_javascript_compatibility || is_patch_source()) {
      ASSERT(num_arguments == 2);
      return new(Z) ComparisonNode(ident_pos,
                                   Token::kEQ_STRICT,
                                   arguments->NodeAt(0),
                                   arguments->NodeAt(1));
    }
  }
  return new(Z) StaticCallNode(ident_pos, func, arguments);
}


AstNode* Parser::ParseInstanceCall(AstNode* receiver,
                                   const String& func_name,
                                   intptr_t ident_pos,
                                   bool is_conditional) {
  TRACE_PARSER("ParseInstanceCall");
  CheckToken(Token::kLPAREN);
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  return new(Z) InstanceCallNode(ident_pos,
                                 receiver,
                                 func_name,
                                 arguments,
                                 is_conditional);
}


AstNode* Parser::ParseClosureCall(AstNode* closure) {
  TRACE_PARSER("ParseClosureCall");
  const intptr_t call_pos = TokenPos();
  ASSERT(CurrentToken() == Token::kLPAREN);
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  return BuildClosureCall(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, ident_pos);
  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.
  ASSERT(field.is_static());
  const Class& field_owner = Class::ZoneHandle(Z, field.owner());
  const String& field_name = String::ZoneHandle(Z, field.name());
  const String& getter_name = String::Handle(Z, Field::GetterName(field_name));
  const Function& getter = Function::Handle(Z,
      field_owner.LookupStaticFunction(getter_name));
  // Never load field directly if there is a getter (deterministic AST).
  if (getter.IsNull() || field.is_const()) {
    return new(Z) LoadStaticFieldNode(
        ident_pos, Field::ZoneHandle(Z, field.raw()));
  } else {
    ASSERT(getter.kind() == RawFunction::kImplicitStaticFinalGetter);
    return new(Z) StaticGetterNode(ident_pos,
                                   NULL,  // Receiver.
                                   field_owner,
                                   field_name);
  }
}


// Reference to 'field_name' with explicit class as primary.
AstNode* Parser::GenerateStaticFieldAccess(const Class& cls,
                                           const String& field_name,
                                           intptr_t ident_pos) {
  AstNode* access = NULL;
  const Field& field = Field::ZoneHandle(Z, cls.LookupStaticField(field_name));
  Function& func = Function::ZoneHandle(Z);
  if (field.IsNull()) {
    // No field, check if we have an explicit getter function.
    func = cls.LookupGetterFunction(field_name);
    if (func.IsNull() || func.IsDynamicFunction()) {
      // 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()) {
        access = CreateImplicitClosureNode(func, ident_pos, NULL);
      } else {
        // No function to closurize found found.
        // This field access may turn out to be a call to the setter.
        // Create a getter call, which may later be turned into
        // a setter call, or else the backend will generate
        // a throw NoSuchMethodError().
        access = new(Z) StaticGetterNode(ident_pos,
                                         NULL,
                                         Class::ZoneHandle(Z, cls.raw()),
                                         field_name);
      }
    } else {
      ASSERT(func.kind() != RawFunction::kImplicitStaticFinalGetter);
      access = new(Z) StaticGetterNode(
          ident_pos, NULL, Class::ZoneHandle(Z, cls.raw()), field_name);
    }
  } else {
    access = GenerateStaticFieldLookup(field, ident_pos);
  }
  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()) {
      StaticGetterNode* getter = new(Z) StaticGetterNode(
          primary->token_pos(),
          NULL,  // No receiver.
          Class::ZoneHandle(Z, current_class().raw()),
          name);
      getter->set_is_deferred(primary->is_deferred_reference());
      return getter;
    } 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());
  const Function& func =
      Function::CheckedZoneHandle(primary->primary().raw());
  const String& funcname = String::ZoneHandle(Z, func.name());
  if (func.is_static()) {
    // Static function access.
    ClosureNode* closure =
        CreateImplicitClosureNode(func, primary->token_pos(), NULL);
    closure->set_is_deferred(primary->is_deferred_reference());
    return closure;
  } else {
    // Instance function access.
    if (current_function().is_static() ||
        current_function().IsInFactoryScope()) {
      ReportError(primary->token_pos(),
                  "cannot access instance method '%s' from static method",
                  funcname.ToCString());
    }
    AstNode* receiver = LoadReceiver(primary->token_pos());
    return CallGetter(primary->token_pos(), receiver, funcname);
  }
  UNREACHABLE();
  return NULL;
}


AstNode* Parser::ParseSelectors(AstNode* primary, bool is_cascade) {
  AstNode* left = primary;
  while (true) {
    AstNode* selector = NULL;
    if ((CurrentToken() == Token::kPERIOD) ||
        (CurrentToken() == Token::kQM_PERIOD)) {
      // Unconditional or conditional property extraction or method call.
      bool is_conditional = CurrentToken() == Token::kQM_PERIOD;
      ConsumeToken();
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary_node = left->AsPrimaryNode();
        const intptr_t primary_pos = primary_node->token_pos();
        if (primary_node->primary().IsFunction()) {
          left = LoadClosure(primary_node);
        } else if (primary_node->primary().IsTypeParameter()) {
          if (ParsingStaticMember()) {
            const String& name = String::Handle(Z,
                TypeParameter::Cast(primary_node->primary()).name());
            ReportError(primary_pos,
                        "cannot access type parameter '%s' "
                        "from static function",
                        name.ToCString());
          }
          if (current_block_->scope->function_level() > 0) {
            // Make sure that the instantiator is captured.
            CaptureInstantiator();
          }
          TypeParameter& type_parameter = TypeParameter::ZoneHandle(Z);
          type_parameter ^= ClassFinalizer::FinalizeType(
              current_class(),
              TypeParameter::Cast(primary_node->primary()),
              ClassFinalizer::kCanonicalize);
          ASSERT(!type_parameter.IsMalformed());
          left = new(Z) TypeNode(primary->token_pos(), type_parameter);
        } else {
          // Super field access handled in ParseSuperFieldAccess(),
          // super calls handled in ParseSuperCall().
          ASSERT(!primary_node->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, ident_pos, is_conditional);
        }
      } else {
        // Field access.
        Class& cls = Class::Handle(Z);
        bool is_deferred = false;
        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();
            is_deferred = primary_node->is_deferred_reference();
          }
        }
        if (cls.IsNull()) {
          // Instance field access.
          selector = new(Z) InstanceGetterNode(ident_pos,
                                               left,
                                               *ident,
                                               is_conditional);
        } else {
          // Static field access.
          selector = GenerateStaticFieldAccess(cls, *ident, ident_pos);
          ASSERT(selector != NULL);
          if (selector->IsLoadStaticFieldNode()) {
            selector->AsLoadStaticFieldNode()->set_is_deferred(is_deferred);
          } else if (selector->IsStaticGetterNode()) {
            selector->AsStaticGetterNode()->set_is_deferred(is_deferred);
          }
        }
      }
    } 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_node = left->AsPrimaryNode();
        const intptr_t primary_pos = primary_node->token_pos();
        if (primary_node->primary().IsFunction()) {
          array = LoadClosure(primary_node);
        } else if (primary_node->primary().IsClass()) {
          const Class& type_class = Class::Cast(primary_node->primary());
          AbstractType& type = Type::ZoneHandle(Z,
              Type::New(type_class, TypeArguments::Handle(Z),
                        primary_pos, Heap::kOld));
          type ^= ClassFinalizer::FinalizeType(
              current_class(), type, ClassFinalizer::kCanonicalize);
          // Type may be malbounded, but not malformed.
          ASSERT(!type.IsMalformed());
          array = new(Z) TypeNode(primary_pos, type);
        } else if (primary_node->primary().IsTypeParameter()) {
          if (ParsingStaticMember()) {
            const String& name = String::ZoneHandle(Z,
                TypeParameter::Cast(primary_node->primary()).name());
            ReportError(primary_pos,
                        "cannot access type parameter '%s' "
                        "from static function",
                        name.ToCString());
          }
          if (current_block_->scope->function_level() > 0) {
            // Make sure that the instantiator is captured.
            CaptureInstantiator();
          }
          TypeParameter& type_parameter = TypeParameter::ZoneHandle(Z);
          type_parameter ^= ClassFinalizer::FinalizeType(
              current_class(),
              TypeParameter::Cast(primary_node->primary()),
              ClassFinalizer::kCanonicalize);
          ASSERT(!type_parameter.IsMalformed());
          array = new(Z) TypeNode(primary_pos, type_parameter);
        } else {
          UNREACHABLE();  // Internal parser error.
        }
      }
      selector =  new(Z) LoadIndexedNode(
          bracket_pos, array, index, Class::ZoneHandle(Z));
    } else if (CurrentToken() == Token::kLPAREN) {
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary_node = left->AsPrimaryNode();
        const intptr_t primary_pos = primary_node->token_pos();
        if (primary_node->primary().IsFunction()) {
          const Function& func = Function::Cast(primary_node->primary());
          const String& func_name = String::ZoneHandle(Z, func.name());
          if (func.is_static()) {
            // Parse static function call.
            Class& cls = Class::Handle(Z, func.Owner());
            selector = ParseStaticCall(cls, func_name, primary_pos);
          } else {
            // Dynamic function call on implicit "this" parameter.
            if (current_function().is_static()) {
              ReportError(primary_pos,
                          "cannot access instance method '%s' "
                          "from static function",
                          func_name.ToCString());
            }
            selector = ParseInstanceCall(LoadReceiver(primary_pos),
                                         func_name,
                                         primary_pos,
                                         false /* is_conditional */);
          }
        } else if (primary_node->primary().IsString()) {
          // Primary is an unresolved name.
          if (primary_node->IsSuper()) {
            ReportError(primary_pos, "illegal use of super");
          }
          String& name =
              String::CheckedZoneHandle(primary_node->primary().raw());
          if (current_function().is_static()) {
            // The static call will be converted to throwing a NSM error.
            selector = ParseStaticCall(current_class(), name, primary_pos);
          } else {
            // Treat as call to unresolved (instance) method.
            selector = ParseInstanceCall(LoadReceiver(primary_pos),
                                         name,
                                         primary_pos,
                                         false /* is_conditional */);
          }
        } else if (primary_node->primary().IsTypeParameter()) {
          const String& name = String::ZoneHandle(Z,
              TypeParameter::Cast(primary_node->primary()).name());
          if (ParsingStaticMember()) {
            // Treat as this.T(), because T is in scope.
            ReportError(primary_pos,
                        "cannot access type parameter '%s' "
                        "from static function",
                        name.ToCString());
          } else {
            // Treat as call to unresolved (instance) method.
            selector = ParseInstanceCall(LoadReceiver(primary_pos),
                                         name,
                                         primary_pos,
                                         false /* is_conditional */);
          }
        } else if (primary_node->primary().IsClass()) {
          const Class& type_class = Class::Cast(primary_node->primary());
          AbstractType& type = Type::ZoneHandle(Z, Type::New(
              type_class, TypeArguments::Handle(Z), primary_pos));
          type ^= ClassFinalizer::FinalizeType(
              current_class(), type, ClassFinalizer::kCanonicalize);
          // Type may be malbounded, but not malformed.
          ASSERT(!type.IsMalformed());
          selector = new(Z) TypeNode(primary_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_node = left->AsPrimaryNode();
        const intptr_t primary_pos = primary->token_pos();
        if (primary_node->primary().IsFunction()) {
          // Treat as implicit closure.
          left = LoadClosure(primary_node);
        } else if (primary_node->primary().IsClass()) {
          const Class& type_class = Class::Cast(primary_node->primary());
          AbstractType& type = Type::ZoneHandle(Z, Type::New(
              type_class, TypeArguments::Handle(Z), primary_pos));
          type = ClassFinalizer::FinalizeType(
              current_class(), type, ClassFinalizer::kCanonicalize);
          // Type may be malbounded, but not malformed.
          ASSERT(!type.IsMalformed());
          left = new(Z) TypeNode(primary_pos, type);
        } else if (primary_node->primary().IsTypeParameter()) {
          if (ParsingStaticMember()) {
            const String& name = String::ZoneHandle(Z,
                TypeParameter::Cast(primary_node->primary()).name());
            ReportError(primary_pos,
                        "cannot access type parameter '%s' "
                        "from static function",
                        name.ToCString());
          }
          if (current_block_->scope->function_level() > 0) {
            // Make sure that the instantiator is captured.
            CaptureInstantiator();
          }
          TypeParameter& type_parameter = TypeParameter::ZoneHandle(Z);
          type_parameter ^= ClassFinalizer::FinalizeType(
              current_class(),
              TypeParameter::Cast(primary_node->primary()),
              ClassFinalizer::kCanonicalize);
          ASSERT(!type_parameter.IsMalformed());
          left = new(Z) TypeNode(primary_pos, type_parameter);
        } else if (primary_node->IsSuper()) {
          // Return "super" to handle unary super operator calls,
          // or to report illegal use of "super" otherwise.
          left = primary_node;
        } else {
          UNREACHABLE();  // Internal parser error.
        }
      }
      // Done parsing selectors.
      return left;
    }
    ASSERT(selector != NULL);
    left = selector;
  }
}


// Closurization e#m of getter, setter, method or operator.
AstNode* Parser::ParseClosurization(AstNode* primary) {
  ExpectToken(Token::kHASH);
  intptr_t property_pos = TokenPos();
  bool is_setter_name = false;

  String& extractor_name = String::ZoneHandle(Z);
  if (IsIdentifier()) {
    extractor_name = CurrentLiteral()->raw();
    ConsumeToken();
    if (CurrentToken() == Token::kASSIGN) {
      ConsumeToken();
      is_setter_name = true;
    }
  } else if (Token::CanBeOverloaded(CurrentToken())) {
    extractor_name = String::New(Token::Str(CurrentToken()));
    ConsumeToken();
  } else {
    ReportError("identifier or operator expected");
  }

  if (primary->IsPrimaryNode() && primary->AsPrimaryNode()->IsSuper()) {
    // TODO(hausner): implement super#m
    ReportError("closurization of super method not yet supported");
  }

  // Handle closurization of top-level names from library prefixes, P#m
  if (primary->IsLiteralNode() &&
      primary->AsLiteralNode()->literal().IsLibraryPrefix()) {
    const LibraryPrefix& prefix =
        LibraryPrefix::Cast(primary->AsLiteralNode()->literal());
    Object& obj = Object::Handle(Z);
    const bool is_private_name =
        (extractor_name.CharAt(0) == Library::kPrivateIdentifierStart);
    if (!is_private_name) {
      // Private names are not exported by libraries. The name mangling
      // of private names with a library-specific suffix usually ensures
      // that _x in library A is not found when looked up from library B.
      // In the pathological case where a library imports itself with
      // a prefix, the name mangling does not help in hiding the private
      // name, so we explicitly prevent lookup of private names here.
      obj = prefix.LookupObject(extractor_name);
    }
    if (!prefix.is_loaded() && (parsed_function() != NULL)) {
      // Remember that this function depends on an import prefix of an
      // unloaded deferred library.
      parsed_function()->AddDeferredPrefix(prefix);
    }

    if (obj.IsFunction()) {
      const Function& func = Function::Cast(obj);
      if (!func.IsSetterFunction() || is_setter_name) {
        return CreateImplicitClosureNode(func, property_pos, NULL);
      }
    } else if (obj.IsField()) {
      const Field& field = Field::Cast(obj);
      if (is_setter_name && !field.is_final()) {
        Instance& setter_closure = Instance::ZoneHandle(field.SetterClosure());
        return new(Z) LiteralNode(property_pos, setter_closure);
      }
      if (!is_setter_name) {
        Instance& getter_closure = Instance::ZoneHandle(field.GetterClosure());
        return new(Z) LiteralNode(property_pos, getter_closure);
      }
    }
    return ThrowNoSuchMethodError(property_pos,
                                  current_class(),
                                  extractor_name,
                                  NULL,  // No arguments.
                                  InvocationMirror::kTopLevel,
                                  is_setter_name
                                      ? InvocationMirror::kSetter
                                      : InvocationMirror::kMethod,
                                  NULL);  // No existing function.
  }

  // Handle closurization of static properties of classes, C#n.
  if (primary->IsPrimaryNode() &&
      primary->AsPrimaryNode()->primary().IsClass()) {
    const Class& cls = Class::Cast(primary->AsPrimaryNode()->primary());
    const Field& field =
        Field::Handle(Z, cls.LookupStaticField(extractor_name));
    if (!field.IsNull()) {
      if (is_setter_name) {
        extractor_name = Field::SetterName(extractor_name);
        if (!field.is_final()) {
          const Instance& setter_closure =
              Instance::ZoneHandle(Z, field.SetterClosure());
          ASSERT(setter_closure.IsClosure());
          // Note: the created closure is cached after it's created
          // once. If eager compilation is desired, the compiler can
          // be invoked here. The same applies for getters below.
          return new(Z) LiteralNode(property_pos, setter_closure);
        }
      } else {
        const Instance& getter_closure =
            Instance::ZoneHandle(Z, field.GetterClosure());
        ASSERT(getter_closure.IsClosure());
        return new(Z) LiteralNode(property_pos, getter_closure);
      }
    } else {
      Function& func = Function::Handle(Z);
      if (is_setter_name) {
        extractor_name = Field::SetterName(extractor_name);
        func = cls.LookupStaticFunction(extractor_name);
      } else {
        func = cls.LookupStaticFunction(extractor_name);
        if (func.IsNull()) {
          const String& getter_name =
              String::Handle(Z, Field::GetterName(extractor_name));
          func = cls.LookupStaticFunction(getter_name);
        }
      }
      if (!func.IsNull()) {
        return CreateImplicitClosureNode(func, property_pos, NULL);
      }
    }
    return ThrowNoSuchMethodError(property_pos,
                                  cls,
                                  extractor_name,
                                  NULL,  // No arguments.
                                  InvocationMirror::kStatic,
                                  is_setter_name
                                      ? InvocationMirror::kSetter
                                      : InvocationMirror::kMethod,
                                  NULL);  // No existing function.
  }

  // Closurization of instance getter, setter, method or operator.
  if (is_setter_name) {
    extractor_name = String::Concat(Symbols::SetterPrefix(), extractor_name);
  }
  extractor_name = Symbols::FromConcat(Symbols::HashMark(), extractor_name);
  return new(Z) InstanceGetterNode(property_pos, primary, extractor_name);
}


AstNode* Parser::ParsePostfixExpr() {
  TRACE_PARSER("ParsePostfixExpr");
  String* expr_ident =
      Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
  const intptr_t expr_pos = TokenPos();
  AstNode* expr = ParsePrimary();
  if (CurrentToken() == Token::kHASH) {
    expr = LoadFieldIfUnresolved(expr);
    expr = ParseClosurization(expr);
  } else {
    expr = ParseSelectors(expr, false);
  }
  if (IsIncrementOperator(CurrentToken())) {
    TRACE_PARSER("IncrementOperator");
    if (!IsLegalAssignableSyntax(expr, TokenPos())) {
      ReportError(expr_pos, "expression is not assignable");
    }
    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(Z) BinaryOpNode(
        expr_pos,
        binary_op,
        new(Z) LoadLocalNode(expr_pos, temp),
        new(Z) LiteralNode(expr_pos, Smi::ZoneHandle(Z, Smi::New(1))));
    AstNode* store =
        CreateAssignmentNode(expr, add, expr_ident, expr_pos, true);
    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(Z) 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(Z, type->unresolved_class());
    const String& unresolved_class_name =
        String::Handle(Z, unresolved_class.ident());
    Class& resolved_type_class = Class::Handle(Z);
    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(Z,
            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());
            *type = ClassFinalizer::NewFinalizedMalformedType(
                Error::Handle(Z),  // No previous error.
                script_,
                type->token_pos(),
                "type parameter '%s' cannot be referenced "
                "from static member",
                String::Handle(Z, type_parameter.name()).ToCString());
            return;
          }
          // A type parameter cannot be parameterized, so make the type
          // malformed if type arguments have previously been parsed.
          if (!TypeArguments::Handle(Z, type->arguments()).IsNull()) {
            *type = ClassFinalizer::NewFinalizedMalformedType(
                Error::Handle(Z),  // No previous error.
                script_,
                type_parameter.token_pos(),
                "type parameter '%s' cannot be parameterized",
                String::Handle(Z, type_parameter.name()).ToCString());
            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. Only
      // resolve the class when a finalized type is requested.
      if (finalization > ClassFinalizer::kResolveTypeParameters) {
        resolved_type_class = library_.LookupClass(unresolved_class_name);
      }
    } else {
      // Resolve class name in the scope of the library prefix.
      const LibraryPrefix& lib_prefix =
          LibraryPrefix::Handle(Z, unresolved_class.library_prefix());
      resolved_type_class = lib_prefix.LookupClass(unresolved_class_name);
    }
    // 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) {
      ClassFinalizer::FinalizeMalformedType(
          Error::Handle(Z),  // No previous error.
          script_,
          parameterized_type,
          "type '%s' is not loaded",
          String::Handle(Z, parameterized_type.UserVisibleName()).ToCString());
      return;
    }
  }
  // Resolve type arguments, if any.
  const TypeArguments& arguments = TypeArguments::Handle(Z, type->arguments());
      TypeArguments::Handle(Z, 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(Z,
                                                         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()) {
    ReportError(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());
  Type& type = Type::ZoneHandle(Z, cls.CanonicalType());
  if (!type.IsNull()) {
    return &type;
  }
  if (cls.IsSignatureClass()) {
    type = cls.SignatureType();
  } else {
    type = Type::New(cls,
        TypeArguments::Handle(Z, cls.type_parameters()), 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.
    cls.SetCanonicalType(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;
}


class ConstMapKeyEqualsTraits {
 public:
  static bool IsMatch(const Object& a, const Object& b) {
    return String::Cast(a).Equals(String::Cast(b));
  }
  static bool IsMatch(const char* key, const Object& b) {
    return String::Cast(b).Equals(key);
  }
  static uword Hash(const Object& obj) {
    return String::Cast(obj).Hash();
  }
  static uword Hash(const char* key) {
    return String::Hash(key, strlen(key));
  }
};
typedef UnorderedHashMap<ConstMapKeyEqualsTraits> ConstantsMap;


void Parser::CacheConstantValue(intptr_t token_pos, const Instance& value) {
  String& key = String::Handle(Z, script_.url());
  String& suffix =
      String::Handle(Z, String::NewFormatted("_%" Pd "", token_pos));
  key = Symbols::FromConcat(key, suffix);
  if (isolate()->object_store()->compile_time_constants() == Array::null()) {
    const intptr_t kInitialConstMapSize = 16;
    isolate()->object_store()->set_compile_time_constants(
        Array::Handle(Z, HashTables::New<ConstantsMap>(kInitialConstMapSize,
                                                       Heap::kNew)));
  }
  ConstantsMap constants(isolate()->object_store()->compile_time_constants());
  constants.UpdateOrInsert(key, value);
  if (FLAG_compiler_stats) {
    isolate_->compiler_stats()->num_cached_consts = constants.NumOccupied();
  }
  isolate()->object_store()->set_compile_time_constants(constants.Release());
}


bool Parser::GetCachedConstant(intptr_t token_pos, Instance* value) {
  if (isolate()->object_store()->compile_time_constants() == Array::null()) {
    return false;
  }
  // We don't want to allocate anything in the heap here since this code
  // is called from the optimizing compiler in the background thread. Allocate
  // the key value in the zone instead.
  const char* key = Z->PrintToString("%s_%" Pd "",
      String::Handle(Z, script_.url()).ToCString(),
      token_pos);
  ConstantsMap constants(isolate()->object_store()->compile_time_constants());
  bool is_present = false;
  *value ^= constants.GetOrNull<const char *>(key, &is_present);
  ASSERT(constants.Release().raw() ==
      isolate()->object_store()->compile_time_constants());
  if (FLAG_compiler_stats && is_present) {
    isolate_->compiler_stats()->num_const_cache_hits++;
  }
  return is_present;
}


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(Z, instance.CheckAndCanonicalize(&error_str));
  if (result.IsNull()) {
    ReportError(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.
StaticGetterNode* Parser::RunStaticFieldInitializer(const Field& field,
                                                    intptr_t field_ref_pos) {
  ASSERT(field.is_static());
  const Class& field_owner = Class::ZoneHandle(Z, field.owner());
  const String& field_name = String::ZoneHandle(Z, field.name());
  const String& getter_name = String::Handle(Z, Field::GetterName(field_name));
  const Function& getter = Function::Handle(Z,
      field_owner.LookupStaticFunction(getter_name));
  const Instance& value = Instance::Handle(Z, field.value());
  if (value.raw() == Object::transition_sentinel().raw()) {
    if (field.is_const()) {
      ReportError("circular dependency while initializing static field '%s'",
                  field_name.ToCString());
    } else {
      // The implicit static getter will throw the exception if necessary.
      return new(Z) StaticGetterNode(
          field_ref_pos, NULL, 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(Z,
          Resolver::ResolveStatic(field_owner,
                                  getter_name,
                                  kNumArguments,
                                  Object::empty_array()));
      ASSERT(!func.IsNull());
      ASSERT(func.kind() == RawFunction::kImplicitStaticFinalGetter);
      Object& const_value = Object::Handle(Z);
      {
        PAUSETIMERSCOPE(T, time_compilation);
        const_value = 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().SetIsOptimizable(false);
          field.set_value(Object::null_instance());
          // It is a compile-time error if evaluation of a compile-time constant
          // would raise an exception.
          const String& field_name = String::Handle(Z, field.name());
          ReportErrors(error,
                       script_, field_ref_pos,
                       "error initializing const field '%s'",
                       field_name.ToCString());
        } else {
          ReportError(error);
        }
        UNREACHABLE();
      }
      ASSERT(const_value.IsNull() || const_value.IsInstance());
      Instance& instance = Instance::Handle(Z);
      instance ^= const_value.raw();
      instance = TryCanonicalize(instance, field_ref_pos);
      field.set_value(instance);
      return NULL;   // Constant
    } else {
      return new(Z) StaticGetterNode(
          field_ref_pos, NULL, field_owner, field_name);
    }
  }
  if (getter.IsNull() ||
      (getter.kind() == RawFunction::kImplicitStaticFinalGetter)) {
    return NULL;
  }
  ASSERT(getter.kind() == RawFunction::kImplicitGetter);
  return new(Z) StaticGetterNode(
      field_ref_pos, NULL, field_owner, field_name);
}


RawObject* Parser::EvaluateConstConstructorCall(
    const Class& type_class,
    const TypeArguments& type_arguments,
    const Function& constructor,
    ArgumentListNode* arguments) {
  // Factories have one extra argument: the type arguments.
  // Constructors have 2 extra arguments: rcvr and construction phase.
  const int kNumExtraArgs = constructor.IsFactory() ? 1 : 2;
  const int num_arguments = arguments->length() + kNumExtraArgs;
  const Array& arg_values = Array::Handle(Z, Array::New(num_arguments));
  Instance& instance = Instance::Handle(Z);
  if (!constructor.IsFactory()) {
    instance = Instance::New(type_class, Heap::kOld);
    if (!type_arguments.IsNull()) {
      if (!type_arguments.IsInstantiated()) {
        ReportError("type must be constant in const constructor");
      }
      instance.SetTypeArguments(
          TypeArguments::Handle(Z, type_arguments.Canonicalize()));
    }
    arg_values.SetAt(0, instance);
    arg_values.SetAt(1, Smi::Handle(Z, Smi::New(Function::kCtorPhaseAll)));
  } else {
    // Prepend type_arguments to list of arguments to factory.
    ASSERT(type_arguments.IsZoneHandle());
    arg_values.SetAt(0, type_arguments);
  }
  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(Z,
      ArgumentsDescriptor::New(num_arguments, arguments->names()));
  Object& result = Object::Handle(Z);
  {
    PAUSETIMERSCOPE(T, time_compilation);
    result = 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().SetIsOptimizable(false);
      if (result.IsUnhandledException()) {
        return result.raw();
      } else {
        thread()->long_jump_base()->Jump(1, Error::Cast(result));
        UNREACHABLE();
        return Object::null();
      }
  } else {
    if (constructor.IsFactory()) {
      // The factory method returns the allocated object.
      instance ^= result.raw();
    }
    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 (current_block_ != NULL) {
    current_block_->scope->AddReferencedName(ident_pos, ident);
  }
  if (local != NULL) {
    if (node != NULL) {
      *node = new(Z) LoadLocalNode(ident_pos, local);
    }
    return true;
  }

  // If we are compiling top-level code, we don't need to look for
  // the identifier in the current (top-level) class. The class scope
  // of the top-level class is part of the library scope.
  if (current_class().IsTopLevel()) {
    if (node != NULL) {
      *node = NULL;
    }
    return false;
  }

  // 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(Z);
  if (!current_class().IsMixinApplication()) {
    cls = current_class().raw();
  } else {
    cls = parsed_function()->function().origin();
  }
  Function& func = Function::Handle(Z, Function::null());
  Field& field = Field::Handle(Z, 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() ||
      func.is_abstract())) {
    if (node != NULL) {
      *node = new(Z) PrimaryNode(
          ident_pos, Function::ZoneHandle(Z, func.raw()));
    }
    return true;
  }

  // Now check if a getter/setter method exists for it in which case
  // it is still a field.
  // A setter without a corresponding getter binds to the non-existing
  // getter. (The getter could be followed by an assignment which will
  // convert it to a setter node. If there is no assignment the non-existing
  // getter will throw a NoSuchMethodError.)
  func = cls.LookupGetterFunction(ident);
  if (func.IsNull()) {
    func = cls.LookupSetterFunction(ident);
  }
  if (!func.IsNull()) {
    if (func.IsDynamicFunction() || func.is_abstract()) {
      if (node != NULL) {
        CheckInstanceFieldAccess(ident_pos, ident);
        ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
        *node = CallGetter(ident_pos, LoadReceiver(ident_pos), ident);
      }
      return true;
    } else if (func.IsStaticFunction()) {
      if (node != NULL) {
        *node = new(Z) StaticGetterNode(ident_pos,
                                        NULL,
                                        Class::ZoneHandle(Z, cls.raw()),
                                        ident);
      }
      return true;
    }
  }

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


// 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.
AstNode* Parser::ResolveIdentInCurrentLibraryScope(intptr_t ident_pos,
                                                   const String& ident) {
  TRACE_PARSER("ResolveIdentInCurrentLibraryScope");
  HANDLESCOPE(thread());
  const Object& obj = Object::Handle(Z, library_.ResolveName(ident));
  if (obj.IsClass()) {
    const Class& cls = Class::Cast(obj);
    return new(Z) PrimaryNode(ident_pos, Class::ZoneHandle(Z, cls.raw()));
  } else if (obj.IsField()) {
    const Field& field = Field::Cast(obj);
    ASSERT(field.is_static());
    AstNode* get_field = GenerateStaticFieldLookup(field, ident_pos);
    if (get_field->IsStaticGetterNode()) {
      get_field->AsStaticGetterNode()->set_owner(library_);
    }
    return get_field;
  } else if (obj.IsFunction()) {
    const Function& func = Function::Cast(obj);
    ASSERT(func.is_static());
    if (func.IsGetterFunction() || func.IsSetterFunction()) {
      StaticGetterNode* getter =
          new(Z) StaticGetterNode(ident_pos,
                                  /* receiver */ NULL,
                                  Class::ZoneHandle(Z, func.Owner()),
                                  ident);
      getter->set_owner(library_);
      return getter;
    } else {
      return new(Z) PrimaryNode(ident_pos, Function::ZoneHandle(Z, func.raw()));
    }
  } else if (obj.IsLibraryPrefix()) {
    const LibraryPrefix& prefix = LibraryPrefix::Cast(obj);
    ReportError(ident_pos,
                "illegal use of library prefix '%s'",
                String::Handle(prefix.name()).ToCString());
  } else {
    ASSERT(obj.IsNull());
  }
  // Lexically unresolved primary identifiers are referenced by their name.
  return new(Z) PrimaryNode(ident_pos, ident);
}


// 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.
AstNode* Parser::ResolveIdentInPrefixScope(intptr_t ident_pos,
                                           const LibraryPrefix& prefix,
                                           const String& ident) {
  TRACE_PARSER("ResolveIdentInPrefixScope");
  HANDLESCOPE(thread());
  if (ident.CharAt(0) == Library::kPrivateIdentifierStart) {
    // Private names are not exported by libraries. The name mangling
    // of private names with a library-specific suffix usually ensures
    // that _x in library A is not found when looked up from library B.
    // In the pathological case where a library imports itself with
    // a prefix, the name mangling would not help in hiding the private
    // name, so we need to explicitly reject private names here.
    return NULL;
  }
  Object& obj = Object::Handle(Z);
  if (prefix.is_loaded() || FLAG_load_deferred_eagerly) {
    obj = prefix.LookupObject(ident);
  } else {
    // Remember that this function depends on an import prefix of an
    // unloaded deferred library. Note that parsed_function() can be
    // NULL when parsing expressions outside the scope of a function.
    if (parsed_function() != NULL) {
      parsed_function()->AddDeferredPrefix(prefix);
    }
  }
  const bool is_deferred = prefix.is_deferred_load();
  if (obj.IsNull()) {
    // Unresolved prefixed primary identifier.
    return NULL;
  } else if (obj.IsClass()) {
    const Class& cls = Class::Cast(obj);
    PrimaryNode* primary =
        new(Z) PrimaryNode(ident_pos, Class::ZoneHandle(Z, cls.raw()));
    primary->set_is_deferred(is_deferred);
    return primary;
  } else if (obj.IsField()) {
    const Field& field = Field::Cast(obj);
    ASSERT(field.is_static());
    AstNode* get_field = GenerateStaticFieldLookup(field, ident_pos);
    ASSERT(get_field != NULL);
    ASSERT(get_field->IsLoadStaticFieldNode() ||
           get_field->IsStaticGetterNode());
    if (get_field->IsLoadStaticFieldNode()) {
      get_field->AsLoadStaticFieldNode()->set_is_deferred(is_deferred);
    } else if (get_field->IsStaticGetterNode()) {
      get_field->AsStaticGetterNode()->set_is_deferred(is_deferred);
      get_field->AsStaticGetterNode()->set_owner(prefix);
    }
    return get_field;
  } else if (obj.IsFunction()) {
    const Function& func = Function::Cast(obj);
    ASSERT(func.is_static());
    if (func.IsGetterFunction() || func.IsSetterFunction()) {
      StaticGetterNode* getter = new(Z) StaticGetterNode(
         ident_pos,
         /* receiver */ NULL,
         Class::ZoneHandle(Z, func.Owner()),
         ident);
      getter->set_is_deferred(is_deferred);
      getter->set_owner(prefix);
      return getter;
    } else {
      PrimaryNode* primary = new(Z) PrimaryNode(
           ident_pos, Function::ZoneHandle(Z, func.raw()));
      primary->set_is_deferred(is_deferred);
      return primary;
    }
  }
  // All possible object types are handled above.
  UNREACHABLE();
  return NULL;
}


// 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 generate
// throw NoSuchMethodError 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(Z,
          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::kCanonicalize);
        ASSERT(!type_parameter.IsMalformed());
        return new(Z) 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();
    const intptr_t primary_pos = primary->token_pos();
    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,
                                          NULL,  // No arguments.
                                          InvocationMirror::kStatic,
                                          InvocationMirror::kField,
                                          NULL);  // No existing function.
      } 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 {
        ReportError(ident_pos, "illegal reference to method '%s'",
                    ident.ToCString());
      }
    } else if (primary->primary().IsClass()) {
      const Class& type_class = Class::Cast(primary->primary());
      AbstractType& type = Type::ZoneHandle(Z,
          Type::New(type_class, TypeArguments::Handle(Z), primary_pos));
      type ^= ClassFinalizer::FinalizeType(
          current_class(), type, ClassFinalizer::kCanonicalize);
      // Type may be malbounded, but not malformed.
      ASSERT(!type.IsMalformed());
      resolved = new(Z) TypeNode(primary_pos, type);
    }
  }
  return resolved;
}


RawAbstractType* Parser::ParseType(
    ClassFinalizer::FinalizationKind finalization,
    bool allow_deferred_type,
    bool consume_unresolved_prefix) {
  LibraryPrefix& prefix = LibraryPrefix::Handle(Z);
  return ParseType(finalization, allow_deferred_type,
                         consume_unresolved_prefix, &prefix);
}

// Parses type = [ident "."] ident ["<" type { "," type } ">"], then resolve and
// finalize it according to the given type finalization mode. Returns prefix.
RawAbstractType* Parser::ParseType(
    ClassFinalizer::FinalizationKind finalization,
    bool allow_deferred_type,
    bool consume_unresolved_prefix,
    LibraryPrefix* prefix) {
  TRACE_PARSER("ParseType");
  CheckToken(Token::kIDENT, "type name expected");
  intptr_t ident_pos = TokenPos();
  String& type_name = String::Handle(Z);

  if (finalization == ClassFinalizer::kIgnore) {
    if (!is_top_level_ && (current_block_ != NULL)) {
      // Add the library prefix or type class name to the list of referenced
      // names of this scope, even if the type is ignored.
      current_block_->scope->AddReferencedName(TokenPos(), *CurrentLiteral());
    }
    SkipQualIdent();
  } else {
    *prefix = ParsePrefix();
    if (!prefix->IsNull()) {
      ExpectToken(Token::kPERIOD);
    }
    type_name = CurrentLiteral()->raw();
    ConsumeToken();

    // Check whether we have a malformed qualified type name if the caller
    // requests to consume unresolved prefix names:
    // If we didn't see a valid prefix but the identifier is followed by
    // a period and another identifier, consume the qualified identifier
    // and create a malformed type.
    if (consume_unresolved_prefix &&
        prefix->IsNull() &&
        (CurrentToken() == Token::kPERIOD) &&
        (Token::IsIdentifier(LookaheadToken(1)))) {
      if (!is_top_level_ && (current_block_ != NULL)) {
        // Add the unresolved prefix name to the list of referenced
        // names of this scope.
        current_block_->scope->AddReferencedName(TokenPos(), type_name);
      }
      ConsumeToken();  // Period token.
      ASSERT(IsIdentifier());
      String& qualified_name = String::Handle(Z, type_name.raw());
      qualified_name = String::Concat(qualified_name, Symbols::Dot());
      qualified_name = String::Concat(qualified_name, *CurrentLiteral());
      ConsumeToken();
      // The type is malformed. Skip over its type arguments.
      ParseTypeArguments(ClassFinalizer::kIgnore);
      return ClassFinalizer::NewFinalizedMalformedType(
          Error::Handle(Z),  // No previous error.
          script_,
          ident_pos,
          "qualified name '%s' does not refer to a type",
          qualified_name.ToCString());
    }

    // If parsing inside a local scope, check whether the type name
    // is shadowed by a local declaration.
    if (!is_top_level_ &&
        (prefix->IsNull()) &&
        ResolveIdentInLocalScope(ident_pos, type_name, NULL)) {
      // The type is malformed. Skip over its type arguments.
      ParseTypeArguments(ClassFinalizer::kIgnore);
      return ClassFinalizer::NewFinalizedMalformedType(
          Error::Handle(Z),  // No previous error.
          script_,
          ident_pos,
          "using '%s' in this context is invalid",
          type_name.ToCString());
    }
    if ((!FLAG_load_deferred_eagerly || !allow_deferred_type) &&
        !prefix->IsNull() && prefix->is_deferred_load()) {
      // If deferred prefixes are allowed but it is not yet loaded,
      // remember that this function depends on the prefix.
      if (allow_deferred_type && !prefix->is_loaded()) {
        if (parsed_function() != NULL) {
          parsed_function()->AddDeferredPrefix(*prefix);
        }
      }
      // If the deferred prefixes are not allowed, or if the prefix is not yet
      // loaded when finalization is requested, return a malformed type.
      // Otherwise, handle resolution below, as needed.
      if (!allow_deferred_type ||
          (!prefix->is_loaded()
              && (finalization > ClassFinalizer::kResolveTypeParameters))) {
        ParseTypeArguments(ClassFinalizer::kIgnore);
        return ClassFinalizer::NewFinalizedMalformedType(
            Error::Handle(Z),  // No previous error.
            script_,
            ident_pos,
            !prefix->is_loaded() && allow_deferred_type
                ? "deferred type '%s.%s' is not yet loaded"
                : "using deferred type '%s.%s' is invalid",
            String::Handle(Z, prefix->name()).ToCString(),
            type_name.ToCString());
      }
    }
  }
  Object& type_class = Object::Handle(Z);
  // Leave type_class as null if type finalization mode is kIgnore.
  if (finalization != ClassFinalizer::kIgnore) {
    type_class = UnresolvedClass::New(*prefix, type_name, ident_pos);
  }
  TypeArguments& type_arguments = TypeArguments::Handle(
      Z, ParseTypeArguments(finalization));
  if (finalization == ClassFinalizer::kIgnore) {
    return Type::DynamicType();
  }
  AbstractType& type = AbstractType::Handle(
      Z, Type::New(type_class, type_arguments, 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, const Function& constructor,
    const TypeArguments& type_arguments) {
  if (!type_arguments.IsNull()) {
    const Class& constructor_class = Class::Handle(Z, constructor.Owner());
    ASSERT(!constructor_class.IsNull());
    ASSERT(constructor_class.is_finalized());
    ASSERT(type_arguments.IsCanonical());
    // 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()) {
      ReportError(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 TypeArguments& type_arguments) {
  TRACE_PARSER("ParseListLiteral");
  ASSERT(type_pos >= 0);
  ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX);
  const intptr_t literal_pos = TokenPos();

  if (is_const) {
    Instance& existing_const = Instance::ZoneHandle(Z);
    if (GetCachedConstant(literal_pos, &existing_const)) {
      SkipListLiteral();
      return new(Z) LiteralNode(literal_pos, existing_const);
    }
  }

  bool is_empty_literal = CurrentToken() == Token::kINDEX;
  ConsumeToken();

  AbstractType& element_type = Type::ZoneHandle(Z, Type::DynamicType());
  TypeArguments& list_type_arguments =
      TypeArguments::ZoneHandle(Z, 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);
      ASSERT(!element_type.IsMalformed());  // Would be mapped to dynamic.
      ASSERT(!element_type.IsMalbounded());  // No declared bound in List.
      if (element_type.IsDynamicType()) {
        list_type_arguments = TypeArguments::null();
      } else if (is_const && !element_type.IsInstantiated()) {
        ReportError(type_pos,
                    "the type argument of a constant list literal cannot "
                    "include a type variable");
      }
    } else {
      if (I->flags().error_on_bad_type()) {
        ReportError(type_pos,
                    "a list literal takes one type argument specifying "
                    "the element type");
      }
      // Ignore type arguments.
      list_type_arguments = TypeArguments::null();
    }
  }
  ASSERT(list_type_arguments.IsNull() || (list_type_arguments.Length() == 1));
  const Class& array_class = Class::Handle(Z, I->object_store()->array_class());
  Type& type = Type::ZoneHandle(Z,
      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 (I->flags().type_checks() &&
          !is_const &&
          !element_type.IsDynamicType()) {
        element = new(Z) AssignableNode(element_pos,
                                        element,
                                        element_type,
                                        Symbols::ListLiteralElement());
      }
      element_list.Add(element);
      if (CurrentToken() == Token::kCOMMA) {
        ConsumeToken();
      } else if (CurrentToken() != Token::kRBRACK) {
        ReportError("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(Z,
        Array::New(element_list.length(), Heap::kOld));
    const_list.SetTypeArguments(
        TypeArguments::Handle(Z, list_type_arguments.Canonicalize()));
    Error& malformed_error = Error::Handle(Z);
    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 (I->flags().type_checks() &&
          !element_type.IsDynamicType() &&
          (!elem->AsLiteralNode()->literal().IsNull() &&
           !elem->AsLiteralNode()->literal().IsInstanceOf(
               element_type,
               TypeArguments::Handle(Z),
               &malformed_error))) {
        // If the failure is due to a malformed type error, display it instead.
        if (!malformed_error.IsNull()) {
          ReportError(malformed_error);
        } else {
          ReportError(elem->AsLiteralNode()->token_pos(),
                      "list literal element at index %d must be "
                      "a constant of type '%s'",
                      i,
                      String::Handle(Z,
                          element_type.UserVisibleName()).ToCString());
        }
      }
      const_list.SetAt(i, elem->AsLiteralNode()->literal());
    }
    const_list.MakeImmutable();
    const_list ^= TryCanonicalize(const_list, literal_pos);
    CacheConstantValue(literal_pos, const_list);
    return new(Z) LiteralNode(literal_pos, const_list);
  } else {
    // Factory call at runtime.
    const Class& factory_class =
        Class::Handle(Z, Library::LookupCoreClass(Symbols::List()));
    ASSERT(!factory_class.IsNull());
    const Function& factory_method = Function::ZoneHandle(Z,
        factory_class.LookupFactory(
            Library::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();
    }
    TypeArguments& factory_type_args =
        TypeArguments::ZoneHandle(Z, 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(Z, 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(Z) ArgumentListNode(
        literal_pos);
    if (element_list.length() == 0) {
      LiteralNode* empty_array_literal =
          new(Z) LiteralNode(TokenPos(), Object::empty_array());
      factory_param->Add(empty_array_literal);
    } else {
      ArrayNode* list = new(Z) 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 TypeArguments& type_arguments,
    const Function& constructor,
    ArgumentListNode* arguments) {
  if (!type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
    EnsureExpressionTemp();
  }
  return new(Z) 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 TypeArguments& type_arguments) {
  TRACE_PARSER("ParseMapLiteral");
  ASSERT(type_pos >= 0);
  ASSERT(CurrentToken() == Token::kLBRACE);
  const intptr_t literal_pos = TokenPos();

  if (is_const) {
    Instance& existing_const = Instance::ZoneHandle(Z);
    if (GetCachedConstant(literal_pos, &existing_const)) {
      SkipMapLiteral();
      return new(Z) LiteralNode(literal_pos, existing_const);
    }
  }

  ConsumeToken();  // Opening brace.
  AbstractType& key_type = Type::ZoneHandle(Z, Type::DynamicType());
  AbstractType& value_type = Type::ZoneHandle(Z, Type::DynamicType());
  TypeArguments& map_type_arguments =
      TypeArguments::ZoneHandle(Z, 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);
      // Malformed type arguments are mapped to dynamic.
      ASSERT(!key_type.IsMalformed() && !value_type.IsMalformed());
      // No declared bounds in Map.
      ASSERT(!key_type.IsMalbounded() && !value_type.IsMalbounded());
      if (key_type.IsDynamicType() && value_type.IsDynamicType()) {
        map_type_arguments = TypeArguments::null();
      } else if (is_const && !type_arguments.IsInstantiated()) {
        ReportError(type_pos,
                    "the type arguments of a constant map literal cannot "
                    "include a type variable");
      }
    } else {
      if (I->flags().error_on_bad_type()) {
        ReportError(type_pos,
                    "a map literal takes two type arguments specifying "
                    "the key type and the value type");
      }
      // Ignore type arguments.
      map_type_arguments = TypeArguments::null();
    }
  }
  ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2));
  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 (I->flags().type_checks() &&
        !is_const &&
        !key_type.IsDynamicType()) {
      key = new(Z) AssignableNode(
          key_pos, key, key_type, Symbols::ListLiteralElement());
    }
    if (is_const) {
      ASSERT(key->IsLiteralNode());
      const Instance& key_value = key->AsLiteralNode()->literal();
      if (key_value.IsDouble()) {
        ReportError(key_pos, "key value must not be of type double");
      }
      if (!key_value.IsInteger() &&
          !key_value.IsString() &&
          (key_value.clazz() != I->object_store()->symbol_class()) &&
          ImplementsEqualOperator(key_value)) {
        ReportError(key_pos, "key value must not implement operator ==");
      }
    }
    ExpectToken(Token::kCOLON);
    const intptr_t value_pos = TokenPos();
    AstNode* value = ParseExpr(is_const, kConsumeCascades);
    SetAllowFunctionLiterals(saved_mode);
    if (I->flags().type_checks() &&
        !is_const &&
        !value_type.IsDynamicType()) {
      value = new(Z) 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) {
      ReportError("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(Z, Array::New(kv_pairs_list.length(), Heap::kOld));
    AbstractType& arg_type = Type::Handle(Z);
    Error& malformed_error = Error::Handle(Z);
    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 (I->flags().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_type_arguments(),
                 &malformed_error))) {
          // If the failure is due to a malformed type error, display it.
          if (!malformed_error.IsNull()) {
            ReportError(malformed_error);
          } else {
            ReportError(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(Z,
                                       arg_type.UserVisibleName()).ToCString());
          }
        }
      }
      key_value_array.SetAt(i, arg->AsLiteralNode()->literal());
    }
    key_value_array.MakeImmutable();
    key_value_array ^= TryCanonicalize(key_value_array, TokenPos());

    // Construct the map object.
    const Class& immutable_map_class = Class::Handle(Z,
        Library::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(Z) ArgumentListNode(TokenPos());
    constr_args->Add(new(Z) LiteralNode(literal_pos, key_value_array));
    const Function& map_constr =
        Function::ZoneHandle(Z, immutable_map_class.LookupConstructor(
            Library::PrivateCoreLibName(Symbols::ImmutableMapConstructor())));
    ASSERT(!map_constr.IsNull());
    const Object& constructor_result = Object::Handle(Z,
        EvaluateConstConstructorCall(immutable_map_class,
                                     map_type_arguments,
                                     map_constr,
                                     constr_args));
    if (constructor_result.IsUnhandledException()) {
      ReportErrors(Error::Cast(constructor_result),
                   script_, literal_pos,
                   "error executing const Map constructor");
    } else {
      const Instance& const_instance = Instance::Cast(constructor_result);
      CacheConstantValue(literal_pos, const_instance);
      return new(Z) LiteralNode(
          literal_pos, Instance::ZoneHandle(Z, const_instance.raw()));
    }
  } else {
    // Factory call at runtime.
    const Class& factory_class =
        Class::Handle(Z, Library::LookupCoreClass(Symbols::Map()));
    ASSERT(!factory_class.IsNull());
    const Function& factory_method = Function::ZoneHandle(Z,
        factory_class.LookupFactory(
            Library::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();
    }
    TypeArguments& factory_type_args =
        TypeArguments::ZoneHandle(Z, 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(Z, 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(Z) 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(Z) ArrayNode(
        TokenPos(),
        Type::ZoneHandle(Z, Type::ArrayType()),
        kv_pairs_list);
    factory_param->Add(kv_pairs);
    return CreateConstructorCallNode(literal_pos,
                                     factory_type_args,
                                     factory_method,
                                     factory_param);
  }
  UNREACHABLE();
  return NULL;
}


AstNode* Parser::ParseCompoundLiteral() {
  TRACE_PARSER("ParseCompoundLiteral");
  bool is_const = false;
  if (CurrentToken() == Token::kCONST) {
    is_const = true;
    ConsumeToken();
  }
  const intptr_t type_pos = TokenPos();
  TypeArguments& type_arguments = TypeArguments::Handle(Z,
      ParseTypeArguments(ClassFinalizer::kCanonicalize));
  // Malformed type arguments are mapped to dynamic, so we will not encounter
  // them here.
  // Map and List interfaces do not declare bounds on their type parameters, so
  // we will not see malbounded type arguments 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 {
    UnexpectedToken();
  }
  return primary;
}


AstNode* Parser::ParseSymbolLiteral() {
  ASSERT(CurrentToken() == Token::kHASH);
  ConsumeToken();
  intptr_t symbol_pos = TokenPos();
  String& symbol = String::Handle(Z);
  if (IsIdentifier()) {
    symbol = CurrentLiteral()->raw();
    ConsumeToken();
    while (CurrentToken() == Token::kPERIOD) {
      symbol = String::Concat(symbol, Symbols::Dot());
      ConsumeToken();
      symbol = String::Concat(symbol,
                              *ExpectIdentifier("identifier expected"));
    }
  } else if (Token::CanBeOverloaded(CurrentToken())) {
    symbol = String::New(Token::Str(CurrentToken()));
    ConsumeToken();
  } else {
    ReportError("illegal symbol literal");
  }

  // Call Symbol class constructor to create a symbol instance.
  const Class& symbol_class = Class::Handle(I->object_store()->symbol_class());
  ASSERT(!symbol_class.IsNull());
  ArgumentListNode* constr_args = new(Z) ArgumentListNode(symbol_pos);
  constr_args->Add(new(Z) LiteralNode(
      symbol_pos, String::ZoneHandle(Z, Symbols::New(symbol))));
  const Function& constr = Function::ZoneHandle(Z,
      symbol_class.LookupConstructor(Symbols::SymbolCtor()));
  ASSERT(!constr.IsNull());
  const Object& result = Object::Handle(Z,
      EvaluateConstConstructorCall(symbol_class,
                                   TypeArguments::Handle(Z),
                                   constr,
                                   constr_args));
  if (result.IsUnhandledException()) {
    ReportErrors(Error::Cast(result),
                 script_, symbol_pos,
                 "error executing const Symbol constructor");
  }
  const Instance& instance = Instance::Cast(result);
  return new(Z) LiteralNode(symbol_pos,
                            Instance::ZoneHandle(Z, instance.raw()));
}


RawFunction* Parser::BuildConstructorClosureFunction(const Function& ctr,
                                                     intptr_t token_pos) {
  ASSERT(ctr.kind() == RawFunction::kConstructor);
  Function& closure = Function::Handle(Z);
  closure = current_class().LookupClosureFunction(token_pos);
  if (!closure.IsNull()) {
    ASSERT(closure.IsConstructorClosureFunction());
    return closure.raw();
  }

  String& closure_name = String::Handle(Z, ctr.name());
  closure_name = Symbols::FromConcat(Symbols::ConstructorClosurePrefix(),
                                     closure_name);

  ParamList params;
  params.AddFinalParameter(token_pos,
                           &Symbols::ClosureParameter(),
                           &Type::ZoneHandle(Z, Type::DynamicType()));

  ParseFormalParameters(ctr, &params);
  // Per language spec, the type of the closure parameters is dynamic.
  // Replace the types parsed from the constructor.
  params.EraseParameterTypes();

  closure = Function::NewClosureFunction(closure_name,
                                         innermost_function(),
                                         token_pos);
  closure.set_is_generated_body(true);
  closure.set_is_debuggable(false);
  closure.set_is_visible(false);
  closure.set_result_type(AbstractType::Handle(Type::DynamicType()));
  AddFormalParamsToFunction(&params, closure);

  // Create and set the signature class of the closure.
  const String& sig = String::Handle(Z, closure.Signature());
  Class& sig_cls = Class::Handle(Z, library_.LookupLocalClass(sig));
  if (sig_cls.IsNull()) {
    sig_cls = Class::NewSignatureClass(sig, closure, script_, token_pos);
    library_.AddClass(sig_cls);
  }
  closure.set_signature_class(sig_cls);
  // Finalize types in signature class here, so that the
  // signature type is not computed twice.
  ClassFinalizer::FinalizeTypesInClass(sig_cls);
  const Type& sig_type = Type::Handle(Z, sig_cls.SignatureType());
  ASSERT(sig_type.IsFinalized());
  // Finalization would be premature when top-level parsing.
  ASSERT(!is_top_level_);
  return closure.raw();
}


static 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(Symbols::FromConcat(type_class_name, Symbols::Dot()));
  if (named_constructor != NULL) {
    constructor_name =
        Symbols::FromConcat(constructor_name, *named_constructor);
  }
  return constructor_name;
}


// Parse a primary expression of the form new T# or new T#m.
// Current token position is after the keyword new. Extracts the
// anonymous or named constructor and type arguments.
// Note that type type T has already been parsed before
// (by ParseNewOperator()) and is guaranteed to be well-formed,
// and the constructor is known to exist.
void Parser::ParseConstructorClosurization(Function* constructor,
                                           TypeArguments* type_arguments) {
  *constructor = Function::null();
  *type_arguments = TypeArguments::null();
  const Token::Kind la3 = LookaheadToken(3);
  const bool consume_unresolved_prefix =
      (la3 == Token::kLT) || (la3 == Token::kPERIOD) || (la3 == Token::kHASH);
  LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z);
  AbstractType& type = AbstractType::Handle(Z,
      ParseType(ClassFinalizer::kCanonicalizeWellFormed,
      true,  // allow deferred type
      consume_unresolved_prefix,
      &prefix));
  // A constructor tear-off closure can only have been created for a
  // type that is loaded.
  ASSERT(prefix.IsNull() || prefix.is_loaded());
  ASSERT(!type.IsMalformed() && !type.IsTypeParameter());
  ExpectToken(Token::kHASH);
  String* named_constructor = NULL;
  if (IsIdentifier()) {
    named_constructor = CurrentLiteral();
    ConsumeToken();
  }
  // Resolve the type and optional identifier to a constructor or factory.
  Class& type_class = Class::Handle(Z, type.type_class());
  String& type_class_name = String::Handle(Z, type_class.Name());
  *type_arguments = type.arguments();
  String& constructor_name =
      BuildConstructorName(type_class_name, named_constructor);
  *constructor = type_class.LookupConstructor(constructor_name);
  if (constructor->IsNull()) {
    *constructor = type_class.LookupFactory(constructor_name);
    ASSERT(!constructor->IsNull());
    if (constructor->IsRedirectingFactory()) {
      ClassFinalizer::ResolveRedirectingFactory(type_class, *constructor);
      type = constructor->RedirectionType();
      ASSERT(!type.IsMalformedOrMalbounded());
      if (!type.IsInstantiated()) {
        Error& error = Error::Handle(Z);
        type ^= type.InstantiateFrom(*type_arguments, &error);
        ASSERT(error.IsNull());
      }
      *type_arguments = type.arguments();
      *constructor = constructor->RedirectionTarget();
    }
  }
}


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()) {
    ReportError("type name expected");
  }
  intptr_t type_pos = TokenPos();
  // Can't allocate const objects of a deferred type.
  const bool allow_deferred_type = !is_const;
  const Token::Kind la3 = LookaheadToken(3);
  const bool consume_unresolved_prefix =
      (la3 == Token::kLT) || (la3 == Token::kPERIOD) || (la3 == Token::kHASH);

  LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z);
  AbstractType& type = AbstractType::Handle(Z,
      ParseType(ClassFinalizer::kCanonicalizeWellFormed,
                allow_deferred_type,
                consume_unresolved_prefix,
                &prefix));

  if (FLAG_load_deferred_eagerly &&
      !prefix.IsNull() && prefix.is_deferred_load() && !prefix.is_loaded()) {
    // Add runtime check.
    Type& malformed_type = Type::Handle(Z);
    malformed_type = ClassFinalizer::NewFinalizedMalformedType(
        Error::Handle(Z),  // No previous error.
        script_,
        type_pos,
        "deferred type '%s.%s' is not yet loaded",
        String::Handle(Z, prefix.name()).ToCString(),
        String::Handle(type.Name()).ToCString());
    // Note: Adding a statement to current block is a hack, parsing an
    // expression should have no side-effect.
    current_block_->statements->Add(
        ThrowTypeError(type_pos, malformed_type, &prefix));
  }
  // 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(Z),  // No previous error.
        script_,
        type_pos,
        "%s'%s' cannot be instantiated",
        type.IsTypeParameter() ? "type parameter " : "",
        type.IsTypeParameter() ?
            String::Handle(Z, type.UserVisibleName()).ToCString() :
            "dynamic");
  }
  // Attempting to instantiate an enum type is a compile-time error.
  Class& type_class = Class::Handle(Z, type.type_class());
  if (type_class.is_enum_class()) {
    ReportError(new_pos, "enum type '%s' can not be instantiated",
                String::Handle(Z, type_class.Name()).ToCString());
  }

  // The type can be followed by an optional named constructor identifier.
  // Note that we tell ParseType() above not to consume it as part of
  // a misinterpreted qualified identifier. Only a valid library
  // prefix is accepted as qualifier.
  String* named_constructor = NULL;
  const bool is_tearoff_expression = (CurrentToken() == Token::kHASH);
  if (is_tearoff_expression) {
    if (is_const) {
      ReportError("tear-off closure not allowed with const allocation");
    }
    ConsumeToken();
    if (IsIdentifier()) {
      named_constructor = ExpectIdentifier("name of constructor expected");
    }
  } else if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    named_constructor = ExpectIdentifier("name of constructor expected");
  }

  // Parse constructor parameters.
  intptr_t call_pos = TokenPos();
  ArgumentListNode* arguments = NULL;
  if (!is_tearoff_expression) {
    CheckToken(Token::kLPAREN);
    call_pos = TokenPos();
    arguments = ParseActualParameters(NULL, is_const);
  } else {
    // Allocate dummy node with no arguments so we don't have to deal
    // with the NULL corner case below.
    arguments = new(Z) ArgumentListNode(TokenPos());
  }

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

  // Resolve the type and optional identifier to a constructor or factory.
  String& type_class_name = String::Handle(Z, type_class.Name());
  TypeArguments& type_arguments =
      TypeArguments::ZoneHandle(Z, 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(Z);

  // Make sure that an appropriate constructor exists.
  String& constructor_name =
      BuildConstructorName(type_class_name, named_constructor);
  Function& constructor = Function::ZoneHandle(Z,
      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(Z),  // No previous error.
            script_,
            call_pos,
            "class '%s' has no constructor or factory named '%s'",
            String::Handle(Z, type_class.Name()).ToCString(),
            external_constructor_name.ToCString());
        ReportError(Error::Handle(Z, type.error()));
      }
      return ThrowNoSuchMethodError(call_pos,
                                    type_class,
                                    external_constructor_name,
                                    arguments,
                                    InvocationMirror::kConstructor,
                                    InvocationMirror::kMethod,
                                    NULL);  // No existing function.
    } else if (constructor.IsRedirectingFactory()) {
      ClassFinalizer::ResolveRedirectingFactory(type_class, constructor);
      Type& redirect_type = Type::Handle(Z, constructor.RedirectionType());
      if (!redirect_type.IsMalformedOrMalbounded() &&
          !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& error = Error::Handle(Z);
        redirect_type ^= redirect_type.InstantiateFrom(type_arguments, &error);
        if (!error.IsNull()) {
          redirect_type = ClassFinalizer::NewFinalizedMalformedType(
              error,
              script_,
              call_pos,
              "redirecting factory type '%s' cannot be instantiated",
              String::Handle(Z, redirect_type.UserVisibleName()).ToCString());
        }
      }
      if (!redirect_type.HasResolvedTypeClass()) {
        // If the redirection type is unresolved, we convert the allocation
        // into throwing a type error.
        const UnresolvedClass& cls =
            UnresolvedClass::Handle(Z, redirect_type.unresolved_class());
        const LibraryPrefix& prefix =
            LibraryPrefix::Handle(Z, cls.library_prefix());
        if (!prefix.IsNull() && !prefix.is_loaded()) {
          // If the redirection type is unresolved because it refers to
          // an unloaded deferred prefix, mark this function as depending
          // on the library prefix. It will then get invalidated when the
          // prefix is loaded.
          parsed_function()->AddDeferredPrefix(prefix);
        }
        redirect_type = ClassFinalizer::NewFinalizedMalformedType(
            Error::Handle(Z),
            script_,
            call_pos,
            "redirection type '%s' is not loaded",
            String::Handle(Z, redirect_type.UserVisibleName()).ToCString());
      }

      if (redirect_type.IsMalformedOrMalbounded()) {
        if (is_const) {
          ReportError(Error::Handle(Z, redirect_type.error()));
        }
        return ThrowTypeError(redirect_type.token_pos(), redirect_type);
      }
      if (I->flags().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_class_name = type_class.Name();
      type_arguments = type.arguments();
      constructor = constructor.RedirectionTarget();
      constructor_name = constructor.name();
      ASSERT(!constructor.IsNull());
    }
    if (constructor.IsFactory()) {
      // A factory does not have the implicit 'phase' parameter.
      arguments_length -= 1;
    }
  }
  ASSERT(!constructor.IsNull());

  // It is ok to call a factory method of an abstract class, but it is
  // a dynamic error to instantiate an abstract class.
  if (type_class.is_abstract() && !constructor.IsFactory()) {
    // Evaluate arguments before throwing.
    LetNode* result = new(Z) LetNode(call_pos);
    for (intptr_t i = 0; i < arguments->length(); ++i) {
      result->AddNode(arguments->NodeAt(i));
    }
    ArgumentListNode* error_arguments = new(Z) ArgumentListNode(type_pos);
    error_arguments->Add(new(Z) LiteralNode(
        TokenPos(), Integer::ZoneHandle(Z, Integer::New(type_pos))));
    error_arguments->Add(new(Z) LiteralNode(
        TokenPos(), String::ZoneHandle(Z, type_class_name.raw())));
    result->AddNode(
        MakeStaticCall(Symbols::AbstractClassInstantiationError(),
                       Library::PrivateCoreLibName(Symbols::ThrowNew()),
                       error_arguments));
    return result;
  }

  type_arguments ^= type_arguments.Canonicalize();

  if (is_tearoff_expression) {
    const Function& tearoff_func = Function::ZoneHandle(Z,
        BuildConstructorClosureFunction(constructor, new_pos));

    // Local functions normally get parsed when the enclosing function is
    // compiled. Since constructor tearoff closures don't get parsed here,
    // we need to duplicate some of the side effects of parsing, namely
    // creating a function scope, and capturing the instantiator of the
    // enclosing function if necessary.
    OpenFunctionBlock(tearoff_func);
    // If there are type arguments in the tearoff expression that are
    // not yet instantiated, capture the instantiator.
    if (IsInstantiatorRequired() &&
        !type_arguments.IsNull() && !type_arguments.IsInstantiated()) {
      CaptureInstantiator();
    }
    SequenceNode* tearoff_body = CloseBlock();
    ClosureNode* closure_obj =
        new(Z) ClosureNode(new_pos, tearoff_func, NULL, tearoff_body->scope());
    return closure_obj;
  }

  ASSERT(!is_tearoff_expression);
  String& error_message = String::Handle(Z);
  if (!constructor.AreValidArguments(arguments_length,
                                     arguments->names(),
                                     &error_message)) {
    const String& external_constructor_name =
        (named_constructor ? constructor_name : type_class_name);
    if (is_const) {
      ReportError(call_pos,
                  "invalid arguments passed to constructor '%s' "
                  "for class '%s': %s",
                  external_constructor_name.ToCString(),
                  String::Handle(Z, type_class.Name()).ToCString(),
                  error_message.ToCString());
    }
    return ThrowNoSuchMethodError(call_pos,
                                  type_class,
                                  external_constructor_name,
                                  arguments,
                                  InvocationMirror::kConstructor,
                                  InvocationMirror::kMethod,
                                  &constructor);
  }

  // Return a throw in case of a malformed or malbounded type or report a
  // compile-time error if the constructor is const.
  if (type.IsMalformedOrMalbounded()) {
    if (is_const) {
      ReportError(Error::Handle(Z, type.error()));
    }
    return ThrowTypeError(type_pos, type);
  }

  // Make the constructor call.
  AstNode* new_object = NULL;
  if (is_const) {
    if (!constructor.is_const()) {
      const String& external_constructor_name =
          (named_constructor ? constructor_name : type_class_name);
      ReportError("non-const constructor '%s' cannot be used in "
                  "const object creation",
                  external_constructor_name.ToCString());
    }

    Instance& const_instance = Instance::ZoneHandle(Z);
    if (GetCachedConstant(new_pos, &const_instance)) {
      // Cache hit, nothing else to do.
    } else {
      Object& constructor_result = Object::Handle(Z,
          EvaluateConstConstructorCall(type_class,
                                       type_arguments,
                                       constructor,
                                       arguments));
      if (constructor_result.IsUnhandledException()) {
        // It's a compile-time error if invocation of a const constructor
        // call fails.
        ReportErrors(Error::Cast(constructor_result),
                     script_, new_pos,
                     "error while evaluating const constructor");
      }
      const_instance ^= constructor_result.raw();
      CacheConstantValue(new_pos, const_instance);
    }
    new_object = new(Z) LiteralNode(new_pos, const_instance);
    if (!type_bound.IsNull()) {
      ASSERT(!type_bound.IsMalformed());
      Error& malformed_error = Error::Handle(Z);
      ASSERT(!is_top_level_);  // We cannot check unresolved types.
      if (!const_instance.IsInstanceOf(type_bound,
                                       TypeArguments::Handle(Z),
                                       &malformed_error)) {
        type_bound = ClassFinalizer::NewFinalizedMalformedType(
            malformed_error,
            script_,
            new_pos,
            "const factory result is not an instance of '%s'",
            String::Handle(Z, 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(Z) AssignableNode(
         new_pos, new_object, type_bound, Symbols::FactoryResult());
  }
  return new_object;
}


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

  // Build the array of literal values to interpolate.
  const Array& value_arr = Array::Handle(Z, 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(Z, Array::New(1));
  interpolate_arg.SetAt(0, value_arr);

  // Call interpolation function.
  Object& result = Object::Handle(Z);
  {
    PAUSETIMERSCOPE(T, time_compilation);
    result = DartEntry::InvokeFunction(func, interpolate_arg);
  }
  if (result.IsUnhandledException()) {
    ReportError("%s", Error::Cast(result).ToErrorCString());
  }
  String& concatenated = String::ZoneHandle(Z);
  concatenated ^= result.raw();
  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(bool allow_interpolation) {
  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(Z) LiteralNode(literal_start, *CurrentLiteral());
    ConsumeToken();
    return primary;
  }
  // String interpolation needed.
  bool is_compiletime_const = true;
  bool has_interpolation = false;
  GrowableArray<AstNode*> values_list;
  while (CurrentToken() == Token::kSTRING) {
    if (CurrentLiteral()->Length() > 0) {
      // Only add non-empty string sections to the values list
      // that will be concatenated.
      values_list.Add(new(Z) LiteralNode(TokenPos(), *CurrentLiteral()));
    }
    ConsumeToken();
    while ((CurrentToken() == Token::kINTERPOL_VAR) ||
        (CurrentToken() == Token::kINTERPOL_START)) {
      if (!allow_interpolation) {
        ReportError("string interpolation not allowed in this context");
      }
      has_interpolation = true;
      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();
        const bool saved_mode = SetAllowFunctionLiterals(true);
        expr = ParseExpr(kAllowConst, kConsumeCascades);
        SetAllowFunctionLiterals(saved_mode);
        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 strings, 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(Z) LiteralNode(expr_pos,
                                    EvaluateConstExpr(expr_pos, expr));
        } else {
          is_compiletime_const = false;
        }
      }
      values_list.Add(expr);
    }
  }
  if (is_compiletime_const) {
    if (has_interpolation) {
      primary = new(Z) LiteralNode(literal_start, Interpolate(values_list));
    } else {
      GrowableHandlePtrArray<const String> pieces(Z, values_list.length());
      for (int i = 0; i < values_list.length(); i++) {
        const Instance& part = values_list[i]->AsLiteralNode()->literal();
        ASSERT(part.IsString());
        pieces.Add(String::Cast(part));
      }
      const String& lit = String::ZoneHandle(Z, Symbols::FromConcatAll(pieces));
      primary = new(Z) LiteralNode(literal_start, lit);
    }
  } else {
    ArrayNode* values = new(Z) ArrayNode(
        TokenPos(),
        Type::ZoneHandle(Z, Type::ArrayType()),
        values_list);
    primary = new(Z) StringInterpolateNode(TokenPos(), values);
  }
  return primary;
}


AstNode* Parser::ParsePrimary() {
  TRACE_PARSER("ParsePrimary");
  ASSERT(!is_top_level_);
  AstNode* primary = NULL;
  const Token::Kind token = CurrentToken();
  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()) {
    intptr_t qual_ident_pos = TokenPos();
    const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z, ParsePrefix());
    if (!prefix.IsNull()) {
      if (CurrentToken() == Token::kHASH) {
        // Closurization of top-level entity in prefix scope.
        return new(Z) LiteralNode(qual_ident_pos, prefix);
      } else {
        ExpectToken(Token::kPERIOD);
      }
    }
    String& ident = *CurrentLiteral();
    ConsumeToken();
    if (prefix.IsNull()) {
      if (!ResolveIdentInLocalScope(qual_ident_pos, ident, &primary)) {
        // Check whether the identifier is a type parameter.
        if (!current_class().IsNull()) {
          TypeParameter& type_param = TypeParameter::ZoneHandle(Z,
              current_class().LookupTypeParameter(ident));
          if (!type_param.IsNull()) {
            return new(Z) PrimaryNode(qual_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_pos, 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_pos, prefix, ident);

      // If the identifier could not be resolved, throw a NoSuchMethodError.
      // Note: unlike in the case of an unqualified identifier, do not
      // interpret the unresolved identifier as an instance method or
      // instance getter call when compiling an instance method.
      if (primary == NULL) {
        if (prefix.is_deferred_load() &&
            ident.Equals(Symbols::LoadLibrary())) {
          // Hack Alert: recognize special 'loadLibrary' call on the
          // prefix object. The prefix is the primary. Rewind parser and
          // let ParseSelectors() handle the loadLibrary call.
          SetPosition(qual_ident_pos);
          ConsumeToken();  // Prefix name.
          primary = new(Z) LiteralNode(qual_ident_pos, prefix);
        } else {
          // TODO(hausner): Ideally we should generate the NoSuchMethodError
          // later, when we know more about how the unresolved name is used.
          // For example, we don't know yet whether the unresolved name
          // refers to a getter or a setter. However, it is more awkward
          // to distinuish four NoSuchMethodError cases all over the place
          // in the parser. The four cases are: prefixed vs non-prefixed
          // name, static vs dynamic context in which the unresolved name
          // is used. We cheat a little here by looking at the next token
          // to determine whether we have an unresolved method call or
          // field access.
          String& qualified_name = String::ZoneHandle(Z, prefix.name());
          qualified_name = String::Concat(qualified_name, Symbols::Dot());
          qualified_name = Symbols::FromConcat(qualified_name, ident);
          InvocationMirror::Type call_type =
              CurrentToken() == Token::kLPAREN ?
                  InvocationMirror::kMethod : InvocationMirror::kGetter;
          primary = ThrowNoSuchMethodError(qual_ident_pos,
                                           current_class(),
                                           qualified_name,
                                           NULL,  // No arguments.
                                           InvocationMirror::kTopLevel,
                                           call_type,
                                           NULL);  // No existing function.
        }
      } else if (FLAG_load_deferred_eagerly && prefix.is_deferred_load()) {
        // primary != NULL.
        String& qualified_name = String::ZoneHandle(Z, prefix.name());
        qualified_name = String::Concat(qualified_name, Symbols::Dot());
        qualified_name = Symbols::FromConcat(qualified_name, ident);
        InvocationMirror::Type call_type =
            CurrentToken() == Token::kLPAREN ?
                InvocationMirror::kMethod : InvocationMirror::kGetter;
        // Note: Adding a statement to current block is a hack, parsing an
        // espression should have no side-effect.
        current_block_->statements->Add(ThrowNoSuchMethodError(
                                            qual_ident_pos,
                                            current_class(),
                                            qualified_name,
                                            NULL,  // No arguments.
                                            InvocationMirror::kTopLevel,
                                            call_type,
                                            NULL,  // No existing function.
                                            &prefix));
      }
    }
    ASSERT(primary != NULL);
  } else if (token == Token::kTHIS) {
    LocalVariable* local = LookupLocalScope(Symbols::This());
    if (local == NULL) {
      ReportError("receiver 'this' is not in scope");
    }
    primary = new(Z) LoadLocalNode(TokenPos(), local);
    ConsumeToken();
  } else if (token == Token::kINTEGER) {
    const Integer& literal = Integer::ZoneHandle(Z, CurrentIntegerLiteral());
    primary = new(Z) LiteralNode(TokenPos(), literal);
    ConsumeToken();
  } else if (token == Token::kTRUE) {
    primary = new(Z) LiteralNode(TokenPos(), Bool::True());
    ConsumeToken();
  } else if (token == Token::kFALSE) {
    primary = new(Z) LiteralNode(TokenPos(), Bool::False());
    ConsumeToken();
  } else if (token == Token::kNULL) {
    primary = new(Z) LiteralNode(TokenPos(), Instance::ZoneHandle(Z));
    ConsumeToken();
  } else if (token == Token::kLPAREN) {
    ConsumeToken();
    const bool saved_mode = SetAllowFunctionLiterals(true);
    primary = ParseExpr(kAllowConst, kConsumeCascades);
    SetAllowFunctionLiterals(saved_mode);
    ExpectToken(Token::kRPAREN);
  } else if (token == Token::kDOUBLE) {
    Double& double_value = Double::ZoneHandle(Z, CurrentDoubleLiteral());
    if (double_value.IsNull()) {
      ReportError("invalid double literal");
    }
    primary = new(Z) LiteralNode(TokenPos(), double_value);
    ConsumeToken();
  } else if (token == Token::kSTRING) {
    primary = ParseStringLiteral(true);
  } else if (token == Token::kNEW) {
    ConsumeToken();
    primary = ParseNewOperator(Token::kNEW);
  } else if (token == 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 (token == Token::kLT ||
             token == Token::kLBRACK ||
             token == Token::kINDEX ||
             token == Token::kLBRACE) {
    primary = ParseCompoundLiteral();
  } else if (token == Token::kHASH) {
    primary = ParseSymbolLiteral();
  } else if (token == Token::kSUPER) {
    if (current_function().is_static()) {
      ReportError("cannot access superclass from static method");
    }
    if (current_class().SuperClass() == Class::null()) {
      ReportError("class '%s' does not have a superclass",
                  String::Handle(Z, current_class().Name()).ToCString());
    }
    if (!FLAG_supermixin) {
      if (current_class().IsMixinApplication()) {
        const Type& mixin_type = Type::Handle(Z, current_class().mixin());
        if (mixin_type.type_class() == current_function().origin()) {
          ReportError("method of mixin class '%s' may not refer to 'super'",
                      String::Handle(Z, Class::Handle(Z,
                          current_function().origin()).Name()).ToCString());
        }
      }
    }
    const intptr_t super_pos = TokenPos();
    ConsumeToken();
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      const intptr_t ident_pos = TokenPos();
      const String& ident = *ExpectIdentifier("identifier expected");
      if (CurrentToken() == Token::kLPAREN) {
        primary = ParseSuperCall(ident);
      } else {
        primary = ParseSuperFieldAccess(ident, ident_pos);
      }
    } else if ((CurrentToken() == Token::kLBRACK) ||
        Token::CanBeOverloaded(CurrentToken()) ||
        (CurrentToken() == Token::kNE)) {
      primary = ParseSuperOperator();
    } else if (CurrentToken() == Token::kQM_PERIOD) {
      ReportError("super call or super getter may not use ?.");
    } else {
      primary = new(Z) PrimaryNode(super_pos, 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(intptr_t expr_pos, AstNode* expr) {
  if (expr->IsLiteralNode()) {
    return expr->AsLiteralNode()->literal();
  } else if (expr->IsLoadLocalNode() &&
      expr->AsLoadLocalNode()->local().IsConst()) {
    return *expr->AsLoadLocalNode()->local().ConstValue();
  } else if (expr->IsLoadStaticFieldNode()) {
    const Field& field = expr->AsLoadStaticFieldNode()->field();
    // We already checked that this field is const and has been
    // initialized.
    ASSERT(field.is_const());
    ASSERT(field.value() != Object::sentinel().raw());
    ASSERT(field.value() != Object::transition_sentinel().raw());
    return Instance::ZoneHandle(Z, field.value());
  } else {
    ASSERT(expr->EvalConstExpr() != NULL);
    ReturnNode* ret = new(Z) ReturnNode(expr->token_pos(), expr);
    // Compile time constant expressions cannot reference anything from a
    // local scope.
    LocalScope* empty_scope = new(Z) LocalScope(NULL, 0, 0);
    SequenceNode* seq = new(Z) SequenceNode(expr->token_pos(), empty_scope);
    seq->Add(ret);

    Object& result = Object::Handle(Z, Compiler::ExecuteOnce(seq));
    if (result.IsError()) {
      ReportErrors(Error::Cast(result),
                   script_, expr_pos,
                   "error evaluating constant expression");
    }
    ASSERT(result.IsInstance() || result.IsNull());
    Instance& value = Instance::ZoneHandle(Z);
    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, false, &params);
  }
  RawFunction::AsyncModifier async_modifier = ParseFunctionModifier();
  BoolScope allow_await(&this->await_is_keyword_,
                        async_modifier != RawFunction::kNoModifier);
  if (CurrentToken() == Token::kLBRACE) {
    SkipBlock();
    ExpectToken(Token::kRBRACE);
  } 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) {
    const Token::Kind token = CurrentToken();
    if (token == Token::kLPAREN) {
      return;
    }
    if (token == Token::kGET) {
      if (LookaheadToken(1) == Token::kLPAREN) {
        // Case: Function/method named get.
        ConsumeToken();  // Parse away 'get' (the function's name).
        return;
      }
      // Case: Getter.
      ConsumeToken();  // Parse away 'get'.
      ConsumeToken();  // Parse away the getter name.
      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::SkipSymbolLiteral() {
  ConsumeToken();  // Hash sign.
  if (IsIdentifier()) {
    ConsumeToken();
    while (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("identifier expected");
    }
  } else if (Token::CanBeOverloaded(CurrentToken())) {
    ConsumeToken();
  } else {
    UnexpectedToken();
  }
}


void Parser::SkipNewOperator() {
  ConsumeToken();  // Skip new or const keyword.
  if (IsIdentifier()) {
    SkipType(false);
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      ExpectIdentifier("identifier expected");
    } else if (CurrentToken() == Token::kHASH) {
      ConsumeToken();
      if (IsIdentifier()) {
        ConsumeToken();
      }
      return;
    }
    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();
        const bool saved_mode = SetAllowFunctionLiterals(true);
        SkipExpr();
        SetAllowFunctionLiterals(saved_mode);
        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;
    case Token::kHASH:
      SkipSymbolLiteral();
      break;
    default:
      if (IsIdentifier()) {
        ConsumeToken();  // Handle pseudo-keyword identifiers.
      } else {
        UnexpectedToken();
        UNREACHABLE();
      }
      break;
  }
}


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

void Parser::SkipPostfixExpr() {
  SkipPrimary();
  if (CurrentToken() == Token::kHASH) {
    if (IsIdentifier()) {
      ConsumeToken();
      SkipIf(Token::kASSIGN);
    } else if (Token::CanBeOverloaded(CurrentToken())) {
      ConsumeToken();
    } else {
      ReportError("identifier or operator expected");
    }
  }
  SkipSelectors();
  if (IsIncrementOperator(CurrentToken())) {
    ConsumeToken();
  }
}


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


void Parser::SkipBinaryExpr() {
  SkipUnaryExpr();
  const int min_prec = Token::Precedence(Token::kIFNULL);
  const int max_prec = Token::Precedence(Token::kMUL);
  while (((min_prec <= Token::Precedence(CurrentToken())) &&
      (Token::Precedence(CurrentToken()) <= max_prec))) {
    if (CurrentToken() == Token::kIS) {
      ConsumeToken();
      if (CurrentToken() == Token::kNOT) {
        ConsumeToken();
      }
      SkipType(false);
    } else if (CurrentToken() == Token::kAS) {
      ConsumeToken();
      SkipType(false);
    } else {
      ConsumeToken();
      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
