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
13 namespace v8 {
14 namespace internal {
15 namespace torque {
16 namespace cpp {
17
18 struct TemplateParameter {
TemplateParameterTemplateParameter19 explicit TemplateParameter(std::string name) : name(std::move(name)) {}
TemplateParameterTemplateParameter20 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
27 class Class {
28 public:
Class(std::string name)29 explicit Class(std::string name) : name_(std::move(name)) {}
Class(std::vector<TemplateParameter> template_parameters,std::string name)30 Class(std::vector<TemplateParameter> template_parameters, std::string name)
31 : template_parameters_(std::move(template_parameters)),
32 name_(std::move(name)) {}
33
GetName()34 std::string GetName() const { return name_; }
GetTemplateParameters()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
53 class 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 = {})
typeParameter68 : type(std::move(type)),
69 name(std::move(name)),
70 default_value(std::move(default_value)) {}
71 };
72
Function(std::string name)73 explicit Function(std::string name)
74 : pos_(CurrentSourcePosition::Get()),
75 owning_class_(nullptr),
76 name_(std::move(name)) {}
Function(Class * owning_class,std::string 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
DefaultGetter(std::string return_type,Class * owner,std::string name)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
DefaultSetter(Class * owner,std::string name,std::string parameter_type,std::string parameter_name)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 }
HasFlag(FunctionFlag flag)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); }
FUNCTION_FLAG_LIST(ACCESSOR)120 FUNCTION_FLAG_LIST(ACCESSOR)
121 #undef ACCESSOR
122
123 void SetDescription(std::string description) {
124 description_ = std::move(description);
125 }
SetName(std::string name)126 void SetName(std::string name) { name_ = std::move(name); }
SetReturnType(std::string return_type)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 }
GetParameters()143 std::vector<Parameter> GetParameters() const { return parameters_; }
GetParameterNames()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
DEFINE_OPERATORS_FOR_FLAGS(base::Flags<Function::FunctionFlag>)177 DEFINE_OPERATORS_FOR_FLAGS(base::Flags<Function::FunctionFlag>)
178 #undef FUNCTION_FLAG_LIST
179
180 class 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
208 class IncludeGuardScope {
209 public:
IncludeGuardScope(File * file,std::string name)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;
IncludeGuardScope(IncludeGuardScope && other)215 IncludeGuardScope(IncludeGuardScope&& other) V8_NOEXCEPT : file_(nullptr),
216 name_() {
217 std::swap(file_, other.file_);
218 std::swap(name_, other.name_);
219 }
~IncludeGuardScope()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