// Copyright 2015 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/ast/ast.h"
#include "src/messages.h"
#include "src/objects-inl.h"
#include "src/parsing/expression-scope-reparenter.h"
#include "src/parsing/parser.h"

namespace v8 {

namespace internal {

class PatternRewriter final : public AstVisitor<PatternRewriter> {
 public:
  // Limit the allowed number of local variables in a function. The hard limit
  // is that offsets computed by FullCodeGenerator::StackOperand and similar
  // functions are ints, and they should not overflow. In addition, accessing
  // local variables creates user-controlled constants in the generated code,
  // and we don't want too much user-controlled memory inside the code (this was
  // the reason why this limit was introduced in the first place; see
  // https://codereview.chromium.org/7003030/ ).
  static const int kMaxNumFunctionLocals = 4194303;  // 2^22-1

  typedef Parser::DeclarationDescriptor DeclarationDescriptor;

  static void DeclareAndInitializeVariables(
      Parser* parser, Block* block,
      const DeclarationDescriptor* declaration_descriptor,
      const Parser::DeclarationParsingResult::Declaration* declaration,
      ZoneList<const AstRawString*>* names, bool* ok);

  static void RewriteDestructuringAssignment(Parser* parser,
                                             RewritableExpression* to_rewrite,
                                             Scope* scope);

 private:
  enum PatternContext { BINDING, ASSIGNMENT, ASSIGNMENT_ELEMENT };

  class AssignmentElementScope {
   public:
    explicit AssignmentElementScope(PatternRewriter* rewriter)
        : rewriter_(rewriter), context_(rewriter->context()) {
      if (context_ == ASSIGNMENT) rewriter->context_ = ASSIGNMENT_ELEMENT;
    }
    ~AssignmentElementScope() { rewriter_->context_ = context_; }

   private:
    PatternRewriter* const rewriter_;
    const PatternContext context_;
  };

  PatternRewriter(Scope* scope, Parser* parser, PatternContext context)
      : scope_(scope),
        parser_(parser),
        context_(context),
        initializer_position_(kNoSourcePosition),
        value_beg_position_(kNoSourcePosition),
        block_(nullptr),
        descriptor_(nullptr),
        names_(nullptr),
        current_value_(nullptr),
        recursion_level_(0),
        ok_(nullptr) {}

#define DECLARE_VISIT(type) void Visit##type(v8::internal::type* node);
  // Visiting functions for AST nodes make this an AstVisitor.
  AST_NODE_LIST(DECLARE_VISIT)
#undef DECLARE_VISIT

  PatternContext context() const { return context_; }

  void RecurseIntoSubpattern(AstNode* pattern, Expression* value) {
    Expression* old_value = current_value_;
    current_value_ = value;
    recursion_level_++;
    Visit(pattern);
    recursion_level_--;
    current_value_ = old_value;
  }

  void VisitObjectLiteral(ObjectLiteral* node, Variable** temp_var);
  void VisitArrayLiteral(ArrayLiteral* node, Variable** temp_var);

  bool IsBindingContext() const { return context_ == BINDING; }
  bool IsAssignmentContext() const {
    return context_ == ASSIGNMENT || context_ == ASSIGNMENT_ELEMENT;
  }
  bool IsSubPattern() const { return recursion_level_ > 1; }

  bool DeclaresParameterContainingSloppyEval() const;
  void RewriteParameterScopes(Expression* expr);

  Variable* CreateTempVar(Expression* value = nullptr);

  AstNodeFactory* factory() const { return parser_->factory(); }
  AstValueFactory* ast_value_factory() const {
    return parser_->ast_value_factory();
  }
  Zone* zone() const { return parser_->zone(); }
  Scope* scope() const { return scope_; }

  Scope* const scope_;
  Parser* const parser_;
  PatternContext context_;
  int initializer_position_;
  int value_beg_position_;
  Block* block_;
  const DeclarationDescriptor* descriptor_;
  ZoneList<const AstRawString*>* names_;
  Expression* current_value_;
  int recursion_level_;
  bool* ok_;

