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_FUNC_NAME_INFERRER_H_
6#define V8_FUNC_NAME_INFERRER_H_
7
8#include "src/handles.h"
9#include "src/zone.h"
10
11namespace v8 {
12namespace internal {
13
14class AstRawString;
15class AstString;
16class AstValueFactory;
17class 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.
29class FuncNameInferrer : public ZoneObject {
30 public:
31  FuncNameInferrer(AstValueFactory* ast_value_factory, Zone* zone);
32
33  // Returns whether we have entered name collection state.
34  bool IsOpen() const { return !entries_stack_.is_empty(); }
35
36  // Pushes an enclosing the name of enclosing function onto names stack.
37  void PushEnclosingName(const AstRawString* name);
38
39  // Enters name collection state.
40  void Enter() {
41    entries_stack_.Add(names_stack_.length(), zone());
42  }
43
44  // Pushes an encountered name onto names stack when in collection state.
45  void PushLiteralName(const AstRawString* name);
46
47  void PushVariableName(const AstRawString* name);
48
49  // Adds a function to infer name for.
50  void AddFunction(FunctionLiteral* func_to_infer) {
51    if (IsOpen()) {
52      funcs_to_infer_.Add(func_to_infer, zone());
53    }
54  }
55
56  void RemoveLastFunction() {
57    if (IsOpen() && !funcs_to_infer_.is_empty()) {
58      funcs_to_infer_.RemoveLast();
59    }
60  }
61
62  // Infers a function name and leaves names collection state.
63  void Infer() {
64    DCHECK(IsOpen());
65    if (!funcs_to_infer_.is_empty()) {
66      InferFunctionsNames();
67    }
68  }
69
70  // Leaves names collection state.
71  void Leave() {
72    DCHECK(IsOpen());
73    names_stack_.Rewind(entries_stack_.RemoveLast());
74    if (entries_stack_.is_empty())
75      funcs_to_infer_.Clear();
76  }
77
78 private:
79  enum NameType {
80    kEnclosingConstructorName,
81    kLiteralName,
82    kVariableName
83  };
84  struct Name {
85    Name(const AstRawString* name, NameType type) : name(name), type(type) {}
86    const AstRawString* name;
87    NameType type;
88  };
89
90  Zone* zone() const { return zone_; }
91
92  // Constructs a full name in dotted notation from gathered names.
93  const AstString* MakeNameFromStack();
94
95  // A helper function for MakeNameFromStack.
96  const AstString* MakeNameFromStackHelper(int pos,
97                                               const AstString* prev);
98
99  // Performs name inferring for added functions.
100  void InferFunctionsNames();
101
102  AstValueFactory* ast_value_factory_;
103  ZoneList<int> entries_stack_;
104  ZoneList<Name> names_stack_;
105  ZoneList<FunctionLiteral*> funcs_to_infer_;
106  Zone* zone_;
107
108  DISALLOW_COPY_AND_ASSIGN(FuncNameInferrer);
109};
110
111
112} }  // namespace v8::internal
113
114#endif  // V8_FUNC_NAME_INFERRER_H_
115