// 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 "vm/flags.h"

#ifndef DART_PRECOMPILED_RUNTIME

#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/kernel_to_il.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/resolver.h"
#include "vm/safepoint.h"
#include "vm/scanner.h"
#include "vm/scopes.h"
#include "vm/stack_frame.h"
#include "vm/symbols.h"
#include "vm/tags.h"
#include "vm/timeline.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, trace_parser, false, "Trace parser operations.");
DEFINE_FLAG(bool,
            support_deprecated_tearoff_syntax,
            false,
            "Support new tear-off syntax.");
// TODO(floitsch): remove the conditional-directive flag, once we publicly
// committed to the current version.
DEFINE_FLAG(bool,
            conditional_directives,
            true,
            "Enable conditional directives");
DEFINE_FLAG(bool, generic_method_syntax, true, "Enable generic functions.");
DEFINE_FLAG(bool,
            initializing_formal_access,
            true,
            "Make initializing formal parameters visible in initializer list.");
DEFINE_FLAG(bool,
            warn_super,
            false,
            "Warning if super initializer not last in initializer list.");
DEFINE_FLAG(bool, warn_patch, false, "Warn on old-style patch syntax.");
DEFINE_FLAG(
    bool,
    await_is_keyword,
    false,
    "await and yield are treated as proper keywords in synchronous code.");
DEFINE_FLAG(bool,
            assert_initializer,
            false,
            "Allow asserts in initializer lists.");

DECLARE_FLAG(bool, profile_vm);
DECLARE_FLAG(bool, trace_service);
DECLARE_FLAG(bool, ignore_patch_signature_mismatch);

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

// Quick synthetic token position.
#define ST(token_pos) ((token_pos).ToSynthetic())

#if defined(DEBUG)
class TraceParser : public ValueObject {
 public:
  TraceParser(TokenPosition 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.value());
      }
      (*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;
};


// Helper class to save and restore token position.
class Parser::TokenPosScope : public ValueObject {
 public:
  explicit TokenPosScope(Parser* p) : p_(p) { saved_pos_ = p_->TokenPos(); }
  TokenPosScope(Parser* p, TokenPosition pos) : p_(p), saved_pos_(pos) {}
  ~TokenPosScope() { p_->SetPosition(saved_pos_); }

 private:
  Parser* p_;
  TokenPosition saved_pos_;
  DISALLOW_COPY_AND_ASSIGN(TokenPosScope);
};


class RecursionChecker : public ValueObject {
 public:
  explicit RecursionChecker(Parser* p) : parser_(p) {
    parser_->recursion_counter_++;
    // No need to check the stack unless the parser is in an unusually deep
    // recurive state. Thus, we omit the more expensive stack checks in
    // the common case.
    const int kMaxUncheckedDepth = 100;  // Somewhat arbitrary.
    if (parser_->recursion_counter_ > kMaxUncheckedDepth) {
      parser_->CheckStack();
    }
  }
  ~RecursionChecker() { parser_->recursion_counter_--; }

 private:
  Parser* parser_;
};


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


void ParsedFunction::AddToGuardedFields(const Field* field) const {
  if ((field->guarded_cid() == kDynamicCid) ||
      (field->guarded_cid() == kIllegalCid)) {
    return;
  }

  for (intptr_t j = 0; j < guarded_fields_->length(); j++) {
    const Field* other = (*guarded_fields_)[j];
    if (field->Original() == other->Original()) {
      // Abort background compilation early if the guarded state of this field
      // has changed during compilation. We will not be able to commit
      // the resulting code anyway.
      if (Compiler::IsBackgroundCompilation()) {
        if (!other->IsConsistentWith(*field)) {
          Compiler::AbortBackgroundCompilation(
              Thread::kNoDeoptId,
              "Field's guarded state changed during compilation");
        }
      }
      return;
    }
  }

  // Note: the list of guarded fields must contain copies during background
  // compilation because we will look at their guarded_cid when copying
  // the array of guarded fields from callee into the caller during
  // inlining.
  ASSERT(!field->IsOriginal() || Thread::Current()->IsMutatorThread());
  guarded_fields_->Add(&Field::ZoneHandle(Z, field->raw()));
}


void ParsedFunction::Bailout(const char* origin, const char* reason) const {
  Report::MessageF(Report::kBailout, Script::Handle(function_.script()),
                   function_.token_pos(), Report::AtLocation,
                   "%s Bailout in %s: %s", origin,
                   String::Handle(function_.name()).ToCString(), reason);
  UNREACHABLE();
}


kernel::ScopeBuildingResult* ParsedFunction::EnsureKernelScopes() {
  if (kernel_scopes_ == NULL) {
    kernel::TreeNode* node = NULL;
    if (function().kernel_function() != NULL) {
      node = static_cast<kernel::TreeNode*>(function().kernel_function());
    }
    kernel::ScopeBuilder builder(this, node);
    kernel_scopes_ = builder.BuildScopes();
  }
  return kernel_scopes_;
}


LocalVariable* ParsedFunction::EnsureExpressionTemp() {
  if (!has_expression_temp_var()) {
    LocalVariable* temp =
        new (Z) LocalVariable(function_.token_pos(), function_.token_pos(),
                              Symbols::ExprTemp(), Object::dynamic_type());
    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(), function_.token_pos(),
                              Symbols::FinallyRetVal(), Object::dynamic_type());
    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(TokenPosition::kNoSource),
        type(NULL),
        name(NULL),
        var(NULL) {}
  TokenPosition 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);
  void RemoveJumpToLabel(SourceLabel* label);
  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);
}


void Parser::TryStack::RemoveJumpToLabel(SourceLabel* label) {
  int i = 0;
  while (i < inlined_finally_nodes_.length()) {
    if (inlined_finally_nodes_[i]->IsJumpNode()) {
      JumpNode* jump = inlined_finally_nodes_[i]->AsJumpNode();
      if (jump->label() == label) {
        // Shift remaining entries left and delete last entry.
        for (int j = i + 1; j < inlined_finally_nodes_.length(); j++) {
          inlined_finally_nodes_[j - 1] = inlined_finally_nodes_[j];
        }
        inlined_finally_nodes_.RemoveLast();
        continue;
      }
    }
    i++;
  }
}


// For parsing a compilation unit.
Parser::Parser(const Script& script,
               const Library& library,
               TokenPosition token_pos)
    : thread_(Thread::Current()),
      isolate_(thread()->isolate()),
      script_(Script::Handle(zone(), script.raw())),
      tokens_iterator_(zone(),
                       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),
      recursion_counter_(0) {
  ASSERT(tokens_iterator_.IsValid());
  ASSERT(!library.IsNull());
}


// For parsing a function.
Parser::Parser(const Script& script,
               ParsedFunction* parsed_function,
               TokenPosition token_pos)
    : thread_(Thread::Current()),
      isolate_(thread()->isolate()),
      script_(Script::Handle(zone(), script.raw())),
      tokens_iterator_(zone(),
                       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_(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),
      recursion_counter_(0) {
  ASSERT(tokens_iterator_.IsValid());
  ASSERT(!current_function().IsNull());
  EnsureExpressionTemp();
}


Parser::~Parser() {
  if (unregister_pending_function_) {
    const GrowableObjectArray& pending_functions =
        GrowableObjectArray::Handle(T->pending_functions());
    ASSERT(!pending_functions.IsNull());
    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, TokenPosition 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_;
}


int Parser::FunctionLevel() const {
  if (current_block_ != NULL) {
    return current_block_->scope->function_level();
  }
  return 0;
}


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


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


void Parser::SetPosition(TokenPosition position) {
  tokens_iterator_.SetCurrentPosition(position);
  token_kind_ = Token::kILLEGAL;
  prev_token_pos_ = position;
}


// Set state and increments generational count so that thge background compiler
// can detect if loading/top-level-parsing occured during compilation.
class TopLevelParsingScope : public StackResource {
 public:
  explicit TopLevelParsingScope(Thread* thread) : StackResource(thread) {
    isolate()->IncrTopLevelParsingCount();
  }
  ~TopLevelParsingScope() {
    isolate()->DecrTopLevelParsingCount();
    isolate()->IncrLoadingInvalidationGen();
  }
};


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);
#ifndef PRODUCT
  VMTagScope tagScope(thread, VMTag::kCompileTopLevelTagId);
  TimelineDurationScope tds(thread, Timeline::GetCompilerStream(),
                            "CompileTopLevel");
  if (tds.enabled()) {
    tds.SetNumArguments(1);
    tds.CopyArgument(0, "script", String::Handle(script.url()).ToCString());
  }
#endif

  TopLevelParsingScope scope(thread);
  Parser parser(script, library, TokenPosition::kMinSource);
  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) {
  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());
  return ri;
}


struct ParamDesc {
  ParamDesc()
      : type(NULL),
        name_pos(TokenPosition::kNoSource),
        name(NULL),
        default_value(NULL),
        metadata(NULL),
        var(NULL),
        is_final(false),
        is_field_initializer(false),
        has_explicit_type(false),
        is_covariant(false) {}
  const AbstractType* type;
  TokenPosition 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;
  bool is_covariant;
};


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;
    has_covariant = false;
    implicitly_final = false;
    skipped = false;
    this->parameters = new ZoneGrowableArray<ParamDesc>();
  }

  void AddFinalParameter(TokenPosition 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, TokenPosition token_pos) {
    ASSERT(this->parameters->is_empty());
    AddFinalParameter(token_pos, &Symbols::This(), receiver_type);
  }

  void EraseParameterTypes() {
    const int num_parameters = parameters->length();
    for (int i = 0; i < num_parameters; i++) {
      (*parameters)[i].type = &Object::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 (FLAG_initializing_formal_access || !param.is_field_initializer) {
        param.var->set_invisible(invisible);
      }
    }
  }

  void HideInitFormals() {
    const intptr_t num_params = parameters->length();
    for (int i = 0; i < num_params; i++) {
      ParamDesc& param = (*parameters)[i];
      if (param.is_field_initializer) {
        ASSERT(param.var != NULL);
        param.var->set_invisible(true);
      }
    }
  }

  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 has_covariant;
  bool implicitly_final;
  bool skipped;
  ZoneGrowableArray<ParamDesc>* parameters;
};


struct MemberDesc {
  MemberDesc() { Clear(); }

  void Clear() {
    has_abstract = false;
    has_external = false;
    has_covariant = false;
    has_final = false;
    has_const = false;
    has_static = false;
    has_var = false;
    has_factory = false;
    has_operator = false;
    has_native = false;
    metadata_pos = TokenPosition::kNoSource;
    operator_token = Token::kILLEGAL;
    type = NULL;
    name_pos = TokenPosition::kNoSource;
    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_covariant;
  bool has_final;
  bool has_const;
  bool has_static;
  bool has_var;
  bool has_factory;
  bool has_operator;
  bool has_native;
  TokenPosition metadata_pos;
  Token::Kind operator_token;
  const AbstractType* type;
  TokenPosition name_pos;
  TokenPosition 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,
            TokenPosition 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;
  }

  TokenPosition 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_;
  TokenPosition 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) {
  Thread* thread = Thread::Current();
  Zone* zone = thread->zone();
  const int64_t num_tokes_before = STAT_VALUE(thread, num_tokens_consumed);
#ifndef PRODUCT
  TimelineDurationScope tds(thread, Timeline::GetCompilerStream(),
                            "ParseClass");
  if (tds.enabled()) {
    tds.SetNumArguments(1);
    tds.CopyArgument(0, "class", String::Handle(cls.Name()).ToCString());
  }
#endif
  if (!cls.is_synthesized_class()) {
    ASSERT(thread->long_jump_base()->IsSafeToJump());
    CSTAT_TIMER_SCOPE(thread, parser_timer);
    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()) {
    ASSERT(thread->long_jump_base()->IsSafeToJump());
    CSTAT_TIMER_SCOPE(thread, parser_timer);
    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);
  }
  const int64_t num_tokes_after = STAT_VALUE(thread, num_tokens_consumed);
  INC_STAT(thread, num_class_tokens, num_tokes_after - num_tokes_before);
}


RawObject* Parser::ParseFunctionParameters(const Function& func) {
  ASSERT(!func.IsNull());
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    Thread* thread = Thread::Current();
    StackZone stack_zone(thread);
    Zone* zone = stack_zone.GetZone();
    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, Heap::kOld));
    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 {
    Thread* thread = Thread::Current();
    Error& error = Error::Handle();
    error = thread->sticky_error();
    thread->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()->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());
  Zone* zone = thread->zone();
  CSTAT_TIMER_SCOPE(thread, parser_timer);
  INC_STAT(thread, num_functions_parsed, 1);
#ifndef PRODUCT
  VMTagScope tagScope(thread, VMTag::kCompileParseFunctionTagId,
                      FLAG_profile_vm);
  TimelineDurationScope tds(thread, Timeline::GetCompilerStream(),
                            "ParseFunction");
#endif  // !PRODUCT
  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());
#ifndef PRODUCT
  if (tds.enabled()) {
    tds.SetNumArguments(1);
    tds.CopyArgument(0, "function", String::Handle(func.name()).ToCString());
  }
#endif  // !PRODUCT
  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, false);
      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(thread, num_implicit_final_getters, 1);
      break;
    case RawFunction::kMethodExtractor:
      node_sequence = parser.ParseMethodExtractor(func);
      INC_STAT(thread, num_method_extractors, 1);
      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 Field& meta_data) {
  LongJumpScope jump;
  if (setjmp(*jump.Set()) == 0) {
    Thread* thread = Thread::Current();
    StackZone stack_zone(thread);
    Zone* zone = stack_zone.GetZone();
    const Class& owner_class = Class::Handle(zone, meta_data.Owner());
    const Script& script = Script::Handle(zone, meta_data.Script());
    const TokenPosition token_pos = meta_data.token_pos();
    // 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
                      Object::Handle(zone, meta_data.RawOwner()), 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(owner_class);
    parser.OpenFunctionBlock(fake_function);

    RawObject* metadata = parser.EvaluateMetadata();
    return metadata;
  } else {
    Thread* thread = Thread::Current();
    StackZone stack_zone(thread);
    Zone* zone = stack_zone.GetZone();
    Error& error = Error::Handle(zone);
    error = thread->sticky_error();
    thread->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(Heap::kOld));
  while (CurrentToken() == Token::kAT) {
    ConsumeToken();
    TokenPosition 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 TokenPosition 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, Heap::kOld);
  }
  return Array::MakeArray(meta_values);
}


SequenceNode* Parser::ParseStaticInitializer() {
  ExpectIdentifier("field name expected");
  CheckToken(Token::kASSIGN, "field initialier expected");
  ConsumeToken();
  OpenFunctionBlock(parsed_function()->function());
  TokenPosition 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();
#ifndef PRODUCT
  VMTagScope tagScope(thread, VMTag::kCompileParseFunctionTagId,
                      FLAG_profile_vm);
  TimelineDurationScope tds(thread, Timeline::GetCompilerStream(),
                            "ParseStaticFieldInitializer");
#endif  // !PRODUCT

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

  const Script& script = Script::Handle(zone, field.Script());
  Object& initializer_owner = Object::Handle(field.Owner());
  initializer_owner = PatchClass::New(Class::Handle(field.Owner()), script);

  const Function& initializer = Function::ZoneHandle(
      zone, Function::New(init_name, RawFunction::kImplicitStaticFinalGetter,
                          true,   // static
                          false,  // !const
                          false,  // !abstract
                          false,  // !external
                          false,  // !native
                          initializer_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 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.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;
}


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

  TokenPosition 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));
  ASSERT(!field.IsNull());

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

  const TokenPosition 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 TokenPosition 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(ST(ident_pos), load_field);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


// Create AstNodes for an implicit instance setter method:
//   LoadLocalNode 0 ('this')
//   LoadLocalNode 1 ('value')
//   SetInstanceField (field_name);
//   ReturnNode (void);
SequenceNode* Parser::ParseInstanceSetter(const Function& func) {
  TRACE_PARSER("ParseInstanceSetter");
  // func.token_pos() points to the name of the field.
  const TokenPosition 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,
                                 /* is_initializer = */ false);
  current_block_->statements->Add(store_field);
  current_block_->statements->Add(new ReturnNode(ST(ident_pos)));
  return CloseBlock();
}


SequenceNode* Parser::ParseConstructorClosure(const Function& func) {
  TRACE_PARSER("ParseConstructorClosure");
  const TokenPosition 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(),
                           &Object::dynamic_type());
  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(), Heap::kOld));
    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");
  TokenPosition token_pos = func.token_pos();

  OpenFunctionBlock(func);

  ParamList params;
  params.AddFinalParameter(token_pos, &Symbols::ClosureParameter(),
                           &Object::dynamic_type());

  const Function& parent = Function::Handle(func.parent_function());
  if (parent.IsImplicitSetterFunction()) {
    const TokenPosition ident_pos = func.token_pos();
    ASSERT(IsIdentifier());
    params.AddFinalParameter(ident_pos, &Symbols::Value(),
                             &Object::dynamic_type());
    ASSERT(func.num_fixed_parameters() == 2);  // closure, value.
  } else if (!parent.IsGetterFunction() && !parent.IsImplicitGetterFunction()) {
    // NOTE: For the `kernel -> flowgraph` we don't use the parser.
    if (parent.kernel_function() == NULL) {
      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()) {
    // TODO(srdjan): Must allocate array in old space, since it
    // runs in background compiler. Find a better way.
    const Array& arg_names =
        Array::ZoneHandle(Array::New(func.NumOptionalParameters(), Heap::kOld));
    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);
  }

  const String& func_name = String::ZoneHandle(parent.name());
  const Class& owner = Class::Handle(parent.Owner());
  Function& target = Function::ZoneHandle(owner.LookupFunction(func_name));
  if (target.raw() != parent.raw()) {
    ASSERT(Isolate::Current()->HasAttemptedReload());
    if (target.IsNull() || (target.is_static() != parent.is_static()) ||
        (target.kind() != parent.kind())) {
      target = Function::null();
    }
  }

  AstNode* call = NULL;
  // Check the target still exists and has compatible parameters. If not,
  // throw NSME/call nSM instead of forwarding the call. Note we compare the
  // parent not func because func has an extra parameter for the closure
  // receiver.
  if (!target.IsNull() &&
      (parent.num_fixed_parameters() == target.num_fixed_parameters())) {
    call = new StaticCallNode(token_pos, target, func_args);
  } else if (!parent.is_static()) {
    ASSERT(Isolate::Current()->HasAttemptedReload());
    // If a subsequent reload reintroduces the target in the middle of the
    // Invocation object being constructed, we won't be able to successfully
    // deopt because the generated AST will change.
    func.SetIsOptimizable(false);

    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(
                                    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);
    }
    call = new StaticCallNode(token_pos, no_such_method, arguments);
  } else {
    ASSERT(Isolate::Current()->HasAttemptedReload());
    // If a subsequent reload reintroduces the target in the middle of the
    // arguments array being constructed, we won't be able to successfully
    // deopt because the generated AST will change.
    func.SetIsOptimizable(false);

    InvocationMirror::Type im_type;
    if (parent.IsImplicitGetterFunction()) {
      im_type = InvocationMirror::kGetter;
    } else if (parent.IsImplicitSetterFunction()) {
      im_type = InvocationMirror::kSetter;
    } else {
      im_type = InvocationMirror::kMethod;
    }
    call = ThrowNoSuchMethodError(TokenPos(), owner, func_name, func_args,
                                  InvocationMirror::kStatic, im_type,
                                  NULL);  // No existing function.
  }

  ASSERT(call != NULL);
  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");

  ParamList params;

  const TokenPosition ident_pos = func.token_pos();
  ASSERT(func.token_pos() == TokenPosition::kMethodExtractor);
  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(ident_pos, closure);
  current_block_->statements->Add(return_node);
  return CloseBlock();
}


