wac_parser/ast/
printer.rs

1//! Module for printing WAC documents.
2
3use crate::ast::*;
4use std::fmt::Write;
5
6/// A printer for WAC documents.
7pub struct DocumentPrinter<'a, W: Write> {
8    writer: W,
9    source: &'a str,
10    space: &'static str,
11    indent: usize,
12    indented: bool,
13}
14
15impl<'a, W: Write> DocumentPrinter<'a, W> {
16    /// Creates a new document printer for the given write.
17    ///
18    /// If `space` is `None`, then the printer will use four spaces for
19    /// indentation.
20    pub fn new(writer: W, source: &'a str, space: Option<&'static str>) -> Self {
21        Self {
22            writer,
23            source,
24            space: space.unwrap_or("    "),
25            indent: 0,
26            indented: false,
27        }
28    }
29
30    /// Prints the given document.
31    pub fn document(&mut self, doc: &Document) -> std::fmt::Result {
32        self.docs(&doc.docs)?;
33        self.package_directive(&doc.directive)?;
34
35        for (i, statement) in doc.statements.iter().enumerate() {
36            if i > 0 {
37                self.newline()?;
38            }
39
40            self.statement(statement)?;
41            self.newline()?;
42        }
43
44        Ok(())
45    }
46
47    /// Prints the given package directive.
48    pub fn package_directive(&mut self, directive: &PackageDirective) -> std::fmt::Result {
49        self.indent()?;
50        write!(
51            self.writer,
52            "package {package}",
53            package = self.source(directive.package.span),
54        )?;
55
56        if let Some(targets) = &directive.targets {
57            write!(self.writer, " ")?;
58            self.package_path(targets)?;
59        }
60
61        writeln!(self.writer, ";")?;
62        self.newline()
63    }
64
65    /// Prints the given statement.
66    pub fn statement(&mut self, statement: &Statement) -> std::fmt::Result {
67        match statement {
68            Statement::Import(i) => self.import_statement(i),
69            Statement::Type(t) => self.type_statement(t),
70            Statement::Let(l) => self.let_statement(l),
71            Statement::Export(e) => self.export_statement(e),
72        }
73    }
74
75    /// Prints the given doc comments.
76    pub fn docs(&mut self, docs: &[DocComment]) -> std::fmt::Result {
77        for doc in docs {
78            for line in doc.comment.lines() {
79                self.indent()?;
80                write!(self.writer, "/// {line}", line = line.trim())?;
81                self.newline()?;
82            }
83        }
84
85        Ok(())
86    }
87
88    /// Prints the given import statement.
89    pub fn import_statement(&mut self, statement: &ImportStatement) -> std::fmt::Result {
90        self.docs(&statement.docs)?;
91
92        self.indent()?;
93        write!(
94            self.writer,
95            "import {id}",
96            id = self.source(statement.id.span)
97        )?;
98
99        if let Some(name) = &statement.name {
100            write!(self.writer, " as {name}", name = self.source(name.span()))?;
101        }
102
103        write!(self.writer, ": ")?;
104        self.import_type(&statement.ty)?;
105        write!(self.writer, ";")?;
106
107        Ok(())
108    }
109
110    /// Prints the given import type.
111    pub fn import_type(&mut self, ty: &ImportType) -> std::fmt::Result {
112        match ty {
113            ImportType::Package(p) => self.package_path(p),
114            ImportType::Func(f) => self.func_type(f),
115            ImportType::Interface(i) => self.inline_interface(i),
116            ImportType::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
117        }
118    }
119
120    /// Prints the given package path.
121    pub fn package_path(&mut self, path: &PackagePath) -> std::fmt::Result {
122        write!(self.writer, "{path}", path = self.source(path.span))?;
123        Ok(())
124    }
125
126    /// Prints the given function type.
127    pub fn func_type(&mut self, ty: &FuncType) -> std::fmt::Result {
128        write!(self.writer, "func(")?;
129        self.named_types(&ty.params)?;
130        write!(self.writer, ")")?;
131
132        match &ty.results {
133            ResultList::Empty => Ok(()),
134            ResultList::Scalar(ty) => {
135                write!(self.writer, " -> ")?;
136                self.ty(ty)
137            }
138        }
139    }
140
141    fn named_types(&mut self, types: &[NamedType]) -> std::fmt::Result {
142        for (i, param) in types.iter().enumerate() {
143            if i > 0 {
144                write!(self.writer, ", ")?;
145            }
146
147            write!(self.writer, "{id}: ", id = self.source(param.id.span))?;
148            self.ty(&param.ty)?;
149        }
150
151        Ok(())
152    }
153
154    /// Prints the given type.
155    pub fn ty(&mut self, ty: &Type) -> std::fmt::Result {
156        match ty {
157            Type::U8(_) => write!(self.writer, "u8"),
158            Type::S8(_) => write!(self.writer, "s8"),
159            Type::U16(_) => write!(self.writer, "u16"),
160            Type::S16(_) => write!(self.writer, "s16"),
161            Type::U32(_) => write!(self.writer, "u32"),
162            Type::S32(_) => write!(self.writer, "s32"),
163            Type::U64(_) => write!(self.writer, "u64"),
164            Type::S64(_) => write!(self.writer, "s64"),
165            Type::F32(_) => write!(self.writer, "f32"),
166            Type::F64(_) => write!(self.writer, "f64"),
167            Type::Char(_) => write!(self.writer, "char"),
168            Type::Bool(_) => write!(self.writer, "bool"),
169            Type::String(_) => write!(self.writer, "string"),
170            Type::Tuple(types, _) => {
171                write!(self.writer, "tuple<")?;
172                for (i, ty) in types.iter().enumerate() {
173                    if i > 0 {
174                        write!(self.writer, ", ")?;
175                    }
176
177                    self.ty(ty)?;
178                }
179
180                write!(self.writer, ">")
181            }
182            Type::List(ty, _) => {
183                write!(self.writer, "list<")?;
184                self.ty(ty)?;
185                write!(self.writer, ">")
186            }
187            Type::Option(ty, _) => {
188                write!(self.writer, "option<")?;
189                self.ty(ty)?;
190                write!(self.writer, ">")
191            }
192            Type::Result { ok, err, .. } => match (ok, err) {
193                (None, None) => write!(self.writer, "result"),
194                (None, Some(err)) => {
195                    write!(self.writer, "result<_, ")?;
196                    self.ty(err)?;
197                    write!(self.writer, ">")
198                }
199                (Some(ok), None) => {
200                    write!(self.writer, "result<")?;
201                    self.ty(ok)?;
202                    write!(self.writer, ">")
203                }
204                (Some(ok), Some(err)) => {
205                    write!(self.writer, "result<")?;
206                    self.ty(ok)?;
207                    write!(self.writer, ", ")?;
208                    self.ty(err)?;
209                    write!(self.writer, ">")
210                }
211            },
212            Type::Borrow(id, _) => {
213                write!(self.writer, "borrow<{id}>", id = self.source(id.span))
214            }
215            Type::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
216        }
217    }
218
219    /// Prints the given inline interface.
220    pub fn inline_interface(&mut self, iface: &InlineInterface) -> std::fmt::Result {
221        write!(self.writer, "interface {{")?;
222        self.newline()?;
223
224        self.inc();
225        for (i, item) in iface.items.iter().enumerate() {
226            if i > 0 {
227                self.newline()?;
228            }
229
230            self.interface_item(item)?;
231            self.newline()?;
232        }
233
234        self.dec();
235        self.indent()?;
236        write!(self.writer, "}}")
237    }
238
239    /// Prints the given interface export.
240    pub fn interface_item(&mut self, item: &InterfaceItem) -> std::fmt::Result {
241        match item {
242            InterfaceItem::Use(u) => self.use_type(u),
243            InterfaceItem::Type(t) => self.item_type_decl(t),
244            InterfaceItem::Export(e) => self.interface_export(e),
245        }
246    }
247
248    /// Prints the given use type.
249    pub fn use_type(&mut self, use_ty: &Use) -> std::fmt::Result {
250        self.docs(&use_ty.docs)?;
251        self.indent()?;
252        write!(self.writer, "use ")?;
253        self.use_path(&use_ty.path)?;
254
255        write!(self.writer, ".{{ ")?;
256
257        for (i, item) in use_ty.items.iter().enumerate() {
258            if i > 0 {
259                write!(self.writer, ", ")?;
260            }
261
262            write!(self.writer, "{id}", id = self.source(item.id.span))?;
263            if let Some(as_id) = &item.as_id {
264                write!(self.writer, " as {as_id}", as_id = self.source(as_id.span))?;
265            }
266        }
267
268        write!(self.writer, " }};")
269    }
270
271    /// Prints the given use path.
272    pub fn use_path(&mut self, path: &UsePath) -> std::fmt::Result {
273        match path {
274            UsePath::Package(p) => self.package_path(p),
275            UsePath::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
276        }
277    }
278
279    /// Prints the given type declaration.
280    pub fn item_type_decl(&mut self, decl: &ItemTypeDecl) -> std::fmt::Result {
281        match decl {
282            ItemTypeDecl::Resource(r) => self.resource_decl(r),
283            ItemTypeDecl::Variant(v) => self.variant_decl(v),
284            ItemTypeDecl::Record(r) => self.record_decl(r),
285            ItemTypeDecl::Flags(f) => self.flags_decl(f),
286            ItemTypeDecl::Enum(e) => self.enum_decl(e),
287            ItemTypeDecl::Alias(a) => self.type_alias(a),
288        }
289    }
290
291    /// Prints the given resource declaration.
292    pub fn resource_decl(&mut self, decl: &ResourceDecl) -> std::fmt::Result {
293        self.docs(&decl.docs)?;
294        self.indent()?;
295        write!(
296            self.writer,
297            "resource {id} {{",
298            id = self.source(decl.id.span)
299        )?;
300        self.newline()?;
301
302        self.inc();
303        for (i, method) in decl.methods.iter().enumerate() {
304            if i > 0 {
305                self.newline()?;
306            }
307
308            self.resource_method(method)?;
309            self.newline()?;
310        }
311
312        self.dec();
313        self.indent()?;
314        write!(self.writer, "}}")
315    }
316
317    /// Prints the given resource method.
318    pub fn resource_method(&mut self, method: &ResourceMethod) -> std::fmt::Result {
319        match method {
320            ResourceMethod::Constructor(c) => self.constructor(c),
321            ResourceMethod::Method(m) => self.method(m),
322        }
323    }
324
325    /// Prints the given constructor.
326    pub fn constructor(&mut self, constructor: &Constructor) -> std::fmt::Result {
327        self.docs(&constructor.docs)?;
328        self.indent()?;
329        write!(self.writer, "constructor(")?;
330        self.named_types(&constructor.params)?;
331        write!(self.writer, ");")
332    }
333
334    /// Prints the given method.
335    pub fn method(&mut self, method: &Method) -> std::fmt::Result {
336        self.docs(&method.docs)?;
337        self.indent()?;
338        write!(self.writer, "{id}: ", id = self.source(method.id.span))?;
339
340        if method.is_static {
341            write!(self.writer, "static ")?;
342        }
343
344        self.func_type(&method.ty)?;
345        write!(self.writer, ";")
346    }
347
348    /// Prints the given function type reference.
349    pub fn func_type_ref(&mut self, ty: &FuncTypeRef) -> std::fmt::Result {
350        match ty {
351            FuncTypeRef::Func(ty) => self.func_type(ty),
352            FuncTypeRef::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
353        }
354    }
355
356    /// Prints the given variant declaration.
357    pub fn variant_decl(&mut self, decl: &VariantDecl) -> std::fmt::Result {
358        self.docs(&decl.docs)?;
359        self.indent()?;
360        write!(
361            self.writer,
362            "variant {id} {{",
363            id = self.source(decl.id.span)
364        )?;
365        self.newline()?;
366
367        self.inc();
368        for case in &decl.cases {
369            self.indent()?;
370            self.variant_case(case)?;
371            write!(self.writer, ",")?;
372            self.newline()?;
373        }
374
375        self.dec();
376        self.indent()?;
377        write!(self.writer, "}}")
378    }
379
380    /// Prints the given variant case.
381    pub fn variant_case(&mut self, case: &VariantCase) -> std::fmt::Result {
382        self.docs(&case.docs)?;
383        self.indent()?;
384        write!(self.writer, "{id}", id = self.source(case.id.span))?;
385
386        if let Some(ty) = &case.ty {
387            write!(self.writer, "(")?;
388            self.ty(ty)?;
389            write!(self.writer, ")")?;
390        }
391
392        Ok(())
393    }
394
395    /// Prints the given record declaration.
396    pub fn record_decl(&mut self, decl: &RecordDecl) -> std::fmt::Result {
397        self.docs(&decl.docs)?;
398        self.indent()?;
399        write!(
400            self.writer,
401            "record {id} {{",
402            id = self.source(decl.id.span)
403        )?;
404        self.newline()?;
405
406        self.inc();
407        for field in &decl.fields {
408            self.docs(&field.docs)?;
409            self.indent()?;
410            write!(self.writer, "{id}: ", id = self.source(field.id.span))?;
411            self.ty(&field.ty)?;
412            write!(self.writer, ",")?;
413            self.newline()?;
414        }
415
416        self.dec();
417        self.indent()?;
418        write!(self.writer, "}}")
419    }
420
421    /// Prints the given flags declaration.
422    pub fn flags_decl(&mut self, decl: &FlagsDecl) -> std::fmt::Result {
423        self.docs(&decl.docs)?;
424        self.indent()?;
425        write!(self.writer, "flags {id} {{", id = self.source(decl.id.span))?;
426        self.newline()?;
427
428        self.inc();
429        for flag in &decl.flags {
430            self.docs(&flag.docs)?;
431            self.indent()?;
432            write!(self.writer, "{id},", id = self.source(flag.id.span))?;
433            self.newline()?;
434        }
435
436        self.dec();
437        self.indent()?;
438        write!(self.writer, "}}")
439    }
440
441    /// Prints the given enum declaration.
442    pub fn enum_decl(&mut self, decl: &EnumDecl) -> std::fmt::Result {
443        self.docs(&decl.docs)?;
444        self.indent()?;
445        write!(self.writer, "enum {id} {{", id = self.source(decl.id.span))?;
446        self.newline()?;
447
448        self.inc();
449        for case in &decl.cases {
450            self.docs(&case.docs)?;
451            self.indent()?;
452            write!(self.writer, "{id},", id = self.source(case.id.span))?;
453            self.newline()?;
454        }
455
456        self.dec();
457        self.indent()?;
458        write!(self.writer, "}}")
459    }
460
461    /// Prints the given type alias.
462    pub fn type_alias(&mut self, alias: &TypeAlias) -> std::fmt::Result {
463        self.docs(&alias.docs)?;
464        self.indent()?;
465        write!(self.writer, "type {id} = ", id = self.source(alias.id.span))?;
466        match &alias.kind {
467            TypeAliasKind::Func(ty) => self.func_type(ty)?,
468            TypeAliasKind::Type(ty) => self.ty(ty)?,
469        }
470
471        write!(self.writer, ";")
472    }
473
474    /// Prints the given interface export.
475    pub fn interface_export(&mut self, export: &InterfaceExport) -> std::fmt::Result {
476        self.docs(&export.docs)?;
477        self.indent()?;
478        write!(self.writer, "{id}: ", id = self.source(export.id.span))?;
479        self.func_type_ref(&export.ty)?;
480        write!(self.writer, ";")
481    }
482
483    /// Prints the given type statement.
484    pub fn type_statement(&mut self, stmt: &TypeStatement) -> std::fmt::Result {
485        match stmt {
486            TypeStatement::Interface(i) => self.interface_decl(i),
487            TypeStatement::World(w) => self.world_decl(w),
488            TypeStatement::Type(t) => self.type_decl(t),
489        }
490    }
491
492    /// Prints the given interface declaration.
493    pub fn interface_decl(&mut self, decl: &InterfaceDecl) -> std::fmt::Result {
494        self.docs(&decl.docs)?;
495        self.indent()?;
496        write!(
497            self.writer,
498            "interface {id} {{",
499            id = self.source(decl.id.span)
500        )?;
501        self.newline()?;
502
503        self.inc();
504        for (i, item) in decl.items.iter().enumerate() {
505            if i > 0 {
506                self.newline()?;
507            }
508
509            self.interface_item(item)?;
510            self.newline()?;
511        }
512
513        self.dec();
514        self.indent()?;
515        write!(self.writer, "}}")
516    }
517
518    /// Prints the given world declaration.
519    pub fn world_decl(&mut self, decl: &WorldDecl) -> std::fmt::Result {
520        self.docs(&decl.docs)?;
521        self.indent()?;
522        write!(self.writer, "world {id} {{", id = self.source(decl.id.span))?;
523        self.newline()?;
524
525        self.inc();
526        for (i, item) in decl.items.iter().enumerate() {
527            if i > 0 {
528                self.newline()?;
529            }
530
531            self.world_item(item)?;
532            self.newline()?;
533        }
534
535        self.dec();
536        self.indent()?;
537        write!(self.writer, "}}")
538    }
539
540    /// Prints the given world item.
541    pub fn world_item(&mut self, item: &WorldItem) -> std::fmt::Result {
542        match item {
543            WorldItem::Use(u) => self.use_type(u),
544            WorldItem::Type(t) => self.item_type_decl(t),
545            WorldItem::Import(i) => self.world_import(i),
546            WorldItem::Export(e) => self.world_export(e),
547            WorldItem::Include(i) => self.world_include(i),
548        }
549    }
550
551    /// Prints the given world import.
552    pub fn world_import(&mut self, import: &WorldImport) -> std::fmt::Result {
553        self.docs(&import.docs)?;
554        self.indent()?;
555        write!(self.writer, "import ")?;
556
557        self.world_item_path(&import.path)?;
558        write!(self.writer, ";")
559    }
560
561    /// Prints the given world export.
562    pub fn world_export(&mut self, export: &WorldExport) -> std::fmt::Result {
563        self.docs(&export.docs)?;
564        self.indent()?;
565        write!(self.writer, "export ")?;
566
567        self.world_item_path(&export.path)?;
568        write!(self.writer, ";")
569    }
570
571    /// Prints the given world item path.
572    pub fn world_item_path(&mut self, path: &WorldItemPath) -> std::fmt::Result {
573        match path {
574            WorldItemPath::Named(n) => self.named_world_item(n),
575            WorldItemPath::Package(p) => self.package_path(p),
576            WorldItemPath::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
577        }
578    }
579
580    /// Prints the given named world item.
581    pub fn named_world_item(&mut self, item: &NamedWorldItem) -> std::fmt::Result {
582        write!(self.writer, "{id}: ", id = self.source(item.id.span))?;
583        self.extern_type(&item.ty)
584    }
585
586    /// Prints the given extern type.
587    pub fn extern_type(&mut self, ty: &ExternType) -> std::fmt::Result {
588        match ty {
589            ExternType::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
590            ExternType::Func(ty) => self.func_type(ty),
591            ExternType::Interface(i) => self.inline_interface(i),
592        }
593    }
594
595    /// Prints the given world include.
596    pub fn world_include(&mut self, include: &WorldInclude) -> std::fmt::Result {
597        self.docs(&include.docs)?;
598        self.indent()?;
599        write!(self.writer, "include ")?;
600        self.world_ref(&include.world)?;
601
602        if !include.with.is_empty() {
603            write!(self.writer, " with {{")?;
604            self.newline()?;
605            self.inc();
606
607            for item in &include.with {
608                self.indent()?;
609                write!(
610                    self.writer,
611                    "{source} as {target},",
612                    source = self.source(item.from.span),
613                    target = self.source(item.to.span)
614                )?;
615                self.newline()?;
616            }
617
618            self.dec();
619            self.indent()?;
620            write!(self.writer, "}}")?;
621        }
622
623        write!(self.writer, ";")
624    }
625
626    /// Prints the given world reference.
627    pub fn world_ref(&mut self, reference: &WorldRef) -> std::fmt::Result {
628        match reference {
629            WorldRef::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
630            WorldRef::Package(p) => self.package_path(p),
631        }
632    }
633
634    /// Prints the given type declaration.
635    pub fn type_decl(&mut self, decl: &TypeDecl) -> std::fmt::Result {
636        match decl {
637            TypeDecl::Variant(v) => self.variant_decl(v),
638            TypeDecl::Record(r) => self.record_decl(r),
639            TypeDecl::Flags(f) => self.flags_decl(f),
640            TypeDecl::Enum(e) => self.enum_decl(e),
641            TypeDecl::Alias(a) => self.type_alias(a),
642        }
643    }
644
645    /// Prints the given let statement.
646    pub fn let_statement(&mut self, stmt: &LetStatement) -> std::fmt::Result {
647        self.docs(&stmt.docs)?;
648        self.indent()?;
649        write!(self.writer, "let {id} = ", id = self.source(stmt.id.span))?;
650        self.expr(&stmt.expr)?;
651        write!(self.writer, ";")
652    }
653
654    /// Prints the given expression.
655    pub fn expr(&mut self, expr: &Expr) -> std::fmt::Result {
656        self.primary_expr(&expr.primary)?;
657        for postfix in &expr.postfix {
658            self.postfix_expr(postfix)?;
659        }
660
661        Ok(())
662    }
663
664    /// Prints the given primary expression.
665    pub fn primary_expr(&mut self, expr: &PrimaryExpr) -> std::fmt::Result {
666        match expr {
667            PrimaryExpr::New(e) => self.new_expr(e),
668            PrimaryExpr::Nested(e) => {
669                write!(self.writer, "(")?;
670                self.expr(&e.inner)?;
671                write!(self.writer, ")")
672            }
673            PrimaryExpr::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
674        }
675    }
676
677    /// Prints the given new expression.
678    pub fn new_expr(&mut self, expr: &NewExpr) -> std::fmt::Result {
679        write!(
680            self.writer,
681            "new {name} {{",
682            name = self.source(expr.package.span)
683        )?;
684
685        if expr.arguments.is_empty() {
686            write!(self.writer, "}}")?;
687            return Ok(());
688        }
689
690        if expr.arguments.len() == 1 {
691            if let InstantiationArgument::Fill(_) = expr.arguments[0] {
692                write!(self.writer, " ... }}")?;
693                return Ok(());
694            }
695        }
696
697        self.newline()?;
698        self.inc();
699
700        for arg in &expr.arguments {
701            self.indent()?;
702
703            match arg {
704                InstantiationArgument::Inferred(id) => {
705                    write!(self.writer, "{id},", id = self.source(id.span))?
706                }
707                InstantiationArgument::Spread(id) => {
708                    write!(self.writer, "...{id},", id = self.source(id.span))?
709                }
710                InstantiationArgument::Named(arg) => {
711                    match &arg.name {
712                        InstantiationArgumentName::Ident(id) => {
713                            write!(self.writer, "{id}: ", id = self.source(id.span))?;
714                        }
715                        InstantiationArgumentName::String(s) => {
716                            write!(self.writer, "{s}: ", s = self.source(s.span))?;
717                        }
718                    }
719                    self.expr(&arg.expr)?;
720                    write!(self.writer, ",")?;
721                }
722                InstantiationArgument::Fill(_) => write!(self.writer, "...")?,
723            }
724
725            self.newline()?;
726        }
727
728        self.dec();
729        self.indent()?;
730        write!(self.writer, "}}")
731    }
732
733    /// Prints the given postfix expression.
734    pub fn postfix_expr(&mut self, expr: &PostfixExpr) -> std::fmt::Result {
735        match expr {
736            PostfixExpr::Access(a) => self.access_expr(a),
737            PostfixExpr::NamedAccess(a) => self.named_access_expr(a),
738        }
739    }
740
741    /// Prints the given access expression.
742    pub fn access_expr(&mut self, expr: &AccessExpr) -> std::fmt::Result {
743        write!(self.writer, ".{id}", id = self.source(expr.id.span))
744    }
745
746    /// Prints the given named access expression.
747    pub fn named_access_expr(&mut self, expr: &NamedAccessExpr) -> std::fmt::Result {
748        write!(
749            self.writer,
750            "[{name}]",
751            name = self.source(expr.string.span)
752        )
753    }
754
755    /// Prints the given export statement.
756    pub fn export_statement(&mut self, stmt: &ExportStatement) -> std::fmt::Result {
757        self.docs(&stmt.docs)?;
758        self.indent()?;
759
760        write!(self.writer, "export ")?;
761
762        self.expr(&stmt.expr)?;
763
764        match &stmt.options {
765            ExportOptions::None => {}
766            ExportOptions::Spread(_) => {
767                write!(self.writer, "...")?;
768            }
769            ExportOptions::Rename(name) => {
770                write!(self.writer, " as {name}", name = self.source(name.span()))?;
771            }
772        }
773
774        write!(self.writer, ";")
775    }
776
777    fn newline(&mut self) -> std::fmt::Result {
778        writeln!(self.writer)?;
779        self.indented = false;
780        Ok(())
781    }
782
783    fn indent(&mut self) -> std::fmt::Result {
784        if !self.indented {
785            for _ in 0..self.indent {
786                write!(self.writer, "{space}", space = self.space)?;
787            }
788
789            self.indented = true;
790        }
791
792        Ok(())
793    }
794
795    fn inc(&mut self) {
796        self.indent = self.indent.saturating_add(1);
797    }
798
799    fn dec(&mut self) {
800        self.indent = self.indent.saturating_sub(1);
801    }
802
803    fn source(&self, span: SourceSpan) -> &'a str {
804        &self.source[span.offset()..span.offset() + span.len()]
805    }
806}