// Copyright 2012 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/parsing/parser.h"

#include "src/api.h"
#include "src/ast/ast.h"
#include "src/ast/ast-expression-rewriter.h"
#include "src/ast/ast-expression-visitor.h"
#include "src/ast/ast-literal-reindexer.h"
#include "src/ast/scopeinfo.h"
#include "src/bailout-reason.h"
#include "src/base/platform/platform.h"
#include "src/bootstrapper.h"
#include "src/char-predicates-inl.h"
#include "src/codegen.h"
#include "src/compiler.h"
#include "src/messages.h"
#include "src/parsing/parameter-initializer-rewriter.h"
#include "src/parsing/parser-base.h"
#include "src/parsing/rewriter.h"
#include "src/parsing/scanner-character-streams.h"
#include "src/runtime/runtime.h"
#include "src/string-stream.h"
#include "src/tracing/trace-event.h"

namespace v8 {
namespace internal {

ScriptData::ScriptData(const byte* data, int length)
    : owns_data_(false), rejected_(false), data_(data), length_(length) {
  if (!IsAligned(reinterpret_cast<intptr_t>(data), kPointerAlignment)) {
    byte* copy = NewArray<byte>(length);
    DCHECK(IsAligned(reinterpret_cast<intptr_t>(copy), kPointerAlignment));
    CopyBytes(copy, data, length);
    data_ = copy;
    AcquireDataOwnership();
  }
}

ParseInfo::ParseInfo(Zone* zone)
    : zone_(zone),
      flags_(0),
      source_stream_(nullptr),
      source_stream_encoding_(ScriptCompiler::StreamedSource::ONE_BYTE),
      extension_(nullptr),
      compile_options_(ScriptCompiler::kNoCompileOptions),
      script_scope_(nullptr),
      unicode_cache_(nullptr),
      stack_limit_(0),
      hash_seed_(0),
      isolate_(nullptr),
      cached_data_(nullptr),
      ast_value_factory_(nullptr),
      literal_(nullptr),
      scope_(nullptr) {}

ParseInfo::ParseInfo(Zone* zone, Handle<JSFunction> function)
    : ParseInfo(zone, Handle<SharedFunctionInfo>(function->shared())) {
  set_context(Handle<Context>(function->context()));
}


ParseInfo::ParseInfo(Zone* zone, Handle<SharedFunctionInfo> shared)
    : ParseInfo(zone) {
  isolate_ = shared->GetIsolate();

  set_lazy();
  set_hash_seed(isolate_->heap()->HashSeed());
  set_stack_limit(isolate_->stack_guard()->real_climit());
  set_unicode_cache(isolate_->unicode_cache());
  set_language_mode(shared->language_mode());
  set_shared_info(shared);

  Handle<Script> script(Script::cast(shared->script()));
  set_script(script);
  if (!script.is_null() && script->type() == Script::TYPE_NATIVE) {
    set_native();
  }
}


ParseInfo::ParseInfo(Zone* zone, Handle<Script> script) : ParseInfo(zone) {
  isolate_ = script->GetIsolate();

  set_hash_seed(isolate_->heap()->HashSeed());
  set_stack_limit(isolate_->stack_guard()->real_climit());
  set_unicode_cache(isolate_->unicode_cache());
  set_script(script);

  if (script->type() == Script::TYPE_NATIVE) {
    set_native();
  }
}


FunctionEntry ParseData::GetFunctionEntry(int start) {
  // The current pre-data entry must be a FunctionEntry with the given
  // start position.
  if ((function_index_ + FunctionEntry::kSize <= Length()) &&
      (static_cast<int>(Data()[function_index_]) == start)) {
    int index = function_index_;
    function_index_ += FunctionEntry::kSize;
    Vector<unsigned> subvector(&(Data()[index]), FunctionEntry::kSize);
    return FunctionEntry(subvector);
  }
  return FunctionEntry();
}


int ParseData::FunctionCount() {
  int functions_size = FunctionsSize();
  if (functions_size < 0) return 0;
  if (functions_size % FunctionEntry::kSize != 0) return 0;
  return functions_size / FunctionEntry::kSize;
}


bool ParseData::IsSane() {
  if (!IsAligned(script_data_->length(), sizeof(unsigned))) return false;
  // Check that the header data is valid and doesn't specify
  // point to positions outside the store.
  int data_length = Length();
  if (data_length < PreparseDataConstants::kHeaderSize) return false;
  if (Magic() != PreparseDataConstants::kMagicNumber) return false;
  if (Version() != PreparseDataConstants::kCurrentVersion) return false;
  if (HasError()) return false;
  // Check that the space allocated for function entries is sane.
  int functions_size = FunctionsSize();
  if (functions_size < 0) return false;
  if (functions_size % FunctionEntry::kSize != 0) return false;
  // Check that the total size has room for header and function entries.
  int minimum_size =
      PreparseDataConstants::kHeaderSize + functions_size;
  if (data_length < minimum_size) return false;
  return true;
}


void ParseData::Initialize() {
  // Prepares state for use.
  int data_length = Length();
  if (data_length >= PreparseDataConstants::kHeaderSize) {
    function_index_ = PreparseDataConstants::kHeaderSize;
  }
}


bool ParseData::HasError() {
  return Data()[PreparseDataConstants::kHasErrorOffset];
}


unsigned ParseData::Magic() {
  return Data()[PreparseDataConstants::kMagicOffset];
}


unsigned ParseData::Version() {
  return Data()[PreparseDataConstants::kVersionOffset];
}


int ParseData::FunctionsSize() {
  return static_cast<int>(Data()[PreparseDataConstants::kFunctionsSizeOffset]);
}


void Parser::SetCachedData(ParseInfo* info) {
  if (compile_options_ == ScriptCompiler::kNoCompileOptions) {
    cached_parse_data_ = NULL;
  } else {
    DCHECK(info->cached_data() != NULL);
    if (compile_options_ == ScriptCompiler::kConsumeParserCache) {
      cached_parse_data_ = ParseData::FromCachedData(*info->cached_data());
    }
  }
}

FunctionLiteral* Parser::DefaultConstructor(const AstRawString* name,
                                            bool call_super, Scope* scope,
                                            int pos, int end_pos,
                                            LanguageMode language_mode) {
  int materialized_literal_count = -1;
  int expected_property_count = -1;
  int parameter_count = 0;
  if (name == nullptr) name = ast_value_factory()->empty_string();

  FunctionKind kind = call_super ? FunctionKind::kDefaultSubclassConstructor
                                 : FunctionKind::kDefaultBaseConstructor;
  Scope* function_scope = NewScope(scope, FUNCTION_SCOPE, kind);
  SetLanguageMode(function_scope,
                  static_cast<LanguageMode>(language_mode | STRICT));
  // Set start and end position to the same value
  function_scope->set_start_position(pos);
  function_scope->set_end_position(pos);
  ZoneList<Statement*>* body = NULL;

  {
    AstNodeFactory function_factory(ast_value_factory());
    FunctionState function_state(&function_state_, &scope_, function_scope,
                                 kind, &function_factory);

    body = new (zone()) ZoneList<Statement*>(call_super ? 2 : 1, zone());
    if (call_super) {
      // $super_constructor = %_GetSuperConstructor(<this-function>)
      // %reflect_construct(
      //     $super_constructor, InternalArray(...args), new.target)
      auto constructor_args_name = ast_value_factory()->empty_string();
      bool is_duplicate;
      bool is_rest = true;
      bool is_optional = false;
      Variable* constructor_args =
          function_scope->DeclareParameter(constructor_args_name, TEMPORARY,
                                           is_optional, is_rest, &is_duplicate);

      ZoneList<Expression*>* args =
          new (zone()) ZoneList<Expression*>(2, zone());
      VariableProxy* this_function_proxy = scope_->NewUnresolved(
          factory(), ast_value_factory()->this_function_string(),
          Variable::NORMAL, pos);
      ZoneList<Expression*>* tmp =
          new (zone()) ZoneList<Expression*>(1, zone());
      tmp->Add(this_function_proxy, zone());
      Expression* super_constructor = factory()->NewCallRuntime(
          Runtime::kInlineGetSuperConstructor, tmp, pos);
      args->Add(super_constructor, zone());
      Spread* spread_args = factory()->NewSpread(
          factory()->NewVariableProxy(constructor_args), pos, pos);
      ZoneList<Expression*>* spread_args_expr =
          new (zone()) ZoneList<Expression*>(1, zone());
      spread_args_expr->Add(spread_args, zone());
      args->AddAll(*PrepareSpreadArguments(spread_args_expr), zone());
      VariableProxy* new_target_proxy = scope_->NewUnresolved(
          factory(), ast_value_factory()->new_target_string(), Variable::NORMAL,
          pos);
      args->Add(new_target_proxy, zone());
      CallRuntime* call = factory()->NewCallRuntime(
          Context::REFLECT_CONSTRUCT_INDEX, args, pos);
      body->Add(factory()->NewReturnStatement(call, pos), zone());
    }

    materialized_literal_count = function_state.materialized_literal_count();
    expected_property_count = function_state.expected_property_count();
  }

  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
      name, function_scope, body, materialized_literal_count,
      expected_property_count, parameter_count,
      FunctionLiteral::kNoDuplicateParameters,
      FunctionLiteral::kAnonymousExpression,
      FunctionLiteral::kShouldLazyCompile, kind, pos);

  return function_literal;
}


// ----------------------------------------------------------------------------
// Target is a support class to facilitate manipulation of the
// Parser's target_stack_ (the stack of potential 'break' and
// 'continue' statement targets). Upon construction, a new target is
// added; it is removed upon destruction.

class Target BASE_EMBEDDED {
 public:
  Target(Target** variable, BreakableStatement* statement)
      : variable_(variable), statement_(statement), previous_(*variable) {
    *variable = this;
  }

  ~Target() {
    *variable_ = previous_;
  }

  Target* previous() { return previous_; }
  BreakableStatement* statement() { return statement_; }

 private:
  Target** variable_;
  BreakableStatement* statement_;
  Target* previous_;
};


class TargetScope BASE_EMBEDDED {
 public:
  explicit TargetScope(Target** variable)
      : variable_(variable), previous_(*variable) {
    *variable = NULL;
  }

  ~TargetScope() {
    *variable_ = previous_;
  }

 private:
  Target** variable_;
  Target* previous_;
};


// ----------------------------------------------------------------------------
// The CHECK_OK macro is a convenient macro to enforce error
// handling for functions that may fail (by returning !*ok).
//
// CAUTION: This macro appends extra statements after a call,
// thus it must never be used where only a single statement
// is correct (e.g. an if statement branch w/o braces)!

#define CHECK_OK  ok);   \
  if (!*ok) return NULL; \
  ((void)0
#define DUMMY )  // to make indentation work
#undef DUMMY

#define CHECK_FAILED  /**/);   \
  if (failed_) return NULL; \
  ((void)0
#define DUMMY )  // to make indentation work
#undef DUMMY

// ----------------------------------------------------------------------------
// Implementation of Parser

bool ParserTraits::IsEval(const AstRawString* identifier) const {
  return identifier == parser_->ast_value_factory()->eval_string();
}


bool ParserTraits::IsArguments(const AstRawString* identifier) const {
  return identifier == parser_->ast_value_factory()->arguments_string();
}


bool ParserTraits::IsEvalOrArguments(const AstRawString* identifier) const {
  return IsEval(identifier) || IsArguments(identifier);
}

bool ParserTraits::IsUndefined(const AstRawString* identifier) const {
  return identifier == parser_->ast_value_factory()->undefined_string();
}

bool ParserTraits::IsAwait(const AstRawString* identifier) const {
  return identifier == parser_->ast_value_factory()->await_string();
}

bool ParserTraits::IsPrototype(const AstRawString* identifier) const {
  return identifier == parser_->ast_value_factory()->prototype_string();
}


bool ParserTraits::IsConstructor(const AstRawString* identifier) const {
  return identifier == parser_->ast_value_factory()->constructor_string();
}


bool ParserTraits::IsThisProperty(Expression* expression) {
  DCHECK(expression != NULL);
  Property* property = expression->AsProperty();
  return property != NULL && property->obj()->IsVariableProxy() &&
         property->obj()->AsVariableProxy()->is_this();
}


bool ParserTraits::IsIdentifier(Expression* expression) {
  VariableProxy* operand = expression->AsVariableProxy();
  return operand != NULL && !operand->is_this();
}


void ParserTraits::PushPropertyName(FuncNameInferrer* fni,
                                    Expression* expression) {
  if (expression->IsPropertyName()) {
    fni->PushLiteralName(expression->AsLiteral()->AsRawPropertyName());
  } else {
    fni->PushLiteralName(
        parser_->ast_value_factory()->anonymous_function_string());
  }
}


void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
                                                           Expression* right) {
  DCHECK(left != NULL);
  if (left->IsProperty() && right->IsFunctionLiteral()) {
    right->AsFunctionLiteral()->set_pretenure();
  }
}


Expression* ParserTraits::MarkExpressionAsAssigned(Expression* expression) {
  VariableProxy* proxy =
      expression != NULL ? expression->AsVariableProxy() : NULL;
  if (proxy != NULL) proxy->set_is_assigned();
  return expression;
}


bool ParserTraits::ShortcutNumericLiteralBinaryExpression(
    Expression** x, Expression* y, Token::Value op, int pos,
    AstNodeFactory* factory) {
  if ((*x)->AsLiteral() && (*x)->AsLiteral()->raw_value()->IsNumber() &&
      y->AsLiteral() && y->AsLiteral()->raw_value()->IsNumber()) {
    double x_val = (*x)->AsLiteral()->raw_value()->AsNumber();
    double y_val = y->AsLiteral()->raw_value()->AsNumber();
    bool x_has_dot = (*x)->AsLiteral()->raw_value()->ContainsDot();
    bool y_has_dot = y->AsLiteral()->raw_value()->ContainsDot();
    bool has_dot = x_has_dot || y_has_dot;
    switch (op) {
      case Token::ADD:
        *x = factory->NewNumberLiteral(x_val + y_val, pos, has_dot);
        return true;
      case Token::SUB:
        *x = factory->NewNumberLiteral(x_val - y_val, pos, has_dot);
        return true;
      case Token::MUL:
        *x = factory->NewNumberLiteral(x_val * y_val, pos, has_dot);
        return true;
      case Token::DIV:
        *x = factory->NewNumberLiteral(x_val / y_val, pos, has_dot);
        return true;
      case Token::BIT_OR: {
        int value = DoubleToInt32(x_val) | DoubleToInt32(y_val);
        *x = factory->NewNumberLiteral(value, pos, has_dot);
        return true;
      }
      case Token::BIT_AND: {
        int value = DoubleToInt32(x_val) & DoubleToInt32(y_val);
        *x = factory->NewNumberLiteral(value, pos, has_dot);
        return true;
      }
      case Token::BIT_XOR: {
        int value = DoubleToInt32(x_val) ^ DoubleToInt32(y_val);
        *x = factory->NewNumberLiteral(value, pos, has_dot);
        return true;
      }
      case Token::SHL: {
        int value = DoubleToInt32(x_val) << (DoubleToInt32(y_val) & 0x1f);
        *x = factory->NewNumberLiteral(value, pos, has_dot);
        return true;
      }
      case Token::SHR: {
        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
        uint32_t value = DoubleToUint32(x_val) >> shift;
        *x = factory->NewNumberLiteral(value, pos, has_dot);
        return true;
      }
      case Token::SAR: {
        uint32_t shift = DoubleToInt32(y_val) & 0x1f;
        int value = ArithmeticShiftRight(DoubleToInt32(x_val), shift);
        *x = factory->NewNumberLiteral(value, pos, has_dot);
        return true;
      }
      case Token::EXP: {
        double value = Pow(x_val, y_val);
        int int_value = static_cast<int>(value);
        *x = factory->NewNumberLiteral(
            int_value == value && value != -0.0 ? int_value : value, pos,
            has_dot);
        return true;
      }
      default:
        break;
    }
  }
  return false;
}


Expression* ParserTraits::BuildUnaryExpression(Expression* expression,
                                               Token::Value op, int pos,
                                               AstNodeFactory* factory) {
  DCHECK(expression != NULL);
  if (expression->IsLiteral()) {
    const AstValue* literal = expression->AsLiteral()->raw_value();
    if (op == Token::NOT) {
      // Convert the literal to a boolean condition and negate it.
      bool condition = literal->BooleanValue();
      return factory->NewBooleanLiteral(!condition, pos);
    } else if (literal->IsNumber()) {
      // Compute some expressions involving only number literals.
      double value = literal->AsNumber();
      bool has_dot = literal->ContainsDot();
      switch (op) {
        case Token::ADD:
          return expression;
        case Token::SUB:
          return factory->NewNumberLiteral(-value, pos, has_dot);
        case Token::BIT_NOT:
          return factory->NewNumberLiteral(~DoubleToInt32(value), pos, has_dot);
        default:
          break;
      }
    }
  }
  // Desugar '+foo' => 'foo*1'
  if (op == Token::ADD) {
    return factory->NewBinaryOperation(
        Token::MUL, expression, factory->NewNumberLiteral(1, pos, true), pos);
  }
  // The same idea for '-foo' => 'foo*(-1)'.
  if (op == Token::SUB) {
    return factory->NewBinaryOperation(
        Token::MUL, expression, factory->NewNumberLiteral(-1, pos), pos);
  }
  // ...and one more time for '~foo' => 'foo^(~0)'.
  if (op == Token::BIT_NOT) {
    return factory->NewBinaryOperation(
        Token::BIT_XOR, expression, factory->NewNumberLiteral(~0, pos), pos);
  }
  return factory->NewUnaryOperation(op, expression, pos);
}

Expression* ParserTraits::BuildIteratorResult(Expression* value, bool done) {
  int pos = RelocInfo::kNoPosition;
  AstNodeFactory* factory = parser_->factory();
  Zone* zone = parser_->zone();

  if (value == nullptr) value = factory->NewUndefinedLiteral(pos);

  auto args = new (zone) ZoneList<Expression*>(2, zone);
  args->Add(value, zone);
  args->Add(factory->NewBooleanLiteral(done, pos), zone);

  return factory->NewCallRuntime(Runtime::kInlineCreateIterResultObject, args,
                                 pos);
}

Expression* ParserTraits::NewThrowReferenceError(
    MessageTemplate::Template message, int pos) {
  return NewThrowError(Runtime::kNewReferenceError, message,
                       parser_->ast_value_factory()->empty_string(), pos);
}


Expression* ParserTraits::NewThrowSyntaxError(MessageTemplate::Template message,
                                              const AstRawString* arg,
                                              int pos) {
  return NewThrowError(Runtime::kNewSyntaxError, message, arg, pos);
}


Expression* ParserTraits::NewThrowTypeError(MessageTemplate::Template message,
                                            const AstRawString* arg, int pos) {
  return NewThrowError(Runtime::kNewTypeError, message, arg, pos);
}


Expression* ParserTraits::NewThrowError(Runtime::FunctionId id,
                                        MessageTemplate::Template message,
                                        const AstRawString* arg, int pos) {
  Zone* zone = parser_->zone();
  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(2, zone);
  args->Add(parser_->factory()->NewSmiLiteral(message, pos), zone);
  args->Add(parser_->factory()->NewStringLiteral(arg, pos), zone);
  CallRuntime* call_constructor =
      parser_->factory()->NewCallRuntime(id, args, pos);
  return parser_->factory()->NewThrow(call_constructor, pos);
}


void ParserTraits::ReportMessageAt(Scanner::Location source_location,
                                   MessageTemplate::Template message,
                                   const char* arg, ParseErrorType error_type) {
  if (parser_->stack_overflow()) {
    // Suppress the error message (syntax error or such) in the presence of a
    // stack overflow. The isolate allows only one pending exception at at time
    // and we want to report the stack overflow later.
    return;
  }
  parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
                                                  source_location.end_pos,
                                                  message, arg, error_type);
}


void ParserTraits::ReportMessage(MessageTemplate::Template message,
                                 const char* arg, ParseErrorType error_type) {
  Scanner::Location source_location = parser_->scanner()->location();
  ReportMessageAt(source_location, message, arg, error_type);
}


void ParserTraits::ReportMessage(MessageTemplate::Template message,
                                 const AstRawString* arg,
                                 ParseErrorType error_type) {
  Scanner::Location source_location = parser_->scanner()->location();
  ReportMessageAt(source_location, message, arg, error_type);
}


void ParserTraits::ReportMessageAt(Scanner::Location source_location,
                                   MessageTemplate::Template message,
                                   const AstRawString* arg,
                                   ParseErrorType error_type) {
  if (parser_->stack_overflow()) {
    // Suppress the error message (syntax error or such) in the presence of a
    // stack overflow. The isolate allows only one pending exception at at time
    // and we want to report the stack overflow later.
    return;
  }
  parser_->pending_error_handler_.ReportMessageAt(source_location.beg_pos,
                                                  source_location.end_pos,
                                                  message, arg, error_type);
}


const AstRawString* ParserTraits::GetSymbol(Scanner* scanner) {
  const AstRawString* result =
      parser_->scanner()->CurrentSymbol(parser_->ast_value_factory());
  DCHECK(result != NULL);
  return result;
}


const AstRawString* ParserTraits::GetNumberAsSymbol(Scanner* scanner) {
  double double_value = parser_->scanner()->DoubleValue();
  char array[100];
  const char* string = DoubleToCString(double_value, ArrayVector(array));
  return parser_->ast_value_factory()->GetOneByteString(string);
}


const AstRawString* ParserTraits::GetNextSymbol(Scanner* scanner) {
  return parser_->scanner()->NextSymbol(parser_->ast_value_factory());
}


Expression* ParserTraits::ThisExpression(Scope* scope, AstNodeFactory* factory,
                                         int pos) {
  return scope->NewUnresolved(factory,
                              parser_->ast_value_factory()->this_string(),
                              Variable::THIS, pos, pos + 4);
}


Expression* ParserTraits::SuperPropertyReference(Scope* scope,
                                                 AstNodeFactory* factory,
                                                 int pos) {
  // this_function[home_object_symbol]
  VariableProxy* this_function_proxy = scope->NewUnresolved(
      factory, parser_->ast_value_factory()->this_function_string(),
      Variable::NORMAL, pos);
  Expression* home_object_symbol_literal =
      factory->NewSymbolLiteral("home_object_symbol", RelocInfo::kNoPosition);
  Expression* home_object = factory->NewProperty(
      this_function_proxy, home_object_symbol_literal, pos);
  return factory->NewSuperPropertyReference(
      ThisExpression(scope, factory, pos)->AsVariableProxy(), home_object, pos);
}


Expression* ParserTraits::SuperCallReference(Scope* scope,
                                             AstNodeFactory* factory, int pos) {
  VariableProxy* new_target_proxy = scope->NewUnresolved(
      factory, parser_->ast_value_factory()->new_target_string(),
      Variable::NORMAL, pos);
  VariableProxy* this_function_proxy = scope->NewUnresolved(
      factory, parser_->ast_value_factory()->this_function_string(),
      Variable::NORMAL, pos);
  return factory->NewSuperCallReference(
      ThisExpression(scope, factory, pos)->AsVariableProxy(), new_target_proxy,
      this_function_proxy, pos);
}


Expression* ParserTraits::NewTargetExpression(Scope* scope,
                                              AstNodeFactory* factory,
                                              int pos) {
  static const int kNewTargetStringLength = 10;
  auto proxy = scope->NewUnresolved(
      factory, parser_->ast_value_factory()->new_target_string(),
      Variable::NORMAL, pos, pos + kNewTargetStringLength);
  proxy->set_is_new_target();
  return proxy;
}


Expression* ParserTraits::FunctionSentExpression(Scope* scope,
                                                 AstNodeFactory* factory,
                                                 int pos) {
  // We desugar function.sent into %_GeneratorGetInputOrDebugPos(generator).
  Zone* zone = parser_->zone();
  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(1, zone);
  VariableProxy* generator = factory->NewVariableProxy(
      parser_->function_state_->generator_object_variable());
  args->Add(generator, zone);
  return factory->NewCallRuntime(Runtime::kInlineGeneratorGetInputOrDebugPos,
                                 args, pos);
}


Literal* ParserTraits::ExpressionFromLiteral(Token::Value token, int pos,
                                             Scanner* scanner,
                                             AstNodeFactory* factory) {
  switch (token) {
    case Token::NULL_LITERAL:
      return factory->NewNullLiteral(pos);
    case Token::TRUE_LITERAL:
      return factory->NewBooleanLiteral(true, pos);
    case Token::FALSE_LITERAL:
      return factory->NewBooleanLiteral(false, pos);
    case Token::SMI: {
      int value = scanner->smi_value();
      return factory->NewSmiLiteral(value, pos);
    }
    case Token::NUMBER: {
      bool has_dot = scanner->ContainsDot();
      double value = scanner->DoubleValue();
      return factory->NewNumberLiteral(value, pos, has_dot);
    }
    default:
      DCHECK(false);
  }
  return NULL;
}


Expression* ParserTraits::ExpressionFromIdentifier(const AstRawString* name,
                                                   int start_position,
                                                   int end_position,
                                                   Scope* scope,
                                                   AstNodeFactory* factory) {
  if (parser_->fni_ != NULL) parser_->fni_->PushVariableName(name);
  return scope->NewUnresolved(factory, name, Variable::NORMAL, start_position,
                              end_position);
}


Expression* ParserTraits::ExpressionFromString(int pos, Scanner* scanner,
                                               AstNodeFactory* factory) {
  const AstRawString* symbol = GetSymbol(scanner);
  if (parser_->fni_ != NULL) parser_->fni_->PushLiteralName(symbol);
  return factory->NewStringLiteral(symbol, pos);
}


Expression* ParserTraits::GetIterator(Expression* iterable,
                                      AstNodeFactory* factory, int pos) {
  Expression* iterator_symbol_literal =
      factory->NewSymbolLiteral("iterator_symbol", RelocInfo::kNoPosition);
  Expression* prop =
      factory->NewProperty(iterable, iterator_symbol_literal, pos);
  Zone* zone = parser_->zone();
  ZoneList<Expression*>* args = new (zone) ZoneList<Expression*>(0, zone);
  return factory->NewCall(prop, args, pos);
}


Literal* ParserTraits::GetLiteralTheHole(int position,
                                         AstNodeFactory* factory) {
  return factory->NewTheHoleLiteral(RelocInfo::kNoPosition);
}


Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
  return parser_->ParseV8Intrinsic(ok);
}


FunctionLiteral* ParserTraits::ParseFunctionLiteral(
    const AstRawString* name, Scanner::Location function_name_location,
    FunctionNameValidity function_name_validity, FunctionKind kind,
    int function_token_position, FunctionLiteral::FunctionType type,
    LanguageMode language_mode, bool* ok) {
  return parser_->ParseFunctionLiteral(
      name, function_name_location, function_name_validity, kind,
      function_token_position, type, language_mode, ok);
}

ClassLiteral* ParserTraits::ParseClassLiteral(
    Type::ExpressionClassifier* classifier, const AstRawString* name,
    Scanner::Location class_name_location, bool name_is_strict_reserved,
    int pos, bool* ok) {
  return parser_->ParseClassLiteral(classifier, name, class_name_location,
                                    name_is_strict_reserved, pos, ok);
}

void ParserTraits::MarkTailPosition(Expression* expression) {
  expression->MarkTail();
}

void ParserTraits::MarkCollectedTailCallExpressions() {
  parser_->MarkCollectedTailCallExpressions();
}

Parser::Parser(ParseInfo* info)
    : ParserBase<ParserTraits>(info->zone(), &scanner_, info->stack_limit(),
                               info->extension(), info->ast_value_factory(),
                               NULL, this),
      scanner_(info->unicode_cache()),
      reusable_preparser_(NULL),
      original_scope_(NULL),
      target_stack_(NULL),
      compile_options_(info->compile_options()),
      cached_parse_data_(NULL),
      total_preparse_skipped_(0),
      pre_parse_timer_(NULL),
      parsing_on_main_thread_(true) {
  // Even though we were passed ParseInfo, we should not store it in
  // Parser - this makes sure that Isolate is not accidentally accessed via
  // ParseInfo during background parsing.
  DCHECK(!info->script().is_null() || info->source_stream() != NULL);
  set_allow_lazy(info->allow_lazy_parsing());
  set_allow_natives(FLAG_allow_natives_syntax || info->is_native());
  set_allow_tailcalls(FLAG_harmony_tailcalls && !info->is_native() &&
                      info->isolate()->is_tail_call_elimination_enabled());
  set_allow_harmony_do_expressions(FLAG_harmony_do_expressions);
  set_allow_harmony_for_in(FLAG_harmony_for_in);
  set_allow_harmony_function_sent(FLAG_harmony_function_sent);
  set_allow_harmony_restrictive_declarations(
      FLAG_harmony_restrictive_declarations);
  set_allow_harmony_exponentiation_operator(
      FLAG_harmony_exponentiation_operator);
  set_allow_harmony_async_await(FLAG_harmony_async_await);
  set_allow_harmony_restrictive_generators(FLAG_harmony_restrictive_generators);
  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
       ++feature) {
    use_counts_[feature] = 0;
  }
  if (info->ast_value_factory() == NULL) {
    // info takes ownership of AstValueFactory.
    info->set_ast_value_factory(new AstValueFactory(zone(), info->hash_seed()));
    info->set_ast_value_factory_owned();
    ast_value_factory_ = info->ast_value_factory();
  }
}


FunctionLiteral* Parser::ParseProgram(Isolate* isolate, ParseInfo* info) {
  // TODO(bmeurer): We temporarily need to pass allow_nesting = true here,
  // see comment for HistogramTimerScope class.

  // It's OK to use the Isolate & counters here, since this function is only
  // called in the main thread.
  DCHECK(parsing_on_main_thread_);

  HistogramTimerScope timer_scope(isolate->counters()->parse(), true);
  RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::Parse);
  TRACE_EVENT0("v8", "V8.Parse");
  Handle<String> source(String::cast(info->script()->source()));
  isolate->counters()->total_parse_size()->Increment(source->length());
  base::ElapsedTimer timer;
  if (FLAG_trace_parse) {
    timer.Start();
  }
  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());

  // Initialize parser state.
  CompleteParserRecorder recorder;

  if (produce_cached_parse_data()) {
    log_ = &recorder;
  } else if (consume_cached_parse_data()) {
    cached_parse_data_->Initialize();
  }

  source = String::Flatten(source);
  FunctionLiteral* result;

  if (source->IsExternalTwoByteString()) {
    // Notice that the stream is destroyed at the end of the branch block.
    // The last line of the blocks can't be moved outside, even though they're
    // identical calls.
    ExternalTwoByteStringUtf16CharacterStream stream(
        Handle<ExternalTwoByteString>::cast(source), 0, source->length());
    scanner_.Initialize(&stream);
    result = DoParseProgram(info);
  } else {
    GenericStringUtf16CharacterStream stream(source, 0, source->length());
    scanner_.Initialize(&stream);
    result = DoParseProgram(info);
  }
  if (result != NULL) {
    DCHECK_EQ(scanner_.peek_location().beg_pos, source->length());
  }
  HandleSourceURLComments(isolate, info->script());

  if (FLAG_trace_parse && result != NULL) {
    double ms = timer.Elapsed().InMillisecondsF();
    if (info->is_eval()) {
      PrintF("[parsing eval");
    } else if (info->script()->name()->IsString()) {
      String* name = String::cast(info->script()->name());
      base::SmartArrayPointer<char> name_chars = name->ToCString();
      PrintF("[parsing script: %s", name_chars.get());
    } else {
      PrintF("[parsing script");
    }
    PrintF(" - took %0.3f ms]\n", ms);
  }
  if (produce_cached_parse_data()) {
    if (result != NULL) *info->cached_data() = recorder.GetScriptData();
    log_ = NULL;
  }
  return result;
}


