1// Copyright 2021 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_TORQUE_CPP_BUILDER_H_
6#define V8_TORQUE_CPP_BUILDER_H_
7
8#include <stack>
9
10#include "src/torque/ast.h"
11#include "src/torque/types.h"
12
13namespace v8 {
14namespace internal {
15namespace torque {
16namespace cpp {
17
18struct TemplateParameter {
19  explicit TemplateParameter(std::string name) : name(std::move(name)) {}
20  TemplateParameter(std::string type, std::string name)
21      : name(std::move(name)), type(std::move(type)) {}
22
23  std::string name;
24  std::string type;
25};
26
27class Class {
28 public:
29  explicit Class(std::string name) : name_(std::move(name)) {}
30  Class(std::vector<TemplateParameter> template_parameters, std::string name)
31      : template_parameters_(std::move(template_parameters)),
32        name_(std::move(name)) {}
33
34  std::string GetName() const { return name_; }
35  std::vector<TemplateParameter> GetTemplateParameters() const {
36    return template_parameters_;
37  }
38
39 private:
40  std::vector<TemplateParameter> template_parameters_;
41  std::string name_;
42};
43
44#define FUNCTION_FLAG_LIST(V) \
45  V(Inline, 0x01)             \
46  V(V8Inline, 0x03)           \
47  V(Const, 0x04)              \
48  V(Constexpr, 0x08)          \
49  V(Export, 0x10)             \
50  V(Static, 0x20)             \
51  V(Override, 0x40)
52
53class Function {
54 public:
55  enum FunctionFlag {
56#define ENTRY(name, value) k##name = value,
57    FUNCTION_FLAG_LIST(ENTRY)
58#undef ENTRY
59  };
60
61  struct Parameter {
62    std::string type;
63    std::string name;
64    std::string default_value;
65
66    Parameter(std::string type, std::string name,
67              std::string default_value = {})
68        : type(std::move(type)),
69          name(std::move(name)),
70          default_value(std::move(default_value)) {}
71  };
72
73  explicit Function(std::string name)
74      : pos_(CurrentSourcePosition::Get()),
75        owning_class_(nullptr),
76        name_(std::move(name)) {}
77  Function(Class* owning_class, std::string name)
78      : pos_(CurrentSourcePosition::Get()),
79        owning_class_(owning_class),
80        name_(std::move(name)) {}
81  ~Function() = default;
82
83  static Function DefaultGetter(std::string return_type, Class* owner,
84                                std::string name) {
85    Function getter(owner, std::move(name));
86    getter.SetReturnType(std::move(return_type));
87    getter.SetInline();
88    getter.SetConst();
89    return getter;
90  }
91
92  static Function DefaultSetter(Class* owner, std::string name,
93                                std::string parameter_type,
94                                std::string parameter_name) {
95    Function setter(owner, std::move(name));
96    setter.SetReturnType("void");
97    setter.AddParameter(std::move(parameter_type), std::move(parameter_name));
98    setter.SetInline();
99    return setter;
100  }
101
102  void SetFlag(FunctionFlag flag, bool value = true) {
103    if (value) {
104      flags_ = flags_ | flag;
105    } else {
106      flags_ = flags_.without(flag);
107    }
108  }
109  void SetFlags(base::Flags<FunctionFlag> flags, bool value = true) {
110    if (value) {
111      flags_ |= flags;
112    } else {
113      flags_ &= ~flags;
114    }
115  }
116  bool HasFlag(FunctionFlag flag) const { return (flags_ & flag) == flag; }
117#define ACCESSOR(name, value)                            \
118  void Set##name(bool v = true) { SetFlag(k##name, v); } \
119  bool Is##name() const { return HasFlag(k##name); }
120  FUNCTION_FLAG_LIST(ACCESSOR)
121#undef ACCESSOR
122
123  void SetDescription(std::string description) {
124    description_ = std::move(description);
125  }
126  void SetName(std::string name) { name_ = std::move(name); }
127  void SetReturnType(std::string return_type) {
128    return_type_ = std::move(return_type);
129  }
130  void AddParameter(std::string type, std::string name = {},
131                    std::string default_value = {}) {
132    parameters_.emplace_back(std::move(type), std::move(name),
133                             std::move(default_value));
134  }
135  void InsertParameter(int index, std::string type, std::string name = {},
136                       std::string default_value = {}) {
137    DCHECK_GE(index, 0);
138    DCHECK_LE(index, parameters_.size());
139    parameters_.insert(
140        parameters_.begin() + index,
141        Parameter(std::move(type), std::move(name), std::move(default_value)));
142  }
143  std::vector<Parameter> GetParameters() const { return parameters_; }
144  std::vector<std::string> GetParameterNames() const {
145    std::vector<std::string> names;
146    std::transform(parameters_.begin(), parameters_.end(),
147                   std::back_inserter(names),
148                   [](const Parameter& p) { return p.name; });
149    return names;
150  }
151
152  static constexpr int kAutomaticIndentation = -1;
153  void PrintDeclaration(std::ostream& stream,
154                        int indentation = kAutomaticIndentation) const;
155  void PrintDefinition(std::ostream& stream,
156                       const std::function<void(std::ostream&)>& builder,
157                       int indentation = 0) const;
158  void PrintInlineDefinition(std::ostream& stream,
159                             const std::function<void(std::ostream&)>& builder,
160                             int indentation = 2) const;
161  void PrintBeginDefinition(std::ostream& stream, int indentation = 0) const;
162  void PrintEndDefinition(std::ostream& stream, int indentation = 0) const;
163
164 protected:
165  void PrintDeclarationHeader(std::ostream& stream, int indentation) const;
166
167 private:
168  SourcePosition pos_;
169  Class* owning_class_;
170  std::string description_;
171  std::string name_;
172  std::string return_type_;
173  std::vector<Parameter> parameters_;
174  base::Flags<FunctionFlag> flags_;
175};
176
177DEFINE_OPERATORS_FOR_FLAGS(base::Flags<Function::FunctionFlag>)
178#undef FUNCTION_FLAG_LIST
179
180class File {
181 public:
182  explicit File(std::ostream& stream) : stream_(&stream) {}
183
184  void BeginIncludeGuard(const std::string& name);
185  void EndIncludeGuard(const std::string& name);
186  void BeginNamespace(std::string name);
187  void BeginNamespace(std::string name0, std::string name1);
188  void EndNamespace(const std::string& name);
189  void EndNamespace(const std::string& name0, const std::string& name1);
190
191  void AddInclude(std::string include) { includes_.insert(std::move(include)); }
192
193  template <typename T>
194  File& operator<<(const T& value) {
195    s() << value;
196    return *this;
197  }
198
199 protected:
200  std::ostream& s() { return *stream_; }
201
202 private:
203  std::ostream* stream_;
204  std::set<std::string> includes_;
205  std::stack<std::string> namespaces_;
206};
207
208class IncludeGuardScope {
209 public:
210  explicit IncludeGuardScope(File* file, std::string name)
211      : file_(file), name_(std::move(name)) {
212    file_->BeginIncludeGuard(name_);
213  }
214  IncludeGuardScope(const IncludeGuardScope&) = delete;
215  IncludeGuardScope(IncludeGuardScope&& other) V8_NOEXCEPT : file_(nullptr),
216                                                             name_() {
217    std::swap(file_, other.file_);
218    std::swap(name_, other.name_);
219  }
220  ~IncludeGuardScope() {
221    if (file_) {
222      file_->EndIncludeGuard(name_);
223    }
224  }
225  IncludeGuardScope& operator=(const IncludeGuardScope&) = delete;
226  IncludeGuardScope& operator=(IncludeGuardScope&& other) V8_NOEXCEPT {
227    if (this != &other) {
228      DCHECK_NULL(file_);
229      DCHECK(name_.empty());
230      std::swap(file_, other.file_);
231      std::swap(name_, other.name_);
232    }
233    return *this;
234  }
235
236 private:
237  File* file_;
238  std::string name_;
239};
240
241}  // namespace cpp
242}  // namespace torque
243}  // namespace internal
244}  // namespace v8
245
246#endif  // V8_TORQUE_CPP_BUILDER_H_
247