// Copyright 2018 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.

#ifndef V8_PARSING_EXPRESSION_SCOPE_H_
#define V8_PARSING_EXPRESSION_SCOPE_H_

#include <utility>

#include "src/ast/scopes.h"
#include "src/common/message-template.h"
#include "src/objects/function-kind.h"
#include "src/parsing/scanner.h"
#include "src/zone/zone.h"  // For ScopedPtrList.

namespace v8 {
namespace internal {

template <typename Types>
class ExpressionParsingScope;
template <typename Types>
class AccumulationScope;
template <typename Types>
class ArrowHeadParsingScope;
template <typename Types>
class ParameterDeclarationParsingScope;
template <typename Types>
class VariableDeclarationParsingScope;
class VariableProxy;

// ExpressionScope is used in a stack fashion, and is used to specialize
// expression parsing for the task at hand. It allows the parser to reuse the
// same code to parse destructuring declarations, assignment patterns,
// expressions, and (async) arrow function heads.
//
// One of the specific subclasses needs to be instantiated to tell the parser
// the meaning of the expression it will parse next. The parser then calls
// Record* on the expression_scope() to indicate errors. The expression_scope
// will either discard those errors, immediately report those errors, or
// classify the errors for later validation.
// TODO(verwaest): Record is a slightly odd name since it will directly throw
// for unambiguous scopes.
template <typename Types>
class ExpressionScope {
 public:
  using ParserT = typename Types::Impl;
  using ExpressionT = typename Types::Expression;

  VariableProxy* NewVariable(const AstRawString* name,
                             int pos = kNoSourcePosition) {
    VariableProxy* result = parser_->NewRawVariable(name, pos);
    if (CanBeExpression()) {
      AsExpressionParsingScope()->TrackVariable(result);
    } else {
      Variable* var = Declare(name, pos);
      if (IsVarDeclaration()) {
        bool passed_through_with = false;
        for (Scope* scope = parser()->scope(); !scope->is_declaration_scope();
             scope = scope->outer_scope()) {
          if (scope->is_with_scope()) {
            passed_through_with = true;
          } else if (scope->is_catch_scope()) {
            Variable* var = scope->LookupLocal(name);
            // If a variable is declared in a catch scope with a masking
            // catch-declared variable, the initializing assignment is an
            // assignment to the catch-declared variable instead.
            // https://tc39.es/ecma262/#sec-variablestatements-in-catch-blocks
            if (var != nullptr) {
              result->set_is_assigned();
              if (passed_through_with) break;
              result->BindTo(var);
              var->SetMaybeAssigned();
              return result;
            }
          }
        }
        if (passed_through_with) {
          // If a variable is declared in a with scope, the initializing
          // assignment might target a with-declared variable instead.
          parser()->scope()->AddUnresolved(result);
          return result;
        }
      }
      DCHECK_NOT_NULL(var);
      result->BindTo(var);
    }
    return result;
  }

  void MergeVariableList(
      ScopedList<std::pair<VariableProxy*, int>>* variable_list) {
    if (!CanBeExpression()) return;
    // Merged variables come from a CanBeDeclaration expression scope, and
    // weren't added as unresolved references to the variable scope yet. Add
    // them to the variable scope on the boundary where it becomes clear they
    // aren't declarations. We explicitly delay declaring the variables up to
    // that point to avoid trying to add them to the unresolved list multiple
    // times, e.g., for (((a))).
    if (!CanBeDeclaration()) {
      for (auto& proxy_initializer_pair : *variable_list) {
        VariableProxy* proxy = proxy_initializer_pair.first;
        this->parser()->scope()->AddUnresolved(proxy);
      }
    }
    variable_list->MergeInto(AsExpressionParsingScope()->variable_list());
  }

  Variable* Declare(const AstRawString* name, int pos = kNoSourcePosition) {
    if (type_ == kParameterDeclaration) {
      return AsParameterDeclarationParsingScope()->Declare(name, pos);
    }
    return AsVariableDeclarationParsingScope()->Declare(name, pos);
  }

  void MarkIdentifierAsAssigned() {
    if (!CanBeExpression()) return;
    AsExpressionParsingScope()->MarkIdentifierAsAssigned();
  }

  void ValidateAsPattern(ExpressionT expression, int begin, int end) {
    if (!CanBeExpression()) return;
    AsExpressionParsingScope()->ValidatePattern(expression, begin, end);
    AsExpressionParsingScope()->ClearExpressionError();
  }