FunctionLiteral* Parser::DoParseProgram(ParseInfo* info) {
  // Note that this function can be called from the main thread or from a
  // background thread. We should not access anything Isolate / heap dependent
  // via ParseInfo, and also not pass it forward.
  DCHECK(scope_ == NULL);
  DCHECK(target_stack_ == NULL);

  Mode parsing_mode = FLAG_lazy && allow_lazy() ? PARSE_LAZILY : PARSE_EAGERLY;
  if (allow_natives() || extension_ != NULL) parsing_mode = PARSE_EAGERLY;

  FunctionLiteral* result = NULL;
  {
    // TODO(wingo): Add an outer SCRIPT_SCOPE corresponding to the native
    // context, which will have the "this" binding for script scopes.
    Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
    info->set_script_scope(scope);
    if (!info->context().is_null() && !info->context()->IsNativeContext()) {
      scope = Scope::DeserializeScopeChain(info->isolate(), zone(),
                                           *info->context(), scope);
      // The Scope is backed up by ScopeInfo (which is in the V8 heap); this
      // means the Parser cannot operate independent of the V8 heap. Tell the
      // string table to internalize strings and values right after they're
      // created. This kind of parsing can only be done in the main thread.
      DCHECK(parsing_on_main_thread_);
      ast_value_factory()->Internalize(info->isolate());
    }
    original_scope_ = scope;
    if (info->is_eval()) {
      if (!scope->is_script_scope() || is_strict(info->language_mode())) {
        parsing_mode = PARSE_EAGERLY;
      }
      scope = NewScope(scope, EVAL_SCOPE);
    } else if (info->is_module()) {
      scope = NewScope(scope, MODULE_SCOPE);
    }

    scope->set_start_position(0);

    // Enter 'scope' with the given parsing mode.
    ParsingModeScope parsing_mode_scope(this, parsing_mode);
    AstNodeFactory function_factory(ast_value_factory());
    FunctionState function_state(&function_state_, &scope_, scope,
                                 kNormalFunction, &function_factory);

    ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
    bool ok = true;
    int beg_pos = scanner()->location().beg_pos;
    parsing_module_ = info->is_module();
    if (parsing_module_) {
      ParseModuleItemList(body, &ok);
    } else {
      // Don't count the mode in the use counters--give the program a chance
      // to enable script-wide strict mode below.
      scope_->SetLanguageMode(info->language_mode());
      ParseStatementList(body, Token::EOS, &ok);
    }

    // The parser will peek but not consume EOS.  Our scope logically goes all
    // the way to the EOS, though.
    scope->set_end_position(scanner()->peek_location().beg_pos);

    if (ok && is_strict(language_mode())) {
      CheckStrictOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
      CheckDecimalLiteralWithLeadingZero(use_counts_, beg_pos,
                                         scanner()->location().end_pos);
    }
    if (ok && is_sloppy(language_mode())) {
      // TODO(littledan): Function bindings on the global object that modify
      // pre-existing bindings should be made writable, enumerable and
      // nonconfigurable if possible, whereas this code will leave attributes
      // unchanged if the property already exists.
      InsertSloppyBlockFunctionVarBindings(scope, &ok);
    }
    if (ok) {
      CheckConflictingVarDeclarations(scope_, &ok);
    }

    if (ok && info->parse_restriction() == ONLY_SINGLE_FUNCTION_LITERAL) {
      if (body->length() != 1 ||
          !body->at(0)->IsExpressionStatement() ||
          !body->at(0)->AsExpressionStatement()->
              expression()->IsFunctionLiteral()) {
        ReportMessage(MessageTemplate::kSingleFunctionLiteral);
        ok = false;
      }
    }

    if (ok) {
      ParserTraits::RewriteDestructuringAssignments();
      result = factory()->NewScriptOrEvalFunctionLiteral(
          scope_, body, function_state.materialized_literal_count(),
          function_state.expected_property_count());
    }
  }

  // Make sure the target stack is empty.
  DCHECK(target_stack_ == NULL);

  return result;
}


FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info) {
  // It's OK to use the Isolate & counters here, since this function is only
  // called in the main thread.
  DCHECK(parsing_on_main_thread_);
  RuntimeCallTimerScope runtime_timer(isolate, &RuntimeCallStats::ParseLazy);
  HistogramTimerScope timer_scope(isolate->counters()->parse_lazy());
  TRACE_EVENT0("v8", "V8.ParseLazy");
  Handle<String> source(String::cast(info->script()->source()));
  isolate->counters()->total_parse_size()->Increment(source->length());
  base::ElapsedTimer timer;
  if (FLAG_trace_parse) {
    timer.Start();
  }
  Handle<SharedFunctionInfo> shared_info = info->shared_info();

  // Initialize parser state.
  source = String::Flatten(source);
  FunctionLiteral* result;
  if (source->IsExternalTwoByteString()) {
    ExternalTwoByteStringUtf16CharacterStream stream(
        Handle<ExternalTwoByteString>::cast(source),
        shared_info->start_position(),
        shared_info->end_position());
    result = ParseLazy(isolate, info, &stream);
  } else {
    GenericStringUtf16CharacterStream stream(source,
                                             shared_info->start_position(),
                                             shared_info->end_position());
    result = ParseLazy(isolate, info, &stream);
  }

  if (FLAG_trace_parse && result != NULL) {
    double ms = timer.Elapsed().InMillisecondsF();
    base::SmartArrayPointer<char> name_chars =
        result->debug_name()->ToCString();
    PrintF("[parsing function: %s - took %0.3f ms]\n", name_chars.get(), ms);
  }
  return result;
}

static FunctionLiteral::FunctionType ComputeFunctionType(
    Handle<SharedFunctionInfo> shared_info) {
  if (shared_info->is_declaration()) {
    return FunctionLiteral::kDeclaration;
  } else if (shared_info->is_named_expression()) {
    return FunctionLiteral::kNamedExpression;
  } else if (IsConciseMethod(shared_info->kind()) ||
             IsAccessorFunction(shared_info->kind())) {
    return FunctionLiteral::kAccessorOrMethod;
  }
  return FunctionLiteral::kAnonymousExpression;
}

FunctionLiteral* Parser::ParseLazy(Isolate* isolate, ParseInfo* info,
                                   Utf16CharacterStream* source) {
  Handle<SharedFunctionInfo> shared_info = info->shared_info();
  scanner_.Initialize(source);
  DCHECK(scope_ == NULL);
  DCHECK(target_stack_ == NULL);

  Handle<String> name(String::cast(shared_info->name()));
  DCHECK(ast_value_factory());
  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());
  const AstRawString* raw_name = ast_value_factory()->GetString(name);
  fni_->PushEnclosingName(raw_name);

  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);

  // Place holder for the result.
  FunctionLiteral* result = NULL;

  {
    // Parse the function literal.
    Scope* scope = NewScope(scope_, SCRIPT_SCOPE);
    info->set_script_scope(scope);
    if (!info->context().is_null()) {
      // Ok to use Isolate here, since lazy function parsing is only done in the
      // main thread.
      DCHECK(parsing_on_main_thread_);
      scope = Scope::DeserializeScopeChain(isolate, zone(), *info->context(),
                                           scope);
    }
    original_scope_ = scope;
    AstNodeFactory function_factory(ast_value_factory());
    FunctionState function_state(&function_state_, &scope_, scope,
                                 shared_info->kind(), &function_factory);
    DCHECK(is_sloppy(scope->language_mode()) ||
           is_strict(info->language_mode()));
    DCHECK(info->language_mode() == shared_info->language_mode());
    FunctionLiteral::FunctionType function_type =
        ComputeFunctionType(shared_info);
    bool ok = true;

    if (shared_info->is_arrow()) {
      bool is_async = allow_harmony_async_await() && shared_info->is_async();
      if (is_async) {
        DCHECK(!scanner()->HasAnyLineTerminatorAfterNext());
        Consume(Token::ASYNC);
        DCHECK(peek_any_identifier() || peek() == Token::LPAREN);
      }

      // TODO(adamk): We should construct this scope from the ScopeInfo.
      Scope* scope =
          NewScope(scope_, FUNCTION_SCOPE, FunctionKind::kArrowFunction);

      // These two bits only need to be explicitly set because we're
      // not passing the ScopeInfo to the Scope constructor.
      // TODO(adamk): Remove these calls once the above NewScope call
      // passes the ScopeInfo.
      if (shared_info->scope_info()->CallsEval()) {
        scope->RecordEvalCall();
      }
      SetLanguageMode(scope, shared_info->language_mode());

      scope->set_start_position(shared_info->start_position());
      ExpressionClassifier formals_classifier(this);
      ParserFormalParameters formals(scope);
      Checkpoint checkpoint(this);
      {
        // Parsing patterns as variable reference expression creates
        // NewUnresolved references in current scope. Entrer arrow function
        // scope for formal parameter parsing.
        BlockState block_state(&scope_, scope);
        if (Check(Token::LPAREN)) {
          // '(' StrictFormalParameters ')'
          ParseFormalParameterList(&formals, &formals_classifier, &ok);
          if (ok) ok = Check(Token::RPAREN);
        } else {
          // BindingIdentifier
          ParseFormalParameter(&formals, &formals_classifier, &ok);
          if (ok) {
            DeclareFormalParameter(formals.scope, formals.at(0),
                                   &formals_classifier);
          }
        }
      }

      if (ok) {
        checkpoint.Restore(&formals.materialized_literals_count);
        // Pass `accept_IN=true` to ParseArrowFunctionLiteral --- This should
        // not be observable, or else the preparser would have failed.
        Expression* expression = ParseArrowFunctionLiteral(
            true, formals, is_async, formals_classifier, &ok);
        if (ok) {
          // Scanning must end at the same position that was recorded
          // previously. If not, parsing has been interrupted due to a stack
          // overflow, at which point the partially parsed arrow function
          // concise body happens to be a valid expression. This is a problem
          // only for arrow functions with single expression bodies, since there
          // is no end token such as "}" for normal functions.
          if (scanner()->location().end_pos == shared_info->end_position()) {
            // The pre-parser saw an arrow function here, so the full parser
            // must produce a FunctionLiteral.
            DCHECK(expression->IsFunctionLiteral());
            result = expression->AsFunctionLiteral();
          } else {
            ok = false;
          }
        }
      }
    } else if (shared_info->is_default_constructor()) {
      result = DefaultConstructor(
          raw_name, IsSubclassConstructor(shared_info->kind()), scope,
          shared_info->start_position(), shared_info->end_position(),
          shared_info->language_mode());
    } else {
      result = ParseFunctionLiteral(raw_name, Scanner::Location::invalid(),
                                    kSkipFunctionNameCheck, shared_info->kind(),
                                    RelocInfo::kNoPosition, function_type,
                                    shared_info->language_mode(), &ok);
    }
    // Make sure the results agree.
    DCHECK(ok == (result != NULL));
  }

  // Make sure the target stack is empty.
  DCHECK(target_stack_ == NULL);

  if (result != NULL) {
    Handle<String> inferred_name(shared_info->inferred_name());
    result->set_inferred_name(inferred_name);
  }
  return result;
}


void* Parser::ParseStatementList(ZoneList<Statement*>* body, int end_token,
                                 bool* ok) {
  // StatementList ::
  //   (StatementListItem)* <end_token>

  // Allocate a target stack to use for this set of source
  // elements. This way, all scripts and functions get their own
  // target stack thus avoiding illegal breaks and continues across
  // functions.
  TargetScope scope(&this->target_stack_);

  DCHECK(body != NULL);
  bool directive_prologue = true;     // Parsing directive prologue.

  while (peek() != end_token) {
    if (directive_prologue && peek() != Token::STRING) {
      directive_prologue = false;
    }

    Scanner::Location token_loc = scanner()->peek_location();
    Statement* stat = ParseStatementListItem(CHECK_OK);
    if (stat == NULL || stat->IsEmpty()) {
      directive_prologue = false;   // End of directive prologue.
      continue;
    }

    if (directive_prologue) {
      // A shot at a directive.
      ExpressionStatement* e_stat;
      Literal* literal;
      // Still processing directive prologue?
      if ((e_stat = stat->AsExpressionStatement()) != NULL &&
          (literal = e_stat->expression()->AsLiteral()) != NULL &&
          literal->raw_value()->IsString()) {
        // Check "use strict" directive (ES5 14.1), "use asm" directive.
        bool use_strict_found =
            literal->raw_value()->AsString() ==
                ast_value_factory()->use_strict_string() &&
            token_loc.end_pos - token_loc.beg_pos ==
                ast_value_factory()->use_strict_string()->length() + 2;
        if (use_strict_found) {
          if (is_sloppy(scope_->language_mode())) {
            RaiseLanguageMode(STRICT);
          }

          if (!scope_->HasSimpleParameters()) {
            // TC39 deemed "use strict" directives to be an error when occurring
            // in the body of a function with non-simple parameter list, on
            // 29/7/2015. https://goo.gl/ueA7Ln
            const AstRawString* string = literal->raw_value()->AsString();
            ParserTraits::ReportMessageAt(
                token_loc, MessageTemplate::kIllegalLanguageModeDirective,
                string);
            *ok = false;
            return nullptr;
          }
          // Because declarations in strict eval code don't leak into the scope
          // of the eval call, it is likely that functions declared in strict
          // eval code will be used within the eval code, so lazy parsing is
          // probably not a win.
          if (scope_->is_eval_scope()) mode_ = PARSE_EAGERLY;
        } else if (literal->raw_value()->AsString() ==
                       ast_value_factory()->use_asm_string() &&
                   token_loc.end_pos - token_loc.beg_pos ==
                       ast_value_factory()->use_asm_string()->length() + 2) {
          // Store the usage count; The actual use counter on the isolate is
          // incremented after parsing is done.
          ++use_counts_[v8::Isolate::kUseAsm];
          scope_->SetAsmModule();
        } else {
          // Should not change mode, but will increment UseCounter
          // if appropriate. Ditto usages below.
          RaiseLanguageMode(SLOPPY);
        }
      } else {
        // End of the directive prologue.
        directive_prologue = false;
        RaiseLanguageMode(SLOPPY);
      }
    } else {
      RaiseLanguageMode(SLOPPY);
    }

    body->Add(stat, zone());
  }

  return 0;
}


Statement* Parser::ParseStatementListItem(bool* ok) {
  // (Ecma 262 6th Edition, 13.1):
  // StatementListItem:
  //    Statement
  //    Declaration
  const Token::Value peeked = peek();
  switch (peeked) {
    case Token::FUNCTION:
      return ParseHoistableDeclaration(NULL, ok);
    case Token::CLASS:
      Consume(Token::CLASS);
      return ParseClassDeclaration(NULL, ok);
    case Token::CONST:
      return ParseVariableStatement(kStatementListItem, NULL, ok);
    case Token::VAR:
      return ParseVariableStatement(kStatementListItem, NULL, ok);
    case Token::LET:
      if (IsNextLetKeyword()) {
        return ParseVariableStatement(kStatementListItem, NULL, ok);
      }
      break;
    case Token::ASYNC:
      if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
          !scanner()->HasAnyLineTerminatorAfterNext()) {
        Consume(Token::ASYNC);
        return ParseAsyncFunctionDeclaration(NULL, ok);
      }
    /* falls through */
    default:
      break;
  }
  return ParseStatement(NULL, kAllowLabelledFunctionStatement, ok);
}


Statement* Parser::ParseModuleItem(bool* ok) {
  // (Ecma 262 6th Edition, 15.2):
  // ModuleItem :
  //    ImportDeclaration
  //    ExportDeclaration
  //    StatementListItem

  switch (peek()) {
    case Token::IMPORT:
      return ParseImportDeclaration(ok);
    case Token::EXPORT:
      return ParseExportDeclaration(ok);
    default:
      return ParseStatementListItem(ok);
  }
}


void* Parser::ParseModuleItemList(ZoneList<Statement*>* body, bool* ok) {
  // (Ecma 262 6th Edition, 15.2):
  // Module :
  //    ModuleBody?
  //
  // ModuleBody :
  //    ModuleItem*

  DCHECK(scope_->is_module_scope());

  while (peek() != Token::EOS) {
    Statement* stat = ParseModuleItem(CHECK_OK);
    if (stat && !stat->IsEmpty()) {
      body->Add(stat, zone());
    }
  }

  // Check that all exports are bound.
  ModuleDescriptor* descriptor = scope_->module();
  for (ModuleDescriptor::Iterator it = descriptor->iterator(); !it.done();
       it.Advance()) {
    if (scope_->LookupLocal(it.local_name()) == NULL) {
      // TODO(adamk): Pass both local_name and export_name once ParserTraits
      // supports multiple arg error messages.
      // Also try to report this at a better location.
      ParserTraits::ReportMessage(MessageTemplate::kModuleExportUndefined,
                                  it.local_name());
      *ok = false;
      return NULL;
    }
  }

  return NULL;
}


const AstRawString* Parser::ParseModuleSpecifier(bool* ok) {
  // ModuleSpecifier :
  //    StringLiteral

  Expect(Token::STRING, CHECK_OK);
  return GetSymbol(scanner());
}


void* Parser::ParseExportClause(ZoneList<const AstRawString*>* export_names,
                                ZoneList<Scanner::Location>* export_locations,
                                ZoneList<const AstRawString*>* local_names,
                                Scanner::Location* reserved_loc, bool* ok) {
  // ExportClause :
  //   '{' '}'
  //   '{' ExportsList '}'
  //   '{' ExportsList ',' '}'
  //
  // ExportsList :
  //   ExportSpecifier
  //   ExportsList ',' ExportSpecifier
  //
  // ExportSpecifier :
  //   IdentifierName
  //   IdentifierName 'as' IdentifierName

  Expect(Token::LBRACE, CHECK_OK);

  Token::Value name_tok;
  while ((name_tok = peek()) != Token::RBRACE) {
    // Keep track of the first reserved word encountered in case our
    // caller needs to report an error.
    if (!reserved_loc->IsValid() &&
        !Token::IsIdentifier(name_tok, STRICT, false, parsing_module_)) {
      *reserved_loc = scanner()->location();
    }
    const AstRawString* local_name = ParseIdentifierName(CHECK_OK);
    const AstRawString* export_name = NULL;
    if (CheckContextualKeyword(CStrVector("as"))) {
      export_name = ParseIdentifierName(CHECK_OK);
    }
    if (export_name == NULL) {
      export_name = local_name;
    }
    export_names->Add(export_name, zone());
    local_names->Add(local_name, zone());
    export_locations->Add(scanner()->location(), zone());
    if (peek() == Token::RBRACE) break;
    Expect(Token::COMMA, CHECK_OK);
  }

  Expect(Token::RBRACE, CHECK_OK);

  return 0;
}


ZoneList<ImportDeclaration*>* Parser::ParseNamedImports(int pos, bool* ok) {
  // NamedImports :
  //   '{' '}'
  //   '{' ImportsList '}'
  //   '{' ImportsList ',' '}'
  //
  // ImportsList :
  //   ImportSpecifier
  //   ImportsList ',' ImportSpecifier
  //
  // ImportSpecifier :
  //   BindingIdentifier
  //   IdentifierName 'as' BindingIdentifier

  Expect(Token::LBRACE, CHECK_OK);

  ZoneList<ImportDeclaration*>* result =
      new (zone()) ZoneList<ImportDeclaration*>(1, zone());
  while (peek() != Token::RBRACE) {
    const AstRawString* import_name = ParseIdentifierName(CHECK_OK);
    const AstRawString* local_name = import_name;
    // In the presence of 'as', the left-side of the 'as' can
    // be any IdentifierName. But without 'as', it must be a valid
    // BindingIdentifier.
    if (CheckContextualKeyword(CStrVector("as"))) {
      local_name = ParseIdentifierName(CHECK_OK);
    }
    if (!Token::IsIdentifier(scanner()->current_token(), STRICT, false,
                             parsing_module_)) {
      *ok = false;
      ReportMessage(MessageTemplate::kUnexpectedReserved);
      return NULL;
    } else if (IsEvalOrArguments(local_name)) {
      *ok = false;
      ReportMessage(MessageTemplate::kStrictEvalArguments);
      return NULL;
    }
    VariableProxy* proxy = NewUnresolved(local_name, CONST);
    ImportDeclaration* declaration =
        factory()->NewImportDeclaration(proxy, import_name, NULL, scope_, pos);
    Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
    result->Add(declaration, zone());
    if (peek() == Token::RBRACE) break;
    Expect(Token::COMMA, CHECK_OK);
  }

  Expect(Token::RBRACE, CHECK_OK);

  return result;
}


Statement* Parser::ParseImportDeclaration(bool* ok) {
  // ImportDeclaration :
  //   'import' ImportClause 'from' ModuleSpecifier ';'
  //   'import' ModuleSpecifier ';'
  //
  // ImportClause :
  //   NameSpaceImport
  //   NamedImports
  //   ImportedDefaultBinding
  //   ImportedDefaultBinding ',' NameSpaceImport
  //   ImportedDefaultBinding ',' NamedImports
  //
  // NameSpaceImport :
  //   '*' 'as' ImportedBinding

  int pos = peek_position();
  Expect(Token::IMPORT, CHECK_OK);

  Token::Value tok = peek();

  // 'import' ModuleSpecifier ';'
  if (tok == Token::STRING) {
    const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
    scope_->module()->AddModuleRequest(module_specifier, zone());
    ExpectSemicolon(CHECK_OK);
    return factory()->NewEmptyStatement(pos);
  }

  // Parse ImportedDefaultBinding if present.
  ImportDeclaration* import_default_declaration = NULL;
  if (tok != Token::MUL && tok != Token::LBRACE) {
    const AstRawString* local_name =
        ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
    VariableProxy* proxy = NewUnresolved(local_name, CONST);
    import_default_declaration = factory()->NewImportDeclaration(
        proxy, ast_value_factory()->default_string(), NULL, scope_, pos);
    Declare(import_default_declaration, DeclarationDescriptor::NORMAL, true,
            CHECK_OK);
  }

  const AstRawString* module_instance_binding = NULL;
  ZoneList<ImportDeclaration*>* named_declarations = NULL;
  if (import_default_declaration == NULL || Check(Token::COMMA)) {
    switch (peek()) {
      case Token::MUL: {
        Consume(Token::MUL);
        ExpectContextualKeyword(CStrVector("as"), CHECK_OK);
        module_instance_binding =
            ParseIdentifier(kDontAllowRestrictedIdentifiers, CHECK_OK);
        // TODO(ES6): Add an appropriate declaration.
        break;
      }

      case Token::LBRACE:
        named_declarations = ParseNamedImports(pos, CHECK_OK);
        break;

      default:
        *ok = false;
        ReportUnexpectedToken(scanner()->current_token());
        return NULL;
    }
  }

  ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
  const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
  scope_->module()->AddModuleRequest(module_specifier, zone());

  if (module_instance_binding != NULL) {
    // TODO(ES6): Set the module specifier for the module namespace binding.
  }

  if (import_default_declaration != NULL) {
    import_default_declaration->set_module_specifier(module_specifier);
  }

  if (named_declarations != NULL) {
    for (int i = 0; i < named_declarations->length(); ++i) {
      named_declarations->at(i)->set_module_specifier(module_specifier);
    }
  }

  ExpectSemicolon(CHECK_OK);
  return factory()->NewEmptyStatement(pos);
}


