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