void Parser::BuildDispatcherScope(const Function& func,
                                  const ArgumentsDescriptor& desc) {
  ParamList params;
  // Receiver first.
  TokenPosition 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(T, name));
    p.type = &Object::dynamic_type();
    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 = &Object::dynamic_type();
    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());
  TokenPosition token_pos = func.token_pos();
  ASSERT(func.token_pos() == TokenPosition::kMinSource);
  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(), Heap::kOld));
    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(func.IsInvokeFieldDispatcher());
  TokenPosition token_pos = func.token_pos();
  ASSERT(func.token_pos() == TokenPosition::kMinSource);
  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& closure_cls =
      Class::Handle(Isolate::Current()->object_store()->closure_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() == closure_cls.raw() && name.Equals(Symbols::Call())) {
    function_object = receiver;
  } else {
    const String& getter_name =
        String::ZoneHandle(Z, Field::GetterSymbol(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() == closure_cls.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(TokenPosition 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<TokenPosition> 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 TokenPosition start_pos = TokenPos();
  TokenPosition opening_pos = start_pos;
  token_pos_stack.Add(start_pos);
  bool is_match = true;
  bool unexpected_token_found = false;
  Token::Kind token = opening_token;
  TokenPosition 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:
        opening_token = token_stack.RemoveLast();
        opening_pos = token_pos_stack.RemoveLast();
        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::AtLocation,
        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 final_seen = false;
  bool this_seen = false;

  if (evaluate_metadata && (CurrentToken() == Token::kAT)) {
    parameter.metadata = &Array::ZoneHandle(Z, EvaluateMetadata());
  } else {
    SkipMetadata();
  }

  if (CurrentToken() == Token::kCOVARIANT &&
      (LookaheadToken(1) == Token::kFINAL || LookaheadToken(1) == Token::kVAR ||
       Token::IsIdentifier(LookaheadToken(1)))) {
    parameter.is_covariant = true;
    ConsumeToken();
  }
  if (CurrentToken() == Token::kFINAL) {
    ConsumeToken();
    final_seen = true;
    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 = &Object::dynamic_type();
  }
  if (CurrentToken() == Token::kTHIS) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
    this_seen = true;
    parameter.is_field_initializer = true;
    if (FLAG_initializing_formal_access) {
      parameter.is_final = true;
    }
  }
  if ((parameter.type == NULL) && (CurrentToken() == Token::kVOID)) {
    ConsumeToken();
    // This must later be changed to a closure type if we recognize
    // a closure/function type parameter. We check this at the end
    // of ParseFormalParameter.
    parameter.type = &Object::void_type();
  }
  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");
    }

    // Lookahead to determine whether the next tokens are a return type
    // followed by a parameter name.
    bool found_type = false;
    {
      TokenPosScope saved_pos(this);
      if (TryParseReturnType()) {
        if (IsIdentifier() || (CurrentToken() == Token::kTHIS)) {
          found_type = true;
        }
      }
    }
    if (found_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;
      // It is too early to resolve the type here, since it can be a result type
      // referring to a not yet declared function type parameter.
      parameter.type = &AbstractType::ZoneHandle(
          Z, ParseType(ClassFinalizer::kDoNotResolve));
    } 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 = &Object::dynamic_type();
    }
  }
  if (!this_seen && (CurrentToken() == Token::kTHIS)) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
    this_seen = true;
    parameter.is_field_initializer = true;
    if (FLAG_initializing_formal_access) {
      parameter.is_final = 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 (IsParameterPart()) {
    // 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.
    // TODO(hausner): The language spec appears to allow var and final
    // in signature types when used with initializing formals:
    // fieldFormalParameter:
    // metadata finalConstVarOrType? this ‘.’ identifier formalParameterList? ;
    if (!var_seen && !final_seen) {
      // The parsed parameter type is actually the function result type.
      AbstractType& result_type =
          AbstractType::Handle(Z, parameter.type->raw());

      // In top-level and mixin functions, the source may be in a different
      // script than the script of the current class. However, we never reparse
      // signature functions (except typedef signature functions), therefore
      // we do not need to keep the correct script via a patch class. Use the
      // actual current class as owner of the signature function.
      Function& signature_function =
          Function::Handle(Z, Function::NewSignatureFunction(
                                  current_class(), TokenPosition::kNoSource));
      signature_function.set_parent_function(innermost_function());
      innermost_function_ = signature_function.raw();

      // Finish parsing the function type parameter.
      if (CurrentToken() == Token::kLT) {
        if (!FLAG_generic_method_syntax) {
          ReportError("generic function types not supported");
        }
        ParseTypeParameters(false);  // Not parameterizing class, but function.
      }

      // Now that type parameters are declared, the result type can be resolved.
      ResolveType(is_top_level_ ? ClassFinalizer::kResolveTypeParameters
                                : ClassFinalizer::kCanonicalize,
                  &result_type);

      ASSERT(CurrentToken() == Token::kLPAREN);
      ParamList func_params;

      // Add implicit closure object parameter.
      func_params.AddFinalParameter(TokenPos(), &Symbols::ClosureParameter(),
                                    &Object::dynamic_type());

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

      signature_function.set_result_type(result_type);
      AddFormalParamsToFunction(&func_params, signature_function);

      ASSERT(innermost_function().raw() == signature_function.raw());
      innermost_function_ = signature_function.parent_function();

      Type& signature_type =
          Type::ZoneHandle(Z, signature_function.SignatureType());
      if (!is_top_level_) {
        signature_type ^= ClassFinalizer::FinalizeType(
            current_class(), signature_type, ClassFinalizer::kCanonicalize);
        // Do not refer to signature_function anymore, since it may have been
        // replaced during canonicalization.
        signature_function = Function::null();
      }
      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;
    }
  } else {
    if (!parameter.type->IsFinalized()) {
      AbstractType& type = AbstractType::ZoneHandle(Z, parameter.type->raw());
      if (is_top_level_) {
        ResolveType(ClassFinalizer::kResolveTypeParameters, &type);
      } else {
        ResolveType(ClassFinalizer::kCanonicalize, &type);
        type = ClassFinalizer::FinalizeType(current_class(), type,
                                            ClassFinalizer::kCanonicalize);
      }
      parameter.type = &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 {
      ConsumeToken();
    }
    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);
  if (parameter.is_covariant) {
    params->has_covariant = true;
  }
}


// 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");
  // Optional parameter lists cannot be empty.
  // The completely empty parameter list is handled before getting here.
  bool has_seen_parameter = false;
  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;
    }
    Token::Kind terminator = params->has_optional_positional_parameters
                                 ? Token::kRBRACK
                                 : params->has_optional_named_parameters
                                       ? Token::kRBRACE
                                       : Token::kRPAREN;
    if (has_seen_parameter && CurrentToken() == terminator) {
      // Allow a trailing comma.
      break;
    }
    ParseFormalParameter(allow_explicit_default_values, evaluate_metadata,
                         params);
    has_seen_parameter = true;
  } 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(TokenPosition 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(Z, 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(Z, super_class, getter_name);
    ASSERT(super_func.IsNull() ||
           (super_func.kind() != RawFunction::kImplicitStaticFinalGetter));
  }
  if (super_func.IsNull()) {
    super_func = Resolver::ResolveDynamicAnyArgs(Z, 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(
    TokenPosition call_pos,
    const String& function_name,
    const ArgumentListNode& function_args,
    const LocalVariable* temp_for_last_arg,
    bool is_super_invocation) {
  const TokenPosition 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(
    TokenPosition 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 TokenPosition 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 TokenPosition 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 TokenPosition 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 = Symbols::Token(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 TokenPosition 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 = Symbols::Token(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,
                                               TokenPosition token_pos,
                                               AstNode* receiver) {
  Function& implicit_closure_function =
      Function::ZoneHandle(Z, func.ImplicitClosureFunction());
  return new ClosureNode(token_pos, implicit_closure_function, receiver, NULL);
}


AstNode* Parser::ParseSuperFieldAccess(const String& field_name,
                                       TokenPosition 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::LookupGetterSymbol(field_name));
  Function& super_getter = Function::ZoneHandle(Z);
  if (!getter_name.IsNull()) {
    super_getter = Resolver::ResolveDynamicAnyArgs(Z, super_class, getter_name);
  }
  if (super_getter.IsNull()) {
    const String& setter_name =
        String::ZoneHandle(Z, Field::LookupSetterSymbol(field_name));
    Function& super_setter = Function::ZoneHandle(Z);
    if (!setter_name.IsNull()) {
      super_setter =
          Resolver::ResolveDynamicAnyArgs(Z, 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(Z, 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);
}


StaticCallNode* Parser::GenerateSuperConstructorCall(
    const Class& cls,
    TokenPosition supercall_pos,
    LocalVariable* receiver,
    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 NULL;
  }
  String& super_ctor_name = String::Handle(Z, super_class.Name());
  super_ctor_name = Symbols::FromDot(T, super_ctor_name);

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

  // If this is a super call in a forwarding constructor, add the user-
  // defined arguments to the super call and adjust 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(T, ctor_name, kLen, ctor_name.Length() - kLen);
      super_ctor_name = Symbols::FromConcat(T, 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());
  }
  return new StaticCallNode(supercall_pos, super_ctor, arguments);
}


StaticCallNode* Parser::ParseSuperInitializer(const Class& cls,
                                              LocalVariable* receiver) {
  TRACE_PARSER("ParseSuperInitializer");
  ASSERT(CurrentToken() == Token::kSUPER);
  const TokenPosition 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(T, ctor_name, Symbols::Dot());
  if (CurrentToken() == Token::kPERIOD) {
    ConsumeToken();
    ctor_name = Symbols::FromConcat(
        T, 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);

  // '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 TokenPosition field_pos = TokenPos();
  if (FLAG_assert_initializer && CurrentToken() == Token::kASSERT) {
    return ParseAssertStatement(current_function().is_const());
  }
  if (CurrentToken() == Token::kTHIS) {
    ConsumeToken();
    ExpectToken(Token::kPERIOD);
  }
  const String& field_name = *ExpectIdentifier("field name expected");
  ExpectToken(Token::kASSIGN);

  TokenPosition expr_pos = TokenPos();
  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()) {
    if (!init_expr->IsPotentiallyConst()) {
      ReportError(expr_pos,
                  "initializer expression must be compile time constant.");
    }
    if (init_expr->EvalConstExpr() != NULL) {
      // If the expression is a compile-time constant, ensure that it
      // is evaluated and canonicalized. See issue 27164.
      init_expr = FoldConstExpr(expr_pos, init_expr);
    }
  }
  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,
                                       /* is_initializer = */ true);
  }
  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();
        ASSERT(field.IsOriginal());
        if (initializer->field().Original() == field.raw()) {
          found = true;
          break;
        }
      }
    }

    if (found) continue;

    field.RecordStore(Object::null_object());
  }
}


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 the
  // library and token stream (script).
  // The current_class remains unchanged, so that type arguments
  // are resolved in the correct scope class.
  ASSERT(current_class().raw() != field.Origin());
  const Library& saved_library = Library::Handle(Z, library().raw());
  const Script& saved_script = Script::Handle(Z, script().raw());
  const TokenPosition saved_token_pos = TokenPos();

  const Class& origin_class = Class::Handle(Z, field.Origin());
  set_library(Library::Handle(Z, origin_class.library()));
  SetScript(Script::Handle(Z, origin_class.script()), field.token_pos());

  ASSERT(IsIdentifier());
  ConsumeToken();
  ExpectToken(Token::kASSIGN);
  AstNode* init_expr = NULL;
  TokenPosition expr_pos = TokenPos();
  if (field.is_const()) {
    init_expr = ParseConstExpr();
  } else {
    init_expr = ParseExpr(kAllowConst, kConsumeCascades);
    if (init_expr->EvalConstExpr() != NULL) {
      init_expr = FoldConstExpr(expr_pos, init_expr);
    }
  }
  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 TokenPosition 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 {
          TokenPosition expr_pos = TokenPos();
          init_expr = ParseExpr(kAllowConst, kConsumeCascades);
          if (init_expr->EvalConstExpr() != NULL) {
            init_expr = FoldConstExpr(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,
          /* is_initializer = */ true);
      current_block_->statements->Add(field_init);
    }
  }
  initialized_fields->Add(NULL);  // End of inline initializers.
  SetPosition(saved_pos);
}


AstNode* Parser::CheckDuplicateFieldInit(
    TokenPosition 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, Object::null_array()));

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

      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_is_last = false;
  intptr_t super_init_index = -1;
  StaticCallNode* super_init_call = NULL;
  if (CurrentToken() == Token::kCOLON) {
    do {
      ConsumeToken();  // Colon or comma.
      if (CurrentToken() == Token::kSUPER) {
        if (super_init_call != NULL) {
          ReportError("duplicate call to super constructor");
        }
        super_init_call = ParseSuperInitializer(cls, receiver);
        super_init_index = current_block_->statements->length();
        current_block_->statements->Add(super_init_call);
        super_init_is_last = true;
      } else {
        AstNode* init_statement =
            ParseInitializer(cls, receiver, initialized_fields);
        super_init_is_last = false;
        if (init_statement != NULL) {
          current_block_->statements->Add(init_statement);
        }
      }
    } while (CurrentToken() == Token::kCOMMA);
  }
  if (super_init_call == NULL) {
    // Generate implicit super() if we haven't seen an explicit super call
    // or constructor redirection.
    super_init_call =
        GenerateSuperConstructorCall(cls, TokenPos(), receiver, NULL);
    if (super_init_call != NULL) {
      super_init_index = current_block_->statements->length();
      current_block_->statements->Add(super_init_call);
      super_init_is_last = true;
    }
  }
  if ((super_init_call != NULL) && !super_init_is_last) {
    // If the super initializer call is not at the end of the initializer
    // list, implicitly move it to the end. The actual parameter values
    // are evaluated at the original position in the list and preserved
    // in temporary variables. (The following initializer expressions
    // could have side effects that alter the arguments to the super
    // initializer.) E.g:
    // A(x) : super(x), f = x++ { ... }
    // is transformed to:
    // A(x) : temp = x, f = x++, super(temp) { ... }
    if (FLAG_warn_super) {
      ReportWarning("Super initializer not at end");
    }
    ASSERT(super_init_index >= 0);
    ArgumentListNode* ctor_args = super_init_call->arguments();
    LetNode* saved_args = new (Z) LetNode(super_init_call->token_pos());
    // The super initializer call has at least 1 arguments: the
    // implicit receiver.
    ASSERT(ctor_args->length() >= 1);
    for (int i = 1; i < ctor_args->length(); i++) {
      AstNode* arg = ctor_args->NodeAt(i);
      LocalVariable* temp = CreateTempConstVariable(arg->token_pos(), "sca");
      AstNode* save_temp = new (Z) StoreLocalNode(arg->token_pos(), temp, arg);
      saved_args->AddNode(save_temp);
      ctor_args->SetNodeAt(i, new (Z) LoadLocalNode(arg->token_pos(), temp));
    }
    current_block_->statements->ReplaceNodeAt(super_init_index, saved_args);
    current_block_->statements->Add(super_init_call);
  }
  CheckFieldsInitialized(cls);
}


void Parser::ParseConstructorRedirection(const Class& cls,
                                         LocalVariable* receiver) {
  TRACE_PARSER("ParseConstructorRedirection");
  ExpectToken(Token::kCOLON);
  ASSERT(CurrentToken() == Token::kTHIS);
  const TokenPosition 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(T, 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);

  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",
                String::Handle(Z, redirect_ctor.UserVisibleName()).ToCString());
  }
  if (current_function().is_const() && !redirect_ctor.is_const()) {
    ReportError(call_pos, "redirection constructor '%s' must be const",
                String::Handle(Z, redirect_ctor.UserVisibleName()).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",
                String::Handle(Z, redirect_ctor.UserVisibleName()).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 TokenPosition ctor_pos = TokenPos();
  OpenFunctionBlock(func);

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

  // 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 1.
    forwarding_args = new ArgumentListNode(ST(ctor_pos));
    for (int i = 1; i < func.NumParameters(); i++) {
      LocalVariable* param =
          new LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            String::ZoneHandle(Z, func.ParameterNameAt(i)),
                            Object::dynamic_type());
      current_block_->scope->InsertParameterAt(i, param);
      forwarding_args->Add(new LoadLocalNode(ST(ctor_pos), param));
    }
  }

  AstNode* super_call = GenerateSuperConstructorCall(current_class(), ctor_pos,
                                                     receiver, forwarding_args);
  if (super_call != NULL) {
    current_block_->statements->Add(super_call);
  }
  CheckFieldsInitialized(current_class());

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


// Returns a zone allocated string.
static char* DumpPendingFunctions(
    Zone* zone,
    const GrowableObjectArray& pending_functions) {
  ASSERT(zone != NULL);
  char* result = OS::SCreate(zone, "Pending Functions:\n");
  for (intptr_t i = 0; i < pending_functions.Length(); i++) {
    const Function& func =
        Function::Handle(zone, Function::RawCast(pending_functions.At(i)));
    const String& fname = String::Handle(zone, func.UserVisibleName());
    result = OS::SCreate(zone, "%s%" Pd ": %s\n", result, i, fname.ToCString());
  }
  return result;
}


void Parser::CheckRecursiveInvocation() {
  const GrowableObjectArray& pending_functions =
      GrowableObjectArray::Handle(Z, T->pending_functions());
  ASSERT(!pending_functions.IsNull());
  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());
      if (FLAG_trace_service) {
        const char* pending_function_dump =
            DumpPendingFunctions(Z, pending_functions);
        ASSERT(pending_function_dump != NULL);
        ReportError("circular dependency for function %s\n%s",
                    fname.ToCString(), pending_function_dump);
      } else {
        ReportError("circular dependency for function %s", fname.ToCString());
      }
    }
  }
  ASSERT(!unregister_pending_function_);
  pending_functions.Add(current_function(), Heap::kOld);
  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());

  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) {
    // The first parameter is the implicit receiver.
    ASSERT(params.parameters->length() >= 1);
    for (int i = 1; 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);
        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,
                                     /* is_initializer = */ true);
        }
        current_block_->statements->Add(initializer);
      }
    }
  }

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

  SequenceNode* init_statements = CloseBlock();
  current_block_->statements->Add(init_statements);

  // Parsing of initializers done. Now we parse the constructor body.
  OpenBlock();  // Block to collect constructor body nodes.
  if (FLAG_initializing_formal_access) {
    params.HideInitFormals();
  }
  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) {
    current_block_->statements->Add(ctor_block);
  }
  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, bool check_semicolon) {
  TRACE_PARSER("ParseFunc");
  ASSERT(innermost_function().raw() == 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);
    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(),
                             &Object::dynamic_type());
  } 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(),
                             &Object::dynamic_type());
  }
  // 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()) {
      // Skip formal parameters. They are accessed as context variables.
      // Parsing them again (and discarding them) does not work in case of
      // default values with same name as already parsed formal parameter.
      SkipToMatchingParenthesis();
    }
  } 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()) {
      // Skip formal parameters. They are accessed as context variables.
      // Parsing them again (and discarding them) does not work in case of
      // default values with same name as already parsed formal parameter.
      SkipToMatchingParenthesis();
    }
  } 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()) {
      // Skip formal parameters. They are accessed as context variables.
      // Parsing them again (and discarding them) does not work in case of
      // default values with same name as already parsed formal parameter.
      SkipToMatchingParenthesis();
    }
  } 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.
    // However, they are already set when the local function is compiled, since
    // the local function was parsed when its parent was compiled.
    if (func.parameter_types() == Object::empty_array().raw()) {
      AddFormalParamsToFunction(&params, func);
    }
    SetupDefaultsForOptionalParams(params);
    ASSERT(AbstractType::Handle(Z, func.result_type()).IsResolved());
    ASSERT(func.NumParameters() == params.parameters->length());

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

    if (I->type_checks() && (FunctionLevel() > 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 TokenPosition 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());
  TokenPosition end_token_pos = TokenPosition::kNoSource;
  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 TokenPosition 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();
    if (check_semicolon) {
      ExpectSemicolon();
    }
  } 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);
  last_used_try_index_ = saved_try_index;
  async_temp_scope_ = saved_async_temp_scope;
  return CloseBlock();
}