Statement* Parser::ParseExportDefault(bool* ok) {
  //  Supports the following productions, starting after the 'default' token:
  //    'export' 'default' FunctionDeclaration
  //    'export' 'default' ClassDeclaration
  //    'export' 'default' AssignmentExpression[In] ';'

  Expect(Token::DEFAULT, CHECK_OK);
  Scanner::Location default_loc = scanner()->location();

  const AstRawString* default_string = ast_value_factory()->default_string();
  ZoneList<const AstRawString*> names(1, zone());
  Statement* result = nullptr;
  Expression* default_export = nullptr;
  switch (peek()) {
    case Token::FUNCTION: {
      Consume(Token::FUNCTION);
      int pos = position();
      bool is_generator = Check(Token::MUL);
      if (peek() == Token::LPAREN) {
        // FunctionDeclaration[+Default] ::
        //   'function' '(' FormalParameters ')' '{' FunctionBody '}'
        //
        // GeneratorDeclaration[+Default] ::
        //   'function' '*' '(' FormalParameters ')' '{' FunctionBody '}'
        default_export = ParseFunctionLiteral(
            default_string, Scanner::Location::invalid(),
            kSkipFunctionNameCheck,
            is_generator ? FunctionKind::kGeneratorFunction
                         : FunctionKind::kNormalFunction,
            pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
        result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
      } else {
        result = ParseHoistableDeclaration(
            pos, is_generator ? ParseFunctionFlags::kIsGenerator
                              : ParseFunctionFlags::kIsNormal,
            &names, CHECK_OK);
      }
      break;
    }

    case Token::CLASS:
      Consume(Token::CLASS);
      if (peek() == Token::EXTENDS || peek() == Token::LBRACE) {
        // ClassDeclaration[+Default] ::
        //   'class' ('extends' LeftHandExpression)? '{' ClassBody '}'
        default_export = ParseClassLiteral(nullptr, default_string,
                                           Scanner::Location::invalid(), false,
                                           position(), CHECK_OK);
        result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
      } else {
        result = ParseClassDeclaration(&names, CHECK_OK);
      }
      break;

    case Token::ASYNC:
      if (allow_harmony_async_await() && PeekAhead() == Token::FUNCTION &&
          !scanner()->HasAnyLineTerminatorAfterNext()) {
        Consume(Token::ASYNC);
        Consume(Token::FUNCTION);
        int pos = position();
        if (peek() == Token::LPAREN) {
          // AsyncFunctionDeclaration[+Default] ::
          //   async [no LineTerminator here] function ( FormalParameters ) {
          //      AsyncFunctionBody
          //   }
          default_export = ParseFunctionLiteral(
              default_string, Scanner::Location::invalid(),
              kSkipFunctionNameCheck, FunctionKind::kAsyncFunction, pos,
              FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);
          result = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
        } else {
          result = ParseHoistableDeclaration(pos, ParseFunctionFlags::kIsAsync,
                                             &names, CHECK_OK);
        }
        break;
      }
    /* falls through */

    default: {
      int pos = peek_position();
      ExpressionClassifier classifier(this);
      Expression* expr = ParseAssignmentExpression(true, &classifier, CHECK_OK);
      RewriteNonPattern(&classifier, CHECK_OK);

      ExpectSemicolon(CHECK_OK);
      result = factory()->NewExpressionStatement(expr, pos);
      break;
    }
  }

  DCHECK_LE(names.length(), 1);
  if (names.length() == 1) {
    scope_->module()->AddLocalExport(default_string, names.first(), zone(), ok);
    if (!*ok) {
      ParserTraits::ReportMessageAt(
          default_loc, MessageTemplate::kDuplicateExport, default_string);
      return nullptr;
    }
  } else {
    // TODO(ES6): Assign result to a const binding with the name "*default*"
    // and add an export entry with "*default*" as the local name.
    USE(default_export);
  }

  return result;
}


Statement* Parser::ParseExportDeclaration(bool* ok) {
  // ExportDeclaration:
  //    'export' '*' 'from' ModuleSpecifier ';'
  //    'export' ExportClause ('from' ModuleSpecifier)? ';'
  //    'export' VariableStatement
  //    'export' Declaration
  //    'export' 'default' ... (handled in ParseExportDefault)

  int pos = peek_position();
  Expect(Token::EXPORT, CHECK_OK);

  Statement* result = NULL;
  ZoneList<const AstRawString*> names(1, zone());
  switch (peek()) {
    case Token::DEFAULT:
      return ParseExportDefault(ok);

    case Token::MUL: {
      Consume(Token::MUL);
      ExpectContextualKeyword(CStrVector("from"), CHECK_OK);
      const AstRawString* module_specifier = ParseModuleSpecifier(CHECK_OK);
      scope_->module()->AddModuleRequest(module_specifier, zone());
      // TODO(ES6): scope_->module()->AddStarExport(...)
      ExpectSemicolon(CHECK_OK);
      return factory()->NewEmptyStatement(pos);
    }

    case Token::LBRACE: {
      // There are two cases here:
      //
      // 'export' ExportClause ';'
      // and
      // 'export' ExportClause FromClause ';'
      //
      // In the first case, the exported identifiers in ExportClause must
      // not be reserved words, while in the latter they may be. We
      // pass in a location that gets filled with the first reserved word
      // encountered, and then throw a SyntaxError if we are in the
      // non-FromClause case.
      Scanner::Location reserved_loc = Scanner::Location::invalid();
      ZoneList<const AstRawString*> export_names(1, zone());
      ZoneList<Scanner::Location> export_locations(1, zone());
      ZoneList<const AstRawString*> local_names(1, zone());
      ParseExportClause(&export_names, &export_locations, &local_names,
                        &reserved_loc, CHECK_OK);
      const AstRawString* indirect_export_module_specifier = NULL;
      if (CheckContextualKeyword(CStrVector("from"))) {
        indirect_export_module_specifier = ParseModuleSpecifier(CHECK_OK);
      } else if (reserved_loc.IsValid()) {
        // No FromClause, so reserved words are invalid in ExportClause.
        *ok = false;
        ReportMessageAt(reserved_loc, MessageTemplate::kUnexpectedReserved);
        return NULL;
      }
      ExpectSemicolon(CHECK_OK);
      const int length = export_names.length();
      DCHECK_EQ(length, local_names.length());
      DCHECK_EQ(length, export_locations.length());
      if (indirect_export_module_specifier == NULL) {
        for (int i = 0; i < length; ++i) {
          scope_->module()->AddLocalExport(export_names[i], local_names[i],
                                           zone(), ok);
          if (!*ok) {
            ParserTraits::ReportMessageAt(export_locations[i],
                                          MessageTemplate::kDuplicateExport,
                                          export_names[i]);
            return NULL;
          }
        }
      } else {
        scope_->module()->AddModuleRequest(indirect_export_module_specifier,
                                           zone());
        for (int i = 0; i < length; ++i) {
          // TODO(ES6): scope_->module()->AddIndirectExport(...);(
        }
      }
      return factory()->NewEmptyStatement(pos);
    }

    case Token::FUNCTION:
      result = ParseHoistableDeclaration(&names, CHECK_OK);
      break;

    case Token::CLASS:
      Consume(Token::CLASS);
      result = ParseClassDeclaration(&names, CHECK_OK);
      break;

    case Token::VAR:
    case Token::LET:
    case Token::CONST:
      result = ParseVariableStatement(kStatementListItem, &names, CHECK_OK);
      break;

    case Token::ASYNC:
      if (allow_harmony_async_await()) {
        Consume(Token::ASYNC);
        result = ParseAsyncFunctionDeclaration(&names, CHECK_OK);
        break;
      }
    /* falls through */

    default:
      *ok = false;
      ReportUnexpectedToken(scanner()->current_token());
      return NULL;
  }

  // Extract declared names into export declarations.
  ModuleDescriptor* descriptor = scope_->module();
  for (int i = 0; i < names.length(); ++i) {
    descriptor->AddLocalExport(names[i], names[i], zone(), ok);
    if (!*ok) {
      // TODO(adamk): Possibly report this error at the right place.
      ParserTraits::ReportMessage(MessageTemplate::kDuplicateExport, names[i]);
      return NULL;
    }
  }

  DCHECK_NOT_NULL(result);
  return result;
}

Statement* Parser::ParseStatement(ZoneList<const AstRawString*>* labels,
                                  AllowLabelledFunctionStatement allow_function,
                                  bool* ok) {
  // Statement ::
  //   EmptyStatement
  //   ...

  if (peek() == Token::SEMICOLON) {
    Next();
    return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
  }
  return ParseSubStatement(labels, allow_function, ok);
}

Statement* Parser::ParseSubStatement(
    ZoneList<const AstRawString*>* labels,
    AllowLabelledFunctionStatement allow_function, bool* ok) {
  // Statement ::
  //   Block
  //   VariableStatement
  //   EmptyStatement
  //   ExpressionStatement
  //   IfStatement
  //   IterationStatement
  //   ContinueStatement
  //   BreakStatement
  //   ReturnStatement
  //   WithStatement
  //   LabelledStatement
  //   SwitchStatement
  //   ThrowStatement
  //   TryStatement
  //   DebuggerStatement

  // Note: Since labels can only be used by 'break' and 'continue'
  // statements, which themselves are only valid within blocks,
  // iterations or 'switch' statements (i.e., BreakableStatements),
  // labels can be simply ignored in all other cases; except for
  // trivial labeled break statements 'label: break label' which is
  // parsed into an empty statement.
  switch (peek()) {
    case Token::LBRACE:
      return ParseBlock(labels, ok);

    case Token::SEMICOLON:
      Next();
      return factory()->NewEmptyStatement(RelocInfo::kNoPosition);

    case Token::IF:
      return ParseIfStatement(labels, ok);

    case Token::DO:
      return ParseDoWhileStatement(labels, ok);

    case Token::WHILE:
      return ParseWhileStatement(labels, ok);

    case Token::FOR:
      return ParseForStatement(labels, ok);

    case Token::CONTINUE:
    case Token::BREAK:
    case Token::RETURN:
    case Token::THROW:
    case Token::TRY: {
      // These statements must have their labels preserved in an enclosing
      // block
      if (labels == NULL) {
        return ParseStatementAsUnlabelled(labels, ok);
      } else {
        Block* result =
            factory()->NewBlock(labels, 1, false, RelocInfo::kNoPosition);
        Target target(&this->target_stack_, result);
        Statement* statement = ParseStatementAsUnlabelled(labels, CHECK_OK);
        if (result) result->statements()->Add(statement, zone());
        return result;
      }
    }

    case Token::WITH:
      return ParseWithStatement(labels, ok);

    case Token::SWITCH:
      return ParseSwitchStatement(labels, ok);

    case Token::FUNCTION:
      // FunctionDeclaration only allowed as a StatementListItem, not in
      // an arbitrary Statement position. Exceptions such as
      // ES#sec-functiondeclarations-in-ifstatement-statement-clauses
      // are handled by calling ParseScopedStatement rather than
      // ParseSubStatement directly.
      ReportMessageAt(scanner()->peek_location(),
                      is_strict(language_mode())
                          ? MessageTemplate::kStrictFunction
                          : MessageTemplate::kSloppyFunction);
      *ok = false;
      return nullptr;

    case Token::DEBUGGER:
      return ParseDebuggerStatement(ok);

    case Token::VAR:
      return ParseVariableStatement(kStatement, NULL, ok);

    default:
      return ParseExpressionOrLabelledStatement(labels, allow_function, ok);
  }
}

Statement* Parser::ParseStatementAsUnlabelled(
    ZoneList<const AstRawString*>* labels, bool* ok) {
  switch (peek()) {
    case Token::CONTINUE:
      return ParseContinueStatement(ok);

    case Token::BREAK:
      return ParseBreakStatement(labels, ok);

    case Token::RETURN:
      return ParseReturnStatement(ok);

    case Token::THROW:
      return ParseThrowStatement(ok);

    case Token::TRY:
      return ParseTryStatement(ok);

    default:
      UNREACHABLE();
      return NULL;
  }
}


VariableProxy* Parser::NewUnresolved(const AstRawString* name,
                                     VariableMode mode) {
  // If we are inside a function, a declaration of a var/const variable is a
  // truly local variable, and the scope of the variable is always the function
  // scope.
  // Let/const variables in harmony mode are always added to the immediately
  // enclosing scope.
  Scope* scope =
      IsLexicalVariableMode(mode) ? scope_ : scope_->DeclarationScope();
  return scope->NewUnresolved(factory(), name, Variable::NORMAL,
                              scanner()->location().beg_pos,
                              scanner()->location().end_pos);
}


Variable* Parser::Declare(Declaration* declaration,
                          DeclarationDescriptor::Kind declaration_kind,
                          bool resolve, bool* ok, Scope* scope) {
  VariableProxy* proxy = declaration->proxy();
  DCHECK(proxy->raw_name() != NULL);
  const AstRawString* name = proxy->raw_name();
  VariableMode mode = declaration->mode();
  DCHECK(IsDeclaredVariableMode(mode) && mode != CONST_LEGACY);
  bool is_function_declaration = declaration->IsFunctionDeclaration();
  if (scope == nullptr) scope = scope_;
  Scope* declaration_scope =
      IsLexicalVariableMode(mode) ? scope : scope->DeclarationScope();
  Variable* var = NULL;

  // If a suitable scope exists, then we can statically declare this
  // variable and also set its mode. In any case, a Declaration node
  // will be added to the scope so that the declaration can be added
  // to the corresponding activation frame at runtime if necessary.
  // For instance, var declarations inside a sloppy eval scope need
  // to be added to the calling function context. Similarly, strict
  // mode eval scope and lexical eval bindings do not leak variable
  // declarations to the caller's scope so we declare all locals, too.
  if (declaration_scope->is_function_scope() ||
      declaration_scope->is_block_scope() ||
      declaration_scope->is_module_scope() ||
      declaration_scope->is_script_scope() ||
      (declaration_scope->is_eval_scope() &&
       (is_strict(declaration_scope->language_mode()) ||
        IsLexicalVariableMode(mode)))) {
    // Declare the variable in the declaration scope.
    var = declaration_scope->LookupLocal(name);
    if (var == NULL) {
      // Declare the name.
      Variable::Kind kind = Variable::NORMAL;
      if (is_function_declaration) {
        kind = Variable::FUNCTION;
      }
      var = declaration_scope->DeclareLocal(
          name, mode, declaration->initialization(), kind, kNotAssigned);
    } else if (IsLexicalVariableMode(mode) ||
               IsLexicalVariableMode(var->mode())) {
      // Allow duplicate function decls for web compat, see bug 4693.
      bool duplicate_allowed = false;
      if (is_sloppy(language_mode()) && is_function_declaration &&
          var->is_function()) {
        DCHECK(IsLexicalVariableMode(mode) &&
               IsLexicalVariableMode(var->mode()));
        // If the duplication is allowed, then the var will show up
        // in the SloppyBlockFunctionMap and the new FunctionKind
        // will be a permitted duplicate.
        FunctionKind function_kind =
            declaration->AsFunctionDeclaration()->fun()->kind();
        duplicate_allowed =
            scope->DeclarationScope()->sloppy_block_function_map()->Lookup(
                const_cast<AstRawString*>(name), name->hash()) != nullptr &&
            !IsAsyncFunction(function_kind) &&
            !(allow_harmony_restrictive_generators() &&
              IsGeneratorFunction(function_kind));
      }
      if (duplicate_allowed) {
        ++use_counts_[v8::Isolate::kSloppyModeBlockScopedFunctionRedefinition];
      } else {
        // The name was declared in this scope before; check for conflicting
        // re-declarations. We have a conflict if either of the declarations
        // is not a var (in script scope, we also have to ignore legacy const
        // for compatibility). There is similar code in runtime.cc in the
        // Declare functions. The function CheckConflictingVarDeclarations
        // checks for var and let bindings from different scopes whereas this
        // is a check for conflicting declarations within the same scope. This
        // check also covers the special case
        //
        // function () { let x; { var x; } }
        //
        // because the var declaration is hoisted to the function scope where
        // 'x' is already bound.
        DCHECK(IsDeclaredVariableMode(var->mode()));
        // In harmony we treat re-declarations as early errors. See
        // ES5 16 for a definition of early errors.
        if (declaration_kind == DeclarationDescriptor::NORMAL) {
          ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
        } else {
          ParserTraits::ReportMessage(MessageTemplate::kParamDupe);
        }
        *ok = false;
        return nullptr;
      }
    } else if (mode == VAR) {
      var->set_maybe_assigned();
    }
  } else if (declaration_scope->is_eval_scope() &&
             is_sloppy(declaration_scope->language_mode()) &&
             !IsLexicalVariableMode(mode)) {
    // In a var binding in a sloppy direct eval, pollute the enclosing scope
    // with this new binding by doing the following:
    // The proxy is bound to a lookup variable to force a dynamic declaration
    // using the DeclareEvalVar or DeclareEvalFunction runtime functions.
    Variable::Kind kind = Variable::NORMAL;
    // TODO(sigurds) figure out if kNotAssigned is OK here
    var = new (zone()) Variable(declaration_scope, name, mode, kind,
                                declaration->initialization(), kNotAssigned);
    var->AllocateTo(VariableLocation::LOOKUP, -1);
    resolve = true;
  }


  // We add a declaration node for every declaration. The compiler
  // will only generate code if necessary. In particular, declarations
  // for inner local variables that do not represent functions won't
  // result in any generated code.
  //
  // Note that we always add an unresolved proxy even if it's not
  // used, simply because we don't know in this method (w/o extra
  // parameters) if the proxy is needed or not. The proxy will be
  // bound during variable resolution time unless it was pre-bound
  // below.
  //
  // WARNING: This will lead to multiple declaration nodes for the
  // same variable if it is declared several times. This is not a
  // semantic issue as long as we keep the source order, but it may be
  // a performance issue since it may lead to repeated
  // DeclareEvalVar or DeclareEvalFunction calls.
  declaration_scope->AddDeclaration(declaration);

  // If requested and we have a local variable, bind the proxy to the variable
  // at parse-time. This is used for functions (and consts) declared inside
  // statements: the corresponding function (or const) variable must be in the
  // function scope and not a statement-local scope, e.g. as provided with a
  // 'with' statement:
  //
  //   with (obj) {
  //     function f() {}
  //   }
  //
  // which is translated into:
  //
  //   with (obj) {
  //     // in this case this is not: 'var f; f = function () {};'
  //     var f = function () {};
  //   }
  //
  // Note that if 'f' is accessed from inside the 'with' statement, it
  // will be allocated in the context (because we must be able to look
  // it up dynamically) but it will also be accessed statically, i.e.,
  // with a context slot index and a context chain length for this
  // initialization code. Thus, inside the 'with' statement, we need
  // both access to the static and the dynamic context chain; the
  // runtime needs to provide both.
  if (resolve && var != NULL) {
    proxy->BindTo(var);
  }
  return var;
}


// Language extension which is only enabled for source files loaded
// through the API's extension mechanism.  A native function
// declaration is resolved by looking up the function through a
// callback provided by the extension.
Statement* Parser::ParseNativeDeclaration(bool* ok) {
  int pos = peek_position();
  Expect(Token::FUNCTION, CHECK_OK);
  // Allow "eval" or "arguments" for backward compatibility.
  const AstRawString* name =
      ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  bool done = (peek() == Token::RPAREN);
  while (!done) {
    ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
    done = (peek() == Token::RPAREN);
    if (!done) {
      Expect(Token::COMMA, CHECK_OK);
    }
  }
  Expect(Token::RPAREN, CHECK_OK);
  Expect(Token::SEMICOLON, CHECK_OK);

  // Make sure that the function containing the native declaration
  // isn't lazily compiled. The extension structures are only
  // accessible while parsing the first time not when reparsing
  // because of lazy compilation.
  // TODO(adamk): Should this be ClosureScope()?
  scope_->DeclarationScope()->ForceEagerCompilation();

  // TODO(1240846): It's weird that native function declarations are
  // introduced dynamically when we meet their declarations, whereas
  // other functions are set up when entering the surrounding scope.
  VariableProxy* proxy = NewUnresolved(name, VAR);
  Declaration* declaration =
      factory()->NewVariableDeclaration(proxy, VAR, scope_, pos);
  Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
  NativeFunctionLiteral* lit = factory()->NewNativeFunctionLiteral(
      name, extension_, RelocInfo::kNoPosition);
  return factory()->NewExpressionStatement(
      factory()->NewAssignment(Token::INIT, proxy, lit, RelocInfo::kNoPosition),
      pos);
}


Statement* Parser::ParseHoistableDeclaration(
    ZoneList<const AstRawString*>* names, bool* ok) {
  Expect(Token::FUNCTION, CHECK_OK);
  int pos = position();
  ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
  if (Check(Token::MUL)) {
    flags |= ParseFunctionFlags::kIsGenerator;
  }
  return ParseHoistableDeclaration(pos, flags, names, ok);
}

Statement* Parser::ParseAsyncFunctionDeclaration(
    ZoneList<const AstRawString*>* names, bool* ok) {
  DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
  int pos = position();
  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
    *ok = false;
    ReportUnexpectedToken(scanner()->current_token());
    return nullptr;
  }
  Expect(Token::FUNCTION, CHECK_OK);
  ParseFunctionFlags flags = ParseFunctionFlags::kIsAsync;
  return ParseHoistableDeclaration(pos, flags, names, ok);
}

Statement* Parser::ParseHoistableDeclaration(
    int pos, ParseFunctionFlags flags, ZoneList<const AstRawString*>* names,
    bool* ok) {
  // FunctionDeclaration ::
  //   'function' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
  // GeneratorDeclaration ::
  //   'function' '*' Identifier '(' FormalParameters ')' '{' FunctionBody '}'
  //
  // 'function' and '*' (if present) have been consumed by the caller.
  const bool is_generator = flags & ParseFunctionFlags::kIsGenerator;
  const bool is_async = flags & ParseFunctionFlags::kIsAsync;
  DCHECK(!is_generator || !is_async);

  bool is_strict_reserved = false;
  const AstRawString* name = ParseIdentifierOrStrictReservedWord(
      &is_strict_reserved, CHECK_OK);

  if (V8_UNLIKELY(is_async_function() && this->IsAwait(name))) {
    ReportMessageAt(scanner()->location(),
                    MessageTemplate::kAwaitBindingIdentifier);
    *ok = false;
    return nullptr;
  }

  FuncNameInferrer::State fni_state(fni_);
  if (fni_ != NULL) fni_->PushEnclosingName(name);
  FunctionLiteral* fun = ParseFunctionLiteral(
      name, scanner()->location(),
      is_strict_reserved ? kFunctionNameIsStrictReserved
                         : kFunctionNameValidityUnknown,
      is_generator ? FunctionKind::kGeneratorFunction
                   : is_async ? FunctionKind::kAsyncFunction
                              : FunctionKind::kNormalFunction,
      pos, FunctionLiteral::kDeclaration, language_mode(), CHECK_OK);

  // Even if we're not at the top-level of the global or a function
  // scope, we treat it as such and introduce the function with its
  // initial value upon entering the corresponding scope.
  // In ES6, a function behaves as a lexical binding, except in
  // a script scope, or the initial scope of eval or another function.
  VariableMode mode =
      (!scope_->is_declaration_scope() || scope_->is_module_scope()) ? LET
                                                                     : VAR;
  VariableProxy* proxy = NewUnresolved(name, mode);
  Declaration* declaration =
      factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
  Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
  if (names) names->Add(name, zone());
  EmptyStatement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
  // Async functions don't undergo sloppy mode block scoped hoisting, and don't
  // allow duplicates in a block. Both are represented by the
  // sloppy_block_function_map. Don't add them to the map for async functions.
  // Generators are also supposed to be prohibited; currently doing this behind
  // a flag and UseCounting violations to assess web compatibility.
  if (is_sloppy(language_mode()) && !scope_->is_declaration_scope() &&
      !is_async && !(allow_harmony_restrictive_generators() && is_generator)) {
    SloppyBlockFunctionStatement* delegate =
        factory()->NewSloppyBlockFunctionStatement(empty, scope_);
    scope_->DeclarationScope()->sloppy_block_function_map()->Declare(name,
                                                                     delegate);
    return delegate;
  }
  return empty;
}


Statement* Parser::ParseClassDeclaration(ZoneList<const AstRawString*>* names,
                                         bool* ok) {
  // ClassDeclaration ::
  //   'class' Identifier ('extends' LeftHandExpression)? '{' ClassBody '}'
  //
  // 'class' is expected to be consumed by the caller.
  //
  // A ClassDeclaration
  //
  //   class C { ... }
  //
  // has the same semantics as:
  //
  //   let C = class C { ... };
  //
  // so rewrite it as such.

  int pos = position();
  bool is_strict_reserved = false;
  const AstRawString* name =
      ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
  ClassLiteral* value = ParseClassLiteral(nullptr, name, scanner()->location(),
                                          is_strict_reserved, pos, CHECK_OK);

  VariableProxy* proxy = NewUnresolved(name, LET);
  Declaration* declaration =
      factory()->NewVariableDeclaration(proxy, LET, scope_, pos);
  Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
  proxy->var()->set_initializer_position(position());
  Assignment* assignment =
      factory()->NewAssignment(Token::INIT, proxy, value, pos);
  Statement* assignment_statement =
      factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
  if (names) names->Add(name, zone());
  return assignment_statement;
}


Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels,
                          bool finalize_block_scope, bool* ok) {
  // The harmony mode uses block elements instead of statements.
  //
  // Block ::
  //   '{' StatementList '}'

  // Construct block expecting 16 statements.
  Block* body =
      factory()->NewBlock(labels, 16, false, RelocInfo::kNoPosition);
  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);

  // Parse the statements and collect escaping labels.
  Expect(Token::LBRACE, CHECK_OK);
  block_scope->set_start_position(scanner()->location().beg_pos);
  { BlockState block_state(&scope_, block_scope);
    Target target(&this->target_stack_, body);

    while (peek() != Token::RBRACE) {
      Statement* stat = ParseStatementListItem(CHECK_OK);
      if (stat && !stat->IsEmpty()) {
        body->statements()->Add(stat, zone());
      }
    }
  }
  Expect(Token::RBRACE, CHECK_OK);
  block_scope->set_end_position(scanner()->location().end_pos);
  if (finalize_block_scope) {
    block_scope = block_scope->FinalizeBlockScope();
  }
  body->set_scope(block_scope);
  return body;
}


Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
  return ParseBlock(labels, true, ok);
}


Block* Parser::DeclarationParsingResult::BuildInitializationBlock(
    ZoneList<const AstRawString*>* names, bool* ok) {
  Block* result = descriptor.parser->factory()->NewBlock(
      NULL, 1, true, descriptor.declaration_pos);
  for (auto declaration : declarations) {
    PatternRewriter::DeclareAndInitializeVariables(
        result, &descriptor, &declaration, names, CHECK_OK);
  }
  return result;
}


Block* Parser::ParseVariableStatement(VariableDeclarationContext var_context,
                                      ZoneList<const AstRawString*>* names,
                                      bool* ok) {
  // VariableStatement ::
  //   VariableDeclarations ';'

  // The scope of a var/const declared variable anywhere inside a function
  // is the entire function (ECMA-262, 3rd, 10.1.3, and 12.2). Thus we can
  // transform a source-level var/const declaration into a (Function)
  // Scope declaration, and rewrite the source-level initialization into an
  // assignment statement. We use a block to collect multiple assignments.
  //
  // We mark the block as initializer block because we don't want the
  // rewriter to add a '.result' assignment to such a block (to get compliant
  // behavior for code such as print(eval('var x = 7')), and for cosmetic
  // reasons when pretty-printing. Also, unless an assignment (initialization)
  // is inside an initializer block, it is ignored.

  DeclarationParsingResult parsing_result;
  Block* result =
      ParseVariableDeclarations(var_context, &parsing_result, names, CHECK_OK);
  ExpectSemicolon(CHECK_OK);
  return result;
}

Block* Parser::ParseVariableDeclarations(
    VariableDeclarationContext var_context,
    DeclarationParsingResult* parsing_result,
    ZoneList<const AstRawString*>* names, bool* ok) {
  // VariableDeclarations ::
  //   ('var' | 'const' | 'let') (Identifier ('=' AssignmentExpression)?)+[',']
  //
  // The ES6 Draft Rev3 specifies the following grammar for const declarations
  //
  // ConstDeclaration ::
  //   const ConstBinding (',' ConstBinding)* ';'
  // ConstBinding ::
  //   Identifier '=' AssignmentExpression
  //
  // TODO(ES6):
  // ConstBinding ::
  //   BindingPattern '=' AssignmentExpression

  parsing_result->descriptor.parser = this;
  parsing_result->descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
  parsing_result->descriptor.declaration_pos = peek_position();
  parsing_result->descriptor.initialization_pos = peek_position();
  parsing_result->descriptor.mode = VAR;

  Block* init_block = nullptr;
  if (var_context != kForStatement) {
    init_block = factory()->NewBlock(
        NULL, 1, true, parsing_result->descriptor.declaration_pos);
  }

  if (peek() == Token::VAR) {
    Consume(Token::VAR);
  } else if (peek() == Token::CONST) {
    Consume(Token::CONST);
    DCHECK(var_context != kStatement);
    parsing_result->descriptor.mode = CONST;
  } else if (peek() == Token::LET) {
    Consume(Token::LET);
    DCHECK(var_context != kStatement);
    parsing_result->descriptor.mode = LET;
  } else {
    UNREACHABLE();  // by current callers
  }

  parsing_result->descriptor.scope = scope_;
  parsing_result->descriptor.hoist_scope = nullptr;


  bool first_declaration = true;
  int bindings_start = peek_position();
  do {
    FuncNameInferrer::State fni_state(fni_);

    // Parse name.
    if (!first_declaration) Consume(Token::COMMA);

    Expression* pattern;
    int decl_pos = peek_position();
    {
      ExpressionClassifier pattern_classifier(this);
      pattern = ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
      ValidateBindingPattern(&pattern_classifier, CHECK_OK);
      if (IsLexicalVariableMode(parsing_result->descriptor.mode)) {
        ValidateLetPattern(&pattern_classifier, CHECK_OK);
      }
    }

    Scanner::Location variable_loc = scanner()->location();
    const AstRawString* single_name =
        pattern->IsVariableProxy() ? pattern->AsVariableProxy()->raw_name()
                                   : nullptr;
    if (single_name != nullptr) {
      if (fni_ != NULL) fni_->PushVariableName(single_name);
    }

    Expression* value = NULL;
    int initializer_position = RelocInfo::kNoPosition;
    if (Check(Token::ASSIGN)) {
      ExpressionClassifier classifier(this);
      value = ParseAssignmentExpression(var_context != kForStatement,
                                        &classifier, CHECK_OK);
      RewriteNonPattern(&classifier, CHECK_OK);
      variable_loc.end_pos = scanner()->location().end_pos;

      if (!parsing_result->first_initializer_loc.IsValid()) {
        parsing_result->first_initializer_loc = variable_loc;
      }

      // Don't infer if it is "a = function(){...}();"-like expression.
      if (single_name) {
        if (fni_ != NULL && value->AsCall() == NULL &&
            value->AsCallNew() == NULL) {
          fni_->Infer();
        } else {
          fni_->RemoveLastFunction();
        }
      }

      ParserTraits::SetFunctionNameFromIdentifierRef(value, pattern);

      // End position of the initializer is after the assignment expression.
      initializer_position = scanner()->location().end_pos;
    } else {
      // Initializers may be either required or implied unless this is a
      // for-in/of iteration variable.
      if (var_context != kForStatement || !PeekInOrOf()) {
        // ES6 'const' and binding patterns require initializers.
        if (parsing_result->descriptor.mode == CONST ||
            !pattern->IsVariableProxy()) {
          ParserTraits::ReportMessageAt(
              Scanner::Location(decl_pos, scanner()->location().end_pos),
              MessageTemplate::kDeclarationMissingInitializer,
              !pattern->IsVariableProxy() ? "destructuring" : "const");
          *ok = false;
          return nullptr;
        }

        // 'let x' initializes 'x' to undefined.
        if (parsing_result->descriptor.mode == LET) {
          value = GetLiteralUndefined(position());
        }
      }

      // End position of the initializer is after the variable.
      initializer_position = position();
    }

    DeclarationParsingResult::Declaration decl(pattern, initializer_position,
                                               value);
    if (var_context == kForStatement) {
      // Save the declaration for further handling in ParseForStatement.
      parsing_result->declarations.Add(decl);
    } else {
      // Immediately declare the variable otherwise. This avoids O(N^2)
      // behavior (where N is the number of variables in a single
      // declaration) in the PatternRewriter having to do with removing
      // and adding VariableProxies to the Scope (see bug 4699).
      DCHECK_NOT_NULL(init_block);
      PatternRewriter::DeclareAndInitializeVariables(
          init_block, &parsing_result->descriptor, &decl, names, CHECK_OK);
    }
    first_declaration = false;
  } while (peek() == Token::COMMA);

  parsing_result->bindings_loc =
      Scanner::Location(bindings_start, scanner()->location().end_pos);

  DCHECK(*ok);
  return init_block;
}


static bool ContainsLabel(ZoneList<const AstRawString*>* labels,
                          const AstRawString* label) {
  DCHECK(label != NULL);
  if (labels != NULL) {
    for (int i = labels->length(); i-- > 0; ) {
      if (labels->at(i) == label) {
        return true;
      }
    }
  }
  return false;
}

Statement* Parser::ParseFunctionDeclaration(bool* ok) {
  Consume(Token::FUNCTION);
  int pos = position();
  ParseFunctionFlags flags = ParseFunctionFlags::kIsNormal;
  if (Check(Token::MUL)) {
    flags |= ParseFunctionFlags::kIsGenerator;
    if (allow_harmony_restrictive_declarations()) {
      ParserTraits::ReportMessageAt(scanner()->location(),
                                    MessageTemplate::kGeneratorInLegacyContext);
      *ok = false;
      return nullptr;
    }
  }

  return ParseHoistableDeclaration(pos, flags, nullptr, CHECK_OK);
}

Statement* Parser::ParseExpressionOrLabelledStatement(
    ZoneList<const AstRawString*>* labels,
    AllowLabelledFunctionStatement allow_function, bool* ok) {
  // ExpressionStatement | LabelledStatement ::
  //   Expression ';'
  //   Identifier ':' Statement
  //
  // ExpressionStatement[Yield] :
  //   [lookahead ∉ {{, function, class, let [}] Expression[In, ?Yield] ;

  int pos = peek_position();

  switch (peek()) {
    case Token::FUNCTION:
    case Token::LBRACE:
      UNREACHABLE();  // Always handled by the callers.
    case Token::CLASS:
      ReportUnexpectedToken(Next());
      *ok = false;
      return nullptr;
    default:
      break;
  }

  bool starts_with_idenfifier = peek_any_identifier();
  Expression* expr = ParseExpression(true, CHECK_OK);
  if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
      expr->AsVariableProxy() != NULL &&
      !expr->AsVariableProxy()->is_this()) {
    // Expression is a single identifier, and not, e.g., a parenthesized
    // identifier.
    VariableProxy* var = expr->AsVariableProxy();
    const AstRawString* label = var->raw_name();
    // TODO(1240780): We don't check for redeclaration of labels
    // during preparsing since keeping track of the set of active
    // labels requires nontrivial changes to the way scopes are
    // structured.  However, these are probably changes we want to
    // make later anyway so we should go back and fix this then.
    if (ContainsLabel(labels, label) || TargetStackContainsLabel(label)) {
      ParserTraits::ReportMessage(MessageTemplate::kLabelRedeclaration, label);
      *ok = false;
      return NULL;
    }
    if (labels == NULL) {
      labels = new(zone()) ZoneList<const AstRawString*>(4, zone());
    }
    labels->Add(label, zone());
    // Remove the "ghost" variable that turned out to be a label
    // from the top scope. This way, we don't try to resolve it
    // during the scope processing.
    scope_->RemoveUnresolved(var);
    Expect(Token::COLON, CHECK_OK);
    // ES#sec-labelled-function-declarations Labelled Function Declarations
    if (peek() == Token::FUNCTION && is_sloppy(language_mode())) {
      if (allow_function == kAllowLabelledFunctionStatement) {
        return ParseFunctionDeclaration(ok);
      } else {
        return ParseScopedStatement(labels, true, ok);
      }
    }
    return ParseStatement(labels, kDisallowLabelledFunctionStatement, ok);
  }

  // If we have an extension, we allow a native function declaration.
  // A native function declaration starts with "native function" with
  // no line-terminator between the two words.
  if (extension_ != NULL && peek() == Token::FUNCTION &&
      !scanner()->HasAnyLineTerminatorBeforeNext() && expr != NULL &&
      expr->AsVariableProxy() != NULL &&
      expr->AsVariableProxy()->raw_name() ==
          ast_value_factory()->native_string() &&
      !scanner()->literal_contains_escapes()) {
    return ParseNativeDeclaration(ok);
  }

  // Parsed expression statement, followed by semicolon.
  ExpectSemicolon(CHECK_OK);
  return factory()->NewExpressionStatement(expr, pos);
}


IfStatement* Parser::ParseIfStatement(ZoneList<const AstRawString*>* labels,
                                      bool* ok) {
  // IfStatement ::
  //   'if' '(' Expression ')' Statement ('else' Statement)?

  int pos = peek_position();
  Expect(Token::IF, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  Expression* condition = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);
  Statement* then_statement = ParseScopedStatement(labels, false, CHECK_OK);
  Statement* else_statement = NULL;
  if (peek() == Token::ELSE) {
    Next();
    else_statement = ParseScopedStatement(labels, false, CHECK_OK);
  } else {
    else_statement = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
  }
  return factory()->NewIfStatement(
      condition, then_statement, else_statement, pos);
}


Statement* Parser::ParseContinueStatement(bool* ok) {
  // ContinueStatement ::
  //   'continue' Identifier? ';'

  int pos = peek_position();
  Expect(Token::CONTINUE, CHECK_OK);
  const AstRawString* label = NULL;
  Token::Value tok = peek();
  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
    // ECMA allows "eval" or "arguments" as labels even in strict mode.
    label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
  }
  IterationStatement* target = LookupContinueTarget(label, CHECK_OK);
  if (target == NULL) {
    // Illegal continue statement.
    MessageTemplate::Template message = MessageTemplate::kIllegalContinue;
    if (label != NULL) {
      message = MessageTemplate::kUnknownLabel;
    }
    ParserTraits::ReportMessage(message, label);
    *ok = false;
    return NULL;
  }
  ExpectSemicolon(CHECK_OK);
  return factory()->NewContinueStatement(target, pos);
}


