// Copyright 2011 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_AST_VARIABLES_H_
#define V8_AST_VARIABLES_H_

#include "src/ast/ast-value-factory.h"
#include "src/base/threaded-list.h"
#include "src/common/globals.h"
#include "src/execution/isolate.h"
#include "src/zone/zone.h"

namespace v8 {
namespace internal {

// The AST refers to variables via VariableProxies - placeholders for the actual
// variables. Variables themselves are never directly referred to from the AST,
// they are maintained by scopes, and referred to from VariableProxies and Slots
// after binding and variable allocation.
class Variable final : public ZoneObject {
 public:
  Variable(Scope* scope, const AstRawString* name, VariableMode mode,
           VariableKind kind, InitializationFlag initialization_flag,
           MaybeAssignedFlag maybe_assigned_flag = kNotAssigned,
           IsStaticFlag is_static_flag = IsStaticFlag::kNotStatic)
      : scope_(scope),
        name_(name),
        local_if_not_shadowed_(nullptr),
        next_(nullptr),
        index_(-1),
        initializer_position_(kNoSourcePosition),
        bit_field_(MaybeAssignedFlagField::encode(maybe_assigned_flag) |
                   InitializationFlagField::encode(initialization_flag) |
                   VariableModeField::encode(mode) |
                   IsUsedField::encode(false) |
                   ForceContextAllocationBit::encode(false) |
                   ForceHoleInitializationField::encode(false) |
                   LocationField::encode(VariableLocation::UNALLOCATED) |
                   VariableKindField::encode(kind) |
                   IsStaticFlagField::encode(is_static_flag)) {
    // Var declared variables never need initialization.
    DCHECK(!(mode == VariableMode::kVar &&
             initialization_flag == kNeedsInitialization));
    DCHECK_IMPLIES(is_static_flag == IsStaticFlag::kStatic,
                   IsConstVariableMode(mode));
  }

  explicit Variable(Variable* other);

  // The source code for an eval() call may refer to a variable that is
  // in an outer scope about which we don't know anything (it may not
  // be the script scope). scope() is nullptr in that case. Currently the
  // scope is only used to follow the context chain length.
  Scope* scope() const { return scope_; }

  // This is for adjusting the scope of temporaries used when desugaring
  // parameter initializers.
  void set_scope(Scope* scope) { scope_ = scope; }

  Handle<String> name() const { return name_->string(); }
  const AstRawString* raw_name() const { return name_; }
  VariableMode mode() const { return VariableModeField::decode(bit_field_); }
  void set_mode(VariableMode mode) {
    bit_field_ = VariableModeField::update(bit_field_, mode);
  }
  void set_is_static_flag(IsStaticFlag is_static_flag) {
    bit_field_ = IsStaticFlagField::update(bit_field_, is_static_flag);
  }
  IsStaticFlag is_static_flag() const {
    return IsStaticFlagField::decode(bit_field_);
  }
  bool is_static() const { return is_static_flag() == IsStaticFlag::kStatic; }

  bool has_forced_context_allocation() const {
    return ForceContextAllocationBit::decode(bit_field_);
  }
  void ForceContextAllocation() {
    DCHECK(IsUnallocated() || IsContextSlot() || IsLookupSlot() ||
           location() == VariableLocation::MODULE);
    bit_field_ = ForceContextAllocationBit::update(bit_field_, true);
  }
  bool is_used() { return IsUsedField::decode(bit_field_); }
  void set_is_used() { bit_field_ = IsUsedField::update(bit_field_, true); }
  MaybeAssignedFlag maybe_assigned() const {
    return MaybeAssignedFlagField::decode(bit_field_);
  }
  void clear_maybe_assigned() {
    bit_field_ = MaybeAssignedFlagField::update(bit_field_, kNotAssigned);
  }
  void SetMaybeAssigned() {
    if (mode() == VariableMode::kConst) return;
    // Private names are only initialized once by us.
    if (name_->IsPrivateName()) {
      return;
    }
    // If this variable is dynamically shadowing another variable, then that
    // variable could also be assigned (in the non-shadowing case).
    if (has_local_if_not_shadowed()) {
      // Avoid repeatedly marking the same tree of variables by only recursing
      // when this variable's maybe_assigned status actually changes.
      if (!maybe_assigned()) {
        local_if_not_shadowed()->SetMaybeAssigned();
      }
      DCHECK_IMPLIES(local_if_not_shadowed()->mode() != VariableMode::kConst,
                     local_if_not_shadowed()->maybe_assigned());
    }
    set_maybe_assigned();
  }

  bool requires_brand_check() const {
    return IsPrivateMethodOrAccessorVariableMode(mode());
  }

  int initializer_position() { return initializer_position_; }
  void set_initializer_position(int pos) { initializer_position_ = pos; }

  bool IsUnallocated() const {
    return location() == VariableLocation::UNALLOCATED;
  }
  bool IsParameter() const { return location() == VariableLocation::PARAMETER; }
  bool IsStackLocal() const { return location() == VariableLocation::LOCAL; }
  bool IsStackAllocated() const { return IsParameter() || IsStackLocal(); }
  bool IsContextSlot() const { return location() == VariableLocation::CONTEXT; }
  bool IsLookupSlot() const { return location() == VariableLocation::LOOKUP; }
  bool IsGlobalObjectProperty() const;

  // True for 'let' variables declared in the script scope of a REPL script.
  bool IsReplGlobalLet() const;

  bool is_dynamic() const { return IsDynamicVariableMode(mode()); }

  // Returns the InitializationFlag this Variable was created with.
  // Scope analysis may allow us to relax this initialization
  // requirement, which will be reflected in the return value of
  // binding_needs_init().
  InitializationFlag initialization_flag() const {
    return InitializationFlagField::decode(bit_field_);
  }

