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            self.write(&belief.name.name);
354            self.write(": ");
355            self.format_type(&belief.ty);
356            self.write("\n");
357        }
358
359        // Blank line between fields and handlers if there are both
360        if !agent.beliefs.is_empty() && !agent.handlers.is_empty() {
361            self.newline();
362        }
363
364        // Sort handlers: on start, on message, on error, on stop
365        let mut sorted_handlers: Vec<&HandlerDecl> = agent.handlers.iter().collect();
366        sorted_handlers.sort_by_key(|h| match &h.event {
367            EventKind::Start => 0,
368            EventKind::Message { .. } => 1,
369            EventKind::Error { .. } => 2,
370            EventKind::Stop => 3,
371        });
372
373        for (i, handler) in sorted_handlers.iter().enumerate() {
374            if i > 0 {
375                self.newline();
376            }
377            self.format_handler(handler);
378        }
379
380        self.dedent();
381        self.writeln("}");
382    }
383
384    fn format_handler(&mut self, handler: &HandlerDecl) {
385        self.write_indent();
386        match &handler.event {
387            EventKind::Start => {
388                self.write("on start {\n");
389            }
390            EventKind::Message { param_name, param_ty } => {
391                self.write("on message(");
392                self.write(&param_name.name);
393                self.write(": ");
394                self.format_type(param_ty);
395                self.write(") {\n");
396            }
397            EventKind::Error { param_name } => {
398                self.write("on error(");
399                self.write(&param_name.name);
400                self.write(": Error) {\n");
401            }
402            EventKind::Stop => {
403                self.write("on stop {\n");
404            }
405        }
406        self.indent();
407        self.format_block(&handler.body);
408        self.dedent();
409        self.writeln("}");
410    }
411
412    fn format_test_decl(&mut self, t: &TestDecl) {
413        self.write("test \"");
414        for c in t.name.chars() {
415            match c {
416                '\\' => self.write("\\\\"),
417                '"' => self.write("\\\""),
418                '\n' => self.write("\\n"),
419                _ => self.output.push(c),
420            }
421        }
422        self.write("\" {\n");
423        self.indent();
424        self.format_block(&t.body);
425        self.dedent();
426        self.writeln("}");
427    }
428
429    fn format_block(&mut self, block: &Block) {
430        for stmt in &block.stmts {
431            self.format_stmt(stmt);
432        }
433    }
434
435    fn format_stmt(&mut self, stmt: &Stmt) {
436        match stmt {
437            Stmt::Let { name, ty, value, .. } => {
438                self.write_indent();
439                self.write("let ");
440                self.write(&name.name);
441                if let Some(t) = ty {
442                    self.write(": ");
443                    self.format_type(t);
444                }
445                self.write(" = ");
446                self.format_expr(value);
447                self.write(";\n");
448            }
449            Stmt::LetTuple { names, ty, value, .. } => {
450                self.write_indent();
451                self.write("let (");
452                for (i, name) in names.iter().enumerate() {
453                    if i > 0 {
454                        self.write(", ");
455                    }
456                    self.write(&name.name);
457                }
458                self.write(")");
459                if let Some(t) = ty {
460                    self.write(": ");
461                    self.format_type(t);
462                }
463                self.write(" = ");
464                self.format_expr(value);
465                self.write(";\n");
466            }
467            Stmt::Assign { name, value, .. } => {
468                self.write_indent();
469                self.write(&name.name);
470                self.write(" = ");
471                self.format_expr(value);
472                self.write(";\n");
473            }
474            Stmt::Expr { expr, .. } => {
475                self.write_indent();
476                self.format_expr(expr);
477                self.write(";\n");
478            }
479            Stmt::Return { value, .. } => {
480                self.write_indent();
481                self.write("return");
482                if let Some(v) = value {
483                    self.write(" ");
484                    self.format_expr(v);
485                }
486                self.write(";\n");
487            }
488            Stmt::While { condition, body, .. } => {
489                self.write_indent();
490                self.write("while ");
491                self.format_expr(condition);
492                self.write(" {\n");
493                self.indent();
494                self.format_block(body);
495                self.dedent();
496                self.writeln("}");
497            }
498            Stmt::For { pattern, iter, body, .. } => {
499                self.write_indent();
500                self.write("for ");
501                self.format_pattern(pattern);
502                self.write(" in ");
503                self.format_expr(iter);
504                self.write(" {\n");
505                self.indent();
506                self.format_block(body);
507                self.dedent();
508                self.writeln("}");
509            }
510            Stmt::Loop { body, .. } => {
511                self.writeln("loop {");
512                self.indent();
513                self.format_block(body);
514                self.dedent();
515                self.writeln("}");
516            }
517            Stmt::Break { .. } => {
518                self.writeln("break;");
519            }
520            Stmt::If {
521                condition,
522                then_block,
523                else_block,
524                ..
525            } => {
526                self.write_indent();
527                self.write("if ");
528                self.format_expr(condition);
529                self.write(" {\n");
530                self.indent();
531                self.format_block(then_block);
532                self.dedent();
533                self.write_indent();
534                self.write("}");
535                if let Some(else_b) = else_block {
536                    self.write(" else ");
537                    match else_b {
538                        ElseBranch::ElseIf(if_stmt) => {
539                            // Format the nested if without leading indent
540                            if let Stmt::If {
541                                condition,
542                                then_block,
543                                else_block,
544                                ..
545                            } = if_stmt.as_ref()
546                            {
547                                self.write("if ");
548                                self.format_expr(condition);
549                                self.write(" {\n");
550                                self.indent();
551                                self.format_block(then_block);
552                                self.dedent();
553                                self.write_indent();
554                                self.write("}");
555                                if let Some(eb) = else_block {
556                                    self.format_else_branch(eb);
557                                }
558                            }
559                        }
560                        ElseBranch::Block(block) => {
561                            self.write("{\n");
562                            self.indent();
563                            self.format_block(block);
564                            self.dedent();
565                            self.write_indent();
566                            self.write("}");
567                        }
568                    }
569                }
570                self.write("\n");
571            }
572            Stmt::MockInfer { value, .. } => {
573                self.write_indent();
574                self.write("mock infer -> ");
575                self.format_mock_value(value);
576                self.write(";\n");
577            }
578        }
579    }
580
581    fn format_else_branch(&mut self, else_branch: &ElseBranch) {
582        self.write(" else ");
583        match else_branch {
584            ElseBranch::ElseIf(if_stmt) => {
585                if let Stmt::If {
586                    condition,
587                    then_block,
588                    else_block,
589                    ..
590                } = if_stmt.as_ref()
591                {
592                    self.write("if ");
593                    self.format_expr(condition);
594                    self.write(" {\n");
595                    self.indent();
596                    self.format_block(then_block);
597                    self.dedent();
598                    self.write_indent();
599                    self.write("}");
600                    if let Some(eb) = else_block {
601                        self.format_else_branch(eb);
602                    }
603                }
604            }
605            ElseBranch::Block(block) => {
606                self.write("{\n");
607                self.indent();
608                self.format_block(block);
609                self.dedent();
610                self.write_indent();
611                self.write("}");
612            }
613        }
614    }
615
616    fn format_mock_value(&mut self, value: &MockValue) {
617        match value {
618            MockValue::Value(expr) => self.format_expr(expr),
619            MockValue::Fail(expr) => {
620                self.write("fail(");
621                self.format_expr(expr);
622                self.write(")");
623            }
624        }
625    }
626
627    fn format_pattern(&mut self, pattern: &Pattern) {
628        match pattern {
629            Pattern::Wildcard { .. } => self.write("_"),
630            Pattern::Binding { name, .. } => self.write(&name.name),
631            Pattern::Variant {
632                enum_name,
633                variant,
634                payload,
635                ..
636            } => {
637                if let Some(en) = enum_name {
638                    self.write(&en.name);
639                    self.write("::");
640                }
641                self.write(&variant.name);
642                if let Some(p) = payload {
643                    self.write("(");
644                    self.format_pattern(p);
645                    self.write(")");
646                }
647            }
648            Pattern::Literal { value, .. } => self.format_literal(value),
649            Pattern::Tuple { elements, .. } => {
650                self.write("(");
651                for (i, p) in elements.iter().enumerate() {
652                    if i > 0 {
653                        self.write(", ");
654                    }
655                    self.format_pattern(p);
656                }
657                self.write(")");
658            }
659        }
660    }
661
662    fn format_expr(&mut self, expr: &Expr) {
663        match expr {
664            Expr::Literal { value, .. } => self.format_literal(value),
665            Expr::Var { name, .. } => self.write(&name.name),
666            Expr::Binary { left, op, right, .. } => {
667                self.format_expr(left);
668                self.write(" ");
669                self.write(&op.to_string());
670                self.write(" ");
671                self.format_expr(right);
672            }
673            Expr::Unary { op, operand, .. } => {
674                self.write(&op.to_string());
675                self.format_expr(operand);
676            }
677            Expr::Call { name, args, .. } => {
678                self.write(&name.name);
679                self.write("(");
680                for (i, arg) in args.iter().enumerate() {
681                    if i > 0 {
682                        self.write(", ");
683                    }
684                    self.format_expr(arg);
685                }
686                self.write(")");
687            }
688            Expr::SelfMethodCall { method, args, .. } => {
689                self.write("self.");
690                self.write(&method.name);
691                self.write("(");
692                for (i, arg) in args.iter().enumerate() {
693                    if i > 0 {
694                        self.write(", ");
695                    }
696                    self.format_expr(arg);
697                }
698                self.write(")");
699            }
700            Expr::SelfField { field, .. } => {
701                self.write("self.");
702                self.write(&field.name);
703            }
704            Expr::FieldAccess { object, field, .. } => {
705                self.format_expr(object);
706                self.write(".");
707                self.write(&field.name);
708            }
709            Expr::TupleIndex { tuple, index, .. } => {
710                self.format_expr(tuple);
711                self.write(".");
712                let _ = write!(self.output, "{}", index);
713            }
714            Expr::List { elements, .. } => {
715                self.write("[");
716                for (i, elem) in elements.iter().enumerate() {
717                    if i > 0 {
718                        self.write(", ");
719                    }
720                    self.format_expr(elem);
721                }
722                self.write("]");
723            }
724            Expr::Tuple { elements, .. } => {
725                self.write("(");
726                for (i, elem) in elements.iter().enumerate() {
727                    if i > 0 {
728                        self.write(", ");
729                    }
730                    self.format_expr(elem);
731                }
732                if elements.len() == 1 {
733                    self.write(",");
734                }
735                self.write(")");
736            }
737            Expr::RecordConstruct { name, fields, .. } => {
738                self.write(&name.name);
739                self.write(" { ");
740                for (i, field) in fields.iter().enumerate() {
741                    if i > 0 {
742                        self.write(", ");
743                    }
744                    self.write(&field.name.name);
745                    self.write(": ");
746                    self.format_expr(&field.value);
747                }
748                self.write(" }");
749            }
750            Expr::Map { entries, .. } => {
751                self.write("{");
752                for (i, entry) in entries.iter().enumerate() {
753                    if i > 0 {
754                        self.write(", ");
755                    }
756                    self.format_expr(&entry.key);
757                    self.write(": ");
758                    self.format_expr(&entry.value);
759                }
760                self.write("}");
761            }
762            Expr::VariantConstruct {
763                enum_name,
764                variant,
765                payload,
766                ..
767            } => {
768                self.write(&enum_name.name);
769                self.write(".");
770                self.write(&variant.name);
771                if let Some(p) = payload {
772                    self.write("(");
773                    self.format_expr(p);
774                    self.write(")");
775                }
776            }
777            Expr::Match { scrutinee, arms, .. } => {
778                self.write("match ");
779                self.format_expr(scrutinee);
780                self.write(" {\n");
781                self.indent();
782                for arm in arms {
783                    self.format_match_arm(arm);
784                }
785                self.dedent();
786                self.write_indent();
787                self.write("}");
788            }
789            Expr::Closure { params, body, .. } => {
790                self.write("|");
791                for (i, param) in params.iter().enumerate() {
792                    if i > 0 {
793                        self.write(", ");
794                    }
795                    self.write(&param.name.name);
796                    if let Some(ty) = &param.ty {
797                        self.write(": ");
798                        self.format_type(ty);
799                    }
800                }
801                self.write("| ");
802                self.format_expr(body);
803            }
804            Expr::Paren { inner, .. } => {
805                self.write("(");
806                self.format_expr(inner);
807                self.write(")");
808            }
809            Expr::StringInterp { template, .. } => {
810                self.format_string_template(template);
811            }
812            Expr::Spawn { agent, fields, .. } => {
813                self.write("spawn ");
814                self.write(&agent.name);
815                if fields.is_empty() {
816                    self.write(" {}");
817                } else if fields.len() <= 2 {
818                    self.write(" { ");
819                    for (i, field) in fields.iter().enumerate() {
820                        if i > 0 {
821                            self.write(", ");
822                        }
823                        self.write(&field.name.name);
824                        self.write(": ");
825                        self.format_expr(&field.value);
826                    }
827                    self.write(" }");
828                } else {
829                    self.write(" {\n");
830                    self.indent();
831                    for field in fields {
832                        self.write_indent();
833                        self.write(&field.name.name);
834                        self.write(": ");
835                        self.format_expr(&field.value);
836                        self.write(",\n");
837                    }
838                    self.dedent();
839                    self.write_indent();
840                    self.write("}");
841                }
842            }
843            Expr::Await { handle, timeout, .. } => {
844                self.write("await ");
845                self.format_expr(handle);
846                if let Some(t) = timeout {
847                    self.write(" timeout(");
848                    self.format_expr(t);
849                    self.write(")");
850                }
851            }
852            Expr::Emit { value, .. } => {
853                self.write("emit(");
854                self.format_expr(value);
855                self.write(")");
856            }
857            Expr::Send { handle, message, .. } => {
858                self.write("send(");
859                self.format_expr(handle);
860                self.write(", ");
861                self.format_expr(message);
862                self.write(")");
863            }
864            Expr::Receive { .. } => {
865                self.write("receive()");
866            }
867            Expr::Infer {
868                template,
869                result_ty,
870                ..
871            } => {
872                self.write("infer(");
873                self.format_string_template(template);
874                if let Some(ty) = result_ty {
875                    self.write(" -> ");
876                    self.format_type(ty);
877                }
878                self.write(")");
879            }
880            Expr::Try { expr, .. } => {
881                self.write("try ");
882                self.format_expr(expr);
883            }
884            Expr::Catch {
885                expr,
886                error_bind,
887                recovery,
888                ..
889            } => {
890                self.format_expr(expr);
891                self.write(" catch");
892                if let Some(name) = error_bind {
893                    self.write("(");
894                    self.write(&name.name);
895                    self.write(")");
896                }
897                self.write(" { ");
898                self.format_expr(recovery);
899                self.write(" }");
900            }
901            Expr::Fail { error, .. } => {
902                self.write("fail ");
903                self.format_expr(error);
904            }
905            Expr::Retry {
906                count, delay, body, ..
907            } => {
908                self.write("retry(");
909                self.format_expr(count);
910                if let Some(d) = delay {
911                    self.write(", delay: ");
912                    self.format_expr(d);
913                }
914                self.write(") {\n");
915                self.indent();
916                self.write_indent();
917                self.format_expr(body);
918                self.write("\n");
919                self.dedent();
920                self.write_indent();
921                self.write("}");
922            }
923            Expr::Trace { message, .. } => {
924                self.write("trace(");
925                self.format_expr(message);
926                self.write(")");
927            }
928            Expr::ToolCall {
929                tool,
930                function,
931                args,
932                ..
933            } => {
934                self.write(&tool.name);
935                self.write(".");
936                self.write(&function.name);
937                self.write("(");
938                for (i, arg) in args.iter().enumerate() {
939                    if i > 0 {
940                        self.write(", ");
941                    }
942                    self.format_expr(arg);
943                }
944                self.write(")");
945            }
946        }
947    }
948
949    fn format_string_template(&mut self, template: &StringTemplate) {
950        self.write("\"");
951        for part in &template.parts {
952            match part {
953                StringPart::Literal(s) => {
954                    for c in s.chars() {
955                        match c {
956                            '\\' => self.write("\\\\"),
957                            '"' => self.write("\\\""),
958                            '\n' => self.write("\\n"),
959                            '\r' => self.write("\\r"),
960                            '\t' => self.write("\\t"),
961                            '{' => self.write("{{"),
962                            '}' => self.write("}}"),
963                            _ => self.output.push(c),
964                        }
965                    }
966                }
967                StringPart::Interpolation(interp) => {
968                    self.write("{");
969                    self.format_interp_expr(interp);
970                    self.write("}");
971                }
972            }
973        }
974        self.write("\"");
975    }
976
977    fn format_interp_expr(&mut self, interp: &InterpExpr) {
978        match interp {
979            InterpExpr::Ident(ident) => {
980                self.write(&ident.name);
981            }
982            InterpExpr::FieldAccess { base, field, .. } => {
983                self.format_interp_expr(base);
984                self.write(".");
985                self.write(&field.name);
986            }
987            InterpExpr::TupleIndex { base, index, .. } => {
988                self.format_interp_expr(base);
989                self.write(".");
990                let _ = write!(self.output, "{}", index);
991            }
992        }
993    }
994
995    fn format_match_arm(&mut self, arm: &MatchArm) {
996        self.write_indent();
997        self.format_pattern(&arm.pattern);
998        self.write(" => ");
999        self.format_expr(&arm.body);
1000        self.write(",\n");
1001    }
1002
1003    fn format_literal(&mut self, lit: &Literal) {
1004        match lit {
1005            Literal::Int(n) => {
1006                let _ = write!(self.output, "{}", n);
1007            }
1008            Literal::Float(f) => {
1009                let _ = write!(self.output, "{}", f);
1010            }
1011            Literal::String(s) => {
1012                self.write("\"");
1013                for c in s.chars() {
1014                    match c {
1015                        '\\' => self.write("\\\\"),
1016                        '"' => self.write("\\\""),
1017                        '\n' => self.write("\\n"),
1018                        '\r' => self.write("\\r"),
1019                        '\t' => self.write("\\t"),
1020                        _ => self.output.push(c),
1021                    }
1022                }
1023                self.write("\"");
1024            }
1025            Literal::Bool(b) => {
1026                self.write(if *b { "true" } else { "false" });
1027            }
1028        }
1029    }
1030
1031    fn format_type(&mut self, ty: &TypeExpr) {
1032        match ty {
1033            TypeExpr::Int => self.write("Int"),
1034            TypeExpr::Float => self.write("Float"),
1035            TypeExpr::Bool => self.write("Bool"),
1036            TypeExpr::String => self.write("String"),
1037            TypeExpr::Unit => self.write("Unit"),
1038            TypeExpr::Error => self.write("Error"),
1039            TypeExpr::Named(name) => self.write(&name.name),
1040            TypeExpr::List(inner) => {
1041                self.write("List<");
1042                self.format_type(inner);
1043                self.write(">");
1044            }
1045            TypeExpr::Option(inner) => {
1046                self.write("Option<");
1047                self.format_type(inner);
1048                self.write(">");
1049            }
1050            TypeExpr::Result(ok, err) => {
1051                self.write("Result<");
1052                self.format_type(ok);
1053                self.write(", ");
1054                self.format_type(err);
1055                self.write(">");
1056            }
1057            TypeExpr::Tuple(types) => {
1058                self.write("(");
1059                for (i, t) in types.iter().enumerate() {
1060                    if i > 0 {
1061                        self.write(", ");
1062                    }
1063                    self.format_type(t);
1064                }
1065                self.write(")");
1066            }
1067            TypeExpr::Inferred(inner) => {
1068                self.write("Inferred<");
1069                self.format_type(inner);
1070                self.write(">");
1071            }
1072            TypeExpr::Fn(params, ret) => {
1073                self.write("Fn(");
1074                for (i, p) in params.iter().enumerate() {
1075                    if i > 0 {
1076                        self.write(", ");
1077                    }
1078                    self.format_type(p);
1079                }
1080                self.write(") -> ");
1081                self.format_type(ret);
1082            }
1083            TypeExpr::Map(key, value) => {
1084                self.write("Map<");
1085                self.format_type(key);
1086                self.write(", ");
1087                self.format_type(value);
1088                self.write(">");
1089            }
1090            TypeExpr::Agent(name) => {
1091                self.write("Agent<");
1092                self.write(&name.name);
1093                self.write(">");
1094            }
1095        }
1096    }
1097}
1098
1099#[cfg(test)]
1100mod tests {
1101    use super::*;
1102    use crate::{lex, parse};
1103    use std::sync::Arc;
1104
1105    fn format_source(source: &str) -> String {
1106        let lex_result = lex(source).unwrap();
1107        let source_arc: Arc<str> = Arc::from(source);
1108        let (program, errors) = parse(lex_result.tokens(), source_arc);
1109        assert!(errors.is_empty(), "Parse errors: {:?}", errors);
1110        let program = program.unwrap();
1111        format(&program)
1112    }
1113
1114    #[test]
1115    fn test_format_simple_agent() {
1116        let source = r#"agent Greeter{name:String on start{print("Hello");emit(0);}}run Greeter;"#;
1117        let formatted = format_source(source);
1118        assert!(formatted.contains("agent Greeter {"));
1119        assert!(formatted.contains("    name: String"));
1120        assert!(formatted.contains("    on start {"));
1121    }
1122
1123    #[test]
1124    fn test_format_binary_operators() {
1125        let source = r#"agent Test{on start{let x=1+2*3;emit(x);}}run Test;"#;
1126        let formatted = format_source(source);
1127        assert!(formatted.contains("1 + 2 * 3"));
1128    }
1129}