Statement* Parser::ParseBreakStatement(ZoneList<const AstRawString*>* labels,
                                       bool* ok) {
  // BreakStatement ::
  //   'break' Identifier? ';'

  int pos = peek_position();
  Expect(Token::BREAK, CHECK_OK);
  const AstRawString* label = NULL;
  Token::Value tok = peek();
  if (!scanner()->HasAnyLineTerminatorBeforeNext() &&
      tok != Token::SEMICOLON && tok != Token::RBRACE && tok != Token::EOS) {
    // ECMA allows "eval" or "arguments" as labels even in strict mode.
    label = ParseIdentifier(kAllowRestrictedIdentifiers, CHECK_OK);
  }
  // Parse labeled break statements that target themselves into
  // empty statements, e.g. 'l1: l2: l3: break l2;'
  if (label != NULL && ContainsLabel(labels, label)) {
    ExpectSemicolon(CHECK_OK);
    return factory()->NewEmptyStatement(pos);
  }
  BreakableStatement* target = NULL;
  target = LookupBreakTarget(label, CHECK_OK);
  if (target == NULL) {
    // Illegal break statement.
    MessageTemplate::Template message = MessageTemplate::kIllegalBreak;
    if (label != NULL) {
      message = MessageTemplate::kUnknownLabel;
    }
    ParserTraits::ReportMessage(message, label);
    *ok = false;
    return NULL;
  }
  ExpectSemicolon(CHECK_OK);
  return factory()->NewBreakStatement(target, pos);
}


Statement* Parser::ParseReturnStatement(bool* ok) {
  // ReturnStatement ::
  //   'return' Expression? ';'

  // Consume the return token. It is necessary to do that before
  // reporting any errors on it, because of the way errors are
  // reported (underlining).
  Expect(Token::RETURN, CHECK_OK);
  Scanner::Location loc = scanner()->location();
  function_state_->set_return_location(loc);

  Token::Value tok = peek();
  Statement* result;
  Expression* return_value;
  if (scanner()->HasAnyLineTerminatorBeforeNext() ||
      tok == Token::SEMICOLON ||
      tok == Token::RBRACE ||
      tok == Token::EOS) {
    if (IsSubclassConstructor(function_state_->kind())) {
      return_value = ThisExpression(scope_, factory(), loc.beg_pos);
    } else {
      return_value = GetLiteralUndefined(position());
    }
  } else {
    int pos = peek_position();

    if (IsSubclassConstructor(function_state_->kind())) {
      // Because of the return code rewriting that happens in case of a subclass
      // constructor we don't want to accept tail calls, therefore we don't set
      // ReturnExprScope to kInsideValidReturnStatement here.
      return_value = ParseExpression(true, CHECK_OK);

      // For subclass constructors we need to return this in case of undefined
      // return a Smi (transformed into an exception in the ConstructStub)
      // for a non object.
      //
      //   return expr;
      //
      // Is rewritten as:
      //
      //   return (temp = expr) === undefined ? this :
      //       %_IsJSReceiver(temp) ? temp : 1;

      // temp = expr
      Variable* temp = scope_->NewTemporary(
          ast_value_factory()->empty_string());
      Assignment* assign = factory()->NewAssignment(
          Token::ASSIGN, factory()->NewVariableProxy(temp), return_value, pos);

      // %_IsJSReceiver(temp)
      ZoneList<Expression*>* is_spec_object_args =
          new (zone()) ZoneList<Expression*>(1, zone());
      is_spec_object_args->Add(factory()->NewVariableProxy(temp), zone());
      Expression* is_spec_object_call = factory()->NewCallRuntime(
          Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);

      // %_IsJSReceiver(temp) ? temp : 1;
      Expression* is_object_conditional = factory()->NewConditional(
          is_spec_object_call, factory()->NewVariableProxy(temp),
          factory()->NewSmiLiteral(1, pos), pos);

      // temp === undefined
      Expression* is_undefined = factory()->NewCompareOperation(
          Token::EQ_STRICT, assign,
          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition), pos);

      // is_undefined ? this : is_object_conditional
      return_value = factory()->NewConditional(
          is_undefined, ThisExpression(scope_, factory(), pos),
          is_object_conditional, pos);
    } else {
      ReturnExprScope maybe_allow_tail_calls(
          function_state_, ReturnExprContext::kInsideValidReturnStatement);
      return_value = ParseExpression(true, CHECK_OK);

      if (allow_tailcalls() && !is_sloppy(language_mode()) && !is_resumable()) {
        // ES6 14.6.1 Static Semantics: IsInTailPosition
        function_state_->AddImplicitTailCallExpression(return_value);
      }
    }
  }
  ExpectSemicolon(CHECK_OK);

  if (is_generator()) {
    return_value = BuildIteratorResult(return_value, true);
  } else if (is_async_function()) {
    return_value = BuildPromiseResolve(return_value, return_value->position());
  }

  result = factory()->NewReturnStatement(return_value, loc.beg_pos);

  Scope* decl_scope = scope_->DeclarationScope();
  if (decl_scope->is_script_scope() || decl_scope->is_eval_scope()) {
    ReportMessageAt(loc, MessageTemplate::kIllegalReturn);
    *ok = false;
    return NULL;
  }
  return result;
}


Statement* Parser::ParseWithStatement(ZoneList<const AstRawString*>* labels,
                                      bool* ok) {
  // WithStatement ::
  //   'with' '(' Expression ')' Statement

  Expect(Token::WITH, CHECK_OK);
  int pos = position();

  if (is_strict(language_mode())) {
    ReportMessage(MessageTemplate::kStrictWith);
    *ok = false;
    return NULL;
  }

  Expect(Token::LPAREN, CHECK_OK);
  Expression* expr = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);

  Scope* with_scope = NewScope(scope_, WITH_SCOPE);
  Statement* body;
  { BlockState block_state(&scope_, with_scope);
    with_scope->set_start_position(scanner()->peek_location().beg_pos);
    body = ParseScopedStatement(labels, true, CHECK_OK);
    with_scope->set_end_position(scanner()->location().end_pos);
  }
  return factory()->NewWithStatement(with_scope, expr, body, pos);
}


CaseClause* Parser::ParseCaseClause(bool* default_seen_ptr, bool* ok) {
  // CaseClause ::
  //   'case' Expression ':' StatementList
  //   'default' ':' StatementList

  Expression* label = NULL;  // NULL expression indicates default case
  if (peek() == Token::CASE) {
    Expect(Token::CASE, CHECK_OK);
    label = ParseExpression(true, CHECK_OK);
  } else {
    Expect(Token::DEFAULT, CHECK_OK);
    if (*default_seen_ptr) {
      ReportMessage(MessageTemplate::kMultipleDefaultsInSwitch);
      *ok = false;
      return NULL;
    }
    *default_seen_ptr = true;
  }
  Expect(Token::COLON, CHECK_OK);
  int pos = position();
  ZoneList<Statement*>* statements =
      new(zone()) ZoneList<Statement*>(5, zone());
  Statement* stat = NULL;
  while (peek() != Token::CASE &&
         peek() != Token::DEFAULT &&
         peek() != Token::RBRACE) {
    stat = ParseStatementListItem(CHECK_OK);
    statements->Add(stat, zone());
  }
  return factory()->NewCaseClause(label, statements, pos);
}


Statement* Parser::ParseSwitchStatement(ZoneList<const AstRawString*>* labels,
                                        bool* ok) {
  // SwitchStatement ::
  //   'switch' '(' Expression ')' '{' CaseClause* '}'
  // In order to get the CaseClauses to execute in their own lexical scope,
  // but without requiring downstream code to have special scope handling
  // code for switch statements, desugar into blocks as follows:
  // {  // To group the statements--harmless to evaluate Expression in scope
  //   .tag_variable = Expression;
  //   {  // To give CaseClauses a scope
  //     switch (.tag_variable) { CaseClause* }
  //   }
  // }

  Block* switch_block =
      factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
  int switch_pos = peek_position();

  Expect(Token::SWITCH, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  Expression* tag = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);

  Variable* tag_variable =
      scope_->NewTemporary(ast_value_factory()->dot_switch_tag_string());
  Assignment* tag_assign = factory()->NewAssignment(
      Token::ASSIGN, factory()->NewVariableProxy(tag_variable), tag,
      tag->position());
  Statement* tag_statement =
      factory()->NewExpressionStatement(tag_assign, RelocInfo::kNoPosition);
  switch_block->statements()->Add(tag_statement, zone());

  // make statement: undefined;
  // This is needed so the tag isn't returned as the value, in case the switch
  // statements don't have a value.
  switch_block->statements()->Add(
      factory()->NewExpressionStatement(
          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
          RelocInfo::kNoPosition),
      zone());

  Block* cases_block =
      factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
  Scope* cases_scope = NewScope(scope_, BLOCK_SCOPE);
  cases_scope->SetNonlinear();

  SwitchStatement* switch_statement =
      factory()->NewSwitchStatement(labels, switch_pos);

  cases_scope->set_start_position(scanner()->location().beg_pos);
  {
    BlockState cases_block_state(&scope_, cases_scope);
    Target target(&this->target_stack_, switch_statement);

    Expression* tag_read = factory()->NewVariableProxy(tag_variable);

    bool default_seen = false;
    ZoneList<CaseClause*>* cases =
        new (zone()) ZoneList<CaseClause*>(4, zone());
    Expect(Token::LBRACE, CHECK_OK);
    while (peek() != Token::RBRACE) {
      CaseClause* clause = ParseCaseClause(&default_seen, CHECK_OK);
      cases->Add(clause, zone());
    }
    switch_statement->Initialize(tag_read, cases);
    cases_block->statements()->Add(switch_statement, zone());
  }
  Expect(Token::RBRACE, CHECK_OK);

  cases_scope->set_end_position(scanner()->location().end_pos);
  cases_scope = cases_scope->FinalizeBlockScope();
  cases_block->set_scope(cases_scope);

  switch_block->statements()->Add(cases_block, zone());

  return switch_block;
}


Statement* Parser::ParseThrowStatement(bool* ok) {
  // ThrowStatement ::
  //   'throw' Expression ';'

  Expect(Token::THROW, CHECK_OK);
  int pos = position();
  if (scanner()->HasAnyLineTerminatorBeforeNext()) {
    ReportMessage(MessageTemplate::kNewlineAfterThrow);
    *ok = false;
    return NULL;
  }
  Expression* exception = ParseExpression(true, CHECK_OK);
  ExpectSemicolon(CHECK_OK);

  return factory()->NewExpressionStatement(
      factory()->NewThrow(exception, pos), pos);
}


TryStatement* Parser::ParseTryStatement(bool* ok) {
  // TryStatement ::
  //   'try' Block Catch
  //   'try' Block Finally
  //   'try' Block Catch Finally
  //
  // Catch ::
  //   'catch' '(' Identifier ')' Block
  //
  // Finally ::
  //   'finally' Block

  Expect(Token::TRY, CHECK_OK);
  int pos = position();

  Block* try_block;
  {
    ReturnExprScope no_tail_calls(function_state_,
                                  ReturnExprContext::kInsideTryBlock);
    try_block = ParseBlock(NULL, CHECK_OK);
  }

  Token::Value tok = peek();
  if (tok != Token::CATCH && tok != Token::FINALLY) {
    ReportMessage(MessageTemplate::kNoCatchOrFinally);
    *ok = false;
    return NULL;
  }

  Scope* catch_scope = NULL;
  Variable* catch_variable = NULL;
  Block* catch_block = NULL;
  TailCallExpressionList tail_call_expressions_in_catch_block(zone());
  if (tok == Token::CATCH) {
    Consume(Token::CATCH);

    Expect(Token::LPAREN, CHECK_OK);
    catch_scope = NewScope(scope_, CATCH_SCOPE);
    catch_scope->set_start_position(scanner()->location().beg_pos);

    {
      CollectExpressionsInTailPositionToListScope
          collect_tail_call_expressions_scope(
              function_state_, &tail_call_expressions_in_catch_block);
      BlockState block_state(&scope_, catch_scope);

      catch_block =
          factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);

      // Create a block scope to hold any lexical declarations created
      // as part of destructuring the catch parameter.
      Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
      block_scope->set_start_position(scanner()->location().beg_pos);
      {
        BlockState block_state(&scope_, block_scope);
        Target target(&this->target_stack_, catch_block);

        ExpressionClassifier pattern_classifier(this);
        Expression* pattern =
            ParsePrimaryExpression(&pattern_classifier, CHECK_OK);
        ValidateBindingPattern(&pattern_classifier, CHECK_OK);

        const AstRawString* name = ast_value_factory()->dot_catch_string();
        bool is_simple = pattern->IsVariableProxy();
        if (is_simple) {
          auto proxy = pattern->AsVariableProxy();
          scope_->RemoveUnresolved(proxy);
          name = proxy->raw_name();
        }
        catch_variable = catch_scope->DeclareLocal(
            name, VAR, kCreatedInitialized, Variable::NORMAL);

        Expect(Token::RPAREN, CHECK_OK);

        if (!is_simple) {
          DeclarationDescriptor descriptor;
          descriptor.declaration_kind = DeclarationDescriptor::NORMAL;
          descriptor.parser = this;
          descriptor.scope = scope_;
          descriptor.hoist_scope = nullptr;
          descriptor.mode = LET;
          descriptor.declaration_pos = pattern->position();
          descriptor.initialization_pos = pattern->position();

          // Initializer position for variables declared by the pattern.
          const int initializer_position = position();

          DeclarationParsingResult::Declaration decl(
              pattern, initializer_position,
              factory()->NewVariableProxy(catch_variable));

          Block* init_block =
              factory()->NewBlock(nullptr, 8, true, RelocInfo::kNoPosition);
          PatternRewriter::DeclareAndInitializeVariables(
              init_block, &descriptor, &decl, nullptr, CHECK_OK);
          catch_block->statements()->Add(init_block, zone());
        }

        // TODO(adamk): This should call ParseBlock in order to properly
        // add an additional block scope for the catch body.
        Expect(Token::LBRACE, CHECK_OK);
        while (peek() != Token::RBRACE) {
          Statement* stat = ParseStatementListItem(CHECK_OK);
          if (stat && !stat->IsEmpty()) {
            catch_block->statements()->Add(stat, zone());
          }
        }
        Consume(Token::RBRACE);
      }
      block_scope->set_end_position(scanner()->location().end_pos);
      block_scope = block_scope->FinalizeBlockScope();
      catch_block->set_scope(block_scope);
    }

    catch_scope->set_end_position(scanner()->location().end_pos);
    tok = peek();
  }

  Block* finally_block = NULL;
  DCHECK(tok == Token::FINALLY || catch_block != NULL);
  if (tok == Token::FINALLY) {
    Consume(Token::FINALLY);
    finally_block = ParseBlock(NULL, CHECK_OK);
  }

  // Simplify the AST nodes by converting:
  //   'try B0 catch B1 finally B2'
  // to:
  //   'try { try B0 catch B1 } finally B2'

  if (catch_block != NULL && finally_block != NULL) {
    // If we have both, create an inner try/catch.
    DCHECK(catch_scope != NULL && catch_variable != NULL);
    TryCatchStatement* statement =
        factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
                                        catch_block, RelocInfo::kNoPosition);
    try_block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
    try_block->statements()->Add(statement, zone());
    catch_block = NULL;  // Clear to indicate it's been handled.
  }

  TryStatement* result = NULL;
  if (catch_block != NULL) {
    // For a try-catch construct append return expressions from the catch block
    // to the list of return expressions.
    function_state_->tail_call_expressions().Append(
        tail_call_expressions_in_catch_block);

    DCHECK(finally_block == NULL);
    DCHECK(catch_scope != NULL && catch_variable != NULL);
    result = factory()->NewTryCatchStatement(try_block, catch_scope,
                                             catch_variable, catch_block, pos);
  } else {
    if (FLAG_harmony_explicit_tailcalls &&
        tail_call_expressions_in_catch_block.has_explicit_tail_calls()) {
      // TODO(ishell): update chapter number.
      // ES8 XX.YY.ZZ
      ReportMessageAt(tail_call_expressions_in_catch_block.location(),
                      MessageTemplate::kUnexpectedTailCallInCatchBlock);
      *ok = false;
      return NULL;
    }
    DCHECK(finally_block != NULL);
    result = factory()->NewTryFinallyStatement(try_block, finally_block, pos);
  }

  return result;
}


DoWhileStatement* Parser::ParseDoWhileStatement(
    ZoneList<const AstRawString*>* labels, bool* ok) {
  // DoStatement ::
  //   'do' Statement 'while' '(' Expression ')' ';'

  DoWhileStatement* loop =
      factory()->NewDoWhileStatement(labels, peek_position());
  Target target(&this->target_stack_, loop);

  Expect(Token::DO, CHECK_OK);
  Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
  Expect(Token::WHILE, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);

  Expression* cond = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);

  // Allow do-statements to be terminated with and without
  // semi-colons. This allows code such as 'do;while(0)return' to
  // parse, which would not be the case if we had used the
  // ExpectSemicolon() functionality here.
  if (peek() == Token::SEMICOLON) Consume(Token::SEMICOLON);

  if (loop != NULL) loop->Initialize(cond, body);
  return loop;
}


WhileStatement* Parser::ParseWhileStatement(
    ZoneList<const AstRawString*>* labels, bool* ok) {
  // WhileStatement ::
  //   'while' '(' Expression ')' Statement

  WhileStatement* loop = factory()->NewWhileStatement(labels, peek_position());
  Target target(&this->target_stack_, loop);

  Expect(Token::WHILE, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  Expression* cond = ParseExpression(true, CHECK_OK);
  Expect(Token::RPAREN, CHECK_OK);
  Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);

  if (loop != NULL) loop->Initialize(cond, body);
  return loop;
}


// !%_IsJSReceiver(result = iterator.next()) &&
//     %ThrowIteratorResultNotAnObject(result)
Expression* Parser::BuildIteratorNextResult(Expression* iterator,
                                            Variable* result, int pos) {
  Expression* next_literal = factory()->NewStringLiteral(
      ast_value_factory()->next_string(), RelocInfo::kNoPosition);
  Expression* next_property =
      factory()->NewProperty(iterator, next_literal, RelocInfo::kNoPosition);
  ZoneList<Expression*>* next_arguments =
      new (zone()) ZoneList<Expression*>(0, zone());
  Expression* next_call =
      factory()->NewCall(next_property, next_arguments, pos);
  Expression* result_proxy = factory()->NewVariableProxy(result);
  Expression* left =
      factory()->NewAssignment(Token::ASSIGN, result_proxy, next_call, pos);

  // %_IsJSReceiver(...)
  ZoneList<Expression*>* is_spec_object_args =
      new (zone()) ZoneList<Expression*>(1, zone());
  is_spec_object_args->Add(left, zone());
  Expression* is_spec_object_call = factory()->NewCallRuntime(
      Runtime::kInlineIsJSReceiver, is_spec_object_args, pos);

  // %ThrowIteratorResultNotAnObject(result)
  Expression* result_proxy_again = factory()->NewVariableProxy(result);
  ZoneList<Expression*>* throw_arguments =
      new (zone()) ZoneList<Expression*>(1, zone());
  throw_arguments->Add(result_proxy_again, zone());
  Expression* throw_call = factory()->NewCallRuntime(
      Runtime::kThrowIteratorResultNotAnObject, throw_arguments, pos);

  return factory()->NewBinaryOperation(
      Token::AND,
      factory()->NewUnaryOperation(Token::NOT, is_spec_object_call, pos),
      throw_call, pos);
}

void Parser::InitializeForEachStatement(ForEachStatement* stmt,
                                        Expression* each, Expression* subject,
                                        Statement* body, int each_keyword_pos) {
  ForOfStatement* for_of = stmt->AsForOfStatement();
  if (for_of != NULL) {
    InitializeForOfStatement(for_of, each, subject, body, each_keyword_pos);
  } else {
    if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
      Variable* temp =
          scope_->NewTemporary(ast_value_factory()->empty_string());
      VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
      Expression* assign_each = PatternRewriter::RewriteDestructuringAssignment(
          this, factory()->NewAssignment(Token::ASSIGN, each, temp_proxy,
                                         RelocInfo::kNoPosition),
          scope_);
      auto block =
          factory()->NewBlock(nullptr, 2, false, RelocInfo::kNoPosition);
      block->statements()->Add(factory()->NewExpressionStatement(
                                   assign_each, RelocInfo::kNoPosition),
                               zone());
      block->statements()->Add(body, zone());
      body = block;
      each = factory()->NewVariableProxy(temp);
    }
    stmt->AsForInStatement()->Initialize(each, subject, body);
  }
}

void Parser::InitializeForOfStatement(ForOfStatement* for_of, Expression* each,
                                      Expression* iterable, Statement* body,
                                      int next_result_pos) {
  Variable* iterator =
      scope_->NewTemporary(ast_value_factory()->dot_iterator_string());
  Variable* result =
      scope_->NewTemporary(ast_value_factory()->dot_result_string());

  Expression* assign_iterator;
  Expression* next_result;
  Expression* result_done;
  Expression* assign_each;

  int get_iterator_pos = iterable->position();

  // iterator = iterable[Symbol.iterator]()
  assign_iterator = factory()->NewAssignment(
      Token::ASSIGN, factory()->NewVariableProxy(iterator),
      GetIterator(iterable, factory(), get_iterator_pos), iterable->position());

  // !%_IsJSReceiver(result = iterator.next()) &&
  //     %ThrowIteratorResultNotAnObject(result)
  {
    // result = iterator.next()
    Expression* iterator_proxy = factory()->NewVariableProxy(iterator);
    next_result =
        BuildIteratorNextResult(iterator_proxy, result, next_result_pos);
  }

  // result.done
  {
    Expression* done_literal = factory()->NewStringLiteral(
        ast_value_factory()->done_string(), RelocInfo::kNoPosition);
    Expression* result_proxy = factory()->NewVariableProxy(result);
    result_done = factory()->NewProperty(result_proxy, done_literal,
                                         RelocInfo::kNoPosition);
  }

  // each = result.value
  {
    Expression* value_literal = factory()->NewStringLiteral(
        ast_value_factory()->value_string(), RelocInfo::kNoPosition);
    Expression* result_proxy = factory()->NewVariableProxy(result);
    Expression* result_value = factory()->NewProperty(
        result_proxy, value_literal, RelocInfo::kNoPosition);
    assign_each = factory()->NewAssignment(Token::ASSIGN, each, result_value,
                                           RelocInfo::kNoPosition);
    if (each->IsArrayLiteral() || each->IsObjectLiteral()) {
      assign_each = PatternRewriter::RewriteDestructuringAssignment(
          this, assign_each->AsAssignment(), scope_);
    }
  }

  for_of->Initialize(body, iterator, assign_iterator, next_result, result_done,
                     assign_each);
}

Statement* Parser::DesugarLexicalBindingsInForStatement(
    Scope* inner_scope, VariableMode mode, ZoneList<const AstRawString*>* names,
    ForStatement* loop, Statement* init, Expression* cond, Statement* next,
    Statement* body, bool* ok) {
  // ES6 13.7.4.8 specifies that on each loop iteration the let variables are
  // copied into a new environment.  Moreover, the "next" statement must be
  // evaluated not in the environment of the just completed iteration but in
  // that of the upcoming one.  We achieve this with the following desugaring.
  // Extra care is needed to preserve the completion value of the original loop.
  //
  // We are given a for statement of the form
  //
  //  labels: for (let/const x = i; cond; next) body
  //
  // and rewrite it as follows.  Here we write {{ ... }} for init-blocks, ie.,
  // blocks whose ignore_completion_value_ flag is set.
  //
  //  {
  //    let/const x = i;
  //    temp_x = x;
  //    first = 1;
  //    undefined;
  //    outer: for (;;) {
  //      let/const x = temp_x;
  //      {{ if (first == 1) {
  //           first = 0;
  //         } else {
  //           next;
  //         }
  //         flag = 1;
  //         if (!cond) break;
  //      }}
  //      labels: for (; flag == 1; flag = 0, temp_x = x) {
  //        body
  //      }
  //      {{ if (flag == 1)  // Body used break.
  //           break;
  //      }}
  //    }
  //  }

  DCHECK(names->length() > 0);
  ZoneList<Variable*> temps(names->length(), zone());

  Block* outer_block = factory()->NewBlock(NULL, names->length() + 4, false,
                                           RelocInfo::kNoPosition);

  // Add statement: let/const x = i.
  outer_block->statements()->Add(init, zone());

  const AstRawString* temp_name = ast_value_factory()->dot_for_string();

  // For each lexical variable x:
  //   make statement: temp_x = x.
  for (int i = 0; i < names->length(); i++) {
    VariableProxy* proxy = NewUnresolved(names->at(i), LET);
    Variable* temp = scope_->NewTemporary(temp_name);
    VariableProxy* temp_proxy = factory()->NewVariableProxy(temp);
    Assignment* assignment = factory()->NewAssignment(
        Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
    Statement* assignment_statement = factory()->NewExpressionStatement(
        assignment, RelocInfo::kNoPosition);
    outer_block->statements()->Add(assignment_statement, zone());
    temps.Add(temp, zone());
  }

  Variable* first = NULL;
  // Make statement: first = 1.
  if (next) {
    first = scope_->NewTemporary(temp_name);
    VariableProxy* first_proxy = factory()->NewVariableProxy(first);
    Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
    Assignment* assignment = factory()->NewAssignment(
        Token::ASSIGN, first_proxy, const1, RelocInfo::kNoPosition);
    Statement* assignment_statement =
        factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
    outer_block->statements()->Add(assignment_statement, zone());
  }

  // make statement: undefined;
  outer_block->statements()->Add(
      factory()->NewExpressionStatement(
          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
          RelocInfo::kNoPosition),
      zone());

  // Make statement: outer: for (;;)
  // Note that we don't actually create the label, or set this loop up as an
  // explicit break target, instead handing it directly to those nodes that
  // need to know about it. This should be safe because we don't run any code
  // in this function that looks up break targets.
  ForStatement* outer_loop =
      factory()->NewForStatement(NULL, RelocInfo::kNoPosition);
  outer_block->statements()->Add(outer_loop, zone());
  outer_block->set_scope(scope_);

  Block* inner_block =
      factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);
  {
    BlockState block_state(&scope_, inner_scope);

    Block* ignore_completion_block = factory()->NewBlock(
        NULL, names->length() + 3, true, RelocInfo::kNoPosition);
    ZoneList<Variable*> inner_vars(names->length(), zone());
    // For each let variable x:
    //    make statement: let/const x = temp_x.
    for (int i = 0; i < names->length(); i++) {
      VariableProxy* proxy = NewUnresolved(names->at(i), mode);
      Declaration* declaration = factory()->NewVariableDeclaration(
          proxy, mode, scope_, RelocInfo::kNoPosition);
      Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
      inner_vars.Add(declaration->proxy()->var(), zone());
      VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
      Assignment* assignment = factory()->NewAssignment(
          Token::INIT, proxy, temp_proxy, RelocInfo::kNoPosition);
      Statement* assignment_statement =
          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
      DCHECK(init->position() != RelocInfo::kNoPosition);
      proxy->var()->set_initializer_position(init->position());
      ignore_completion_block->statements()->Add(assignment_statement, zone());
    }

    // Make statement: if (first == 1) { first = 0; } else { next; }
    if (next) {
      DCHECK(first);
      Expression* compare = NULL;
      // Make compare expression: first == 1.
      {
        Expression* const1 =
            factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
        VariableProxy* first_proxy = factory()->NewVariableProxy(first);
        compare = factory()->NewCompareOperation(Token::EQ, first_proxy, const1,
                                                 RelocInfo::kNoPosition);
      }
      Statement* clear_first = NULL;
      // Make statement: first = 0.
      {
        VariableProxy* first_proxy = factory()->NewVariableProxy(first);
        Expression* const0 =
            factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
        Assignment* assignment = factory()->NewAssignment(
            Token::ASSIGN, first_proxy, const0, RelocInfo::kNoPosition);
        clear_first = factory()->NewExpressionStatement(assignment,
                                                        RelocInfo::kNoPosition);
      }
      Statement* clear_first_or_next = factory()->NewIfStatement(
          compare, clear_first, next, RelocInfo::kNoPosition);
      ignore_completion_block->statements()->Add(clear_first_or_next, zone());
    }

    Variable* flag = scope_->NewTemporary(temp_name);
    // Make statement: flag = 1.
    {
      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
      Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
      Assignment* assignment = factory()->NewAssignment(
          Token::ASSIGN, flag_proxy, const1, RelocInfo::kNoPosition);
      Statement* assignment_statement =
          factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
      ignore_completion_block->statements()->Add(assignment_statement, zone());
    }

    // Make statement: if (!cond) break.
    if (cond) {
      Statement* stop =
          factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
      Statement* noop = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
      ignore_completion_block->statements()->Add(
          factory()->NewIfStatement(cond, noop, stop, cond->position()),
          zone());
    }

    inner_block->statements()->Add(ignore_completion_block, zone());
    // Make cond expression for main loop: flag == 1.
    Expression* flag_cond = NULL;
    {
      Expression* const1 = factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
      VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
      flag_cond = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
                                                 RelocInfo::kNoPosition);
    }

    // Create chain of expressions "flag = 0, temp_x = x, ..."
    Statement* compound_next_statement = NULL;
    {
      Expression* compound_next = NULL;
      // Make expression: flag = 0.
      {
        VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
        Expression* const0 =
            factory()->NewSmiLiteral(0, RelocInfo::kNoPosition);
        compound_next = factory()->NewAssignment(
            Token::ASSIGN, flag_proxy, const0, RelocInfo::kNoPosition);
      }

      // Make the comma-separated list of temp_x = x assignments.
      int inner_var_proxy_pos = scanner()->location().beg_pos;
      for (int i = 0; i < names->length(); i++) {
        VariableProxy* temp_proxy = factory()->NewVariableProxy(temps.at(i));
        VariableProxy* proxy =
            factory()->NewVariableProxy(inner_vars.at(i), inner_var_proxy_pos);
        Assignment* assignment = factory()->NewAssignment(
            Token::ASSIGN, temp_proxy, proxy, RelocInfo::kNoPosition);
        compound_next = factory()->NewBinaryOperation(
            Token::COMMA, compound_next, assignment, RelocInfo::kNoPosition);
      }

      compound_next_statement = factory()->NewExpressionStatement(
          compound_next, RelocInfo::kNoPosition);
    }

    // Make statement: labels: for (; flag == 1; flag = 0, temp_x = x)
    // Note that we re-use the original loop node, which retains its labels
    // and ensures that any break or continue statements in body point to
    // the right place.
    loop->Initialize(NULL, flag_cond, compound_next_statement, body);
    inner_block->statements()->Add(loop, zone());

    // Make statement: {{if (flag == 1) break;}}
    {
      Expression* compare = NULL;
      // Make compare expresion: flag == 1.
      {
        Expression* const1 =
            factory()->NewSmiLiteral(1, RelocInfo::kNoPosition);
        VariableProxy* flag_proxy = factory()->NewVariableProxy(flag);
        compare = factory()->NewCompareOperation(Token::EQ, flag_proxy, const1,
                                                 RelocInfo::kNoPosition);
      }
      Statement* stop =
          factory()->NewBreakStatement(outer_loop, RelocInfo::kNoPosition);
      Statement* empty = factory()->NewEmptyStatement(RelocInfo::kNoPosition);
      Statement* if_flag_break = factory()->NewIfStatement(
          compare, stop, empty, RelocInfo::kNoPosition);
      Block* ignore_completion_block =
          factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
      ignore_completion_block->statements()->Add(if_flag_break, zone());
      inner_block->statements()->Add(ignore_completion_block, zone());
    }

    inner_scope->set_end_position(scanner()->location().end_pos);
    inner_block->set_scope(inner_scope);
  }

  outer_loop->Initialize(NULL, NULL, NULL, inner_block);
  return outer_block;
}

