summaryrefslogtreecommitdiff
path: root/deps/v8/src/parsing/func-name-inferrer.h
blob: 66dd21f8cdffe52b29e8ea9ea2d1f5735e519b2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// 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_