Skip to main content

wgsl_parse/
syntax_impl.rs

1use wgsl_types::inst::LiteralInstance;
2
3use super::syntax::*;
4use crate::span::Spanned;
5
6impl TranslationUnit {
7    /// New empty [`TranslationUnit`]
8    pub fn new() -> Self {
9        Self::default()
10    }
11
12    /// Remove all [`GlobalDeclaration::Void`] and [`Statement::Void`]
13    pub fn remove_voids(&mut self) {
14        self.global_declarations
15            .retain_mut(|decl| match decl.node() {
16                GlobalDeclaration::Void => false,
17                _ => {
18                    decl.remove_voids();
19                    true
20                }
21            })
22    }
23
24    pub fn sort_declarations(&mut self) {
25        use std::cmp::Ordering::*;
26        type Decl = GlobalDeclaration;
27        self.global_declarations
28            .sort_unstable_by(|a, b| match (a.node(), b.node()) {
29                (Decl::Compound(_), Decl::Compound(_)) => Equal,
30                (Decl::Compound(_), _) => Less,
31                (_, Decl::Compound(_)) => Greater,
32
33                (Decl::Void, Decl::Void) => Equal,
34                (Decl::Void, Decl::Declaration(_)) => Less,
35                (Decl::Void, Decl::Struct(_)) => Less,
36                (Decl::Void, Decl::TypeAlias(_)) => Less,
37                (Decl::Void, Decl::ConstAssert(_)) => Less,
38                (Decl::Void, Decl::Function(_)) => Less,
39
40                (Decl::Declaration(_), Decl::Void) => Greater,
41                (Decl::Declaration(d1), Decl::Declaration(d2)) => {
42                    // sort in this order: const < override < let < var
43                    // then sort by name.
44                    match (d1.kind, d2.kind) {
45                        (DeclarationKind::Const, DeclarationKind::Const)
46                        | (DeclarationKind::Override, DeclarationKind::Override)
47                        | (DeclarationKind::Let, DeclarationKind::Let)
48                        | (DeclarationKind::Var(_), DeclarationKind::Var(_)) => {
49                            d1.ident.name().cmp(&d2.ident.name())
50                        }
51                        (DeclarationKind::Const, DeclarationKind::Override) => Less,
52                        (DeclarationKind::Const, DeclarationKind::Let) => Less,
53                        (DeclarationKind::Const, DeclarationKind::Var(_)) => Less,
54                        (DeclarationKind::Override, DeclarationKind::Const) => Greater,
55                        (DeclarationKind::Override, DeclarationKind::Let) => Less,
56                        (DeclarationKind::Override, DeclarationKind::Var(_)) => Less,
57                        (DeclarationKind::Let, DeclarationKind::Const) => Greater,
58                        (DeclarationKind::Let, DeclarationKind::Override) => Greater,
59                        (DeclarationKind::Let, DeclarationKind::Var(_)) => Less,
60                        (DeclarationKind::Var(_), DeclarationKind::Const) => Greater,
61                        (DeclarationKind::Var(_), DeclarationKind::Override) => Greater,
62                        (DeclarationKind::Var(_), DeclarationKind::Let) => Greater,
63                    }
64                }
65                (Decl::Declaration(_), Decl::Struct(_)) => Less,
66                (Decl::Declaration(_), Decl::TypeAlias(_)) => Less,
67                (Decl::Declaration(_), Decl::ConstAssert(_)) => Less,
68                (Decl::Declaration(_), Decl::Function(_)) => Less,
69
70                (Decl::Struct(_), Decl::Void) => Greater,
71                (Decl::Struct(_), Decl::Declaration(_)) => Greater,
72                (Decl::Struct(d1), Decl::Struct(d2)) => d1.ident.name().cmp(&d2.ident.name()),
73                (Decl::Struct(_), Decl::TypeAlias(_)) => Less,
74                (Decl::Struct(_), Decl::ConstAssert(_)) => Less,
75                (Decl::Struct(_), Decl::Function(_)) => Less,
76
77                (Decl::TypeAlias(_), Decl::Void) => Greater,
78                (Decl::TypeAlias(_), Decl::Declaration(_)) => Greater,
79                (Decl::TypeAlias(_), Decl::Struct(_)) => Greater,
80                (Decl::TypeAlias(d1), Decl::TypeAlias(d2)) => d1.ident.name().cmp(&d2.ident.name()),
81                (Decl::TypeAlias(_), Decl::ConstAssert(_)) => Less,
82                (Decl::TypeAlias(_), Decl::Function(_)) => Less,
83
84                (Decl::ConstAssert(_), Decl::Void) => Greater,
85                (Decl::ConstAssert(_), Decl::Declaration(_)) => Greater,
86                (Decl::ConstAssert(_), Decl::Struct(_)) => Greater,
87                (Decl::ConstAssert(_), Decl::TypeAlias(_)) => Greater,
88                (Decl::ConstAssert(c1), Decl::ConstAssert(c2)) => {
89                    // const_assert have no identifiers, we compare the stringification
90                    c1.to_string().cmp(&c2.to_string())
91                }
92                (Decl::ConstAssert(_), Decl::Function(_)) => Less,
93
94                (Decl::Function(_), Decl::Void) => Greater,
95                (Decl::Function(_), Decl::Declaration(_)) => Greater,
96                (Decl::Function(_), Decl::Struct(_)) => Greater,
97                (Decl::Function(_), Decl::TypeAlias(_)) => Greater,
98                (Decl::Function(_), Decl::ConstAssert(_)) => Greater,
99                (Decl::Function(d1), Decl::Function(d2)) => d1.ident.name().cmp(&d2.ident.name()),
100            });
101    }
102}
103
104impl ModulePath {
105    /// Create a new module path from components.
106    ///
107    /// Precondition: the path components must be valid WGSL identifiers.
108    pub fn new(origin: PathOrigin, components: Vec<String>) -> Self {
109        Self { origin, components }
110    }
111
112    /// Create a module path that refers to the root module, i.e. `package`.
113    ///
114    /// Technically `import package;` is not a valid import statement in WESL code.
115    /// However adding an item to the path, such as `import package::foo;` points at
116    /// declaration `foo` in the root module.
117    pub fn new_root() -> Self {
118        Self::new(PathOrigin::Absolute, vec![])
119    }
120
121    /// Create a new module path from a filesystem path.
122    ///
123    /// * Paths with a root (leading `/` on Unix) produce `package::` paths.
124    /// * Relative paths (starting with `.` or `..`) produce `self::` or `super::` paths.
125    /// * The file extension is ignored.
126    ///
127    /// # Panics
128    ///
129    /// * The path must not start with a prefix, like C:\ on windows.
130    /// * The path must contain at least one named component.
131    /// * Named components must be valid module names.
132    ///   (Module names are WGSL identifiers + certain reserved names, see wesl-spec#127)
133    pub fn from_path(path: impl AsRef<std::path::Path>) -> Self {
134        use std::path::Component;
135        let path = path.as_ref().with_extension("");
136        let mut parts = path.components().peekable();
137
138        let origin = match parts.next() {
139            Some(Component::Prefix(_)) => panic!("path starts with a Windows prefix"),
140            Some(Component::RootDir) => PathOrigin::Absolute,
141            Some(Component::CurDir) => PathOrigin::Relative(0),
142            Some(Component::ParentDir) => {
143                let mut n = 1;
144                while let Some(&Component::ParentDir) = parts.peek() {
145                    n += 1;
146                    parts.next().unwrap();
147                }
148                PathOrigin::Relative(n)
149            }
150            Some(Component::Normal(name)) => {
151                PathOrigin::Package(name.to_string_lossy().to_string())
152            }
153            None => panic!("path is empty"),
154        };
155
156        let mut components = Vec::new();
157        for part in parts {
158            match part {
159                Component::Prefix(_) | Component::RootDir => panic!("unexpected path component"),
160                Component::CurDir => {}
161                Component::ParentDir => {
162                    components.pop().expect("path escapes its origin");
163                    // TODO: if we escape the root we should insert a `super::`
164                }
165                Component::Normal(name) => {
166                    components.push(name.to_string_lossy().to_string());
167                }
168            }
169        }
170
171        Self { origin, components }
172    }
173
174    /// Create a `PathBuf` from a `ModulePath`.
175    ///
176    /// * `package::` paths are rooted (start with `/`).
177    /// * self::` or `super::` are relative (starting with `.` or `..`)`.
178    /// * There is no file extension.
179    pub fn to_path_buf(&self) -> std::path::PathBuf {
180        use std::path::PathBuf;
181        let mut fs_path = match &self.origin {
182            PathOrigin::Absolute => PathBuf::from("/"),
183            PathOrigin::Relative(0) => PathBuf::from("."),
184            PathOrigin::Relative(n) => PathBuf::from_iter((0..*n).map(|_| "..")),
185            PathOrigin::Package(name) => PathBuf::from(name),
186        };
187        fs_path.extend(&self.components);
188        fs_path
189    }
190
191    /// Append a component to the path.
192    ///
193    /// Precondition: the `item` must be a valid WGSL identifier.
194    pub fn push(&mut self, item: &str) {
195        self.components.push(item.to_string());
196    }
197
198    /// Get the first component of the module path.
199    pub fn first(&self) -> Option<&str> {
200        self.components.first().map(String::as_str)
201    }
202
203    /// Get the last component of the module path.
204    pub fn last(&self) -> Option<&str> {
205        self.components.last().map(String::as_str)
206    }
207
208    /// Append `suffix` to the module path.
209    pub fn join(mut self, suffix: impl IntoIterator<Item = String>) -> Self {
210        self.components.extend(suffix);
211        self
212    }
213
214    /// Append `suffix` to the module path.
215    ///
216    /// This function produces a `ModulePath` relative to `self`, as if `suffix` was
217    /// imported from module `self`.
218    ///
219    /// * If `suffix` is relative, it appends its components to `self`.
220    /// * If `suffix` if absolute or package, it ignores `self` components.
221    /// * If both `self` and `suffix` are package paths, then `suffix` imports from a
222    ///   sub-package. The package is renamed with a slash separating package names.
223    ///   (TODO: this is a hack)
224    pub fn join_path(&self, suffix: &Self) -> Self {
225        match suffix.origin {
226            PathOrigin::Absolute => {
227                match self.origin {
228                    PathOrigin::Absolute | PathOrigin::Relative(_) => suffix.clone(),
229                    PathOrigin::Package(_) => {
230                        // absolute import from inside a package is a package import
231                        let origin = self.origin.clone();
232                        let components = suffix.components.clone();
233                        Self { origin, components }
234                    }
235                }
236            }
237            PathOrigin::Relative(n) => {
238                let to_keep = self.components.len().saturating_sub(n);
239                let components = self
240                    .components
241                    .iter()
242                    .take(to_keep)
243                    .chain(&suffix.components)
244                    .cloned()
245                    .collect::<Vec<_>>();
246                let origin = match self.origin {
247                    PathOrigin::Absolute | PathOrigin::Package(_) => self.origin.clone(),
248                    PathOrigin::Relative(m) => {
249                        PathOrigin::Relative(m + n.saturating_sub(self.components.len()))
250                    }
251                };
252                Self { origin, components }
253            }
254            PathOrigin::Package(ref suffix_pkg) => {
255                match &self.origin {
256                    PathOrigin::Absolute | PathOrigin::Relative(_) => suffix.clone(),
257                    PathOrigin::Package(self_pkg) => {
258                        if self_pkg.rsplit('/').next() == suffix_pkg.rsplit('/').next() {
259                            // Same package - just use the suffix path with the package origin
260                            let origin = self.origin.clone();
261                            let components = suffix.components.clone();
262                            Self { origin, components }
263                        } else {
264                            // Importing a sub-package. This is a hack: we rename the package to
265                            // parent/child, which cannot be spelled in code.
266                            let origin = PathOrigin::Package(format!("{self_pkg}/{suffix_pkg}"));
267                            let components = suffix.components.clone();
268                            Self { origin, components }
269                        }
270                    }
271                }
272            }
273        }
274    }
275
276    /// Whether the module path starts with a `prefix`.
277    pub fn starts_with(&self, prefix: &Self) -> bool {
278        self.origin == prefix.origin
279            && self.components.len() >= prefix.components.len()
280            && prefix
281                .components
282                .iter()
283                .zip(&self.components)
284                .all(|(a, b)| a == b)
285    }
286
287    /// Whether the module path points at the route module.
288    ///
289    /// See [`Self::new_root`].
290    pub fn is_root(&self) -> bool {
291        self.origin.is_absolute() && self.components.is_empty()
292    }
293}
294
295#[test]
296fn test_module_path_join() {
297    use std::str::FromStr;
298    let cases = [
299        ("package::m1", "package::foo", "package::foo"),
300        ("package::m1", "self::foo", "package::m1::foo"),
301        ("package::m1", "super::foo", "package::foo"),
302        ("pkg::m1::m2", "package::foo", "pkg::foo"),
303        ("pkg::m1::m2", "self::foo", "pkg::m1::m2::foo"),
304        ("pkg::m1::m2", "super::foo", "pkg::m1::foo"),
305        ("pkg::m1", "super::super::foo", "pkg::foo"),
306        ("lygia::m1", "lygia::math", "lygia::math"),
307        ("lygia::m1", "pkg/lygia", "lygia"),
308        ("pkg/lygia::m1", "lygia", "pkg/lygia"),
309        ("pkg/lygia::m1", "lygia::math", "pkg/lygia::math"),
310        ("pkg1/lygia::m1", "pkg2/lygia::math", "pkg1/lygia::math"),
311        ("super", "super::foo", "super::super::foo"),
312        ("super::m1::m2::m3", "super::super::m4", "super::m1::m4"),
313        ("super", "self::foo", "super::foo"),
314        ("self", "super::foo", "super::foo"),
315    ];
316
317    for (parent, child, expect) in cases {
318        let parent = ModulePath::from_str(parent).unwrap();
319        let child = ModulePath::from_str(child).unwrap();
320        let expect = ModulePath::from_str(expect).unwrap();
321        println!("testing ModulePath::join_path({parent}, {child}) -> {expect}");
322        assert_eq!(parent.join_path(&child), expect);
323    }
324}
325
326#[derive(Clone, Copy, PartialEq, Eq, Debug, thiserror::Error)]
327pub enum ModulePathParseError {
328    #[error("module name cannot be empty")]
329    Empty,
330    #[error("`package` must be a prefix of the module path")]
331    MisplacedPackage,
332    #[error("`self` must be a prefix of the module path")]
333    MisplacedSelf,
334    #[error("`super` must be a prefix of the module path")]
335    MisplacedSuper,
336}
337
338impl std::str::FromStr for ModulePath {
339    type Err = ModulePathParseError;
340
341    /// Parse a WGSL string into a module path.
342    ///
343    /// Preconditions:
344    /// * The path components must be valid WESL module names.
345    fn from_str(s: &str) -> Result<Self, Self::Err> {
346        let mut parts = s.split("::").peekable();
347
348        let origin = match parts.next() {
349            Some("package") => PathOrigin::Absolute,
350            Some("self") => PathOrigin::Relative(0),
351            Some("super") => {
352                let mut n = 1;
353                while let Some(&"super") = parts.peek() {
354                    n += 1;
355                    parts.next().unwrap();
356                }
357                PathOrigin::Relative(n)
358            }
359            Some("") | None => return Err(ModulePathParseError::Empty),
360            Some(name) => PathOrigin::Package(name.to_string()),
361        };
362
363        let components = parts
364            .map(|part| match part {
365                "package" => Err(ModulePathParseError::MisplacedPackage),
366                "self" => Err(ModulePathParseError::MisplacedSelf),
367                "super" => Err(ModulePathParseError::MisplacedSuper),
368                _ => Ok(part.to_string()),
369            })
370            .collect::<Result<Vec<_>, _>>()?;
371
372        Ok(Self { origin, components })
373    }
374}
375
376#[test]
377fn test_module_path_fromstr() {
378    use std::str::FromStr;
379
380    let ok_cases = [
381        ("self", ModulePath::new(PathOrigin::Relative(0), vec![])),
382        ("super", ModulePath::new(PathOrigin::Relative(1), vec![])),
383        ("package", ModulePath::new(PathOrigin::Absolute, vec![])),
384        (
385            "a",
386            ModulePath::new(PathOrigin::Package("a".to_string()), vec![]),
387        ),
388        (
389            "super::super::a",
390            ModulePath::new(PathOrigin::Relative(2), vec!["a".to_string()]),
391        ),
392    ];
393    let err_cases = [
394        ("", ModulePathParseError::Empty),
395        ("a::super", ModulePathParseError::MisplacedSuper),
396        ("super::self", ModulePathParseError::MisplacedSelf),
397        ("self::package", ModulePathParseError::MisplacedPackage),
398    ];
399
400    for (s, m) in ok_cases {
401        assert_eq!(ModulePath::from_str(s), Ok(m))
402    }
403    for (s, e) in err_cases {
404        assert_eq!(ModulePath::from_str(s), Err(e))
405    }
406}
407
408impl GlobalDeclaration {
409    /// Remove all [`Statement::Void`].
410    pub fn remove_voids(&mut self) {
411        if let GlobalDeclaration::Function(decl) = self {
412            decl.body.remove_voids();
413        }
414    }
415
416    /// Get the [`Visibility`] of a global declaration.
417    pub fn visibility(&self) -> Visibility {
418        match self {
419            GlobalDeclaration::Declaration(decl) => decl.visibility,
420            GlobalDeclaration::TypeAlias(decl) => decl.visibility,
421            GlobalDeclaration::Struct(decl) => decl.visibility,
422            GlobalDeclaration::Function(decl) => decl.visibility,
423            GlobalDeclaration::Void
424            | GlobalDeclaration::ConstAssert(_)
425            | GlobalDeclaration::Compound(_) => Visibility::Private,
426        }
427    }
428}
429
430impl TypeAlias {
431    pub fn new(ident: Ident, ty: TypeExpression) -> Self {
432        Self {
433            attributes: Default::default(),
434            visibility: Default::default(),
435            ident,
436            ty,
437        }
438    }
439}
440
441impl Struct {
442    pub fn new(ident: Ident) -> Self {
443        Self {
444            attributes: Default::default(),
445            visibility: Default::default(),
446            ident,
447            members: Default::default(),
448        }
449    }
450}
451
452impl StructMember {
453    pub fn new(ident: Ident, ty: TypeExpression) -> Self {
454        Self {
455            attributes: Default::default(),
456            ident,
457            ty,
458        }
459    }
460}
461
462impl Function {
463    pub fn new(ident: Ident) -> Self {
464        Self {
465            attributes: Default::default(),
466            visibility: Default::default(),
467            ident,
468            parameters: Default::default(),
469            return_attributes: Default::default(),
470            return_type: Default::default(),
471            body: Default::default(),
472        }
473    }
474}
475
476impl FormalParameter {
477    pub fn new(ident: Ident, ty: TypeExpression) -> Self {
478        Self {
479            attributes: Default::default(),
480            ident,
481            ty,
482        }
483    }
484}
485
486impl ConstAssert {
487    pub fn new(expression: Expression) -> Self {
488        Self {
489            attributes: Default::default(),
490            expression: expression.into(),
491        }
492    }
493}
494
495impl TypeExpression {
496    /// New [`TypeExpression`] with no template.
497    pub fn new(ident: Ident) -> Self {
498        Self {
499            path: None,
500            ident,
501            template_args: None,
502        }
503    }
504}
505
506impl CompoundStatement {
507    /// Remove all [`Statement::Void`]
508    pub fn remove_voids(&mut self) {
509        self.statements.retain_mut(|stmt| match stmt.node_mut() {
510            Statement::Void => false,
511            _ => {
512                stmt.remove_voids();
513                true
514            }
515        })
516    }
517}
518
519impl Statement {
520    /// Remove all [`Statement::Void`]
521    pub fn remove_voids(&mut self) {
522        match self {
523            Statement::Compound(stmt) => {
524                stmt.remove_voids();
525            }
526            Statement::If(stmt) => {
527                stmt.if_clause.body.remove_voids();
528                for clause in &mut stmt.else_if_clauses {
529                    clause.body.remove_voids();
530                }
531                if let Some(clause) = &mut stmt.else_clause {
532                    clause.body.remove_voids();
533                }
534            }
535            Statement::Switch(stmt) => stmt
536                .clauses
537                .iter_mut()
538                .for_each(|clause| clause.body.remove_voids()),
539            Statement::Loop(stmt) => stmt.body.remove_voids(),
540            Statement::For(stmt) => stmt.body.remove_voids(),
541            Statement::While(stmt) => stmt.body.remove_voids(),
542            _ => (),
543        }
544    }
545}
546
547impl From<LiteralExpression> for LiteralInstance {
548    fn from(lit: LiteralExpression) -> Self {
549        match lit {
550            LiteralExpression::Bool(l) => LiteralInstance::Bool(l),
551            LiteralExpression::AbstractInt(l) => LiteralInstance::AbstractInt(l),
552            LiteralExpression::AbstractFloat(l) => LiteralInstance::AbstractFloat(l),
553            LiteralExpression::I32(l) => LiteralInstance::I32(l),
554            LiteralExpression::U32(l) => LiteralInstance::U32(l),
555            LiteralExpression::F32(l) => LiteralInstance::F32(l),
556            LiteralExpression::F16(l) => LiteralInstance::F16(wgsl_types::f16::from_f32(l)),
557            #[cfg(feature = "naga-ext")]
558            LiteralExpression::I64(l) => LiteralInstance::I64(l),
559            #[cfg(feature = "naga-ext")]
560            LiteralExpression::U64(l) => LiteralInstance::U64(l),
561            #[cfg(feature = "naga-ext")]
562            LiteralExpression::F64(l) => LiteralInstance::F64(l),
563        }
564    }
565}
566
567impl From<Ident> for TypeExpression {
568    fn from(ident: Ident) -> Self {
569        Self::new(ident)
570    }
571}
572
573impl From<ExpressionNode> for ReturnStatement {
574    fn from(expression: ExpressionNode) -> Self {
575        Self {
576            attributes: Default::default(),
577            expression: Some(expression),
578        }
579    }
580}
581impl From<Expression> for ReturnStatement {
582    fn from(expression: Expression) -> Self {
583        Self::from(ExpressionNode::from(expression))
584    }
585}
586
587impl From<FunctionCall> for FunctionCallStatement {
588    fn from(call: FunctionCall) -> Self {
589        Self {
590            attributes: Default::default(),
591            call,
592        }
593    }
594}
595
596// Transitive `From` implementations.
597// They have to be implemented manually unfortunately.
598
599macro_rules! impl_transitive_from {
600    ($from:ident => $middle:ident => $into:ident) => {
601        impl From<$from> for $into {
602            fn from(value: $from) -> Self {
603                $into::from($middle::from(value))
604            }
605        }
606    };
607}
608
609impl_transitive_from!(bool => LiteralExpression => Expression);
610impl_transitive_from!(i64 => LiteralExpression => Expression);
611impl_transitive_from!(f64 => LiteralExpression => Expression);
612impl_transitive_from!(i32 => LiteralExpression => Expression);
613impl_transitive_from!(u32 => LiteralExpression => Expression);
614impl_transitive_from!(f32 => LiteralExpression => Expression);
615impl_transitive_from!(Ident => TypeExpression => Expression);
616
617/// Trait implemented for all syntax node types.
618///
619/// This trait is useful for generic implementations over different syntax node types.
620/// Node types that do not have a span, an ident, or attributes return `None`.
621pub trait SyntaxNode {
622    /// Span of a syntax node.
623    fn span(&self) -> Option<Span> {
624        None
625    }
626
627    /// Identifier, if the syntax node is a declaration.
628    fn ident(&self) -> Option<Ident> {
629        None
630    }
631
632    /// List all attributes of a syntax node.
633    fn attributes(&self) -> &[AttributeNode] {
634        &[]
635    }
636    /// List all attributes of a syntax node.
637    fn attributes_mut(&mut self) -> &mut [AttributeNode] {
638        &mut []
639    }
640    /// Whether the node contains an attribute.
641    fn contains_attribute(&self, attribute: &Attribute) -> bool {
642        self.attributes().iter().any(|v| v.node() == attribute)
643    }
644    /// Remove attributes with predicate.
645    fn retain_attributes_mut<F>(&mut self, _predicate: F)
646    where
647        F: FnMut(&mut Attribute) -> bool,
648    {
649    }
650}
651
652impl<T: SyntaxNode> SyntaxNode for Spanned<T> {
653    fn span(&self) -> Option<Span> {
654        Some(self.span())
655    }
656
657    fn ident(&self) -> Option<Ident> {
658        self.node().ident()
659    }
660
661    fn attributes(&self) -> &[AttributeNode] {
662        self.node().attributes()
663    }
664
665    fn attributes_mut(&mut self) -> &mut [AttributeNode] {
666        self.node_mut().attributes_mut()
667    }
668
669    fn retain_attributes_mut<F>(&mut self, mut f: F)
670    where
671        F: FnMut(&mut Attribute) -> bool,
672    {
673        self.node_mut().retain_attributes_mut(|v| f(v))
674    }
675}
676
677macro_rules! impl_attrs_struct {
678    () => {
679        fn attributes(&self) -> &[AttributeNode] {
680            &self.attributes
681        }
682        fn attributes_mut(&mut self) -> &mut [AttributeNode] {
683            &mut self.attributes
684        }
685        fn retain_attributes_mut<F>(&mut self, mut f: F)
686        where
687            F: FnMut(&mut Attribute) -> bool,
688        {
689            self.attributes.retain_mut(|v| f(v))
690        }
691    };
692}
693
694#[allow(unused)]
695macro_rules! impl_attrs_enum {
696    ($($variant: path),* $(,)?) => {
697        fn attributes(&self) -> &[AttributeNode] {
698            match self {
699                $(
700                    $variant(x) => &x.attributes,
701                )*
702                #[allow(unreachable_patterns)]
703                _ => &[]
704            }
705        }
706        fn attributes_mut(&mut self) -> &mut [AttributeNode] {
707            match self {
708                $(
709                    $variant(x) => &mut x.attributes,
710                )*
711                #[allow(unreachable_patterns)]
712                _ => &mut []
713            }
714        }
715        fn retain_attributes_mut<F>(&mut self, mut f: F)
716        where
717            F: FnMut(&mut Attribute) -> bool,
718        {
719            match self {
720                $(
721                    $variant(x) => x.attributes.retain_mut(|v| f(v)),
722                )*
723                #[allow(unreachable_patterns)]
724                _ => {}
725            }
726        }
727    };
728}
729
730impl SyntaxNode for ImportStatement {
731    impl_attrs_struct! {}
732}
733
734impl SyntaxNode for GlobalDirective {
735    impl_attrs_enum! {
736        GlobalDirective::Diagnostic,
737        GlobalDirective::Enable,
738        GlobalDirective::Requires
739    }
740}
741
742impl SyntaxNode for DiagnosticDirective {
743    impl_attrs_struct! {}
744}
745
746impl SyntaxNode for EnableDirective {
747    impl_attrs_struct! {}
748}
749
750impl SyntaxNode for RequiresDirective {
751    impl_attrs_struct! {}
752}
753
754impl SyntaxNode for GlobalDeclaration {
755    fn ident(&self) -> Option<Ident> {
756        match self {
757            GlobalDeclaration::Void => None,
758            GlobalDeclaration::Declaration(decl) => Some(decl.ident.clone()),
759            GlobalDeclaration::TypeAlias(decl) => Some(decl.ident.clone()),
760            GlobalDeclaration::Struct(decl) => Some(decl.ident.clone()),
761            GlobalDeclaration::Function(decl) => Some(decl.ident.clone()),
762            GlobalDeclaration::ConstAssert(_) => None,
763            GlobalDeclaration::Compound(_) => None,
764        }
765    }
766
767    impl_attrs_enum! {
768        GlobalDeclaration::Declaration,
769        GlobalDeclaration::TypeAlias,
770        GlobalDeclaration::Struct,
771        GlobalDeclaration::Function,
772        GlobalDeclaration::ConstAssert,
773        GlobalDeclaration::Compound,
774    }
775}
776
777impl SyntaxNode for Declaration {
778    fn ident(&self) -> Option<Ident> {
779        Some(self.ident.clone())
780    }
781
782    impl_attrs_struct! {}
783}
784
785impl SyntaxNode for TypeAlias {
786    fn ident(&self) -> Option<Ident> {
787        Some(self.ident.clone())
788    }
789
790    impl_attrs_struct! {}
791}
792
793impl SyntaxNode for Struct {
794    fn ident(&self) -> Option<Ident> {
795        Some(self.ident.clone())
796    }
797
798    impl_attrs_struct! {}
799}
800
801impl SyntaxNode for StructMember {
802    fn ident(&self) -> Option<Ident> {
803        Some(self.ident.clone())
804    }
805
806    impl_attrs_struct! {}
807}
808
809impl SyntaxNode for Function {
810    fn ident(&self) -> Option<Ident> {
811        Some(self.ident.clone())
812    }
813
814    impl_attrs_struct! {}
815}
816
817impl SyntaxNode for FormalParameter {
818    fn ident(&self) -> Option<Ident> {
819        Some(self.ident.clone())
820    }
821
822    impl_attrs_struct! {}
823}
824
825impl SyntaxNode for ConstAssert {
826    impl_attrs_struct! {}
827}
828
829impl SyntaxNode for Expression {}
830impl SyntaxNode for LiteralExpression {}
831impl SyntaxNode for ParenthesizedExpression {}
832impl SyntaxNode for NamedComponentExpression {}
833impl SyntaxNode for IndexingExpression {}
834impl SyntaxNode for UnaryExpression {}
835impl SyntaxNode for BinaryExpression {}
836impl SyntaxNode for FunctionCall {}
837impl SyntaxNode for TypeExpression {}
838
839impl SyntaxNode for Statement {
840    impl_attrs_enum! {
841        Statement::Compound,
842        Statement::Assignment,
843        Statement::Increment,
844        Statement::Decrement,
845        Statement::If,
846        Statement::Switch,
847        Statement::Loop,
848        Statement::For,
849        Statement::While,
850        Statement::Break,
851        Statement::Continue,
852        Statement::Return,
853        Statement::Discard,
854        Statement::FunctionCall,
855        Statement::ConstAssert,
856        Statement::Declaration,
857    }
858}
859
860impl SyntaxNode for CompoundStatement {
861    impl_attrs_struct! {}
862}
863
864impl SyntaxNode for AssignmentStatement {
865    impl_attrs_struct! {}
866}
867
868impl SyntaxNode for IncrementStatement {
869    impl_attrs_struct! {}
870}
871
872impl SyntaxNode for DecrementStatement {
873    impl_attrs_struct! {}
874}
875
876impl SyntaxNode for IfStatement {
877    impl_attrs_struct! {}
878}
879
880impl SyntaxNode for IfClause {}
881
882impl SyntaxNode for ElseIfClause {
883    impl_attrs_struct! {}
884}
885
886impl SyntaxNode for ElseClause {
887    impl_attrs_struct! {}
888}
889
890impl SyntaxNode for SwitchStatement {
891    impl_attrs_struct! {}
892}
893
894impl SyntaxNode for SwitchClause {
895    impl_attrs_struct! {}
896}
897
898impl SyntaxNode for LoopStatement {
899    impl_attrs_struct! {}
900}
901
902impl SyntaxNode for ContinuingStatement {
903    impl_attrs_struct! {}
904}
905
906impl SyntaxNode for BreakIfStatement {
907    impl_attrs_struct! {}
908}
909
910impl SyntaxNode for ForStatement {
911    impl_attrs_struct! {}
912}
913
914impl SyntaxNode for WhileStatement {
915    impl_attrs_struct! {}
916}
917
918impl SyntaxNode for BreakStatement {
919    impl_attrs_struct! {}
920}
921
922impl SyntaxNode for ContinueStatement {
923    impl_attrs_struct! {}
924}
925
926impl SyntaxNode for ReturnStatement {
927    impl_attrs_struct! {}
928}
929
930impl SyntaxNode for DiscardStatement {
931    impl_attrs_struct! {}
932}
933
934impl SyntaxNode for FunctionCallStatement {
935    impl_attrs_struct! {}
936}