Statement* Parser::ParseScopedStatement(ZoneList<const AstRawString*>* labels,
                                        bool legacy, bool* ok) {
  if (is_strict(language_mode()) || peek() != Token::FUNCTION ||
      (legacy && allow_harmony_restrictive_declarations())) {
    return ParseSubStatement(labels, kDisallowLabelledFunctionStatement, ok);
  } else {
    if (legacy) {
      ++use_counts_[v8::Isolate::kLegacyFunctionDeclaration];
    }
    // Make a block around the statement for a lexical binding
    // is introduced by a FunctionDeclaration.
    Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
    body_scope->set_start_position(scanner()->location().beg_pos);
    BlockState block_state(&scope_, body_scope);
    Block* block = factory()->NewBlock(NULL, 1, false, RelocInfo::kNoPosition);
    Statement* body = ParseFunctionDeclaration(CHECK_OK);
    block->statements()->Add(body, zone());
    body_scope->set_end_position(scanner()->location().end_pos);
    body_scope = body_scope->FinalizeBlockScope();
    block->set_scope(body_scope);
    return block;
  }
}

Statement* Parser::ParseForStatement(ZoneList<const AstRawString*>* labels,
                                     bool* ok) {
  int stmt_pos = peek_position();
  Statement* init = NULL;
  ZoneList<const AstRawString*> lexical_bindings(1, zone());

  // Create an in-between scope for let-bound iteration variables.
  Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);

  BlockState block_state(&scope_, for_scope);
  Expect(Token::FOR, CHECK_OK);
  Expect(Token::LPAREN, CHECK_OK);
  for_scope->set_start_position(scanner()->location().beg_pos);
  for_scope->set_is_hidden();
  DeclarationParsingResult parsing_result;
  if (peek() != Token::SEMICOLON) {
    if (peek() == Token::VAR || peek() == Token::CONST ||
        (peek() == Token::LET && IsNextLetKeyword())) {
      ParseVariableDeclarations(kForStatement, &parsing_result, nullptr,
                                CHECK_OK);

      ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;
      int each_beg_pos = scanner()->location().beg_pos;
      int each_end_pos = scanner()->location().end_pos;

      if (CheckInOrOf(&mode, ok)) {
        if (!*ok) return nullptr;
        if (parsing_result.declarations.length() != 1) {
          ParserTraits::ReportMessageAt(
              parsing_result.bindings_loc,
              MessageTemplate::kForInOfLoopMultiBindings,
              ForEachStatement::VisitModeString(mode));
          *ok = false;
          return nullptr;
        }
        DeclarationParsingResult::Declaration& decl =
            parsing_result.declarations[0];
        if (parsing_result.first_initializer_loc.IsValid() &&
            (is_strict(language_mode()) || mode == ForEachStatement::ITERATE ||
             IsLexicalVariableMode(parsing_result.descriptor.mode) ||
             !decl.pattern->IsVariableProxy() || allow_harmony_for_in())) {
          // Only increment the use count if we would have let this through
          // without the flag.
          if (allow_harmony_for_in()) {
            ++use_counts_[v8::Isolate::kForInInitializer];
          }
          ParserTraits::ReportMessageAt(
              parsing_result.first_initializer_loc,
              MessageTemplate::kForInOfLoopInitializer,
              ForEachStatement::VisitModeString(mode));
          *ok = false;
          return nullptr;
        }

        Block* init_block = nullptr;

        // special case for legacy for (var/const x =.... in)
        if (!IsLexicalVariableMode(parsing_result.descriptor.mode) &&
            decl.pattern->IsVariableProxy() && decl.initializer != nullptr) {
          DCHECK(!allow_harmony_for_in());
          ++use_counts_[v8::Isolate::kForInInitializer];
          const AstRawString* name =
              decl.pattern->AsVariableProxy()->raw_name();
          VariableProxy* single_var = scope_->NewUnresolved(
              factory(), name, Variable::NORMAL, each_beg_pos, each_end_pos);
          init_block = factory()->NewBlock(
              nullptr, 2, true, parsing_result.descriptor.declaration_pos);
          init_block->statements()->Add(
              factory()->NewExpressionStatement(
                  factory()->NewAssignment(Token::ASSIGN, single_var,
                                           decl.initializer,
                                           RelocInfo::kNoPosition),
                  RelocInfo::kNoPosition),
              zone());
        }

        // Rewrite a for-in/of statement of the form
        //
        //   for (let/const/var x in/of e) b
        //
        // into
        //
        //   {
        //     <let x' be a temporary variable>
        //     for (x' in/of e) {
        //       let/const/var x;
        //       x = x';
        //       b;
        //     }
        //     let x;  // for TDZ
        //   }

        Variable* temp =
            scope_->NewTemporary(ast_value_factory()->dot_for_string());
        ForEachStatement* loop =
            factory()->NewForEachStatement(mode, labels, stmt_pos);
        Target target(&this->target_stack_, loop);

        int each_keyword_position = scanner()->location().beg_pos;

        Expression* enumerable;
        if (mode == ForEachStatement::ITERATE) {
          ExpressionClassifier classifier(this);
          enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
          RewriteNonPattern(&classifier, CHECK_OK);
        } else {
          enumerable = ParseExpression(true, CHECK_OK);
        }

        Expect(Token::RPAREN, CHECK_OK);

        Scope* body_scope = NewScope(scope_, BLOCK_SCOPE);
        body_scope->set_start_position(scanner()->location().beg_pos);

        Block* body_block =
            factory()->NewBlock(NULL, 3, false, RelocInfo::kNoPosition);

        {
          ReturnExprScope no_tail_calls(function_state_,
                                        ReturnExprContext::kInsideForInOfBody);
          BlockState block_state(&scope_, body_scope);

          Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);

          auto each_initialization_block =
              factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
          {
            auto descriptor = parsing_result.descriptor;
            descriptor.declaration_pos = RelocInfo::kNoPosition;
            descriptor.initialization_pos = RelocInfo::kNoPosition;
            decl.initializer = factory()->NewVariableProxy(temp);

            PatternRewriter::DeclareAndInitializeVariables(
                each_initialization_block, &descriptor, &decl,
                IsLexicalVariableMode(descriptor.mode) ? &lexical_bindings
                                                       : nullptr,
                CHECK_OK);
          }

          body_block->statements()->Add(each_initialization_block, zone());
          body_block->statements()->Add(body, zone());
          VariableProxy* temp_proxy =
              factory()->NewVariableProxy(temp, each_beg_pos, each_end_pos);
          InitializeForEachStatement(loop, temp_proxy, enumerable, body_block,
                                     each_keyword_position);
        }
        body_scope->set_end_position(scanner()->location().end_pos);
        body_scope = body_scope->FinalizeBlockScope();
        body_block->set_scope(body_scope);

        // Create a TDZ for any lexically-bound names.
        if (IsLexicalVariableMode(parsing_result.descriptor.mode)) {
          DCHECK_NULL(init_block);

          init_block =
              factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);

          for (int i = 0; i < lexical_bindings.length(); ++i) {
            // TODO(adamk): This needs to be some sort of special
            // INTERNAL variable that's invisible to the debugger
            // but visible to everything else.
            VariableProxy* tdz_proxy =
                NewUnresolved(lexical_bindings[i], LET);
            Declaration* tdz_decl = factory()->NewVariableDeclaration(
                tdz_proxy, LET, scope_, RelocInfo::kNoPosition);
            Variable* tdz_var = Declare(
                tdz_decl, DeclarationDescriptor::NORMAL, true, CHECK_OK);
            tdz_var->set_initializer_position(position());
          }
        }

        Statement* final_loop = loop->IsForOfStatement()
            ? FinalizeForOfStatement(
                loop->AsForOfStatement(), RelocInfo::kNoPosition)
            : loop;

        for_scope->set_end_position(scanner()->location().end_pos);
        for_scope = for_scope->FinalizeBlockScope();
        // Parsed for-in loop w/ variable declarations.
        if (init_block != nullptr) {
          init_block->statements()->Add(final_loop, zone());
          init_block->set_scope(for_scope);
          return init_block;
        } else {
          DCHECK_NULL(for_scope);
          return final_loop;
        }
      } else {
        init = parsing_result.BuildInitializationBlock(
            IsLexicalVariableMode(parsing_result.descriptor.mode)
                ? &lexical_bindings
                : nullptr,
            CHECK_OK);
      }
    } else {
      int lhs_beg_pos = peek_position();
      ExpressionClassifier classifier(this);
      Expression* expression = ParseExpression(false, &classifier, CHECK_OK);
      int lhs_end_pos = scanner()->location().end_pos;
      ForEachStatement::VisitMode mode = ForEachStatement::ENUMERATE;

      bool is_for_each = CheckInOrOf(&mode, ok);
      if (!*ok) return nullptr;
      bool is_destructuring = is_for_each && (expression->IsArrayLiteral() ||
                                              expression->IsObjectLiteral());

      if (is_destructuring) {
        ValidateAssignmentPattern(&classifier, CHECK_OK);
      } else {
        RewriteNonPattern(&classifier, CHECK_OK);
      }

      if (is_for_each) {
        if (!is_destructuring) {
          expression = this->CheckAndRewriteReferenceExpression(
              expression, lhs_beg_pos, lhs_end_pos,
              MessageTemplate::kInvalidLhsInFor, kSyntaxError, CHECK_OK);
        }

        ForEachStatement* loop =
            factory()->NewForEachStatement(mode, labels, stmt_pos);
        Target target(&this->target_stack_, loop);

        int each_keyword_position = scanner()->location().beg_pos;

        Expression* enumerable;
        if (mode == ForEachStatement::ITERATE) {
          ExpressionClassifier classifier(this);
          enumerable = ParseAssignmentExpression(true, &classifier, CHECK_OK);
          RewriteNonPattern(&classifier, CHECK_OK);
        } else {
          enumerable = ParseExpression(true, CHECK_OK);
        }

        Expect(Token::RPAREN, CHECK_OK);

        // For legacy compat reasons, give for loops similar treatment to
        // if statements in allowing a function declaration for a body
        Statement* body = ParseScopedStatement(NULL, true, CHECK_OK);
        InitializeForEachStatement(loop, expression, enumerable, body,
                                   each_keyword_position);

        Statement* final_loop = loop->IsForOfStatement()
            ? FinalizeForOfStatement(
                loop->AsForOfStatement(), RelocInfo::kNoPosition)
            : loop;

        for_scope->set_end_position(scanner()->location().end_pos);
        for_scope = for_scope->FinalizeBlockScope();
        DCHECK(for_scope == nullptr);
        return final_loop;

      } else {
        init = factory()->NewExpressionStatement(expression, lhs_beg_pos);
      }
    }
  }

  // Standard 'for' loop
  ForStatement* loop = factory()->NewForStatement(labels, stmt_pos);
  Target target(&this->target_stack_, loop);

  // Parsed initializer at this point.
  Expect(Token::SEMICOLON, CHECK_OK);

  Expression* cond = NULL;
  Statement* next = NULL;
  Statement* body = NULL;

  // If there are let bindings, then condition and the next statement of the
  // for loop must be parsed in a new scope.
  Scope* inner_scope = scope_;
  if (lexical_bindings.length() > 0) {
    inner_scope = NewScope(for_scope, BLOCK_SCOPE);
    inner_scope->set_start_position(scanner()->location().beg_pos);
  }
  {
    BlockState block_state(&scope_, inner_scope);

    if (peek() != Token::SEMICOLON) {
      cond = ParseExpression(true, CHECK_OK);
    }
    Expect(Token::SEMICOLON, CHECK_OK);

    if (peek() != Token::RPAREN) {
      Expression* exp = ParseExpression(true, CHECK_OK);
      next = factory()->NewExpressionStatement(exp, exp->position());
    }
    Expect(Token::RPAREN, CHECK_OK);

    body = ParseScopedStatement(NULL, true, CHECK_OK);
  }

  Statement* result = NULL;
  if (lexical_bindings.length() > 0) {
    BlockState block_state(&scope_, for_scope);
    result = DesugarLexicalBindingsInForStatement(
        inner_scope, parsing_result.descriptor.mode, &lexical_bindings, loop,
        init, cond, next, body, CHECK_OK);
    for_scope->set_end_position(scanner()->location().end_pos);
  } else {
    for_scope->set_end_position(scanner()->location().end_pos);
    for_scope = for_scope->FinalizeBlockScope();
    if (for_scope) {
      // Rewrite a for statement of the form
      //   for (const x = i; c; n) b
      //
      // into
      //
      //   {
      //     const x = i;
      //     for (; c; n) b
      //   }
      //
      // or, desugar
      //   for (; c; n) b
      // into
      //   {
      //     for (; c; n) b
      //   }
      // just in case b introduces a lexical binding some other way, e.g., if b
      // is a FunctionDeclaration.
      Block* block =
          factory()->NewBlock(NULL, 2, false, RelocInfo::kNoPosition);
      if (init != nullptr) {
        block->statements()->Add(init, zone());
      }
      block->statements()->Add(loop, zone());
      block->set_scope(for_scope);
      loop->Initialize(NULL, cond, next, body);
      result = block;
    } else {
      loop->Initialize(init, cond, next, body);
      result = loop;
    }
  }
  return result;
}


DebuggerStatement* Parser::ParseDebuggerStatement(bool* ok) {
  // In ECMA-262 'debugger' is defined as a reserved keyword. In some browser
  // contexts this is used as a statement which invokes the debugger as i a
  // break point is present.
  // DebuggerStatement ::
  //   'debugger' ';'

  int pos = peek_position();
  Expect(Token::DEBUGGER, CHECK_OK);
  ExpectSemicolon(CHECK_OK);
  return factory()->NewDebuggerStatement(pos);
}


bool CompileTimeValue::IsCompileTimeValue(Expression* expression) {
  if (expression->IsLiteral()) return true;
  MaterializedLiteral* lit = expression->AsMaterializedLiteral();
  return lit != NULL && lit->is_simple();
}


Handle<FixedArray> CompileTimeValue::GetValue(Isolate* isolate,
                                              Expression* expression) {
  Factory* factory = isolate->factory();
  DCHECK(IsCompileTimeValue(expression));
  Handle<FixedArray> result = factory->NewFixedArray(2, TENURED);
  ObjectLiteral* object_literal = expression->AsObjectLiteral();
  if (object_literal != NULL) {
    DCHECK(object_literal->is_simple());
    if (object_literal->fast_elements()) {
      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_FAST_ELEMENTS));
    } else {
      result->set(kLiteralTypeSlot, Smi::FromInt(OBJECT_LITERAL_SLOW_ELEMENTS));
    }
    result->set(kElementsSlot, *object_literal->constant_properties());
  } else {
    ArrayLiteral* array_literal = expression->AsArrayLiteral();
    DCHECK(array_literal != NULL && array_literal->is_simple());
    result->set(kLiteralTypeSlot, Smi::FromInt(ARRAY_LITERAL));
    result->set(kElementsSlot, *array_literal->constant_elements());
  }
  return result;
}


CompileTimeValue::LiteralType CompileTimeValue::GetLiteralType(
    Handle<FixedArray> value) {
  Smi* literal_type = Smi::cast(value->get(kLiteralTypeSlot));
  return static_cast<LiteralType>(literal_type->value());
}


Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
  return Handle<FixedArray>(FixedArray::cast(value->get(kElementsSlot)));
}

void ParserTraits::ParseArrowFunctionFormalParameters(
    ParserFormalParameters* parameters, Expression* expr, int end_pos,
    bool* ok) {
  // ArrowFunctionFormals ::
  //    Binary(Token::COMMA, NonTailArrowFunctionFormals, Tail)
  //    Tail
  // NonTailArrowFunctionFormals ::
  //    Binary(Token::COMMA, NonTailArrowFunctionFormals, VariableProxy)
  //    VariableProxy
  // Tail ::
  //    VariableProxy
  //    Spread(VariableProxy)
  //
  // As we need to visit the parameters in left-to-right order, we recurse on
  // the left-hand side of comma expressions.
  //
  if (expr->IsBinaryOperation()) {
    BinaryOperation* binop = expr->AsBinaryOperation();
    // The classifier has already run, so we know that the expression is a valid
    // arrow function formals production.
    DCHECK_EQ(binop->op(), Token::COMMA);
    Expression* left = binop->left();
    Expression* right = binop->right();
    int comma_pos = binop->position();
    ParseArrowFunctionFormalParameters(parameters, left, comma_pos, ok);
    if (!*ok) return;
    // LHS of comma expression should be unparenthesized.
    expr = right;
  }

  // Only the right-most expression may be a rest parameter.
  DCHECK(!parameters->has_rest);

  bool is_rest = expr->IsSpread();
  if (is_rest) {
    expr = expr->AsSpread()->expression();
    parameters->has_rest = true;
  }
  if (parameters->is_simple) {
    parameters->is_simple = !is_rest && expr->IsVariableProxy();
  }

  Expression* initializer = nullptr;
  if (expr->IsVariableProxy()) {
    // When the formal parameter was originally seen, it was parsed as a
    // VariableProxy and recorded as unresolved in the scope.  Here we undo that
    // parse-time side-effect for parameters that are single-names (not
    // patterns; for patterns that happens uniformly in
    // PatternRewriter::VisitVariableProxy).
    parser_->scope_->RemoveUnresolved(expr->AsVariableProxy());
  } else if (expr->IsAssignment()) {
    Assignment* assignment = expr->AsAssignment();
    DCHECK(!assignment->is_compound());
    initializer = assignment->value();
    expr = assignment->target();

    // TODO(adamk): Only call this if necessary.
    RewriteParameterInitializerScope(parser_->stack_limit(), initializer,
                                     parser_->scope_, parameters->scope);
  }

  AddFormalParameter(parameters, expr, initializer, end_pos, is_rest);
}

void ParserTraits::ParseAsyncArrowSingleExpressionBody(
    ZoneList<Statement*>* body, bool accept_IN,
    Type::ExpressionClassifier* classifier, int pos, bool* ok) {
  parser_->DesugarAsyncFunctionBody(
      parser_->ast_value_factory()->empty_string(), parser_->scope_, body,
      classifier, kAsyncArrowFunction, FunctionBody::SingleExpression,
      accept_IN, pos, ok);
}

void Parser::DesugarAsyncFunctionBody(const AstRawString* function_name,
                                      Scope* scope, ZoneList<Statement*>* body,
                                      ExpressionClassifier* classifier,
                                      FunctionKind kind, FunctionBody body_type,
                                      bool accept_IN, int pos, bool* ok) {
  // function async_function() {
  //   try {
  //     .generator_object = %CreateGeneratorObject();
  //     ... function body ...
  //   } catch (e) {
  //     return Promise.reject(e);
  //   }
  // }
  scope->ForceContextAllocation();
  Variable* temp =
      scope_->NewTemporary(ast_value_factory()->dot_generator_object_string());
  function_state_->set_generator_object_variable(temp);

  Expression* init_generator_variable = factory()->NewAssignment(
      Token::INIT, factory()->NewVariableProxy(temp),
      BuildCreateJSGeneratorObject(pos, kind), RelocInfo::kNoPosition);
  body->Add(factory()->NewExpressionStatement(init_generator_variable,
                                              RelocInfo::kNoPosition),
            zone());

  Block* try_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);

  ZoneList<Statement*>* inner_body = try_block->statements();

  Expression* return_value = nullptr;
  if (body_type == FunctionBody::Normal) {
    ParseStatementList(inner_body, Token::RBRACE, ok);
    if (!*ok) return;
    return_value = factory()->NewUndefinedLiteral(RelocInfo::kNoPosition);
  } else {
    return_value = ParseAssignmentExpression(accept_IN, classifier, ok);
    if (!*ok) return;
    ParserTraits::RewriteNonPattern(classifier, ok);
    if (!*ok) return;
  }

  return_value = BuildPromiseResolve(return_value, return_value->position());
  inner_body->Add(
      factory()->NewReturnStatement(return_value, return_value->position()),
      zone());
  body->Add(BuildRejectPromiseOnException(try_block), zone());
  scope->set_end_position(scanner()->location().end_pos);
}

DoExpression* Parser::ParseDoExpression(bool* ok) {
  // AssignmentExpression ::
  //     do '{' StatementList '}'
  int pos = peek_position();

  Expect(Token::DO, CHECK_OK);
  Variable* result =
      scope_->NewTemporary(ast_value_factory()->dot_result_string());
  Block* block = ParseBlock(nullptr, false, CHECK_OK);
  DoExpression* expr = factory()->NewDoExpression(block, result, pos);
  if (!Rewriter::Rewrite(this, expr, ast_value_factory())) {
    *ok = false;
    return nullptr;
  }
  block->set_scope(block->scope()->FinalizeBlockScope());
  return expr;
}


void ParserTraits::ParseArrowFunctionFormalParameterList(
    ParserFormalParameters* parameters, Expression* expr,
    const Scanner::Location& params_loc,
    Scanner::Location* duplicate_loc, bool* ok) {
  if (expr->IsEmptyParentheses()) return;

  ParseArrowFunctionFormalParameters(parameters, expr, params_loc.end_pos, ok);
  if (!*ok) return;

  if (parameters->Arity() > Code::kMaxArguments) {
    ReportMessageAt(params_loc, MessageTemplate::kMalformedArrowFunParamList);
    *ok = false;
    return;
  }

  Type::ExpressionClassifier classifier(parser_);
  if (!parameters->is_simple) {
    classifier.RecordNonSimpleParameter();
  }
  for (int i = 0; i < parameters->Arity(); ++i) {
    auto parameter = parameters->at(i);
    DeclareFormalParameter(parameters->scope, parameter, &classifier);
    if (!duplicate_loc->IsValid()) {
      *duplicate_loc = classifier.duplicate_formal_parameter_error().location;
    }
  }
  DCHECK_EQ(parameters->is_simple, parameters->scope->has_simple_parameters());
}


void ParserTraits::ReindexLiterals(const ParserFormalParameters& parameters) {
  if (parser_->function_state_->materialized_literal_count() > 0) {
    AstLiteralReindexer reindexer;

    for (const auto p : parameters.params) {
      if (p.pattern != nullptr) reindexer.Reindex(p.pattern);
      if (p.initializer != nullptr) reindexer.Reindex(p.initializer);
    }

    DCHECK(reindexer.count() <=
           parser_->function_state_->materialized_literal_count());
  }
}


FunctionLiteral* Parser::ParseFunctionLiteral(
    const AstRawString* function_name, Scanner::Location function_name_location,
    FunctionNameValidity function_name_validity, FunctionKind kind,
    int function_token_pos, FunctionLiteral::FunctionType function_type,
    LanguageMode language_mode, bool* ok) {
  // Function ::
  //   '(' FormalParameterList? ')' '{' FunctionBody '}'
  //
  // Getter ::
  //   '(' ')' '{' FunctionBody '}'
  //
  // Setter ::
  //   '(' PropertySetParameterList ')' '{' FunctionBody '}'

  int pos = function_token_pos == RelocInfo::kNoPosition
      ? peek_position() : function_token_pos;

  bool is_generator = IsGeneratorFunction(kind);

  // Anonymous functions were passed either the empty symbol or a null
  // handle as the function name.  Remember if we were passed a non-empty
  // handle to decide whether to invoke function name inference.
  bool should_infer_name = function_name == NULL;

  // We want a non-null handle as the function name.
  if (should_infer_name) {
    function_name = ast_value_factory()->empty_string();
  }

  Scope* scope = NewScope(scope_, FUNCTION_SCOPE, kind);
  SetLanguageMode(scope, language_mode);
  ZoneList<Statement*>* body = NULL;
  int arity = -1;
  int materialized_literal_count = -1;
  int expected_property_count = -1;
  DuplicateFinder duplicate_finder(scanner()->unicode_cache());
  bool should_be_used_once_hint = false;
  bool has_duplicate_parameters;
  FunctionLiteral::EagerCompileHint eager_compile_hint;

  // Parse function.
  {
    AstNodeFactory function_factory(ast_value_factory());
    FunctionState function_state(&function_state_, &scope_, scope, kind,
                                 &function_factory);
    scope_->SetScopeName(function_name);
    ExpressionClassifier formals_classifier(this, &duplicate_finder);

    eager_compile_hint = function_state_->this_function_is_parenthesized()
                             ? FunctionLiteral::kShouldEagerCompile
                             : FunctionLiteral::kShouldLazyCompile;

    if (is_generator) {
      // For generators, allocating variables in contexts is currently a win
      // because it minimizes the work needed to suspend and resume an
      // activation.  The machine code produced for generators (by full-codegen)
      // relies on this forced context allocation, but not in an essential way.
      scope_->ForceContextAllocation();

      // Calling a generator returns a generator object.  That object is stored
      // in a temporary variable, a definition that is used by "yield"
      // expressions. This also marks the FunctionState as a generator.
      Variable* temp = scope_->NewTemporary(
          ast_value_factory()->dot_generator_object_string());
      function_state.set_generator_object_variable(temp);
    }

    Expect(Token::LPAREN, CHECK_OK);
    int start_position = scanner()->location().beg_pos;
    scope_->set_start_position(start_position);
    ParserFormalParameters formals(scope);
    ParseFormalParameterList(&formals, &formals_classifier, CHECK_OK);
    arity = formals.Arity();
    Expect(Token::RPAREN, CHECK_OK);
    int formals_end_position = scanner()->location().end_pos;

    CheckArityRestrictions(arity, kind, formals.has_rest, start_position,
                           formals_end_position, CHECK_OK);
    Expect(Token::LBRACE, CHECK_OK);
    // Don't include the rest parameter into the function's formal parameter
    // count (esp. the SharedFunctionInfo::internal_formal_parameter_count,
    // which says whether we need to create an arguments adaptor frame).
    if (formals.has_rest) arity--;

    // Determine if the function can be parsed lazily. Lazy parsing is different
    // from lazy compilation; we need to parse more eagerly than we compile.

    // We can only parse lazily if we also compile lazily. The heuristics for
    // lazy compilation are:
    // - It must not have been prohibited by the caller to Parse (some callers
    //   need a full AST).
    // - The outer scope must allow lazy compilation of inner functions.
    // - The function mustn't be a function expression with an open parenthesis
    //   before; we consider that a hint that the function will be called
    //   immediately, and it would be a waste of time to make it lazily
    //   compiled.
    // These are all things we can know at this point, without looking at the
    // function itself.

    // In addition, we need to distinguish between these cases:
    // (function foo() {
    //   bar = function() { return 1; }
    //  })();
    // and
    // (function foo() {
    //   var a = 1;
    //   bar = function() { return a; }
    //  })();

    // Now foo will be parsed eagerly and compiled eagerly (optimization: assume
    // parenthesis before the function means that it will be called
    // immediately). The inner function *must* be parsed eagerly to resolve the
    // possible reference to the variable in foo's scope. However, it's possible
    // that it will be compiled lazily.

    // To make this additional case work, both Parser and PreParser implement a
    // logic where only top-level functions will be parsed lazily.
    bool is_lazily_parsed = mode() == PARSE_LAZILY &&
                            scope_->AllowsLazyParsing() &&
                            !function_state_->this_function_is_parenthesized();

    // Eager or lazy parse?
    // If is_lazily_parsed, we'll parse lazy. If we can set a bookmark, we'll
    // pass it to SkipLazyFunctionBody, which may use it to abort lazy
    // parsing if it suspect that wasn't a good idea. If so, or if we didn't
    // try to lazy parse in the first place, we'll have to parse eagerly.
    Scanner::BookmarkScope bookmark(scanner());
    if (is_lazily_parsed) {
      Scanner::BookmarkScope* maybe_bookmark =
          bookmark.Set() ? &bookmark : nullptr;
      SkipLazyFunctionBody(&materialized_literal_count,
                           &expected_property_count, /*CHECK_OK*/ ok,
                           maybe_bookmark);

      materialized_literal_count += formals.materialized_literals_count +
                                    function_state.materialized_literal_count();

      if (bookmark.HasBeenReset()) {
        // Trigger eager (re-)parsing, just below this block.
        is_lazily_parsed = false;

        // This is probably an initialization function. Inform the compiler it
        // should also eager-compile this function, and that we expect it to be
        // used once.
        eager_compile_hint = FunctionLiteral::kShouldEagerCompile;
        should_be_used_once_hint = true;
      }
    }
    if (!is_lazily_parsed) {
      // Determine whether the function body can be discarded after parsing.
      // The preconditions are:
      // - Lazy compilation has to be enabled.
      // - Neither V8 natives nor native function declarations can be allowed,
      //   since parsing one would retroactively force the function to be
      //   eagerly compiled.
      // - The invoker of this parser can't depend on the AST being eagerly
      //   built (either because the function is about to be compiled, or
      //   because the AST is going to be inspected for some reason).
      // - Because of the above, we can't be attempting to parse a
      //   FunctionExpression; even without enclosing parentheses it might be
      //   immediately invoked.
      // - The function literal shouldn't be hinted to eagerly compile.
      // - For asm.js functions the body needs to be available when module
      //   validation is active, because we examine the entire module at once.
      bool use_temp_zone =
          FLAG_lazy && !allow_natives() && extension_ == NULL && allow_lazy() &&
          function_type == FunctionLiteral::kDeclaration &&
          eager_compile_hint != FunctionLiteral::kShouldEagerCompile &&
          !(FLAG_validate_asm && scope->asm_function());
      // Open a new BodyScope, which sets our AstNodeFactory to allocate in the
      // new temporary zone if the preconditions are satisfied, and ensures that
      // the previous zone is always restored after parsing the body.
      // For the purpose of scope analysis, some ZoneObjects allocated by the
      // factory must persist after the function body is thrown away and
      // temp_zone is deallocated. These objects are instead allocated in a
      // parser-persistent zone (see parser_zone_ in AstNodeFactory).
      {
        Zone temp_zone(zone()->allocator());
        AstNodeFactory::BodyScope inner(factory(), &temp_zone, use_temp_zone);

        body = ParseEagerFunctionBody(function_name, pos, formals, kind,
                                      function_type, CHECK_OK);
      }
      materialized_literal_count = function_state.materialized_literal_count();
      expected_property_count = function_state.expected_property_count();
      if (use_temp_zone) {
        // If the preconditions are correct the function body should never be
        // accessed, but do this anyway for better behaviour if they're wrong.
        body = NULL;
      }
    }

    // Parsing the body may change the language mode in our scope.
    language_mode = scope->language_mode();

    // Validate name and parameter names. We can do this only after parsing the
    // function, since the function can declare itself strict.
    CheckFunctionName(language_mode, function_name, function_name_validity,
                      function_name_location, CHECK_OK);
    const bool allow_duplicate_parameters =
        is_sloppy(language_mode) && formals.is_simple && !IsConciseMethod(kind);
    ValidateFormalParameters(&formals_classifier, language_mode,
                             allow_duplicate_parameters, CHECK_OK);

    if (is_strict(language_mode)) {
      CheckStrictOctalLiteral(scope->start_position(), scope->end_position(),
                              CHECK_OK);
      CheckDecimalLiteralWithLeadingZero(use_counts_, scope->start_position(),
                                         scope->end_position());
    }
    if (is_sloppy(language_mode)) {
      InsertSloppyBlockFunctionVarBindings(scope, CHECK_OK);
    }
    CheckConflictingVarDeclarations(scope, CHECK_OK);

    if (body) {
      // If body can be inspected, rewrite queued destructuring assignments
      ParserTraits::RewriteDestructuringAssignments();
    }
    has_duplicate_parameters =
      !formals_classifier.is_valid_formal_parameter_list_without_duplicates();
  }

  FunctionLiteral::ParameterFlag duplicate_parameters =
      has_duplicate_parameters ? FunctionLiteral::kHasDuplicateParameters
                               : FunctionLiteral::kNoDuplicateParameters;

  FunctionLiteral* function_literal = factory()->NewFunctionLiteral(
      function_name, scope, body, materialized_literal_count,
      expected_property_count, arity, duplicate_parameters, function_type,
      eager_compile_hint, kind, pos);
  function_literal->set_function_token_position(function_token_pos);
  if (should_be_used_once_hint)
    function_literal->set_should_be_used_once_hint();

  if (fni_ != NULL && should_infer_name) fni_->AddFunction(function_literal);
  return function_literal;
}

