11cb0ef41Sopenharmony_ci// Copyright 2006-2009 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#ifndef V8_PARSING_FUNC_NAME_INFERRER_H_
61cb0ef41Sopenharmony_ci#define V8_PARSING_FUNC_NAME_INFERRER_H_
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci#include <vector>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/base/macros.h"
111cb0ef41Sopenharmony_ci#include "src/base/pointer-with-payload.h"
121cb0ef41Sopenharmony_ci
131cb0ef41Sopenharmony_cinamespace v8 {
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_cinamespace internal {
161cb0ef41Sopenharmony_ciclass AstRawString;
171cb0ef41Sopenharmony_ci}
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cinamespace base {
201cb0ef41Sopenharmony_citemplate <>
211cb0ef41Sopenharmony_cistruct PointerWithPayloadTraits<v8::internal::AstRawString> {
221cb0ef41Sopenharmony_ci  static constexpr int kAvailableBits = 2;
231cb0ef41Sopenharmony_ci};
241cb0ef41Sopenharmony_ci}  // namespace base
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_cinamespace internal {
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciclass AstConsString;
291cb0ef41Sopenharmony_ciclass AstValueFactory;
301cb0ef41Sopenharmony_ciclass FunctionLiteral;
311cb0ef41Sopenharmony_ci
321cb0ef41Sopenharmony_cienum class InferName { kYes, kNo };
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci// FuncNameInferrer is a stateful class that is used to perform name
351cb0ef41Sopenharmony_ci// inference for anonymous functions during static analysis of source code.
361cb0ef41Sopenharmony_ci// Inference is performed in cases when an anonymous function is assigned
371cb0ef41Sopenharmony_ci// to a variable or a property (see test-func-name-inference.cc for examples.)
381cb0ef41Sopenharmony_ci//
391cb0ef41Sopenharmony_ci// The basic idea is that during parsing of LHSs of certain expressions
401cb0ef41Sopenharmony_ci// (assignments, declarations, object literals) we collect name strings,
411cb0ef41Sopenharmony_ci// and during parsing of the RHS, a function literal can be collected. After
421cb0ef41Sopenharmony_ci// parsing the RHS we can infer a name for function literals that do not have
431cb0ef41Sopenharmony_ci// a name.
441cb0ef41Sopenharmony_ciclass FuncNameInferrer {
451cb0ef41Sopenharmony_ci public:
461cb0ef41Sopenharmony_ci  explicit FuncNameInferrer(AstValueFactory* ast_value_factory);
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_ci  FuncNameInferrer(const FuncNameInferrer&) = delete;
491cb0ef41Sopenharmony_ci  FuncNameInferrer& operator=(const FuncNameInferrer&) = delete;
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  // To enter function name inference state, put a FuncNameInferrer::State
521cb0ef41Sopenharmony_ci  // on the stack.
531cb0ef41Sopenharmony_ci  class State {
541cb0ef41Sopenharmony_ci   public:
551cb0ef41Sopenharmony_ci    explicit State(FuncNameInferrer* fni)
561cb0ef41Sopenharmony_ci        : fni_(fni), top_(fni->names_stack_.size()) {
571cb0ef41Sopenharmony_ci      ++fni_->scope_depth_;
581cb0ef41Sopenharmony_ci    }
591cb0ef41Sopenharmony_ci    ~State() {
601cb0ef41Sopenharmony_ci      DCHECK(fni_->IsOpen());
611cb0ef41Sopenharmony_ci      fni_->names_stack_.resize(top_);
621cb0ef41Sopenharmony_ci      --fni_->scope_depth_;
631cb0ef41Sopenharmony_ci    }
641cb0ef41Sopenharmony_ci    State(const State&) = delete;
651cb0ef41Sopenharmony_ci    State& operator=(const State&) = delete;
661cb0ef41Sopenharmony_ci
671cb0ef41Sopenharmony_ci   private:
681cb0ef41Sopenharmony_ci    FuncNameInferrer* fni_;
691cb0ef41Sopenharmony_ci    size_t top_;
701cb0ef41Sopenharmony_ci  };
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  // Returns whether we have entered name collection state.
731cb0ef41Sopenharmony_ci  bool IsOpen() const { return scope_depth_ > 0; }
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  // Pushes an enclosing the name of enclosing function onto names stack.
761cb0ef41Sopenharmony_ci  void PushEnclosingName(const AstRawString* name);
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  // Pushes an encountered name onto names stack when in collection state.
791cb0ef41Sopenharmony_ci  void PushLiteralName(const AstRawString* name);
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ci  void PushVariableName(const AstRawString* name);
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  // Adds a function to infer name for.
841cb0ef41Sopenharmony_ci  void AddFunction(FunctionLiteral* func_to_infer) {
851cb0ef41Sopenharmony_ci    if (IsOpen()) {
861cb0ef41Sopenharmony_ci      funcs_to_infer_.push_back(func_to_infer);
871cb0ef41Sopenharmony_ci    }
881cb0ef41Sopenharmony_ci  }
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_ci  void RemoveLastFunction() {
911cb0ef41Sopenharmony_ci    if (IsOpen() && !funcs_to_infer_.empty()) funcs_to_infer_.pop_back();
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  void RemoveAsyncKeywordFromEnd();
951cb0ef41Sopenharmony_ci
961cb0ef41Sopenharmony_ci  // Infers a function name and leaves names collection state.
971cb0ef41Sopenharmony_ci  void Infer() {
981cb0ef41Sopenharmony_ci    DCHECK(IsOpen());
991cb0ef41Sopenharmony_ci    if (!funcs_to_infer_.empty()) InferFunctionsNames();
1001cb0ef41Sopenharmony_ci  }
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci private:
1031cb0ef41Sopenharmony_ci  enum NameType : uint8_t {
1041cb0ef41Sopenharmony_ci    kEnclosingConstructorName,
1051cb0ef41Sopenharmony_ci    kLiteralName,
1061cb0ef41Sopenharmony_ci    kVariableName
1071cb0ef41Sopenharmony_ci  };
1081cb0ef41Sopenharmony_ci  struct Name {
1091cb0ef41Sopenharmony_ci    // Needed for names_stack_.resize()
1101cb0ef41Sopenharmony_ci    Name() { UNREACHABLE(); }
1111cb0ef41Sopenharmony_ci    Name(const AstRawString* name, NameType type)
1121cb0ef41Sopenharmony_ci        : name_and_type_(name, type) {}
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci    base::PointerWithPayload<const AstRawString, NameType, 2> name_and_type_;
1151cb0ef41Sopenharmony_ci    inline const AstRawString* name() const {
1161cb0ef41Sopenharmony_ci      return name_and_type_.GetPointer();
1171cb0ef41Sopenharmony_ci    }
1181cb0ef41Sopenharmony_ci    inline NameType type() const { return name_and_type_.GetPayload(); }
1191cb0ef41Sopenharmony_ci  };
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ci  // Constructs a full name in dotted notation from gathered names.
1221cb0ef41Sopenharmony_ci  AstConsString* MakeNameFromStack();
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  // Performs name inferring for added functions.
1251cb0ef41Sopenharmony_ci  void InferFunctionsNames();
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  AstValueFactory* ast_value_factory_;
1281cb0ef41Sopenharmony_ci  std::vector<Name> names_stack_;
1291cb0ef41Sopenharmony_ci  std::vector<FunctionLiteral*> funcs_to_infer_;
1301cb0ef41Sopenharmony_ci  size_t scope_depth_ = 0;
1311cb0ef41Sopenharmony_ci};
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci}  // namespace internal
1351cb0ef41Sopenharmony_ci}  // namespace v8
1361cb0ef41Sopenharmony_ci
1371cb0ef41Sopenharmony_ci#endif  // V8_PARSING_FUNC_NAME_INFERRER_H_
138