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/zone/zone.h"
      9 
     10 namespace v8 {
     11 namespace internal {
     12 
     13 class AstRawString;
     14 class AstString;
     15 class AstValueFactory;
     16 class FunctionLiteral;
     17 
     18 enum class InferName { kYes, kNo };
     19 
     20 // FuncNameInferrer is a stateful class that is used to perform name
     21 // inference for anonymous functions during static analysis of source code.
     22 // Inference is performed in cases when an anonymous function is assigned
     23 // to a variable or a property (see test-func-name-inference.cc for examples.)
     24 //
     25 // The basic idea is that during parsing of LHSs of certain expressions
     26 // (assignments, declarations, object literals) we collect name strings,
     27 // and during parsing of the RHS, a function literal can be collected. After
     28 // parsing the RHS we can infer a name for function literals that do not have
     29 // a name.
     30 class FuncNameInferrer : public ZoneObject {
     31  public:
     32   FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
     33 
     34   // To enter function name inference state, put a FuncNameInferrer::State
     35   // on the stack.
     36   class State {
     37    public:
     38     explicit State(FuncNameInferrer* fni) : fni_(fni) {
     39       if (fni_ != nullptr) fni_->Enter();
     40     }
     41     ~State() {
     42       if (fni_ != nullptr) fni_->Leave();
     43     }
     44 
     45    private:
     46     FuncNameInferrer* fni_;
     47 
     48     DISALLOW_COPY_AND_ASSIGN(State);
     49   };
     50 
     51   // Returns whether we have entered name collection state.
     52   bool IsOpen() const { return !entries_stack_.is_empty(); }
     53 
     54   // Pushes an enclosing the name of enclosing function onto names stack.
     55   void PushEnclosingName(const AstRawString* name);
     56 
     57   // Pushes an encountered name onto names stack when in collection state.
     58   void PushLiteralName(const AstRawString* name);
     59 
     60   void PushVariableName(const AstRawString* name);
     61 
     62   // Adds a function to infer name for.
     63   void AddFunction(FunctionLiteral* func_to_infer) {
     64     if (IsOpen()) {
     65       funcs_to_infer_.Add(func_to_infer, zone());
     66     }
     67   }
     68 
     69   void RemoveLastFunction() {
     70     if (IsOpen() && !funcs_to_infer_.is_empty()) {
     71       funcs_to_infer_.RemoveLast();
     72     }
     73   }
     74 
     75   void RemoveAsyncKeywordFromEnd();
     76 
     77   // Infers a function name and leaves names collection state.
     78   void Infer() {
     79     DCHECK(IsOpen());
     80     if (!funcs_to_infer_.is_empty()) {
     81       InferFunctionsNames();
     82     }
     83   }
     84 
     85  private:
     86   enum NameType {
     87     kEnclosingConstructorName,
     88     kLiteralName,
     89     kVariableName
     90   };
     91   struct Name {
     92     Name(const AstRawString* name, NameType type) : name(name), type(type) {}
     93     const AstRawString* name;
     94     NameType type;
     95   };
     96 
     97   void Enter() { entries_stack_.Add(names_stack_.length(), zone()); }
     98 
     99   void Leave() {
    100     DCHECK(IsOpen());
    101     names_stack_.Rewind(entries_stack_.RemoveLast());
    102     if (entries_stack_.is_empty()) funcs_to_infer_.Clear();
    103   }
    104 
    105   Zone* zone() const { return zone_; }
    106 
    107   // Constructs a full name in dotted notation from gathered names.
    108   const AstString* MakeNameFromStack();
    109 
    110   // A helper function for MakeNameFromStack.
    111   const AstString* MakeNameFromStackHelper(int pos,
    112                                                const AstString* prev);
    113 
    114   // Performs name inferring for added functions.
    115   void InferFunctionsNames();
    116 
    117   AstValueFactory* ast_value_factory_;
    118   ZoneList<int> entries_stack_;
    119   ZoneList<Name> names_stack_;
    120   ZoneList<FunctionLiteral*> funcs_to_infer_;
    121   Zone* zone_;
    122 
    123   DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
    124 };
    125 
    126 
    127 }  // namespace internal
    128 }  // namespace v8
    129 
    130 #endif  // V8_PARSING_FUNC_NAME_INFERRER_H_
    131