Expression* Parser::ParseAsyncFunctionExpression(bool* ok) {
  // AsyncFunctionDeclaration ::
  //   async [no LineTerminator here] function ( FormalParameters[Await] )
  //       { AsyncFunctionBody }
  //
  //   async [no LineTerminator here] function BindingIdentifier[Await]
  //       ( FormalParameters[Await] ) { AsyncFunctionBody }
  DCHECK_EQ(scanner()->current_token(), Token::ASYNC);
  int pos = position();
  Expect(Token::FUNCTION, CHECK_OK);
  bool is_strict_reserved = false;
  const AstRawString* name = nullptr;
  FunctionLiteral::FunctionType type = FunctionLiteral::kAnonymousExpression;

  if (peek_any_identifier()) {
    type = FunctionLiteral::kNamedExpression;
    name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved, CHECK_OK);
    if (this->IsAwait(name)) {
      ReportMessageAt(scanner()->location(),
                      MessageTemplate::kAwaitBindingIdentifier);
      *ok = false;
      return nullptr;
    }
  }
  return ParseFunctionLiteral(name, scanner()->location(),
                              is_strict_reserved ? kFunctionNameIsStrictReserved
                                                 : kFunctionNameValidityUnknown,
                              FunctionKind::kAsyncFunction, pos, type,
                              language_mode(), CHECK_OK);
}

void Parser::SkipLazyFunctionBody(int* materialized_literal_count,
                                  int* expected_property_count, bool* ok,
                                  Scanner::BookmarkScope* bookmark) {
  DCHECK_IMPLIES(bookmark, bookmark->HasBeenSet());
  if (produce_cached_parse_data()) CHECK(log_);

  int function_block_pos = position();
  if (consume_cached_parse_data() && !cached_parse_data_->rejected()) {
    // If we have cached data, we use it to skip parsing the function body. The
    // data contains the information we need to construct the lazy function.
    FunctionEntry entry =
        cached_parse_data_->GetFunctionEntry(function_block_pos);
    // Check that cached data is valid. If not, mark it as invalid (the embedder
    // handles it). Note that end position greater than end of stream is safe,
    // and hard to check.
    if (entry.is_valid() && entry.end_pos() > function_block_pos) {
      scanner()->SeekForward(entry.end_pos() - 1);

      scope_->set_end_position(entry.end_pos());
      Expect(Token::RBRACE, ok);
      if (!*ok) {
        return;
      }
      total_preparse_skipped_ += scope_->end_position() - function_block_pos;
      *materialized_literal_count = entry.literal_count();
      *expected_property_count = entry.property_count();
      SetLanguageMode(scope_, entry.language_mode());
      if (entry.uses_super_property()) scope_->RecordSuperPropertyUsage();
      if (entry.calls_eval()) scope_->RecordEvalCall();
      return;
    }
    cached_parse_data_->Reject();
  }
  // With no cached data, we partially parse the function, without building an
  // AST. This gathers the data needed to build a lazy function.
  SingletonLogger logger;
  PreParser::PreParseResult result =
      ParseLazyFunctionBodyWithPreParser(&logger, bookmark);
  if (bookmark && bookmark->HasBeenReset()) {
    return;  // Return immediately if pre-parser devided to abort parsing.
  }
  if (result == PreParser::kPreParseStackOverflow) {
    // Propagate stack overflow.
    set_stack_overflow();
    *ok = false;
    return;
  }
  if (logger.has_error()) {
    ParserTraits::ReportMessageAt(
        Scanner::Location(logger.start(), logger.end()), logger.message(),
        logger.argument_opt(), logger.error_type());
    *ok = false;
    return;
  }
  scope_->set_end_position(logger.end());
  Expect(Token::RBRACE, ok);
  if (!*ok) {
    return;
  }
  total_preparse_skipped_ += scope_->end_position() - function_block_pos;
  *materialized_literal_count = logger.literals();
  *expected_property_count = logger.properties();
  SetLanguageMode(scope_, logger.language_mode());
  if (logger.uses_super_property()) {
    scope_->RecordSuperPropertyUsage();
  }
  if (logger.calls_eval()) {
    scope_->RecordEvalCall();
  }
  if (produce_cached_parse_data()) {
    DCHECK(log_);
    // Position right after terminal '}'.
    int body_end = scanner()->location().end_pos;
    log_->LogFunction(function_block_pos, body_end, *materialized_literal_count,
                      *expected_property_count, scope_->language_mode(),
                      scope_->uses_super_property(), scope_->calls_eval());
  }
}


Statement* Parser::BuildAssertIsCoercible(Variable* var) {
  // if (var === null || var === undefined)
  //     throw /* type error kNonCoercible) */;

  Expression* condition = factory()->NewBinaryOperation(
      Token::OR, factory()->NewCompareOperation(
                     Token::EQ_STRICT, factory()->NewVariableProxy(var),
                     factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
                     RelocInfo::kNoPosition),
      factory()->NewCompareOperation(
          Token::EQ_STRICT, factory()->NewVariableProxy(var),
          factory()->NewNullLiteral(RelocInfo::kNoPosition),
          RelocInfo::kNoPosition),
      RelocInfo::kNoPosition);
  Expression* throw_type_error = this->NewThrowTypeError(
      MessageTemplate::kNonCoercible, ast_value_factory()->empty_string(),
      RelocInfo::kNoPosition);
  IfStatement* if_statement = factory()->NewIfStatement(
      condition, factory()->NewExpressionStatement(throw_type_error,
                                                   RelocInfo::kNoPosition),
      factory()->NewEmptyStatement(RelocInfo::kNoPosition),
      RelocInfo::kNoPosition);
  return if_statement;
}


class InitializerRewriter : public AstExpressionVisitor {
 public:
  InitializerRewriter(uintptr_t stack_limit, Expression* root, Parser* parser,
                      Scope* scope)
      : AstExpressionVisitor(stack_limit, root),
        parser_(parser),
        scope_(scope) {}

 private:
  void VisitExpression(Expression* expr) override {
    RewritableExpression* to_rewrite = expr->AsRewritableExpression();
    if (to_rewrite == nullptr || to_rewrite->is_rewritten()) return;

    Parser::PatternRewriter::RewriteDestructuringAssignment(parser_, to_rewrite,
                                                            scope_);
  }

  // Code in function literals does not need to be eagerly rewritten, it will be
  // rewritten when scheduled.
  void VisitFunctionLiteral(FunctionLiteral* expr) override {}

 private:
  Parser* parser_;
  Scope* scope_;
};


void Parser::RewriteParameterInitializer(Expression* expr, Scope* scope) {
  InitializerRewriter rewriter(stack_limit_, expr, this, scope);
  rewriter.Run();
}


Block* Parser::BuildParameterInitializationBlock(
    const ParserFormalParameters& parameters, bool* ok) {
  DCHECK(!parameters.is_simple);
  DCHECK(scope_->is_function_scope());
  Block* init_block =
      factory()->NewBlock(NULL, 1, true, RelocInfo::kNoPosition);
  for (int i = 0; i < parameters.params.length(); ++i) {
    auto parameter = parameters.params[i];
    if (parameter.is_rest && parameter.pattern->IsVariableProxy()) break;
    DeclarationDescriptor descriptor;
    descriptor.declaration_kind = DeclarationDescriptor::PARAMETER;
    descriptor.parser = this;
    descriptor.scope = scope_;
    descriptor.hoist_scope = nullptr;
    descriptor.mode = LET;
    descriptor.declaration_pos = parameter.pattern->position();
    // The position that will be used by the AssignmentExpression
    // which copies from the temp parameter to the pattern.
    //
    // TODO(adamk): Should this be RelocInfo::kNoPosition, since
    // it's just copying from a temp var to the real param var?
    descriptor.initialization_pos = parameter.pattern->position();
    // The initializer position which will end up in,
    // Variable::initializer_position(), used for hole check elimination.
    int initializer_position = parameter.pattern->position();
    Expression* initial_value =
        factory()->NewVariableProxy(parameters.scope->parameter(i));
    if (parameter.initializer != nullptr) {
      // IS_UNDEFINED($param) ? initializer : $param

      // Ensure initializer is rewritten
      RewriteParameterInitializer(parameter.initializer, scope_);

      auto condition = factory()->NewCompareOperation(
          Token::EQ_STRICT,
          factory()->NewVariableProxy(parameters.scope->parameter(i)),
          factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
          RelocInfo::kNoPosition);
      initial_value = factory()->NewConditional(
          condition, parameter.initializer, initial_value,
          RelocInfo::kNoPosition);
      descriptor.initialization_pos = parameter.initializer->position();
      initializer_position = parameter.initializer_end_position;
    }

    Scope* param_scope = scope_;
    Block* param_block = init_block;
    if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
      param_scope = NewScope(scope_, BLOCK_SCOPE);
      param_scope->set_is_declaration_scope();
      param_scope->set_start_position(descriptor.initialization_pos);
      param_scope->set_end_position(parameter.initializer_end_position);
      param_scope->RecordEvalCall();
      param_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
      param_block->set_scope(param_scope);
      descriptor.hoist_scope = scope_;
      // Pass the appropriate scope in so that PatternRewriter can appropriately
      // rewrite inner initializers of the pattern to param_scope
      descriptor.scope = param_scope;
      // Rewrite the outer initializer to point to param_scope
      RewriteParameterInitializerScope(stack_limit(), initial_value, scope_,
                                       param_scope);
    }

    {
      BlockState block_state(&scope_, param_scope);
      DeclarationParsingResult::Declaration decl(
          parameter.pattern, initializer_position, initial_value);
      PatternRewriter::DeclareAndInitializeVariables(param_block, &descriptor,
                                                     &decl, nullptr, CHECK_OK);
    }

    if (!parameter.is_simple() && scope_->calls_sloppy_eval()) {
      param_scope = param_scope->FinalizeBlockScope();
      if (param_scope != nullptr) {
        CheckConflictingVarDeclarations(param_scope, CHECK_OK);
      }
      init_block->statements()->Add(param_block, zone());
    }
  }
  return init_block;
}

Block* Parser::BuildRejectPromiseOnException(Block* block) {
  // try { <block> } catch (error) { return Promise.reject(error); }
  Block* try_block = block;
  Scope* catch_scope = NewScope(scope_, CATCH_SCOPE);
  catch_scope->set_is_hidden();
  Variable* catch_variable =
      catch_scope->DeclareLocal(ast_value_factory()->dot_catch_string(), VAR,
                                kCreatedInitialized, Variable::NORMAL);
  Block* catch_block =
      factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);

  Expression* promise_reject = BuildPromiseReject(
      factory()->NewVariableProxy(catch_variable), RelocInfo::kNoPosition);

  ReturnStatement* return_promise_reject =
      factory()->NewReturnStatement(promise_reject, RelocInfo::kNoPosition);
  catch_block->statements()->Add(return_promise_reject, zone());
  TryStatement* try_catch_statement =
      factory()->NewTryCatchStatement(try_block, catch_scope, catch_variable,
                                      catch_block, RelocInfo::kNoPosition);

  block = factory()->NewBlock(nullptr, 1, true, RelocInfo::kNoPosition);
  block->statements()->Add(try_catch_statement, zone());
  return block;
}

Expression* Parser::BuildCreateJSGeneratorObject(int pos, FunctionKind kind) {
  DCHECK_NOT_NULL(function_state_->generator_object_variable());
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
  args->Add(factory()->NewThisFunction(pos), zone());
  args->Add(IsArrowFunction(kind)
                ? GetLiteralUndefined(pos)
                : ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
            zone());
  return factory()->NewCallRuntime(Runtime::kCreateJSGeneratorObject, args,
                                   pos);
}

Expression* Parser::BuildPromiseResolve(Expression* value, int pos) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
  args->Add(value, zone());
  return factory()->NewCallRuntime(Context::PROMISE_CREATE_RESOLVED_INDEX, args,
                                   pos);
}

Expression* Parser::BuildPromiseReject(Expression* value, int pos) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(1, zone());
  args->Add(value, zone());
  return factory()->NewCallRuntime(Context::PROMISE_CREATE_REJECTED_INDEX, args,
                                   pos);
}

ZoneList<Statement*>* Parser::ParseEagerFunctionBody(
    const AstRawString* function_name, int pos,
    const ParserFormalParameters& parameters, FunctionKind kind,
    FunctionLiteral::FunctionType function_type, bool* ok) {
  // Everything inside an eagerly parsed function will be parsed eagerly
  // (see comment above).
  ParsingModeScope parsing_mode(this, PARSE_EAGERLY);
  ZoneList<Statement*>* result = new(zone()) ZoneList<Statement*>(8, zone());

  static const int kFunctionNameAssignmentIndex = 0;
  if (function_type == FunctionLiteral::kNamedExpression) {
    DCHECK(function_name != NULL);
    // If we have a named function expression, we add a local variable
    // declaration to the body of the function with the name of the
    // function and let it refer to the function itself (closure).
    // Not having parsed the function body, the language mode may still change,
    // so we reserve a spot and create the actual const assignment later.
    DCHECK_EQ(kFunctionNameAssignmentIndex, result->length());
    result->Add(NULL, zone());
  }

  ZoneList<Statement*>* body = result;
  Scope* inner_scope = scope_;
  Block* inner_block = nullptr;
  if (!parameters.is_simple) {
    inner_scope = NewScope(scope_, BLOCK_SCOPE);
    inner_scope->set_is_declaration_scope();
    inner_scope->set_start_position(scanner()->location().beg_pos);
    inner_block = factory()->NewBlock(NULL, 8, true, RelocInfo::kNoPosition);
    inner_block->set_scope(inner_scope);
    body = inner_block->statements();
  }

  {
    BlockState block_state(&scope_, inner_scope);

    if (IsGeneratorFunction(kind)) {
      // We produce:
      //
      // try { InitialYield; ...body...; return {value: undefined, done: true} }
      // finally { %_GeneratorClose(generator) }
      //
      // - InitialYield yields the actual generator object.
      // - Any return statement inside the body will have its argument wrapped
      //   in a "done" iterator result object.
      // - If the generator terminates for whatever reason, we must close it.
      //   Hence the finally clause.

      Block* try_block =
          factory()->NewBlock(nullptr, 3, false, RelocInfo::kNoPosition);

      {
        Expression* allocation = BuildCreateJSGeneratorObject(pos, kind);
        VariableProxy* init_proxy = factory()->NewVariableProxy(
            function_state_->generator_object_variable());
        Assignment* assignment = factory()->NewAssignment(
            Token::INIT, init_proxy, allocation, RelocInfo::kNoPosition);
        VariableProxy* get_proxy = factory()->NewVariableProxy(
            function_state_->generator_object_variable());
        // The position of the yield is important for reporting the exception
        // caused by calling the .throw method on a generator suspended at the
        // initial yield (i.e. right after generator instantiation).
        Yield* yield = factory()->NewYield(get_proxy, assignment,
                                           scope_->start_position());
        try_block->statements()->Add(
            factory()->NewExpressionStatement(yield, RelocInfo::kNoPosition),
            zone());
      }

      ParseStatementList(try_block->statements(), Token::RBRACE, CHECK_OK);

      Statement* final_return = factory()->NewReturnStatement(
          BuildIteratorResult(nullptr, true), RelocInfo::kNoPosition);
      try_block->statements()->Add(final_return, zone());

      Block* finally_block =
          factory()->NewBlock(nullptr, 1, false, RelocInfo::kNoPosition);
      ZoneList<Expression*>* args =
          new (zone()) ZoneList<Expression*>(1, zone());
      VariableProxy* call_proxy = factory()->NewVariableProxy(
          function_state_->generator_object_variable());
      args->Add(call_proxy, zone());
      Expression* call = factory()->NewCallRuntime(
          Runtime::kInlineGeneratorClose, args, RelocInfo::kNoPosition);
      finally_block->statements()->Add(
          factory()->NewExpressionStatement(call, RelocInfo::kNoPosition),
          zone());

      body->Add(factory()->NewTryFinallyStatement(try_block, finally_block,
                                                  RelocInfo::kNoPosition),
                zone());
    } else if (IsAsyncFunction(kind)) {
      const bool accept_IN = true;
      DesugarAsyncFunctionBody(function_name, inner_scope, body, nullptr, kind,
                               FunctionBody::Normal, accept_IN, pos, CHECK_OK);
    } else {
      ParseStatementList(body, Token::RBRACE, CHECK_OK);
    }

    if (IsSubclassConstructor(kind)) {
      body->Add(
          factory()->NewReturnStatement(
              this->ThisExpression(scope_, factory(), RelocInfo::kNoPosition),
              RelocInfo::kNoPosition),
              zone());
    }
  }

  Expect(Token::RBRACE, CHECK_OK);
  scope_->set_end_position(scanner()->location().end_pos);

  if (!parameters.is_simple) {
    DCHECK_NOT_NULL(inner_scope);
    DCHECK_EQ(body, inner_block->statements());
    SetLanguageMode(scope_, inner_scope->language_mode());
    Block* init_block = BuildParameterInitializationBlock(parameters, CHECK_OK);

    if (IsAsyncFunction(kind)) {
      init_block = BuildRejectPromiseOnException(init_block);
    }

    DCHECK_NOT_NULL(init_block);

    inner_scope->set_end_position(scanner()->location().end_pos);
    inner_scope = inner_scope->FinalizeBlockScope();
    if (inner_scope != nullptr) {
      CheckConflictingVarDeclarations(inner_scope, CHECK_OK);
      InsertShadowingVarBindingInitializers(inner_block);
    }

    result->Add(init_block, zone());
    result->Add(inner_block, zone());
  }

  if (function_type == FunctionLiteral::kNamedExpression) {
    // Now that we know the language mode, we can create the const assignment
    // in the previously reserved spot.
    // NOTE: We create a proxy and resolve it here so that in the
    // future we can change the AST to only refer to VariableProxies
    // instead of Variables and Proxies as is the case now.
    VariableMode fvar_mode = is_strict(language_mode()) ? CONST : CONST_LEGACY;
    Variable* fvar = new (zone())
        Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
                 kCreatedInitialized, kNotAssigned);
    VariableProxy* proxy = factory()->NewVariableProxy(fvar);
    VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
        proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
    scope_->DeclareFunctionVar(fvar_declaration);

    VariableProxy* fproxy = factory()->NewVariableProxy(fvar);
    result->Set(kFunctionNameAssignmentIndex,
                factory()->NewExpressionStatement(
                    factory()->NewAssignment(Token::INIT, fproxy,
                                             factory()->NewThisFunction(pos),
                                             RelocInfo::kNoPosition),
                    RelocInfo::kNoPosition));
  }

  MarkCollectedTailCallExpressions();
  return result;
}


PreParser::PreParseResult Parser::ParseLazyFunctionBodyWithPreParser(
    SingletonLogger* logger, Scanner::BookmarkScope* bookmark) {
  // This function may be called on a background thread too; record only the
  // main thread preparse times.
  if (pre_parse_timer_ != NULL) {
    pre_parse_timer_->Start();
  }
  TRACE_EVENT0("v8", "V8.PreParse");

  DCHECK_EQ(Token::LBRACE, scanner()->current_token());

  if (reusable_preparser_ == NULL) {
    reusable_preparser_ = new PreParser(zone(), &scanner_, ast_value_factory(),
                                        NULL, stack_limit_);
    reusable_preparser_->set_allow_lazy(true);
#define SET_ALLOW(name) reusable_preparser_->set_allow_##name(allow_##name());
    SET_ALLOW(natives);
    SET_ALLOW(harmony_do_expressions);
    SET_ALLOW(harmony_for_in);
    SET_ALLOW(harmony_function_sent);
    SET_ALLOW(harmony_exponentiation_operator);
    SET_ALLOW(harmony_restrictive_declarations);
    SET_ALLOW(harmony_async_await);
#undef SET_ALLOW
  }
  PreParser::PreParseResult result = reusable_preparser_->PreParseLazyFunction(
      language_mode(), function_state_->kind(), scope_->has_simple_parameters(),
      parsing_module_, logger, bookmark, use_counts_);
  if (pre_parse_timer_ != NULL) {
    pre_parse_timer_->Stop();
  }
  return result;
}

ClassLiteral* Parser::ParseClassLiteral(ExpressionClassifier* classifier,
                                        const AstRawString* name,
                                        Scanner::Location class_name_location,
                                        bool name_is_strict_reserved, int pos,
                                        bool* ok) {
  // All parts of a ClassDeclaration and ClassExpression are strict code.
  if (name_is_strict_reserved) {
    ReportMessageAt(class_name_location,
                    MessageTemplate::kUnexpectedStrictReserved);
    *ok = false;
    return NULL;
  }
  if (IsEvalOrArguments(name)) {
    ReportMessageAt(class_name_location, MessageTemplate::kStrictEvalArguments);
    *ok = false;
    return NULL;
  }

  Scope* block_scope = NewScope(scope_, BLOCK_SCOPE);
  BlockState block_state(&scope_, block_scope);
  RaiseLanguageMode(STRICT);
  scope_->SetScopeName(name);

  VariableProxy* proxy = NULL;
  if (name != NULL) {
    proxy = NewUnresolved(name, CONST);
    Declaration* declaration =
        factory()->NewVariableDeclaration(proxy, CONST, block_scope, pos);
    Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
  }

  Expression* extends = NULL;
  if (Check(Token::EXTENDS)) {
    block_scope->set_start_position(scanner()->location().end_pos);
    ExpressionClassifier extends_classifier(this);
    extends = ParseLeftHandSideExpression(&extends_classifier, CHECK_OK);
    CheckNoTailCallExpressions(&extends_classifier, CHECK_OK);
    RewriteNonPattern(&extends_classifier, CHECK_OK);
    if (classifier != nullptr) {
      classifier->Accumulate(&extends_classifier,
                             ExpressionClassifier::ExpressionProductions);
    }
  } else {
    block_scope->set_start_position(scanner()->location().end_pos);
  }


  ClassLiteralChecker checker(this);
  ZoneList<ObjectLiteral::Property*>* properties = NewPropertyList(4, zone());
  FunctionLiteral* constructor = NULL;
  bool has_seen_constructor = false;

  Expect(Token::LBRACE, CHECK_OK);

  const bool has_extends = extends != nullptr;
  while (peek() != Token::RBRACE) {
    if (Check(Token::SEMICOLON)) continue;
    FuncNameInferrer::State fni_state(fni_);
    const bool in_class = true;
    bool is_computed_name = false;  // Classes do not care about computed
                                    // property names here.
    ExpressionClassifier property_classifier(this);
    const AstRawString* property_name = nullptr;
    ObjectLiteral::Property* property = ParsePropertyDefinition(
        &checker, in_class, has_extends, MethodKind::Normal, &is_computed_name,
        &has_seen_constructor, &property_classifier, &property_name, CHECK_OK);
    RewriteNonPattern(&property_classifier, CHECK_OK);
    if (classifier != nullptr) {
      classifier->Accumulate(&property_classifier,
                             ExpressionClassifier::ExpressionProductions);
    }

    if (has_seen_constructor && constructor == NULL) {
      constructor = GetPropertyValue(property)->AsFunctionLiteral();
      DCHECK_NOT_NULL(constructor);
      constructor->set_raw_name(
          name != nullptr ? name : ast_value_factory()->empty_string());
    } else {
      properties->Add(property, zone());
    }

    if (fni_ != NULL) fni_->Infer();

    if (property_name != ast_value_factory()->constructor_string()) {
      SetFunctionNameFromPropertyName(property, property_name);
    }
  }

  Expect(Token::RBRACE, CHECK_OK);
  int end_pos = scanner()->location().end_pos;

  if (constructor == NULL) {
    constructor = DefaultConstructor(name, has_extends, block_scope, pos,
                                     end_pos, block_scope->language_mode());
  }

  // Note that we do not finalize this block scope because it is
  // used as a sentinel value indicating an anonymous class.
  block_scope->set_end_position(end_pos);

  if (name != NULL) {
    DCHECK_NOT_NULL(proxy);
    proxy->var()->set_initializer_position(end_pos);
  }

  return factory()->NewClassLiteral(block_scope, proxy, extends, constructor,
                                    properties, pos, end_pos);
}


Expression* Parser::ParseV8Intrinsic(bool* ok) {
  // CallRuntime ::
  //   '%' Identifier Arguments

  int pos = peek_position();
  Expect(Token::MOD, CHECK_OK);
  // Allow "eval" or "arguments" for backward compatibility.
  const AstRawString* name = ParseIdentifier(kAllowRestrictedIdentifiers,
                                             CHECK_OK);
  Scanner::Location spread_pos;
  ExpressionClassifier classifier(this);
  ZoneList<Expression*>* args =
      ParseArguments(&spread_pos, &classifier, CHECK_OK);

  DCHECK(!spread_pos.IsValid());

  if (extension_ != NULL) {
    // The extension structures are only accessible while parsing the
    // very first time not when reparsing because of lazy compilation.
    scope_->DeclarationScope()->ForceEagerCompilation();
  }

  const Runtime::Function* function = Runtime::FunctionForName(name->string());

  if (function != NULL) {
    // Check for possible name clash.
    DCHECK_EQ(Context::kNotFound,
              Context::IntrinsicIndexForName(name->string()));
    // Check for built-in IS_VAR macro.
    if (function->function_id == Runtime::kIS_VAR) {
      DCHECK_EQ(Runtime::RUNTIME, function->intrinsic_type);
      // %IS_VAR(x) evaluates to x if x is a variable,
      // leads to a parse error otherwise.  Could be implemented as an
      // inline function %_IS_VAR(x) to eliminate this special case.
      if (args->length() == 1 && args->at(0)->AsVariableProxy() != NULL) {
        return args->at(0);
      } else {
        ReportMessage(MessageTemplate::kNotIsvar);
        *ok = false;
        return NULL;
      }
    }

    // Check that the expected number of arguments are being passed.
    if (function->nargs != -1 && function->nargs != args->length()) {
      ReportMessage(MessageTemplate::kRuntimeWrongNumArgs);
      *ok = false;
      return NULL;
    }

    return factory()->NewCallRuntime(function, args, pos);
  }

  int context_index = Context::IntrinsicIndexForName(name->string());

  // Check that the function is defined.
  if (context_index == Context::kNotFound) {
    ParserTraits::ReportMessage(MessageTemplate::kNotDefined, name);
    *ok = false;
    return NULL;
  }

  return factory()->NewCallRuntime(context_index, args, pos);
}


Literal* Parser::GetLiteralUndefined(int position) {
  return factory()->NewUndefinedLiteral(position);
}


void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
  Declaration* decl = scope->CheckConflictingVarDeclarations();
  if (decl != NULL) {
    // In ES6, conflicting variable bindings are early errors.
    const AstRawString* name = decl->proxy()->raw_name();
    int position = decl->proxy()->position();
    Scanner::Location location = position == RelocInfo::kNoPosition
        ? Scanner::Location::invalid()
        : Scanner::Location(position, position + 1);
    ParserTraits::ReportMessageAt(location, MessageTemplate::kVarRedeclaration,
                                  name);
    *ok = false;
  }
}


void Parser::InsertShadowingVarBindingInitializers(Block* inner_block) {
  // For each var-binding that shadows a parameter, insert an assignment
  // initializing the variable with the parameter.
  Scope* inner_scope = inner_block->scope();
  DCHECK(inner_scope->is_declaration_scope());
  Scope* function_scope = inner_scope->outer_scope();
  DCHECK(function_scope->is_function_scope());
  ZoneList<Declaration*>* decls = inner_scope->declarations();
  for (int i = 0; i < decls->length(); ++i) {
    Declaration* decl = decls->at(i);
    if (decl->mode() != VAR || !decl->IsVariableDeclaration()) continue;
    const AstRawString* name = decl->proxy()->raw_name();
    Variable* parameter = function_scope->LookupLocal(name);
    if (parameter == nullptr) continue;
    VariableProxy* to = inner_scope->NewUnresolved(factory(), name);
    VariableProxy* from = factory()->NewVariableProxy(parameter);
    Expression* assignment = factory()->NewAssignment(
        Token::ASSIGN, to, from, RelocInfo::kNoPosition);
    Statement* statement = factory()->NewExpressionStatement(
        assignment, RelocInfo::kNoPosition);
    inner_block->statements()->InsertAt(0, statement, zone());
  }
}


void Parser::InsertSloppyBlockFunctionVarBindings(Scope* scope, bool* ok) {
  // For each variable which is used as a function declaration in a sloppy
  // block,
  DCHECK(scope->is_declaration_scope());
  SloppyBlockFunctionMap* map = scope->sloppy_block_function_map();
  for (ZoneHashMap::Entry* p = map->Start(); p != nullptr; p = map->Next(p)) {
    AstRawString* name = static_cast<AstRawString*>(p->key);
    // If the variable wouldn't conflict with a lexical declaration,
    Variable* var = scope->LookupLocal(name);
    if (var == nullptr || !IsLexicalVariableMode(var->mode())) {
      // Declare a var-style binding for the function in the outer scope
      VariableProxy* proxy = scope->NewUnresolved(factory(), name);
      Declaration* declaration = factory()->NewVariableDeclaration(
          proxy, VAR, scope, RelocInfo::kNoPosition);
      Declare(declaration, DeclarationDescriptor::NORMAL, true, ok, scope);
      DCHECK(ok);  // Based on the preceding check, this should not fail
      if (!ok) return;

      // Write in assignments to var for each block-scoped function declaration
      auto delegates = static_cast<SloppyBlockFunctionMap::Vector*>(p->value);
      for (SloppyBlockFunctionStatement* delegate : *delegates) {
        // Read from the local lexical scope and write to the function scope
        VariableProxy* to = scope->NewUnresolved(factory(), name);
        VariableProxy* from = delegate->scope()->NewUnresolved(factory(), name);
        Expression* assignment = factory()->NewAssignment(
            Token::ASSIGN, to, from, RelocInfo::kNoPosition);
        Statement* statement = factory()->NewExpressionStatement(
            assignment, RelocInfo::kNoPosition);
        delegate->set_statement(statement);
      }
    }
  }
}


// ----------------------------------------------------------------------------
// Parser support

bool Parser::TargetStackContainsLabel(const AstRawString* label) {
  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
    if (ContainsLabel(t->statement()->labels(), label)) return true;
  }
  return false;
}


