• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  // Copyright 2006-2009 the V8 project authors. All rights reserved.
2  // Use of this source code is governed by a BSD-style license that can be
3  // found in the LICENSE file.
4  
5  #ifndef V8_FUNC_NAME_INFERRER_H_
6  #define V8_FUNC_NAME_INFERRER_H_
7  
8  #include "src/handles.h"
9  #include "src/zone.h"
10  
11  namespace v8 {
12  namespace internal {
13  
14  class AstRawString;
15  class AstString;
16  class AstValueFactory;
17  class FunctionLiteral;
18  
19  // FuncNameInferrer is a stateful class that is used to perform name
20  // inference for anonymous functions during static analysis of source code.
21  // Inference is performed in cases when an anonymous function is assigned
22  // to a variable or a property (see test-func-name-inference.cc for examples.)
23  //
24  // The basic idea is that during parsing of LHSs of certain expressions
25  // (assignments, declarations, object literals) we collect name strings,
26  // and during parsing of the RHS, a function literal can be collected. After
27  // parsing the RHS we can infer a name for function literals that do not have
28  // a name.
29  class FuncNameInferrer : public ZoneObject {
30   public:
31    FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
32  
33    // Returns whether we have entered name collection state.
IsOpen()34    bool IsOpen() const { return !entries_stack_.is_empty(); }
35  
36    // Pushes an enclosing the name of enclosing function onto names stack.
37    void PushEnclosingName(const AstRawString* name);
38  
39    // Enters name collection state.
Enter()40    void Enter() {
41      entries_stack_.Add(names_stack_.length(), zone());
42    }
43  
44    // Pushes an encountered name onto names stack when in collection state.
45    void PushLiteralName(const AstRawString* name);
46  
47    void PushVariableName(const AstRawString* name);
48  
49    // Adds a function to infer name for.
AddFunction(FunctionLiteral * func_to_infer)50    void AddFunction(FunctionLiteral* func_to_infer) {
51      if (IsOpen()) {
52        funcs_to_infer_.Add(func_to_infer, zone());
53      }
54    }
55  
RemoveLastFunction()56    void RemoveLastFunction() {
57      if (IsOpen() && !funcs_to_infer_.is_empty()) {
58        funcs_to_infer_.RemoveLast();
59      }
60    }
61  
62    // Infers a function name and leaves names collection state.
Infer()63    void Infer() {
64      DCHECK(IsOpen());
65      if (!funcs_to_infer_.is_empty()) {
66        InferFunctionsNames();
67      }
68    }
69  
70    // Leaves names collection state.
Leave()71    void Leave() {
72      DCHECK(IsOpen());
73      names_stack_.Rewind(entries_stack_.RemoveLast());
74      if (entries_stack_.is_empty())
75        funcs_to_infer_.Clear();
76    }
77  
78   private:
79    enum NameType {
80      kEnclosingConstructorName,
81      kLiteralName,
82      kVariableName
83    };
84    struct Name {
NameName85      Name(const AstRawString* name, NameType type) : name(name), type(type) {}
86      const AstRawString* name;
87      NameType type;
88    };
89  
zone()90    Zone* zone() const { return zone_; }
91  
92    // Constructs a full name in dotted notation from gathered names.
93    const AstString* MakeNameFromStack();
94  
95    // A helper function for MakeNameFromStack.
96    const AstString* MakeNameFromStackHelper(int pos,
97                                                 const AstString* prev);
98  
99    // Performs name inferring for added functions.
100    void InferFunctionsNames();
101  
102    AstValueFactory* ast_value_factory_;
103    ZoneList<int> entries_stack_;
104    ZoneList<Name> names_stack_;
105    ZoneList<FunctionLiteral*> funcs_to_infer_;
106    Zone* zone_;
107  
108    DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
109  };
110  
111  
112  } }  // namespace v8::internal
113  
114  #endif  // V8_FUNC_NAME_INFERRER_H_
115