  void ValidateAsExpression() {
    if (!CanBeExpression()) return;
    AsExpressionParsingScope()->ValidateExpression();
    AsExpressionParsingScope()->ClearPatternError();
  }

  // Record async arrow parameters errors in all ambiguous async arrow scopes in
  // the chain up to the first unambiguous scope.
  void RecordAsyncArrowParametersError(const Scanner::Location& loc,
                                       MessageTemplate message) {
    // Only ambiguous scopes (ExpressionParsingScope, *ArrowHeadParsingScope)
    // need to propagate errors to a possible kAsyncArrowHeadParsingScope, so
    // immediately return if the current scope is not ambiguous.
    if (!CanBeExpression()) return;
    AsExpressionParsingScope()->RecordAsyncArrowParametersError(loc, message);
  }

  // Record initializer errors in all scopes that can turn into parameter scopes
  // (ArrowHeadParsingScopes) up to the first known unambiguous parameter scope.
  void RecordParameterInitializerError(const Scanner::Location& loc,
                                       MessageTemplate message) {
    ExpressionScope* scope = this;
    while (!scope->IsCertainlyParameterDeclaration()) {
      if (!has_possible_parameter_in_scope_chain_) return;
      if (scope->CanBeParameterDeclaration()) {
        scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
      }
      scope = scope->parent();
      if (scope == nullptr) return;
    }
    Report(loc, message);
  }

  void RecordThisUse() {
    ExpressionScope* scope = this;
    do {
      if (scope->IsArrowHeadParsingScope()) {
        scope->AsArrowHeadParsingScope()->RecordThisUse();
      }
      scope = scope->parent();
    } while (scope != nullptr);
  }

  void RecordPatternError(const Scanner::Location& loc,
                          MessageTemplate message) {
    // TODO(verwaest): Non-assigning expression?
    if (IsCertainlyPattern()) {
      Report(loc, message);
    } else {
      AsExpressionParsingScope()->RecordPatternError(loc, message);
    }
  }

  void RecordStrictModeParameterError(const Scanner::Location& loc,
                                      MessageTemplate message) {
    DCHECK_IMPLIES(!has_error(), loc.IsValid());
    if (!CanBeParameterDeclaration()) return;
    if (IsCertainlyParameterDeclaration()) {
      if (is_strict(parser_->language_mode())) {
        Report(loc, message);
      } else {
        parser_->parameters_->set_strict_parameter_error(loc, message);
      }
    } else {
      parser_->next_arrow_function_info_.strict_parameter_error_location = loc;
      parser_->next_arrow_function_info_.strict_parameter_error_message =
          message;
    }
  }

  void RecordDeclarationError(const Scanner::Location& loc,
                              MessageTemplate message) {
    if (!CanBeDeclaration()) return;
    if (IsCertainlyDeclaration()) {
      Report(loc, message);
    } else {
      AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
    }
  }

  void RecordExpressionError(const Scanner::Location& loc,
                             MessageTemplate message) {
    if (!CanBeExpression()) return;
    // TODO(verwaest): Non-assigning expression?
    // if (IsCertainlyExpression()) Report(loc, message);
    AsExpressionParsingScope()->RecordExpressionError(loc, message);
  }

  void RecordNonSimpleParameter() {
    if (!IsArrowHeadParsingScope()) return;
    AsArrowHeadParsingScope()->RecordNonSimpleParameter();
  }

  bool IsCertainlyDeclaration() const {
    return base::IsInRange(type_, kParameterDeclaration, kLexicalDeclaration);
  }

  int SetInitializers(int variable_index, int peek_position) {
    if (CanBeExpression()) {
      return AsExpressionParsingScope()->SetInitializers(variable_index,
                                                         peek_position);
    }
    return variable_index;
  }

  bool has_possible_arrow_parameter_in_scope_chain() const {
    return has_possible_arrow_parameter_in_scope_chain_;
  }

 protected:
  enum ScopeType : uint8_t {
    // Expression or assignment target.
    kExpression,

    // Declaration or expression or assignment target.
    kMaybeArrowParameterDeclaration,
    kMaybeAsyncArrowParameterDeclaration,

    // Declarations.
    kParameterDeclaration,
    kVarDeclaration,
    kLexicalDeclaration,
  };

