aboutsummaryrefslogtreecommitdiff
path: root/src/parsing/func-name-inferrer.h
blob: cc9204bb6d12c25fbd73e20b9395d60b7845d92f (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
131
// 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 "src/handles.h"
#include "src/zone/zone.h"

namespace v8 {
namespace internal {

class AstRawString;
class AstString;
class AstValueFactory;
class FunctionLiteral;

enum class InferName { kYes, kNo };

// 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 ZoneObject {
 public:
  FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);

  // To enter function name inference state, put a FuncNameInferrer::State
  // on the stack.
  class State {
   public:
    explicit State(FuncNameInferrer* fni) : fni_(fni) {
      if (fni_ != nullptr) fni_->Enter();
    }
    ~State() {
      if (fni_ != nullptr) fni_->Leave();
    }

   private:
    FuncNameInferrer* fni_;

    DISALLOW_COPY_AND_ASSIGN(State);
  };

  // Returns whether we have entered name collection state.
  bool IsOpen() const { return !entries_stack_.is_empty(); }

  // 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_.Add(func_to_infer, zone());
    }
  }

  void RemoveLastFunction() {
    if (IsOpen() && !funcs_to_infer_.is_empty()) {
      funcs_to_infer_.RemoveLast();
    }
  }

  void RemoveAsyncKeywordFromEnd();

  // Infers a function name and leaves names collection state.
  void Infer() {
    DCHECK(IsOpen());
    if (!funcs_to_infer_.is_empty()) {
      InferFunctionsNames();
    }
  }

 private:
  enum NameType {
    kEnclosingConstructorName,
    kLiteralName,
    kVariableName
  };
  struct Name {
    Name(const AstRawString* name, NameType type) : name(name), type(type) {}
    const AstRawString* name;
    NameType type;
  };

  void Enter() { entries_stack_.Add(names_stack_.length(), zone()); }

  void Leave() {
    DCHECK(IsOpen());
    names_stack_.Rewind(entries_stack_.RemoveLast());
    if (entries_stack_.is_empty()) funcs_to_infer_.Clear();
  }

  Zone* zone() const { return zone_; }

  // Constructs a full name in dotted notation from gathered names.
  const AstString* MakeNameFromStack();

  // A helper function for MakeNameFromStack.
  const AstString* MakeNameFromStackHelper(int pos,
                                               const AstString* prev);

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

  AstValueFactory* ast_value_factory_;
  ZoneList<int> entries_stack_;
  ZoneList<Name> names_stack_;
  ZoneList<FunctionLiteral*> funcs_to_infer_;
  Zone* zone_;

  DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
};


}  // namespace internal
}  // namespace v8

#endif  // V8_PARSING_FUNC_NAME_INFERRER_H_