blob: 5396cdd0c5ddf137b565e8abfa613827da87c705 [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001// Copyright 2021 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef SRC_TINT_PROGRAM_BUILDER_H_
16#define SRC_TINT_PROGRAM_BUILDER_H_
17
18#include <string>
19#include <unordered_set>
20#include <utility>
21
Ben Clayton9a6acc42022-07-27 20:50:40 +000022#include "tint/override_id.h"
23
Ryan Harrisondbc13af2022-02-21 15:19:07 +000024#include "src/tint/ast/alias.h"
25#include "src/tint/ast/array.h"
26#include "src/tint/ast/assignment_statement.h"
27#include "src/tint/ast/atomic.h"
28#include "src/tint/ast/binary_expression.h"
29#include "src/tint/ast/binding_attribute.h"
30#include "src/tint/ast/bitcast_expression.h"
31#include "src/tint/ast/bool.h"
32#include "src/tint/ast/bool_literal_expression.h"
dan sinclairb8b0c212022-10-20 22:45:50 +000033#include "src/tint/ast/break_if_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000034#include "src/tint/ast/break_statement.h"
35#include "src/tint/ast/call_expression.h"
36#include "src/tint/ast/call_statement.h"
37#include "src/tint/ast/case_statement.h"
James Pricec022ff52022-03-31 22:30:10 +000038#include "src/tint/ast/compound_assignment_statement.h"
Ben Claytone3834c42022-06-25 23:21:39 +000039#include "src/tint/ast/const.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000040#include "src/tint/ast/continue_statement.h"
41#include "src/tint/ast/depth_multisampled_texture.h"
42#include "src/tint/ast/depth_texture.h"
43#include "src/tint/ast/disable_validation_attribute.h"
44#include "src/tint/ast/discard_statement.h"
Zhaoming Jiang7098d3d2022-04-27 02:27:52 +000045#include "src/tint/ast/enable.h"
Ben Clayton7f2b8cd2022-05-18 22:41:48 +000046#include "src/tint/ast/extension.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000047#include "src/tint/ast/external_texture.h"
Zhaoming Jiang62bfd312022-05-13 12:01:11 +000048#include "src/tint/ast/f16.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000049#include "src/tint/ast/f32.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000050#include "src/tint/ast/float_literal_expression.h"
51#include "src/tint/ast/for_loop_statement.h"
52#include "src/tint/ast/i32.h"
53#include "src/tint/ast/id_attribute.h"
54#include "src/tint/ast/if_statement.h"
James Priceebe97412022-04-07 13:42:45 +000055#include "src/tint/ast/increment_decrement_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000056#include "src/tint/ast/index_accessor_expression.h"
dan sinclaird32fbe02022-10-19 00:43:41 +000057#include "src/tint/ast/int_literal_expression.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000058#include "src/tint/ast/interpolate_attribute.h"
59#include "src/tint/ast/invariant_attribute.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000060#include "src/tint/ast/let.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000061#include "src/tint/ast/loop_statement.h"
62#include "src/tint/ast/matrix.h"
63#include "src/tint/ast/member_accessor_expression.h"
64#include "src/tint/ast/module.h"
65#include "src/tint/ast/multisampled_texture.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000066#include "src/tint/ast/override.h"
67#include "src/tint/ast/parameter.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000068#include "src/tint/ast/phony_expression.h"
69#include "src/tint/ast/pointer.h"
70#include "src/tint/ast/return_statement.h"
71#include "src/tint/ast/sampled_texture.h"
72#include "src/tint/ast/sampler.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000073#include "src/tint/ast/stage_attribute.h"
Ben Claytonbfd1a812022-08-02 23:16:25 +000074#include "src/tint/ast/static_assert.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000075#include "src/tint/ast/storage_texture.h"
76#include "src/tint/ast/stride_attribute.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000077#include "src/tint/ast/struct_member_align_attribute.h"
78#include "src/tint/ast/struct_member_offset_attribute.h"
79#include "src/tint/ast/struct_member_size_attribute.h"
80#include "src/tint/ast/switch_statement.h"
81#include "src/tint/ast/type_name.h"
82#include "src/tint/ast/u32.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000083#include "src/tint/ast/unary_op_expression.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000084#include "src/tint/ast/var.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000085#include "src/tint/ast/variable_decl_statement.h"
86#include "src/tint/ast/vector.h"
87#include "src/tint/ast/void.h"
dan sinclair49d1a2d2022-06-16 12:01:27 +000088#include "src/tint/ast/while_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000089#include "src/tint/ast/workgroup_attribute.h"
dan sinclair02b466f2022-12-15 21:56:32 +000090#include "src/tint/constant/composite.h"
91#include "src/tint/constant/splat.h"
dan sinclairb53b8cf2022-12-15 16:25:31 +000092#include "src/tint/constant/value.h"
Ben Clayton0ce9ab02022-05-05 20:23:40 +000093#include "src/tint/number.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000094#include "src/tint/program.h"
95#include "src/tint/program_id.h"
dan sinclair4b1d79e2022-12-01 23:45:18 +000096#include "src/tint/sem/array_count.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000097#include "src/tint/sem/struct.h"
dan sinclair946858a2022-12-08 22:21:24 +000098#include "src/tint/type/array.h"
dan sinclaird37ecf92022-12-08 16:39:59 +000099#include "src/tint/type/bool.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000100#include "src/tint/type/depth_texture.h"
101#include "src/tint/type/external_texture.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000102#include "src/tint/type/f16.h"
103#include "src/tint/type/f32.h"
104#include "src/tint/type/i32.h"
dan sinclair0e780da2022-12-08 22:21:24 +0000105#include "src/tint/type/matrix.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000106#include "src/tint/type/multisampled_texture.h"
dan sinclair4d56b482022-12-08 17:50:50 +0000107#include "src/tint/type/pointer.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000108#include "src/tint/type/sampled_texture.h"
109#include "src/tint/type/storage_texture.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000110#include "src/tint/type/u32.h"
dan sinclair0e780da2022-12-08 22:21:24 +0000111#include "src/tint/type/vector.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000112#include "src/tint/type/void.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000113
Ben Clayton8fa6c252022-11-03 19:16:26 +0000114#ifdef CURRENTLY_IN_TINT_PUBLIC_HEADER
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000115#error "internal tint header being #included from tint.h"
116#endif
117
118// Forward declarations
Ben Claytona7230f02022-04-11 14:37:21 +0000119namespace tint {
120class CloneContext;
121} // namespace tint
dan sinclair8155b9d2022-04-07 19:10:25 +0000122namespace tint::ast {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000123class VariableDeclStatement;
dan sinclair8155b9d2022-04-07 19:10:25 +0000124} // namespace tint::ast
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000125
126namespace tint {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000127
Ben Clayton783b1692022-08-02 17:03:35 +0000128namespace detail {
129
130/// IsVectorLike<T>::value is true if T is a utils::Vector or utils::VectorRef.
131template <typename T>
132struct IsVectorLike {
133 /// Non-specialized form of IsVectorLike defaults to false
134 static constexpr bool value = false;
135};
136
137/// IsVectorLike specialization for utils::Vector
138template <typename T, size_t N>
139struct IsVectorLike<utils::Vector<T, N>> {
140 /// True for the IsVectorLike specialization of utils::Vector
141 static constexpr bool value = true;
142};
143
144/// IsVectorLike specialization for utils::VectorRef
145template <typename T>
146struct IsVectorLike<utils::VectorRef<T>> {
147 /// True for the IsVectorLike specialization of utils::VectorRef
148 static constexpr bool value = true;
149};
150} // namespace detail
151
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000152/// ProgramBuilder is a mutable builder for a Program.
153/// To construct a Program, populate the builder and then `std::move` it to a
154/// Program.
155class ProgramBuilder {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000156 /// A helper used to disable overloads if the first type in `TYPES` is a
157 /// Source. Used to avoid ambiguities in overloads that take a Source as the
158 /// first parameter and those that perfectly-forward the first argument.
159 template <typename... TYPES>
160 using DisableIfSource =
161 traits::EnableIfIsNotType<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>, Source>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000162
Ben Clayton783b1692022-08-02 17:03:35 +0000163 /// A helper used to disable overloads if the first type in `TYPES` is a utils::Vector,
164 /// utils::VectorRef or utils::VectorRef.
165 template <typename... TYPES>
166 using DisableIfVectorLike = traits::EnableIf<
167 !detail::IsVectorLike<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>::value>;
168
Ben Clayton58794ae2022-08-19 17:28:53 +0000169 /// VarOptions is a helper for accepting an arbitrary number of order independent options for
170 /// constructing an ast::Var.
171 struct VarOptions {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000172 template <typename... ARGS>
Ben Clayton58794ae2022-08-19 17:28:53 +0000173 explicit VarOptions(ARGS&&... args) {
174 (Set(std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000175 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000176 ~VarOptions();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000177
Ben Clayton58794ae2022-08-19 17:28:53 +0000178 const ast::Type* type = nullptr;
dan sinclairff7cf212022-10-03 14:05:23 +0000179 ast::AddressSpace address_space = ast::AddressSpace::kNone;
Ben Claytond2e0db32022-10-12 18:49:15 +0000180 ast::Access access = ast::Access::kUndefined;
dan sinclair6e77b472022-10-20 13:38:28 +0000181 const ast::Expression* initializer = nullptr;
Ben Clayton783b1692022-08-02 17:03:35 +0000182 utils::Vector<const ast::Attribute*, 4> attributes;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000183
dan sinclair41e4d9a2022-05-01 14:40:55 +0000184 private:
Ben Clayton58794ae2022-08-19 17:28:53 +0000185 void Set(const ast::Type* t) { type = t; }
dan sinclairff7cf212022-10-03 14:05:23 +0000186 void Set(ast::AddressSpace addr_space) { address_space = addr_space; }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000187 void Set(ast::Access ac) { access = ac; }
dan sinclair6e77b472022-10-20 13:38:28 +0000188 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton783b1692022-08-02 17:03:35 +0000189 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
Ben Clayton58794ae2022-08-19 17:28:53 +0000190 void Set(const ast::Attribute* a) { attributes.Push(a); }
191 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000192
Ben Clayton58794ae2022-08-19 17:28:53 +0000193 /// LetOptions is a helper for accepting an arbitrary number of order independent options for
194 /// constructing an ast::Let.
195 struct LetOptions {
196 template <typename... ARGS>
197 explicit LetOptions(ARGS&&... args) {
198 static constexpr bool has_init =
199 (traits::IsTypeOrDerived<std::remove_pointer_t<std::remove_reference_t<ARGS>>,
200 ast::Expression> ||
201 ...);
202 static_assert(has_init, "Let() must be constructed with an initializer expression");
203 (Set(std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000204 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000205 ~LetOptions();
206
207 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000208 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000209 utils::Vector<const ast::Attribute*, 4> attributes;
210
211 private:
212 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000213 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000214 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
215 void Set(const ast::Attribute* a) { attributes.Push(a); }
216 };
217
218 /// ConstOptions is a helper for accepting an arbitrary number of order independent options for
219 /// constructing an ast::Const.
220 struct ConstOptions {
221 template <typename... ARGS>
222 explicit ConstOptions(ARGS&&... args) {
223 static constexpr bool has_init =
224 (traits::IsTypeOrDerived<std::remove_pointer_t<std::remove_reference_t<ARGS>>,
225 ast::Expression> ||
226 ...);
227 static_assert(has_init, "Const() must be constructed with an initializer expression");
228 (Set(std::forward<ARGS>(args)), ...);
229 }
230 ~ConstOptions();
231
232 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000233 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000234 utils::Vector<const ast::Attribute*, 4> attributes;
235
236 private:
237 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000238 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000239 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
240 void Set(const ast::Attribute* a) { attributes.Push(a); }
241 };
242
243 /// OverrideOptions is a helper for accepting an arbitrary number of order independent options
244 /// for constructing an ast::Override.
245 struct OverrideOptions {
246 template <typename... ARGS>
247 explicit OverrideOptions(ARGS&&... args) {
248 (Set(std::forward<ARGS>(args)), ...);
249 }
250 ~OverrideOptions();
251
252 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000253 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000254 utils::Vector<const ast::Attribute*, 4> attributes;
255
256 private:
257 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000258 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000259 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
260 void Set(const ast::Attribute* a) { attributes.Push(a); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000261 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000262
dan sinclair41e4d9a2022-05-01 14:40:55 +0000263 public:
264 /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node>
265 using ASTNodeAllocator = utils::BlockAllocator<ast::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000266
dan sinclair41e4d9a2022-05-01 14:40:55 +0000267 /// SemNodeAllocator is an alias to BlockAllocator<sem::Node>
268 using SemNodeAllocator = utils::BlockAllocator<sem::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000269
dan sinclairb53b8cf2022-12-15 16:25:31 +0000270 /// ConstantAllocator is an alias to BlockAllocator<constant::Value>
271 using ConstantAllocator = utils::BlockAllocator<constant::Value>;
Ben Claytonaa037ac2022-06-29 19:07:30 +0000272
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000273 /// Constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000274 ProgramBuilder();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000275
dan sinclair41e4d9a2022-05-01 14:40:55 +0000276 /// Move constructor
277 /// @param rhs the builder to move
278 ProgramBuilder(ProgramBuilder&& rhs);
279
280 /// Destructor
281 virtual ~ProgramBuilder();
282
283 /// Move assignment operator
284 /// @param rhs the builder to move
285 /// @return this builder
286 ProgramBuilder& operator=(ProgramBuilder&& rhs);
287
288 /// Wrap returns a new ProgramBuilder wrapping the Program `program` without
289 /// making a deep clone of the Program contents.
290 /// ProgramBuilder returned by Wrap() is intended to temporarily extend an
291 /// existing immutable program.
292 /// As the returned ProgramBuilder wraps `program`, `program` must not be
293 /// destructed or assigned while using the returned ProgramBuilder.
294 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this
295 /// function. See crbug.com/tint/460.
296 /// @param program the immutable Program to wrap
297 /// @return the ProgramBuilder that wraps `program`
298 static ProgramBuilder Wrap(const Program* program);
299
300 /// @returns the unique identifier for this program
301 ProgramID ID() const { return id_; }
302
303 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000304 type::Manager& Types() {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000305 AssertNotMoved();
306 return types_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000307 }
308
dan sinclair41e4d9a2022-05-01 14:40:55 +0000309 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000310 const type::Manager& Types() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000311 AssertNotMoved();
312 return types_;
313 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000314
dan sinclair41e4d9a2022-05-01 14:40:55 +0000315 /// @returns a reference to the program's AST nodes storage
316 ASTNodeAllocator& ASTNodes() {
317 AssertNotMoved();
318 return ast_nodes_;
319 }
320
321 /// @returns a reference to the program's AST nodes storage
322 const ASTNodeAllocator& ASTNodes() const {
323 AssertNotMoved();
324 return ast_nodes_;
325 }
326
327 /// @returns a reference to the program's semantic nodes storage
328 SemNodeAllocator& SemNodes() {
329 AssertNotMoved();
330 return sem_nodes_;
331 }
332
333 /// @returns a reference to the program's semantic nodes storage
334 const SemNodeAllocator& SemNodes() const {
335 AssertNotMoved();
336 return sem_nodes_;
337 }
338
Ben Claytonaa037ac2022-06-29 19:07:30 +0000339 /// @returns a reference to the program's semantic constant storage
340 ConstantAllocator& ConstantNodes() {
341 AssertNotMoved();
342 return constant_nodes_;
343 }
344
dan sinclair41e4d9a2022-05-01 14:40:55 +0000345 /// @returns a reference to the program's AST root Module
346 ast::Module& AST() {
347 AssertNotMoved();
348 return *ast_;
349 }
350
351 /// @returns a reference to the program's AST root Module
352 const ast::Module& AST() const {
353 AssertNotMoved();
354 return *ast_;
355 }
356
357 /// @returns a reference to the program's semantic info
358 sem::Info& Sem() {
359 AssertNotMoved();
360 return sem_;
361 }
362
363 /// @returns a reference to the program's semantic info
364 const sem::Info& Sem() const {
365 AssertNotMoved();
366 return sem_;
367 }
368
369 /// @returns a reference to the program's SymbolTable
370 SymbolTable& Symbols() {
371 AssertNotMoved();
372 return symbols_;
373 }
374
375 /// @returns a reference to the program's SymbolTable
376 const SymbolTable& Symbols() const {
377 AssertNotMoved();
378 return symbols_;
379 }
380
381 /// @returns a reference to the program's diagnostics
382 diag::List& Diagnostics() {
383 AssertNotMoved();
384 return diagnostics_;
385 }
386
387 /// @returns a reference to the program's diagnostics
388 const diag::List& Diagnostics() const {
389 AssertNotMoved();
390 return diagnostics_;
391 }
392
393 /// Controls whether the Resolver will be run on the program when it is built.
394 /// @param enable the new flag value (defaults to true)
395 void SetResolveOnBuild(bool enable) { resolve_on_build_ = enable; }
396
397 /// @return true if the Resolver will be run on the program when it is
398 /// built.
399 bool ResolveOnBuild() const { return resolve_on_build_; }
400
401 /// @returns true if the program has no error diagnostics and is not missing
402 /// information
403 bool IsValid() const;
404
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000405 /// @returns the last allocated (numerically highest) AST node identifier.
406 ast::NodeID LastAllocatedNodeID() const { return last_ast_node_id_; }
407
408 /// @returns the next sequentially unique node identifier.
409 ast::NodeID AllocateNodeID() {
410 auto out = ast::NodeID{last_ast_node_id_.value + 1};
411 last_ast_node_id_ = out;
412 return out;
413 }
414
dan sinclair41e4d9a2022-05-01 14:40:55 +0000415 /// Creates a new ast::Node owned by the ProgramBuilder. When the
416 /// ProgramBuilder is destructed, the ast::Node will also be destructed.
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000417 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000418 /// @param args the arguments to pass to the type constructor
419 /// @returns the node pointer
420 template <typename T, typename... ARGS>
421 traits::EnableIfIsType<T, ast::Node>* create(const Source& source, ARGS&&... args) {
422 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000423 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000424 }
425
dan sinclair41e4d9a2022-05-01 14:40:55 +0000426 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
427 /// Source as set by the last call to SetSource() as the only argument to the
428 /// constructor.
429 /// When the ProgramBuilder is destructed, the ast::Node will also be
430 /// destructed.
431 /// @returns the node pointer
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000432 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000433 traits::EnableIfIsType<T, ast::Node>* create() {
434 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000435 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000436 }
437
dan sinclair41e4d9a2022-05-01 14:40:55 +0000438 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
439 /// Source as set by the last call to SetSource() as the first argument to the
440 /// constructor.
441 /// When the ProgramBuilder is destructed, the ast::Node will also be
442 /// destructed.
443 /// @param arg0 the first arguments to pass to the type constructor
444 /// @param args the remaining arguments to pass to the type constructor
445 /// @returns the node pointer
446 template <typename T, typename ARG0, typename... ARGS>
447 traits::EnableIf</* T is ast::Node and ARG0 is not Source */
448 traits::IsTypeOrDerived<T, ast::Node> &&
449 !traits::IsTypeOrDerived<ARG0, Source>,
450 T>*
451 create(ARG0&& arg0, ARGS&&... args) {
452 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000453 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_, std::forward<ARG0>(arg0),
dan sinclair41e4d9a2022-05-01 14:40:55 +0000454 std::forward<ARGS>(args)...);
455 }
456
457 /// Creates a new sem::Node owned by the ProgramBuilder.
Ben Claytonaa037ac2022-06-29 19:07:30 +0000458 /// When the ProgramBuilder is destructed, the sem::Node will also be destructed.
459 /// @param args the arguments to pass to the constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000460 /// @returns the node pointer
461 template <typename T, typename... ARGS>
462 traits::EnableIf<traits::IsTypeOrDerived<T, sem::Node> &&
dan sinclair5f764d82022-12-08 00:32:27 +0000463 !traits::IsTypeOrDerived<T, type::Node>,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000464 T>*
465 create(ARGS&&... args) {
466 AssertNotMoved();
467 return sem_nodes_.Create<T>(std::forward<ARGS>(args)...);
468 }
469
dan sinclairb53b8cf2022-12-15 16:25:31 +0000470 /// Creates a new constant::Value owned by the ProgramBuilder.
Ben Claytonaa037ac2022-06-29 19:07:30 +0000471 /// When the ProgramBuilder is destructed, the sem::Node will also be destructed.
472 /// @param args the arguments to pass to the constructor
473 /// @returns the node pointer
474 template <typename T, typename... ARGS>
dan sinclair02b466f2022-12-15 21:56:32 +0000475 traits::EnableIf<traits::IsTypeOrDerived<T, constant::Value> &&
476 !traits::IsTypeOrDerived<T, constant::Composite> &&
477 !traits::IsTypeOrDerived<T, constant::Splat>,
478 T>*
479 create(ARGS&&... args) {
Ben Claytonaa037ac2022-06-29 19:07:30 +0000480 AssertNotMoved();
481 return constant_nodes_.Create<T>(std::forward<ARGS>(args)...);
482 }
483
dan sinclair02b466f2022-12-15 21:56:32 +0000484 /// Constructs a constant of a vector, matrix or array type.
485 ///
486 /// Examines the element values and will return either a constant::Composite or a
487 /// constant::Splat, depending on the element types and values.
488 ///
489 /// @param type the composite type
490 /// @param elements the composite elements
491 /// @returns the node pointer
492 template <typename T>
493 traits::EnableIf<traits::IsTypeOrDerived<T, constant::Composite> ||
494 traits::IsTypeOrDerived<T, constant::Splat>,
495 const constant::Value>*
496 create(const type::Type* type, utils::VectorRef<const constant::Value*> elements) {
497 AssertNotMoved();
498 if (elements.IsEmpty()) {
499 return nullptr;
500 }
501
502 bool any_zero = false;
503 bool all_zero = true;
504 bool all_equal = true;
505 auto* first = elements.Front();
506 for (auto* el : elements) {
507 if (!el) {
508 return nullptr;
509 }
510 if (!any_zero && el->AnyZero()) {
511 any_zero = true;
512 }
513 if (all_zero && !el->AllZero()) {
514 all_zero = false;
515 }
516 if (all_equal && el != first) {
517 if (!el->Equal(first)) {
518 all_equal = false;
519 }
520 }
521 }
522 if (all_equal) {
523 return create<constant::Splat>(type, elements[0], elements.Length());
524 }
525
526 return constant_nodes_.Create<constant::Composite>(type, std::move(elements), all_zero,
527 any_zero);
528 }
529
530 /// Constructs a splat constant.
531 /// @param type the splat type
532 /// @param element the splat element
533 /// @param n the number of elements
534 /// @returns the node pointer
535 template <typename T>
536 traits::EnableIf<traits::IsTypeOrDerived<T, constant::Splat>, const constant::Splat>*
537 create(const type::Type* type, const constant::Value* element, size_t n) {
538 AssertNotMoved();
539 return constant_nodes_.Create<constant::Splat>(type, element, n);
540 }
541
Ben Clayton7c3e9a62022-12-16 15:31:19 +0000542 /// Creates a new type::Node owned by the ProgramBuilder.
543 /// When the ProgramBuilder is destructed, owned ProgramBuilder and the returned node will also
544 /// be destructed. If T derives from type::UniqueNode, then the calling create() for the same
545 /// `T` and arguments will return the same pointer.
546 /// @param args the arguments to pass to the constructor
547 /// @returns the new, or existing node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000548 template <typename T, typename... ARGS>
Ben Clayton7c3e9a62022-12-16 15:31:19 +0000549 traits::EnableIfIsType<T, type::Node>* create(ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000550 AssertNotMoved();
551 return types_.Get<T>(std::forward<ARGS>(args)...);
552 }
dan sinclair5f764d82022-12-08 00:32:27 +0000553
dan sinclair41e4d9a2022-05-01 14:40:55 +0000554 /// Marks this builder as moved, preventing any further use of the builder.
555 void MarkAsMoved();
556
557 //////////////////////////////////////////////////////////////////////////////
558 // TypesBuilder
559 //////////////////////////////////////////////////////////////////////////////
560
561 /// TypesBuilder holds basic `tint` types and methods for constructing
562 /// complex types.
563 class TypesBuilder {
564 public:
565 /// Constructor
566 /// @param builder the program builder
567 explicit TypesBuilder(ProgramBuilder* builder);
568
569 /// @return the tint AST type for the C type `T`.
570 template <typename T>
571 const ast::Type* Of() const {
572 return CToAST<T>::get(this);
573 }
574
575 /// @returns a boolean type
576 const ast::Bool* bool_() const { return builder->create<ast::Bool>(); }
577
578 /// @param source the Source of the node
579 /// @returns a boolean type
580 const ast::Bool* bool_(const Source& source) const {
581 return builder->create<ast::Bool>(source);
582 }
583
Zhaoming Jiang62bfd312022-05-13 12:01:11 +0000584 /// @returns a f16 type
585 const ast::F16* f16() const { return builder->create<ast::F16>(); }
586
587 /// @param source the Source of the node
588 /// @returns a f16 type
589 const ast::F16* f16(const Source& source) const {
590 return builder->create<ast::F16>(source);
591 }
592
dan sinclair41e4d9a2022-05-01 14:40:55 +0000593 /// @returns a f32 type
594 const ast::F32* f32() const { return builder->create<ast::F32>(); }
595
596 /// @param source the Source of the node
597 /// @returns a f32 type
598 const ast::F32* f32(const Source& source) const {
599 return builder->create<ast::F32>(source);
600 }
601
602 /// @returns a i32 type
603 const ast::I32* i32() const { return builder->create<ast::I32>(); }
604
605 /// @param source the Source of the node
606 /// @returns a i32 type
607 const ast::I32* i32(const Source& source) const {
608 return builder->create<ast::I32>(source);
609 }
610
611 /// @returns a u32 type
612 const ast::U32* u32() const { return builder->create<ast::U32>(); }
613
614 /// @param source the Source of the node
615 /// @returns a u32 type
616 const ast::U32* u32(const Source& source) const {
617 return builder->create<ast::U32>(source);
618 }
619
620 /// @returns a void type
621 const ast::Void* void_() const { return builder->create<ast::Void>(); }
622
623 /// @param source the Source of the node
624 /// @returns a void type
625 const ast::Void* void_(const Source& source) const {
626 return builder->create<ast::Void>(source);
627 }
628
629 /// @param type vector subtype
630 /// @param n vector width in elements
631 /// @return the tint AST type for a `n`-element vector of `type`.
632 const ast::Vector* vec(const ast::Type* type, uint32_t n) const {
633 return builder->create<ast::Vector>(type, n);
634 }
635
636 /// @param source the Source of the node
637 /// @param type vector subtype
638 /// @param n vector width in elements
639 /// @return the tint AST type for a `n`-element vector of `type`.
640 const ast::Vector* vec(const Source& source, const ast::Type* type, uint32_t n) const {
641 return builder->create<ast::Vector>(source, type, n);
642 }
643
644 /// @param type vector subtype
645 /// @return the tint AST type for a 2-element vector of `type`.
646 const ast::Vector* vec2(const ast::Type* type) const { return vec(type, 2u); }
647
Ben Clayton6315a272022-08-01 17:18:04 +0000648 /// @param source the vector source
649 /// @param type vector subtype
650 /// @return the tint AST type for a 2-element vector of `type`.
651 const ast::Vector* vec2(const Source& source, const ast::Type* type) const {
652 return vec(source, type, 2u);
653 }
654
dan sinclair41e4d9a2022-05-01 14:40:55 +0000655 /// @param type vector subtype
656 /// @return the tint AST type for a 3-element vector of `type`.
657 const ast::Vector* vec3(const ast::Type* type) const { return vec(type, 3u); }
658
Ben Clayton6315a272022-08-01 17:18:04 +0000659 /// @param source the vector source
660 /// @param type vector subtype
661 /// @return the tint AST type for a 3-element vector of `type`.
662 const ast::Vector* vec3(const Source& source, const ast::Type* type) const {
663 return vec(source, type, 3u);
664 }
665
dan sinclair41e4d9a2022-05-01 14:40:55 +0000666 /// @param type vector subtype
667 /// @return the tint AST type for a 4-element vector of `type`.
668 const ast::Vector* vec4(const ast::Type* type) const { return vec(type, 4u); }
669
Ben Clayton6315a272022-08-01 17:18:04 +0000670 /// @param source the vector source
671 /// @param type vector subtype
672 /// @return the tint AST type for a 4-element vector of `type`.
673 const ast::Vector* vec4(const Source& source, const ast::Type* type) const {
674 return vec(source, type, 4u);
675 }
676
dan sinclair41e4d9a2022-05-01 14:40:55 +0000677 /// @param n vector width in elements
678 /// @return the tint AST type for a `n`-element vector of `type`.
679 template <typename T>
680 const ast::Vector* vec(uint32_t n) const {
681 return vec(Of<T>(), n);
682 }
683
684 /// @return the tint AST type for a 2-element vector of the C type `T`.
685 template <typename T>
686 const ast::Vector* vec2() const {
687 return vec2(Of<T>());
688 }
689
Ben Clayton6315a272022-08-01 17:18:04 +0000690 /// @param source the Source of the node
691 /// @return the tint AST type for a 2-element vector of the C type `T`.
692 template <typename T>
693 const ast::Vector* vec2(const Source& source) const {
694 return vec2(source, Of<T>());
695 }
696
dan sinclair41e4d9a2022-05-01 14:40:55 +0000697 /// @return the tint AST type for a 3-element vector of the C type `T`.
698 template <typename T>
699 const ast::Vector* vec3() const {
700 return vec3(Of<T>());
701 }
702
Ben Clayton6315a272022-08-01 17:18:04 +0000703 /// @param source the Source of the node
704 /// @return the tint AST type for a 3-element vector of the C type `T`.
705 template <typename T>
706 const ast::Vector* vec3(const Source& source) const {
707 return vec3(source, Of<T>());
708 }
709
dan sinclair41e4d9a2022-05-01 14:40:55 +0000710 /// @return the tint AST type for a 4-element vector of the C type `T`.
711 template <typename T>
712 const ast::Vector* vec4() const {
713 return vec4(Of<T>());
714 }
715
Ben Clayton6315a272022-08-01 17:18:04 +0000716 /// @param source the Source of the node
717 /// @return the tint AST type for a 4-element vector of the C type `T`.
718 template <typename T>
719 const ast::Vector* vec4(const Source& source) const {
720 return vec4(source, Of<T>());
721 }
722
dan sinclair41e4d9a2022-05-01 14:40:55 +0000723 /// @param type matrix subtype
724 /// @param columns number of columns for the matrix
725 /// @param rows number of rows for the matrix
726 /// @return the tint AST type for a matrix of `type`
727 const ast::Matrix* mat(const ast::Type* type, uint32_t columns, uint32_t rows) const {
728 return builder->create<ast::Matrix>(type, rows, columns);
729 }
730
731 /// @param source the Source of the node
732 /// @param type matrix subtype
733 /// @param columns number of columns for the matrix
734 /// @param rows number of rows for the matrix
735 /// @return the tint AST type for a matrix of `type`
736 const ast::Matrix* mat(const Source& source,
737 const ast::Type* type,
738 uint32_t columns,
739 uint32_t rows) const {
740 return builder->create<ast::Matrix>(source, type, rows, columns);
741 }
742
743 /// @param type matrix subtype
744 /// @return the tint AST type for a 2x3 matrix of `type`.
745 const ast::Matrix* mat2x2(const ast::Type* type) const { return mat(type, 2u, 2u); }
746
747 /// @param type matrix subtype
748 /// @return the tint AST type for a 2x3 matrix of `type`.
749 const ast::Matrix* mat2x3(const ast::Type* type) const { return mat(type, 2u, 3u); }
750
751 /// @param type matrix subtype
752 /// @return the tint AST type for a 2x4 matrix of `type`.
753 const ast::Matrix* mat2x4(const ast::Type* type) const { return mat(type, 2u, 4u); }
754
755 /// @param type matrix subtype
756 /// @return the tint AST type for a 3x2 matrix of `type`.
757 const ast::Matrix* mat3x2(const ast::Type* type) const { return mat(type, 3u, 2u); }
758
759 /// @param type matrix subtype
760 /// @return the tint AST type for a 3x3 matrix of `type`.
761 const ast::Matrix* mat3x3(const ast::Type* type) const { return mat(type, 3u, 3u); }
762
763 /// @param type matrix subtype
764 /// @return the tint AST type for a 3x4 matrix of `type`.
765 const ast::Matrix* mat3x4(const ast::Type* type) const { return mat(type, 3u, 4u); }
766
767 /// @param type matrix subtype
768 /// @return the tint AST type for a 4x2 matrix of `type`.
769 const ast::Matrix* mat4x2(const ast::Type* type) const { return mat(type, 4u, 2u); }
770
771 /// @param type matrix subtype
772 /// @return the tint AST type for a 4x3 matrix of `type`.
773 const ast::Matrix* mat4x3(const ast::Type* type) const { return mat(type, 4u, 3u); }
774
775 /// @param type matrix subtype
776 /// @return the tint AST type for a 4x4 matrix of `type`.
777 const ast::Matrix* mat4x4(const ast::Type* type) const { return mat(type, 4u, 4u); }
778
779 /// @param columns number of columns for the matrix
780 /// @param rows number of rows for the matrix
781 /// @return the tint AST type for a matrix of `type`
782 template <typename T>
783 const ast::Matrix* mat(uint32_t columns, uint32_t rows) const {
784 return mat(Of<T>(), columns, rows);
785 }
786
787 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
788 template <typename T>
789 const ast::Matrix* mat2x2() const {
790 return mat2x2(Of<T>());
791 }
792
793 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
794 template <typename T>
795 const ast::Matrix* mat2x3() const {
796 return mat2x3(Of<T>());
797 }
798
799 /// @return the tint AST type for a 2x4 matrix of the C type `T`.
800 template <typename T>
801 const ast::Matrix* mat2x4() const {
802 return mat2x4(Of<T>());
803 }
804
805 /// @return the tint AST type for a 3x2 matrix of the C type `T`.
806 template <typename T>
807 const ast::Matrix* mat3x2() const {
808 return mat3x2(Of<T>());
809 }
810
811 /// @return the tint AST type for a 3x3 matrix of the C type `T`.
812 template <typename T>
813 const ast::Matrix* mat3x3() const {
814 return mat3x3(Of<T>());
815 }
816
817 /// @return the tint AST type for a 3x4 matrix of the C type `T`.
818 template <typename T>
819 const ast::Matrix* mat3x4() const {
820 return mat3x4(Of<T>());
821 }
822
823 /// @return the tint AST type for a 4x2 matrix of the C type `T`.
824 template <typename T>
825 const ast::Matrix* mat4x2() const {
826 return mat4x2(Of<T>());
827 }
828
829 /// @return the tint AST type for a 4x3 matrix of the C type `T`.
830 template <typename T>
831 const ast::Matrix* mat4x3() const {
832 return mat4x3(Of<T>());
833 }
834
835 /// @return the tint AST type for a 4x4 matrix of the C type `T`.
836 template <typename T>
837 const ast::Matrix* mat4x4() const {
838 return mat4x4(Of<T>());
839 }
840
841 /// @param subtype the array element type
842 /// @param n the array size. nullptr represents a runtime-array
843 /// @param attrs the optional attributes for the array
844 /// @return the tint AST type for a array of size `n` of type `T`
845 template <typename EXPR = ast::Expression*>
Ben Clayton783b1692022-08-02 17:03:35 +0000846 const ast::Array* array(
847 const ast::Type* subtype,
848 EXPR&& n = nullptr,
849 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000850 return builder->create<ast::Array>(subtype, builder->Expr(std::forward<EXPR>(n)),
Ben Clayton783b1692022-08-02 17:03:35 +0000851 std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000852 }
853
854 /// @param source the Source of the node
855 /// @param subtype the array element type
856 /// @param n the array size. nullptr represents a runtime-array
857 /// @param attrs the optional attributes for the array
858 /// @return the tint AST type for a array of size `n` of type `T`
859 template <typename EXPR = ast::Expression*>
Ben Clayton783b1692022-08-02 17:03:35 +0000860 const ast::Array* array(
861 const Source& source,
862 const ast::Type* subtype,
863 EXPR&& n = nullptr,
864 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
865 return builder->create<ast::Array>(
866 source, subtype, builder->Expr(std::forward<EXPR>(n)), std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000867 }
868
869 /// @param subtype the array element type
870 /// @param n the array size. nullptr represents a runtime-array
871 /// @param stride the array stride. 0 represents implicit stride
872 /// @return the tint AST type for a array of size `n` of type `T`
873 template <typename EXPR>
874 const ast::Array* array(const ast::Type* subtype, EXPR&& n, uint32_t stride) const {
Ben Clayton783b1692022-08-02 17:03:35 +0000875 utils::Vector<const ast::Attribute*, 2> attrs;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000876 if (stride) {
Ben Clayton783b1692022-08-02 17:03:35 +0000877 attrs.Push(builder->create<ast::StrideAttribute>(stride));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000878 }
879 return array(subtype, std::forward<EXPR>(n), std::move(attrs));
880 }
881
882 /// @param source the Source of the node
883 /// @param subtype the array element type
884 /// @param n the array size. nullptr represents a runtime-array
885 /// @param stride the array stride. 0 represents implicit stride
886 /// @return the tint AST type for a array of size `n` of type `T`
887 template <typename EXPR>
888 const ast::Array* array(const Source& source,
889 const ast::Type* subtype,
890 EXPR&& n,
891 uint32_t stride) const {
Ben Clayton783b1692022-08-02 17:03:35 +0000892 utils::Vector<const ast::Attribute*, 2> attrs;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000893 if (stride) {
Ben Clayton783b1692022-08-02 17:03:35 +0000894 attrs.Push(builder->create<ast::StrideAttribute>(stride));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000895 }
896 return array(source, subtype, std::forward<EXPR>(n), std::move(attrs));
897 }
898
899 /// @return the tint AST type for a runtime-sized array of type `T`
900 template <typename T>
901 const ast::Array* array() const {
902 return array(Of<T>(), nullptr);
903 }
904
905 /// @return the tint AST type for an array of size `N` of type `T`
906 template <typename T, int N>
907 const ast::Array* array() const {
Ben Clayton0ce9ab02022-05-05 20:23:40 +0000908 return array(Of<T>(), builder->Expr(tint::u32(N)));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000909 }
910
911 /// @param stride the array stride
912 /// @return the tint AST type for a runtime-sized array of type `T`
913 template <typename T>
914 const ast::Array* array(uint32_t stride) const {
915 return array(Of<T>(), nullptr, stride);
916 }
917
918 /// @param stride the array stride
919 /// @return the tint AST type for an array of size `N` of type `T`
920 template <typename T, int N>
921 const ast::Array* array(uint32_t stride) const {
Ben Clayton0ce9ab02022-05-05 20:23:40 +0000922 return array(Of<T>(), builder->Expr(tint::u32(N)), stride);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000923 }
924
925 /// Creates a type name
926 /// @param name the name
927 /// @returns the type name
928 template <typename NAME>
929 const ast::TypeName* type_name(NAME&& name) const {
930 return builder->create<ast::TypeName>(builder->Sym(std::forward<NAME>(name)));
931 }
932
933 /// Creates a type name
934 /// @param source the Source of the node
935 /// @param name the name
936 /// @returns the type name
937 template <typename NAME>
938 const ast::TypeName* type_name(const Source& source, NAME&& name) const {
939 return builder->create<ast::TypeName>(source, builder->Sym(std::forward<NAME>(name)));
940 }
941
942 /// Creates an alias type
943 /// @param name the alias name
944 /// @param type the alias type
945 /// @returns the alias pointer
946 template <typename NAME>
947 const ast::Alias* alias(NAME&& name, const ast::Type* type) const {
948 auto sym = builder->Sym(std::forward<NAME>(name));
949 return builder->create<ast::Alias>(sym, type);
950 }
951
952 /// Creates an alias type
953 /// @param source the Source of the node
954 /// @param name the alias name
955 /// @param type the alias type
956 /// @returns the alias pointer
957 template <typename NAME>
958 const ast::Alias* alias(const Source& source, NAME&& name, const ast::Type* type) const {
959 auto sym = builder->Sym(std::forward<NAME>(name));
960 return builder->create<ast::Alias>(source, sym, type);
961 }
962
963 /// @param type the type of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000964 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000965 /// @param access the optional access control of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000966 /// @return the pointer to `type` with the given ast::AddressSpace
dan sinclair41e4d9a2022-05-01 14:40:55 +0000967 const ast::Pointer* pointer(const ast::Type* type,
dan sinclairff7cf212022-10-03 14:05:23 +0000968 ast::AddressSpace address_space,
Ben Claytond2e0db32022-10-12 18:49:15 +0000969 ast::Access access = ast::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000970 return builder->create<ast::Pointer>(type, address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000971 }
972
973 /// @param source the Source of the node
974 /// @param type the type of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000975 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000976 /// @param access the optional access control of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000977 /// @return the pointer to `type` with the given ast::AddressSpace
dan sinclair41e4d9a2022-05-01 14:40:55 +0000978 const ast::Pointer* pointer(const Source& source,
979 const ast::Type* type,
dan sinclairff7cf212022-10-03 14:05:23 +0000980 ast::AddressSpace address_space,
Ben Claytond2e0db32022-10-12 18:49:15 +0000981 ast::Access access = ast::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000982 return builder->create<ast::Pointer>(source, type, address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000983 }
984
dan sinclairff7cf212022-10-03 14:05:23 +0000985 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000986 /// @param access the optional access control of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000987 /// @return the pointer to type `T` with the given ast::AddressSpace.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000988 template <typename T>
dan sinclairff7cf212022-10-03 14:05:23 +0000989 const ast::Pointer* pointer(ast::AddressSpace address_space,
Ben Claytond2e0db32022-10-12 18:49:15 +0000990 ast::Access access = ast::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000991 return pointer(Of<T>(), address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000992 }
993
994 /// @param source the Source of the node
dan sinclairff7cf212022-10-03 14:05:23 +0000995 /// @param address_space the address space of the pointer
Ben Claytoncfe07a12022-07-15 13:01:49 +0000996 /// @param access the optional access control of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000997 /// @return the pointer to type `T` with the given ast::AddressSpace.
Ben Claytoncfe07a12022-07-15 13:01:49 +0000998 template <typename T>
999 const ast::Pointer* pointer(const Source& source,
dan sinclairff7cf212022-10-03 14:05:23 +00001000 ast::AddressSpace address_space,
Ben Claytond2e0db32022-10-12 18:49:15 +00001001 ast::Access access = ast::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +00001002 return pointer(source, Of<T>(), address_space, access);
Ben Claytoncfe07a12022-07-15 13:01:49 +00001003 }
1004
1005 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +00001006 /// @param type the type of the atomic
1007 /// @return the atomic to `type`
1008 const ast::Atomic* atomic(const Source& source, const ast::Type* type) const {
1009 return builder->create<ast::Atomic>(source, type);
1010 }
1011
1012 /// @param type the type of the atomic
1013 /// @return the atomic to `type`
1014 const ast::Atomic* atomic(const ast::Type* type) const {
1015 return builder->create<ast::Atomic>(type);
1016 }
1017
1018 /// @return the atomic to type `T`
1019 template <typename T>
1020 const ast::Atomic* atomic() const {
1021 return atomic(Of<T>());
1022 }
1023
1024 /// @param kind the kind of sampler
1025 /// @returns the sampler
1026 const ast::Sampler* sampler(ast::SamplerKind kind) const {
1027 return builder->create<ast::Sampler>(kind);
1028 }
1029
1030 /// @param source the Source of the node
1031 /// @param kind the kind of sampler
1032 /// @returns the sampler
1033 const ast::Sampler* sampler(const Source& source, ast::SamplerKind kind) const {
1034 return builder->create<ast::Sampler>(source, kind);
1035 }
1036
1037 /// @param dims the dimensionality of the texture
1038 /// @returns the depth texture
1039 const ast::DepthTexture* depth_texture(ast::TextureDimension dims) const {
1040 return builder->create<ast::DepthTexture>(dims);
1041 }
1042
1043 /// @param source the Source of the node
1044 /// @param dims the dimensionality of the texture
1045 /// @returns the depth texture
1046 const ast::DepthTexture* depth_texture(const Source& source,
1047 ast::TextureDimension dims) const {
1048 return builder->create<ast::DepthTexture>(source, dims);
1049 }
1050
1051 /// @param dims the dimensionality of the texture
1052 /// @returns the multisampled depth texture
1053 const ast::DepthMultisampledTexture* depth_multisampled_texture(
1054 ast::TextureDimension dims) const {
1055 return builder->create<ast::DepthMultisampledTexture>(dims);
1056 }
1057
1058 /// @param source the Source of the node
1059 /// @param dims the dimensionality of the texture
1060 /// @returns the multisampled depth texture
1061 const ast::DepthMultisampledTexture* depth_multisampled_texture(
1062 const Source& source,
1063 ast::TextureDimension dims) const {
1064 return builder->create<ast::DepthMultisampledTexture>(source, dims);
1065 }
1066
1067 /// @param dims the dimensionality of the texture
1068 /// @param subtype the texture subtype.
1069 /// @returns the sampled texture
1070 const ast::SampledTexture* sampled_texture(ast::TextureDimension dims,
1071 const ast::Type* subtype) const {
1072 return builder->create<ast::SampledTexture>(dims, subtype);
1073 }
1074
1075 /// @param source the Source of the node
1076 /// @param dims the dimensionality of the texture
1077 /// @param subtype the texture subtype.
1078 /// @returns the sampled texture
1079 const ast::SampledTexture* sampled_texture(const Source& source,
1080 ast::TextureDimension dims,
1081 const ast::Type* subtype) const {
1082 return builder->create<ast::SampledTexture>(source, dims, subtype);
1083 }
1084
1085 /// @param dims the dimensionality of the texture
1086 /// @param subtype the texture subtype.
1087 /// @returns the multisampled texture
1088 const ast::MultisampledTexture* multisampled_texture(ast::TextureDimension dims,
1089 const ast::Type* subtype) const {
1090 return builder->create<ast::MultisampledTexture>(dims, subtype);
1091 }
1092
1093 /// @param source the Source of the node
1094 /// @param dims the dimensionality of the texture
1095 /// @param subtype the texture subtype.
1096 /// @returns the multisampled texture
1097 const ast::MultisampledTexture* multisampled_texture(const Source& source,
1098 ast::TextureDimension dims,
1099 const ast::Type* subtype) const {
1100 return builder->create<ast::MultisampledTexture>(source, dims, subtype);
1101 }
1102
1103 /// @param dims the dimensionality of the texture
1104 /// @param format the texel format of the texture
1105 /// @param access the access control of the texture
1106 /// @returns the storage texture
1107 const ast::StorageTexture* storage_texture(ast::TextureDimension dims,
1108 ast::TexelFormat format,
1109 ast::Access access) const {
1110 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
1111 return builder->create<ast::StorageTexture>(dims, format, subtype, access);
1112 }
1113
1114 /// @param source the Source of the node
1115 /// @param dims the dimensionality of the texture
1116 /// @param format the texel format of the texture
1117 /// @param access the access control of the texture
1118 /// @returns the storage texture
1119 const ast::StorageTexture* storage_texture(const Source& source,
1120 ast::TextureDimension dims,
1121 ast::TexelFormat format,
1122 ast::Access access) const {
1123 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
1124 return builder->create<ast::StorageTexture>(source, dims, format, subtype, access);
1125 }
1126
1127 /// @returns the external texture
1128 const ast::ExternalTexture* external_texture() const {
1129 return builder->create<ast::ExternalTexture>();
1130 }
1131
1132 /// @param source the Source of the node
1133 /// @returns the external texture
1134 const ast::ExternalTexture* external_texture(const Source& source) const {
1135 return builder->create<ast::ExternalTexture>(source);
1136 }
1137
1138 /// Constructs a TypeName for the type declaration.
1139 /// @param type the type
1140 /// @return either type or a pointer to a new ast::TypeName
1141 const ast::TypeName* Of(const ast::TypeDecl* type) const;
1142
1143 /// The ProgramBuilder
1144 ProgramBuilder* const builder;
1145
1146 private:
1147 /// CToAST<T> is specialized for various `T` types and each specialization
1148 /// contains a single static `get()` method for obtaining the corresponding
1149 /// AST type for the C type `T`.
1150 /// `get()` has the signature:
1151 /// `static const ast::Type* get(Types* t)`
1152 template <typename T>
1153 struct CToAST {};
1154 };
1155
1156 //////////////////////////////////////////////////////////////////////////////
1157 // AST helper methods
1158 //////////////////////////////////////////////////////////////////////////////
1159
1160 /// @return a new unnamed symbol
1161 Symbol Sym() { return Symbols().New(); }
1162
1163 /// @param name the symbol string
1164 /// @return a Symbol with the given name
1165 Symbol Sym(const std::string& name) { return Symbols().Register(name); }
1166
1167 /// @param sym the symbol
1168 /// @return `sym`
1169 Symbol Sym(Symbol sym) { return sym; }
1170
1171 /// @param expr the expression
1172 /// @return expr
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001173 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001174 traits::EnableIfIsType<T, ast::Expression>* Expr(T* expr) {
1175 return expr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001176 }
1177
dan sinclair41e4d9a2022-05-01 14:40:55 +00001178 /// Passthrough for nullptr
1179 /// @return nullptr
1180 const ast::IdentifierExpression* Expr(std::nullptr_t) { return nullptr; }
1181
1182 /// @param source the source information
1183 /// @param symbol the identifier symbol
1184 /// @return an ast::IdentifierExpression with the given symbol
1185 const ast::IdentifierExpression* Expr(const Source& source, Symbol symbol) {
1186 return create<ast::IdentifierExpression>(source, symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001187 }
1188
dan sinclair41e4d9a2022-05-01 14:40:55 +00001189 /// @param symbol the identifier symbol
1190 /// @return an ast::IdentifierExpression with the given symbol
1191 const ast::IdentifierExpression* Expr(Symbol symbol) {
1192 return create<ast::IdentifierExpression>(symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001193 }
1194
dan sinclair41e4d9a2022-05-01 14:40:55 +00001195 /// @param source the source information
1196 /// @param variable the AST variable
1197 /// @return an ast::IdentifierExpression with the variable's symbol
1198 const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) {
1199 return create<ast::IdentifierExpression>(source, variable->symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001200 }
1201
dan sinclair41e4d9a2022-05-01 14:40:55 +00001202 /// @param variable the AST variable
1203 /// @return an ast::IdentifierExpression with the variable's symbol
1204 const ast::IdentifierExpression* Expr(const ast::Variable* variable) {
1205 return create<ast::IdentifierExpression>(variable->symbol);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001206 }
1207
dan sinclair41e4d9a2022-05-01 14:40:55 +00001208 /// @param source the source information
1209 /// @param name the identifier name
1210 /// @return an ast::IdentifierExpression with the given name
1211 const ast::IdentifierExpression* Expr(const Source& source, const char* name) {
1212 return create<ast::IdentifierExpression>(source, Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001213 }
1214
dan sinclair41e4d9a2022-05-01 14:40:55 +00001215 /// @param name the identifier name
1216 /// @return an ast::IdentifierExpression with the given name
1217 const ast::IdentifierExpression* Expr(const char* name) {
1218 return create<ast::IdentifierExpression>(Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001219 }
1220
dan sinclair41e4d9a2022-05-01 14:40:55 +00001221 /// @param source the source information
1222 /// @param name the identifier name
1223 /// @return an ast::IdentifierExpression with the given name
1224 const ast::IdentifierExpression* Expr(const Source& source, const std::string& name) {
1225 return create<ast::IdentifierExpression>(source, Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001226 }
1227
dan sinclair41e4d9a2022-05-01 14:40:55 +00001228 /// @param name the identifier name
1229 /// @return an ast::IdentifierExpression with the given name
1230 const ast::IdentifierExpression* Expr(const std::string& name) {
1231 return create<ast::IdentifierExpression>(Symbols().Register(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001232 }
1233
dan sinclair41e4d9a2022-05-01 14:40:55 +00001234 /// @param source the source information
1235 /// @param value the boolean value
1236 /// @return a Scalar constructor for the given value
Ben Clayton17fa42d2022-05-10 15:29:14 +00001237 template <typename BOOL>
1238 std::enable_if_t<std::is_same_v<BOOL, bool>, const ast::BoolLiteralExpression*> Expr(
1239 const Source& source,
1240 BOOL value) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001241 return create<ast::BoolLiteralExpression>(source, value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001242 }
1243
dan sinclair41e4d9a2022-05-01 14:40:55 +00001244 /// @param value the boolean value
1245 /// @return a Scalar constructor for the given value
Ben Clayton17fa42d2022-05-10 15:29:14 +00001246 template <typename BOOL>
1247 std::enable_if_t<std::is_same_v<BOOL, bool>, const ast::BoolLiteralExpression*> Expr(
1248 BOOL value) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001249 return create<ast::BoolLiteralExpression>(value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001250 }
1251
dan sinclair41e4d9a2022-05-01 14:40:55 +00001252 /// @param source the source information
1253 /// @param value the float value
Ben Clayton41285aa2022-05-10 14:55:34 +00001254 /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value
1255 const ast::FloatLiteralExpression* Expr(const Source& source, f32 value) {
1256 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1257 ast::FloatLiteralExpression::Suffix::kF);
1258 }
1259
1260 /// @param value the float value
1261 /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value
dan sinclair41e4d9a2022-05-01 14:40:55 +00001262 const ast::FloatLiteralExpression* Expr(f32 value) {
Ben Clayton41285aa2022-05-10 14:55:34 +00001263 return create<ast::FloatLiteralExpression>(static_cast<double>(value.value),
1264 ast::FloatLiteralExpression::Suffix::kF);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001265 }
1266
dan sinclair41e4d9a2022-05-01 14:40:55 +00001267 /// @param source the source information
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00001268 /// @param value the float value
1269 /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
1270 const ast::FloatLiteralExpression* Expr(const Source& source, f16 value) {
1271 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1272 ast::FloatLiteralExpression::Suffix::kH);
1273 }
1274
1275 /// @param value the float value
1276 /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
1277 const ast::FloatLiteralExpression* Expr(f16 value) {
1278 return create<ast::FloatLiteralExpression>(static_cast<double>(value.value),
1279 ast::FloatLiteralExpression::Suffix::kH);
1280 }
1281
1282 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001283 /// @param value the integer value
Ben Clayton508e4a52022-05-10 22:08:04 +00001284 /// @return an unsuffixed IntLiteralExpression for the AInt value
1285 const ast::IntLiteralExpression* Expr(const Source& source, AInt value) {
1286 return create<ast::IntLiteralExpression>(source, value,
1287 ast::IntLiteralExpression::Suffix::kNone);
1288 }
1289
1290 /// @param value the integer value
1291 /// @return an unsuffixed IntLiteralExpression for the AInt value
1292 const ast::IntLiteralExpression* Expr(AInt value) {
1293 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kNone);
1294 }
1295
1296 /// @param source the source information
1297 /// @param value the integer value
1298 /// @return an unsuffixed FloatLiteralExpression for the AFloat value
1299 const ast::FloatLiteralExpression* Expr(const Source& source, AFloat value) {
1300 return create<ast::FloatLiteralExpression>(source, value.value,
1301 ast::FloatLiteralExpression::Suffix::kNone);
1302 }
1303
1304 /// @param value the integer value
1305 /// @return an unsuffixed FloatLiteralExpression for the AFloat value
1306 const ast::FloatLiteralExpression* Expr(AFloat value) {
1307 return create<ast::FloatLiteralExpression>(value.value,
1308 ast::FloatLiteralExpression::Suffix::kNone);
1309 }
1310
1311 /// @param source the source information
1312 /// @param value the integer value
Ben Clayton41285aa2022-05-10 14:55:34 +00001313 /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001314 const ast::IntLiteralExpression* Expr(const Source& source, i32 value) {
1315 return create<ast::IntLiteralExpression>(source, value,
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001316 ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001317 }
1318
dan sinclair41e4d9a2022-05-01 14:40:55 +00001319 /// @param value the integer value
Ben Clayton41285aa2022-05-10 14:55:34 +00001320 /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001321 const ast::IntLiteralExpression* Expr(i32 value) {
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001322 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001323 }
1324
dan sinclair41e4d9a2022-05-01 14:40:55 +00001325 /// @param source the source information
1326 /// @param value the unsigned int value
Ben Clayton41285aa2022-05-10 14:55:34 +00001327 /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001328 const ast::IntLiteralExpression* Expr(const Source& source, u32 value) {
1329 return create<ast::IntLiteralExpression>(source, value,
1330 ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001331 }
1332
dan sinclair41e4d9a2022-05-01 14:40:55 +00001333 /// @param value the unsigned int value
Ben Clayton41285aa2022-05-10 14:55:34 +00001334 /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001335 const ast::IntLiteralExpression* Expr(u32 value) {
1336 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001337 }
1338
dan sinclair41e4d9a2022-05-01 14:40:55 +00001339 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
1340 /// `list`.
1341 /// @param list the list to append too
1342 /// @param arg the arg to create
Ben Clayton783b1692022-08-02 17:03:35 +00001343 template <size_t N, typename ARG>
1344 void Append(utils::Vector<const ast::Expression*, N>& list, ARG&& arg) {
1345 list.Push(Expr(std::forward<ARG>(arg)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001346 }
1347
dan sinclair41e4d9a2022-05-01 14:40:55 +00001348 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
1349 /// then appends them to `list`.
1350 /// @param list the list to append too
1351 /// @param arg0 the first argument
1352 /// @param args the rest of the arguments
Ben Clayton783b1692022-08-02 17:03:35 +00001353 template <size_t N, typename ARG0, typename... ARGS>
1354 void Append(utils::Vector<const ast::Expression*, N>& list, ARG0&& arg0, ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001355 Append(list, std::forward<ARG0>(arg0));
1356 Append(list, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001357 }
1358
Ben Clayton783b1692022-08-02 17:03:35 +00001359 /// @return utils::EmptyType
1360 utils::EmptyType ExprList() { return utils::Empty; }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001361
1362 /// @param args the list of expressions
1363 /// @return the list of expressions converted to `ast::Expression`s using
1364 /// `Expr()`,
Ben Clayton783b1692022-08-02 17:03:35 +00001365 template <typename... ARGS, typename = DisableIfVectorLike<ARGS...>>
1366 auto ExprList(ARGS&&... args) {
1367 utils::Vector<const ast::Expression*, sizeof...(ARGS)> list;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001368 Append(list, std::forward<ARGS>(args)...);
1369 return list;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001370 }
1371
dan sinclair41e4d9a2022-05-01 14:40:55 +00001372 /// @param list the list of expressions
1373 /// @return `list`
Ben Clayton783b1692022-08-02 17:03:35 +00001374 template <typename T, size_t N>
1375 utils::Vector<T, N> ExprList(utils::Vector<T, N>&& list) {
1376 return std::move(list);
1377 }
1378
1379 /// @param list the list of expressions
1380 /// @return `list`
1381 utils::VectorRef<const ast::Expression*> ExprList(
1382 utils::VectorRef<const ast::Expression*> list) {
1383 return list;
1384 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001385
1386 /// @param args the arguments for the type constructor
1387 /// @return an `ast::CallExpression` of type `ty`, with the values
1388 /// of `args` converted to `ast::Expression`s using `Expr()`
1389 template <typename T, typename... ARGS>
1390 const ast::CallExpression* Construct(ARGS&&... args) {
1391 return Construct(ty.Of<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001392 }
1393
dan sinclair41e4d9a2022-05-01 14:40:55 +00001394 /// @param type the type to construct
1395 /// @param args the arguments for the constructor
1396 /// @return an `ast::CallExpression` of `type` constructed with the
1397 /// values `args`.
1398 template <typename... ARGS>
1399 const ast::CallExpression* Construct(const ast::Type* type, ARGS&&... args) {
1400 return Construct(source_, type, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001401 }
1402
dan sinclair41e4d9a2022-05-01 14:40:55 +00001403 /// @param source the source information
1404 /// @param type the type to construct
1405 /// @param args the arguments for the constructor
1406 /// @return an `ast::CallExpression` of `type` constructed with the
1407 /// values `args`.
1408 template <typename... ARGS>
1409 const ast::CallExpression* Construct(const Source& source,
1410 const ast::Type* type,
1411 ARGS&&... args) {
1412 return create<ast::CallExpression>(source, type, ExprList(std::forward<ARGS>(args)...));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001413 }
1414
dan sinclair41e4d9a2022-05-01 14:40:55 +00001415 /// @param expr the expression for the bitcast
1416 /// @return an `ast::BitcastExpression` of type `ty`, with the values of
1417 /// `expr` converted to `ast::Expression`s using `Expr()`
1418 template <typename T, typename EXPR>
1419 const ast::BitcastExpression* Bitcast(EXPR&& expr) {
1420 return Bitcast(ty.Of<T>(), std::forward<EXPR>(expr));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001421 }
1422
dan sinclair41e4d9a2022-05-01 14:40:55 +00001423 /// @param type the type to cast to
1424 /// @param expr the expression for the bitcast
1425 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1426 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001427 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001428 const ast::BitcastExpression* Bitcast(const ast::Type* type, EXPR&& expr) {
1429 return create<ast::BitcastExpression>(type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001430 }
1431
dan sinclair41e4d9a2022-05-01 14:40:55 +00001432 /// @param source the source information
1433 /// @param type the type to cast to
1434 /// @param expr the expression for the bitcast
1435 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1436 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001437 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001438 const ast::BitcastExpression* Bitcast(const Source& source,
1439 const ast::Type* type,
1440 EXPR&& expr) {
1441 return create<ast::BitcastExpression>(source, type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001442 }
1443
dan sinclair6e77b472022-10-20 13:38:28 +00001444 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001445 /// @param type the vector type
1446 /// @param size the vector size
1447 /// @return an `ast::CallExpression` of a `size`-element vector of
1448 /// type `type`, constructed with the values `args`.
1449 template <typename... ARGS>
1450 const ast::CallExpression* vec(const ast::Type* type, uint32_t size, ARGS&&... args) {
1451 return Construct(ty.vec(type, size), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001452 }
1453
dan sinclair6e77b472022-10-20 13:38:28 +00001454 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001455 /// @return an `ast::CallExpression` of a 2-element vector of type
1456 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001457 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001458 const ast::CallExpression* vec2(ARGS&&... args) {
1459 return Construct(ty.vec2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001460 }
1461
Ben Clayton6315a272022-08-01 17:18:04 +00001462 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001463 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001464 /// @return an `ast::CallExpression` of a 2-element vector of type
1465 /// `T`, constructed with the values `args`.
1466 template <typename T, typename... ARGS>
1467 const ast::CallExpression* vec2(const Source& source, ARGS&&... args) {
1468 return Construct(source, ty.vec2<T>(), std::forward<ARGS>(args)...);
1469 }
1470
dan sinclair6e77b472022-10-20 13:38:28 +00001471 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001472 /// @return an `ast::CallExpression` of a 3-element vector of type
1473 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001474 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001475 const ast::CallExpression* vec3(ARGS&&... args) {
1476 return Construct(ty.vec3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001477 }
1478
Ben Clayton6315a272022-08-01 17:18:04 +00001479 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001480 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001481 /// @return an `ast::CallExpression` of a 3-element vector of type
1482 /// `T`, constructed with the values `args`.
1483 template <typename T, typename... ARGS>
1484 const ast::CallExpression* vec3(const Source& source, ARGS&&... args) {
1485 return Construct(source, ty.vec3<T>(), std::forward<ARGS>(args)...);
1486 }
1487
dan sinclair6e77b472022-10-20 13:38:28 +00001488 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001489 /// @return an `ast::CallExpression` of a 4-element vector of type
1490 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001491 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001492 const ast::CallExpression* vec4(ARGS&&... args) {
1493 return Construct(ty.vec4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001494 }
1495
Ben Clayton6315a272022-08-01 17:18:04 +00001496 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001497 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001498 /// @return an `ast::CallExpression` of a 4-element vector of type
1499 /// `T`, constructed with the values `args`.
1500 template <typename T, typename... ARGS>
1501 const ast::CallExpression* vec4(const Source& source, ARGS&&... args) {
1502 return Construct(source, ty.vec4<T>(), std::forward<ARGS>(args)...);
1503 }
1504
dan sinclair6e77b472022-10-20 13:38:28 +00001505 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001506 /// @return an `ast::CallExpression` of a 2x2 matrix of type
1507 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001508 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001509 const ast::CallExpression* mat2x2(ARGS&&... args) {
1510 return Construct(ty.mat2x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001511 }
1512
Ben Clayton6315a272022-08-01 17:18:04 +00001513 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001514 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001515 /// @return an `ast::CallExpression` of a 2x2 matrix of type
1516 /// `T`, constructed with the values `args`.
1517 template <typename T, typename... ARGS>
1518 const ast::CallExpression* mat2x2(const Source& source, ARGS&&... args) {
1519 return Construct(source, ty.mat2x2<T>(), std::forward<ARGS>(args)...);
1520 }
1521
dan sinclair6e77b472022-10-20 13:38:28 +00001522 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001523 /// @return an `ast::CallExpression` of a 2x3 matrix of type
1524 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001525 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001526 const ast::CallExpression* mat2x3(ARGS&&... args) {
1527 return Construct(ty.mat2x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001528 }
1529
Ben Clayton6315a272022-08-01 17:18:04 +00001530 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001531 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001532 /// @return an `ast::CallExpression` of a 2x3 matrix of type
1533 /// `T`, constructed with the values `args`.
1534 template <typename T, typename... ARGS>
1535 const ast::CallExpression* mat2x3(const Source& source, ARGS&&... args) {
1536 return Construct(source, ty.mat2x3<T>(), std::forward<ARGS>(args)...);
1537 }
1538
dan sinclair6e77b472022-10-20 13:38:28 +00001539 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001540 /// @return an `ast::CallExpression` of a 2x4 matrix of type
1541 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001542 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001543 const ast::CallExpression* mat2x4(ARGS&&... args) {
1544 return Construct(ty.mat2x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001545 }
1546
Ben Clayton6315a272022-08-01 17:18:04 +00001547 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001548 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001549 /// @return an `ast::CallExpression` of a 2x4 matrix of type
1550 /// `T`, constructed with the values `args`.
1551 template <typename T, typename... ARGS>
1552 const ast::CallExpression* mat2x4(const Source& source, ARGS&&... args) {
1553 return Construct(source, ty.mat2x4<T>(), std::forward<ARGS>(args)...);
1554 }
1555
dan sinclair6e77b472022-10-20 13:38:28 +00001556 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001557 /// @return an `ast::CallExpression` of a 3x2 matrix of type
1558 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001559 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001560 const ast::CallExpression* mat3x2(ARGS&&... args) {
1561 return Construct(ty.mat3x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001562 }
1563
Ben Clayton6315a272022-08-01 17:18:04 +00001564 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001565 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001566 /// @return an `ast::CallExpression` of a 3x2 matrix of type
1567 /// `T`, constructed with the values `args`.
1568 template <typename T, typename... ARGS>
1569 const ast::CallExpression* mat3x2(const Source& source, ARGS&&... args) {
1570 return Construct(source, ty.mat3x2<T>(), std::forward<ARGS>(args)...);
1571 }
1572
dan sinclair6e77b472022-10-20 13:38:28 +00001573 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001574 /// @return an `ast::CallExpression` of a 3x3 matrix of type
1575 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001576 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001577 const ast::CallExpression* mat3x3(ARGS&&... args) {
1578 return Construct(ty.mat3x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001579 }
1580
Ben Clayton6315a272022-08-01 17:18:04 +00001581 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001582 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001583 /// @return an `ast::CallExpression` of a 3x3 matrix of type
1584 /// `T`, constructed with the values `args`.
1585 template <typename T, typename... ARGS>
1586 const ast::CallExpression* mat3x3(const Source& source, ARGS&&... args) {
1587 return Construct(source, ty.mat3x3<T>(), std::forward<ARGS>(args)...);
1588 }
1589
dan sinclair6e77b472022-10-20 13:38:28 +00001590 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001591 /// @return an `ast::CallExpression` of a 3x4 matrix of type
1592 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001593 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001594 const ast::CallExpression* mat3x4(ARGS&&... args) {
1595 return Construct(ty.mat3x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001596 }
1597
Ben Clayton6315a272022-08-01 17:18:04 +00001598 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001599 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001600 /// @return an `ast::CallExpression` of a 3x4 matrix of type
1601 /// `T`, constructed with the values `args`.
1602 template <typename T, typename... ARGS>
1603 const ast::CallExpression* mat3x4(const Source& source, ARGS&&... args) {
1604 return Construct(source, ty.mat3x4<T>(), std::forward<ARGS>(args)...);
1605 }
1606
dan sinclair6e77b472022-10-20 13:38:28 +00001607 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001608 /// @return an `ast::CallExpression` of a 4x2 matrix of type
1609 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001610 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001611 const ast::CallExpression* mat4x2(ARGS&&... args) {
1612 return Construct(ty.mat4x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001613 }
1614
Ben Clayton6315a272022-08-01 17:18:04 +00001615 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001616 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001617 /// @return an `ast::CallExpression` of a 4x2 matrix of type
1618 /// `T`, constructed with the values `args`.
1619 template <typename T, typename... ARGS>
1620 const ast::CallExpression* mat4x2(const Source& source, ARGS&&... args) {
1621 return Construct(source, ty.mat4x2<T>(), std::forward<ARGS>(args)...);
1622 }
1623
dan sinclair6e77b472022-10-20 13:38:28 +00001624 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001625 /// @return an `ast::CallExpression` of a 4x3 matrix of type
1626 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001627 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001628 const ast::CallExpression* mat4x3(ARGS&&... args) {
1629 return Construct(ty.mat4x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001630 }
1631
Ben Clayton6315a272022-08-01 17:18:04 +00001632 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001633 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001634 /// @return an `ast::CallExpression` of a 4x3 matrix of type
1635 /// `T`, constructed with the values `args`.
1636 template <typename T, typename... ARGS>
1637 const ast::CallExpression* mat4x3(const Source& source, ARGS&&... args) {
1638 return Construct(source, ty.mat4x3<T>(), std::forward<ARGS>(args)...);
1639 }
1640
dan sinclair6e77b472022-10-20 13:38:28 +00001641 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001642 /// @return an `ast::CallExpression` of a 4x4 matrix of type
1643 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001644 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001645 const ast::CallExpression* mat4x4(ARGS&&... args) {
1646 return Construct(ty.mat4x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001647 }
1648
Ben Clayton6315a272022-08-01 17:18:04 +00001649 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001650 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001651 /// @return an `ast::CallExpression` of a 4x4 matrix of type
1652 /// `T`, constructed with the values `args`.
1653 template <typename T, typename... ARGS>
1654 const ast::CallExpression* mat4x4(const Source& source, ARGS&&... args) {
1655 return Construct(source, ty.mat4x4<T>(), std::forward<ARGS>(args)...);
1656 }
1657
dan sinclair6e77b472022-10-20 13:38:28 +00001658 /// @param args the arguments for the array initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001659 /// @return an `ast::CallExpression` of an array with element type
1660 /// `T` and size `N`, constructed with the values `args`.
1661 template <typename T, int N, typename... ARGS>
1662 const ast::CallExpression* array(ARGS&&... args) {
1663 return Construct(ty.array<T, N>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001664 }
1665
Ben Clayton6315a272022-08-01 17:18:04 +00001666 /// @param source the array source
dan sinclair6e77b472022-10-20 13:38:28 +00001667 /// @param args the arguments for the array initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001668 /// @return an `ast::CallExpression` of an array with element type
1669 /// `T` and size `N`, constructed with the values `args`.
1670 template <typename T, int N, typename... ARGS>
1671 const ast::CallExpression* array(const Source& source, ARGS&&... args) {
1672 return Construct(source, ty.array<T, N>(), std::forward<ARGS>(args)...);
1673 }
1674
dan sinclair41e4d9a2022-05-01 14:40:55 +00001675 /// @param subtype the array element type
1676 /// @param n the array size. nullptr represents a runtime-array.
dan sinclair6e77b472022-10-20 13:38:28 +00001677 /// @param args the arguments for the array initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001678 /// @return an `ast::CallExpression` of an array with element type
1679 /// `subtype`, constructed with the values `args`.
1680 template <typename EXPR, typename... ARGS>
1681 const ast::CallExpression* array(const ast::Type* subtype, EXPR&& n, ARGS&&... args) {
1682 return Construct(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001683 }
1684
Ben Clayton6315a272022-08-01 17:18:04 +00001685 /// @param source the array source
1686 /// @param subtype the array element type
1687 /// @param n the array size. nullptr represents a runtime-array.
dan sinclair6e77b472022-10-20 13:38:28 +00001688 /// @param args the arguments for the array initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001689 /// @return an `ast::CallExpression` of an array with element type
1690 /// `subtype`, constructed with the values `args`.
1691 template <typename EXPR, typename... ARGS>
1692 const ast::CallExpression* array(const Source& source,
1693 const ast::Type* subtype,
1694 EXPR&& n,
1695 ARGS&&... args) {
1696 return Construct(source, ty.array(subtype, std::forward<EXPR>(n)),
1697 std::forward<ARGS>(args)...);
1698 }
1699
Ben Clayton7f2b8cd2022-05-18 22:41:48 +00001700 /// Adds the extension to the list of enable directives at the top of the module.
1701 /// @param ext the extension to enable
1702 /// @return an `ast::Enable` enabling the given extension.
1703 const ast::Enable* Enable(ast::Extension ext) {
1704 auto* enable = create<ast::Enable>(ext);
1705 AST().AddEnable(enable);
1706 return enable;
1707 }
1708
Ben Clayton1a567782022-10-14 13:38:27 +00001709 /// Adds the extension to the list of enable directives at the top of the module.
1710 /// @param source the enable source
1711 /// @param ext the extension to enable
1712 /// @return an `ast::Enable` enabling the given extension.
1713 const ast::Enable* Enable(const Source& source, ast::Extension ext) {
1714 auto* enable = create<ast::Enable>(source, ext);
1715 AST().AddEnable(enable);
1716 return enable;
1717 }
1718
dan sinclair41e4d9a2022-05-01 14:40:55 +00001719 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001720 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001721 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001722 /// * ast::Type* - specifies the variable type
dan sinclairff7cf212022-10-03 14:05:23 +00001723 /// * ast::AddressSpace - specifies the variable address space
dan sinclair41e4d9a2022-05-01 14:40:55 +00001724 /// * ast::Access - specifies the variable's access control
1725 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001726 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1727 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001728 /// @returns a `ast::Var` with the given name, type and additional
dan sinclair41e4d9a2022-05-01 14:40:55 +00001729 /// options
Ben Clayton58794ae2022-08-19 17:28:53 +00001730 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1731 const ast::Var* Var(NAME&& name, OPTIONS&&... options) {
1732 VarOptions opts(std::forward<OPTIONS>(options)...);
dan sinclairff7cf212022-10-03 14:05:23 +00001733 return create<ast::Var>(Sym(std::forward<NAME>(name)), opts.type, opts.address_space,
dan sinclair6e77b472022-10-20 13:38:28 +00001734 opts.access, opts.initializer, std::move(opts.attributes));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001735 }
1736
dan sinclair41e4d9a2022-05-01 14:40:55 +00001737 /// @param source the variable source
1738 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001739 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001740 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001741 /// * ast::Type* - specifies the variable type
dan sinclairff7cf212022-10-03 14:05:23 +00001742 /// * ast::AddressSpace - specifies the variable address space
dan sinclair41e4d9a2022-05-01 14:40:55 +00001743 /// * ast::Access - specifies the variable's access control
1744 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001745 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1746 /// Note that non-repeatable arguments of the same type will use the last argument's value.
dan sinclairff7cf212022-10-03 14:05:23 +00001747 /// @returns a `ast::Var` with the given name, address_space and type
Ben Clayton58794ae2022-08-19 17:28:53 +00001748 template <typename NAME, typename... OPTIONS>
1749 const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) {
1750 VarOptions opts(std::forward<OPTIONS>(options)...);
dan sinclairff7cf212022-10-03 14:05:23 +00001751 return create<ast::Var>(source, Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001752 opts.address_space, opts.access, opts.initializer,
dan sinclairff7cf212022-10-03 14:05:23 +00001753 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001754 }
1755
1756 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001757 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001758 /// Can be any of the following, in any order:
1759 /// * ast::Expression* - specifies the variable's initializer expression (required)
1760 /// * ast::Type* - specifies the variable type
1761 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1762 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1763 /// @returns an `ast::Const` with the given name, type and additional options
1764 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1765 const ast::Const* Const(NAME&& name, OPTIONS&&... options) {
1766 ConstOptions opts(std::forward<OPTIONS>(options)...);
dan sinclair6e77b472022-10-20 13:38:28 +00001767 return create<ast::Const>(Sym(std::forward<NAME>(name)), opts.type, opts.initializer,
Ben Clayton58794ae2022-08-19 17:28:53 +00001768 std::move(opts.attributes));
Ben Claytone3834c42022-06-25 23:21:39 +00001769 }
1770
1771 /// @param source the variable source
1772 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001773 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001774 /// Can be any of the following, in any order:
1775 /// * ast::Expression* - specifies the variable's initializer expression (required)
1776 /// * ast::Type* - specifies the variable type
1777 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1778 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1779 /// @returns an `ast::Const` with the given name, type and additional options
1780 template <typename NAME, typename... OPTIONS>
1781 const ast::Const* Const(const Source& source, NAME&& name, OPTIONS&&... options) {
1782 ConstOptions opts(std::forward<OPTIONS>(options)...);
1783 return create<ast::Const>(source, Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001784 opts.initializer, std::move(opts.attributes));
Ben Claytone3834c42022-06-25 23:21:39 +00001785 }
1786
1787 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001788 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001789 /// Can be any of the following, in any order:
1790 /// * ast::Expression* - specifies the variable's initializer expression (required)
1791 /// * ast::Type* - specifies the variable type
1792 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1793 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1794 /// @returns an `ast::Let` with the given name, type and additional options
1795 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1796 const ast::Let* Let(NAME&& name, OPTIONS&&... options) {
1797 LetOptions opts(std::forward<OPTIONS>(options)...);
dan sinclair6e77b472022-10-20 13:38:28 +00001798 return create<ast::Let>(Sym(std::forward<NAME>(name)), opts.type, opts.initializer,
Ben Clayton58794ae2022-08-19 17:28:53 +00001799 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001800 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001801
dan sinclair41e4d9a2022-05-01 14:40:55 +00001802 /// @param source the variable source
1803 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001804 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001805 /// Can be any of the following, in any order:
1806 /// * ast::Expression* - specifies the variable's initializer expression (required)
1807 /// * ast::Type* - specifies the variable type
1808 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1809 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1810 /// @returns an `ast::Let` with the given name, type and additional options
1811 template <typename NAME, typename... OPTIONS>
1812 const ast::Let* Let(const Source& source, NAME&& name, OPTIONS&&... options) {
1813 LetOptions opts(std::forward<OPTIONS>(options)...);
dan sinclair6e77b472022-10-20 13:38:28 +00001814 return create<ast::Let>(source, Sym(std::forward<NAME>(name)), opts.type, opts.initializer,
Ben Clayton58794ae2022-08-19 17:28:53 +00001815 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001816 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001817
dan sinclair41e4d9a2022-05-01 14:40:55 +00001818 /// @param name the parameter name
1819 /// @param type the parameter type
1820 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001821 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001822 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001823 const ast::Parameter* Param(NAME&& name,
1824 const ast::Type* type,
Ben Clayton783b1692022-08-02 17:03:35 +00001825 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Claytondcdf66e2022-06-17 12:48:51 +00001826 return create<ast::Parameter>(Sym(std::forward<NAME>(name)), type, attributes);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001827 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001828
dan sinclair41e4d9a2022-05-01 14:40:55 +00001829 /// @param source the parameter source
1830 /// @param name the parameter name
1831 /// @param type the parameter type
1832 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001833 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001834 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001835 const ast::Parameter* Param(const Source& source,
1836 NAME&& name,
1837 const ast::Type* type,
Ben Clayton783b1692022-08-02 17:03:35 +00001838 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Claytondcdf66e2022-06-17 12:48:51 +00001839 return create<ast::Parameter>(source, Sym(std::forward<NAME>(name)), type, attributes);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001840 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001841
dan sinclair41e4d9a2022-05-01 14:40:55 +00001842 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001843 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001844 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001845 /// * ast::Type* - specifies the variable type
dan sinclairff7cf212022-10-03 14:05:23 +00001846 /// * ast::AddressSpace - specifies the variable address space
dan sinclair41e4d9a2022-05-01 14:40:55 +00001847 /// * ast::Access - specifies the variable's access control
1848 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001849 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1850 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001851 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1852 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001853 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1854 const ast::Var* GlobalVar(NAME&& name, OPTIONS&&... options) {
1855 auto* variable = Var(std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1856 AST().AddGlobalVariable(variable);
1857 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001858 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001859
dan sinclair41e4d9a2022-05-01 14:40:55 +00001860 /// @param source the variable source
1861 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001862 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001863 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001864 /// * ast::Type* - specifies the variable type
dan sinclairff7cf212022-10-03 14:05:23 +00001865 /// * ast::AddressSpace - specifies the variable address space
dan sinclair41e4d9a2022-05-01 14:40:55 +00001866 /// * ast::Access - specifies the variable's access control
1867 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001868 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1869 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001870 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1871 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001872 template <typename NAME, typename... OPTIONS>
1873 const ast::Var* GlobalVar(const Source& source, NAME&& name, OPTIONS&&... options) {
1874 auto* variable = Var(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1875 AST().AddGlobalVariable(variable);
1876 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001877 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001878
dan sinclair41e4d9a2022-05-01 14:40:55 +00001879 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001880 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001881 /// Can be any of the following, in any order:
1882 /// * ast::Expression* - specifies the variable's initializer expression (required)
1883 /// * ast::Type* - specifies the variable type
1884 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1885 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1886 /// @returns an `ast::Const` with the given name, type and additional options, which is
1887 /// automatically registered as a global variable with the ast::Module.
1888 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1889 const ast::Const* GlobalConst(NAME&& name, OPTIONS&&... options) {
1890 auto* variable = Const(std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1891 AST().AddGlobalVariable(variable);
1892 return variable;
Ben Claytone3834c42022-06-25 23:21:39 +00001893 }
1894
1895 /// @param source the variable source
1896 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001897 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001898 /// Can be any of the following, in any order:
1899 /// * ast::Expression* - specifies the variable's initializer expression (required)
1900 /// * ast::Type* - specifies the variable type
1901 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1902 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1903 /// @returns an `ast::Const` with the given name, type and additional options, which is
1904 /// automatically registered as a global variable with the ast::Module.
1905 template <typename NAME, typename... OPTIONS>
1906 const ast::Const* GlobalConst(const Source& source, NAME&& name, OPTIONS&&... options) {
1907 auto* variable = Const(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1908 AST().AddGlobalVariable(variable);
1909 return variable;
Ben Claytone3834c42022-06-25 23:21:39 +00001910 }
1911
1912 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001913 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001914 /// Can be any of the following, in any order:
1915 /// * ast::Expression* - specifies the variable's initializer expression (required)
1916 /// * ast::Type* - specifies the variable type
1917 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1918 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1919 /// @returns an `ast::Override` with the given name, type and additional options, which is
1920 /// automatically registered as a global variable with the ast::Module.
1921 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1922 const ast::Override* Override(NAME&& name, OPTIONS&&... options) {
1923 OverrideOptions opts(std::forward<OPTIONS>(options)...);
1924 auto* variable = create<ast::Override>(Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001925 opts.initializer, std::move(opts.attributes));
Ben Clayton58794ae2022-08-19 17:28:53 +00001926 AST().AddGlobalVariable(variable);
1927 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001928 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001929
dan sinclair41e4d9a2022-05-01 14:40:55 +00001930 /// @param source the variable source
1931 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001932 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001933 /// Can be any of the following, in any order:
1934 /// * ast::Expression* - specifies the variable's initializer expression (required)
1935 /// * ast::Type* - specifies the variable type
1936 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1937 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1938 /// @returns an `ast::Override` with the given name, type and additional options, which is
1939 /// automatically registered as a global variable with the ast::Module.
1940 template <typename NAME, typename... OPTIONS>
1941 const ast::Override* Override(const Source& source, NAME&& name, OPTIONS&&... options) {
1942 OverrideOptions opts(std::forward<OPTIONS>(options)...);
1943 auto* variable = create<ast::Override>(source, Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001944 opts.initializer, std::move(opts.attributes));
Ben Clayton58794ae2022-08-19 17:28:53 +00001945 AST().AddGlobalVariable(variable);
1946 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001947 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001948
dan sinclair41e4d9a2022-05-01 14:40:55 +00001949 /// @param source the source information
Ben Claytonbfd1a812022-08-02 23:16:25 +00001950 /// @param condition the assertion condition
1951 /// @returns a new `ast::StaticAssert`, which is automatically registered as a global statement
1952 /// with the ast::Module.
1953 template <typename EXPR>
1954 const ast::StaticAssert* GlobalStaticAssert(const Source& source, EXPR&& condition) {
1955 auto* sa = StaticAssert(source, std::forward<EXPR>(condition));
1956 AST().AddStaticAssert(sa);
1957 return sa;
1958 }
1959
1960 /// @param condition the assertion condition
1961 /// @returns a new `ast::StaticAssert`, which is automatically registered as a global statement
1962 /// with the ast::Module.
1963 template <typename EXPR, typename = DisableIfSource<EXPR>>
1964 const ast::StaticAssert* GlobalStaticAssert(EXPR&& condition) {
1965 auto* sa = StaticAssert(std::forward<EXPR>(condition));
1966 AST().AddStaticAssert(sa);
1967 return sa;
1968 }
1969
1970 /// @param source the source information
1971 /// @param condition the assertion condition
1972 /// @returns a new `ast::StaticAssert` with the given assertion condition
1973 template <typename EXPR>
1974 const ast::StaticAssert* StaticAssert(const Source& source, EXPR&& condition) {
1975 return create<ast::StaticAssert>(source, Expr(std::forward<EXPR>(condition)));
1976 }
1977
1978 /// @param condition the assertion condition
1979 /// @returns a new `ast::StaticAssert` with the given assertion condition
1980 template <typename EXPR, typename = DisableIfSource<EXPR>>
1981 const ast::StaticAssert* StaticAssert(EXPR&& condition) {
1982 return create<ast::StaticAssert>(Expr(std::forward<EXPR>(condition)));
1983 }
1984
1985 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001986 /// @param expr the expression to take the address of
1987 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1988 template <typename EXPR>
1989 const ast::UnaryOpExpression* AddressOf(const Source& source, EXPR&& expr) {
1990 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kAddressOf,
1991 Expr(std::forward<EXPR>(expr)));
1992 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001993
dan sinclair41e4d9a2022-05-01 14:40:55 +00001994 /// @param expr the expression to take the address of
1995 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1996 template <typename EXPR>
1997 const ast::UnaryOpExpression* AddressOf(EXPR&& expr) {
1998 return create<ast::UnaryOpExpression>(ast::UnaryOp::kAddressOf,
1999 Expr(std::forward<EXPR>(expr)));
2000 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002001
dan sinclair41e4d9a2022-05-01 14:40:55 +00002002 /// @param source the source information
2003 /// @param expr the expression to perform an indirection on
2004 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
2005 template <typename EXPR>
2006 const ast::UnaryOpExpression* Deref(const Source& source, EXPR&& expr) {
2007 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kIndirection,
2008 Expr(std::forward<EXPR>(expr)));
2009 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002010
dan sinclair41e4d9a2022-05-01 14:40:55 +00002011 /// @param expr the expression to perform an indirection on
2012 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
2013 template <typename EXPR>
2014 const ast::UnaryOpExpression* Deref(EXPR&& expr) {
2015 return create<ast::UnaryOpExpression>(ast::UnaryOp::kIndirection,
2016 Expr(std::forward<EXPR>(expr)));
2017 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002018
dan sinclair41e4d9a2022-05-01 14:40:55 +00002019 /// @param expr the expression to perform a unary not on
2020 /// @return an ast::UnaryOpExpression that is the unary not of the input
2021 /// expression
2022 template <typename EXPR>
2023 const ast::UnaryOpExpression* Not(EXPR&& expr) {
2024 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(std::forward<EXPR>(expr)));
2025 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002026
Antonio Maiorano28779af2022-12-09 21:28:51 +00002027 /// @param source the source information
2028 /// @param expr the expression to perform a unary not on
2029 /// @return an ast::UnaryOpExpression that is the unary not of the input
2030 /// expression
2031 template <typename EXPR>
2032 const ast::UnaryOpExpression* Not(const Source& source, EXPR&& expr) {
2033 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kNot,
2034 Expr(std::forward<EXPR>(expr)));
2035 }
2036
dan sinclair41e4d9a2022-05-01 14:40:55 +00002037 /// @param expr the expression to perform a unary complement on
2038 /// @return an ast::UnaryOpExpression that is the unary complement of the
2039 /// input expression
2040 template <typename EXPR>
2041 const ast::UnaryOpExpression* Complement(EXPR&& expr) {
2042 return create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement,
2043 Expr(std::forward<EXPR>(expr)));
2044 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002045
Author: Shiyu Liub3aab092022-05-04 13:07:29 +00002046 /// @param expr the expression to perform a unary negation on
2047 /// @return an ast::UnaryOpExpression that is the unary negation of the
2048 /// input expression
2049 template <typename EXPR>
2050 const ast::UnaryOpExpression* Negation(EXPR&& expr) {
2051 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation,
2052 Expr(std::forward<EXPR>(expr)));
2053 }
2054
dan sinclair41e4d9a2022-05-01 14:40:55 +00002055 /// @param source the source information
2056 /// @param func the function name
2057 /// @param args the function call arguments
2058 /// @returns a `ast::CallExpression` to the function `func`, with the
2059 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
2060 template <typename NAME, typename... ARGS>
2061 const ast::CallExpression* Call(const Source& source, NAME&& func, ARGS&&... args) {
2062 return create<ast::CallExpression>(source, Expr(func),
2063 ExprList(std::forward<ARGS>(args)...));
2064 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002065
dan sinclair41e4d9a2022-05-01 14:40:55 +00002066 /// @param func the function name
2067 /// @param args the function call arguments
2068 /// @returns a `ast::CallExpression` to the function `func`, with the
2069 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
2070 template <typename NAME, typename... ARGS, typename = DisableIfSource<NAME>>
2071 const ast::CallExpression* Call(NAME&& func, ARGS&&... args) {
2072 return create<ast::CallExpression>(Expr(func), ExprList(std::forward<ARGS>(args)...));
2073 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002074
dan sinclair41e4d9a2022-05-01 14:40:55 +00002075 /// @param source the source information
2076 /// @param call the call expression to wrap in a call statement
2077 /// @returns a `ast::CallStatement` for the given call expression
2078 const ast::CallStatement* CallStmt(const Source& source, const ast::CallExpression* call) {
2079 return create<ast::CallStatement>(source, call);
2080 }
James Pricec022ff52022-03-31 22:30:10 +00002081
dan sinclair41e4d9a2022-05-01 14:40:55 +00002082 /// @param call the call expression to wrap in a call statement
2083 /// @returns a `ast::CallStatement` for the given call expression
2084 const ast::CallStatement* CallStmt(const ast::CallExpression* call) {
2085 return create<ast::CallStatement>(call);
2086 }
James Pricec022ff52022-03-31 22:30:10 +00002087
dan sinclair41e4d9a2022-05-01 14:40:55 +00002088 /// @param source the source information
2089 /// @returns a `ast::PhonyExpression`
2090 const ast::PhonyExpression* Phony(const Source& source) {
2091 return create<ast::PhonyExpression>(source);
2092 }
James Priceebe97412022-04-07 13:42:45 +00002093
dan sinclair41e4d9a2022-05-01 14:40:55 +00002094 /// @returns a `ast::PhonyExpression`
2095 const ast::PhonyExpression* Phony() { return create<ast::PhonyExpression>(); }
James Priceebe97412022-04-07 13:42:45 +00002096
dan sinclair41e4d9a2022-05-01 14:40:55 +00002097 /// @param expr the expression to ignore
2098 /// @returns a `ast::AssignmentStatement` that assigns 'expr' to the phony
2099 /// (underscore) variable.
2100 template <typename EXPR>
2101 const ast::AssignmentStatement* Ignore(EXPR&& expr) {
2102 return create<ast::AssignmentStatement>(Phony(), Expr(expr));
2103 }
James Priceebe97412022-04-07 13:42:45 +00002104
dan sinclair41e4d9a2022-05-01 14:40:55 +00002105 /// @param lhs the left hand argument to the addition operation
2106 /// @param rhs the right hand argument to the addition operation
2107 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2108 template <typename LHS, typename RHS>
2109 const ast::BinaryExpression* Add(LHS&& lhs, RHS&& rhs) {
2110 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd, Expr(std::forward<LHS>(lhs)),
2111 Expr(std::forward<RHS>(rhs)));
2112 }
James Priceebe97412022-04-07 13:42:45 +00002113
Antonio Maiorano7058a172022-08-10 18:06:43 +00002114 /// @param source the source information
2115 /// @param lhs the left hand argument to the addition operation
2116 /// @param rhs the right hand argument to the addition operation
2117 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2118 template <typename LHS, typename RHS>
2119 const ast::BinaryExpression* Add(const Source& source, LHS&& lhs, RHS&& rhs) {
2120 return create<ast::BinaryExpression>(source, ast::BinaryOp::kAdd,
2121 Expr(std::forward<LHS>(lhs)),
2122 Expr(std::forward<RHS>(rhs)));
2123 }
2124
dan sinclair41e4d9a2022-05-01 14:40:55 +00002125 /// @param lhs the left hand argument to the and operation
2126 /// @param rhs the right hand argument to the and operation
2127 /// @returns a `ast::BinaryExpression` bitwise anding `lhs` and `rhs`
2128 template <typename LHS, typename RHS>
2129 const ast::BinaryExpression* And(LHS&& lhs, RHS&& rhs) {
2130 return create<ast::BinaryExpression>(ast::BinaryOp::kAnd, Expr(std::forward<LHS>(lhs)),
2131 Expr(std::forward<RHS>(rhs)));
2132 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002133
dan sinclair41e4d9a2022-05-01 14:40:55 +00002134 /// @param lhs the left hand argument to the or operation
2135 /// @param rhs the right hand argument to the or operation
2136 /// @returns a `ast::BinaryExpression` bitwise or-ing `lhs` and `rhs`
2137 template <typename LHS, typename RHS>
2138 const ast::BinaryExpression* Or(LHS&& lhs, RHS&& rhs) {
2139 return create<ast::BinaryExpression>(ast::BinaryOp::kOr, Expr(std::forward<LHS>(lhs)),
2140 Expr(std::forward<RHS>(rhs)));
2141 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002142
dan sinclair41e4d9a2022-05-01 14:40:55 +00002143 /// @param lhs the left hand argument to the subtraction operation
2144 /// @param rhs the right hand argument to the subtraction operation
2145 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs`
2146 template <typename LHS, typename RHS>
2147 const ast::BinaryExpression* Sub(LHS&& lhs, RHS&& rhs) {
2148 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract, Expr(std::forward<LHS>(lhs)),
2149 Expr(std::forward<RHS>(rhs)));
2150 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002151
dan sinclair41e4d9a2022-05-01 14:40:55 +00002152 /// @param lhs the left hand argument to the multiplication operation
2153 /// @param rhs the right hand argument to the multiplication operation
2154 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2155 template <typename LHS, typename RHS>
2156 const ast::BinaryExpression* Mul(LHS&& lhs, RHS&& rhs) {
2157 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, Expr(std::forward<LHS>(lhs)),
2158 Expr(std::forward<RHS>(rhs)));
2159 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002160
dan sinclair41e4d9a2022-05-01 14:40:55 +00002161 /// @param source the source information
2162 /// @param lhs the left hand argument to the multiplication operation
2163 /// @param rhs the right hand argument to the multiplication operation
2164 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2165 template <typename LHS, typename RHS>
2166 const ast::BinaryExpression* Mul(const Source& source, LHS&& lhs, RHS&& rhs) {
2167 return create<ast::BinaryExpression>(source, ast::BinaryOp::kMultiply,
2168 Expr(std::forward<LHS>(lhs)),
2169 Expr(std::forward<RHS>(rhs)));
2170 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002171
dan sinclair41e4d9a2022-05-01 14:40:55 +00002172 /// @param lhs the left hand argument to the division operation
2173 /// @param rhs the right hand argument to the division operation
2174 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2175 template <typename LHS, typename RHS>
2176 const ast::BinaryExpression* Div(LHS&& lhs, RHS&& rhs) {
2177 return create<ast::BinaryExpression>(ast::BinaryOp::kDivide, Expr(std::forward<LHS>(lhs)),
2178 Expr(std::forward<RHS>(rhs)));
2179 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002180
Antonio Maiorano28779af2022-12-09 21:28:51 +00002181 /// @param source the source information
2182 /// @param lhs the left hand argument to the division operation
2183 /// @param rhs the right hand argument to the division operation
2184 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2185 template <typename LHS, typename RHS>
2186 const ast::BinaryExpression* Div(const Source& source, LHS&& lhs, RHS&& rhs) {
2187 return create<ast::BinaryExpression>(source, ast::BinaryOp::kDivide,
2188 Expr(std::forward<LHS>(lhs)),
2189 Expr(std::forward<RHS>(rhs)));
2190 }
2191
dan sinclair41e4d9a2022-05-01 14:40:55 +00002192 /// @param lhs the left hand argument to the modulo operation
2193 /// @param rhs the right hand argument to the modulo operation
2194 /// @returns a `ast::BinaryExpression` applying modulo of `lhs` by `rhs`
2195 template <typename LHS, typename RHS>
2196 const ast::BinaryExpression* Mod(LHS&& lhs, RHS&& rhs) {
2197 return create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr(std::forward<LHS>(lhs)),
2198 Expr(std::forward<RHS>(rhs)));
2199 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002200
dan sinclair41e4d9a2022-05-01 14:40:55 +00002201 /// @param lhs the left hand argument to the bit shift right operation
2202 /// @param rhs the right hand argument to the bit shift right operation
2203 /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs`
2204 template <typename LHS, typename RHS>
2205 const ast::BinaryExpression* Shr(LHS&& lhs, RHS&& rhs) {
2206 return create<ast::BinaryExpression>(
2207 ast::BinaryOp::kShiftRight, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2208 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002209
dan sinclair41e4d9a2022-05-01 14:40:55 +00002210 /// @param lhs the left hand argument to the bit shift left operation
2211 /// @param rhs the right hand argument to the bit shift left operation
2212 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2213 template <typename LHS, typename RHS>
2214 const ast::BinaryExpression* Shl(LHS&& lhs, RHS&& rhs) {
2215 return create<ast::BinaryExpression>(
2216 ast::BinaryOp::kShiftLeft, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2217 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002218
Antonio Maiorano5f33fac2022-09-23 21:58:29 +00002219 /// @param source the source information
2220 /// @param lhs the left hand argument to the bit shift left operation
2221 /// @param rhs the right hand argument to the bit shift left operation
2222 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2223 template <typename LHS, typename RHS>
2224 const ast::BinaryExpression* Shl(const Source& source, LHS&& lhs, RHS&& rhs) {
2225 return create<ast::BinaryExpression>(source, ast::BinaryOp::kShiftLeft,
2226 Expr(std::forward<LHS>(lhs)),
2227 Expr(std::forward<RHS>(rhs)));
2228 }
2229
dan sinclair41e4d9a2022-05-01 14:40:55 +00002230 /// @param lhs the left hand argument to the xor operation
2231 /// @param rhs the right hand argument to the xor operation
2232 /// @returns a `ast::BinaryExpression` bitwise xor-ing `lhs` and `rhs`
2233 template <typename LHS, typename RHS>
2234 const ast::BinaryExpression* Xor(LHS&& lhs, RHS&& rhs) {
2235 return create<ast::BinaryExpression>(ast::BinaryOp::kXor, Expr(std::forward<LHS>(lhs)),
2236 Expr(std::forward<RHS>(rhs)));
2237 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002238
dan sinclair41e4d9a2022-05-01 14:40:55 +00002239 /// @param lhs the left hand argument to the logical and operation
2240 /// @param rhs the right hand argument to the logical and operation
2241 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2242 template <typename LHS, typename RHS>
2243 const ast::BinaryExpression* LogicalAnd(LHS&& lhs, RHS&& rhs) {
2244 return create<ast::BinaryExpression>(
2245 ast::BinaryOp::kLogicalAnd, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2246 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002247
Antonio Maiorano28779af2022-12-09 21:28:51 +00002248 /// @param source the source information
2249 /// @param lhs the left hand argument to the logical and operation
2250 /// @param rhs the right hand argument to the logical and operation
2251 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2252 template <typename LHS, typename RHS>
2253 const ast::BinaryExpression* LogicalAnd(const Source& source, LHS&& lhs, RHS&& rhs) {
2254 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalAnd,
2255 Expr(std::forward<LHS>(lhs)),
2256 Expr(std::forward<RHS>(rhs)));
2257 }
2258
dan sinclair41e4d9a2022-05-01 14:40:55 +00002259 /// @param lhs the left hand argument to the logical or operation
2260 /// @param rhs the right hand argument to the logical or operation
2261 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2262 template <typename LHS, typename RHS>
2263 const ast::BinaryExpression* LogicalOr(LHS&& lhs, RHS&& rhs) {
2264 return create<ast::BinaryExpression>(
2265 ast::BinaryOp::kLogicalOr, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2266 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002267
Antonio Maiorano28779af2022-12-09 21:28:51 +00002268 /// @param source the source information
2269 /// @param lhs the left hand argument to the logical or operation
2270 /// @param rhs the right hand argument to the logical or operation
2271 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2272 template <typename LHS, typename RHS>
2273 const ast::BinaryExpression* LogicalOr(const Source& source, LHS&& lhs, RHS&& rhs) {
2274 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalOr,
2275 Expr(std::forward<LHS>(lhs)),
2276 Expr(std::forward<RHS>(rhs)));
2277 }
2278
dan sinclair41e4d9a2022-05-01 14:40:55 +00002279 /// @param lhs the left hand argument to the greater than operation
2280 /// @param rhs the right hand argument to the greater than operation
2281 /// @returns a `ast::BinaryExpression` of `lhs` > `rhs`
2282 template <typename LHS, typename RHS>
2283 const ast::BinaryExpression* GreaterThan(LHS&& lhs, RHS&& rhs) {
2284 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThan,
2285 Expr(std::forward<LHS>(lhs)),
2286 Expr(std::forward<RHS>(rhs)));
2287 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002288
dan sinclair41e4d9a2022-05-01 14:40:55 +00002289 /// @param lhs the left hand argument to the greater than or equal operation
2290 /// @param rhs the right hand argument to the greater than or equal operation
2291 /// @returns a `ast::BinaryExpression` of `lhs` >= `rhs`
2292 template <typename LHS, typename RHS>
2293 const ast::BinaryExpression* GreaterThanEqual(LHS&& lhs, RHS&& rhs) {
2294 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThanEqual,
2295 Expr(std::forward<LHS>(lhs)),
2296 Expr(std::forward<RHS>(rhs)));
2297 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002298
dan sinclair41e4d9a2022-05-01 14:40:55 +00002299 /// @param lhs the left hand argument to the less than operation
2300 /// @param rhs the right hand argument to the less than operation
2301 /// @returns a `ast::BinaryExpression` of `lhs` < `rhs`
2302 template <typename LHS, typename RHS>
2303 const ast::BinaryExpression* LessThan(LHS&& lhs, RHS&& rhs) {
2304 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThan, Expr(std::forward<LHS>(lhs)),
2305 Expr(std::forward<RHS>(rhs)));
2306 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002307
dan sinclair41e4d9a2022-05-01 14:40:55 +00002308 /// @param lhs the left hand argument to the less than or equal operation
2309 /// @param rhs the right hand argument to the less than or equal operation
2310 /// @returns a `ast::BinaryExpression` of `lhs` <= `rhs`
2311 template <typename LHS, typename RHS>
2312 const ast::BinaryExpression* LessThanEqual(LHS&& lhs, RHS&& rhs) {
2313 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThanEqual,
2314 Expr(std::forward<LHS>(lhs)),
2315 Expr(std::forward<RHS>(rhs)));
2316 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002317
dan sinclair41e4d9a2022-05-01 14:40:55 +00002318 /// @param lhs the left hand argument to the equal expression
2319 /// @param rhs the right hand argument to the equal expression
2320 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2321 template <typename LHS, typename RHS>
2322 const ast::BinaryExpression* Equal(LHS&& lhs, RHS&& rhs) {
2323 return create<ast::BinaryExpression>(ast::BinaryOp::kEqual, Expr(std::forward<LHS>(lhs)),
2324 Expr(std::forward<RHS>(rhs)));
2325 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002326
Antonio Maiorano28779af2022-12-09 21:28:51 +00002327 /// @param source the source information
2328 /// @param lhs the left hand argument to the equal expression
2329 /// @param rhs the right hand argument to the equal expression
2330 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2331 template <typename LHS, typename RHS>
2332 const ast::BinaryExpression* Equal(const Source& source, LHS&& lhs, RHS&& rhs) {
2333 return create<ast::BinaryExpression>(source, ast::BinaryOp::kEqual,
2334 Expr(std::forward<LHS>(lhs)),
2335 Expr(std::forward<RHS>(rhs)));
2336 }
2337
dan sinclair41e4d9a2022-05-01 14:40:55 +00002338 /// @param lhs the left hand argument to the not-equal expression
2339 /// @param rhs the right hand argument to the not-equal expression
2340 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` for
2341 /// disequality
2342 template <typename LHS, typename RHS>
2343 const ast::BinaryExpression* NotEqual(LHS&& lhs, RHS&& rhs) {
2344 return create<ast::BinaryExpression>(ast::BinaryOp::kNotEqual, Expr(std::forward<LHS>(lhs)),
2345 Expr(std::forward<RHS>(rhs)));
2346 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002347
dan sinclair41e4d9a2022-05-01 14:40:55 +00002348 /// @param source the source information
2349 /// @param obj the object for the index accessor expression
2350 /// @param idx the index argument for the index accessor expression
2351 /// @returns a `ast::IndexAccessorExpression` that indexes `arr` with `idx`
2352 template <typename OBJ, typename IDX>
2353 const ast::IndexAccessorExpression* IndexAccessor(const Source& source, OBJ&& obj, IDX&& idx) {
2354 return create<ast::IndexAccessorExpression>(source, Expr(std::forward<OBJ>(obj)),
2355 Expr(std::forward<IDX>(idx)));
2356 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002357
dan sinclair41e4d9a2022-05-01 14:40:55 +00002358 /// @param obj the object for the index accessor expression
2359 /// @param idx the index argument for the index accessor expression
2360 /// @returns a `ast::IndexAccessorExpression` that indexes `arr` with `idx`
2361 template <typename OBJ, typename IDX>
2362 const ast::IndexAccessorExpression* IndexAccessor(OBJ&& obj, IDX&& idx) {
2363 return create<ast::IndexAccessorExpression>(Expr(std::forward<OBJ>(obj)),
2364 Expr(std::forward<IDX>(idx)));
2365 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002366
dan sinclair41e4d9a2022-05-01 14:40:55 +00002367 /// @param source the source information
2368 /// @param obj the object for the member accessor expression
2369 /// @param idx the index argument for the member accessor expression
2370 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx`
2371 template <typename OBJ, typename IDX>
2372 const ast::MemberAccessorExpression* MemberAccessor(const Source& source,
2373 OBJ&& obj,
2374 IDX&& idx) {
2375 return create<ast::MemberAccessorExpression>(source, Expr(std::forward<OBJ>(obj)),
2376 Expr(std::forward<IDX>(idx)));
2377 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002378
dan sinclair41e4d9a2022-05-01 14:40:55 +00002379 /// @param obj the object for the member accessor expression
2380 /// @param idx the index argument for the member accessor expression
2381 /// @returns a `ast::MemberAccessorExpression` that indexes `obj` with `idx`
2382 template <typename OBJ, typename IDX>
2383 const ast::MemberAccessorExpression* MemberAccessor(OBJ&& obj, IDX&& idx) {
2384 return create<ast::MemberAccessorExpression>(Expr(std::forward<OBJ>(obj)),
2385 Expr(std::forward<IDX>(idx)));
2386 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002387
dan sinclair41e4d9a2022-05-01 14:40:55 +00002388 /// Creates a ast::StructMemberOffsetAttribute
dan sinclair93df9672022-09-09 14:49:09 +00002389 /// @param val the offset expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002390 /// @returns the offset attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002391 template <typename EXPR>
2392 const ast::StructMemberOffsetAttribute* MemberOffset(EXPR&& val) {
2393 return create<ast::StructMemberOffsetAttribute>(source_, Expr(std::forward<EXPR>(val)));
2394 }
2395
2396 /// Creates a ast::StructMemberOffsetAttribute
2397 /// @param source the source information
2398 /// @param val the offset expression
2399 /// @returns the offset attribute pointer
2400 template <typename EXPR>
2401 const ast::StructMemberOffsetAttribute* MemberOffset(const Source& source, EXPR&& val) {
2402 return create<ast::StructMemberOffsetAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002403 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002404
dan sinclair41e4d9a2022-05-01 14:40:55 +00002405 /// Creates a ast::StructMemberSizeAttribute
2406 /// @param source the source information
2407 /// @param val the size value
2408 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002409 template <typename EXPR>
2410 const ast::StructMemberSizeAttribute* MemberSize(const Source& source, EXPR&& val) {
2411 return create<ast::StructMemberSizeAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002412 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002413
dan sinclair41e4d9a2022-05-01 14:40:55 +00002414 /// Creates a ast::StructMemberSizeAttribute
2415 /// @param val the size value
2416 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002417 template <typename EXPR>
2418 const ast::StructMemberSizeAttribute* MemberSize(EXPR&& val) {
2419 return create<ast::StructMemberSizeAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002420 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002421
dan sinclair41e4d9a2022-05-01 14:40:55 +00002422 /// Creates a ast::StructMemberAlignAttribute
2423 /// @param source the source information
dan sinclair4964d9b2022-08-23 13:28:44 +00002424 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002425 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002426 template <typename EXPR>
2427 const ast::StructMemberAlignAttribute* MemberAlign(const Source& source, EXPR&& val) {
2428 return create<ast::StructMemberAlignAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002429 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002430
dan sinclair41e4d9a2022-05-01 14:40:55 +00002431 /// Creates a ast::StructMemberAlignAttribute
dan sinclair4964d9b2022-08-23 13:28:44 +00002432 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002433 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002434 template <typename EXPR>
2435 const ast::StructMemberAlignAttribute* MemberAlign(EXPR&& val) {
2436 return create<ast::StructMemberAlignAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002437 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002438
dan sinclair41e4d9a2022-05-01 14:40:55 +00002439 /// Creates the ast::GroupAttribute
dan sinclairbe4c9f42022-08-29 21:22:31 +00002440 /// @param value group attribute index expresion
dan sinclair41e4d9a2022-05-01 14:40:55 +00002441 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002442 template <typename EXPR>
2443 const ast::GroupAttribute* Group(EXPR&& value) {
2444 return create<ast::GroupAttribute>(Expr(std::forward<EXPR>(value)));
2445 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002446
dan sinclairf9b831c2022-08-29 21:13:00 +00002447 /// Creates the ast::GroupAttribute
2448 /// @param source the source
dan sinclairbe4c9f42022-08-29 21:22:31 +00002449 /// @param value group attribute index expression
dan sinclairf9b831c2022-08-29 21:13:00 +00002450 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002451 template <typename EXPR>
2452 const ast::GroupAttribute* Group(const Source& source, EXPR&& value) {
2453 return create<ast::GroupAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclairf9b831c2022-08-29 21:13:00 +00002454 }
2455
dan sinclair41e4d9a2022-05-01 14:40:55 +00002456 /// Creates the ast::BindingAttribute
dan sinclairf9b831c2022-08-29 21:13:00 +00002457 /// @param value the binding index expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002458 /// @returns the binding deocration pointer
dan sinclairf9b831c2022-08-29 21:13:00 +00002459 template <typename EXPR>
2460 const ast::BindingAttribute* Binding(EXPR&& value) {
2461 return create<ast::BindingAttribute>(Expr(std::forward<EXPR>(value)));
2462 }
2463
2464 /// Creates the ast::BindingAttribute
2465 /// @param source the source
2466 /// @param value the binding index expression
2467 /// @returns the binding deocration pointer
2468 template <typename EXPR>
2469 const ast::BindingAttribute* Binding(const Source& source, EXPR&& value) {
2470 return create<ast::BindingAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002471 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002472
dan sinclair41e4d9a2022-05-01 14:40:55 +00002473 /// Creates an ast::Function and registers it with the ast::Module.
2474 /// @param source the source information
2475 /// @param name the function name
2476 /// @param params the function parameters
2477 /// @param type the function return type
2478 /// @param body the function body
2479 /// @param attributes the optional function attributes
2480 /// @param return_type_attributes the optional function return type
2481 /// attributes
2482 /// @returns the function pointer
2483 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002484 const ast::Function* Func(
2485 const Source& source,
2486 NAME&& name,
2487 utils::VectorRef<const ast::Parameter*> params,
2488 const ast::Type* type,
2489 utils::VectorRef<const ast::Statement*> body,
2490 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
2491 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2492 auto* func =
2493 create<ast::Function>(source, Sym(std::forward<NAME>(name)), std::move(params), type,
2494 create<ast::BlockStatement>(std::move(body)),
2495 std::move(attributes), std::move(return_type_attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002496 AST().AddFunction(func);
2497 return func;
2498 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002499
dan sinclair41e4d9a2022-05-01 14:40:55 +00002500 /// Creates an ast::Function and registers it with the ast::Module.
2501 /// @param name the function name
2502 /// @param params the function parameters
2503 /// @param type the function return type
2504 /// @param body the function body
2505 /// @param attributes the optional function attributes
2506 /// @param return_type_attributes the optional function return type
2507 /// attributes
2508 /// @returns the function pointer
2509 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002510 const ast::Function* Func(
2511 NAME&& name,
2512 utils::VectorRef<const ast::Parameter*> params,
2513 const ast::Type* type,
2514 utils::VectorRef<const ast::Statement*> body,
2515 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
2516 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2517 auto* func =
2518 create<ast::Function>(Sym(std::forward<NAME>(name)), std::move(params), type,
2519 create<ast::BlockStatement>(std::move(body)),
2520 std::move(attributes), std::move(return_type_attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002521 AST().AddFunction(func);
2522 return func;
2523 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002524
dan sinclair41e4d9a2022-05-01 14:40:55 +00002525 /// Creates an ast::BreakStatement
2526 /// @param source the source information
2527 /// @returns the break statement pointer
2528 const ast::BreakStatement* Break(const Source& source) {
2529 return create<ast::BreakStatement>(source);
2530 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002531
dan sinclair41e4d9a2022-05-01 14:40:55 +00002532 /// Creates an ast::BreakStatement
2533 /// @returns the break statement pointer
2534 const ast::BreakStatement* Break() { return create<ast::BreakStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002535
dan sinclairb8b0c212022-10-20 22:45:50 +00002536 /// Creates a ast::BreakIfStatement with input condition
2537 /// @param source the source information for the if statement
2538 /// @param condition the if statement condition expression
2539 /// @returns the break-if statement pointer
2540 template <typename CONDITION>
2541 const ast::BreakIfStatement* BreakIf(const Source& source, CONDITION&& condition) {
2542 return create<ast::BreakIfStatement>(source, Expr(std::forward<CONDITION>(condition)));
2543 }
2544
2545 /// Creates a ast::BreakIfStatement with input condition
2546 /// @param condition the if statement condition expression
2547 /// @returns the break-if statement pointer
2548 template <typename CONDITION>
2549 const ast::BreakIfStatement* BreakIf(CONDITION&& condition) {
2550 return create<ast::BreakIfStatement>(Expr(std::forward<CONDITION>(condition)));
2551 }
2552
dan sinclair41e4d9a2022-05-01 14:40:55 +00002553 /// Creates an ast::ContinueStatement
2554 /// @param source the source information
2555 /// @returns the continue statement pointer
2556 const ast::ContinueStatement* Continue(const Source& source) {
2557 return create<ast::ContinueStatement>(source);
2558 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002559
dan sinclair41e4d9a2022-05-01 14:40:55 +00002560 /// Creates an ast::ContinueStatement
2561 /// @returns the continue statement pointer
2562 const ast::ContinueStatement* Continue() { return create<ast::ContinueStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002563
dan sinclair41e4d9a2022-05-01 14:40:55 +00002564 /// Creates an ast::ReturnStatement with no return value
2565 /// @param source the source information
2566 /// @returns the return statement pointer
2567 const ast::ReturnStatement* Return(const Source& source) {
2568 return create<ast::ReturnStatement>(source);
2569 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002570
dan sinclair41e4d9a2022-05-01 14:40:55 +00002571 /// Creates an ast::ReturnStatement with no return value
2572 /// @returns the return statement pointer
2573 const ast::ReturnStatement* Return() { return create<ast::ReturnStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002574
dan sinclair41e4d9a2022-05-01 14:40:55 +00002575 /// Creates an ast::ReturnStatement with the given return value
2576 /// @param source the source information
2577 /// @param val the return value
2578 /// @returns the return statement pointer
2579 template <typename EXPR>
2580 const ast::ReturnStatement* Return(const Source& source, EXPR&& val) {
2581 return create<ast::ReturnStatement>(source, Expr(std::forward<EXPR>(val)));
2582 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002583
dan sinclair41e4d9a2022-05-01 14:40:55 +00002584 /// Creates an ast::ReturnStatement with the given return value
2585 /// @param val the return value
2586 /// @returns the return statement pointer
2587 template <typename EXPR, typename = DisableIfSource<EXPR>>
2588 const ast::ReturnStatement* Return(EXPR&& val) {
2589 return create<ast::ReturnStatement>(Expr(std::forward<EXPR>(val)));
2590 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002591
dan sinclair41e4d9a2022-05-01 14:40:55 +00002592 /// Creates an ast::DiscardStatement
2593 /// @param source the source information
2594 /// @returns the discard statement pointer
2595 const ast::DiscardStatement* Discard(const Source& source) {
2596 return create<ast::DiscardStatement>(source);
2597 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002598
dan sinclair41e4d9a2022-05-01 14:40:55 +00002599 /// Creates an ast::DiscardStatement
2600 /// @returns the discard statement pointer
2601 const ast::DiscardStatement* Discard() { return create<ast::DiscardStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002602
dan sinclair41e4d9a2022-05-01 14:40:55 +00002603 /// Creates a ast::Alias registering it with the AST().TypeDecls().
2604 /// @param source the source information
2605 /// @param name the alias name
2606 /// @param type the alias target type
2607 /// @returns the alias type
2608 template <typename NAME>
2609 const ast::Alias* Alias(const Source& source, NAME&& name, const ast::Type* type) {
2610 auto* out = ty.alias(source, std::forward<NAME>(name), type);
2611 AST().AddTypeDecl(out);
2612 return out;
2613 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002614
dan sinclair41e4d9a2022-05-01 14:40:55 +00002615 /// Creates a ast::Alias registering it with the AST().TypeDecls().
2616 /// @param name the alias name
2617 /// @param type the alias target type
2618 /// @returns the alias type
2619 template <typename NAME>
2620 const ast::Alias* Alias(NAME&& name, const ast::Type* type) {
2621 auto* out = ty.alias(std::forward<NAME>(name), type);
2622 AST().AddTypeDecl(out);
2623 return out;
2624 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002625
dan sinclair41e4d9a2022-05-01 14:40:55 +00002626 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2627 /// @param source the source information
2628 /// @param name the struct name
2629 /// @param members the struct members
2630 /// @returns the struct type
2631 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002632 const ast::Struct* Structure(const Source& source,
2633 NAME&& name,
2634 utils::VectorRef<const ast::StructMember*> members) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002635 auto sym = Sym(std::forward<NAME>(name));
Ben Clayton783b1692022-08-02 17:03:35 +00002636 auto* type = create<ast::Struct>(source, sym, std::move(members), utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002637 AST().AddTypeDecl(type);
2638 return type;
2639 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002640
dan sinclair41e4d9a2022-05-01 14:40:55 +00002641 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2642 /// @param name the struct name
2643 /// @param members the struct members
2644 /// @returns the struct type
2645 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002646 const ast::Struct* Structure(NAME&& name, utils::VectorRef<const ast::StructMember*> members) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002647 auto sym = Sym(std::forward<NAME>(name));
Ben Clayton783b1692022-08-02 17:03:35 +00002648 auto* type = create<ast::Struct>(sym, std::move(members), utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002649 AST().AddTypeDecl(type);
2650 return type;
2651 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002652
dan sinclair41e4d9a2022-05-01 14:40:55 +00002653 /// Creates a ast::StructMember
2654 /// @param source the source information
2655 /// @param name the struct member name
2656 /// @param type the struct member type
2657 /// @param attributes the optional struct member attributes
2658 /// @returns the struct member pointer
2659 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002660 const ast::StructMember* Member(
2661 const Source& source,
2662 NAME&& name,
2663 const ast::Type* type,
2664 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002665 return create<ast::StructMember>(source, Sym(std::forward<NAME>(name)), type,
2666 std::move(attributes));
2667 }
2668
2669 /// Creates a ast::StructMember
2670 /// @param name the struct member name
2671 /// @param type the struct member type
2672 /// @param attributes the optional struct member attributes
2673 /// @returns the struct member pointer
2674 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002675 const ast::StructMember* Member(
2676 NAME&& name,
2677 const ast::Type* type,
2678 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002679 return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
2680 std::move(attributes));
2681 }
2682
2683 /// Creates a ast::StructMember with the given byte offset
Ben Clayton783b1692022-08-02 17:03:35 +00002684 /// @param offset the offset to use in the StructMemberOffsetAttribute
dan sinclair41e4d9a2022-05-01 14:40:55 +00002685 /// @param name the struct member name
2686 /// @param type the struct member type
2687 /// @returns the struct member pointer
2688 template <typename NAME>
2689 const ast::StructMember* Member(uint32_t offset, NAME&& name, const ast::Type* type) {
2690 return create<ast::StructMember>(source_, Sym(std::forward<NAME>(name)), type,
Ben Clayton783b1692022-08-02 17:03:35 +00002691 utils::Vector<const ast::Attribute*, 1>{
dan sinclair93df9672022-09-09 14:49:09 +00002692 MemberOffset(AInt(offset)),
dan sinclair41e4d9a2022-05-01 14:40:55 +00002693 });
2694 }
2695
2696 /// Creates a ast::BlockStatement with input statements
2697 /// @param source the source information for the block
2698 /// @param statements statements of block
2699 /// @returns the block statement pointer
2700 template <typename... Statements>
2701 const ast::BlockStatement* Block(const Source& source, Statements&&... statements) {
2702 return create<ast::BlockStatement>(
Ben Clayton783b1692022-08-02 17:03:35 +00002703 source, utils::Vector<const ast::Statement*, sizeof...(statements)>{
2704 std::forward<Statements>(statements)...,
2705 });
dan sinclair41e4d9a2022-05-01 14:40:55 +00002706 }
2707
2708 /// Creates a ast::BlockStatement with input statements
2709 /// @param statements statements of block
2710 /// @returns the block statement pointer
2711 template <typename... STATEMENTS, typename = DisableIfSource<STATEMENTS...>>
2712 const ast::BlockStatement* Block(STATEMENTS&&... statements) {
2713 return create<ast::BlockStatement>(
Ben Clayton783b1692022-08-02 17:03:35 +00002714 utils::Vector<const ast::Statement*, sizeof...(statements)>{
2715 std::forward<STATEMENTS>(statements)...,
2716 });
dan sinclair41e4d9a2022-05-01 14:40:55 +00002717 }
2718
James Price8aff0ed2022-05-02 14:53:36 +00002719 /// A wrapper type for the Else statement used to create If statements.
2720 struct ElseStmt {
2721 /// Default constructor - no else statement.
2722 ElseStmt() : stmt(nullptr) {}
2723 /// Constructor
2724 /// @param s The else statement
2725 explicit ElseStmt(const ast::Statement* s) : stmt(s) {}
2726 /// The else statement, or nullptr.
2727 const ast::Statement* stmt;
2728 };
2729
dan sinclair41e4d9a2022-05-01 14:40:55 +00002730 /// Creates a ast::IfStatement with input condition, body, and optional
2731 /// else statement
2732 /// @param source the source information for the if statement
2733 /// @param condition the if statement condition expression
2734 /// @param body the if statement body
2735 /// @param else_stmt optional else statement
2736 /// @returns the if statement pointer
2737 template <typename CONDITION>
2738 const ast::IfStatement* If(const Source& source,
2739 CONDITION&& condition,
2740 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002741 const ElseStmt else_stmt = ElseStmt()) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002742 return create<ast::IfStatement>(source, Expr(std::forward<CONDITION>(condition)), body,
James Price8aff0ed2022-05-02 14:53:36 +00002743 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002744 }
2745
2746 /// Creates a ast::IfStatement with input condition, body, and optional
2747 /// else statement
2748 /// @param condition the if statement condition expression
2749 /// @param body the if statement body
2750 /// @param else_stmt optional else statement
2751 /// @returns the if statement pointer
2752 template <typename CONDITION>
2753 const ast::IfStatement* If(CONDITION&& condition,
2754 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002755 const ElseStmt else_stmt = ElseStmt()) {
2756 return create<ast::IfStatement>(Expr(std::forward<CONDITION>(condition)), body,
2757 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002758 }
2759
James Price8aff0ed2022-05-02 14:53:36 +00002760 /// Creates an Else object.
2761 /// @param stmt else statement
2762 /// @returns the Else object
2763 ElseStmt Else(const ast::Statement* stmt) { return ElseStmt(stmt); }
2764
dan sinclair41e4d9a2022-05-01 14:40:55 +00002765 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2766 /// @param source the source information
2767 /// @param lhs the left hand side expression initializer
2768 /// @param rhs the right hand side expression initializer
2769 /// @returns the assignment statement pointer
2770 template <typename LhsExpressionInit, typename RhsExpressionInit>
2771 const ast::AssignmentStatement* Assign(const Source& source,
2772 LhsExpressionInit&& lhs,
2773 RhsExpressionInit&& rhs) {
2774 return create<ast::AssignmentStatement>(source, Expr(std::forward<LhsExpressionInit>(lhs)),
2775 Expr(std::forward<RhsExpressionInit>(rhs)));
2776 }
2777
2778 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2779 /// @param lhs the left hand side expression initializer
2780 /// @param rhs the right hand side expression initializer
2781 /// @returns the assignment statement pointer
2782 template <typename LhsExpressionInit, typename RhsExpressionInit>
2783 const ast::AssignmentStatement* Assign(LhsExpressionInit&& lhs, RhsExpressionInit&& rhs) {
2784 return create<ast::AssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2785 Expr(std::forward<RhsExpressionInit>(rhs)));
2786 }
2787
2788 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2789 /// expressions, and a binary operator.
2790 /// @param source the source information
2791 /// @param lhs the left hand side expression initializer
2792 /// @param rhs the right hand side expression initializer
2793 /// @param op the binary operator
2794 /// @returns the compound assignment statement pointer
2795 template <typename LhsExpressionInit, typename RhsExpressionInit>
2796 const ast::CompoundAssignmentStatement* CompoundAssign(const Source& source,
2797 LhsExpressionInit&& lhs,
2798 RhsExpressionInit&& rhs,
2799 ast::BinaryOp op) {
2800 return create<ast::CompoundAssignmentStatement>(
2801 source, Expr(std::forward<LhsExpressionInit>(lhs)),
2802 Expr(std::forward<RhsExpressionInit>(rhs)), op);
2803 }
2804
2805 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2806 /// expressions, and a binary operator.
2807 /// @param lhs the left hand side expression initializer
2808 /// @param rhs the right hand side expression initializer
2809 /// @param op the binary operator
2810 /// @returns the compound assignment statement pointer
2811 template <typename LhsExpressionInit, typename RhsExpressionInit>
2812 const ast::CompoundAssignmentStatement* CompoundAssign(LhsExpressionInit&& lhs,
2813 RhsExpressionInit&& rhs,
2814 ast::BinaryOp op) {
2815 return create<ast::CompoundAssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2816 Expr(std::forward<RhsExpressionInit>(rhs)),
2817 op);
2818 }
2819
2820 /// Creates an ast::IncrementDecrementStatement with input lhs.
2821 /// @param source the source information
2822 /// @param lhs the left hand side expression initializer
2823 /// @returns the increment decrement statement pointer
2824 template <typename LhsExpressionInit>
2825 const ast::IncrementDecrementStatement* Increment(const Source& source,
2826 LhsExpressionInit&& lhs) {
2827 return create<ast::IncrementDecrementStatement>(
2828 source, Expr(std::forward<LhsExpressionInit>(lhs)), true);
2829 }
2830
2831 /// Creates a ast::IncrementDecrementStatement with input lhs.
2832 /// @param lhs the left hand side expression initializer
2833 /// @returns the increment decrement statement pointer
2834 template <typename LhsExpressionInit>
2835 const ast::IncrementDecrementStatement* Increment(LhsExpressionInit&& lhs) {
2836 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2837 true);
2838 }
2839
2840 /// Creates an ast::IncrementDecrementStatement with input lhs.
2841 /// @param source the source information
2842 /// @param lhs the left hand side expression initializer
2843 /// @returns the increment decrement statement pointer
2844 template <typename LhsExpressionInit>
2845 const ast::IncrementDecrementStatement* Decrement(const Source& source,
2846 LhsExpressionInit&& lhs) {
2847 return create<ast::IncrementDecrementStatement>(
2848 source, Expr(std::forward<LhsExpressionInit>(lhs)), false);
2849 }
2850
2851 /// Creates a ast::IncrementDecrementStatement with input lhs.
2852 /// @param lhs the left hand side expression initializer
2853 /// @returns the increment decrement statement pointer
2854 template <typename LhsExpressionInit>
2855 const ast::IncrementDecrementStatement* Decrement(LhsExpressionInit&& lhs) {
2856 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2857 false);
2858 }
2859
2860 /// Creates a ast::LoopStatement with input body and optional continuing
2861 /// @param source the source information
2862 /// @param body the loop body
2863 /// @param continuing the optional continuing block
2864 /// @returns the loop statement pointer
2865 const ast::LoopStatement* Loop(const Source& source,
2866 const ast::BlockStatement* body,
2867 const ast::BlockStatement* continuing = nullptr) {
2868 return create<ast::LoopStatement>(source, body, continuing);
2869 }
2870
2871 /// Creates a ast::LoopStatement with input body and optional continuing
2872 /// @param body the loop body
2873 /// @param continuing the optional continuing block
2874 /// @returns the loop statement pointer
2875 const ast::LoopStatement* Loop(const ast::BlockStatement* body,
2876 const ast::BlockStatement* continuing = nullptr) {
2877 return create<ast::LoopStatement>(body, continuing);
2878 }
2879
2880 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2881 /// condition and continuing.
2882 /// @param source the source information
2883 /// @param init the optional loop initializer
2884 /// @param cond the optional loop condition
2885 /// @param cont the optional loop continuing
2886 /// @param body the loop body
2887 /// @returns the for loop statement pointer
2888 template <typename COND>
2889 const ast::ForLoopStatement* For(const Source& source,
2890 const ast::Statement* init,
2891 COND&& cond,
2892 const ast::Statement* cont,
2893 const ast::BlockStatement* body) {
2894 return create<ast::ForLoopStatement>(source, init, Expr(std::forward<COND>(cond)), cont,
2895 body);
2896 }
2897
2898 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2899 /// condition and continuing.
2900 /// @param init the optional loop initializer
2901 /// @param cond the optional loop condition
2902 /// @param cont the optional loop continuing
2903 /// @param body the loop body
2904 /// @returns the for loop statement pointer
2905 template <typename COND>
2906 const ast::ForLoopStatement* For(const ast::Statement* init,
2907 COND&& cond,
2908 const ast::Statement* cont,
2909 const ast::BlockStatement* body) {
2910 return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), cont, body);
2911 }
2912
dan sinclair49d1a2d2022-06-16 12:01:27 +00002913 /// Creates a ast::WhileStatement with input body and condition.
2914 /// @param source the source information
2915 /// @param cond the loop condition
2916 /// @param body the loop body
2917 /// @returns the while statement pointer
2918 template <typename COND>
2919 const ast::WhileStatement* While(const Source& source,
2920 COND&& cond,
2921 const ast::BlockStatement* body) {
2922 return create<ast::WhileStatement>(source, Expr(std::forward<COND>(cond)), body);
2923 }
2924
2925 /// Creates a ast::WhileStatement with given condition and body.
2926 /// @param cond the condition
2927 /// @param body the loop body
2928 /// @returns the while loop statement pointer
2929 template <typename COND>
2930 const ast::WhileStatement* While(COND&& cond, const ast::BlockStatement* body) {
2931 return create<ast::WhileStatement>(Expr(std::forward<COND>(cond)), body);
2932 }
2933
dan sinclair41e4d9a2022-05-01 14:40:55 +00002934 /// Creates a ast::VariableDeclStatement for the input variable
2935 /// @param source the source information
2936 /// @param var the variable to wrap in a decl statement
2937 /// @returns the variable decl statement pointer
2938 const ast::VariableDeclStatement* Decl(const Source& source, const ast::Variable* var) {
2939 return create<ast::VariableDeclStatement>(source, var);
2940 }
2941
2942 /// Creates a ast::VariableDeclStatement for the input variable
2943 /// @param var the variable to wrap in a decl statement
2944 /// @returns the variable decl statement pointer
2945 const ast::VariableDeclStatement* Decl(const ast::Variable* var) {
2946 return create<ast::VariableDeclStatement>(var);
2947 }
2948
2949 /// Creates a ast::SwitchStatement with input expression and cases
2950 /// @param source the source information
2951 /// @param condition the condition expression initializer
2952 /// @param cases case statements
2953 /// @returns the switch statement pointer
2954 template <typename ExpressionInit, typename... Cases>
2955 const ast::SwitchStatement* Switch(const Source& source,
2956 ExpressionInit&& condition,
2957 Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00002958 return create<ast::SwitchStatement>(
2959 source, Expr(std::forward<ExpressionInit>(condition)),
2960 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
2961 std::forward<Cases>(cases)...});
dan sinclair41e4d9a2022-05-01 14:40:55 +00002962 }
2963
2964 /// Creates a ast::SwitchStatement with input expression and cases
2965 /// @param condition the condition expression initializer
2966 /// @param cases case statements
2967 /// @returns the switch statement pointer
2968 template <typename ExpressionInit,
2969 typename... Cases,
2970 typename = DisableIfSource<ExpressionInit>>
2971 const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00002972 return create<ast::SwitchStatement>(
2973 Expr(std::forward<ExpressionInit>(condition)),
2974 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
2975 std::forward<Cases>(cases)...});
dan sinclair41e4d9a2022-05-01 14:40:55 +00002976 }
2977
2978 /// Creates a ast::CaseStatement with input list of selectors, and body
2979 /// @param source the source information
2980 /// @param selectors list of selectors
2981 /// @param body the case body
2982 /// @returns the case statement pointer
2983 const ast::CaseStatement* Case(const Source& source,
dan sinclairf148f082022-10-19 15:55:02 +00002984 utils::VectorRef<const ast::CaseSelector*> selectors,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002985 const ast::BlockStatement* body = nullptr) {
2986 return create<ast::CaseStatement>(source, std::move(selectors), body ? body : Block());
2987 }
2988
2989 /// Creates a ast::CaseStatement with input list of selectors, and body
2990 /// @param selectors list of selectors
2991 /// @param body the case body
2992 /// @returns the case statement pointer
dan sinclairf148f082022-10-19 15:55:02 +00002993 const ast::CaseStatement* Case(utils::VectorRef<const ast::CaseSelector*> selectors,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002994 const ast::BlockStatement* body = nullptr) {
2995 return create<ast::CaseStatement>(std::move(selectors), body ? body : Block());
2996 }
2997
2998 /// Convenient overload that takes a single selector
2999 /// @param selector a single case selector
3000 /// @param body the case body
3001 /// @returns the case statement pointer
dan sinclairf148f082022-10-19 15:55:02 +00003002 const ast::CaseStatement* Case(const ast::CaseSelector* selector,
dan sinclair41e4d9a2022-05-01 14:40:55 +00003003 const ast::BlockStatement* body = nullptr) {
Ben Clayton783b1692022-08-02 17:03:35 +00003004 return Case(utils::Vector{selector}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003005 }
3006
3007 /// Convenience function that creates a 'default' ast::CaseStatement
3008 /// @param source the source information
3009 /// @param body the case body
3010 /// @returns the case statement pointer
3011 const ast::CaseStatement* DefaultCase(const Source& source,
3012 const ast::BlockStatement* body = nullptr) {
dan sinclairf148f082022-10-19 15:55:02 +00003013 return Case(source, utils::Vector{DefaultCaseSelector(source)}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003014 }
3015
3016 /// Convenience function that creates a 'default' ast::CaseStatement
3017 /// @param body the case body
3018 /// @returns the case statement pointer
3019 const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) {
dan sinclairf148f082022-10-19 15:55:02 +00003020 return Case(utils::Vector{DefaultCaseSelector()}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003021 }
3022
dan sinclairf148f082022-10-19 15:55:02 +00003023 /// Convenience function that creates a case selector
3024 /// @param source the source information
3025 /// @param expr the selector expression
3026 /// @returns the selector pointer
3027 template <typename EXPR>
3028 const ast::CaseSelector* CaseSelector(const Source& source, EXPR&& expr) {
3029 return create<ast::CaseSelector>(source, Expr(std::forward<EXPR>(expr)));
3030 }
3031
3032 /// Convenience function that creates a case selector
3033 /// @param expr the selector expression
3034 /// @returns the selector pointer
3035 template <typename EXPR>
3036 const ast::CaseSelector* CaseSelector(EXPR&& expr) {
3037 return create<ast::CaseSelector>(source_, Expr(std::forward<EXPR>(expr)));
3038 }
3039
3040 /// Convenience function that creates a default case selector
3041 /// @param source the source information
3042 /// @returns the selector pointer
3043 const ast::CaseSelector* DefaultCaseSelector(const Source& source) {
3044 return create<ast::CaseSelector>(source, nullptr);
3045 }
3046
3047 /// Convenience function that creates a default case selector
3048 /// @returns the selector pointer
3049 const ast::CaseSelector* DefaultCaseSelector() { return create<ast::CaseSelector>(nullptr); }
3050
dan sinclair41e4d9a2022-05-01 14:40:55 +00003051 /// Creates an ast::BuiltinAttribute
3052 /// @param source the source information
3053 /// @param builtin the builtin value
3054 /// @returns the builtin attribute pointer
Ben Claytonf3302292022-07-27 18:48:06 +00003055 const ast::BuiltinAttribute* Builtin(const Source& source, ast::BuiltinValue builtin) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003056 return create<ast::BuiltinAttribute>(source, builtin);
3057 }
3058
3059 /// Creates an ast::BuiltinAttribute
3060 /// @param builtin the builtin value
3061 /// @returns the builtin attribute pointer
Ben Claytonf3302292022-07-27 18:48:06 +00003062 const ast::BuiltinAttribute* Builtin(ast::BuiltinValue builtin) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003063 return create<ast::BuiltinAttribute>(source_, builtin);
3064 }
3065
3066 /// Creates an ast::InterpolateAttribute
3067 /// @param source the source information
3068 /// @param type the interpolation type
3069 /// @param sampling the interpolation sampling
3070 /// @returns the interpolate attribute pointer
3071 const ast::InterpolateAttribute* Interpolate(
3072 const Source& source,
3073 ast::InterpolationType type,
Ben Claytond2e0db32022-10-12 18:49:15 +00003074 ast::InterpolationSampling sampling = ast::InterpolationSampling::kUndefined) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003075 return create<ast::InterpolateAttribute>(source, type, sampling);
3076 }
3077
3078 /// Creates an ast::InterpolateAttribute
3079 /// @param type the interpolation type
3080 /// @param sampling the interpolation sampling
3081 /// @returns the interpolate attribute pointer
3082 const ast::InterpolateAttribute* Interpolate(
3083 ast::InterpolationType type,
Ben Claytond2e0db32022-10-12 18:49:15 +00003084 ast::InterpolationSampling sampling = ast::InterpolationSampling::kUndefined) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003085 return create<ast::InterpolateAttribute>(source_, type, sampling);
3086 }
3087
3088 /// Creates an ast::InterpolateAttribute using flat interpolation
3089 /// @param source the source information
3090 /// @returns the interpolate attribute pointer
3091 const ast::InterpolateAttribute* Flat(const Source& source) {
3092 return Interpolate(source, ast::InterpolationType::kFlat);
3093 }
3094
3095 /// Creates an ast::InterpolateAttribute using flat interpolation
3096 /// @returns the interpolate attribute pointer
3097 const ast::InterpolateAttribute* Flat() { return Interpolate(ast::InterpolationType::kFlat); }
3098
3099 /// Creates an ast::InvariantAttribute
3100 /// @param source the source information
3101 /// @returns the invariant attribute pointer
3102 const ast::InvariantAttribute* Invariant(const Source& source) {
3103 return create<ast::InvariantAttribute>(source);
3104 }
3105
3106 /// Creates an ast::InvariantAttribute
3107 /// @returns the invariant attribute pointer
3108 const ast::InvariantAttribute* Invariant() { return create<ast::InvariantAttribute>(source_); }
3109
3110 /// Creates an ast::LocationAttribute
3111 /// @param source the source information
dan sinclairf9eeed62022-09-07 22:25:24 +00003112 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003113 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003114 template <typename EXPR>
3115 const ast::LocationAttribute* Location(const Source& source, EXPR&& location) {
3116 return create<ast::LocationAttribute>(source, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003117 }
3118
3119 /// Creates an ast::LocationAttribute
dan sinclairf9eeed62022-09-07 22:25:24 +00003120 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003121 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003122 template <typename EXPR>
3123 const ast::LocationAttribute* Location(EXPR&& location) {
3124 return create<ast::LocationAttribute>(source_, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003125 }
3126
3127 /// Creates an ast::IdAttribute
3128 /// @param source the source information
3129 /// @param id the id value
3130 /// @returns the override attribute pointer
Ben Clayton9a6acc42022-07-27 20:50:40 +00003131 const ast::IdAttribute* Id(const Source& source, OverrideId id) {
dan sinclair5361d9e2022-08-31 13:39:48 +00003132 return create<ast::IdAttribute>(source, Expr(AInt(id.value)));
Ben Clayton9a6acc42022-07-27 20:50:40 +00003133 }
3134
3135 /// Creates an ast::IdAttribute with an override identifier
3136 /// @param id the optional id value
3137 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003138 const ast::IdAttribute* Id(OverrideId id) {
3139 return create<ast::IdAttribute>(Expr(AInt(id.value)));
3140 }
Ben Clayton9a6acc42022-07-27 20:50:40 +00003141
3142 /// Creates an ast::IdAttribute
3143 /// @param source the source information
dan sinclair5361d9e2022-08-31 13:39:48 +00003144 /// @param id the id value expression
Ben Clayton9a6acc42022-07-27 20:50:40 +00003145 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003146 template <typename EXPR>
3147 const ast::IdAttribute* Id(const Source& source, EXPR&& id) {
3148 return create<ast::IdAttribute>(source, Expr(std::forward<EXPR>(id)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003149 }
3150
Ben Clayton9a6acc42022-07-27 20:50:40 +00003151 /// Creates an ast::IdAttribute with an override identifier
dan sinclair5361d9e2022-08-31 13:39:48 +00003152 /// @param id the optional id value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003153 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003154 template <typename EXPR>
3155 const ast::IdAttribute* Id(EXPR&& id) {
3156 return create<ast::IdAttribute>(Expr(std::forward<EXPR>(id)));
3157 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00003158
3159 /// Creates an ast::StageAttribute
3160 /// @param source the source information
3161 /// @param stage the pipeline stage
3162 /// @returns the stage attribute pointer
3163 const ast::StageAttribute* Stage(const Source& source, ast::PipelineStage stage) {
3164 return create<ast::StageAttribute>(source, stage);
3165 }
3166
3167 /// Creates an ast::StageAttribute
3168 /// @param stage the pipeline stage
3169 /// @returns the stage attribute pointer
3170 const ast::StageAttribute* Stage(ast::PipelineStage stage) {
3171 return create<ast::StageAttribute>(source_, stage);
3172 }
3173
3174 /// Creates an ast::WorkgroupAttribute
3175 /// @param x the x dimension expression
3176 /// @returns the workgroup attribute pointer
3177 template <typename EXPR_X>
3178 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x) {
3179 return WorkgroupSize(std::forward<EXPR_X>(x), nullptr, nullptr);
3180 }
3181
3182 /// Creates an ast::WorkgroupAttribute
Ben Claytonb8ac9332022-05-28 10:34:06 +00003183 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00003184 /// @param x the x dimension expression
dan sinclair7517e212022-08-24 21:31:45 +00003185 /// @returns the workgroup attribute pointer
3186 template <typename EXPR_X>
3187 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x) {
3188 return WorkgroupSize(source, std::forward<EXPR_X>(x), nullptr, nullptr);
3189 }
3190
3191 /// Creates an ast::WorkgroupAttribute
3192 /// @param source the source information
3193 /// @param x the x dimension expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003194 /// @param y the y dimension expression
3195 /// @returns the workgroup attribute pointer
3196 template <typename EXPR_X, typename EXPR_Y>
Ben Claytonb8ac9332022-05-28 10:34:06 +00003197 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x, EXPR_Y&& y) {
3198 return WorkgroupSize(source, std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3199 }
3200
3201 /// Creates an ast::WorkgroupAttribute
3202 /// @param x the x dimension expression
3203 /// @param y the y dimension expression
3204 /// @returns the workgroup attribute pointer
3205 template <typename EXPR_X, typename EXPR_Y, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003206 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y) {
3207 return WorkgroupSize(std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3208 }
3209
3210 /// Creates an ast::WorkgroupAttribute
3211 /// @param source the source information
3212 /// @param x the x dimension expression
3213 /// @param y the y dimension expression
3214 /// @param z the z dimension expression
3215 /// @returns the workgroup attribute pointer
3216 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z>
3217 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source,
3218 EXPR_X&& x,
3219 EXPR_Y&& y,
3220 EXPR_Z&& z) {
3221 return create<ast::WorkgroupAttribute>(source, Expr(std::forward<EXPR_X>(x)),
3222 Expr(std::forward<EXPR_Y>(y)),
3223 Expr(std::forward<EXPR_Z>(z)));
3224 }
3225
3226 /// Creates an ast::WorkgroupAttribute
3227 /// @param x the x dimension expression
3228 /// @param y the y dimension expression
3229 /// @param z the z dimension expression
3230 /// @returns the workgroup attribute pointer
Ben Claytonb8ac9332022-05-28 10:34:06 +00003231 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003232 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y, EXPR_Z&& z) {
3233 return create<ast::WorkgroupAttribute>(source_, Expr(std::forward<EXPR_X>(x)),
3234 Expr(std::forward<EXPR_Y>(y)),
3235 Expr(std::forward<EXPR_Z>(z)));
3236 }
3237
3238 /// Creates an ast::DisableValidationAttribute
3239 /// @param validation the validation to disable
3240 /// @returns the disable validation attribute pointer
3241 const ast::DisableValidationAttribute* Disable(ast::DisabledValidation validation) {
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003242 return ASTNodes().Create<ast::DisableValidationAttribute>(ID(), AllocateNodeID(),
3243 validation);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003244 }
3245
3246 /// Sets the current builder source to `src`
3247 /// @param src the Source used for future create() calls
3248 void SetSource(const Source& src) {
3249 AssertNotMoved();
3250 source_ = src;
3251 }
3252
3253 /// Sets the current builder source to `loc`
3254 /// @param loc the Source used for future create() calls
3255 void SetSource(const Source::Location& loc) {
3256 AssertNotMoved();
3257 source_ = Source(loc);
3258 }
3259
3260 /// Helper for returning the resolved semantic type of the expression `expr`.
3261 /// @note As the Resolver is run when the Program is built, this will only be
3262 /// useful for the Resolver itself and tests that use their own Resolver.
3263 /// @param expr the AST expression
3264 /// @return the resolved semantic type for the expression, or nullptr if the
3265 /// expression has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003266 const type::Type* TypeOf(const ast::Expression* expr) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003267
3268 /// Helper for returning the resolved semantic type of the variable `var`.
3269 /// @note As the Resolver is run when the Program is built, this will only be
3270 /// useful for the Resolver itself and tests that use their own Resolver.
3271 /// @param var the AST variable
3272 /// @return the resolved semantic type for the variable, or nullptr if the
3273 /// variable has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003274 const type::Type* TypeOf(const ast::Variable* var) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003275
3276 /// Helper for returning the resolved semantic type of the AST type `type`.
3277 /// @note As the Resolver is run when the Program is built, this will only be
3278 /// useful for the Resolver itself and tests that use their own Resolver.
3279 /// @param type the AST type
3280 /// @return the resolved semantic type for the type, or nullptr if the type
3281 /// has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003282 const type::Type* TypeOf(const ast::Type* type) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003283
3284 /// Helper for returning the resolved semantic type of the AST type
3285 /// declaration `type_decl`.
3286 /// @note As the Resolver is run when the Program is built, this will only be
3287 /// useful for the Resolver itself and tests that use their own Resolver.
3288 /// @param type_decl the AST type declaration
3289 /// @return the resolved semantic type for the type declaration, or nullptr if
3290 /// the type declaration has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003291 const type::Type* TypeOf(const ast::TypeDecl* type_decl) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003292
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003293 /// @param type a type
3294 /// @returns the name for `type` that closely resembles how it would be
3295 /// declared in WGSL.
Ben Claytond7d71882022-09-05 20:51:23 +00003296 std::string FriendlyName(const ast::Type* type) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003297
3298 /// @param type a type
3299 /// @returns the name for `type` that closely resembles how it would be
3300 /// declared in WGSL.
dan sinclair5f764d82022-12-08 00:32:27 +00003301 std::string FriendlyName(const type::Type* type) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003302
3303 /// Overload of FriendlyName, which removes an ambiguity when passing nullptr.
3304 /// Simplifies test code.
3305 /// @returns "<null>"
Ben Claytond7d71882022-09-05 20:51:23 +00003306 std::string FriendlyName(std::nullptr_t) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003307
dan sinclair41e4d9a2022-05-01 14:40:55 +00003308 /// Wraps the ast::Expression in a statement. This is used by tests that
3309 /// construct a partial AST and require the Resolver to reach these
3310 /// nodes.
3311 /// @param expr the ast::Expression to be wrapped by an ast::Statement
3312 /// @return the ast::Statement that wraps the ast::Expression
3313 const ast::Statement* WrapInStatement(const ast::Expression* expr);
3314 /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by
3315 /// tests that construct a partial AST and require the Resolver to reach
3316 /// these nodes.
3317 /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement
3318 /// @return the ast::VariableDeclStatement that wraps the ast::Variable
3319 const ast::VariableDeclStatement* WrapInStatement(const ast::Variable* v);
3320 /// Returns the statement argument. Used as a passthrough-overload by
3321 /// WrapInFunction().
3322 /// @param stmt the ast::Statement
3323 /// @return `stmt`
3324 const ast::Statement* WrapInStatement(const ast::Statement* stmt);
3325 /// Wraps the list of arguments in a simple function so that each is reachable
3326 /// by the Resolver.
3327 /// @param args a mix of ast::Expression, ast::Statement, ast::Variables.
3328 /// @returns the function
3329 template <typename... ARGS>
3330 const ast::Function* WrapInFunction(ARGS&&... args) {
Ben Clayton783b1692022-08-02 17:03:35 +00003331 utils::Vector stmts{
3332 WrapInStatement(std::forward<ARGS>(args))...,
3333 };
3334 return WrapInFunction(utils::VectorRef<const ast::Statement*>{std::move(stmts)});
dan sinclair41e4d9a2022-05-01 14:40:55 +00003335 }
3336 /// @param stmts a list of ast::Statement that will be wrapped by a function,
3337 /// so that each statement is reachable by the Resolver.
3338 /// @returns the function
Ben Clayton783b1692022-08-02 17:03:35 +00003339 const ast::Function* WrapInFunction(utils::VectorRef<const ast::Statement*> stmts);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003340
3341 /// The builder types
3342 TypesBuilder const ty{this};
3343
3344 protected:
3345 /// Asserts that the builder has not been moved.
3346 void AssertNotMoved() const;
3347
3348 private:
3349 ProgramID id_;
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003350 ast::NodeID last_ast_node_id_ = ast::NodeID{static_cast<decltype(ast::NodeID::value)>(0) - 1};
dan sinclair837b8042022-12-09 05:00:07 +00003351 type::Manager types_;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003352 ASTNodeAllocator ast_nodes_;
3353 SemNodeAllocator sem_nodes_;
Ben Claytonaa037ac2022-06-29 19:07:30 +00003354 ConstantAllocator constant_nodes_;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003355 ast::Module* ast_;
3356 sem::Info sem_;
3357 SymbolTable symbols_{id_};
3358 diag::List diagnostics_;
3359
3360 /// The source to use when creating AST nodes without providing a Source as
3361 /// the first argument.
3362 Source source_;
3363
3364 /// Set by SetResolveOnBuild(). If set, the Resolver will be run on the
3365 /// program when built.
3366 bool resolve_on_build_ = true;
3367
3368 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder.
3369 bool moved_ = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003370};
3371
3372//! @cond Doxygen_Suppress
3373// Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
3374template <>
Ben Clayton46ee6392022-11-09 22:04:11 +00003375struct ProgramBuilder::TypesBuilder::CToAST<AInt> {
3376 static const ast::Type* get(const ProgramBuilder::TypesBuilder*) { return nullptr; }
3377};
3378template <>
3379struct ProgramBuilder::TypesBuilder::CToAST<AFloat> {
3380 static const ast::Type* get(const ProgramBuilder::TypesBuilder*) { return nullptr; }
3381};
3382template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003383struct ProgramBuilder::TypesBuilder::CToAST<i32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003384 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->i32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003385};
3386template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003387struct ProgramBuilder::TypesBuilder::CToAST<u32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003388 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->u32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003389};
3390template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003391struct ProgramBuilder::TypesBuilder::CToAST<f32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003392 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003393};
3394template <>
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00003395struct ProgramBuilder::TypesBuilder::CToAST<f16> {
3396 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f16(); }
3397};
3398template <>
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003399struct ProgramBuilder::TypesBuilder::CToAST<bool> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003400 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003401};
3402template <>
3403struct ProgramBuilder::TypesBuilder::CToAST<void> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003404 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->void_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003405};
3406//! @endcond
3407
3408/// @param builder the ProgramBuilder
3409/// @returns the ProgramID of the ProgramBuilder
3410inline ProgramID ProgramIDOf(const ProgramBuilder* builder) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003411 return builder->ID();
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003412}
3413
3414} // namespace tint
3415
3416#endif // SRC_TINT_PROGRAM_BUILDER_H_