  ParserT* parser() const { return parser_; }
  ExpressionScope* parent() const { return parent_; }

  void Report(const Scanner::Location& loc, MessageTemplate message) const {
    parser_->ReportMessageAt(loc, message);
  }

  ExpressionScope(ParserT* parser, ScopeType type)
      : parser_(parser),
        parent_(parser->expression_scope_),
        type_(type),
        has_possible_parameter_in_scope_chain_(
            CanBeParameterDeclaration() ||
            (parent_ && parent_->has_possible_parameter_in_scope_chain_)),
        has_possible_arrow_parameter_in_scope_chain_(
            CanBeArrowParameterDeclaration() ||
            (parent_ &&
             parent_->has_possible_arrow_parameter_in_scope_chain_)) {
    parser->expression_scope_ = this;
  }

  ~ExpressionScope() {
    DCHECK(parser_->expression_scope_ == this ||
           parser_->expression_scope_ == parent_);
    parser_->expression_scope_ = parent_;
  }

  ExpressionParsingScope<Types>* AsExpressionParsingScope() {
    DCHECK(CanBeExpression());
    return static_cast<ExpressionParsingScope<Types>*>(this);
  }

#ifdef DEBUG
  bool has_error() const { return parser_->has_error(); }
#endif

  bool CanBeExpression() const {
    return base::IsInRange(type_, kExpression,
                           kMaybeAsyncArrowParameterDeclaration);
  }
  bool CanBeDeclaration() const {
    return base::IsInRange(type_, kMaybeArrowParameterDeclaration,
                           kLexicalDeclaration);
  }
  bool IsVariableDeclaration() const {
    return base::IsInRange(type_, kVarDeclaration, kLexicalDeclaration);
  }
  bool IsLexicalDeclaration() const { return type_ == kLexicalDeclaration; }
  bool IsAsyncArrowHeadParsingScope() const {
    return type_ == kMaybeAsyncArrowParameterDeclaration;
  }
  bool IsVarDeclaration() const { return type_ == kVarDeclaration; }

 private:
  friend class AccumulationScope<Types>;
  friend class ExpressionParsingScope<Types>;

  ArrowHeadParsingScope<Types>* AsArrowHeadParsingScope() {
    DCHECK(IsArrowHeadParsingScope());
    return static_cast<ArrowHeadParsingScope<Types>*>(this);
  }

  ParameterDeclarationParsingScope<Types>*
  AsParameterDeclarationParsingScope() {
    DCHECK(IsCertainlyParameterDeclaration());
    return static_cast<ParameterDeclarationParsingScope<Types>*>(this);
  }

  VariableDeclarationParsingScope<Types>* AsVariableDeclarationParsingScope() {
    DCHECK(IsVariableDeclaration());
    return static_cast<VariableDeclarationParsingScope<Types>*>(this);
  }

  bool IsArrowHeadParsingScope() const {
    return base::IsInRange(type_, kMaybeArrowParameterDeclaration,
                           kMaybeAsyncArrowParameterDeclaration);
  }
  bool IsCertainlyPattern() const { return IsCertainlyDeclaration(); }
  bool CanBeParameterDeclaration() const {
    return base::IsInRange(type_, kMaybeArrowParameterDeclaration,
                           kParameterDeclaration);
  }
  bool CanBeArrowParameterDeclaration() const {
    return base::IsInRange(type_, kMaybeArrowParameterDeclaration,
                           kMaybeAsyncArrowParameterDeclaration);
  }
  bool IsCertainlyParameterDeclaration() const {
    return type_ == kParameterDeclaration;
  }

  ParserT* parser_;
  ExpressionScope<Types>* parent_;
  ScopeType type_;
  bool has_possible_parameter_in_scope_chain_;
  bool has_possible_arrow_parameter_in_scope_chain_;

  DISALLOW_COPY_AND_ASSIGN(ExpressionScope);
};

// Used to unambiguously parse var, let, const declarations.
template <typename Types>
class VariableDeclarationParsingScope : public ExpressionScope<Types> {
 public:
  using ParserT = typename Types::Impl;
  using ExpressionScopeT = ExpressionScope<Types>;
  using ScopeType = typename ExpressionScopeT::ScopeType;

