text: // Copyright 2006-2009 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_FUNC_NAME_INFERRER_H_
  #define V8_PARSING_FUNC_NAME_INFERRER_H_
  
  #include <vector>
  
  #include "src/base/macros.h"
  #include "src/utils/pointer-with-payload.h"
  
  namespace v8 {
  namespace internal {
  
  class AstConsString;
  class AstRawString;
  class AstValueFactory;
  class FunctionLiteral;
  
  enum class InferName { kYes, kNo };
  
  template <>
  struct PointerWithPayloadTraits<AstRawString> {
    static constexpr int value = 2;
  };
  
  // FuncNameInferrer is a stateful class that is used to perform name
  // inference for anonymous functions during static analysis of source code.
  // Inference is performed in cases when an anonymous function is assigned
  // to a variable or a property (see test-func-name-inference.cc for examples.)
  //
  // The basic idea is that during parsing of LHSs of certain expressions
  // (assignments, declarations, object literals) we collect name strings,
  // and during parsing of the RHS, a function literal can be collected. After
  // parsing the RHS we can infer a name for function literals that do not have
  // a name.
  class FuncNameInferrer {
   public:
    explicit FuncNameInferrer(AstValueFactory* ast_value_factory);
  
    // To enter function name inference state, put a FuncNameInferrer::State
    // on the stack.
    class State {
     public:
      explicit State(FuncNameInferrer* fni)
          : fni_(fni), top_(fni->names_stack_.size()) {
        ++fni_->scope_depth_;
      }
      ~State() {
        DCHECK(fni_->IsOpen());
        fni_->names_stack_.resize(top_);
        --fni_->scope_depth_;
      }
  
     private:
      FuncNameInferrer* fni_;
      size_t top_;
  
      DISALLOW_COPY_AND_ASSIGN(State);
    };
  
    // Returns whether we have entered name collection state.
    bool IsOpen() const { return scope_depth_ > 0; }
  
    // Pushes an enclosing the name of enclosing function onto names stack.
    void PushEnclosingName(const AstRawString* name);
  
    // Pushes an encountered name onto names stack when in collection state.
    void PushLiteralName(const AstRawString* name);
  
    void PushVariableName(const AstRawString* name);
  
    // Adds a function to infer name for.
    void AddFunction(FunctionLiteral* func_to_infer) {
      if (IsOpen()) {
        funcs_to_infer_.push_back(func_to_infer);
      }
    }
  
    void RemoveLastFunction() {
      if (IsOpen() && !funcs_to_infer_.empty()) funcs_to_infer_.pop_back();
    }
  
    void RemoveAsyncKeywordFromEnd();
  
    // Infers a function name and leaves names collection state.
    void Infer() {
      DCHECK(IsOpen());
      if (!funcs_to_infer_.empty()) InferFunctionsNames();
    }
  
   private:
    enum NameType : uint8_t {
      kEnclosingConstructorName,
      kLiteralName,
      kVariableName
    };
    struct Name {
      // Needed for names_stack_.resize()
      Name() { UNREACHABLE(); }
      Name(const AstRawString* name, NameType type)
          : name_and_type_(name, type) {}
  
      PointerWithPayload<const AstRawString, NameType, 2> name_and_type_;
      inline const AstRawString* name() const {
        return name_and_type_.GetPointer();
      }
      inline NameType type() const { return name_and_type_.GetPayload(); }
    };
  
    // Constructs a full name in dotted notation from gathered names.
    const AstConsString* MakeNameFromStack();
  
    // Performs name inferring for added functions.
    void InferFunctionsNames();
  
    AstValueFactory* ast_value_factory_;
    std::vector<Name> names_stack_;
    std::vector<FunctionLiteral*> funcs_to_infer_;
    size_t scope_depth_ = 0;
  
    DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
  };
  
  
  }  // namespace internal
  }  // namespace v8
  
  #endif  // V8_PARSING_FUNC_NAME_INFERRER_H_
  