func-name-inferrer.h 3.61 KB
Newer Older
1
// Copyright 2006-2009 the V8 project authors. All rights reserved.
2 3
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
4

5 6
#ifndef V8_PARSING_FUNC_NAME_INFERRER_H_
#define V8_PARSING_FUNC_NAME_INFERRER_H_
7

8 9 10
#include <vector>

#include "src/base/macros.h"
11
#include "src/pointer-with-payload.h"
12

13 14
namespace v8 {
namespace internal {
15

16
class AstConsString;
17 18
class AstRawString;
class AstValueFactory;
19
class FunctionLiteral;
20

21
enum class InferName { kYes, kNo };
22

23 24 25 26 27
template <>
struct PointerWithPayloadTraits<AstRawString> {
  static constexpr int value = 2;
};

28 29 30 31
// 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.)
32
//
33 34 35 36 37
// 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.
38
class FuncNameInferrer {
39
 public:
40
  explicit FuncNameInferrer(AstValueFactory* ast_value_factory);
41

42 43 44 45
  // To enter function name inference state, put a FuncNameInferrer::State
  // on the stack.
  class State {
   public:
46 47 48 49 50 51 52 53 54
    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_;
    }
55 56 57

   private:
    FuncNameInferrer* fni_;
58
    size_t top_;
59 60 61 62

    DISALLOW_COPY_AND_ASSIGN(State);
  };

63
  // Returns whether we have entered name collection state.
64
  bool IsOpen() const { return scope_depth_ > 0; }
65

66
  // Pushes an enclosing the name of enclosing function onto names stack.
67
  void PushEnclosingName(const AstRawString* name);
68

69
  // Pushes an encountered name onto names stack when in collection state.
70
  void PushLiteralName(const AstRawString* name);
71

72
  void PushVariableName(const AstRawString* name);
73

74
  // Adds a function to infer name for.
75
  void AddFunction(FunctionLiteral* func_to_infer) {
76
    if (IsOpen()) {
77
      funcs_to_infer_.push_back(func_to_infer);
78 79 80
    }
  }

81
  void RemoveLastFunction() {
82
    if (IsOpen() && !funcs_to_infer_.empty()) funcs_to_infer_.pop_back();
83 84
  }

85 86
  void RemoveAsyncKeywordFromEnd();

87
  // Infers a function name and leaves names collection state.
88
  void Infer() {
89
    DCHECK(IsOpen());
90
    if (!funcs_to_infer_.empty()) InferFunctionsNames();
91 92
  }

93
 private:
94
  enum NameType : uint8_t {
95 96 97 98 99
    kEnclosingConstructorName,
    kLiteralName,
    kVariableName
  };
  struct Name {
100 101
    // Needed for names_stack_.resize()
    Name() { UNREACHABLE(); }
102 103 104 105 106 107 108 109
    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(); }
110 111
  };

112
  // Constructs a full name in dotted notation from gathered names.
113
  const AstConsString* MakeNameFromStack();
114 115

  // Performs name inferring for added functions.
116
  void InferFunctionsNames();
117

118
  AstValueFactory* ast_value_factory_;
119 120 121
  std::vector<Name> names_stack_;
  std::vector<FunctionLiteral*> funcs_to_infer_;
  size_t scope_depth_ = 0;
122 123 124 125 126

  DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
};


127 128
}  // namespace internal
}  // namespace v8
129

130
#endif  // V8_PARSING_FUNC_NAME_INFERRER_H_