  VariableDeclarationParsingScope(ParserT* parser, VariableMode mode,
                                  ZonePtrList<const AstRawString>* names)
      : ExpressionScopeT(parser, IsLexicalVariableMode(mode)
                                     ? ExpressionScopeT::kLexicalDeclaration
                                     : ExpressionScopeT::kVarDeclaration),
        mode_(mode),
        names_(names) {}

  Variable* Declare(const AstRawString* name, int pos) {
    VariableKind kind = NORMAL_VARIABLE;
    bool was_added;
    Variable* var = this->parser()->DeclareVariable(
        name, kind, mode_, Variable::DefaultInitializationFlag(mode_),
        this->parser()->scope(), &was_added, pos);
    if (was_added &&
        this->parser()->scope()->num_var() > kMaxNumFunctionLocals) {
      this->parser()->ReportMessage(MessageTemplate::kTooManyVariables);
    }
    if (names_) names_->Add(name, this->parser()->zone());
    if (this->IsLexicalDeclaration()) {
      if (this->parser()->IsLet(name)) {
        this->parser()->ReportMessageAt(
            Scanner::Location(pos, pos + name->length()),
            MessageTemplate::kLetInLexicalBinding);
      }
    } else {
      if (this->parser()->loop_nesting_depth() > 0) {
        // Due to hoisting, the value of a 'var'-declared variable may actually
        // change even if the code contains only the "initial" assignment,
        // namely when that assignment occurs inside a loop.  For example:
        //
        //   let i = 10;
        //   do { var x = i } while (i--):
        //
        // Note that non-lexical variables include temporaries, which may also
        // get assigned inside a loop due to the various rewritings that the
        // parser performs.
        //
        // Pessimistically mark all vars in loops as assigned. This
        // overapproximates the actual assigned vars due to unassigned var
        // without initializer, but that's unlikely anyway.
        //
        // This also handles marking of loop variables in for-in and for-of
        // loops, as determined by loop-nesting-depth.
        DCHECK_NOT_NULL(var);
        var->SetMaybeAssigned();
      }
    }
    return var;
  }

 private:
  // Limit the allowed number of local variables in a function. The hard limit
  // in Ignition is 2^31-1 due to the size of register operands. We limit it to
  // a more reasonable lower up-limit.
  static const int kMaxNumFunctionLocals = (1 << 23) - 1;

  VariableMode mode_;
  ZonePtrList<const AstRawString>* names_;

  DISALLOW_COPY_AND_ASSIGN(VariableDeclarationParsingScope);
};

template <typename Types>
class ParameterDeclarationParsingScope : public ExpressionScope<Types> {
 public:
  using ParserT = typename Types::Impl;
  using ExpressionScopeT = ExpressionScope<Types>;
  using ScopeType = typename ExpressionScopeT::ScopeType;

  explicit ParameterDeclarationParsingScope(ParserT* parser)
      : ExpressionScopeT(parser, ExpressionScopeT::kParameterDeclaration) {}

  Variable* Declare(const AstRawString* name, int pos) {
    VariableKind kind = PARAMETER_VARIABLE;
    VariableMode mode = VariableMode::kVar;
    bool was_added;
    Variable* var = this->parser()->DeclareVariable(
        name, kind, mode, Variable::DefaultInitializationFlag(mode),
        this->parser()->scope(), &was_added, pos);
    if (!has_duplicate() && !was_added) {
      duplicate_loc_ = Scanner::Location(pos, pos + name->length());
    }
    return var;
  }

  bool has_duplicate() const { return duplicate_loc_.IsValid(); }

  const Scanner::Location& duplicate_location() const { return duplicate_loc_; }

 private:
  Scanner::Location duplicate_loc_ = Scanner::Location::invalid();
  DISALLOW_COPY_AND_ASSIGN(ParameterDeclarationParsingScope);
};

// Parsing expressions is always ambiguous between at least left-hand-side and
// right-hand-side of assignments. This class is used to keep track of errors
// relevant for either side until it is clear what was being parsed.
// The class also keeps track of all variable proxies that are created while the
// scope was active. If the scope is an expression, the variable proxies will be
// added to the unresolved list. Otherwise they are declarations and aren't
// added. The list is also used to mark the variables as assigned in case we are
// parsing an assignment expression.
template <typename Types>
class ExpressionParsingScope : public ExpressionScope<Types> {
 public:
  using ParserT = typename Types::Impl;
  using ExpressionT = typename Types::Expression;
  using ExpressionScopeT = ExpressionScope<Types>;
  using ScopeType = typename ExpressionScopeT::ScopeType;

