1use crate::ast::*;
4use std::fmt::Write;
5
6pub 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 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 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 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 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 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 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 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 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 pub fn func_type(&mut self, ty: &FuncType) -> std::fmt::Result {
128 if ty.is_async {
129 write!(self.writer, "async ")?;
130 }
131 write!(self.writer, "func(")?;
132 self.named_types(&ty.params)?;
133 write!(self.writer, ")")?;
134
135 match &ty.results {
136 ResultList::Empty => Ok(()),
137 ResultList::Scalar(ty) => {
138 write!(self.writer, " -> ")?;
139 self.ty(ty)
140 }
141 }
142 }
143
144 fn named_types(&mut self, types: &[NamedType]) -> std::fmt::Result {
145 for (i, param) in types.iter().enumerate() {
146 if i > 0 {
147 write!(self.writer, ", ")?;
148 }
149
150 write!(self.writer, "{id}: ", id = self.source(param.id.span))?;
151 self.ty(¶m.ty)?;
152 }
153
154 Ok(())
155 }
156
157 pub fn ty(&mut self, ty: &Type) -> std::fmt::Result {
159 match ty {
160 Type::U8(_) => write!(self.writer, "u8"),
161 Type::S8(_) => write!(self.writer, "s8"),
162 Type::U16(_) => write!(self.writer, "u16"),
163 Type::S16(_) => write!(self.writer, "s16"),
164 Type::U32(_) => write!(self.writer, "u32"),
165 Type::S32(_) => write!(self.writer, "s32"),
166 Type::U64(_) => write!(self.writer, "u64"),
167 Type::S64(_) => write!(self.writer, "s64"),
168 Type::F32(_) => write!(self.writer, "f32"),
169 Type::F64(_) => write!(self.writer, "f64"),
170 Type::Char(_) => write!(self.writer, "char"),
171 Type::Bool(_) => write!(self.writer, "bool"),
172 Type::String(_) => write!(self.writer, "string"),
173 Type::Tuple(types, _) => {
174 write!(self.writer, "tuple<")?;
175 for (i, ty) in types.iter().enumerate() {
176 if i > 0 {
177 write!(self.writer, ", ")?;
178 }
179
180 self.ty(ty)?;
181 }
182
183 write!(self.writer, ">")
184 }
185 Type::List(ty, _) => {
186 write!(self.writer, "list<")?;
187 self.ty(ty)?;
188 write!(self.writer, ">")
189 }
190 Type::Option(ty, _) => {
191 write!(self.writer, "option<")?;
192 self.ty(ty)?;
193 write!(self.writer, ">")
194 }
195 Type::Result { ok, err, .. } => match (ok, err) {
196 (None, None) => write!(self.writer, "result"),
197 (None, Some(err)) => {
198 write!(self.writer, "result<_, ")?;
199 self.ty(err)?;
200 write!(self.writer, ">")
201 }
202 (Some(ok), None) => {
203 write!(self.writer, "result<")?;
204 self.ty(ok)?;
205 write!(self.writer, ">")
206 }
207 (Some(ok), Some(err)) => {
208 write!(self.writer, "result<")?;
209 self.ty(ok)?;
210 write!(self.writer, ", ")?;
211 self.ty(err)?;
212 write!(self.writer, ">")
213 }
214 },
215 Type::Borrow(id, _) => {
216 write!(self.writer, "borrow<{id}>", id = self.source(id.span))
217 }
218 Type::Stream(ty, _) => match ty {
219 Some(ty) => {
220 write!(self.writer, "stream<")?;
221 self.ty(ty)?;
222 write!(self.writer, ">")
223 }
224 None => write!(self.writer, "stream"),
225 },
226 Type::Future(ty, _) => match ty {
227 Some(ty) => {
228 write!(self.writer, "future<")?;
229 self.ty(ty)?;
230 write!(self.writer, ">")
231 }
232 None => write!(self.writer, "future"),
233 },
234 Type::ErrorContext(_) => write!(self.writer, "error-context"),
235 Type::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
236 }
237 }
238
239 pub fn inline_interface(&mut self, iface: &InlineInterface) -> std::fmt::Result {
241 write!(self.writer, "interface {{")?;
242 self.newline()?;
243
244 self.inc();
245 for (i, item) in iface.items.iter().enumerate() {
246 if i > 0 {
247 self.newline()?;
248 }
249
250 self.interface_item(item)?;
251 self.newline()?;
252 }
253
254 self.dec();
255 self.indent()?;
256 write!(self.writer, "}}")
257 }
258
259 pub fn interface_item(&mut self, item: &InterfaceItem) -> std::fmt::Result {
261 match item {
262 InterfaceItem::Use(u) => self.use_type(u),
263 InterfaceItem::Type(t) => self.item_type_decl(t),
264 InterfaceItem::Export(e) => self.interface_export(e),
265 }
266 }
267
268 pub fn use_type(&mut self, use_ty: &Use) -> std::fmt::Result {
270 self.docs(&use_ty.docs)?;
271 self.indent()?;
272 write!(self.writer, "use ")?;
273 self.use_path(&use_ty.path)?;
274
275 write!(self.writer, ".{{ ")?;
276
277 for (i, item) in use_ty.items.iter().enumerate() {
278 if i > 0 {
279 write!(self.writer, ", ")?;
280 }
281
282 write!(self.writer, "{id}", id = self.source(item.id.span))?;
283 if let Some(as_id) = &item.as_id {
284 write!(self.writer, " as {as_id}", as_id = self.source(as_id.span))?;
285 }
286 }
287
288 write!(self.writer, " }};")
289 }
290
291 pub fn use_path(&mut self, path: &UsePath) -> std::fmt::Result {
293 match path {
294 UsePath::Package(p) => self.package_path(p),
295 UsePath::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
296 }
297 }
298
299 pub fn item_type_decl(&mut self, decl: &ItemTypeDecl) -> std::fmt::Result {
301 match decl {
302 ItemTypeDecl::Resource(r) => self.resource_decl(r),
303 ItemTypeDecl::Variant(v) => self.variant_decl(v),
304 ItemTypeDecl::Record(r) => self.record_decl(r),
305 ItemTypeDecl::Flags(f) => self.flags_decl(f),
306 ItemTypeDecl::Enum(e) => self.enum_decl(e),
307 ItemTypeDecl::Alias(a) => self.type_alias(a),
308 }
309 }
310
311 pub fn resource_decl(&mut self, decl: &ResourceDecl) -> std::fmt::Result {
313 self.docs(&decl.docs)?;
314 self.indent()?;
315 write!(
316 self.writer,
317 "resource {id} {{",
318 id = self.source(decl.id.span)
319 )?;
320 self.newline()?;
321
322 self.inc();
323 for (i, method) in decl.methods.iter().enumerate() {
324 if i > 0 {
325 self.newline()?;
326 }
327
328 self.resource_method(method)?;
329 self.newline()?;
330 }
331
332 self.dec();
333 self.indent()?;
334 write!(self.writer, "}}")
335 }
336
337 pub fn resource_method(&mut self, method: &ResourceMethod) -> std::fmt::Result {
339 match method {
340 ResourceMethod::Constructor(c) => self.constructor(c),
341 ResourceMethod::Method(m) => self.method(m),
342 }
343 }
344
345 pub fn constructor(&mut self, constructor: &Constructor) -> std::fmt::Result {
347 self.docs(&constructor.docs)?;
348 self.indent()?;
349 write!(self.writer, "constructor(")?;
350 self.named_types(&constructor.params)?;
351 write!(self.writer, ");")
352 }
353
354 pub fn method(&mut self, method: &Method) -> std::fmt::Result {
356 self.docs(&method.docs)?;
357 self.indent()?;
358 write!(self.writer, "{id}: ", id = self.source(method.id.span))?;
359
360 if method.is_static {
361 write!(self.writer, "static ")?;
362 }
363
364 self.func_type(&method.ty)?;
365 write!(self.writer, ";")
366 }
367
368 pub fn func_type_ref(&mut self, ty: &FuncTypeRef) -> std::fmt::Result {
370 match ty {
371 FuncTypeRef::Func(ty) => self.func_type(ty),
372 FuncTypeRef::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
373 }
374 }
375
376 pub fn variant_decl(&mut self, decl: &VariantDecl) -> std::fmt::Result {
378 self.docs(&decl.docs)?;
379 self.indent()?;
380 write!(
381 self.writer,
382 "variant {id} {{",
383 id = self.source(decl.id.span)
384 )?;
385 self.newline()?;
386
387 self.inc();
388 for case in &decl.cases {
389 self.indent()?;
390 self.variant_case(case)?;
391 write!(self.writer, ",")?;
392 self.newline()?;
393 }
394
395 self.dec();
396 self.indent()?;
397 write!(self.writer, "}}")
398 }
399
400 pub fn variant_case(&mut self, case: &VariantCase) -> std::fmt::Result {
402 self.docs(&case.docs)?;
403 self.indent()?;
404 write!(self.writer, "{id}", id = self.source(case.id.span))?;
405
406 if let Some(ty) = &case.ty {
407 write!(self.writer, "(")?;
408 self.ty(ty)?;
409 write!(self.writer, ")")?;
410 }
411
412 Ok(())
413 }
414
415 pub fn record_decl(&mut self, decl: &RecordDecl) -> std::fmt::Result {
417 self.docs(&decl.docs)?;
418 self.indent()?;
419 write!(
420 self.writer,
421 "record {id} {{",
422 id = self.source(decl.id.span)
423 )?;
424 self.newline()?;
425
426 self.inc();
427 for field in &decl.fields {
428 self.docs(&field.docs)?;
429 self.indent()?;
430 write!(self.writer, "{id}: ", id = self.source(field.id.span))?;
431 self.ty(&field.ty)?;
432 write!(self.writer, ",")?;
433 self.newline()?;
434 }
435
436 self.dec();
437 self.indent()?;
438 write!(self.writer, "}}")
439 }
440
441 pub fn flags_decl(&mut self, decl: &FlagsDecl) -> std::fmt::Result {
443 self.docs(&decl.docs)?;
444 self.indent()?;
445 write!(self.writer, "flags {id} {{", id = self.source(decl.id.span))?;
446 self.newline()?;
447
448 self.inc();
449 for flag in &decl.flags {
450 self.docs(&flag.docs)?;
451 self.indent()?;
452 write!(self.writer, "{id},", id = self.source(flag.id.span))?;
453 self.newline()?;
454 }
455
456 self.dec();
457 self.indent()?;
458 write!(self.writer, "}}")
459 }
460
461 pub fn enum_decl(&mut self, decl: &EnumDecl) -> std::fmt::Result {
463 self.docs(&decl.docs)?;
464 self.indent()?;
465 write!(self.writer, "enum {id} {{", id = self.source(decl.id.span))?;
466 self.newline()?;
467
468 self.inc();
469 for case in &decl.cases {
470 self.docs(&case.docs)?;
471 self.indent()?;
472 write!(self.writer, "{id},", id = self.source(case.id.span))?;
473 self.newline()?;
474 }
475
476 self.dec();
477 self.indent()?;
478 write!(self.writer, "}}")
479 }
480
481 pub fn type_alias(&mut self, alias: &TypeAlias) -> std::fmt::Result {
483 self.docs(&alias.docs)?;
484 self.indent()?;
485 write!(self.writer, "type {id} = ", id = self.source(alias.id.span))?;
486 match &alias.kind {
487 TypeAliasKind::Func(ty) => self.func_type(ty)?,
488 TypeAliasKind::Type(ty) => self.ty(ty)?,
489 }
490
491 write!(self.writer, ";")
492 }
493
494 pub fn interface_export(&mut self, export: &InterfaceExport) -> std::fmt::Result {
496 self.docs(&export.docs)?;
497 self.indent()?;
498 write!(self.writer, "{id}: ", id = self.source(export.id.span))?;
499 self.func_type_ref(&export.ty)?;
500 write!(self.writer, ";")
501 }
502
503 pub fn type_statement(&mut self, stmt: &TypeStatement) -> std::fmt::Result {
505 match stmt {
506 TypeStatement::Interface(i) => self.interface_decl(i),
507 TypeStatement::World(w) => self.world_decl(w),
508 TypeStatement::Type(t) => self.type_decl(t),
509 }
510 }
511
512 pub fn interface_decl(&mut self, decl: &InterfaceDecl) -> std::fmt::Result {
514 self.docs(&decl.docs)?;
515 self.indent()?;
516 write!(
517 self.writer,
518 "interface {id} {{",
519 id = self.source(decl.id.span)
520 )?;
521 self.newline()?;
522
523 self.inc();
524 for (i, item) in decl.items.iter().enumerate() {
525 if i > 0 {
526 self.newline()?;
527 }
528
529 self.interface_item(item)?;
530 self.newline()?;
531 }
532
533 self.dec();
534 self.indent()?;
535 write!(self.writer, "}}")
536 }
537
538 pub fn world_decl(&mut self, decl: &WorldDecl) -> std::fmt::Result {
540 self.docs(&decl.docs)?;
541 self.indent()?;
542 write!(self.writer, "world {id} {{", id = self.source(decl.id.span))?;
543 self.newline()?;
544
545 self.inc();
546 for (i, item) in decl.items.iter().enumerate() {
547 if i > 0 {
548 self.newline()?;
549 }
550
551 self.world_item(item)?;
552 self.newline()?;
553 }
554
555 self.dec();
556 self.indent()?;
557 write!(self.writer, "}}")
558 }
559
560 pub fn world_item(&mut self, item: &WorldItem) -> std::fmt::Result {
562 match item {
563 WorldItem::Use(u) => self.use_type(u),
564 WorldItem::Type(t) => self.item_type_decl(t),
565 WorldItem::Import(i) => self.world_import(i),
566 WorldItem::Export(e) => self.world_export(e),
567 WorldItem::Include(i) => self.world_include(i),
568 }
569 }
570
571 pub fn world_import(&mut self, import: &WorldImport) -> std::fmt::Result {
573 self.docs(&import.docs)?;
574 self.indent()?;
575 write!(self.writer, "import ")?;
576
577 self.world_item_path(&import.path)?;
578 write!(self.writer, ";")
579 }
580
581 pub fn world_export(&mut self, export: &WorldExport) -> std::fmt::Result {
583 self.docs(&export.docs)?;
584 self.indent()?;
585 write!(self.writer, "export ")?;
586
587 self.world_item_path(&export.path)?;
588 write!(self.writer, ";")
589 }
590
591 pub fn world_item_path(&mut self, path: &WorldItemPath) -> std::fmt::Result {
593 match path {
594 WorldItemPath::Named(n) => self.named_world_item(n),
595 WorldItemPath::Package(p) => self.package_path(p),
596 WorldItemPath::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
597 }
598 }
599
600 pub fn named_world_item(&mut self, item: &NamedWorldItem) -> std::fmt::Result {
602 write!(self.writer, "{id}: ", id = self.source(item.id.span))?;
603 self.extern_type(&item.ty)
604 }
605
606 pub fn extern_type(&mut self, ty: &ExternType) -> std::fmt::Result {
608 match ty {
609 ExternType::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
610 ExternType::Func(ty) => self.func_type(ty),
611 ExternType::Interface(i) => self.inline_interface(i),
612 }
613 }
614
615 pub fn world_include(&mut self, include: &WorldInclude) -> std::fmt::Result {
617 self.docs(&include.docs)?;
618 self.indent()?;
619 write!(self.writer, "include ")?;
620 self.world_ref(&include.world)?;
621
622 if !include.with.is_empty() {
623 write!(self.writer, " with {{")?;
624 self.newline()?;
625 self.inc();
626
627 for item in &include.with {
628 self.indent()?;
629 write!(
630 self.writer,
631 "{source} as {target},",
632 source = self.source(item.from.span),
633 target = self.source(item.to.span)
634 )?;
635 self.newline()?;
636 }
637
638 self.dec();
639 self.indent()?;
640 write!(self.writer, "}}")?;
641 }
642
643 write!(self.writer, ";")
644 }
645
646 pub fn world_ref(&mut self, reference: &WorldRef) -> std::fmt::Result {
648 match reference {
649 WorldRef::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
650 WorldRef::Package(p) => self.package_path(p),
651 }
652 }
653
654 pub fn type_decl(&mut self, decl: &TypeDecl) -> std::fmt::Result {
656 match decl {
657 TypeDecl::Variant(v) => self.variant_decl(v),
658 TypeDecl::Record(r) => self.record_decl(r),
659 TypeDecl::Flags(f) => self.flags_decl(f),
660 TypeDecl::Enum(e) => self.enum_decl(e),
661 TypeDecl::Alias(a) => self.type_alias(a),
662 }
663 }
664
665 pub fn let_statement(&mut self, stmt: &LetStatement) -> std::fmt::Result {
667 self.docs(&stmt.docs)?;
668 self.indent()?;
669 write!(self.writer, "let {id} = ", id = self.source(stmt.id.span))?;
670 self.expr(&stmt.expr)?;
671 write!(self.writer, ";")
672 }
673
674 pub fn expr(&mut self, expr: &Expr) -> std::fmt::Result {
676 self.primary_expr(&expr.primary)?;
677 for postfix in &expr.postfix {
678 self.postfix_expr(postfix)?;
679 }
680
681 Ok(())
682 }
683
684 pub fn primary_expr(&mut self, expr: &PrimaryExpr) -> std::fmt::Result {
686 match expr {
687 PrimaryExpr::New(e) => self.new_expr(e),
688 PrimaryExpr::Nested(e) => {
689 write!(self.writer, "(")?;
690 self.expr(&e.inner)?;
691 write!(self.writer, ")")
692 }
693 PrimaryExpr::Ident(id) => write!(self.writer, "{id}", id = self.source(id.span)),
694 }
695 }
696
697 pub fn new_expr(&mut self, expr: &NewExpr) -> std::fmt::Result {
699 write!(
700 self.writer,
701 "new {name} {{",
702 name = self.source(expr.package.span)
703 )?;
704
705 if expr.arguments.is_empty() {
706 write!(self.writer, "}}")?;
707 return Ok(());
708 }
709
710 if expr.arguments.len() == 1 {
711 if let InstantiationArgument::Fill(_) = expr.arguments[0] {
712 write!(self.writer, " ... }}")?;
713 return Ok(());
714 }
715 }
716
717 self.newline()?;
718 self.inc();
719
720 for arg in &expr.arguments {
721 self.indent()?;
722
723 match arg {
724 InstantiationArgument::Inferred(id) => {
725 write!(self.writer, "{id},", id = self.source(id.span))?
726 }
727 InstantiationArgument::Spread(id) => {
728 write!(self.writer, "...{id},", id = self.source(id.span))?
729 }
730 InstantiationArgument::Named(arg) => {
731 match &arg.name {
732 InstantiationArgumentName::Ident(id) => {
733 write!(self.writer, "{id}: ", id = self.source(id.span))?;
734 }
735 InstantiationArgumentName::String(s) => {
736 write!(self.writer, "{s}: ", s = self.source(s.span))?;
737 }
738 }
739 self.expr(&arg.expr)?;
740 write!(self.writer, ",")?;
741 }
742 InstantiationArgument::Fill(_) => write!(self.writer, "...")?,
743 }
744
745 self.newline()?;
746 }
747
748 self.dec();
749 self.indent()?;
750 write!(self.writer, "}}")
751 }
752
753 pub fn postfix_expr(&mut self, expr: &PostfixExpr) -> std::fmt::Result {
755 match expr {
756 PostfixExpr::Access(a) => self.access_expr(a),
757 PostfixExpr::NamedAccess(a) => self.named_access_expr(a),
758 }
759 }
760
761 pub fn access_expr(&mut self, expr: &AccessExpr) -> std::fmt::Result {
763 write!(self.writer, ".{id}", id = self.source(expr.id.span))
764 }
765
766 pub fn named_access_expr(&mut self, expr: &NamedAccessExpr) -> std::fmt::Result {
768 write!(
769 self.writer,
770 "[{name}]",
771 name = self.source(expr.string.span)
772 )
773 }
774
775 pub fn export_statement(&mut self, stmt: &ExportStatement) -> std::fmt::Result {
777 self.docs(&stmt.docs)?;
778 self.indent()?;
779
780 write!(self.writer, "export ")?;
781
782 self.expr(&stmt.expr)?;
783
784 match &stmt.options {
785 ExportOptions::None => {}
786 ExportOptions::Spread(_) => {
787 write!(self.writer, "...")?;
788 }
789 ExportOptions::Rename(name) => {
790 write!(self.writer, " as {name}", name = self.source(name.span()))?;
791 }
792 }
793
794 write!(self.writer, ";")
795 }
796
797 fn newline(&mut self) -> std::fmt::Result {
798 writeln!(self.writer)?;
799 self.indented = false;
800 Ok(())
801 }
802
803 fn indent(&mut self) -> std::fmt::Result {
804 if !self.indented {
805 for _ in 0..self.indent {
806 write!(self.writer, "{space}", space = self.space)?;
807 }
808
809 self.indented = true;
810 }
811
812 Ok(())
813 }
814
815 fn inc(&mut self) {
816 self.indent = self.indent.saturating_add(1);
817 }
818
819 fn dec(&mut self) {
820 self.indent = self.indent.saturating_sub(1);
821 }
822
823 fn source(&self, span: SourceSpan) -> &'a str {
824 &self.source[span.offset()..span.offset() + span.len()]
825 }
826}