void Parser::AddEqualityNullCheck() {
  AstNode* argument = new LoadLocalNode(
      TokenPosition::kNoSource, current_block_->scope->parent()->VariableAt(1));
  LiteralNode* null_operand =
      new LiteralNode(TokenPosition::kNoSource, Instance::ZoneHandle(Z));
  ComparisonNode* check_arg = new ComparisonNode(
      TokenPosition::kNoSource, Token::kEQ_STRICT, argument, null_operand);
  ComparisonNode* result =
      new ComparisonNode(TokenPosition::kNoSource, Token::kEQ_STRICT,
                         LoadReceiver(TokenPosition::kNoSource), null_operand);
  SequenceNode* arg_is_null =
      new SequenceNode(TokenPosition::kNoSource, current_block_->scope);
  arg_is_null->Add(new ReturnNode(TokenPosition::kNoSource, result));
  IfNode* if_arg_null =
      new IfNode(TokenPosition::kNoSource, 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 if (FLAG_assert_initializer && (CurrentToken() == Token::kASSERT)) {
      ConsumeToken();
      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, NULL)) {
    return LibraryPrefix::null();
  }
  // Check whether the identifier is shadowed by a function type parameter.
  // TODO(regis): Shortcut this lookup if no generic functions in scope.
  if (!innermost_function().IsNull() &&
      (innermost_function().LookupTypeParameter(ident, NULL) !=
       TypeParameter::null())) {
    return LibraryPrefix::null();
  }
  // Check whether the identifier is shadowed by a class 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");
  // We are at the beginning of the formal parameters list.
  ASSERT(CurrentToken() == Token::kLPAREN || CurrentToken() == Token::kLT ||
         method->IsGetter());
  ASSERT(method->type != NULL);  // May still be unresolved.
  ASSERT(current_member_ == method);

  if (method->has_covariant) {
    ReportError(method->name_pos,
                "methods and constructors cannot be declared covariant");
  }
  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();
  }

  Function& func = Function::Handle(
      Z,
      Function::New(*method->name,  // May change.
                    method->kind, method->has_static, method->has_const,
                    method->has_abstract,  // May change.
                    method->has_external,
                    method->has_native,  // May change.
                    current_class(), method->decl_begin_pos));

  ASSERT(innermost_function().IsNull());
  innermost_function_ = func.raw();

  if (CurrentToken() == Token::kLT) {
    if (!FLAG_generic_method_syntax) {
      ReportError("generic type arguments not supported.");
    }
    TokenPosition type_param_pos = TokenPos();
    if (method->IsFactoryOrConstructor()) {
      ReportError(method->name_pos, "constructor cannot be generic");
    }
    if (method->IsGetter() || method->IsSetter()) {
      ReportError(type_param_pos, "%s cannot be generic",
                  method->IsGetter() ? "getter" : "setter");
    }
    ParseTypeParameters(false);  // Not parameterizing class, but function.
  }

  // Now that type parameters are declared, the result type can be resolved.
  if (!method->type->IsResolved()) {
    AbstractType& type = AbstractType::ZoneHandle(Z, method->type->raw());
    ResolveType(ClassFinalizer::kResolveTypeParameters, &type);
    method->type = &type;
  }

  // Parse the formal parameters.
  const bool are_implicitly_final = method->has_const;
  const bool allow_explicit_default_values = true;
  const TokenPosition 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(),
                                     &Object::dynamic_type());
  }
  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::Token(Token::kNEGATE).raw();
    }
    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(T, *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 TokenPosition 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);
      GrowableHandlePtrArray<const String> pieces(Z, 3);
      pieces.Add(members->class_name());
      pieces.Add(Symbols::Dot());
      if (CurrentToken() == Token::kPERIOD) {
        ConsumeToken();
        pieces.Add(*ExpectIdentifier("constructor name expected"));
      }
      String& redir_name =
          String::ZoneHandle(Z, Symbols::FromConcatAll(T, pieces));

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

  TokenPosition method_end_pos = TokenPos();
  String* native_name = NULL;
  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");
    }
    native_name = &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());
  }

  // Update function object.
  func.set_name(*method->name);
  func.set_is_abstract(method->has_abstract);
  func.set_is_native(method->has_native);
  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 (is_patch_source() && IsPatchAnnotation(method->metadata_pos)) {
    // Currently, we just ignore the patch annotation. If the function
    // name already exists in the patched class, this function will replace
    // the one in the patched class.
    method->metadata_pos = TokenPosition::kNoSource;
  }
  if (FLAG_enable_mirrors && (method->metadata_pos.IsReal())) {
    library_.AddFunctionMetadata(func, method->metadata_pos);
  }
  if (method->has_native) {
    func.set_native_name(*native_name);
  }

  // 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);
  ASSERT(innermost_function().raw() == func.raw());
  innermost_function_ = Function::null();
  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.IsReal());
  ASSERT(current_member_ == field);
  // All const fields are also final.
  ASSERT(!field->has_const || field->has_final);

  if (field->has_covariant) {
    if (field->has_static) {
      ReportError("static fields cannot be declared covariant");
    } else if (field->has_final) {
      ReportError("final fields cannot be declared covariant");
    }
  }
  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->type, field->name_pos);
    class_field.set_has_initializer(has_initializer);
    members->AddField(class_field);
    field->field_ = &class_field;
    if (is_patch_source() && IsPatchAnnotation(field->metadata_pos)) {
      // Currently, we just ignore the patch annotation on fields.
      // All fields in the patch class are added to the patched class.
      field->metadata_pos = TokenPosition::kNoSource;
    }
    if (FLAG_enable_mirrors && (field->metadata_pos.IsReal())) {
      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.SetStaticValue(init_value, true);
      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(Object::void_type());
        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,
                                        TokenPosition 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::kCOVARIANT) {
    ConsumeToken();
    member.has_covariant = 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 = &Object::dynamic_type();
  } else if ((CurrentToken() == Token::kFACTORY) &&
             (LookaheadToken(1) != Token::kLPAREN)) {
    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 = &Object::void_type();
  } else {
    bool found_type = false;
    {
      // Lookahead to determine whether the next tokens are a return type.
      TokenPosScope saved_pos(this);
      if (TryParseReturnType()) {
        if (IsIdentifier() || (CurrentToken() == Token::kGET) ||
            (CurrentToken() == Token::kSET) ||
            (CurrentToken() == Token::kOPERATOR)) {
          found_type = true;
        }
      }
    }
    if (found_type) {
      // It is too early to resolve the type here, since it can be a result type
      // referring to a not yet declared function type parameter.
      member.type = &AbstractType::ZoneHandle(
          Z, ParseType(ClassFinalizer::kDoNotResolve));
    }
  }

  // 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(T, to_concat);
    CheckToken(Token::kLPAREN);
  } else if ((CurrentToken() == Token::kGET) && !member.has_var &&
             (LookaheadToken(1) != Token::kLPAREN) &&
             (LookaheadToken(1) != Token::kLT) &&
             (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::kLT) &&
             (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 = &Object::dynamic_type();
    }
  } else if ((CurrentToken() == Token::kOPERATOR) && !member.has_var &&
             (LookaheadToken(1) != Token::kLPAREN) &&
             (LookaheadToken(1) != Token::kASSIGN) &&
             (LookaheadToken(1) != Token::kCOMMA) &&
             (LookaheadToken(1) != Token::kSEMICOLON)) {
    // TODO(hausner): handle the case of a generic function named 'operator':
    // eg: T operator<T>(a, b) => ...
    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::Token(member.operator_token).raw());
    ConsumeToken();
  } else if (IsIdentifier()) {
    member.name = CurrentLiteral();
    member.name_pos = TokenPos();
    ConsumeToken();
  } else {
    ReportError("identifier expected");
  }

  ASSERT(member.name != NULL);
  if (IsParameterPart() || member.IsGetter()) {
    // Constructor or method.
    if (member.type == NULL) {
      member.type = &Object::dynamic_type();
    }
    ASSERT(member.IsFactory() == member.has_factory);
    // Note that member.type may still be unresolved.
    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 = &Object::dynamic_type();
      } else {
        ReportError(
            "missing 'var', 'final', 'const' or type"
            " in field declaration");
      }
    } else if (member.type->IsVoidType()) {
      ReportError(member.name_pos, "field may not be 'void'");
    }
    if (!member.type->IsResolved()) {
      AbstractType& type = AbstractType::ZoneHandle(Z, member.type->raw());
      ResolveType(ClassFinalizer::kResolveTypeParameters, &type);
      member.type = &type;
    }
    ParseFieldDefinition(members, &member);
  } else {
    UnexpectedToken();
  }
  current_member_ = NULL;
  CheckMemberNameConflict(members, &member);
  members->AddMember(member);
}


void Parser::ParseEnumDeclaration(const GrowableObjectArray& pending_classes,
                                  const Object& tl_owner,
                                  TokenPosition metadata_pos) {
  TRACE_PARSER("ParseEnumDeclaration");
  const TokenPosition declaration_pos =
      (metadata_pos.IsReal()) ? metadata_pos : TokenPos();
  ConsumeToken();
  const TokenPosition 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(library_, *enum_name, script_, declaration_pos);
  library_.AddClass(cls);
  cls.set_is_synthesized_class();
  cls.set_is_enum_class();
  if (FLAG_enable_mirrors && (metadata_pos.IsReal())) {
    library_.AddClassMetadata(cls, tl_owner, 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 Object& tl_owner,
                                   TokenPosition metadata_pos) {
  TRACE_PARSER("ParseClassDeclaration");
  bool is_patch = false;
  bool is_abstract = false;
  TokenPosition declaration_pos =
      metadata_pos.IsReal() ? metadata_pos : TokenPos();
  if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
    is_patch = true;
    metadata_pos = TokenPosition::kNoSource;
    declaration_pos = TokenPos();
  } else if (CurrentToken() == Token::kABSTRACT) {
    is_abstract = true;
    ConsumeToken();
  }
  ExpectToken(Token::kCLASS);
  const TokenPosition 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(library_, 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();
      cls = Class::New(library_, class_name, script_, declaration_pos);
    } 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(true);  // Parameterizing current class.
  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());
    }
    if (!FLAG_ignore_patch_signature_mismatch) {
      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 (FLAG_enable_mirrors && metadata_pos.IsReal()) {
    library_.AddClassMetadata(cls, tl_owner, 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 TokenPosition 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) {
    cls.set_is_patch();
    // Apply the changes to the patched class looked up above.
    ASSERT(obj.raw() == library_.LookupLocalObject(class_name));
    const Class& orig_class = Class::Cast(obj);
    if (orig_class.is_finalized()) {
      orig_class.SetRefinalizeAfterPatch();
      pending_classes.Add(orig_class, Heap::kOld);
    }
    library_.AddPatchClass(cls);
  }
  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(thread(), num_classes_parsed, 1);
  set_current_class(cls);
  is_top_level_ = true;
  String& class_name = String::Handle(Z, cls.Name());
  SkipMetadata();
  if (CurrentToken() == Token::kABSTRACT) {
    ConsumeToken();
  }
  ExpectToken(Token::kCLASS);
  const TokenPosition class_pos = TokenPos();
  ClassDesc members(Z, cls, class_name, false, class_pos);
  while (CurrentToken() != Token::kLBRACE) {
    ConsumeToken();
  }
  ExpectToken(Token::kLBRACE);
  while (CurrentToken() != Token::kRBRACE) {
    TokenPosition metadata_pos = SkipMetadata();
    ParseClassMemberDefinition(&members, metadata_pos);
  }
  ExpectToken(Token::kRBRACE);

  if (cls.LookupTypeParameter(class_name) != TypeParameter::null()) {
    ReportError(class_pos, "class name conflicts with type parameter '%s'",
                class_name.ToCString());
  }
  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);
    // Check if this is a case of patching a class after it has already
    // been finalized.
    if (orig_class.is_refinalize_after_patch()) {
      if (!cls.ValidatePostFinalizePatch(orig_class, &error)) {
        Report::LongJumpF(error, script_, class_pos,
                          "patch validation failed, not applying patch.\n");
      }
    }
    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(thread(), num_classes_parsed, 1);

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

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

  const String& enum_name = String::Handle(Z, cls.ScrubbedName());
  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());
  index_field = Field::New(Symbols::Index(),
                           false,  // Not static.
                           true,   // Field is final.
                           false,  // Not const.
                           true,   // Is reflectable.
                           cls, int_type, cls.token_pos());
  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(&Object::dynamic_type(), cls.token_pos());
  AddFormalParamsToFunction(&params, getter);
  enum_members.AddFunction(getter);

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

  ConsumeToken();  // Enum type name.
  ExpectToken(Token::kLBRACE);
  Field& enum_value = Field::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.
    // Note that we do not set the field type to E, because we temporarily store
    // a Smi in the field. The class finalizer would detect the bad type and
    // reset the value to sentinel.
    enum_value = Field::New(*enum_ident,
                            /* is_static = */ true,
                            /* is_final = */ true,
                            /* is_const = */ true,
                            /* is_reflectable = */ true, cls,
                            Object::dynamic_type(), cls.token_pos());
    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.SetStaticValue(ordinal_value, true);
    enum_value.RecordStore(ordinal_value);
    i++;

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

  const Class& array_class = Class::Handle(Z, I->object_store()->array_class());
  TypeArguments& values_type_args =
      TypeArguments::ZoneHandle(Z, TypeArguments::New(1));
  const Type& enum_type = Type::Handle(Type::NewNonParameterizedType(cls));
  values_type_args.SetTypeAt(0, enum_type);
  Type& values_type = Type::ZoneHandle(
      Z, Type::New(array_class, values_type_args, cls.token_pos(), Heap::kOld));
  values_type ^= ClassFinalizer::FinalizeType(cls, values_type,
                                              ClassFinalizer::kCanonicalize);
  values_type_args = values_type.arguments();  // Get canonical type arguments.
  // Add static field 'const List<E> 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, values_type,
                            cls.token_pos());
  enum_members.AddField(values_field);

  // Add static field 'const _deleted_enum_sentinel'.
  // This field does not need to be of type E.
  Field& deleted_enum_sentinel = Field::ZoneHandle(Z);
  deleted_enum_sentinel = Field::New(Symbols::_DeletedEnumSentinel(),
                                     /* is_static = */ true,
                                     /* is_final = */ true,
                                     /* is_const = */ true,
                                     /* is_reflectable = */ false, cls,
                                     Object::dynamic_type(), cls.token_pos());
  enum_members.AddField(deleted_enum_sentinel);

  // 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_array.SetTypeArguments(values_type_args);
  values_field.SetStaticValue(values_array, true);
  values_field.RecordStore(values_array);

  // Clone the _name field from the helper class.
  Field& _name_field = Field::Handle(
      Z, helper_class.LookupInstanceFieldAllowPrivate(Symbols::_name()));
  ASSERT(!_name_field.IsNull());
  _name_field = _name_field.Clone(cls);
  enum_members.AddField(_name_field);

  // Add an implicit getter function for the _name field. We use the field's
  // name directly here so that the private key matches those of the other
  // cloned helper functions and fields.
  const Type& string_type = Type::Handle(Z, Type::StringType());
  const String& name_getter_name = String::Handle(
      Z, Field::GetterSymbol(String::Handle(_name_field.name())));
  Function& name_getter = Function::Handle(Z);
  name_getter = Function::New(name_getter_name, RawFunction::kImplicitGetter,
                              /* is_static = */ false,
                              /* is_const = */ true,
                              /* is_abstract = */ false,
                              /* is_external = */ false,
                              /* is_native = */ false, cls, cls.token_pos());
  name_getter.set_result_type(string_type);
  name_getter.set_is_debuggable(false);
  ParamList name_params;
  name_params.AddReceiver(&Object::dynamic_type(), cls.token_pos());
  AddFormalParamsToFunction(&name_params, name_getter);
  enum_members.AddFunction(name_getter);

  // 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(
      Z, 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::FromDot(T, ctor_name);
  // To indicate that this is an implicit constructor, we set the
  // token position and end token position of the function
  // to the token position of the class.
  Function& ctor = Function::Handle(
      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());

  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 Object& tl_owner,
                                TokenPosition metadata_pos) {
  TRACE_PARSER("ParseMixinAppAlias");
  const TokenPosition 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(library_, class_name, script_, classname_pos));
  mixin_application.set_is_mixin_app_alias();
  library_.AddClass(mixin_application);
  set_current_class(mixin_application);
  ParseTypeParameters(true);  // Parameterizing current class.

  ExpectToken(Token::kASSIGN);

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

  const TokenPosition 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 (FLAG_enable_mirrors && metadata_pos.IsReal()) {
    library_.AddClassMetadata(mixin_application, tl_owner, 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 TokenPosScope saved_pos(this);
  if (IsIdentifier() && (LookaheadToken(1) == Token::kLT)) {
    ConsumeToken();
    if (TryParseTypeParameters() && (CurrentToken() == Token::kLPAREN)) {
      return true;
    }
  }
  return false;
}


void Parser::ParseTypedef(const GrowableObjectArray& pending_classes,
                          const Object& tl_owner,
                          TokenPosition metadata_pos) {
  TRACE_PARSER("ParseTypedef");
  TokenPosition declaration_pos =
      metadata_pos.IsReal() ? metadata_pos : TokenPos();
  ExpectToken(Token::kTYPEDEF);

  // 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 TokenPosition 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 scope 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 scope class as
  // they are parsed.
  const Class& function_type_alias = Class::Handle(
      Z, Class::New(library_, *alias_name, script_, declaration_pos));
  function_type_alias.set_is_synthesized_class();
  function_type_alias.set_is_abstract();
  function_type_alias.set_is_prefinalized();
  library_.AddClass(function_type_alias);
  set_current_class(function_type_alias);
  // Parse the type parameters of the typedef class.
  ParseTypeParameters(true);  // Parameterizing current class.
  // At this point, the type parameters have been parsed, so we can resolve the
  // result type.
  if (!result_type.IsNull()) {
    ResolveType(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(),
                                &Object::dynamic_type());

  // Mark the current class as a typedef class (by setting its signature
  // function field to a non-null function) before parsing its formal parameters
  // so that parsed function types are aware that their owner class is a
  // typedef class.
  Function& signature_function = Function::Handle(
      Z, Function::NewSignatureFunction(function_type_alias, alias_name_pos));
  ASSERT(innermost_function().IsNull());
  innermost_function_ = signature_function.raw();
  // Set the signature function in the function type alias class.
  function_type_alias.set_signature_function(signature_function);

  const bool no_explicit_default_values = false;
  ParseFormalParameterList(no_explicit_default_values, false, &func_params);
  ExpectSemicolon();
  signature_function.set_result_type(result_type);
  AddFormalParamsToFunction(&func_params, signature_function);

  ASSERT(innermost_function().raw() == signature_function.raw());
  innermost_function_ = Function::null();

  if (FLAG_trace_parser) {
    OS::Print("TopLevel parsing function type alias '%s'\n",
              String::Handle(Z, signature_function.Signature()).ToCString());
  }
  // 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.is_finalized());
  pending_classes.Add(function_type_alias, Heap::kOld);
  if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
    library_.AddClassMetadata(function_type_alias, tl_owner, 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 bracket, it is replaced by a single 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();
  }
}


bool Parser::IsPatchAnnotation(TokenPosition pos) {
  if (pos == TokenPosition::kNoSource) {
    return false;
  }
  TokenPosScope saved_pos(this);
  SetPosition(pos);
  ExpectToken(Token::kAT);
  return IsSymbol(Symbols::Patch());
}


TokenPosition Parser::SkipMetadata() {
  if (CurrentToken() != Token::kAT) {
    return TokenPosition::kNoSource;
  }
  TokenPosition 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(bool parameterizing_class) {
  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 TokenPosition metadata_pos = SkipMetadata();
      const TokenPosition type_parameter_pos = TokenPos();
      const TokenPosition declaration_pos =
          metadata_pos.IsReal() ? 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) ||
          (!parameterizing_class && (CurrentToken() == Token::kSUPER))) {
        ConsumeToken();
        // TODO(regis): Handle 'super' differently than 'extends'.
        // A bound may refer to the owner of the type parameter it applies to,
        // i.e. to the class or function currently being parsed.
        // Postpone resolution in order to avoid resolving the owner and its
        // type parameters, as they are not fully parsed yet.
        type_parameter_bound = ParseType(ClassFinalizer::kDoNotResolve);
        if (!parameterizing_class) {
          // TODO(regis): Resolve and finalize function type parameter bounds in
          // class finalizer. For now, ignore parsed bounds to avoid unresolved
          // bounds while writing snapshots.
          type_parameter_bound = I->object_store()->object_type();
        }
      } else {
        type_parameter_bound = I->object_store()->object_type();
      }
      type_parameter = TypeParameter::New(
          parameterizing_class ? current_class() : Class::Handle(Z),
          parameterizing_class ? Function::Handle(Z) : innermost_function(),
          index, type_parameter_name, type_parameter_bound, declaration_pos);
      if (!parameterizing_class) {
        // TODO(regis): Resolve and finalize function type parameter in
        // class finalizer. For now, already mark as finalized.
        type_parameter.SetIsFinalized();
      }
      type_parameters_array.Add(
          &AbstractType::ZoneHandle(Z, type_parameter.raw()));
      if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
        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));
    if (parameterizing_class) {
      current_class().set_type_parameters(type_parameters);
    } else {
      innermost_function().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();
      ResolveType(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(Heap::kOld));
  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();
    TokenPosition 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(Heap::kOld));
  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,
                                   const Object& owner,
                                   TokenPosition 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 TokenPosition 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::NewTopLevel(var_name, is_final, is_const, owner, name_pos);
    field.SetFieldType(type);
    field.set_is_reflectable(is_reflectable);
    field.SetStaticValue(Object::null_instance(), true);
    top_level->AddField(field);
    library_.AddObject(field, var_name);
    if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
      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.SetStaticValue(field_value, true);
      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, owner, name_pos);
        getter.set_result_type(type);
        getter.set_is_debuggable(false);
        getter.set_is_reflectable(is_reflectable);
        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,
                                   const Object& owner,
                                   TokenPosition metadata_pos) {
  TRACE_PARSER("ParseTopLevelFunction");
  const TokenPosition decl_begin_pos = TokenPos();
  AbstractType& result_type = Type::Handle(Z, Type::DynamicType());
  bool is_external = false;
  bool is_patch = false;
  if (is_patch_source() && IsPatchAnnotation(metadata_pos)) {
    is_patch = true;
    metadata_pos = TokenPosition::kNoSource;
  } else if (CurrentToken() == Token::kEXTERNAL) {
    ConsumeToken();
    is_external = true;
  }
  if (CurrentToken() == Token::kVOID) {
    ConsumeToken();
    result_type = Type::VoidType();
  } else {
    // Parse optional type.
    if (IsFunctionReturnType()) {
      // It is too early to resolve the type here, since it can be a result type
      // referring to a not yet declared function type parameter.
      result_type = ParseType(ClassFinalizer::kDoNotResolve);
    }
  }
  const TokenPosition 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.

  Function& func = Function::Handle(
      Z, Function::New(func_name, RawFunction::kRegularFunction,
                       /* is_static = */ true,
                       /* is_const = */ false,
                       /* is_abstract = */ false, is_external,
                       /* is_native = */ false,  // May change.
                       owner, decl_begin_pos));

  ASSERT(innermost_function().IsNull());
  innermost_function_ = func.raw();

  if (CurrentToken() == Token::kLT) {
    if (!FLAG_generic_method_syntax) {
      ReportError("generic functions not supported");
    }
    ParseTypeParameters(false);  // Not parameterizing class, but function.
  }
  // At this point, the type parameters have been parsed, so we can resolve the
  // result type.
  if (!result_type.IsNull()) {
    ResolveType(ClassFinalizer::kResolveTypeParameters, &result_type);
  }

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

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

  TokenPosition function_end_pos = function_pos;
  bool is_native = false;
  String* native_name = NULL;
  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())) {
    native_name = &ParseNativeDeclaration();
    function_end_pos = TokenPos();
    ExpectSemicolon();
    is_native = true;
    func.set_is_native(true);
  } else {
    ReportError("function block expected");
  }
  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);
  }
  if (is_native) {
    func.set_native_name(*native_name);
  }
  AddFormalParamsToFunction(&params, func);
  ASSERT(innermost_function().raw() == func.raw());
  innermost_function_ = Function::null();
  top_level->AddFunction(func);
  if (!is_patch) {
    library_.AddObject(func, func_name);
  } else {
    // Need to remove the previously added function that is being patched.
    const Class& toplevel_cls = Class::Handle(Z, library_.toplevel_class());
    const Function& replaced_func =
        Function::Handle(Z, toplevel_cls.LookupStaticFunction(func_name));
    ASSERT(!replaced_func.IsNull());
    toplevel_cls.RemoveFunction(replaced_func);
    library_.ReplaceObject(func, func_name);
  }
  if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
    library_.AddFunctionMetadata(func, metadata_pos);
  }
}