BreakableStatement* Parser::LookupBreakTarget(const AstRawString* label,
                                              bool* ok) {
  bool anonymous = label == NULL;
  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
    BreakableStatement* stat = t->statement();
    if ((anonymous && stat->is_target_for_anonymous()) ||
        (!anonymous && ContainsLabel(stat->labels(), label))) {
      return stat;
    }
  }
  return NULL;
}


IterationStatement* Parser::LookupContinueTarget(const AstRawString* label,
                                                 bool* ok) {
  bool anonymous = label == NULL;
  for (Target* t = target_stack_; t != NULL; t = t->previous()) {
    IterationStatement* stat = t->statement()->AsIterationStatement();
    if (stat == NULL) continue;

    DCHECK(stat->is_target_for_anonymous());
    if (anonymous || ContainsLabel(stat->labels(), label)) {
      return stat;
    }
  }
  return NULL;
}


void Parser::HandleSourceURLComments(Isolate* isolate, Handle<Script> script) {
  if (scanner_.source_url()->length() > 0) {
    Handle<String> source_url = scanner_.source_url()->Internalize(isolate);
    script->set_source_url(*source_url);
  }
  if (scanner_.source_mapping_url()->length() > 0) {
    Handle<String> source_mapping_url =
        scanner_.source_mapping_url()->Internalize(isolate);
    script->set_source_mapping_url(*source_mapping_url);
  }
}


void Parser::Internalize(Isolate* isolate, Handle<Script> script, bool error) {
  // Internalize strings.
  ast_value_factory()->Internalize(isolate);

  // Error processing.
  if (error) {
    if (stack_overflow()) {
      isolate->StackOverflow();
    } else {
      DCHECK(pending_error_handler_.has_pending_error());
      pending_error_handler_.ThrowPendingError(isolate, script);
    }
  }

  // Move statistics to Isolate.
  for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
       ++feature) {
    if (use_counts_[feature] > 0) {
      isolate->CountUsage(v8::Isolate::UseCounterFeature(feature));
    }
  }
  if (scanner_.FoundHtmlComment()) {
    isolate->CountUsage(v8::Isolate::kHtmlComment);
    if (script->line_offset() == 0 && script->column_offset() == 0) {
      isolate->CountUsage(v8::Isolate::kHtmlCommentInExternalScript);
    }
  }
  isolate->counters()->total_preparse_skipped()->Increment(
      total_preparse_skipped_);
}


// ----------------------------------------------------------------------------
// The Parser interface.


bool Parser::ParseStatic(ParseInfo* info) {
  Parser parser(info);
  if (parser.Parse(info)) {
    info->set_language_mode(info->literal()->language_mode());
    return true;
  }
  return false;
}


bool Parser::Parse(ParseInfo* info) {
  DCHECK(info->literal() == NULL);
  FunctionLiteral* result = NULL;
  // Ok to use Isolate here; this function is only called in the main thread.
  DCHECK(parsing_on_main_thread_);
  Isolate* isolate = info->isolate();
  pre_parse_timer_ = isolate->counters()->pre_parse();
  if (FLAG_trace_parse || allow_natives() || extension_ != NULL) {
    // If intrinsics are allowed, the Parser cannot operate independent of the
    // V8 heap because of Runtime. Tell the string table to internalize strings
    // and values right after they're created.
    ast_value_factory()->Internalize(isolate);
  }

  if (info->is_lazy()) {
    DCHECK(!info->is_eval());
    if (info->shared_info()->is_function()) {
      result = ParseLazy(isolate, info);
    } else {
      result = ParseProgram(isolate, info);
    }
  } else {
    SetCachedData(info);
    result = ParseProgram(isolate, info);
  }
  info->set_literal(result);

  Internalize(isolate, info->script(), result == NULL);
  DCHECK(ast_value_factory()->IsInternalized());
  return (result != NULL);
}


void Parser::ParseOnBackground(ParseInfo* info) {
  parsing_on_main_thread_ = false;

  DCHECK(info->literal() == NULL);
  FunctionLiteral* result = NULL;
  fni_ = new (zone()) FuncNameInferrer(ast_value_factory(), zone());

  CompleteParserRecorder recorder;
  if (produce_cached_parse_data()) log_ = &recorder;

  DCHECK(info->source_stream() != NULL);
  ExternalStreamingStream stream(info->source_stream(),
                                 info->source_stream_encoding());
  scanner_.Initialize(&stream);
  DCHECK(info->context().is_null() || info->context()->IsNativeContext());

  // When streaming, we don't know the length of the source until we have parsed
  // it. The raw data can be UTF-8, so we wouldn't know the source length until
  // we have decoded it anyway even if we knew the raw data length (which we
  // don't). We work around this by storing all the scopes which need their end
  // position set at the end of the script (the top scope and possible eval
  // scopes) and set their end position after we know the script length.
  result = DoParseProgram(info);

  info->set_literal(result);

  // We cannot internalize on a background thread; a foreground task will take
  // care of calling Parser::Internalize just before compilation.

  if (produce_cached_parse_data()) {
    if (result != NULL) *info->cached_data() = recorder.GetScriptData();
    log_ = NULL;
  }
}


ParserTraits::TemplateLiteralState Parser::OpenTemplateLiteral(int pos) {
  return new (zone()) ParserTraits::TemplateLiteral(zone(), pos);
}


void Parser::AddTemplateSpan(TemplateLiteralState* state, bool tail) {
  int pos = scanner()->location().beg_pos;
  int end = scanner()->location().end_pos - (tail ? 1 : 2);
  const AstRawString* tv = scanner()->CurrentSymbol(ast_value_factory());
  const AstRawString* trv = scanner()->CurrentRawSymbol(ast_value_factory());
  Literal* cooked = factory()->NewStringLiteral(tv, pos);
  Literal* raw = factory()->NewStringLiteral(trv, pos);
  (*state)->AddTemplateSpan(cooked, raw, end, zone());
}


void Parser::AddTemplateExpression(TemplateLiteralState* state,
                                   Expression* expression) {
  (*state)->AddExpression(expression, zone());
}


Expression* Parser::CloseTemplateLiteral(TemplateLiteralState* state, int start,
                                         Expression* tag) {
  TemplateLiteral* lit = *state;
  int pos = lit->position();
  const ZoneList<Expression*>* cooked_strings = lit->cooked();
  const ZoneList<Expression*>* raw_strings = lit->raw();
  const ZoneList<Expression*>* expressions = lit->expressions();
  DCHECK_EQ(cooked_strings->length(), raw_strings->length());
  DCHECK_EQ(cooked_strings->length(), expressions->length() + 1);

  if (!tag) {
    // Build tree of BinaryOps to simplify code-generation
    Expression* expr = cooked_strings->at(0);
    int i = 0;
    while (i < expressions->length()) {
      Expression* sub = expressions->at(i++);
      Expression* cooked_str = cooked_strings->at(i);

      // Let middle be ToString(sub).
      ZoneList<Expression*>* args =
          new (zone()) ZoneList<Expression*>(1, zone());
      args->Add(sub, zone());
      Expression* middle = factory()->NewCallRuntime(Runtime::kInlineToString,
                                                     args, sub->position());

      expr = factory()->NewBinaryOperation(
          Token::ADD, factory()->NewBinaryOperation(
                          Token::ADD, expr, middle, expr->position()),
          cooked_str, sub->position());
    }
    return expr;
  } else {
    uint32_t hash = ComputeTemplateLiteralHash(lit);

    int cooked_idx = function_state_->NextMaterializedLiteralIndex();
    int raw_idx = function_state_->NextMaterializedLiteralIndex();

    // $getTemplateCallSite
    ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(4, zone());
    args->Add(factory()->NewArrayLiteral(
                  const_cast<ZoneList<Expression*>*>(cooked_strings),
                  cooked_idx, pos),
              zone());
    args->Add(
        factory()->NewArrayLiteral(
            const_cast<ZoneList<Expression*>*>(raw_strings), raw_idx, pos),
        zone());

    // Ensure hash is suitable as a Smi value
    Smi* hash_obj = Smi::cast(Internals::IntToSmi(static_cast<int>(hash)));
    args->Add(factory()->NewSmiLiteral(hash_obj->value(), pos), zone());

    Expression* call_site = factory()->NewCallRuntime(
        Context::GET_TEMPLATE_CALL_SITE_INDEX, args, start);

    // Call TagFn
    ZoneList<Expression*>* call_args =
        new (zone()) ZoneList<Expression*>(expressions->length() + 1, zone());
    call_args->Add(call_site, zone());
    call_args->AddAll(*expressions, zone());
    return factory()->NewCall(tag, call_args, pos);
  }
}


uint32_t Parser::ComputeTemplateLiteralHash(const TemplateLiteral* lit) {
  const ZoneList<Expression*>* raw_strings = lit->raw();
  int total = raw_strings->length();
  DCHECK(total);

  uint32_t running_hash = 0;

  for (int index = 0; index < total; ++index) {
    if (index) {
      running_hash = StringHasher::ComputeRunningHashOneByte(
          running_hash, "${}", 3);
    }

    const AstRawString* raw_string =
        raw_strings->at(index)->AsLiteral()->raw_value()->AsString();
    if (raw_string->is_one_byte()) {
      const char* data = reinterpret_cast<const char*>(raw_string->raw_data());
      running_hash = StringHasher::ComputeRunningHashOneByte(
          running_hash, data, raw_string->length());
    } else {
      const uc16* data = reinterpret_cast<const uc16*>(raw_string->raw_data());
      running_hash = StringHasher::ComputeRunningHash(running_hash, data,
                                                      raw_string->length());
    }
  }

  return running_hash;
}


ZoneList<v8::internal::Expression*>* Parser::PrepareSpreadArguments(
    ZoneList<v8::internal::Expression*>* list) {
  ZoneList<v8::internal::Expression*>* args =
      new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
  if (list->length() == 1) {
    // Spread-call with single spread argument produces an InternalArray
    // containing the values from the array.
    //
    // Function is called or constructed with the produced array of arguments
    //
    // EG: Apply(Func, Spread(spread0))
    ZoneList<Expression*>* spread_list =
        new (zone()) ZoneList<Expression*>(0, zone());
    spread_list->Add(list->at(0)->AsSpread()->expression(), zone());
    args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
                                        spread_list, RelocInfo::kNoPosition),
              zone());
    return args;
  } else {
    // Spread-call with multiple arguments produces array literals for each
    // sequences of unspread arguments, and converts each spread iterable to
    // an Internal array. Finally, all of these produced arrays are flattened
    // into a single InternalArray, containing the arguments for the call.
    //
    // EG: Apply(Func, Flatten([unspread0, unspread1], Spread(spread0),
    //                         Spread(spread1), [unspread2, unspread3]))
    int i = 0;
    int n = list->length();
    while (i < n) {
      if (!list->at(i)->IsSpread()) {
        ZoneList<v8::internal::Expression*>* unspread =
            new (zone()) ZoneList<v8::internal::Expression*>(1, zone());

        // Push array of unspread parameters
        while (i < n && !list->at(i)->IsSpread()) {
          unspread->Add(list->at(i++), zone());
        }
        int literal_index = function_state_->NextMaterializedLiteralIndex();
        args->Add(factory()->NewArrayLiteral(unspread, literal_index,
                                             RelocInfo::kNoPosition),
                  zone());

        if (i == n) break;
      }

      // Push eagerly spread argument
      ZoneList<v8::internal::Expression*>* spread_list =
          new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
      spread_list->Add(list->at(i++)->AsSpread()->expression(), zone());
      args->Add(factory()->NewCallRuntime(Context::SPREAD_ITERABLE_INDEX,
                                          spread_list, RelocInfo::kNoPosition),
                zone());
    }

    list = new (zone()) ZoneList<v8::internal::Expression*>(1, zone());
    list->Add(factory()->NewCallRuntime(Context::SPREAD_ARGUMENTS_INDEX, args,
                                        RelocInfo::kNoPosition),
              zone());
    return list;
  }
  UNREACHABLE();
}


Expression* Parser::SpreadCall(Expression* function,
                               ZoneList<v8::internal::Expression*>* args,
                               int pos) {
  if (function->IsSuperCallReference()) {
    // Super calls
    // $super_constructor = %_GetSuperConstructor(<this-function>)
    // %reflect_construct($super_constructor, args, new.target)
    ZoneList<Expression*>* tmp = new (zone()) ZoneList<Expression*>(1, zone());
    tmp->Add(function->AsSuperCallReference()->this_function_var(), zone());
    Expression* super_constructor = factory()->NewCallRuntime(
        Runtime::kInlineGetSuperConstructor, tmp, pos);
    args->InsertAt(0, super_constructor, zone());
    args->Add(function->AsSuperCallReference()->new_target_var(), zone());
    return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args,
                                     pos);
  } else {
    if (function->IsProperty()) {
      // Method calls
      if (function->AsProperty()->IsSuperAccess()) {
        Expression* home =
            ThisExpression(scope_, factory(), RelocInfo::kNoPosition);
        args->InsertAt(0, function, zone());
        args->InsertAt(1, home, zone());
      } else {
        Variable* temp =
            scope_->NewTemporary(ast_value_factory()->empty_string());
        VariableProxy* obj = factory()->NewVariableProxy(temp);
        Assignment* assign_obj = factory()->NewAssignment(
            Token::ASSIGN, obj, function->AsProperty()->obj(),
            RelocInfo::kNoPosition);
        function = factory()->NewProperty(
            assign_obj, function->AsProperty()->key(), RelocInfo::kNoPosition);
        args->InsertAt(0, function, zone());
        obj = factory()->NewVariableProxy(temp);
        args->InsertAt(1, obj, zone());
      }
    } else {
      // Non-method calls
      args->InsertAt(0, function, zone());
      args->InsertAt(1, factory()->NewUndefinedLiteral(RelocInfo::kNoPosition),
                     zone());
    }
    return factory()->NewCallRuntime(Context::REFLECT_APPLY_INDEX, args, pos);
  }
}


Expression* Parser::SpreadCallNew(Expression* function,
                                  ZoneList<v8::internal::Expression*>* args,
                                  int pos) {
  args->InsertAt(0, function, zone());

  return factory()->NewCallRuntime(Context::REFLECT_CONSTRUCT_INDEX, args, pos);
}


void Parser::SetLanguageMode(Scope* scope, LanguageMode mode) {
  v8::Isolate::UseCounterFeature feature;
  if (is_sloppy(mode))
    feature = v8::Isolate::kSloppyMode;
  else if (is_strict(mode))
    feature = v8::Isolate::kStrictMode;
  else
    UNREACHABLE();
  ++use_counts_[feature];
  scope->SetLanguageMode(mode);
}


void Parser::RaiseLanguageMode(LanguageMode mode) {
  LanguageMode old = scope_->language_mode();
  SetLanguageMode(scope_, old > mode ? old : mode);
}

void Parser::MarkCollectedTailCallExpressions() {
  const ZoneList<Expression*>& tail_call_expressions =
      function_state_->tail_call_expressions().expressions();
  for (int i = 0; i < tail_call_expressions.length(); ++i) {
    Expression* expression = tail_call_expressions[i];
    // If only FLAG_harmony_explicit_tailcalls is enabled then expression
    // must be a Call expression.
    DCHECK(FLAG_harmony_tailcalls || !FLAG_harmony_explicit_tailcalls ||
           expression->IsCall());
    MarkTailPosition(expression);
  }
}

Expression* ParserTraits::ExpressionListToExpression(
    ZoneList<Expression*>* args) {
  AstNodeFactory* factory = parser_->factory();
  Expression* expr = args->at(0);
  for (int i = 1; i < args->length(); ++i) {
    expr = factory->NewBinaryOperation(Token::COMMA, expr, args->at(i),
                                       expr->position());
  }
  return expr;
}

void ParserTraits::RewriteDestructuringAssignments() {
  parser_->RewriteDestructuringAssignments();
}

Expression* ParserTraits::RewriteExponentiation(Expression* left,
                                                Expression* right, int pos) {
  return parser_->RewriteExponentiation(left, right, pos);
}

Expression* ParserTraits::RewriteAssignExponentiation(Expression* left,
                                                      Expression* right,
                                                      int pos) {
  return parser_->RewriteAssignExponentiation(left, right, pos);
}

void ParserTraits::RewriteNonPattern(Type::ExpressionClassifier* classifier,
                                     bool* ok) {
  parser_->RewriteNonPattern(classifier, ok);
}

Expression* ParserTraits::RewriteAwaitExpression(Expression* value,
                                                 int await_pos) {
  // yield %AsyncFunctionAwait(.generator_object, <operand>)
  Variable* generator_object_variable =
      parser_->function_state_->generator_object_variable();

  // If generator_object_variable is null,
  if (!generator_object_variable) return value;

  auto factory = parser_->factory();
  const int nopos = RelocInfo::kNoPosition;

  Variable* temp_var = parser_->scope_->NewTemporary(
      parser_->ast_value_factory()->empty_string());
  VariableProxy* temp_proxy = factory->NewVariableProxy(temp_var);
  Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);

  // Wrap value evaluation to provide a break location.
  Expression* value_assignment =
      factory->NewAssignment(Token::ASSIGN, temp_proxy, value, nopos);
  do_block->statements()->Add(
      factory->NewExpressionStatement(value_assignment, value->position()),
      zone());

  ZoneList<Expression*>* async_function_await_args =
      new (zone()) ZoneList<Expression*>(2, zone());
  Expression* generator_object =
      factory->NewVariableProxy(generator_object_variable);
  async_function_await_args->Add(generator_object, zone());
  async_function_await_args->Add(temp_proxy, zone());
  Expression* async_function_await = parser_->factory()->NewCallRuntime(
      Context::ASYNC_FUNCTION_AWAIT_INDEX, async_function_await_args, nopos);
  // Wrap await to provide a break location between value evaluation and yield.
  Expression* await_assignment = factory->NewAssignment(
      Token::ASSIGN, temp_proxy, async_function_await, nopos);
  do_block->statements()->Add(
      factory->NewExpressionStatement(await_assignment, await_pos), zone());
  Expression* do_expr = factory->NewDoExpression(do_block, temp_var, nopos);

  generator_object = factory->NewVariableProxy(generator_object_variable);
  return factory->NewYield(generator_object, do_expr, nopos);
}

ZoneList<Expression*>* ParserTraits::GetNonPatternList() const {
  return parser_->function_state_->non_patterns_to_rewrite();
}


ZoneList<typename ParserTraits::Type::ExpressionClassifier::Error>*
ParserTraits::GetReportedErrorList() const {
  return parser_->function_state_->GetReportedErrorList();
}


Zone* ParserTraits::zone() const {
  return parser_->function_state_->scope()->zone();
}


class NonPatternRewriter : public AstExpressionRewriter {
 public:
  NonPatternRewriter(uintptr_t stack_limit, Parser* parser)
      : AstExpressionRewriter(stack_limit), parser_(parser) {}
  ~NonPatternRewriter() override {}

 private:
  bool RewriteExpression(Expression* expr) override {
    if (expr->IsRewritableExpression()) return true;
    // Rewrite only what could have been a pattern but is not.
    if (expr->IsArrayLiteral()) {
      // Spread rewriting in array literals.
      ArrayLiteral* lit = expr->AsArrayLiteral();
      VisitExpressions(lit->values());
      replacement_ = parser_->RewriteSpreads(lit);
      return false;
    }
    if (expr->IsObjectLiteral()) {
      return true;
    }
    if (expr->IsBinaryOperation() &&
        expr->AsBinaryOperation()->op() == Token::COMMA) {
      return true;
    }
    // Everything else does not need rewriting.
    return false;
  }

  void VisitObjectLiteralProperty(ObjectLiteralProperty* property) override {
    if (property == nullptr) return;
    // Do not rewrite (computed) key expressions
    AST_REWRITE_PROPERTY(Expression, property, value);
  }

  Parser* parser_;
};


void Parser::RewriteNonPattern(ExpressionClassifier* classifier, bool* ok) {
  ValidateExpression(classifier, ok);
  if (!*ok) return;
  auto non_patterns_to_rewrite = function_state_->non_patterns_to_rewrite();
  int begin = classifier->GetNonPatternBegin();
  int end = non_patterns_to_rewrite->length();
  if (begin < end) {
    NonPatternRewriter rewriter(stack_limit_, this);
    for (int i = begin; i < end; i++) {
      DCHECK(non_patterns_to_rewrite->at(i)->IsRewritableExpression());
      rewriter.Rewrite(non_patterns_to_rewrite->at(i));
    }
    non_patterns_to_rewrite->Rewind(begin);
  }
}


void Parser::RewriteDestructuringAssignments() {
  const auto& assignments =
      function_state_->destructuring_assignments_to_rewrite();
  for (int i = assignments.length() - 1; i >= 0; --i) {
    // Rewrite list in reverse, so that nested assignment patterns are rewritten
    // correctly.
    const DestructuringAssignment& pair = assignments.at(i);
    RewritableExpression* to_rewrite =
        pair.assignment->AsRewritableExpression();
    DCHECK_NOT_NULL(to_rewrite);
    if (!to_rewrite->is_rewritten()) {
      PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite,
                                                      pair.scope);
    }
  }
}

Expression* Parser::RewriteExponentiation(Expression* left, Expression* right,
                                          int pos) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
  args->Add(left, zone());
  args->Add(right, zone());
  return factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
}

Expression* Parser::RewriteAssignExponentiation(Expression* left,
                                                Expression* right, int pos) {
  ZoneList<Expression*>* args = new (zone()) ZoneList<Expression*>(2, zone());
  if (left->IsVariableProxy()) {
    VariableProxy* lhs = left->AsVariableProxy();

    Expression* result;
    DCHECK_NOT_NULL(lhs->raw_name());
    result =
        this->ExpressionFromIdentifier(lhs->raw_name(), lhs->position(),
                                       lhs->end_position(), scope_, factory());
    args->Add(left, zone());
    args->Add(right, zone());
    Expression* call =
        factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
    return factory()->NewAssignment(Token::ASSIGN, result, call, pos);
  } else if (left->IsProperty()) {
    Property* prop = left->AsProperty();
    auto temp_obj = scope_->NewTemporary(ast_value_factory()->empty_string());
    auto temp_key = scope_->NewTemporary(ast_value_factory()->empty_string());
    Expression* assign_obj = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(temp_obj), prop->obj(),
        RelocInfo::kNoPosition);
    Expression* assign_key = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(temp_key), prop->key(),
        RelocInfo::kNoPosition);
    args->Add(factory()->NewProperty(factory()->NewVariableProxy(temp_obj),
                                     factory()->NewVariableProxy(temp_key),
                                     left->position()),
              zone());
    args->Add(right, zone());
    Expression* call =
        factory()->NewCallRuntime(Context::MATH_POW_METHOD_INDEX, args, pos);
    Expression* target = factory()->NewProperty(
        factory()->NewVariableProxy(temp_obj),
        factory()->NewVariableProxy(temp_key), RelocInfo::kNoPosition);
    Expression* assign =
        factory()->NewAssignment(Token::ASSIGN, target, call, pos);
    return factory()->NewBinaryOperation(
        Token::COMMA, assign_obj,
        factory()->NewBinaryOperation(Token::COMMA, assign_key, assign, pos),
        pos);
  }
  UNREACHABLE();
  return nullptr;
}

Expression* Parser::RewriteSpreads(ArrayLiteral* lit) {
  // Array literals containing spreads are rewritten using do expressions, e.g.
  //    [1, 2, 3, ...x, 4, ...y, 5]
  // is roughly rewritten as:
  //    do {
  //      $R = [1, 2, 3];
  //      for ($i of x) %AppendElement($R, $i);
  //      %AppendElement($R, 4);
  //      for ($j of y) %AppendElement($R, $j);
  //      %AppendElement($R, 5);
  //      $R
  //    }
  // where $R, $i and $j are fresh temporary variables.
  ZoneList<Expression*>::iterator s = lit->FirstSpread();
  if (s == lit->EndValue()) return nullptr;  // no spread, no rewriting...
  Variable* result =
      scope_->NewTemporary(ast_value_factory()->dot_result_string());
  // NOTE: The value assigned to R is the whole original array literal,
  // spreads included. This will be fixed before the rewritten AST is returned.
  // $R = lit
  Expression* init_result =
      factory()->NewAssignment(Token::INIT, factory()->NewVariableProxy(result),
                               lit, RelocInfo::kNoPosition);
  Block* do_block =
      factory()->NewBlock(nullptr, 16, false, RelocInfo::kNoPosition);
  do_block->statements()->Add(
      factory()->NewExpressionStatement(init_result, RelocInfo::kNoPosition),
      zone());
  // Traverse the array literal starting from the first spread.
  while (s != lit->EndValue()) {
    Expression* value = *s++;
    Spread* spread = value->AsSpread();
    if (spread == nullptr) {
      // If the element is not a spread, we're adding a single:
      // %AppendElement($R, value)
      ZoneList<Expression*>* append_element_args = NewExpressionList(2, zone());
      append_element_args->Add(factory()->NewVariableProxy(result), zone());
      append_element_args->Add(value, zone());
      do_block->statements()->Add(
          factory()->NewExpressionStatement(
              factory()->NewCallRuntime(Runtime::kAppendElement,
                                        append_element_args,
                                        RelocInfo::kNoPosition),
              RelocInfo::kNoPosition),
          zone());
    } else {
      // If it's a spread, we're adding a for/of loop iterating through it.
      Variable* each =
          scope_->NewTemporary(ast_value_factory()->dot_for_string());
      Expression* subject = spread->expression();
      // %AppendElement($R, each)
      Statement* append_body;
      {
        ZoneList<Expression*>* append_element_args =
            NewExpressionList(2, zone());
        append_element_args->Add(factory()->NewVariableProxy(result), zone());
        append_element_args->Add(factory()->NewVariableProxy(each), zone());
        append_body = factory()->NewExpressionStatement(
            factory()->NewCallRuntime(Runtime::kAppendElement,
                                      append_element_args,
                                      RelocInfo::kNoPosition),
            RelocInfo::kNoPosition);
      }
      // for (each of spread) %AppendElement($R, each)
      ForEachStatement* loop = factory()->NewForEachStatement(
          ForEachStatement::ITERATE, nullptr, RelocInfo::kNoPosition);
      InitializeForOfStatement(loop->AsForOfStatement(),
                               factory()->NewVariableProxy(each), subject,
                               append_body);
      do_block->statements()->Add(loop, zone());
    }
  }
  // Now, rewind the original array literal to truncate everything from the
  // first spread (included) until the end. This fixes $R's initialization.
  lit->RewindSpreads();
  return factory()->NewDoExpression(do_block, result, lit->position());
}


void ParserTraits::QueueDestructuringAssignmentForRewriting(Expression* expr) {
  DCHECK(expr->IsRewritableExpression());
  parser_->function_state_->AddDestructuringAssignment(
      Parser::DestructuringAssignment(expr, parser_->scope_));
}


void ParserTraits::QueueNonPatternForRewriting(Expression* expr, bool* ok) {
  DCHECK(expr->IsRewritableExpression());
  parser_->function_state_->AddNonPatternForRewriting(expr, ok);
}


void ParserTraits::SetFunctionNameFromPropertyName(
    ObjectLiteralProperty* property, const AstRawString* name) {
  Expression* value = property->value();

  // Computed name setting must happen at runtime.
  if (property->is_computed_name()) return;

  // Getter and setter names are handled here because their names
  // change in ES2015, even though they are not anonymous.
  auto function = value->AsFunctionLiteral();
  if (function != nullptr) {
    bool is_getter = property->kind() == ObjectLiteralProperty::GETTER;
    bool is_setter = property->kind() == ObjectLiteralProperty::SETTER;
    if (is_getter || is_setter) {
      DCHECK_NOT_NULL(name);
      const AstRawString* prefix =
          is_getter ? parser_->ast_value_factory()->get_space_string()
                    : parser_->ast_value_factory()->set_space_string();
      function->set_raw_name(
          parser_->ast_value_factory()->NewConsString(prefix, name));
      return;
    }
  }

  if (!value->IsAnonymousFunctionDefinition()) return;
  DCHECK_NOT_NULL(name);

  // Ignore "__proto__" as a name when it's being used to set the [[Prototype]]
  // of an object literal.
  if (property->kind() == ObjectLiteralProperty::PROTOTYPE) return;

  if (function != nullptr) {
    function->set_raw_name(name);
    DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
  } else {
    DCHECK(value->IsClassLiteral());
    DCHECK_EQ(ObjectLiteralProperty::COMPUTED, property->kind());
    value->AsClassLiteral()->constructor()->set_raw_name(name);
  }
}


void ParserTraits::SetFunctionNameFromIdentifierRef(Expression* value,
                                                    Expression* identifier) {
  if (!value->IsAnonymousFunctionDefinition()) return;
  if (!identifier->IsVariableProxy()) return;

  auto name = identifier->AsVariableProxy()->raw_name();
  DCHECK_NOT_NULL(name);

  auto function = value->AsFunctionLiteral();
  if (function != nullptr) {
    function->set_raw_name(name);
  } else {
    DCHECK(value->IsClassLiteral());
    value->AsClassLiteral()->constructor()->set_raw_name(name);
  }
}


// Desugaring of yield*
// ====================
//
// With the help of do-expressions and function.sent, we desugar yield* into a
// loop containing a "raw" yield (a yield that doesn't wrap an iterator result
// object around its argument).  Concretely, "yield* iterable" turns into
// roughly the following code:
//
//   do {
//     const kNext = 0;
//     const kReturn = 1;
//     const kThrow = 2;
//
//     let input = function.sent;
//     let mode = kNext;
//     let output = undefined;
//
//     let iterator = iterable[Symbol.iterator]();
//     if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
//
//     while (true) {
//       // From the generator to the iterator:
//       // Forward input according to resume mode and obtain output.
//       switch (mode) {
//         case kNext:
//           output = iterator.next(input);
//           if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
//           break;
//         case kReturn:
//           IteratorClose(iterator, input, output);  // See below.
//           break;
//         case kThrow:
//           let iteratorThrow = iterator.throw;
//           if (IS_NULL_OR_UNDEFINED(iteratorThrow)) {
//             IteratorClose(iterator);  // See below.
//             throw MakeTypeError(kThrowMethodMissing);
//           }
//           output = %_Call(iteratorThrow, iterator, input);
//           if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
//           break;
//       }
//       if (output.done) break;
//
//       // From the generator to its user:
//       // Forward output, receive new input, and determine resume mode.
//       mode = kReturn;
//       try {
//         try {
//           RawYield(output);  // See explanation above.
//           mode = kNext;
//         } catch (error) {
//           mode = kThrow;
//         }
//       } finally {
//         input = function.sent;
//         continue;
//       }
//     }
//
//     if (mode === kReturn) {
//       return {value: output.value, done: true};
//     }
//     output.value
//   }
//
// IteratorClose(iterator) expands to the following:
//
//   let iteratorReturn = iterator.return;
//   if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
//     let output = %_Call(iteratorReturn, iterator);
//     if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
//   }
//
// IteratorClose(iterator, input, output) expands to the following:
//
//   let iteratorReturn = iterator.return;
//   if (IS_NULL_OR_UNDEFINED(iteratorReturn)) return input;
//   output = %_Call(iteratorReturn, iterator, input);
//   if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);