  explicit ExpressionParsingScope(
      ParserT* parser, ScopeType type = ExpressionScopeT::kExpression)
      : ExpressionScopeT(parser, type),
        variable_list_(parser->variable_buffer()),
        has_async_arrow_in_scope_chain_(
            type == ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration ||
            (this->parent() && this->parent()->CanBeExpression() &&
             this->parent()
                 ->AsExpressionParsingScope()
                 ->has_async_arrow_in_scope_chain_)) {
    DCHECK(this->CanBeExpression());
    clear(kExpressionIndex);
    clear(kPatternIndex);
  }

  void RecordAsyncArrowParametersError(const Scanner::Location& loc,
                                       MessageTemplate message) {
    for (ExpressionScopeT* scope = this; scope != nullptr;
         scope = scope->parent()) {
      if (!has_async_arrow_in_scope_chain_) break;
      if (scope->type_ ==
          ExpressionScopeT::kMaybeAsyncArrowParameterDeclaration) {
        scope->AsArrowHeadParsingScope()->RecordDeclarationError(loc, message);
      }
    }
  }

  ~ExpressionParsingScope() { DCHECK(this->has_error() || verified_); }

  ExpressionT ValidateAndRewriteReference(ExpressionT expression, int beg_pos,
                                          int end_pos) {
    if (V8_LIKELY(this->parser()->IsAssignableIdentifier(expression))) {
      MarkIdentifierAsAssigned();
      this->mark_verified();
      return expression;
    } else if (V8_LIKELY(expression->IsProperty())) {
      ValidateExpression();
      return expression;
    }
    this->mark_verified();
    const bool early_error = false;
    return this->parser()->RewriteInvalidReferenceExpression(
        expression, beg_pos, end_pos, MessageTemplate::kInvalidLhsInFor,
        early_error);
  }

  void RecordExpressionError(const Scanner::Location& loc,
                             MessageTemplate message) {
    Record(kExpressionIndex, loc, message);
  }

  void RecordPatternError(const Scanner::Location& loc,
                          MessageTemplate message) {
    Record(kPatternIndex, loc, message);
  }

  void ValidateExpression() { Validate(kExpressionIndex); }

  void ValidatePattern(ExpressionT expression, int begin, int end) {
    Validate(kPatternIndex);
    if (expression->is_parenthesized()) {
      ExpressionScopeT::Report(Scanner::Location(begin, end),
                               MessageTemplate::kInvalidDestructuringTarget);
    }
    for (auto& variable_initializer_pair : variable_list_) {
      variable_initializer_pair.first->set_is_assigned();
    }
  }

  void ClearExpressionError() {
    DCHECK(verified_);
#ifdef DEBUG
    verified_ = false;
#endif
    clear(kExpressionIndex);
  }

  void ClearPatternError() {
    DCHECK(verified_);
#ifdef DEBUG
    verified_ = false;
#endif
    clear(kPatternIndex);
  }

  void TrackVariable(VariableProxy* variable) {
    if (!this->CanBeDeclaration()) {
      this->parser()->scope()->AddUnresolved(variable);
    }
    variable_list_.Add({variable, kNoSourcePosition});
  }

  void MarkIdentifierAsAssigned() {
    // It's possible we're parsing a syntax error. In that case it's not
    // guaranteed that there's a variable in the list.
    if (variable_list_.length() == 0) return;
    variable_list_.at(variable_list_.length() - 1).first->set_is_assigned();
  }

  int SetInitializers(int first_variable_index, int position) {
    int len = variable_list_.length();
    if (len == 0) return 0;

    int end = len - 1;
    // Loop backwards and abort as soon as we see one that's already set to
    // avoid a loop on expressions like a,b,c,d,e,f,g (outside of an arrowhead).
    // TODO(delphick): Look into removing this loop.
    for (int i = end; i >= first_variable_index &&
                      variable_list_.at(i).second == kNoSourcePosition;
         --i) {
      variable_list_.at(i).second = position;
    }
    return end;
  }

  ScopedList<std::pair<VariableProxy*, int>>* variable_list() {
    return &variable_list_;
  }