void Parser::ParseTopLevelAccessor(TopLevel* top_level,
                                   const Object& owner,
                                   TokenPosition metadata_pos) {
  TRACE_PARSER("ParseTopLevelAccessor");
  const TokenPosition 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() && IsPatchAnnotation(metadata_pos)) {
    is_patch = true;
    metadata_pos = TokenPosition::kNoSource;
  } 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 TokenPosition name_pos = TokenPos();
  const String* field_name = ExpectIdentifier("accessor name expected");

  const TokenPosition 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 TokenPosition 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*");
  }

  TokenPosition accessor_end_pos = accessor_pos;
  bool is_native = false;
  String* native_name = NULL;
  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())) {
    native_name = &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, owner,
                       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);
    func.set_native_name(*native_name);
  }
  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 {
    // Need to remove the previously added accessor that is being patched.
    const Class& toplevel_cls = Class::Handle(
        Z, owner.IsClass() ? Class::Cast(owner).raw()
                           : PatchClass::Cast(owner).patched_class());
    const Function& replaced_func =
        Function::Handle(Z, toplevel_cls.LookupFunction(accessor_name));
    ASSERT(!replaced_func.IsNull());
    toplevel_cls.RemoveFunction(replaced_func);
    library_.ReplaceObject(func, accessor_name);
  }
  if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
    library_.AddFunctionMetadata(func, metadata_pos);
  }
}


RawObject* Parser::CallLibraryTagHandler(Dart_LibraryTag tag,
                                         TokenPosition 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();
  Object& result = Object::Handle(Z);
  {
    TransitionVMToNative transition(T);
    Api::Scope api_scope(T);
    Dart_Handle retval = handler(tag, Api::NewHandle(T, library_.raw()),
                                 Api::NewHandle(T, url.raw()));
    result = Api::UnwrapHandle(retval);
  }
  I->UnblockClassFinalization();
  if (result.IsError()) {
    // In case of an error we append an explanatory error message to the
    // error obtained from the library tag handler.
    const Error& prev_error = Error::Cast(result);
    Report::LongJumpF(prev_error, script_, token_pos, "library handler failed");
  }
  if (tag == Dart_kCanonicalizeUrl) {
    if (!result.IsString()) {
      ReportError(token_pos, "library handler failed URI canonicalization");
    }
  }
  return result.raw();
}