  DEFINE_AST_VISITOR_MEMBERS_WITHOUT_STACKOVERFLOW()
};

void Parser::DeclareAndInitializeVariables(
    Block* block, const DeclarationDescriptor* declaration_descriptor,
    const DeclarationParsingResult::Declaration* declaration,
    ZoneList<const AstRawString*>* names, bool* ok) {
  PatternRewriter::DeclareAndInitializeVariables(
      this, block, declaration_descriptor, declaration, names, ok);
}

void Parser::RewriteDestructuringAssignment(RewritableExpression* to_rewrite) {
  PatternRewriter::RewriteDestructuringAssignment(this, to_rewrite, scope());
}

Expression* Parser::RewriteDestructuringAssignment(Assignment* assignment) {
  DCHECK_NOT_NULL(assignment);
  DCHECK_EQ(Token::ASSIGN, assignment->op());
  auto to_rewrite = factory()->NewRewritableExpression(assignment, scope());
  RewriteDestructuringAssignment(to_rewrite);
  return to_rewrite->expression();
}

void PatternRewriter::DeclareAndInitializeVariables(
    Parser* parser, Block* block,
    const DeclarationDescriptor* declaration_descriptor,
    const Parser::DeclarationParsingResult::Declaration* declaration,
    ZoneList<const AstRawString*>* names, bool* ok) {
  DCHECK(block->ignore_completion_value());

  PatternRewriter rewriter(declaration_descriptor->scope, parser, BINDING);
  rewriter.initializer_position_ = declaration->initializer_position;
  rewriter.value_beg_position_ = declaration->value_beg_position;
  rewriter.block_ = block;
  rewriter.descriptor_ = declaration_descriptor;
  rewriter.names_ = names;
  rewriter.ok_ = ok;

  rewriter.RecurseIntoSubpattern(declaration->pattern,
                                 declaration->initializer);
}

void PatternRewriter::RewriteDestructuringAssignment(
    Parser* parser, RewritableExpression* to_rewrite, Scope* scope) {
  DCHECK(!scope->HasBeenRemoved());
  DCHECK(!to_rewrite->is_rewritten());

  PatternRewriter rewriter(scope, parser, ASSIGNMENT);
  rewriter.RecurseIntoSubpattern(to_rewrite, nullptr);
}

void PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
  Expression* value = current_value_;

  if (IsAssignmentContext()) {
    // In an assignment context, simply perform the assignment
    Assignment* assignment = factory()->NewAssignment(
        Token::ASSIGN, pattern, value, pattern->position());
    block_->statements()->Add(
        factory()->NewExpressionStatement(assignment, pattern->position()),
        zone());
    return;
  }

  DCHECK_NOT_NULL(block_);
  DCHECK_NOT_NULL(descriptor_);
  DCHECK_NOT_NULL(ok_);

  descriptor_->scope->RemoveUnresolved(pattern);

  // Declare variable.
  // Note that we *always* must treat the initial value via a separate init
  // assignment for variables and constants because the value must be assigned
  // when the variable is encountered in the source. But the variable/constant
  // is declared (and set to 'undefined') upon entering the function within
  // which the variable or constant is declared. Only function variables have
  // an initial value in the declaration (because they are initialized upon
  // entering the function).
  const AstRawString* name = pattern->raw_name();
  VariableProxy* proxy =
      factory()->NewVariableProxy(name, NORMAL_VARIABLE, pattern->position());
  Declaration* declaration;
  if (descriptor_->mode == VAR && !descriptor_->scope->is_declaration_scope()) {
    DCHECK(descriptor_->scope->is_block_scope() ||
           descriptor_->scope->is_with_scope());
    declaration = factory()->NewNestedVariableDeclaration(
        proxy, descriptor_->scope, descriptor_->declaration_pos);
  } else {
    declaration =
        factory()->NewVariableDeclaration(proxy, descriptor_->declaration_pos);
  }

  // When an extra declaration scope needs to be inserted to account for
  // a sloppy eval in a default parameter or function body, the parameter
  // needs to be declared in the function's scope, not in the varblock
  // scope which will be used for the initializer expression.
  Scope* outer_function_scope = nullptr;
  if (DeclaresParameterContainingSloppyEval()) {
    outer_function_scope = descriptor_->scope->outer_scope();
  }
  Variable* var = parser_->Declare(
      declaration, descriptor_->declaration_kind, descriptor_->mode,
      Variable::DefaultInitializationFlag(descriptor_->mode), ok_,
      outer_function_scope);
  if (!*ok_) return;
  DCHECK_NOT_NULL(var);
  DCHECK(proxy->is_resolved());
  DCHECK_NE(initializer_position_, kNoSourcePosition);
  var->set_initializer_position(initializer_position_);

