1use alloc::vec::Vec;
2use core::hash::Hash;
3
4use crate::diagnostic_filter::DiagnosticFilterNode;
5use crate::front::wgsl::parse::directive::enable_extension::EnableExtensions;
6use crate::front::wgsl::parse::number::Number;
7use crate::front::wgsl::Scalar;
8use crate::{Arena, FastIndexSet, Handle, Span};
9
10#[derive(Debug, Default)]
11pub struct TranslationUnit<'a> {
12    pub enable_extensions: EnableExtensions,
13    pub decls: Arena<GlobalDecl<'a>>,
14    pub expressions: Arena<Expression<'a>>,
26
27    pub types: Arena<Type<'a>>,
32
33    pub diagnostic_filters: Arena<DiagnosticFilterNode>,
38    pub diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
43
44    pub doc_comments: Vec<&'a str>,
47}
48
49#[derive(Debug, Clone, Copy)]
50pub struct Ident<'a> {
51    pub name: &'a str,
52    pub span: Span,
53}
54
55#[derive(Debug)]
56pub enum IdentExpr<'a> {
57    Unresolved(&'a str),
58    Local(Handle<Local>),
59}
60
61#[derive(Debug)]
68pub struct Dependency<'a> {
69    pub ident: &'a str,
71
72    pub usage: Span,
74}
75
76impl Hash for Dependency<'_> {
77    fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
78        self.ident.hash(state);
79    }
80}
81
82impl PartialEq for Dependency<'_> {
83    fn eq(&self, other: &Self) -> bool {
84        self.ident == other.ident
85    }
86}
87
88impl Eq for Dependency<'_> {}
89
90#[derive(Debug)]
92pub struct GlobalDecl<'a> {
93    pub kind: GlobalDeclKind<'a>,
94
95    pub dependencies: FastIndexSet<Dependency<'a>>,
98}
99
100#[derive(Debug)]
101pub enum GlobalDeclKind<'a> {
102    Fn(Function<'a>),
103    Var(GlobalVariable<'a>),
104    Const(Const<'a>),
105    Override(Override<'a>),
106    Struct(Struct<'a>),
107    Type(TypeAlias<'a>),
108    ConstAssert(Handle<Expression<'a>>),
109}
110
111#[derive(Debug)]
112pub struct FunctionArgument<'a> {
113    pub name: Ident<'a>,
114    pub ty: Handle<Type<'a>>,
115    pub binding: Option<Binding<'a>>,
116    pub handle: Handle<Local>,
117}
118
119#[derive(Debug)]
120pub struct FunctionResult<'a> {
121    pub ty: Handle<Type<'a>>,
122    pub binding: Option<Binding<'a>>,
123    pub must_use: bool,
124}
125
126#[derive(Debug)]
127pub struct EntryPoint<'a> {
128    pub stage: crate::ShaderStage,
129    pub early_depth_test: Option<crate::EarlyDepthTest>,
130    pub workgroup_size: Option<[Option<Handle<Expression<'a>>>; 3]>,
131}
132
133#[cfg(doc)]
134use crate::front::wgsl::lower::{LocalExpressionContext, StatementContext};
135
136#[derive(Debug)]
137pub struct Function<'a> {
138    pub entry_point: Option<EntryPoint<'a>>,
139    pub name: Ident<'a>,
140    pub arguments: Vec<FunctionArgument<'a>>,
141    pub result: Option<FunctionResult<'a>>,
142    pub body: Block<'a>,
143    pub diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
144    pub doc_comments: Vec<&'a str>,
145}
146
147#[derive(Debug)]
148pub enum Binding<'a> {
149    BuiltIn(crate::BuiltIn),
150    Location {
151        location: Handle<Expression<'a>>,
152        interpolation: Option<crate::Interpolation>,
153        sampling: Option<crate::Sampling>,
154        blend_src: Option<Handle<Expression<'a>>>,
155    },
156}
157
158#[derive(Debug)]
159pub struct ResourceBinding<'a> {
160    pub group: Handle<Expression<'a>>,
161    pub binding: Handle<Expression<'a>>,
162}
163
164#[derive(Debug)]
165pub struct GlobalVariable<'a> {
166    pub name: Ident<'a>,
167    pub space: crate::AddressSpace,
168    pub binding: Option<ResourceBinding<'a>>,
169    pub ty: Option<Handle<Type<'a>>>,
170    pub init: Option<Handle<Expression<'a>>>,
171    pub doc_comments: Vec<&'a str>,
172}
173
174#[derive(Debug)]
175pub struct StructMember<'a> {
176    pub name: Ident<'a>,
177    pub ty: Handle<Type<'a>>,
178    pub binding: Option<Binding<'a>>,
179    pub align: Option<Handle<Expression<'a>>>,
180    pub size: Option<Handle<Expression<'a>>>,
181    pub doc_comments: Vec<&'a str>,
182}
183
184#[derive(Debug)]
185pub struct Struct<'a> {
186    pub name: Ident<'a>,
187    pub members: Vec<StructMember<'a>>,
188    pub doc_comments: Vec<&'a str>,
189}
190
191#[derive(Debug)]
192pub struct TypeAlias<'a> {
193    pub name: Ident<'a>,
194    pub ty: Handle<Type<'a>>,
195}
196
197#[derive(Debug)]
198pub struct Const<'a> {
199    pub name: Ident<'a>,
200    pub ty: Option<Handle<Type<'a>>>,
201    pub init: Handle<Expression<'a>>,
202    pub doc_comments: Vec<&'a str>,
203}
204
205#[derive(Debug)]
206pub struct Override<'a> {
207    pub name: Ident<'a>,
208    pub id: Option<Handle<Expression<'a>>>,
209    pub ty: Option<Handle<Type<'a>>>,
210    pub init: Option<Handle<Expression<'a>>>,
211}
212
213#[derive(Debug, Copy, Clone)]
218pub enum ArraySize<'a> {
219    Constant(Handle<Expression<'a>>),
221    Dynamic,
222}
223
224#[derive(Debug)]
225pub enum Type<'a> {
226    Scalar(Scalar),
227    Vector {
228        size: crate::VectorSize,
229        ty: Handle<Type<'a>>,
230        ty_span: Span,
231    },
232    Matrix {
233        columns: crate::VectorSize,
234        rows: crate::VectorSize,
235        ty: Handle<Type<'a>>,
236        ty_span: Span,
237    },
238    Atomic(Scalar),
239    Pointer {
240        base: Handle<Type<'a>>,
241        space: crate::AddressSpace,
242    },
243    Array {
244        base: Handle<Type<'a>>,
245        size: ArraySize<'a>,
246    },
247    Image {
248        dim: crate::ImageDimension,
249        arrayed: bool,
250        class: crate::ImageClass,
251    },
252    Sampler {
253        comparison: bool,
254    },
255    AccelerationStructure {
256        vertex_return: bool,
257    },
258    RayQuery {
259        vertex_return: bool,
260    },
261    RayDesc,
262    RayIntersection,
263    BindingArray {
264        base: Handle<Type<'a>>,
265        size: ArraySize<'a>,
266    },
267
268    User(Ident<'a>),
270}
271
272#[derive(Debug, Default)]
273pub struct Block<'a> {
274    pub stmts: Vec<Statement<'a>>,
275}
276
277#[derive(Debug)]
278pub struct Statement<'a> {
279    pub kind: StatementKind<'a>,
280    pub span: Span,
281}
282
283#[derive(Debug)]
284pub enum StatementKind<'a> {
285    LocalDecl(LocalDecl<'a>),
286    Block(Block<'a>),
287    If {
288        condition: Handle<Expression<'a>>,
289        accept: Block<'a>,
290        reject: Block<'a>,
291    },
292    Switch {
293        selector: Handle<Expression<'a>>,
294        cases: Vec<SwitchCase<'a>>,
295    },
296    Loop {
297        body: Block<'a>,
298        continuing: Block<'a>,
299        break_if: Option<Handle<Expression<'a>>>,
300    },
301    Break,
302    Continue,
303    Return {
304        value: Option<Handle<Expression<'a>>>,
305    },
306    Kill,
307    Call {
308        function: Ident<'a>,
309        arguments: Vec<Handle<Expression<'a>>>,
310    },
311    Assign {
312        target: Handle<Expression<'a>>,
313        op: Option<crate::BinaryOperator>,
314        value: Handle<Expression<'a>>,
315    },
316    Increment(Handle<Expression<'a>>),
317    Decrement(Handle<Expression<'a>>),
318    Phony(Handle<Expression<'a>>),
319    ConstAssert(Handle<Expression<'a>>),
320}
321
322#[derive(Debug)]
323pub enum SwitchValue<'a> {
324    Expr(Handle<Expression<'a>>),
325    Default,
326}
327
328#[derive(Debug)]
329pub struct SwitchCase<'a> {
330    pub value: SwitchValue<'a>,
331    pub body: Block<'a>,
332    pub fall_through: bool,
333}
334
335#[derive(Debug)]
356pub enum ConstructorType<'a> {
357    Scalar(Scalar),
359
360    PartialVector { size: crate::VectorSize },
363
364    Vector {
367        size: crate::VectorSize,
368        ty: Handle<Type<'a>>,
369        ty_span: Span,
370    },
371
372    PartialMatrix {
375        columns: crate::VectorSize,
376        rows: crate::VectorSize,
377    },
378
379    Matrix {
382        columns: crate::VectorSize,
383        rows: crate::VectorSize,
384        ty: Handle<Type<'a>>,
385        ty_span: Span,
386    },
387
388    PartialArray,
391
392    Array {
395        base: Handle<Type<'a>>,
396        size: ArraySize<'a>,
397    },
398
399    Type(Handle<crate::Type>),
404}
405
406#[derive(Debug, Copy, Clone)]
407pub enum Literal {
408    Bool(bool),
409    Number(Number),
410}
411
412#[cfg(doc)]
413use crate::front::wgsl::lower::Lowerer;
414
415#[derive(Debug)]
416pub enum Expression<'a> {
417    Literal(Literal),
418    Ident(IdentExpr<'a>),
419
420    Construct {
435        ty: ConstructorType<'a>,
436        ty_span: Span,
437        components: Vec<Handle<Expression<'a>>>,
438    },
439    Unary {
440        op: crate::UnaryOperator,
441        expr: Handle<Expression<'a>>,
442    },
443    AddrOf(Handle<Expression<'a>>),
444    Deref(Handle<Expression<'a>>),
445    Binary {
446        op: crate::BinaryOperator,
447        left: Handle<Expression<'a>>,
448        right: Handle<Expression<'a>>,
449    },
450
451    Call {
466        function: Ident<'a>,
467        arguments: Vec<Handle<Expression<'a>>>,
468    },
469    Index {
470        base: Handle<Expression<'a>>,
471        index: Handle<Expression<'a>>,
472    },
473    Member {
474        base: Handle<Expression<'a>>,
475        field: Ident<'a>,
476    },
477    Bitcast {
478        expr: Handle<Expression<'a>>,
479        to: Handle<Type<'a>>,
480        ty_span: Span,
481    },
482}
483
484#[derive(Debug)]
485pub struct LocalVariable<'a> {
486    pub name: Ident<'a>,
487    pub ty: Option<Handle<Type<'a>>>,
488    pub init: Option<Handle<Expression<'a>>>,
489    pub handle: Handle<Local>,
490}
491
492#[derive(Debug)]
493pub struct Let<'a> {
494    pub name: Ident<'a>,
495    pub ty: Option<Handle<Type<'a>>>,
496    pub init: Handle<Expression<'a>>,
497    pub handle: Handle<Local>,
498}
499
500#[derive(Debug)]
501pub struct LocalConst<'a> {
502    pub name: Ident<'a>,
503    pub ty: Option<Handle<Type<'a>>>,
504    pub init: Handle<Expression<'a>>,
505    pub handle: Handle<Local>,
506}
507
508#[derive(Debug)]
509pub enum LocalDecl<'a> {
510    Var(LocalVariable<'a>),
511    Let(Let<'a>),
512    Const(LocalConst<'a>),
513}
514
515#[derive(Debug)]
516pub struct Local;