void Parser::ParseLibraryName() {
  ASSERT(CurrentToken() == Token::kLIBRARY);
  ConsumeToken();
  String& lib_name = *ExpectIdentifier("library name expected");
  if (CurrentToken() == Token::kPERIOD) {
    GrowableHandlePtrArray<const String> pieces(Z, 3);
    pieces.Add(lib_name);
    while (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      pieces.Add(Symbols::Dot());
      pieces.Add(*ExpectIdentifier("malformed library name"));
    }
    lib_name = Symbols::FromConcatAll(T, pieces);
  }
  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(const Object& tl_owner,
                                      TokenPosition metadata_pos) {
  ASSERT(Thread::Current()->IsMutatorThread());
  bool is_import = (CurrentToken() == Token::kIMPORT);
  bool is_export = (CurrentToken() == Token::kEXPORT);
  ASSERT(is_import || is_export);
  const TokenPosition import_pos = TokenPos();
  ConsumeToken();
  CheckToken(Token::kSTRING, "library url expected");
  AstNode* url_literal = ParseStringLiteral(false);
  if (FLAG_conditional_directives) {
    bool condition_triggered = false;
    while (CurrentToken() == Token::kIF) {
      // Conditional import: if (env == val) uri.
      ConsumeToken();
      ExpectToken(Token::kLPAREN);
      // Parse dotted name.
      const GrowableObjectArray& pieces =
          GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
      pieces.Add(*ExpectIdentifier("identifier expected"));
      while (CurrentToken() == Token::kPERIOD) {
        pieces.Add(Symbols::Dot());
        ConsumeToken();
        pieces.Add(*ExpectIdentifier("identifier expected"));
      }
      AstNode* valueNode = NULL;
      if (CurrentToken() == Token::kEQ) {
        ConsumeToken();
        CheckToken(Token::kSTRING, "string literal expected");
        valueNode = ParseStringLiteral(false);
        ASSERT(valueNode->IsLiteralNode());
        ASSERT(valueNode->AsLiteralNode()->literal().IsString());
      }
      ExpectToken(Token::kRPAREN);
      CheckToken(Token::kSTRING, "library url expected");
      AstNode* conditional_url_literal = ParseStringLiteral(false);

      // If there was already a condition that triggered, don't try to match
      // again.
      if (condition_triggered) {
        continue;
      }
      // Check if this conditional line overrides the default import.
      const String& key = String::Handle(
          String::ConcatAll(Array::Handle(Array::MakeArray(pieces))));
      const String& value =
          (valueNode == NULL)
              ? Symbols::True()
              : String::Cast(valueNode->AsLiteralNode()->literal());
      // Call the embedder to supply us with the environment.
      const String& env_value =
          String::Handle(Api::GetEnvironmentValue(T, key));
      if (!env_value.IsNull() && env_value.Equals(value)) {
        condition_triggered = true;
        url_literal = conditional_url_literal;
      }
    }
  }
  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);
  TokenPosition prefix_pos = TokenPosition::kNoSource;
  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(T, canon_url));
  if (library.IsNull()) {
    library = Library::New(canon_url);
    library.Register(T);
  }

  // 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 (FLAG_enable_mirrors && metadata_pos.IsReal()) {
    ns.AddMetadata(tl_owner, metadata_pos);
  }

  // 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 TokenPosition source_pos = TokenPos();
  ConsumeToken();  // Consume "part".
  if (IsSymbol(Symbols::Of())) {
    ReportError("part of declarations are not allowed in script files");
  }
  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(const Object& tl_owner) {
  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.
  TokenPosition rewind_pos = TokenPos();
  TokenPosition metadata_pos = SkipMetadata();
  if (CurrentToken() == Token::kLIBRARY) {
    if (is_patch_source()) {
      ReportError("patch cannot override library name");
    }
    ParseLibraryName();
    if (FLAG_enable_mirrors && metadata_pos.IsReal()) {
      library_.AddLibraryMetadata(tl_owner, metadata_pos);
    }
    rewind_pos = TokenPos();
    metadata_pos = SkipMetadata();
  }
  while ((CurrentToken() == Token::kIMPORT) ||
         (CurrentToken() == Token::kEXPORT)) {
    ParseLibraryImportExport(tl_owner, 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(TokenPosition::kMinSource);
  is_top_level_ = true;
  TopLevel top_level(Z);

  Object& tl_owner = Object::Handle(Z);
  Class& toplevel_class = Class::Handle(Z, library_.toplevel_class());
  if (toplevel_class.IsNull()) {
    toplevel_class =
        Class::New(library_, Symbols::TopLevel(), script_, TokenPos());
    toplevel_class.set_library(library_);
    library_.set_toplevel_class(toplevel_class);
    tl_owner = toplevel_class.raw();
  } else {
    tl_owner = PatchClass::New(toplevel_class, script_);
  }

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

  const Class& cls = Class::Handle(Z);
  while (true) {
    set_current_class(cls);  // No current class.
    TokenPosition metadata_pos = SkipMetadata();
    if (CurrentToken() == Token::kCLASS) {
      ParseClassDeclaration(pending_classes, tl_owner, metadata_pos);
    } else if (CurrentToken() == Token::kENUM) {
      ParseEnumDeclaration(pending_classes, tl_owner, metadata_pos);
    } else if ((CurrentToken() == Token::kTYPEDEF) &&
               (LookaheadToken(1) != Token::kLPAREN)) {
      set_current_class(toplevel_class);
      ParseTypedef(pending_classes, tl_owner, metadata_pos);
    } else if ((CurrentToken() == Token::kABSTRACT) &&
               (LookaheadToken(1) == Token::kCLASS)) {
      ParseClassDeclaration(pending_classes, tl_owner, metadata_pos);
    } else {
      set_current_class(toplevel_class);
      if (IsVariableDeclaration()) {
        ParseTopLevelVariable(&top_level, tl_owner, metadata_pos);
      } else if (IsFunctionDeclaration()) {
        ParseTopLevelFunction(&top_level, tl_owner, metadata_pos);
      } else if (IsTopLevelAccessor()) {
        ParseTopLevelAccessor(&top_level, tl_owner, metadata_pos);
      } else if (CurrentToken() == Token::kEOS) {
        break;
      } else {
        UnexpectedToken();
      }
    }
  }

  if (top_level.fields().length() > 0) {
    toplevel_class.AddFields(top_level.fields());
  }
  for (intptr_t i = 0; i < top_level.functions().length(); i++) {
    toplevel_class.AddFunction(*top_level.functions()[i]);
  }
  if (toplevel_class.is_finalized()) {
    toplevel_class.ResetFinalization();
  }
  pending_classes.Add(toplevel_class, Heap::kOld);
}


void Parser::CheckStack() {
  volatile uword c_stack_pos = Thread::GetCurrentStackPointer();
  volatile uword c_stack_base = OSThread::Current()->stack_base();
  volatile uword c_stack_limit =
      c_stack_base - OSThread::GetSpecifiedStackSize();
  // Note: during early initialization the stack_base() can return 0.
  if ((c_stack_base > 0) && (c_stack_pos < c_stack_limit)) {
    ReportError("stack overflow while parsing");
  }
}


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 TokenPosition 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.
  CatchParamDesc exception_param;
  CatchParamDesc stack_trace_param;
  exception_param.token_pos = TokenPosition::kNoSource;
  exception_param.type = &Object::dynamic_type();
  exception_param.name = &Symbols::ExceptionParameter();
  stack_trace_param.token_pos = TokenPosition::kNoSource;
  stack_trace_param.type = &Object::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(
        TokenPosition::kNoSource, exception_param.var,
        new (Z) LoadLocalNode(TokenPosition::kNoSource, 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(
        TokenPosition::kNoSource, stack_trace_param.var,
        new (Z) LoadLocalNode(TokenPosition::kNoSource, 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(TokenPosition::kNoSource);
  args->Add(new (Z)
                LoadLocalNode(TokenPosition::kNoSource, exception_param.var));
  args->Add(new (Z)
                LoadLocalNode(TokenPosition::kNoSource, stack_trace_param.var));
  current_block_->statements->Add(new (Z) InstanceCallNode(
      try_end_pos, new (Z) LoadLocalNode(TokenPosition::kNoSource, controller),
      Symbols::AddError(), args));
  ReturnNode* return_node = new (Z) ReturnNode(TokenPosition::kNoSource);
  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(TokenPosition::kNoSource);
    current_block_->statements->Add(new (Z) InstanceCallNode(
        try_end_pos,
        new (Z) LoadLocalNode(TokenPosition::kNoSource, controller),
        Symbols::Close(), no_args));

    // Suspend after the close.
    AwaitMarkerNode* await_marker = new (Z) AwaitMarkerNode(
        async_temp_scope_, current_block_->scope, TokenPosition::kNoSource);
    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(Heap::kOld));
  // Catch block handles all exceptions.
  handler_types.Add(Object::dynamic_type());

  CatchClauseNode* catch_clause = new (Z) CatchClauseNode(
      TokenPosition::kNoSource, 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(TokenPosition::kNoSource, body, context_var, catch_clause,
                   finally_clause, try_index, finally_clause);
  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.
  CatchParamDesc exception_param;
  CatchParamDesc stack_trace_param;
  exception_param.token_pos = TokenPosition::kNoSource;
  exception_param.type = &Object::dynamic_type();
  exception_param.name = &Symbols::ExceptionParameter();
  stack_trace_param.token_pos = TokenPosition::kNoSource;
  stack_trace_param.type = &Object::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(
        TokenPosition::kNoSource, exception_param.var,
        new (Z) LoadLocalNode(TokenPosition::kNoSource, 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(
        TokenPosition::kNoSource, stack_trace_param.var,
        new (Z) LoadLocalNode(TokenPosition::kNoSource, 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(TokenPosition::kNoSource);
  completer_args->Add(
      new (Z) LoadLocalNode(TokenPosition::kNoSource, exception_param.var));
  completer_args->Add(
      new (Z) LoadLocalNode(TokenPosition::kNoSource, stack_trace_param.var));
  current_block_->statements->Add(new (Z) InstanceCallNode(
      TokenPos(),
      new (Z) LoadLocalNode(TokenPosition::kNoSource, async_completer),
      Symbols::CompleterCompleteError(), completer_args));
  ReturnNode* return_node = new (Z) ReturnNode(TokenPosition::kNoSource);
  // 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(Heap::kOld));
  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(
      TokenPosition::kNoSource, 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(
      TokenPosition::kNoSource, try_block, context_var, catch_clause,
      NULL,  // No finally clause.
      try_index,
      NULL);  // No rethrow-finally clause.
  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
  // Add implicit closure parameter if not already present.
  if (params->parameters->length() == 0) {
    params->AddFinalParameter(TokenPosition::kMinSource,
                              &Symbols::ClosureParameter(),
                              &Object::dynamic_type());
  }
  ParamDesc iterator_param;
  iterator_param.name = &Symbols::IteratorParameter();
  iterator_param.type = &Object::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(TokenPosition 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, I->LookupClosureFunction(innermost_function(), func_pos));
  if (!found_func.IsNull()) {
    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 =
        Symbols::NewFormatted(T, "<%s_sync_body>", generator_name.ToCString());
    body = Function::NewClosureFunction(body_closure_name, innermost_function(),
                                        func_pos);
    body.set_is_generated_body(true);
    body.set_result_type(Object::dynamic_type());
    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);

    // Finalize function type.
    Type& signature_type = Type::Handle(Z, body.SignatureType());
    signature_type ^= ClassFinalizer::FinalizeType(
        current_class(), signature_type, ClassFinalizer::kCanonicalize);
    body.SetSignatureType(signature_type);
    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(TokenPosition::kNoSource, Smi::ZoneHandle(Smi::New(-1)));
  current_block_->statements->Add(
      new (Z) StoreLocalNode(TokenPosition::kNoSource, 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(TokenPosition::kNoSource);
  ClosureNode* closure_obj = new (Z) ClosureNode(
      TokenPosition::kNoSource, closure, NULL, closure_body->scope());
  arguments->Add(closure_obj);
  ConstructorCallNode* new_iterable = new (Z) ConstructorCallNode(
      TokenPosition::kNoSource, TypeArguments::ZoneHandle(Z),
      iterable_constructor, arguments);
  ReturnNode* return_node =
      new (Z) ReturnNode(TokenPosition::kNoSource, 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.
  ASSERT(params->parameters->length() <= 1);
  // Add implicit closure parameter if not yet present.
  if (params->parameters->length() == 0) {
    params->AddFinalParameter(TokenPosition::kMinSource,
                              &Symbols::ClosureParameter(),
                              &Object::dynamic_type());
  }
  ParamDesc result_param;
  result_param.name = &Symbols::AsyncOperationParam();
  result_param.default_value = &Object::null_instance();
  result_param.type = &Object::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 = &Object::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 = &Object::dynamic_type();
  params->parameters->Add(stack_trace_param);
  params->has_optional_positional_parameters = true;
  params->num_optional_parameters += 3;
}


RawFunction* Parser::OpenAsyncFunction(TokenPosition 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, I->LookupClosureFunction(innermost_function(), async_func_pos));
  if (!found_func.IsNull()) {
    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, Symbols::NewFormatted(T, "<%s_async_body>",
                                                async_func_name.ToCString()));
    closure = Function::NewClosureFunction(closure_name, innermost_function(),
                                           async_func_pos);
    closure.set_is_generated_body(true);
    closure.set_result_type(Object::dynamic_type());
    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);

    // Finalize function type.
    Type& signature_type = Type::Handle(Z, closure.SignatureType());
    signature_type ^= ClassFinalizer::FinalizeType(
        current_class(), signature_type, ClassFinalizer::kCanonicalize);
    closure.SetSignatureType(signature_type);
    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;

  // Capture instantiator in case it may be needed to generate the type
  // check of the return value. (C.f. handling of Token::kRETURN.)
  ASSERT(FunctionLevel() > 0);
  if (I->type_checks() && IsInstantiatorRequired()) {
    CaptureInstantiator();
  }
  return closure.raw();
}


void Parser::AddContinuationVariables() {
  // Add to current block's scope:
  //   var :await_jump_var;
  //   var :await_ctx_var;
  LocalVariable* await_jump_var =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            Symbols::AwaitJumpVar(), Object::dynamic_type());
  current_block_->scope->AddVariable(await_jump_var);
  LocalVariable* await_ctx_var =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            Symbols::AwaitContextVar(), Object::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;
  LocalVariable* async_op_var =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            Symbols::AsyncOperation(), Object::dynamic_type());
  current_block_->scope->AddVariable(async_op_var);
  LocalVariable* async_then_callback_var = new (Z)
      LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                    Symbols::AsyncThenCallback(), Object::dynamic_type());
  current_block_->scope->AddVariable(async_then_callback_var);
  LocalVariable* async_catch_error_callback_var = new (Z)
      LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                    Symbols::AsyncCatchErrorCallback(), Object::dynamic_type());
  current_block_->scope->AddVariable(async_catch_error_callback_var);
  LocalVariable* async_completer =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            Symbols::AsyncCompleter(), Object::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.
  LocalVariable* controller_var =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            Symbols::Controller(), Object::dynamic_type());
  current_block_->scope->AddVariable(controller_var);
  LocalVariable* async_op_var =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            Symbols::AsyncOperation(), Object::dynamic_type());
  current_block_->scope->AddVariable(async_op_var);
  LocalVariable* async_then_callback_var = new (Z)
      LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                    Symbols::AsyncThenCallback(), Object::dynamic_type());
  current_block_->scope->AddVariable(async_then_callback_var);
  LocalVariable* async_catch_error_callback_var = new (Z)
      LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                    Symbols::AsyncCatchErrorCallback(), Object::dynamic_type());
  current_block_->scope->AddVariable(async_catch_error_callback_var);
}


RawFunction* Parser::OpenAsyncGeneratorFunction(TokenPosition 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, I->LookupClosureFunction(innermost_function(), async_func_pos));
  if (!found_func.IsNull()) {
    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());
    const String& closure_name = String::Handle(
        Z, Symbols::NewFormatted(T, "<%s_async_gen_body>",
                                 async_generator_name.ToCString()));
    closure = Function::NewClosureFunction(closure_name, innermost_function(),
                                           async_func_pos);
    closure.set_is_generated_body(true);
    closure.set_result_type(Object::dynamic_type());
    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);

    // Finalize function type.
    Type& signature_type = Type::Handle(Z, closure.SignatureType());
    signature_type ^= ClassFinalizer::FinalizeType(
        current_class(), signature_type, ClassFinalizer::kCanonicalize);
    closure.SetSignatureType(signature_type);
    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(TokenPosition::kNoSource, Smi::ZoneHandle(Smi::New(-1)));
  current_block_->statements->Add(
      new (Z) StoreLocalNode(TokenPosition::kNoSource, 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(
      TokenPosition::kNoSource, closure_func, NULL, closure_body->scope());
  StoreLocalNode* store_async_op = new (Z)
      StoreLocalNode(TokenPosition::kNoSource, 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(TokenPosition::kNoSource);
  async_then_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(TokenPosition::kNoSource, async_op_var));
  StaticCallNode* then_wrapper_call = new (Z)
      StaticCallNode(TokenPosition::kNoSource, 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(
      TokenPosition::kNoSource, 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(TokenPosition::kNoSource);
  async_error_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(TokenPosition::kNoSource, async_op_var));
  StaticCallNode* error_wrapper_call = new (Z)
      StaticCallNode(TokenPosition::kNoSource, 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(TokenPosition::kNoSource, 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(TokenPosition::kNoSource);
  arguments->Add(new (Z) LoadLocalNode(TokenPosition::kNoSource, async_op_var));
  ConstructorCallNode* controller_constructor_call =
      new (Z) ConstructorCallNode(TokenPosition::kNoSource,
                                  TypeArguments::ZoneHandle(Z),
                                  controller_constructor, arguments);
  LocalVariable* controller_var =
      current_block_->scope->LookupVariable(Symbols::Controller(), false);
  StoreLocalNode* store_controller = new (Z) StoreLocalNode(
      TokenPosition::kNoSource, controller_var, controller_constructor_call);
  current_block_->statements->Add(store_controller);

  // return :controller.stream;
  ReturnNode* return_node = new (Z) ReturnNode(
      TokenPosition::kNoSource,
      new (Z) InstanceGetterNode(
          TokenPosition::kNoSource,
          new (Z) LoadLocalNode(TokenPosition::kNoSource, 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,
                                      TokenPosition 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);

  const TokenPosition token_pos = ST(closure_body->token_pos());
  // Add to AST:
  //   :async_completer = new Completer.sync();
  ArgumentListNode* empty_args = new (Z) ArgumentListNode(token_pos);
  ConstructorCallNode* completer_constructor_node =
      new (Z) ConstructorCallNode(token_pos, TypeArguments::ZoneHandle(Z),
                                  completer_constructor, empty_args);
  StoreLocalNode* store_completer = new (Z)
      StoreLocalNode(token_pos, 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(token_pos, Smi::ZoneHandle(Smi::New(-1)));
  current_block_->statements->Add(
      new (Z) StoreLocalNode(token_pos, 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(token_pos, closure, NULL, closure_body->scope());
  StoreLocalNode* store_async_op =
      new (Z) StoreLocalNode(token_pos, 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(token_pos);
  async_then_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(token_pos, async_op_var));
  StaticCallNode* then_wrapper_call = new (Z) StaticCallNode(
      token_pos, 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(token_pos, 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(token_pos);
  async_error_wrapper_helper_args->Add(
      new (Z) LoadLocalNode(token_pos, async_op_var));
  StaticCallNode* error_wrapper_call = new (Z) StaticCallNode(
      token_pos, 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(
      token_pos, 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(token_pos);
  arguments->Add(new (Z) LoadLocalNode(token_pos, async_op_var));
  ConstructorCallNode* future_node = new (Z) ConstructorCallNode(
      token_pos, TypeArguments::ZoneHandle(Z), constructor, arguments);
  current_block_->statements->Add(future_node);

  // Add to AST:
  //   return :async_completer.future;
  ReturnNode* return_node = new (Z) ReturnNode(
      token_pos,
      new (Z) InstanceGetterNode(
          token_pos, new (Z) LoadLocalNode(token_pos, 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(),
                     Report::AtLocation, "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());
  ASSERT(func.parameter_types() == Object::empty_array().raw());
  ASSERT(func.parameter_names() == Object::empty_array().raw());
  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);
    if (param_desc.is_field_initializer && !func.IsGenerativeConstructor()) {
      // Redirecting constructors are detected later in ParseConstructor.
      ReportError(param_desc.name_pos,
                  "only generative constructors may have "
                  "initializing formal parameters");
    }
    if (param_desc.is_covariant) {
      if (!func.IsDynamicFunction(true)) {
        ReportError(param_desc.name_pos,
                    "only instance functions may have "
                    "covariant parameters");
      }
    }
  }
}


// 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, 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 (FLAG_initializing_formal_access) {
      // Field initializer parameters are implicitly final.
      ASSERT(!param_desc.is_field_initializer || param_desc.is_final);
    } else 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());
  ASSERT(func.NumParameters() == params->parameters->length());
  TRACE_PARSER("ParseNativeFunctionBlock");

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

  // Now add the NativeBodyNode and return statement.
  current_block_->statements->Add(new (Z) ReturnNode(
      TokenPos(),
      new (Z) NativeBodyNode(TokenPos(), Function::ZoneHandle(Z, func.raw()),
                             native_name, current_block_->scope,
                             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);
}


void Parser::CaptureInstantiator() {
  ASSERT(FunctionLevel() > 0);
  const String* variable_name = current_function().IsInFactoryScope()
                                    ? &Symbols::TypeArgumentsParameter()
                                    : &Symbols::This();
  current_block_->scope->CaptureVariable(
      current_block_->scope->LookupVariable(*variable_name, true));
}


void Parser::CaptureFunctionInstantiator() {
  ASSERT(FunctionLevel() > 0);
  const String* variable_name = &Symbols::FunctionInstantiatorVar();
  current_block_->scope->CaptureVariable(
      current_block_->scope->LookupVariable(*variable_name, true));
}


AstNode* Parser::LoadReceiver(TokenPosition 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(TokenPosition 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 TokenPosition ident_pos = TokenPos();
  const String& ident = *CurrentLiteral();
  ConsumeToken();  // Variable identifier.
  const TokenPosition 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 TokenPosition expr_end_pos = TokenPos();
    variable = new (Z) LocalVariable(ident_pos, 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(ident_pos, assign_pos, ident, type);
    AstNode* null_expr =
        new (Z) LiteralNode(ident_pos, Object::null_instance());
    initialization = new (Z) StoreLocalNode(ident_pos, variable, null_expr);
  }

  ASSERT(current_block_ != NULL);
  const TokenPosition previous_pos =
      current_block_->scope->PreviousReferencePos(ident);
  if (previous_pos.IsReal()) {
    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->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* function_name = NULL;

  result_type = Type::DynamicType();

  const TokenPosition function_pos = TokenPos();
  TokenPosition function_name_pos = TokenPosition::kNoSource;
  TokenPosition metadata_pos = TokenPosition::kNoSource;
  if (is_literal) {
    ASSERT(CurrentToken() == Token::kLPAREN || CurrentToken() == Token::kLT);
    function_name = &Symbols::AnonymousClosure();
  } else {
    metadata_pos = SkipMetadata();
    if (CurrentToken() == Token::kVOID) {
      ConsumeToken();
      result_type = Type::VoidType();
    } else if (IsFunctionReturnType()) {
      // It is too early to resolve the type here, since it can be a result type
      // referring to a not yet declared function type parameter.
      result_type = ParseType(ClassFinalizer::kDoNotResolve);
    }
    function_name_pos = TokenPos();
    function_name = ExpectIdentifier("function name expected");

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

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

  ASSERT(function.parent_function() == innermost_function_.raw());
  innermost_function_ = function.raw();

  if (CurrentToken() == Token::kLT) {
    if (!FLAG_generic_method_syntax) {
      ReportError("generic functions not supported");
    }
    if (!found_func) {
      ParseTypeParameters(false);  // Not parameterizing class, but function.
    } else {
      TryParseTypeParameters();
    }
  }

  if (!found_func && !result_type.IsFinalized()) {
    // Now that type parameters are declared, the result type can be resolved
    // and finalized.
    ResolveType(ClassFinalizer::kCanonicalize, &result_type);
    result_type = ClassFinalizer::FinalizeType(current_class(), result_type,
                                               ClassFinalizer::kCanonicalize);
    function.set_result_type(result_type);
  }

  CheckToken(Token::kLPAREN);

  // 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 (!is_literal) {
    // 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
    // function type to be patched after the actual type is known.
    // We temporarily use the Closure class as scope class.
    const Class& unknown_scope_class =
        Class::Handle(Z, I->object_store()->closure_class());
    function_type =
        Type::New(unknown_scope_class, TypeArguments::Handle(Z), function_pos);
    function_type.set_signature(function);
    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_name_pos, function_pos,
                                              *function_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());
    }
  }

  Type& signature_type = Type::ZoneHandle(Z);
  SequenceNode* statements = NULL;
  if (!found_func) {
    // Parse the local function. As a side effect of the parsing, the
    // variables of this function's scope that are referenced by the local
    // function (and its inner nested functions) will be marked as captured.

    ASSERT(AbstractType::Handle(Z, function.result_type()).IsResolved());
    statements = Parser::ParseFunc(function, !is_literal);
    INC_STAT(thread(), num_functions_parsed, 1);

    // Now that the local function has formal parameters, lookup the signature
    signature_type = function.SignatureType();
    signature_type ^= ClassFinalizer::FinalizeType(
        current_class(), signature_type, ClassFinalizer::kCanonicalize);
    function.SetSignatureType(signature_type);
  } else {
    // The local function was parsed before. The captured variables are
    // saved in the function's context scope. Iterate over the context scope
    // and mark its variables as captured.
    const ContextScope& context_scope =
        ContextScope::Handle(Z, function.context_scope());
    ASSERT(!context_scope.IsNull());
    String& var_name = String::Handle(Z);
    for (int i = 0; i < context_scope.num_variables(); i++) {
      var_name = context_scope.NameAt(i);
      // We need to look up the name in a way that returns even hidden
      // variables, e.g. 'this' in an initializer list.
      LocalVariable* v = current_block_->scope->LookupVariable(var_name, true);
      ASSERT(v != NULL);
      current_block_->scope->CaptureVariable(v);
    }
    SkipFunctionLiteral();
    signature_type = function.SignatureType();
  }

  // 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());
  ASSERT(signature_type.IsFinalized());

  // Make sure that the instantiator is captured.
  if ((FunctionLevel() > 0) &&
      Class::Handle(signature_type.type_class()).IsGeneric()) {
    CaptureInstantiator();
  }

  // A local 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 (!is_literal) {
    // Patch the function type of the variable now that the signature is known.
    function_type.set_type_class(Class::Handle(Z, signature_type.type_class()));
    function_type.set_arguments(
        TypeArguments::Handle(Z, signature_type.arguments()));
    ASSERT(function_type.signature() == function.raw());

    // 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->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 != NULL ? statements->scope() : NULL);

  ASSERT(innermost_function_.raw() == function.raw());
  innermost_function_ = function.parent_function();

  return is_literal ? closure : new (Z) StoreLocalNode(
                                    function_pos, function_variable, closure);
}


// 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() {
  ASSERT(CurrentToken() == Token::kLT);
  int nesting_level = 0;
  do {
    Token::Kind ct = CurrentToken();
    if (ct == Token::kLT) {
      nesting_level++;
    } else if (ct == Token::kGT) {
      nesting_level--;
    } else if (ct == Token::kSHR) {
      nesting_level -= 2;
    } else if (ct == 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 ((ct != Token::kCOMMA) && (ct != Token::kEXTENDS) &&
               (!FLAG_generic_method_syntax || (ct != Token::kSUPER))) {
      // We are looking at something other than type parameters.
      return false;
    }
    ConsumeToken();
  } while (nesting_level > 0);
  if (nesting_level < 0) {
    return false;
  }
  return true;
}


// Returns true if the next tokens can be parsed as type parameters.
bool Parser::IsTypeParameters() {
  if (CurrentToken() == Token::kLT) {
    TokenPosScope param_pos(this);
    if (!TryParseTypeParameters()) {
      return false;
    }
    return true;
  }
  return false;
}


// Returns true if the next tokens are [ typeParameters ] '('.
bool Parser::IsParameterPart() {
  if (CurrentToken() == Token::kLPAREN) {
    return true;
  }
  if (CurrentToken() == Token::kLT) {
    TokenPosScope type_arg_pos(this);
    if (!TryParseTypeParameters()) {
      return false;
    }
    return CurrentToken() == Token::kLPAREN;
  }
  return false;
}


// Returns true if the current and next tokens can be parsed as type
// arguments. Current token position is not saved and restored.
bool Parser::TryParseTypeArguments() {
  ASSERT(CurrentToken() == Token::kLT);
  int nesting_level = 0;
  do {
    Token::Kind ct = CurrentToken();
    if (ct == Token::kLT) {
      nesting_level++;
    } else if (ct == Token::kGT) {
      nesting_level--;
    } else if (ct == Token::kSHR) {
      nesting_level -= 2;
    } else if (ct == 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 (ct != Token::kCOMMA) {
      return false;
    }
    ConsumeToken();
  } while (nesting_level > 0);
  if (nesting_level < 0) {
    return false;
  }
  return true;
}


// Returns true if the next tokens are [ typeArguments ] '('.
bool Parser::IsArgumentPart() {
  if (CurrentToken() == Token::kLPAREN) {
    return true;
  }
  if (CurrentToken() == Token::kLT) {
    TokenPosScope type_arg_pos(this);
    if (!TryParseTypeArguments()) {
      return false;
    }
    return CurrentToken() == Token::kLPAREN;
  }
  return false;
}


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 TokenPosition 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 TokenPosition 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 TokenPosition 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 see if the following tokens are a return type followed
// by an identifier.
bool Parser::IsFunctionReturnType() {
  TokenPosScope decl_pos(this);
  if (TryParseReturnType()) {
    if (IsIdentifier()) {
      // Return type followed by function name.
      return true;
    }
  }
  return false;
}


// Look ahead to detect whether the next tokens should be parsed as
// a function declaration. Token position remains unchanged.
bool Parser::IsFunctionDeclaration() {
  bool is_external = false;
  TokenPosScope decl_pos(this);
  SkipMetadata();
  if ((is_top_level_) && (CurrentToken() == Token::kEXTERNAL)) {
    // Skip over 'external' for top-level function declarations.
    is_external = true;
    ConsumeToken();
  }
  const TokenPosition type_or_name_pos = TokenPos();
  if (TryParseReturnType()) {
    if (!IsIdentifier()) {
      SetPosition(type_or_name_pos);
    }
  } else {
    SetPosition(type_or_name_pos);
  }
  // Check for function name followed by optional type parameters.
  if (!IsIdentifier()) {
    return false;
  }
  ConsumeToken();
  if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) {
    return false;
  }

  // Optional type, function name and optinal type parameters are parsed.
  if (CurrentToken() != Token::kLPAREN) {
    return false;
  }

  // Check parameter list and the following token.
  SkipToMatchingParenthesis();
  if ((CurrentToken() == Token::kLBRACE) || (CurrentToken() == Token::kARROW) ||
      (is_top_level_ && IsSymbol(Symbols::Native())) || is_external ||
      IsSymbol(Symbols::Async()) || IsSymbol(Symbols::Sync())) {
    return true;
  }
  return false;
}


bool Parser::IsTopLevelAccessor() {
  const TokenPosScope saved_pos(this);
  if (CurrentToken() == Token::kEXTERNAL) {
    ConsumeToken();
  }
  if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
    return true;
  }
  if (TryParseReturnType()) {
    if ((CurrentToken() == Token::kGET) || (CurrentToken() == Token::kSET)) {
      if (Token::IsIdentifier(LookaheadToken(1))) {  // Accessor name.
        return true;
      }
    }
  }
  return false;
}


bool Parser::IsFunctionLiteral() {
  if (!allow_function_literals_) {
    return false;
  }
  if ((CurrentToken() == Token::kLPAREN) || (CurrentToken() == Token::kLT)) {
    TokenPosScope saved_pos(this);
    if ((CurrentToken() == Token::kLT) && !TryParseTypeParameters()) {
      return false;
    }
    if (CurrentToken() != Token::kLPAREN) {
      return false;
    }
    SkipToMatchingParenthesis();
    ParseFunctionModifier();
    if ((CurrentToken() == Token::kLBRACE) ||
        (CurrentToken() == Token::kARROW)) {
      return true;
    }
  }
  return false;
}


// 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 TokenPosScope saved_pos(this);
  // 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) {
      return true;
    } else if (TryParseOptionalType()) {
      if (IsIdentifier()) {
        ConsumeToken();
      }
      return CurrentToken() == Token::kIN;
    }
  }
  return false;
}


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;
  RecursionChecker rc(this);
  while (CurrentToken() != Token::kRBRACE) {
    const TokenPosition 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 {
    RecursionChecker rc(this);
    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 TokenPosition 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(Zone* zone, const Instance& value) {
  Class& cls = Class::Handle(value.clazz());
  const Function& equal_op = Function::Handle(
      zone,
      Resolver::ResolveDynamicAnyArgs(zone, 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 TokenPosition 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(Z, 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 TokenPosition 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 TokenPosition 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().value(), Heap::kOld))));
        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 TokenPosition switch_pos = TokenPos();
  SourceLabel* label =
      SourceLabel::New(switch_pos, label_name, SourceLabel::kSwitch);
  ConsumeToken();
  ExpectToken(Token::kLPAREN);
  const TokenPosition 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, 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 TokenPosition 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();
        RemoveNodesForFinallyInlining(case_label);
      } 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 TokenPosition 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 TokenPosition 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;
  TokenPosition 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(Thread* thread,
                                                    LocalScope* scope,
                                                    uint16_t try_index) {
  Zone* zone = thread->zone();
  const String& async_saved_try_ctx_name = String::ZoneHandle(
      zone, Symbols::NewFormatted(
                thread, "%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 = FunctionLevel();
    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(T, 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(T, 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(TokenPosition::kNoSource);
  String& msg = String::ZoneHandle(Symbols::NewFormatted(T, "%s", str));
  one_arg->Add(new (Z) LiteralNode(TokenPosition::kNoSource, msg));
  AstNode* print_call =
      new (Z) StaticCallNode(TokenPosition::kNoSource, print_fn, one_arg);
  return print_call;
}


AstNode* Parser::ParseAwaitForStatement(String* label_name) {
  TRACE_PARSER("ParseAwaitForStatement");
  ASSERT(IsAwaitKeyword());
  const TokenPosition 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->type_checks()
                                                 ? ClassFinalizer::kCanonicalize
                                                 : ClassFinalizer::kIgnore);
  }
  TokenPosition loop_var_pos = TokenPos();
  const String* loop_var_name = ExpectIdentifier("variable name expected");

  // Parse stream expression.
  ExpectToken(Token::kIN);

  // Open a block for the iterator variable and the try-finally statement
  // that contains the loop. Ensure that the block starts at a different
  // token position than the following loop block. Both blocks can allocate
  // contexts and if they have a matching token position range,
  // it can be an issue (cf. bug 26941).
  OpenBlock();
  const Block* await_for_block = current_block_;

  const TokenPosition stream_expr_pos = TokenPos();
  AstNode* stream_expr =
      ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
  ExpectToken(Token::kRPAREN);

  // 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(stream_expr_pos);
  ctor_args->Add(stream_expr);
  ConstructorCallNode* ctor_call = new (Z) ConstructorCallNode(
      stream_expr_pos, TypeArguments::ZoneHandle(Z), iterator_ctor, ctor_args);
  const AbstractType& iterator_type = Object::dynamic_type();
  LocalVariable* iterator_var = new (Z) LocalVariable(
      stream_expr_pos, stream_expr_pos, Symbols::ForInIter(), iterator_type);
  current_block_->scope->AddVariable(iterator_var);
  AstNode* iterator_init =
      new (Z) StoreLocalNode(stream_expr_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_expr_pos);
  AstNode* iterator_moveNext = new (Z) InstanceCallNode(
      stream_expr_pos, new (Z) LoadLocalNode(stream_expr_pos, iterator_var),
      Symbols::MoveNext(), no_args);
  OpenBlock();
  AstNode* await_moveNext = new (Z) AwaitNode(
      stream_expr_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 TokenPosition 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_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(
        TokenPosition::kNoSource, outer_saved_try_ctx,
        new (Z) LoadLocalNode(TokenPosition::kNoSource,
                              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();

    // Restore the saved try context of the enclosing try block if one
    // exists.
    if (outer_saved_try_ctx != NULL) {
      current_block_->statements->Add(new (Z) StoreLocalNode(
          TokenPosition::kNoSource, outer_saved_try_ctx,
          new (Z) LoadLocalNode(TokenPosition::kNoSource,
                                outer_async_saved_try_ctx)));
    }
    // :for-in-iter.cancel();
    ArgumentListNode* no_args =
        new (Z) ArgumentListNode(TokenPosition::kNoSource);
    current_block_->statements->Add(new (Z) InstanceCallNode(
        TokenPosition::kNoSource,
        new (Z) LoadLocalNode(TokenPosition::kNoSource, 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(TokenPosition::kNoSource, 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 Array& handler_types = Array::ZoneHandle(Z, Array::New(1, Heap::kOld));
  // Catch block handles all exceptions.
  handler_types.SetAt(0, Object::dynamic_type());

  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, finally_clause);

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

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


AstNode* Parser::ParseForInStatement(TokenPosition 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;
  TokenPosition loop_var_pos = TokenPosition::kNoSource;
  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->type_checks()
                                                 ? ClassFinalizer::kCanonicalize
                                                 : ClassFinalizer::kIgnore);
    loop_var_pos = TokenPos();
    loop_var_name = ExpectIdentifier("variable name expected");
  }
  ExpectToken(Token::kIN);

  // Ensure that the block token range contains the call to moveNext and it
  // also starts the block at a different token position than the following
  // loop block. Both blocks can allocate contexts and if they have a matching
  // token position range, it can be an issue (cf. bug 26941).
  OpenBlock();  // Implicit block around while loop.

  const TokenPosition collection_pos = TokenPos();
  AstNode* collection_expr =
      ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
  ExpectToken(Token::kRPAREN);

  // 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 = Object::dynamic_type();
  LocalVariable* iterator_var = new (Z) LocalVariable(
      collection_pos, 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 TokenPosition 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_pos, 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 TokenPosition 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 TokenPosition 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 TokenPosition 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::ParseAssertStatement(bool is_const) {
  TRACE_PARSER("ParseAssertStatement");
  ConsumeToken();  // Consume assert keyword.
  ExpectToken(Token::kLPAREN);
  const TokenPosition condition_pos = TokenPos();
  if (!I->asserts()) {
    SkipExpr();
    if (CurrentToken() == Token::kCOMMA) {
      ConsumeToken();
      SkipExpr();
    }
    ExpectToken(Token::kRPAREN);
    return NULL;
  }

  BoolScope saved_seen_await(&parsed_function()->have_seen_await_expr_, false);
  AstNode* condition = ParseExpr(kAllowConst, kConsumeCascades);
  if (is_const && !condition->IsPotentiallyConst()) {
    ReportError(condition_pos,
                "initializer assert expression must be compile time constant.");
  }
  const TokenPosition condition_end = TokenPos();
  AstNode* message = NULL;
  TokenPosition message_pos = TokenPosition::kNoSource;
  if (CurrentToken() == Token::kCOMMA) {
    ConsumeToken();
    message_pos = TokenPos();
    message = ParseExpr(kAllowConst, kConsumeCascades);
    if (is_const && !message->IsPotentiallyConst()) {
      ReportError(
          message_pos,
          "initializer assert expression must be compile time constant.");
    }
  }
  ExpectToken(Token::kRPAREN);

  if (!is_const) {
    // Check for assertion condition being a function if not const.
    ArgumentListNode* arguments = new (Z) ArgumentListNode(condition_pos);
    arguments->Add(condition);
    condition = MakeStaticCall(
        Symbols::AssertionError(),
        Library::PrivateCoreLibName(Symbols::EvaluateAssertion()), arguments);
  }
  AstNode* not_condition =
      new (Z) UnaryOpNode(condition_pos, Token::kNOT, condition);

  // Build call to _AsertionError._throwNew(start, end, message)
  ArgumentListNode* arguments = new (Z) ArgumentListNode(condition_pos);
  arguments->Add(new (Z) LiteralNode(
      condition_pos,
      Integer::ZoneHandle(Z, Integer::New(condition_pos.Pos()))));
  arguments->Add(new (Z) LiteralNode(
      condition_end,
      Integer::ZoneHandle(Z, Integer::New(condition_end.Pos()))));
  if (message == NULL) {
    message = new (Z) LiteralNode(condition_end, Instance::ZoneHandle(Z));
  }
  arguments->Add(message);
  AstNode* assert_throw = MakeStaticCall(
      Symbols::AssertionError(),
      Library::PrivateCoreLibName(Symbols::ThrowNew()), arguments);

  AstNode* assertion_check = NULL;
  if (parsed_function()->have_seen_await()) {
    // The await transformation must be done manually because assertions
    // are parsed as statements, not expressions. Thus, we need to check
    // explicitely whether the arguments contain await operators. (Note that
    // we must not parse the arguments with ParseAwaitableExpr(). In the
    // corner case of assert(await a, await b), this would create two
    // sibling scopes containing the temporary values for a and b. Both
    // values would be allocated in the same internal context variable.)
    //
    // Build !condition ? _AsertionError._throwNew(...) : null;
    // We need to use a conditional expression because the await transformer
    // cannot transform if statements.
    assertion_check = new (Z) ConditionalExprNode(
        condition_pos, not_condition, assert_throw,
        new (Z) LiteralNode(condition_pos, Object::null_instance()));
    OpenBlock();
    AwaitTransformer at(current_block_->statements, async_temp_scope_);
    AstNode* transformed_assertion = at.Transform(assertion_check);
    SequenceNode* preamble = CloseBlock();
    preamble->Add(transformed_assertion);
    assertion_check = preamble;
  } else {
    // Build if (!condition) _AsertionError._throwNew(...)
    assertion_check = new (Z)
        IfNode(condition_pos, not_condition,
               NodeAsSequenceNode(condition_pos, assert_throw, NULL), NULL);
  }
  return assertion_check;
}


// 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->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->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(
      TokenPosition::kNoSource, saved_exception_var,
      new (Z) LoadLocalNode(TokenPosition::kNoSource, exception_var)));

  ASSERT(saved_stack_trace_var != NULL);
  ASSERT(stack_trace_var != NULL);
  statements->Add(new (Z) StoreLocalNode(
      TokenPosition::kNoSource, saved_stack_trace_var,
      new (Z) LoadLocalNode(TokenPosition::kNoSource, 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)));
  // Increasing the loop level prevents the reuse of a parent context and forces
  // the allocation of a local context to hold captured variables declared
  // inside the finally clause. Otherwise, a captured variable gets allocated at
  // different slots in the parent context each time the finally clause is
  // reparsed, which is done to duplicate the ast. Since only one closure is
  // kept due to canonicalization, it will access the correct slot in only one
  // copy of the finally clause and the wrong slot in all others. By allocating
  // a local context, all copies use the same slot in different local contexts.
  // See issue #26948. This is a temporary fix until we eliminate reparsing.
  OpenLoopBlock();
  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 context 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(
            T, async_temp_scope_, try_stack_->try_index());
        current_block_->statements->Add(new (Z) StoreLocalNode(
            TokenPosition::kNoSource, saved_try_ctx,
            new (Z)
                LoadLocalNode(TokenPosition::kNoSource, 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());
  const intptr_t func_level = FunctionLevel();
  TryStack* iterator = try_stack_;
  while ((iterator != NULL) &&
         (iterator->try_block()->scope->function_level() == func_level)) {
    // 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.
      // For unresolved forward jumps to switch cases, we don't yet know
      // to which scope the label will be resolved. Tentatively add the
      // jump to all nested try statements and remove the outermost ones
      // when we know the exact jump target. (See
      // RemoveNodesForFinallyInlining below.)
      if (!label->IsUnresolved() && label->owner()->IsNestedWithin(try_scope)) {
        break;
      }
    }
    iterator->AddNodeForFinallyInlining(node);
    iterator = iterator->outer_try();
  }
}


void Parser::RemoveNodesForFinallyInlining(SourceLabel* label) {
  TryStack* iterator = try_stack_;
  const intptr_t func_level = FunctionLevel();
  while ((iterator != NULL) &&
         (iterator->try_block()->scope->function_level() == func_level)) {
    iterator->RemoveJumpToLabel(label);
    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) {
    if (FunctionLevel() == 0) {
      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(
    TokenPosition 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 TokenPosition 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 = &Object::dynamic_type();
    }
    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 = &Object::dynamic_type();
        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() && (FunctionLevel() > 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(
            T, async_temp_scope_, try_block->try_index());
        async_code->Add(new (Z) StoreLocalNode(
            TokenPosition::kNoSource, saved_try_ctx,
            new (Z)
                LoadLocalNode(TokenPosition::kNoSource, 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::NewFormatted(T, "%s%d",
                               Symbols::AsyncSavedTryCtxVarPrefix().ToCString(),
                               last_used_try_index_ - 1));
  LocalVariable* async_saved_try_ctx =
      new (Z) LocalVariable(TokenPosition::kNoSource, TokenPosition::kNoSource,
                            async_saved_try_ctx_name, Object::dynamic_type());
  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(
      TokenPosition::kNoSource, async_saved_try_ctx,
      new (Z) LoadLocalNode(TokenPosition::kNoSource, 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) {
  // 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(), TokenPos(), Symbols::SavedTryContextVar(),
                      Object::dynamic_type());
    try_scope->AddVariable(*context_var);
  }
  *exception_var = try_scope->LocalLookupVariable(Symbols::ExceptionVar());
  if (*exception_var == NULL) {
    *exception_var =
        new (Z) LocalVariable(TokenPos(), TokenPos(), Symbols::ExceptionVar(),
                              Object::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(), TokenPos(), Symbols::StackTraceVar(),
                              Object::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(), TokenPos(), Symbols::SavedExceptionVar(),
                        Object::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(), TokenPos(), Symbols::SavedStackTraceVar(),
                        Object::dynamic_type());
      try_scope->AddVariable(*saved_stack_trace_var);
    }
  }
}


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

  const TokenPosition 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 TokenPosition handler_pos = TokenPos();
  const GrowableObjectArray& handler_types =
      GrowableObjectArray::Handle(Z, GrowableObjectArray::New(Heap::kOld));
  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;
  SequenceNode* rethrow_clause = NULL;
  const bool parse = CurrentToken() == Token::kFINALLY;
  if (parse || (is_async && (try_stack_ != NULL))) {
    if (parse) {
      ConsumeToken();  // Consume the 'finally'.
    }
    const TokenPosition 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);
    if (finally_clause != NULL) {
      // Re-parse to create a duplicate of finally clause to avoid unintended
      // sharing of try-indices if the finally-block contains a try-catch.
      // The flow graph builder emits two copies of the finally-block if the
      // try-block has a normal exit: one for the exception- and one for the
      // non-exception case (see EffectGraphVisitor::VisitTryCatchNode)
      tokens_iterator_.SetCurrentPosition(finally_pos);
      rethrow_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, rethrow_clause);

  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 TokenPosition 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 = Z->MakeCopyOfString(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() != FunctionLevel()) {
    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 TokenPosition 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(TokenPosition::kNoSource, iterator_param);
    AstNode* store_current = new (Z) InstanceSetterNode(
        TokenPosition::kNoSource, iterator,
        Library::PrivateCoreLibName(Symbols::_current()), expr);
    yield->AddNode(store_current);
    if (is_yield_each) {
      // Generate :iterator.isYieldEach = true;
      AstNode* set_is_yield_each = new (Z)
          InstanceSetterNode(TokenPosition::kNoSource, 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, TokenPosition::kNoSource);
    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(
          TokenPosition::kNoSource, saved_try_ctx,
          new (Z)
              LoadLocalNode(TokenPosition::kNoSource, async_saved_try_ctx)));
      if (outer_saved_try_ctx != NULL) {
        yield->AddNode(new (Z) StoreLocalNode(
            TokenPosition::kNoSource, outer_saved_try_ctx,
            new (Z) LoadLocalNode(TokenPosition::kNoSource,
                                  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(TokenPosition::kNoSource, 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(TokenPosition::kNoSource, 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(TokenPosition::kNoSource, add_call, true_branch, NULL);
    yield->AddNode(if_is_cancelled);

    AwaitMarkerNode* await_marker = new (Z) AwaitMarkerNode(
        async_temp_scope_, current_block_->scope, TokenPosition::kNoSource);
    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(
          TokenPosition::kNoSource, saved_try_ctx,
          new (Z)
              LoadLocalNode(TokenPosition::kNoSource, async_saved_try_ctx)));
      if (outer_saved_try_ctx != NULL) {
        yield->AddNode(new (Z) StoreLocalNode(
            TokenPosition::kNoSource, outer_saved_try_ctx,
            new (Z) LoadLocalNode(TokenPosition::kNoSource,
                                  outer_async_saved_try_ctx)));
      }
    } else {
      ASSERT(outer_saved_try_ctx == NULL);
    }
  }
  return yield;
}


AstNode* Parser::ParseStatement() {
  TRACE_PARSER("ParseStatement");
  AstNode* statement = NULL;
  TokenPosition label_pos = TokenPosition::kNoSource;
  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.IsReal());
      ConsumeToken();  // Consume identifier.
      ConsumeToken();  // Consume colon.
    }
  }
  const TokenPosition 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 TokenPosition return_pos = TokenPos();
    ConsumeToken();
    if (CurrentToken() != Token::kSEMICOLON) {
      const TokenPosition expr_pos = TokenPos();
      const int function_level = FunctionLevel();
      if (current_function().IsGenerativeConstructor() &&
          (function_level == 0)) {
        ReportError(expr_pos,
                    "return of a value is not allowed in constructors");
      } else if (current_function().IsGeneratorClosure() &&
                 (function_level == 0)) {
        ReportError(expr_pos, "generator functions may not return a value");
      }
      AstNode* expr = ParseAwaitableExpr(kAllowConst, kConsumeCascades, NULL);
      if (I->type_checks() &&
          (((function_level == 0) && current_function().IsAsyncClosure()))) {
        // In checked mode, when the declared result type is Future<T>, verify
        // that the returned expression is of type T or Future<T> as follows:
        // return temp = expr, temp is Future ? temp as Future<T> : temp as T;
        // In case of a mismatch, we need a TypeError and not a CastError, so
        // we do not actually implement an "as" test, but an "assignable" test.
        Function& async_func =
            Function::Handle(Z, current_function().parent_function());
        const AbstractType& result_type =
            AbstractType::ZoneHandle(Z, async_func.result_type());
        const Class& future_class =
            Class::ZoneHandle(Z, I->object_store()->future_class());
        ASSERT(!future_class.IsNull());
        if (result_type.type_class() == future_class.raw()) {
          const TypeArguments& result_type_args =
              TypeArguments::ZoneHandle(Z, result_type.arguments());
          if (!result_type_args.IsNull() && (result_type_args.Length() == 1)) {
            const AbstractType& result_type_arg =
                AbstractType::ZoneHandle(Z, result_type_args.TypeAt(0));
            LetNode* checked_expr = new (Z) LetNode(expr_pos);
            LocalVariable* temp = checked_expr->AddInitializer(expr);
            temp->set_is_final();
            const AbstractType& future_type =
                AbstractType::ZoneHandle(Z, future_class.RareType());
            AstNode* is_future = new (Z) LoadLocalNode(expr_pos, temp);
            is_future =
                new (Z) ComparisonNode(expr_pos, Token::kIS, is_future,
                                       new (Z) TypeNode(expr_pos, future_type));
            AstNode* as_future_t = new (Z) LoadLocalNode(expr_pos, temp);
            as_future_t = new (Z) AssignableNode(
                expr_pos, as_future_t, result_type, Symbols::FunctionResult());
            AstNode* as_t = new (Z) LoadLocalNode(expr_pos, temp);
            as_t = new (Z) AssignableNode(expr_pos, as_t, result_type_arg,
                                          Symbols::FunctionResult());
            checked_expr->AddNode(new (Z) ConditionalExprNode(
                expr_pos, is_future, as_future_t, as_t));
            expr = checked_expr;
          }
        }
      }
      statement = new (Z) ReturnNode(statement_pos, expr);
    } else {
      if (current_function().IsSyncGenClosure() && (FunctionLevel() == 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. Find the inntermost enclosing
    // catch block.
    TryStack* try_statement = try_stack_;
    while ((try_statement != NULL) && !try_statement->inside_catch()) {
      try_statement = try_statement->outer_try();
    }
    if (try_statement == NULL) {
      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_statement->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,
                          TokenPosition 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(TokenPosition token_pos,
                         const char* format,
                         ...) const {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kError, script_, token_pos, Report::AtLocation,
                   format, args);
  va_end(args);
  UNREACHABLE();
}


void Parser::ReportErrorBefore(const char* format, ...) {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kError, script_, PrevTokenPos(),
                   Report::AfterLocation, 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(), Report::AtLocation,
                   format, args);
  va_end(args);
  UNREACHABLE();
}


void Parser::ReportWarning(TokenPosition token_pos,
                           const char* format,
                           ...) const {
  va_list args;
  va_start(args, format);
  Report::MessageV(Report::kWarning, script_, token_pos, Report::AtLocation,
                   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(), Report::AtLocation,
                   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) {
    ReportErrorBefore("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 (FLAG_await_is_keyword || await_is_keyword_) &&
         IsSymbol(Symbols::Await());
}


bool Parser::IsYieldKeyword() {
  return (FLAG_await_is_keyword || 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(TokenPosition 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(TokenPosition 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.value(), Heap::kOld))));
  // Src value argument.
  arguments->Add(new (Z) LiteralNode(type_pos, Object::null_instance()));
  // Dst type argument.
  arguments->Add(new (Z) LiteralNode(type_pos, type));
  // Dst name argument.
  arguments->Add(new (Z) LiteralNode(type_pos, Symbols::Empty()));
  // Bound error msg argument.
  arguments->Add(new (Z) LiteralNode(type_pos, Object::null_instance()));
  return MakeStaticCall(Symbols::TypeError(), method_name, arguments);
}


// Call _throwNewIfNotLoaded if prefix is not NULL, otherwise call _throwNew.
AstNode* Parser::ThrowNoSuchMethodError(TokenPosition 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 || !prefix->is_deferred_load()) {
    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 {
    AbstractType& type = AbstractType::ZoneHandle(Z);
    type ^= 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(T, 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, Object::null_array()));
  } 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, Object::null_array()));
  } 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 TokenPosition 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 TokenPosition type_pos = TokenPos();
        const AbstractType& type = AbstractType::ZoneHandle(
            Z, ParseType(ClassFinalizer::kCanonicalize));
        if (!type.IsInstantiated() && (FunctionLevel() > 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 (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(TokenPosition token_pos,
                                               const char* s) {
  char name[64];
  OS::SNPrint(name, 64, ":%s%" Pd "", s, token_pos.value());
  LocalVariable* temp = new (Z) LocalVariable(
      token_pos, token_pos, String::ZoneHandle(Z, Symbols::New(T, name)),
      Object::dynamic_type());
  temp->set_is_final();
  current_block_->scope->AddVariable(temp);
  return temp;
}


AstNode* Parser::OptimizeBinaryOpNode(TokenPosition 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 (binary_op == Token::kIFNULL) {
    // Handle a ?? b.
    if ((lhs->EvalConstExpr() != NULL) && (rhs->EvalConstExpr() != NULL)) {
      Instance& expr_value = Instance::ZoneHandle(
          Z, EvaluateConstExpr(lhs->token_pos(), lhs).raw());
      if (expr_value.IsNull()) {
        expr_value = EvaluateConstExpr(rhs->token_pos(), rhs).raw();
      }
      return new (Z) LiteralNode(op_pos, expr_value);
    }

    LetNode* result = new (Z) LetNode(op_pos);
    LocalVariable* left_temp = result->AddInitializer(lhs);
    left_temp->set_is_final();
    const TokenPosition no_pos = TokenPosition::kNoSource;
    LiteralNode* null_operand =
        new (Z) LiteralNode(no_pos, Object::null_instance());
    LoadLocalNode* load_left_temp = new (Z) LoadLocalNode(no_pos, left_temp);
    ComparisonNode* null_compare = new (Z)
        ComparisonNode(no_pos, Token::kNE_STRICT, load_left_temp, null_operand);
    result->AddNode(
        new (Z) ConditionalExprNode(op_pos, null_compare, load_left_temp, rhs));
    return result;
  }
  return new (Z) BinaryOpNode(op_pos, binary_op, lhs, rhs);
}


AstNode* Parser::ExpandAssignableOp(TokenPosition 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(TokenPosition 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;
  TokenPosition 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, TokenPosition end_pos) {
  ASSERT(expr->token_pos().IsReal());
  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,
                                      TokenPosition 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(T, 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");
    }
    ArgumentListNode* error_arguments =
        new (Z) ArgumentListNode(rhs->token_pos());
    error_arguments->Add(rhs);
    result = ThrowNoSuchMethodError(original->token_pos(), *target_cls,
                                    String::Handle(Z, Field::SetterName(name)),
                                    error_arguments, InvocationMirror::kStatic,
                                    original->IsLoadLocalNode()
                                        ? InvocationMirror::kLocalVar
                                        : InvocationMirror::kSetter,
                                    NULL);  // No existing function.
  }
  // 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 = OptimizeBinaryOpNode(ifnull->token_pos(), ifnull->kind(),
                                  ifnull->left(), modified_assign);
  }
  return result;
}


AstNode* Parser::ParseCascades(AstNode* expr) {
  TokenPosition 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 TokenPosition 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 TokenPosition 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.StaticValue() != Object::sentinel().raw());
      ASSERT(field.StaticValue() != Object::transition_sentinel().raw());
      return new (zone) LiteralNode(
          expr->token_pos(), Instance::ZoneHandle(zone, field.StaticValue()));
    }
  }
  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 TokenPosition expr_pos = TokenPos();

  RecursionChecker rc(this);

  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) {
      expr = FoldConstExpr(expr_pos, expr);
    } 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 TokenPosition assignment_pos = TokenPos();
  ConsumeToken();
  const TokenPosition 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");
  TokenPosition 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 TokenPosition 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 TokenPosition 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 TokenPosition 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 (CurrentToken() == Token::kRPAREN) {
        // Allow trailing comma.
        break;
      }
      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,
                                 TokenPosition ident_pos,
                                 const LibraryPrefix* prefix) {
  TRACE_PARSER("ParseStaticCall");
  const TokenPosition 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.
                                  prefix);
  } 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.
    ASSERT(num_arguments == 2);

    // If both arguments are constant expressions of type string,
    // evaluate and canonicalize them.
    // This guarantees that identical("ab", "a"+"b") is true.
    // An alternative way to guarantee this would be to introduce
    // an AST node that canonicalizes a value.
    AstNode* arg0 = arguments->NodeAt(0);
    const Instance* val0 = arg0->EvalConstExpr();
    if ((val0 != NULL) && (val0->IsString())) {
      AstNode* arg1 = arguments->NodeAt(1);
      const Instance* val1 = arg1->EvalConstExpr();
      if ((val1 != NULL) && (val1->IsString())) {
        arguments->SetNodeAt(
            0, new (Z) LiteralNode(arg0->token_pos(),
                                   EvaluateConstExpr(arg0->token_pos(), arg0)));
        arguments->SetNodeAt(
            1, new (Z) LiteralNode(arg1->token_pos(),
                                   EvaluateConstExpr(arg1->token_pos(), arg1)));
      }
    }
    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,
                                   TokenPosition 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 TokenPosition call_pos = TokenPos();
  ASSERT(CurrentToken() == Token::kLPAREN);
  ArgumentListNode* arguments = ParseActualParameters(NULL, kAllowConst);
  return BuildClosureCall(call_pos, closure, arguments);
}


AstNode* Parser::GenerateStaticFieldLookup(const Field& field,
                                           TokenPosition 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::GetterSymbol(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,
                                           TokenPosition 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.)
    const String& name =
        String::Cast(Object::ZoneHandle(primary->primary().raw()));
    if (primary->is_deferred_reference()) {
      StaticGetterNode* getter = new (Z) StaticGetterNode(
          primary->token_pos(),
          NULL,  // No receiver.
          Class::ZoneHandle(Z, library_.toplevel_class()), name);
      getter->set_is_deferred(primary->is_deferred_reference());
      return getter;
    } else 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::Cast(Object::ZoneHandle(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::LoadTypeParameter(PrimaryNode* primary) {
  const TokenPosition primary_pos = primary->token_pos();
  TypeParameter& type_parameter = TypeParameter::ZoneHandle(Z);
  type_parameter = TypeParameter::Cast(primary->primary()).raw();
  if (type_parameter.IsClassTypeParameter()) {
    if (ParsingStaticMember()) {
      const String& name = String::Handle(Z, type_parameter.name());
      ReportError(primary_pos,
                  "cannot access type parameter '%s' "
                  "from static function",
                  name.ToCString());
    }
    // TODO(regis): Verify that CaptureInstantiator() was already called
    // and remove call below.
    if (FunctionLevel() > 0) {
      // Make sure that the class instantiator is captured.
      CaptureInstantiator();
    }
    type_parameter ^= ClassFinalizer::FinalizeType(
        current_class(), type_parameter, ClassFinalizer::kCanonicalize);
    ASSERT(!type_parameter.IsMalformed());
    return new (Z) TypeNode(primary_pos, type_parameter);
  } else {
    ASSERT(type_parameter.IsFunctionTypeParameter());
    // TODO(regis): Verify that CaptureFunctionInstantiator() was already
    // called if necessary.
    // TODO(regis): Finalize type parameter and return as type node.
    // For now, map to dynamic type.
    Type& type = Type::ZoneHandle(Z, Type::DynamicType());
    return new (Z) TypeNode(primary_pos, type);
  }
}


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();
        if (primary_node->primary().IsFunction()) {
          left = LoadClosure(primary_node);
        } else if (primary_node->primary().IsTypeParameter()) {
          left = LoadTypeParameter(primary_node);
        } else {
          // Super field access handled in ParseSuperFieldAccess(),
          // super calls handled in ParseSuperCall().
          ASSERT(!primary_node->IsSuper());
          left = LoadFieldIfUnresolved(left);
        }
      }
      const TokenPosition ident_pos = TokenPos();
      String* ident = ExpectIdentifier("identifier expected");
      if (IsArgumentPart()) {
        // Identifier followed by optional type arguments and opening paren:
        // method call.
        if (CurrentToken() == Token::kLT) {
          // Type arguments.
          if (!FLAG_generic_method_syntax) {
            ReportError("generic type arguments not supported.");
          }
          // TODO(regis): Pass type arguments in generic call.
          // For now, resolve type arguments and ignore.
          ParseTypeArguments(ClassFinalizer::kCanonicalize);
        }
        PrimaryNode* primary_node = left->AsPrimaryNode();
        if ((primary_node != NULL) && primary_node->primary().IsClass()) {
          // Static method call prefixed with class name.
          const Class& cls = Class::Cast(primary_node->primary());
          selector =
              ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix());
        } else {
          if ((primary_node != NULL) && primary_node->is_deferred_reference()) {
            const Class& cls = Class::Handle(library_.toplevel_class());
            selector =
                ParseStaticCall(cls, *ident, ident_pos, primary_node->prefix());
          } 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();
          is_deferred = primary_node->is_deferred_reference();
          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 if (is_deferred) {
            cls = library_.toplevel_class();
          }
        }
        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 TokenPosition 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 TokenPosition 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()) {
          array = LoadTypeParameter(primary_node);
        } else {
          UNREACHABLE();  // Internal parser error.
        }
      }
      selector = new (Z)
          LoadIndexedNode(bracket_pos, array, index, Class::ZoneHandle(Z));
    } else if (IsArgumentPart()) {
      if (CurrentToken() == Token::kLT) {
        // Type arguments.
        if (!FLAG_generic_method_syntax) {
          ReportError("generic type arguments not supported.");
        }
        // TODO(regis): Pass type arguments in generic call.
        // For now, resolve type arguments and ignore.
        ParseTypeArguments(ClassFinalizer::kCanonicalize);
      }
      if (left->IsPrimaryNode()) {
        PrimaryNode* primary_node = left->AsPrimaryNode();
        const TokenPosition 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");
          }
          const String& name =
              String::Cast(Object::ZoneHandle(primary_node->primary().raw()));
          if (primary_node->is_deferred_reference()) {
            // The static call will be converted to throwing a NSM error.
            const Class& cls = Class::Handle(library_.toplevel_class());
            selector =
                ParseStaticCall(cls, name, primary_pos, primary_node->prefix());
          } else 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()) {
          TypeParameter& type_parameter = TypeParameter::ZoneHandle(Z);
          type_parameter = TypeParameter::Cast(primary_node->primary()).raw();
          const String& name = String::ZoneHandle(Z, type_parameter.name());
          if (type_parameter.IsClassTypeParameter()) {
            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 {
            ASSERT(type_parameter.IsFunctionTypeParameter());
            // TODO(regis): Should we throw a type error instead?
            ReportError(primary_pos,
                        "illegal use of function type parameter '%s'",
                        name.ToCString());
          }
        } 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());
          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 TokenPosition 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,
                           Heap::kOld));
          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()) {
          left = LoadTypeParameter(primary_node);
        } 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) {
  if (!FLAG_support_deprecated_tearoff_syntax) {
    ReportError("tear-off using the x#id syntax is a deprecated feature");
    return NULL;
  }
  ExpectToken(Token::kHASH);
  TokenPosition 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 = Symbols::Token(CurrentToken()).raw();
    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.
      if (is_setter_name) {
        const String& setter_name =
            String::Handle(Z, Field::SetterName(extractor_name));
        obj = prefix.LookupObject(setter_name);
      }
      if (obj.IsNull()) {
        obj = prefix.LookupObject(extractor_name);
      }
    }
    if (!prefix.is_loaded() && (parsed_function() != NULL) &&
        !FLAG_load_deferred_eagerly) {
      // 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()) {
        const Instance& setter_closure =
            Instance::ZoneHandle(field.SetterClosure());
        return new (Z) LiteralNode(property_pos, setter_closure);
      }
      if (!is_setter_name) {
        const 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.
  GrowableHandlePtrArray<const String> pieces(Z, 3);
  pieces.Add(Symbols::HashMark());
  if (is_setter_name) {
    pieces.Add(Symbols::SetterPrefix());
  }
  pieces.Add(extractor_name);
  extractor_name = Symbols::FromConcatAll(T, pieces);
  return new (Z) InstanceGetterNode(property_pos, primary, extractor_name);
}


AstNode* Parser::ParsePostfixExpr() {
  TRACE_PARSER("ParsePostfixExpr");
  String* expr_ident =
      Token::IsIdentifier(CurrentToken()) ? CurrentLiteral() : NULL;
  const TokenPosition 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();
    const TokenPosition op_pos = TokenPos();
    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(
        op_pos, binary_op, new (Z) LoadLocalNode(op_pos, temp),
        new (Z) LiteralNode(op_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(op_pos, temp));
    return let_expr;
  }
  return expr;
}


// Resolve the given type and its type arguments from the current function and
// current class according to the given type finalization mode.
// Not all involved type classes may get resolved yet, but at least type
// parameters will get resolved, thereby relieving the class
// finalizer from resolving type parameters out of context.
// TODO(regis): Refactor this code which is partially duplicated in the class
// finalizer, paying attention to type parameter resolution and mixin library.
void Parser::ResolveType(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_or_library_prefix() == Object::null()) {
      // First check if the type is a function type parameter.
      if (!innermost_function().IsNull()) {
        // TODO(regis): Shortcut this lookup if no generic functions in scope.
        TypeParameter& type_parameter = TypeParameter::ZoneHandle(
            Z, innermost_function().LookupTypeParameter(unresolved_class_name,
                                                        NULL));
        if (!type_parameter.IsNull()) {
          // TODO(regis): Check for absence of type arguments.
          // For now, resolve the function type parameter to dynamic.
          *type = Type::DynamicType();
          return;
        }
      }
      // Then check if the type is a class type parameter.
      const TypeParameter& type_parameter = TypeParameter::Handle(
          Z, current_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()) {
          *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 (type->arguments() != TypeArguments::null()) {
          *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.
      // Note that when compiling a cloned mixin function, library_ may be
      // different than current_class's library.
      if (finalization > ClassFinalizer::kResolveTypeParameters) {
        resolved_type_class = library_.LookupClass(unresolved_class_name);
      }
    } else {
      // Resolve class name in the scope of the library prefix.
      const Object& prefix =
          Object::Handle(Z, unresolved_class.library_or_library_prefix());
      ASSERT(prefix.IsLibraryPrefix());
      resolved_type_class =
          LibraryPrefix::Cast(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);
      // Promote type to a function type in case its type class is a typedef.
      if (resolved_type_class.IsTypedefClass()) {
        ASSERT(!parameterized_type.IsFunctionType());
        parameterized_type.set_signature(
            Function::Handle(Z, resolved_type_class.signature_function()));
      }
      // Replace FutureOr<T> type of async library with dynamic.
      if ((resolved_type_class.library() == Library::AsyncLibrary()) &&
          (resolved_type_class.Name() == Symbols::FutureOr().raw())) {
        parameterized_type.set_type_class(
            Class::Handle(Object::dynamic_class()));
        parameterized_type.set_arguments(Object::null_type_arguments());
      }
    } 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;
    }
  }
  if (finalization > ClassFinalizer::kResolveTypeParameters) {
    type->SetIsResolved();
  }
  // Resolve type arguments, if any.
  if (type->arguments() != TypeArguments::null()) {
    const TypeArguments& arguments =
        TypeArguments::Handle(Z, type->arguments());
    const intptr_t num_arguments = arguments.Length();
    AbstractType& type_argument = AbstractType::Handle(Z);
    for (intptr_t i = 0; i < num_arguments; i++) {
      type_argument ^= arguments.TypeAt(i);
      ResolveType(finalization, &type_argument);
      arguments.SetTypeAt(i, type_argument);
    }
  }
  if (type->IsFunctionType()) {
    const Function& signature =
        Function::Handle(Z, Type::Cast(*type).signature());
    Type& signature_type = Type::Handle(Z, signature.SignatureType());
    if (signature_type.raw() != type->raw()) {
      ResolveType(finalization, &signature_type);
    } else {
      AbstractType& type = AbstractType::Handle(signature.result_type());
      ResolveType(finalization, &type);
      signature.set_result_type(type);
      const intptr_t num_parameters = signature.NumParameters();
      for (intptr_t i = 0; i < num_parameters; i++) {
        type = signature.ParameterTypeAt(i);
        ResolveType(finalization, &type);
        signature.SetParameterTypeAt(i, type);
      }
      if (signature.IsSignatureFunction()) {
        // Drop fields that are not necessary anymore after resolution.
        // The parent function, owner, and token position of a shared
        // canonical function type are meaningless, since the canonical
        // representent is picked arbitrarily.
        signature.set_parent_function(Function::Handle(Z));
        // TODO(regis): As long as we support metadata in typedef signatures,
        // we cannot reset these fields used to reparse a typedef.
        // Note that the scope class of a typedef function type is always
        // preserved as the typedef class (not reset to _Closure class), thereby
        // preventing sharing of canonical function types between typedefs.
        // Not being shared, these fields are therefore always meaningful for
        // typedefs.
        if (type.HasResolvedTypeClass()) {
          const Class& scope_class = Class::Handle(Z, type.type_class());
          if (!scope_class.IsTypedefClass()) {
            signature.set_owner(Object::Handle(Z));
            signature.set_token_pos(TokenPosition::kNoSource);
          }
        }
      }
    }
  }
}


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(TokenPosition 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());
  ASSERT(!cls.IsTypedefClass());
  // Note that if cls is _Closure, the returned type will be _Closure,
  // and not the signature type.
  Type& type = Type::ZoneHandle(Z, cls.CanonicalType());
  if (!type.IsNull()) {
    return &type;
  }
  type = Type::New(cls, TypeArguments::Handle(Z, cls.type_parameters()),
                   cls.token_pos(), Heap::kOld);
  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().IsGeneric();
}


void Parser::InsertCachedConstantValue(const Script& script,
                                       TokenPosition token_pos,
                                       const Instance& value) {
  ASSERT(Thread::Current()->IsMutatorThread());
  const intptr_t kInitialConstMapSize = 16;
  ASSERT(!script.InVMHeap());
  if (script.compile_time_constants() == Array::null()) {
    const Array& array = Array::Handle(
        HashTables::New<ConstantsMap>(kInitialConstMapSize, Heap::kNew));
    script.set_compile_time_constants(array);
  }
  ConstantsMap constants(script.compile_time_constants());
  constants.InsertNewOrGetValue(token_pos, value);
  script.set_compile_time_constants(constants.Release());
}


void Parser::CacheConstantValue(TokenPosition token_pos,
                                const Instance& value) {
  if (current_function().kind() == RawFunction::kImplicitStaticFinalGetter) {
    // Don't cache constants in initializer expressions. They get
    // evaluated only once.
    return;
  }
  InsertCachedConstantValue(script_, token_pos, value);
  INC_STAT(thread_, num_cached_consts, 1);
}


bool Parser::GetCachedConstant(TokenPosition token_pos, Instance* value) {
  bool is_present = false;
  ASSERT(!script_.InVMHeap());
  if (script_.compile_time_constants() == Array::null()) {
    return false;
  }
  ConstantsMap constants(script_.compile_time_constants());
  *value ^= constants.GetOrNull(token_pos, &is_present);
  // Mutator compiler thread may add constants while background compiler
  // is running, and thus change the value of 'compile_time_constants';
  // do not assert that 'compile_time_constants' has not changed.
  constants.Release();
  if (FLAG_compiler_stats && is_present) {
    thread_->compiler_stats()->num_const_cache_hits++;
  }
  return is_present;
}


RawInstance* Parser::TryCanonicalize(const Instance& instance,
                                     TokenPosition token_pos) {
  if (instance.IsNull()) {
    return instance.raw();
  }
  const char* error_str = NULL;
  Instance& result =
      Instance::Handle(Z, instance.CheckAndCanonicalize(thread(), &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,
    TokenPosition 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::GetterSymbol(field_name));
  const Function& getter =
      Function::Handle(Z, field_owner.LookupStaticFunction(getter_name));
  const Instance& value = Instance::Handle(Z, field.StaticValue());
  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()) {
      NoReloadScope no_reload_scope(isolate(), thread());
      NoOOBMessageScope no_msg_scope(thread());
      field.SetStaticValue(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);
      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.SetStaticValue(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.SetStaticValue(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) {
  NoReloadScope no_reload_scope(isolate(), thread());
  NoOOBMessageScope no_msg_scope(thread());
  // Factories have one extra argument: the type arguments.
  // Constructors have 1 extra arguments: receiver.
  const int kNumExtraArgs = 1;
  const int num_arguments = arguments->length() + kNumExtraArgs;
  const Array& arg_values =
      Array::Handle(Z, Array::New(num_arguments, Heap::kOld));
  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);
  } 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()));
  const Object& result = Object::Handle(
      Z, 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(TokenPosition ident_pos,
                                      const String& ident,
                                      AstNode** node,
                                      intptr_t* function_level) {
  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);
    }
    if (function_level != NULL) {
      *function_level = local->owner()->function_level();
    }
    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);
      }
    }
    if (function_level != NULL) {
      *function_level = 0;
    }
    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(TokenPosition 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(TokenPosition 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()));
    if (is_deferred) {
      primary->set_prefix(&prefix);
    }
    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()));
      if (is_deferred) {
        primary->set_prefix(&prefix);
      }
      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(TokenPosition 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;
  intptr_t resolved_func_level = 0;
  ResolveIdentInLocalScope(ident_pos, ident, &resolved, &resolved_func_level);
  if (!innermost_function().IsNull()) {
    // TODO(regis): Shortcut this lookup if no generic functions in scope.
    intptr_t type_param_func_level = FunctionLevel();
    const TypeParameter& type_parameter =
        TypeParameter::ZoneHandle(Z, innermost_function().LookupTypeParameter(
                                         ident, &type_param_func_level));
    if (!type_parameter.IsNull()) {
      if ((resolved == NULL) || (resolved_func_level < type_param_func_level)) {
        // The identifier is a function type parameter, possibly shadowing
        // 'resolved'.
        if (type_param_func_level < FunctionLevel()) {
          // Make sure that the function instantiator is captured.
          CaptureFunctionInstantiator();
        }
        // TODO(regis): Finalize type parameter and return as type node.
        // For now, map to dynamic type.
        Type& type = Type::ZoneHandle(Z, Type::DynamicType());
        return new (Z) TypeNode(ident_pos, type);
      }
    }
  }
  if (resolved == NULL) {
    // Check whether the identifier is a class type parameter.
    if (!current_class().IsNull()) {
      TypeParameter& type_parameter = TypeParameter::ZoneHandle(
          Z, current_class().LookupTypeParameter(ident));
      if (!type_parameter.IsNull()) {
        if (FunctionLevel() > 0) {
          // Make sure that the class 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 TokenPosition 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, Heap::kOld));
      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");
  TokenPosition 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, 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, Heap::kOld));
  if (finalization >= ClassFinalizer::kResolveTypeParameters) {
    ResolveType(finalization, &type);
    if (finalization >= ClassFinalizer::kCanonicalize) {
      type ^= ClassFinalizer::FinalizeType(current_class(), type, finalization);
    }
  }
  return type.raw();
}


void Parser::CheckConstructorCallTypeArguments(
    TokenPosition 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(TokenPosition type_pos,
                                  bool is_const,
                                  const TypeArguments& type_arguments) {
  TRACE_PARSER("ParseListLiteral");
  ASSERT(type_pos.IsReal());
  ASSERT(CurrentToken() == Token::kLBRACK || CurrentToken() == Token::kINDEX);
  const TokenPosition 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->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, Heap::kOld));
  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 TokenPosition element_pos = TokenPos();
      AstNode* element = ParseExpr(is_const, kConsumeCascades);
      if (I->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.
    if ((element_list.length() == 0) && list_type_arguments.IsNull()) {
      return new (Z) LiteralNode(literal_pos, Object::empty_array());
    }
    Array& const_list =
        Array::ZoneHandle(Z, Array::New(element_list.length(), Heap::kOld));
    const_list.SetTypeArguments(
        TypeArguments::Handle(Z, list_type_arguments.Canonicalize()));
    Error& bound_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->type_checks() && !element_type.IsDynamicType() &&
          (!elem->AsLiteralNode()->literal().IsNull() &&
           !elem->AsLiteralNode()->literal().IsInstanceOf(
               element_type, TypeArguments::Handle(Z), &bound_error))) {
        // If the failure is due to a bound error, display it instead.
        if (!bound_error.IsNull()) {
          ReportError(bound_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() && (FunctionLevel() > 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::kOld));
      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(
    TokenPosition 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(TokenPosition type_pos,
                                 bool is_const,
                                 const TypeArguments& type_arguments) {
  TRACE_PARSER("ParseMapLiteral");
  ASSERT(type_pos.IsReal());
  ASSERT(CurrentToken() == Token::kLBRACE);
  const TokenPosition 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->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 TokenPosition key_pos = TokenPos();
    AstNode* key = ParseExpr(is_const, kConsumeCascades);
    if (I->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(Z, key_value)) {
        ReportError(key_pos, "key value must not implement operator ==");
      }
    }
    ExpectToken(Token::kCOLON);
    const TokenPosition value_pos = TokenPos();
    AstNode* value = ParseExpr(is_const, kConsumeCascades);
    SetAllowFunctionLiterals(saved_mode);
    if (I->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& bound_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->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(), &bound_error))) {
          // If the failure is due to a bound error, display it.
          if (!bound_error.IsNull()) {
            ReportError(bound_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.LookupConstructorAllowPrivate(
               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() &&
        (FunctionLevel() > 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::kOld));
      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. Pass a pre-allocated
    // array for the common empty map literal case.
    if (kv_pairs_list.length() == 0) {
      LiteralNode* empty_array_literal =
          new (Z) LiteralNode(TokenPos(), Object::empty_array());
      factory_param->Add(empty_array_literal);
    } else {
      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 TokenPosition 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();
  TokenPosition symbol_pos = TokenPos();
  String& symbol = String::ZoneHandle(Z);
  if (IsIdentifier()) {
    symbol = CurrentLiteral()->raw();
    ConsumeToken();
    GrowableHandlePtrArray<const String> pieces(Z, 3);
    pieces.Add(symbol);
    while (CurrentToken() == Token::kPERIOD) {
      pieces.Add(Symbols::Dot());
      ConsumeToken();
      pieces.Add(*ExpectIdentifier("identifier expected"));
    }
    symbol = Symbols::FromConcatAll(T, pieces);
  } else if (Token::CanBeOverloaded(CurrentToken())) {
    symbol = Symbols::Token(CurrentToken()).raw();
    ConsumeToken();
  } else {
    ReportError("illegal symbol literal");
  }
  ASSERT(symbol.IsSymbol());

  Instance& symbol_instance = Instance::ZoneHandle(Z);
  if (GetCachedConstant(symbol_pos, &symbol_instance)) {
    return new (Z) LiteralNode(symbol_pos, symbol_instance);
  }

  // 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, 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");
  }
  symbol_instance ^= result.raw();
  CacheConstantValue(symbol_pos, symbol_instance);
  return new (Z) LiteralNode(symbol_pos, symbol_instance);
}


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

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

  ParamList params;
  params.AddFinalParameter(token_pos, &Symbols::ClosureParameter(),
                           &Object::dynamic_type());

  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(Object::dynamic_type());
  AddFormalParamsToFunction(&params, closure);

  // Finalize function type.
  Type& signature_type = Type::Handle(Z, closure.SignatureType());
  signature_type ^= ClassFinalizer::FinalizeType(
      current_class(), signature_type, ClassFinalizer::kCanonicalize);
  closure.SetSignatureType(signature_type);
  // Finalization would be premature when top-level parsing.
  ASSERT(!is_top_level_);
  return closure.raw();
}


static String& BuildConstructorName(Thread* thread,
                                    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.
  Zone* zone = thread->zone();
  String& constructor_name =
      String::Handle(zone, Symbols::FromDot(thread, type_class_name));
  if (named_constructor != NULL) {
    constructor_name =
        Symbols::FromConcat(thread, 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());
  if (!FLAG_support_deprecated_tearoff_syntax) {
    ReportError("tear-off using the x#id syntax is a deprecated feature");
    return;
  }
  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(T, 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,
                                     NULL,  // instantiation_trail
                                     NULL,  // bound_trail
                                     Heap::kOld);
        ASSERT(error.IsNull());
      }
      *type_arguments = type.arguments();
      *constructor = constructor->RedirectionTarget();
    }
  }
}


AstNode* Parser::ParseNewOperator(Token::Kind op_kind) {
  TRACE_PARSER("ParseNewOperator");
  const TokenPosition 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");
  }
  TokenPosition 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::ZoneHandle(
      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::ZoneHandle(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 (!FLAG_support_deprecated_tearoff_syntax) {
      ReportError("tear-off using the x#id syntax is a deprecated feature");
    }
    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.
  TokenPosition 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);
    }
    if (arguments->length() > 0) {
      // Evaluate arguments for side-effects and throw.
      LetNode* error_result = new (Z) LetNode(type_pos);
      for (intptr_t i = 0; i < arguments->length(); ++i) {
        error_result->AddNode(arguments->NodeAt(i));
      }
      error_result->AddNode(ThrowTypeError(type_pos, type));
      return error_result;
    }
    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).
  intptr_t arguments_length = arguments->length() + 1;

  // 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(T, 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::ZoneHandle(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,
                                          NULL,  // instantiation_trail
                                          NULL,  // bound_trail
                                          Heap::kOld);
        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::Cast(
            Object::Handle(Z, cls.library_or_library_prefix()));
        if (!prefix.IsNull() && !prefix.is_loaded() &&
            !FLAG_load_deferred_eagerly) {
          // 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->type_checks() &&
          !redirect_type.IsSubtypeOf(type, NULL, NULL, Heap::kOld)) {
        // 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());
    }
  }
  ASSERT(!constructor.IsNull());

  // It is a compile time error to instantiate a const instance of an
  // abstract class. Factory methods are ok.
  if (is_const && type_class.is_abstract() && !constructor.IsFactory()) {
    ReportError(new_pos, "cannot instantiate abstract class");
  }

  // 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.value(), Heap::kOld))));
    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& bound_error = Error::Handle(Z);
      ASSERT(!is_top_level_);  // We cannot check unresolved types.
      if (!const_instance.IsInstanceOf(type_bound, TypeArguments::Handle(Z),
                                       &bound_error)) {
        type_bound = ClassFinalizer::NewFinalizedMalformedType(
            bound_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() &&
        (FunctionLevel() > 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) {
  NoReloadScope no_reload_scope(isolate(), thread());
  NoOOBMessageScope no_msg_scope(thread());
  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(), Heap::kOld));
  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, Heap::kOld));
  interpolate_arg.SetAt(0, value_arr);

  // Call interpolation function.
  Object& result = Object::Handle(Z);
  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(T, 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 TokenPosition 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.

  // First, check whether we've cached a compile-time constant for this
  // string interpolation.
  Instance& cached_string = Instance::Handle(Z);
  if (GetCachedConstant(literal_start, &cached_string)) {
    SkipStringLiteral();
    return new (Z) LiteralNode(literal_start,
                               Instance::ZoneHandle(Z, cached_string.raw()));
  }

  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 TokenPosition 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) {
      const String& interpolated_string = Interpolate(values_list);
      primary = new (Z) LiteralNode(literal_start, interpolated_string);
      CacheConstantValue(literal_start, interpolated_string);
    } 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(T, pieces));
      primary = new (Z) LiteralNode(literal_start, lit);
      // Caching of constant not necessary because the symbol lookup will
      // find the value next time.
    }
  } 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()) {
    primary = ParseFunctionStatement(true);
  } else if (IsIdentifier()) {
    TokenPosition qual_ident_pos = TokenPos();
    const LibraryPrefix& prefix = LibraryPrefix::ZoneHandle(Z, ParsePrefix());
    if (!prefix.IsNull()) {
      if (CurrentToken() == Token::kHASH) {
        if (!FLAG_support_deprecated_tearoff_syntax) {
          ReportError("tear-off using the x#id syntax is a deprecated feature");
        }
        // 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()) {
      intptr_t primary_func_level = 0;
      ResolveIdentInLocalScope(qual_ident_pos, ident, &primary,
                               &primary_func_level);
      // Check whether the identifier is shadowed by a function type parameter.
      if (!innermost_function().IsNull()) {
        // TODO(regis): Shortcut this lookup if no generic functions in scope.
        intptr_t type_param_func_level = FunctionLevel();
        TypeParameter& type_param = TypeParameter::ZoneHandle(
            Z, innermost_function().LookupTypeParameter(
                   ident, &type_param_func_level));
        if (!type_param.IsNull()) {
          if ((primary == NULL) ||
              (primary_func_level < type_param_func_level)) {
            // The identifier is a function type parameter, possibly shadowing
            // already resolved 'primary'.
            if (type_param_func_level < FunctionLevel()) {
              // Make sure that the function instantiator is captured.
              CaptureFunctionInstantiator();
            }
            return new (Z) PrimaryNode(qual_ident_pos, type_param);
          }
        }
      }
      if (primary == NULL) {
        // 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 {
          GrowableHandlePtrArray<const String> pieces(Z, 3);
          pieces.Add(String::Handle(Z, prefix.name()));
          pieces.Add(Symbols::Dot());
          pieces.Add(ident);
          const String& qualified_name =
              String::ZoneHandle(Z, Symbols::FromConcatAll(T, pieces));
          primary = new (Z) PrimaryNode(qual_ident_pos, qualified_name);
          if (prefix.is_deferred_load()) {
            primary->AsPrimaryNode()->set_prefix(&prefix);
          }
        }
      } else if (FLAG_load_deferred_eagerly && prefix.is_deferred_load()) {
        // primary != NULL.
        GrowableHandlePtrArray<const String> pieces(Z, 3);
        pieces.Add(String::Handle(Z, prefix.name()));
        pieces.Add(Symbols::Dot());
        pieces.Add(ident);
        const String& qualified_name =
            String::ZoneHandle(Z, Symbols::FromConcatAll(T, pieces));
        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(), Object::null_instance());
    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) {
    const 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());
    }
    const TokenPosition super_pos = TokenPos();
    ConsumeToken();
    if (CurrentToken() == Token::kPERIOD) {
      ConsumeToken();
      const TokenPosition 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(TokenPosition expr_pos,
                                          AstNode* expr) {
  NoReloadScope no_reload_scope(isolate(), thread());
  NoOOBMessageScope no_msg_scope(thread());
  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.StaticValue() != Object::sentinel().raw());
    ASSERT(field.StaticValue() != Object::transition_sentinel().raw());
    return Instance::ZoneHandle(Z, field.StaticValue());
  } else if (expr->IsTypeNode()) {
    AbstractType& type =
        AbstractType::ZoneHandle(Z, expr->AsTypeNode()->type().raw());
    ASSERT(type.IsInstantiated() && !type.IsMalformedOrMalbounded());
    return type;
  } else if (expr->IsClosureNode()) {
    const Function& func = expr->AsClosureNode()->function();
    ASSERT((func.IsImplicitStaticClosureFunction()));
    Instance& closure = Instance::ZoneHandle(Z, func.ImplicitStaticClosure());
    closure = TryCanonicalize(closure, expr_pos);
    return closure;
  } else {
    ASSERT(expr->EvalConstExpr() != NULL);
    Instance& value = Instance::ZoneHandle(Z);
    if (GetCachedConstant(expr_pos, &value)) {
      return value;
    }
    ReturnNode* ret = new (Z) ReturnNode(expr_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_pos, empty_scope);
    seq->Add(ret);

    INC_STAT(thread_, num_execute_const, 1);
    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());
    value ^= result.raw();
    value = TryCanonicalize(value, expr_pos);
    CacheConstantValue(expr_pos, value);
    return value;
  }
}


