| // Copyright 2006-2009 the V8 project authors. All rights reserved. | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef V8_PARSING_FUNC_NAME_INFERRER_H_ | 
 | #define V8_PARSING_FUNC_NAME_INFERRER_H_ | 
 |  | 
 | #include <vector> | 
 |  | 
 | #include "src/base/macros.h" | 
 | #include "src/utils/pointer-with-payload.h" | 
 |  | 
 | namespace v8 { | 
 | namespace internal { | 
 |  | 
 | class AstConsString; | 
 | class AstRawString; | 
 | class AstValueFactory; | 
 | class FunctionLiteral; | 
 |  | 
 | enum class InferName { kYes, kNo }; | 
 |  | 
 | template <> | 
 | struct PointerWithPayloadTraits<AstRawString> { | 
 |   static constexpr int value = 2; | 
 | }; | 
 |  | 
 | // FuncNameInferrer is a stateful class that is used to perform name | 
 | // inference for anonymous functions during static analysis of source code. | 
 | // Inference is performed in cases when an anonymous function is assigned | 
 | // to a variable or a property (see test-func-name-inference.cc for examples.) | 
 | // | 
 | // The basic idea is that during parsing of LHSs of certain expressions | 
 | // (assignments, declarations, object literals) we collect name strings, | 
 | // and during parsing of the RHS, a function literal can be collected. After | 
 | // parsing the RHS we can infer a name for function literals that do not have | 
 | // a name. | 
 | class FuncNameInferrer { | 
 |  public: | 
 |   explicit FuncNameInferrer(AstValueFactory* ast_value_factory); | 
 |  | 
 |   // To enter function name inference state, put a FuncNameInferrer::State | 
 |   // on the stack. | 
 |   class State { | 
 |    public: | 
 |     explicit State(FuncNameInferrer* fni) | 
 |         : fni_(fni), top_(fni->names_stack_.size()) { | 
 |       ++fni_->scope_depth_; | 
 |     } | 
 |     ~State() { | 
 |       DCHECK(fni_->IsOpen()); | 
 |       fni_->names_stack_.resize(top_); | 
 |       --fni_->scope_depth_; | 
 |     } | 
 |  | 
 |    private: | 
 |     FuncNameInferrer* fni_; | 
 |     size_t top_; | 
 |  | 
 |     DISALLOW_COPY_AND_ASSIGN(State); | 
 |   }; | 
 |  | 
 |   // Returns whether we have entered name collection state. | 
 |   bool IsOpen() const { return scope_depth_ > 0; } | 
 |  | 
 |   // Pushes an enclosing the name of enclosing function onto names stack. | 
 |   void PushEnclosingName(const AstRawString* name); | 
 |  | 
 |   // Pushes an encountered name onto names stack when in collection state. | 
 |   void PushLiteralName(const AstRawString* name); | 
 |  | 
 |   void PushVariableName(const AstRawString* name); | 
 |  | 
 |   // Adds a function to infer name for. | 
 |   void AddFunction(FunctionLiteral* func_to_infer) { | 
 |     if (IsOpen()) { | 
 |       funcs_to_infer_.push_back(func_to_infer); | 
 |     } | 
 |   } | 
 |  | 
 |   void RemoveLastFunction() { | 
 |     if (IsOpen() && !funcs_to_infer_.empty()) funcs_to_infer_.pop_back(); | 
 |   } | 
 |  | 
 |   void RemoveAsyncKeywordFromEnd(); | 
 |  | 
 |   // Infers a function name and leaves names collection state. | 
 |   void Infer() { | 
 |     DCHECK(IsOpen()); | 
 |     if (!funcs_to_infer_.empty()) InferFunctionsNames(); | 
 |   } | 
 |  | 
 |  private: | 
 |   enum NameType : uint8_t { | 
 |     kEnclosingConstructorName, | 
 |     kLiteralName, | 
 |     kVariableName | 
 |   }; | 
 |   struct Name { | 
 |     // Needed for names_stack_.resize() | 
 |     Name() { UNREACHABLE(); } | 
 |     Name(const AstRawString* name, NameType type) | 
 |         : name_and_type_(name, type) {} | 
 |  | 
 |     PointerWithPayload<const AstRawString, NameType, 2> name_and_type_; | 
 |     inline const AstRawString* name() const { | 
 |       return name_and_type_.GetPointer(); | 
 |     } | 
 |     inline NameType type() const { return name_and_type_.GetPayload(); } | 
 |   }; | 
 |  | 
 |   // Constructs a full name in dotted notation from gathered names. | 
 |   AstConsString* MakeNameFromStack(); | 
 |  | 
 |   // Performs name inferring for added functions. | 
 |   void InferFunctionsNames(); | 
 |  | 
 |   AstValueFactory* ast_value_factory_; | 
 |   std::vector<Name> names_stack_; | 
 |   std::vector<FunctionLiteral*> funcs_to_infer_; | 
 |   size_t scope_depth_ = 0; | 
 |  | 
 |   DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer); | 
 | }; | 
 |  | 
 |  | 
 | }  // namespace internal | 
 | }  // namespace v8 | 
 |  | 
 | #endif  // V8_PARSING_FUNC_NAME_INFERRER_H_ |