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_PARSING_FUNC_NAME_INFERRER_H_ 6 #define V8_PARSING_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 // To enter function name inference state, put a FuncNameInferrer::State 34 // on the stack. 35 class State { 36 public: State(FuncNameInferrer * fni)37 explicit State(FuncNameInferrer* fni) : fni_(fni) { 38 if (fni_ != nullptr) fni_->Enter(); 39 } ~State()40 ~State() { 41 if (fni_ != nullptr) fni_->Leave(); 42 } 43 44 private: 45 FuncNameInferrer* fni_; 46 47 DISALLOW_COPY_AND_ASSIGN(State); 48 }; 49 50 // Returns whether we have entered name collection state. IsOpen()51 bool IsOpen() const { return !entries_stack_.is_empty(); } 52 53 // Pushes an enclosing the name of enclosing function onto names stack. 54 void PushEnclosingName(const AstRawString* name); 55 56 // Pushes an encountered name onto names stack when in collection state. 57 void PushLiteralName(const AstRawString* name); 58 59 void PushVariableName(const AstRawString* name); 60 61 // Adds a function to infer name for. AddFunction(FunctionLiteral * func_to_infer)62 void AddFunction(FunctionLiteral* func_to_infer) { 63 if (IsOpen()) { 64 funcs_to_infer_.Add(func_to_infer, zone()); 65 } 66 } 67 RemoveLastFunction()68 void RemoveLastFunction() { 69 if (IsOpen() && !funcs_to_infer_.is_empty()) { 70 funcs_to_infer_.RemoveLast(); 71 } 72 } 73 74 // Infers a function name and leaves names collection state. Infer()75 void Infer() { 76 DCHECK(IsOpen()); 77 if (!funcs_to_infer_.is_empty()) { 78 InferFunctionsNames(); 79 } 80 } 81 82 private: 83 enum NameType { 84 kEnclosingConstructorName, 85 kLiteralName, 86 kVariableName 87 }; 88 struct Name { NameName89 Name(const AstRawString* name, NameType type) : name(name), type(type) {} 90 const AstRawString* name; 91 NameType type; 92 }; 93 Enter()94 void Enter() { entries_stack_.Add(names_stack_.length(), zone()); } 95 Leave()96 void Leave() { 97 DCHECK(IsOpen()); 98 names_stack_.Rewind(entries_stack_.RemoveLast()); 99 if (entries_stack_.is_empty()) funcs_to_infer_.Clear(); 100 } 101 zone()102 Zone* zone() const { return zone_; } 103 104 // Constructs a full name in dotted notation from gathered names. 105 const AstString* MakeNameFromStack(); 106 107 // A helper function for MakeNameFromStack. 108 const AstString* MakeNameFromStackHelper(int pos, 109 const AstString* prev); 110 111 // Performs name inferring for added functions. 112 void InferFunctionsNames(); 113 114 AstValueFactory* ast_value_factory_; 115 ZoneList<int> entries_stack_; 116 ZoneList<Name> names_stack_; 117 ZoneList<FunctionLiteral*> funcs_to_infer_; 118 Zone* zone_; 119 120 DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer); 121 }; 122 123 124 } // namespace internal 125 } // namespace v8 126 127 #endif // V8_PARSING_FUNC_NAME_INFERRER_H_ 128