blob: c27d090d8d05d756eea4ae30544f90486ff7afa4 [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
dan sinclair91b68cd2023-07-20 09:21:10 +000024#include "src/tint/core/string.h"
dan sinclairb14a7782023-07-20 09:21:10 +000025#include "src/tint/lang/base/builtin/extension.h"
26#include "src/tint/lang/base/builtin/fluent_types.h"
27#include "src/tint/lang/base/builtin/interpolation_sampling.h"
28#include "src/tint/lang/base/builtin/interpolation_type.h"
29#include "src/tint/lang/base/builtin/number.h"
dan sinclaira2e9b492023-07-20 09:21:10 +000030#include "src/tint/lang/base/constant/manager.h"
dan sinclair99181d82023-07-20 01:14:15 +000031#include "src/tint/lang/wgsl/ast/alias.h"
32#include "src/tint/lang/wgsl/ast/assignment_statement.h"
33#include "src/tint/lang/wgsl/ast/binary_expression.h"
34#include "src/tint/lang/wgsl/ast/binding_attribute.h"
35#include "src/tint/lang/wgsl/ast/bitcast_expression.h"
36#include "src/tint/lang/wgsl/ast/bool_literal_expression.h"
37#include "src/tint/lang/wgsl/ast/break_if_statement.h"
38#include "src/tint/lang/wgsl/ast/break_statement.h"
39#include "src/tint/lang/wgsl/ast/call_expression.h"
40#include "src/tint/lang/wgsl/ast/call_statement.h"
41#include "src/tint/lang/wgsl/ast/case_statement.h"
42#include "src/tint/lang/wgsl/ast/compound_assignment_statement.h"
43#include "src/tint/lang/wgsl/ast/const.h"
44#include "src/tint/lang/wgsl/ast/const_assert.h"
45#include "src/tint/lang/wgsl/ast/continue_statement.h"
46#include "src/tint/lang/wgsl/ast/diagnostic_attribute.h"
47#include "src/tint/lang/wgsl/ast/diagnostic_control.h"
48#include "src/tint/lang/wgsl/ast/diagnostic_directive.h"
49#include "src/tint/lang/wgsl/ast/diagnostic_rule_name.h"
50#include "src/tint/lang/wgsl/ast/disable_validation_attribute.h"
51#include "src/tint/lang/wgsl/ast/discard_statement.h"
52#include "src/tint/lang/wgsl/ast/enable.h"
53#include "src/tint/lang/wgsl/ast/float_literal_expression.h"
54#include "src/tint/lang/wgsl/ast/for_loop_statement.h"
55#include "src/tint/lang/wgsl/ast/id_attribute.h"
56#include "src/tint/lang/wgsl/ast/identifier.h"
57#include "src/tint/lang/wgsl/ast/if_statement.h"
58#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h"
59#include "src/tint/lang/wgsl/ast/index_accessor_expression.h"
60#include "src/tint/lang/wgsl/ast/index_attribute.h"
61#include "src/tint/lang/wgsl/ast/int_literal_expression.h"
62#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
63#include "src/tint/lang/wgsl/ast/invariant_attribute.h"
64#include "src/tint/lang/wgsl/ast/let.h"
65#include "src/tint/lang/wgsl/ast/loop_statement.h"
66#include "src/tint/lang/wgsl/ast/member_accessor_expression.h"
67#include "src/tint/lang/wgsl/ast/module.h"
68#include "src/tint/lang/wgsl/ast/must_use_attribute.h"
69#include "src/tint/lang/wgsl/ast/override.h"
70#include "src/tint/lang/wgsl/ast/parameter.h"
71#include "src/tint/lang/wgsl/ast/phony_expression.h"
72#include "src/tint/lang/wgsl/ast/return_statement.h"
73#include "src/tint/lang/wgsl/ast/stage_attribute.h"
74#include "src/tint/lang/wgsl/ast/stride_attribute.h"
75#include "src/tint/lang/wgsl/ast/struct_member_align_attribute.h"
76#include "src/tint/lang/wgsl/ast/struct_member_offset_attribute.h"
77#include "src/tint/lang/wgsl/ast/struct_member_size_attribute.h"
78#include "src/tint/lang/wgsl/ast/switch_statement.h"
79#include "src/tint/lang/wgsl/ast/templated_identifier.h"
80#include "src/tint/lang/wgsl/ast/type.h"
81#include "src/tint/lang/wgsl/ast/unary_op_expression.h"
82#include "src/tint/lang/wgsl/ast/var.h"
83#include "src/tint/lang/wgsl/ast/variable_decl_statement.h"
84#include "src/tint/lang/wgsl/ast/while_statement.h"
85#include "src/tint/lang/wgsl/ast/workgroup_attribute.h"
dan sinclaird3b13692023-07-20 01:14:15 +000086#include "src/tint/lang/wgsl/sem/array_count.h"
87#include "src/tint/lang/wgsl/sem/struct.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000088#include "src/tint/program.h"
89#include "src/tint/program_id.h"
dan sinclair946858a2022-12-08 22:21:24 +000090#include "src/tint/type/array.h"
dan sinclaird37ecf92022-12-08 16:39:59 +000091#include "src/tint/type/bool.h"
dan sinclair4595fb72022-12-08 14:14:10 +000092#include "src/tint/type/depth_texture.h"
93#include "src/tint/type/external_texture.h"
dan sinclaird37ecf92022-12-08 16:39:59 +000094#include "src/tint/type/f16.h"
95#include "src/tint/type/f32.h"
96#include "src/tint/type/i32.h"
dan sinclair0e780da2022-12-08 22:21:24 +000097#include "src/tint/type/matrix.h"
dan sinclair4595fb72022-12-08 14:14:10 +000098#include "src/tint/type/multisampled_texture.h"
dan sinclair4d56b482022-12-08 17:50:50 +000099#include "src/tint/type/pointer.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000100#include "src/tint/type/sampled_texture.h"
Ben Claytoned3389f2023-02-09 23:56:42 +0000101#include "src/tint/type/sampler_kind.h"
dan sinclair4595fb72022-12-08 14:14:10 +0000102#include "src/tint/type/storage_texture.h"
dan sinclair3cbf3fc2023-01-21 19:16:15 +0000103#include "src/tint/type/texture_dimension.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000104#include "src/tint/type/u32.h"
dan sinclair0e780da2022-12-08 22:21:24 +0000105#include "src/tint/type/vector.h"
dan sinclaird37ecf92022-12-08 16:39:59 +0000106#include "src/tint/type/void.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000107
Ben Clayton8fa6c252022-11-03 19:16:26 +0000108#ifdef CURRENTLY_IN_TINT_PUBLIC_HEADER
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000109#error "internal tint header being #included from tint.h"
110#endif
111
112// Forward declarations
Ben Claytona7230f02022-04-11 14:37:21 +0000113namespace tint {
114class CloneContext;
115} // namespace tint
dan sinclair8155b9d2022-04-07 19:10:25 +0000116namespace tint::ast {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000117class VariableDeclStatement;
dan sinclair8155b9d2022-04-07 19:10:25 +0000118} // namespace tint::ast
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000119
120namespace tint {
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000121
Ben Clayton971318f2023-02-14 13:52:43 +0000122/// Evaluates to true if T is a Infer, AInt or AFloat.
123template <typename T>
124static constexpr const bool IsInferOrAbstract =
Ben Clayton66805b02023-06-14 22:00:01 +0000125 std::is_same_v<std::decay_t<T>, builtin::fluent_types::Infer> || IsAbstract<std::decay_t<T>>;
Ben Clayton971318f2023-02-14 13:52:43 +0000126
Antonio Maioranodfa92a92022-12-23 17:56:56 +0000127// Forward declare metafunction that evaluates to true iff T can be wrapped in a statement.
128template <typename T, typename = void>
129struct CanWrapInStatement;
130
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000131/// ProgramBuilder is a mutable builder for a Program.
132/// To construct a Program, populate the builder and then `std::move` it to a
133/// Program.
134class ProgramBuilder {
Ben Clayton01ac21c2023-02-07 16:14:25 +0000135 /// Evaluates to true if T is a Source
136 template <typename T>
137 static constexpr const bool IsSource = std::is_same_v<T, Source>;
138
139 /// Evaluates to true if T is a Number or bool.
140 template <typename T>
141 static constexpr const bool IsScalar =
142 std::is_integral_v<UnwrapNumber<T>> || std::is_floating_point_v<UnwrapNumber<T>> ||
143 std::is_same_v<T, bool>;
144
Ben Clayton971318f2023-02-14 13:52:43 +0000145 /// Evaluates to true if T can be converted to an identifier.
146 template <typename T>
dan sinclair05590052023-04-19 16:52:46 +0000147 static constexpr const bool IsIdentifierLike = std::is_same_v<T, Symbol> || // Symbol
148 std::is_enum_v<T> || // Enum
149 utils::traits::IsStringLike<T>; // String
Ben Clayton971318f2023-02-14 13:52:43 +0000150
Ben Clayton01ac21c2023-02-07 16:14:25 +0000151 /// A helper used to disable overloads if the first type in `TYPES` is a Source. Used to avoid
152 /// ambiguities in overloads that take a Source as the first parameter and those that
153 /// perfectly-forward the first argument.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000154 template <typename... TYPES>
dan sinclair05590052023-04-19 16:52:46 +0000155 using DisableIfSource = utils::traits::EnableIf<
156 !IsSource<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
Ben Clayton01ac21c2023-02-07 16:14:25 +0000157
158 /// A helper used to disable overloads if the first type in `TYPES` is a scalar type. Used to
159 /// avoid ambiguities in overloads that take a scalar as the first parameter and those that
160 /// perfectly-forward the first argument.
161 template <typename... TYPES>
dan sinclair05590052023-04-19 16:52:46 +0000162 using DisableIfScalar = utils::traits::EnableIf<
163 !IsScalar<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000164
Ben Clayton971318f2023-02-14 13:52:43 +0000165 /// A helper used to enable overloads if the first type in `TYPES` is a scalar type. Used to
166 /// avoid ambiguities in overloads that take a scalar as the first parameter and those that
167 /// perfectly-forward the first argument.
168 template <typename... TYPES>
dan sinclair05590052023-04-19 16:52:46 +0000169 using EnableIfScalar = utils::traits::EnableIf<
170 IsScalar<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
Ben Clayton971318f2023-02-14 13:52:43 +0000171
Ben Clayton039ffdc2023-06-09 22:58:09 +0000172 /// A helper used to disable overloads if the first type in `TYPES` is a utils::Vector or
173 /// utils::VectorRef.
Ben Clayton783b1692022-08-02 17:03:35 +0000174 template <typename... TYPES>
Ben Clayton039ffdc2023-06-09 22:58:09 +0000175 using DisableIfVectorLike = utils::traits::EnableIf<
176 !utils::IsVectorLike<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
Ben Clayton783b1692022-08-02 17:03:35 +0000177
Ben Clayton971318f2023-02-14 13:52:43 +0000178 /// A helper used to enable overloads if the first type in `TYPES` is identifier-like.
179 template <typename... TYPES>
dan sinclair05590052023-04-19 16:52:46 +0000180 using EnableIfIdentifierLike = utils::traits::EnableIf<
181 IsIdentifierLike<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
Ben Clayton971318f2023-02-14 13:52:43 +0000182
183 /// A helper used to disable overloads if the first type in `TYPES` is Infer or an abstract
184 /// numeric.
185 template <typename... TYPES>
dan sinclair05590052023-04-19 16:52:46 +0000186 using DisableIfInferOrAbstract = utils::traits::EnableIf<
187 !IsInferOrAbstract<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
Ben Clayton971318f2023-02-14 13:52:43 +0000188
189 /// A helper used to enable overloads if the first type in `TYPES` is Infer or an abstract
190 /// numeric.
191 template <typename... TYPES>
dan sinclair05590052023-04-19 16:52:46 +0000192 using EnableIfInferOrAbstract = utils::traits::EnableIf<
193 IsInferOrAbstract<utils::traits::Decay<utils::traits::NthTypeOf<0, TYPES..., void>>>>;
Ben Clayton971318f2023-02-14 13:52:43 +0000194
Ben Clayton58794ae2022-08-19 17:28:53 +0000195 /// VarOptions is a helper for accepting an arbitrary number of order independent options for
196 /// constructing an ast::Var.
197 struct VarOptions {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000198 template <typename... ARGS>
Ben Clayton79781f22023-02-18 17:13:18 +0000199 explicit VarOptions(ProgramBuilder& b, ARGS&&... args) {
200 (Set(b, std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000201 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000202 ~VarOptions();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000203
Ben Clayton971318f2023-02-14 13:52:43 +0000204 ast::Type type;
Ben Clayton79781f22023-02-18 17:13:18 +0000205 const ast::Expression* address_space = nullptr;
206 const ast::Expression* access = nullptr;
dan sinclair6e77b472022-10-20 13:38:28 +0000207 const ast::Expression* initializer = nullptr;
Ben Clayton783b1692022-08-02 17:03:35 +0000208 utils::Vector<const ast::Attribute*, 4> attributes;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000209
dan sinclair41e4d9a2022-05-01 14:40:55 +0000210 private:
Ben Clayton79781f22023-02-18 17:13:18 +0000211 void Set(ProgramBuilder&, ast::Type t) { type = t; }
dan sinclair2a651632023-02-19 04:03:55 +0000212 void Set(ProgramBuilder& b, builtin::AddressSpace addr_space) {
213 if (addr_space != builtin::AddressSpace::kUndefined) {
Ben Clayton79781f22023-02-18 17:13:18 +0000214 address_space = b.Expr(addr_space);
215 }
216 }
dan sinclairb6cc4cb2023-02-19 04:01:29 +0000217 void Set(ProgramBuilder& b, builtin::Access ac) {
218 if (ac != builtin::Access::kUndefined) {
Ben Clayton79781f22023-02-18 17:13:18 +0000219 access = b.Expr(ac);
220 }
221 }
222 void Set(ProgramBuilder&, const ast::Expression* c) { initializer = c; }
223 void Set(ProgramBuilder&, utils::VectorRef<const ast::Attribute*> l) {
224 attributes = std::move(l);
225 }
226 void Set(ProgramBuilder&, const ast::Attribute* a) { attributes.Push(a); }
Ben Clayton58794ae2022-08-19 17:28:53 +0000227 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000228
Ben Clayton58794ae2022-08-19 17:28:53 +0000229 /// LetOptions is a helper for accepting an arbitrary number of order independent options for
230 /// constructing an ast::Let.
231 struct LetOptions {
232 template <typename... ARGS>
233 explicit LetOptions(ARGS&&... args) {
234 static constexpr bool has_init =
dan sinclair05590052023-04-19 16:52:46 +0000235 (utils::traits::IsTypeOrDerived<utils::traits::PtrElTy<ARGS>, ast::Expression> ||
236 ...);
Ben Clayton58794ae2022-08-19 17:28:53 +0000237 static_assert(has_init, "Let() must be constructed with an initializer expression");
238 (Set(std::forward<ARGS>(args)), ...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000239 }
Ben Clayton58794ae2022-08-19 17:28:53 +0000240 ~LetOptions();
241
Ben Clayton971318f2023-02-14 13:52:43 +0000242 ast::Type type;
dan sinclair6e77b472022-10-20 13:38:28 +0000243 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000244 utils::Vector<const ast::Attribute*, 4> attributes;
245
246 private:
Ben Clayton971318f2023-02-14 13:52:43 +0000247 void Set(ast::Type t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000248 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000249 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
250 void Set(const ast::Attribute* a) { attributes.Push(a); }
251 };
252
253 /// ConstOptions is a helper for accepting an arbitrary number of order independent options for
254 /// constructing an ast::Const.
255 struct ConstOptions {
256 template <typename... ARGS>
257 explicit ConstOptions(ARGS&&... args) {
258 static constexpr bool has_init =
dan sinclair05590052023-04-19 16:52:46 +0000259 (utils::traits::IsTypeOrDerived<utils::traits::PtrElTy<ARGS>, ast::Expression> ||
260 ...);
Ben Clayton58794ae2022-08-19 17:28:53 +0000261 static_assert(has_init, "Const() must be constructed with an initializer expression");
262 (Set(std::forward<ARGS>(args)), ...);
263 }
264 ~ConstOptions();
265
Ben Clayton971318f2023-02-14 13:52:43 +0000266 ast::Type type;
dan sinclair6e77b472022-10-20 13:38:28 +0000267 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000268 utils::Vector<const ast::Attribute*, 4> attributes;
269
270 private:
Ben Clayton971318f2023-02-14 13:52:43 +0000271 void Set(ast::Type t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000272 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000273 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
274 void Set(const ast::Attribute* a) { attributes.Push(a); }
275 };
276
277 /// OverrideOptions is a helper for accepting an arbitrary number of order independent options
278 /// for constructing an ast::Override.
279 struct OverrideOptions {
280 template <typename... ARGS>
281 explicit OverrideOptions(ARGS&&... args) {
282 (Set(std::forward<ARGS>(args)), ...);
283 }
284 ~OverrideOptions();
285
Ben Clayton971318f2023-02-14 13:52:43 +0000286 ast::Type type;
dan sinclair6e77b472022-10-20 13:38:28 +0000287 const ast::Expression* initializer = nullptr;
Ben Clayton58794ae2022-08-19 17:28:53 +0000288 utils::Vector<const ast::Attribute*, 4> attributes;
289
290 private:
Ben Clayton971318f2023-02-14 13:52:43 +0000291 void Set(ast::Type t) { type = t; }
dan sinclair6e77b472022-10-20 13:38:28 +0000292 void Set(const ast::Expression* c) { initializer = c; }
Ben Clayton58794ae2022-08-19 17:28:53 +0000293 void Set(utils::VectorRef<const ast::Attribute*> l) { attributes = std::move(l); }
294 void Set(const ast::Attribute* a) { attributes.Push(a); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000295 };
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000296
dan sinclair41e4d9a2022-05-01 14:40:55 +0000297 public:
298 /// ASTNodeAllocator is an alias to BlockAllocator<ast::Node>
299 using ASTNodeAllocator = utils::BlockAllocator<ast::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000300
dan sinclair41e4d9a2022-05-01 14:40:55 +0000301 /// SemNodeAllocator is an alias to BlockAllocator<sem::Node>
302 using SemNodeAllocator = utils::BlockAllocator<sem::Node>;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000303
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000304 /// Constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000305 ProgramBuilder();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000306
dan sinclair41e4d9a2022-05-01 14:40:55 +0000307 /// Move constructor
308 /// @param rhs the builder to move
309 ProgramBuilder(ProgramBuilder&& rhs);
310
311 /// Destructor
312 virtual ~ProgramBuilder();
313
314 /// Move assignment operator
315 /// @param rhs the builder to move
316 /// @return this builder
317 ProgramBuilder& operator=(ProgramBuilder&& rhs);
318
319 /// Wrap returns a new ProgramBuilder wrapping the Program `program` without
320 /// making a deep clone of the Program contents.
321 /// ProgramBuilder returned by Wrap() is intended to temporarily extend an
322 /// existing immutable program.
323 /// As the returned ProgramBuilder wraps `program`, `program` must not be
324 /// destructed or assigned while using the returned ProgramBuilder.
325 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this
326 /// function. See crbug.com/tint/460.
327 /// @param program the immutable Program to wrap
328 /// @return the ProgramBuilder that wraps `program`
329 static ProgramBuilder Wrap(const Program* program);
330
331 /// @returns the unique identifier for this program
332 ProgramID ID() const { return id_; }
333
334 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000335 type::Manager& Types() {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000336 AssertNotMoved();
Ben Clayton1e67e532023-05-24 23:07:36 +0000337 return constants.types;
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000338 }
339
dan sinclair41e4d9a2022-05-01 14:40:55 +0000340 /// @returns a reference to the program's types
dan sinclair837b8042022-12-09 05:00:07 +0000341 const type::Manager& Types() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000342 AssertNotMoved();
Ben Clayton1e67e532023-05-24 23:07:36 +0000343 return constants.types;
dan sinclair41e4d9a2022-05-01 14:40:55 +0000344 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000345
dan sinclair41e4d9a2022-05-01 14:40:55 +0000346 /// @returns a reference to the program's AST nodes storage
347 ASTNodeAllocator& ASTNodes() {
348 AssertNotMoved();
349 return ast_nodes_;
350 }
351
352 /// @returns a reference to the program's AST nodes storage
353 const ASTNodeAllocator& ASTNodes() const {
354 AssertNotMoved();
355 return ast_nodes_;
356 }
357
358 /// @returns a reference to the program's semantic nodes storage
359 SemNodeAllocator& SemNodes() {
360 AssertNotMoved();
361 return sem_nodes_;
362 }
363
364 /// @returns a reference to the program's semantic nodes storage
365 const SemNodeAllocator& SemNodes() const {
366 AssertNotMoved();
367 return sem_nodes_;
368 }
369
370 /// @returns a reference to the program's AST root Module
371 ast::Module& AST() {
372 AssertNotMoved();
373 return *ast_;
374 }
375
376 /// @returns a reference to the program's AST root Module
377 const ast::Module& AST() const {
378 AssertNotMoved();
379 return *ast_;
380 }
381
382 /// @returns a reference to the program's semantic info
383 sem::Info& Sem() {
384 AssertNotMoved();
385 return sem_;
386 }
387
388 /// @returns a reference to the program's semantic info
389 const sem::Info& Sem() const {
390 AssertNotMoved();
391 return sem_;
392 }
393
394 /// @returns a reference to the program's SymbolTable
395 SymbolTable& Symbols() {
396 AssertNotMoved();
397 return symbols_;
398 }
399
400 /// @returns a reference to the program's SymbolTable
401 const SymbolTable& Symbols() const {
402 AssertNotMoved();
403 return symbols_;
404 }
405
406 /// @returns a reference to the program's diagnostics
407 diag::List& Diagnostics() {
408 AssertNotMoved();
409 return diagnostics_;
410 }
411
412 /// @returns a reference to the program's diagnostics
413 const diag::List& Diagnostics() const {
414 AssertNotMoved();
415 return diagnostics_;
416 }
417
418 /// Controls whether the Resolver will be run on the program when it is built.
419 /// @param enable the new flag value (defaults to true)
420 void SetResolveOnBuild(bool enable) { resolve_on_build_ = enable; }
421
422 /// @return true if the Resolver will be run on the program when it is
423 /// built.
424 bool ResolveOnBuild() const { return resolve_on_build_; }
425
426 /// @returns true if the program has no error diagnostics and is not missing
427 /// information
428 bool IsValid() const;
429
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000430 /// @returns the last allocated (numerically highest) AST node identifier.
431 ast::NodeID LastAllocatedNodeID() const { return last_ast_node_id_; }
432
433 /// @returns the next sequentially unique node identifier.
434 ast::NodeID AllocateNodeID() {
435 auto out = ast::NodeID{last_ast_node_id_.value + 1};
436 last_ast_node_id_ = out;
437 return out;
438 }
439
dan sinclair41e4d9a2022-05-01 14:40:55 +0000440 /// Creates a new ast::Node owned by the ProgramBuilder. When the
441 /// ProgramBuilder is destructed, the ast::Node will also be destructed.
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000442 /// @param source the Source of the node
Ben Clayton54a104e2023-02-22 20:04:40 +0000443 /// @param args the arguments to pass to the constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000444 /// @returns the node pointer
445 template <typename T, typename... ARGS>
dan sinclair05590052023-04-19 16:52:46 +0000446 utils::traits::EnableIfIsType<T, ast::Node>* create(const Source& source, ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000447 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000448 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000449 }
450
dan sinclair41e4d9a2022-05-01 14:40:55 +0000451 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
452 /// Source as set by the last call to SetSource() as the only argument to the
453 /// constructor.
454 /// When the ProgramBuilder is destructed, the ast::Node will also be
455 /// destructed.
456 /// @returns the node pointer
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000457 template <typename T>
dan sinclair05590052023-04-19 16:52:46 +0000458 utils::traits::EnableIfIsType<T, ast::Node>* create() {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000459 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000460 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000461 }
462
dan sinclair41e4d9a2022-05-01 14:40:55 +0000463 /// Creates a new ast::Node owned by the ProgramBuilder, injecting the current
464 /// Source as set by the last call to SetSource() as the first argument to the
465 /// constructor.
466 /// When the ProgramBuilder is destructed, the ast::Node will also be
467 /// destructed.
Ben Clayton54a104e2023-02-22 20:04:40 +0000468 /// @param arg0 the first arguments to pass to the constructor
469 /// @param args the remaining arguments to pass to the constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000470 /// @returns the node pointer
471 template <typename T, typename ARG0, typename... ARGS>
dan sinclair05590052023-04-19 16:52:46 +0000472 utils::traits::EnableIf</* T is ast::Node and ARG0 is not Source */
473 utils::traits::IsTypeOrDerived<T, ast::Node> &&
474 !utils::traits::IsTypeOrDerived<ARG0, Source>,
475 T>*
dan sinclair41e4d9a2022-05-01 14:40:55 +0000476 create(ARG0&& arg0, ARGS&&... args) {
477 AssertNotMoved();
Ben Clayton4a92a3c2022-07-18 20:50:02 +0000478 return ast_nodes_.Create<T>(id_, AllocateNodeID(), source_, std::forward<ARG0>(arg0),
dan sinclair41e4d9a2022-05-01 14:40:55 +0000479 std::forward<ARGS>(args)...);
480 }
481
482 /// Creates a new sem::Node owned by the ProgramBuilder.
Ben Claytonaa037ac2022-06-29 19:07:30 +0000483 /// When the ProgramBuilder is destructed, the sem::Node will also be destructed.
484 /// @param args the arguments to pass to the constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +0000485 /// @returns the node pointer
486 template <typename T, typename... ARGS>
dan sinclair05590052023-04-19 16:52:46 +0000487 utils::traits::EnableIf<utils::traits::IsTypeOrDerived<T, sem::Node> &&
488 !utils::traits::IsTypeOrDerived<T, type::Node>,
489 T>*
dan sinclair41e4d9a2022-05-01 14:40:55 +0000490 create(ARGS&&... args) {
491 AssertNotMoved();
492 return sem_nodes_.Create<T>(std::forward<ARGS>(args)...);
493 }
494
Ben Clayton7c3e9a62022-12-16 15:31:19 +0000495 /// Creates a new type::Node owned by the ProgramBuilder.
496 /// When the ProgramBuilder is destructed, owned ProgramBuilder and the returned node will also
497 /// be destructed. If T derives from type::UniqueNode, then the calling create() for the same
498 /// `T` and arguments will return the same pointer.
499 /// @param args the arguments to pass to the constructor
500 /// @returns the new, or existing node
dan sinclair41e4d9a2022-05-01 14:40:55 +0000501 template <typename T, typename... ARGS>
dan sinclair05590052023-04-19 16:52:46 +0000502 utils::traits::EnableIfIsType<T, type::Node>* create(ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000503 AssertNotMoved();
Ben Clayton1e67e532023-05-24 23:07:36 +0000504 return constants.types.Get<T>(std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000505 }
dan sinclair5f764d82022-12-08 00:32:27 +0000506
dan sinclair41e4d9a2022-05-01 14:40:55 +0000507 /// Marks this builder as moved, preventing any further use of the builder.
508 void MarkAsMoved();
509
510 //////////////////////////////////////////////////////////////////////////////
511 // TypesBuilder
512 //////////////////////////////////////////////////////////////////////////////
513
514 /// TypesBuilder holds basic `tint` types and methods for constructing
515 /// complex types.
516 class TypesBuilder {
517 public:
518 /// Constructor
519 /// @param builder the program builder
520 explicit TypesBuilder(ProgramBuilder* builder);
521
Ben Clayton971318f2023-02-14 13:52:43 +0000522 /// @return the C type `T`.
dan sinclair41e4d9a2022-05-01 14:40:55 +0000523 template <typename T>
Ben Clayton971318f2023-02-14 13:52:43 +0000524 ast::Type Of() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000525 return CToAST<T>::get(this);
526 }
527
Ben Clayton971318f2023-02-14 13:52:43 +0000528 /// @param type the type to return
529 /// @return type (passthrough)
530 ast::Type operator()(const ast::Type& type) const { return type; }
Ben Clayton19068572023-02-07 21:28:09 +0000531
Ben Clayton971318f2023-02-14 13:52:43 +0000532 /// Creates a type
533 /// @param name the name
534 /// @param args the optional template arguments
535 /// @returns the type
536 template <typename NAME,
537 typename... ARGS,
538 typename = DisableIfSource<NAME>,
539 typename = std::enable_if_t<!std::is_same_v<std::decay_t<NAME>, ast::Type>>>
540 ast::Type operator()(NAME&& name, ARGS&&... args) const {
dan sinclair05590052023-04-19 16:52:46 +0000541 if constexpr (utils::traits::IsTypeOrDerived<utils::traits::PtrElTy<NAME>,
542 ast::Expression>) {
Ben Clayton971318f2023-02-14 13:52:43 +0000543 static_assert(sizeof...(ARGS) == 0);
544 return {name};
545 } else {
546 return {builder->Expr(
547 builder->Ident(std::forward<NAME>(name), std::forward<ARGS>(args)...))};
548 }
549 }
550
551 /// Creates a type
552 /// @param source the Source of the node
553 /// @param name the name
554 /// @param args the optional template arguments
555 /// @returns the type
556 template <typename NAME,
557 typename... ARGS,
558 typename = std::enable_if_t<!std::is_same_v<std::decay_t<NAME>, ast::Type>>>
559 ast::Type operator()(const Source& source, NAME&& name, ARGS&&... args) const {
560 return {builder->Expr(
561 builder->Ident(source, std::forward<NAME>(name), std::forward<ARGS>(args)...))};
562 }
563
564 /// @returns a a nullptr expression wrapped in an ast::Type
565 ast::Type void_() const { return ast::Type{}; }
566
567 /// @returns a 'bool' type
568 ast::Type bool_() const { return (*this)("bool"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000569
570 /// @param source the Source of the node
Ben Clayton971318f2023-02-14 13:52:43 +0000571 /// @returns a 'bool' type
572 ast::Type bool_(const Source& source) const { return (*this)(source, "bool"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000573
Ben Clayton971318f2023-02-14 13:52:43 +0000574 /// @returns a 'f16' type
575 ast::Type f16() const { return (*this)("f16"); }
Zhaoming Jiang62bfd312022-05-13 12:01:11 +0000576
577 /// @param source the Source of the node
Ben Clayton971318f2023-02-14 13:52:43 +0000578 /// @returns a 'f16' type
579 ast::Type f16(const Source& source) const { return (*this)(source, "f16"); }
Zhaoming Jiang62bfd312022-05-13 12:01:11 +0000580
Ben Clayton971318f2023-02-14 13:52:43 +0000581 /// @returns a 'f32' type
582 ast::Type f32() const { return (*this)("f32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000583
584 /// @param source the Source of the node
Ben Clayton971318f2023-02-14 13:52:43 +0000585 /// @returns a 'f32' type
586 ast::Type f32(const Source& source) const { return (*this)(source, "f32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000587
Ben Clayton971318f2023-02-14 13:52:43 +0000588 /// @returns a 'i32' type
589 ast::Type i32() const { return (*this)("i32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000590
591 /// @param source the Source of the node
Ben Clayton971318f2023-02-14 13:52:43 +0000592 /// @returns a 'i32' type
593 ast::Type i32(const Source& source) const { return (*this)(source, "i32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000594
Ben Clayton971318f2023-02-14 13:52:43 +0000595 /// @returns a 'u32' type
596 ast::Type u32() const { return (*this)("u32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000597
598 /// @param source the Source of the node
Ben Clayton971318f2023-02-14 13:52:43 +0000599 /// @returns a 'u32' type
600 ast::Type u32(const Source& source) const { return (*this)(source, "u32"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000601
dan sinclair41e4d9a2022-05-01 14:40:55 +0000602 /// @param type vector subtype
603 /// @param n vector width in elements
Ben Clayton971318f2023-02-14 13:52:43 +0000604 /// @return a @p n element vector of @p type
605 ast::Type vec(ast::Type type, uint32_t n) const { return vec(builder->source_, type, n); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000606
607 /// @param source the Source of the node
608 /// @param type vector subtype
609 /// @param n vector width in elements
Ben Clayton971318f2023-02-14 13:52:43 +0000610 /// @return a @p n element vector of @p type
611 ast::Type vec(const Source& source, ast::Type type, uint32_t n) const {
612 switch (n) {
613 case 2:
614 return vec2(source, type);
615 case 3:
616 return vec3(source, type);
617 case 4:
618 return vec4(source, type);
619 }
620 TINT_ICE(ProgramBuilder, builder->Diagnostics()) << "invalid vector width " << n;
621 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +0000622 }
623
624 /// @param type vector subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000625 /// @return a 2-element vector of @p type
626 ast::Type vec2(ast::Type type) const { return vec2(builder->source_, type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000627
Ben Clayton6315a272022-08-01 17:18:04 +0000628 /// @param source the vector source
629 /// @param type vector subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000630 /// @return a 2-element vector of @p type
631 ast::Type vec2(const Source& source, ast::Type type) const {
632 return (*this)(source, "vec2", type);
Ben Clayton6315a272022-08-01 17:18:04 +0000633 }
634
dan sinclair41e4d9a2022-05-01 14:40:55 +0000635 /// @param type vector subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000636 /// @return a 3-element vector of @p type
637 ast::Type vec3(ast::Type type) const { return vec3(builder->source_, type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000638
Ben Clayton6315a272022-08-01 17:18:04 +0000639 /// @param source the vector source
640 /// @param type vector subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000641 /// @return a 3-element vector of @p type
642 ast::Type vec3(const Source& source, ast::Type type) const {
643 return (*this)(source, "vec3", type);
Ben Clayton6315a272022-08-01 17:18:04 +0000644 }
645
dan sinclair41e4d9a2022-05-01 14:40:55 +0000646 /// @param type vector subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000647 /// @return a 4-element vector of @p type
648 ast::Type vec4(ast::Type type) const { return vec4(builder->source_, type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000649
Ben Clayton6315a272022-08-01 17:18:04 +0000650 /// @param source the vector source
651 /// @param type vector subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000652 /// @return a 4-element vector of @p type
653 ast::Type vec4(const Source& source, ast::Type type) const {
654 return (*this)(source, "vec4", type);
655 }
656
657 /// @param source the Source of the node
658 /// @return a 2-element vector of the type `T`
659 template <typename T>
660 ast::Type vec2(const Source& source) const {
661 if constexpr (IsInferOrAbstract<T>) {
662 return (*this)(source, "vec2");
663 } else {
664 return (*this)(source, "vec2", Of<T>());
665 }
666 }
667
668 /// @param source the Source of the node
669 /// @return a 3-element vector of the type `T`
670 template <typename T>
671 ast::Type vec3(const Source& source) const {
672 if constexpr (IsInferOrAbstract<T>) {
673 return (*this)(source, "vec3");
674 } else {
675 return (*this)(source, "vec3", Of<T>());
676 }
677 }
678
679 /// @param source the Source of the node
680 /// @return a 4-element vector of the type `T`
681 template <typename T>
682 ast::Type vec4(const Source& source) const {
683 if constexpr (IsInferOrAbstract<T>) {
684 return (*this)(source, "vec4");
685 } else {
686 return (*this)(source, "vec4", Of<T>());
687 }
688 }
689
690 /// @return a 2-element vector of the type `T`
691 template <typename T>
692 ast::Type vec2() const {
693 return vec2<T>(builder->source_);
694 }
695
696 /// @return a 3-element vector of the type `T`
697 template <typename T>
698 ast::Type vec3() const {
699 return vec3<T>(builder->source_);
700 }
701
702 /// @return a 4-element vector of the type `T`
703 template <typename T>
704 ast::Type vec4() const {
705 return vec4<T>(builder->source_);
706 }
707
708 /// @param source the Source of the node
709 /// @param n vector width in elements
710 /// @return a @p n element vector of @p type
711 template <typename T>
712 ast::Type vec(const Source& source, uint32_t n) const {
713 switch (n) {
714 case 2:
715 return vec2<T>(source);
716 case 3:
717 return vec3<T>(source);
718 case 4:
719 return vec4<T>(source);
720 }
721 TINT_ICE(ProgramBuilder, builder->Diagnostics()) << "invalid vector width " << n;
722 return ast::Type{};
723 }
724
725 /// @return a @p N element vector of @p type
726 template <typename T, uint32_t N>
727 ast::Type vec() const {
728 return vec<T>(builder->source_, N);
Ben Clayton6315a272022-08-01 17:18:04 +0000729 }
730
dan sinclair41e4d9a2022-05-01 14:40:55 +0000731 /// @param n vector width in elements
Ben Clayton971318f2023-02-14 13:52:43 +0000732 /// @return a @p n element vector of @p type
dan sinclair41e4d9a2022-05-01 14:40:55 +0000733 template <typename T>
Ben Clayton971318f2023-02-14 13:52:43 +0000734 ast::Type vec(uint32_t n) const {
735 return vec<T>(builder->source_, n);
Ben Clayton6315a272022-08-01 17:18:04 +0000736 }
737
dan sinclair41e4d9a2022-05-01 14:40:55 +0000738 /// @param type matrix subtype
739 /// @param columns number of columns for the matrix
740 /// @param rows number of rows for the matrix
Ben Clayton971318f2023-02-14 13:52:43 +0000741 /// @return a matrix of @p type
742 ast::Type mat(ast::Type type, uint32_t columns, uint32_t rows) const {
743 return mat(builder->source_, type, columns, rows);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000744 }
745
746 /// @param source the Source of the node
747 /// @param type matrix subtype
748 /// @param columns number of columns for the matrix
749 /// @param rows number of rows for the matrix
Ben Clayton971318f2023-02-14 13:52:43 +0000750 /// @return a matrix of @p type
751 ast::Type mat(const Source& source, ast::Type type, uint32_t columns, uint32_t rows) const {
752 if (TINT_LIKELY(columns >= 2 && columns <= 4 && rows >= 2 && rows <= 4)) {
753 static constexpr const char* names[] = {
754 "mat2x2", "mat2x3", "mat2x4", //
755 "mat3x2", "mat3x3", "mat3x4", //
756 "mat4x2", "mat4x3", "mat4x4", //
757 };
758 auto i = (columns - 2) * 3 + (rows - 2);
759 return (*this)(source, names[i], type);
760 }
761 TINT_ICE(ProgramBuilder, builder->Diagnostics())
762 << "invalid matrix dimensions " << columns << "x" << rows;
763 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +0000764 }
765
766 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000767 /// @return a 2x3 matrix of @p type.
768 ast::Type mat2x2(ast::Type type) const { return (*this)("mat2x2", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000769
770 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000771 /// @return a 2x3 matrix of @p type.
772 ast::Type mat2x3(ast::Type type) const { return (*this)("mat2x3", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000773
774 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000775 /// @return a 2x4 matrix of @p type.
776 ast::Type mat2x4(ast::Type type) const { return (*this)("mat2x4", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000777
778 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000779 /// @return a 3x2 matrix of @p type.
780 ast::Type mat3x2(ast::Type type) const { return (*this)("mat3x2", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000781
782 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000783 /// @return a 3x3 matrix of @p type.
784 ast::Type mat3x3(ast::Type type) const { return (*this)("mat3x3", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000785
786 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000787 /// @return a 3x4 matrix of @p type.
788 ast::Type mat3x4(ast::Type type) const { return (*this)("mat3x4", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000789
790 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000791 /// @return a 4x2 matrix of @p type.
792 ast::Type mat4x2(ast::Type type) const { return (*this)("mat4x2", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000793
794 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000795 /// @return a 4x3 matrix of @p type.
796 ast::Type mat4x3(ast::Type type) const { return (*this)("mat4x3", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000797
798 /// @param type matrix subtype
Ben Clayton971318f2023-02-14 13:52:43 +0000799 /// @return a 4x4 matrix of @p type.
800 ast::Type mat4x4(ast::Type type) const { return (*this)("mat4x4", type); }
801
802 /// @param source the source of the type
803 /// @return a 2x2 matrix of the type `T`
804 template <typename T>
805 ast::Type mat2x2(const Source& source) const {
806 if constexpr (IsInferOrAbstract<T>) {
807 return (*this)(source, "mat2x2");
808 } else {
809 return (*this)(source, "mat2x2", Of<T>());
810 }
811 }
812
813 /// @param source the source of the type
814 /// @return a 2x3 matrix of the type `T`
815 template <typename T>
816 ast::Type mat2x3(const Source& source) const {
817 if constexpr (IsInferOrAbstract<T>) {
818 return (*this)(source, "mat2x3");
819 } else {
820 return (*this)(source, "mat2x3", Of<T>());
821 }
822 }
823
824 /// @param source the source of the type
825 /// @return a 2x4 matrix of the type `T`
826 template <typename T>
827 ast::Type mat2x4(const Source& source) const {
828 if constexpr (IsInferOrAbstract<T>) {
829 return (*this)(source, "mat2x4");
830 } else {
831 return (*this)(source, "mat2x4", Of<T>());
832 }
833 }
834
835 /// @param source the source of the type
836 /// @return a 3x2 matrix of the type `T`
837 template <typename T>
838 ast::Type mat3x2(const Source& source) const {
839 if constexpr (IsInferOrAbstract<T>) {
840 return (*this)(source, "mat3x2");
841 } else {
842 return (*this)(source, "mat3x2", Of<T>());
843 }
844 }
845
846 /// @param source the source of the type
847 /// @return a 3x3 matrix of the type `T`
848 template <typename T>
849 ast::Type mat3x3(const Source& source) const {
850 if constexpr (IsInferOrAbstract<T>) {
851 return (*this)(source, "mat3x3");
852 } else {
853 return (*this)(source, "mat3x3", Of<T>());
854 }
855 }
856
857 /// @param source the source of the type
858 /// @return a 3x4 matrix of the type `T`
859 template <typename T>
860 ast::Type mat3x4(const Source& source) const {
861 if constexpr (IsInferOrAbstract<T>) {
862 return (*this)(source, "mat3x4");
863 } else {
864 return (*this)(source, "mat3x4", Of<T>());
865 }
866 }
867
868 /// @param source the source of the type
869 /// @return a 4x2 matrix of the type `T`
870 template <typename T>
871 ast::Type mat4x2(const Source& source) const {
872 if constexpr (IsInferOrAbstract<T>) {
873 return (*this)(source, "mat4x2");
874 } else {
875 return (*this)(source, "mat4x2", Of<T>());
876 }
877 }
878
879 /// @param source the source of the type
880 /// @return a 4x3 matrix of the type `T`
881 template <typename T>
882 ast::Type mat4x3(const Source& source) const {
883 if constexpr (IsInferOrAbstract<T>) {
884 return (*this)(source, "mat4x3");
885 } else {
886 return (*this)(source, "mat4x3", Of<T>());
887 }
888 }
889
890 /// @param source the source of the type
891 /// @return a 4x4 matrix of the type `T`
892 template <typename T>
893 ast::Type mat4x4(const Source& source) const {
894 if constexpr (IsInferOrAbstract<T>) {
895 return (*this)(source, "mat4x4");
896 } else {
897 return (*this)(source, "mat4x4", Of<T>());
898 }
899 }
900
901 /// @return a 2x2 matrix of the type `T`
902 template <typename T>
903 ast::Type mat2x2() const {
904 return mat2x2<T>(builder->source_);
905 }
906
907 /// @return a 2x3 matrix of the type `T`
908 template <typename T>
909 ast::Type mat2x3() const {
910 return mat2x3<T>(builder->source_);
911 }
912
913 /// @return a 2x4 matrix of the type `T`
914 template <typename T>
915 ast::Type mat2x4() const {
916 return mat2x4<T>(builder->source_);
917 }
918
919 /// @return a 3x2 matrix of the type `T`
920 template <typename T>
921 ast::Type mat3x2() const {
922 return mat3x2<T>(builder->source_);
923 }
924
925 /// @return a 3x3 matrix of the type `T`
926 template <typename T>
927 ast::Type mat3x3() const {
928 return mat3x3<T>(builder->source_);
929 }
930
931 /// @return a 3x4 matrix of the type `T`
932 template <typename T>
933 ast::Type mat3x4() const {
934 return mat3x4<T>(builder->source_);
935 }
936
937 /// @return a 4x2 matrix of the type `T`
938 template <typename T>
939 ast::Type mat4x2() const {
940 return mat4x2<T>(builder->source_);
941 }
942
943 /// @return a 4x3 matrix of the type `T`
944 template <typename T>
945 ast::Type mat4x3() const {
946 return mat4x3<T>(builder->source_);
947 }
948
949 /// @return a 4x4 matrix of the type `T`
950 template <typename T>
951 ast::Type mat4x4() const {
952 return mat4x4<T>(builder->source_);
953 }
954
955 /// @param source the Source of the node
956 /// @param columns number of columns for the matrix
957 /// @param rows number of rows for the matrix
958 /// @return a matrix of @p type
959 template <typename T>
960 ast::Type mat(const Source& source, uint32_t columns, uint32_t rows) const {
961 switch ((columns - 2) * 3 + (rows - 2)) {
962 case 0:
963 return mat2x2<T>(source);
964 case 1:
965 return mat2x3<T>(source);
966 case 2:
967 return mat2x4<T>(source);
968 case 3:
969 return mat3x2<T>(source);
970 case 4:
971 return mat3x3<T>(source);
972 case 5:
973 return mat3x4<T>(source);
974 case 6:
975 return mat4x2<T>(source);
976 case 7:
977 return mat4x3<T>(source);
978 case 8:
979 return mat4x4<T>(source);
980 default:
981 TINT_ICE(ProgramBuilder, builder->Diagnostics())
982 << "invalid matrix dimensions " << columns << "x" << rows;
983 return ast::Type{};
984 }
985 }
dan sinclair41e4d9a2022-05-01 14:40:55 +0000986
987 /// @param columns number of columns for the matrix
988 /// @param rows number of rows for the matrix
Ben Clayton971318f2023-02-14 13:52:43 +0000989 /// @return a matrix of @p type
dan sinclair41e4d9a2022-05-01 14:40:55 +0000990 template <typename T>
Ben Clayton971318f2023-02-14 13:52:43 +0000991 ast::Type mat(uint32_t columns, uint32_t rows) const {
992 return mat<T>(builder->source_, columns, rows);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000993 }
994
Ben Clayton971318f2023-02-14 13:52:43 +0000995 /// @return a matrix of @p type
996 template <typename T, uint32_t COLUMNS, uint32_t ROWS>
997 ast::Type mat() const {
998 return mat<T>(builder->source_, COLUMNS, ROWS);
dan sinclair41e4d9a2022-05-01 14:40:55 +0000999 }
1000
Ben Clayton971318f2023-02-14 13:52:43 +00001001 /// @param subtype the array element type
1002 /// @param attrs the optional attributes for the array
1003 /// @return an array of type `T`
1004 ast::Type array(ast::Type subtype,
1005 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
1006 return array(builder->source_, subtype, std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001007 }
1008
dan sinclair41e4d9a2022-05-01 14:40:55 +00001009 /// @param source the Source of the node
1010 /// @param subtype the array element type
Ben Clayton971318f2023-02-14 13:52:43 +00001011 /// @param attrs the optional attributes for the array
1012 /// @return an array of type `T`
1013 ast::Type array(const Source& source,
1014 ast::Type subtype,
1015 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
1016 return ast::Type{builder->Expr(
1017 builder->create<ast::TemplatedIdentifier>(source, builder->Sym("array"),
1018 utils::Vector{
1019 subtype.expr,
1020 },
1021 std::move(attrs)))};
1022 }
1023
Ben Clayton66805b02023-06-14 22:00:01 +00001024 /// @param subtype the array element type
1025 /// @param n the array size. nullptr represents a runtime-array
1026 /// @param attrs the optional attributes for the array
1027 /// @return an array of size `n` of type `T`
1028 template <typename COUNT, typename = DisableIfVectorLike<COUNT>>
1029 ast::Type array(ast::Type subtype,
1030 COUNT&& n,
1031 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
1032 return array(builder->source_, subtype, std::forward<COUNT>(n), std::move(attrs));
1033 }
1034
Ben Clayton971318f2023-02-14 13:52:43 +00001035 /// @param source the Source of the node
1036 /// @param subtype the array element type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001037 /// @param n the array size. nullptr represents a runtime-array
1038 /// @param attrs the optional attributes for the array
Ben Clayton971318f2023-02-14 13:52:43 +00001039 /// @return an array of size `n` of type `T`
1040 template <typename COUNT, typename = DisableIfVectorLike<COUNT>>
1041 ast::Type array(const Source& source,
1042 ast::Type subtype,
1043 COUNT&& n,
1044 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
1045 return ast::Type{builder->Expr(
1046 builder->create<ast::TemplatedIdentifier>(source, builder->Sym("array"),
1047 utils::Vector{
1048 subtype.expr,
1049 builder->Expr(std::forward<COUNT>(n)),
1050 },
1051 std::move(attrs)))};
dan sinclair41e4d9a2022-05-01 14:40:55 +00001052 }
1053
dan sinclair41e4d9a2022-05-01 14:40:55 +00001054 /// @param source the Source of the node
Ben Clayton971318f2023-02-14 13:52:43 +00001055 /// @return a inferred-size or runtime-sized array of type `T`
Ben Clayton66805b02023-06-14 22:00:01 +00001056 template <typename T, int N = 0, typename = EnableIfInferOrAbstract<T>>
Ben Clayton971318f2023-02-14 13:52:43 +00001057 ast::Type array(const Source& source) const {
Ben Clayton66805b02023-06-14 22:00:01 +00001058 static_assert(N == 0, "arrays with a count cannot be inferred");
Ben Clayton971318f2023-02-14 13:52:43 +00001059 return (*this)(source, "array");
1060 }
1061
1062 /// @return a inferred-size or runtime-sized array of type `T`
Ben Clayton66805b02023-06-14 22:00:01 +00001063 template <typename T, int N = 0, typename = EnableIfInferOrAbstract<T>>
Ben Clayton971318f2023-02-14 13:52:43 +00001064 ast::Type array() const {
Ben Clayton66805b02023-06-14 22:00:01 +00001065 static_assert(N == 0, "arrays with a count cannot be inferred");
Ben Clayton971318f2023-02-14 13:52:43 +00001066 return array<T>(builder->source_);
1067 }
1068
1069 /// @param source the Source of the node
1070 /// @param attrs the optional attributes for the array
1071 /// @return a inferred-size or runtime-sized array of type `T`
Ben Clayton66805b02023-06-14 22:00:01 +00001072 template <typename T, int N = 0, typename = DisableIfInferOrAbstract<T>>
Ben Clayton971318f2023-02-14 13:52:43 +00001073 ast::Type array(const Source& source,
1074 utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
Ben Clayton66805b02023-06-14 22:00:01 +00001075 if constexpr (N == 0) {
1076 return ast::Type{builder->Expr(builder->create<ast::TemplatedIdentifier>(
1077 source, builder->Sym("array"),
1078 utils::Vector<const ast::Expression*, 1>{
1079 Of<T>().expr,
1080 },
1081 std::move(attrs)))};
1082 } else {
1083 return ast::Type{builder->Expr(builder->create<ast::TemplatedIdentifier>(
1084 source, builder->Sym("array"),
1085 utils::Vector{
1086 Of<T>().expr,
1087 builder->Expr(builder->source_, tint::u32(N)),
1088 },
1089 std::move(attrs)))};
1090 }
Ben Clayton971318f2023-02-14 13:52:43 +00001091 }
1092
1093 /// @param attrs the optional attributes for the array
1094 /// @return an array of size `N` of type `T`
Ben Clayton66805b02023-06-14 22:00:01 +00001095 template <typename T, int N = 0, typename = DisableIfInferOrAbstract<T>>
Ben Clayton971318f2023-02-14 13:52:43 +00001096 ast::Type array(utils::VectorRef<const ast::Attribute*> attrs = utils::Empty) const {
Ben Clayton971318f2023-02-14 13:52:43 +00001097 return array<T, N>(builder->source_, std::move(attrs));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001098 }
1099
1100 /// Creates an alias type
1101 /// @param name the alias name
1102 /// @param type the alias type
1103 /// @returns the alias pointer
1104 template <typename NAME>
Ben Clayton971318f2023-02-14 13:52:43 +00001105 const ast::Alias* alias(NAME&& name, ast::Type type) const {
Ben Claytonb75252b2023-02-09 10:34:14 +00001106 return alias(builder->source_, std::forward<NAME>(name), type);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001107 }
1108
1109 /// Creates an alias type
1110 /// @param source the Source of the node
1111 /// @param name the alias name
1112 /// @param type the alias type
1113 /// @returns the alias pointer
1114 template <typename NAME>
Ben Clayton971318f2023-02-14 13:52:43 +00001115 const ast::Alias* alias(const Source& source, NAME&& name, ast::Type type) const {
Ben Claytonb75252b2023-02-09 10:34:14 +00001116 return builder->create<ast::Alias>(source, builder->Ident(std::forward<NAME>(name)),
1117 type);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001118 }
1119
dan sinclairff7cf212022-10-03 14:05:23 +00001120 /// @param address_space the address space of the pointer
Ben Clayton1a8a19d2023-06-13 17:01:16 +00001121 /// @param type the type of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001122 /// @param access the optional access control of the pointer
dan sinclair2a651632023-02-19 04:03:55 +00001123 /// @return the pointer to `type` with the given builtin::AddressSpace
Ben Clayton1a8a19d2023-06-13 17:01:16 +00001124 ast::Type ptr(builtin::AddressSpace address_space,
1125 ast::Type type,
1126 builtin::Access access = builtin::Access::kUndefined) const {
1127 return ptr(builder->source_, address_space, type, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001128 }
1129
1130 /// @param source the Source of the node
dan sinclairff7cf212022-10-03 14:05:23 +00001131 /// @param address_space the address space of the pointer
Ben Clayton1a8a19d2023-06-13 17:01:16 +00001132 /// @param type the type of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001133 /// @param access the optional access control of the pointer
dan sinclair2a651632023-02-19 04:03:55 +00001134 /// @return the pointer to `type` with the given builtin::AddressSpace
Ben Clayton1a8a19d2023-06-13 17:01:16 +00001135 ast::Type ptr(const Source& source,
1136 builtin::AddressSpace address_space,
1137 ast::Type type,
1138 builtin::Access access = builtin::Access::kUndefined) const {
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001139 if (access != builtin::Access::kUndefined) {
Ben Clayton971318f2023-02-14 13:52:43 +00001140 return (*this)(source, "ptr", address_space, type, access);
1141 } else {
1142 return (*this)(source, "ptr", address_space, type);
1143 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001144 }
1145
dan sinclairff7cf212022-10-03 14:05:23 +00001146 /// @param address_space the address space of the pointer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001147 /// @param access the optional access control of the pointer
dan sinclair2a651632023-02-19 04:03:55 +00001148 /// @return the pointer to type `T` with the given builtin::AddressSpace.
dan sinclair41e4d9a2022-05-01 14:40:55 +00001149 template <typename T>
Ben Clayton1a8a19d2023-06-13 17:01:16 +00001150 ast::Type ptr(builtin::AddressSpace address_space,
1151 builtin::Access access = builtin::Access::kUndefined) const {
1152 return ptr<T>(builder->source_, address_space, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001153 }
1154
1155 /// @param source the Source of the node
Ben Clayton66805b02023-06-14 22:00:01 +00001156 /// @return the pointer to type `T` with the builtin::AddressSpace `ADDRESS` and access
1157 /// control `ACCESS`.
1158 template <builtin::AddressSpace ADDRESS,
1159 typename T,
1160 builtin::Access ACCESS = builtin::Access::kUndefined>
1161 ast::Type ptr(const Source& source) const {
1162 return ptr<T>(source, ADDRESS, ACCESS);
1163 }
1164
1165 /// @param type the type of the pointer
1166 /// @return the pointer to the given type with the builtin::AddressSpace `ADDRESS` and
1167 /// access control `ACCESS`.
1168 template <builtin::AddressSpace ADDRESS,
1169 builtin::Access ACCESS = builtin::Access::kUndefined>
1170 ast::Type ptr(ast::Type type) const {
1171 return ptr(builder->source_, ADDRESS, type, ACCESS);
1172 }
1173
1174 /// @param source the Source of the node
1175 /// @param type the type of the pointer
1176 /// @return the pointer to the given type with the builtin::AddressSpace `ADDRESS` and
1177 /// access control `ACCESS`.
1178 template <builtin::AddressSpace ADDRESS,
1179 builtin::Access ACCESS = builtin::Access::kUndefined>
1180 ast::Type ptr(const Source& source, ast::Type type) const {
1181 return ptr(source, ADDRESS, type, ACCESS);
1182 }
1183
1184 /// @return the pointer to type `T` with the builtin::AddressSpace `ADDRESS` and access
1185 /// control `ACCESS`.
1186 template <builtin::AddressSpace ADDRESS,
1187 typename T,
1188 builtin::Access ACCESS = builtin::Access::kUndefined>
1189 ast::Type ptr() const {
1190 return ptr<T>(builder->source_, ADDRESS, ACCESS);
1191 }
1192
1193 /// @param source the Source of the node
dan sinclairff7cf212022-10-03 14:05:23 +00001194 /// @param address_space the address space of the pointer
Ben Claytoncfe07a12022-07-15 13:01:49 +00001195 /// @param access the optional access control of the pointer
Ben Clayton66805b02023-06-14 22:00:01 +00001196 /// @return the pointer to type `T` the builtin::AddressSpace `ADDRESS` and access control
1197 /// `ACCESS`.
Ben Claytoncfe07a12022-07-15 13:01:49 +00001198 template <typename T>
Ben Clayton1a8a19d2023-06-13 17:01:16 +00001199 ast::Type ptr(const Source& source,
1200 builtin::AddressSpace address_space,
1201 builtin::Access access = builtin::Access::kUndefined) const {
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001202 if (access != builtin::Access::kUndefined) {
Ben Clayton971318f2023-02-14 13:52:43 +00001203 return (*this)(source, "ptr", address_space, Of<T>(), access);
1204 } else {
1205 return (*this)(source, "ptr", address_space, Of<T>());
1206 }
Ben Claytoncfe07a12022-07-15 13:01:49 +00001207 }
1208
1209 /// @param source the Source of the node
dan sinclair41e4d9a2022-05-01 14:40:55 +00001210 /// @param type the type of the atomic
1211 /// @return the atomic to `type`
Ben Clayton971318f2023-02-14 13:52:43 +00001212 ast::Type atomic(const Source& source, ast::Type type) const {
1213 return (*this)(source, "atomic", type);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001214 }
1215
1216 /// @param type the type of the atomic
1217 /// @return the atomic to `type`
Ben Clayton971318f2023-02-14 13:52:43 +00001218 ast::Type atomic(ast::Type type) const { return (*this)("atomic", type); }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001219
1220 /// @return the atomic to type `T`
1221 template <typename T>
Ben Clayton971318f2023-02-14 13:52:43 +00001222 ast::Type atomic() const {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001223 return atomic(Of<T>());
1224 }
1225
1226 /// @param kind the kind of sampler
Ben Clayton971318f2023-02-14 13:52:43 +00001227 /// @returns the sampler
1228 ast::Type sampler(type::SamplerKind kind) const { return sampler(builder->source_, kind); }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001229
1230 /// @param source the Source of the node
1231 /// @param kind the kind of sampler
Ben Clayton971318f2023-02-14 13:52:43 +00001232 /// @returns the sampler
1233 ast::Type sampler(const Source& source, type::SamplerKind kind) const {
Ben Claytoned3389f2023-02-09 23:56:42 +00001234 switch (kind) {
1235 case type::SamplerKind::kSampler:
1236 return (*this)(source, "sampler");
1237 case type::SamplerKind::kComparisonSampler:
1238 return (*this)(source, "sampler_comparison");
1239 }
1240 TINT_ICE(ProgramBuilder, builder->Diagnostics()) << "invalid sampler kind " << kind;
Ben Clayton971318f2023-02-14 13:52:43 +00001241 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +00001242 }
1243
1244 /// @param dims the dimensionality of the texture
Ben Clayton971318f2023-02-14 13:52:43 +00001245 /// @returns the depth texture
1246 ast::Type depth_texture(type::TextureDimension dims) const {
Ben Claytona5fec202023-02-10 02:34:21 +00001247 return depth_texture(builder->source_, dims);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001248 }
1249
1250 /// @param source the Source of the node
1251 /// @param dims the dimensionality of the texture
Ben Clayton971318f2023-02-14 13:52:43 +00001252 /// @returns the depth texture
1253 ast::Type depth_texture(const Source& source, type::TextureDimension dims) const {
Ben Claytona5fec202023-02-10 02:34:21 +00001254 switch (dims) {
1255 case type::TextureDimension::k2d:
1256 return (*this)(source, "texture_depth_2d");
1257 case type::TextureDimension::k2dArray:
1258 return (*this)(source, "texture_depth_2d_array");
1259 case type::TextureDimension::kCube:
1260 return (*this)(source, "texture_depth_cube");
1261 case type::TextureDimension::kCubeArray:
1262 return (*this)(source, "texture_depth_cube_array");
1263 default:
1264 break;
1265 }
1266 TINT_ICE(ProgramBuilder, builder->Diagnostics())
1267 << "invalid depth_texture dimensions: " << dims;
Ben Clayton971318f2023-02-14 13:52:43 +00001268 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +00001269 }
1270
1271 /// @param dims the dimensionality of the texture
Ben Clayton971318f2023-02-14 13:52:43 +00001272 /// @returns the multisampled depth texture
1273 ast::Type depth_multisampled_texture(type::TextureDimension dims) const {
Ben Claytona5fec202023-02-10 02:34:21 +00001274 return depth_multisampled_texture(builder->source_, dims);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001275 }
1276
1277 /// @param source the Source of the node
1278 /// @param dims the dimensionality of the texture
Ben Clayton971318f2023-02-14 13:52:43 +00001279 /// @returns the multisampled depth texture
1280 ast::Type depth_multisampled_texture(const Source& source,
1281 type::TextureDimension dims) const {
Ben Claytona5fec202023-02-10 02:34:21 +00001282 if (dims == type::TextureDimension::k2d) {
1283 return (*this)(source, "texture_depth_multisampled_2d");
1284 }
1285 TINT_ICE(ProgramBuilder, builder->Diagnostics())
1286 << "invalid depth_multisampled_texture dimensions: " << dims;
Ben Clayton971318f2023-02-14 13:52:43 +00001287 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +00001288 }
1289
1290 /// @param dims the dimensionality of the texture
1291 /// @param subtype the texture subtype.
1292 /// @returns the sampled texture
Ben Clayton971318f2023-02-14 13:52:43 +00001293 ast::Type sampled_texture(type::TextureDimension dims, ast::Type subtype) const {
1294 return sampled_texture(builder->source_, dims, subtype);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001295 }
1296
1297 /// @param source the Source of the node
1298 /// @param dims the dimensionality of the texture
1299 /// @param subtype the texture subtype.
1300 /// @returns the sampled texture
Ben Clayton971318f2023-02-14 13:52:43 +00001301 ast::Type sampled_texture(const Source& source,
1302 type::TextureDimension dims,
1303 ast::Type subtype) const {
1304 switch (dims) {
1305 case type::TextureDimension::k1d:
1306 return (*this)(source, "texture_1d", subtype);
1307 case type::TextureDimension::k2d:
1308 return (*this)(source, "texture_2d", subtype);
1309 case type::TextureDimension::k3d:
1310 return (*this)(source, "texture_3d", subtype);
1311 case type::TextureDimension::k2dArray:
1312 return (*this)(source, "texture_2d_array", subtype);
1313 case type::TextureDimension::kCube:
1314 return (*this)(source, "texture_cube", subtype);
1315 case type::TextureDimension::kCubeArray:
1316 return (*this)(source, "texture_cube_array", subtype);
1317 default:
1318 break;
1319 }
1320 TINT_ICE(ProgramBuilder, builder->Diagnostics())
1321 << "invalid sampled_texture dimensions: " << dims;
1322 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +00001323 }
1324
1325 /// @param dims the dimensionality of the texture
1326 /// @param subtype the texture subtype.
1327 /// @returns the multisampled texture
Ben Clayton971318f2023-02-14 13:52:43 +00001328 ast::Type multisampled_texture(type::TextureDimension dims, ast::Type subtype) const {
1329 return multisampled_texture(builder->source_, dims, subtype);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001330 }
1331
1332 /// @param source the Source of the node
1333 /// @param dims the dimensionality of the texture
1334 /// @param subtype the texture subtype.
1335 /// @returns the multisampled texture
Ben Clayton971318f2023-02-14 13:52:43 +00001336 ast::Type multisampled_texture(const Source& source,
1337 type::TextureDimension dims,
1338 ast::Type subtype) const {
1339 if (dims == type::TextureDimension::k2d) {
1340 return (*this)(source, "texture_multisampled_2d", subtype);
1341 }
1342 TINT_ICE(ProgramBuilder, builder->Diagnostics())
1343 << "invalid multisampled_texture dimensions: " << dims;
1344 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +00001345 }
1346
1347 /// @param dims the dimensionality of the texture
1348 /// @param format the texel format of the texture
1349 /// @param access the access control of the texture
Ben Clayton971318f2023-02-14 13:52:43 +00001350 /// @returns the storage texture
1351 ast::Type storage_texture(type::TextureDimension dims,
dan sinclairba082fd2023-02-19 04:14:19 +00001352 builtin::TexelFormat format,
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001353 builtin::Access access) const {
Ben Clayton1131d312023-02-10 19:24:24 +00001354 return storage_texture(builder->source_, dims, format, access);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001355 }
1356
1357 /// @param source the Source of the node
1358 /// @param dims the dimensionality of the texture
1359 /// @param format the texel format of the texture
1360 /// @param access the access control of the texture
Ben Clayton971318f2023-02-14 13:52:43 +00001361 /// @returns the storage texture
1362 ast::Type storage_texture(const Source& source,
1363 type::TextureDimension dims,
dan sinclairba082fd2023-02-19 04:14:19 +00001364 builtin::TexelFormat format,
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001365 builtin::Access access) const {
Ben Clayton1131d312023-02-10 19:24:24 +00001366 switch (dims) {
1367 case type::TextureDimension::k1d:
Ben Clayton971318f2023-02-14 13:52:43 +00001368 return (*this)(source, "texture_storage_1d", format, access);
Ben Clayton1131d312023-02-10 19:24:24 +00001369 case type::TextureDimension::k2d:
Ben Clayton971318f2023-02-14 13:52:43 +00001370 return (*this)(source, "texture_storage_2d", format, access);
Ben Clayton1131d312023-02-10 19:24:24 +00001371 case type::TextureDimension::k2dArray:
Ben Clayton971318f2023-02-14 13:52:43 +00001372 return (*this)(source, "texture_storage_2d_array", format, access);
Ben Clayton1131d312023-02-10 19:24:24 +00001373 case type::TextureDimension::k3d:
Ben Clayton971318f2023-02-14 13:52:43 +00001374 return (*this)(source, "texture_storage_3d", format, access);
Ben Clayton1131d312023-02-10 19:24:24 +00001375 default:
1376 break;
1377 }
1378 TINT_ICE(ProgramBuilder, builder->Diagnostics())
Ben Clayton971318f2023-02-14 13:52:43 +00001379 << "invalid storage_texture dimensions: " << dims;
1380 return ast::Type{};
dan sinclair41e4d9a2022-05-01 14:40:55 +00001381 }
1382
1383 /// @returns the external texture
Ben Clayton971318f2023-02-14 13:52:43 +00001384 ast::Type external_texture() const { return (*this)("texture_external"); }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001385
1386 /// @param source the Source of the node
Ben Clayton971318f2023-02-14 13:52:43 +00001387 /// @returns the external texture
1388 ast::Type external_texture(const Source& source) const {
Ben Clayton4906b032023-02-09 23:59:07 +00001389 return (*this)(source, "texture_external");
dan sinclair41e4d9a2022-05-01 14:40:55 +00001390 }
1391
dan sinclair41e4d9a2022-05-01 14:40:55 +00001392 /// @param type the type
Ben Clayton971318f2023-02-14 13:52:43 +00001393 /// @return an ast::Type of the type declaration.
1394 ast::Type Of(const ast::TypeDecl* type) const { return (*this)(type->name->symbol); }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001395
1396 /// The ProgramBuilder
1397 ProgramBuilder* const builder;
1398
1399 private:
1400 /// CToAST<T> is specialized for various `T` types and each specialization
1401 /// contains a single static `get()` method for obtaining the corresponding
1402 /// AST type for the C type `T`.
1403 /// `get()` has the signature:
Ben Clayton971318f2023-02-14 13:52:43 +00001404 /// `static ast::Type get(Types* t)`
dan sinclair41e4d9a2022-05-01 14:40:55 +00001405 template <typename T>
1406 struct CToAST {};
1407 };
1408
1409 //////////////////////////////////////////////////////////////////////////////
1410 // AST helper methods
1411 //////////////////////////////////////////////////////////////////////////////
1412
1413 /// @return a new unnamed symbol
1414 Symbol Sym() { return Symbols().New(); }
1415
Ben Clayton971318f2023-02-14 13:52:43 +00001416 /// Passthrough
dan sinclair41e4d9a2022-05-01 14:40:55 +00001417 /// @param sym the symbol
1418 /// @return `sym`
1419 Symbol Sym(Symbol sym) { return sym; }
1420
Ben Clayton971318f2023-02-14 13:52:43 +00001421 /// @param name the symbol string
1422 /// @return a Symbol with the given name
Ben Clayton47dd3012023-04-26 18:27:53 +00001423 Symbol Sym(std::string_view name) { return Symbols().Register(name); }
Ben Clayton971318f2023-02-14 13:52:43 +00001424
1425 /// @param enumerator the enumerator
1426 /// @return a Symbol with the given enum value
1427 template <typename ENUM, typename = std::enable_if_t<std::is_enum_v<std::decay_t<ENUM>>>>
1428 Symbol Sym(ENUM&& enumerator) {
1429 return Sym(utils::ToString(enumerator));
1430 }
1431
1432 /// @return nullptr
1433 const ast::Identifier* Ident(std::nullptr_t) { return nullptr; }
1434
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001435 /// @param identifier the identifier symbol
1436 /// @return an ast::Identifier with the given symbol
Ben Clayton971318f2023-02-14 13:52:43 +00001437 template <typename IDENTIFIER>
1438 const ast::Identifier* Ident(IDENTIFIER&& identifier) {
dan sinclair05590052023-04-19 16:52:46 +00001439 if constexpr (utils::traits::IsTypeOrDerived<utils::traits::PtrElTy<IDENTIFIER>,
1440 ast::Identifier>) {
Ben Clayton971318f2023-02-14 13:52:43 +00001441 return identifier; // Passthrough
Ben Clayton2cdf1342023-02-03 13:24:18 +00001442 } else {
Ben Clayton971318f2023-02-14 13:52:43 +00001443 return Ident(source_, std::forward<IDENTIFIER>(identifier));
Ben Clayton2cdf1342023-02-03 13:24:18 +00001444 }
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001445 }
1446
Ben Clayton971318f2023-02-14 13:52:43 +00001447 /// @param source the source information
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001448 /// @param identifier the identifier symbol
1449 /// @return an ast::Identifier with the given symbol
Ben Clayton971318f2023-02-14 13:52:43 +00001450 template <typename IDENTIFIER>
1451 const ast::Identifier* Ident(const Source& source, IDENTIFIER&& identifier) {
1452 return create<ast::Identifier>(source, Sym(std::forward<IDENTIFIER>(identifier)));
1453 }
1454
1455 /// @param identifier the identifier symbol
1456 /// @param args the templated identifier arguments
Ben Clayton60d37382023-02-21 22:01:48 +00001457 /// @return an ast::Identifier with the given symbol and template arguments
Ben Clayton2cdf1342023-02-03 13:24:18 +00001458 template <typename IDENTIFIER, typename... ARGS, typename = DisableIfSource<IDENTIFIER>>
Ben Clayton60d37382023-02-21 22:01:48 +00001459 const ast::Identifier* Ident(IDENTIFIER&& identifier, ARGS&&... args) {
Ben Clayton971318f2023-02-14 13:52:43 +00001460 return Ident(source_, std::forward<IDENTIFIER>(identifier), std::forward<ARGS>(args)...);
1461 }
1462
1463 /// @param source the source information
1464 /// @param identifier the identifier symbol
1465 /// @param args the templated identifier arguments
Ben Clayton60d37382023-02-21 22:01:48 +00001466 /// @return an ast::Identifier with the given symbol and template arguments
Ben Clayton971318f2023-02-14 13:52:43 +00001467 template <typename IDENTIFIER, typename... ARGS>
Ben Clayton60d37382023-02-21 22:01:48 +00001468 const ast::Identifier* Ident(const Source& source, IDENTIFIER&& identifier, ARGS&&... args) {
1469 auto arg_exprs = ExprList(std::forward<ARGS>(args)...);
1470 if (arg_exprs.IsEmpty()) {
1471 return create<ast::Identifier>(source, Sym(std::forward<IDENTIFIER>(identifier)));
1472 }
Ben Clayton971318f2023-02-14 13:52:43 +00001473 return create<ast::TemplatedIdentifier>(source, Sym(std::forward<IDENTIFIER>(identifier)),
Ben Clayton60d37382023-02-21 22:01:48 +00001474 std::move(arg_exprs), utils::Empty);
Ben Claytonc87b1fe2023-02-02 15:04:31 +00001475 }
1476
dan sinclair41e4d9a2022-05-01 14:40:55 +00001477 /// @param expr the expression
Ben Clayton971318f2023-02-14 13:52:43 +00001478 /// @return expr (passthrough)
dan sinclair05590052023-04-19 16:52:46 +00001479 template <typename T, typename = utils::traits::EnableIfIsType<T, ast::Expression>>
Ben Clayton971318f2023-02-14 13:52:43 +00001480 const T* Expr(const T* expr) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001481 return expr;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001482 }
1483
Ben Clayton971318f2023-02-14 13:52:43 +00001484 /// @param type an ast::Type
1485 /// @return type.expr
1486 const ast::IdentifierExpression* Expr(ast::Type type) { return type.expr; }
1487
1488 /// @param ident the identifier
1489 /// @return an ast::IdentifierExpression with the given identifier
1490 const ast::IdentifierExpression* Expr(const ast::Identifier* ident) {
1491 return ident ? create<ast::IdentifierExpression>(ident->source, ident) : nullptr;
1492 }
1493
dan sinclair41e4d9a2022-05-01 14:40:55 +00001494 /// Passthrough for nullptr
1495 /// @return nullptr
1496 const ast::IdentifierExpression* Expr(std::nullptr_t) { return nullptr; }
1497
Ben Clayton971318f2023-02-14 13:52:43 +00001498 /// @param name the identifier name
1499 /// @return an ast::IdentifierExpression with the given name
1500 template <typename NAME, typename = EnableIfIdentifierLike<NAME>>
1501 const ast::IdentifierExpression* Expr(NAME&& name) {
1502 auto* ident = Ident(source_, name);
1503 return create<ast::IdentifierExpression>(ident->source, ident);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001504 }
1505
dan sinclair41e4d9a2022-05-01 14:40:55 +00001506 /// @param source the source information
1507 /// @param name the identifier name
1508 /// @return an ast::IdentifierExpression with the given name
Ben Clayton971318f2023-02-14 13:52:43 +00001509 template <typename NAME, typename = EnableIfIdentifierLike<NAME>>
1510 const ast::IdentifierExpression* Expr(const Source& source, NAME&& name) {
Ben Clayton6cba18b2023-02-02 20:37:19 +00001511 return create<ast::IdentifierExpression>(source, Ident(source, name));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001512 }
1513
Ben Clayton971318f2023-02-14 13:52:43 +00001514 /// @param variable the AST variable
1515 /// @return an ast::IdentifierExpression with the variable's symbol
1516 const ast::IdentifierExpression* Expr(const ast::Variable* variable) {
1517 auto* ident = Ident(variable->source, variable->name->symbol);
1518 return create<ast::IdentifierExpression>(ident->source, ident);
Ben Clayton6cba18b2023-02-02 20:37:19 +00001519 }
1520
1521 /// @param source the source information
1522 /// @param variable the AST variable
1523 /// @return an ast::IdentifierExpression with the variable's symbol
1524 const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001525 return create<ast::IdentifierExpression>(source, Ident(source, variable->name->symbol));
Ben Clayton6cba18b2023-02-02 20:37:19 +00001526 }
1527
dan sinclair41e4d9a2022-05-01 14:40:55 +00001528 /// @param source the source information
1529 /// @param value the boolean value
1530 /// @return a Scalar constructor for the given value
Ben Clayton17fa42d2022-05-10 15:29:14 +00001531 template <typename BOOL>
1532 std::enable_if_t<std::is_same_v<BOOL, bool>, const ast::BoolLiteralExpression*> Expr(
1533 const Source& source,
1534 BOOL value) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001535 return create<ast::BoolLiteralExpression>(source, value);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001536 }
1537
dan sinclair41e4d9a2022-05-01 14:40:55 +00001538 /// @param source the source information
1539 /// @param value the float value
Ben Clayton41285aa2022-05-10 14:55:34 +00001540 /// @return a 'f'-suffixed FloatLiteralExpression for the f32 value
1541 const ast::FloatLiteralExpression* Expr(const Source& source, f32 value) {
1542 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1543 ast::FloatLiteralExpression::Suffix::kF);
1544 }
1545
dan sinclair41e4d9a2022-05-01 14:40:55 +00001546 /// @param source the source information
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00001547 /// @param value the float value
1548 /// @return a 'h'-suffixed FloatLiteralExpression for the f16 value
1549 const ast::FloatLiteralExpression* Expr(const Source& source, f16 value) {
1550 return create<ast::FloatLiteralExpression>(source, static_cast<double>(value.value),
1551 ast::FloatLiteralExpression::Suffix::kH);
1552 }
1553
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00001554 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001555 /// @param value the integer value
Ben Clayton508e4a52022-05-10 22:08:04 +00001556 /// @return an unsuffixed IntLiteralExpression for the AInt value
1557 const ast::IntLiteralExpression* Expr(const Source& source, AInt value) {
1558 return create<ast::IntLiteralExpression>(source, value,
1559 ast::IntLiteralExpression::Suffix::kNone);
1560 }
1561
Ben Clayton508e4a52022-05-10 22:08:04 +00001562 /// @param source the source information
1563 /// @param value the integer value
1564 /// @return an unsuffixed FloatLiteralExpression for the AFloat value
1565 const ast::FloatLiteralExpression* Expr(const Source& source, AFloat value) {
1566 return create<ast::FloatLiteralExpression>(source, value.value,
1567 ast::FloatLiteralExpression::Suffix::kNone);
1568 }
1569
Ben Clayton508e4a52022-05-10 22:08:04 +00001570 /// @param source the source information
1571 /// @param value the integer value
Ben Clayton41285aa2022-05-10 14:55:34 +00001572 /// @return a signed 'i'-suffixed IntLiteralExpression for the i32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001573 const ast::IntLiteralExpression* Expr(const Source& source, i32 value) {
1574 return create<ast::IntLiteralExpression>(source, value,
Ben Clayton0ce9ab02022-05-05 20:23:40 +00001575 ast::IntLiteralExpression::Suffix::kI);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001576 }
1577
dan sinclair41e4d9a2022-05-01 14:40:55 +00001578 /// @param source the source information
1579 /// @param value the unsigned int value
Ben Clayton41285aa2022-05-10 14:55:34 +00001580 /// @return an unsigned 'u'-suffixed IntLiteralExpression for the u32 value
Ben Clayton8822e292022-05-04 22:18:49 +00001581 const ast::IntLiteralExpression* Expr(const Source& source, u32 value) {
1582 return create<ast::IntLiteralExpression>(source, value,
1583 ast::IntLiteralExpression::Suffix::kU);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001584 }
1585
Ben Clayton971318f2023-02-14 13:52:43 +00001586 /// @param value the scalar value
1587 /// @return literal expression of the appropriate type
1588 template <typename SCALAR, typename = EnableIfScalar<SCALAR>>
1589 const auto* Expr(SCALAR&& value) {
1590 return Expr(source_, std::forward<SCALAR>(value));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001591 }
1592
dan sinclair41e4d9a2022-05-01 14:40:55 +00001593 /// Converts `arg` to an `ast::Expression` using `Expr()`, then appends it to
1594 /// `list`.
1595 /// @param list the list to append too
1596 /// @param arg the arg to create
Ben Clayton783b1692022-08-02 17:03:35 +00001597 template <size_t N, typename ARG>
1598 void Append(utils::Vector<const ast::Expression*, N>& list, ARG&& arg) {
1599 list.Push(Expr(std::forward<ARG>(arg)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001600 }
1601
dan sinclair41e4d9a2022-05-01 14:40:55 +00001602 /// Converts `arg0` and `args` to `ast::Expression`s using `Expr()`,
1603 /// then appends them to `list`.
1604 /// @param list the list to append too
1605 /// @param arg0 the first argument
1606 /// @param args the rest of the arguments
Ben Clayton783b1692022-08-02 17:03:35 +00001607 template <size_t N, typename ARG0, typename... ARGS>
1608 void Append(utils::Vector<const ast::Expression*, N>& list, ARG0&& arg0, ARGS&&... args) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001609 Append(list, std::forward<ARG0>(arg0));
1610 Append(list, std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001611 }
1612
Ben Clayton783b1692022-08-02 17:03:35 +00001613 /// @return utils::EmptyType
1614 utils::EmptyType ExprList() { return utils::Empty; }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001615
1616 /// @param args the list of expressions
1617 /// @return the list of expressions converted to `ast::Expression`s using
1618 /// `Expr()`,
Ben Clayton783b1692022-08-02 17:03:35 +00001619 template <typename... ARGS, typename = DisableIfVectorLike<ARGS...>>
1620 auto ExprList(ARGS&&... args) {
Ben Clayton971318f2023-02-14 13:52:43 +00001621 return utils::Vector<const ast::Expression*, sizeof...(ARGS)>{Expr(args)...};
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001622 }
1623
dan sinclair41e4d9a2022-05-01 14:40:55 +00001624 /// @param list the list of expressions
1625 /// @return `list`
Ben Clayton783b1692022-08-02 17:03:35 +00001626 template <typename T, size_t N>
1627 utils::Vector<T, N> ExprList(utils::Vector<T, N>&& list) {
1628 return std::move(list);
1629 }
1630
1631 /// @param list the list of expressions
1632 /// @return `list`
1633 utils::VectorRef<const ast::Expression*> ExprList(
1634 utils::VectorRef<const ast::Expression*> list) {
1635 return list;
1636 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00001637
dan sinclair41e4d9a2022-05-01 14:40:55 +00001638 /// @param expr the expression for the bitcast
1639 /// @return an `ast::BitcastExpression` of type `ty`, with the values of
1640 /// `expr` converted to `ast::Expression`s using `Expr()`
1641 template <typename T, typename EXPR>
1642 const ast::BitcastExpression* Bitcast(EXPR&& expr) {
1643 return Bitcast(ty.Of<T>(), std::forward<EXPR>(expr));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001644 }
1645
dan sinclair41e4d9a2022-05-01 14:40:55 +00001646 /// @param type the type to cast to
1647 /// @param expr the expression for the bitcast
Ben Clayton971318f2023-02-14 13:52:43 +00001648 /// @return an `ast::BitcastExpression` of @p type constructed with the values
dan sinclair41e4d9a2022-05-01 14:40:55 +00001649 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001650 template <typename EXPR>
Ben Clayton971318f2023-02-14 13:52:43 +00001651 const ast::BitcastExpression* Bitcast(ast::Type type, EXPR&& expr) {
1652 return Bitcast(source_, type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001653 }
1654
dan sinclair41e4d9a2022-05-01 14:40:55 +00001655 /// @param source the source information
1656 /// @param type the type to cast to
1657 /// @param expr the expression for the bitcast
Ben Clayton971318f2023-02-14 13:52:43 +00001658 /// @return an `ast::BitcastExpression` of @p type constructed with the values
dan sinclair41e4d9a2022-05-01 14:40:55 +00001659 /// `expr`.
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001660 template <typename EXPR>
Ben Clayton971318f2023-02-14 13:52:43 +00001661 const ast::BitcastExpression* Bitcast(const Source& source, ast::Type type, EXPR&& expr) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00001662 return create<ast::BitcastExpression>(source, type, Expr(std::forward<EXPR>(expr)));
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001663 }
1664
dan sinclair41e4d9a2022-05-01 14:40:55 +00001665 /// @param type the vector type
1666 /// @param size the vector size
Ben Clayton54a104e2023-02-22 20:04:40 +00001667 /// @param args the arguments for the vector constructor
dan sinclair41e4d9a2022-05-01 14:40:55 +00001668 /// @return an `ast::CallExpression` of a `size`-element vector of
Ben Clayton971318f2023-02-14 13:52:43 +00001669 /// type `type`, constructed with the values @p args.
dan sinclair41e4d9a2022-05-01 14:40:55 +00001670 template <typename... ARGS>
Ben Clayton971318f2023-02-14 13:52:43 +00001671 const ast::CallExpression* vec(ast::Type type, uint32_t size, ARGS&&... args) {
1672 return vec(source_, type, size, std::forward<ARGS>(args)...);
1673 }
1674
1675 /// @param source the source of the call
1676 /// @param type the vector type
1677 /// @param size the vector size
Ben Clayton54a104e2023-02-22 20:04:40 +00001678 /// @param args the arguments for the vector constructor
Ben Clayton971318f2023-02-14 13:52:43 +00001679 /// @return an `ast::CallExpression` of a `size`-element vector of
1680 /// type `type`, constructed with the values @p args.
1681 template <typename... ARGS>
1682 const ast::CallExpression* vec(const Source& source,
1683 ast::Type type,
1684 uint32_t size,
1685 ARGS&&... args) {
1686 return Call(source, ty.vec(type, size), std::forward<ARGS>(args)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001687 }
1688
Ben Clayton7f2b8cd2022-05-18 22:41:48 +00001689 /// Adds the extension to the list of enable directives at the top of the module.
Ben Clayton8f80d992023-03-15 05:06:57 +00001690 /// @param extension the extension to enable
Ben Clayton7f2b8cd2022-05-18 22:41:48 +00001691 /// @return an `ast::Enable` enabling the given extension.
Ben Clayton8f80d992023-03-15 05:06:57 +00001692 const ast::Enable* Enable(builtin::Extension extension) {
1693 auto* ext = create<ast::Extension>(extension);
1694 auto* enable = create<ast::Enable>(utils::Vector{ext});
Ben Clayton7f2b8cd2022-05-18 22:41:48 +00001695 AST().AddEnable(enable);
1696 return enable;
1697 }
1698
Ben Clayton1a567782022-10-14 13:38:27 +00001699 /// Adds the extension to the list of enable directives at the top of the module.
1700 /// @param source the enable source
Ben Clayton8f80d992023-03-15 05:06:57 +00001701 /// @param extension the extension to enable
Ben Clayton1a567782022-10-14 13:38:27 +00001702 /// @return an `ast::Enable` enabling the given extension.
Ben Clayton8f80d992023-03-15 05:06:57 +00001703 const ast::Enable* Enable(const Source& source, builtin::Extension extension) {
1704 auto* ext = create<ast::Extension>(source, extension);
1705 auto* enable = create<ast::Enable>(source, utils::Vector{ext});
Ben Clayton1a567782022-10-14 13:38:27 +00001706 AST().AddEnable(enable);
1707 return enable;
1708 }
1709
dan sinclair41e4d9a2022-05-01 14:40:55 +00001710 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001711 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001712 /// Can be any of the following, in any order:
Ben Clayton54a104e2023-02-22 20:04:40 +00001713 /// * ast::Type - specifies the variable's type
dan sinclair2a651632023-02-19 04:03:55 +00001714 /// * builtin::AddressSpace - specifies the variable's address space
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001715 /// * builtin::Access - specifies the variable's access control
Ben Clayton54a104e2023-02-22 20:04:40 +00001716 /// * ast::Expression* - specifies the variable's initializer expression
1717 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
Ben Clayton58794ae2022-08-19 17:28:53 +00001718 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001719 /// @returns a `ast::Var` with the given name, type and additional
dan sinclair41e4d9a2022-05-01 14:40:55 +00001720 /// options
Ben Clayton58794ae2022-08-19 17:28:53 +00001721 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1722 const ast::Var* Var(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001723 return Var(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001724 }
1725
dan sinclair41e4d9a2022-05-01 14:40:55 +00001726 /// @param source the variable source
1727 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001728 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001729 /// Can be any of the following, in any order:
Ben Clayton54a104e2023-02-22 20:04:40 +00001730 /// * ast::Type - specifies the variable's type
dan sinclair2a651632023-02-19 04:03:55 +00001731 /// * builtin::AddressSpace - specifies the variable's address space
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001732 /// * builtin::Access - specifies the variable's access control
Ben Clayton54a104e2023-02-22 20:04:40 +00001733 /// * ast::Expression* - specifies the variable's initializer expression
1734 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
Ben Clayton58794ae2022-08-19 17:28:53 +00001735 /// Note that non-repeatable arguments of the same type will use the last argument's value.
dan sinclairff7cf212022-10-03 14:05:23 +00001736 /// @returns a `ast::Var` with the given name, address_space and type
Ben Clayton58794ae2022-08-19 17:28:53 +00001737 template <typename NAME, typename... OPTIONS>
1738 const ast::Var* Var(const Source& source, NAME&& name, OPTIONS&&... options) {
Ben Clayton79781f22023-02-18 17:13:18 +00001739 VarOptions opts(*this, std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001740 return create<ast::Var>(source, Ident(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001741 opts.address_space, opts.access, opts.initializer,
dan sinclairff7cf212022-10-03 14:05:23 +00001742 std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001743 }
1744
1745 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001746 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001747 /// Can be any of the following, in any order:
1748 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001749 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001750 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1751 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1752 /// @returns an `ast::Const` with the given name, type and additional options
1753 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1754 const ast::Const* Const(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001755 return Const(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
Ben Claytone3834c42022-06-25 23:21:39 +00001756 }
1757
1758 /// @param source the variable source
1759 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001760 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001761 /// Can be any of the following, in any order:
1762 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001763 /// * ast::Identifier* - specifies the variable's type
1764 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001765 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1766 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1767 /// @returns an `ast::Const` with the given name, type and additional options
1768 template <typename NAME, typename... OPTIONS>
1769 const ast::Const* Const(const Source& source, NAME&& name, OPTIONS&&... options) {
1770 ConstOptions opts(std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001771 return create<ast::Const>(source, Ident(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001772 opts.initializer, std::move(opts.attributes));
Ben Claytone3834c42022-06-25 23:21:39 +00001773 }
1774
1775 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001776 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001777 /// Can be any of the following, in any order:
1778 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001779 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001780 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1781 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1782 /// @returns an `ast::Let` with the given name, type and additional options
1783 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1784 const ast::Let* Let(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001785 return Let(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001786 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001787
dan sinclair41e4d9a2022-05-01 14:40:55 +00001788 /// @param source the variable source
1789 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001790 /// @param options the extra options passed to the ast::Var initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001791 /// Can be any of the following, in any order:
1792 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001793 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001794 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1795 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1796 /// @returns an `ast::Let` with the given name, type and additional options
1797 template <typename NAME, typename... OPTIONS>
1798 const ast::Let* Let(const Source& source, NAME&& name, OPTIONS&&... options) {
1799 LetOptions opts(std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001800 return create<ast::Let>(source, Ident(std::forward<NAME>(name)), opts.type,
1801 opts.initializer, std::move(opts.attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001802 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001803
dan sinclair41e4d9a2022-05-01 14:40:55 +00001804 /// @param name the parameter name
1805 /// @param type the parameter type
1806 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001807 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001808 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001809 const ast::Parameter* Param(NAME&& name,
Ben Clayton971318f2023-02-14 13:52:43 +00001810 ast::Type type,
Ben Clayton783b1692022-08-02 17:03:35 +00001811 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001812 return Param(source_, std::forward<NAME>(name), type, std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001813 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001814
dan sinclair41e4d9a2022-05-01 14:40:55 +00001815 /// @param source the parameter source
1816 /// @param name the parameter name
1817 /// @param type the parameter type
1818 /// @param attributes optional parameter attributes
Ben Claytondcdf66e2022-06-17 12:48:51 +00001819 /// @returns an `ast::Parameter` with the given name and type
dan sinclair41e4d9a2022-05-01 14:40:55 +00001820 template <typename NAME>
Ben Claytondcdf66e2022-06-17 12:48:51 +00001821 const ast::Parameter* Param(const Source& source,
1822 NAME&& name,
Ben Clayton971318f2023-02-14 13:52:43 +00001823 ast::Type type,
Ben Clayton783b1692022-08-02 17:03:35 +00001824 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Clayton971318f2023-02-14 13:52:43 +00001825 return create<ast::Parameter>(source, Ident(std::forward<NAME>(name)), type,
1826 std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00001827 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001828
dan sinclair41e4d9a2022-05-01 14:40:55 +00001829 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001830 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001831 /// Can be any of the following, in any order:
Ben Clayton79781f22023-02-18 17:13:18 +00001832 /// * ast::Type - specifies the variable's type
dan sinclair2a651632023-02-19 04:03:55 +00001833 /// * builtin::AddressSpace - specifies the variable address space
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001834 /// * builtin::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001835 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001836 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1837 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001838 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1839 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001840 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1841 const ast::Var* GlobalVar(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001842 return GlobalVar(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001843 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001844
dan sinclair41e4d9a2022-05-01 14:40:55 +00001845 /// @param source the variable source
1846 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001847 /// @param options the extra options passed to the ast::Var initializer
dan sinclair41e4d9a2022-05-01 14:40:55 +00001848 /// Can be any of the following, in any order:
Ben Clayton79781f22023-02-18 17:13:18 +00001849 /// * ast::Type - specifies the variable's type
dan sinclair2a651632023-02-19 04:03:55 +00001850 /// * builtin::AddressSpace - specifies the variable address space
dan sinclairb6cc4cb2023-02-19 04:01:29 +00001851 /// * builtin::Access - specifies the variable's access control
dan sinclair41e4d9a2022-05-01 14:40:55 +00001852 /// * ast::Expression* - specifies the variable's initializer expression
Ben Clayton58794ae2022-08-19 17:28:53 +00001853 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1854 /// Note that non-repeatable arguments of the same type will use the last argument's value.
Ben Claytondcdf66e2022-06-17 12:48:51 +00001855 /// @returns a new `ast::Var`, which is automatically registered as a global variable with the
1856 /// ast::Module.
Ben Clayton58794ae2022-08-19 17:28:53 +00001857 template <typename NAME, typename... OPTIONS>
1858 const ast::Var* GlobalVar(const Source& source, NAME&& name, OPTIONS&&... options) {
1859 auto* variable = Var(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1860 AST().AddGlobalVariable(variable);
1861 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001862 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001863
dan sinclair41e4d9a2022-05-01 14:40:55 +00001864 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001865 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001866 /// Can be any of the following, in any order:
1867 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001868 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001869 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1870 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1871 /// @returns an `ast::Const` with the given name, type and additional options, which is
1872 /// automatically registered as a global variable with the ast::Module.
1873 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1874 const ast::Const* GlobalConst(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001875 return GlobalConst(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
Ben Claytone3834c42022-06-25 23:21:39 +00001876 }
1877
1878 /// @param source the variable source
1879 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001880 /// @param options the extra options passed to the ast::Const initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001881 /// Can be any of the following, in any order:
1882 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001883 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001884 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1885 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1886 /// @returns an `ast::Const` with the given name, type and additional options, which is
1887 /// automatically registered as a global variable with the ast::Module.
1888 template <typename NAME, typename... OPTIONS>
1889 const ast::Const* GlobalConst(const Source& source, NAME&& name, OPTIONS&&... options) {
1890 auto* variable = Const(source, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
1891 AST().AddGlobalVariable(variable);
1892 return variable;
Ben Claytone3834c42022-06-25 23:21:39 +00001893 }
1894
1895 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001896 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001897 /// Can be any of the following, in any order:
1898 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001899 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001900 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1901 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1902 /// @returns an `ast::Override` with the given name, type and additional options, which is
1903 /// automatically registered as a global variable with the ast::Module.
1904 template <typename NAME, typename... OPTIONS, typename = DisableIfSource<NAME>>
1905 const ast::Override* Override(NAME&& name, OPTIONS&&... options) {
Ben Clayton651d9e22023-02-09 10:34:14 +00001906 return Override(source_, std::forward<NAME>(name), std::forward<OPTIONS>(options)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00001907 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001908
dan sinclair41e4d9a2022-05-01 14:40:55 +00001909 /// @param source the variable source
1910 /// @param name the variable name
dan sinclair6e77b472022-10-20 13:38:28 +00001911 /// @param options the extra options passed to the ast::Override initializer
Ben Clayton58794ae2022-08-19 17:28:53 +00001912 /// Can be any of the following, in any order:
1913 /// * ast::Expression* - specifies the variable's initializer expression (required)
Ben Clayton79781f22023-02-18 17:13:18 +00001914 /// * ast::Type - specifies the variable's type
Ben Clayton58794ae2022-08-19 17:28:53 +00001915 /// * ast::Attribute* - specifies the variable's attributes (repeatable, or vector)
1916 /// Note that non-repeatable arguments of the same type will use the last argument's value.
1917 /// @returns an `ast::Override` with the given name, type and additional options, which is
1918 /// automatically registered as a global variable with the ast::Module.
1919 template <typename NAME, typename... OPTIONS>
1920 const ast::Override* Override(const Source& source, NAME&& name, OPTIONS&&... options) {
1921 OverrideOptions opts(std::forward<OPTIONS>(options)...);
Ben Clayton651d9e22023-02-09 10:34:14 +00001922 auto* variable = create<ast::Override>(source, Ident(std::forward<NAME>(name)), opts.type,
dan sinclair6e77b472022-10-20 13:38:28 +00001923 opts.initializer, std::move(opts.attributes));
Ben Clayton58794ae2022-08-19 17:28:53 +00001924 AST().AddGlobalVariable(variable);
1925 return variable;
dan sinclair41e4d9a2022-05-01 14:40:55 +00001926 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001927
dan sinclair41e4d9a2022-05-01 14:40:55 +00001928 /// @param source the source information
Ben Claytonbfd1a812022-08-02 23:16:25 +00001929 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001930 /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement
Ben Claytonbfd1a812022-08-02 23:16:25 +00001931 /// with the ast::Module.
1932 template <typename EXPR>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001933 const ast::ConstAssert* GlobalConstAssert(const Source& source, EXPR&& condition) {
1934 auto* sa = ConstAssert(source, std::forward<EXPR>(condition));
1935 AST().AddConstAssert(sa);
Ben Claytonbfd1a812022-08-02 23:16:25 +00001936 return sa;
1937 }
1938
1939 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001940 /// @returns a new `ast::ConstAssert`, which is automatically registered as a global statement
Ben Claytonbfd1a812022-08-02 23:16:25 +00001941 /// with the ast::Module.
1942 template <typename EXPR, typename = DisableIfSource<EXPR>>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001943 const ast::ConstAssert* GlobalConstAssert(EXPR&& condition) {
1944 auto* sa = ConstAssert(std::forward<EXPR>(condition));
1945 AST().AddConstAssert(sa);
Ben Claytonbfd1a812022-08-02 23:16:25 +00001946 return sa;
1947 }
1948
1949 /// @param source the source information
1950 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001951 /// @returns a new `ast::ConstAssert` with the given assertion condition
Ben Claytonbfd1a812022-08-02 23:16:25 +00001952 template <typename EXPR>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001953 const ast::ConstAssert* ConstAssert(const Source& source, EXPR&& condition) {
1954 return create<ast::ConstAssert>(source, Expr(std::forward<EXPR>(condition)));
Ben Claytonbfd1a812022-08-02 23:16:25 +00001955 }
1956
1957 /// @param condition the assertion condition
Ben Claytonc98d57d2023-01-24 14:59:43 +00001958 /// @returns a new `ast::ConstAssert` with the given assertion condition
Ben Claytonbfd1a812022-08-02 23:16:25 +00001959 template <typename EXPR, typename = DisableIfSource<EXPR>>
Ben Claytonc98d57d2023-01-24 14:59:43 +00001960 const ast::ConstAssert* ConstAssert(EXPR&& condition) {
1961 return create<ast::ConstAssert>(Expr(std::forward<EXPR>(condition)));
Ben Claytonbfd1a812022-08-02 23:16:25 +00001962 }
1963
1964 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00001965 /// @param expr the expression to take the address of
1966 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1967 template <typename EXPR>
1968 const ast::UnaryOpExpression* AddressOf(const Source& source, EXPR&& expr) {
1969 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kAddressOf,
1970 Expr(std::forward<EXPR>(expr)));
1971 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001972
dan sinclair41e4d9a2022-05-01 14:40:55 +00001973 /// @param expr the expression to take the address of
1974 /// @return an ast::UnaryOpExpression that takes the address of `expr`
1975 template <typename EXPR>
1976 const ast::UnaryOpExpression* AddressOf(EXPR&& expr) {
1977 return create<ast::UnaryOpExpression>(ast::UnaryOp::kAddressOf,
1978 Expr(std::forward<EXPR>(expr)));
1979 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001980
dan sinclair41e4d9a2022-05-01 14:40:55 +00001981 /// @param source the source information
1982 /// @param expr the expression to perform an indirection on
1983 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1984 template <typename EXPR>
1985 const ast::UnaryOpExpression* Deref(const Source& source, EXPR&& expr) {
1986 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kIndirection,
1987 Expr(std::forward<EXPR>(expr)));
1988 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001989
dan sinclair41e4d9a2022-05-01 14:40:55 +00001990 /// @param expr the expression to perform an indirection on
1991 /// @return an ast::UnaryOpExpression that dereferences the pointer `expr`
1992 template <typename EXPR>
1993 const ast::UnaryOpExpression* Deref(EXPR&& expr) {
1994 return create<ast::UnaryOpExpression>(ast::UnaryOp::kIndirection,
1995 Expr(std::forward<EXPR>(expr)));
1996 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00001997
dan sinclair41e4d9a2022-05-01 14:40:55 +00001998 /// @param expr the expression to perform a unary not on
1999 /// @return an ast::UnaryOpExpression that is the unary not of the input
2000 /// expression
2001 template <typename EXPR>
2002 const ast::UnaryOpExpression* Not(EXPR&& expr) {
2003 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNot, Expr(std::forward<EXPR>(expr)));
2004 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002005
Antonio Maiorano28779af2022-12-09 21:28:51 +00002006 /// @param source the source information
2007 /// @param expr the expression to perform a unary not on
2008 /// @return an ast::UnaryOpExpression that is the unary not of the input
2009 /// expression
2010 template <typename EXPR>
2011 const ast::UnaryOpExpression* Not(const Source& source, EXPR&& expr) {
2012 return create<ast::UnaryOpExpression>(source, ast::UnaryOp::kNot,
2013 Expr(std::forward<EXPR>(expr)));
2014 }
2015
dan sinclair41e4d9a2022-05-01 14:40:55 +00002016 /// @param expr the expression to perform a unary complement on
2017 /// @return an ast::UnaryOpExpression that is the unary complement of the
2018 /// input expression
2019 template <typename EXPR>
2020 const ast::UnaryOpExpression* Complement(EXPR&& expr) {
2021 return create<ast::UnaryOpExpression>(ast::UnaryOp::kComplement,
2022 Expr(std::forward<EXPR>(expr)));
2023 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002024
Author: Shiyu Liub3aab092022-05-04 13:07:29 +00002025 /// @param expr the expression to perform a unary negation on
2026 /// @return an ast::UnaryOpExpression that is the unary negation of the
2027 /// input expression
2028 template <typename EXPR>
2029 const ast::UnaryOpExpression* Negation(EXPR&& expr) {
2030 return create<ast::UnaryOpExpression>(ast::UnaryOp::kNegation,
2031 Expr(std::forward<EXPR>(expr)));
2032 }
2033
Ben Clayton54a104e2023-02-22 20:04:40 +00002034 /// @param args the arguments for the constructor
Ben Clayton971318f2023-02-14 13:52:43 +00002035 /// @returns an ast::CallExpression to the type `T`, with the arguments of @p args converted to
2036 /// `ast::Expression`s using Expr().
2037 template <typename T, typename... ARGS, typename = DisableIfSource<ARGS...>>
2038 const ast::CallExpression* Call(ARGS&&... args) {
2039 return Call(source_, ty.Of<T>(), std::forward<ARGS>(args)...);
2040 }
2041
2042 /// @param source the source of the call
Ben Clayton54a104e2023-02-22 20:04:40 +00002043 /// @param args the arguments for the constructor
Ben Clayton971318f2023-02-14 13:52:43 +00002044 /// @returns an ast::CallExpression to the type `T` with the arguments of @p args converted to
2045 /// `ast::Expression`s using Expr().
2046 template <typename T, typename... ARGS>
2047 const ast::CallExpression* Call(const Source& source, ARGS&&... args) {
2048 return Call(source, ty.Of<T>(), std::forward<ARGS>(args)...);
2049 }
2050
Ben Clayton01ac21c2023-02-07 16:14:25 +00002051 /// @param target the call target
dan sinclair41e4d9a2022-05-01 14:40:55 +00002052 /// @param args the function call arguments
Ben Clayton971318f2023-02-14 13:52:43 +00002053 /// @returns an ast::CallExpression to the target @p target, with the arguments of @p args
2054 /// converted to `ast::Expression`s using Expr().
Ben Clayton01ac21c2023-02-07 16:14:25 +00002055 template <typename TARGET,
2056 typename... ARGS,
2057 typename = DisableIfSource<TARGET>,
2058 typename = DisableIfScalar<TARGET>>
2059 const ast::CallExpression* Call(TARGET&& target, ARGS&&... args) {
Ben Clayton971318f2023-02-14 13:52:43 +00002060 return Call(source_, Expr(std::forward<TARGET>(target)), std::forward<ARGS>(args)...);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002061 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002062
Ben Clayton971318f2023-02-14 13:52:43 +00002063 /// @param source the source of the call
2064 /// @param target the call target
dan sinclair41e4d9a2022-05-01 14:40:55 +00002065 /// @param args the function call arguments
Ben Clayton971318f2023-02-14 13:52:43 +00002066 /// @returns an ast::CallExpression to the target @p target, with the arguments of @p args
Ben Clayton01ac21c2023-02-07 16:14:25 +00002067 /// converted to `ast::Expression`s using Expr().
2068 template <typename TARGET, typename... ARGS, typename = DisableIfScalar<TARGET>>
2069 const ast::CallExpression* Call(const Source& source, TARGET&& target, ARGS&&... args) {
Ben Clayton971318f2023-02-14 13:52:43 +00002070 return create<ast::CallExpression>(source, Expr(std::forward<TARGET>(target)),
2071 ExprList(std::forward<ARGS>(args)...));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002072 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002073
dan sinclair41e4d9a2022-05-01 14:40:55 +00002074 /// @param source the source information
2075 /// @param call the call expression to wrap in a call statement
2076 /// @returns a `ast::CallStatement` for the given call expression
2077 const ast::CallStatement* CallStmt(const Source& source, const ast::CallExpression* call) {
2078 return create<ast::CallStatement>(source, call);
2079 }
James Pricec022ff52022-03-31 22:30:10 +00002080
dan sinclair41e4d9a2022-05-01 14:40:55 +00002081 /// @param call the call expression to wrap in a call statement
2082 /// @returns a `ast::CallStatement` for the given call expression
2083 const ast::CallStatement* CallStmt(const ast::CallExpression* call) {
2084 return create<ast::CallStatement>(call);
2085 }
James Pricec022ff52022-03-31 22:30:10 +00002086
dan sinclair41e4d9a2022-05-01 14:40:55 +00002087 /// @param source the source information
2088 /// @returns a `ast::PhonyExpression`
2089 const ast::PhonyExpression* Phony(const Source& source) {
2090 return create<ast::PhonyExpression>(source);
2091 }
James Priceebe97412022-04-07 13:42:45 +00002092
dan sinclair41e4d9a2022-05-01 14:40:55 +00002093 /// @returns a `ast::PhonyExpression`
2094 const ast::PhonyExpression* Phony() { return create<ast::PhonyExpression>(); }
James Priceebe97412022-04-07 13:42:45 +00002095
dan sinclair41e4d9a2022-05-01 14:40:55 +00002096 /// @param expr the expression to ignore
2097 /// @returns a `ast::AssignmentStatement` that assigns 'expr' to the phony
2098 /// (underscore) variable.
2099 template <typename EXPR>
2100 const ast::AssignmentStatement* Ignore(EXPR&& expr) {
2101 return create<ast::AssignmentStatement>(Phony(), Expr(expr));
2102 }
James Priceebe97412022-04-07 13:42:45 +00002103
dan sinclair41e4d9a2022-05-01 14:40:55 +00002104 /// @param lhs the left hand argument to the addition operation
2105 /// @param rhs the right hand argument to the addition operation
2106 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2107 template <typename LHS, typename RHS>
2108 const ast::BinaryExpression* Add(LHS&& lhs, RHS&& rhs) {
2109 return create<ast::BinaryExpression>(ast::BinaryOp::kAdd, Expr(std::forward<LHS>(lhs)),
2110 Expr(std::forward<RHS>(rhs)));
2111 }
James Priceebe97412022-04-07 13:42:45 +00002112
Antonio Maiorano7058a172022-08-10 18:06:43 +00002113 /// @param source the source information
2114 /// @param lhs the left hand argument to the addition operation
2115 /// @param rhs the right hand argument to the addition operation
2116 /// @returns a `ast::BinaryExpression` summing the arguments `lhs` and `rhs`
2117 template <typename LHS, typename RHS>
2118 const ast::BinaryExpression* Add(const Source& source, LHS&& lhs, RHS&& rhs) {
2119 return create<ast::BinaryExpression>(source, ast::BinaryOp::kAdd,
2120 Expr(std::forward<LHS>(lhs)),
2121 Expr(std::forward<RHS>(rhs)));
2122 }
2123
dan sinclair41e4d9a2022-05-01 14:40:55 +00002124 /// @param lhs the left hand argument to the and operation
2125 /// @param rhs the right hand argument to the and operation
2126 /// @returns a `ast::BinaryExpression` bitwise anding `lhs` and `rhs`
2127 template <typename LHS, typename RHS>
2128 const ast::BinaryExpression* And(LHS&& lhs, RHS&& rhs) {
2129 return create<ast::BinaryExpression>(ast::BinaryOp::kAnd, Expr(std::forward<LHS>(lhs)),
2130 Expr(std::forward<RHS>(rhs)));
2131 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002132
dan sinclair41e4d9a2022-05-01 14:40:55 +00002133 /// @param lhs the left hand argument to the or operation
2134 /// @param rhs the right hand argument to the or operation
2135 /// @returns a `ast::BinaryExpression` bitwise or-ing `lhs` and `rhs`
2136 template <typename LHS, typename RHS>
2137 const ast::BinaryExpression* Or(LHS&& lhs, RHS&& rhs) {
2138 return create<ast::BinaryExpression>(ast::BinaryOp::kOr, Expr(std::forward<LHS>(lhs)),
2139 Expr(std::forward<RHS>(rhs)));
2140 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002141
dan sinclair41e4d9a2022-05-01 14:40:55 +00002142 /// @param lhs the left hand argument to the subtraction operation
2143 /// @param rhs the right hand argument to the subtraction operation
2144 /// @returns a `ast::BinaryExpression` subtracting `rhs` from `lhs`
2145 template <typename LHS, typename RHS>
2146 const ast::BinaryExpression* Sub(LHS&& lhs, RHS&& rhs) {
2147 return create<ast::BinaryExpression>(ast::BinaryOp::kSubtract, Expr(std::forward<LHS>(lhs)),
2148 Expr(std::forward<RHS>(rhs)));
2149 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002150
dan sinclair41e4d9a2022-05-01 14:40:55 +00002151 /// @param lhs the left hand argument to the multiplication operation
2152 /// @param rhs the right hand argument to the multiplication operation
2153 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2154 template <typename LHS, typename RHS>
2155 const ast::BinaryExpression* Mul(LHS&& lhs, RHS&& rhs) {
2156 return create<ast::BinaryExpression>(ast::BinaryOp::kMultiply, Expr(std::forward<LHS>(lhs)),
2157 Expr(std::forward<RHS>(rhs)));
2158 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002159
dan sinclair41e4d9a2022-05-01 14:40:55 +00002160 /// @param source the source information
2161 /// @param lhs the left hand argument to the multiplication operation
2162 /// @param rhs the right hand argument to the multiplication operation
2163 /// @returns a `ast::BinaryExpression` multiplying `rhs` from `lhs`
2164 template <typename LHS, typename RHS>
2165 const ast::BinaryExpression* Mul(const Source& source, LHS&& lhs, RHS&& rhs) {
2166 return create<ast::BinaryExpression>(source, ast::BinaryOp::kMultiply,
2167 Expr(std::forward<LHS>(lhs)),
2168 Expr(std::forward<RHS>(rhs)));
2169 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002170
dan sinclair41e4d9a2022-05-01 14:40:55 +00002171 /// @param lhs the left hand argument to the division operation
2172 /// @param rhs the right hand argument to the division operation
2173 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2174 template <typename LHS, typename RHS>
2175 const ast::BinaryExpression* Div(LHS&& lhs, RHS&& rhs) {
2176 return create<ast::BinaryExpression>(ast::BinaryOp::kDivide, Expr(std::forward<LHS>(lhs)),
2177 Expr(std::forward<RHS>(rhs)));
2178 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002179
Antonio Maiorano28779af2022-12-09 21:28:51 +00002180 /// @param source the source information
2181 /// @param lhs the left hand argument to the division operation
2182 /// @param rhs the right hand argument to the division operation
2183 /// @returns a `ast::BinaryExpression` dividing `lhs` by `rhs`
2184 template <typename LHS, typename RHS>
2185 const ast::BinaryExpression* Div(const Source& source, LHS&& lhs, RHS&& rhs) {
2186 return create<ast::BinaryExpression>(source, ast::BinaryOp::kDivide,
2187 Expr(std::forward<LHS>(lhs)),
2188 Expr(std::forward<RHS>(rhs)));
2189 }
2190
dan sinclair41e4d9a2022-05-01 14:40:55 +00002191 /// @param lhs the left hand argument to the modulo operation
2192 /// @param rhs the right hand argument to the modulo operation
2193 /// @returns a `ast::BinaryExpression` applying modulo of `lhs` by `rhs`
2194 template <typename LHS, typename RHS>
2195 const ast::BinaryExpression* Mod(LHS&& lhs, RHS&& rhs) {
2196 return create<ast::BinaryExpression>(ast::BinaryOp::kModulo, Expr(std::forward<LHS>(lhs)),
2197 Expr(std::forward<RHS>(rhs)));
2198 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002199
dan sinclair41e4d9a2022-05-01 14:40:55 +00002200 /// @param lhs the left hand argument to the bit shift right operation
2201 /// @param rhs the right hand argument to the bit shift right operation
2202 /// @returns a `ast::BinaryExpression` bit shifting right `lhs` by `rhs`
2203 template <typename LHS, typename RHS>
2204 const ast::BinaryExpression* Shr(LHS&& lhs, RHS&& rhs) {
2205 return create<ast::BinaryExpression>(
2206 ast::BinaryOp::kShiftRight, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2207 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002208
dan sinclair41e4d9a2022-05-01 14:40:55 +00002209 /// @param lhs the left hand argument to the bit shift left operation
2210 /// @param rhs the right hand argument to the bit shift left operation
2211 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2212 template <typename LHS, typename RHS>
2213 const ast::BinaryExpression* Shl(LHS&& lhs, RHS&& rhs) {
2214 return create<ast::BinaryExpression>(
2215 ast::BinaryOp::kShiftLeft, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2216 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002217
Antonio Maiorano5f33fac2022-09-23 21:58:29 +00002218 /// @param source the source information
2219 /// @param lhs the left hand argument to the bit shift left operation
2220 /// @param rhs the right hand argument to the bit shift left operation
2221 /// @returns a `ast::BinaryExpression` bit shifting left `lhs` by `rhs`
2222 template <typename LHS, typename RHS>
2223 const ast::BinaryExpression* Shl(const Source& source, LHS&& lhs, RHS&& rhs) {
2224 return create<ast::BinaryExpression>(source, ast::BinaryOp::kShiftLeft,
2225 Expr(std::forward<LHS>(lhs)),
2226 Expr(std::forward<RHS>(rhs)));
2227 }
2228
dan sinclair41e4d9a2022-05-01 14:40:55 +00002229 /// @param lhs the left hand argument to the xor operation
2230 /// @param rhs the right hand argument to the xor operation
2231 /// @returns a `ast::BinaryExpression` bitwise xor-ing `lhs` and `rhs`
2232 template <typename LHS, typename RHS>
2233 const ast::BinaryExpression* Xor(LHS&& lhs, RHS&& rhs) {
2234 return create<ast::BinaryExpression>(ast::BinaryOp::kXor, Expr(std::forward<LHS>(lhs)),
2235 Expr(std::forward<RHS>(rhs)));
2236 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002237
dan sinclair41e4d9a2022-05-01 14:40:55 +00002238 /// @param lhs the left hand argument to the logical and operation
2239 /// @param rhs the right hand argument to the logical and operation
2240 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2241 template <typename LHS, typename RHS>
2242 const ast::BinaryExpression* LogicalAnd(LHS&& lhs, RHS&& rhs) {
2243 return create<ast::BinaryExpression>(
2244 ast::BinaryOp::kLogicalAnd, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2245 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002246
Antonio Maiorano28779af2022-12-09 21:28:51 +00002247 /// @param source the source information
2248 /// @param lhs the left hand argument to the logical and operation
2249 /// @param rhs the right hand argument to the logical and operation
2250 /// @returns a `ast::BinaryExpression` of `lhs` && `rhs`
2251 template <typename LHS, typename RHS>
2252 const ast::BinaryExpression* LogicalAnd(const Source& source, LHS&& lhs, RHS&& rhs) {
2253 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalAnd,
2254 Expr(std::forward<LHS>(lhs)),
2255 Expr(std::forward<RHS>(rhs)));
2256 }
2257
dan sinclair41e4d9a2022-05-01 14:40:55 +00002258 /// @param lhs the left hand argument to the logical or operation
2259 /// @param rhs the right hand argument to the logical or operation
2260 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2261 template <typename LHS, typename RHS>
2262 const ast::BinaryExpression* LogicalOr(LHS&& lhs, RHS&& rhs) {
2263 return create<ast::BinaryExpression>(
2264 ast::BinaryOp::kLogicalOr, Expr(std::forward<LHS>(lhs)), Expr(std::forward<RHS>(rhs)));
2265 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002266
Antonio Maiorano28779af2022-12-09 21:28:51 +00002267 /// @param source the source information
2268 /// @param lhs the left hand argument to the logical or operation
2269 /// @param rhs the right hand argument to the logical or operation
2270 /// @returns a `ast::BinaryExpression` of `lhs` || `rhs`
2271 template <typename LHS, typename RHS>
2272 const ast::BinaryExpression* LogicalOr(const Source& source, LHS&& lhs, RHS&& rhs) {
2273 return create<ast::BinaryExpression>(source, ast::BinaryOp::kLogicalOr,
2274 Expr(std::forward<LHS>(lhs)),
2275 Expr(std::forward<RHS>(rhs)));
2276 }
2277
dan sinclair41e4d9a2022-05-01 14:40:55 +00002278 /// @param lhs the left hand argument to the greater than operation
2279 /// @param rhs the right hand argument to the greater than operation
2280 /// @returns a `ast::BinaryExpression` of `lhs` > `rhs`
2281 template <typename LHS, typename RHS>
2282 const ast::BinaryExpression* GreaterThan(LHS&& lhs, RHS&& rhs) {
2283 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThan,
2284 Expr(std::forward<LHS>(lhs)),
2285 Expr(std::forward<RHS>(rhs)));
2286 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002287
dan sinclair41e4d9a2022-05-01 14:40:55 +00002288 /// @param lhs the left hand argument to the greater than or equal operation
2289 /// @param rhs the right hand argument to the greater than or equal operation
2290 /// @returns a `ast::BinaryExpression` of `lhs` >= `rhs`
2291 template <typename LHS, typename RHS>
2292 const ast::BinaryExpression* GreaterThanEqual(LHS&& lhs, RHS&& rhs) {
2293 return create<ast::BinaryExpression>(ast::BinaryOp::kGreaterThanEqual,
2294 Expr(std::forward<LHS>(lhs)),
2295 Expr(std::forward<RHS>(rhs)));
2296 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002297
dan sinclair41e4d9a2022-05-01 14:40:55 +00002298 /// @param lhs the left hand argument to the less than operation
2299 /// @param rhs the right hand argument to the less than operation
2300 /// @returns a `ast::BinaryExpression` of `lhs` < `rhs`
2301 template <typename LHS, typename RHS>
2302 const ast::BinaryExpression* LessThan(LHS&& lhs, RHS&& rhs) {
2303 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThan, Expr(std::forward<LHS>(lhs)),
2304 Expr(std::forward<RHS>(rhs)));
2305 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002306
dan sinclair41e4d9a2022-05-01 14:40:55 +00002307 /// @param lhs the left hand argument to the less than or equal operation
2308 /// @param rhs the right hand argument to the less than or equal operation
2309 /// @returns a `ast::BinaryExpression` of `lhs` <= `rhs`
2310 template <typename LHS, typename RHS>
2311 const ast::BinaryExpression* LessThanEqual(LHS&& lhs, RHS&& rhs) {
2312 return create<ast::BinaryExpression>(ast::BinaryOp::kLessThanEqual,
2313 Expr(std::forward<LHS>(lhs)),
2314 Expr(std::forward<RHS>(rhs)));
2315 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002316
dan sinclair41e4d9a2022-05-01 14:40:55 +00002317 /// @param lhs the left hand argument to the equal expression
2318 /// @param rhs the right hand argument to the equal expression
2319 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2320 template <typename LHS, typename RHS>
2321 const ast::BinaryExpression* Equal(LHS&& lhs, RHS&& rhs) {
2322 return create<ast::BinaryExpression>(ast::BinaryOp::kEqual, Expr(std::forward<LHS>(lhs)),
2323 Expr(std::forward<RHS>(rhs)));
2324 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002325
Antonio Maiorano28779af2022-12-09 21:28:51 +00002326 /// @param source the source information
2327 /// @param lhs the left hand argument to the equal expression
2328 /// @param rhs the right hand argument to the equal expression
2329 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs`
2330 template <typename LHS, typename RHS>
2331 const ast::BinaryExpression* Equal(const Source& source, LHS&& lhs, RHS&& rhs) {
2332 return create<ast::BinaryExpression>(source, ast::BinaryOp::kEqual,
2333 Expr(std::forward<LHS>(lhs)),
2334 Expr(std::forward<RHS>(rhs)));
2335 }
2336
dan sinclair41e4d9a2022-05-01 14:40:55 +00002337 /// @param lhs the left hand argument to the not-equal expression
2338 /// @param rhs the right hand argument to the not-equal expression
2339 /// @returns a `ast::BinaryExpression` comparing `lhs` equal to `rhs` for
2340 /// disequality
2341 template <typename LHS, typename RHS>
2342 const ast::BinaryExpression* NotEqual(LHS&& lhs, RHS&& rhs) {
2343 return create<ast::BinaryExpression>(ast::BinaryOp::kNotEqual, Expr(std::forward<LHS>(lhs)),
2344 Expr(std::forward<RHS>(rhs)));
2345 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002346
dan sinclair41e4d9a2022-05-01 14:40:55 +00002347 /// @param source the source information
Ben Clayton2cdf1342023-02-03 13:24:18 +00002348 /// @param object the object for the index accessor expression
2349 /// @param index the index argument for the index accessor expression
2350 /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index
2351 template <typename OBJECT, typename INDEX>
2352 const ast::IndexAccessorExpression* IndexAccessor(const Source& source,
2353 OBJECT&& object,
2354 INDEX&& index) {
2355 return create<ast::IndexAccessorExpression>(source, Expr(std::forward<OBJECT>(object)),
2356 Expr(std::forward<INDEX>(index)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002357 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002358
Ben Clayton2cdf1342023-02-03 13:24:18 +00002359 /// @param object the object for the index accessor expression
2360 /// @param index the index argument for the index accessor expression
2361 /// @returns a `ast::IndexAccessorExpression` that indexes @p object with @p index
2362 template <typename OBJECT, typename INDEX>
2363 const ast::IndexAccessorExpression* IndexAccessor(OBJECT&& object, INDEX&& index) {
2364 return create<ast::IndexAccessorExpression>(Expr(std::forward<OBJECT>(object)),
2365 Expr(std::forward<INDEX>(index)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002366 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002367
dan sinclair41e4d9a2022-05-01 14:40:55 +00002368 /// @param source the source information
Ben Clayton2cdf1342023-02-03 13:24:18 +00002369 /// @param object the object for the member accessor expression
2370 /// @param member the member argument for the member accessor expression
2371 /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member
2372 template <typename OBJECT, typename MEMBER>
dan sinclair41e4d9a2022-05-01 14:40:55 +00002373 const ast::MemberAccessorExpression* MemberAccessor(const Source& source,
Ben Clayton2cdf1342023-02-03 13:24:18 +00002374 OBJECT&& object,
2375 MEMBER&& member) {
dan sinclair05590052023-04-19 16:52:46 +00002376 static_assert(
2377 !utils::traits::IsType<utils::traits::PtrElTy<MEMBER>, ast::TemplatedIdentifier>,
2378 "it is currently invalid for a structure to hold a templated member");
Ben Clayton2cdf1342023-02-03 13:24:18 +00002379 return create<ast::MemberAccessorExpression>(source, Expr(std::forward<OBJECT>(object)),
2380 Ident(std::forward<MEMBER>(member)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002381 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002382
Ben Clayton2cdf1342023-02-03 13:24:18 +00002383 /// @param object the object for the member accessor expression
2384 /// @param member the member argument for the member accessor expression
2385 /// @returns a `ast::MemberAccessorExpression` that indexes @p object with @p member
2386 template <typename OBJECT, typename MEMBER>
2387 const ast::MemberAccessorExpression* MemberAccessor(OBJECT&& object, MEMBER&& member) {
2388 return MemberAccessor(source_, std::forward<OBJECT>(object), std::forward<MEMBER>(member));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002389 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002390
dan sinclair41e4d9a2022-05-01 14:40:55 +00002391 /// Creates a ast::StructMemberOffsetAttribute
dan sinclair93df9672022-09-09 14:49:09 +00002392 /// @param val the offset expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002393 /// @returns the offset attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002394 template <typename EXPR>
2395 const ast::StructMemberOffsetAttribute* MemberOffset(EXPR&& val) {
2396 return create<ast::StructMemberOffsetAttribute>(source_, Expr(std::forward<EXPR>(val)));
2397 }
2398
2399 /// Creates a ast::StructMemberOffsetAttribute
2400 /// @param source the source information
2401 /// @param val the offset expression
2402 /// @returns the offset attribute pointer
2403 template <typename EXPR>
2404 const ast::StructMemberOffsetAttribute* MemberOffset(const Source& source, EXPR&& val) {
2405 return create<ast::StructMemberOffsetAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002406 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002407
dan sinclair41e4d9a2022-05-01 14:40:55 +00002408 /// Creates a ast::StructMemberSizeAttribute
2409 /// @param source the source information
2410 /// @param val the size value
2411 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002412 template <typename EXPR>
2413 const ast::StructMemberSizeAttribute* MemberSize(const Source& source, EXPR&& val) {
2414 return create<ast::StructMemberSizeAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002415 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002416
dan sinclair41e4d9a2022-05-01 14:40:55 +00002417 /// Creates a ast::StructMemberSizeAttribute
2418 /// @param val the size value
2419 /// @returns the size attribute pointer
dan sinclair93df9672022-09-09 14:49:09 +00002420 template <typename EXPR>
2421 const ast::StructMemberSizeAttribute* MemberSize(EXPR&& val) {
2422 return create<ast::StructMemberSizeAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002423 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002424
dan sinclair41e4d9a2022-05-01 14:40:55 +00002425 /// Creates a ast::StructMemberAlignAttribute
2426 /// @param source the source information
dan sinclair4964d9b2022-08-23 13:28:44 +00002427 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002428 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002429 template <typename EXPR>
2430 const ast::StructMemberAlignAttribute* MemberAlign(const Source& source, EXPR&& val) {
2431 return create<ast::StructMemberAlignAttribute>(source, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002432 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002433
dan sinclair41e4d9a2022-05-01 14:40:55 +00002434 /// Creates a ast::StructMemberAlignAttribute
dan sinclair4964d9b2022-08-23 13:28:44 +00002435 /// @param val the align value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002436 /// @returns the align attribute pointer
dan sinclair4964d9b2022-08-23 13:28:44 +00002437 template <typename EXPR>
2438 const ast::StructMemberAlignAttribute* MemberAlign(EXPR&& val) {
2439 return create<ast::StructMemberAlignAttribute>(source_, Expr(std::forward<EXPR>(val)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002440 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002441
Ben Clayton9e367232023-02-08 14:17:37 +00002442 /// Creates a ast::StrideAttribute
2443 /// @param stride the array stride
2444 /// @returns the ast::StrideAttribute attribute
2445 const ast::StrideAttribute* Stride(uint32_t stride) {
2446 return create<ast::StrideAttribute>(source_, stride);
2447 }
2448
dan sinclair41e4d9a2022-05-01 14:40:55 +00002449 /// Creates the ast::GroupAttribute
dan sinclairbe4c9f42022-08-29 21:22:31 +00002450 /// @param value group attribute index expresion
dan sinclair41e4d9a2022-05-01 14:40:55 +00002451 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002452 template <typename EXPR>
2453 const ast::GroupAttribute* Group(EXPR&& value) {
2454 return create<ast::GroupAttribute>(Expr(std::forward<EXPR>(value)));
2455 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002456
dan sinclairf9b831c2022-08-29 21:13:00 +00002457 /// Creates the ast::GroupAttribute
2458 /// @param source the source
dan sinclairbe4c9f42022-08-29 21:22:31 +00002459 /// @param value group attribute index expression
dan sinclairf9b831c2022-08-29 21:13:00 +00002460 /// @returns the group attribute pointer
dan sinclairbe4c9f42022-08-29 21:22:31 +00002461 template <typename EXPR>
2462 const ast::GroupAttribute* Group(const Source& source, EXPR&& value) {
2463 return create<ast::GroupAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclairf9b831c2022-08-29 21:13:00 +00002464 }
2465
dan sinclair41e4d9a2022-05-01 14:40:55 +00002466 /// Creates the ast::BindingAttribute
dan sinclairf9b831c2022-08-29 21:13:00 +00002467 /// @param value the binding index expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00002468 /// @returns the binding deocration pointer
dan sinclairf9b831c2022-08-29 21:13:00 +00002469 template <typename EXPR>
2470 const ast::BindingAttribute* Binding(EXPR&& value) {
2471 return create<ast::BindingAttribute>(Expr(std::forward<EXPR>(value)));
2472 }
2473
2474 /// Creates the ast::BindingAttribute
2475 /// @param source the source
2476 /// @param value the binding index expression
2477 /// @returns the binding deocration pointer
2478 template <typename EXPR>
2479 const ast::BindingAttribute* Binding(const Source& source, EXPR&& value) {
2480 return create<ast::BindingAttribute>(source, Expr(std::forward<EXPR>(value)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002481 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002482
dan sinclair41e4d9a2022-05-01 14:40:55 +00002483 /// Creates an ast::Function and registers it with the ast::Module.
Ben Clayton17aa6532023-02-07 21:28:09 +00002484 /// @param name the function name
2485 /// @param params the function parameters
2486 /// @param type the function return type
2487 /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
2488 /// be automatically placed into a block, or nullptr for a stub function.
2489 /// @param attributes the optional function attributes
2490 /// @param return_type_attributes the optional function return type attributes
Ben Clayton17aa6532023-02-07 21:28:09 +00002491 /// @returns the function pointer
2492 template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
2493 const ast::Function* Func(
2494 NAME&& name,
2495 utils::VectorRef<const ast::Parameter*> params,
Ben Clayton971318f2023-02-14 13:52:43 +00002496 ast::Type type,
Ben Clayton17aa6532023-02-07 21:28:09 +00002497 BODY&& body,
2498 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
2499 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2500 return Func(source_, std::forward<NAME>(name), std::move(params), type,
2501 std::forward<BODY>(body), std::move(attributes),
2502 std::move(return_type_attributes));
2503 }
2504
2505 /// Creates an ast::Function and registers it with the ast::Module.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002506 /// @param source the source information
2507 /// @param name the function name
2508 /// @param params the function parameters
2509 /// @param type the function return type
Ben Clayton17aa6532023-02-07 21:28:09 +00002510 /// @param body the function body. Can be an ast::BlockStatement*, as ast::Statement* which will
2511 /// be automatically placed into a block, or nullptr for a stub function.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002512 /// @param attributes the optional function attributes
James Priced9f65962023-02-01 23:14:10 +00002513 /// @param return_type_attributes the optional function return type attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002514 /// @returns the function pointer
Ben Clayton17aa6532023-02-07 21:28:09 +00002515 template <typename NAME, typename BODY = utils::VectorRef<const ast::Statement*>>
Ben Clayton783b1692022-08-02 17:03:35 +00002516 const ast::Function* Func(
2517 const Source& source,
2518 NAME&& name,
2519 utils::VectorRef<const ast::Parameter*> params,
Ben Clayton971318f2023-02-14 13:52:43 +00002520 ast::Type type,
Ben Clayton17aa6532023-02-07 21:28:09 +00002521 BODY&& body,
Ben Clayton783b1692022-08-02 17:03:35 +00002522 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty,
Ben Clayton17aa6532023-02-07 21:28:09 +00002523 utils::VectorRef<const ast::Attribute*> return_type_attributes = utils::Empty) {
2524 const ast::BlockStatement* block = nullptr;
dan sinclair05590052023-04-19 16:52:46 +00002525 using BODY_T = utils::traits::PtrElTy<BODY>;
2526 if constexpr (utils::traits::IsTypeOrDerived<BODY_T, ast::BlockStatement> ||
Ben Clayton17aa6532023-02-07 21:28:09 +00002527 std::is_same_v<BODY_T, std::nullptr_t>) {
2528 block = body;
2529 } else {
2530 block = Block(std::forward<BODY>(body));
2531 }
2532 auto* func =
Ben Claytonce31d182023-02-09 10:34:14 +00002533 create<ast::Function>(source, Ident(std::forward<NAME>(name)), std::move(params), type,
Ben Clayton17aa6532023-02-07 21:28:09 +00002534 block, std::move(attributes), std::move(return_type_attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002535 AST().AddFunction(func);
2536 return func;
2537 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002538
dan sinclair41e4d9a2022-05-01 14:40:55 +00002539 /// Creates an ast::BreakStatement
2540 /// @param source the source information
2541 /// @returns the break statement pointer
2542 const ast::BreakStatement* Break(const Source& source) {
2543 return create<ast::BreakStatement>(source);
2544 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002545
dan sinclair41e4d9a2022-05-01 14:40:55 +00002546 /// Creates an ast::BreakStatement
2547 /// @returns the break statement pointer
2548 const ast::BreakStatement* Break() { return create<ast::BreakStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002549
dan sinclairb8b0c212022-10-20 22:45:50 +00002550 /// Creates a ast::BreakIfStatement with input condition
2551 /// @param source the source information for the if statement
2552 /// @param condition the if statement condition expression
2553 /// @returns the break-if statement pointer
2554 template <typename CONDITION>
2555 const ast::BreakIfStatement* BreakIf(const Source& source, CONDITION&& condition) {
2556 return create<ast::BreakIfStatement>(source, Expr(std::forward<CONDITION>(condition)));
2557 }
2558
2559 /// Creates a ast::BreakIfStatement with input condition
2560 /// @param condition the if statement condition expression
2561 /// @returns the break-if statement pointer
2562 template <typename CONDITION>
2563 const ast::BreakIfStatement* BreakIf(CONDITION&& condition) {
2564 return create<ast::BreakIfStatement>(Expr(std::forward<CONDITION>(condition)));
2565 }
2566
dan sinclair41e4d9a2022-05-01 14:40:55 +00002567 /// Creates an ast::ContinueStatement
2568 /// @param source the source information
2569 /// @returns the continue statement pointer
2570 const ast::ContinueStatement* Continue(const Source& source) {
2571 return create<ast::ContinueStatement>(source);
2572 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002573
dan sinclair41e4d9a2022-05-01 14:40:55 +00002574 /// Creates an ast::ContinueStatement
2575 /// @returns the continue statement pointer
2576 const ast::ContinueStatement* Continue() { return create<ast::ContinueStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002577
dan sinclair41e4d9a2022-05-01 14:40:55 +00002578 /// Creates an ast::ReturnStatement with no return value
2579 /// @param source the source information
2580 /// @returns the return statement pointer
2581 const ast::ReturnStatement* Return(const Source& source) {
2582 return create<ast::ReturnStatement>(source);
2583 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002584
dan sinclair41e4d9a2022-05-01 14:40:55 +00002585 /// Creates an ast::ReturnStatement with no return value
2586 /// @returns the return statement pointer
2587 const ast::ReturnStatement* Return() { return create<ast::ReturnStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002588
dan sinclair41e4d9a2022-05-01 14:40:55 +00002589 /// Creates an ast::ReturnStatement with the given return value
2590 /// @param source the source information
2591 /// @param val the return value
2592 /// @returns the return statement pointer
2593 template <typename EXPR>
2594 const ast::ReturnStatement* Return(const Source& source, EXPR&& val) {
2595 return create<ast::ReturnStatement>(source, Expr(std::forward<EXPR>(val)));
2596 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002597
dan sinclair41e4d9a2022-05-01 14:40:55 +00002598 /// Creates an ast::ReturnStatement with the given return value
2599 /// @param val the return value
2600 /// @returns the return statement pointer
2601 template <typename EXPR, typename = DisableIfSource<EXPR>>
2602 const ast::ReturnStatement* Return(EXPR&& val) {
2603 return create<ast::ReturnStatement>(Expr(std::forward<EXPR>(val)));
2604 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002605
dan sinclair41e4d9a2022-05-01 14:40:55 +00002606 /// Creates an ast::DiscardStatement
2607 /// @param source the source information
2608 /// @returns the discard statement pointer
2609 const ast::DiscardStatement* Discard(const Source& source) {
2610 return create<ast::DiscardStatement>(source);
2611 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002612
dan sinclair41e4d9a2022-05-01 14:40:55 +00002613 /// Creates an ast::DiscardStatement
2614 /// @returns the discard statement pointer
2615 const ast::DiscardStatement* Discard() { return create<ast::DiscardStatement>(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002616
dan sinclair41e4d9a2022-05-01 14:40:55 +00002617 /// Creates a ast::Alias registering it with the AST().TypeDecls().
Ben Claytonb75252b2023-02-09 10:34:14 +00002618 /// @param name the alias name
2619 /// @param type the alias target type
2620 /// @returns the alias type
2621 template <typename NAME>
Ben Clayton971318f2023-02-14 13:52:43 +00002622 const ast::Alias* Alias(NAME&& name, ast::Type type) {
Ben Claytonb75252b2023-02-09 10:34:14 +00002623 return Alias(source_, std::forward<NAME>(name), type);
2624 }
2625
2626 /// Creates a ast::Alias registering it with the AST().TypeDecls().
dan sinclair41e4d9a2022-05-01 14:40:55 +00002627 /// @param source the source information
2628 /// @param name the alias name
2629 /// @param type the alias target type
2630 /// @returns the alias type
2631 template <typename NAME>
Ben Clayton971318f2023-02-14 13:52:43 +00002632 const ast::Alias* Alias(const Source& source, NAME&& name, ast::Type type) {
2633 auto out = ty.alias(source, std::forward<NAME>(name), type);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002634 AST().AddTypeDecl(out);
2635 return out;
2636 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002637
Ben Claytonb75252b2023-02-09 10:34:14 +00002638 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2639 /// @param name the struct name
2640 /// @param members the struct members
2641 /// @param attributes the optional struct attributes
2642 /// @returns the struct type
dan sinclair41e4d9a2022-05-01 14:40:55 +00002643 template <typename NAME>
Ben Claytonb75252b2023-02-09 10:34:14 +00002644 const ast::Struct* Structure(
2645 NAME&& name,
2646 utils::VectorRef<const ast::StructMember*> members,
2647 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2648 return Structure(source_, std::forward<NAME>(name), std::move(members),
2649 std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002650 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002651
dan sinclair41e4d9a2022-05-01 14:40:55 +00002652 /// Creates a ast::Struct registering it with the AST().TypeDecls().
2653 /// @param source the source information
2654 /// @param name the struct name
2655 /// @param members the struct members
Ben Claytonb75252b2023-02-09 10:34:14 +00002656 /// @param attributes the optional struct attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002657 /// @returns the struct type
2658 template <typename NAME>
Ben Claytonb75252b2023-02-09 10:34:14 +00002659 const ast::Struct* Structure(
2660 const Source& source,
2661 NAME&& name,
2662 utils::VectorRef<const ast::StructMember*> members,
2663 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2664 auto* type = create<ast::Struct>(source, Ident(std::forward<NAME>(name)),
2665 std::move(members), std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002666 AST().AddTypeDecl(type);
2667 return type;
2668 }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00002669
dan sinclair41e4d9a2022-05-01 14:40:55 +00002670 /// Creates a ast::StructMember
Ben Clayton199440e2023-02-09 10:34:14 +00002671 /// @param name the struct member name
2672 /// @param type the struct member type
2673 /// @param attributes the optional struct member attributes
2674 /// @returns the struct member pointer
Ben Clayton971318f2023-02-14 13:52:43 +00002675 template <typename NAME, typename = DisableIfSource<NAME>>
Ben Clayton199440e2023-02-09 10:34:14 +00002676 const ast::StructMember* Member(
2677 NAME&& name,
Ben Clayton971318f2023-02-14 13:52:43 +00002678 ast::Type type,
Ben Clayton199440e2023-02-09 10:34:14 +00002679 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2680 return Member(source_, std::forward<NAME>(name), type, std::move(attributes));
2681 }
2682
2683 /// Creates a ast::StructMember
Ben Clayton971318f2023-02-14 13:52:43 +00002684 /// @param source the struct member source
dan sinclair41e4d9a2022-05-01 14:40:55 +00002685 /// @param name the struct member name
2686 /// @param type the struct member type
2687 /// @param attributes the optional struct member attributes
2688 /// @returns the struct member pointer
2689 template <typename NAME>
Ben Clayton783b1692022-08-02 17:03:35 +00002690 const ast::StructMember* Member(
2691 const Source& source,
2692 NAME&& name,
Ben Clayton971318f2023-02-14 13:52:43 +00002693 ast::Type type,
Ben Clayton783b1692022-08-02 17:03:35 +00002694 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
Ben Clayton199440e2023-02-09 10:34:14 +00002695 return create<ast::StructMember>(source, Ident(std::forward<NAME>(name)), type,
dan sinclair41e4d9a2022-05-01 14:40:55 +00002696 std::move(attributes));
2697 }
2698
2699 /// Creates a ast::StructMember with the given byte offset
Ben Clayton783b1692022-08-02 17:03:35 +00002700 /// @param offset the offset to use in the StructMemberOffsetAttribute
dan sinclair41e4d9a2022-05-01 14:40:55 +00002701 /// @param name the struct member name
2702 /// @param type the struct member type
2703 /// @returns the struct member pointer
2704 template <typename NAME>
Ben Clayton971318f2023-02-14 13:52:43 +00002705 const ast::StructMember* Member(uint32_t offset, NAME&& name, ast::Type type) {
Ben Clayton199440e2023-02-09 10:34:14 +00002706 return create<ast::StructMember>(source_, Ident(std::forward<NAME>(name)), type,
Ben Clayton783b1692022-08-02 17:03:35 +00002707 utils::Vector<const ast::Attribute*, 1>{
dan sinclair93df9672022-09-09 14:49:09 +00002708 MemberOffset(AInt(offset)),
dan sinclair41e4d9a2022-05-01 14:40:55 +00002709 });
2710 }
2711
Ben Clayton17aa6532023-02-07 21:28:09 +00002712 /// Creates a ast::BlockStatement with input statements and attributes
2713 /// @param statements the statements of the block
2714 /// @param attributes the optional attributes of the block
2715 /// @returns the block statement pointer
2716 const ast::BlockStatement* Block(
2717 utils::VectorRef<const ast::Statement*> statements,
2718 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2719 return Block(source_, std::move(statements), std::move(attributes));
2720 }
2721
2722 /// Creates a ast::BlockStatement with input statements and attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002723 /// @param source the source information for the block
Ben Clayton17aa6532023-02-07 21:28:09 +00002724 /// @param statements the statements of the block
2725 /// @param attributes the optional attributes of the block
2726 /// @returns the block statement pointer
2727 const ast::BlockStatement* Block(
2728 const Source& source,
2729 utils::VectorRef<const ast::Statement*> statements,
2730 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2731 return create<ast::BlockStatement>(source, std::move(statements), std::move(attributes));
2732 }
2733
2734 /// Creates a ast::BlockStatement with a parameter list of input statements
2735 /// @param statements the optional statements of the block
2736 /// @returns the block statement pointer
2737 template <typename... STATEMENTS,
2738 typename = DisableIfSource<STATEMENTS...>,
2739 typename = DisableIfVectorLike<STATEMENTS...>>
2740 const ast::BlockStatement* Block(STATEMENTS&&... statements) {
2741 return Block(source_, std::forward<STATEMENTS>(statements)...);
2742 }
2743
2744 /// Creates a ast::BlockStatement with a parameter list of input statements
2745 /// @param source the source information for the block
2746 /// @param statements the optional statements of the block
dan sinclair41e4d9a2022-05-01 14:40:55 +00002747 /// @returns the block statement pointer
James Priced9f65962023-02-01 23:14:10 +00002748 template <typename... STATEMENTS, typename = DisableIfVectorLike<STATEMENTS...>>
2749 const ast::BlockStatement* Block(const Source& source, STATEMENTS&&... statements) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002750 return create<ast::BlockStatement>(
James Priced9f65962023-02-01 23:14:10 +00002751 source,
2752 utils::Vector<const ast::Statement*, sizeof...(statements)>{
2753 std::forward<STATEMENTS>(statements)...,
2754 },
2755 utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00002756 }
2757
James Price8aff0ed2022-05-02 14:53:36 +00002758 /// A wrapper type for the Else statement used to create If statements.
2759 struct ElseStmt {
2760 /// Default constructor - no else statement.
2761 ElseStmt() : stmt(nullptr) {}
2762 /// Constructor
2763 /// @param s The else statement
2764 explicit ElseStmt(const ast::Statement* s) : stmt(s) {}
2765 /// The else statement, or nullptr.
2766 const ast::Statement* stmt;
2767 };
2768
dan sinclair41e4d9a2022-05-01 14:40:55 +00002769 /// Creates a ast::IfStatement with input condition, body, and optional
2770 /// else statement
2771 /// @param source the source information for the if statement
2772 /// @param condition the if statement condition expression
2773 /// @param body the if statement body
2774 /// @param else_stmt optional else statement
James Price06077962023-03-14 21:11:53 +00002775 /// @param attributes optional attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002776 /// @returns the if statement pointer
2777 template <typename CONDITION>
2778 const ast::IfStatement* If(const Source& source,
2779 CONDITION&& condition,
2780 const ast::BlockStatement* body,
James Price06077962023-03-14 21:11:53 +00002781 const ElseStmt else_stmt = ElseStmt(),
2782 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002783 return create<ast::IfStatement>(source, Expr(std::forward<CONDITION>(condition)), body,
James Price06077962023-03-14 21:11:53 +00002784 else_stmt.stmt, std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002785 }
2786
2787 /// Creates a ast::IfStatement with input condition, body, and optional
2788 /// else statement
2789 /// @param condition the if statement condition expression
2790 /// @param body the if statement body
2791 /// @param else_stmt optional else statement
James Price06077962023-03-14 21:11:53 +00002792 /// @param attributes optional attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002793 /// @returns the if statement pointer
2794 template <typename CONDITION>
2795 const ast::IfStatement* If(CONDITION&& condition,
2796 const ast::BlockStatement* body,
James Price06077962023-03-14 21:11:53 +00002797 const ElseStmt else_stmt = ElseStmt(),
2798 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
James Price8aff0ed2022-05-02 14:53:36 +00002799 return create<ast::IfStatement>(Expr(std::forward<CONDITION>(condition)), body,
James Price06077962023-03-14 21:11:53 +00002800 else_stmt.stmt, std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002801 }
2802
James Price8aff0ed2022-05-02 14:53:36 +00002803 /// Creates an Else object.
2804 /// @param stmt else statement
2805 /// @returns the Else object
2806 ElseStmt Else(const ast::Statement* stmt) { return ElseStmt(stmt); }
2807
dan sinclair41e4d9a2022-05-01 14:40:55 +00002808 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2809 /// @param source the source information
2810 /// @param lhs the left hand side expression initializer
2811 /// @param rhs the right hand side expression initializer
2812 /// @returns the assignment statement pointer
2813 template <typename LhsExpressionInit, typename RhsExpressionInit>
2814 const ast::AssignmentStatement* Assign(const Source& source,
2815 LhsExpressionInit&& lhs,
2816 RhsExpressionInit&& rhs) {
2817 return create<ast::AssignmentStatement>(source, Expr(std::forward<LhsExpressionInit>(lhs)),
2818 Expr(std::forward<RhsExpressionInit>(rhs)));
2819 }
2820
2821 /// Creates a ast::AssignmentStatement with input lhs and rhs expressions
2822 /// @param lhs the left hand side expression initializer
2823 /// @param rhs the right hand side expression initializer
2824 /// @returns the assignment statement pointer
2825 template <typename LhsExpressionInit, typename RhsExpressionInit>
2826 const ast::AssignmentStatement* Assign(LhsExpressionInit&& lhs, RhsExpressionInit&& rhs) {
2827 return create<ast::AssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2828 Expr(std::forward<RhsExpressionInit>(rhs)));
2829 }
2830
2831 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2832 /// expressions, and a binary operator.
2833 /// @param source the source information
2834 /// @param lhs the left hand side expression initializer
2835 /// @param rhs the right hand side expression initializer
2836 /// @param op the binary operator
2837 /// @returns the compound assignment statement pointer
2838 template <typename LhsExpressionInit, typename RhsExpressionInit>
2839 const ast::CompoundAssignmentStatement* CompoundAssign(const Source& source,
2840 LhsExpressionInit&& lhs,
2841 RhsExpressionInit&& rhs,
2842 ast::BinaryOp op) {
2843 return create<ast::CompoundAssignmentStatement>(
2844 source, Expr(std::forward<LhsExpressionInit>(lhs)),
2845 Expr(std::forward<RhsExpressionInit>(rhs)), op);
2846 }
2847
2848 /// Creates a ast::CompoundAssignmentStatement with input lhs and rhs
2849 /// expressions, and a binary operator.
2850 /// @param lhs the left hand side expression initializer
2851 /// @param rhs the right hand side expression initializer
2852 /// @param op the binary operator
2853 /// @returns the compound assignment statement pointer
2854 template <typename LhsExpressionInit, typename RhsExpressionInit>
2855 const ast::CompoundAssignmentStatement* CompoundAssign(LhsExpressionInit&& lhs,
2856 RhsExpressionInit&& rhs,
2857 ast::BinaryOp op) {
2858 return create<ast::CompoundAssignmentStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2859 Expr(std::forward<RhsExpressionInit>(rhs)),
2860 op);
2861 }
2862
2863 /// Creates an ast::IncrementDecrementStatement with input lhs.
2864 /// @param source the source information
2865 /// @param lhs the left hand side expression initializer
2866 /// @returns the increment decrement statement pointer
2867 template <typename LhsExpressionInit>
2868 const ast::IncrementDecrementStatement* Increment(const Source& source,
2869 LhsExpressionInit&& lhs) {
2870 return create<ast::IncrementDecrementStatement>(
2871 source, Expr(std::forward<LhsExpressionInit>(lhs)), true);
2872 }
2873
2874 /// Creates a ast::IncrementDecrementStatement with input lhs.
2875 /// @param lhs the left hand side expression initializer
2876 /// @returns the increment decrement statement pointer
2877 template <typename LhsExpressionInit>
2878 const ast::IncrementDecrementStatement* Increment(LhsExpressionInit&& lhs) {
2879 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2880 true);
2881 }
2882
2883 /// Creates an ast::IncrementDecrementStatement with input lhs.
2884 /// @param source the source information
2885 /// @param lhs the left hand side expression initializer
2886 /// @returns the increment decrement statement pointer
2887 template <typename LhsExpressionInit>
2888 const ast::IncrementDecrementStatement* Decrement(const Source& source,
2889 LhsExpressionInit&& lhs) {
2890 return create<ast::IncrementDecrementStatement>(
2891 source, Expr(std::forward<LhsExpressionInit>(lhs)), false);
2892 }
2893
2894 /// Creates a ast::IncrementDecrementStatement with input lhs.
2895 /// @param lhs the left hand side expression initializer
2896 /// @returns the increment decrement statement pointer
2897 template <typename LhsExpressionInit>
2898 const ast::IncrementDecrementStatement* Decrement(LhsExpressionInit&& lhs) {
2899 return create<ast::IncrementDecrementStatement>(Expr(std::forward<LhsExpressionInit>(lhs)),
2900 false);
2901 }
2902
2903 /// Creates a ast::LoopStatement with input body and optional continuing
2904 /// @param source the source information
2905 /// @param body the loop body
2906 /// @param continuing the optional continuing block
James Priced7d8b802023-03-16 12:21:44 +00002907 /// @param attributes optional attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002908 /// @returns the loop statement pointer
James Priced7d8b802023-03-16 12:21:44 +00002909 const ast::LoopStatement* Loop(
2910 const Source& source,
2911 const ast::BlockStatement* body,
2912 const ast::BlockStatement* continuing = nullptr,
2913 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2914 return create<ast::LoopStatement>(source, body, continuing, std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002915 }
2916
2917 /// Creates a ast::LoopStatement with input body and optional continuing
2918 /// @param body the loop body
2919 /// @param continuing the optional continuing block
James Priced7d8b802023-03-16 12:21:44 +00002920 /// @param attributes optional attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002921 /// @returns the loop statement pointer
James Priced7d8b802023-03-16 12:21:44 +00002922 const ast::LoopStatement* Loop(
2923 const ast::BlockStatement* body,
2924 const ast::BlockStatement* continuing = nullptr,
2925 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2926 return create<ast::LoopStatement>(body, continuing, std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002927 }
2928
James Priceed28de32023-03-15 02:44:47 +00002929 /// Creates a ast::ForLoopStatement with input body and optional initializer, condition,
2930 /// continuing, and attributes.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002931 /// @param source the source information
2932 /// @param init the optional loop initializer
2933 /// @param cond the optional loop condition
2934 /// @param cont the optional loop continuing
2935 /// @param body the loop body
James Priceed28de32023-03-15 02:44:47 +00002936 /// @param attributes optional attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002937 /// @returns the for loop statement pointer
2938 template <typename COND>
James Priceed28de32023-03-15 02:44:47 +00002939 const ast::ForLoopStatement* For(
2940 const Source& source,
2941 const ast::Statement* init,
2942 COND&& cond,
2943 const ast::Statement* cont,
2944 const ast::BlockStatement* body,
2945 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00002946 return create<ast::ForLoopStatement>(source, init, Expr(std::forward<COND>(cond)), cont,
James Priceed28de32023-03-15 02:44:47 +00002947 body, std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002948 }
2949
James Priceed28de32023-03-15 02:44:47 +00002950 /// Creates a ast::ForLoopStatement with input body and optional initializer, condition,
2951 /// continuing, and attributes.
dan sinclair41e4d9a2022-05-01 14:40:55 +00002952 /// @param init the optional loop initializer
2953 /// @param cond the optional loop condition
2954 /// @param cont the optional loop continuing
2955 /// @param body the loop body
James Priceed28de32023-03-15 02:44:47 +00002956 /// @param attributes optional attributes
dan sinclair41e4d9a2022-05-01 14:40:55 +00002957 /// @returns the for loop statement pointer
2958 template <typename COND>
James Priceed28de32023-03-15 02:44:47 +00002959 const ast::ForLoopStatement* For(
2960 const ast::Statement* init,
2961 COND&& cond,
2962 const ast::Statement* cont,
2963 const ast::BlockStatement* body,
2964 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2965 return create<ast::ForLoopStatement>(init, Expr(std::forward<COND>(cond)), cont, body,
2966 std::move(attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00002967 }
2968
James Price9536ced2023-03-15 00:33:38 +00002969 /// Creates a ast::WhileStatement with input body, condition, and optional attributes.
dan sinclair49d1a2d2022-06-16 12:01:27 +00002970 /// @param source the source information
2971 /// @param cond the loop condition
2972 /// @param body the loop body
James Price9536ced2023-03-15 00:33:38 +00002973 /// @param attributes optional attributes
dan sinclair49d1a2d2022-06-16 12:01:27 +00002974 /// @returns the while statement pointer
2975 template <typename COND>
James Price9536ced2023-03-15 00:33:38 +00002976 const ast::WhileStatement* While(
2977 const Source& source,
2978 COND&& cond,
2979 const ast::BlockStatement* body,
2980 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2981 return create<ast::WhileStatement>(source, Expr(std::forward<COND>(cond)), body,
2982 std::move(attributes));
dan sinclair49d1a2d2022-06-16 12:01:27 +00002983 }
2984
James Price9536ced2023-03-15 00:33:38 +00002985 /// Creates a ast::WhileStatement with input body, condition, and optional attributes.
dan sinclair49d1a2d2022-06-16 12:01:27 +00002986 /// @param cond the condition
2987 /// @param body the loop body
James Price9536ced2023-03-15 00:33:38 +00002988 /// @param attributes optional attributes
dan sinclair49d1a2d2022-06-16 12:01:27 +00002989 /// @returns the while loop statement pointer
2990 template <typename COND>
James Price9536ced2023-03-15 00:33:38 +00002991 const ast::WhileStatement* While(
2992 COND&& cond,
2993 const ast::BlockStatement* body,
2994 utils::VectorRef<const ast::Attribute*> attributes = utils::Empty) {
2995 return create<ast::WhileStatement>(Expr(std::forward<COND>(cond)), body,
2996 std::move(attributes));
dan sinclair49d1a2d2022-06-16 12:01:27 +00002997 }
2998
dan sinclair41e4d9a2022-05-01 14:40:55 +00002999 /// Creates a ast::VariableDeclStatement for the input variable
3000 /// @param source the source information
3001 /// @param var the variable to wrap in a decl statement
3002 /// @returns the variable decl statement pointer
3003 const ast::VariableDeclStatement* Decl(const Source& source, const ast::Variable* var) {
3004 return create<ast::VariableDeclStatement>(source, var);
3005 }
3006
3007 /// Creates a ast::VariableDeclStatement for the input variable
3008 /// @param var the variable to wrap in a decl statement
3009 /// @returns the variable decl statement pointer
3010 const ast::VariableDeclStatement* Decl(const ast::Variable* var) {
3011 return create<ast::VariableDeclStatement>(var);
3012 }
3013
3014 /// Creates a ast::SwitchStatement with input expression and cases
3015 /// @param source the source information
3016 /// @param condition the condition expression initializer
3017 /// @param cases case statements
3018 /// @returns the switch statement pointer
James Priced0ed63e2023-03-14 22:49:51 +00003019 template <typename ExpressionInit, typename... Cases, typename = DisableIfVectorLike<Cases...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003020 const ast::SwitchStatement* Switch(const Source& source,
3021 ExpressionInit&& condition,
3022 Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00003023 return create<ast::SwitchStatement>(
3024 source, Expr(std::forward<ExpressionInit>(condition)),
3025 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
James Priced0ed63e2023-03-14 22:49:51 +00003026 std::forward<Cases>(cases)...},
James Price8cf01ee2023-03-16 19:48:20 +00003027 utils::Empty, utils::Empty);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003028 }
3029
3030 /// Creates a ast::SwitchStatement with input expression and cases
3031 /// @param condition the condition expression initializer
3032 /// @param cases case statements
3033 /// @returns the switch statement pointer
3034 template <typename ExpressionInit,
3035 typename... Cases,
James Priced0ed63e2023-03-14 22:49:51 +00003036 typename = DisableIfSource<ExpressionInit>,
3037 typename = DisableIfVectorLike<Cases...>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003038 const ast::SwitchStatement* Switch(ExpressionInit&& condition, Cases&&... cases) {
Ben Clayton783b1692022-08-02 17:03:35 +00003039 return create<ast::SwitchStatement>(
3040 Expr(std::forward<ExpressionInit>(condition)),
3041 utils::Vector<const ast::CaseStatement*, sizeof...(cases)>{
James Priced0ed63e2023-03-14 22:49:51 +00003042 std::forward<Cases>(cases)...},
James Price8cf01ee2023-03-16 19:48:20 +00003043 utils::Empty, utils::Empty);
James Priced0ed63e2023-03-14 22:49:51 +00003044 }
3045
3046 /// Creates a ast::SwitchStatement with input expression, cases, and optional attributes
3047 /// @param source the source information
3048 /// @param condition the condition expression initializer
3049 /// @param cases case statements
James Price8cf01ee2023-03-16 19:48:20 +00003050 /// @param stmt_attributes optional statement attributes
3051 /// @param body_attributes optional body attributes
James Priced0ed63e2023-03-14 22:49:51 +00003052 /// @returns the switch statement pointer
3053 template <typename ExpressionInit>
3054 const ast::SwitchStatement* Switch(
3055 const Source& source,
3056 ExpressionInit&& condition,
3057 utils::VectorRef<const ast::CaseStatement*> cases,
James Price8cf01ee2023-03-16 19:48:20 +00003058 utils::VectorRef<const ast::Attribute*> stmt_attributes = utils::Empty,
3059 utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
James Priced0ed63e2023-03-14 22:49:51 +00003060 return create<ast::SwitchStatement>(source, Expr(std::forward<ExpressionInit>(condition)),
James Price8cf01ee2023-03-16 19:48:20 +00003061 cases, std::move(stmt_attributes),
3062 std::move(body_attributes));
James Priced0ed63e2023-03-14 22:49:51 +00003063 }
3064
3065 /// Creates a ast::SwitchStatement with input expression, cases, and optional attributes
3066 /// @param condition the condition expression initializer
3067 /// @param cases case statements
James Price8cf01ee2023-03-16 19:48:20 +00003068 /// @param stmt_attributes optional statement attributes
3069 /// @param body_attributes optional body attributes
James Priced0ed63e2023-03-14 22:49:51 +00003070 /// @returns the switch statement pointer
3071 template <typename ExpressionInit, typename = DisableIfSource<ExpressionInit>>
3072 const ast::SwitchStatement* Switch(
3073 ExpressionInit&& condition,
3074 utils::VectorRef<const ast::CaseStatement*> cases,
James Price8cf01ee2023-03-16 19:48:20 +00003075 utils::VectorRef<const ast::Attribute*> stmt_attributes = utils::Empty,
3076 utils::VectorRef<const ast::Attribute*> body_attributes = utils::Empty) {
James Priced0ed63e2023-03-14 22:49:51 +00003077 return create<ast::SwitchStatement>(Expr(std::forward<ExpressionInit>(condition)), cases,
James Price8cf01ee2023-03-16 19:48:20 +00003078 std::move(stmt_attributes), std::move(body_attributes));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003079 }
3080
3081 /// Creates a ast::CaseStatement with input list of selectors, and body
Ben Clayton971318f2023-02-14 13:52:43 +00003082 /// @param selectors list of selectors
3083 /// @param body the case body
3084 /// @returns the case statement pointer
3085 const ast::CaseStatement* Case(utils::VectorRef<const ast::CaseSelector*> selectors,
3086 const ast::BlockStatement* body = nullptr) {
3087 return Case(source_, std::move(selectors), body);
3088 }
3089
3090 /// Creates a ast::CaseStatement with input list of selectors, and body
dan sinclair41e4d9a2022-05-01 14:40:55 +00003091 /// @param source the source information
3092 /// @param selectors list of selectors
3093 /// @param body the case body
3094 /// @returns the case statement pointer
3095 const ast::CaseStatement* Case(const Source& source,
dan sinclairf148f082022-10-19 15:55:02 +00003096 utils::VectorRef<const ast::CaseSelector*> selectors,
dan sinclair41e4d9a2022-05-01 14:40:55 +00003097 const ast::BlockStatement* body = nullptr) {
3098 return create<ast::CaseStatement>(source, std::move(selectors), body ? body : Block());
3099 }
3100
dan sinclair41e4d9a2022-05-01 14:40:55 +00003101 /// Convenient overload that takes a single selector
3102 /// @param selector a single case selector
3103 /// @param body the case body
3104 /// @returns the case statement pointer
dan sinclairf148f082022-10-19 15:55:02 +00003105 const ast::CaseStatement* Case(const ast::CaseSelector* selector,
dan sinclair41e4d9a2022-05-01 14:40:55 +00003106 const ast::BlockStatement* body = nullptr) {
Ben Clayton971318f2023-02-14 13:52:43 +00003107 return Case(utils::Vector{selector}, body ? body : Block());
3108 }
3109
3110 /// Convenience function that creates a 'default' ast::CaseStatement
3111 /// @param body the case body
3112 /// @returns the case statement pointer
3113 const ast::CaseStatement* DefaultCase(const ast::BlockStatement* body = nullptr) {
3114 return DefaultCase(source_, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003115 }
3116
3117 /// Convenience function that creates a 'default' ast::CaseStatement
3118 /// @param source the source information
3119 /// @param body the case body
3120 /// @returns the case statement pointer
3121 const ast::CaseStatement* DefaultCase(const Source& source,
3122 const ast::BlockStatement* body = nullptr) {
dan sinclairf148f082022-10-19 15:55:02 +00003123 return Case(source, utils::Vector{DefaultCaseSelector(source)}, body);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003124 }
3125
dan sinclairf148f082022-10-19 15:55:02 +00003126 /// Convenience function that creates a case selector
3127 /// @param source the source information
3128 /// @param expr the selector expression
3129 /// @returns the selector pointer
3130 template <typename EXPR>
3131 const ast::CaseSelector* CaseSelector(const Source& source, EXPR&& expr) {
3132 return create<ast::CaseSelector>(source, Expr(std::forward<EXPR>(expr)));
3133 }
3134
3135 /// Convenience function that creates a case selector
3136 /// @param expr the selector expression
3137 /// @returns the selector pointer
3138 template <typename EXPR>
3139 const ast::CaseSelector* CaseSelector(EXPR&& expr) {
3140 return create<ast::CaseSelector>(source_, Expr(std::forward<EXPR>(expr)));
3141 }
3142
3143 /// Convenience function that creates a default case selector
3144 /// @param source the source information
3145 /// @returns the selector pointer
3146 const ast::CaseSelector* DefaultCaseSelector(const Source& source) {
3147 return create<ast::CaseSelector>(source, nullptr);
3148 }
3149
3150 /// Convenience function that creates a default case selector
3151 /// @returns the selector pointer
3152 const ast::CaseSelector* DefaultCaseSelector() { return create<ast::CaseSelector>(nullptr); }
3153
dan sinclair41e4d9a2022-05-01 14:40:55 +00003154 /// Creates an ast::BuiltinAttribute
3155 /// @param source the source information
3156 /// @param builtin the builtin value
3157 /// @returns the builtin attribute pointer
Ben Clayton4d3ff972023-02-21 17:33:54 +00003158 template <typename BUILTIN>
3159 const ast::BuiltinAttribute* Builtin(const Source& source, BUILTIN&& builtin) {
3160 return create<ast::BuiltinAttribute>(source, Expr(std::forward<BUILTIN>(builtin)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003161 }
3162
3163 /// Creates an ast::BuiltinAttribute
3164 /// @param builtin the builtin value
3165 /// @returns the builtin attribute pointer
Ben Clayton4d3ff972023-02-21 17:33:54 +00003166 template <typename BUILTIN>
3167 const ast::BuiltinAttribute* Builtin(BUILTIN&& builtin) {
3168 return create<ast::BuiltinAttribute>(source_, Expr(std::forward<BUILTIN>(builtin)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003169 }
3170
3171 /// Creates an ast::InterpolateAttribute
Ben Claytonf0b4dbb2023-02-21 21:05:28 +00003172 /// @param type the interpolation type
3173 /// @returns the interpolate attribute pointer
3174 template <typename TYPE, typename = DisableIfSource<TYPE>>
3175 const ast::InterpolateAttribute* Interpolate(TYPE&& type) {
3176 return Interpolate(source_, std::forward<TYPE>(type));
3177 }
3178
3179 /// Creates an ast::InterpolateAttribute
dan sinclair41e4d9a2022-05-01 14:40:55 +00003180 /// @param source the source information
3181 /// @param type the interpolation type
dan sinclair41e4d9a2022-05-01 14:40:55 +00003182 /// @returns the interpolate attribute pointer
Ben Claytonf0b4dbb2023-02-21 21:05:28 +00003183 template <typename TYPE>
3184 const ast::InterpolateAttribute* Interpolate(const Source& source, TYPE&& type) {
3185 return create<ast::InterpolateAttribute>(source, Expr(std::forward<TYPE>(type)), nullptr);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003186 }
3187
3188 /// Creates an ast::InterpolateAttribute
3189 /// @param type the interpolation type
3190 /// @param sampling the interpolation sampling
3191 /// @returns the interpolate attribute pointer
Ben Claytonf0b4dbb2023-02-21 21:05:28 +00003192 template <typename TYPE, typename SAMPLING, typename = DisableIfSource<TYPE>>
3193 const ast::InterpolateAttribute* Interpolate(TYPE&& type, SAMPLING&& sampling) {
3194 return Interpolate(source_, std::forward<TYPE>(type), std::forward<SAMPLING>(sampling));
3195 }
3196
3197 /// Creates an ast::InterpolateAttribute
3198 /// @param source the source information
3199 /// @param type the interpolation type
3200 /// @param sampling the interpolation sampling
3201 /// @returns the interpolate attribute pointer
3202 template <typename TYPE, typename SAMPLING>
3203 const ast::InterpolateAttribute* Interpolate(const Source& source,
3204 TYPE&& type,
3205 SAMPLING&& sampling) {
3206 if constexpr (std::is_same_v<std::decay_t<SAMPLING>, builtin::InterpolationSampling>) {
3207 if (sampling == builtin::InterpolationSampling::kUndefined) {
3208 return create<ast::InterpolateAttribute>(source, Expr(std::forward<TYPE>(type)),
3209 nullptr);
3210 }
3211 }
3212 return create<ast::InterpolateAttribute>(source, Expr(std::forward<TYPE>(type)),
3213 Expr(std::forward<SAMPLING>(sampling)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003214 }
3215
3216 /// Creates an ast::InterpolateAttribute using flat interpolation
3217 /// @param source the source information
3218 /// @returns the interpolate attribute pointer
3219 const ast::InterpolateAttribute* Flat(const Source& source) {
dan sinclair993a6582023-02-20 08:37:45 +00003220 return Interpolate(source, builtin::InterpolationType::kFlat);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003221 }
3222
3223 /// Creates an ast::InterpolateAttribute using flat interpolation
3224 /// @returns the interpolate attribute pointer
dan sinclair993a6582023-02-20 08:37:45 +00003225 const ast::InterpolateAttribute* Flat() {
3226 return Interpolate(builtin::InterpolationType::kFlat);
3227 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00003228
3229 /// Creates an ast::InvariantAttribute
3230 /// @param source the source information
3231 /// @returns the invariant attribute pointer
3232 const ast::InvariantAttribute* Invariant(const Source& source) {
3233 return create<ast::InvariantAttribute>(source);
3234 }
3235
3236 /// Creates an ast::InvariantAttribute
3237 /// @returns the invariant attribute pointer
3238 const ast::InvariantAttribute* Invariant() { return create<ast::InvariantAttribute>(source_); }
3239
dan sinclaira79c6602023-02-21 18:49:40 +00003240 /// Creates an ast::MustUseAttribute
3241 /// @param source the source information
3242 /// @returns the invariant attribute pointer
3243 const ast::MustUseAttribute* MustUse(const Source& source) {
3244 return create<ast::MustUseAttribute>(source);
3245 }
3246
3247 /// Creates an ast::MustUseAttribute
3248 /// @returns the invariant attribute pointer
3249 const ast::MustUseAttribute* MustUse() { return create<ast::MustUseAttribute>(source_); }
3250
dan sinclair41e4d9a2022-05-01 14:40:55 +00003251 /// Creates an ast::LocationAttribute
3252 /// @param source the source information
dan sinclairf9eeed62022-09-07 22:25:24 +00003253 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003254 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003255 template <typename EXPR>
3256 const ast::LocationAttribute* Location(const Source& source, EXPR&& location) {
3257 return create<ast::LocationAttribute>(source, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003258 }
3259
3260 /// Creates an ast::LocationAttribute
dan sinclairf9eeed62022-09-07 22:25:24 +00003261 /// @param location the location value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003262 /// @returns the location attribute pointer
dan sinclairf9eeed62022-09-07 22:25:24 +00003263 template <typename EXPR>
3264 const ast::LocationAttribute* Location(EXPR&& location) {
3265 return create<ast::LocationAttribute>(source_, Expr(std::forward<EXPR>(location)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003266 }
3267
Brandon Jones3ef08ef2023-06-20 19:56:24 +00003268 /// Creates an ast::IndexAttribute
3269 /// @param source the source information
3270 /// @param index the index value expression
3271 /// @returns the index attribute pointer
3272 template <typename EXPR>
3273 const ast::IndexAttribute* Index(const Source& source, EXPR&& index) {
3274 return create<ast::IndexAttribute>(source, Expr(std::forward<EXPR>(index)));
3275 }
3276
3277 /// Creates an ast::IndexAttribute
3278 /// @param index the index value expression
3279 /// @returns the index attribute pointer
3280 template <typename EXPR>
3281 const ast::IndexAttribute* Index(EXPR&& index) {
3282 return create<ast::IndexAttribute>(source_, Expr(std::forward<EXPR>(index)));
3283 }
3284
dan sinclair41e4d9a2022-05-01 14:40:55 +00003285 /// Creates an ast::IdAttribute
3286 /// @param source the source information
3287 /// @param id the id value
3288 /// @returns the override attribute pointer
Ben Clayton9a6acc42022-07-27 20:50:40 +00003289 const ast::IdAttribute* Id(const Source& source, OverrideId id) {
dan sinclair5361d9e2022-08-31 13:39:48 +00003290 return create<ast::IdAttribute>(source, Expr(AInt(id.value)));
Ben Clayton9a6acc42022-07-27 20:50:40 +00003291 }
3292
3293 /// Creates an ast::IdAttribute with an override identifier
3294 /// @param id the optional id value
3295 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003296 const ast::IdAttribute* Id(OverrideId id) {
3297 return create<ast::IdAttribute>(Expr(AInt(id.value)));
3298 }
Ben Clayton9a6acc42022-07-27 20:50:40 +00003299
3300 /// Creates an ast::IdAttribute
3301 /// @param source the source information
dan sinclair5361d9e2022-08-31 13:39:48 +00003302 /// @param id the id value expression
Ben Clayton9a6acc42022-07-27 20:50:40 +00003303 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003304 template <typename EXPR>
3305 const ast::IdAttribute* Id(const Source& source, EXPR&& id) {
3306 return create<ast::IdAttribute>(source, Expr(std::forward<EXPR>(id)));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003307 }
3308
Ben Clayton9a6acc42022-07-27 20:50:40 +00003309 /// Creates an ast::IdAttribute with an override identifier
dan sinclair5361d9e2022-08-31 13:39:48 +00003310 /// @param id the optional id value expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003311 /// @returns the override attribute pointer
dan sinclair5361d9e2022-08-31 13:39:48 +00003312 template <typename EXPR>
3313 const ast::IdAttribute* Id(EXPR&& id) {
3314 return create<ast::IdAttribute>(Expr(std::forward<EXPR>(id)));
3315 }
dan sinclair41e4d9a2022-05-01 14:40:55 +00003316
3317 /// Creates an ast::StageAttribute
3318 /// @param source the source information
3319 /// @param stage the pipeline stage
3320 /// @returns the stage attribute pointer
3321 const ast::StageAttribute* Stage(const Source& source, ast::PipelineStage stage) {
3322 return create<ast::StageAttribute>(source, stage);
3323 }
3324
3325 /// Creates an ast::StageAttribute
3326 /// @param stage the pipeline stage
3327 /// @returns the stage attribute pointer
3328 const ast::StageAttribute* Stage(ast::PipelineStage stage) {
3329 return create<ast::StageAttribute>(source_, stage);
3330 }
3331
3332 /// Creates an ast::WorkgroupAttribute
3333 /// @param x the x dimension expression
3334 /// @returns the workgroup attribute pointer
3335 template <typename EXPR_X>
3336 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x) {
3337 return WorkgroupSize(std::forward<EXPR_X>(x), nullptr, nullptr);
3338 }
3339
3340 /// Creates an ast::WorkgroupAttribute
Ben Claytonb8ac93392022-05-28 10:34:06 +00003341 /// @param source the source information
dan sinclair41e4d9a2022-05-01 14:40:55 +00003342 /// @param x the x dimension expression
dan sinclair7517e212022-08-24 21:31:45 +00003343 /// @returns the workgroup attribute pointer
3344 template <typename EXPR_X>
3345 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x) {
3346 return WorkgroupSize(source, std::forward<EXPR_X>(x), nullptr, nullptr);
3347 }
3348
3349 /// Creates an ast::WorkgroupAttribute
3350 /// @param source the source information
3351 /// @param x the x dimension expression
dan sinclair41e4d9a2022-05-01 14:40:55 +00003352 /// @param y the y dimension expression
3353 /// @returns the workgroup attribute pointer
3354 template <typename EXPR_X, typename EXPR_Y>
Ben Claytonb8ac93392022-05-28 10:34:06 +00003355 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source, EXPR_X&& x, EXPR_Y&& y) {
3356 return WorkgroupSize(source, std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3357 }
3358
3359 /// Creates an ast::WorkgroupAttribute
3360 /// @param x the x dimension expression
3361 /// @param y the y dimension expression
3362 /// @returns the workgroup attribute pointer
3363 template <typename EXPR_X, typename EXPR_Y, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003364 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y) {
3365 return WorkgroupSize(std::forward<EXPR_X>(x), std::forward<EXPR_Y>(y), nullptr);
3366 }
3367
3368 /// Creates an ast::WorkgroupAttribute
3369 /// @param source the source information
3370 /// @param x the x dimension expression
3371 /// @param y the y dimension expression
3372 /// @param z the z dimension expression
3373 /// @returns the workgroup attribute pointer
3374 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z>
3375 const ast::WorkgroupAttribute* WorkgroupSize(const Source& source,
3376 EXPR_X&& x,
3377 EXPR_Y&& y,
3378 EXPR_Z&& z) {
3379 return create<ast::WorkgroupAttribute>(source, Expr(std::forward<EXPR_X>(x)),
3380 Expr(std::forward<EXPR_Y>(y)),
3381 Expr(std::forward<EXPR_Z>(z)));
3382 }
3383
3384 /// Creates an ast::WorkgroupAttribute
3385 /// @param x the x dimension expression
3386 /// @param y the y dimension expression
3387 /// @param z the z dimension expression
3388 /// @returns the workgroup attribute pointer
Ben Claytonb8ac93392022-05-28 10:34:06 +00003389 template <typename EXPR_X, typename EXPR_Y, typename EXPR_Z, typename = DisableIfSource<EXPR_X>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003390 const ast::WorkgroupAttribute* WorkgroupSize(EXPR_X&& x, EXPR_Y&& y, EXPR_Z&& z) {
3391 return create<ast::WorkgroupAttribute>(source_, Expr(std::forward<EXPR_X>(x)),
3392 Expr(std::forward<EXPR_Y>(y)),
3393 Expr(std::forward<EXPR_Z>(z)));
3394 }
3395
3396 /// Creates an ast::DisableValidationAttribute
3397 /// @param validation the validation to disable
3398 /// @returns the disable validation attribute pointer
3399 const ast::DisableValidationAttribute* Disable(ast::DisabledValidation validation) {
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003400 return ASTNodes().Create<ast::DisableValidationAttribute>(ID(), AllocateNodeID(),
3401 validation);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003402 }
3403
Ben Clayton7883a0c2023-04-20 23:51:53 +00003404 /// Passthrough overload
3405 /// @param name the diagnostic rule name
3406 /// @returns @p name
3407 const ast::DiagnosticRuleName* DiagnosticRuleName(const ast::DiagnosticRuleName* name) {
3408 return name;
3409 }
3410
3411 /// Creates an ast::DiagnosticRuleName
3412 /// @param name the diagnostic rule name
3413 /// @returns the diagnostic rule name
Ben Clayton12914ee2023-02-02 22:20:32 +00003414 template <typename NAME>
Ben Clayton7883a0c2023-04-20 23:51:53 +00003415 const ast::DiagnosticRuleName* DiagnosticRuleName(NAME&& name) {
dan sinclair05590052023-04-19 16:52:46 +00003416 static_assert(
3417 !utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
3418 "it is invalid for a diagnostic rule name to be templated");
Ben Clayton7883a0c2023-04-20 23:51:53 +00003419 auto* name_ident = Ident(std::forward<NAME>(name));
3420 return create<ast::DiagnosticRuleName>(name_ident->source, name_ident);
3421 }
3422
3423 /// Creates an ast::DiagnosticRuleName
3424 /// @param category the diagnostic rule category
3425 /// @param name the diagnostic rule name
3426 /// @returns the diagnostic rule name
3427 template <typename CATEGORY, typename NAME, typename = DisableIfSource<CATEGORY>>
3428 const ast::DiagnosticRuleName* DiagnosticRuleName(CATEGORY&& category, NAME&& name) {
3429 static_assert(
3430 !utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
3431 "it is invalid for a diagnostic rule name to be templated");
3432 static_assert(
3433 !utils::traits::IsType<utils::traits::PtrElTy<CATEGORY>, ast::TemplatedIdentifier>,
3434 "it is invalid for a diagnostic rule category to be templated");
3435 auto* category_ident = Ident(std::forward<CATEGORY>(category));
3436 auto* name_ident = Ident(std::forward<NAME>(name));
3437 Source source = category_ident->source;
3438 source.range.end = name_ident->source.range.end;
3439 return create<ast::DiagnosticRuleName>(source, category_ident, name_ident);
3440 }
3441
3442 /// Creates an ast::DiagnosticRuleName
3443 /// @param source the source information
3444 /// @param name the diagnostic rule name
3445 /// @returns the diagnostic rule name
3446 template <typename NAME>
3447 const ast::DiagnosticRuleName* DiagnosticRuleName(const Source& source, NAME&& name) {
3448 static_assert(
3449 !utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
3450 "it is invalid for a diagnostic rule name to be templated");
3451 auto* name_ident = Ident(std::forward<NAME>(name));
3452 return create<ast::DiagnosticRuleName>(source, name_ident);
3453 }
3454
3455 /// Creates an ast::DiagnosticRuleName
3456 /// @param source the source information
3457 /// @param category the diagnostic rule category
3458 /// @param name the diagnostic rule name
3459 /// @returns the diagnostic rule name
3460 template <typename CATEGORY, typename NAME>
3461 const ast::DiagnosticRuleName* DiagnosticRuleName(const Source& source,
3462 CATEGORY&& category,
3463 NAME&& name) {
3464 static_assert(
3465 !utils::traits::IsType<utils::traits::PtrElTy<NAME>, ast::TemplatedIdentifier>,
3466 "it is invalid for a diagnostic rule name to be templated");
3467 static_assert(
3468 !utils::traits::IsType<utils::traits::PtrElTy<CATEGORY>, ast::TemplatedIdentifier>,
3469 "it is invalid for a diagnostic rule category to be templated");
3470 auto* category_ident = Ident(std::forward<CATEGORY>(category));
3471 auto* name_ident = Ident(std::forward<NAME>(name));
3472 return create<ast::DiagnosticRuleName>(source, category_ident, name_ident);
3473 }
3474
3475 /// Creates an ast::DiagnosticAttribute
3476 /// @param source the source information
3477 /// @param severity the diagnostic severity control
3478 /// @param rule_args the arguments used to construct the rule name
3479 /// @returns the diagnostic attribute pointer
3480 template <typename... RULE_ARGS>
3481 const ast::DiagnosticAttribute* DiagnosticAttribute(const Source& source,
3482 builtin::DiagnosticSeverity severity,
3483 RULE_ARGS&&... rule_args) {
Ben Clayton12914ee2023-02-02 22:20:32 +00003484 return create<ast::DiagnosticAttribute>(
Ben Clayton7883a0c2023-04-20 23:51:53 +00003485 source, ast::DiagnosticControl(
3486 severity, DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...)));
James Priceef5434d2023-01-24 18:44:27 +00003487 }
3488
3489 /// Creates an ast::DiagnosticAttribute
3490 /// @param severity the diagnostic severity control
Ben Clayton7883a0c2023-04-20 23:51:53 +00003491 /// @param rule_args the arguments used to construct the rule name
James Priceef5434d2023-01-24 18:44:27 +00003492 /// @returns the diagnostic attribute pointer
Ben Clayton7883a0c2023-04-20 23:51:53 +00003493 template <typename... RULE_ARGS>
dan sinclairb5af23d2023-02-19 17:34:44 +00003494 const ast::DiagnosticAttribute* DiagnosticAttribute(builtin::DiagnosticSeverity severity,
Ben Clayton7883a0c2023-04-20 23:51:53 +00003495 RULE_ARGS&&... rule_args) {
Ben Clayton12914ee2023-02-02 22:20:32 +00003496 return create<ast::DiagnosticAttribute>(
Ben Clayton7883a0c2023-04-20 23:51:53 +00003497 source_, ast::DiagnosticControl(
3498 severity, DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...)));
James Priceef5434d2023-01-24 18:44:27 +00003499 }
3500
James Price98dc5a82023-02-04 12:20:55 +00003501 /// Add a diagnostic directive to the module.
James Price5f3449f2023-01-23 17:55:55 +00003502 /// @param source the source information
3503 /// @param severity the diagnostic severity control
Ben Clayton7883a0c2023-04-20 23:51:53 +00003504 /// @param rule_args the arguments used to construct the rule name
James Price98dc5a82023-02-04 12:20:55 +00003505 /// @returns the diagnostic directive pointer
Ben Clayton7883a0c2023-04-20 23:51:53 +00003506 template <typename... RULE_ARGS>
James Price98dc5a82023-02-04 12:20:55 +00003507 const ast::DiagnosticDirective* DiagnosticDirective(const Source& source,
dan sinclairb5af23d2023-02-19 17:34:44 +00003508 builtin::DiagnosticSeverity severity,
Ben Clayton7883a0c2023-04-20 23:51:53 +00003509 RULE_ARGS&&... rule_args) {
3510 auto* rule = DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...);
3511 auto* directive =
3512 create<ast::DiagnosticDirective>(source, ast::DiagnosticControl(severity, rule));
James Price98dc5a82023-02-04 12:20:55 +00003513 AST().AddDiagnosticDirective(directive);
3514 return directive;
James Price5f3449f2023-01-23 17:55:55 +00003515 }
3516
James Price98dc5a82023-02-04 12:20:55 +00003517 /// Add a diagnostic directive to the module.
James Price5f3449f2023-01-23 17:55:55 +00003518 /// @param severity the diagnostic severity control
Ben Clayton7883a0c2023-04-20 23:51:53 +00003519 /// @param rule_args the arguments used to construct the rule name
James Price98dc5a82023-02-04 12:20:55 +00003520 /// @returns the diagnostic directive pointer
Ben Clayton7883a0c2023-04-20 23:51:53 +00003521 template <typename... RULE_ARGS>
dan sinclairb5af23d2023-02-19 17:34:44 +00003522 const ast::DiagnosticDirective* DiagnosticDirective(builtin::DiagnosticSeverity severity,
Ben Clayton7883a0c2023-04-20 23:51:53 +00003523 RULE_ARGS&&... rule_args) {
3524 auto* rule = DiagnosticRuleName(std::forward<RULE_ARGS>(rule_args)...);
3525 auto* directive =
3526 create<ast::DiagnosticDirective>(source_, ast::DiagnosticControl(severity, rule));
James Price98dc5a82023-02-04 12:20:55 +00003527 AST().AddDiagnosticDirective(directive);
3528 return directive;
James Price15bf15d2023-01-24 21:01:36 +00003529 }
3530
dan sinclair41e4d9a2022-05-01 14:40:55 +00003531 /// Sets the current builder source to `src`
3532 /// @param src the Source used for future create() calls
3533 void SetSource(const Source& src) {
3534 AssertNotMoved();
3535 source_ = src;
3536 }
3537
3538 /// Sets the current builder source to `loc`
3539 /// @param loc the Source used for future create() calls
3540 void SetSource(const Source::Location& loc) {
3541 AssertNotMoved();
3542 source_ = Source(loc);
3543 }
3544
3545 /// Helper for returning the resolved semantic type of the expression `expr`.
3546 /// @note As the Resolver is run when the Program is built, this will only be
3547 /// useful for the Resolver itself and tests that use their own Resolver.
3548 /// @param expr the AST expression
3549 /// @return the resolved semantic type for the expression, or nullptr if the
3550 /// expression has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003551 const type::Type* TypeOf(const ast::Expression* expr) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003552
3553 /// Helper for returning the resolved semantic type of the variable `var`.
3554 /// @note As the Resolver is run when the Program is built, this will only be
3555 /// useful for the Resolver itself and tests that use their own Resolver.
3556 /// @param var the AST variable
3557 /// @return the resolved semantic type for the variable, or nullptr if the
3558 /// variable has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003559 const type::Type* TypeOf(const ast::Variable* var) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003560
dan sinclair41e4d9a2022-05-01 14:40:55 +00003561 /// Helper for returning the resolved semantic type of the AST type
3562 /// declaration `type_decl`.
3563 /// @note As the Resolver is run when the Program is built, this will only be
3564 /// useful for the Resolver itself and tests that use their own Resolver.
3565 /// @param type_decl the AST type declaration
3566 /// @return the resolved semantic type for the type declaration, or nullptr if
3567 /// the type declaration has no resolved type.
dan sinclair5f764d82022-12-08 00:32:27 +00003568 const type::Type* TypeOf(const ast::TypeDecl* type_decl) const;
dan sinclair41e4d9a2022-05-01 14:40:55 +00003569
3570 /// Wraps the ast::Expression in a statement. This is used by tests that
3571 /// construct a partial AST and require the Resolver to reach these
3572 /// nodes.
3573 /// @param expr the ast::Expression to be wrapped by an ast::Statement
3574 /// @return the ast::Statement that wraps the ast::Expression
3575 const ast::Statement* WrapInStatement(const ast::Expression* expr);
3576 /// Wraps the ast::Variable in a ast::VariableDeclStatement. This is used by
3577 /// tests that construct a partial AST and require the Resolver to reach
3578 /// these nodes.
3579 /// @param v the ast::Variable to be wrapped by an ast::VariableDeclStatement
3580 /// @return the ast::VariableDeclStatement that wraps the ast::Variable
3581 const ast::VariableDeclStatement* WrapInStatement(const ast::Variable* v);
3582 /// Returns the statement argument. Used as a passthrough-overload by
3583 /// WrapInFunction().
3584 /// @param stmt the ast::Statement
3585 /// @return `stmt`
3586 const ast::Statement* WrapInStatement(const ast::Statement* stmt);
3587 /// Wraps the list of arguments in a simple function so that each is reachable
3588 /// by the Resolver.
3589 /// @param args a mix of ast::Expression, ast::Statement, ast::Variables.
3590 /// @returns the function
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003591 template <typename... ARGS,
dan sinclair05590052023-04-19 16:52:46 +00003592 typename = utils::traits::EnableIf<(CanWrapInStatement<ARGS>::value && ...)>>
dan sinclair41e4d9a2022-05-01 14:40:55 +00003593 const ast::Function* WrapInFunction(ARGS&&... args) {
Ben Clayton783b1692022-08-02 17:03:35 +00003594 utils::Vector stmts{
3595 WrapInStatement(std::forward<ARGS>(args))...,
3596 };
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003597 return WrapInFunction(std::move(stmts));
dan sinclair41e4d9a2022-05-01 14:40:55 +00003598 }
3599 /// @param stmts a list of ast::Statement that will be wrapped by a function,
3600 /// so that each statement is reachable by the Resolver.
3601 /// @returns the function
Ben Clayton783b1692022-08-02 17:03:35 +00003602 const ast::Function* WrapInFunction(utils::VectorRef<const ast::Statement*> stmts);
dan sinclair41e4d9a2022-05-01 14:40:55 +00003603
Ben Clayton1e67e532023-05-24 23:07:36 +00003604 /// The constants manager
3605 constant::Manager constants;
3606
dan sinclair41e4d9a2022-05-01 14:40:55 +00003607 /// The builder types
3608 TypesBuilder const ty{this};
3609
3610 protected:
3611 /// Asserts that the builder has not been moved.
3612 void AssertNotMoved() const;
3613
3614 private:
3615 ProgramID id_;
Ben Clayton4a92a3c2022-07-18 20:50:02 +00003616 ast::NodeID last_ast_node_id_ = ast::NodeID{static_cast<decltype(ast::NodeID::value)>(0) - 1};
dan sinclair41e4d9a2022-05-01 14:40:55 +00003617 ASTNodeAllocator ast_nodes_;
3618 SemNodeAllocator sem_nodes_;
3619 ast::Module* ast_;
3620 sem::Info sem_;
3621 SymbolTable symbols_{id_};
3622 diag::List diagnostics_;
3623
3624 /// The source to use when creating AST nodes without providing a Source as
3625 /// the first argument.
3626 Source source_;
3627
3628 /// Set by SetResolveOnBuild(). If set, the Resolver will be run on the
3629 /// program when built.
3630 bool resolve_on_build_ = true;
3631
3632 /// Set by MarkAsMoved(). Once set, no methods may be called on this builder.
3633 bool moved_ = false;
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003634};
3635
3636//! @cond Doxygen_Suppress
3637// Various template specializations for ProgramBuilder::TypesBuilder::CToAST.
3638template <>
Ben Clayton46ee6392022-11-09 22:04:11 +00003639struct ProgramBuilder::TypesBuilder::CToAST<AInt> {
Ben Clayton971318f2023-02-14 13:52:43 +00003640 static ast::Type get(const ProgramBuilder::TypesBuilder*) { return ast::Type{}; }
Ben Clayton46ee6392022-11-09 22:04:11 +00003641};
3642template <>
3643struct ProgramBuilder::TypesBuilder::CToAST<AFloat> {
Ben Clayton971318f2023-02-14 13:52:43 +00003644 static ast::Type get(const ProgramBuilder::TypesBuilder*) { return ast::Type{}; }
Ben Clayton46ee6392022-11-09 22:04:11 +00003645};
3646template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003647struct ProgramBuilder::TypesBuilder::CToAST<i32> {
Ben Clayton971318f2023-02-14 13:52:43 +00003648 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->i32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003649};
3650template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003651struct ProgramBuilder::TypesBuilder::CToAST<u32> {
Ben Clayton971318f2023-02-14 13:52:43 +00003652 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->u32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003653};
3654template <>
Ben Clayton0ce9ab02022-05-05 20:23:40 +00003655struct ProgramBuilder::TypesBuilder::CToAST<f32> {
Ben Clayton971318f2023-02-14 13:52:43 +00003656 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->f32(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003657};
3658template <>
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00003659struct ProgramBuilder::TypesBuilder::CToAST<f16> {
Ben Clayton971318f2023-02-14 13:52:43 +00003660 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->f16(); }
Zhaoming Jiang62bfd312022-05-13 12:01:11 +00003661};
3662template <>
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003663struct ProgramBuilder::TypesBuilder::CToAST<bool> {
Ben Clayton971318f2023-02-14 13:52:43 +00003664 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->bool_(); }
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003665};
Ben Clayton66805b02023-06-14 22:00:01 +00003666template <typename T, uint32_t N>
3667struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::array<T, N>> {
3668 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->array<T, N>(); }
3669};
3670template <typename T>
3671struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::atomic<T>> {
3672 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->atomic<T>(); }
3673};
3674template <uint32_t C, uint32_t R, typename T>
3675struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::mat<C, R, T>> {
3676 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->mat<T>(C, R); }
3677};
3678template <uint32_t N, typename T>
3679struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::vec<N, T>> {
3680 static ast::Type get(const ProgramBuilder::TypesBuilder* t) { return t->vec<T, N>(); }
3681};
3682template <builtin::AddressSpace ADDRESS, typename T, builtin::Access ACCESS>
3683struct ProgramBuilder::TypesBuilder::CToAST<tint::builtin::fluent_types::ptr<ADDRESS, T, ACCESS>> {
3684 static ast::Type get(const ProgramBuilder::TypesBuilder* t) {
3685 return t->ptr<ADDRESS, T, ACCESS>();
3686 }
3687};
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003688//! @endcond
3689
3690/// @param builder the ProgramBuilder
3691/// @returns the ProgramID of the ProgramBuilder
3692inline ProgramID ProgramIDOf(const ProgramBuilder* builder) {
dan sinclair41e4d9a2022-05-01 14:40:55 +00003693 return builder->ID();
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003694}
3695
Antonio Maioranodfa92a92022-12-23 17:56:56 +00003696// Primary template for metafunction that evaluates to true iff T can be wrapped in a statement.
3697template <typename T, typename /* = void */>
3698struct CanWrapInStatement : std::false_type {};
3699
3700// Specialization of CanWrapInStatement
3701template <typename T>
3702struct CanWrapInStatement<
3703 T,
3704 std::void_t<decltype(std::declval<ProgramBuilder>().WrapInStatement(std::declval<T>()))>>
3705 : std::true_type {};
3706
Ryan Harrisondbc13af2022-02-21 15:19:07 +00003707} // namespace tint
3708
3709#endif // SRC_TINT_PROGRAM_BUILDER_H_