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