  // Whether this variable needs to be initialized with the hole at
  // declaration time. Only returns valid results after scope analysis.
  bool binding_needs_init() const {
    DCHECK_IMPLIES(initialization_flag() == kNeedsInitialization,
                   IsLexicalVariableMode(mode()) ||
                       IsPrivateMethodOrAccessorVariableMode(mode()));
    DCHECK_IMPLIES(ForceHoleInitializationField::decode(bit_field_),
                   initialization_flag() == kNeedsInitialization);

    // Always initialize if hole initialization was forced during
    // scope analysis.
    if (ForceHoleInitializationField::decode(bit_field_)) return true;

    // If initialization was not forced, no need for initialization
    // for stack allocated variables, since UpdateNeedsHoleCheck()
    // in scopes.cc has proven that no VariableProxy refers to
    // this variable in such a way that a runtime hole check
    // would be generated.
    if (IsStackAllocated()) return false;

    // Otherwise, defer to the flag set when this Variable was constructed.
    return initialization_flag() == kNeedsInitialization;
  }

  // Called during scope analysis when a VariableProxy is found to
  // reference this Variable in such a way that a hole check will
  // be required at runtime.
  void ForceHoleInitialization() {
    DCHECK_EQ(kNeedsInitialization, initialization_flag());
    DCHECK(IsLexicalVariableMode(mode()) ||
           IsPrivateMethodOrAccessorVariableMode(mode()));
    bit_field_ = ForceHoleInitializationField::update(bit_field_, true);
  }

  bool throw_on_const_assignment(LanguageMode language_mode) const {
    return kind() != SLOPPY_FUNCTION_NAME_VARIABLE || is_strict(language_mode);
  }

  bool is_this() const { return kind() == THIS_VARIABLE; }
  bool is_sloppy_function_name() const {
    return kind() == SLOPPY_FUNCTION_NAME_VARIABLE;
  }

  bool is_parameter() const { return kind() == PARAMETER_VARIABLE; }
  bool is_sloppy_block_function() {
    return kind() == SLOPPY_BLOCK_FUNCTION_VARIABLE;
  }

  Variable* local_if_not_shadowed() const {
    DCHECK((mode() == VariableMode::kDynamicLocal ||
            mode() == VariableMode::kDynamic) &&
           has_local_if_not_shadowed());
    return local_if_not_shadowed_;
  }

  bool has_local_if_not_shadowed() const {
    return local_if_not_shadowed_ != nullptr;
  }

  void set_local_if_not_shadowed(Variable* local) {
    local_if_not_shadowed_ = local;
  }

  VariableLocation location() const {
    return LocationField::decode(bit_field_);
  }
  VariableKind kind() const { return VariableKindField::decode(bit_field_); }

  int index() const { return index_; }

  bool IsReceiver() const {
    DCHECK(IsParameter());

    return index_ == -1;
  }

  bool IsExport() const {
    DCHECK_EQ(location(), VariableLocation::MODULE);
    DCHECK_NE(index(), 0);
    return index() > 0;
  }

  void AllocateTo(VariableLocation location, int index) {
    DCHECK(IsUnallocated() ||
           (this->location() == location && this->index() == index));
    DCHECK_IMPLIES(location == VariableLocation::MODULE, index != 0);
    bit_field_ = LocationField::update(bit_field_, location);
    DCHECK_EQ(location, this->location());
    index_ = index;
  }

  void MakeParameterNonSimple() {
    DCHECK(is_parameter());
    bit_field_ = VariableModeField::update(bit_field_, VariableMode::kLet);
    bit_field_ =
        InitializationFlagField::update(bit_field_, kNeedsInitialization);
  }

  static InitializationFlag DefaultInitializationFlag(VariableMode mode) {
    DCHECK(IsDeclaredVariableMode(mode));
    return mode == VariableMode::kVar ? kCreatedInitialized
                                      : kNeedsInitialization;
  }

  // Rewrites the VariableLocation of repl script scope 'lets' to REPL_GLOBAL.
  void RewriteLocationForRepl();

  using List = base::ThreadedList<Variable>;

 private:
  Scope* scope_;
  const AstRawString* name_;

  // If this field is set, this variable references the stored locally bound
  // variable, but it might be shadowed by variable bindings introduced by with
  // blocks or sloppy 'eval' calls between the reference scope (inclusive) and
  // the binding scope (exclusive).
  Variable* local_if_not_shadowed_;
  Variable* next_;
  int index_;
  int initializer_position_;
  uint16_t bit_field_;

  void set_maybe_assigned() {
    bit_field_ = MaybeAssignedFlagField::update(bit_field_, kMaybeAssigned);
  }

  using VariableModeField = base::BitField16<VariableMode, 0, 4>;
  using VariableKindField = VariableModeField::Next<VariableKind, 3>;
  using LocationField = VariableKindField::Next<VariableLocation, 3>;
  using ForceContextAllocationBit = LocationField::Next<bool, 1>;
  using IsUsedField = ForceContextAllocationBit::Next<bool, 1>;
  using InitializationFlagField = IsUsedField::Next<InitializationFlag, 1>;
  using ForceHoleInitializationField = InitializationFlagField::Next<bool, 1>;
  using MaybeAssignedFlagField =
      ForceHoleInitializationField::Next<MaybeAssignedFlag, 1>;
  using IsStaticFlagField = MaybeAssignedFlagField::Next<IsStaticFlag, 1>;

  Variable** next() { return &next_; }
  friend List;
  friend base::ThreadedListTraits<Variable>;
};
}  // namespace internal
}  // namespace v8

#endif  // V8_AST_VARIABLES_H_
