11cb0ef41Sopenharmony_ci// Copyright 2006-2009 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_PARSING_FUNC_NAME_INFERRER_H_ 61cb0ef41Sopenharmony_ci#define V8_PARSING_FUNC_NAME_INFERRER_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include <vector> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/base/macros.h" 111cb0ef41Sopenharmony_ci#include "src/base/pointer-with-payload.h" 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cinamespace v8 { 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_cinamespace internal { 161cb0ef41Sopenharmony_ciclass AstRawString; 171cb0ef41Sopenharmony_ci} 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_cinamespace base { 201cb0ef41Sopenharmony_citemplate <> 211cb0ef41Sopenharmony_cistruct PointerWithPayloadTraits<v8::internal::AstRawString> { 221cb0ef41Sopenharmony_ci static constexpr int kAvailableBits = 2; 231cb0ef41Sopenharmony_ci}; 241cb0ef41Sopenharmony_ci} // namespace base 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace internal { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ciclass AstConsString; 291cb0ef41Sopenharmony_ciclass AstValueFactory; 301cb0ef41Sopenharmony_ciclass FunctionLiteral; 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_cienum class InferName { kYes, kNo }; 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci// FuncNameInferrer is a stateful class that is used to perform name 351cb0ef41Sopenharmony_ci// inference for anonymous functions during static analysis of source code. 361cb0ef41Sopenharmony_ci// Inference is performed in cases when an anonymous function is assigned 371cb0ef41Sopenharmony_ci// to a variable or a property (see test-func-name-inference.cc for examples.) 381cb0ef41Sopenharmony_ci// 391cb0ef41Sopenharmony_ci// The basic idea is that during parsing of LHSs of certain expressions 401cb0ef41Sopenharmony_ci// (assignments, declarations, object literals) we collect name strings, 411cb0ef41Sopenharmony_ci// and during parsing of the RHS, a function literal can be collected. After 421cb0ef41Sopenharmony_ci// parsing the RHS we can infer a name for function literals that do not have 431cb0ef41Sopenharmony_ci// a name. 441cb0ef41Sopenharmony_ciclass FuncNameInferrer { 451cb0ef41Sopenharmony_ci public: 461cb0ef41Sopenharmony_ci explicit FuncNameInferrer(AstValueFactory* ast_value_factory); 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_ci FuncNameInferrer(const FuncNameInferrer&) = delete; 491cb0ef41Sopenharmony_ci FuncNameInferrer& operator=(const FuncNameInferrer&) = delete; 501cb0ef41Sopenharmony_ci 511cb0ef41Sopenharmony_ci // To enter function name inference state, put a FuncNameInferrer::State 521cb0ef41Sopenharmony_ci // on the stack. 531cb0ef41Sopenharmony_ci class State { 541cb0ef41Sopenharmony_ci public: 551cb0ef41Sopenharmony_ci explicit State(FuncNameInferrer* fni) 561cb0ef41Sopenharmony_ci : fni_(fni), top_(fni->names_stack_.size()) { 571cb0ef41Sopenharmony_ci ++fni_->scope_depth_; 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci ~State() { 601cb0ef41Sopenharmony_ci DCHECK(fni_->IsOpen()); 611cb0ef41Sopenharmony_ci fni_->names_stack_.resize(top_); 621cb0ef41Sopenharmony_ci --fni_->scope_depth_; 631cb0ef41Sopenharmony_ci } 641cb0ef41Sopenharmony_ci State(const State&) = delete; 651cb0ef41Sopenharmony_ci State& operator=(const State&) = delete; 661cb0ef41Sopenharmony_ci 671cb0ef41Sopenharmony_ci private: 681cb0ef41Sopenharmony_ci FuncNameInferrer* fni_; 691cb0ef41Sopenharmony_ci size_t top_; 701cb0ef41Sopenharmony_ci }; 711cb0ef41Sopenharmony_ci 721cb0ef41Sopenharmony_ci // Returns whether we have entered name collection state. 731cb0ef41Sopenharmony_ci bool IsOpen() const { return scope_depth_ > 0; } 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci // Pushes an enclosing the name of enclosing function onto names stack. 761cb0ef41Sopenharmony_ci void PushEnclosingName(const AstRawString* name); 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci // Pushes an encountered name onto names stack when in collection state. 791cb0ef41Sopenharmony_ci void PushLiteralName(const AstRawString* name); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci void PushVariableName(const AstRawString* name); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci // Adds a function to infer name for. 841cb0ef41Sopenharmony_ci void AddFunction(FunctionLiteral* func_to_infer) { 851cb0ef41Sopenharmony_ci if (IsOpen()) { 861cb0ef41Sopenharmony_ci funcs_to_infer_.push_back(func_to_infer); 871cb0ef41Sopenharmony_ci } 881cb0ef41Sopenharmony_ci } 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_ci void RemoveLastFunction() { 911cb0ef41Sopenharmony_ci if (IsOpen() && !funcs_to_infer_.empty()) funcs_to_infer_.pop_back(); 921cb0ef41Sopenharmony_ci } 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci void RemoveAsyncKeywordFromEnd(); 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_ci // Infers a function name and leaves names collection state. 971cb0ef41Sopenharmony_ci void Infer() { 981cb0ef41Sopenharmony_ci DCHECK(IsOpen()); 991cb0ef41Sopenharmony_ci if (!funcs_to_infer_.empty()) InferFunctionsNames(); 1001cb0ef41Sopenharmony_ci } 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci private: 1031cb0ef41Sopenharmony_ci enum NameType : uint8_t { 1041cb0ef41Sopenharmony_ci kEnclosingConstructorName, 1051cb0ef41Sopenharmony_ci kLiteralName, 1061cb0ef41Sopenharmony_ci kVariableName 1071cb0ef41Sopenharmony_ci }; 1081cb0ef41Sopenharmony_ci struct Name { 1091cb0ef41Sopenharmony_ci // Needed for names_stack_.resize() 1101cb0ef41Sopenharmony_ci Name() { UNREACHABLE(); } 1111cb0ef41Sopenharmony_ci Name(const AstRawString* name, NameType type) 1121cb0ef41Sopenharmony_ci : name_and_type_(name, type) {} 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci base::PointerWithPayload<const AstRawString, NameType, 2> name_and_type_; 1151cb0ef41Sopenharmony_ci inline const AstRawString* name() const { 1161cb0ef41Sopenharmony_ci return name_and_type_.GetPointer(); 1171cb0ef41Sopenharmony_ci } 1181cb0ef41Sopenharmony_ci inline NameType type() const { return name_and_type_.GetPayload(); } 1191cb0ef41Sopenharmony_ci }; 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci // Constructs a full name in dotted notation from gathered names. 1221cb0ef41Sopenharmony_ci AstConsString* MakeNameFromStack(); 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci // Performs name inferring for added functions. 1251cb0ef41Sopenharmony_ci void InferFunctionsNames(); 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci AstValueFactory* ast_value_factory_; 1281cb0ef41Sopenharmony_ci std::vector<Name> names_stack_; 1291cb0ef41Sopenharmony_ci std::vector<FunctionLiteral*> funcs_to_infer_; 1301cb0ef41Sopenharmony_ci size_t scope_depth_ = 0; 1311cb0ef41Sopenharmony_ci}; 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci} // namespace internal 1351cb0ef41Sopenharmony_ci} // namespace v8 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci#endif // V8_PARSING_FUNC_NAME_INFERRER_H_ 138