// 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);
  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 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), 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->IsLiteral() && value->AsLiteral()->raw_value()->IsTheHole())) {
      {
        // 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),
                                         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(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(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