void Parser::SkipFunctionLiteral() {
  if (IsIdentifier()) {
    if (LookaheadToken(1) != Token::kLPAREN) {
      SkipType(true);
    }
    ExpectIdentifier("function name expected");
  }
  if (CurrentToken() == Token::kLPAREN) {
    SkipToMatchingParenthesis();
  }
  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() {
  if (CurrentToken() == Token::kLT) {
    SkipTypeArguments();
  }
  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 (IsArgumentPart()) {
      SkipActualParameters();
    } else {
      break;
    }
  }
}

void Parser::SkipPostfixExpr() {
  SkipPrimary();
  if (CurrentToken() == Token::kHASH) {
    ConsumeToken();
    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


#else  // DART_PRECOMPILED_RUNTIME


namespace dart {

void ParsedFunction::AddToGuardedFields(const Field* field) const {
  UNREACHABLE();
}


kernel::ScopeBuildingResult* ParsedFunction::EnsureKernelScopes() {
  UNREACHABLE();
  return NULL;
}


LocalVariable* ParsedFunction::EnsureExpressionTemp() {
  UNREACHABLE();
  return NULL;
}


void ParsedFunction::SetNodeSequence(SequenceNode* node_sequence) {
  UNREACHABLE();
}


void ParsedFunction::SetRegExpCompileData(
    RegExpCompileData* regexp_compile_data) {
  UNREACHABLE();
}


void ParsedFunction::AllocateVariables() {
  UNREACHABLE();
}


void ParsedFunction::AllocateIrregexpVariables(intptr_t num_stack_locals) {
  UNREACHABLE();
}


void ParsedFunction::Bailout(const char* origin, const char* reason) const {
  UNREACHABLE();
}


void Parser::ParseCompilationUnit(const Library& library,
                                  const Script& script) {
  UNREACHABLE();
}


void Parser::ParseClass(const Class& cls) {
  UNREACHABLE();
}


RawObject* Parser::ParseFunctionParameters(const Function& func) {
  UNREACHABLE();
  return Object::null();
}


void Parser::ParseFunction(ParsedFunction* parsed_function) {
  UNREACHABLE();
}


RawObject* Parser::ParseMetadata(const Field& meta_data) {
  UNREACHABLE();
  return Object::null();
}


ParsedFunction* Parser::ParseStaticFieldInitializer(const Field& field) {
  UNREACHABLE();
  return NULL;
}


void Parser::InsertCachedConstantValue(const Script& script,
                                       TokenPosition token_pos,
                                       const Instance& value) {
  UNREACHABLE();
}


ArgumentListNode* Parser::BuildNoSuchMethodArguments(
    TokenPosition call_pos,
    const String& function_name,
    const ArgumentListNode& function_args,
    const LocalVariable* temp_for_last_arg,
    bool is_super_invocation) {
  UNREACHABLE();
  return NULL;
}

}  // namespace dart

#endif  // DART_PRECOMPILED_RUNTIME