Expression* ParserTraits::RewriteYieldStar(
    Expression* generator, Expression* iterable, int pos) {

  const int nopos = RelocInfo::kNoPosition;

  auto factory = parser_->factory();
  auto avfactory = parser_->ast_value_factory();
  auto scope = parser_->scope_;
  auto zone = parser_->zone();


  // Forward definition for break/continue statements.
  WhileStatement* loop = factory->NewWhileStatement(nullptr, nopos);


  // let input = undefined;
  Variable* var_input = scope->NewTemporary(avfactory->empty_string());
  Statement* initialize_input;
  {
    Expression* input_proxy = factory->NewVariableProxy(var_input);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, input_proxy, factory->NewUndefinedLiteral(nopos), nopos);
    initialize_input = factory->NewExpressionStatement(assignment, nopos);
  }


  // let mode = kNext;
  Variable* var_mode = scope->NewTemporary(avfactory->empty_string());
  Statement* initialize_mode;
  {
    Expression* mode_proxy = factory->NewVariableProxy(var_mode);
    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
    Expression* assignment =
        factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
    initialize_mode = factory->NewExpressionStatement(assignment, nopos);
  }


  // let output = undefined;
  Variable* var_output = scope->NewTemporary(avfactory->empty_string());
  Statement* initialize_output;
  {
    Expression* output_proxy = factory->NewVariableProxy(var_output);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, output_proxy, factory->NewUndefinedLiteral(nopos),
        nopos);
    initialize_output = factory->NewExpressionStatement(assignment, nopos);
  }


  // let iterator = iterable[Symbol.iterator];
  Variable* var_iterator = scope->NewTemporary(avfactory->empty_string());
  Statement* get_iterator;
  {
    Expression* iterator = GetIterator(iterable, factory, nopos);
    Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, iterator_proxy, iterator, nopos);
    get_iterator = factory->NewExpressionStatement(assignment, nopos);
  }


  // if (!IS_RECEIVER(iterator)) throw MakeTypeError(kSymbolIteratorInvalid);
  Statement* validate_iterator;
  {
    Expression* is_receiver_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_iterator), zone);
      is_receiver_call =
          factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
    }

    Statement* throw_call;
    {
      Expression* call = NewThrowTypeError(
          MessageTemplate::kSymbolIteratorInvalid, avfactory->empty_string(),
          nopos);
      throw_call = factory->NewExpressionStatement(call, nopos);
    }

    validate_iterator = factory->NewIfStatement(
        is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
  }


  // output = iterator.next(input);
  Statement* call_next;
  {
    Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
    Expression* literal =
        factory->NewStringLiteral(avfactory->next_string(), nopos);
    Expression* next_property =
        factory->NewProperty(iterator_proxy, literal, nopos);
    Expression* input_proxy = factory->NewVariableProxy(var_input);
    auto args = new (zone) ZoneList<Expression*>(1, zone);
    args->Add(input_proxy, zone);
    Expression* call = factory->NewCall(next_property, args, nopos);
    Expression* output_proxy = factory->NewVariableProxy(var_output);
    Expression* assignment =
        factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
    call_next = factory->NewExpressionStatement(assignment, nopos);
  }


  // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
  Statement* validate_next_output;
  {
    Expression* is_receiver_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      is_receiver_call =
          factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
    }

    Statement* throw_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      Expression* call = factory->NewCallRuntime(
          Runtime::kThrowIteratorResultNotAnObject, args, nopos);
      throw_call = factory->NewExpressionStatement(call, nopos);
    }

    validate_next_output = factory->NewIfStatement(
        is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
  }


  // let iteratorThrow = iterator.throw;
  Variable* var_throw = scope->NewTemporary(avfactory->empty_string());
  Statement* get_throw;
  {
    Expression* iterator_proxy = factory->NewVariableProxy(var_iterator);
    Expression* literal =
        factory->NewStringLiteral(avfactory->throw_string(), nopos);
    Expression* property =
        factory->NewProperty(iterator_proxy, literal, nopos);
    Expression* throw_proxy = factory->NewVariableProxy(var_throw);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, throw_proxy, property, nopos);
    get_throw = factory->NewExpressionStatement(assignment, nopos);
  }


  // if (IS_NULL_OR_UNDEFINED(iteratorThrow) {
  //   IteratorClose(iterator);
  //   throw MakeTypeError(kThrowMethodMissing);
  // }
  Statement* check_throw;
  {
    Expression* condition = factory->NewCompareOperation(
        Token::EQ, factory->NewVariableProxy(var_throw),
        factory->NewNullLiteral(nopos), nopos);

    Expression* call = NewThrowTypeError(
        MessageTemplate::kThrowMethodMissing,
        avfactory->empty_string(), nopos);
    Statement* throw_call = factory->NewExpressionStatement(call, nopos);

    Block* then = factory->NewBlock(nullptr, 4+1, false, nopos);
    parser_->BuildIteratorCloseForCompletion(
        then->statements(), var_iterator,
        factory->NewSmiLiteral(Parser::kNormalCompletion, nopos));
    then->statements()->Add(throw_call, zone);
    check_throw = factory->NewIfStatement(
        condition, then, factory->NewEmptyStatement(nopos), nopos);
  }


  // output = %_Call(iteratorThrow, iterator, input);
  Statement* call_throw;
  {
    auto args = new (zone) ZoneList<Expression*>(3, zone);
    args->Add(factory->NewVariableProxy(var_throw), zone);
    args->Add(factory->NewVariableProxy(var_iterator), zone);
    args->Add(factory->NewVariableProxy(var_input), zone);
    Expression* call =
        factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, factory->NewVariableProxy(var_output), call, nopos);
    call_throw = factory->NewExpressionStatement(assignment, nopos);
  }


  // if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
  Statement* validate_throw_output;
  {
    Expression* is_receiver_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      is_receiver_call =
          factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
    }

    Statement* throw_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      Expression* call = factory->NewCallRuntime(
          Runtime::kThrowIteratorResultNotAnObject, args, nopos);
      throw_call = factory->NewExpressionStatement(call, nopos);
    }

    validate_throw_output = factory->NewIfStatement(
        is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
  }


  // if (output.done) break;
  Statement* if_done;
  {
    Expression* output_proxy = factory->NewVariableProxy(var_output);
    Expression* literal =
        factory->NewStringLiteral(avfactory->done_string(), nopos);
    Expression* property = factory->NewProperty(output_proxy, literal, nopos);
    BreakStatement* break_loop = factory->NewBreakStatement(loop, nopos);
    if_done = factory->NewIfStatement(
        property, break_loop, factory->NewEmptyStatement(nopos), nopos);
  }


  // mode = kReturn;
  Statement* set_mode_return;
  {
    Expression* mode_proxy = factory->NewVariableProxy(var_mode);
    Expression* kreturn =
        factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
    Expression* assignment =
        factory->NewAssignment(Token::ASSIGN, mode_proxy, kreturn, nopos);
    set_mode_return = factory->NewExpressionStatement(assignment, nopos);
  }

  // Yield(output);
  Statement* yield_output;
  {
    Expression* output_proxy = factory->NewVariableProxy(var_output);
    Yield* yield = factory->NewYield(generator, output_proxy, nopos);
    yield_output = factory->NewExpressionStatement(yield, nopos);
  }


  // mode = kNext;
  Statement* set_mode_next;
  {
    Expression* mode_proxy = factory->NewVariableProxy(var_mode);
    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
    Expression* assignment =
        factory->NewAssignment(Token::ASSIGN, mode_proxy, knext, nopos);
    set_mode_next = factory->NewExpressionStatement(assignment, nopos);
  }


  // mode = kThrow;
  Statement* set_mode_throw;
  {
    Expression* mode_proxy = factory->NewVariableProxy(var_mode);
    Expression* kthrow =
        factory->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
    Expression* assignment =
        factory->NewAssignment(Token::ASSIGN, mode_proxy, kthrow, nopos);
    set_mode_throw = factory->NewExpressionStatement(assignment, nopos);
  }


  // input = function.sent;
  Statement* get_input;
  {
    Expression* function_sent = FunctionSentExpression(scope, factory, nopos);
    Expression* input_proxy = factory->NewVariableProxy(var_input);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, input_proxy, function_sent, nopos);
    get_input = factory->NewExpressionStatement(assignment, nopos);
  }


  // if (mode === kReturn) {
  //   return {value: output.value, done: true};
  // }
  Statement* maybe_return_value;
  {
    Expression* mode_proxy = factory->NewVariableProxy(var_mode);
    Expression* kreturn =
        factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
    Expression* condition = factory->NewCompareOperation(
        Token::EQ_STRICT, mode_proxy, kreturn, nopos);

    Expression* output_proxy = factory->NewVariableProxy(var_output);
    Expression* literal =
        factory->NewStringLiteral(avfactory->value_string(), nopos);
    Expression* property = factory->NewProperty(output_proxy, literal, nopos);
    Statement* return_value =
        factory->NewReturnStatement(BuildIteratorResult(property, true), nopos);

    maybe_return_value = factory->NewIfStatement(
        condition, return_value, factory->NewEmptyStatement(nopos), nopos);
  }


  // output.value
  Statement* get_value;
  {
    Expression* output_proxy = factory->NewVariableProxy(var_output);
    Expression* literal =
        factory->NewStringLiteral(avfactory->value_string(), nopos);
    Expression* property = factory->NewProperty(output_proxy, literal, nopos);
    get_value = factory->NewExpressionStatement(property, nopos);
  }


  // Now put things together.


  // try { ... } catch(e) { ... }
  Statement* try_catch;
  {
    Block* try_block = factory->NewBlock(nullptr, 2, false, nopos);
    try_block->statements()->Add(yield_output, zone);
    try_block->statements()->Add(set_mode_next, zone);

    Block* catch_block = factory->NewBlock(nullptr, 1, false, nopos);
    catch_block->statements()->Add(set_mode_throw, zone);

    Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
    catch_scope->set_is_hidden();
    const AstRawString* name = avfactory->dot_catch_string();
    Variable* catch_variable =
        catch_scope->DeclareLocal(name, VAR, kCreatedInitialized,
                                               Variable::NORMAL);

    try_catch = factory->NewTryCatchStatement(
        try_block, catch_scope, catch_variable, catch_block, nopos);
  }


  // try { ... } finally { ... }
  Statement* try_finally;
  {
    Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
    try_block->statements()->Add(try_catch, zone);

    Block* finally = factory->NewBlock(nullptr, 2, false, nopos);
    finally->statements()->Add(get_input, zone);
    finally->statements()->Add(
        factory->NewContinueStatement(loop, nopos), zone);

    try_finally = factory->NewTryFinallyStatement(try_block, finally, nopos);
  }


  // switch (mode) { ... }
  SwitchStatement* switch_mode = factory->NewSwitchStatement(nullptr, nopos);
  {
    auto case_next = new (zone) ZoneList<Statement*>(3, zone);
    case_next->Add(call_next, zone);
    case_next->Add(validate_next_output, zone);
    case_next->Add(factory->NewBreakStatement(switch_mode, nopos), zone);

    auto case_return = new (zone) ZoneList<Statement*>(5, zone);
    BuildIteratorClose(case_return, var_iterator, var_input, var_output);
    case_return->Add(factory->NewBreakStatement(switch_mode, nopos), zone);

    auto case_throw = new (zone) ZoneList<Statement*>(5, zone);
    case_throw->Add(get_throw, zone);
    case_throw->Add(check_throw, zone);
    case_throw->Add(call_throw, zone);
    case_throw->Add(validate_throw_output, zone);
    case_throw->Add(factory->NewBreakStatement(switch_mode, nopos), zone);

    auto cases = new (zone) ZoneList<CaseClause*>(3, zone);
    Expression* knext = factory->NewSmiLiteral(JSGeneratorObject::kNext, nopos);
    Expression* kreturn =
        factory->NewSmiLiteral(JSGeneratorObject::kReturn, nopos);
    Expression* kthrow =
        factory->NewSmiLiteral(JSGeneratorObject::kThrow, nopos);
    cases->Add(factory->NewCaseClause(knext, case_next, nopos), zone);
    cases->Add(factory->NewCaseClause(kreturn, case_return, nopos), zone);
    cases->Add(factory->NewCaseClause(kthrow, case_throw, nopos), zone);

    switch_mode->Initialize(factory->NewVariableProxy(var_mode), cases);
  }


  // while (true) { ... }
  // Already defined earlier: WhileStatement* loop = ...
  {
    Block* loop_body = factory->NewBlock(nullptr, 4, false, nopos);
    loop_body->statements()->Add(switch_mode, zone);
    loop_body->statements()->Add(if_done, zone);
    loop_body->statements()->Add(set_mode_return, zone);
    loop_body->statements()->Add(try_finally, zone);

    loop->Initialize(factory->NewBooleanLiteral(true, nopos), loop_body);
  }


  // do { ... }
  DoExpression* yield_star;
  {
    // The rewriter needs to process the get_value statement only, hence we
    // put the preceding statements into an init block.

    Block* do_block_ = factory->NewBlock(nullptr, 7, true, nopos);
    do_block_->statements()->Add(initialize_input, zone);
    do_block_->statements()->Add(initialize_mode, zone);
    do_block_->statements()->Add(initialize_output, zone);
    do_block_->statements()->Add(get_iterator, zone);
    do_block_->statements()->Add(validate_iterator, zone);
    do_block_->statements()->Add(loop, zone);
    do_block_->statements()->Add(maybe_return_value, zone);

    Block* do_block = factory->NewBlock(nullptr, 2, false, nopos);
    do_block->statements()->Add(do_block_, zone);
    do_block->statements()->Add(get_value, zone);

    Variable* dot_result = scope->NewTemporary(avfactory->dot_result_string());
    yield_star = factory->NewDoExpression(do_block, dot_result, nopos);
    Rewriter::Rewrite(parser_, yield_star, avfactory);
  }

  return yield_star;
}

Statement* ParserTraits::CheckCallable(Variable* var, Expression* error,
                                       int pos) {
  auto factory = parser_->factory();
  auto avfactory = parser_->ast_value_factory();
  const int nopos = RelocInfo::kNoPosition;
  Statement* validate_var;
  {
    Expression* type_of = factory->NewUnaryOperation(
        Token::TYPEOF, factory->NewVariableProxy(var), nopos);
    Expression* function_literal =
        factory->NewStringLiteral(avfactory->function_string(), nopos);
    Expression* condition = factory->NewCompareOperation(
        Token::EQ_STRICT, type_of, function_literal, nopos);

    Statement* throw_call = factory->NewExpressionStatement(error, pos);

    validate_var = factory->NewIfStatement(
        condition, factory->NewEmptyStatement(nopos), throw_call, nopos);
  }
  return validate_var;
}

void ParserTraits::BuildIteratorClose(ZoneList<Statement*>* statements,
                                      Variable* iterator, Variable* input,
                                      Variable* var_output) {
  //
  // This function adds four statements to [statements], corresponding to the
  // following code:
  //
  //   let iteratorReturn = iterator.return;
  //   if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
  //     return {value: input, done: true};
  //   }
  //   output = %_Call(iteratorReturn, iterator, input);
  //   if (!IS_RECEIVER(output)) %ThrowIterResultNotAnObject(output);
  //

  const int nopos = RelocInfo::kNoPosition;
  auto factory = parser_->factory();
  auto avfactory = parser_->ast_value_factory();
  auto zone = parser_->zone();

  // let iteratorReturn = iterator.return;
  Variable* var_return = var_output;  // Reusing the output variable.
  Statement* get_return;
  {
    Expression* iterator_proxy = factory->NewVariableProxy(iterator);
    Expression* literal =
        factory->NewStringLiteral(avfactory->return_string(), nopos);
    Expression* property =
        factory->NewProperty(iterator_proxy, literal, nopos);
    Expression* return_proxy = factory->NewVariableProxy(var_return);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, return_proxy, property, nopos);
    get_return = factory->NewExpressionStatement(assignment, nopos);
  }

  // if (IS_NULL_OR_UNDEFINED(iteratorReturn) {
  //   return {value: input, done: true};
  // }
  Statement* check_return;
  {
    Expression* condition = factory->NewCompareOperation(
        Token::EQ, factory->NewVariableProxy(var_return),
        factory->NewNullLiteral(nopos), nopos);

    Expression* value = factory->NewVariableProxy(input);

    Statement* return_input =
        factory->NewReturnStatement(BuildIteratorResult(value, true), nopos);

    check_return = factory->NewIfStatement(
        condition, return_input, factory->NewEmptyStatement(nopos), nopos);
  }

  // output = %_Call(iteratorReturn, iterator, input);
  Statement* call_return;
  {
    auto args = new (zone) ZoneList<Expression*>(3, zone);
    args->Add(factory->NewVariableProxy(var_return), zone);
    args->Add(factory->NewVariableProxy(iterator), zone);
    args->Add(factory->NewVariableProxy(input), zone);

    Expression* call =
        factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);
    Expression* output_proxy = factory->NewVariableProxy(var_output);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, output_proxy, call, nopos);
    call_return = factory->NewExpressionStatement(assignment, nopos);
  }

  // if (!IS_RECEIVER(output)) %ThrowIteratorResultNotAnObject(output);
  Statement* validate_output;
  {
    Expression* is_receiver_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      is_receiver_call =
          factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
    }

    Statement* throw_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      Expression* call = factory->NewCallRuntime(
          Runtime::kThrowIteratorResultNotAnObject, args, nopos);
      throw_call = factory->NewExpressionStatement(call, nopos);
    }

    validate_output = factory->NewIfStatement(
        is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);
  }

  statements->Add(get_return, zone);
  statements->Add(check_return, zone);
  statements->Add(call_return, zone);
  statements->Add(validate_output, zone);
}

void ParserTraits::FinalizeIteratorUse(Variable* completion,
                                       Expression* condition, Variable* iter,
                                       Block* iterator_use, Block* target) {
  //
  // This function adds two statements to [target], corresponding to the
  // following code:
  //
  //   completion = kNormalCompletion;
  //   try {
  //     try {
  //       iterator_use
  //     } catch(e) {
  //       if (completion === kAbruptCompletion) completion = kThrowCompletion;
  //       %ReThrow(e);
  //     }
  //   } finally {
  //     if (condition) {
  //       #BuildIteratorCloseForCompletion(iter, completion)
  //     }
  //   }
  //

  const int nopos = RelocInfo::kNoPosition;
  auto factory = parser_->factory();
  auto avfactory = parser_->ast_value_factory();
  auto scope = parser_->scope_;
  auto zone = parser_->zone();

  // completion = kNormalCompletion;
  Statement* initialize_completion;
  {
    Expression* proxy = factory->NewVariableProxy(completion);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, proxy,
        factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
    initialize_completion = factory->NewExpressionStatement(assignment, nopos);
  }

  // if (completion === kAbruptCompletion) completion = kThrowCompletion;
  Statement* set_completion_throw;
  {
    Expression* condition = factory->NewCompareOperation(
        Token::EQ_STRICT, factory->NewVariableProxy(completion),
        factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);

    Expression* proxy = factory->NewVariableProxy(completion);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, proxy,
        factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);
    Statement* statement = factory->NewExpressionStatement(assignment, nopos);
    set_completion_throw = factory->NewIfStatement(
        condition, statement, factory->NewEmptyStatement(nopos), nopos);
  }

  // if (condition) {
  //   #BuildIteratorCloseForCompletion(iter, completion)
  // }
  Block* maybe_close;
  {
    Block* block = factory->NewBlock(nullptr, 2, true, nopos);
    Expression* proxy = factory->NewVariableProxy(completion);
    parser_->BuildIteratorCloseForCompletion(block->statements(), iter, proxy);
    DCHECK(block->statements()->length() == 2);

    maybe_close = factory->NewBlock(nullptr, 1, true, nopos);
    maybe_close->statements()->Add(
        factory->NewIfStatement(condition, block,
                                factory->NewEmptyStatement(nopos), nopos),
        zone);
  }

  // try { #try_block }
  // catch(e) {
  //   #set_completion_throw;
  //   %ReThrow(e);
  // }
  Statement* try_catch;
  {
    Scope* catch_scope = parser_->NewScope(scope, CATCH_SCOPE);
    Variable* catch_variable =
        catch_scope->DeclareLocal(avfactory->dot_catch_string(), VAR,
                                  kCreatedInitialized, Variable::NORMAL);
    catch_scope->set_is_hidden();

    Statement* rethrow;
    // We use %ReThrow rather than the ordinary throw because we want to
    // preserve the original exception message.  This is also why we create a
    // TryCatchStatementForReThrow below (which does not clear the pending
    // message), rather than a TryCatchStatement.
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(catch_variable), zone);
      rethrow = factory->NewExpressionStatement(
          factory->NewCallRuntime(Runtime::kReThrow, args, nopos), nopos);
    }

    Block* catch_block = factory->NewBlock(nullptr, 2, false, nopos);
    catch_block->statements()->Add(set_completion_throw, zone);
    catch_block->statements()->Add(rethrow, zone);

    try_catch = factory->NewTryCatchStatementForReThrow(
        iterator_use, catch_scope, catch_variable, catch_block, nopos);
  }

  // try { #try_catch } finally { #maybe_close }
  Statement* try_finally;
  {
    Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
    try_block->statements()->Add(try_catch, zone);

    try_finally =
        factory->NewTryFinallyStatement(try_block, maybe_close, nopos);
  }

  target->statements()->Add(initialize_completion, zone);
  target->statements()->Add(try_finally, zone);
}

void ParserTraits::BuildIteratorCloseForCompletion(
    ZoneList<Statement*>* statements, Variable* iterator,
    Expression* completion) {
  //
  // This function adds two statements to [statements], corresponding to the
  // following code:
  //
  //   let iteratorReturn = iterator.return;
  //   if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) {
  //     if (completion === kThrowCompletion) {
  //       if (!IS_CALLABLE(iteratorReturn)) {
  //         throw MakeTypeError(kReturnMethodNotCallable);
  //       }
  //       try { %_Call(iteratorReturn, iterator) } catch (_) { }
  //     } else {
  //       let output = %_Call(iteratorReturn, iterator);
  //       if (!IS_RECEIVER(output)) {
  //         %ThrowIterResultNotAnObject(output);
  //       }
  //     }
  //   }
  //

  const int nopos = RelocInfo::kNoPosition;
  auto factory = parser_->factory();
  auto avfactory = parser_->ast_value_factory();
  auto scope = parser_->scope_;
  auto zone = parser_->zone();


  // let iteratorReturn = iterator.return;
  Variable* var_return = scope->NewTemporary(avfactory->empty_string());
  Statement* get_return;
  {
    Expression* iterator_proxy = factory->NewVariableProxy(iterator);
    Expression* literal =
        factory->NewStringLiteral(avfactory->return_string(), nopos);
    Expression* property =
        factory->NewProperty(iterator_proxy, literal, nopos);
    Expression* return_proxy = factory->NewVariableProxy(var_return);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, return_proxy, property, nopos);
    get_return = factory->NewExpressionStatement(assignment, nopos);
  }

  // if (!IS_CALLABLE(iteratorReturn)) {
  //   throw MakeTypeError(kReturnMethodNotCallable);
  // }
  Statement* check_return_callable;
  {
    Expression* throw_expr = NewThrowTypeError(
        MessageTemplate::kReturnMethodNotCallable,
        avfactory->empty_string(), nopos);
    check_return_callable = CheckCallable(var_return, throw_expr, nopos);
  }

  // try { %_Call(iteratorReturn, iterator) } catch (_) { }
  Statement* try_call_return;
  {
    auto args = new (zone) ZoneList<Expression*>(2, zone);
    args->Add(factory->NewVariableProxy(var_return), zone);
    args->Add(factory->NewVariableProxy(iterator), zone);

    Expression* call =
        factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);

    Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
    try_block->statements()->Add(factory->NewExpressionStatement(call, nopos),
                                 zone);

    Block* catch_block = factory->NewBlock(nullptr, 0, false, nopos);

    Scope* catch_scope = NewScope(scope, CATCH_SCOPE);
    Variable* catch_variable = catch_scope->DeclareLocal(
        avfactory->dot_catch_string(), VAR, kCreatedInitialized,
        Variable::NORMAL);
    catch_scope->set_is_hidden();

    try_call_return = factory->NewTryCatchStatement(
        try_block, catch_scope, catch_variable, catch_block, nopos);
  }

  // let output = %_Call(iteratorReturn, iterator);
  // if (!IS_RECEIVER(output)) {
  //   %ThrowIteratorResultNotAnObject(output);
  // }
  Block* validate_return;
  {
    Variable* var_output = scope->NewTemporary(avfactory->empty_string());
    Statement* call_return;
    {
      auto args = new (zone) ZoneList<Expression*>(2, zone);
      args->Add(factory->NewVariableProxy(var_return), zone);
      args->Add(factory->NewVariableProxy(iterator), zone);
      Expression* call =
          factory->NewCallRuntime(Runtime::kInlineCall, args, nopos);

      Expression* output_proxy = factory->NewVariableProxy(var_output);
      Expression* assignment =
          factory->NewAssignment(Token::ASSIGN, output_proxy, call, nopos);
      call_return = factory->NewExpressionStatement(assignment, nopos);
    }

    Expression* is_receiver_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      is_receiver_call =
          factory->NewCallRuntime(Runtime::kInlineIsJSReceiver, args, nopos);
    }

    Statement* throw_call;
    {
      auto args = new (zone) ZoneList<Expression*>(1, zone);
      args->Add(factory->NewVariableProxy(var_output), zone);
      Expression* call = factory->NewCallRuntime(
          Runtime::kThrowIteratorResultNotAnObject, args, nopos);
      throw_call = factory->NewExpressionStatement(call, nopos);
    }

    Statement* check_return = factory->NewIfStatement(
        is_receiver_call, factory->NewEmptyStatement(nopos), throw_call, nopos);

    validate_return = factory->NewBlock(nullptr, 2, false, nopos);
    validate_return->statements()->Add(call_return, zone);
    validate_return->statements()->Add(check_return, zone);
  }

  // if (completion === kThrowCompletion) {
  //   #check_return_callable;
  //   #try_call_return;
  // } else {
  //   #validate_return;
  // }
  Statement* call_return_carefully;
  {
    Expression* condition = factory->NewCompareOperation(
        Token::EQ_STRICT, completion,
        factory->NewSmiLiteral(Parser::kThrowCompletion, nopos), nopos);

    Block* then_block = factory->NewBlock(nullptr, 2, false, nopos);
    then_block->statements()->Add(check_return_callable, zone);
    then_block->statements()->Add(try_call_return, zone);

    call_return_carefully =
        factory->NewIfStatement(condition, then_block, validate_return, nopos);
  }

  // if (!IS_NULL_OR_UNDEFINED(iteratorReturn)) { ... }
  Statement* maybe_call_return;
  {
    Expression* condition = factory->NewCompareOperation(
        Token::EQ, factory->NewVariableProxy(var_return),
        factory->NewNullLiteral(nopos), nopos);

    maybe_call_return =
        factory->NewIfStatement(condition, factory->NewEmptyStatement(nopos),
                                call_return_carefully, nopos);
  }


  statements->Add(get_return, zone);
  statements->Add(maybe_call_return, zone);
}


Statement* ParserTraits::FinalizeForOfStatement(ForOfStatement* loop, int pos) {
  //
  // This function replaces the loop with the following wrapping:
  //
  //   let each;
  //   let completion = kNormalCompletion;
  //   try {
  //     try {
  //       #loop;
  //     } catch(e) {
  //       if (completion === kAbruptCompletion) completion = kThrowCompletion;
  //       %ReThrow(e);
  //     }
  //   } finally {
  //     if (!(completion === kNormalCompletion || IS_UNDEFINED(#iterator))) {
  //       #BuildIteratorCloseForCompletion(#iterator, completion)
  //     }
  //   }
  //
  // where the loop's body is wrapped as follows:
  //
  //   {
  //     #loop-body
  //     {{completion = kNormalCompletion;}}
  //   }
  //
  // and the loop's assign_each is wrapped as follows
  //
  //   do {
  //     {{completion = kAbruptCompletion;}}
  //     #assign-each
  //   }
  //

  const int nopos = RelocInfo::kNoPosition;
  auto factory = parser_->factory();
  auto avfactory = parser_->ast_value_factory();
  auto scope = parser_->scope_;
  auto zone = parser_->zone();

  Variable* var_completion = scope->NewTemporary(avfactory->empty_string());

  // let each;
  Variable* var_each = scope->NewTemporary(avfactory->empty_string());
  Statement* initialize_each;
  {
    Expression* proxy = factory->NewVariableProxy(var_each);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, proxy,
        factory->NewUndefinedLiteral(nopos), nopos);
    initialize_each =
        factory->NewExpressionStatement(assignment, nopos);
  }

  // !(completion === kNormalCompletion || IS_UNDEFINED(#iterator))
  Expression* closing_condition;
  {
    Expression* lhs = factory->NewCompareOperation(
        Token::EQ_STRICT, factory->NewVariableProxy(var_completion),
        factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);
    Expression* rhs = factory->NewCompareOperation(
        Token::EQ_STRICT, factory->NewVariableProxy(loop->iterator()),
        factory->NewUndefinedLiteral(nopos), nopos);
    closing_condition = factory->NewUnaryOperation(
        Token::NOT, factory->NewBinaryOperation(Token::OR, lhs, rhs, nopos),
        nopos);
  }

  // {{completion = kNormalCompletion;}}
  Statement* set_completion_normal;
  {
    Expression* proxy = factory->NewVariableProxy(var_completion);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, proxy,
        factory->NewSmiLiteral(Parser::kNormalCompletion, nopos), nopos);

    Block* block = factory->NewBlock(nullptr, 1, true, nopos);
    block->statements()->Add(
        factory->NewExpressionStatement(assignment, nopos), zone);
    set_completion_normal = block;
  }

  // {{completion = kAbruptCompletion;}}
  Statement* set_completion_abrupt;
  {
    Expression* proxy = factory->NewVariableProxy(var_completion);
    Expression* assignment = factory->NewAssignment(
        Token::ASSIGN, proxy,
        factory->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);

    Block* block = factory->NewBlock(nullptr, 1, true, nopos);
    block->statements()->Add(factory->NewExpressionStatement(assignment, nopos),
                             zone);
    set_completion_abrupt = block;
  }

  // { #loop-body; #set_completion_normal }
  Block* new_body = factory->NewBlock(nullptr, 2, false, nopos);
  {
    new_body->statements()->Add(loop->body(), zone);
    new_body->statements()->Add(set_completion_normal, zone);
  }

  // { #set_completion_abrupt; #assign-each }
  Block* new_assign_each = factory->NewBlock(nullptr, 2, false, nopos);
  {
    new_assign_each->statements()->Add(set_completion_abrupt, zone);
    new_assign_each->statements()->Add(
        factory->NewExpressionStatement(loop->assign_each(), nopos), zone);
  }

  // Now put things together.

  loop->set_body(new_body);
  loop->set_assign_each(
      factory->NewDoExpression(new_assign_each, var_each, nopos));

  Statement* final_loop;
  {
    Block* target = factory->NewBlock(nullptr, 3, false, nopos);
    target->statements()->Add(initialize_each, zone);

    Block* try_block = factory->NewBlock(nullptr, 1, false, nopos);
    try_block->statements()->Add(loop, zone);

    FinalizeIteratorUse(var_completion, closing_condition, loop->iterator(),
                        try_block, target);
    final_loop = target;
  }

  return final_loop;
}


}  // namespace internal
}  // namespace v8