 protected:
  bool is_verified() const {
#ifdef DEBUG
    return verified_;
#else
    return false;
#endif
  }

  void ValidatePattern() { Validate(kPatternIndex); }

 private:
  friend class AccumulationScope<Types>;

  enum ErrorNumber : uint8_t {
    kExpressionIndex = 0,
    kPatternIndex = 1,
    kNumberOfErrors = 2,
  };
  void clear(int index) {
    messages_[index] = MessageTemplate::kNone;
    locations_[index] = Scanner::Location::invalid();
  }
  bool is_valid(int index) const { return !locations_[index].IsValid(); }
  void Record(int index, const Scanner::Location& loc,
              MessageTemplate message) {
    DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
    if (!is_valid(index)) return;
    messages_[index] = message;
    locations_[index] = loc;
  }
  void Validate(int index) {
    DCHECK(!this->is_verified());
    if (!is_valid(index)) Report(index);
    this->mark_verified();
  }
  void Report(int index) const {
    ExpressionScopeT::Report(locations_[index], messages_[index]);
  }

  // Debug verification to make sure every scope is validated exactly once.
  void mark_verified() {
#ifdef DEBUG
    verified_ = true;
#endif
  }
  void clear_verified() {
#ifdef DEBUG
    verified_ = false;
#endif
  }
#ifdef DEBUG
  bool verified_ = false;
#endif

  ScopedList<std::pair<VariableProxy*, int>> variable_list_;
  MessageTemplate messages_[kNumberOfErrors];
  Scanner::Location locations_[kNumberOfErrors];
  bool has_async_arrow_in_scope_chain_;

  DISALLOW_COPY_AND_ASSIGN(ExpressionParsingScope);
};

// This class is used to parse multiple ambiguous expressions and declarations
// in the same scope. E.g., in async(X,Y,Z) or [X,Y,Z], X and Y and Z will all
// be parsed in the respective outer ArrowHeadParsingScope and
// ExpressionParsingScope. It provides a clean error state in the underlying
// scope to parse the individual expressions, while keeping track of the
// expression and pattern errors since the start. The AccumulationScope is only
// used to keep track of the errors so far, and the underlying ExpressionScope
// keeps being used as the expression_scope(). If the expression_scope() isn't
// ambiguous, this class does not do anything.
template <typename Types>
class AccumulationScope {
 public:
  using ParserT = typename Types::Impl;

  static const int kNumberOfErrors =
      ExpressionParsingScope<Types>::kNumberOfErrors;
  explicit AccumulationScope(ExpressionScope<Types>* scope) : scope_(nullptr) {
    if (!scope->CanBeExpression()) return;
    scope_ = scope->AsExpressionParsingScope();
    for (int i = 0; i < kNumberOfErrors; i++) {
      copy(i);
      scope_->clear(i);
    }
  }

  // Merge errors from the underlying ExpressionParsingScope into this scope.
  // Only keeps the first error across all accumulate calls, and removes the
  // error from the underlying scope.
  void Accumulate() {
    if (scope_ == nullptr) return;
    DCHECK(!scope_->is_verified());
    for (int i = 0; i < kNumberOfErrors; i++) {
      if (!locations_[i].IsValid()) copy(i);
      scope_->clear(i);
    }
  }

  // This is called instead of Accumulate in case the parsed member is already
  // known to be an expression. In that case we don't need to accumulate the
  // expression but rather validate it immediately. We also ignore the pattern
  // error since the parsed member is known to not be a pattern. This is
  // necessary for "{x:1}.y" parsed as part of an assignment pattern. {x:1} will
  // record a pattern error, but "{x:1}.y" is actually a valid as part of an
  // assignment pattern since it's a property access.
  void ValidateExpression() {
    if (scope_ == nullptr) return;
    DCHECK(!scope_->is_verified());
    scope_->ValidateExpression();
    DCHECK(scope_->is_verified());
    scope_->clear(ExpressionParsingScope<Types>::kPatternIndex);
#ifdef DEBUG
    scope_->clear_verified();
#endif
  }

  ~AccumulationScope() {
    if (scope_ == nullptr) return;
    Accumulate();
    for (int i = 0; i < kNumberOfErrors; i++) copy_back(i);
  }

 private:
  void copy(int entry) {
    messages_[entry] = scope_->messages_[entry];
    locations_[entry] = scope_->locations_[entry];
  }

