wgsl_parse/
syntax_display.rs

1use crate::{span::Spanned, syntax::*};
2use core::fmt;
3use std::fmt::{Display, Formatter};
4
5use itertools::Itertools;
6
7// unstable: https://doc.rust-lang.org/std/fmt/struct.FormatterFn.html
8struct FormatFn<F: (Fn(&mut Formatter) -> fmt::Result)>(F);
9
10impl<F: Fn(&mut Formatter) -> fmt::Result> Display for FormatFn<F> {
11    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
12        (self.0)(f)
13    }
14}
15
16impl<T: Display> Display for Spanned<T> {
17    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
18        self.node().fmt(f)
19    }
20}
21
22struct Indent<T: Display>(pub T);
23
24impl<T: Display> Display for Indent<T> {
25    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26        let indent = "    ";
27        let inner_display = self.0.to_string();
28        let fmt = inner_display
29            .lines()
30            .format_with("\n", |l, f| f(&format_args!("{indent}{l}")));
31        write!(f, "{}", fmt)?;
32        Ok(())
33    }
34}
35
36impl Display for TranslationUnit {
37    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
38        #[cfg(feature = "imports")]
39        if !self.imports.is_empty() {
40            for import in &self.imports {
41                writeln!(f, "import {import}\n")?;
42            }
43        }
44        if !self.global_directives.is_empty() {
45            let directives = self.global_directives.iter().format("\n");
46            write!(f, "{directives}\n\n")?;
47        }
48        let declarations = self
49            .global_declarations
50            .iter()
51            .filter(|decl| !matches!(decl, GlobalDeclaration::Void))
52            .format("\n\n");
53        writeln!(f, "{declarations}")
54    }
55}
56
57impl Display for Ident {
58    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
59        write!(f, "{}", self.name())
60    }
61}
62
63#[cfg(feature = "imports")]
64impl Display for ImportStatement {
65    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
66        #[cfg(feature = "attributes")]
67        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
68        let path = &self.path;
69        let content = &self.content;
70        write!(f, "{path}::{content};")
71    }
72}
73
74#[cfg(feature = "imports")]
75impl Display for ModulePath {
76    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77        match self.origin {
78            PathOrigin::Absolute => write!(f, "package::")?,
79            PathOrigin::Relative(0) => write!(f, "self::")?,
80            PathOrigin::Relative(n) => write!(f, "{}::", (0..n).map(|_| "super").format("::"))?,
81            PathOrigin::Package => (),
82        };
83        write!(f, "{}", self.components.iter().format("::"))
84    }
85}
86
87#[cfg(feature = "imports")]
88impl Display for Import {
89    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
90        let path = self.path.iter().format("::");
91        let content = &self.content;
92        write!(f, "{path}{content}")
93    }
94}
95
96#[cfg(feature = "imports")]
97impl Display for ImportContent {
98    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
99        match self {
100            ImportContent::Item(item) => {
101                write!(f, "{}", item.ident)?;
102                if let Some(rename) = &item.rename {
103                    write!(f, " as {rename}")?;
104                }
105                Ok(())
106            }
107            ImportContent::Collection(coll) => {
108                let coll = coll.iter().format(", ");
109                write!(f, "{{ {coll} }}")
110            }
111        }
112    }
113}
114
115impl Display for GlobalDirective {
116    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
117        match self {
118            GlobalDirective::Diagnostic(print) => write!(f, "{}", print),
119            GlobalDirective::Enable(print) => write!(f, "{}", print),
120            GlobalDirective::Requires(print) => write!(f, "{}", print),
121        }
122    }
123}
124
125impl Display for DiagnosticDirective {
126    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
127        #[cfg(feature = "attributes")]
128        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
129        let severity = &self.severity;
130        let rule = &self.rule_name;
131        write!(f, "diagnostic ({severity}, {rule});")
132    }
133}
134
135impl Display for DiagnosticSeverity {
136    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
137        match self {
138            Self::Error => write!(f, "error"),
139            Self::Warning => write!(f, "warning"),
140            Self::Info => write!(f, "info"),
141            Self::Off => write!(f, "off"),
142        }
143    }
144}
145
146impl Display for EnableDirective {
147    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
148        #[cfg(feature = "attributes")]
149        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
150        let exts = self.extensions.iter().format(", ");
151        write!(f, "enable {exts};")
152    }
153}
154
155impl Display for RequiresDirective {
156    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
157        #[cfg(feature = "attributes")]
158        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
159        let exts = self.extensions.iter().format(", ");
160        write!(f, "requires {exts};")
161    }
162}
163
164impl Display for GlobalDeclaration {
165    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
166        match self {
167            GlobalDeclaration::Void => write!(f, ";"),
168            GlobalDeclaration::Declaration(print) => write!(f, "{}", print),
169            GlobalDeclaration::TypeAlias(print) => write!(f, "{}", print),
170            GlobalDeclaration::Struct(print) => write!(f, "{}", print),
171            GlobalDeclaration::Function(print) => write!(f, "{}", print),
172            GlobalDeclaration::ConstAssert(print) => write!(f, "{}", print),
173        }
174    }
175}
176
177impl Display for Declaration {
178    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
179        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
180        let kind = &self.kind;
181        let name = &self.ident;
182        let typ = self
183            .ty
184            .iter()
185            .format_with("", |ty, f| f(&format_args!(": {}", ty)));
186        let init = self
187            .initializer
188            .iter()
189            .format_with("", |ty, f| f(&format_args!(" = {}", ty)));
190        write!(f, "{kind} {name}{typ}{init};")
191    }
192}
193
194impl Display for DeclarationKind {
195    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
196        match self {
197            Self::Const => write!(f, "const"),
198            Self::Override => write!(f, "override"),
199            Self::Let => write!(f, "let"),
200            Self::Var(addr_space) => match addr_space {
201                Some(addr_space) => write!(f, "var<{addr_space}>"),
202                None => write!(f, "var"),
203            },
204        }
205    }
206}
207
208impl Display for AddressSpace {
209    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
210        match self {
211            Self::Function => write!(f, "function"),
212            Self::Private => write!(f, "private"),
213            Self::Workgroup => write!(f, "workgroup"),
214            Self::Uniform => write!(f, "uniform"),
215            Self::Storage(access_mode) => match access_mode {
216                Some(access_mode) => write!(f, "storage, {access_mode}"),
217                None => write!(f, "storage"),
218            },
219            Self::Handle => write!(f, "handle"),
220        }
221    }
222}
223
224impl Display for AccessMode {
225    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
226        match self {
227            Self::Read => write!(f, "read"),
228            Self::Write => write!(f, "write"),
229            Self::ReadWrite => write!(f, "read_write"),
230        }
231    }
232}
233
234impl Display for TypeAlias {
235    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
236        #[cfg(feature = "attributes")]
237        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
238        let name = &self.ident;
239        let typ = &self.ty;
240        write!(f, "alias {name} = {typ};")
241    }
242}
243
244impl Display for Struct {
245    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
246        #[cfg(feature = "attributes")]
247        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
248        let name = &self.ident;
249        let members = Indent(self.members.iter().format(",\n"));
250        write!(f, "struct {name} {{\n{members}\n}}")
251    }
252}
253
254impl Display for StructMember {
255    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
256        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
257        let name = &self.ident;
258        let typ = &self.ty;
259        write!(f, "{name}: {typ}")
260    }
261}
262
263impl Display for Function {
264    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
265        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
266        let name = &self.ident;
267        let params = self.parameters.iter().format(", ");
268        let ret_ty = self.return_type.iter().format_with("", |ty, f| {
269            f(&FormatFn(|f: &mut Formatter| {
270                write!(f, "-> ")?;
271                write!(f, "{}", fmt_attrs(&self.return_attributes, true))?;
272                write!(f, "{ty} ")?;
273                Ok(())
274            }))
275        });
276        let body = &self.body;
277        write!(f, "fn {name}({params}) {ret_ty}{body}")
278    }
279}
280
281impl Display for FormalParameter {
282    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
283        write!(f, "{}", fmt_attrs(&self.attributes, true))?;
284        let name = &self.ident;
285        let typ = &self.ty;
286        write!(f, "{name}: {typ}")
287    }
288}
289
290impl Display for ConstAssert {
291    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
292        #[cfg(feature = "attributes")]
293        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
294        let expr = &self.expression;
295        write!(f, "const_assert {expr};",)
296    }
297}
298
299impl Display for BuiltinValue {
300    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
301        match self {
302            Self::VertexIndex => write!(f, "vertex_index"),
303            Self::InstanceIndex => write!(f, "instance_index"),
304            Self::Position => write!(f, "position"),
305            Self::FrontFacing => write!(f, "front_facing"),
306            Self::FragDepth => write!(f, "frag_depth"),
307            Self::SampleIndex => write!(f, "sample_index"),
308            Self::SampleMask => write!(f, "sample_mask"),
309            Self::LocalInvocationId => write!(f, "local_invocation_id"),
310            Self::LocalInvocationIndex => write!(f, "local_invocation_index"),
311            Self::GlobalInvocationId => write!(f, "global_invocation_id"),
312            Self::WorkgroupId => write!(f, "workgroup_id"),
313            Self::NumWorkgroups => write!(f, "num_workgroups"),
314        }
315    }
316}
317
318impl Display for InterpolationType {
319    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
320        match self {
321            InterpolationType::Perspective => write!(f, "perspective"),
322            InterpolationType::Linear => write!(f, "linear"),
323            InterpolationType::Flat => write!(f, "flat"),
324        }
325    }
326}
327
328impl Display for InterpolationSampling {
329    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
330        match self {
331            Self::Center => write!(f, "center"),
332            Self::Centroid => write!(f, "centroid"),
333            Self::Sample => write!(f, "sample"),
334            Self::First => write!(f, "first"),
335            Self::Either => write!(f, "either"),
336        }
337    }
338}
339
340impl Display for Attribute {
341    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
342        match self {
343            Attribute::Align(e1) => write!(f, "@align({e1})"),
344            Attribute::Binding(e1) => write!(f, "@binding({e1})"),
345            Attribute::BlendSrc(e1) => write!(f, "@blend_src({e1})"),
346            Attribute::Builtin(e1) => write!(f, "@builtin({e1})"),
347            Attribute::Const => write!(f, "@const"),
348            Attribute::Diagnostic(DiagnosticAttribute { severity, rule }) => {
349                write!(f, "@diagnostic({severity}, {rule})")
350            }
351            Attribute::Group(e1) => write!(f, "@group({e1})"),
352            Attribute::Id(e1) => write!(f, "@id({e1})"),
353            Attribute::Interpolate(InterpolateAttribute { ty, sampling }) => {
354                if let Some(sampling) = sampling {
355                    write!(f, "@interpolate({ty}, {sampling})")
356                } else {
357                    write!(f, "@interpolate({ty})")
358                }
359            }
360            Attribute::Invariant => write!(f, "@invariant"),
361            Attribute::Location(e1) => write!(f, "@location({e1})"),
362            Attribute::MustUse => write!(f, "@must_use"),
363            Attribute::Size(e1) => write!(f, "@size({e1})"),
364            Attribute::WorkgroupSize(WorkgroupSizeAttribute { x, y, z }) => {
365                let xyz = std::iter::once(x).chain(y).chain(z).format(", ");
366                write!(f, "@workgroup_size({xyz})")
367            }
368            Attribute::Vertex => write!(f, "@vertex"),
369            Attribute::Fragment => write!(f, "@fragment"),
370            Attribute::Compute => write!(f, "@compute"),
371            #[cfg(feature = "condcomp")]
372            Attribute::If(e1) => write!(f, "@if({e1})"),
373            #[cfg(feature = "condcomp")]
374            Attribute::Elif(e1) => write!(f, "@elif({e1})"),
375            #[cfg(feature = "condcomp")]
376            Attribute::Else => write!(f, "@else"),
377            #[cfg(feature = "generics")]
378            Attribute::Type(e1) => write!(f, "@type({e1})"),
379            Attribute::Custom(custom) => {
380                let name = &custom.name;
381                let args = custom.arguments.iter().format_with("", |args, f| {
382                    f(&format_args!("({})", args.iter().format(", ")))
383                });
384                write!(f, "@{name}{args}")
385            }
386        }
387    }
388}
389
390#[cfg(feature = "generics")]
391impl Display for TypeConstraint {
392    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
393        let name = &self.ident;
394        let variants = self.variants.iter().format(" | ");
395        write!(f, "{name}, {variants}")
396    }
397}
398
399fn fmt_attrs(attrs: &[Attribute], inline: bool) -> impl fmt::Display + '_ {
400    FormatFn(move |f| {
401        let print = attrs.iter().format(" ");
402        let suffix = if attrs.is_empty() {
403            ""
404        } else if inline {
405            " "
406        } else {
407            "\n"
408        };
409        write!(f, "{print}{suffix}")
410    })
411}
412
413impl Display for Expression {
414    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
415        match self {
416            Expression::Literal(print) => write!(f, "{print}"),
417            Expression::Parenthesized(print) => {
418                write!(f, "{print}")
419            }
420            Expression::NamedComponent(print) => write!(f, "{print}"),
421            Expression::Indexing(print) => write!(f, "{print}"),
422            Expression::Unary(print) => write!(f, "{print}"),
423            Expression::Binary(print) => write!(f, "{print}"),
424            Expression::FunctionCall(print) => write!(f, "{print}"),
425            Expression::TypeOrIdentifier(print) => write!(f, "{print}"),
426        }
427    }
428}
429
430impl Display for LiteralExpression {
431    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
432        match self {
433            LiteralExpression::Bool(true) => write!(f, "true"),
434            LiteralExpression::Bool(false) => write!(f, "false"),
435            LiteralExpression::AbstractInt(num) => write!(f, "{num}"),
436            LiteralExpression::AbstractFloat(num) => write!(f, "{num:?}"), // using the Debug formatter to print the trailing .0 in floats representing integers. because format!("{}", 3.0f32) == "3"
437            LiteralExpression::I32(num) => write!(f, "{num}i"),
438            LiteralExpression::U32(num) => write!(f, "{num}u"),
439            LiteralExpression::F32(num) => write!(f, "{num}f"),
440            LiteralExpression::F16(num) => write!(f, "{num}h"),
441        }
442    }
443}
444
445impl Display for ParenthesizedExpression {
446    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
447        let expr = &self.expression;
448        write!(f, "({expr})")
449    }
450}
451
452impl Display for NamedComponentExpression {
453    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
454        let base = &self.base;
455        let component = &self.component;
456        write!(f, "{base}.{component}")
457    }
458}
459
460impl Display for IndexingExpression {
461    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
462        let base = &self.base;
463        let index = &self.index;
464        write!(f, "{base}[{index}]")
465    }
466}
467
468impl Display for UnaryExpression {
469    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
470        let operator = &self.operator;
471        let operand = &self.operand;
472        write!(f, "{operator}{operand}")
473    }
474}
475
476impl Display for UnaryOperator {
477    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
478        match self {
479            UnaryOperator::LogicalNegation => write!(f, "!"),
480            UnaryOperator::Negation => write!(f, "-"),
481            UnaryOperator::BitwiseComplement => write!(f, "~"),
482            UnaryOperator::AddressOf => write!(f, "&"),
483            UnaryOperator::Indirection => write!(f, "*"),
484        }
485    }
486}
487
488impl Display for BinaryExpression {
489    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
490        let operator = &self.operator;
491        let left = &self.left;
492        let right = &self.right;
493        write!(f, "{left} {operator} {right}")
494    }
495}
496
497impl Display for BinaryOperator {
498    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
499        match self {
500            BinaryOperator::ShortCircuitOr => write!(f, "||"),
501            BinaryOperator::ShortCircuitAnd => write!(f, "&&"),
502            BinaryOperator::Addition => write!(f, "+"),
503            BinaryOperator::Subtraction => write!(f, "-"),
504            BinaryOperator::Multiplication => write!(f, "*"),
505            BinaryOperator::Division => write!(f, "/"),
506            BinaryOperator::Remainder => write!(f, "%"),
507            BinaryOperator::Equality => write!(f, "=="),
508            BinaryOperator::Inequality => write!(f, "!="),
509            BinaryOperator::LessThan => write!(f, "<"),
510            BinaryOperator::LessThanEqual => write!(f, "<="),
511            BinaryOperator::GreaterThan => write!(f, ">"),
512            BinaryOperator::GreaterThanEqual => write!(f, ">="),
513            BinaryOperator::BitwiseOr => write!(f, "|"),
514            BinaryOperator::BitwiseAnd => write!(f, "&"),
515            BinaryOperator::BitwiseXor => write!(f, "^"),
516            BinaryOperator::ShiftLeft => write!(f, "<<"),
517            BinaryOperator::ShiftRight => write!(f, ">>"),
518        }
519    }
520}
521
522impl Display for FunctionCall {
523    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
524        let ty = &self.ty;
525        let args = self.arguments.iter().format(", ");
526        write!(f, "{ty}({args})")
527    }
528}
529
530impl Display for TypeExpression {
531    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
532        let name = &self.ident;
533        let tplt = fmt_template(&self.template_args);
534        write!(f, "{name}{tplt}")
535    }
536}
537
538impl Display for TemplateArg {
539    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
540        let expr = &self.expression;
541        write!(f, "{expr}")
542    }
543}
544
545fn fmt_template(tplt: &Option<Vec<TemplateArg>>) -> impl fmt::Display + '_ {
546    tplt.iter().format_with("", |tplt, f| {
547        f(&format_args!("<{}>", tplt.iter().format(", ")))
548    })
549}
550
551impl Display for Statement {
552    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
553        match self {
554            Statement::Void => write!(f, ";"),
555            Statement::Compound(print) => write!(f, "{print}"),
556            Statement::Assignment(print) => write!(f, "{print}"),
557            Statement::Increment(print) => write!(f, "{print}"),
558            Statement::Decrement(print) => write!(f, "{print}"),
559            Statement::If(print) => write!(f, "{print}"),
560            Statement::Switch(print) => write!(f, "{print}"),
561            Statement::Loop(print) => write!(f, "{print}"),
562            Statement::For(print) => write!(f, "{print}"),
563            Statement::While(print) => write!(f, "{print}"),
564            Statement::Break(print) => write!(f, "{print}"),
565            Statement::Continue(print) => write!(f, "{print}"),
566            Statement::Return(print) => write!(f, "{print}"),
567            Statement::Discard(print) => write!(f, "{print}"),
568            Statement::FunctionCall(print) => write!(f, "{print}"),
569            Statement::ConstAssert(print) => write!(f, "{print}"),
570            Statement::Declaration(print) => write!(f, "{print}"),
571        }
572    }
573}
574
575impl Display for CompoundStatement {
576    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
577        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
578        let stmts = Indent(
579            self.statements
580                .iter()
581                .filter(|stmt| !matches!(stmt.node(), Statement::Void))
582                .format("\n"),
583        );
584        write!(f, "{{\n{stmts}\n}}")
585    }
586}
587
588impl Display for AssignmentStatement {
589    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
590        #[cfg(feature = "attributes")]
591        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
592        let operator = &self.operator;
593        let lhs = &self.lhs;
594        let rhs = &self.rhs;
595        write!(f, "{lhs} {operator} {rhs};")
596    }
597}
598
599impl Display for AssignmentOperator {
600    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
601        match self {
602            AssignmentOperator::Equal => write!(f, "="),
603            AssignmentOperator::PlusEqual => write!(f, "+="),
604            AssignmentOperator::MinusEqual => write!(f, "-="),
605            AssignmentOperator::TimesEqual => write!(f, "*="),
606            AssignmentOperator::DivisionEqual => write!(f, "/="),
607            AssignmentOperator::ModuloEqual => write!(f, "%="),
608            AssignmentOperator::AndEqual => write!(f, "&="),
609            AssignmentOperator::OrEqual => write!(f, "|="),
610            AssignmentOperator::XorEqual => write!(f, "^="),
611            AssignmentOperator::ShiftRightAssign => write!(f, ">>="),
612            AssignmentOperator::ShiftLeftAssign => write!(f, "<<="),
613        }
614    }
615}
616
617impl Display for IncrementStatement {
618    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
619        #[cfg(feature = "attributes")]
620        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
621        let expr = &self.expression;
622        write!(f, "{expr}++;")
623    }
624}
625
626impl Display for DecrementStatement {
627    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
628        #[cfg(feature = "attributes")]
629        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
630        let expr = &self.expression;
631        write!(f, "{expr}--;")
632    }
633}
634
635impl Display for IfStatement {
636    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
637        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
638        let if_clause = &self.if_clause;
639        write!(f, "{if_clause}")?;
640        for else_if_clause in self.else_if_clauses.iter() {
641            write!(f, "\n{else_if_clause}")?;
642        }
643        if let Some(else_clause) = &self.else_clause {
644            write!(f, "\n{else_clause}")?;
645        }
646        Ok(())
647    }
648}
649
650impl Display for IfClause {
651    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
652        let expr = &self.expression;
653        let stmt = &self.body;
654        write!(f, "if {expr} {stmt}")
655    }
656}
657
658impl Display for ElseIfClause {
659    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
660        #[cfg(feature = "attributes")]
661        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
662        let expr = &self.expression;
663        let stmt = &self.body;
664        write!(f, "else if {expr} {stmt}")
665    }
666}
667
668impl Display for ElseClause {
669    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
670        #[cfg(feature = "attributes")]
671        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
672        let stmt = &self.body;
673        write!(f, "else {stmt}")
674    }
675}
676
677impl Display for SwitchStatement {
678    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
679        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
680        let expr = &self.expression;
681        let body_attrs = fmt_attrs(&self.body_attributes, false);
682        let clauses = Indent(self.clauses.iter().format("\n"));
683        write!(f, "switch {expr} {body_attrs}{{\n{clauses}\n}}")
684    }
685}
686
687impl Display for SwitchClause {
688    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
689        #[cfg(feature = "attributes")]
690        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
691        let cases = self.case_selectors.iter().format(", ");
692        let body = &self.body;
693        write!(f, "case {cases} {body}")
694    }
695}
696
697impl Display for CaseSelector {
698    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
699        match self {
700            CaseSelector::Default => write!(f, "default"),
701            CaseSelector::Expression(expr) => {
702                write!(f, "{}", expr)
703            }
704        }
705    }
706}
707
708impl Display for LoopStatement {
709    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
710        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
711        let body_attrs = fmt_attrs(&self.body.attributes, false);
712        let stmts = Indent(
713            self.body
714                .statements
715                .iter()
716                .filter(|stmt| !matches!(stmt.node(), Statement::Void))
717                .format("\n"),
718        );
719        let continuing = self
720            .continuing
721            .iter()
722            .format_with("", |cont, f| f(&format_args!("{}\n", Indent(cont))));
723        write!(f, "loop {body_attrs}{{\n{stmts}\n{continuing}}}")
724    }
725}
726
727impl Display for ContinuingStatement {
728    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
729        #[cfg(feature = "attributes")]
730        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
731        let body_attrs = fmt_attrs(&self.body.attributes, false);
732        let stmts = Indent(
733            self.body
734                .statements
735                .iter()
736                .filter(|stmt| !matches!(stmt.node(), Statement::Void))
737                .format("\n"),
738        );
739        let break_if = self
740            .break_if
741            .iter()
742            .format_with("", |stmt, f| f(&format_args!("{}\n", Indent(stmt))));
743        write!(f, "continuing {body_attrs}{{\n{stmts}\n{break_if}}}")
744    }
745}
746
747impl Display for BreakIfStatement {
748    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
749        #[cfg(feature = "attributes")]
750        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
751        let expr = &self.expression;
752        write!(f, "break if {expr};")
753    }
754}
755
756impl Display for ForStatement {
757    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
758        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
759        let mut init = self
760            .initializer
761            .as_ref()
762            .map(|stmt| format!("{}", stmt))
763            .unwrap_or_default();
764        if init.ends_with(';') {
765            init.pop();
766        }
767        let cond = self
768            .condition
769            .iter()
770            .format_with("", |expr, f| f(&format_args!("{expr}")));
771        let mut updt = self
772            .update
773            .as_ref()
774            .map(|stmt| format!("{}", stmt))
775            .unwrap_or_default();
776        if updt.ends_with(';') {
777            updt.pop();
778        }
779        let body = &self.body;
780        write!(f, "for ({init}; {cond}; {updt}) {body}")
781    }
782}
783
784impl Display for WhileStatement {
785    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
786        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
787        let cond = &self.condition;
788        let body = &self.body;
789        write!(f, "while ({cond}) {body}")
790    }
791}
792
793impl Display for BreakStatement {
794    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
795        #[cfg(feature = "attributes")]
796        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
797        write!(f, "break;")
798    }
799}
800
801impl Display for ContinueStatement {
802    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
803        #[cfg(feature = "attributes")]
804        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
805        write!(f, "continue;")
806    }
807}
808
809impl Display for ReturnStatement {
810    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
811        #[cfg(feature = "attributes")]
812        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
813        let expr = self
814            .expression
815            .iter()
816            .format_with("", |expr, f| f(&format_args!(" {expr}")));
817        write!(f, "return{expr};")
818    }
819}
820
821impl Display for DiscardStatement {
822    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
823        #[cfg(feature = "attributes")]
824        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
825        write!(f, "discard;")
826    }
827}
828
829impl Display for FunctionCallStatement {
830    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
831        #[cfg(feature = "attributes")]
832        write!(f, "{}", fmt_attrs(&self.attributes, false))?;
833        let call = &self.call;
834        write!(f, "{call};")
835    }
836}