blob: cbf532b6b5860668018726367f8b6252e1871b08 [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"
Ben Claytonc98d57d2023-01-24 14:59:43 +000040#include "src/tint/ast/const_assert.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000041#include "src/tint/ast/continue_statement.h"
42#include "src/tint/ast/depth_multisampled_texture.h"
43#include "src/tint/ast/depth_texture.h"
James Priceef5434d2023-01-24 18:44:27 +000044#include "src/tint/ast/diagnostic_attribute.h"
James Price5f3449f2023-01-23 17:55:55 +000045#include "src/tint/ast/diagnostic_control.h"
James Price98dc5a82023-02-04 12:20:55 +000046#include "src/tint/ast/diagnostic_directive.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000047#include "src/tint/ast/disable_validation_attribute.h"
48#include "src/tint/ast/discard_statement.h"
Zhaoming Jiang7098d3d2022-04-27 02:27:52 +000049#include "src/tint/ast/enable.h"
Ben Clayton7f2b8cd2022-05-18 22:41:48 +000050#include "src/tint/ast/extension.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000051#include "src/tint/ast/external_texture.h"
Zhaoming Jiang62bfd312022-05-13 12:01:11 +000052#include "src/tint/ast/f16.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000053#include "src/tint/ast/f32.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000054#include "src/tint/ast/float_literal_expression.h"
55#include "src/tint/ast/for_loop_statement.h"
56#include "src/tint/ast/i32.h"
57#include "src/tint/ast/id_attribute.h"
Ben Claytonc87b1fe2023-02-02 15:04:31 +000058#include "src/tint/ast/identifier.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000059#include "src/tint/ast/if_statement.h"
James Priceebe97412022-04-07 13:42:45 +000060#include "src/tint/ast/increment_decrement_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000061#include "src/tint/ast/index_accessor_expression.h"
dan sinclaird32fbe02022-10-19 00:43:41 +000062#include "src/tint/ast/int_literal_expression.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000063#include "src/tint/ast/interpolate_attribute.h"
64#include "src/tint/ast/invariant_attribute.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000065#include "src/tint/ast/let.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000066#include "src/tint/ast/loop_statement.h"
67#include "src/tint/ast/matrix.h"
68#include "src/tint/ast/member_accessor_expression.h"
69#include "src/tint/ast/module.h"
70#include "src/tint/ast/multisampled_texture.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000071#include "src/tint/ast/override.h"
72#include "src/tint/ast/parameter.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000073#include "src/tint/ast/phony_expression.h"
74#include "src/tint/ast/pointer.h"
75#include "src/tint/ast/return_statement.h"
76#include "src/tint/ast/sampled_texture.h"
77#include "src/tint/ast/sampler.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000078#include "src/tint/ast/stage_attribute.h"
79#include "src/tint/ast/storage_texture.h"
80#include "src/tint/ast/stride_attribute.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000081#include "src/tint/ast/struct_member_align_attribute.h"
82#include "src/tint/ast/struct_member_offset_attribute.h"
83#include "src/tint/ast/struct_member_size_attribute.h"
84#include "src/tint/ast/switch_statement.h"
Ben Clayton2cdf1342023-02-03 13:24:18 +000085#include "src/tint/ast/templated_identifier.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000086#include "src/tint/ast/type_name.h"
87#include "src/tint/ast/u32.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000088#include "src/tint/ast/unary_op_expression.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000089#include "src/tint/ast/var.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000090#include "src/tint/ast/variable_decl_statement.h"
91#include "src/tint/ast/vector.h"
dan sinclair49d1a2d2022-06-16 12:01:27 +000092#include "src/tint/ast/while_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000093#include "src/tint/ast/workgroup_attribute.h"
dan sinclair02b466f2022-12-15 21:56:32 +000094#include "src/tint/constant/composite.h"
95#include "src/tint/constant/splat.h"
dan sinclairb53b8cf2022-12-15 16:25:31 +000096#include "src/tint/constant/value.h"
Ben Clayton0ce9ab02022-05-05 20:23:40 +000097#include "src/tint/number.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000098#include "src/tint/program.h"
99#include "src/tint/program_id.h"
dan sinclair4b1d79e2022-12-01 23:45:18 +0000100#include "src/tint/sem/array_count.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000101#include "src/tint/sem/struct.h"
dan sinclair946858a2022-12-08 22:21:24 +0000102#include "src/tint/type/array.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000103#include "src/tint/type/bool.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000104#include "src/tint/type/depth_texture.h"
105#include "src/tint/type/external_texture.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000106#include "src/tint/type/f16.h"
107#include "src/tint/type/f32.h"
108#include "src/tint/type/i32.h"
dan sinclair0e780da2022-12-08 22:21:24 +0000109#include "src/tint/type/matrix.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000110#include "src/tint/type/multisampled_texture.h"
dan sinclair4d56b482022-12-08 17:50:50 +0000111#include "src/tint/type/pointer.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000112#include "src/tint/type/sampled_texture.h"
113#include "src/tint/type/storage_texture.h"
dan sinclair3cbf3fc2023-01-21 19:16:15 +0000114#include "src/tint/type/texture_dimension.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000115#include "src/tint/type/u32.h"
dan sinclair0e780da2022-12-08 22:21:24 +0000116#include "src/tint/type/vector.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000117#include "src/tint/type/void.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000118
Ben Clayton8fa6c252022-11-03 19:16:26 +0000119#ifdef CURRENTLY_IN_TINT_PUBLIC_HEADER
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000120#error "internal tint header being #included from tint.h"
121#endif
122
123// Forward declarations
Ben Claytona7230f02022-04-11 14:37:21 +0000124namespace tint {
125class CloneContext;
126} // namespace tint
dan sinclair8155b9d2022-04-07 19:10:25 +0000127namespace tint::ast {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000128class VariableDeclStatement;
dan sinclair8155b9d2022-04-07 19:10:25 +0000129} // namespace tint::ast
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000130
131namespace tint {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000132
Ben Clayton783b1692022-08-02 17:03:35 +0000133namespace detail {
134
135/// IsVectorLike<T>::value is true if T is a utils::Vector or utils::VectorRef.
136template <typename T>
137struct IsVectorLike {
138 /// Non-specialized form of IsVectorLike defaults to false
139 static constexpr bool value = false;
140};
141
142/// IsVectorLike specialization for utils::Vector
143template <typename T, size_t N>
144struct IsVectorLike<utils::Vector<T, N>> {
145 /// True for the IsVectorLike specialization of utils::Vector
146 static constexpr bool value = true;
147};
148
149/// IsVectorLike specialization for utils::VectorRef
150template <typename T>
151struct IsVectorLike<utils::VectorRef<T>> {
152 /// True for the IsVectorLike specialization of utils::VectorRef
153 static constexpr bool value = true;
154};
155} // namespace detail
156
Antonio Maioranodfa92a92022-12-23 17:56:56 +0000157// Forward declare metafunction that evaluates to true iff T can be wrapped in a statement.
158template <typename T, typename = void>
159struct CanWrapInStatement;
160
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000161/// ProgramBuilder is a mutable builder for a Program.
162/// To construct a Program, populate the builder and then `std::move` it to a
163/// Program.
164class ProgramBuilder {
Ben Clayton01ac21c2023-02-07 16:14:25 +0000165 /// Evaluates to true if T is a Source
166 template <typename T>
167 static constexpr const bool IsSource = std::is_same_v<T, Source>;
168
169 /// Evaluates to true if T is a Number or bool.
170 template <typename T>
171 static constexpr const bool IsScalar =
172 std::is_integral_v<UnwrapNumber<T>> || std::is_floating_point_v<UnwrapNumber<T>> ||
173 std::is_same_v<T, bool>;
174
175 /// A helper used to disable overloads if the first type in `TYPES` is a Source. Used to avoid
176 /// ambiguities in overloads that take a Source as the first parameter and those that
177 /// perfectly-forward the first argument.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000178 template <typename... TYPES>
179 using DisableIfSource =
Ben Clayton01ac21c2023-02-07 16:14:25 +0000180 traits::EnableIf<!IsSource<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>>;
181
182 /// A helper used to disable overloads if the first type in `TYPES` is a scalar type. Used to
183 /// avoid ambiguities in overloads that take a scalar as the first parameter and those that
184 /// perfectly-forward the first argument.
185 template <typename... TYPES>
186 using DisableIfScalar =
187 traits::EnableIf<!IsScalar<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000188
Ben Clayton783b1692022-08-02 17:03:35 +0000189 /// A helper used to disable overloads if the first type in `TYPES` is a utils::Vector,
190 /// utils::VectorRef or utils::VectorRef.
191 template <typename... TYPES>
192 using DisableIfVectorLike = traits::EnableIf<
193 !detail::IsVectorLike<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>::value>;
194
Ben Clayton58794ae2022-08-19 17:28:53 +0000195 /// VarOptions is a helper for accepting an arbitrary number of order independent options for
196 /// constructing an ast::Var.
197 struct VarOptions {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000198 template <typename... ARGS>
Ben Clayton58794ae2022-08-19 17:28:53 +0000199 explicit VarOptions(ARGS&&... args) {
200 (Set(std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000201 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000202 ~VarOptions();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000203
Ben Clayton58794ae2022-08-19 17:28:53 +0000204 const ast::Type* type = nullptr;
dan sinclair18b21582023-01-21 19:56:49 +0000205 type::AddressSpace address_space = type::AddressSpace::kNone;
dan sinclair61c16eb2023-01-21 23:44:38 +0000206 type::Access access = type::Access::kUndefined;
dan sinclair6e77b472022-10-20 13:38:28 +0000207 const ast::Expression* initializer = nullptr;
Ben Clayton783b1692022-08-02 17:03:35 +0000208 utils::Vector<const ast::Attribute*, 4> attributes;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000209
dan sinclair41e4d9a2022-05-01 14:40:55 +0000210 private:
Ben Clayton58794ae2022-08-19 17:28:53 +0000211 void Set(const ast::Type* t) { type = t; }
dan sinclair18b21582023-01-21 19:56:49 +0000212 void Set(type::AddressSpace addr_space) { address_space = addr_space; }
dan sinclair61c16eb2023-01-21 23:44:38 +0000213 void Set(type::Access ac) { access = ac; }
dan sinclair6e77b472022-10-20 13:38:28 +0000214 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton783b1692022-08-02 17:03:35 +0000215 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
Ben Clayton58794ae2022-08-19 17:28:53 +0000216 void Set(const ast::Attribute* a) { attributes.Push(a); }
217 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000218
Ben Clayton58794ae2022-08-19 17:28:53 +0000219 /// LetOptions is a helper for accepting an arbitrary number of order independent options for
220 /// constructing an ast::Let.
221 struct LetOptions {
222 template <typename... ARGS>
223 explicit LetOptions(ARGS&&... args) {
224 static constexpr bool has_init =
Ben Clayton2cdf1342023-02-03 13:24:18 +0000225 (traits::IsTypeOrDerived<traits::PtrElTy<ARGS>, ast::Expression> || ...);
Ben Clayton58794ae2022-08-19 17:28:53 +0000226 static_assert(has_init, "Let() must be constructed with an initializer expression");
227 (Set(std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000228 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000229 ~LetOptions();
230
231 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000232 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000233 utils::Vector<const ast::Attribute*, 4> attributes;
234
235 private:
236 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000237 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000238 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
239 void Set(const ast::Attribute* a) { attributes.Push(a); }
240 };
241
242 /// ConstOptions is a helper for accepting an arbitrary number of order independent options for
243 /// constructing an ast::Const.
244 struct ConstOptions {
245 template <typename... ARGS>
246 explicit ConstOptions(ARGS&&... args) {
247 static constexpr bool has_init =
Ben Clayton2cdf1342023-02-03 13:24:18 +0000248 (traits::IsTypeOrDerived<traits::PtrElTy<ARGS>, ast::Expression> || ...);
Ben Clayton58794ae2022-08-19 17:28:53 +0000249 static_assert(has_init, "Const() must be constructed with an initializer expression");
250 (Set(std::forward<ARGS>(args)), ...);
251 }
252 ~ConstOptions();
253
254 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000255 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000256 utils::Vector<const ast::Attribute*, 4> attributes;
257
258 private:
259 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000260 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000261 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
262 void Set(const ast::Attribute* a) { attributes.Push(a); }
263 };
264
265 /// OverrideOptions is a helper for accepting an arbitrary number of order independent options
266 /// for constructing an ast::Override.
267 struct OverrideOptions {
268 template <typename... ARGS>
269 explicit OverrideOptions(ARGS&&... args) {
270 (Set(std::forward<ARGS>(args)), ...);
271 }
272 ~OverrideOptions();
273
274 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000275 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000276 utils::Vector<const ast::Attribute*, 4> attributes;
277
278 private:
279 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000280 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000281 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
282 void Set(const ast::Attribute* a) { attributes.Push(a); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000283 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000284
dan sinclair41e4d9a2022-05-01 14:40:55 +0000285 public:
286 /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node>
287 using ASTNodeAllocator = utils::BlockAllocator<ast::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000288
dan sinclair41e4d9a2022-05-01 14:40:55 +0000289 /// SemNodeAllocator is an alias to BlockAllocator<sem::Node>
290 using SemNodeAllocator = utils::BlockAllocator<sem::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000291
dan sinclairb53b8cf2022-12-15 16:25:31 +0000292 /// ConstantAllocator is an alias to BlockAllocator<constant::Value>
293 using ConstantAllocator = utils::BlockAllocator<constant::Value>;
Ben Claytonaa037ac2022-06-29 19:07:30 +0000294
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000295 /// Constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000296 ProgramBuilder();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000297
dan sinclair41e4d9a2022-05-01 14:40:55 +0000298 /// Move constructor
299 /// @param rhs the builder to move
300 ProgramBuilder(ProgramBuilder&& rhs);
301
302 /// Destructor
303 virtual ~ProgramBuilder();
304
305 /// Move assignment operator
306 /// @param rhs the builder to move
307 /// @return this builder
308 ProgramBuilder& operator=(ProgramBuilder&& rhs);
309
310 /// Wrap returns a new ProgramBuilder wrapping the Program `program` without
311 /// making a deep clone of the Program contents.
312 /// ProgramBuilder returned by Wrap() is intended to temporarily extend an
313 /// existing immutable program.
314 /// As the returned ProgramBuilder wraps `program`, `program` must not be
315 /// destructed or assigned while using the returned ProgramBuilder.
316 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this
317 /// function. See crbug.com/tint/460.
318 /// @param program the immutable Program to wrap
319 /// @return the ProgramBuilder that wraps `program`
320 static ProgramBuilder Wrap(const Program* program);
321
322 /// @returns the unique identifier for this program
323 ProgramID ID() const { return id_; }
324
325 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000326 type::Manager& Types() {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000327 AssertNotMoved();
328 return types_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000329 }
330
dan sinclair41e4d9a2022-05-01 14:40:55 +0000331 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000332 const type::Manager& Types() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000333 AssertNotMoved();
334 return types_;
335 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000336
dan sinclair41e4d9a2022-05-01 14:40:55 +0000337 /// @returns a reference to the program's AST nodes storage
338 ASTNodeAllocator& ASTNodes() {
339 AssertNotMoved();
340 return ast_nodes_;
341 }
342
343 /// @returns a reference to the program's AST nodes storage
344 const ASTNodeAllocator& ASTNodes() const {
345 AssertNotMoved();
346 return ast_nodes_;
347 }
348
349 /// @returns a reference to the program's semantic nodes storage
350 SemNodeAllocator& SemNodes() {
351 AssertNotMoved();
352 return sem_nodes_;
353 }
354
355 /// @returns a reference to the program's semantic nodes storage
356 const SemNodeAllocator& SemNodes() const {
357 AssertNotMoved();
358 return sem_nodes_;
359 }
360
Ben Claytonaa037ac2022-06-29 19:07:30 +0000361 /// @returns a reference to the program's semantic constant storage
362 ConstantAllocator& ConstantNodes() {
363 AssertNotMoved();
364 return constant_nodes_;
365 }
366
dan sinclair41e4d9a2022-05-01 14:40:55 +0000367 /// @returns a reference to the program's AST root Module
368 ast::Module& AST() {
369 AssertNotMoved();
370 return *ast_;
371 }
372
373 /// @returns a reference to the program's AST root Module
374 const ast::Module& AST() const {
375 AssertNotMoved();
376 return *ast_;
377 }
378
379 /// @returns a reference to the program's semantic info
380 sem::Info& Sem() {
381 AssertNotMoved();
382 return sem_;
383 }
384
385 /// @returns a reference to the program's semantic info
386 const sem::Info& Sem() const {
387 AssertNotMoved();
388 return sem_;
389 }
390
391 /// @returns a reference to the program's SymbolTable
392 SymbolTable& Symbols() {
393 AssertNotMoved();
394 return symbols_;
395 }
396
397 /// @returns a reference to the program's SymbolTable
398 const SymbolTable& Symbols() const {
399 AssertNotMoved();
400 return symbols_;
401 }
402
403 /// @returns a reference to the program's diagnostics
404 diag::List& Diagnostics() {
405 AssertNotMoved();
406 return diagnostics_;
407 }
408
409 /// @returns a reference to the program's diagnostics
410 const diag::List& Diagnostics() const {
411 AssertNotMoved();
412 return diagnostics_;
413 }
414
415 /// Controls whether the Resolver will be run on the program when it is built.
416 /// @param enable the new flag value (defaults to true)
417 void SetResolveOnBuild(bool enable) { resolve_on_build_ = enable; }
418
419 /// @return true if the Resolver will be run on the program when it is
420 /// built.
421 bool ResolveOnBuild() const { return resolve_on_build_; }
422
423 /// @returns true if the program has no error diagnostics and is not missing
424 /// information
425 bool IsValid() const;
426
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000427 /// @returns the last allocated (numerically highest) AST node identifier.
428 ast::NodeID LastAllocatedNodeID() const { return last_ast_node_id_; }
429
430 /// @returns the next sequentially unique node identifier.
431 ast::NodeID AllocateNodeID() {
432 auto out = ast::NodeID{last_ast_node_id_.value + 1};
433 last_ast_node_id_ = out;
434 return out;
435 }
436
dan sinclair41e4d9a2022-05-01 14:40:55 +0000437 /// Creates a new ast::Node owned by the ProgramBuilder. When the
438 /// ProgramBuilder is destructed, the ast::Node will also be destructed.
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000439 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000440 /// @param args the arguments to pass to the type constructor
441 /// @returns the node pointer
442 template <typename T, typename... ARGS>
443 traits::EnableIfIsType<T, ast::Node>* create(const Source& source, ARGS&&... args) {
444 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000445 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000446 }
447
dan sinclair41e4d9a2022-05-01 14:40:55 +0000448 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
449 /// Source as set by the last call to SetSource() as the only argument to the
450 /// constructor.
451 /// When the ProgramBuilder is destructed, the ast::Node will also be
452 /// destructed.
453 /// @returns the node pointer
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000454 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000455 traits::EnableIfIsType<T, ast::Node>* create() {
456 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000457 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000458 }
459
dan sinclair41e4d9a2022-05-01 14:40:55 +0000460 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
461 /// Source as set by the last call to SetSource() as the first argument to the
462 /// constructor.
463 /// When the ProgramBuilder is destructed, the ast::Node will also be
464 /// destructed.
465 /// @param arg0 the first arguments to pass to the type constructor
466 /// @param args the remaining arguments to pass to the type constructor
467 /// @returns the node pointer
468 template <typename T, typename ARG0, typename... ARGS>
469 traits::EnableIf</* T is ast::Node and ARG0 is not Source */
470 traits::IsTypeOrDerived<T, ast::Node> &&
471 !traits::IsTypeOrDerived<ARG0, Source>,
472 T>*
473 create(ARG0&& arg0, ARGS&&... args) {
474 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000475 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_, std::forward<ARG0>(arg0),
dan sinclair41e4d9a2022-05-01 14:40:55 +0000476 std::forward<ARGS>(args)...);
477 }
478
479 /// Creates a new sem::Node owned by the ProgramBuilder.
Ben Claytonaa037ac2022-06-29 19:07:30 +0000480 /// When the ProgramBuilder is destructed, the sem::Node will also be destructed.
481 /// @param args the arguments to pass to the constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000482 /// @returns the node pointer
483 template <typename T, typename... ARGS>
484 traits::EnableIf<traits::IsTypeOrDerived<T, sem::Node> &&
dan sinclair5f764d82022-12-08 00:32:27 +0000485 !traits::IsTypeOrDerived<T, type::Node>,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000486 T>*
487 create(ARGS&&... args) {
488 AssertNotMoved();
489 return sem_nodes_.Create<T>(std::forward<ARGS>(args)...);
490 }
491
dan sinclairb53b8cf2022-12-15 16:25:31 +0000492 /// Creates a new constant::Value owned by the ProgramBuilder.
Ben Claytonaa037ac2022-06-29 19:07:30 +0000493 /// When the ProgramBuilder is destructed, the sem::Node will also be destructed.
494 /// @param args the arguments to pass to the constructor
495 /// @returns the node pointer
496 template <typename T, typename... ARGS>
dan sinclair02b466f2022-12-15 21:56:32 +0000497 traits::EnableIf<traits::IsTypeOrDerived<T, constant::Value> &&
498 !traits::IsTypeOrDerived<T, constant::Composite> &&
499 !traits::IsTypeOrDerived<T, constant::Splat>,
500 T>*
501 create(ARGS&&... args) {
Ben Claytonaa037ac2022-06-29 19:07:30 +0000502 AssertNotMoved();
503 return constant_nodes_.Create<T>(std::forward<ARGS>(args)...);
504 }
505
dan sinclair02b466f2022-12-15 21:56:32 +0000506 /// Constructs a constant of a vector, matrix or array type.
507 ///
508 /// Examines the element values and will return either a constant::Composite or a
509 /// constant::Splat, depending on the element types and values.
510 ///
511 /// @param type the composite type
512 /// @param elements the composite elements
513 /// @returns the node pointer
dan sinclaircf581222023-01-03 20:25:37 +0000514 template <typename T,
515 typename = traits::EnableIf<traits::IsTypeOrDerived<T, constant::Composite> ||
516 traits::IsTypeOrDerived<T, constant::Splat>>>
517 const constant::Value* create(const type::Type* type,
518 utils::VectorRef<const constant::Value*> elements) {
dan sinclair02b466f2022-12-15 21:56:32 +0000519 AssertNotMoved();
dan sinclaircf581222023-01-03 20:25:37 +0000520 return createSplatOrComposite(type, elements);
dan sinclair02b466f2022-12-15 21:56:32 +0000521 }
522
523 /// Constructs a splat constant.
524 /// @param type the splat type
525 /// @param element the splat element
526 /// @param n the number of elements
527 /// @returns the node pointer
dan sinclaircf581222023-01-03 20:25:37 +0000528 template <typename T, typename = traits::EnableIf<traits::IsTypeOrDerived<T, constant::Splat>>>
529 const constant::Splat* create(const type::Type* type,
530 const constant::Value* element,
531 size_t n) {
dan sinclair02b466f2022-12-15 21:56:32 +0000532 AssertNotMoved();
533 return constant_nodes_.Create<constant::Splat>(type, element, n);
534 }
535
Ben Clayton7c3e9a62022-12-16 15:31:19 +0000536 /// Creates a new type::Node owned by the ProgramBuilder.
537 /// When the ProgramBuilder is destructed, owned ProgramBuilder and the returned node will also
538 /// be destructed. If T derives from type::UniqueNode, then the calling create() for the same
539 /// `T` and arguments will return the same pointer.
540 /// @param args the arguments to pass to the constructor
541 /// @returns the new, or existing node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000542 template <typename T, typename... ARGS>
Ben Clayton7c3e9a62022-12-16 15:31:19 +0000543 traits::EnableIfIsType<T, type::Node>* create(ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000544 AssertNotMoved();
545 return types_.Get<T>(std::forward<ARGS>(args)...);
546 }
dan sinclair5f764d82022-12-08 00:32:27 +0000547
dan sinclair41e4d9a2022-05-01 14:40:55 +0000548 /// Marks this builder as moved, preventing any further use of the builder.
549 void MarkAsMoved();
550
551 //////////////////////////////////////////////////////////////////////////////
552 // TypesBuilder
553 //////////////////////////////////////////////////////////////////////////////
554
555 /// TypesBuilder holds basic `tint` types and methods for constructing
556 /// complex types.
557 class TypesBuilder {
558 public:
559 /// Constructor
560 /// @param builder the program builder
561 explicit TypesBuilder(ProgramBuilder* builder);
562
563 /// @return the tint AST type for the C type `T`.
564 template <typename T>
565 const ast::Type* Of() const {
566 return CToAST<T>::get(this);
567 }
568
Ben Clayton19068572023-02-07 21:28:09 +0000569 /// @returns nullptr ast::Type
570 const ast::Type* void_() const { return nullptr; }
571
dan sinclair41e4d9a2022-05-01 14:40:55 +0000572 /// @returns a boolean type
573 const ast::Bool* bool_() const { return builder->create<ast::Bool>(); }
574
575 /// @param source the Source of the node
576 /// @returns a boolean type
577 const ast::Bool* bool_(const Source& source) const {
578 return builder->create<ast::Bool>(source);
579 }
580
Zhaoming Jiang62bfd312022-05-13 12:01:11 +0000581 /// @returns a f16 type
582 const ast::F16* f16() const { return builder->create<ast::F16>(); }
583
584 /// @param source the Source of the node
585 /// @returns a f16 type
586 const ast::F16* f16(const Source& source) const {
587 return builder->create<ast::F16>(source);
588 }
589
dan sinclair41e4d9a2022-05-01 14:40:55 +0000590 /// @returns a f32 type
591 const ast::F32* f32() const { return builder->create<ast::F32>(); }
592
593 /// @param source the Source of the node
594 /// @returns a f32 type
595 const ast::F32* f32(const Source& source) const {
596 return builder->create<ast::F32>(source);
597 }
598
599 /// @returns a i32 type
600 const ast::I32* i32() const { return builder->create<ast::I32>(); }
601
602 /// @param source the Source of the node
603 /// @returns a i32 type
604 const ast::I32* i32(const Source& source) const {
605 return builder->create<ast::I32>(source);
606 }
607
608 /// @returns a u32 type
609 const ast::U32* u32() const { return builder->create<ast::U32>(); }
610
611 /// @param source the Source of the node
612 /// @returns a u32 type
613 const ast::U32* u32(const Source& source) const {
614 return builder->create<ast::U32>(source);
615 }
616
dan sinclair41e4d9a2022-05-01 14:40:55 +0000617 /// @param type vector subtype
618 /// @param n vector width in elements
619 /// @return the tint AST type for a `n`-element vector of `type`.
620 const ast::Vector* vec(const ast::Type* type, uint32_t n) const {
621 return builder->create<ast::Vector>(type, n);
622 }
623
624 /// @param source the Source of the node
625 /// @param type vector subtype
626 /// @param n vector width in elements
627 /// @return the tint AST type for a `n`-element vector of `type`.
628 const ast::Vector* vec(const Source& source, const ast::Type* type, uint32_t n) const {
629 return builder->create<ast::Vector>(source, type, n);
630 }
631
632 /// @param type vector subtype
633 /// @return the tint AST type for a 2-element vector of `type`.
634 const ast::Vector* vec2(const ast::Type* type) const { return vec(type, 2u); }
635
Ben Clayton6315a272022-08-01 17:18:04 +0000636 /// @param source the vector source
637 /// @param type vector subtype
638 /// @return the tint AST type for a 2-element vector of `type`.
639 const ast::Vector* vec2(const Source& source, const ast::Type* type) const {
640 return vec(source, type, 2u);
641 }
642
dan sinclair41e4d9a2022-05-01 14:40:55 +0000643 /// @param type vector subtype
644 /// @return the tint AST type for a 3-element vector of `type`.
645 const ast::Vector* vec3(const ast::Type* type) const { return vec(type, 3u); }
646
Ben Clayton6315a272022-08-01 17:18:04 +0000647 /// @param source the vector source
648 /// @param type vector subtype
649 /// @return the tint AST type for a 3-element vector of `type`.
650 const ast::Vector* vec3(const Source& source, const ast::Type* type) const {
651 return vec(source, type, 3u);
652 }
653
dan sinclair41e4d9a2022-05-01 14:40:55 +0000654 /// @param type vector subtype
655 /// @return the tint AST type for a 4-element vector of `type`.
656 const ast::Vector* vec4(const ast::Type* type) const { return vec(type, 4u); }
657
Ben Clayton6315a272022-08-01 17:18:04 +0000658 /// @param source the vector source
659 /// @param type vector subtype
660 /// @return the tint AST type for a 4-element vector of `type`.
661 const ast::Vector* vec4(const Source& source, const ast::Type* type) const {
662 return vec(source, type, 4u);
663 }
664
dan sinclair41e4d9a2022-05-01 14:40:55 +0000665 /// @param n vector width in elements
666 /// @return the tint AST type for a `n`-element vector of `type`.
667 template <typename T>
668 const ast::Vector* vec(uint32_t n) const {
669 return vec(Of<T>(), n);
670 }
671
672 /// @return the tint AST type for a 2-element vector of the C type `T`.
673 template <typename T>
674 const ast::Vector* vec2() const {
675 return vec2(Of<T>());
676 }
677
Ben Clayton6315a272022-08-01 17:18:04 +0000678 /// @param source the Source of the node
679 /// @return the tint AST type for a 2-element vector of the C type `T`.
680 template <typename T>
681 const ast::Vector* vec2(const Source& source) const {
682 return vec2(source, Of<T>());
683 }
684
dan sinclair41e4d9a2022-05-01 14:40:55 +0000685 /// @return the tint AST type for a 3-element vector of the C type `T`.
686 template <typename T>
687 const ast::Vector* vec3() const {
688 return vec3(Of<T>());
689 }
690
Ben Clayton6315a272022-08-01 17:18:04 +0000691 /// @param source the Source of the node
692 /// @return the tint AST type for a 3-element vector of the C type `T`.
693 template <typename T>
694 const ast::Vector* vec3(const Source& source) const {
695 return vec3(source, Of<T>());
696 }
697
dan sinclair41e4d9a2022-05-01 14:40:55 +0000698 /// @return the tint AST type for a 4-element vector of the C type `T`.
699 template <typename T>
700 const ast::Vector* vec4() const {
701 return vec4(Of<T>());
702 }
703
Ben Clayton6315a272022-08-01 17:18:04 +0000704 /// @param source the Source of the node
705 /// @return the tint AST type for a 4-element vector of the C type `T`.
706 template <typename T>
707 const ast::Vector* vec4(const Source& source) const {
708 return vec4(source, Of<T>());
709 }
710
dan sinclair41e4d9a2022-05-01 14:40:55 +0000711 /// @param type matrix subtype
712 /// @param columns number of columns for the matrix
713 /// @param rows number of rows for the matrix
714 /// @return the tint AST type for a matrix of `type`
715 const ast::Matrix* mat(const ast::Type* type, uint32_t columns, uint32_t rows) const {
716 return builder->create<ast::Matrix>(type, rows, columns);
717 }
718
719 /// @param source the Source of the node
720 /// @param type matrix subtype
721 /// @param columns number of columns for the matrix
722 /// @param rows number of rows for the matrix
723 /// @return the tint AST type for a matrix of `type`
724 const ast::Matrix* mat(const Source& source,
725 const ast::Type* type,
726 uint32_t columns,
727 uint32_t rows) const {
728 return builder->create<ast::Matrix>(source, type, rows, columns);
729 }
730
731 /// @param type matrix subtype
732 /// @return the tint AST type for a 2x3 matrix of `type`.
733 const ast::Matrix* mat2x2(const ast::Type* type) const { return mat(type, 2u, 2u); }
734
735 /// @param type matrix subtype
736 /// @return the tint AST type for a 2x3 matrix of `type`.
737 const ast::Matrix* mat2x3(const ast::Type* type) const { return mat(type, 2u, 3u); }
738
739 /// @param type matrix subtype
740 /// @return the tint AST type for a 2x4 matrix of `type`.
741 const ast::Matrix* mat2x4(const ast::Type* type) const { return mat(type, 2u, 4u); }
742
743 /// @param type matrix subtype
744 /// @return the tint AST type for a 3x2 matrix of `type`.
745 const ast::Matrix* mat3x2(const ast::Type* type) const { return mat(type, 3u, 2u); }
746
747 /// @param type matrix subtype
748 /// @return the tint AST type for a 3x3 matrix of `type`.
749 const ast::Matrix* mat3x3(const ast::Type* type) const { return mat(type, 3u, 3u); }
750
751 /// @param type matrix subtype
752 /// @return the tint AST type for a 3x4 matrix of `type`.
753 const ast::Matrix* mat3x4(const ast::Type* type) const { return mat(type, 3u, 4u); }
754
755 /// @param type matrix subtype
756 /// @return the tint AST type for a 4x2 matrix of `type`.
757 const ast::Matrix* mat4x2(const ast::Type* type) const { return mat(type, 4u, 2u); }
758
759 /// @param type matrix subtype
760 /// @return the tint AST type for a 4x3 matrix of `type`.
761 const ast::Matrix* mat4x3(const ast::Type* type) const { return mat(type, 4u, 3u); }
762
763 /// @param type matrix subtype
764 /// @return the tint AST type for a 4x4 matrix of `type`.
765 const ast::Matrix* mat4x4(const ast::Type* type) const { return mat(type, 4u, 4u); }
766
767 /// @param columns number of columns for the matrix
768 /// @param rows number of rows for the matrix
769 /// @return the tint AST type for a matrix of `type`
770 template <typename T>
771 const ast::Matrix* mat(uint32_t columns, uint32_t rows) const {
772 return mat(Of<T>(), columns, rows);
773 }
774
775 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
776 template <typename T>
777 const ast::Matrix* mat2x2() const {
778 return mat2x2(Of<T>());
779 }
780
781 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
782 template <typename T>
783 const ast::Matrix* mat2x3() const {
784 return mat2x3(Of<T>());
785 }
786
787 /// @return the tint AST type for a 2x4 matrix of the C type `T`.
788 template <typename T>
789 const ast::Matrix* mat2x4() const {
790 return mat2x4(Of<T>());
791 }
792
793 /// @return the tint AST type for a 3x2 matrix of the C type `T`.
794 template <typename T>
795 const ast::Matrix* mat3x2() const {
796 return mat3x2(Of<T>());
797 }
798
799 /// @return the tint AST type for a 3x3 matrix of the C type `T`.
800 template <typename T>
801 const ast::Matrix* mat3x3() const {
802 return mat3x3(Of<T>());
803 }
804
805 /// @return the tint AST type for a 3x4 matrix of the C type `T`.
806 template <typename T>
807 const ast::Matrix* mat3x4() const {
808 return mat3x4(Of<T>());
809 }
810
811 /// @return the tint AST type for a 4x2 matrix of the C type `T`.
812 template <typename T>
813 const ast::Matrix* mat4x2() const {
814 return mat4x2(Of<T>());
815 }
816
817 /// @return the tint AST type for a 4x3 matrix of the C type `T`.
818 template <typename T>
819 const ast::Matrix* mat4x3() const {
820 return mat4x3(Of<T>());
821 }
822
823 /// @return the tint AST type for a 4x4 matrix of the C type `T`.
824 template <typename T>
825 const ast::Matrix* mat4x4() const {
826 return mat4x4(Of<T>());
827 }
828
829 /// @param subtype the array element type
830 /// @param n the array size. nullptr represents a runtime-array
831 /// @param attrs the optional attributes for the array
Ben Clayton9e367232023-02-08 14:17:37 +0000832 /// @return the array of size `n` of type `T`
833 template <typename COUNT = std::nullptr_t>
Ben Clayton783b1692022-08-02 17:03:35 +0000834 const ast::Array* array(
835 const ast::Type* subtype,
Ben Clayton9e367232023-02-08 14:17:37 +0000836 COUNT&& n = nullptr,
Ben Clayton783b1692022-08-02 17:03:35 +0000837 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
Ben Clayton9e367232023-02-08 14:17:37 +0000838 return array(builder->source_, subtype, std::forward<COUNT>(n), std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000839 }
840
841 /// @param source the Source of the node
842 /// @param subtype the array element type
843 /// @param n the array size. nullptr represents a runtime-array
844 /// @param attrs the optional attributes for the array
Ben Clayton9e367232023-02-08 14:17:37 +0000845 /// @return the array of size `n` of type `T`
846 template <typename COUNT = std::nullptr_t>
Ben Clayton783b1692022-08-02 17:03:35 +0000847 const ast::Array* array(
848 const Source& source,
849 const ast::Type* subtype,
Ben Clayton9e367232023-02-08 14:17:37 +0000850 COUNT&& n = nullptr,
Ben Clayton783b1692022-08-02 17:03:35 +0000851 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
Ben Clayton9e367232023-02-08 14:17:37 +0000852 if constexpr (std::is_same_v<traits::Decay<COUNT>, std::nullptr_t>) {
853 return builder->create<ast::Array>(source, subtype, nullptr, std::move(attrs));
854 } else {
855 return builder->create<ast::Array>(
856 source, subtype, builder->Expr(std::forward<COUNT>(n)), std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000857 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000858 }
859
Ben Clayton9e367232023-02-08 14:17:37 +0000860 /// @param attrs the optional attributes for the array
861 /// @return the runtime-sized array of type `T`
dan sinclair41e4d9a2022-05-01 14:40:55 +0000862 template <typename T>
Ben Clayton9e367232023-02-08 14:17:37 +0000863 const ast::Array* array(
864 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
865 return array(Of<T>(), nullptr, std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000866 }
867
Ben Clayton9e367232023-02-08 14:17:37 +0000868 /// @param attrs the optional attributes for the array
869 /// @return the array of size `N` of type `T`
dan sinclair41e4d9a2022-05-01 14:40:55 +0000870 template <typename T, int N>
Ben Clayton9e367232023-02-08 14:17:37 +0000871 const ast::Array* array(
872 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
873 return array(Of<T>(), tint::u32(N), std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000874 }
875
876 /// Creates a type name
877 /// @param name the name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000878 /// @param args the optional template arguments
dan sinclair41e4d9a2022-05-01 14:40:55 +0000879 /// @returns the type name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000880 template <typename NAME, typename... ARGS, typename _ = DisableIfSource<NAME>>
Ben Clayton2117f802023-02-03 14:01:43 +0000881 const ast::TypeName* operator()(NAME&& name, ARGS&&... args) const {
Ben Claytoncf0e9302023-02-08 15:18:43 +0000882 return (*this)(builder->source_, std::forward<NAME>(name), std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000883 }
884
885 /// Creates a type name
886 /// @param source the Source of the node
887 /// @param name the name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000888 /// @param args the optional template arguments
dan sinclair41e4d9a2022-05-01 14:40:55 +0000889 /// @returns the type name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000890 template <typename NAME, typename... ARGS>
Ben Clayton2117f802023-02-03 14:01:43 +0000891 const ast::TypeName* operator()(const Source& source, NAME&& name, ARGS&&... args) const {
Ben Clayton2cdf1342023-02-03 13:24:18 +0000892 return builder->create<ast::TypeName>(
Ben Claytoncf0e9302023-02-08 15:18:43 +0000893 source,
894 builder->Ident(source, std::forward<NAME>(name), std::forward<ARGS>(args)...));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000895 }
896
897 /// Creates an alias type
898 /// @param name the alias name
899 /// @param type the alias type
900 /// @returns the alias pointer
901 template <typename NAME>
902 const ast::Alias* alias(NAME&& name, const ast::Type* type) const {
903 auto sym = builder->Sym(std::forward<NAME>(name));
904 return builder->create<ast::Alias>(sym, type);
905 }
906
907 /// Creates an alias type
908 /// @param source the Source of the node
909 /// @param name the alias name
910 /// @param type the alias type
911 /// @returns the alias pointer
912 template <typename NAME>
913 const ast::Alias* alias(const Source& source, NAME&& name, const ast::Type* type) const {
914 auto sym = builder->Sym(std::forward<NAME>(name));
915 return builder->create<ast::Alias>(source, sym, type);
916 }
917
918 /// @param type the type of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000919 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000920 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000921 /// @return the pointer to `type` with the given type::AddressSpace
dan sinclair41e4d9a2022-05-01 14:40:55 +0000922 const ast::Pointer* pointer(const ast::Type* type,
dan sinclair18b21582023-01-21 19:56:49 +0000923 type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000924 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000925 return builder->create<ast::Pointer>(type, address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000926 }
927
928 /// @param source the Source of the node
929 /// @param type the type of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000930 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000931 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000932 /// @return the pointer to `type` with the given type::AddressSpace
dan sinclair41e4d9a2022-05-01 14:40:55 +0000933 const ast::Pointer* pointer(const Source& source,
934 const ast::Type* type,
dan sinclair18b21582023-01-21 19:56:49 +0000935 type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000936 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000937 return builder->create<ast::Pointer>(source, type, address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000938 }
939
dan sinclairff7cf212022-10-03 14:05:23 +0000940 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000941 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000942 /// @return the pointer to type `T` with the given type::AddressSpace.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000943 template <typename T>
dan sinclair18b21582023-01-21 19:56:49 +0000944 const ast::Pointer* pointer(type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000945 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000946 return pointer(Of<T>(), address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000947 }
948
949 /// @param source the Source of the node
dan sinclairff7cf212022-10-03 14:05:23 +0000950 /// @param address_space the address space of the pointer
Ben Claytoncfe07a12022-07-15 13:01:49 +0000951 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000952 /// @return the pointer to type `T` with the given type::AddressSpace.
Ben Claytoncfe07a12022-07-15 13:01:49 +0000953 template <typename T>
954 const ast::Pointer* pointer(const Source& source,
dan sinclair18b21582023-01-21 19:56:49 +0000955 type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000956 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000957 return pointer(source, Of<T>(), address_space, access);
Ben Claytoncfe07a12022-07-15 13:01:49 +0000958 }
959
960 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000961 /// @param type the type of the atomic
962 /// @return the atomic to `type`
963 const ast::Atomic* atomic(const Source& source, const ast::Type* type) const {
964 return builder->create<ast::Atomic>(source, type);
965 }
966
967 /// @param type the type of the atomic
968 /// @return the atomic to `type`
969 const ast::Atomic* atomic(const ast::Type* type) const {
970 return builder->create<ast::Atomic>(type);
971 }
972
973 /// @return the atomic to type `T`
974 template <typename T>
975 const ast::Atomic* atomic() const {
976 return atomic(Of<T>());
977 }
978
979 /// @param kind the kind of sampler
980 /// @returns the sampler
dan sinclair3085e232023-01-23 16:24:12 +0000981 const ast::Sampler* sampler(type::SamplerKind kind) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000982 return builder->create<ast::Sampler>(kind);
983 }
984
985 /// @param source the Source of the node
986 /// @param kind the kind of sampler
987 /// @returns the sampler
dan sinclair3085e232023-01-23 16:24:12 +0000988 const ast::Sampler* sampler(const Source& source, type::SamplerKind kind) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000989 return builder->create<ast::Sampler>(source, kind);
990 }
991
992 /// @param dims the dimensionality of the texture
993 /// @returns the depth texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +0000994 const ast::DepthTexture* depth_texture(type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000995 return builder->create<ast::DepthTexture>(dims);
996 }
997
998 /// @param source the Source of the node
999 /// @param dims the dimensionality of the texture
1000 /// @returns the depth texture
1001 const ast::DepthTexture* depth_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001002 type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001003 return builder->create<ast::DepthTexture>(source, dims);
1004 }
1005
1006 /// @param dims the dimensionality of the texture
1007 /// @returns the multisampled depth texture
1008 const ast::DepthMultisampledTexture* depth_multisampled_texture(
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001009 type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001010 return builder->create<ast::DepthMultisampledTexture>(dims);
1011 }
1012
1013 /// @param source the Source of the node
1014 /// @param dims the dimensionality of the texture
1015 /// @returns the multisampled depth texture
1016 const ast::DepthMultisampledTexture* depth_multisampled_texture(
1017 const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001018 type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001019 return builder->create<ast::DepthMultisampledTexture>(source, dims);
1020 }
1021
1022 /// @param dims the dimensionality of the texture
1023 /// @param subtype the texture subtype.
1024 /// @returns the sampled texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001025 const ast::SampledTexture* sampled_texture(type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001026 const ast::Type* subtype) const {
1027 return builder->create<ast::SampledTexture>(dims, subtype);
1028 }
1029
1030 /// @param source the Source of the node
1031 /// @param dims the dimensionality of the texture
1032 /// @param subtype the texture subtype.
1033 /// @returns the sampled texture
1034 const ast::SampledTexture* sampled_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001035 type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001036 const ast::Type* subtype) const {
1037 return builder->create<ast::SampledTexture>(source, dims, subtype);
1038 }
1039
1040 /// @param dims the dimensionality of the texture
1041 /// @param subtype the texture subtype.
1042 /// @returns the multisampled texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001043 const ast::MultisampledTexture* multisampled_texture(type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001044 const ast::Type* subtype) const {
1045 return builder->create<ast::MultisampledTexture>(dims, subtype);
1046 }
1047
1048 /// @param source the Source of the node
1049 /// @param dims the dimensionality of the texture
1050 /// @param subtype the texture subtype.
1051 /// @returns the multisampled texture
1052 const ast::MultisampledTexture* multisampled_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001053 type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001054 const ast::Type* subtype) const {
1055 return builder->create<ast::MultisampledTexture>(source, dims, subtype);
1056 }
1057
1058 /// @param dims the dimensionality of the texture
1059 /// @param format the texel format of the texture
1060 /// @param access the access control of the texture
1061 /// @returns the storage texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001062 const ast::StorageTexture* storage_texture(type::TextureDimension dims,
dan sinclair57c0bbc2023-01-21 23:51:25 +00001063 type::TexelFormat format,
dan sinclair61c16eb2023-01-21 23:44:38 +00001064 type::Access access) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001065 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
1066 return builder->create<ast::StorageTexture>(dims, format, subtype, access);
1067 }
1068
1069 /// @param source the Source of the node
1070 /// @param dims the dimensionality of the texture
1071 /// @param format the texel format of the texture
1072 /// @param access the access control of the texture
1073 /// @returns the storage texture
1074 const ast::StorageTexture* storage_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001075 type::TextureDimension dims,
dan sinclair57c0bbc2023-01-21 23:51:25 +00001076 type::TexelFormat format,
dan sinclair61c16eb2023-01-21 23:44:38 +00001077 type::Access access) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001078 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
1079 return builder->create<ast::StorageTexture>(source, dims, format, subtype, access);
1080 }
1081
1082 /// @returns the external texture
1083 const ast::ExternalTexture* external_texture() const {
1084 return builder->create<ast::ExternalTexture>();
1085 }
1086
1087 /// @param source the Source of the node
1088 /// @returns the external texture
1089 const ast::ExternalTexture* external_texture(const Source& source) const {
1090 return builder->create<ast::ExternalTexture>(source);
1091 }
1092
1093 /// Constructs a TypeName for the type declaration.
1094 /// @param type the type
1095 /// @return either type or a pointer to a new ast::TypeName
1096 const ast::TypeName* Of(const ast::TypeDecl* type) const;
1097
1098 /// The ProgramBuilder
1099 ProgramBuilder* const builder;
1100
1101 private:
1102 /// CToAST<T> is specialized for various `T` types and each specialization
1103 /// contains a single static `get()` method for obtaining the corresponding
1104 /// AST type for the C type `T`.
1105 /// `get()` has the signature:
1106 /// `static const ast::Type* get(Types* t)`
1107 template <typename T>
1108 struct CToAST {};
1109 };
1110
1111 //////////////////////////////////////////////////////////////////////////////
1112 // AST helper methods
1113 //////////////////////////////////////////////////////////////////////////////
1114
1115 /// @return a new unnamed symbol
1116 Symbol Sym() { return Symbols().New(); }
1117
1118 /// @param name the symbol string
1119 /// @return a Symbol with the given name
1120 Symbol Sym(const std::string& name) { return Symbols().Register(name); }
1121
1122 /// @param sym the symbol
1123 /// @return `sym`
1124 Symbol Sym(Symbol sym) { return sym; }
1125
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001126 /// @param source the source information
1127 /// @param identifier the identifier symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001128 /// @param args optional templated identifier arguments
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001129 /// @return an ast::Identifier with the given symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001130 template <typename IDENTIFIER, typename... ARGS>
1131 const auto* Ident(const Source& source, IDENTIFIER&& identifier, ARGS&&... args) {
1132 Symbol sym = Sym(std::forward<IDENTIFIER>(identifier));
1133 if constexpr (sizeof...(args) > 0) {
1134 return create<ast::TemplatedIdentifier>(source, sym,
1135 ExprList(std::forward<ARGS>(args)...));
1136 } else {
1137 return create<ast::Identifier>(source, sym);
1138 }
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001139 }
1140
1141 /// @param identifier the identifier symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001142 /// @param args optional templated identifier arguments
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001143 /// @return an ast::Identifier with the given symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001144 template <typename IDENTIFIER, typename... ARGS, typename = DisableIfSource<IDENTIFIER>>
1145 const auto* Ident(IDENTIFIER&& identifier, ARGS&&... args) {
1146 if constexpr (traits::IsTypeOrDerived<traits::PtrElTy<IDENTIFIER>, ast::Identifier>) {
1147 static_assert(sizeof...(args) == 0);
Ben Clayton999db742023-02-02 15:16:28 +00001148 return identifier; // Pass-through
1149 } else {
Ben Clayton2cdf1342023-02-03 13:24:18 +00001150 return Ident(source_, std::forward<IDENTIFIER>(identifier),
1151 std::forward<ARGS>(args)...);
Ben Clayton999db742023-02-02 15:16:28 +00001152 }
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001153 }
1154
dan sinclair41e4d9a2022-05-01 14:40:55 +00001155 /// @param expr the expression
1156 /// @return expr
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001157 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001158 traits::EnableIfIsType<T, ast::Expression>* Expr(T* expr) {
1159 return expr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001160 }
1161
dan sinclair41e4d9a2022-05-01 14:40:55 +00001162 /// Passthrough for nullptr
1163 /// @return nullptr
1164 const ast::IdentifierExpression* Expr(std::nullptr_t) { return nullptr; }
1165
1166 /// @param source the source information
1167 /// @param symbol the identifier symbol
1168 /// @return an ast::IdentifierExpression with the given symbol
1169 const ast::IdentifierExpression* Expr(const Source& source, Symbol symbol) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001170 return create<ast::IdentifierExpression>(source, Ident(source, symbol));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001171 }
1172
dan sinclair41e4d9a2022-05-01 14:40:55 +00001173 /// @param symbol the identifier symbol
1174 /// @return an ast::IdentifierExpression with the given symbol
1175 const ast::IdentifierExpression* Expr(Symbol symbol) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001176 return create<ast::IdentifierExpression>(Ident(symbol));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001177 }
1178
dan sinclair41e4d9a2022-05-01 14:40:55 +00001179 /// @param source the source information
1180 /// @param name the identifier name
1181 /// @return an ast::IdentifierExpression with the given name
1182 const ast::IdentifierExpression* Expr(const Source& source, const char* name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001183 return create<ast::IdentifierExpression>(source, Ident(source, name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001184 }
1185
dan sinclair41e4d9a2022-05-01 14:40:55 +00001186 /// @param name the identifier name
1187 /// @return an ast::IdentifierExpression with the given name
1188 const ast::IdentifierExpression* Expr(const char* name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001189 return create<ast::IdentifierExpression>(Ident(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001190 }
1191
dan sinclair41e4d9a2022-05-01 14:40:55 +00001192 /// @param source the source information
1193 /// @param name the identifier name
1194 /// @return an ast::IdentifierExpression with the given name
1195 const ast::IdentifierExpression* Expr(const Source& source, const std::string& name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001196 return create<ast::IdentifierExpression>(source, Ident(source, name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001197 }
1198
dan sinclair41e4d9a2022-05-01 14:40:55 +00001199 /// @param name the identifier name
1200 /// @return an ast::IdentifierExpression with the given name
1201 const ast::IdentifierExpression* Expr(const std::string& name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001202 return create<ast::IdentifierExpression>(Ident(name));
1203 }
1204
1205 /// @param source the source information
1206 /// @param variable the AST variable
1207 /// @return an ast::IdentifierExpression with the variable's symbol
1208 const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) {
1209 return create<ast::IdentifierExpression>(source, Ident(source, variable->symbol));
1210 }
1211
1212 /// @param variable the AST variable
1213 /// @return an ast::IdentifierExpression with the variable's symbol
1214 const ast::IdentifierExpression* Expr(const ast::Variable* variable) {
1215 return create<ast::IdentifierExpression>(Ident(variable->symbol));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001216 }
1217
Ben Clayton2cdf1342023-02-03 13:24:18 +00001218 /// @param ident the identifier
1219 /// @return an ast::IdentifierExpression with the given identifier
1220 template <typename IDENTIFIER, typename = traits::EnableIfIsType<IDENTIFIER, ast::Identifier>>
1221 const ast::IdentifierExpression* Expr(const IDENTIFIER* ident) {
Ben Clayton2cdf1342023-02-03 13:24:18 +00001222 return create<ast::IdentifierExpression>(ident);
1223 }
1224
dan sinclair41e4d9a2022-05-01 14:40:55 +00001225 /// @param source the source information
1226 /// @param value the boolean value
1227 /// @return a Scalar constructor for the given value
Ben Clayton17fa42d2022-05-10 15:29:14 +00001228 template <typename BOOL>
1229 std::enable_if_t<std::is_same_v<BOOL, bool>, const ast::BoolLiteralExpression*> Expr(
1230 const Source& source,
1231 BOOL value) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001232 return create<ast::BoolLiteralExpression>(source, value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001233 }
1234
dan sinclair41e4d9a2022-05-01 14:40:55 +00001235 /// @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 BOOL value) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001240 return create<ast::BoolLiteralExpression>(value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001241 }
1242
dan sinclair41e4d9a2022-05-01 14:40:55 +00001243 /// @param source the source information
1244 /// @param value the float value
Ben Clayton41285aa2022-05-10 14:55:34 +00001245 /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value
1246 const ast::FloatLiteralExpression* Expr(const Source& source, f32 value) {
1247 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1248 ast::FloatLiteralExpression::Suffix::kF);
1249 }
1250
1251 /// @param value the float value
1252 /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value
dan sinclair41e4d9a2022-05-01 14:40:55 +00001253 const ast::FloatLiteralExpression* Expr(f32 value) {
Ben Clayton41285aa2022-05-10 14:55:34 +00001254 return create<ast::FloatLiteralExpression>(static_cast<double>(value.value),
1255 ast::FloatLiteralExpression::Suffix::kF);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001256 }
1257
dan sinclair41e4d9a2022-05-01 14:40:55 +00001258 /// @param source the source information
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00001259 /// @param value the float value
1260 /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
1261 const ast::FloatLiteralExpression* Expr(const Source& source, f16 value) {
1262 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1263 ast::FloatLiteralExpression::Suffix::kH);
1264 }
1265
1266 /// @param value the float value
1267 /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
1268 const ast::FloatLiteralExpression* Expr(f16 value) {
1269 return create<ast::FloatLiteralExpression>(static_cast<double>(value.value),
1270 ast::FloatLiteralExpression::Suffix::kH);
1271 }
1272
1273 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001274 /// @param value the integer value
Ben Clayton508e4a52022-05-10 22:08:04 +00001275 /// @return an unsuffixed IntLiteralExpression for the AInt value
1276 const ast::IntLiteralExpression* Expr(const Source& source, AInt value) {
1277 return create<ast::IntLiteralExpression>(source, value,
1278 ast::IntLiteralExpression::Suffix::kNone);
1279 }
1280
1281 /// @param value the integer value
1282 /// @return an unsuffixed IntLiteralExpression for the AInt value
1283 const ast::IntLiteralExpression* Expr(AInt value) {
1284 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kNone);
1285 }
1286
1287 /// @param source the source information
1288 /// @param value the integer value
1289 /// @return an unsuffixed FloatLiteralExpression for the AFloat value
1290 const ast::FloatLiteralExpression* Expr(const Source& source, AFloat value) {
1291 return create<ast::FloatLiteralExpression>(source, value.value,
1292 ast::FloatLiteralExpression::Suffix::kNone);
1293 }
1294
1295 /// @param value the integer value
1296 /// @return an unsuffixed FloatLiteralExpression for the AFloat value
1297 const ast::FloatLiteralExpression* Expr(AFloat value) {
1298 return create<ast::FloatLiteralExpression>(value.value,
1299 ast::FloatLiteralExpression::Suffix::kNone);
1300 }
1301
1302 /// @param source the source information
1303 /// @param value the integer value
Ben Clayton41285aa2022-05-10 14:55:34 +00001304 /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001305 const ast::IntLiteralExpression* Expr(const Source& source, i32 value) {
1306 return create<ast::IntLiteralExpression>(source, value,
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001307 ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001308 }
1309
dan sinclair41e4d9a2022-05-01 14:40:55 +00001310 /// @param value the integer value
Ben Clayton41285aa2022-05-10 14:55:34 +00001311 /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001312 const ast::IntLiteralExpression* Expr(i32 value) {
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001313 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001314 }
1315
dan sinclair41e4d9a2022-05-01 14:40:55 +00001316 /// @param source the source information
1317 /// @param value the unsigned int value
Ben Clayton41285aa2022-05-10 14:55:34 +00001318 /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001319 const ast::IntLiteralExpression* Expr(const Source& source, u32 value) {
1320 return create<ast::IntLiteralExpression>(source, value,
1321 ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001322 }
1323
dan sinclair41e4d9a2022-05-01 14:40:55 +00001324 /// @param value the unsigned int value
Ben Clayton41285aa2022-05-10 14:55:34 +00001325 /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001326 const ast::IntLiteralExpression* Expr(u32 value) {
1327 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001328 }
1329
dan sinclair41e4d9a2022-05-01 14:40:55 +00001330 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
1331 /// `list`.
1332 /// @param list the list to append too
1333 /// @param arg the arg to create
Ben Clayton783b1692022-08-02 17:03:35 +00001334 template <size_t N, typename ARG>
1335 void Append(utils::Vector<const ast::Expression*, N>& list, ARG&& arg) {
1336 list.Push(Expr(std::forward<ARG>(arg)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001337 }
1338
dan sinclair41e4d9a2022-05-01 14:40:55 +00001339 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
1340 /// then appends them to `list`.
1341 /// @param list the list to append too
1342 /// @param arg0 the first argument
1343 /// @param args the rest of the arguments
Ben Clayton783b1692022-08-02 17:03:35 +00001344 template <size_t N, typename ARG0, typename... ARGS>
1345 void Append(utils::Vector<const ast::Expression*, N>& list, ARG0&& arg0, ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001346 Append(list, std::forward<ARG0>(arg0));
1347 Append(list, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001348 }
1349
Ben Clayton783b1692022-08-02 17:03:35 +00001350 /// @return utils::EmptyType
1351 utils::EmptyType ExprList() { return utils::Empty; }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001352
1353 /// @param args the list of expressions
1354 /// @return the list of expressions converted to `ast::Expression`s using
1355 /// `Expr()`,
Ben Clayton783b1692022-08-02 17:03:35 +00001356 template <typename... ARGS, typename = DisableIfVectorLike<ARGS...>>
1357 auto ExprList(ARGS&&... args) {
1358 utils::Vector<const ast::Expression*, sizeof...(ARGS)> list;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001359 Append(list, std::forward<ARGS>(args)...);
1360 return list;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001361 }
1362
dan sinclair41e4d9a2022-05-01 14:40:55 +00001363 /// @param list the list of expressions
1364 /// @return `list`
Ben Clayton783b1692022-08-02 17:03:35 +00001365 template <typename T, size_t N>
1366 utils::Vector<T, N> ExprList(utils::Vector<T, N>&& list) {
1367 return std::move(list);
1368 }
1369
1370 /// @param list the list of expressions
1371 /// @return `list`
1372 utils::VectorRef<const ast::Expression*> ExprList(
1373 utils::VectorRef<const ast::Expression*> list) {
1374 return list;
1375 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001376
dan sinclair41e4d9a2022-05-01 14:40:55 +00001377 /// @param expr the expression for the bitcast
1378 /// @return an `ast::BitcastExpression` of type `ty`, with the values of
1379 /// `expr` converted to `ast::Expression`s using `Expr()`
1380 template <typename T, typename EXPR>
1381 const ast::BitcastExpression* Bitcast(EXPR&& expr) {
1382 return Bitcast(ty.Of<T>(), std::forward<EXPR>(expr));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001383 }
1384
dan sinclair41e4d9a2022-05-01 14:40:55 +00001385 /// @param type the type to cast to
1386 /// @param expr the expression for the bitcast
1387 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1388 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001389 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001390 const ast::BitcastExpression* Bitcast(const ast::Type* type, EXPR&& expr) {
1391 return create<ast::BitcastExpression>(type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001392 }
1393
dan sinclair41e4d9a2022-05-01 14:40:55 +00001394 /// @param source the source information
1395 /// @param type the type to cast to
1396 /// @param expr the expression for the bitcast
1397 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1398 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001399 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001400 const ast::BitcastExpression* Bitcast(const Source& source,
1401 const ast::Type* type,
1402 EXPR&& expr) {
1403 return create<ast::BitcastExpression>(source, type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001404 }
1405
dan sinclair6e77b472022-10-20 13:38:28 +00001406 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001407 /// @param type the vector type
1408 /// @param size the vector size
1409 /// @return an `ast::CallExpression` of a `size`-element vector of
1410 /// type `type`, constructed with the values `args`.
1411 template <typename... ARGS>
1412 const ast::CallExpression* vec(const ast::Type* type, uint32_t size, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001413 return Call(ty.vec(type, size), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001414 }
1415
dan sinclair6e77b472022-10-20 13:38:28 +00001416 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001417 /// @return an `ast::CallExpression` of a 2-element vector of type
1418 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001419 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001420 const ast::CallExpression* vec2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001421 return Call(ty.vec2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001422 }
1423
Ben Clayton6315a272022-08-01 17:18:04 +00001424 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001425 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001426 /// @return an `ast::CallExpression` of a 2-element vector of type
1427 /// `T`, constructed with the values `args`.
1428 template <typename T, typename... ARGS>
1429 const ast::CallExpression* vec2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001430 return Call(source, ty.vec2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001431 }
1432
dan sinclair6e77b472022-10-20 13:38:28 +00001433 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001434 /// @return an `ast::CallExpression` of a 3-element vector of type
1435 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001436 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001437 const ast::CallExpression* vec3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001438 return Call(ty.vec3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001439 }
1440
Ben Clayton6315a272022-08-01 17:18:04 +00001441 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001442 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001443 /// @return an `ast::CallExpression` of a 3-element vector of type
1444 /// `T`, constructed with the values `args`.
1445 template <typename T, typename... ARGS>
1446 const ast::CallExpression* vec3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001447 return Call(source, ty.vec3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001448 }
1449
dan sinclair6e77b472022-10-20 13:38:28 +00001450 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001451 /// @return an `ast::CallExpression` of a 4-element vector of type
1452 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001453 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001454 const ast::CallExpression* vec4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001455 return Call(ty.vec4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001456 }
1457
Ben Clayton6315a272022-08-01 17:18:04 +00001458 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001459 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001460 /// @return an `ast::CallExpression` of a 4-element vector of type
1461 /// `T`, constructed with the values `args`.
1462 template <typename T, typename... ARGS>
1463 const ast::CallExpression* vec4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001464 return Call(source, ty.vec4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001465 }
1466
dan sinclair6e77b472022-10-20 13:38:28 +00001467 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001468 /// @return an `ast::CallExpression` of a 2x2 matrix of type
1469 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001470 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001471 const ast::CallExpression* mat2x2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001472 return Call(ty.mat2x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001473 }
1474
Ben Clayton6315a272022-08-01 17:18:04 +00001475 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001476 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001477 /// @return an `ast::CallExpression` of a 2x2 matrix of type
1478 /// `T`, constructed with the values `args`.
1479 template <typename T, typename... ARGS>
1480 const ast::CallExpression* mat2x2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001481 return Call(source, ty.mat2x2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001482 }
1483
dan sinclair6e77b472022-10-20 13:38:28 +00001484 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001485 /// @return an `ast::CallExpression` of a 2x3 matrix of type
1486 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001487 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001488 const ast::CallExpression* mat2x3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001489 return Call(ty.mat2x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001490 }
1491
Ben Clayton6315a272022-08-01 17:18:04 +00001492 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001493 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001494 /// @return an `ast::CallExpression` of a 2x3 matrix of type
1495 /// `T`, constructed with the values `args`.
1496 template <typename T, typename... ARGS>
1497 const ast::CallExpression* mat2x3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001498 return Call(source, ty.mat2x3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001499 }
1500
dan sinclair6e77b472022-10-20 13:38:28 +00001501 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001502 /// @return an `ast::CallExpression` of a 2x4 matrix of type
1503 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001504 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001505 const ast::CallExpression* mat2x4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001506 return Call(ty.mat2x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001507 }
1508
Ben Clayton6315a272022-08-01 17:18:04 +00001509 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001510 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001511 /// @return an `ast::CallExpression` of a 2x4 matrix of type
1512 /// `T`, constructed with the values `args`.
1513 template <typename T, typename... ARGS>
1514 const ast::CallExpression* mat2x4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001515 return Call(source, ty.mat2x4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001516 }
1517
dan sinclair6e77b472022-10-20 13:38:28 +00001518 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001519 /// @return an `ast::CallExpression` of a 3x2 matrix of type
1520 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001521 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001522 const ast::CallExpression* mat3x2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001523 return Call(ty.mat3x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001524 }
1525
Ben Clayton6315a272022-08-01 17:18:04 +00001526 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001527 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001528 /// @return an `ast::CallExpression` of a 3x2 matrix of type
1529 /// `T`, constructed with the values `args`.
1530 template <typename T, typename... ARGS>
1531 const ast::CallExpression* mat3x2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001532 return Call(source, ty.mat3x2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001533 }
1534
dan sinclair6e77b472022-10-20 13:38:28 +00001535 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001536 /// @return an `ast::CallExpression` of a 3x3 matrix of type
1537 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001538 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001539 const ast::CallExpression* mat3x3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001540 return Call(ty.mat3x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001541 }
1542
Ben Clayton6315a272022-08-01 17:18:04 +00001543 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001544 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001545 /// @return an `ast::CallExpression` of a 3x3 matrix of type
1546 /// `T`, constructed with the values `args`.
1547 template <typename T, typename... ARGS>
1548 const ast::CallExpression* mat3x3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001549 return Call(source, ty.mat3x3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001550 }
1551
dan sinclair6e77b472022-10-20 13:38:28 +00001552 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001553 /// @return an `ast::CallExpression` of a 3x4 matrix of type
1554 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001555 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001556 const ast::CallExpression* mat3x4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001557 return Call(ty.mat3x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001558 }
1559
Ben Clayton6315a272022-08-01 17:18:04 +00001560 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001561 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001562 /// @return an `ast::CallExpression` of a 3x4 matrix of type
1563 /// `T`, constructed with the values `args`.
1564 template <typename T, typename... ARGS>
1565 const ast::CallExpression* mat3x4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001566 return Call(source, ty.mat3x4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001567 }
1568
dan sinclair6e77b472022-10-20 13:38:28 +00001569 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001570 /// @return an `ast::CallExpression` of a 4x2 matrix of type
1571 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001572 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001573 const ast::CallExpression* mat4x2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001574 return Call(ty.mat4x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001575 }
1576
Ben Clayton6315a272022-08-01 17:18:04 +00001577 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001578 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001579 /// @return an `ast::CallExpression` of a 4x2 matrix of type
1580 /// `T`, constructed with the values `args`.
1581 template <typename T, typename... ARGS>
1582 const ast::CallExpression* mat4x2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001583 return Call(source, ty.mat4x2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001584 }
1585
dan sinclair6e77b472022-10-20 13:38:28 +00001586 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001587 /// @return an `ast::CallExpression` of a 4x3 matrix of type
1588 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001589 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001590 const ast::CallExpression* mat4x3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001591 return Call(ty.mat4x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001592 }
1593
Ben Clayton6315a272022-08-01 17:18:04 +00001594 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001595 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001596 /// @return an `ast::CallExpression` of a 4x3 matrix of type
1597 /// `T`, constructed with the values `args`.
1598 template <typename T, typename... ARGS>
1599 const ast::CallExpression* mat4x3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001600 return Call(source, ty.mat4x3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001601 }
1602
dan sinclair6e77b472022-10-20 13:38:28 +00001603 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001604 /// @return an `ast::CallExpression` of a 4x4 matrix of type
1605 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001606 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001607 const ast::CallExpression* mat4x4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001608 return Call(ty.mat4x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001609 }
1610
Ben Clayton6315a272022-08-01 17:18:04 +00001611 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001612 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001613 /// @return an `ast::CallExpression` of a 4x4 matrix of type
1614 /// `T`, constructed with the values `args`.
1615 template <typename T, typename... ARGS>
1616 const ast::CallExpression* mat4x4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001617 return Call(source, ty.mat4x4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001618 }
1619
dan sinclair6e77b472022-10-20 13:38:28 +00001620 /// @param args the arguments for the array initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001621 /// @return an `ast::CallExpression` of an array with element type
1622 /// `T` and size `N`, constructed with the values `args`.
1623 template <typename T, int N, typename... ARGS>
1624 const ast::CallExpression* array(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001625 return Call(ty.array<T, N>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001626 }
1627
Ben Clayton6315a272022-08-01 17:18:04 +00001628 /// @param source the array source
dan sinclair6e77b472022-10-20 13:38:28 +00001629 /// @param args the arguments for the array initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001630 /// @return an `ast::CallExpression` of an array with element type
1631 /// `T` and size `N`, constructed with the values `args`.
1632 template <typename T, int N, typename... ARGS>
1633 const ast::CallExpression* array(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001634 return Call(source, ty.array<T, N>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001635 }
1636
dan sinclair41e4d9a2022-05-01 14:40:55 +00001637 /// @param subtype the array element type
1638 /// @param n the array size. nullptr represents a runtime-array.
dan sinclair6e77b472022-10-20 13:38:28 +00001639 /// @param args the arguments for the array initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001640 /// @return an `ast::CallExpression` of an array with element type
1641 /// `subtype`, constructed with the values `args`.
1642 template <typename EXPR, typename... ARGS>
1643 const ast::CallExpression* array(const ast::Type* subtype, EXPR&& n, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001644 return Call(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001645 }
1646
Ben Clayton6315a272022-08-01 17:18:04 +00001647 /// @param source the array source
1648 /// @param subtype the array element type
1649 /// @param n the array size. nullptr represents a runtime-array.
dan sinclair6e77b472022-10-20 13:38:28 +00001650 /// @param args the arguments for the array initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001651 /// @return an `ast::CallExpression` of an array with element type
1652 /// `subtype`, constructed with the values `args`.
1653 template <typename EXPR, typename... ARGS>
1654 const ast::CallExpression* array(const Source& source,
1655 const ast::Type* subtype,
1656 EXPR&& n,
1657 ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001658 return Call(source, ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001659 }
1660
Ben Clayton7f2b8cd2022-05-18 22:41:48 +00001661 /// Adds the extension to the list of enable directives at the top of the module.
1662 /// @param ext the extension to enable
1663 /// @return an `ast::Enable` enabling the given extension.
1664 const ast::Enable* Enable(ast::Extension ext) {
1665 auto* enable = create<ast::Enable>(ext);
1666 AST().AddEnable(enable);
1667 return enable;
1668 }
1669
Ben Clayton1a567782022-10-14 13:38:27 +00001670 /// Adds the extension to the list of enable directives at the top of the module.
1671 /// @param source the enable source
1672 /// @param ext the extension to enable
1673 /// @return an `ast::Enable` enabling the given extension.
1674 const ast::Enable* Enable(const Source& source, ast::Extension ext) {
1675 auto* enable = create<ast::Enable>(source, ext);
1676 AST().AddEnable(enable);
1677 return enable;
1678 }
1679
dan sinclair41e4d9a2022-05-01 14:40:55 +00001680 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001681 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001682 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001683 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001684 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001685 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001686 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001687 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1688 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001689 /// @returns a `ast::Var` with the given name, type and additional
dan sinclair41e4d9a2022-05-01 14:40:55 +00001690 /// options
Ben Clayton58794ae2022-08-19 17:28:53 +00001691 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1692 const ast::Var* Var(NAME&& name, OPTIONS&&... options) {
1693 VarOptions opts(std::forward<OPTIONS>(options)...);
dan sinclairff7cf212022-10-03 14:05:23 +00001694 return create<ast::Var>(Sym(std::forward<NAME>(name)), opts.type, opts.address_space,
dan sinclair6e77b472022-10-20 13:38:28 +00001695 opts.access, opts.initializer, std::move(opts.attributes));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001696 }
1697
dan sinclair41e4d9a2022-05-01 14:40:55 +00001698 /// @param source the variable source
1699 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001700 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001701 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001702 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001703 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001704 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001705 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001706 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1707 /// Note that non-repeatable arguments of the same type will use the last argument's value.
dan sinclairff7cf212022-10-03 14:05:23 +00001708 /// @returns a `ast::Var` with the given name, address_space and type
Ben Clayton58794ae2022-08-19 17:28:53 +00001709 template <typename NAME, typename... OPTIONS>
1710 const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) {
1711 VarOptions opts(std::forward<OPTIONS>(options)...);
dan sinclairff7cf212022-10-03 14:05:23 +00001712 return create<ast::Var>(source, Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001713 opts.address_space, opts.access, opts.initializer,
dan sinclairff7cf212022-10-03 14:05:23 +00001714 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001715 }
1716
1717 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001718 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001719 /// Can be any of the following, in any order:
1720 /// * ast::Expression* - specifies the variable's initializer expression (required)
1721 /// * ast::Type* - specifies the variable type
1722 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1723 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1724 /// @returns an `ast::Const` with the given name, type and additional options
1725 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1726 const ast::Const* Const(NAME&& name, OPTIONS&&... options) {
1727 ConstOptions opts(std::forward<OPTIONS>(options)...);
dan sinclair6e77b472022-10-20 13:38:28 +00001728 return create<ast::Const>(Sym(std::forward<NAME>(name)), opts.type, opts.initializer,
Ben Clayton58794ae2022-08-19 17:28:53 +00001729 std::move(opts.attributes));
Ben Claytone3834c42022-06-25 23:21:39 +00001730 }
1731
1732 /// @param source the variable source
1733 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001734 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001735 /// Can be any of the following, in any order:
1736 /// * ast::Expression* - specifies the variable's initializer expression (required)
1737 /// * ast::Type* - specifies the variable type
1738 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1739 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1740 /// @returns an `ast::Const` with the given name, type and additional options
1741 template <typename NAME, typename... OPTIONS>
1742 const ast::Const* Const(const Source& source, NAME&& name, OPTIONS&&... options) {
1743 ConstOptions opts(std::forward<OPTIONS>(options)...);
1744 return create<ast::Const>(source, Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001745 opts.initializer, std::move(opts.attributes));
Ben Claytone3834c42022-06-25 23:21:39 +00001746 }
1747
1748 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001749 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001750 /// Can be any of the following, in any order:
1751 /// * ast::Expression* - specifies the variable's initializer expression (required)
1752 /// * ast::Type* - specifies the variable type
1753 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1754 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1755 /// @returns an `ast::Let` with the given name, type and additional options
1756 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1757 const ast::Let* Let(NAME&& name, OPTIONS&&... options) {
1758 LetOptions opts(std::forward<OPTIONS>(options)...);
dan sinclair6e77b472022-10-20 13:38:28 +00001759 return create<ast::Let>(Sym(std::forward<NAME>(name)), opts.type, opts.initializer,
Ben Clayton58794ae2022-08-19 17:28:53 +00001760 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001761 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001762
dan sinclair41e4d9a2022-05-01 14:40:55 +00001763 /// @param source the variable source
1764 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001765 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001766 /// Can be any of the following, in any order:
1767 /// * ast::Expression* - specifies the variable's initializer expression (required)
1768 /// * ast::Type* - specifies the variable type
1769 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1770 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1771 /// @returns an `ast::Let` with the given name, type and additional options
1772 template <typename NAME, typename... OPTIONS>
1773 const ast::Let* Let(const Source& source, NAME&& name, OPTIONS&&... options) {
1774 LetOptions opts(std::forward<OPTIONS>(options)...);
dan sinclair6e77b472022-10-20 13:38:28 +00001775 return create<ast::Let>(source, Sym(std::forward<NAME>(name)), opts.type, opts.initializer,
Ben Clayton58794ae2022-08-19 17:28:53 +00001776 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001777 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001778
dan sinclair41e4d9a2022-05-01 14:40:55 +00001779 /// @param name the parameter name
1780 /// @param type the parameter type
1781 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001782 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001783 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001784 const ast::Parameter* Param(NAME&& name,
1785 const ast::Type* type,
Ben Clayton783b1692022-08-02 17:03:35 +00001786 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Claytondcdf66e2022-06-17 12:48:51 +00001787 return create<ast::Parameter>(Sym(std::forward<NAME>(name)), type, attributes);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001788 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001789
dan sinclair41e4d9a2022-05-01 14:40:55 +00001790 /// @param source the parameter source
1791 /// @param name the parameter name
1792 /// @param type the parameter type
1793 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001794 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001795 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001796 const ast::Parameter* Param(const Source& source,
1797 NAME&& name,
1798 const ast::Type* type,
Ben Clayton783b1692022-08-02 17:03:35 +00001799 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Claytondcdf66e2022-06-17 12:48:51 +00001800 return create<ast::Parameter>(source, Sym(std::forward<NAME>(name)), type, attributes);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001801 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001802
dan sinclair41e4d9a2022-05-01 14:40:55 +00001803 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001804 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001805 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001806 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001807 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001808 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001809 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001810 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1811 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001812 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1813 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001814 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1815 const ast::Var* GlobalVar(NAME&& name, OPTIONS&&... options) {
1816 auto* variable = Var(std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1817 AST().AddGlobalVariable(variable);
1818 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001819 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001820
dan sinclair41e4d9a2022-05-01 14:40:55 +00001821 /// @param source the variable source
1822 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001823 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001824 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001825 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001826 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001827 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001828 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001829 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1830 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001831 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1832 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001833 template <typename NAME, typename... OPTIONS>
1834 const ast::Var* GlobalVar(const Source& source, NAME&& name, OPTIONS&&... options) {
1835 auto* variable = Var(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1836 AST().AddGlobalVariable(variable);
1837 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001838 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001839
dan sinclair41e4d9a2022-05-01 14:40:55 +00001840 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001841 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001842 /// Can be any of the following, in any order:
1843 /// * ast::Expression* - specifies the variable's initializer expression (required)
1844 /// * ast::Type* - specifies the variable type
1845 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1846 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1847 /// @returns an `ast::Const` with the given name, type and additional options, which is
1848 /// automatically registered as a global variable with the ast::Module.
1849 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1850 const ast::Const* GlobalConst(NAME&& name, OPTIONS&&... options) {
1851 auto* variable = Const(std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1852 AST().AddGlobalVariable(variable);
1853 return variable;
Ben Claytone3834c42022-06-25 23:21:39 +00001854 }
1855
1856 /// @param source the variable source
1857 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001858 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001859 /// Can be any of the following, in any order:
1860 /// * ast::Expression* - specifies the variable's initializer expression (required)
1861 /// * ast::Type* - specifies the variable type
1862 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1863 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1864 /// @returns an `ast::Const` with the given name, type and additional options, which is
1865 /// automatically registered as a global variable with the ast::Module.
1866 template <typename NAME, typename... OPTIONS>
1867 const ast::Const* GlobalConst(const Source& source, NAME&& name, OPTIONS&&... options) {
1868 auto* variable = Const(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1869 AST().AddGlobalVariable(variable);
1870 return variable;
Ben Claytone3834c42022-06-25 23:21:39 +00001871 }
1872
1873 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001874 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001875 /// Can be any of the following, in any order:
1876 /// * ast::Expression* - specifies the variable's initializer expression (required)
1877 /// * ast::Type* - specifies the variable type
1878 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1879 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1880 /// @returns an `ast::Override` with the given name, type and additional options, which is
1881 /// automatically registered as a global variable with the ast::Module.
1882 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1883 const ast::Override* Override(NAME&& name, OPTIONS&&... options) {
1884 OverrideOptions opts(std::forward<OPTIONS>(options)...);
1885 auto* variable = create<ast::Override>(Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001886 opts.initializer, std::move(opts.attributes));
Ben Clayton58794ae2022-08-19 17:28:53 +00001887 AST().AddGlobalVariable(variable);
1888 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001889 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001890
dan sinclair41e4d9a2022-05-01 14:40:55 +00001891 /// @param source the variable source
1892 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001893 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001894 /// Can be any of the following, in any order:
1895 /// * ast::Expression* - specifies the variable's initializer expression (required)
1896 /// * ast::Type* - specifies the variable type
1897 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1898 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1899 /// @returns an `ast::Override` with the given name, type and additional options, which is
1900 /// automatically registered as a global variable with the ast::Module.
1901 template <typename NAME, typename... OPTIONS>
1902 const ast::Override* Override(const Source& source, NAME&& name, OPTIONS&&... options) {
1903 OverrideOptions opts(std::forward<OPTIONS>(options)...);
1904 auto* variable = create<ast::Override>(source, Sym(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001905 opts.initializer, std::move(opts.attributes));
Ben Clayton58794ae2022-08-19 17:28:53 +00001906 AST().AddGlobalVariable(variable);
1907 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001908 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001909
dan sinclair41e4d9a2022-05-01 14:40:55 +00001910 /// @param source the source information
Ben Claytonbfd1a812022-08-02 23:16:25 +00001911 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001912 /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement
Ben Claytonbfd1a812022-08-02 23:16:25 +00001913 /// with the ast::Module.
1914 template <typename EXPR>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001915 const ast::ConstAssert* GlobalConstAssert(const Source& source, EXPR&& condition) {
1916 auto* sa = ConstAssert(source, std::forward<EXPR>(condition));
1917 AST().AddConstAssert(sa);
Ben Claytonbfd1a812022-08-02 23:16:25 +00001918 return sa;
1919 }
1920
1921 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001922 /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement
Ben Claytonbfd1a812022-08-02 23:16:25 +00001923 /// with the ast::Module.
1924 template <typename EXPR, typename = DisableIfSource<EXPR>>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001925 const ast::ConstAssert* GlobalConstAssert(EXPR&& condition) {
1926 auto* sa = ConstAssert(std::forward<EXPR>(condition));
1927 AST().AddConstAssert(sa);
Ben Claytonbfd1a812022-08-02 23:16:25 +00001928 return sa;
1929 }
1930
1931 /// @param source the source information
1932 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001933 /// @returns a new `ast::ConstAssert` with the given assertion condition
Ben Claytonbfd1a812022-08-02 23:16:25 +00001934 template <typename EXPR>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001935 const ast::ConstAssert* ConstAssert(const Source& source, EXPR&& condition) {
1936 return create<ast::ConstAssert>(source, Expr(std::forward<EXPR>(condition)));
Ben Claytonbfd1a812022-08-02 23:16:25 +00001937 }
1938
1939 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001940 /// @returns a new `ast::ConstAssert` with the given assertion condition
Ben Claytonbfd1a812022-08-02 23:16:25 +00001941 template <typename EXPR, typename = DisableIfSource<EXPR>>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001942 const ast::ConstAssert* ConstAssert(EXPR&& condition) {
1943 return create<ast::ConstAssert>(Expr(std::forward<EXPR>(condition)));
Ben Claytonbfd1a812022-08-02 23:16:25 +00001944 }
1945
1946 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001947 /// @param expr the expression to take the address of
1948 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1949 template <typename EXPR>
1950 const ast::UnaryOpExpression* AddressOf(const Source& source, EXPR&& expr) {
1951 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kAddressOf,
1952 Expr(std::forward<EXPR>(expr)));
1953 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001954
dan sinclair41e4d9a2022-05-01 14:40:55 +00001955 /// @param expr the expression to take the address of
1956 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1957 template <typename EXPR>
1958 const ast::UnaryOpExpression* AddressOf(EXPR&& expr) {
1959 return create<ast::UnaryOpExpression>(ast::UnaryOp::kAddressOf,
1960 Expr(std::forward<EXPR>(expr)));
1961 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001962
dan sinclair41e4d9a2022-05-01 14:40:55 +00001963 /// @param source the source information
1964 /// @param expr the expression to perform an indirection on
1965 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1966 template <typename EXPR>
1967 const ast::UnaryOpExpression* Deref(const Source& source, EXPR&& expr) {
1968 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kIndirection,
1969 Expr(std::forward<EXPR>(expr)));
1970 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001971
dan sinclair41e4d9a2022-05-01 14:40:55 +00001972 /// @param expr the expression to perform an indirection on
1973 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1974 template <typename EXPR>
1975 const ast::UnaryOpExpression* Deref(EXPR&& expr) {
1976 return create<ast::UnaryOpExpression>(ast::UnaryOp::kIndirection,
1977 Expr(std::forward<EXPR>(expr)));
1978 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001979
dan sinclair41e4d9a2022-05-01 14:40:55 +00001980 /// @param expr the expression to perform a unary not on
1981 /// @return an ast::UnaryOpExpression that is the unary not of the input
1982 /// expression
1983 template <typename EXPR>
1984 const ast::UnaryOpExpression* Not(EXPR&& expr) {
1985 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(std::forward<EXPR>(expr)));
1986 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001987
Antonio Maiorano28779af2022-12-09 21:28:51 +00001988 /// @param source the source information
1989 /// @param expr the expression to perform a unary not on
1990 /// @return an ast::UnaryOpExpression that is the unary not of the input
1991 /// expression
1992 template <typename EXPR>
1993 const ast::UnaryOpExpression* Not(const Source& source, EXPR&& expr) {
1994 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kNot,
1995 Expr(std::forward<EXPR>(expr)));
1996 }
1997
dan sinclair41e4d9a2022-05-01 14:40:55 +00001998 /// @param expr the expression to perform a unary complement on
1999 /// @return an ast::UnaryOpExpression that is the unary complement of the
2000 /// input expression
2001 template <typename EXPR>
2002 const ast::UnaryOpExpression* Complement(EXPR&& expr) {
2003 return create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement,
2004 Expr(std::forward<EXPR>(expr)));
2005 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002006
Author: Shiyu Liub3aab092022-05-04 13:07:29 +00002007 /// @param expr the expression to perform a unary negation on
2008 /// @return an ast::UnaryOpExpression that is the unary negation of the
2009 /// input expression
2010 template <typename EXPR>
2011 const ast::UnaryOpExpression* Negation(EXPR&& expr) {
2012 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation,
2013 Expr(std::forward<EXPR>(expr)));
2014 }
2015
Ben Clayton01ac21c2023-02-07 16:14:25 +00002016 /// @param target the call target
dan sinclair41e4d9a2022-05-01 14:40:55 +00002017 /// @param args the function call arguments
2018 /// @returns a `ast::CallExpression` to the function `func`, with the
2019 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
Ben Clayton01ac21c2023-02-07 16:14:25 +00002020 template <typename TARGET,
2021 typename... ARGS,
2022 typename = DisableIfSource<TARGET>,
2023 typename = DisableIfScalar<TARGET>>
2024 const ast::CallExpression* Call(TARGET&& target, ARGS&&... args) {
2025 return Call(source_, std::forward<TARGET>(target), std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002026 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002027
Ben Clayton01ac21c2023-02-07 16:14:25 +00002028 /// @param source the source information
2029 /// @param target the call target. Can be an ast::Type or ast::Identifier, or string-like.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002030 /// @param args the function call arguments
Ben Clayton01ac21c2023-02-07 16:14:25 +00002031 /// @returns a `ast::CallExpression` to the target @p target, with the arguments of @p args
2032 /// converted to `ast::Expression`s using Expr().
2033 template <typename TARGET, typename... ARGS, typename = DisableIfScalar<TARGET>>
2034 const ast::CallExpression* Call(const Source& source, TARGET&& target, ARGS&&... args) {
2035 if constexpr (traits::IsTypeOrDerived<traits::PtrElTy<TARGET>, ast::Type>) {
2036 return create<ast::CallExpression>(source, target,
2037 ExprList(std::forward<ARGS>(args)...));
2038
2039 } else {
2040 return create<ast::CallExpression>(source, Ident(target),
2041 ExprList(std::forward<ARGS>(args)...));
2042 }
2043 }
2044
2045 /// @param args the arguments for the type constructor
2046 /// @return an `ast::CallExpression` of type `ty`, with the values
2047 /// of `args` converted to `ast::Expression`s using `Expr()`
2048 template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
2049 const ast::CallExpression* Call(ARGS&&... args) {
2050 return Call(ty.Of<T>(), std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002051 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002052
dan sinclair41e4d9a2022-05-01 14:40:55 +00002053 /// @param source the source information
2054 /// @param call the call expression to wrap in a call statement
2055 /// @returns a `ast::CallStatement` for the given call expression
2056 const ast::CallStatement* CallStmt(const Source& source, const ast::CallExpression* call) {
2057 return create<ast::CallStatement>(source, call);
2058 }
James Pricec022ff52022-03-31 22:30:10 +00002059
dan sinclair41e4d9a2022-05-01 14:40:55 +00002060 /// @param call the call expression to wrap in a call statement
2061 /// @returns a `ast::CallStatement` for the given call expression
2062 const ast::CallStatement* CallStmt(const ast::CallExpression* call) {
2063 return create<ast::CallStatement>(call);
2064 }
James Pricec022ff52022-03-31 22:30:10 +00002065
dan sinclair41e4d9a2022-05-01 14:40:55 +00002066 /// @param source the source information
2067 /// @returns a `ast::PhonyExpression`
2068 const ast::PhonyExpression* Phony(const Source& source) {
2069 return create<ast::PhonyExpression>(source);
2070 }
James Priceebe97412022-04-07 13:42:45 +00002071
dan sinclair41e4d9a2022-05-01 14:40:55 +00002072 /// @returns a `ast::PhonyExpression`
2073 const ast::PhonyExpression* Phony() { return create<ast::PhonyExpression>(); }
James Priceebe97412022-04-07 13:42:45 +00002074
dan sinclair41e4d9a2022-05-01 14:40:55 +00002075 /// @param expr the expression to ignore
2076 /// @returns a `ast::AssignmentStatement` that assigns 'expr' to the phony
2077 /// (underscore) variable.
2078 template <typename EXPR>
2079 const ast::AssignmentStatement* Ignore(EXPR&& expr) {
2080 return create<ast::AssignmentStatement>(Phony(), Expr(expr));
2081 }
James Priceebe97412022-04-07 13:42:45 +00002082
dan sinclair41e4d9a2022-05-01 14:40:55 +00002083 /// @param lhs the left hand argument to the addition operation
2084 /// @param rhs the right hand argument to the addition operation
2085 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2086 template <typename LHS, typename RHS>
2087 const ast::BinaryExpression* Add(LHS&& lhs, RHS&& rhs) {
2088 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd, Expr(std::forward<LHS>(lhs)),
2089 Expr(std::forward<RHS>(rhs)));
2090 }
James Priceebe97412022-04-07 13:42:45 +00002091
Antonio Maiorano7058a172022-08-10 18:06:43 +00002092 /// @param source the source information
2093 /// @param lhs the left hand argument to the addition operation
2094 /// @param rhs the right hand argument to the addition operation
2095 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2096 template <typename LHS, typename RHS>
2097 const ast::BinaryExpression* Add(const Source& source, LHS&& lhs, RHS&& rhs) {
2098 return create<ast::BinaryExpression>(source, ast::BinaryOp::kAdd,
2099 Expr(std::forward<LHS>(lhs)),
2100 Expr(std::forward<RHS>(rhs)));
2101 }
2102
dan sinclair41e4d9a2022-05-01 14:40:55 +00002103 /// @param lhs the left hand argument to the and operation
2104 /// @param rhs the right hand argument to the and operation
2105 /// @returns a `ast::BinaryExpression` bitwise anding `lhs` and `rhs`
2106 template <typename LHS, typename RHS>
2107 const ast::BinaryExpression* And(LHS&& lhs, RHS&& rhs) {
2108 return create<ast::BinaryExpression>(ast::BinaryOp::kAnd, Expr(std::forward<LHS>(lhs)),
2109 Expr(std::forward<RHS>(rhs)));
2110 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002111
dan sinclair41e4d9a2022-05-01 14:40:55 +00002112 /// @param lhs the left hand argument to the or operation
2113 /// @param rhs the right hand argument to the or operation
2114 /// @returns a `ast::BinaryExpression` bitwise or-ing `lhs` and `rhs`
2115 template <typename LHS, typename RHS>
2116 const ast::BinaryExpression* Or(LHS&& lhs, RHS&& rhs) {
2117 return create<ast::BinaryExpression>(ast::BinaryOp::kOr, Expr(std::forward<LHS>(lhs)),
2118 Expr(std::forward<RHS>(rhs)));
2119 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002120
dan sinclair41e4d9a2022-05-01 14:40:55 +00002121 /// @param lhs the left hand argument to the subtraction operation
2122 /// @param rhs the right hand argument to the subtraction operation
2123 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs`
2124 template <typename LHS, typename RHS>
2125 const ast::BinaryExpression* Sub(LHS&& lhs, RHS&& rhs) {
2126 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract, Expr(std::forward<LHS>(lhs)),
2127 Expr(std::forward<RHS>(rhs)));
2128 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002129
dan sinclair41e4d9a2022-05-01 14:40:55 +00002130 /// @param lhs the left hand argument to the multiplication operation
2131 /// @param rhs the right hand argument to the multiplication operation
2132 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2133 template <typename LHS, typename RHS>
2134 const ast::BinaryExpression* Mul(LHS&& lhs, RHS&& rhs) {
2135 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, Expr(std::forward<LHS>(lhs)),
2136 Expr(std::forward<RHS>(rhs)));
2137 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002138
dan sinclair41e4d9a2022-05-01 14:40:55 +00002139 /// @param source the source information
2140 /// @param lhs the left hand argument to the multiplication operation
2141 /// @param rhs the right hand argument to the multiplication operation
2142 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2143 template <typename LHS, typename RHS>
2144 const ast::BinaryExpression* Mul(const Source& source, LHS&& lhs, RHS&& rhs) {
2145 return create<ast::BinaryExpression>(source, ast::BinaryOp::kMultiply,
2146 Expr(std::forward<LHS>(lhs)),
2147 Expr(std::forward<RHS>(rhs)));
2148 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002149
dan sinclair41e4d9a2022-05-01 14:40:55 +00002150 /// @param lhs the left hand argument to the division operation
2151 /// @param rhs the right hand argument to the division operation
2152 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2153 template <typename LHS, typename RHS>
2154 const ast::BinaryExpression* Div(LHS&& lhs, RHS&& rhs) {
2155 return create<ast::BinaryExpression>(ast::BinaryOp::kDivide, Expr(std::forward<LHS>(lhs)),
2156 Expr(std::forward<RHS>(rhs)));
2157 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002158
Antonio Maiorano28779af2022-12-09 21:28:51 +00002159 /// @param source the source information
2160 /// @param lhs the left hand argument to the division operation
2161 /// @param rhs the right hand argument to the division operation
2162 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2163 template <typename LHS, typename RHS>
2164 const ast::BinaryExpression* Div(const Source& source, LHS&& lhs, RHS&& rhs) {
2165 return create<ast::BinaryExpression>(source, ast::BinaryOp::kDivide,
2166 Expr(std::forward<LHS>(lhs)),
2167 Expr(std::forward<RHS>(rhs)));
2168 }
2169
dan sinclair41e4d9a2022-05-01 14:40:55 +00002170 /// @param lhs the left hand argument to the modulo operation
2171 /// @param rhs the right hand argument to the modulo operation
2172 /// @returns a `ast::BinaryExpression` applying modulo of `lhs` by `rhs`
2173 template <typename LHS, typename RHS>
2174 const ast::BinaryExpression* Mod(LHS&& lhs, RHS&& rhs) {
2175 return create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr(std::forward<LHS>(lhs)),
2176 Expr(std::forward<RHS>(rhs)));
2177 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002178
dan sinclair41e4d9a2022-05-01 14:40:55 +00002179 /// @param lhs the left hand argument to the bit shift right operation
2180 /// @param rhs the right hand argument to the bit shift right operation
2181 /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs`
2182 template <typename LHS, typename RHS>
2183 const ast::BinaryExpression* Shr(LHS&& lhs, RHS&& rhs) {
2184 return create<ast::BinaryExpression>(
2185 ast::BinaryOp::kShiftRight, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2186 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002187
dan sinclair41e4d9a2022-05-01 14:40:55 +00002188 /// @param lhs the left hand argument to the bit shift left operation
2189 /// @param rhs the right hand argument to the bit shift left operation
2190 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2191 template <typename LHS, typename RHS>
2192 const ast::BinaryExpression* Shl(LHS&& lhs, RHS&& rhs) {
2193 return create<ast::BinaryExpression>(
2194 ast::BinaryOp::kShiftLeft, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2195 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002196
Antonio Maiorano5f33fac2022-09-23 21:58:29 +00002197 /// @param source the source information
2198 /// @param lhs the left hand argument to the bit shift left operation
2199 /// @param rhs the right hand argument to the bit shift left operation
2200 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2201 template <typename LHS, typename RHS>
2202 const ast::BinaryExpression* Shl(const Source& source, LHS&& lhs, RHS&& rhs) {
2203 return create<ast::BinaryExpression>(source, ast::BinaryOp::kShiftLeft,
2204 Expr(std::forward<LHS>(lhs)),
2205 Expr(std::forward<RHS>(rhs)));
2206 }
2207
dan sinclair41e4d9a2022-05-01 14:40:55 +00002208 /// @param lhs the left hand argument to the xor operation
2209 /// @param rhs the right hand argument to the xor operation
2210 /// @returns a `ast::BinaryExpression` bitwise xor-ing `lhs` and `rhs`
2211 template <typename LHS, typename RHS>
2212 const ast::BinaryExpression* Xor(LHS&& lhs, RHS&& rhs) {
2213 return create<ast::BinaryExpression>(ast::BinaryOp::kXor, Expr(std::forward<LHS>(lhs)),
2214 Expr(std::forward<RHS>(rhs)));
2215 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002216
dan sinclair41e4d9a2022-05-01 14:40:55 +00002217 /// @param lhs the left hand argument to the logical and operation
2218 /// @param rhs the right hand argument to the logical and operation
2219 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2220 template <typename LHS, typename RHS>
2221 const ast::BinaryExpression* LogicalAnd(LHS&& lhs, RHS&& rhs) {
2222 return create<ast::BinaryExpression>(
2223 ast::BinaryOp::kLogicalAnd, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2224 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002225
Antonio Maiorano28779af2022-12-09 21:28:51 +00002226 /// @param source the source information
2227 /// @param lhs the left hand argument to the logical and operation
2228 /// @param rhs the right hand argument to the logical and operation
2229 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2230 template <typename LHS, typename RHS>
2231 const ast::BinaryExpression* LogicalAnd(const Source& source, LHS&& lhs, RHS&& rhs) {
2232 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalAnd,
2233 Expr(std::forward<LHS>(lhs)),
2234 Expr(std::forward<RHS>(rhs)));
2235 }
2236
dan sinclair41e4d9a2022-05-01 14:40:55 +00002237 /// @param lhs the left hand argument to the logical or operation
2238 /// @param rhs the right hand argument to the logical or operation
2239 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2240 template <typename LHS, typename RHS>
2241 const ast::BinaryExpression* LogicalOr(LHS&& lhs, RHS&& rhs) {
2242 return create<ast::BinaryExpression>(
2243 ast::BinaryOp::kLogicalOr, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2244 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002245
Antonio Maiorano28779af2022-12-09 21:28:51 +00002246 /// @param source the source information
2247 /// @param lhs the left hand argument to the logical or operation
2248 /// @param rhs the right hand argument to the logical or operation
2249 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2250 template <typename LHS, typename RHS>
2251 const ast::BinaryExpression* LogicalOr(const Source& source, LHS&& lhs, RHS&& rhs) {
2252 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalOr,
2253 Expr(std::forward<LHS>(lhs)),
2254 Expr(std::forward<RHS>(rhs)));
2255 }
2256
dan sinclair41e4d9a2022-05-01 14:40:55 +00002257 /// @param lhs the left hand argument to the greater than operation
2258 /// @param rhs the right hand argument to the greater than operation
2259 /// @returns a `ast::BinaryExpression` of `lhs` > `rhs`
2260 template <typename LHS, typename RHS>
2261 const ast::BinaryExpression* GreaterThan(LHS&& lhs, RHS&& rhs) {
2262 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThan,
2263 Expr(std::forward<LHS>(lhs)),
2264 Expr(std::forward<RHS>(rhs)));
2265 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002266
dan sinclair41e4d9a2022-05-01 14:40:55 +00002267 /// @param lhs the left hand argument to the greater than or equal operation
2268 /// @param rhs the right hand argument to the greater than or equal operation
2269 /// @returns a `ast::BinaryExpression` of `lhs` >= `rhs`
2270 template <typename LHS, typename RHS>
2271 const ast::BinaryExpression* GreaterThanEqual(LHS&& lhs, RHS&& rhs) {
2272 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThanEqual,
2273 Expr(std::forward<LHS>(lhs)),
2274 Expr(std::forward<RHS>(rhs)));
2275 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002276
dan sinclair41e4d9a2022-05-01 14:40:55 +00002277 /// @param lhs the left hand argument to the less than operation
2278 /// @param rhs the right hand argument to the less than operation
2279 /// @returns a `ast::BinaryExpression` of `lhs` < `rhs`
2280 template <typename LHS, typename RHS>
2281 const ast::BinaryExpression* LessThan(LHS&& lhs, RHS&& rhs) {
2282 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThan, Expr(std::forward<LHS>(lhs)),
2283 Expr(std::forward<RHS>(rhs)));
2284 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002285
dan sinclair41e4d9a2022-05-01 14:40:55 +00002286 /// @param lhs the left hand argument to the less than or equal operation
2287 /// @param rhs the right hand argument to the less than or equal operation
2288 /// @returns a `ast::BinaryExpression` of `lhs` <= `rhs`
2289 template <typename LHS, typename RHS>
2290 const ast::BinaryExpression* LessThanEqual(LHS&& lhs, RHS&& rhs) {
2291 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThanEqual,
2292 Expr(std::forward<LHS>(lhs)),
2293 Expr(std::forward<RHS>(rhs)));
2294 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002295
dan sinclair41e4d9a2022-05-01 14:40:55 +00002296 /// @param lhs the left hand argument to the equal expression
2297 /// @param rhs the right hand argument to the equal expression
2298 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2299 template <typename LHS, typename RHS>
2300 const ast::BinaryExpression* Equal(LHS&& lhs, RHS&& rhs) {
2301 return create<ast::BinaryExpression>(ast::BinaryOp::kEqual, Expr(std::forward<LHS>(lhs)),
2302 Expr(std::forward<RHS>(rhs)));
2303 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002304
Antonio Maiorano28779af2022-12-09 21:28:51 +00002305 /// @param source the source information
2306 /// @param lhs the left hand argument to the equal expression
2307 /// @param rhs the right hand argument to the equal expression
2308 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2309 template <typename LHS, typename RHS>
2310 const ast::BinaryExpression* Equal(const Source& source, LHS&& lhs, RHS&& rhs) {
2311 return create<ast::BinaryExpression>(source, ast::BinaryOp::kEqual,
2312 Expr(std::forward<LHS>(lhs)),
2313 Expr(std::forward<RHS>(rhs)));
2314 }
2315
dan sinclair41e4d9a2022-05-01 14:40:55 +00002316 /// @param lhs the left hand argument to the not-equal expression
2317 /// @param rhs the right hand argument to the not-equal expression
2318 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` for
2319 /// disequality
2320 template <typename LHS, typename RHS>
2321 const ast::BinaryExpression* NotEqual(LHS&& lhs, RHS&& rhs) {
2322 return create<ast::BinaryExpression>(ast::BinaryOp::kNotEqual, Expr(std::forward<LHS>(lhs)),
2323 Expr(std::forward<RHS>(rhs)));
2324 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002325
dan sinclair41e4d9a2022-05-01 14:40:55 +00002326 /// @param source the source information
Ben Clayton2cdf1342023-02-03 13:24:18 +00002327 /// @param object the object for the index accessor expression
2328 /// @param index the index argument for the index accessor expression
2329 /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index
2330 template <typename OBJECT, typename INDEX>
2331 const ast::IndexAccessorExpression* IndexAccessor(const Source& source,
2332 OBJECT&& object,
2333 INDEX&& index) {
2334 return create<ast::IndexAccessorExpression>(source, Expr(std::forward<OBJECT>(object)),
2335 Expr(std::forward<INDEX>(index)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002336 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002337
Ben Clayton2cdf1342023-02-03 13:24:18 +00002338 /// @param object the object for the index accessor expression
2339 /// @param index the index argument for the index accessor expression
2340 /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index
2341 template <typename OBJECT, typename INDEX>
2342 const ast::IndexAccessorExpression* IndexAccessor(OBJECT&& object, INDEX&& index) {
2343 return create<ast::IndexAccessorExpression>(Expr(std::forward<OBJECT>(object)),
2344 Expr(std::forward<INDEX>(index)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002345 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002346
dan sinclair41e4d9a2022-05-01 14:40:55 +00002347 /// @param source the source information
Ben Clayton2cdf1342023-02-03 13:24:18 +00002348 /// @param object the object for the member accessor expression
2349 /// @param member the member argument for the member accessor expression
2350 /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member
2351 template <typename OBJECT, typename MEMBER>
dan sinclair41e4d9a2022-05-01 14:40:55 +00002352 const ast::MemberAccessorExpression* MemberAccessor(const Source& source,
Ben Clayton2cdf1342023-02-03 13:24:18 +00002353 OBJECT&& object,
2354 MEMBER&& member) {
2355 static_assert(!traits::IsType<traits::PtrElTy<MEMBER>, ast::TemplatedIdentifier>,
2356 "it is currently invalid for a structure to hold a templated member");
2357 return create<ast::MemberAccessorExpression>(source, Expr(std::forward<OBJECT>(object)),
2358 Ident(std::forward<MEMBER>(member)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002359 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002360
Ben Clayton2cdf1342023-02-03 13:24:18 +00002361 /// @param object the object for the member accessor expression
2362 /// @param member the member argument for the member accessor expression
2363 /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member
2364 template <typename OBJECT, typename MEMBER>
2365 const ast::MemberAccessorExpression* MemberAccessor(OBJECT&& object, MEMBER&& member) {
2366 return MemberAccessor(source_, std::forward<OBJECT>(object), std::forward<MEMBER>(member));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002367 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002368
dan sinclair41e4d9a2022-05-01 14:40:55 +00002369 /// Creates a ast::StructMemberOffsetAttribute
dan sinclair93df9672022-09-09 14:49:09 +00002370 /// @param val the offset expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002371 /// @returns the offset attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002372 template <typename EXPR>
2373 const ast::StructMemberOffsetAttribute* MemberOffset(EXPR&& val) {
2374 return create<ast::StructMemberOffsetAttribute>(source_, Expr(std::forward<EXPR>(val)));
2375 }
2376
2377 /// Creates a ast::StructMemberOffsetAttribute
2378 /// @param source the source information
2379 /// @param val the offset expression
2380 /// @returns the offset attribute pointer
2381 template <typename EXPR>
2382 const ast::StructMemberOffsetAttribute* MemberOffset(const Source& source, EXPR&& val) {
2383 return create<ast::StructMemberOffsetAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002384 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002385
dan sinclair41e4d9a2022-05-01 14:40:55 +00002386 /// Creates a ast::StructMemberSizeAttribute
2387 /// @param source the source information
2388 /// @param val the size value
2389 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002390 template <typename EXPR>
2391 const ast::StructMemberSizeAttribute* MemberSize(const Source& source, EXPR&& val) {
2392 return create<ast::StructMemberSizeAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002393 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002394
dan sinclair41e4d9a2022-05-01 14:40:55 +00002395 /// Creates a ast::StructMemberSizeAttribute
2396 /// @param val the size value
2397 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002398 template <typename EXPR>
2399 const ast::StructMemberSizeAttribute* MemberSize(EXPR&& val) {
2400 return create<ast::StructMemberSizeAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002401 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002402
dan sinclair41e4d9a2022-05-01 14:40:55 +00002403 /// Creates a ast::StructMemberAlignAttribute
2404 /// @param source the source information
dan sinclair4964d9b2022-08-23 13:28:44 +00002405 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002406 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002407 template <typename EXPR>
2408 const ast::StructMemberAlignAttribute* MemberAlign(const Source& source, EXPR&& val) {
2409 return create<ast::StructMemberAlignAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002410 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002411
dan sinclair41e4d9a2022-05-01 14:40:55 +00002412 /// Creates a ast::StructMemberAlignAttribute
dan sinclair4964d9b2022-08-23 13:28:44 +00002413 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002414 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002415 template <typename EXPR>
2416 const ast::StructMemberAlignAttribute* MemberAlign(EXPR&& val) {
2417 return create<ast::StructMemberAlignAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002418 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002419
Ben Clayton9e367232023-02-08 14:17:37 +00002420 /// Creates a ast::StrideAttribute
2421 /// @param stride the array stride
2422 /// @returns the ast::StrideAttribute attribute
2423 const ast::StrideAttribute* Stride(uint32_t stride) {
2424 return create<ast::StrideAttribute>(source_, stride);
2425 }
2426
dan sinclair41e4d9a2022-05-01 14:40:55 +00002427 /// Creates the ast::GroupAttribute
dan sinclairbe4c9f42022-08-29 21:22:31 +00002428 /// @param value group attribute index expresion
dan sinclair41e4d9a2022-05-01 14:40:55 +00002429 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002430 template <typename EXPR>
2431 const ast::GroupAttribute* Group(EXPR&& value) {
2432 return create<ast::GroupAttribute>(Expr(std::forward<EXPR>(value)));
2433 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002434
dan sinclairf9b831c2022-08-29 21:13:00 +00002435 /// Creates the ast::GroupAttribute
2436 /// @param source the source
dan sinclairbe4c9f42022-08-29 21:22:31 +00002437 /// @param value group attribute index expression
dan sinclairf9b831c2022-08-29 21:13:00 +00002438 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002439 template <typename EXPR>
2440 const ast::GroupAttribute* Group(const Source& source, EXPR&& value) {
2441 return create<ast::GroupAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclairf9b831c2022-08-29 21:13:00 +00002442 }
2443
dan sinclair41e4d9a2022-05-01 14:40:55 +00002444 /// Creates the ast::BindingAttribute
dan sinclairf9b831c2022-08-29 21:13:00 +00002445 /// @param value the binding index expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002446 /// @returns the binding deocration pointer
dan sinclairf9b831c2022-08-29 21:13:00 +00002447 template <typename EXPR>
2448 const ast::BindingAttribute* Binding(EXPR&& value) {
2449 return create<ast::BindingAttribute>(Expr(std::forward<EXPR>(value)));
2450 }
2451
2452 /// Creates the ast::BindingAttribute
2453 /// @param source the source
2454 /// @param value the binding index expression
2455 /// @returns the binding deocration pointer
2456 template <typename EXPR>
2457 const ast::BindingAttribute* Binding(const Source& source, EXPR&& value) {
2458 return create<ast::BindingAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002459 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002460
dan sinclair41e4d9a2022-05-01 14:40:55 +00002461 /// Creates an ast::Function and registers it with the ast::Module.
Ben Clayton17aa6532023-02-07 21:28:09 +00002462 /// @param name the function name
2463 /// @param params the function parameters
2464 /// @param type the function return type
2465 /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
2466 /// be automatically placed into a block, or nullptr for a stub function.
2467 /// @param attributes the optional function attributes
2468 /// @param return_type_attributes the optional function return type attributes
2469 /// attributes
2470 /// @returns the function pointer
2471 template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
2472 const ast::Function* Func(
2473 NAME&& name,
2474 utils::VectorRef<const ast::Parameter*> params,
2475 const ast::Type* type,
2476 BODY&& body,
2477 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
2478 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2479 return Func(source_, std::forward<NAME>(name), std::move(params), type,
2480 std::forward<BODY>(body), std::move(attributes),
2481 std::move(return_type_attributes));
2482 }
2483
2484 /// Creates an ast::Function and registers it with the ast::Module.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002485 /// @param source the source information
2486 /// @param name the function name
2487 /// @param params the function parameters
2488 /// @param type the function return type
Ben Clayton17aa6532023-02-07 21:28:09 +00002489 /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
2490 /// be automatically placed into a block, or nullptr for a stub function.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002491 /// @param attributes the optional function attributes
James Priced9f65962023-02-01 23:14:10 +00002492 /// @param return_type_attributes the optional function return type attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002493 /// attributes
2494 /// @returns the function pointer
Ben Clayton17aa6532023-02-07 21:28:09 +00002495 template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
Ben Clayton783b1692022-08-02 17:03:35 +00002496 const ast::Function* Func(
2497 const Source& source,
2498 NAME&& name,
2499 utils::VectorRef<const ast::Parameter*> params,
2500 const ast::Type* type,
Ben Clayton17aa6532023-02-07 21:28:09 +00002501 BODY&& body,
Ben Clayton783b1692022-08-02 17:03:35 +00002502 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
Ben Clayton17aa6532023-02-07 21:28:09 +00002503 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2504 const ast::BlockStatement* block = nullptr;
2505 using BODY_T = traits::PtrElTy<BODY>;
2506 if constexpr (traits::IsTypeOrDerived<BODY_T, ast::BlockStatement> ||
2507 std::is_same_v<BODY_T, std::nullptr_t>) {
2508 block = body;
2509 } else {
2510 block = Block(std::forward<BODY>(body));
2511 }
2512 auto* func =
Ben Claytonce31d182023-02-09 10:34:14 +00002513 create<ast::Function>(source, Ident(std::forward<NAME>(name)), std::move(params), type,
Ben Clayton17aa6532023-02-07 21:28:09 +00002514 block, std::move(attributes), std::move(return_type_attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002515 AST().AddFunction(func);
2516 return func;
2517 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002518
dan sinclair41e4d9a2022-05-01 14:40:55 +00002519 /// Creates an ast::BreakStatement
2520 /// @param source the source information
2521 /// @returns the break statement pointer
2522 const ast::BreakStatement* Break(const Source& source) {
2523 return create<ast::BreakStatement>(source);
2524 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002525
dan sinclair41e4d9a2022-05-01 14:40:55 +00002526 /// Creates an ast::BreakStatement
2527 /// @returns the break statement pointer
2528 const ast::BreakStatement* Break() { return create<ast::BreakStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002529
dan sinclairb8b0c212022-10-20 22:45:50 +00002530 /// Creates a ast::BreakIfStatement with input condition
2531 /// @param source the source information for the if statement
2532 /// @param condition the if statement condition expression
2533 /// @returns the break-if statement pointer
2534 template <typename CONDITION>
2535 const ast::BreakIfStatement* BreakIf(const Source& source, CONDITION&& condition) {
2536 return create<ast::BreakIfStatement>(source, Expr(std::forward<CONDITION>(condition)));
2537 }
2538
2539 /// Creates a ast::BreakIfStatement with input condition
2540 /// @param condition the if statement condition expression
2541 /// @returns the break-if statement pointer
2542 template <typename CONDITION>
2543 const ast::BreakIfStatement* BreakIf(CONDITION&& condition) {
2544 return create<ast::BreakIfStatement>(Expr(std::forward<CONDITION>(condition)));
2545 }
2546
dan sinclair41e4d9a2022-05-01 14:40:55 +00002547 /// Creates an ast::ContinueStatement
2548 /// @param source the source information
2549 /// @returns the continue statement pointer
2550 const ast::ContinueStatement* Continue(const Source& source) {
2551 return create<ast::ContinueStatement>(source);
2552 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002553
dan sinclair41e4d9a2022-05-01 14:40:55 +00002554 /// Creates an ast::ContinueStatement
2555 /// @returns the continue statement pointer
2556 const ast::ContinueStatement* Continue() { return create<ast::ContinueStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002557
dan sinclair41e4d9a2022-05-01 14:40:55 +00002558 /// Creates an ast::ReturnStatement with no return value
2559 /// @param source the source information
2560 /// @returns the return statement pointer
2561 const ast::ReturnStatement* Return(const Source& source) {
2562 return create<ast::ReturnStatement>(source);
2563 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002564
dan sinclair41e4d9a2022-05-01 14:40:55 +00002565 /// Creates an ast::ReturnStatement with no return value
2566 /// @returns the return statement pointer
2567 const ast::ReturnStatement* Return() { return create<ast::ReturnStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002568
dan sinclair41e4d9a2022-05-01 14:40:55 +00002569 /// Creates an ast::ReturnStatement with the given return value
2570 /// @param source the source information
2571 /// @param val the return value
2572 /// @returns the return statement pointer
2573 template <typename EXPR>
2574 const ast::ReturnStatement* Return(const Source& source, EXPR&& val) {
2575 return create<ast::ReturnStatement>(source, Expr(std::forward<EXPR>(val)));
2576 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002577
dan sinclair41e4d9a2022-05-01 14:40:55 +00002578 /// Creates an ast::ReturnStatement with the given return value
2579 /// @param val the return value
2580 /// @returns the return statement pointer
2581 template <typename EXPR, typename = DisableIfSource<EXPR>>
2582 const ast::ReturnStatement* Return(EXPR&& val) {
2583 return create<ast::ReturnStatement>(Expr(std::forward<EXPR>(val)));
2584 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002585
dan sinclair41e4d9a2022-05-01 14:40:55 +00002586 /// Creates an ast::DiscardStatement
2587 /// @param source the source information
2588 /// @returns the discard statement pointer
2589 const ast::DiscardStatement* Discard(const Source& source) {
2590 return create<ast::DiscardStatement>(source);
2591 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002592
dan sinclair41e4d9a2022-05-01 14:40:55 +00002593 /// Creates an ast::DiscardStatement
2594 /// @returns the discard statement pointer
2595 const ast::DiscardStatement* Discard() { return create<ast::DiscardStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002596
dan sinclair41e4d9a2022-05-01 14:40:55 +00002597 /// Creates a ast::Alias registering it with the AST().TypeDecls().
2598 /// @param source the source information
2599 /// @param name the alias name
2600 /// @param type the alias target type
2601 /// @returns the alias type
2602 template <typename NAME>
2603 const ast::Alias* Alias(const Source& source, NAME&& name, const ast::Type* type) {
2604 auto* out = ty.alias(source, std::forward<NAME>(name), type);
2605 AST().AddTypeDecl(out);
2606 return out;
2607 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002608
dan sinclair41e4d9a2022-05-01 14:40:55 +00002609 /// Creates a ast::Alias registering it with the AST().TypeDecls().
2610 /// @param name the alias name
2611 /// @param type the alias target type
2612 /// @returns the alias type
2613 template <typename NAME>
2614 const ast::Alias* Alias(NAME&& name, const ast::Type* type) {
2615 auto* out = ty.alias(std::forward<NAME>(name), type);
2616 AST().AddTypeDecl(out);
2617 return out;
2618 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002619
dan sinclair41e4d9a2022-05-01 14:40:55 +00002620 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2621 /// @param source the source information
2622 /// @param name the struct name
2623 /// @param members the struct members
2624 /// @returns the struct type
2625 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002626 const ast::Struct* Structure(const Source& source,
2627 NAME&& name,
2628 utils::VectorRef<const ast::StructMember*> members) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002629 auto sym = Sym(std::forward<NAME>(name));
Ben Clayton783b1692022-08-02 17:03:35 +00002630 auto* type = create<ast::Struct>(source, sym, std::move(members), utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002631 AST().AddTypeDecl(type);
2632 return type;
2633 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002634
dan sinclair41e4d9a2022-05-01 14:40:55 +00002635 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2636 /// @param name the struct name
2637 /// @param members the struct members
2638 /// @returns the struct type
2639 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002640 const ast::Struct* Structure(NAME&& name, utils::VectorRef<const ast::StructMember*> members) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002641 auto sym = Sym(std::forward<NAME>(name));
Ben Clayton783b1692022-08-02 17:03:35 +00002642 auto* type = create<ast::Struct>(sym, std::move(members), utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002643 AST().AddTypeDecl(type);
2644 return type;
2645 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002646
dan sinclair41e4d9a2022-05-01 14:40:55 +00002647 /// Creates a ast::StructMember
Ben Clayton199440e2023-02-09 10:34:14 +00002648 /// @param name the struct member name
2649 /// @param type the struct member type
2650 /// @param attributes the optional struct member attributes
2651 /// @returns the struct member pointer
2652 template <typename NAME>
2653 const ast::StructMember* Member(
2654 NAME&& name,
2655 const ast::Type* type,
2656 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2657 return Member(source_, std::forward<NAME>(name), type, std::move(attributes));
2658 }
2659
2660 /// Creates a ast::StructMember
dan sinclair41e4d9a2022-05-01 14:40:55 +00002661 /// @param source the source information
2662 /// @param name the struct member name
2663 /// @param type the struct member type
2664 /// @param attributes the optional struct member attributes
2665 /// @returns the struct member pointer
2666 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002667 const ast::StructMember* Member(
2668 const Source& source,
2669 NAME&& name,
2670 const ast::Type* type,
2671 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Clayton199440e2023-02-09 10:34:14 +00002672 return create<ast::StructMember>(source, Ident(std::forward<NAME>(name)), type,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002673 std::move(attributes));
2674 }
2675
2676 /// Creates a ast::StructMember with the given byte offset
Ben Clayton783b1692022-08-02 17:03:35 +00002677 /// @param offset the offset to use in the StructMemberOffsetAttribute
dan sinclair41e4d9a2022-05-01 14:40:55 +00002678 /// @param name the struct member name
2679 /// @param type the struct member type
2680 /// @returns the struct member pointer
2681 template <typename NAME>
2682 const ast::StructMember* Member(uint32_t offset, NAME&& name, const ast::Type* type) {
Ben Clayton199440e2023-02-09 10:34:14 +00002683 return create<ast::StructMember>(source_, Ident(std::forward<NAME>(name)), type,
Ben Clayton783b1692022-08-02 17:03:35 +00002684 utils::Vector<const ast::Attribute*, 1>{
dan sinclair93df9672022-09-09 14:49:09 +00002685 MemberOffset(AInt(offset)),
dan sinclair41e4d9a2022-05-01 14:40:55 +00002686 });
2687 }
2688
Ben Clayton17aa6532023-02-07 21:28:09 +00002689 /// Creates a ast::BlockStatement with input statements and attributes
2690 /// @param statements the statements of the block
2691 /// @param attributes the optional attributes of the block
2692 /// @returns the block statement pointer
2693 const ast::BlockStatement* Block(
2694 utils::VectorRef<const ast::Statement*> statements,
2695 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2696 return Block(source_, std::move(statements), std::move(attributes));
2697 }
2698
2699 /// Creates a ast::BlockStatement with input statements and attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002700 /// @param source the source information for the block
Ben Clayton17aa6532023-02-07 21:28:09 +00002701 /// @param statements the statements of the block
2702 /// @param attributes the optional attributes of the block
2703 /// @returns the block statement pointer
2704 const ast::BlockStatement* Block(
2705 const Source& source,
2706 utils::VectorRef<const ast::Statement*> statements,
2707 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2708 return create<ast::BlockStatement>(source, std::move(statements), std::move(attributes));
2709 }
2710
2711 /// Creates a ast::BlockStatement with a parameter list of input statements
2712 /// @param statements the optional statements of the block
2713 /// @returns the block statement pointer
2714 template <typename... STATEMENTS,
2715 typename = DisableIfSource<STATEMENTS...>,
2716 typename = DisableIfVectorLike<STATEMENTS...>>
2717 const ast::BlockStatement* Block(STATEMENTS&&... statements) {
2718 return Block(source_, std::forward<STATEMENTS>(statements)...);
2719 }
2720
2721 /// Creates a ast::BlockStatement with a parameter list of input statements
2722 /// @param source the source information for the block
2723 /// @param statements the optional statements of the block
dan sinclair41e4d9a2022-05-01 14:40:55 +00002724 /// @returns the block statement pointer
James Priced9f65962023-02-01 23:14:10 +00002725 template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>>
2726 const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002727 return create<ast::BlockStatement>(
James Priced9f65962023-02-01 23:14:10 +00002728 source,
2729 utils::Vector<const ast::Statement*, sizeof...(statements)>{
2730 std::forward<STATEMENTS>(statements)...,
2731 },
2732 utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002733 }
2734
James Price8aff0ed2022-05-02 14:53:36 +00002735 /// A wrapper type for the Else statement used to create If statements.
2736 struct ElseStmt {
2737 /// Default constructor - no else statement.
2738 ElseStmt() : stmt(nullptr) {}
2739 /// Constructor
2740 /// @param s The else statement
2741 explicit ElseStmt(const ast::Statement* s) : stmt(s) {}
2742 /// The else statement, or nullptr.
2743 const ast::Statement* stmt;
2744 };
2745
dan sinclair41e4d9a2022-05-01 14:40:55 +00002746 /// Creates a ast::IfStatement with input condition, body, and optional
2747 /// else statement
2748 /// @param source the source information for the if statement
2749 /// @param condition the if statement condition expression
2750 /// @param body the if statement body
2751 /// @param else_stmt optional else statement
2752 /// @returns the if statement pointer
2753 template <typename CONDITION>
2754 const ast::IfStatement* If(const Source& source,
2755 CONDITION&& condition,
2756 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002757 const ElseStmt else_stmt = ElseStmt()) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002758 return create<ast::IfStatement>(source, Expr(std::forward<CONDITION>(condition)), body,
James Price8aff0ed2022-05-02 14:53:36 +00002759 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002760 }
2761
2762 /// Creates a ast::IfStatement with input condition, body, and optional
2763 /// else statement
2764 /// @param condition the if statement condition expression
2765 /// @param body the if statement body
2766 /// @param else_stmt optional else statement
2767 /// @returns the if statement pointer
2768 template <typename CONDITION>
2769 const ast::IfStatement* If(CONDITION&& condition,
2770 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002771 const ElseStmt else_stmt = ElseStmt()) {
2772 return create<ast::IfStatement>(Expr(std::forward<CONDITION>(condition)), body,
2773 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002774 }
2775
James Price8aff0ed2022-05-02 14:53:36 +00002776 /// Creates an Else object.
2777 /// @param stmt else statement
2778 /// @returns the Else object
2779 ElseStmt Else(const ast::Statement* stmt) { return ElseStmt(stmt); }
2780
dan sinclair41e4d9a2022-05-01 14:40:55 +00002781 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2782 /// @param source the source information
2783 /// @param lhs the left hand side expression initializer
2784 /// @param rhs the right hand side expression initializer
2785 /// @returns the assignment statement pointer
2786 template <typename LhsExpressionInit, typename RhsExpressionInit>
2787 const ast::AssignmentStatement* Assign(const Source& source,
2788 LhsExpressionInit&& lhs,
2789 RhsExpressionInit&& rhs) {
2790 return create<ast::AssignmentStatement>(source, Expr(std::forward<LhsExpressionInit>(lhs)),
2791 Expr(std::forward<RhsExpressionInit>(rhs)));
2792 }
2793
2794 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2795 /// @param lhs the left hand side expression initializer
2796 /// @param rhs the right hand side expression initializer
2797 /// @returns the assignment statement pointer
2798 template <typename LhsExpressionInit, typename RhsExpressionInit>
2799 const ast::AssignmentStatement* Assign(LhsExpressionInit&& lhs, RhsExpressionInit&& rhs) {
2800 return create<ast::AssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2801 Expr(std::forward<RhsExpressionInit>(rhs)));
2802 }
2803
2804 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2805 /// expressions, and a binary operator.
2806 /// @param source the source information
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(const Source& source,
2813 LhsExpressionInit&& lhs,
2814 RhsExpressionInit&& rhs,
2815 ast::BinaryOp op) {
2816 return create<ast::CompoundAssignmentStatement>(
2817 source, Expr(std::forward<LhsExpressionInit>(lhs)),
2818 Expr(std::forward<RhsExpressionInit>(rhs)), op);
2819 }
2820
2821 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2822 /// expressions, and a binary operator.
2823 /// @param lhs the left hand side expression initializer
2824 /// @param rhs the right hand side expression initializer
2825 /// @param op the binary operator
2826 /// @returns the compound assignment statement pointer
2827 template <typename LhsExpressionInit, typename RhsExpressionInit>
2828 const ast::CompoundAssignmentStatement* CompoundAssign(LhsExpressionInit&& lhs,
2829 RhsExpressionInit&& rhs,
2830 ast::BinaryOp op) {
2831 return create<ast::CompoundAssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2832 Expr(std::forward<RhsExpressionInit>(rhs)),
2833 op);
2834 }
2835
2836 /// Creates an ast::IncrementDecrementStatement with input lhs.
2837 /// @param source the source information
2838 /// @param lhs the left hand side expression initializer
2839 /// @returns the increment decrement statement pointer
2840 template <typename LhsExpressionInit>
2841 const ast::IncrementDecrementStatement* Increment(const Source& source,
2842 LhsExpressionInit&& lhs) {
2843 return create<ast::IncrementDecrementStatement>(
2844 source, Expr(std::forward<LhsExpressionInit>(lhs)), true);
2845 }
2846
2847 /// Creates a ast::IncrementDecrementStatement with input lhs.
2848 /// @param lhs the left hand side expression initializer
2849 /// @returns the increment decrement statement pointer
2850 template <typename LhsExpressionInit>
2851 const ast::IncrementDecrementStatement* Increment(LhsExpressionInit&& lhs) {
2852 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2853 true);
2854 }
2855
2856 /// Creates an ast::IncrementDecrementStatement with input lhs.
2857 /// @param source the source information
2858 /// @param lhs the left hand side expression initializer
2859 /// @returns the increment decrement statement pointer
2860 template <typename LhsExpressionInit>
2861 const ast::IncrementDecrementStatement* Decrement(const Source& source,
2862 LhsExpressionInit&& lhs) {
2863 return create<ast::IncrementDecrementStatement>(
2864 source, Expr(std::forward<LhsExpressionInit>(lhs)), false);
2865 }
2866
2867 /// Creates a ast::IncrementDecrementStatement with input lhs.
2868 /// @param lhs the left hand side expression initializer
2869 /// @returns the increment decrement statement pointer
2870 template <typename LhsExpressionInit>
2871 const ast::IncrementDecrementStatement* Decrement(LhsExpressionInit&& lhs) {
2872 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2873 false);
2874 }
2875
2876 /// Creates a ast::LoopStatement with input body and optional continuing
2877 /// @param source the source information
2878 /// @param body the loop body
2879 /// @param continuing the optional continuing block
2880 /// @returns the loop statement pointer
2881 const ast::LoopStatement* Loop(const Source& source,
2882 const ast::BlockStatement* body,
2883 const ast::BlockStatement* continuing = nullptr) {
2884 return create<ast::LoopStatement>(source, body, continuing);
2885 }
2886
2887 /// Creates a ast::LoopStatement with input body and optional continuing
2888 /// @param body the loop body
2889 /// @param continuing the optional continuing block
2890 /// @returns the loop statement pointer
2891 const ast::LoopStatement* Loop(const ast::BlockStatement* body,
2892 const ast::BlockStatement* continuing = nullptr) {
2893 return create<ast::LoopStatement>(body, continuing);
2894 }
2895
2896 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2897 /// condition and continuing.
2898 /// @param source the source information
2899 /// @param init the optional loop initializer
2900 /// @param cond the optional loop condition
2901 /// @param cont the optional loop continuing
2902 /// @param body the loop body
2903 /// @returns the for loop statement pointer
2904 template <typename COND>
2905 const ast::ForLoopStatement* For(const Source& source,
2906 const ast::Statement* init,
2907 COND&& cond,
2908 const ast::Statement* cont,
2909 const ast::BlockStatement* body) {
2910 return create<ast::ForLoopStatement>(source, init, Expr(std::forward<COND>(cond)), cont,
2911 body);
2912 }
2913
2914 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2915 /// condition and continuing.
2916 /// @param init the optional loop initializer
2917 /// @param cond the optional loop condition
2918 /// @param cont the optional loop continuing
2919 /// @param body the loop body
2920 /// @returns the for loop statement pointer
2921 template <typename COND>
2922 const ast::ForLoopStatement* For(const ast::Statement* init,
2923 COND&& cond,
2924 const ast::Statement* cont,
2925 const ast::BlockStatement* body) {
2926 return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), cont, body);
2927 }
2928
dan sinclair49d1a2d2022-06-16 12:01:27 +00002929 /// Creates a ast::WhileStatement with input body and condition.
2930 /// @param source the source information
2931 /// @param cond the loop condition
2932 /// @param body the loop body
2933 /// @returns the while statement pointer
2934 template <typename COND>
2935 const ast::WhileStatement* While(const Source& source,
2936 COND&& cond,
2937 const ast::BlockStatement* body) {
2938 return create<ast::WhileStatement>(source, Expr(std::forward<COND>(cond)), body);
2939 }
2940
2941 /// Creates a ast::WhileStatement with given condition and body.
2942 /// @param cond the condition
2943 /// @param body the loop body
2944 /// @returns the while loop statement pointer
2945 template <typename COND>
2946 const ast::WhileStatement* While(COND&& cond, const ast::BlockStatement* body) {
2947 return create<ast::WhileStatement>(Expr(std::forward<COND>(cond)), body);
2948 }
2949
dan sinclair41e4d9a2022-05-01 14:40:55 +00002950 /// Creates a ast::VariableDeclStatement for the input variable
2951 /// @param source the source information
2952 /// @param var the variable to wrap in a decl statement
2953 /// @returns the variable decl statement pointer
2954 const ast::VariableDeclStatement* Decl(const Source& source, const ast::Variable* var) {
2955 return create<ast::VariableDeclStatement>(source, var);
2956 }
2957
2958 /// Creates a ast::VariableDeclStatement for the input variable
2959 /// @param var the variable to wrap in a decl statement
2960 /// @returns the variable decl statement pointer
2961 const ast::VariableDeclStatement* Decl(const ast::Variable* var) {
2962 return create<ast::VariableDeclStatement>(var);
2963 }
2964
2965 /// Creates a ast::SwitchStatement with input expression and cases
2966 /// @param source the source information
2967 /// @param condition the condition expression initializer
2968 /// @param cases case statements
2969 /// @returns the switch statement pointer
2970 template <typename ExpressionInit, typename... Cases>
2971 const ast::SwitchStatement* Switch(const Source& source,
2972 ExpressionInit&& condition,
2973 Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00002974 return create<ast::SwitchStatement>(
2975 source, Expr(std::forward<ExpressionInit>(condition)),
2976 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
2977 std::forward<Cases>(cases)...});
dan sinclair41e4d9a2022-05-01 14:40:55 +00002978 }
2979
2980 /// Creates a ast::SwitchStatement with input expression and cases
2981 /// @param condition the condition expression initializer
2982 /// @param cases case statements
2983 /// @returns the switch statement pointer
2984 template <typename ExpressionInit,
2985 typename... Cases,
2986 typename = DisableIfSource<ExpressionInit>>
2987 const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00002988 return create<ast::SwitchStatement>(
2989 Expr(std::forward<ExpressionInit>(condition)),
2990 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
2991 std::forward<Cases>(cases)...});
dan sinclair41e4d9a2022-05-01 14:40:55 +00002992 }
2993
2994 /// Creates a ast::CaseStatement with input list of selectors, and body
2995 /// @param source the source information
2996 /// @param selectors list of selectors
2997 /// @param body the case body
2998 /// @returns the case statement pointer
2999 const ast::CaseStatement* Case(const Source& source,
dan sinclairf148f082022-10-19 15:55:02 +00003000 utils::VectorRef<const ast::CaseSelector*> selectors,
dan sinclair41e4d9a2022-05-01 14:40:55 +00003001 const ast::BlockStatement* body = nullptr) {
3002 return create<ast::CaseStatement>(source, std::move(selectors), body ? body : Block());
3003 }
3004
3005 /// Creates a ast::CaseStatement with input list of selectors, and body
3006 /// @param selectors list of selectors
3007 /// @param body the case body
3008 /// @returns the case statement pointer
dan sinclairf148f082022-10-19 15:55:02 +00003009 const ast::CaseStatement* Case(utils::VectorRef<const ast::CaseSelector*> selectors,
dan sinclair41e4d9a2022-05-01 14:40:55 +00003010 const ast::BlockStatement* body = nullptr) {
3011 return create<ast::CaseStatement>(std::move(selectors), body ? body : Block());
3012 }
3013
3014 /// Convenient overload that takes a single selector
3015 /// @param selector a single case selector
3016 /// @param body the case body
3017 /// @returns the case statement pointer
dan sinclairf148f082022-10-19 15:55:02 +00003018 const ast::CaseStatement* Case(const ast::CaseSelector* selector,
dan sinclair41e4d9a2022-05-01 14:40:55 +00003019 const ast::BlockStatement* body = nullptr) {
Ben Clayton783b1692022-08-02 17:03:35 +00003020 return Case(utils::Vector{selector}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003021 }
3022
3023 /// Convenience function that creates a 'default' ast::CaseStatement
3024 /// @param source the source information
3025 /// @param body the case body
3026 /// @returns the case statement pointer
3027 const ast::CaseStatement* DefaultCase(const Source& source,
3028 const ast::BlockStatement* body = nullptr) {
dan sinclairf148f082022-10-19 15:55:02 +00003029 return Case(source, utils::Vector{DefaultCaseSelector(source)}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003030 }
3031
3032 /// Convenience function that creates a 'default' ast::CaseStatement
3033 /// @param body the case body
3034 /// @returns the case statement pointer
3035 const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) {
dan sinclairf148f082022-10-19 15:55:02 +00003036 return Case(utils::Vector{DefaultCaseSelector()}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003037 }
3038
dan sinclairf148f082022-10-19 15:55:02 +00003039 /// Convenience function that creates a case selector
3040 /// @param source the source information
3041 /// @param expr the selector expression
3042 /// @returns the selector pointer
3043 template <typename EXPR>
3044 const ast::CaseSelector* CaseSelector(const Source& source, EXPR&& expr) {
3045 return create<ast::CaseSelector>(source, Expr(std::forward<EXPR>(expr)));
3046 }
3047
3048 /// Convenience function that creates a case selector
3049 /// @param expr the selector expression
3050 /// @returns the selector pointer
3051 template <typename EXPR>
3052 const ast::CaseSelector* CaseSelector(EXPR&& expr) {
3053 return create<ast::CaseSelector>(source_, Expr(std::forward<EXPR>(expr)));
3054 }
3055
3056 /// Convenience function that creates a default case selector
3057 /// @param source the source information
3058 /// @returns the selector pointer
3059 const ast::CaseSelector* DefaultCaseSelector(const Source& source) {
3060 return create<ast::CaseSelector>(source, nullptr);
3061 }
3062
3063 /// Convenience function that creates a default case selector
3064 /// @returns the selector pointer
3065 const ast::CaseSelector* DefaultCaseSelector() { return create<ast::CaseSelector>(nullptr); }
3066
dan sinclair41e4d9a2022-05-01 14:40:55 +00003067 /// Creates an ast::BuiltinAttribute
3068 /// @param source the source information
3069 /// @param builtin the builtin value
3070 /// @returns the builtin attribute pointer
Ben Claytonf3302292022-07-27 18:48:06 +00003071 const ast::BuiltinAttribute* Builtin(const Source& source, ast::BuiltinValue builtin) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003072 return create<ast::BuiltinAttribute>(source, builtin);
3073 }
3074
3075 /// Creates an ast::BuiltinAttribute
3076 /// @param builtin the builtin value
3077 /// @returns the builtin attribute pointer
Ben Claytonf3302292022-07-27 18:48:06 +00003078 const ast::BuiltinAttribute* Builtin(ast::BuiltinValue builtin) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003079 return create<ast::BuiltinAttribute>(source_, builtin);
3080 }
3081
3082 /// Creates an ast::InterpolateAttribute
3083 /// @param source the source information
3084 /// @param type the interpolation type
3085 /// @param sampling the interpolation sampling
3086 /// @returns the interpolate attribute pointer
3087 const ast::InterpolateAttribute* Interpolate(
3088 const Source& source,
3089 ast::InterpolationType type,
Ben Claytond2e0db32022-10-12 18:49:15 +00003090 ast::InterpolationSampling sampling = ast::InterpolationSampling::kUndefined) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003091 return create<ast::InterpolateAttribute>(source, type, sampling);
3092 }
3093
3094 /// Creates an ast::InterpolateAttribute
3095 /// @param type the interpolation type
3096 /// @param sampling the interpolation sampling
3097 /// @returns the interpolate attribute pointer
3098 const ast::InterpolateAttribute* Interpolate(
3099 ast::InterpolationType type,
Ben Claytond2e0db32022-10-12 18:49:15 +00003100 ast::InterpolationSampling sampling = ast::InterpolationSampling::kUndefined) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003101 return create<ast::InterpolateAttribute>(source_, type, sampling);
3102 }
3103
3104 /// Creates an ast::InterpolateAttribute using flat interpolation
3105 /// @param source the source information
3106 /// @returns the interpolate attribute pointer
3107 const ast::InterpolateAttribute* Flat(const Source& source) {
3108 return Interpolate(source, ast::InterpolationType::kFlat);
3109 }
3110
3111 /// Creates an ast::InterpolateAttribute using flat interpolation
3112 /// @returns the interpolate attribute pointer
3113 const ast::InterpolateAttribute* Flat() { return Interpolate(ast::InterpolationType::kFlat); }
3114
3115 /// Creates an ast::InvariantAttribute
3116 /// @param source the source information
3117 /// @returns the invariant attribute pointer
3118 const ast::InvariantAttribute* Invariant(const Source& source) {
3119 return create<ast::InvariantAttribute>(source);
3120 }
3121
3122 /// Creates an ast::InvariantAttribute
3123 /// @returns the invariant attribute pointer
3124 const ast::InvariantAttribute* Invariant() { return create<ast::InvariantAttribute>(source_); }
3125
3126 /// Creates an ast::LocationAttribute
3127 /// @param source the source information
dan sinclairf9eeed62022-09-07 22:25:24 +00003128 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003129 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003130 template <typename EXPR>
3131 const ast::LocationAttribute* Location(const Source& source, EXPR&& location) {
3132 return create<ast::LocationAttribute>(source, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003133 }
3134
3135 /// Creates an ast::LocationAttribute
dan sinclairf9eeed62022-09-07 22:25:24 +00003136 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003137 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003138 template <typename EXPR>
3139 const ast::LocationAttribute* Location(EXPR&& location) {
3140 return create<ast::LocationAttribute>(source_, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003141 }
3142
3143 /// Creates an ast::IdAttribute
3144 /// @param source the source information
3145 /// @param id the id value
3146 /// @returns the override attribute pointer
Ben Clayton9a6acc42022-07-27 20:50:40 +00003147 const ast::IdAttribute* Id(const Source& source, OverrideId id) {
dan sinclair5361d9e2022-08-31 13:39:48 +00003148 return create<ast::IdAttribute>(source, Expr(AInt(id.value)));
Ben Clayton9a6acc42022-07-27 20:50:40 +00003149 }
3150
3151 /// Creates an ast::IdAttribute with an override identifier
3152 /// @param id the optional id value
3153 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003154 const ast::IdAttribute* Id(OverrideId id) {
3155 return create<ast::IdAttribute>(Expr(AInt(id.value)));
3156 }
Ben Clayton9a6acc42022-07-27 20:50:40 +00003157
3158 /// Creates an ast::IdAttribute
3159 /// @param source the source information
dan sinclair5361d9e2022-08-31 13:39:48 +00003160 /// @param id the id value expression
Ben Clayton9a6acc42022-07-27 20:50:40 +00003161 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003162 template <typename EXPR>
3163 const ast::IdAttribute* Id(const Source& source, EXPR&& id) {
3164 return create<ast::IdAttribute>(source, Expr(std::forward<EXPR>(id)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003165 }
3166
Ben Clayton9a6acc42022-07-27 20:50:40 +00003167 /// Creates an ast::IdAttribute with an override identifier
dan sinclair5361d9e2022-08-31 13:39:48 +00003168 /// @param id the optional id value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003169 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003170 template <typename EXPR>
3171 const ast::IdAttribute* Id(EXPR&& id) {
3172 return create<ast::IdAttribute>(Expr(std::forward<EXPR>(id)));
3173 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00003174
3175 /// Creates an ast::StageAttribute
3176 /// @param source the source information
3177 /// @param stage the pipeline stage
3178 /// @returns the stage attribute pointer
3179 const ast::StageAttribute* Stage(const Source& source, ast::PipelineStage stage) {
3180 return create<ast::StageAttribute>(source, stage);
3181 }
3182
3183 /// Creates an ast::StageAttribute
3184 /// @param stage the pipeline stage
3185 /// @returns the stage attribute pointer
3186 const ast::StageAttribute* Stage(ast::PipelineStage stage) {
3187 return create<ast::StageAttribute>(source_, stage);
3188 }
3189
3190 /// Creates an ast::WorkgroupAttribute
3191 /// @param x the x dimension expression
3192 /// @returns the workgroup attribute pointer
3193 template <typename EXPR_X>
3194 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x) {
3195 return WorkgroupSize(std::forward<EXPR_X>(x), nullptr, nullptr);
3196 }
3197
3198 /// Creates an ast::WorkgroupAttribute
Ben Claytonb8ac9332022-05-28 10:34:06 +00003199 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00003200 /// @param x the x dimension expression
dan sinclair7517e212022-08-24 21:31:45 +00003201 /// @returns the workgroup attribute pointer
3202 template <typename EXPR_X>
3203 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x) {
3204 return WorkgroupSize(source, std::forward<EXPR_X>(x), nullptr, nullptr);
3205 }
3206
3207 /// Creates an ast::WorkgroupAttribute
3208 /// @param source the source information
3209 /// @param x the x dimension expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003210 /// @param y the y dimension expression
3211 /// @returns the workgroup attribute pointer
3212 template <typename EXPR_X, typename EXPR_Y>
Ben Claytonb8ac9332022-05-28 10:34:06 +00003213 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x, EXPR_Y&& y) {
3214 return WorkgroupSize(source, std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3215 }
3216
3217 /// Creates an ast::WorkgroupAttribute
3218 /// @param x the x dimension expression
3219 /// @param y the y dimension expression
3220 /// @returns the workgroup attribute pointer
3221 template <typename EXPR_X, typename EXPR_Y, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003222 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y) {
3223 return WorkgroupSize(std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3224 }
3225
3226 /// Creates an ast::WorkgroupAttribute
3227 /// @param source the source information
3228 /// @param x the x dimension expression
3229 /// @param y the y dimension expression
3230 /// @param z the z dimension expression
3231 /// @returns the workgroup attribute pointer
3232 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z>
3233 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source,
3234 EXPR_X&& x,
3235 EXPR_Y&& y,
3236 EXPR_Z&& z) {
3237 return create<ast::WorkgroupAttribute>(source, Expr(std::forward<EXPR_X>(x)),
3238 Expr(std::forward<EXPR_Y>(y)),
3239 Expr(std::forward<EXPR_Z>(z)));
3240 }
3241
3242 /// Creates an ast::WorkgroupAttribute
3243 /// @param x the x dimension expression
3244 /// @param y the y dimension expression
3245 /// @param z the z dimension expression
3246 /// @returns the workgroup attribute pointer
Ben Claytonb8ac9332022-05-28 10:34:06 +00003247 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003248 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y, EXPR_Z&& z) {
3249 return create<ast::WorkgroupAttribute>(source_, Expr(std::forward<EXPR_X>(x)),
3250 Expr(std::forward<EXPR_Y>(y)),
3251 Expr(std::forward<EXPR_Z>(z)));
3252 }
3253
3254 /// Creates an ast::DisableValidationAttribute
3255 /// @param validation the validation to disable
3256 /// @returns the disable validation attribute pointer
3257 const ast::DisableValidationAttribute* Disable(ast::DisabledValidation validation) {
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003258 return ASTNodes().Create<ast::DisableValidationAttribute>(ID(), AllocateNodeID(),
3259 validation);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003260 }
3261
James Priceef5434d2023-01-24 18:44:27 +00003262 /// Creates an ast::DiagnosticAttribute
3263 /// @param source the source information
3264 /// @param severity the diagnostic severity control
3265 /// @param rule_name the diagnostic rule name
3266 /// @returns the diagnostic attribute pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003267 template <typename NAME>
3268 const ast::DiagnosticAttribute* DiagnosticAttribute(const Source& source,
3269 ast::DiagnosticSeverity severity,
3270 NAME&& rule_name) {
Ben Clayton2cdf1342023-02-03 13:24:18 +00003271 static_assert(!traits::IsType<traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
3272 "it is invalid for a diagnostic rule name to be templated");
Ben Clayton12914ee2023-02-02 22:20:32 +00003273 return create<ast::DiagnosticAttribute>(
James Price98dc5a82023-02-04 12:20:55 +00003274 source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
James Priceef5434d2023-01-24 18:44:27 +00003275 }
3276
3277 /// Creates an ast::DiagnosticAttribute
3278 /// @param severity the diagnostic severity control
3279 /// @param rule_name the diagnostic rule name
3280 /// @returns the diagnostic attribute pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003281 template <typename NAME>
3282 const ast::DiagnosticAttribute* DiagnosticAttribute(ast::DiagnosticSeverity severity,
3283 NAME&& rule_name) {
3284 return create<ast::DiagnosticAttribute>(
James Price98dc5a82023-02-04 12:20:55 +00003285 source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
James Priceef5434d2023-01-24 18:44:27 +00003286 }
3287
James Price98dc5a82023-02-04 12:20:55 +00003288 /// Add a diagnostic directive to the module.
James Price5f3449f2023-01-23 17:55:55 +00003289 /// @param source the source information
3290 /// @param severity the diagnostic severity control
3291 /// @param rule_name the diagnostic rule name
James Price98dc5a82023-02-04 12:20:55 +00003292 /// @returns the diagnostic directive pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003293 template <typename NAME>
James Price98dc5a82023-02-04 12:20:55 +00003294 const ast::DiagnosticDirective* DiagnosticDirective(const Source& source,
3295 ast::DiagnosticSeverity severity,
3296 NAME&& rule_name) {
3297 auto* directive = create<ast::DiagnosticDirective>(
3298 source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
3299 AST().AddDiagnosticDirective(directive);
3300 return directive;
James Price5f3449f2023-01-23 17:55:55 +00003301 }
3302
James Price98dc5a82023-02-04 12:20:55 +00003303 /// Add a diagnostic directive to the module.
James Price5f3449f2023-01-23 17:55:55 +00003304 /// @param severity the diagnostic severity control
3305 /// @param rule_name the diagnostic rule name
James Price98dc5a82023-02-04 12:20:55 +00003306 /// @returns the diagnostic directive pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003307 template <typename NAME>
James Price98dc5a82023-02-04 12:20:55 +00003308 const ast::DiagnosticDirective* DiagnosticDirective(ast::DiagnosticSeverity severity,
3309 NAME&& rule_name) {
3310 auto* directive = create<ast::DiagnosticDirective>(
3311 source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
3312 AST().AddDiagnosticDirective(directive);
3313 return directive;
James Price15bf15d2023-01-24 21:01:36 +00003314 }
3315
dan sinclair41e4d9a2022-05-01 14:40:55 +00003316 /// Sets the current builder source to `src`
3317 /// @param src the Source used for future create() calls
3318 void SetSource(const Source& src) {
3319 AssertNotMoved();
3320 source_ = src;
3321 }
3322
3323 /// Sets the current builder source to `loc`
3324 /// @param loc the Source used for future create() calls
3325 void SetSource(const Source::Location& loc) {
3326 AssertNotMoved();
3327 source_ = Source(loc);
3328 }
3329
3330 /// Helper for returning the resolved semantic type of the expression `expr`.
3331 /// @note As the Resolver is run when the Program is built, this will only be
3332 /// useful for the Resolver itself and tests that use their own Resolver.
3333 /// @param expr the AST expression
3334 /// @return the resolved semantic type for the expression, or nullptr if the
3335 /// expression has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003336 const type::Type* TypeOf(const ast::Expression* expr) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003337
3338 /// Helper for returning the resolved semantic type of the variable `var`.
3339 /// @note As the Resolver is run when the Program is built, this will only be
3340 /// useful for the Resolver itself and tests that use their own Resolver.
3341 /// @param var the AST variable
3342 /// @return the resolved semantic type for the variable, or nullptr if the
3343 /// variable has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003344 const type::Type* TypeOf(const ast::Variable* var) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003345
3346 /// Helper for returning the resolved semantic type of the AST type `type`.
3347 /// @note As the Resolver is run when the Program is built, this will only be
3348 /// useful for the Resolver itself and tests that use their own Resolver.
3349 /// @param type the AST type
3350 /// @return the resolved semantic type for the type, or nullptr if the type
3351 /// has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003352 const type::Type* TypeOf(const ast::Type* type) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003353
3354 /// Helper for returning the resolved semantic type of the AST type
3355 /// declaration `type_decl`.
3356 /// @note As the Resolver is run when the Program is built, this will only be
3357 /// useful for the Resolver itself and tests that use their own Resolver.
3358 /// @param type_decl the AST type declaration
3359 /// @return the resolved semantic type for the type declaration, or nullptr if
3360 /// the type declaration has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003361 const type::Type* TypeOf(const ast::TypeDecl* type_decl) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003362
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003363 /// @param type a type
3364 /// @returns the name for `type` that closely resembles how it would be
3365 /// declared in WGSL.
Ben Claytond7d71882022-09-05 20:51:23 +00003366 std::string FriendlyName(const ast::Type* type) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003367
3368 /// @param type a type
3369 /// @returns the name for `type` that closely resembles how it would be
3370 /// declared in WGSL.
dan sinclair5f764d82022-12-08 00:32:27 +00003371 std::string FriendlyName(const type::Type* type) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003372
3373 /// Overload of FriendlyName, which removes an ambiguity when passing nullptr.
3374 /// Simplifies test code.
3375 /// @returns "<null>"
Ben Claytond7d71882022-09-05 20:51:23 +00003376 std::string FriendlyName(std::nullptr_t) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003377
dan sinclair41e4d9a2022-05-01 14:40:55 +00003378 /// Wraps the ast::Expression in a statement. This is used by tests that
3379 /// construct a partial AST and require the Resolver to reach these
3380 /// nodes.
3381 /// @param expr the ast::Expression to be wrapped by an ast::Statement
3382 /// @return the ast::Statement that wraps the ast::Expression
3383 const ast::Statement* WrapInStatement(const ast::Expression* expr);
3384 /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by
3385 /// tests that construct a partial AST and require the Resolver to reach
3386 /// these nodes.
3387 /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement
3388 /// @return the ast::VariableDeclStatement that wraps the ast::Variable
3389 const ast::VariableDeclStatement* WrapInStatement(const ast::Variable* v);
3390 /// Returns the statement argument. Used as a passthrough-overload by
3391 /// WrapInFunction().
3392 /// @param stmt the ast::Statement
3393 /// @return `stmt`
3394 const ast::Statement* WrapInStatement(const ast::Statement* stmt);
3395 /// Wraps the list of arguments in a simple function so that each is reachable
3396 /// by the Resolver.
3397 /// @param args a mix of ast::Expression, ast::Statement, ast::Variables.
3398 /// @returns the function
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003399 template <typename... ARGS,
3400 typename = traits::EnableIf<(CanWrapInStatement<ARGS>::value && ...)>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003401 const ast::Function* WrapInFunction(ARGS&&... args) {
Ben Clayton783b1692022-08-02 17:03:35 +00003402 utils::Vector stmts{
3403 WrapInStatement(std::forward<ARGS>(args))...,
3404 };
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003405 return WrapInFunction(std::move(stmts));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003406 }
3407 /// @param stmts a list of ast::Statement that will be wrapped by a function,
3408 /// so that each statement is reachable by the Resolver.
3409 /// @returns the function
Ben Clayton783b1692022-08-02 17:03:35 +00003410 const ast::Function* WrapInFunction(utils::VectorRef<const ast::Statement*> stmts);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003411
3412 /// The builder types
3413 TypesBuilder const ty{this};
3414
3415 protected:
3416 /// Asserts that the builder has not been moved.
3417 void AssertNotMoved() const;
3418
3419 private:
dan sinclaircf581222023-01-03 20:25:37 +00003420 const constant::Value* createSplatOrComposite(
3421 const type::Type* type,
3422 utils::VectorRef<const constant::Value*> elements);
3423
dan sinclair41e4d9a2022-05-01 14:40:55 +00003424 ProgramID id_;
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003425 ast::NodeID last_ast_node_id_ = ast::NodeID{static_cast<decltype(ast::NodeID::value)>(0) - 1};
dan sinclair837b8042022-12-09 05:00:07 +00003426 type::Manager types_;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003427 ASTNodeAllocator ast_nodes_;
3428 SemNodeAllocator sem_nodes_;
Ben Claytonaa037ac2022-06-29 19:07:30 +00003429 ConstantAllocator constant_nodes_;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003430 ast::Module* ast_;
3431 sem::Info sem_;
3432 SymbolTable symbols_{id_};
3433 diag::List diagnostics_;
3434
3435 /// The source to use when creating AST nodes without providing a Source as
3436 /// the first argument.
3437 Source source_;
3438
3439 /// Set by SetResolveOnBuild(). If set, the Resolver will be run on the
3440 /// program when built.
3441 bool resolve_on_build_ = true;
3442
3443 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder.
3444 bool moved_ = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003445};
3446
3447//! @cond Doxygen_Suppress
3448// Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
3449template <>
Ben Clayton46ee6392022-11-09 22:04:11 +00003450struct ProgramBuilder::TypesBuilder::CToAST<AInt> {
3451 static const ast::Type* get(const ProgramBuilder::TypesBuilder*) { return nullptr; }
3452};
3453template <>
3454struct ProgramBuilder::TypesBuilder::CToAST<AFloat> {
3455 static const ast::Type* get(const ProgramBuilder::TypesBuilder*) { return nullptr; }
3456};
3457template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003458struct ProgramBuilder::TypesBuilder::CToAST<i32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003459 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->i32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003460};
3461template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003462struct ProgramBuilder::TypesBuilder::CToAST<u32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003463 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->u32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003464};
3465template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003466struct ProgramBuilder::TypesBuilder::CToAST<f32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003467 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003468};
3469template <>
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00003470struct ProgramBuilder::TypesBuilder::CToAST<f16> {
3471 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f16(); }
3472};
3473template <>
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003474struct ProgramBuilder::TypesBuilder::CToAST<bool> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003475 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003476};
3477template <>
3478struct ProgramBuilder::TypesBuilder::CToAST<void> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003479 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->void_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003480};
3481//! @endcond
3482
3483/// @param builder the ProgramBuilder
3484/// @returns the ProgramID of the ProgramBuilder
3485inline ProgramID ProgramIDOf(const ProgramBuilder* builder) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003486 return builder->ID();
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003487}
3488
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003489// Primary template for metafunction that evaluates to true iff T can be wrapped in a statement.
3490template <typename T, typename /* = void */>
3491struct CanWrapInStatement : std::false_type {};
3492
3493// Specialization of CanWrapInStatement
3494template <typename T>
3495struct CanWrapInStatement<
3496 T,
3497 std::void_t<decltype(std::declval<ProgramBuilder>().WrapInStatement(std::declval<T>()))>>
3498 : std::true_type {};
3499
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003500} // namespace tint
3501
3502#endif // SRC_TINT_PROGRAM_BUILDER_H_