  void copy_back(int entry) {
    if (!locations_[entry].IsValid()) return;
    scope_->messages_[entry] = messages_[entry];
    scope_->locations_[entry] = locations_[entry];
  }

  ExpressionParsingScope<Types>* scope_;
  MessageTemplate messages_[2];
  Scanner::Location locations_[2];

  DISALLOW_COPY_AND_ASSIGN(AccumulationScope);
};

// The head of an arrow function is ambiguous between expression, assignment
// pattern and declaration. This keeps track of the additional declaration
// error and allows the scope to be validated as a declaration rather than an
// expression or a pattern.
template <typename Types>
class ArrowHeadParsingScope : public ExpressionParsingScope<Types> {
 public:
  using ParserT = typename Types::Impl;
  using ScopeType = typename ExpressionScope<Types>::ScopeType;

  ArrowHeadParsingScope(ParserT* parser, FunctionKind kind)
      : ExpressionParsingScope<Types>(
            parser,
            kind == FunctionKind::kArrowFunction
                ? ExpressionScope<Types>::kMaybeArrowParameterDeclaration
                : ExpressionScope<
                      Types>::kMaybeAsyncArrowParameterDeclaration) {
    DCHECK(kind == FunctionKind::kAsyncArrowFunction ||
           kind == FunctionKind::kArrowFunction);
    DCHECK(this->CanBeDeclaration());
    DCHECK(!this->IsCertainlyDeclaration());
  }

  void ValidateExpression() {
    // Turns out this is not an arrow head. Clear any possible tracked strict
    // parameter errors, and reinterpret tracked variables as unresolved
    // references.
    this->parser()->next_arrow_function_info_.ClearStrictParameterError();
    ExpressionParsingScope<Types>::ValidateExpression();
    this->parent()->MergeVariableList(this->variable_list());
  }

  DeclarationScope* ValidateAndCreateScope() {
    DCHECK(!this->is_verified());
    DeclarationScope* result = this->parser()->NewFunctionScope(kind());
    if (declaration_error_location.IsValid()) {
      ExpressionScope<Types>::Report(declaration_error_location,
                                     declaration_error_message);
      return result;
    }
    this->ValidatePattern();

    if (!has_simple_parameter_list_) result->SetHasNonSimpleParameters();
    VariableKind kind = PARAMETER_VARIABLE;
    VariableMode mode =
        has_simple_parameter_list_ ? VariableMode::kVar : VariableMode::kLet;
    for (auto& proxy_initializer_pair : *this->variable_list()) {
      VariableProxy* proxy = proxy_initializer_pair.first;
      int initializer_position = proxy_initializer_pair.second;
      // Default values for parameters will have been parsed as assignments so
      // clear the is_assigned bit as they are not actually assignments.
      proxy->clear_is_assigned();
      bool was_added;
      this->parser()->DeclareAndBindVariable(proxy, kind, mode, result,
                                             &was_added, initializer_position);
      if (!was_added) {
        ExpressionScope<Types>::Report(proxy->location(),
                                       MessageTemplate::kParamDupe);
      }
    }

#ifdef DEBUG
    if (!this->has_error()) {
      for (auto declaration : *result->declarations()) {
        DCHECK_NE(declaration->var()->initializer_position(),
                  kNoSourcePosition);
      }
    }
#endif  // DEBUG

    if (uses_this_) result->UsesThis();
    return result;
  }

  void RecordDeclarationError(const Scanner::Location& loc,
                              MessageTemplate message) {
    DCHECK_IMPLIES(!this->has_error(), loc.IsValid());
    declaration_error_location = loc;
    declaration_error_message = message;
  }

  void RecordNonSimpleParameter() { has_simple_parameter_list_ = false; }
  void RecordThisUse() { uses_this_ = true; }

 private:
  FunctionKind kind() const {
    return this->IsAsyncArrowHeadParsingScope()
               ? FunctionKind::kAsyncArrowFunction
               : FunctionKind::kArrowFunction;
  }

  Scanner::Location declaration_error_location = Scanner::Location::invalid();
  MessageTemplate declaration_error_message = MessageTemplate::kNone;
  bool has_simple_parameter_list_ = true;
  bool uses_this_ = false;

  DISALLOW_COPY_AND_ASSIGN(ArrowHeadParsingScope);
};

}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_EXPRESSION_SCOPE_H_
