Home | History | Annotate | Download | only in parsing
      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:
     37     explicit State(FuncNameInferrer* fni) : fni_(fni) {
     38       if (fni_ != nullptr) fni_->Enter();
     39     }
     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.
     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.
     62   void AddFunction(FunctionLiteral* func_to_infer) {
     63     if (IsOpen()) {
     64       funcs_to_infer_.Add(func_to_infer, zone());
     65     }
     66   }
     67 
     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.
     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 {
     89     Name(const AstRawString* name, NameType type) : name(name), type(type) {}
     90     const AstRawString* name;
     91     NameType type;
     92   };
     93 
     94   void Enter() { entries_stack_.Add(names_stack_.length(), zone()); }
     95 
     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 
    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