wgsl_parse/
syntax_impl.rs

1use crate::span::Spanned;
2
3use super::syntax::*;
4
5impl TranslationUnit {
6    /// New empty [`TranslationUnit`]
7    pub fn new() -> Self {
8        Self::default()
9    }
10
11    /// Remove all [`GlobalDeclaration::Void`] and [`Statement::Void`]
12    pub fn remove_voids(&mut self) {
13        self.global_declarations.retain_mut(|decl| match decl {
14            GlobalDeclaration::Void => false,
15            _ => {
16                decl.remove_voids();
17                true
18            }
19        })
20    }
21}
22
23impl GlobalDeclaration {
24    /// Remove all [`Statement::Void`]
25    pub fn remove_voids(&mut self) {
26        if let GlobalDeclaration::Function(decl) = self {
27            decl.body.remove_voids();
28        }
29    }
30}
31
32impl TypeExpression {
33    /// New [`TypeExpression`] with no template.
34    pub fn new(ident: Ident) -> Self {
35        Self {
36            #[cfg(feature = "imports")]
37            path: None,
38            ident,
39            template_args: None,
40        }
41    }
42}
43
44impl CompoundStatement {
45    /// Remove all [`Statement::Void`]
46    pub fn remove_voids(&mut self) {
47        self.statements.retain_mut(|stmt| match stmt.node_mut() {
48            Statement::Void => false,
49            _ => {
50                stmt.remove_voids();
51                true
52            }
53        })
54    }
55}
56
57impl Statement {
58    /// Remove all [`Statement::Void`]
59    pub fn remove_voids(&mut self) {
60        match self {
61            Statement::Compound(stmt) => {
62                stmt.remove_voids();
63            }
64            Statement::If(stmt) => {
65                stmt.if_clause.body.remove_voids();
66                for clause in &mut stmt.else_if_clauses {
67                    clause.body.remove_voids();
68                }
69                if let Some(clause) = &mut stmt.else_clause {
70                    clause.body.remove_voids();
71                }
72            }
73            Statement::Switch(stmt) => stmt
74                .clauses
75                .iter_mut()
76                .for_each(|clause| clause.body.remove_voids()),
77            Statement::Loop(stmt) => stmt.body.remove_voids(),
78            Statement::For(stmt) => stmt.body.remove_voids(),
79            Statement::While(stmt) => stmt.body.remove_voids(),
80            _ => (),
81        }
82    }
83}
84
85impl AccessMode {
86    /// Is [`Self::Read`] or [`Self::ReadWrite`]
87    pub fn is_read(&self) -> bool {
88        matches!(self, Self::Read | Self::ReadWrite)
89    }
90    /// Is [`Self::Write`] or [`Self::ReadWrite`]
91    pub fn is_write(&self) -> bool {
92        matches!(self, Self::Write | Self::ReadWrite)
93    }
94}
95
96impl From<Ident> for TypeExpression {
97    fn from(name: Ident) -> Self {
98        Self {
99            #[cfg(feature = "imports")]
100            path: None,
101            ident: name,
102            template_args: None,
103        }
104    }
105}
106
107impl From<ExpressionNode> for ReturnStatement {
108    fn from(expression: ExpressionNode) -> Self {
109        Self {
110            #[cfg(feature = "attributes")]
111            attributes: Default::default(),
112            expression: Some(expression),
113        }
114    }
115}
116impl From<Expression> for ReturnStatement {
117    fn from(expression: Expression) -> Self {
118        Self::from(ExpressionNode::from(expression))
119    }
120}
121
122impl From<FunctionCall> for FunctionCallStatement {
123    fn from(call: FunctionCall) -> Self {
124        Self {
125            #[cfg(feature = "attributes")]
126            attributes: Default::default(),
127            call,
128        }
129    }
130}
131
132impl GlobalDeclaration {
133    /// Get the name of the declaration, if it has one.
134    pub fn ident(&self) -> Option<&Ident> {
135        match self {
136            GlobalDeclaration::Void => None,
137            GlobalDeclaration::Declaration(decl) => Some(&decl.ident),
138            GlobalDeclaration::TypeAlias(decl) => Some(&decl.ident),
139            GlobalDeclaration::Struct(decl) => Some(&decl.ident),
140            GlobalDeclaration::Function(decl) => Some(&decl.ident),
141            GlobalDeclaration::ConstAssert(_) => None,
142        }
143    }
144    /// Get the name of the declaration, if it has one.
145    pub fn ident_mut(&mut self) -> Option<&mut Ident> {
146        match self {
147            GlobalDeclaration::Void => None,
148            GlobalDeclaration::Declaration(decl) => Some(&mut decl.ident),
149            GlobalDeclaration::TypeAlias(decl) => Some(&mut decl.ident),
150            GlobalDeclaration::Struct(decl) => Some(&mut decl.ident),
151            GlobalDeclaration::Function(decl) => Some(&mut decl.ident),
152            GlobalDeclaration::ConstAssert(_) => None,
153        }
154    }
155}
156
157/// A trait implemented on all types that can be prefixed by attributes.
158pub trait Decorated {
159    /// List all attributes (`@name`) of a syntax node.
160    fn attributes(&self) -> &[Attribute];
161    /// List all attributes (`@name`) of a syntax node.
162    fn attributes_mut(&mut self) -> &mut [Attribute];
163}
164
165impl<T: Decorated> Decorated for Spanned<T> {
166    fn attributes(&self) -> &[Attribute] {
167        self.node().attributes()
168    }
169
170    fn attributes_mut(&mut self) -> &mut [Attribute] {
171        self.node_mut().attributes_mut()
172    }
173}
174
175macro_rules! impl_decorated_struct {
176    ($ty:ty) => {
177        impl Decorated for $ty {
178            fn attributes(&self) -> &[Attribute] {
179                &self.attributes
180            }
181            fn attributes_mut(&mut self) -> &mut [Attribute] {
182                &mut self.attributes
183            }
184        }
185    };
186}
187
188#[cfg(all(feature = "imports", feature = "attributes"))]
189impl_decorated_struct!(Import);
190
191#[cfg(feature = "attributes")]
192impl Decorated for GlobalDirective {
193    fn attributes(&self) -> &[Attribute] {
194        match self {
195            GlobalDirective::Diagnostic(directive) => &directive.attributes,
196            GlobalDirective::Enable(directive) => &directive.attributes,
197            GlobalDirective::Requires(directive) => &directive.attributes,
198        }
199    }
200
201    fn attributes_mut(&mut self) -> &mut [Attribute] {
202        match self {
203            GlobalDirective::Diagnostic(directive) => &mut directive.attributes,
204            GlobalDirective::Enable(directive) => &mut directive.attributes,
205            GlobalDirective::Requires(directive) => &mut directive.attributes,
206        }
207    }
208}
209
210#[cfg(feature = "attributes")]
211impl_decorated_struct!(DiagnosticDirective);
212
213#[cfg(feature = "attributes")]
214impl_decorated_struct!(EnableDirective);
215
216#[cfg(feature = "attributes")]
217impl_decorated_struct!(RequiresDirective);
218
219#[cfg(feature = "attributes")]
220impl Decorated for GlobalDeclaration {
221    fn attributes(&self) -> &[Attribute] {
222        match self {
223            GlobalDeclaration::Void => &[],
224            GlobalDeclaration::Declaration(decl) => &decl.attributes,
225            GlobalDeclaration::TypeAlias(decl) => &decl.attributes,
226            GlobalDeclaration::Struct(decl) => &decl.attributes,
227            GlobalDeclaration::Function(decl) => &decl.attributes,
228            GlobalDeclaration::ConstAssert(decl) => &decl.attributes,
229        }
230    }
231
232    fn attributes_mut(&mut self) -> &mut [Attribute] {
233        match self {
234            GlobalDeclaration::Void => &mut [],
235            GlobalDeclaration::Declaration(decl) => &mut decl.attributes,
236            GlobalDeclaration::TypeAlias(decl) => &mut decl.attributes,
237            GlobalDeclaration::Struct(decl) => &mut decl.attributes,
238            GlobalDeclaration::Function(decl) => &mut decl.attributes,
239            GlobalDeclaration::ConstAssert(decl) => &mut decl.attributes,
240        }
241    }
242}
243
244impl_decorated_struct!(Declaration);
245
246#[cfg(feature = "attributes")]
247impl_decorated_struct!(TypeAlias);
248
249#[cfg(feature = "attributes")]
250impl_decorated_struct!(Struct);
251
252impl_decorated_struct!(StructMember);
253
254impl_decorated_struct!(Function);
255
256impl_decorated_struct!(FormalParameter);
257
258#[cfg(feature = "attributes")]
259impl_decorated_struct!(ConstAssert);
260
261#[cfg(feature = "attributes")]
262impl Decorated for Statement {
263    fn attributes(&self) -> &[Attribute] {
264        match self {
265            Statement::Void => &[],
266            Statement::Compound(stmt) => &stmt.attributes,
267            Statement::Assignment(stmt) => &stmt.attributes,
268            Statement::Increment(stmt) => &stmt.attributes,
269            Statement::Decrement(stmt) => &stmt.attributes,
270            Statement::If(stmt) => &stmt.attributes,
271            Statement::Switch(stmt) => &stmt.attributes,
272            Statement::Loop(stmt) => &stmt.attributes,
273            Statement::For(stmt) => &stmt.attributes,
274            Statement::While(stmt) => &stmt.attributes,
275            Statement::Break(stmt) => &stmt.attributes,
276            Statement::Continue(stmt) => &stmt.attributes,
277            Statement::Return(stmt) => &stmt.attributes,
278            Statement::Discard(stmt) => &stmt.attributes,
279            Statement::FunctionCall(stmt) => &stmt.attributes,
280            Statement::ConstAssert(stmt) => &stmt.attributes,
281            Statement::Declaration(stmt) => &stmt.attributes,
282        }
283    }
284
285    fn attributes_mut(&mut self) -> &mut [Attribute] {
286        match self {
287            Statement::Void => &mut [],
288            Statement::Compound(stmt) => &mut stmt.attributes,
289            Statement::Assignment(stmt) => &mut stmt.attributes,
290            Statement::Increment(stmt) => &mut stmt.attributes,
291            Statement::Decrement(stmt) => &mut stmt.attributes,
292            Statement::If(stmt) => &mut stmt.attributes,
293            Statement::Switch(stmt) => &mut stmt.attributes,
294            Statement::Loop(stmt) => &mut stmt.attributes,
295            Statement::For(stmt) => &mut stmt.attributes,
296            Statement::While(stmt) => &mut stmt.attributes,
297            Statement::Break(stmt) => &mut stmt.attributes,
298            Statement::Continue(stmt) => &mut stmt.attributes,
299            Statement::Return(stmt) => &mut stmt.attributes,
300            Statement::Discard(stmt) => &mut stmt.attributes,
301            Statement::FunctionCall(stmt) => &mut stmt.attributes,
302            Statement::ConstAssert(stmt) => &mut stmt.attributes,
303            Statement::Declaration(stmt) => &mut stmt.attributes,
304        }
305    }
306}
307
308impl_decorated_struct!(CompoundStatement);
309
310#[cfg(feature = "attributes")]
311impl_decorated_struct!(AssignmentStatement);
312
313#[cfg(feature = "attributes")]
314impl_decorated_struct!(IncrementStatement);
315
316#[cfg(feature = "attributes")]
317impl_decorated_struct!(DecrementStatement);
318
319impl_decorated_struct!(IfStatement);
320
321#[cfg(feature = "attributes")]
322impl_decorated_struct!(ElseIfClause);
323
324#[cfg(feature = "attributes")]
325impl_decorated_struct!(ElseClause);
326
327impl_decorated_struct!(SwitchStatement);
328
329#[cfg(feature = "attributes")]
330impl_decorated_struct!(SwitchClause);
331
332impl_decorated_struct!(LoopStatement);
333
334#[cfg(feature = "attributes")]
335impl_decorated_struct!(ContinuingStatement);
336
337#[cfg(feature = "attributes")]
338impl_decorated_struct!(BreakIfStatement);
339
340impl_decorated_struct!(ForStatement);
341
342impl_decorated_struct!(WhileStatement);
343
344#[cfg(feature = "attributes")]
345impl_decorated_struct!(BreakStatement);
346
347#[cfg(feature = "attributes")]
348impl_decorated_struct!(ContinueStatement);
349
350#[cfg(feature = "attributes")]
351impl_decorated_struct!(ReturnStatement);
352
353#[cfg(feature = "attributes")]
354impl_decorated_struct!(DiscardStatement);
355
356#[cfg(feature = "attributes")]
357impl_decorated_struct!(FunctionCallStatement);