  Scope* declaration_scope =
      outer_function_scope != nullptr
          ? outer_function_scope
          : (IsLexicalVariableMode(descriptor_->mode)
                 ? descriptor_->scope
                 : descriptor_->scope->GetDeclarationScope());
  if (declaration_scope->num_var() > kMaxNumFunctionLocals) {
    parser_->ReportMessage(MessageTemplate::kTooManyVariables);
    *ok_ = false;
    return;
  }
  if (names_) {
    names_->Add(name, zone());
  }

  // If there's no initializer, we're done.
  if (value == nullptr) return;

  Scope* var_init_scope = descriptor_->scope;
  Parser::MarkLoopVariableAsAssigned(var_init_scope, proxy->var(),
                                     descriptor_->declaration_kind);

  // A declaration of the form:
  //
  //    var v = x;
  //
  // is syntactic sugar for:
  //
  //    var v; v = x;
  //
  // In particular, we need to re-lookup 'v' as it may be a different
  // 'v' than the 'v' in the declaration (e.g., if we are inside a
  // 'with' statement or 'catch' block). Global var declarations
  // also need special treatment.

  // For 'let' and 'const' declared variables the initialization always
  // assigns to the declared variable.
  // But for var declarations we need to do a new lookup.
  if (descriptor_->mode == VAR) {
    proxy = var_init_scope->NewUnresolved(factory(), name);
  } else {
    DCHECK_NOT_NULL(proxy);
    DCHECK_NOT_NULL(proxy->var());
  }
  // Add break location for destructured sub-pattern.
  int pos = value_beg_position_;
  if (pos == kNoSourcePosition) {
    pos = IsSubPattern() ? pattern->position() : value->position();
  }
  Assignment* assignment =
      factory()->NewAssignment(Token::INIT, proxy, value, pos);
  block_->statements()->Add(factory()->NewExpressionStatement(assignment, pos),
                            zone());
}

Variable* PatternRewriter::CreateTempVar(Expression* value) {
  auto temp = scope()->NewTemporary(ast_value_factory()->empty_string());
  if (value != nullptr) {
    auto assignment = factory()->NewAssignment(
        Token::ASSIGN, factory()->NewVariableProxy(temp), value,
        kNoSourcePosition);

    block_->statements()->Add(
        factory()->NewExpressionStatement(assignment, kNoSourcePosition),
        zone());
  }
  return temp;
}

void PatternRewriter::VisitRewritableExpression(RewritableExpression* node) {
  if (!node->expression()->IsAssignment()) {
    // RewritableExpressions are also used for desugaring Spread, which is
    // orthogonal to PatternRewriter; just visit the underlying expression.
    DCHECK_EQ(AstNode::kArrayLiteral, node->expression()->node_type());
    return Visit(node->expression());
  } else if (context() != ASSIGNMENT) {
    // This is not a destructuring assignment. Mark the node as rewritten to
    // prevent redundant rewriting and visit the underlying expression.
    DCHECK(!node->is_rewritten());
    node->set_rewritten();
    return Visit(node->expression());
  }

  DCHECK(!node->is_rewritten());
  DCHECK_EQ(ASSIGNMENT, context());
  Assignment* assign = node->expression()->AsAssignment();
  DCHECK_NOT_NULL(assign);
  DCHECK_EQ(Token::ASSIGN, assign->op());

  int pos = assign->position();
  Block* old_block = block_;
  block_ = factory()->NewBlock(8, true);
  Variable* temp = nullptr;
  Expression* pattern = assign->target();
  Expression* old_value = current_value_;
  current_value_ = assign->value();
  if (pattern->IsObjectLiteral()) {
    VisitObjectLiteral(pattern->AsObjectLiteral(), &temp);
  } else {
    DCHECK(pattern->IsArrayLiteral());
    VisitArrayLiteral(pattern->AsArrayLiteral(), &temp);
  }
  DCHECK_NOT_NULL(temp);
  current_value_ = old_value;
  Expression* expr = factory()->NewDoExpression(block_, temp, pos);
  node->Rewrite(expr);
  block_ = old_block;
  if (block_) {
    block_->statements()->Add(factory()->NewExpressionStatement(expr, pos),
                              zone());
  }
}

bool PatternRewriter::DeclaresParameterContainingSloppyEval() const {
  // Need to check for a binding context to make sure we have a descriptor.
  if (IsBindingContext() &&
      // Only relevant for parameters.
      descriptor_->declaration_kind == DeclarationDescriptor::PARAMETER &&
      // And only when scope is a block scope;
      // without eval, it is a function scope.
      scope()->is_block_scope()) {
    DCHECK(scope()->is_declaration_scope());
    DCHECK(scope()->AsDeclarationScope()->calls_sloppy_eval());
    DCHECK(scope()->outer_scope()->is_function_scope());
    return true;
  }

  return false;
}

// When an extra declaration scope needs to be inserted to account for
// a sloppy eval in a default parameter or function body, the expressions
// needs to be in that new inner scope which was added after initial
// parsing.
void PatternRewriter::RewriteParameterScopes(Expression* expr) {
  if (DeclaresParameterContainingSloppyEval()) {
    ReparentExpressionScope(parser_->stack_limit(), expr, scope());
  }
}

void PatternRewriter::VisitObjectLiteral(ObjectLiteral* pattern,
                                         Variable** temp_var) {
  auto temp = *temp_var = CreateTempVar(current_value_);

  ZoneList<Expression*>* rest_runtime_callargs = nullptr;
  if (pattern->has_rest_property()) {
    // non_rest_properties_count = pattern->properties()->length - 1;
    // args_length = 1 + non_rest_properties_count because we need to
    // pass temp as well to the runtime function.
    int args_length = pattern->properties()->length();
    rest_runtime_callargs =
        new (zone()) ZoneList<Expression*>(args_length, zone());
    rest_runtime_callargs->Add(factory()->NewVariableProxy(temp), zone());
  }

  block_->statements()->Add(parser_->BuildAssertIsCoercible(temp, pattern),
                            zone());

  for (ObjectLiteralProperty* property : *pattern->properties()) {
    Expression* value;

    if (property->kind() == ObjectLiteralProperty::Kind::SPREAD) {
      // var { y, [x++]: a, ...c } = temp
      //     becomes
      // var y = temp.y;
      // var temp1 = %ToName(x++);
      // var a = temp[temp1];
      // var c;
      // c = %CopyDataPropertiesWithExcludedProperties(temp, "y", temp1);
      value = factory()->NewCallRuntime(
          Runtime::kCopyDataPropertiesWithExcludedProperties,
          rest_runtime_callargs, kNoSourcePosition);
    } else {
      Expression* key = property->key();

      if (!key->IsLiteral()) {
        // Computed property names contain expressions which might require
        // scope rewriting.
        RewriteParameterScopes(key);
      }

      if (pattern->has_rest_property()) {
        Expression* excluded_property = key;

        if (property->is_computed_name()) {
          DCHECK(!key->IsPropertyName() || !key->IsNumberLiteral());
          auto args = new (zone()) ZoneList<Expression*>(1, zone());
          args->Add(key, zone());
          auto to_name_key = CreateTempVar(factory()->NewCallRuntime(
              Runtime::kToName, args, kNoSourcePosition));
          key = factory()->NewVariableProxy(to_name_key);
          excluded_property = factory()->NewVariableProxy(to_name_key);
        } else {
          DCHECK(key->IsPropertyName() || key->IsNumberLiteral());
        }

        DCHECK_NOT_NULL(rest_runtime_callargs);
        rest_runtime_callargs->Add(excluded_property, zone());
      }

      value = factory()->NewProperty(factory()->NewVariableProxy(temp), key,
                                     kNoSourcePosition);
    }

    AssignmentElementScope element_scope(this);
    RecurseIntoSubpattern(property->value(), value);
  }
}

void PatternRewriter::VisitObjectLiteral(ObjectLiteral* node) {
  Variable* temp_var = nullptr;
  VisitObjectLiteral(node, &temp_var);
}

void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node,
                                        Variable** temp_var) {
  DCHECK(block_->ignore_completion_value());

  auto temp = *temp_var = CreateTempVar(current_value_);
  auto iterator = CreateTempVar(factory()->NewGetIterator(
      factory()->NewVariableProxy(temp), current_value_, IteratorType::kNormal,
      current_value_->position()));
  auto next = CreateTempVar(factory()->NewProperty(
      factory()->NewVariableProxy(iterator),
      factory()->NewStringLiteral(ast_value_factory()->next_string(),
                                  kNoSourcePosition),
      kNoSourcePosition));
  auto done =
      CreateTempVar(factory()->NewBooleanLiteral(false, kNoSourcePosition));
  auto result = CreateTempVar();
  auto v = CreateTempVar();
  auto completion = CreateTempVar();
  auto nopos = kNoSourcePosition;

  // For the purpose of iterator finalization, we temporarily set block_ to a
  // new block.  In the main body of this function, we write to block_ (both
  // explicitly and implicitly via recursion).  At the end of the function, we
  // wrap this new block in a try-finally statement, restore block_ to its
  // original value, and add the try-finally statement to block_.
  auto target = block_;
  block_ = factory()->NewBlock(8, true);

  Spread* spread = nullptr;
  for (Expression* value : *node->values()) {
    if (value->IsSpread()) {
      spread = value->AsSpread();
      break;
    }

    // if (!done) {
    //   done = true;  // If .next, .done or .value throws, don't close.
    //   result = IteratorNext(iterator);
    //   if (result.done) {
    //     v = undefined;
    //   } else {
    //     v = result.value;
    //     done = false;
    //   }
    // }
    Statement* if_not_done;
    {
      auto result_done = factory()->NewProperty(
          factory()->NewVariableProxy(result),
          factory()->NewStringLiteral(ast_value_factory()->done_string(),
                                      kNoSourcePosition),
          kNoSourcePosition);

      auto assign_undefined = factory()->NewAssignment(
          Token::ASSIGN, factory()->NewVariableProxy(v),
          factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);

      auto assign_value = factory()->NewAssignment(
          Token::ASSIGN, factory()->NewVariableProxy(v),
          factory()->NewProperty(
              factory()->NewVariableProxy(result),
              factory()->NewStringLiteral(ast_value_factory()->value_string(),
                                          kNoSourcePosition),
              kNoSourcePosition),
          kNoSourcePosition);

      auto unset_done = factory()->NewAssignment(
          Token::ASSIGN, factory()->NewVariableProxy(done),
          factory()->NewBooleanLiteral(false, kNoSourcePosition),
          kNoSourcePosition);

      auto inner_else = factory()->NewBlock(2, true);
      inner_else->statements()->Add(
          factory()->NewExpressionStatement(assign_value, nopos), zone());
      inner_else->statements()->Add(
          factory()->NewExpressionStatement(unset_done, nopos), zone());

      auto inner_if = factory()->NewIfStatement(
          result_done,
          factory()->NewExpressionStatement(assign_undefined, nopos),
          inner_else, nopos);

      auto next_block = factory()->NewBlock(3, true);
      next_block->statements()->Add(
          factory()->NewExpressionStatement(
              factory()->NewAssignment(
                  Token::ASSIGN, factory()->NewVariableProxy(done),
                  factory()->NewBooleanLiteral(true, nopos), nopos),
              nopos),
          zone());
      next_block->statements()->Add(
          factory()->NewExpressionStatement(
              parser_->BuildIteratorNextResult(
                  factory()->NewVariableProxy(iterator),
                  factory()->NewVariableProxy(next), result,
                  IteratorType::kNormal, kNoSourcePosition),
              kNoSourcePosition),
          zone());
      next_block->statements()->Add(inner_if, zone());

      if_not_done = factory()->NewIfStatement(
          factory()->NewUnaryOperation(
              Token::NOT, factory()->NewVariableProxy(done), kNoSourcePosition),
          next_block, factory()->NewEmptyStatement(kNoSourcePosition),
          kNoSourcePosition);
    }
    block_->statements()->Add(if_not_done, zone());

    if (!value->IsTheHoleLiteral()) {
      {
        // completion = kAbruptCompletion;
        Expression* proxy = factory()->NewVariableProxy(completion);
        Expression* assignment = factory()->NewAssignment(
            Token::ASSIGN, proxy,
            factory()->NewSmiLiteral(Parser::kAbruptCompletion, nopos), nopos);
        block_->statements()->Add(
            factory()->NewExpressionStatement(assignment, nopos), zone());
      }

      {
        AssignmentElementScope element_scope(this);
        RecurseIntoSubpattern(value, factory()->NewVariableProxy(v));
      }

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

  if (spread != nullptr) {
    // A spread can only occur as the last component.  It is not handled by
    // RecurseIntoSubpattern above.

    // let array = [];
    // while (!done) {
    //   done = true;  // If .next, .done or .value throws, don't close.
    //   result = IteratorNext(iterator);
    //   if (!result.done) {
    //     %AppendElement(array, result.value);
    //     done = false;
    //   }
    // }

    // let array = [];
    Variable* array;
    {
      auto empty_exprs = new (zone()) ZoneList<Expression*>(0, zone());
      array = CreateTempVar(
          factory()->NewArrayLiteral(empty_exprs, kNoSourcePosition));
    }

    // done = true;
    Statement* set_done = factory()->NewExpressionStatement(
        factory()->NewAssignment(
            Token::ASSIGN, factory()->NewVariableProxy(done),
            factory()->NewBooleanLiteral(true, nopos), nopos),
        nopos);

    // result = IteratorNext(iterator);
    Statement* get_next = factory()->NewExpressionStatement(
        parser_->BuildIteratorNextResult(factory()->NewVariableProxy(iterator),
                                         factory()->NewVariableProxy(next),
                                         result, IteratorType::kNormal, nopos),
        nopos);

    // %AppendElement(array, result.value);
    Statement* append_element;
    {
      auto args = new (zone()) ZoneList<Expression*>(2, zone());
      args->Add(factory()->NewVariableProxy(array), zone());
      args->Add(factory()->NewProperty(
                    factory()->NewVariableProxy(result),
                    factory()->NewStringLiteral(
                        ast_value_factory()->value_string(), nopos),
                    nopos),
                zone());
      append_element = factory()->NewExpressionStatement(
          factory()->NewCallRuntime(Runtime::kAppendElement, args, nopos),
          nopos);
    }

    // done = false;
    Statement* unset_done = factory()->NewExpressionStatement(
        factory()->NewAssignment(
            Token::ASSIGN, factory()->NewVariableProxy(done),
            factory()->NewBooleanLiteral(false, nopos), nopos),
        nopos);

    // if (!result.done) { #append_element; #unset_done }
    Statement* maybe_append_and_unset_done;
    {
      Expression* result_done =
          factory()->NewProperty(factory()->NewVariableProxy(result),
                                 factory()->NewStringLiteral(
                                     ast_value_factory()->done_string(), nopos),
                                 nopos);

      Block* then = factory()->NewBlock(2, true);
      then->statements()->Add(append_element, zone());
      then->statements()->Add(unset_done, zone());

      maybe_append_and_unset_done = factory()->NewIfStatement(
          factory()->NewUnaryOperation(Token::NOT, result_done, nopos), then,
          factory()->NewEmptyStatement(nopos), nopos);
    }

    // while (!done) {
    //   #set_done;
    //   #get_next;
    //   #maybe_append_and_unset_done;
    // }
    WhileStatement* loop = factory()->NewWhileStatement(nullptr, nopos);
    {
      Expression* condition = factory()->NewUnaryOperation(
          Token::NOT, factory()->NewVariableProxy(done), nopos);
      Block* body = factory()->NewBlock(3, true);
      body->statements()->Add(set_done, zone());
      body->statements()->Add(get_next, zone());
      body->statements()->Add(maybe_append_and_unset_done, zone());
      loop->Initialize(condition, body);
    }

    block_->statements()->Add(loop, zone());
    RecurseIntoSubpattern(spread->expression(),
                          factory()->NewVariableProxy(array));
  }

  Expression* closing_condition = factory()->NewUnaryOperation(
      Token::NOT, factory()->NewVariableProxy(done), nopos);

  parser_->FinalizeIteratorUse(completion, closing_condition, iterator, block_,
                               target, IteratorType::kNormal);
  block_ = target;
}

void PatternRewriter::VisitArrayLiteral(ArrayLiteral* node) {
  Variable* temp_var = nullptr;
  VisitArrayLiteral(node, &temp_var);
}

void PatternRewriter::VisitAssignment(Assignment* node) {
  // let {<pattern> = <init>} = <value>
  //   becomes
  // temp = <value>;
  // <pattern> = temp === undefined ? <init> : temp;
  DCHECK_EQ(Token::ASSIGN, node->op());

  // Rewriting of Assignment nodes for destructuring assignment
  // is handled in VisitRewritableExpression().
  DCHECK_NE(ASSIGNMENT, context());

  auto initializer = node->value();
  auto value = initializer;
  auto temp = CreateTempVar(current_value_);

  Expression* is_undefined = factory()->NewCompareOperation(
      Token::EQ_STRICT, factory()->NewVariableProxy(temp),
      factory()->NewUndefinedLiteral(kNoSourcePosition), kNoSourcePosition);
  value = factory()->NewConditional(is_undefined, initializer,
                                    factory()->NewVariableProxy(temp),
                                    kNoSourcePosition);

  // Initializer may have been parsed in the wrong scope.
  RewriteParameterScopes(initializer);

  RecurseIntoSubpattern(node->target(), value);
}


// =============== AssignmentPattern only ==================

void PatternRewriter::VisitProperty(v8::internal::Property* node) {
  DCHECK(IsAssignmentContext());
  auto value = current_value_;

  Assignment* assignment =
      factory()->NewAssignment(Token::ASSIGN, node, value, node->position());

  block_->statements()->Add(
      factory()->NewExpressionStatement(assignment, kNoSourcePosition), zone());
}


// =============== UNREACHABLE =============================

#define NOT_A_PATTERN(Node) \
  void PatternRewriter::Visit##Node(v8::internal::Node*) { UNREACHABLE(); }

NOT_A_PATTERN(BinaryOperation)
NOT_A_PATTERN(NaryOperation)
NOT_A_PATTERN(Block)
NOT_A_PATTERN(BreakStatement)
NOT_A_PATTERN(Call)
NOT_A_PATTERN(CallNew)
NOT_A_PATTERN(CallRuntime)
NOT_A_PATTERN(ClassLiteral)
NOT_A_PATTERN(CompareOperation)
NOT_A_PATTERN(CompoundAssignment)
NOT_A_PATTERN(Conditional)
NOT_A_PATTERN(ContinueStatement)
NOT_A_PATTERN(CountOperation)
NOT_A_PATTERN(DebuggerStatement)
NOT_A_PATTERN(DoExpression)
NOT_A_PATTERN(DoWhileStatement)
NOT_A_PATTERN(EmptyStatement)
NOT_A_PATTERN(EmptyParentheses)
NOT_A_PATTERN(ExpressionStatement)
NOT_A_PATTERN(ForInStatement)
NOT_A_PATTERN(ForOfStatement)
NOT_A_PATTERN(ForStatement)
NOT_A_PATTERN(FunctionDeclaration)
NOT_A_PATTERN(FunctionLiteral)
NOT_A_PATTERN(GetIterator)
NOT_A_PATTERN(GetTemplateObject)
NOT_A_PATTERN(IfStatement)
NOT_A_PATTERN(ImportCallExpression)
NOT_A_PATTERN(Literal)
NOT_A_PATTERN(NativeFunctionLiteral)
NOT_A_PATTERN(RegExpLiteral)
NOT_A_PATTERN(ResolvedProperty)
NOT_A_PATTERN(ReturnStatement)
NOT_A_PATTERN(SloppyBlockFunctionStatement)
NOT_A_PATTERN(Spread)
NOT_A_PATTERN(SuperPropertyReference)
NOT_A_PATTERN(SuperCallReference)
NOT_A_PATTERN(SwitchStatement)
NOT_A_PATTERN(ThisFunction)
NOT_A_PATTERN(Throw)
NOT_A_PATTERN(TryCatchStatement)
NOT_A_PATTERN(TryFinallyStatement)
NOT_A_PATTERN(UnaryOperation)
NOT_A_PATTERN(VariableDeclaration)
NOT_A_PATTERN(WhileStatement)
NOT_A_PATTERN(WithStatement)
NOT_A_PATTERN(Yield)
NOT_A_PATTERN(YieldStar)
NOT_A_PATTERN(Await)
NOT_A_PATTERN(InitializeClassFieldsStatement)

#undef NOT_A_PATTERN
}  // namespace internal
}  // namespace v8
