1// Copyright 2011 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#include "src/parsing/func-name-inferrer.h" 6 7#include "src/ast/ast.h" 8#include "src/ast/ast-value-factory.h" 9#include "src/list-inl.h" 10 11namespace v8 { 12namespace internal { 13 14FuncNameInferrer::FuncNameInferrer(AstValueFactory* ast_value_factory, 15 Zone* zone) 16 : ast_value_factory_(ast_value_factory), 17 entries_stack_(10, zone), 18 names_stack_(5, zone), 19 funcs_to_infer_(4, zone), 20 zone_(zone) { 21} 22 23 24void FuncNameInferrer::PushEnclosingName(const AstRawString* name) { 25 // Enclosing name is a name of a constructor function. To check 26 // that it is really a constructor, we check that it is not empty 27 // and starts with a capital letter. 28 if (!name->IsEmpty() && unibrow::Uppercase::Is(name->FirstCharacter())) { 29 names_stack_.Add(Name(name, kEnclosingConstructorName), zone()); 30 } 31} 32 33 34void FuncNameInferrer::PushLiteralName(const AstRawString* name) { 35 if (IsOpen() && name != ast_value_factory_->prototype_string()) { 36 names_stack_.Add(Name(name, kLiteralName), zone()); 37 } 38} 39 40 41void FuncNameInferrer::PushVariableName(const AstRawString* name) { 42 if (IsOpen() && name != ast_value_factory_->dot_result_string()) { 43 names_stack_.Add(Name(name, kVariableName), zone()); 44 } 45} 46 47void FuncNameInferrer::RemoveAsyncKeywordFromEnd() { 48 if (IsOpen()) { 49 DCHECK(names_stack_.length() > 0); 50 DCHECK(names_stack_.last().name->IsOneByteEqualTo("async")); 51 names_stack_.RemoveLast(); 52 } 53} 54 55const AstString* FuncNameInferrer::MakeNameFromStack() { 56 return MakeNameFromStackHelper(0, ast_value_factory_->empty_string()); 57} 58 59const AstString* FuncNameInferrer::MakeNameFromStackHelper( 60 int pos, const AstString* prev) { 61 if (pos >= names_stack_.length()) return prev; 62 if (pos < names_stack_.length() - 1 && 63 names_stack_.at(pos).type == kVariableName && 64 names_stack_.at(pos + 1).type == kVariableName) { 65 // Skip consecutive variable declarations. 66 return MakeNameFromStackHelper(pos + 1, prev); 67 } else { 68 if (prev->length() > 0) { 69 const AstRawString* name = names_stack_.at(pos).name; 70 if (prev->length() + name->length() + 1 > String::kMaxLength) return prev; 71 const AstConsString* curr = ast_value_factory_->NewConsString( 72 ast_value_factory_->dot_string(), name); 73 curr = ast_value_factory_->NewConsString(prev, curr); 74 return MakeNameFromStackHelper(pos + 1, curr); 75 } else { 76 return MakeNameFromStackHelper(pos + 1, names_stack_.at(pos).name); 77 } 78 } 79} 80 81 82void FuncNameInferrer::InferFunctionsNames() { 83 const AstString* func_name = MakeNameFromStack(); 84 for (int i = 0; i < funcs_to_infer_.length(); ++i) { 85 funcs_to_infer_[i]->set_raw_inferred_name(func_name); 86 } 87 funcs_to_infer_.Rewind(0); 88} 89 90 91} // namespace internal 92} // namespace v8 93