Skip to main content

sage_parser/
formatter.rs

1//! Sage source code formatter.
2//!
3//! Provides an opinionated, non-configurable formatter for Sage source code.
4//! Similar in spirit to `gofmt` and `rustfmt`.
5//!
6//! # Formatting Rules
7//!
8//! - Indent with 4 spaces (no tabs)
9//! - One blank line between top-level declarations
10//! - Two blank lines before `run` statement
11//! - Handler ordering: `on start` → `on message` → `on error` → `on stop`
12//! - Binary operators with spaces either side
13//! - Closing braces on their own line
14//! - Spawn initializer fields: one per line if >2 fields, inline if ≤2
15
16use crate::ast::*;
17use crate::ty::TypeExpr;
18use std::fmt::Write;
19
20/// Formats a Sage program into canonical source code.
21pub fn format(program: &Program) -> String {
22    let mut formatter = Formatter::new();
23    formatter.format_program(program);
24    formatter.output
25}
26
27struct Formatter {
28    output: String,
29    indent: usize,
30}
31
32impl Formatter {
33    fn new() -> Self {
34        Self {
35            output: String::new(),
36            indent: 0,
37        }
38    }
39
40    fn write(&mut self, s: &str) {
41        self.output.push_str(s);
42    }
43
44    fn writeln(&mut self, s: &str) {
45        self.write_indent();
46        self.output.push_str(s);
47        self.output.push('\n');
48    }
49
50    fn newline(&mut self) {
51        self.output.push('\n');
52    }
53
54    fn write_indent(&mut self) {
55        for _ in 0..self.indent {
56            self.output.push_str("    ");
57        }
58    }
59
60    fn indent(&mut self) {
61        self.indent += 1;
62    }
63
64    fn dedent(&mut self) {
65        self.indent = self.indent.saturating_sub(1);
66    }
67
68    fn format_program(&mut self, program: &Program) {
69        let mut first = true;
70
71        // Module declarations
72        for m in &program.mod_decls {
73            if !first {
74                self.newline();
75            }
76            first = false;
77            self.format_mod_decl(m);
78        }
79
80        // Use declarations
81        for u in &program.use_decls {
82            if !first {
83                self.newline();
84            }
85            first = false;
86            self.format_use_decl(u);
87        }
88
89        // Constants
90        for c in &program.consts {
91            if !first {
92                self.newline();
93            }
94            first = false;
95            self.format_const_decl(c);
96        }
97
98        // Records
99        for r in &program.records {
100            if !first {
101                self.newline();
102            }
103            first = false;
104            self.format_record_decl(r);
105        }
106
107        // Enums
108        for e in &program.enums {
109            if !first {
110                self.newline();
111            }
112            first = false;
113            self.format_enum_decl(e);
114        }
115
116        // Tools
117        for t in &program.tools {
118            if !first {
119                self.newline();
120            }
121            first = false;
122            self.format_tool_decl(t);
123        }
124
125        // Functions
126        for f in &program.functions {
127            if !first {
128                self.newline();
129            }
130            first = false;
131            self.format_fn_decl(f);
132        }
133
134        // Agents
135        for a in &program.agents {
136            if !first {
137                self.newline();
138            }
139            first = false;
140            self.format_agent_decl(a);
141        }
142
143        // Tests
144        for t in &program.tests {
145            if !first {
146                self.newline();
147            }
148            first = false;
149            self.format_test_decl(t);
150        }
151
152        // Run statement (two blank lines before)
153        if let Some(run_agent) = &program.run_agent {
154            if !first {
155                self.newline();
156                self.newline();
157            }
158            self.write("run ");
159            self.write(&run_agent.name);
160            self.writeln(";");
161        }
162    }
163
164    fn format_mod_decl(&mut self, m: &ModDecl) {
165        if m.is_pub {
166            self.write("pub ");
167        }
168        self.write("mod ");
169        self.write(&m.name.name);
170        self.writeln(";");
171    }
172
173    fn format_use_decl(&mut self, u: &UseDecl) {
174        if u.is_pub {
175            self.write("pub ");
176        }
177        self.write("use ");
178        self.write(
179            &u.path
180                .iter()
181                .map(|i| i.name.as_str())
182                .collect::<Vec<_>>()
183                .join("::"),
184        );
185        match &u.kind {
186            UseKind::Simple(alias) => {
187                if let Some(a) = alias {
188                    self.write(" as ");
189                    self.write(&a.name);
190                }
191            }
192            UseKind::Glob => {
193                self.write("::*");
194            }
195            UseKind::Group(names) => {
196                self.write("::{");
197                for (i, (name, alias)) in names.iter().enumerate() {
198                    if i > 0 {
199                        self.write(", ");
200                    }
201                    self.write(&name.name);
202                    if let Some(a) = alias {
203                        self.write(" as ");
204                        self.write(&a.name);
205                    }
206                }
207                self.write("}");
208            }
209        }
210        self.writeln(";");
211    }
212
213    fn format_const_decl(&mut self, c: &ConstDecl) {
214        if c.is_pub {
215            self.write("pub ");
216        }
217        self.write("const ");
218        self.write(&c.name.name);
219        self.write(": ");
220        self.format_type(&c.ty);
221        self.write(" = ");
222        self.format_expr(&c.value);
223        self.writeln(";");
224    }
225
226    fn format_record_decl(&mut self, r: &RecordDecl) {
227        if r.is_pub {
228            self.write("pub ");
229        }
230        self.write("record ");
231        self.write(&r.name.name);
232        self.write(" {\n");
233        self.indent();
234        for field in &r.fields {
235            self.write_indent();
236            self.write(&field.name.name);
237            self.write(": ");
238            self.format_type(&field.ty);
239            self.write("\n");
240        }
241        self.dedent();
242        self.writeln("}");
243    }
244
245    fn format_enum_decl(&mut self, e: &EnumDecl) {
246        if e.is_pub {
247            self.write("pub ");
248        }
249        self.write("enum ");
250        self.write(&e.name.name);
251        self.write(" {\n");
252        self.indent();
253        for variant in &e.variants {
254            self.write_indent();
255            self.write(&variant.name.name);
256            if let Some(payload) = &variant.payload {
257                self.write("(");
258                self.format_type(payload);
259                self.write(")");
260            }
261            self.write("\n");
262        }
263        self.dedent();
264        self.writeln("}");
265    }
266
267    fn format_tool_decl(&mut self, t: &ToolDecl) {
268        if t.is_pub {
269            self.write("pub ");
270        }
271        self.write("tool ");
272        self.write(&t.name.name);
273        self.write(" {\n");
274        self.indent();
275        for func in &t.functions {
276            self.write_indent();
277            self.write("fn ");
278            self.write(&func.name.name);
279            self.write("(");
280            for (i, param) in func.params.iter().enumerate() {
281                if i > 0 {
282                    self.write(", ");
283                }
284                self.write(&param.name.name);
285                self.write(": ");
286                self.format_type(&param.ty);
287            }
288            self.write(") -> ");
289            self.format_type(&func.return_ty);
290            self.write("\n");
291        }
292        self.dedent();
293        self.writeln("}");
294    }
295
296    fn format_fn_decl(&mut self, f: &FnDecl) {
297        if f.is_pub {
298            self.write("pub ");
299        }
300        self.write("fn ");
301        self.write(&f.name.name);
302        self.write("(");
303        for (i, param) in f.params.iter().enumerate() {
304            if i > 0 {
305                self.write(", ");
306            }
307            self.write(&param.name.name);
308            self.write(": ");
309            self.format_type(&param.ty);
310        }
311        self.write(") -> ");
312        self.format_type(&f.return_ty);
313        if f.is_fallible {
314            self.write(" fails");
315        }
316        self.write(" {\n");
317        self.indent();
318        self.format_block(&f.body);
319        self.dedent();
320        self.writeln("}");
321    }
322
323    fn format_agent_decl(&mut self, agent: &AgentDecl) {
324        if agent.is_pub {
325            self.write("pub ");
326        }
327        self.write("agent ");
328        self.write(&agent.name.name);
329
330        // Receives clause
331        if let Some(recv) = &agent.receives {
332            self.write(" receives ");
333            self.format_type(recv);
334        }
335
336        // Tool uses
337        if !agent.tool_uses.is_empty() {
338            self.write(" uses ");
339            for (i, tool) in agent.tool_uses.iter().enumerate() {
340                if i > 0 {
341                    self.write(", ");
342                }
343                self.write(&tool.name);
344            }
345        }
346
347        self.write(" {\n");
348        self.indent();
349
350        // Beliefs (fields)
351        for belief in &agent.beliefs {
352            self.write_indent();
353            if belief.is_persistent {
354                self.write("@persistent ");
355            }
356            self.write(&belief.name.name);
357            self.write(": ");
358            self.format_type(&belief.ty);
359            self.write("\n");
360        }
361
362        // Blank line between fields and handlers if there are both
363        if !agent.beliefs.is_empty() && !agent.handlers.is_empty() {
364            self.newline();
365        }
366
367        // Sort handlers: waking, start, message, pause, resume, error, stop/resting
368        let mut sorted_handlers: Vec<&HandlerDecl> = agent.handlers.iter().collect();
369        sorted_handlers.sort_by_key(|h| match &h.event {
370            EventKind::Waking => 0,
371            EventKind::Start => 1,
372            EventKind::Message { .. } => 2,
373            EventKind::Pause => 3,
374            EventKind::Resume => 4,
375            EventKind::Error { .. } => 5,
376            EventKind::Stop => 6,
377            EventKind::Resting => 7,
378        });
379
380        for (i, handler) in sorted_handlers.iter().enumerate() {
381            if i > 0 {
382                self.newline();
383            }
384            self.format_handler(handler);
385        }
386
387        self.dedent();
388        self.writeln("}");
389    }
390
391    fn format_handler(&mut self, handler: &HandlerDecl) {
392        self.write_indent();
393        match &handler.event {
394            EventKind::Waking => {
395                self.write("on waking {\n");
396            }
397            EventKind::Start => {
398                self.write("on start {\n");
399            }
400            EventKind::Message {
401                param_name,
402                param_ty,
403            } => {
404                self.write("on message(");
405                self.write(&param_name.name);
406                self.write(": ");
407                self.format_type(param_ty);
408                self.write(") {\n");
409            }
410            EventKind::Pause => {
411                self.write("on pause {\n");
412            }
413            EventKind::Resume => {
414                self.write("on resume {\n");
415            }
416            EventKind::Error { param_name } => {
417                self.write("on error(");
418                self.write(&param_name.name);
419                self.write(": Error) {\n");
420            }
421            EventKind::Stop => {
422                self.write("on stop {\n");
423            }
424            EventKind::Resting => {
425                self.write("on resting {\n");
426            }
427        }
428        self.indent();
429        self.format_block(&handler.body);
430        self.dedent();
431        self.writeln("}");
432    }
433
434    fn format_test_decl(&mut self, t: &TestDecl) {
435        self.write("test \"");
436        for c in t.name.chars() {
437            match c {
438                '\\' => self.write("\\\\"),
439                '"' => self.write("\\\""),
440                '\n' => self.write("\\n"),
441                _ => self.output.push(c),
442            }
443        }
444        self.write("\" {\n");
445        self.indent();
446        self.format_block(&t.body);
447        self.dedent();
448        self.writeln("}");
449    }
450
451    fn format_block(&mut self, block: &Block) {
452        for stmt in &block.stmts {
453            self.format_stmt(stmt);
454        }
455    }
456
457    fn format_stmt(&mut self, stmt: &Stmt) {
458        match stmt {
459            Stmt::Let {
460                name, ty, value, ..
461            } => {
462                self.write_indent();
463                self.write("let ");
464                self.write(&name.name);
465                if let Some(t) = ty {
466                    self.write(": ");
467                    self.format_type(t);
468                }
469                self.write(" = ");
470                self.format_expr(value);
471                self.write(";\n");
472            }
473            Stmt::LetTuple {
474                names, ty, value, ..
475            } => {
476                self.write_indent();
477                self.write("let (");
478                for (i, name) in names.iter().enumerate() {
479                    if i > 0 {
480                        self.write(", ");
481                    }
482                    self.write(&name.name);
483                }
484                self.write(")");
485                if let Some(t) = ty {
486                    self.write(": ");
487                    self.format_type(t);
488                }
489                self.write(" = ");
490                self.format_expr(value);
491                self.write(";\n");
492            }
493            Stmt::Assign { name, value, .. } => {
494                self.write_indent();
495                self.write(&name.name);
496                self.write(" = ");
497                self.format_expr(value);
498                self.write(";\n");
499            }
500            Stmt::Expr { expr, .. } => {
501                self.write_indent();
502                self.format_expr(expr);
503                self.write(";\n");
504            }
505            Stmt::Return { value, .. } => {
506                self.write_indent();
507                self.write("return");
508                if let Some(v) = value {
509                    self.write(" ");
510                    self.format_expr(v);
511                }
512                self.write(";\n");
513            }
514            Stmt::While {
515                condition, body, ..
516            } => {
517                self.write_indent();
518                self.write("while ");
519                self.format_expr(condition);
520                self.write(" {\n");
521                self.indent();
522                self.format_block(body);
523                self.dedent();
524                self.writeln("}");
525            }
526            Stmt::For {
527                pattern,
528                iter,
529                body,
530                ..
531            } => {
532                self.write_indent();
533                self.write("for ");
534                self.format_pattern(pattern);
535                self.write(" in ");
536                self.format_expr(iter);
537                self.write(" {\n");
538                self.indent();
539                self.format_block(body);
540                self.dedent();
541                self.writeln("}");
542            }
543            Stmt::Loop { body, .. } => {
544                self.writeln("loop {");
545                self.indent();
546                self.format_block(body);
547                self.dedent();
548                self.writeln("}");
549            }
550            Stmt::Break { .. } => {
551                self.writeln("break;");
552            }
553            Stmt::SpanBlock { name, body, .. } => {
554                self.write_indent();
555                self.write("span ");
556                self.format_expr(name);
557                self.write(" {\n");
558                self.indent();
559                self.format_block(body);
560                self.dedent();
561                self.write_indent();
562                self.writeln("}");
563            }
564            Stmt::Checkpoint { .. } => {
565                self.write_indent();
566                self.writeln("checkpoint();");
567            }
568            Stmt::If {
569                condition,
570                then_block,
571                else_block,
572                ..
573            } => {
574                self.write_indent();
575                self.write("if ");
576                self.format_expr(condition);
577                self.write(" {\n");
578                self.indent();
579                self.format_block(then_block);
580                self.dedent();
581                self.write_indent();
582                self.write("}");
583                if let Some(else_b) = else_block {
584                    self.write(" else ");
585                    match else_b {
586                        ElseBranch::ElseIf(if_stmt) => {
587                            // Format the nested if without leading indent
588                            if let Stmt::If {
589                                condition,
590                                then_block,
591                                else_block,
592                                ..
593                            } = if_stmt.as_ref()
594                            {
595                                self.write("if ");
596                                self.format_expr(condition);
597                                self.write(" {\n");
598                                self.indent();
599                                self.format_block(then_block);
600                                self.dedent();
601                                self.write_indent();
602                                self.write("}");
603                                if let Some(eb) = else_block {
604                                    self.format_else_branch(eb);
605                                }
606                            }
607                        }
608                        ElseBranch::Block(block) => {
609                            self.write("{\n");
610                            self.indent();
611                            self.format_block(block);
612                            self.dedent();
613                            self.write_indent();
614                            self.write("}");
615                        }
616                    }
617                }
618                self.write("\n");
619            }
620            Stmt::MockDivine { value, .. } => {
621                self.write_indent();
622                self.write("mock divine -> ");
623                self.format_mock_value(value);
624                self.write(";\n");
625            }
626            Stmt::MockTool {
627                tool_name,
628                fn_name,
629                value,
630                ..
631            } => {
632                self.write_indent();
633                self.write("mock tool ");
634                self.write(&tool_name.name);
635                self.write(".");
636                self.write(&fn_name.name);
637                self.write(" -> ");
638                self.format_mock_value(value);
639                self.write(";\n");
640            }
641        }
642    }
643
644    fn format_else_branch(&mut self, else_branch: &ElseBranch) {
645        self.write(" else ");
646        match else_branch {
647            ElseBranch::ElseIf(if_stmt) => {
648                if let Stmt::If {
649                    condition,
650                    then_block,
651                    else_block,
652                    ..
653                } = if_stmt.as_ref()
654                {
655                    self.write("if ");
656                    self.format_expr(condition);
657                    self.write(" {\n");
658                    self.indent();
659                    self.format_block(then_block);
660                    self.dedent();
661                    self.write_indent();
662                    self.write("}");
663                    if let Some(eb) = else_block {
664                        self.format_else_branch(eb);
665                    }
666                }
667            }
668            ElseBranch::Block(block) => {
669                self.write("{\n");
670                self.indent();
671                self.format_block(block);
672                self.dedent();
673                self.write_indent();
674                self.write("}");
675            }
676        }
677    }
678
679    fn format_mock_value(&mut self, value: &MockValue) {
680        match value {
681            MockValue::Value(expr) => self.format_expr(expr),
682            MockValue::Fail(expr) => {
683                self.write("fail(");
684                self.format_expr(expr);
685                self.write(")");
686            }
687        }
688    }
689
690    fn format_pattern(&mut self, pattern: &Pattern) {
691        match pattern {
692            Pattern::Wildcard { .. } => self.write("_"),
693            Pattern::Binding { name, .. } => self.write(&name.name),
694            Pattern::Variant {
695                enum_name,
696                variant,
697                payload,
698                ..
699            } => {
700                if let Some(en) = enum_name {
701                    self.write(&en.name);
702                    self.write("::");
703                }
704                self.write(&variant.name);
705                if let Some(p) = payload {
706                    self.write("(");
707                    self.format_pattern(p);
708                    self.write(")");
709                }
710            }
711            Pattern::Literal { value, .. } => self.format_literal(value),
712            Pattern::Tuple { elements, .. } => {
713                self.write("(");
714                for (i, p) in elements.iter().enumerate() {
715                    if i > 0 {
716                        self.write(", ");
717                    }
718                    self.format_pattern(p);
719                }
720                self.write(")");
721            }
722        }
723    }
724
725    fn format_expr(&mut self, expr: &Expr) {
726        match expr {
727            Expr::Literal { value, .. } => self.format_literal(value),
728            Expr::Var { name, .. } => self.write(&name.name),
729            Expr::Binary {
730                left, op, right, ..
731            } => {
732                self.format_expr(left);
733                self.write(" ");
734                self.write(&op.to_string());
735                self.write(" ");
736                self.format_expr(right);
737            }
738            Expr::Unary { op, operand, .. } => {
739                self.write(&op.to_string());
740                self.format_expr(operand);
741            }
742            Expr::Call { name, args, .. } => {
743                self.write(&name.name);
744                self.write("(");
745                for (i, arg) in args.iter().enumerate() {
746                    if i > 0 {
747                        self.write(", ");
748                    }
749                    self.format_expr(arg);
750                }
751                self.write(")");
752            }
753            Expr::Apply { callee, args, .. } => {
754                self.format_expr(callee);
755                self.write("(");
756                for (i, arg) in args.iter().enumerate() {
757                    if i > 0 {
758                        self.write(", ");
759                    }
760                    self.format_expr(arg);
761                }
762                self.write(")");
763            }
764            Expr::SelfMethodCall { method, args, .. } => {
765                self.write("self.");
766                self.write(&method.name);
767                self.write("(");
768                for (i, arg) in args.iter().enumerate() {
769                    if i > 0 {
770                        self.write(", ");
771                    }
772                    self.format_expr(arg);
773                }
774                self.write(")");
775            }
776            Expr::SelfField { field, .. } => {
777                self.write("self.");
778                self.write(&field.name);
779            }
780            Expr::FieldAccess { object, field, .. } => {
781                self.format_expr(object);
782                self.write(".");
783                self.write(&field.name);
784            }
785            Expr::TupleIndex { tuple, index, .. } => {
786                self.format_expr(tuple);
787                self.write(".");
788                let _ = write!(self.output, "{}", index);
789            }
790            Expr::List { elements, .. } => {
791                self.write("[");
792                for (i, elem) in elements.iter().enumerate() {
793                    if i > 0 {
794                        self.write(", ");
795                    }
796                    self.format_expr(elem);
797                }
798                self.write("]");
799            }
800            Expr::Tuple { elements, .. } => {
801                self.write("(");
802                for (i, elem) in elements.iter().enumerate() {
803                    if i > 0 {
804                        self.write(", ");
805                    }
806                    self.format_expr(elem);
807                }
808                if elements.len() == 1 {
809                    self.write(",");
810                }
811                self.write(")");
812            }
813            Expr::RecordConstruct { name, fields, .. } => {
814                self.write(&name.name);
815                self.write(" { ");
816                for (i, field) in fields.iter().enumerate() {
817                    if i > 0 {
818                        self.write(", ");
819                    }
820                    self.write(&field.name.name);
821                    self.write(": ");
822                    self.format_expr(&field.value);
823                }
824                self.write(" }");
825            }
826            Expr::Map { entries, .. } => {
827                self.write("{");
828                for (i, entry) in entries.iter().enumerate() {
829                    if i > 0 {
830                        self.write(", ");
831                    }
832                    self.format_expr(&entry.key);
833                    self.write(": ");
834                    self.format_expr(&entry.value);
835                }
836                self.write("}");
837            }
838            Expr::VariantConstruct {
839                enum_name,
840                variant,
841                payload,
842                ..
843            } => {
844                self.write(&enum_name.name);
845                self.write(".");
846                self.write(&variant.name);
847                if let Some(p) = payload {
848                    self.write("(");
849                    self.format_expr(p);
850                    self.write(")");
851                }
852            }
853            Expr::Match {
854                scrutinee, arms, ..
855            } => {
856                self.write("match ");
857                self.format_expr(scrutinee);
858                self.write(" {\n");
859                self.indent();
860                for arm in arms {
861                    self.format_match_arm(arm);
862                }
863                self.dedent();
864                self.write_indent();
865                self.write("}");
866            }
867            Expr::Closure { params, body, .. } => {
868                self.write("|");
869                for (i, param) in params.iter().enumerate() {
870                    if i > 0 {
871                        self.write(", ");
872                    }
873                    self.write(&param.name.name);
874                    if let Some(ty) = &param.ty {
875                        self.write(": ");
876                        self.format_type(ty);
877                    }
878                }
879                self.write("| ");
880                self.format_expr(body);
881            }
882            Expr::Paren { inner, .. } => {
883                self.write("(");
884                self.format_expr(inner);
885                self.write(")");
886            }
887            Expr::StringInterp { template, .. } => {
888                self.format_string_template(template);
889            }
890            Expr::Summon { agent, fields, .. } => {
891                self.write("summon ");
892                self.write(&agent.name);
893                if fields.is_empty() {
894                    self.write(" {}");
895                } else if fields.len() <= 2 {
896                    self.write(" { ");
897                    for (i, field) in fields.iter().enumerate() {
898                        if i > 0 {
899                            self.write(", ");
900                        }
901                        self.write(&field.name.name);
902                        self.write(": ");
903                        self.format_expr(&field.value);
904                    }
905                    self.write(" }");
906                } else {
907                    self.write(" {\n");
908                    self.indent();
909                    for field in fields {
910                        self.write_indent();
911                        self.write(&field.name.name);
912                        self.write(": ");
913                        self.format_expr(&field.value);
914                        self.write(",\n");
915                    }
916                    self.dedent();
917                    self.write_indent();
918                    self.write("}");
919                }
920            }
921            Expr::Await {
922                handle, timeout, ..
923            } => {
924                self.write("await ");
925                self.format_expr(handle);
926                if let Some(t) = timeout {
927                    self.write(" timeout(");
928                    self.format_expr(t);
929                    self.write(")");
930                }
931            }
932            Expr::Yield { value, .. } => {
933                self.write("yield(");
934                self.format_expr(value);
935                self.write(")");
936            }
937            Expr::Send {
938                handle, message, ..
939            } => {
940                self.write("send(");
941                self.format_expr(handle);
942                self.write(", ");
943                self.format_expr(message);
944                self.write(")");
945            }
946            Expr::Receive { .. } => {
947                self.write("receive()");
948            }
949            Expr::Divine {
950                template,
951                result_ty,
952                ..
953            } => {
954                self.write("divine(");
955                self.format_string_template(template);
956                if let Some(ty) = result_ty {
957                    self.write(" -> ");
958                    self.format_type(ty);
959                }
960                self.write(")");
961            }
962            Expr::Try { expr, .. } => {
963                self.write("try ");
964                self.format_expr(expr);
965            }
966            Expr::Catch {
967                expr,
968                error_bind,
969                recovery,
970                ..
971            } => {
972                self.format_expr(expr);
973                self.write(" catch");
974                if let Some(name) = error_bind {
975                    self.write("(");
976                    self.write(&name.name);
977                    self.write(")");
978                }
979                self.write(" { ");
980                self.format_expr(recovery);
981                self.write(" }");
982            }
983            Expr::Fail { error, .. } => {
984                self.write("fail ");
985                self.format_expr(error);
986            }
987            Expr::Retry {
988                count, delay, body, ..
989            } => {
990                self.write("retry(");
991                self.format_expr(count);
992                if let Some(d) = delay {
993                    self.write(", delay: ");
994                    self.format_expr(d);
995                }
996                self.write(") {\n");
997                self.indent();
998                self.write_indent();
999                self.format_expr(body);
1000                self.write("\n");
1001                self.dedent();
1002                self.write_indent();
1003                self.write("}");
1004            }
1005            Expr::Trace { message, .. } => {
1006                self.write("trace(");
1007                self.format_expr(message);
1008                self.write(")");
1009            }
1010            Expr::ToolCall {
1011                tool,
1012                function,
1013                args,
1014                ..
1015            } => {
1016                self.write(&tool.name);
1017                self.write(".");
1018                self.write(&function.name);
1019                self.write("(");
1020                for (i, arg) in args.iter().enumerate() {
1021                    if i > 0 {
1022                        self.write(", ");
1023                    }
1024                    self.format_expr(arg);
1025                }
1026                self.write(")");
1027            }
1028            Expr::Reply { message, .. } => {
1029                self.write("reply(");
1030                self.format_expr(message);
1031                self.write(")");
1032            }
1033        }
1034    }
1035
1036    fn format_string_template(&mut self, template: &StringTemplate) {
1037        self.write("\"");
1038        for part in &template.parts {
1039            match part {
1040                StringPart::Literal(s) => {
1041                    for c in s.chars() {
1042                        match c {
1043                            '\\' => self.write("\\\\"),
1044                            '"' => self.write("\\\""),
1045                            '\n' => self.write("\\n"),
1046                            '\r' => self.write("\\r"),
1047                            '\t' => self.write("\\t"),
1048                            '{' => self.write("{{"),
1049                            '}' => self.write("}}"),
1050                            _ => self.output.push(c),
1051                        }
1052                    }
1053                }
1054                StringPart::Interpolation(expr) => {
1055                    self.write("{");
1056                    self.format_expr(expr);
1057                    self.write("}");
1058                }
1059            }
1060        }
1061        self.write("\"");
1062    }
1063
1064    fn format_match_arm(&mut self, arm: &MatchArm) {
1065        self.write_indent();
1066        self.format_pattern(&arm.pattern);
1067        self.write(" => ");
1068        self.format_expr(&arm.body);
1069        self.write(",\n");
1070    }
1071
1072    fn format_literal(&mut self, lit: &Literal) {
1073        match lit {
1074            Literal::Int(n) => {
1075                let _ = write!(self.output, "{}", n);
1076            }
1077            Literal::Float(f) => {
1078                let _ = write!(self.output, "{}", f);
1079            }
1080            Literal::String(s) => {
1081                self.write("\"");
1082                for c in s.chars() {
1083                    match c {
1084                        '\\' => self.write("\\\\"),
1085                        '"' => self.write("\\\""),
1086                        '\n' => self.write("\\n"),
1087                        '\r' => self.write("\\r"),
1088                        '\t' => self.write("\\t"),
1089                        _ => self.output.push(c),
1090                    }
1091                }
1092                self.write("\"");
1093            }
1094            Literal::Bool(b) => {
1095                self.write(if *b { "true" } else { "false" });
1096            }
1097        }
1098    }
1099
1100    fn format_type(&mut self, ty: &TypeExpr) {
1101        match ty {
1102            TypeExpr::Int => self.write("Int"),
1103            TypeExpr::Float => self.write("Float"),
1104            TypeExpr::Bool => self.write("Bool"),
1105            TypeExpr::String => self.write("String"),
1106            TypeExpr::Unit => self.write("Unit"),
1107            TypeExpr::Error => self.write("Error"),
1108            TypeExpr::Named(name, type_args) => {
1109                self.write(&name.name);
1110                if !type_args.is_empty() {
1111                    self.write("<");
1112                    for (i, arg) in type_args.iter().enumerate() {
1113                        if i > 0 {
1114                            self.write(", ");
1115                        }
1116                        self.format_type(arg);
1117                    }
1118                    self.write(">");
1119                }
1120            }
1121            TypeExpr::List(inner) => {
1122                self.write("List<");
1123                self.format_type(inner);
1124                self.write(">");
1125            }
1126            TypeExpr::Option(inner) => {
1127                self.write("Option<");
1128                self.format_type(inner);
1129                self.write(">");
1130            }
1131            TypeExpr::Result(ok, err) => {
1132                self.write("Result<");
1133                self.format_type(ok);
1134                self.write(", ");
1135                self.format_type(err);
1136                self.write(">");
1137            }
1138            TypeExpr::Tuple(types) => {
1139                self.write("(");
1140                for (i, t) in types.iter().enumerate() {
1141                    if i > 0 {
1142                        self.write(", ");
1143                    }
1144                    self.format_type(t);
1145                }
1146                self.write(")");
1147            }
1148            TypeExpr::Oracle(inner) => {
1149                self.write("Oracle<");
1150                self.format_type(inner);
1151                self.write(">");
1152            }
1153            TypeExpr::Fn(params, ret) => {
1154                self.write("Fn(");
1155                for (i, p) in params.iter().enumerate() {
1156                    if i > 0 {
1157                        self.write(", ");
1158                    }
1159                    self.format_type(p);
1160                }
1161                self.write(") -> ");
1162                self.format_type(ret);
1163            }
1164            TypeExpr::Map(key, value) => {
1165                self.write("Map<");
1166                self.format_type(key);
1167                self.write(", ");
1168                self.format_type(value);
1169                self.write(">");
1170            }
1171            TypeExpr::Agent(name) => {
1172                self.write("Agent<");
1173                self.write(&name.name);
1174                self.write(">");
1175            }
1176        }
1177    }
1178}
1179
1180#[cfg(test)]
1181mod tests {
1182    use super::*;
1183    use crate::{lex, parse};
1184    use std::sync::Arc;
1185
1186    fn format_source(source: &str) -> String {
1187        let lex_result = lex(source).unwrap();
1188        let source_arc: Arc<str> = Arc::from(source);
1189        let (program, errors) = parse(lex_result.tokens(), source_arc);
1190        assert!(errors.is_empty(), "Parse errors: {:?}", errors);
1191        let program = program.unwrap();
1192        format(&program)
1193    }
1194
1195    #[test]
1196    fn test_format_simple_agent() {
1197        let source = r#"agent Greeter{name:String on start{print("Hello");emit(0);}}run Greeter;"#;
1198        let formatted = format_source(source);
1199        assert!(formatted.contains("agent Greeter {"));
1200        assert!(formatted.contains("    name: String"));
1201        assert!(formatted.contains("    on start {"));
1202    }
1203
1204    #[test]
1205    fn test_format_binary_operators() {
1206        let source = r#"agent Test{on start{let x=1+2*3;emit(x);}}run Test;"#;
1207        let formatted = format_source(source);
1208        assert!(formatted.contains("1 + 2 * 3"));
1209    }
1210}