blob: 77995f3be52e7d88290745dc07f3ce071dcec81e [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"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000031#include "src/tint/ast/bool_literal_expression.h"
dan sinclairb8b0c212022-10-20 22:45:50 +000032#include "src/tint/ast/break_if_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000033#include "src/tint/ast/break_statement.h"
34#include "src/tint/ast/call_expression.h"
35#include "src/tint/ast/call_statement.h"
36#include "src/tint/ast/case_statement.h"
James Pricec022ff52022-03-31 22:30:10 +000037#include "src/tint/ast/compound_assignment_statement.h"
Ben Claytone3834c42022-06-25 23:21:39 +000038#include "src/tint/ast/const.h"
Ben Claytonc98d57d2023-01-24 14:59:43 +000039#include "src/tint/ast/const_assert.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000040#include "src/tint/ast/continue_statement.h"
41#include "src/tint/ast/depth_multisampled_texture.h"
42#include "src/tint/ast/depth_texture.h"
James Priceef5434d2023-01-24 18:44:27 +000043#include "src/tint/ast/diagnostic_attribute.h"
James Price5f3449f2023-01-23 17:55:55 +000044#include "src/tint/ast/diagnostic_control.h"
James Price98dc5a82023-02-04 12:20:55 +000045#include "src/tint/ast/diagnostic_directive.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000046#include "src/tint/ast/disable_validation_attribute.h"
47#include "src/tint/ast/discard_statement.h"
Zhaoming Jiang7098d3d2022-04-27 02:27:52 +000048#include "src/tint/ast/enable.h"
Ben Clayton7f2b8cd2022-05-18 22:41:48 +000049#include "src/tint/ast/extension.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000050#include "src/tint/ast/float_literal_expression.h"
51#include "src/tint/ast/for_loop_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000052#include "src/tint/ast/id_attribute.h"
Ben Claytonc87b1fe2023-02-02 15:04:31 +000053#include "src/tint/ast/identifier.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000054#include "src/tint/ast/if_statement.h"
James Priceebe97412022-04-07 13:42:45 +000055#include "src/tint/ast/increment_decrement_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000056#include "src/tint/ast/index_accessor_expression.h"
dan sinclaird32fbe02022-10-19 00:43:41 +000057#include "src/tint/ast/int_literal_expression.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000058#include "src/tint/ast/interpolate_attribute.h"
59#include "src/tint/ast/invariant_attribute.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000060#include "src/tint/ast/let.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000061#include "src/tint/ast/loop_statement.h"
62#include "src/tint/ast/matrix.h"
63#include "src/tint/ast/member_accessor_expression.h"
64#include "src/tint/ast/module.h"
65#include "src/tint/ast/multisampled_texture.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000066#include "src/tint/ast/override.h"
67#include "src/tint/ast/parameter.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000068#include "src/tint/ast/phony_expression.h"
69#include "src/tint/ast/pointer.h"
70#include "src/tint/ast/return_statement.h"
71#include "src/tint/ast/sampled_texture.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000072#include "src/tint/ast/stage_attribute.h"
73#include "src/tint/ast/storage_texture.h"
74#include "src/tint/ast/stride_attribute.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000075#include "src/tint/ast/struct_member_align_attribute.h"
76#include "src/tint/ast/struct_member_offset_attribute.h"
77#include "src/tint/ast/struct_member_size_attribute.h"
78#include "src/tint/ast/switch_statement.h"
Ben Clayton2cdf1342023-02-03 13:24:18 +000079#include "src/tint/ast/templated_identifier.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000080#include "src/tint/ast/type_name.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000081#include "src/tint/ast/unary_op_expression.h"
Ben Claytondcdf66e2022-06-17 12:48:51 +000082#include "src/tint/ast/var.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000083#include "src/tint/ast/variable_decl_statement.h"
84#include "src/tint/ast/vector.h"
dan sinclair49d1a2d2022-06-16 12:01:27 +000085#include "src/tint/ast/while_statement.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000086#include "src/tint/ast/workgroup_attribute.h"
dan sinclair02b466f2022-12-15 21:56:32 +000087#include "src/tint/constant/composite.h"
88#include "src/tint/constant/splat.h"
dan sinclairb53b8cf2022-12-15 16:25:31 +000089#include "src/tint/constant/value.h"
Ben Clayton0ce9ab02022-05-05 20:23:40 +000090#include "src/tint/number.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000091#include "src/tint/program.h"
92#include "src/tint/program_id.h"
dan sinclair4b1d79e2022-12-01 23:45:18 +000093#include "src/tint/sem/array_count.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000094#include "src/tint/sem/struct.h"
dan sinclair946858a2022-12-08 22:21:24 +000095#include "src/tint/type/array.h"
dan sinclaird37ecf92022-12-08 16:39:59 +000096#include "src/tint/type/bool.h"
dan sinclair4595fb72022-12-08 14:14:10 +000097#include "src/tint/type/depth_texture.h"
98#include "src/tint/type/external_texture.h"
dan sinclaird37ecf92022-12-08 16:39:59 +000099#include "src/tint/type/f16.h"
100#include "src/tint/type/f32.h"
101#include "src/tint/type/i32.h"
dan sinclair0e780da2022-12-08 22:21:24 +0000102#include "src/tint/type/matrix.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000103#include "src/tint/type/multisampled_texture.h"
dan sinclair4d56b482022-12-08 17:50:50 +0000104#include "src/tint/type/pointer.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000105#include "src/tint/type/sampled_texture.h"
Ben Claytoned3389f2023-02-09 23:56:42 +0000106#include "src/tint/type/sampler_kind.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000107#include "src/tint/type/storage_texture.h"
dan sinclair3cbf3fc2023-01-21 19:16:15 +0000108#include "src/tint/type/texture_dimension.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000109#include "src/tint/type/u32.h"
dan sinclair0e780da2022-12-08 22:21:24 +0000110#include "src/tint/type/vector.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000111#include "src/tint/type/void.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000112
Ben Clayton8fa6c252022-11-03 19:16:26 +0000113#ifdef CURRENTLY_IN_TINT_PUBLIC_HEADER
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000114#error "internal tint header being #included from tint.h"
115#endif
116
117// Forward declarations
Ben Claytona7230f02022-04-11 14:37:21 +0000118namespace tint {
119class CloneContext;
120} // namespace tint
dan sinclair8155b9d2022-04-07 19:10:25 +0000121namespace tint::ast {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000122class VariableDeclStatement;
dan sinclair8155b9d2022-04-07 19:10:25 +0000123} // namespace tint::ast
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000124
125namespace tint {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000126
Ben Clayton783b1692022-08-02 17:03:35 +0000127namespace detail {
128
129/// IsVectorLike<T>::value is true if T is a utils::Vector or utils::VectorRef.
130template <typename T>
131struct IsVectorLike {
132 /// Non-specialized form of IsVectorLike defaults to false
133 static constexpr bool value = false;
134};
135
136/// IsVectorLike specialization for utils::Vector
137template <typename T, size_t N>
138struct IsVectorLike<utils::Vector<T, N>> {
139 /// True for the IsVectorLike specialization of utils::Vector
140 static constexpr bool value = true;
141};
142
143/// IsVectorLike specialization for utils::VectorRef
144template <typename T>
145struct IsVectorLike<utils::VectorRef<T>> {
146 /// True for the IsVectorLike specialization of utils::VectorRef
147 static constexpr bool value = true;
148};
149} // namespace detail
150
Antonio Maioranodfa92a92022-12-23 17:56:56 +0000151// Forward declare metafunction that evaluates to true iff T can be wrapped in a statement.
152template <typename T, typename = void>
153struct CanWrapInStatement;
154
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000155/// ProgramBuilder is a mutable builder for a Program.
156/// To construct a Program, populate the builder and then `std::move` it to a
157/// Program.
158class ProgramBuilder {
Ben Clayton01ac21c2023-02-07 16:14:25 +0000159 /// Evaluates to true if T is a Source
160 template <typename T>
161 static constexpr const bool IsSource = std::is_same_v<T, Source>;
162
163 /// Evaluates to true if T is a Number or bool.
164 template <typename T>
165 static constexpr const bool IsScalar =
166 std::is_integral_v<UnwrapNumber<T>> || std::is_floating_point_v<UnwrapNumber<T>> ||
167 std::is_same_v<T, bool>;
168
169 /// A helper used to disable overloads if the first type in `TYPES` is a Source. Used to avoid
170 /// ambiguities in overloads that take a Source as the first parameter and those that
171 /// perfectly-forward the first argument.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000172 template <typename... TYPES>
173 using DisableIfSource =
Ben Clayton01ac21c2023-02-07 16:14:25 +0000174 traits::EnableIf<!IsSource<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>>;
175
176 /// A helper used to disable overloads if the first type in `TYPES` is a scalar type. Used to
177 /// avoid ambiguities in overloads that take a scalar as the first parameter and those that
178 /// perfectly-forward the first argument.
179 template <typename... TYPES>
180 using DisableIfScalar =
181 traits::EnableIf<!IsScalar<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000182
Ben Clayton783b1692022-08-02 17:03:35 +0000183 /// A helper used to disable overloads if the first type in `TYPES` is a utils::Vector,
184 /// utils::VectorRef or utils::VectorRef.
185 template <typename... TYPES>
186 using DisableIfVectorLike = traits::EnableIf<
187 !detail::IsVectorLike<traits::Decay<traits::NthTypeOf<0, TYPES..., void>>>::value>;
188
Ben Clayton58794ae2022-08-19 17:28:53 +0000189 /// VarOptions is a helper for accepting an arbitrary number of order independent options for
190 /// constructing an ast::Var.
191 struct VarOptions {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000192 template <typename... ARGS>
Ben Clayton58794ae2022-08-19 17:28:53 +0000193 explicit VarOptions(ARGS&&... args) {
194 (Set(std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000195 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000196 ~VarOptions();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000197
Ben Clayton58794ae2022-08-19 17:28:53 +0000198 const ast::Type* type = nullptr;
dan sinclair18b21582023-01-21 19:56:49 +0000199 type::AddressSpace address_space = type::AddressSpace::kNone;
dan sinclair61c16eb2023-01-21 23:44:38 +0000200 type::Access access = type::Access::kUndefined;
dan sinclair6e77b472022-10-20 13:38:28 +0000201 const ast::Expression* initializer = nullptr;
Ben Clayton783b1692022-08-02 17:03:35 +0000202 utils::Vector<const ast::Attribute*, 4> attributes;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000203
dan sinclair41e4d9a2022-05-01 14:40:55 +0000204 private:
Ben Clayton58794ae2022-08-19 17:28:53 +0000205 void Set(const ast::Type* t) { type = t; }
dan sinclair18b21582023-01-21 19:56:49 +0000206 void Set(type::AddressSpace addr_space) { address_space = addr_space; }
dan sinclair61c16eb2023-01-21 23:44:38 +0000207 void Set(type::Access ac) { access = ac; }
dan sinclair6e77b472022-10-20 13:38:28 +0000208 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton783b1692022-08-02 17:03:35 +0000209 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
Ben Clayton58794ae2022-08-19 17:28:53 +0000210 void Set(const ast::Attribute* a) { attributes.Push(a); }
211 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000212
Ben Clayton58794ae2022-08-19 17:28:53 +0000213 /// LetOptions is a helper for accepting an arbitrary number of order independent options for
214 /// constructing an ast::Let.
215 struct LetOptions {
216 template <typename... ARGS>
217 explicit LetOptions(ARGS&&... args) {
218 static constexpr bool has_init =
Ben Clayton2cdf1342023-02-03 13:24:18 +0000219 (traits::IsTypeOrDerived<traits::PtrElTy<ARGS>, ast::Expression> || ...);
Ben Clayton58794ae2022-08-19 17:28:53 +0000220 static_assert(has_init, "Let() must be constructed with an initializer expression");
221 (Set(std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000222 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000223 ~LetOptions();
224
225 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000226 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000227 utils::Vector<const ast::Attribute*, 4> attributes;
228
229 private:
230 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000231 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000232 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
233 void Set(const ast::Attribute* a) { attributes.Push(a); }
234 };
235
236 /// ConstOptions is a helper for accepting an arbitrary number of order independent options for
237 /// constructing an ast::Const.
238 struct ConstOptions {
239 template <typename... ARGS>
240 explicit ConstOptions(ARGS&&... args) {
241 static constexpr bool has_init =
Ben Clayton2cdf1342023-02-03 13:24:18 +0000242 (traits::IsTypeOrDerived<traits::PtrElTy<ARGS>, ast::Expression> || ...);
Ben Clayton58794ae2022-08-19 17:28:53 +0000243 static_assert(has_init, "Const() must be constructed with an initializer expression");
244 (Set(std::forward<ARGS>(args)), ...);
245 }
246 ~ConstOptions();
247
248 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000249 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000250 utils::Vector<const ast::Attribute*, 4> attributes;
251
252 private:
253 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000254 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000255 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
256 void Set(const ast::Attribute* a) { attributes.Push(a); }
257 };
258
259 /// OverrideOptions is a helper for accepting an arbitrary number of order independent options
260 /// for constructing an ast::Override.
261 struct OverrideOptions {
262 template <typename... ARGS>
263 explicit OverrideOptions(ARGS&&... args) {
264 (Set(std::forward<ARGS>(args)), ...);
265 }
266 ~OverrideOptions();
267
268 const ast::Type* type = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000269 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000270 utils::Vector<const ast::Attribute*, 4> attributes;
271
272 private:
273 void Set(const ast::Type* t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000274 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000275 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
276 void Set(const ast::Attribute* a) { attributes.Push(a); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000277 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000278
dan sinclair41e4d9a2022-05-01 14:40:55 +0000279 public:
280 /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node>
281 using ASTNodeAllocator = utils::BlockAllocator<ast::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000282
dan sinclair41e4d9a2022-05-01 14:40:55 +0000283 /// SemNodeAllocator is an alias to BlockAllocator<sem::Node>
284 using SemNodeAllocator = utils::BlockAllocator<sem::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000285
dan sinclairb53b8cf2022-12-15 16:25:31 +0000286 /// ConstantAllocator is an alias to BlockAllocator<constant::Value>
287 using ConstantAllocator = utils::BlockAllocator<constant::Value>;
Ben Claytonaa037ac2022-06-29 19:07:30 +0000288
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000289 /// Constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000290 ProgramBuilder();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000291
dan sinclair41e4d9a2022-05-01 14:40:55 +0000292 /// Move constructor
293 /// @param rhs the builder to move
294 ProgramBuilder(ProgramBuilder&& rhs);
295
296 /// Destructor
297 virtual ~ProgramBuilder();
298
299 /// Move assignment operator
300 /// @param rhs the builder to move
301 /// @return this builder
302 ProgramBuilder& operator=(ProgramBuilder&& rhs);
303
304 /// Wrap returns a new ProgramBuilder wrapping the Program `program` without
305 /// making a deep clone of the Program contents.
306 /// ProgramBuilder returned by Wrap() is intended to temporarily extend an
307 /// existing immutable program.
308 /// As the returned ProgramBuilder wraps `program`, `program` must not be
309 /// destructed or assigned while using the returned ProgramBuilder.
310 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this
311 /// function. See crbug.com/tint/460.
312 /// @param program the immutable Program to wrap
313 /// @return the ProgramBuilder that wraps `program`
314 static ProgramBuilder Wrap(const Program* program);
315
316 /// @returns the unique identifier for this program
317 ProgramID ID() const { return id_; }
318
319 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000320 type::Manager& Types() {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000321 AssertNotMoved();
322 return types_;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000323 }
324
dan sinclair41e4d9a2022-05-01 14:40:55 +0000325 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000326 const type::Manager& Types() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000327 AssertNotMoved();
328 return types_;
329 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000330
dan sinclair41e4d9a2022-05-01 14:40:55 +0000331 /// @returns a reference to the program's AST nodes storage
332 ASTNodeAllocator& ASTNodes() {
333 AssertNotMoved();
334 return ast_nodes_;
335 }
336
337 /// @returns a reference to the program's AST nodes storage
338 const ASTNodeAllocator& ASTNodes() const {
339 AssertNotMoved();
340 return ast_nodes_;
341 }
342
343 /// @returns a reference to the program's semantic nodes storage
344 SemNodeAllocator& SemNodes() {
345 AssertNotMoved();
346 return sem_nodes_;
347 }
348
349 /// @returns a reference to the program's semantic nodes storage
350 const SemNodeAllocator& SemNodes() const {
351 AssertNotMoved();
352 return sem_nodes_;
353 }
354
Ben Claytonaa037ac2022-06-29 19:07:30 +0000355 /// @returns a reference to the program's semantic constant storage
356 ConstantAllocator& ConstantNodes() {
357 AssertNotMoved();
358 return constant_nodes_;
359 }
360
dan sinclair41e4d9a2022-05-01 14:40:55 +0000361 /// @returns a reference to the program's AST root Module
362 ast::Module& AST() {
363 AssertNotMoved();
364 return *ast_;
365 }
366
367 /// @returns a reference to the program's AST root Module
368 const ast::Module& AST() const {
369 AssertNotMoved();
370 return *ast_;
371 }
372
373 /// @returns a reference to the program's semantic info
374 sem::Info& Sem() {
375 AssertNotMoved();
376 return sem_;
377 }
378
379 /// @returns a reference to the program's semantic info
380 const sem::Info& Sem() const {
381 AssertNotMoved();
382 return sem_;
383 }
384
385 /// @returns a reference to the program's SymbolTable
386 SymbolTable& Symbols() {
387 AssertNotMoved();
388 return symbols_;
389 }
390
391 /// @returns a reference to the program's SymbolTable
392 const SymbolTable& Symbols() const {
393 AssertNotMoved();
394 return symbols_;
395 }
396
397 /// @returns a reference to the program's diagnostics
398 diag::List& Diagnostics() {
399 AssertNotMoved();
400 return diagnostics_;
401 }
402
403 /// @returns a reference to the program's diagnostics
404 const diag::List& Diagnostics() const {
405 AssertNotMoved();
406 return diagnostics_;
407 }
408
409 /// Controls whether the Resolver will be run on the program when it is built.
410 /// @param enable the new flag value (defaults to true)
411 void SetResolveOnBuild(bool enable) { resolve_on_build_ = enable; }
412
413 /// @return true if the Resolver will be run on the program when it is
414 /// built.
415 bool ResolveOnBuild() const { return resolve_on_build_; }
416
417 /// @returns true if the program has no error diagnostics and is not missing
418 /// information
419 bool IsValid() const;
420
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000421 /// @returns the last allocated (numerically highest) AST node identifier.
422 ast::NodeID LastAllocatedNodeID() const { return last_ast_node_id_; }
423
424 /// @returns the next sequentially unique node identifier.
425 ast::NodeID AllocateNodeID() {
426 auto out = ast::NodeID{last_ast_node_id_.value + 1};
427 last_ast_node_id_ = out;
428 return out;
429 }
430
dan sinclair41e4d9a2022-05-01 14:40:55 +0000431 /// Creates a new ast::Node owned by the ProgramBuilder. When the
432 /// ProgramBuilder is destructed, the ast::Node will also be destructed.
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000433 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000434 /// @param args the arguments to pass to the type constructor
435 /// @returns the node pointer
436 template <typename T, typename... ARGS>
437 traits::EnableIfIsType<T, ast::Node>* create(const Source& source, ARGS&&... args) {
438 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000439 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000440 }
441
dan sinclair41e4d9a2022-05-01 14:40:55 +0000442 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
443 /// Source as set by the last call to SetSource() as the only argument to the
444 /// constructor.
445 /// When the ProgramBuilder is destructed, the ast::Node will also be
446 /// destructed.
447 /// @returns the node pointer
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000448 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +0000449 traits::EnableIfIsType<T, ast::Node>* create() {
450 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000451 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000452 }
453
dan sinclair41e4d9a2022-05-01 14:40:55 +0000454 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
455 /// Source as set by the last call to SetSource() as the first argument to the
456 /// constructor.
457 /// When the ProgramBuilder is destructed, the ast::Node will also be
458 /// destructed.
459 /// @param arg0 the first arguments to pass to the type constructor
460 /// @param args the remaining arguments to pass to the type constructor
461 /// @returns the node pointer
462 template <typename T, typename ARG0, typename... ARGS>
463 traits::EnableIf</* T is ast::Node and ARG0 is not Source */
464 traits::IsTypeOrDerived<T, ast::Node> &&
465 !traits::IsTypeOrDerived<ARG0, Source>,
466 T>*
467 create(ARG0&& arg0, ARGS&&... args) {
468 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000469 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_, std::forward<ARG0>(arg0),
dan sinclair41e4d9a2022-05-01 14:40:55 +0000470 std::forward<ARGS>(args)...);
471 }
472
473 /// Creates a new sem::Node owned by the ProgramBuilder.
Ben Claytonaa037ac2022-06-29 19:07:30 +0000474 /// When the ProgramBuilder is destructed, the sem::Node will also be destructed.
475 /// @param args the arguments to pass to the constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000476 /// @returns the node pointer
477 template <typename T, typename... ARGS>
478 traits::EnableIf<traits::IsTypeOrDerived<T, sem::Node> &&
dan sinclair5f764d82022-12-08 00:32:27 +0000479 !traits::IsTypeOrDerived<T, type::Node>,
dan sinclair41e4d9a2022-05-01 14:40:55 +0000480 T>*
481 create(ARGS&&... args) {
482 AssertNotMoved();
483 return sem_nodes_.Create<T>(std::forward<ARGS>(args)...);
484 }
485
dan sinclairb53b8cf2022-12-15 16:25:31 +0000486 /// Creates a new constant::Value owned by the ProgramBuilder.
Ben Claytonaa037ac2022-06-29 19:07:30 +0000487 /// When the ProgramBuilder is destructed, the sem::Node will also be destructed.
488 /// @param args the arguments to pass to the constructor
489 /// @returns the node pointer
490 template <typename T, typename... ARGS>
dan sinclair02b466f2022-12-15 21:56:32 +0000491 traits::EnableIf<traits::IsTypeOrDerived<T, constant::Value> &&
492 !traits::IsTypeOrDerived<T, constant::Composite> &&
493 !traits::IsTypeOrDerived<T, constant::Splat>,
494 T>*
495 create(ARGS&&... args) {
Ben Claytonaa037ac2022-06-29 19:07:30 +0000496 AssertNotMoved();
497 return constant_nodes_.Create<T>(std::forward<ARGS>(args)...);
498 }
499
dan sinclair02b466f2022-12-15 21:56:32 +0000500 /// Constructs a constant of a vector, matrix or array type.
501 ///
502 /// Examines the element values and will return either a constant::Composite or a
503 /// constant::Splat, depending on the element types and values.
504 ///
505 /// @param type the composite type
506 /// @param elements the composite elements
507 /// @returns the node pointer
dan sinclaircf581222023-01-03 20:25:37 +0000508 template <typename T,
509 typename = traits::EnableIf<traits::IsTypeOrDerived<T, constant::Composite> ||
510 traits::IsTypeOrDerived<T, constant::Splat>>>
511 const constant::Value* create(const type::Type* type,
512 utils::VectorRef<const constant::Value*> elements) {
dan sinclair02b466f2022-12-15 21:56:32 +0000513 AssertNotMoved();
dan sinclaircf581222023-01-03 20:25:37 +0000514 return createSplatOrComposite(type, elements);
dan sinclair02b466f2022-12-15 21:56:32 +0000515 }
516
517 /// Constructs a splat constant.
518 /// @param type the splat type
519 /// @param element the splat element
520 /// @param n the number of elements
521 /// @returns the node pointer
dan sinclaircf581222023-01-03 20:25:37 +0000522 template <typename T, typename = traits::EnableIf<traits::IsTypeOrDerived<T, constant::Splat>>>
523 const constant::Splat* create(const type::Type* type,
524 const constant::Value* element,
525 size_t n) {
dan sinclair02b466f2022-12-15 21:56:32 +0000526 AssertNotMoved();
527 return constant_nodes_.Create<constant::Splat>(type, element, n);
528 }
529
Ben Clayton7c3e9a62022-12-16 15:31:19 +0000530 /// Creates a new type::Node owned by the ProgramBuilder.
531 /// When the ProgramBuilder is destructed, owned ProgramBuilder and the returned node will also
532 /// be destructed. If T derives from type::UniqueNode, then the calling create() for the same
533 /// `T` and arguments will return the same pointer.
534 /// @param args the arguments to pass to the constructor
535 /// @returns the new, or existing node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000536 template <typename T, typename... ARGS>
Ben Clayton7c3e9a62022-12-16 15:31:19 +0000537 traits::EnableIfIsType<T, type::Node>* create(ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000538 AssertNotMoved();
539 return types_.Get<T>(std::forward<ARGS>(args)...);
540 }
dan sinclair5f764d82022-12-08 00:32:27 +0000541
dan sinclair41e4d9a2022-05-01 14:40:55 +0000542 /// Marks this builder as moved, preventing any further use of the builder.
543 void MarkAsMoved();
544
545 //////////////////////////////////////////////////////////////////////////////
546 // TypesBuilder
547 //////////////////////////////////////////////////////////////////////////////
548
549 /// TypesBuilder holds basic `tint` types and methods for constructing
550 /// complex types.
551 class TypesBuilder {
552 public:
553 /// Constructor
554 /// @param builder the program builder
555 explicit TypesBuilder(ProgramBuilder* builder);
556
557 /// @return the tint AST type for the C type `T`.
558 template <typename T>
559 const ast::Type* Of() const {
560 return CToAST<T>::get(this);
561 }
562
Ben Clayton19068572023-02-07 21:28:09 +0000563 /// @returns nullptr ast::Type
564 const ast::Type* void_() const { return nullptr; }
565
Ben Clayton6e0a5152023-02-09 23:33:24 +0000566 /// @returns a 'bool' typename
567 const ast::TypeName* bool_() const { return (*this)("bool"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000568
569 /// @param source the Source of the node
Ben Clayton6e0a5152023-02-09 23:33:24 +0000570 /// @returns a 'bool' typename
571 const ast::TypeName* bool_(const Source& source) const { return (*this)(source, "bool"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000572
Ben Clayton6e0a5152023-02-09 23:33:24 +0000573 /// @returns a 'f16' typename
574 const ast::TypeName* f16() const { return (*this)("f16"); }
Zhaoming Jiang62bfd312022-05-13 12:01:11 +0000575
576 /// @param source the Source of the node
Ben Clayton6e0a5152023-02-09 23:33:24 +0000577 /// @returns a 'f16' typename
578 const ast::TypeName* f16(const Source& source) const { return (*this)(source, "f16"); }
Zhaoming Jiang62bfd312022-05-13 12:01:11 +0000579
Ben Clayton6e0a5152023-02-09 23:33:24 +0000580 /// @returns a 'f32' typename
581 const ast::TypeName* f32() const { return (*this)("f32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000582
583 /// @param source the Source of the node
Ben Clayton6e0a5152023-02-09 23:33:24 +0000584 /// @returns a 'f32' typename
585 const ast::TypeName* f32(const Source& source) const { return (*this)(source, "f32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000586
Ben Clayton6e0a5152023-02-09 23:33:24 +0000587 /// @returns a 'i32' typename
588 const ast::TypeName* i32() const { return (*this)("i32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000589
590 /// @param source the Source of the node
Ben Clayton6e0a5152023-02-09 23:33:24 +0000591 /// @returns a 'i32' typename
592 const ast::TypeName* i32(const Source& source) const { return (*this)(source, "i32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000593
Ben Clayton6e0a5152023-02-09 23:33:24 +0000594 /// @returns a 'u32' typename
595 const ast::TypeName* u32() const { return (*this)("u32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000596
597 /// @param source the Source of the node
Ben Clayton6e0a5152023-02-09 23:33:24 +0000598 /// @returns a 'u32' typename
599 const ast::TypeName* u32(const Source& source) const { return (*this)(source, "u32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000600
dan sinclair41e4d9a2022-05-01 14:40:55 +0000601 /// @param type vector subtype
602 /// @param n vector width in elements
603 /// @return the tint AST type for a `n`-element vector of `type`.
604 const ast::Vector* vec(const ast::Type* type, uint32_t n) const {
605 return builder->create<ast::Vector>(type, n);
606 }
607
608 /// @param source the Source of the node
609 /// @param type vector subtype
610 /// @param n vector width in elements
611 /// @return the tint AST type for a `n`-element vector of `type`.
612 const ast::Vector* vec(const Source& source, const ast::Type* type, uint32_t n) const {
613 return builder->create<ast::Vector>(source, type, n);
614 }
615
616 /// @param type vector subtype
617 /// @return the tint AST type for a 2-element vector of `type`.
618 const ast::Vector* vec2(const ast::Type* type) const { return vec(type, 2u); }
619
Ben Clayton6315a272022-08-01 17:18:04 +0000620 /// @param source the vector source
621 /// @param type vector subtype
622 /// @return the tint AST type for a 2-element vector of `type`.
623 const ast::Vector* vec2(const Source& source, const ast::Type* type) const {
624 return vec(source, type, 2u);
625 }
626
dan sinclair41e4d9a2022-05-01 14:40:55 +0000627 /// @param type vector subtype
628 /// @return the tint AST type for a 3-element vector of `type`.
629 const ast::Vector* vec3(const ast::Type* type) const { return vec(type, 3u); }
630
Ben Clayton6315a272022-08-01 17:18:04 +0000631 /// @param source the vector source
632 /// @param type vector subtype
633 /// @return the tint AST type for a 3-element vector of `type`.
634 const ast::Vector* vec3(const Source& source, const ast::Type* type) const {
635 return vec(source, type, 3u);
636 }
637
dan sinclair41e4d9a2022-05-01 14:40:55 +0000638 /// @param type vector subtype
639 /// @return the tint AST type for a 4-element vector of `type`.
640 const ast::Vector* vec4(const ast::Type* type) const { return vec(type, 4u); }
641
Ben Clayton6315a272022-08-01 17:18:04 +0000642 /// @param source the vector source
643 /// @param type vector subtype
644 /// @return the tint AST type for a 4-element vector of `type`.
645 const ast::Vector* vec4(const Source& source, const ast::Type* type) const {
646 return vec(source, type, 4u);
647 }
648
dan sinclair41e4d9a2022-05-01 14:40:55 +0000649 /// @param n vector width in elements
650 /// @return the tint AST type for a `n`-element vector of `type`.
651 template <typename T>
652 const ast::Vector* vec(uint32_t n) const {
653 return vec(Of<T>(), n);
654 }
655
656 /// @return the tint AST type for a 2-element vector of the C type `T`.
657 template <typename T>
658 const ast::Vector* vec2() const {
659 return vec2(Of<T>());
660 }
661
Ben Clayton6315a272022-08-01 17:18:04 +0000662 /// @param source the Source of the node
663 /// @return the tint AST type for a 2-element vector of the C type `T`.
664 template <typename T>
665 const ast::Vector* vec2(const Source& source) const {
666 return vec2(source, Of<T>());
667 }
668
dan sinclair41e4d9a2022-05-01 14:40:55 +0000669 /// @return the tint AST type for a 3-element vector of the C type `T`.
670 template <typename T>
671 const ast::Vector* vec3() const {
672 return vec3(Of<T>());
673 }
674
Ben Clayton6315a272022-08-01 17:18:04 +0000675 /// @param source the Source of the node
676 /// @return the tint AST type for a 3-element vector of the C type `T`.
677 template <typename T>
678 const ast::Vector* vec3(const Source& source) const {
679 return vec3(source, Of<T>());
680 }
681
dan sinclair41e4d9a2022-05-01 14:40:55 +0000682 /// @return the tint AST type for a 4-element vector of the C type `T`.
683 template <typename T>
684 const ast::Vector* vec4() const {
685 return vec4(Of<T>());
686 }
687
Ben Clayton6315a272022-08-01 17:18:04 +0000688 /// @param source the Source of the node
689 /// @return the tint AST type for a 4-element vector of the C type `T`.
690 template <typename T>
691 const ast::Vector* vec4(const Source& source) const {
692 return vec4(source, Of<T>());
693 }
694
dan sinclair41e4d9a2022-05-01 14:40:55 +0000695 /// @param type matrix subtype
696 /// @param columns number of columns for the matrix
697 /// @param rows number of rows for the matrix
698 /// @return the tint AST type for a matrix of `type`
699 const ast::Matrix* mat(const ast::Type* type, uint32_t columns, uint32_t rows) const {
700 return builder->create<ast::Matrix>(type, rows, columns);
701 }
702
703 /// @param source the Source of the node
704 /// @param type matrix subtype
705 /// @param columns number of columns for the matrix
706 /// @param rows number of rows for the matrix
707 /// @return the tint AST type for a matrix of `type`
708 const ast::Matrix* mat(const Source& source,
709 const ast::Type* type,
710 uint32_t columns,
711 uint32_t rows) const {
712 return builder->create<ast::Matrix>(source, type, rows, columns);
713 }
714
715 /// @param type matrix subtype
716 /// @return the tint AST type for a 2x3 matrix of `type`.
717 const ast::Matrix* mat2x2(const ast::Type* type) const { return mat(type, 2u, 2u); }
718
719 /// @param type matrix subtype
720 /// @return the tint AST type for a 2x3 matrix of `type`.
721 const ast::Matrix* mat2x3(const ast::Type* type) const { return mat(type, 2u, 3u); }
722
723 /// @param type matrix subtype
724 /// @return the tint AST type for a 2x4 matrix of `type`.
725 const ast::Matrix* mat2x4(const ast::Type* type) const { return mat(type, 2u, 4u); }
726
727 /// @param type matrix subtype
728 /// @return the tint AST type for a 3x2 matrix of `type`.
729 const ast::Matrix* mat3x2(const ast::Type* type) const { return mat(type, 3u, 2u); }
730
731 /// @param type matrix subtype
732 /// @return the tint AST type for a 3x3 matrix of `type`.
733 const ast::Matrix* mat3x3(const ast::Type* type) const { return mat(type, 3u, 3u); }
734
735 /// @param type matrix subtype
736 /// @return the tint AST type for a 3x4 matrix of `type`.
737 const ast::Matrix* mat3x4(const ast::Type* type) const { return mat(type, 3u, 4u); }
738
739 /// @param type matrix subtype
740 /// @return the tint AST type for a 4x2 matrix of `type`.
741 const ast::Matrix* mat4x2(const ast::Type* type) const { return mat(type, 4u, 2u); }
742
743 /// @param type matrix subtype
744 /// @return the tint AST type for a 4x3 matrix of `type`.
745 const ast::Matrix* mat4x3(const ast::Type* type) const { return mat(type, 4u, 3u); }
746
747 /// @param type matrix subtype
748 /// @return the tint AST type for a 4x4 matrix of `type`.
749 const ast::Matrix* mat4x4(const ast::Type* type) const { return mat(type, 4u, 4u); }
750
751 /// @param columns number of columns for the matrix
752 /// @param rows number of rows for the matrix
753 /// @return the tint AST type for a matrix of `type`
754 template <typename T>
755 const ast::Matrix* mat(uint32_t columns, uint32_t rows) const {
756 return mat(Of<T>(), columns, rows);
757 }
758
759 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
760 template <typename T>
761 const ast::Matrix* mat2x2() const {
762 return mat2x2(Of<T>());
763 }
764
765 /// @return the tint AST type for a 2x3 matrix of the C type `T`.
766 template <typename T>
767 const ast::Matrix* mat2x3() const {
768 return mat2x3(Of<T>());
769 }
770
771 /// @return the tint AST type for a 2x4 matrix of the C type `T`.
772 template <typename T>
773 const ast::Matrix* mat2x4() const {
774 return mat2x4(Of<T>());
775 }
776
777 /// @return the tint AST type for a 3x2 matrix of the C type `T`.
778 template <typename T>
779 const ast::Matrix* mat3x2() const {
780 return mat3x2(Of<T>());
781 }
782
783 /// @return the tint AST type for a 3x3 matrix of the C type `T`.
784 template <typename T>
785 const ast::Matrix* mat3x3() const {
786 return mat3x3(Of<T>());
787 }
788
789 /// @return the tint AST type for a 3x4 matrix of the C type `T`.
790 template <typename T>
791 const ast::Matrix* mat3x4() const {
792 return mat3x4(Of<T>());
793 }
794
795 /// @return the tint AST type for a 4x2 matrix of the C type `T`.
796 template <typename T>
797 const ast::Matrix* mat4x2() const {
798 return mat4x2(Of<T>());
799 }
800
801 /// @return the tint AST type for a 4x3 matrix of the C type `T`.
802 template <typename T>
803 const ast::Matrix* mat4x3() const {
804 return mat4x3(Of<T>());
805 }
806
807 /// @return the tint AST type for a 4x4 matrix of the C type `T`.
808 template <typename T>
809 const ast::Matrix* mat4x4() const {
810 return mat4x4(Of<T>());
811 }
812
813 /// @param subtype the array element type
814 /// @param n the array size. nullptr represents a runtime-array
815 /// @param attrs the optional attributes for the array
Ben Clayton9e367232023-02-08 14:17:37 +0000816 /// @return the array of size `n` of type `T`
817 template <typename COUNT = std::nullptr_t>
Ben Clayton783b1692022-08-02 17:03:35 +0000818 const ast::Array* array(
819 const ast::Type* subtype,
Ben Clayton9e367232023-02-08 14:17:37 +0000820 COUNT&& n = nullptr,
Ben Clayton783b1692022-08-02 17:03:35 +0000821 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
Ben Clayton9e367232023-02-08 14:17:37 +0000822 return array(builder->source_, subtype, std::forward<COUNT>(n), std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000823 }
824
825 /// @param source the Source of the node
826 /// @param subtype the array element type
827 /// @param n the array size. nullptr represents a runtime-array
828 /// @param attrs the optional attributes for the array
Ben Clayton9e367232023-02-08 14:17:37 +0000829 /// @return the array of size `n` of type `T`
830 template <typename COUNT = std::nullptr_t>
Ben Clayton783b1692022-08-02 17:03:35 +0000831 const ast::Array* array(
832 const Source& source,
833 const ast::Type* subtype,
Ben Clayton9e367232023-02-08 14:17:37 +0000834 COUNT&& n = nullptr,
Ben Clayton783b1692022-08-02 17:03:35 +0000835 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
Ben Clayton9e367232023-02-08 14:17:37 +0000836 if constexpr (std::is_same_v<traits::Decay<COUNT>, std::nullptr_t>) {
837 return builder->create<ast::Array>(source, subtype, nullptr, std::move(attrs));
838 } else {
839 return builder->create<ast::Array>(
840 source, subtype, builder->Expr(std::forward<COUNT>(n)), std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000841 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000842 }
843
Ben Clayton9e367232023-02-08 14:17:37 +0000844 /// @param attrs the optional attributes for the array
845 /// @return the runtime-sized array of type `T`
dan sinclair41e4d9a2022-05-01 14:40:55 +0000846 template <typename T>
Ben Clayton9e367232023-02-08 14:17:37 +0000847 const ast::Array* array(
848 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
849 return array(Of<T>(), nullptr, std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000850 }
851
Ben Clayton9e367232023-02-08 14:17:37 +0000852 /// @param attrs the optional attributes for the array
853 /// @return the array of size `N` of type `T`
dan sinclair41e4d9a2022-05-01 14:40:55 +0000854 template <typename T, int N>
Ben Clayton9e367232023-02-08 14:17:37 +0000855 const ast::Array* array(
856 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
857 return array(Of<T>(), tint::u32(N), std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000858 }
859
860 /// Creates a type name
861 /// @param name the name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000862 /// @param args the optional template arguments
dan sinclair41e4d9a2022-05-01 14:40:55 +0000863 /// @returns the type name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000864 template <typename NAME, typename... ARGS, typename _ = DisableIfSource<NAME>>
Ben Clayton2117f802023-02-03 14:01:43 +0000865 const ast::TypeName* operator()(NAME&& name, ARGS&&... args) const {
Ben Claytoncf0e9302023-02-08 15:18:43 +0000866 return (*this)(builder->source_, std::forward<NAME>(name), std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000867 }
868
869 /// Creates a type name
870 /// @param source the Source of the node
871 /// @param name the name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000872 /// @param args the optional template arguments
dan sinclair41e4d9a2022-05-01 14:40:55 +0000873 /// @returns the type name
Ben Clayton2cdf1342023-02-03 13:24:18 +0000874 template <typename NAME, typename... ARGS>
Ben Clayton2117f802023-02-03 14:01:43 +0000875 const ast::TypeName* operator()(const Source& source, NAME&& name, ARGS&&... args) const {
Ben Clayton2cdf1342023-02-03 13:24:18 +0000876 return builder->create<ast::TypeName>(
Ben Claytoncf0e9302023-02-08 15:18:43 +0000877 source,
878 builder->Ident(source, std::forward<NAME>(name), std::forward<ARGS>(args)...));
dan sinclair41e4d9a2022-05-01 14:40:55 +0000879 }
880
881 /// Creates an alias type
882 /// @param name the alias name
883 /// @param type the alias type
884 /// @returns the alias pointer
885 template <typename NAME>
886 const ast::Alias* alias(NAME&& name, const ast::Type* type) const {
Ben Claytonb75252b2023-02-09 10:34:14 +0000887 return alias(builder->source_, std::forward<NAME>(name), type);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000888 }
889
890 /// Creates an alias type
891 /// @param source the Source of the node
892 /// @param name the alias name
893 /// @param type the alias type
894 /// @returns the alias pointer
895 template <typename NAME>
896 const ast::Alias* alias(const Source& source, NAME&& name, const ast::Type* type) const {
Ben Claytonb75252b2023-02-09 10:34:14 +0000897 return builder->create<ast::Alias>(source, builder->Ident(std::forward<NAME>(name)),
898 type);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000899 }
900
901 /// @param type the type of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000902 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000903 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000904 /// @return the pointer to `type` with the given type::AddressSpace
dan sinclair41e4d9a2022-05-01 14:40:55 +0000905 const ast::Pointer* pointer(const ast::Type* type,
dan sinclair18b21582023-01-21 19:56:49 +0000906 type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000907 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000908 return builder->create<ast::Pointer>(type, address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000909 }
910
911 /// @param source the Source of the node
912 /// @param type the type of the pointer
dan sinclairff7cf212022-10-03 14:05:23 +0000913 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000914 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000915 /// @return the pointer to `type` with the given type::AddressSpace
dan sinclair41e4d9a2022-05-01 14:40:55 +0000916 const ast::Pointer* pointer(const Source& source,
917 const ast::Type* type,
dan sinclair18b21582023-01-21 19:56:49 +0000918 type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000919 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000920 return builder->create<ast::Pointer>(source, type, address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000921 }
922
dan sinclairff7cf212022-10-03 14:05:23 +0000923 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +0000924 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000925 /// @return the pointer to type `T` with the given type::AddressSpace.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000926 template <typename T>
dan sinclair18b21582023-01-21 19:56:49 +0000927 const ast::Pointer* pointer(type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000928 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000929 return pointer(Of<T>(), address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000930 }
931
932 /// @param source the Source of the node
dan sinclairff7cf212022-10-03 14:05:23 +0000933 /// @param address_space the address space of the pointer
Ben Claytoncfe07a12022-07-15 13:01:49 +0000934 /// @param access the optional access control of the pointer
dan sinclair18b21582023-01-21 19:56:49 +0000935 /// @return the pointer to type `T` with the given type::AddressSpace.
Ben Claytoncfe07a12022-07-15 13:01:49 +0000936 template <typename T>
937 const ast::Pointer* pointer(const Source& source,
dan sinclair18b21582023-01-21 19:56:49 +0000938 type::AddressSpace address_space,
dan sinclair61c16eb2023-01-21 23:44:38 +0000939 type::Access access = type::Access::kUndefined) const {
dan sinclairff7cf212022-10-03 14:05:23 +0000940 return pointer(source, Of<T>(), address_space, access);
Ben Claytoncfe07a12022-07-15 13:01:49 +0000941 }
942
943 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000944 /// @param type the type of the atomic
945 /// @return the atomic to `type`
946 const ast::Atomic* atomic(const Source& source, const ast::Type* type) const {
947 return builder->create<ast::Atomic>(source, type);
948 }
949
950 /// @param type the type of the atomic
951 /// @return the atomic to `type`
952 const ast::Atomic* atomic(const ast::Type* type) const {
953 return builder->create<ast::Atomic>(type);
954 }
955
956 /// @return the atomic to type `T`
957 template <typename T>
958 const ast::Atomic* atomic() const {
959 return atomic(Of<T>());
960 }
961
962 /// @param kind the kind of sampler
Ben Claytoned3389f2023-02-09 23:56:42 +0000963 /// @returns the sampler typename
964 const ast::TypeName* sampler(type::SamplerKind kind) const {
965 return sampler(builder->source_, kind);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000966 }
967
968 /// @param source the Source of the node
969 /// @param kind the kind of sampler
Ben Claytoned3389f2023-02-09 23:56:42 +0000970 /// @returns the sampler typename
971 const ast::TypeName* sampler(const Source& source, type::SamplerKind kind) const {
972 switch (kind) {
973 case type::SamplerKind::kSampler:
974 return (*this)(source, "sampler");
975 case type::SamplerKind::kComparisonSampler:
976 return (*this)(source, "sampler_comparison");
977 }
978 TINT_ICE(ProgramBuilder, builder->Diagnostics()) << "invalid sampler kind " << kind;
979 return nullptr;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000980 }
981
982 /// @param dims the dimensionality of the texture
983 /// @returns the depth texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +0000984 const ast::DepthTexture* depth_texture(type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000985 return builder->create<ast::DepthTexture>(dims);
986 }
987
988 /// @param source the Source of the node
989 /// @param dims the dimensionality of the texture
990 /// @returns the depth texture
991 const ast::DepthTexture* depth_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +0000992 type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000993 return builder->create<ast::DepthTexture>(source, dims);
994 }
995
996 /// @param dims the dimensionality of the texture
997 /// @returns the multisampled depth texture
998 const ast::DepthMultisampledTexture* depth_multisampled_texture(
dan sinclair3cbf3fc2023-01-21 19:16:15 +0000999 type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001000 return builder->create<ast::DepthMultisampledTexture>(dims);
1001 }
1002
1003 /// @param source the Source of the node
1004 /// @param dims the dimensionality of the texture
1005 /// @returns the multisampled depth texture
1006 const ast::DepthMultisampledTexture* depth_multisampled_texture(
1007 const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001008 type::TextureDimension dims) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001009 return builder->create<ast::DepthMultisampledTexture>(source, dims);
1010 }
1011
1012 /// @param dims the dimensionality of the texture
1013 /// @param subtype the texture subtype.
1014 /// @returns the sampled texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001015 const ast::SampledTexture* sampled_texture(type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001016 const ast::Type* subtype) const {
1017 return builder->create<ast::SampledTexture>(dims, subtype);
1018 }
1019
1020 /// @param source the Source of the node
1021 /// @param dims the dimensionality of the texture
1022 /// @param subtype the texture subtype.
1023 /// @returns the sampled texture
1024 const ast::SampledTexture* sampled_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001025 type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001026 const ast::Type* subtype) const {
1027 return builder->create<ast::SampledTexture>(source, dims, subtype);
1028 }
1029
1030 /// @param dims the dimensionality of the texture
1031 /// @param subtype the texture subtype.
1032 /// @returns the multisampled texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001033 const ast::MultisampledTexture* multisampled_texture(type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001034 const ast::Type* subtype) const {
1035 return builder->create<ast::MultisampledTexture>(dims, subtype);
1036 }
1037
1038 /// @param source the Source of the node
1039 /// @param dims the dimensionality of the texture
1040 /// @param subtype the texture subtype.
1041 /// @returns the multisampled texture
1042 const ast::MultisampledTexture* multisampled_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001043 type::TextureDimension dims,
dan sinclair41e4d9a2022-05-01 14:40:55 +00001044 const ast::Type* subtype) const {
1045 return builder->create<ast::MultisampledTexture>(source, dims, subtype);
1046 }
1047
1048 /// @param dims the dimensionality of the texture
1049 /// @param format the texel format of the texture
1050 /// @param access the access control of the texture
1051 /// @returns the storage texture
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001052 const ast::StorageTexture* storage_texture(type::TextureDimension dims,
dan sinclair57c0bbc2023-01-21 23:51:25 +00001053 type::TexelFormat format,
dan sinclair61c16eb2023-01-21 23:44:38 +00001054 type::Access access) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001055 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
1056 return builder->create<ast::StorageTexture>(dims, format, subtype, access);
1057 }
1058
1059 /// @param source the Source of the node
1060 /// @param dims the dimensionality of the texture
1061 /// @param format the texel format of the texture
1062 /// @param access the access control of the texture
1063 /// @returns the storage texture
1064 const ast::StorageTexture* storage_texture(const Source& source,
dan sinclair3cbf3fc2023-01-21 19:16:15 +00001065 type::TextureDimension dims,
dan sinclair57c0bbc2023-01-21 23:51:25 +00001066 type::TexelFormat format,
dan sinclair61c16eb2023-01-21 23:44:38 +00001067 type::Access access) const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001068 auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
1069 return builder->create<ast::StorageTexture>(source, dims, format, subtype, access);
1070 }
1071
1072 /// @returns the external texture
Ben Clayton4906b032023-02-09 23:59:07 +00001073 const ast::TypeName* external_texture() const { return external_texture(builder->source_); }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001074
1075 /// @param source the Source of the node
Ben Clayton4906b032023-02-09 23:59:07 +00001076 /// @returns the external texture typename
1077 const ast::TypeName* external_texture(const Source& source) const {
1078 return (*this)(source, "texture_external");
dan sinclair41e4d9a2022-05-01 14:40:55 +00001079 }
1080
1081 /// Constructs a TypeName for the type declaration.
1082 /// @param type the type
1083 /// @return either type or a pointer to a new ast::TypeName
1084 const ast::TypeName* Of(const ast::TypeDecl* type) const;
1085
1086 /// The ProgramBuilder
1087 ProgramBuilder* const builder;
1088
1089 private:
1090 /// CToAST<T> is specialized for various `T` types and each specialization
1091 /// contains a single static `get()` method for obtaining the corresponding
1092 /// AST type for the C type `T`.
1093 /// `get()` has the signature:
1094 /// `static const ast::Type* get(Types* t)`
1095 template <typename T>
1096 struct CToAST {};
1097 };
1098
1099 //////////////////////////////////////////////////////////////////////////////
1100 // AST helper methods
1101 //////////////////////////////////////////////////////////////////////////////
1102
1103 /// @return a new unnamed symbol
1104 Symbol Sym() { return Symbols().New(); }
1105
1106 /// @param name the symbol string
1107 /// @return a Symbol with the given name
1108 Symbol Sym(const std::string& name) { return Symbols().Register(name); }
1109
1110 /// @param sym the symbol
1111 /// @return `sym`
1112 Symbol Sym(Symbol sym) { return sym; }
1113
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001114 /// @param source the source information
1115 /// @param identifier the identifier symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001116 /// @param args optional templated identifier arguments
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001117 /// @return an ast::Identifier with the given symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001118 template <typename IDENTIFIER, typename... ARGS>
1119 const auto* Ident(const Source& source, IDENTIFIER&& identifier, ARGS&&... args) {
1120 Symbol sym = Sym(std::forward<IDENTIFIER>(identifier));
1121 if constexpr (sizeof...(args) > 0) {
1122 return create<ast::TemplatedIdentifier>(source, sym,
1123 ExprList(std::forward<ARGS>(args)...));
1124 } else {
1125 return create<ast::Identifier>(source, sym);
1126 }
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001127 }
1128
1129 /// @param identifier the identifier symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001130 /// @param args optional templated identifier arguments
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001131 /// @return an ast::Identifier with the given symbol
Ben Clayton2cdf1342023-02-03 13:24:18 +00001132 template <typename IDENTIFIER, typename... ARGS, typename = DisableIfSource<IDENTIFIER>>
1133 const auto* Ident(IDENTIFIER&& identifier, ARGS&&... args) {
1134 if constexpr (traits::IsTypeOrDerived<traits::PtrElTy<IDENTIFIER>, ast::Identifier>) {
1135 static_assert(sizeof...(args) == 0);
Ben Clayton999db742023-02-02 15:16:28 +00001136 return identifier; // Pass-through
1137 } else {
Ben Clayton2cdf1342023-02-03 13:24:18 +00001138 return Ident(source_, std::forward<IDENTIFIER>(identifier),
1139 std::forward<ARGS>(args)...);
Ben Clayton999db742023-02-02 15:16:28 +00001140 }
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001141 }
1142
dan sinclair41e4d9a2022-05-01 14:40:55 +00001143 /// @param expr the expression
1144 /// @return expr
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001145 template <typename T>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001146 traits::EnableIfIsType<T, ast::Expression>* Expr(T* expr) {
1147 return expr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001148 }
1149
dan sinclair41e4d9a2022-05-01 14:40:55 +00001150 /// Passthrough for nullptr
1151 /// @return nullptr
1152 const ast::IdentifierExpression* Expr(std::nullptr_t) { return nullptr; }
1153
1154 /// @param source the source information
1155 /// @param symbol the identifier symbol
1156 /// @return an ast::IdentifierExpression with the given symbol
1157 const ast::IdentifierExpression* Expr(const Source& source, Symbol symbol) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001158 return create<ast::IdentifierExpression>(source, Ident(source, symbol));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001159 }
1160
dan sinclair41e4d9a2022-05-01 14:40:55 +00001161 /// @param symbol the identifier symbol
1162 /// @return an ast::IdentifierExpression with the given symbol
1163 const ast::IdentifierExpression* Expr(Symbol symbol) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001164 return create<ast::IdentifierExpression>(Ident(symbol));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001165 }
1166
dan sinclair41e4d9a2022-05-01 14:40:55 +00001167 /// @param source the source information
1168 /// @param name the identifier name
1169 /// @return an ast::IdentifierExpression with the given name
1170 const ast::IdentifierExpression* Expr(const Source& source, const char* name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001171 return create<ast::IdentifierExpression>(source, Ident(source, name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001172 }
1173
dan sinclair41e4d9a2022-05-01 14:40:55 +00001174 /// @param name the identifier name
1175 /// @return an ast::IdentifierExpression with the given name
1176 const ast::IdentifierExpression* Expr(const char* name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001177 return create<ast::IdentifierExpression>(Ident(name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001178 }
1179
dan sinclair41e4d9a2022-05-01 14:40:55 +00001180 /// @param source the source information
1181 /// @param name the identifier name
1182 /// @return an ast::IdentifierExpression with the given name
1183 const ast::IdentifierExpression* Expr(const Source& source, const std::string& name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001184 return create<ast::IdentifierExpression>(source, Ident(source, name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001185 }
1186
dan sinclair41e4d9a2022-05-01 14:40:55 +00001187 /// @param name the identifier name
1188 /// @return an ast::IdentifierExpression with the given name
1189 const ast::IdentifierExpression* Expr(const std::string& name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001190 return create<ast::IdentifierExpression>(Ident(name));
1191 }
1192
1193 /// @param source the source information
1194 /// @param variable the AST variable
1195 /// @return an ast::IdentifierExpression with the variable's symbol
1196 const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001197 return create<ast::IdentifierExpression>(source, Ident(source, variable->name->symbol));
Ben Clayton6cba18b2023-02-02 20:37:19 +00001198 }
1199
1200 /// @param variable the AST variable
1201 /// @return an ast::IdentifierExpression with the variable's symbol
1202 const ast::IdentifierExpression* Expr(const ast::Variable* variable) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001203 return create<ast::IdentifierExpression>(Ident(variable->name->symbol));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001204 }
1205
Ben Clayton2cdf1342023-02-03 13:24:18 +00001206 /// @param ident the identifier
1207 /// @return an ast::IdentifierExpression with the given identifier
1208 template <typename IDENTIFIER, typename = traits::EnableIfIsType<IDENTIFIER, ast::Identifier>>
1209 const ast::IdentifierExpression* Expr(const IDENTIFIER* ident) {
Ben Clayton2cdf1342023-02-03 13:24:18 +00001210 return create<ast::IdentifierExpression>(ident);
1211 }
1212
dan sinclair41e4d9a2022-05-01 14:40:55 +00001213 /// @param source the source information
1214 /// @param value the boolean value
1215 /// @return a Scalar constructor for the given value
Ben Clayton17fa42d2022-05-10 15:29:14 +00001216 template <typename BOOL>
1217 std::enable_if_t<std::is_same_v<BOOL, bool>, const ast::BoolLiteralExpression*> Expr(
1218 const Source& source,
1219 BOOL value) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001220 return create<ast::BoolLiteralExpression>(source, value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001221 }
1222
dan sinclair41e4d9a2022-05-01 14:40:55 +00001223 /// @param value the boolean value
1224 /// @return a Scalar constructor for the given value
Ben Clayton17fa42d2022-05-10 15:29:14 +00001225 template <typename BOOL>
1226 std::enable_if_t<std::is_same_v<BOOL, bool>, const ast::BoolLiteralExpression*> Expr(
1227 BOOL value) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001228 return create<ast::BoolLiteralExpression>(value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001229 }
1230
dan sinclair41e4d9a2022-05-01 14:40:55 +00001231 /// @param source the source information
1232 /// @param value the float value
Ben Clayton41285aa2022-05-10 14:55:34 +00001233 /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value
1234 const ast::FloatLiteralExpression* Expr(const Source& source, f32 value) {
1235 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1236 ast::FloatLiteralExpression::Suffix::kF);
1237 }
1238
1239 /// @param value the float value
1240 /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value
dan sinclair41e4d9a2022-05-01 14:40:55 +00001241 const ast::FloatLiteralExpression* Expr(f32 value) {
Ben Clayton41285aa2022-05-10 14:55:34 +00001242 return create<ast::FloatLiteralExpression>(static_cast<double>(value.value),
1243 ast::FloatLiteralExpression::Suffix::kF);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001244 }
1245
dan sinclair41e4d9a2022-05-01 14:40:55 +00001246 /// @param source the source information
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00001247 /// @param value the float value
1248 /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
1249 const ast::FloatLiteralExpression* Expr(const Source& source, f16 value) {
1250 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1251 ast::FloatLiteralExpression::Suffix::kH);
1252 }
1253
1254 /// @param value the float value
1255 /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
1256 const ast::FloatLiteralExpression* Expr(f16 value) {
1257 return create<ast::FloatLiteralExpression>(static_cast<double>(value.value),
1258 ast::FloatLiteralExpression::Suffix::kH);
1259 }
1260
1261 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001262 /// @param value the integer value
Ben Clayton508e4a52022-05-10 22:08:04 +00001263 /// @return an unsuffixed IntLiteralExpression for the AInt value
1264 const ast::IntLiteralExpression* Expr(const Source& source, AInt value) {
1265 return create<ast::IntLiteralExpression>(source, value,
1266 ast::IntLiteralExpression::Suffix::kNone);
1267 }
1268
1269 /// @param value the integer value
1270 /// @return an unsuffixed IntLiteralExpression for the AInt value
1271 const ast::IntLiteralExpression* Expr(AInt value) {
1272 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kNone);
1273 }
1274
1275 /// @param source the source information
1276 /// @param value the integer value
1277 /// @return an unsuffixed FloatLiteralExpression for the AFloat value
1278 const ast::FloatLiteralExpression* Expr(const Source& source, AFloat value) {
1279 return create<ast::FloatLiteralExpression>(source, value.value,
1280 ast::FloatLiteralExpression::Suffix::kNone);
1281 }
1282
1283 /// @param value the integer value
1284 /// @return an unsuffixed FloatLiteralExpression for the AFloat value
1285 const ast::FloatLiteralExpression* Expr(AFloat value) {
1286 return create<ast::FloatLiteralExpression>(value.value,
1287 ast::FloatLiteralExpression::Suffix::kNone);
1288 }
1289
1290 /// @param source the source information
1291 /// @param value the integer value
Ben Clayton41285aa2022-05-10 14:55:34 +00001292 /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001293 const ast::IntLiteralExpression* Expr(const Source& source, i32 value) {
1294 return create<ast::IntLiteralExpression>(source, value,
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001295 ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001296 }
1297
dan sinclair41e4d9a2022-05-01 14:40:55 +00001298 /// @param value the integer value
Ben Clayton41285aa2022-05-10 14:55:34 +00001299 /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001300 const ast::IntLiteralExpression* Expr(i32 value) {
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001301 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001302 }
1303
dan sinclair41e4d9a2022-05-01 14:40:55 +00001304 /// @param source the source information
1305 /// @param value the unsigned int value
Ben Clayton41285aa2022-05-10 14:55:34 +00001306 /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001307 const ast::IntLiteralExpression* Expr(const Source& source, u32 value) {
1308 return create<ast::IntLiteralExpression>(source, value,
1309 ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001310 }
1311
dan sinclair41e4d9a2022-05-01 14:40:55 +00001312 /// @param value the unsigned int value
Ben Clayton41285aa2022-05-10 14:55:34 +00001313 /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001314 const ast::IntLiteralExpression* Expr(u32 value) {
1315 return create<ast::IntLiteralExpression>(value, ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001316 }
1317
dan sinclair41e4d9a2022-05-01 14:40:55 +00001318 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
1319 /// `list`.
1320 /// @param list the list to append too
1321 /// @param arg the arg to create
Ben Clayton783b1692022-08-02 17:03:35 +00001322 template <size_t N, typename ARG>
1323 void Append(utils::Vector<const ast::Expression*, N>& list, ARG&& arg) {
1324 list.Push(Expr(std::forward<ARG>(arg)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001325 }
1326
dan sinclair41e4d9a2022-05-01 14:40:55 +00001327 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
1328 /// then appends them to `list`.
1329 /// @param list the list to append too
1330 /// @param arg0 the first argument
1331 /// @param args the rest of the arguments
Ben Clayton783b1692022-08-02 17:03:35 +00001332 template <size_t N, typename ARG0, typename... ARGS>
1333 void Append(utils::Vector<const ast::Expression*, N>& list, ARG0&& arg0, ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001334 Append(list, std::forward<ARG0>(arg0));
1335 Append(list, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001336 }
1337
Ben Clayton783b1692022-08-02 17:03:35 +00001338 /// @return utils::EmptyType
1339 utils::EmptyType ExprList() { return utils::Empty; }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001340
1341 /// @param args the list of expressions
1342 /// @return the list of expressions converted to `ast::Expression`s using
1343 /// `Expr()`,
Ben Clayton783b1692022-08-02 17:03:35 +00001344 template <typename... ARGS, typename = DisableIfVectorLike<ARGS...>>
1345 auto ExprList(ARGS&&... args) {
1346 utils::Vector<const ast::Expression*, sizeof...(ARGS)> list;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001347 Append(list, std::forward<ARGS>(args)...);
1348 return list;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001349 }
1350
dan sinclair41e4d9a2022-05-01 14:40:55 +00001351 /// @param list the list of expressions
1352 /// @return `list`
Ben Clayton783b1692022-08-02 17:03:35 +00001353 template <typename T, size_t N>
1354 utils::Vector<T, N> ExprList(utils::Vector<T, N>&& list) {
1355 return std::move(list);
1356 }
1357
1358 /// @param list the list of expressions
1359 /// @return `list`
1360 utils::VectorRef<const ast::Expression*> ExprList(
1361 utils::VectorRef<const ast::Expression*> list) {
1362 return list;
1363 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001364
dan sinclair41e4d9a2022-05-01 14:40:55 +00001365 /// @param expr the expression for the bitcast
1366 /// @return an `ast::BitcastExpression` of type `ty`, with the values of
1367 /// `expr` converted to `ast::Expression`s using `Expr()`
1368 template <typename T, typename EXPR>
1369 const ast::BitcastExpression* Bitcast(EXPR&& expr) {
1370 return Bitcast(ty.Of<T>(), std::forward<EXPR>(expr));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001371 }
1372
dan sinclair41e4d9a2022-05-01 14:40:55 +00001373 /// @param type the type to cast to
1374 /// @param expr the expression for the bitcast
1375 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1376 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001377 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001378 const ast::BitcastExpression* Bitcast(const ast::Type* type, EXPR&& expr) {
1379 return create<ast::BitcastExpression>(type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001380 }
1381
dan sinclair41e4d9a2022-05-01 14:40:55 +00001382 /// @param source the source information
1383 /// @param type the type to cast to
1384 /// @param expr the expression for the bitcast
1385 /// @return an `ast::BitcastExpression` of `type` constructed with the values
1386 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001387 template <typename EXPR>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001388 const ast::BitcastExpression* Bitcast(const Source& source,
1389 const ast::Type* type,
1390 EXPR&& expr) {
1391 return create<ast::BitcastExpression>(source, type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001392 }
1393
dan sinclair6e77b472022-10-20 13:38:28 +00001394 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001395 /// @param type the vector type
1396 /// @param size the vector size
1397 /// @return an `ast::CallExpression` of a `size`-element vector of
1398 /// type `type`, constructed with the values `args`.
1399 template <typename... ARGS>
1400 const ast::CallExpression* vec(const ast::Type* type, uint32_t size, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001401 return Call(ty.vec(type, size), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001402 }
1403
dan sinclair6e77b472022-10-20 13:38:28 +00001404 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001405 /// @return an `ast::CallExpression` of a 2-element vector of type
1406 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001407 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001408 const ast::CallExpression* vec2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001409 return Call(ty.vec2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001410 }
1411
Ben Clayton6315a272022-08-01 17:18:04 +00001412 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001413 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001414 /// @return an `ast::CallExpression` of a 2-element vector of type
1415 /// `T`, constructed with the values `args`.
1416 template <typename T, typename... ARGS>
1417 const ast::CallExpression* vec2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001418 return Call(source, ty.vec2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001419 }
1420
dan sinclair6e77b472022-10-20 13:38:28 +00001421 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001422 /// @return an `ast::CallExpression` of a 3-element vector of type
1423 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001424 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001425 const ast::CallExpression* vec3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001426 return Call(ty.vec3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001427 }
1428
Ben Clayton6315a272022-08-01 17:18:04 +00001429 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001430 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001431 /// @return an `ast::CallExpression` of a 3-element vector of type
1432 /// `T`, constructed with the values `args`.
1433 template <typename T, typename... ARGS>
1434 const ast::CallExpression* vec3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001435 return Call(source, ty.vec3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001436 }
1437
dan sinclair6e77b472022-10-20 13:38:28 +00001438 /// @param args the arguments for the vector initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001439 /// @return an `ast::CallExpression` of a 4-element vector of type
1440 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001441 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001442 const ast::CallExpression* vec4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001443 return Call(ty.vec4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001444 }
1445
Ben Clayton6315a272022-08-01 17:18:04 +00001446 /// @param source the vector source
dan sinclair6e77b472022-10-20 13:38:28 +00001447 /// @param args the arguments for the vector initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001448 /// @return an `ast::CallExpression` of a 4-element vector of type
1449 /// `T`, constructed with the values `args`.
1450 template <typename T, typename... ARGS>
1451 const ast::CallExpression* vec4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001452 return Call(source, ty.vec4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001453 }
1454
dan sinclair6e77b472022-10-20 13:38:28 +00001455 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001456 /// @return an `ast::CallExpression` of a 2x2 matrix of type
1457 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001458 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001459 const ast::CallExpression* mat2x2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001460 return Call(ty.mat2x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001461 }
1462
Ben Clayton6315a272022-08-01 17:18:04 +00001463 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001464 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001465 /// @return an `ast::CallExpression` of a 2x2 matrix of type
1466 /// `T`, constructed with the values `args`.
1467 template <typename T, typename... ARGS>
1468 const ast::CallExpression* mat2x2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001469 return Call(source, ty.mat2x2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001470 }
1471
dan sinclair6e77b472022-10-20 13:38:28 +00001472 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001473 /// @return an `ast::CallExpression` of a 2x3 matrix of type
1474 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001475 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001476 const ast::CallExpression* mat2x3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001477 return Call(ty.mat2x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001478 }
1479
Ben Clayton6315a272022-08-01 17:18:04 +00001480 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001481 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001482 /// @return an `ast::CallExpression` of a 2x3 matrix of type
1483 /// `T`, constructed with the values `args`.
1484 template <typename T, typename... ARGS>
1485 const ast::CallExpression* mat2x3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001486 return Call(source, ty.mat2x3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001487 }
1488
dan sinclair6e77b472022-10-20 13:38:28 +00001489 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001490 /// @return an `ast::CallExpression` of a 2x4 matrix of type
1491 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001492 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001493 const ast::CallExpression* mat2x4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001494 return Call(ty.mat2x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001495 }
1496
Ben Clayton6315a272022-08-01 17:18:04 +00001497 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001498 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001499 /// @return an `ast::CallExpression` of a 2x4 matrix of type
1500 /// `T`, constructed with the values `args`.
1501 template <typename T, typename... ARGS>
1502 const ast::CallExpression* mat2x4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001503 return Call(source, ty.mat2x4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001504 }
1505
dan sinclair6e77b472022-10-20 13:38:28 +00001506 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001507 /// @return an `ast::CallExpression` of a 3x2 matrix of type
1508 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001509 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001510 const ast::CallExpression* mat3x2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001511 return Call(ty.mat3x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001512 }
1513
Ben Clayton6315a272022-08-01 17:18:04 +00001514 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001515 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001516 /// @return an `ast::CallExpression` of a 3x2 matrix of type
1517 /// `T`, constructed with the values `args`.
1518 template <typename T, typename... ARGS>
1519 const ast::CallExpression* mat3x2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001520 return Call(source, ty.mat3x2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001521 }
1522
dan sinclair6e77b472022-10-20 13:38:28 +00001523 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001524 /// @return an `ast::CallExpression` of a 3x3 matrix of type
1525 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001526 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001527 const ast::CallExpression* mat3x3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001528 return Call(ty.mat3x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001529 }
1530
Ben Clayton6315a272022-08-01 17:18:04 +00001531 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001532 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001533 /// @return an `ast::CallExpression` of a 3x3 matrix of type
1534 /// `T`, constructed with the values `args`.
1535 template <typename T, typename... ARGS>
1536 const ast::CallExpression* mat3x3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001537 return Call(source, ty.mat3x3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001538 }
1539
dan sinclair6e77b472022-10-20 13:38:28 +00001540 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001541 /// @return an `ast::CallExpression` of a 3x4 matrix of type
1542 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001543 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001544 const ast::CallExpression* mat3x4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001545 return Call(ty.mat3x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001546 }
1547
Ben Clayton6315a272022-08-01 17:18:04 +00001548 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001549 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001550 /// @return an `ast::CallExpression` of a 3x4 matrix of type
1551 /// `T`, constructed with the values `args`.
1552 template <typename T, typename... ARGS>
1553 const ast::CallExpression* mat3x4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001554 return Call(source, ty.mat3x4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001555 }
1556
dan sinclair6e77b472022-10-20 13:38:28 +00001557 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001558 /// @return an `ast::CallExpression` of a 4x2 matrix of type
1559 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001560 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001561 const ast::CallExpression* mat4x2(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001562 return Call(ty.mat4x2<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001563 }
1564
Ben Clayton6315a272022-08-01 17:18:04 +00001565 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001566 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001567 /// @return an `ast::CallExpression` of a 4x2 matrix of type
1568 /// `T`, constructed with the values `args`.
1569 template <typename T, typename... ARGS>
1570 const ast::CallExpression* mat4x2(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001571 return Call(source, ty.mat4x2<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001572 }
1573
dan sinclair6e77b472022-10-20 13:38:28 +00001574 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001575 /// @return an `ast::CallExpression` of a 4x3 matrix of type
1576 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001577 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001578 const ast::CallExpression* mat4x3(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001579 return Call(ty.mat4x3<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001580 }
1581
Ben Clayton6315a272022-08-01 17:18:04 +00001582 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001583 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001584 /// @return an `ast::CallExpression` of a 4x3 matrix of type
1585 /// `T`, constructed with the values `args`.
1586 template <typename T, typename... ARGS>
1587 const ast::CallExpression* mat4x3(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001588 return Call(source, ty.mat4x3<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001589 }
1590
dan sinclair6e77b472022-10-20 13:38:28 +00001591 /// @param args the arguments for the matrix initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001592 /// @return an `ast::CallExpression` of a 4x4 matrix of type
1593 /// `T`, constructed with the values `args`.
Ben Clayton6315a272022-08-01 17:18:04 +00001594 template <typename T, typename... ARGS, typename _ = DisableIfSource<ARGS...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00001595 const ast::CallExpression* mat4x4(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001596 return Call(ty.mat4x4<T>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001597 }
1598
Ben Clayton6315a272022-08-01 17:18:04 +00001599 /// @param source the matrix source
dan sinclair6e77b472022-10-20 13:38:28 +00001600 /// @param args the arguments for the matrix initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001601 /// @return an `ast::CallExpression` of a 4x4 matrix of type
1602 /// `T`, constructed with the values `args`.
1603 template <typename T, typename... ARGS>
1604 const ast::CallExpression* mat4x4(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001605 return Call(source, ty.mat4x4<T>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001606 }
1607
dan sinclair6e77b472022-10-20 13:38:28 +00001608 /// @param args the arguments for the array initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001609 /// @return an `ast::CallExpression` of an array with element type
1610 /// `T` and size `N`, constructed with the values `args`.
1611 template <typename T, int N, typename... ARGS>
1612 const ast::CallExpression* array(ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001613 return Call(ty.array<T, N>(), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001614 }
1615
Ben Clayton6315a272022-08-01 17:18:04 +00001616 /// @param source the array source
dan sinclair6e77b472022-10-20 13:38:28 +00001617 /// @param args the arguments for the array initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001618 /// @return an `ast::CallExpression` of an array with element type
1619 /// `T` and size `N`, constructed with the values `args`.
1620 template <typename T, int N, typename... ARGS>
1621 const ast::CallExpression* array(const Source& source, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001622 return Call(source, ty.array<T, N>(), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001623 }
1624
dan sinclair41e4d9a2022-05-01 14:40:55 +00001625 /// @param subtype the array element type
1626 /// @param n the array size. nullptr represents a runtime-array.
dan sinclair6e77b472022-10-20 13:38:28 +00001627 /// @param args the arguments for the array initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001628 /// @return an `ast::CallExpression` of an array with element type
1629 /// `subtype`, constructed with the values `args`.
1630 template <typename EXPR, typename... ARGS>
1631 const ast::CallExpression* array(const ast::Type* subtype, EXPR&& n, ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001632 return Call(ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001633 }
1634
Ben Clayton6315a272022-08-01 17:18:04 +00001635 /// @param source the array source
1636 /// @param subtype the array element type
1637 /// @param n the array size. nullptr represents a runtime-array.
dan sinclair6e77b472022-10-20 13:38:28 +00001638 /// @param args the arguments for the array initializer
Ben Clayton6315a272022-08-01 17:18:04 +00001639 /// @return an `ast::CallExpression` of an array with element type
1640 /// `subtype`, constructed with the values `args`.
1641 template <typename EXPR, typename... ARGS>
1642 const ast::CallExpression* array(const Source& source,
1643 const ast::Type* subtype,
1644 EXPR&& n,
1645 ARGS&&... args) {
Ben Clayton01ac21c2023-02-07 16:14:25 +00001646 return Call(source, ty.array(subtype, std::forward<EXPR>(n)), std::forward<ARGS>(args)...);
Ben Clayton6315a272022-08-01 17:18:04 +00001647 }
1648
Ben Clayton7f2b8cd2022-05-18 22:41:48 +00001649 /// Adds the extension to the list of enable directives at the top of the module.
1650 /// @param ext the extension to enable
1651 /// @return an `ast::Enable` enabling the given extension.
1652 const ast::Enable* Enable(ast::Extension ext) {
1653 auto* enable = create<ast::Enable>(ext);
1654 AST().AddEnable(enable);
1655 return enable;
1656 }
1657
Ben Clayton1a567782022-10-14 13:38:27 +00001658 /// Adds the extension to the list of enable directives at the top of the module.
1659 /// @param source the enable source
1660 /// @param ext the extension to enable
1661 /// @return an `ast::Enable` enabling the given extension.
1662 const ast::Enable* Enable(const Source& source, ast::Extension ext) {
1663 auto* enable = create<ast::Enable>(source, ext);
1664 AST().AddEnable(enable);
1665 return enable;
1666 }
1667
dan sinclair41e4d9a2022-05-01 14:40:55 +00001668 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001669 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001670 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001671 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001672 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001673 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001674 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001675 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1676 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001677 /// @returns a `ast::Var` with the given name, type and additional
dan sinclair41e4d9a2022-05-01 14:40:55 +00001678 /// options
Ben Clayton58794ae2022-08-19 17:28:53 +00001679 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1680 const ast::Var* Var(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001681 return Var(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001682 }
1683
dan sinclair41e4d9a2022-05-01 14:40:55 +00001684 /// @param source the variable source
1685 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001686 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001687 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001688 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001689 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001690 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001691 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001692 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1693 /// Note that non-repeatable arguments of the same type will use the last argument's value.
dan sinclairff7cf212022-10-03 14:05:23 +00001694 /// @returns a `ast::Var` with the given name, address_space and type
Ben Clayton58794ae2022-08-19 17:28:53 +00001695 template <typename NAME, typename... OPTIONS>
1696 const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) {
1697 VarOptions opts(std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001698 return create<ast::Var>(source, Ident(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001699 opts.address_space, opts.access, opts.initializer,
dan sinclairff7cf212022-10-03 14:05:23 +00001700 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001701 }
1702
1703 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001704 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001705 /// Can be any of the following, in any order:
1706 /// * ast::Expression* - specifies the variable's initializer expression (required)
1707 /// * ast::Type* - specifies the variable type
1708 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1709 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1710 /// @returns an `ast::Const` with the given name, type and additional options
1711 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1712 const ast::Const* Const(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001713 return Const(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
Ben Claytone3834c42022-06-25 23:21:39 +00001714 }
1715
1716 /// @param source the variable source
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>
1726 const ast::Const* Const(const Source& source, NAME&& name, OPTIONS&&... options) {
1727 ConstOptions opts(std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001728 return create<ast::Const>(source, Ident(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001729 opts.initializer, std::move(opts.attributes));
Ben Claytone3834c42022-06-25 23:21:39 +00001730 }
1731
1732 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001733 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001734 /// Can be any of the following, in any order:
1735 /// * ast::Expression* - specifies the variable's initializer expression (required)
1736 /// * ast::Type* - specifies the variable type
1737 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1738 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1739 /// @returns an `ast::Let` with the given name, type and additional options
1740 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1741 const ast::Let* Let(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001742 return Let(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001743 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001744
dan sinclair41e4d9a2022-05-01 14:40:55 +00001745 /// @param source the variable source
1746 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001747 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001748 /// Can be any of the following, in any order:
1749 /// * ast::Expression* - specifies the variable's initializer expression (required)
1750 /// * ast::Type* - specifies the variable type
1751 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1752 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1753 /// @returns an `ast::Let` with the given name, type and additional options
1754 template <typename NAME, typename... OPTIONS>
1755 const ast::Let* Let(const Source& source, NAME&& name, OPTIONS&&... options) {
1756 LetOptions opts(std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001757 return create<ast::Let>(source, Ident(std::forward<NAME>(name)), opts.type,
1758 opts.initializer, std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001759 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001760
dan sinclair41e4d9a2022-05-01 14:40:55 +00001761 /// @param name the parameter name
1762 /// @param type the parameter type
1763 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001764 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001765 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001766 const ast::Parameter* Param(NAME&& name,
1767 const ast::Type* type,
Ben Clayton783b1692022-08-02 17:03:35 +00001768 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001769 return Param(source_, std::forward<NAME>(name), type, std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001770 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001771
dan sinclair41e4d9a2022-05-01 14:40:55 +00001772 /// @param source the parameter source
1773 /// @param name the parameter name
1774 /// @param type the parameter type
1775 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001776 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001777 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001778 const ast::Parameter* Param(const Source& source,
1779 NAME&& name,
1780 const ast::Type* type,
Ben Clayton783b1692022-08-02 17:03:35 +00001781 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001782 return create<ast::Parameter>(source, Ident(std::forward<NAME>(name)), type, attributes);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001783 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001784
dan sinclair41e4d9a2022-05-01 14:40:55 +00001785 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001786 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001787 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001788 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001789 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001790 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001791 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001792 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1793 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001794 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1795 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001796 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1797 const ast::Var* GlobalVar(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001798 return GlobalVar(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001799 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001800
dan sinclair41e4d9a2022-05-01 14:40:55 +00001801 /// @param source the variable source
1802 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001803 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001804 /// Can be any of the following, in any order:
Ben Clayton58794ae2022-08-19 17:28:53 +00001805 /// * ast::Type* - specifies the variable type
dan sinclair18b21582023-01-21 19:56:49 +00001806 /// * type::AddressSpace - specifies the variable address space
dan sinclair61c16eb2023-01-21 23:44:38 +00001807 /// * type::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001808 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001809 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1810 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001811 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1812 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001813 template <typename NAME, typename... OPTIONS>
1814 const ast::Var* GlobalVar(const Source& source, NAME&& name, OPTIONS&&... options) {
1815 auto* variable = Var(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1816 AST().AddGlobalVariable(variable);
1817 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001818 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001819
dan sinclair41e4d9a2022-05-01 14:40:55 +00001820 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001821 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001822 /// Can be any of the following, in any order:
1823 /// * ast::Expression* - specifies the variable's initializer expression (required)
1824 /// * ast::Type* - specifies the variable type
1825 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1826 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1827 /// @returns an `ast::Const` with the given name, type and additional options, which is
1828 /// automatically registered as a global variable with the ast::Module.
1829 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1830 const ast::Const* GlobalConst(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001831 return GlobalConst(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
Ben Claytone3834c42022-06-25 23:21:39 +00001832 }
1833
1834 /// @param source the variable source
1835 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001836 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001837 /// Can be any of the following, in any order:
1838 /// * ast::Expression* - specifies the variable's initializer expression (required)
1839 /// * ast::Type* - specifies the variable type
1840 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1841 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1842 /// @returns an `ast::Const` with the given name, type and additional options, which is
1843 /// automatically registered as a global variable with the ast::Module.
1844 template <typename NAME, typename... OPTIONS>
1845 const ast::Const* GlobalConst(const Source& source, NAME&& name, OPTIONS&&... options) {
1846 auto* variable = Const(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1847 AST().AddGlobalVariable(variable);
1848 return variable;
Ben Claytone3834c42022-06-25 23:21:39 +00001849 }
1850
1851 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001852 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001853 /// Can be any of the following, in any order:
1854 /// * ast::Expression* - specifies the variable's initializer expression (required)
1855 /// * ast::Type* - specifies the variable type
1856 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1857 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1858 /// @returns an `ast::Override` with the given name, type and additional options, which is
1859 /// automatically registered as a global variable with the ast::Module.
1860 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1861 const ast::Override* Override(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001862 return Override(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001863 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001864
dan sinclair41e4d9a2022-05-01 14:40:55 +00001865 /// @param source the variable source
1866 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001867 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001868 /// Can be any of the following, in any order:
1869 /// * ast::Expression* - specifies the variable's initializer expression (required)
1870 /// * ast::Type* - specifies the variable type
1871 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1872 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1873 /// @returns an `ast::Override` with the given name, type and additional options, which is
1874 /// automatically registered as a global variable with the ast::Module.
1875 template <typename NAME, typename... OPTIONS>
1876 const ast::Override* Override(const Source& source, NAME&& name, OPTIONS&&... options) {
1877 OverrideOptions opts(std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001878 auto* variable = create<ast::Override>(source, Ident(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001879 opts.initializer, std::move(opts.attributes));
Ben Clayton58794ae2022-08-19 17:28:53 +00001880 AST().AddGlobalVariable(variable);
1881 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001882 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001883
dan sinclair41e4d9a2022-05-01 14:40:55 +00001884 /// @param source the source information
Ben Claytonbfd1a812022-08-02 23:16:25 +00001885 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001886 /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement
Ben Claytonbfd1a812022-08-02 23:16:25 +00001887 /// with the ast::Module.
1888 template <typename EXPR>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001889 const ast::ConstAssert* GlobalConstAssert(const Source& source, EXPR&& condition) {
1890 auto* sa = ConstAssert(source, std::forward<EXPR>(condition));
1891 AST().AddConstAssert(sa);
Ben Claytonbfd1a812022-08-02 23:16:25 +00001892 return sa;
1893 }
1894
1895 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001896 /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement
Ben Claytonbfd1a812022-08-02 23:16:25 +00001897 /// with the ast::Module.
1898 template <typename EXPR, typename = DisableIfSource<EXPR>>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001899 const ast::ConstAssert* GlobalConstAssert(EXPR&& condition) {
1900 auto* sa = ConstAssert(std::forward<EXPR>(condition));
1901 AST().AddConstAssert(sa);
Ben Claytonbfd1a812022-08-02 23:16:25 +00001902 return sa;
1903 }
1904
1905 /// @param source the source information
1906 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001907 /// @returns a new `ast::ConstAssert` with the given assertion condition
Ben Claytonbfd1a812022-08-02 23:16:25 +00001908 template <typename EXPR>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001909 const ast::ConstAssert* ConstAssert(const Source& source, EXPR&& condition) {
1910 return create<ast::ConstAssert>(source, Expr(std::forward<EXPR>(condition)));
Ben Claytonbfd1a812022-08-02 23:16:25 +00001911 }
1912
1913 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001914 /// @returns a new `ast::ConstAssert` with the given assertion condition
Ben Claytonbfd1a812022-08-02 23:16:25 +00001915 template <typename EXPR, typename = DisableIfSource<EXPR>>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001916 const ast::ConstAssert* ConstAssert(EXPR&& condition) {
1917 return create<ast::ConstAssert>(Expr(std::forward<EXPR>(condition)));
Ben Claytonbfd1a812022-08-02 23:16:25 +00001918 }
1919
1920 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001921 /// @param expr the expression to take the address of
1922 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1923 template <typename EXPR>
1924 const ast::UnaryOpExpression* AddressOf(const Source& source, EXPR&& expr) {
1925 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kAddressOf,
1926 Expr(std::forward<EXPR>(expr)));
1927 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001928
dan sinclair41e4d9a2022-05-01 14:40:55 +00001929 /// @param expr the expression to take the address of
1930 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1931 template <typename EXPR>
1932 const ast::UnaryOpExpression* AddressOf(EXPR&& expr) {
1933 return create<ast::UnaryOpExpression>(ast::UnaryOp::kAddressOf,
1934 Expr(std::forward<EXPR>(expr)));
1935 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001936
dan sinclair41e4d9a2022-05-01 14:40:55 +00001937 /// @param source the source information
1938 /// @param expr the expression to perform an indirection on
1939 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1940 template <typename EXPR>
1941 const ast::UnaryOpExpression* Deref(const Source& source, EXPR&& expr) {
1942 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kIndirection,
1943 Expr(std::forward<EXPR>(expr)));
1944 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001945
dan sinclair41e4d9a2022-05-01 14:40:55 +00001946 /// @param expr the expression to perform an indirection on
1947 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1948 template <typename EXPR>
1949 const ast::UnaryOpExpression* Deref(EXPR&& expr) {
1950 return create<ast::UnaryOpExpression>(ast::UnaryOp::kIndirection,
1951 Expr(std::forward<EXPR>(expr)));
1952 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001953
dan sinclair41e4d9a2022-05-01 14:40:55 +00001954 /// @param expr the expression to perform a unary not on
1955 /// @return an ast::UnaryOpExpression that is the unary not of the input
1956 /// expression
1957 template <typename EXPR>
1958 const ast::UnaryOpExpression* Not(EXPR&& expr) {
1959 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(std::forward<EXPR>(expr)));
1960 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001961
Antonio Maiorano28779af2022-12-09 21:28:51 +00001962 /// @param source the source information
1963 /// @param expr the expression to perform a unary not on
1964 /// @return an ast::UnaryOpExpression that is the unary not of the input
1965 /// expression
1966 template <typename EXPR>
1967 const ast::UnaryOpExpression* Not(const Source& source, EXPR&& expr) {
1968 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kNot,
1969 Expr(std::forward<EXPR>(expr)));
1970 }
1971
dan sinclair41e4d9a2022-05-01 14:40:55 +00001972 /// @param expr the expression to perform a unary complement on
1973 /// @return an ast::UnaryOpExpression that is the unary complement of the
1974 /// input expression
1975 template <typename EXPR>
1976 const ast::UnaryOpExpression* Complement(EXPR&& expr) {
1977 return create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement,
1978 Expr(std::forward<EXPR>(expr)));
1979 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001980
Author: Shiyu Liub3aab092022-05-04 13:07:29 +00001981 /// @param expr the expression to perform a unary negation on
1982 /// @return an ast::UnaryOpExpression that is the unary negation of the
1983 /// input expression
1984 template <typename EXPR>
1985 const ast::UnaryOpExpression* Negation(EXPR&& expr) {
1986 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation,
1987 Expr(std::forward<EXPR>(expr)));
1988 }
1989
Ben Clayton01ac21c2023-02-07 16:14:25 +00001990 /// @param target the call target
dan sinclair41e4d9a2022-05-01 14:40:55 +00001991 /// @param args the function call arguments
1992 /// @returns a `ast::CallExpression` to the function `func`, with the
1993 /// arguments of `args` converted to `ast::Expression`s using `Expr()`.
Ben Clayton01ac21c2023-02-07 16:14:25 +00001994 template <typename TARGET,
1995 typename... ARGS,
1996 typename = DisableIfSource<TARGET>,
1997 typename = DisableIfScalar<TARGET>>
1998 const ast::CallExpression* Call(TARGET&& target, ARGS&&... args) {
1999 return Call(source_, std::forward<TARGET>(target), std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002000 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002001
Ben Clayton01ac21c2023-02-07 16:14:25 +00002002 /// @param source the source information
2003 /// @param target the call target. Can be an ast::Type or ast::Identifier, or string-like.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002004 /// @param args the function call arguments
Ben Clayton01ac21c2023-02-07 16:14:25 +00002005 /// @returns a `ast::CallExpression` to the target @p target, with the arguments of @p args
2006 /// converted to `ast::Expression`s using Expr().
2007 template <typename TARGET, typename... ARGS, typename = DisableIfScalar<TARGET>>
2008 const ast::CallExpression* Call(const Source& source, TARGET&& target, ARGS&&... args) {
2009 if constexpr (traits::IsTypeOrDerived<traits::PtrElTy<TARGET>, ast::Type>) {
2010 return create<ast::CallExpression>(source, target,
2011 ExprList(std::forward<ARGS>(args)...));
2012
2013 } else {
2014 return create<ast::CallExpression>(source, Ident(target),
2015 ExprList(std::forward<ARGS>(args)...));
2016 }
2017 }
2018
2019 /// @param args the arguments for the type constructor
2020 /// @return an `ast::CallExpression` of type `ty`, with the values
2021 /// of `args` converted to `ast::Expression`s using `Expr()`
2022 template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
2023 const ast::CallExpression* Call(ARGS&&... args) {
2024 return Call(ty.Of<T>(), std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002025 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002026
dan sinclair41e4d9a2022-05-01 14:40:55 +00002027 /// @param source the source information
2028 /// @param call the call expression to wrap in a call statement
2029 /// @returns a `ast::CallStatement` for the given call expression
2030 const ast::CallStatement* CallStmt(const Source& source, const ast::CallExpression* call) {
2031 return create<ast::CallStatement>(source, call);
2032 }
James Pricec022ff52022-03-31 22:30:10 +00002033
dan sinclair41e4d9a2022-05-01 14:40:55 +00002034 /// @param call the call expression to wrap in a call statement
2035 /// @returns a `ast::CallStatement` for the given call expression
2036 const ast::CallStatement* CallStmt(const ast::CallExpression* call) {
2037 return create<ast::CallStatement>(call);
2038 }
James Pricec022ff52022-03-31 22:30:10 +00002039
dan sinclair41e4d9a2022-05-01 14:40:55 +00002040 /// @param source the source information
2041 /// @returns a `ast::PhonyExpression`
2042 const ast::PhonyExpression* Phony(const Source& source) {
2043 return create<ast::PhonyExpression>(source);
2044 }
James Priceebe97412022-04-07 13:42:45 +00002045
dan sinclair41e4d9a2022-05-01 14:40:55 +00002046 /// @returns a `ast::PhonyExpression`
2047 const ast::PhonyExpression* Phony() { return create<ast::PhonyExpression>(); }
James Priceebe97412022-04-07 13:42:45 +00002048
dan sinclair41e4d9a2022-05-01 14:40:55 +00002049 /// @param expr the expression to ignore
2050 /// @returns a `ast::AssignmentStatement` that assigns 'expr' to the phony
2051 /// (underscore) variable.
2052 template <typename EXPR>
2053 const ast::AssignmentStatement* Ignore(EXPR&& expr) {
2054 return create<ast::AssignmentStatement>(Phony(), Expr(expr));
2055 }
James Priceebe97412022-04-07 13:42:45 +00002056
dan sinclair41e4d9a2022-05-01 14:40:55 +00002057 /// @param lhs the left hand argument to the addition operation
2058 /// @param rhs the right hand argument to the addition operation
2059 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2060 template <typename LHS, typename RHS>
2061 const ast::BinaryExpression* Add(LHS&& lhs, RHS&& rhs) {
2062 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd, Expr(std::forward<LHS>(lhs)),
2063 Expr(std::forward<RHS>(rhs)));
2064 }
James Priceebe97412022-04-07 13:42:45 +00002065
Antonio Maiorano7058a172022-08-10 18:06:43 +00002066 /// @param source the source information
2067 /// @param lhs the left hand argument to the addition operation
2068 /// @param rhs the right hand argument to the addition operation
2069 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2070 template <typename LHS, typename RHS>
2071 const ast::BinaryExpression* Add(const Source& source, LHS&& lhs, RHS&& rhs) {
2072 return create<ast::BinaryExpression>(source, ast::BinaryOp::kAdd,
2073 Expr(std::forward<LHS>(lhs)),
2074 Expr(std::forward<RHS>(rhs)));
2075 }
2076
dan sinclair41e4d9a2022-05-01 14:40:55 +00002077 /// @param lhs the left hand argument to the and operation
2078 /// @param rhs the right hand argument to the and operation
2079 /// @returns a `ast::BinaryExpression` bitwise anding `lhs` and `rhs`
2080 template <typename LHS, typename RHS>
2081 const ast::BinaryExpression* And(LHS&& lhs, RHS&& rhs) {
2082 return create<ast::BinaryExpression>(ast::BinaryOp::kAnd, Expr(std::forward<LHS>(lhs)),
2083 Expr(std::forward<RHS>(rhs)));
2084 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002085
dan sinclair41e4d9a2022-05-01 14:40:55 +00002086 /// @param lhs the left hand argument to the or operation
2087 /// @param rhs the right hand argument to the or operation
2088 /// @returns a `ast::BinaryExpression` bitwise or-ing `lhs` and `rhs`
2089 template <typename LHS, typename RHS>
2090 const ast::BinaryExpression* Or(LHS&& lhs, RHS&& rhs) {
2091 return create<ast::BinaryExpression>(ast::BinaryOp::kOr, Expr(std::forward<LHS>(lhs)),
2092 Expr(std::forward<RHS>(rhs)));
2093 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002094
dan sinclair41e4d9a2022-05-01 14:40:55 +00002095 /// @param lhs the left hand argument to the subtraction operation
2096 /// @param rhs the right hand argument to the subtraction operation
2097 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs`
2098 template <typename LHS, typename RHS>
2099 const ast::BinaryExpression* Sub(LHS&& lhs, RHS&& rhs) {
2100 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract, Expr(std::forward<LHS>(lhs)),
2101 Expr(std::forward<RHS>(rhs)));
2102 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002103
dan sinclair41e4d9a2022-05-01 14:40:55 +00002104 /// @param lhs the left hand argument to the multiplication operation
2105 /// @param rhs the right hand argument to the multiplication operation
2106 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2107 template <typename LHS, typename RHS>
2108 const ast::BinaryExpression* Mul(LHS&& lhs, RHS&& rhs) {
2109 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, Expr(std::forward<LHS>(lhs)),
2110 Expr(std::forward<RHS>(rhs)));
2111 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002112
dan sinclair41e4d9a2022-05-01 14:40:55 +00002113 /// @param source the source information
2114 /// @param lhs the left hand argument to the multiplication operation
2115 /// @param rhs the right hand argument to the multiplication operation
2116 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2117 template <typename LHS, typename RHS>
2118 const ast::BinaryExpression* Mul(const Source& source, LHS&& lhs, RHS&& rhs) {
2119 return create<ast::BinaryExpression>(source, ast::BinaryOp::kMultiply,
2120 Expr(std::forward<LHS>(lhs)),
2121 Expr(std::forward<RHS>(rhs)));
2122 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002123
dan sinclair41e4d9a2022-05-01 14:40:55 +00002124 /// @param lhs the left hand argument to the division operation
2125 /// @param rhs the right hand argument to the division operation
2126 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2127 template <typename LHS, typename RHS>
2128 const ast::BinaryExpression* Div(LHS&& lhs, RHS&& rhs) {
2129 return create<ast::BinaryExpression>(ast::BinaryOp::kDivide, Expr(std::forward<LHS>(lhs)),
2130 Expr(std::forward<RHS>(rhs)));
2131 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002132
Antonio Maiorano28779af2022-12-09 21:28:51 +00002133 /// @param source the source information
2134 /// @param lhs the left hand argument to the division operation
2135 /// @param rhs the right hand argument to the division operation
2136 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2137 template <typename LHS, typename RHS>
2138 const ast::BinaryExpression* Div(const Source& source, LHS&& lhs, RHS&& rhs) {
2139 return create<ast::BinaryExpression>(source, ast::BinaryOp::kDivide,
2140 Expr(std::forward<LHS>(lhs)),
2141 Expr(std::forward<RHS>(rhs)));
2142 }
2143
dan sinclair41e4d9a2022-05-01 14:40:55 +00002144 /// @param lhs the left hand argument to the modulo operation
2145 /// @param rhs the right hand argument to the modulo operation
2146 /// @returns a `ast::BinaryExpression` applying modulo of `lhs` by `rhs`
2147 template <typename LHS, typename RHS>
2148 const ast::BinaryExpression* Mod(LHS&& lhs, RHS&& rhs) {
2149 return create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr(std::forward<LHS>(lhs)),
2150 Expr(std::forward<RHS>(rhs)));
2151 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002152
dan sinclair41e4d9a2022-05-01 14:40:55 +00002153 /// @param lhs the left hand argument to the bit shift right operation
2154 /// @param rhs the right hand argument to the bit shift right operation
2155 /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs`
2156 template <typename LHS, typename RHS>
2157 const ast::BinaryExpression* Shr(LHS&& lhs, RHS&& rhs) {
2158 return create<ast::BinaryExpression>(
2159 ast::BinaryOp::kShiftRight, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2160 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002161
dan sinclair41e4d9a2022-05-01 14:40:55 +00002162 /// @param lhs the left hand argument to the bit shift left operation
2163 /// @param rhs the right hand argument to the bit shift left operation
2164 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2165 template <typename LHS, typename RHS>
2166 const ast::BinaryExpression* Shl(LHS&& lhs, RHS&& rhs) {
2167 return create<ast::BinaryExpression>(
2168 ast::BinaryOp::kShiftLeft, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2169 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002170
Antonio Maiorano5f33fac2022-09-23 21:58:29 +00002171 /// @param source the source information
2172 /// @param lhs the left hand argument to the bit shift left operation
2173 /// @param rhs the right hand argument to the bit shift left operation
2174 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2175 template <typename LHS, typename RHS>
2176 const ast::BinaryExpression* Shl(const Source& source, LHS&& lhs, RHS&& rhs) {
2177 return create<ast::BinaryExpression>(source, ast::BinaryOp::kShiftLeft,
2178 Expr(std::forward<LHS>(lhs)),
2179 Expr(std::forward<RHS>(rhs)));
2180 }
2181
dan sinclair41e4d9a2022-05-01 14:40:55 +00002182 /// @param lhs the left hand argument to the xor operation
2183 /// @param rhs the right hand argument to the xor operation
2184 /// @returns a `ast::BinaryExpression` bitwise xor-ing `lhs` and `rhs`
2185 template <typename LHS, typename RHS>
2186 const ast::BinaryExpression* Xor(LHS&& lhs, RHS&& rhs) {
2187 return create<ast::BinaryExpression>(ast::BinaryOp::kXor, Expr(std::forward<LHS>(lhs)),
2188 Expr(std::forward<RHS>(rhs)));
2189 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002190
dan sinclair41e4d9a2022-05-01 14:40:55 +00002191 /// @param lhs the left hand argument to the logical and operation
2192 /// @param rhs the right hand argument to the logical and operation
2193 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2194 template <typename LHS, typename RHS>
2195 const ast::BinaryExpression* LogicalAnd(LHS&& lhs, RHS&& rhs) {
2196 return create<ast::BinaryExpression>(
2197 ast::BinaryOp::kLogicalAnd, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2198 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002199
Antonio Maiorano28779af2022-12-09 21:28:51 +00002200 /// @param source the source information
2201 /// @param lhs the left hand argument to the logical and operation
2202 /// @param rhs the right hand argument to the logical and operation
2203 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2204 template <typename LHS, typename RHS>
2205 const ast::BinaryExpression* LogicalAnd(const Source& source, LHS&& lhs, RHS&& rhs) {
2206 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalAnd,
2207 Expr(std::forward<LHS>(lhs)),
2208 Expr(std::forward<RHS>(rhs)));
2209 }
2210
dan sinclair41e4d9a2022-05-01 14:40:55 +00002211 /// @param lhs the left hand argument to the logical or operation
2212 /// @param rhs the right hand argument to the logical or operation
2213 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2214 template <typename LHS, typename RHS>
2215 const ast::BinaryExpression* LogicalOr(LHS&& lhs, RHS&& rhs) {
2216 return create<ast::BinaryExpression>(
2217 ast::BinaryOp::kLogicalOr, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2218 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002219
Antonio Maiorano28779af2022-12-09 21:28:51 +00002220 /// @param source the source information
2221 /// @param lhs the left hand argument to the logical or operation
2222 /// @param rhs the right hand argument to the logical or operation
2223 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2224 template <typename LHS, typename RHS>
2225 const ast::BinaryExpression* LogicalOr(const Source& source, LHS&& lhs, RHS&& rhs) {
2226 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalOr,
2227 Expr(std::forward<LHS>(lhs)),
2228 Expr(std::forward<RHS>(rhs)));
2229 }
2230
dan sinclair41e4d9a2022-05-01 14:40:55 +00002231 /// @param lhs the left hand argument to the greater than operation
2232 /// @param rhs the right hand argument to the greater than operation
2233 /// @returns a `ast::BinaryExpression` of `lhs` > `rhs`
2234 template <typename LHS, typename RHS>
2235 const ast::BinaryExpression* GreaterThan(LHS&& lhs, RHS&& rhs) {
2236 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThan,
2237 Expr(std::forward<LHS>(lhs)),
2238 Expr(std::forward<RHS>(rhs)));
2239 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002240
dan sinclair41e4d9a2022-05-01 14:40:55 +00002241 /// @param lhs the left hand argument to the greater than or equal operation
2242 /// @param rhs the right hand argument to the greater than or equal operation
2243 /// @returns a `ast::BinaryExpression` of `lhs` >= `rhs`
2244 template <typename LHS, typename RHS>
2245 const ast::BinaryExpression* GreaterThanEqual(LHS&& lhs, RHS&& rhs) {
2246 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThanEqual,
2247 Expr(std::forward<LHS>(lhs)),
2248 Expr(std::forward<RHS>(rhs)));
2249 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002250
dan sinclair41e4d9a2022-05-01 14:40:55 +00002251 /// @param lhs the left hand argument to the less than operation
2252 /// @param rhs the right hand argument to the less than operation
2253 /// @returns a `ast::BinaryExpression` of `lhs` < `rhs`
2254 template <typename LHS, typename RHS>
2255 const ast::BinaryExpression* LessThan(LHS&& lhs, RHS&& rhs) {
2256 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThan, Expr(std::forward<LHS>(lhs)),
2257 Expr(std::forward<RHS>(rhs)));
2258 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002259
dan sinclair41e4d9a2022-05-01 14:40:55 +00002260 /// @param lhs the left hand argument to the less than or equal operation
2261 /// @param rhs the right hand argument to the less than or equal operation
2262 /// @returns a `ast::BinaryExpression` of `lhs` <= `rhs`
2263 template <typename LHS, typename RHS>
2264 const ast::BinaryExpression* LessThanEqual(LHS&& lhs, RHS&& rhs) {
2265 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThanEqual,
2266 Expr(std::forward<LHS>(lhs)),
2267 Expr(std::forward<RHS>(rhs)));
2268 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002269
dan sinclair41e4d9a2022-05-01 14:40:55 +00002270 /// @param lhs the left hand argument to the equal expression
2271 /// @param rhs the right hand argument to the equal expression
2272 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2273 template <typename LHS, typename RHS>
2274 const ast::BinaryExpression* Equal(LHS&& lhs, RHS&& rhs) {
2275 return create<ast::BinaryExpression>(ast::BinaryOp::kEqual, Expr(std::forward<LHS>(lhs)),
2276 Expr(std::forward<RHS>(rhs)));
2277 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002278
Antonio Maiorano28779af2022-12-09 21:28:51 +00002279 /// @param source the source information
2280 /// @param lhs the left hand argument to the equal expression
2281 /// @param rhs the right hand argument to the equal expression
2282 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2283 template <typename LHS, typename RHS>
2284 const ast::BinaryExpression* Equal(const Source& source, LHS&& lhs, RHS&& rhs) {
2285 return create<ast::BinaryExpression>(source, ast::BinaryOp::kEqual,
2286 Expr(std::forward<LHS>(lhs)),
2287 Expr(std::forward<RHS>(rhs)));
2288 }
2289
dan sinclair41e4d9a2022-05-01 14:40:55 +00002290 /// @param lhs the left hand argument to the not-equal expression
2291 /// @param rhs the right hand argument to the not-equal expression
2292 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` for
2293 /// disequality
2294 template <typename LHS, typename RHS>
2295 const ast::BinaryExpression* NotEqual(LHS&& lhs, RHS&& rhs) {
2296 return create<ast::BinaryExpression>(ast::BinaryOp::kNotEqual, Expr(std::forward<LHS>(lhs)),
2297 Expr(std::forward<RHS>(rhs)));
2298 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002299
dan sinclair41e4d9a2022-05-01 14:40:55 +00002300 /// @param source the source information
Ben Clayton2cdf1342023-02-03 13:24:18 +00002301 /// @param object the object for the index accessor expression
2302 /// @param index the index argument for the index accessor expression
2303 /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index
2304 template <typename OBJECT, typename INDEX>
2305 const ast::IndexAccessorExpression* IndexAccessor(const Source& source,
2306 OBJECT&& object,
2307 INDEX&& index) {
2308 return create<ast::IndexAccessorExpression>(source, Expr(std::forward<OBJECT>(object)),
2309 Expr(std::forward<INDEX>(index)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002310 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002311
Ben Clayton2cdf1342023-02-03 13:24:18 +00002312 /// @param object the object for the index accessor expression
2313 /// @param index the index argument for the index accessor expression
2314 /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index
2315 template <typename OBJECT, typename INDEX>
2316 const ast::IndexAccessorExpression* IndexAccessor(OBJECT&& object, INDEX&& index) {
2317 return create<ast::IndexAccessorExpression>(Expr(std::forward<OBJECT>(object)),
2318 Expr(std::forward<INDEX>(index)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002319 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002320
dan sinclair41e4d9a2022-05-01 14:40:55 +00002321 /// @param source the source information
Ben Clayton2cdf1342023-02-03 13:24:18 +00002322 /// @param object the object for the member accessor expression
2323 /// @param member the member argument for the member accessor expression
2324 /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member
2325 template <typename OBJECT, typename MEMBER>
dan sinclair41e4d9a2022-05-01 14:40:55 +00002326 const ast::MemberAccessorExpression* MemberAccessor(const Source& source,
Ben Clayton2cdf1342023-02-03 13:24:18 +00002327 OBJECT&& object,
2328 MEMBER&& member) {
2329 static_assert(!traits::IsType<traits::PtrElTy<MEMBER>, ast::TemplatedIdentifier>,
2330 "it is currently invalid for a structure to hold a templated member");
2331 return create<ast::MemberAccessorExpression>(source, Expr(std::forward<OBJECT>(object)),
2332 Ident(std::forward<MEMBER>(member)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002333 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002334
Ben Clayton2cdf1342023-02-03 13:24:18 +00002335 /// @param object the object for the member accessor expression
2336 /// @param member the member argument for the member accessor expression
2337 /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member
2338 template <typename OBJECT, typename MEMBER>
2339 const ast::MemberAccessorExpression* MemberAccessor(OBJECT&& object, MEMBER&& member) {
2340 return MemberAccessor(source_, std::forward<OBJECT>(object), std::forward<MEMBER>(member));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002341 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002342
dan sinclair41e4d9a2022-05-01 14:40:55 +00002343 /// Creates a ast::StructMemberOffsetAttribute
dan sinclair93df9672022-09-09 14:49:09 +00002344 /// @param val the offset expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002345 /// @returns the offset attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002346 template <typename EXPR>
2347 const ast::StructMemberOffsetAttribute* MemberOffset(EXPR&& val) {
2348 return create<ast::StructMemberOffsetAttribute>(source_, Expr(std::forward<EXPR>(val)));
2349 }
2350
2351 /// Creates a ast::StructMemberOffsetAttribute
2352 /// @param source the source information
2353 /// @param val the offset expression
2354 /// @returns the offset attribute pointer
2355 template <typename EXPR>
2356 const ast::StructMemberOffsetAttribute* MemberOffset(const Source& source, EXPR&& val) {
2357 return create<ast::StructMemberOffsetAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002358 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002359
dan sinclair41e4d9a2022-05-01 14:40:55 +00002360 /// Creates a ast::StructMemberSizeAttribute
2361 /// @param source the source information
2362 /// @param val the size value
2363 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002364 template <typename EXPR>
2365 const ast::StructMemberSizeAttribute* MemberSize(const Source& source, EXPR&& val) {
2366 return create<ast::StructMemberSizeAttribute>(source, Expr(std::forward<EXPR>(val)));
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::StructMemberSizeAttribute
2370 /// @param val the size value
2371 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002372 template <typename EXPR>
2373 const ast::StructMemberSizeAttribute* MemberSize(EXPR&& val) {
2374 return create<ast::StructMemberSizeAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002375 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002376
dan sinclair41e4d9a2022-05-01 14:40:55 +00002377 /// Creates a ast::StructMemberAlignAttribute
2378 /// @param source the source information
dan sinclair4964d9b2022-08-23 13:28:44 +00002379 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002380 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002381 template <typename EXPR>
2382 const ast::StructMemberAlignAttribute* MemberAlign(const Source& source, EXPR&& val) {
2383 return create<ast::StructMemberAlignAttribute>(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::StructMemberAlignAttribute
dan sinclair4964d9b2022-08-23 13:28:44 +00002387 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002388 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002389 template <typename EXPR>
2390 const ast::StructMemberAlignAttribute* MemberAlign(EXPR&& val) {
2391 return create<ast::StructMemberAlignAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002392 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002393
Ben Clayton9e367232023-02-08 14:17:37 +00002394 /// Creates a ast::StrideAttribute
2395 /// @param stride the array stride
2396 /// @returns the ast::StrideAttribute attribute
2397 const ast::StrideAttribute* Stride(uint32_t stride) {
2398 return create<ast::StrideAttribute>(source_, stride);
2399 }
2400
dan sinclair41e4d9a2022-05-01 14:40:55 +00002401 /// Creates the ast::GroupAttribute
dan sinclairbe4c9f42022-08-29 21:22:31 +00002402 /// @param value group attribute index expresion
dan sinclair41e4d9a2022-05-01 14:40:55 +00002403 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002404 template <typename EXPR>
2405 const ast::GroupAttribute* Group(EXPR&& value) {
2406 return create<ast::GroupAttribute>(Expr(std::forward<EXPR>(value)));
2407 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002408
dan sinclairf9b831c2022-08-29 21:13:00 +00002409 /// Creates the ast::GroupAttribute
2410 /// @param source the source
dan sinclairbe4c9f42022-08-29 21:22:31 +00002411 /// @param value group attribute index expression
dan sinclairf9b831c2022-08-29 21:13:00 +00002412 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002413 template <typename EXPR>
2414 const ast::GroupAttribute* Group(const Source& source, EXPR&& value) {
2415 return create<ast::GroupAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclairf9b831c2022-08-29 21:13:00 +00002416 }
2417
dan sinclair41e4d9a2022-05-01 14:40:55 +00002418 /// Creates the ast::BindingAttribute
dan sinclairf9b831c2022-08-29 21:13:00 +00002419 /// @param value the binding index expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002420 /// @returns the binding deocration pointer
dan sinclairf9b831c2022-08-29 21:13:00 +00002421 template <typename EXPR>
2422 const ast::BindingAttribute* Binding(EXPR&& value) {
2423 return create<ast::BindingAttribute>(Expr(std::forward<EXPR>(value)));
2424 }
2425
2426 /// Creates the ast::BindingAttribute
2427 /// @param source the source
2428 /// @param value the binding index expression
2429 /// @returns the binding deocration pointer
2430 template <typename EXPR>
2431 const ast::BindingAttribute* Binding(const Source& source, EXPR&& value) {
2432 return create<ast::BindingAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002433 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002434
dan sinclair41e4d9a2022-05-01 14:40:55 +00002435 /// Creates an ast::Function and registers it with the ast::Module.
Ben Clayton17aa6532023-02-07 21:28:09 +00002436 /// @param name the function name
2437 /// @param params the function parameters
2438 /// @param type the function return type
2439 /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
2440 /// be automatically placed into a block, or nullptr for a stub function.
2441 /// @param attributes the optional function attributes
2442 /// @param return_type_attributes the optional function return type attributes
2443 /// attributes
2444 /// @returns the function pointer
2445 template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
2446 const ast::Function* Func(
2447 NAME&& name,
2448 utils::VectorRef<const ast::Parameter*> params,
2449 const ast::Type* type,
2450 BODY&& body,
2451 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
2452 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2453 return Func(source_, std::forward<NAME>(name), std::move(params), type,
2454 std::forward<BODY>(body), std::move(attributes),
2455 std::move(return_type_attributes));
2456 }
2457
2458 /// Creates an ast::Function and registers it with the ast::Module.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002459 /// @param source the source information
2460 /// @param name the function name
2461 /// @param params the function parameters
2462 /// @param type the function return type
Ben Clayton17aa6532023-02-07 21:28:09 +00002463 /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
2464 /// be automatically placed into a block, or nullptr for a stub function.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002465 /// @param attributes the optional function attributes
James Priced9f65962023-02-01 23:14:10 +00002466 /// @param return_type_attributes the optional function return type attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002467 /// attributes
2468 /// @returns the function pointer
Ben Clayton17aa6532023-02-07 21:28:09 +00002469 template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
Ben Clayton783b1692022-08-02 17:03:35 +00002470 const ast::Function* Func(
2471 const Source& source,
2472 NAME&& name,
2473 utils::VectorRef<const ast::Parameter*> params,
2474 const ast::Type* type,
Ben Clayton17aa6532023-02-07 21:28:09 +00002475 BODY&& body,
Ben Clayton783b1692022-08-02 17:03:35 +00002476 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
Ben Clayton17aa6532023-02-07 21:28:09 +00002477 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2478 const ast::BlockStatement* block = nullptr;
2479 using BODY_T = traits::PtrElTy<BODY>;
2480 if constexpr (traits::IsTypeOrDerived<BODY_T, ast::BlockStatement> ||
2481 std::is_same_v<BODY_T, std::nullptr_t>) {
2482 block = body;
2483 } else {
2484 block = Block(std::forward<BODY>(body));
2485 }
2486 auto* func =
Ben Claytonce31d182023-02-09 10:34:14 +00002487 create<ast::Function>(source, Ident(std::forward<NAME>(name)), std::move(params), type,
Ben Clayton17aa6532023-02-07 21:28:09 +00002488 block, std::move(attributes), std::move(return_type_attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002489 AST().AddFunction(func);
2490 return func;
2491 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002492
dan sinclair41e4d9a2022-05-01 14:40:55 +00002493 /// Creates an ast::BreakStatement
2494 /// @param source the source information
2495 /// @returns the break statement pointer
2496 const ast::BreakStatement* Break(const Source& source) {
2497 return create<ast::BreakStatement>(source);
2498 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002499
dan sinclair41e4d9a2022-05-01 14:40:55 +00002500 /// Creates an ast::BreakStatement
2501 /// @returns the break statement pointer
2502 const ast::BreakStatement* Break() { return create<ast::BreakStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002503
dan sinclairb8b0c212022-10-20 22:45:50 +00002504 /// Creates a ast::BreakIfStatement with input condition
2505 /// @param source the source information for the if statement
2506 /// @param condition the if statement condition expression
2507 /// @returns the break-if statement pointer
2508 template <typename CONDITION>
2509 const ast::BreakIfStatement* BreakIf(const Source& source, CONDITION&& condition) {
2510 return create<ast::BreakIfStatement>(source, Expr(std::forward<CONDITION>(condition)));
2511 }
2512
2513 /// Creates a ast::BreakIfStatement with input condition
2514 /// @param condition the if statement condition expression
2515 /// @returns the break-if statement pointer
2516 template <typename CONDITION>
2517 const ast::BreakIfStatement* BreakIf(CONDITION&& condition) {
2518 return create<ast::BreakIfStatement>(Expr(std::forward<CONDITION>(condition)));
2519 }
2520
dan sinclair41e4d9a2022-05-01 14:40:55 +00002521 /// Creates an ast::ContinueStatement
2522 /// @param source the source information
2523 /// @returns the continue statement pointer
2524 const ast::ContinueStatement* Continue(const Source& source) {
2525 return create<ast::ContinueStatement>(source);
2526 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002527
dan sinclair41e4d9a2022-05-01 14:40:55 +00002528 /// Creates an ast::ContinueStatement
2529 /// @returns the continue statement pointer
2530 const ast::ContinueStatement* Continue() { return create<ast::ContinueStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002531
dan sinclair41e4d9a2022-05-01 14:40:55 +00002532 /// Creates an ast::ReturnStatement with no return value
2533 /// @param source the source information
2534 /// @returns the return statement pointer
2535 const ast::ReturnStatement* Return(const Source& source) {
2536 return create<ast::ReturnStatement>(source);
2537 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002538
dan sinclair41e4d9a2022-05-01 14:40:55 +00002539 /// Creates an ast::ReturnStatement with no return value
2540 /// @returns the return statement pointer
2541 const ast::ReturnStatement* Return() { return create<ast::ReturnStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002542
dan sinclair41e4d9a2022-05-01 14:40:55 +00002543 /// Creates an ast::ReturnStatement with the given return value
2544 /// @param source the source information
2545 /// @param val the return value
2546 /// @returns the return statement pointer
2547 template <typename EXPR>
2548 const ast::ReturnStatement* Return(const Source& source, EXPR&& val) {
2549 return create<ast::ReturnStatement>(source, Expr(std::forward<EXPR>(val)));
2550 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002551
dan sinclair41e4d9a2022-05-01 14:40:55 +00002552 /// Creates an ast::ReturnStatement with the given return value
2553 /// @param val the return value
2554 /// @returns the return statement pointer
2555 template <typename EXPR, typename = DisableIfSource<EXPR>>
2556 const ast::ReturnStatement* Return(EXPR&& val) {
2557 return create<ast::ReturnStatement>(Expr(std::forward<EXPR>(val)));
2558 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002559
dan sinclair41e4d9a2022-05-01 14:40:55 +00002560 /// Creates an ast::DiscardStatement
2561 /// @param source the source information
2562 /// @returns the discard statement pointer
2563 const ast::DiscardStatement* Discard(const Source& source) {
2564 return create<ast::DiscardStatement>(source);
2565 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002566
dan sinclair41e4d9a2022-05-01 14:40:55 +00002567 /// Creates an ast::DiscardStatement
2568 /// @returns the discard statement pointer
2569 const ast::DiscardStatement* Discard() { return create<ast::DiscardStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002570
dan sinclair41e4d9a2022-05-01 14:40:55 +00002571 /// Creates a ast::Alias registering it with the AST().TypeDecls().
Ben Claytonb75252b2023-02-09 10:34:14 +00002572 /// @param name the alias name
2573 /// @param type the alias target type
2574 /// @returns the alias type
2575 template <typename NAME>
2576 const ast::Alias* Alias(NAME&& name, const ast::Type* type) {
2577 return Alias(source_, std::forward<NAME>(name), type);
2578 }
2579
2580 /// Creates a ast::Alias registering it with the AST().TypeDecls().
dan sinclair41e4d9a2022-05-01 14:40:55 +00002581 /// @param source the source information
2582 /// @param name the alias name
2583 /// @param type the alias target type
2584 /// @returns the alias type
2585 template <typename NAME>
2586 const ast::Alias* Alias(const Source& source, NAME&& name, const ast::Type* type) {
2587 auto* out = ty.alias(source, std::forward<NAME>(name), type);
2588 AST().AddTypeDecl(out);
2589 return out;
2590 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002591
Ben Claytonb75252b2023-02-09 10:34:14 +00002592 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2593 /// @param name the struct name
2594 /// @param members the struct members
2595 /// @param attributes the optional struct attributes
2596 /// @returns the struct type
dan sinclair41e4d9a2022-05-01 14:40:55 +00002597 template <typename NAME>
Ben Claytonb75252b2023-02-09 10:34:14 +00002598 const ast::Struct* Structure(
2599 NAME&& name,
2600 utils::VectorRef<const ast::StructMember*> members,
2601 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2602 return Structure(source_, std::forward<NAME>(name), std::move(members),
2603 std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002604 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002605
dan sinclair41e4d9a2022-05-01 14:40:55 +00002606 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2607 /// @param source the source information
2608 /// @param name the struct name
2609 /// @param members the struct members
Ben Claytonb75252b2023-02-09 10:34:14 +00002610 /// @param attributes the optional struct attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002611 /// @returns the struct type
2612 template <typename NAME>
Ben Claytonb75252b2023-02-09 10:34:14 +00002613 const ast::Struct* Structure(
2614 const Source& source,
2615 NAME&& name,
2616 utils::VectorRef<const ast::StructMember*> members,
2617 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2618 auto* type = create<ast::Struct>(source, Ident(std::forward<NAME>(name)),
2619 std::move(members), std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002620 AST().AddTypeDecl(type);
2621 return type;
2622 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002623
dan sinclair41e4d9a2022-05-01 14:40:55 +00002624 /// Creates a ast::StructMember
Ben Clayton199440e2023-02-09 10:34:14 +00002625 /// @param name the struct member name
2626 /// @param type the struct member type
2627 /// @param attributes the optional struct member attributes
2628 /// @returns the struct member pointer
2629 template <typename NAME>
2630 const ast::StructMember* Member(
2631 NAME&& name,
2632 const ast::Type* type,
2633 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2634 return Member(source_, std::forward<NAME>(name), type, std::move(attributes));
2635 }
2636
2637 /// Creates a ast::StructMember
dan sinclair41e4d9a2022-05-01 14:40:55 +00002638 /// @param source the source information
2639 /// @param name the struct member name
2640 /// @param type the struct member type
2641 /// @param attributes the optional struct member attributes
2642 /// @returns the struct member pointer
2643 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002644 const ast::StructMember* Member(
2645 const Source& source,
2646 NAME&& name,
2647 const ast::Type* type,
2648 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Clayton199440e2023-02-09 10:34:14 +00002649 return create<ast::StructMember>(source, Ident(std::forward<NAME>(name)), type,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002650 std::move(attributes));
2651 }
2652
2653 /// Creates a ast::StructMember with the given byte offset
Ben Clayton783b1692022-08-02 17:03:35 +00002654 /// @param offset the offset to use in the StructMemberOffsetAttribute
dan sinclair41e4d9a2022-05-01 14:40:55 +00002655 /// @param name the struct member name
2656 /// @param type the struct member type
2657 /// @returns the struct member pointer
2658 template <typename NAME>
2659 const ast::StructMember* Member(uint32_t offset, NAME&& name, const ast::Type* type) {
Ben Clayton199440e2023-02-09 10:34:14 +00002660 return create<ast::StructMember>(source_, Ident(std::forward<NAME>(name)), type,
Ben Clayton783b1692022-08-02 17:03:35 +00002661 utils::Vector<const ast::Attribute*, 1>{
dan sinclair93df9672022-09-09 14:49:09 +00002662 MemberOffset(AInt(offset)),
dan sinclair41e4d9a2022-05-01 14:40:55 +00002663 });
2664 }
2665
Ben Clayton17aa6532023-02-07 21:28:09 +00002666 /// Creates a ast::BlockStatement with input statements and attributes
2667 /// @param statements the statements of the block
2668 /// @param attributes the optional attributes of the block
2669 /// @returns the block statement pointer
2670 const ast::BlockStatement* Block(
2671 utils::VectorRef<const ast::Statement*> statements,
2672 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2673 return Block(source_, std::move(statements), std::move(attributes));
2674 }
2675
2676 /// Creates a ast::BlockStatement with input statements and attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002677 /// @param source the source information for the block
Ben Clayton17aa6532023-02-07 21:28:09 +00002678 /// @param statements the statements of the block
2679 /// @param attributes the optional attributes of the block
2680 /// @returns the block statement pointer
2681 const ast::BlockStatement* Block(
2682 const Source& source,
2683 utils::VectorRef<const ast::Statement*> statements,
2684 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2685 return create<ast::BlockStatement>(source, std::move(statements), std::move(attributes));
2686 }
2687
2688 /// Creates a ast::BlockStatement with a parameter list of input statements
2689 /// @param statements the optional statements of the block
2690 /// @returns the block statement pointer
2691 template <typename... STATEMENTS,
2692 typename = DisableIfSource<STATEMENTS...>,
2693 typename = DisableIfVectorLike<STATEMENTS...>>
2694 const ast::BlockStatement* Block(STATEMENTS&&... statements) {
2695 return Block(source_, std::forward<STATEMENTS>(statements)...);
2696 }
2697
2698 /// Creates a ast::BlockStatement with a parameter list of input statements
2699 /// @param source the source information for the block
2700 /// @param statements the optional statements of the block
dan sinclair41e4d9a2022-05-01 14:40:55 +00002701 /// @returns the block statement pointer
James Priced9f65962023-02-01 23:14:10 +00002702 template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>>
2703 const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002704 return create<ast::BlockStatement>(
James Priced9f65962023-02-01 23:14:10 +00002705 source,
2706 utils::Vector<const ast::Statement*, sizeof...(statements)>{
2707 std::forward<STATEMENTS>(statements)...,
2708 },
2709 utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002710 }
2711
James Price8aff0ed2022-05-02 14:53:36 +00002712 /// A wrapper type for the Else statement used to create If statements.
2713 struct ElseStmt {
2714 /// Default constructor - no else statement.
2715 ElseStmt() : stmt(nullptr) {}
2716 /// Constructor
2717 /// @param s The else statement
2718 explicit ElseStmt(const ast::Statement* s) : stmt(s) {}
2719 /// The else statement, or nullptr.
2720 const ast::Statement* stmt;
2721 };
2722
dan sinclair41e4d9a2022-05-01 14:40:55 +00002723 /// Creates a ast::IfStatement with input condition, body, and optional
2724 /// else statement
2725 /// @param source the source information for the if statement
2726 /// @param condition the if statement condition expression
2727 /// @param body the if statement body
2728 /// @param else_stmt optional else statement
2729 /// @returns the if statement pointer
2730 template <typename CONDITION>
2731 const ast::IfStatement* If(const Source& source,
2732 CONDITION&& condition,
2733 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002734 const ElseStmt else_stmt = ElseStmt()) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002735 return create<ast::IfStatement>(source, Expr(std::forward<CONDITION>(condition)), body,
James Price8aff0ed2022-05-02 14:53:36 +00002736 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002737 }
2738
2739 /// Creates a ast::IfStatement with input condition, body, and optional
2740 /// else statement
2741 /// @param condition the if statement condition expression
2742 /// @param body the if statement body
2743 /// @param else_stmt optional else statement
2744 /// @returns the if statement pointer
2745 template <typename CONDITION>
2746 const ast::IfStatement* If(CONDITION&& condition,
2747 const ast::BlockStatement* body,
James Price8aff0ed2022-05-02 14:53:36 +00002748 const ElseStmt else_stmt = ElseStmt()) {
2749 return create<ast::IfStatement>(Expr(std::forward<CONDITION>(condition)), body,
2750 else_stmt.stmt);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002751 }
2752
James Price8aff0ed2022-05-02 14:53:36 +00002753 /// Creates an Else object.
2754 /// @param stmt else statement
2755 /// @returns the Else object
2756 ElseStmt Else(const ast::Statement* stmt) { return ElseStmt(stmt); }
2757
dan sinclair41e4d9a2022-05-01 14:40:55 +00002758 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2759 /// @param source the source information
2760 /// @param lhs the left hand side expression initializer
2761 /// @param rhs the right hand side expression initializer
2762 /// @returns the assignment statement pointer
2763 template <typename LhsExpressionInit, typename RhsExpressionInit>
2764 const ast::AssignmentStatement* Assign(const Source& source,
2765 LhsExpressionInit&& lhs,
2766 RhsExpressionInit&& rhs) {
2767 return create<ast::AssignmentStatement>(source, Expr(std::forward<LhsExpressionInit>(lhs)),
2768 Expr(std::forward<RhsExpressionInit>(rhs)));
2769 }
2770
2771 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2772 /// @param lhs the left hand side expression initializer
2773 /// @param rhs the right hand side expression initializer
2774 /// @returns the assignment statement pointer
2775 template <typename LhsExpressionInit, typename RhsExpressionInit>
2776 const ast::AssignmentStatement* Assign(LhsExpressionInit&& lhs, RhsExpressionInit&& rhs) {
2777 return create<ast::AssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2778 Expr(std::forward<RhsExpressionInit>(rhs)));
2779 }
2780
2781 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2782 /// expressions, and a binary operator.
2783 /// @param source the source information
2784 /// @param lhs the left hand side expression initializer
2785 /// @param rhs the right hand side expression initializer
2786 /// @param op the binary operator
2787 /// @returns the compound assignment statement pointer
2788 template <typename LhsExpressionInit, typename RhsExpressionInit>
2789 const ast::CompoundAssignmentStatement* CompoundAssign(const Source& source,
2790 LhsExpressionInit&& lhs,
2791 RhsExpressionInit&& rhs,
2792 ast::BinaryOp op) {
2793 return create<ast::CompoundAssignmentStatement>(
2794 source, Expr(std::forward<LhsExpressionInit>(lhs)),
2795 Expr(std::forward<RhsExpressionInit>(rhs)), op);
2796 }
2797
2798 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2799 /// expressions, and a binary operator.
2800 /// @param lhs the left hand side expression initializer
2801 /// @param rhs the right hand side expression initializer
2802 /// @param op the binary operator
2803 /// @returns the compound assignment statement pointer
2804 template <typename LhsExpressionInit, typename RhsExpressionInit>
2805 const ast::CompoundAssignmentStatement* CompoundAssign(LhsExpressionInit&& lhs,
2806 RhsExpressionInit&& rhs,
2807 ast::BinaryOp op) {
2808 return create<ast::CompoundAssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2809 Expr(std::forward<RhsExpressionInit>(rhs)),
2810 op);
2811 }
2812
2813 /// Creates an ast::IncrementDecrementStatement with input lhs.
2814 /// @param source the source information
2815 /// @param lhs the left hand side expression initializer
2816 /// @returns the increment decrement statement pointer
2817 template <typename LhsExpressionInit>
2818 const ast::IncrementDecrementStatement* Increment(const Source& source,
2819 LhsExpressionInit&& lhs) {
2820 return create<ast::IncrementDecrementStatement>(
2821 source, Expr(std::forward<LhsExpressionInit>(lhs)), true);
2822 }
2823
2824 /// Creates a ast::IncrementDecrementStatement with input lhs.
2825 /// @param lhs the left hand side expression initializer
2826 /// @returns the increment decrement statement pointer
2827 template <typename LhsExpressionInit>
2828 const ast::IncrementDecrementStatement* Increment(LhsExpressionInit&& lhs) {
2829 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2830 true);
2831 }
2832
2833 /// Creates an ast::IncrementDecrementStatement with input lhs.
2834 /// @param source the source information
2835 /// @param lhs the left hand side expression initializer
2836 /// @returns the increment decrement statement pointer
2837 template <typename LhsExpressionInit>
2838 const ast::IncrementDecrementStatement* Decrement(const Source& source,
2839 LhsExpressionInit&& lhs) {
2840 return create<ast::IncrementDecrementStatement>(
2841 source, Expr(std::forward<LhsExpressionInit>(lhs)), false);
2842 }
2843
2844 /// Creates a ast::IncrementDecrementStatement with input lhs.
2845 /// @param lhs the left hand side expression initializer
2846 /// @returns the increment decrement statement pointer
2847 template <typename LhsExpressionInit>
2848 const ast::IncrementDecrementStatement* Decrement(LhsExpressionInit&& lhs) {
2849 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2850 false);
2851 }
2852
2853 /// Creates a ast::LoopStatement with input body and optional continuing
2854 /// @param source the source information
2855 /// @param body the loop body
2856 /// @param continuing the optional continuing block
2857 /// @returns the loop statement pointer
2858 const ast::LoopStatement* Loop(const Source& source,
2859 const ast::BlockStatement* body,
2860 const ast::BlockStatement* continuing = nullptr) {
2861 return create<ast::LoopStatement>(source, body, continuing);
2862 }
2863
2864 /// Creates a ast::LoopStatement with input body and optional continuing
2865 /// @param body the loop body
2866 /// @param continuing the optional continuing block
2867 /// @returns the loop statement pointer
2868 const ast::LoopStatement* Loop(const ast::BlockStatement* body,
2869 const ast::BlockStatement* continuing = nullptr) {
2870 return create<ast::LoopStatement>(body, continuing);
2871 }
2872
2873 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2874 /// condition and continuing.
2875 /// @param source the source information
2876 /// @param init the optional loop initializer
2877 /// @param cond the optional loop condition
2878 /// @param cont the optional loop continuing
2879 /// @param body the loop body
2880 /// @returns the for loop statement pointer
2881 template <typename COND>
2882 const ast::ForLoopStatement* For(const Source& source,
2883 const ast::Statement* init,
2884 COND&& cond,
2885 const ast::Statement* cont,
2886 const ast::BlockStatement* body) {
2887 return create<ast::ForLoopStatement>(source, init, Expr(std::forward<COND>(cond)), cont,
2888 body);
2889 }
2890
2891 /// Creates a ast::ForLoopStatement with input body and optional initializer,
2892 /// condition and continuing.
2893 /// @param init the optional loop initializer
2894 /// @param cond the optional loop condition
2895 /// @param cont the optional loop continuing
2896 /// @param body the loop body
2897 /// @returns the for loop statement pointer
2898 template <typename COND>
2899 const ast::ForLoopStatement* For(const ast::Statement* init,
2900 COND&& cond,
2901 const ast::Statement* cont,
2902 const ast::BlockStatement* body) {
2903 return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), cont, body);
2904 }
2905
dan sinclair49d1a2d2022-06-16 12:01:27 +00002906 /// Creates a ast::WhileStatement with input body and condition.
2907 /// @param source the source information
2908 /// @param cond the loop condition
2909 /// @param body the loop body
2910 /// @returns the while statement pointer
2911 template <typename COND>
2912 const ast::WhileStatement* While(const Source& source,
2913 COND&& cond,
2914 const ast::BlockStatement* body) {
2915 return create<ast::WhileStatement>(source, Expr(std::forward<COND>(cond)), body);
2916 }
2917
2918 /// Creates a ast::WhileStatement with given condition and body.
2919 /// @param cond the condition
2920 /// @param body the loop body
2921 /// @returns the while loop statement pointer
2922 template <typename COND>
2923 const ast::WhileStatement* While(COND&& cond, const ast::BlockStatement* body) {
2924 return create<ast::WhileStatement>(Expr(std::forward<COND>(cond)), body);
2925 }
2926
dan sinclair41e4d9a2022-05-01 14:40:55 +00002927 /// Creates a ast::VariableDeclStatement for the input variable
2928 /// @param source the source information
2929 /// @param var the variable to wrap in a decl statement
2930 /// @returns the variable decl statement pointer
2931 const ast::VariableDeclStatement* Decl(const Source& source, const ast::Variable* var) {
2932 return create<ast::VariableDeclStatement>(source, var);
2933 }
2934
2935 /// Creates a ast::VariableDeclStatement for the input variable
2936 /// @param var the variable to wrap in a decl statement
2937 /// @returns the variable decl statement pointer
2938 const ast::VariableDeclStatement* Decl(const ast::Variable* var) {
2939 return create<ast::VariableDeclStatement>(var);
2940 }
2941
2942 /// Creates a ast::SwitchStatement with input expression and cases
2943 /// @param source the source information
2944 /// @param condition the condition expression initializer
2945 /// @param cases case statements
2946 /// @returns the switch statement pointer
2947 template <typename ExpressionInit, typename... Cases>
2948 const ast::SwitchStatement* Switch(const Source& source,
2949 ExpressionInit&& condition,
2950 Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00002951 return create<ast::SwitchStatement>(
2952 source, Expr(std::forward<ExpressionInit>(condition)),
2953 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
2954 std::forward<Cases>(cases)...});
dan sinclair41e4d9a2022-05-01 14:40:55 +00002955 }
2956
2957 /// Creates a ast::SwitchStatement with input expression and cases
2958 /// @param condition the condition expression initializer
2959 /// @param cases case statements
2960 /// @returns the switch statement pointer
2961 template <typename ExpressionInit,
2962 typename... Cases,
2963 typename = DisableIfSource<ExpressionInit>>
2964 const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00002965 return create<ast::SwitchStatement>(
2966 Expr(std::forward<ExpressionInit>(condition)),
2967 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
2968 std::forward<Cases>(cases)...});
dan sinclair41e4d9a2022-05-01 14:40:55 +00002969 }
2970
2971 /// Creates a ast::CaseStatement with input list of selectors, and body
2972 /// @param source the source information
2973 /// @param selectors list of selectors
2974 /// @param body the case body
2975 /// @returns the case statement pointer
2976 const ast::CaseStatement* Case(const Source& source,
dan sinclairf148f082022-10-19 15:55:02 +00002977 utils::VectorRef<const ast::CaseSelector*> selectors,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002978 const ast::BlockStatement* body = nullptr) {
2979 return create<ast::CaseStatement>(source, std::move(selectors), body ? body : Block());
2980 }
2981
2982 /// Creates a ast::CaseStatement with input list of selectors, and body
2983 /// @param selectors list of selectors
2984 /// @param body the case body
2985 /// @returns the case statement pointer
dan sinclairf148f082022-10-19 15:55:02 +00002986 const ast::CaseStatement* Case(utils::VectorRef<const ast::CaseSelector*> selectors,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002987 const ast::BlockStatement* body = nullptr) {
2988 return create<ast::CaseStatement>(std::move(selectors), body ? body : Block());
2989 }
2990
2991 /// Convenient overload that takes a single selector
2992 /// @param selector a single case selector
2993 /// @param body the case body
2994 /// @returns the case statement pointer
dan sinclairf148f082022-10-19 15:55:02 +00002995 const ast::CaseStatement* Case(const ast::CaseSelector* selector,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002996 const ast::BlockStatement* body = nullptr) {
Ben Clayton783b1692022-08-02 17:03:35 +00002997 return Case(utils::Vector{selector}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002998 }
2999
3000 /// Convenience function that creates a 'default' ast::CaseStatement
3001 /// @param source the source information
3002 /// @param body the case body
3003 /// @returns the case statement pointer
3004 const ast::CaseStatement* DefaultCase(const Source& source,
3005 const ast::BlockStatement* body = nullptr) {
dan sinclairf148f082022-10-19 15:55:02 +00003006 return Case(source, utils::Vector{DefaultCaseSelector(source)}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003007 }
3008
3009 /// Convenience function that creates a 'default' ast::CaseStatement
3010 /// @param body the case body
3011 /// @returns the case statement pointer
3012 const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) {
dan sinclairf148f082022-10-19 15:55:02 +00003013 return Case(utils::Vector{DefaultCaseSelector()}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003014 }
3015
dan sinclairf148f082022-10-19 15:55:02 +00003016 /// Convenience function that creates a case selector
3017 /// @param source the source information
3018 /// @param expr the selector expression
3019 /// @returns the selector pointer
3020 template <typename EXPR>
3021 const ast::CaseSelector* CaseSelector(const Source& source, EXPR&& expr) {
3022 return create<ast::CaseSelector>(source, Expr(std::forward<EXPR>(expr)));
3023 }
3024
3025 /// Convenience function that creates a case selector
3026 /// @param expr the selector expression
3027 /// @returns the selector pointer
3028 template <typename EXPR>
3029 const ast::CaseSelector* CaseSelector(EXPR&& expr) {
3030 return create<ast::CaseSelector>(source_, Expr(std::forward<EXPR>(expr)));
3031 }
3032
3033 /// Convenience function that creates a default case selector
3034 /// @param source the source information
3035 /// @returns the selector pointer
3036 const ast::CaseSelector* DefaultCaseSelector(const Source& source) {
3037 return create<ast::CaseSelector>(source, nullptr);
3038 }
3039
3040 /// Convenience function that creates a default case selector
3041 /// @returns the selector pointer
3042 const ast::CaseSelector* DefaultCaseSelector() { return create<ast::CaseSelector>(nullptr); }
3043
dan sinclair41e4d9a2022-05-01 14:40:55 +00003044 /// Creates an ast::BuiltinAttribute
3045 /// @param source the source information
3046 /// @param builtin the builtin value
3047 /// @returns the builtin attribute pointer
Ben Claytonf3302292022-07-27 18:48:06 +00003048 const ast::BuiltinAttribute* Builtin(const Source& source, ast::BuiltinValue builtin) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003049 return create<ast::BuiltinAttribute>(source, builtin);
3050 }
3051
3052 /// Creates an ast::BuiltinAttribute
3053 /// @param builtin the builtin value
3054 /// @returns the builtin attribute pointer
Ben Claytonf3302292022-07-27 18:48:06 +00003055 const ast::BuiltinAttribute* Builtin(ast::BuiltinValue builtin) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003056 return create<ast::BuiltinAttribute>(source_, builtin);
3057 }
3058
3059 /// Creates an ast::InterpolateAttribute
3060 /// @param source the source information
3061 /// @param type the interpolation type
3062 /// @param sampling the interpolation sampling
3063 /// @returns the interpolate attribute pointer
3064 const ast::InterpolateAttribute* Interpolate(
3065 const Source& source,
3066 ast::InterpolationType type,
Ben Claytond2e0db32022-10-12 18:49:15 +00003067 ast::InterpolationSampling sampling = ast::InterpolationSampling::kUndefined) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003068 return create<ast::InterpolateAttribute>(source, type, sampling);
3069 }
3070
3071 /// Creates an ast::InterpolateAttribute
3072 /// @param type the interpolation type
3073 /// @param sampling the interpolation sampling
3074 /// @returns the interpolate attribute pointer
3075 const ast::InterpolateAttribute* Interpolate(
3076 ast::InterpolationType type,
Ben Claytond2e0db32022-10-12 18:49:15 +00003077 ast::InterpolationSampling sampling = ast::InterpolationSampling::kUndefined) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003078 return create<ast::InterpolateAttribute>(source_, type, sampling);
3079 }
3080
3081 /// Creates an ast::InterpolateAttribute using flat interpolation
3082 /// @param source the source information
3083 /// @returns the interpolate attribute pointer
3084 const ast::InterpolateAttribute* Flat(const Source& source) {
3085 return Interpolate(source, ast::InterpolationType::kFlat);
3086 }
3087
3088 /// Creates an ast::InterpolateAttribute using flat interpolation
3089 /// @returns the interpolate attribute pointer
3090 const ast::InterpolateAttribute* Flat() { return Interpolate(ast::InterpolationType::kFlat); }
3091
3092 /// Creates an ast::InvariantAttribute
3093 /// @param source the source information
3094 /// @returns the invariant attribute pointer
3095 const ast::InvariantAttribute* Invariant(const Source& source) {
3096 return create<ast::InvariantAttribute>(source);
3097 }
3098
3099 /// Creates an ast::InvariantAttribute
3100 /// @returns the invariant attribute pointer
3101 const ast::InvariantAttribute* Invariant() { return create<ast::InvariantAttribute>(source_); }
3102
3103 /// Creates an ast::LocationAttribute
3104 /// @param source the source information
dan sinclairf9eeed62022-09-07 22:25:24 +00003105 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003106 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003107 template <typename EXPR>
3108 const ast::LocationAttribute* Location(const Source& source, EXPR&& location) {
3109 return create<ast::LocationAttribute>(source, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003110 }
3111
3112 /// Creates an ast::LocationAttribute
dan sinclairf9eeed62022-09-07 22:25:24 +00003113 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003114 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003115 template <typename EXPR>
3116 const ast::LocationAttribute* Location(EXPR&& location) {
3117 return create<ast::LocationAttribute>(source_, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003118 }
3119
3120 /// Creates an ast::IdAttribute
3121 /// @param source the source information
3122 /// @param id the id value
3123 /// @returns the override attribute pointer
Ben Clayton9a6acc42022-07-27 20:50:40 +00003124 const ast::IdAttribute* Id(const Source& source, OverrideId id) {
dan sinclair5361d9e2022-08-31 13:39:48 +00003125 return create<ast::IdAttribute>(source, Expr(AInt(id.value)));
Ben Clayton9a6acc42022-07-27 20:50:40 +00003126 }
3127
3128 /// Creates an ast::IdAttribute with an override identifier
3129 /// @param id the optional id value
3130 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003131 const ast::IdAttribute* Id(OverrideId id) {
3132 return create<ast::IdAttribute>(Expr(AInt(id.value)));
3133 }
Ben Clayton9a6acc42022-07-27 20:50:40 +00003134
3135 /// Creates an ast::IdAttribute
3136 /// @param source the source information
dan sinclair5361d9e2022-08-31 13:39:48 +00003137 /// @param id the id value expression
Ben Clayton9a6acc42022-07-27 20:50:40 +00003138 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003139 template <typename EXPR>
3140 const ast::IdAttribute* Id(const Source& source, EXPR&& id) {
3141 return create<ast::IdAttribute>(source, Expr(std::forward<EXPR>(id)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003142 }
3143
Ben Clayton9a6acc42022-07-27 20:50:40 +00003144 /// Creates an ast::IdAttribute with an override identifier
dan sinclair5361d9e2022-08-31 13:39:48 +00003145 /// @param id the optional id value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003146 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003147 template <typename EXPR>
3148 const ast::IdAttribute* Id(EXPR&& id) {
3149 return create<ast::IdAttribute>(Expr(std::forward<EXPR>(id)));
3150 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00003151
3152 /// Creates an ast::StageAttribute
3153 /// @param source the source information
3154 /// @param stage the pipeline stage
3155 /// @returns the stage attribute pointer
3156 const ast::StageAttribute* Stage(const Source& source, ast::PipelineStage stage) {
3157 return create<ast::StageAttribute>(source, stage);
3158 }
3159
3160 /// Creates an ast::StageAttribute
3161 /// @param stage the pipeline stage
3162 /// @returns the stage attribute pointer
3163 const ast::StageAttribute* Stage(ast::PipelineStage stage) {
3164 return create<ast::StageAttribute>(source_, stage);
3165 }
3166
3167 /// Creates an ast::WorkgroupAttribute
3168 /// @param x the x dimension expression
3169 /// @returns the workgroup attribute pointer
3170 template <typename EXPR_X>
3171 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x) {
3172 return WorkgroupSize(std::forward<EXPR_X>(x), nullptr, nullptr);
3173 }
3174
3175 /// Creates an ast::WorkgroupAttribute
Ben Claytonb8ac9332022-05-28 10:34:06 +00003176 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00003177 /// @param x the x dimension expression
dan sinclair7517e212022-08-24 21:31:45 +00003178 /// @returns the workgroup attribute pointer
3179 template <typename EXPR_X>
3180 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x) {
3181 return WorkgroupSize(source, std::forward<EXPR_X>(x), nullptr, nullptr);
3182 }
3183
3184 /// Creates an ast::WorkgroupAttribute
3185 /// @param source the source information
3186 /// @param x the x dimension expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003187 /// @param y the y dimension expression
3188 /// @returns the workgroup attribute pointer
3189 template <typename EXPR_X, typename EXPR_Y>
Ben Claytonb8ac9332022-05-28 10:34:06 +00003190 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x, EXPR_Y&& y) {
3191 return WorkgroupSize(source, std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3192 }
3193
3194 /// Creates an ast::WorkgroupAttribute
3195 /// @param x the x dimension expression
3196 /// @param y the y dimension expression
3197 /// @returns the workgroup attribute pointer
3198 template <typename EXPR_X, typename EXPR_Y, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003199 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y) {
3200 return WorkgroupSize(std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3201 }
3202
3203 /// Creates an ast::WorkgroupAttribute
3204 /// @param source the source information
3205 /// @param x the x dimension expression
3206 /// @param y the y dimension expression
3207 /// @param z the z dimension expression
3208 /// @returns the workgroup attribute pointer
3209 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z>
3210 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source,
3211 EXPR_X&& x,
3212 EXPR_Y&& y,
3213 EXPR_Z&& z) {
3214 return create<ast::WorkgroupAttribute>(source, Expr(std::forward<EXPR_X>(x)),
3215 Expr(std::forward<EXPR_Y>(y)),
3216 Expr(std::forward<EXPR_Z>(z)));
3217 }
3218
3219 /// Creates an ast::WorkgroupAttribute
3220 /// @param x the x dimension expression
3221 /// @param y the y dimension expression
3222 /// @param z the z dimension expression
3223 /// @returns the workgroup attribute pointer
Ben Claytonb8ac9332022-05-28 10:34:06 +00003224 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003225 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y, EXPR_Z&& z) {
3226 return create<ast::WorkgroupAttribute>(source_, Expr(std::forward<EXPR_X>(x)),
3227 Expr(std::forward<EXPR_Y>(y)),
3228 Expr(std::forward<EXPR_Z>(z)));
3229 }
3230
3231 /// Creates an ast::DisableValidationAttribute
3232 /// @param validation the validation to disable
3233 /// @returns the disable validation attribute pointer
3234 const ast::DisableValidationAttribute* Disable(ast::DisabledValidation validation) {
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003235 return ASTNodes().Create<ast::DisableValidationAttribute>(ID(), AllocateNodeID(),
3236 validation);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003237 }
3238
James Priceef5434d2023-01-24 18:44:27 +00003239 /// Creates an ast::DiagnosticAttribute
3240 /// @param source the source information
3241 /// @param severity the diagnostic severity control
3242 /// @param rule_name the diagnostic rule name
3243 /// @returns the diagnostic attribute pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003244 template <typename NAME>
3245 const ast::DiagnosticAttribute* DiagnosticAttribute(const Source& source,
3246 ast::DiagnosticSeverity severity,
3247 NAME&& rule_name) {
Ben Clayton2cdf1342023-02-03 13:24:18 +00003248 static_assert(!traits::IsType<traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
3249 "it is invalid for a diagnostic rule name to be templated");
Ben Clayton12914ee2023-02-02 22:20:32 +00003250 return create<ast::DiagnosticAttribute>(
James Price98dc5a82023-02-04 12:20:55 +00003251 source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
James Priceef5434d2023-01-24 18:44:27 +00003252 }
3253
3254 /// Creates an ast::DiagnosticAttribute
3255 /// @param severity the diagnostic severity control
3256 /// @param rule_name the diagnostic rule name
3257 /// @returns the diagnostic attribute pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003258 template <typename NAME>
3259 const ast::DiagnosticAttribute* DiagnosticAttribute(ast::DiagnosticSeverity severity,
3260 NAME&& rule_name) {
3261 return create<ast::DiagnosticAttribute>(
James Price98dc5a82023-02-04 12:20:55 +00003262 source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
James Priceef5434d2023-01-24 18:44:27 +00003263 }
3264
James Price98dc5a82023-02-04 12:20:55 +00003265 /// Add a diagnostic directive to the module.
James Price5f3449f2023-01-23 17:55:55 +00003266 /// @param source the source information
3267 /// @param severity the diagnostic severity control
3268 /// @param rule_name the diagnostic rule name
James Price98dc5a82023-02-04 12:20:55 +00003269 /// @returns the diagnostic directive pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003270 template <typename NAME>
James Price98dc5a82023-02-04 12:20:55 +00003271 const ast::DiagnosticDirective* DiagnosticDirective(const Source& source,
3272 ast::DiagnosticSeverity severity,
3273 NAME&& rule_name) {
3274 auto* directive = create<ast::DiagnosticDirective>(
3275 source, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
3276 AST().AddDiagnosticDirective(directive);
3277 return directive;
James Price5f3449f2023-01-23 17:55:55 +00003278 }
3279
James Price98dc5a82023-02-04 12:20:55 +00003280 /// Add a diagnostic directive to the module.
James Price5f3449f2023-01-23 17:55:55 +00003281 /// @param severity the diagnostic severity control
3282 /// @param rule_name the diagnostic rule name
James Price98dc5a82023-02-04 12:20:55 +00003283 /// @returns the diagnostic directive pointer
Ben Clayton12914ee2023-02-02 22:20:32 +00003284 template <typename NAME>
James Price98dc5a82023-02-04 12:20:55 +00003285 const ast::DiagnosticDirective* DiagnosticDirective(ast::DiagnosticSeverity severity,
3286 NAME&& rule_name) {
3287 auto* directive = create<ast::DiagnosticDirective>(
3288 source_, ast::DiagnosticControl(severity, Ident(std::forward<NAME>(rule_name))));
3289 AST().AddDiagnosticDirective(directive);
3290 return directive;
James Price15bf15d2023-01-24 21:01:36 +00003291 }
3292
dan sinclair41e4d9a2022-05-01 14:40:55 +00003293 /// Sets the current builder source to `src`
3294 /// @param src the Source used for future create() calls
3295 void SetSource(const Source& src) {
3296 AssertNotMoved();
3297 source_ = src;
3298 }
3299
3300 /// Sets the current builder source to `loc`
3301 /// @param loc the Source used for future create() calls
3302 void SetSource(const Source::Location& loc) {
3303 AssertNotMoved();
3304 source_ = Source(loc);
3305 }
3306
3307 /// Helper for returning the resolved semantic type of the expression `expr`.
3308 /// @note As the Resolver is run when the Program is built, this will only be
3309 /// useful for the Resolver itself and tests that use their own Resolver.
3310 /// @param expr the AST expression
3311 /// @return the resolved semantic type for the expression, or nullptr if the
3312 /// expression has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003313 const type::Type* TypeOf(const ast::Expression* expr) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003314
3315 /// Helper for returning the resolved semantic type of the variable `var`.
3316 /// @note As the Resolver is run when the Program is built, this will only be
3317 /// useful for the Resolver itself and tests that use their own Resolver.
3318 /// @param var the AST variable
3319 /// @return the resolved semantic type for the variable, or nullptr if the
3320 /// variable has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003321 const type::Type* TypeOf(const ast::Variable* var) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003322
3323 /// Helper for returning the resolved semantic type of the AST type `type`.
3324 /// @note As the Resolver is run when the Program is built, this will only be
3325 /// useful for the Resolver itself and tests that use their own Resolver.
3326 /// @param type the AST type
3327 /// @return the resolved semantic type for the type, or nullptr if the type
3328 /// has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003329 const type::Type* TypeOf(const ast::Type* type) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003330
3331 /// Helper for returning the resolved semantic type of the AST type
3332 /// declaration `type_decl`.
3333 /// @note As the Resolver is run when the Program is built, this will only be
3334 /// useful for the Resolver itself and tests that use their own Resolver.
3335 /// @param type_decl the AST type declaration
3336 /// @return the resolved semantic type for the type declaration, or nullptr if
3337 /// the type declaration has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003338 const type::Type* TypeOf(const ast::TypeDecl* type_decl) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003339
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003340 /// @param type a type
3341 /// @returns the name for `type` that closely resembles how it would be
3342 /// declared in WGSL.
Ben Claytond7d71882022-09-05 20:51:23 +00003343 std::string FriendlyName(const ast::Type* type) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003344
3345 /// @param type a type
3346 /// @returns the name for `type` that closely resembles how it would be
3347 /// declared in WGSL.
dan sinclair5f764d82022-12-08 00:32:27 +00003348 std::string FriendlyName(const type::Type* type) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003349
3350 /// Overload of FriendlyName, which removes an ambiguity when passing nullptr.
3351 /// Simplifies test code.
3352 /// @returns "<null>"
Ben Claytond7d71882022-09-05 20:51:23 +00003353 std::string FriendlyName(std::nullptr_t) const;
Ben Clayton1b35e3f2022-05-19 21:55:29 +00003354
dan sinclair41e4d9a2022-05-01 14:40:55 +00003355 /// Wraps the ast::Expression in a statement. This is used by tests that
3356 /// construct a partial AST and require the Resolver to reach these
3357 /// nodes.
3358 /// @param expr the ast::Expression to be wrapped by an ast::Statement
3359 /// @return the ast::Statement that wraps the ast::Expression
3360 const ast::Statement* WrapInStatement(const ast::Expression* expr);
3361 /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by
3362 /// tests that construct a partial AST and require the Resolver to reach
3363 /// these nodes.
3364 /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement
3365 /// @return the ast::VariableDeclStatement that wraps the ast::Variable
3366 const ast::VariableDeclStatement* WrapInStatement(const ast::Variable* v);
3367 /// Returns the statement argument. Used as a passthrough-overload by
3368 /// WrapInFunction().
3369 /// @param stmt the ast::Statement
3370 /// @return `stmt`
3371 const ast::Statement* WrapInStatement(const ast::Statement* stmt);
3372 /// Wraps the list of arguments in a simple function so that each is reachable
3373 /// by the Resolver.
3374 /// @param args a mix of ast::Expression, ast::Statement, ast::Variables.
3375 /// @returns the function
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003376 template <typename... ARGS,
3377 typename = traits::EnableIf<(CanWrapInStatement<ARGS>::value && ...)>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003378 const ast::Function* WrapInFunction(ARGS&&... args) {
Ben Clayton783b1692022-08-02 17:03:35 +00003379 utils::Vector stmts{
3380 WrapInStatement(std::forward<ARGS>(args))...,
3381 };
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003382 return WrapInFunction(std::move(stmts));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003383 }
3384 /// @param stmts a list of ast::Statement that will be wrapped by a function,
3385 /// so that each statement is reachable by the Resolver.
3386 /// @returns the function
Ben Clayton783b1692022-08-02 17:03:35 +00003387 const ast::Function* WrapInFunction(utils::VectorRef<const ast::Statement*> stmts);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003388
3389 /// The builder types
3390 TypesBuilder const ty{this};
3391
3392 protected:
3393 /// Asserts that the builder has not been moved.
3394 void AssertNotMoved() const;
3395
3396 private:
dan sinclaircf581222023-01-03 20:25:37 +00003397 const constant::Value* createSplatOrComposite(
3398 const type::Type* type,
3399 utils::VectorRef<const constant::Value*> elements);
3400
dan sinclair41e4d9a2022-05-01 14:40:55 +00003401 ProgramID id_;
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003402 ast::NodeID last_ast_node_id_ = ast::NodeID{static_cast<decltype(ast::NodeID::value)>(0) - 1};
dan sinclair837b8042022-12-09 05:00:07 +00003403 type::Manager types_;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003404 ASTNodeAllocator ast_nodes_;
3405 SemNodeAllocator sem_nodes_;
Ben Claytonaa037ac2022-06-29 19:07:30 +00003406 ConstantAllocator constant_nodes_;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003407 ast::Module* ast_;
3408 sem::Info sem_;
3409 SymbolTable symbols_{id_};
3410 diag::List diagnostics_;
3411
3412 /// The source to use when creating AST nodes without providing a Source as
3413 /// the first argument.
3414 Source source_;
3415
3416 /// Set by SetResolveOnBuild(). If set, the Resolver will be run on the
3417 /// program when built.
3418 bool resolve_on_build_ = true;
3419
3420 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder.
3421 bool moved_ = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003422};
3423
3424//! @cond Doxygen_Suppress
3425// Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
3426template <>
Ben Clayton46ee6392022-11-09 22:04:11 +00003427struct ProgramBuilder::TypesBuilder::CToAST<AInt> {
3428 static const ast::Type* get(const ProgramBuilder::TypesBuilder*) { return nullptr; }
3429};
3430template <>
3431struct ProgramBuilder::TypesBuilder::CToAST<AFloat> {
3432 static const ast::Type* get(const ProgramBuilder::TypesBuilder*) { return nullptr; }
3433};
3434template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003435struct ProgramBuilder::TypesBuilder::CToAST<i32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003436 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->i32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003437};
3438template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003439struct ProgramBuilder::TypesBuilder::CToAST<u32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003440 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->u32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003441};
3442template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003443struct ProgramBuilder::TypesBuilder::CToAST<f32> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003444 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003445};
3446template <>
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00003447struct ProgramBuilder::TypesBuilder::CToAST<f16> {
3448 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->f16(); }
3449};
3450template <>
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003451struct ProgramBuilder::TypesBuilder::CToAST<bool> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003452 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003453};
3454template <>
3455struct ProgramBuilder::TypesBuilder::CToAST<void> {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003456 static const ast::Type* get(const ProgramBuilder::TypesBuilder* t) { return t->void_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003457};
3458//! @endcond
3459
3460/// @param builder the ProgramBuilder
3461/// @returns the ProgramID of the ProgramBuilder
3462inline ProgramID ProgramIDOf(const ProgramBuilder* builder) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003463 return builder->ID();
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003464}
3465
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003466// Primary template for metafunction that evaluates to true iff T can be wrapped in a statement.
3467template <typename T, typename /* = void */>
3468struct CanWrapInStatement : std::false_type {};
3469
3470// Specialization of CanWrapInStatement
3471template <typename T>
3472struct CanWrapInStatement<
3473 T,
3474 std::void_t<decltype(std::declval<ProgramBuilder>().WrapInStatement(std::declval<T>()))>>
3475 : std::true_type {};
3476
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003477} // namespace tint
3478
3479#endif // SRC_TINT_PROGRAM_BUILDER_H_