Skip to main content

cjc_ast/
lib.rs

1//! Abstract syntax tree definitions for CJC.
2//!
3//! Defines `Program`, `Stmt`, `Expr`, `Decl`, and all AST node variants
4//! produced by the parser. This is a leaf crate with no internal dependencies.
5
6pub mod inspect;
7pub mod metrics;
8pub mod node_utils;
9pub mod validate;
10pub mod visit;
11
12use std::fmt;
13
14/// Source span: byte offset range in source code.
15/// Duplicated from cjc-diag to avoid circular dependency.
16/// AST is a leaf crate with no dependencies.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub struct Span {
19    pub start: usize,
20    pub end: usize,
21}
22
23impl Span {
24    pub fn new(start: usize, end: usize) -> Self {
25        Self { start, end }
26    }
27
28    pub fn merge(self, other: Span) -> Span {
29        Span {
30            start: self.start.min(other.start),
31            end: self.end.max(other.end),
32        }
33    }
34
35    pub fn dummy() -> Self {
36        Self { start: 0, end: 0 }
37    }
38}
39
40// ── Visibility ──────────────────────────────────────────────────
41
42/// Visibility qualifier for declarations and fields.
43/// `pub` makes an item publicly visible; the default is private.
44/// NOTE: Enforcement is deferred — single-file programs treat all items as
45/// public regardless of annotation. This enum is stored but not checked yet.
46#[derive(Debug, Clone, Copy, PartialEq, Eq)]
47pub enum Visibility {
48    Public,
49    Private,
50}
51
52impl Default for Visibility {
53    fn default() -> Self {
54        Visibility::Private
55    }
56}
57
58// ── AST Node Types ──────────────────────────────────────────────
59
60/// Top-level program: a sequence of declarations.
61#[derive(Debug, Clone)]
62pub struct Program {
63    pub declarations: Vec<Decl>,
64}
65
66/// A declaration (top-level item).
67#[derive(Debug, Clone)]
68pub struct Decl {
69    pub kind: DeclKind,
70    pub span: Span,
71}
72
73#[derive(Debug, Clone)]
74pub enum DeclKind {
75    Struct(StructDecl),
76    Class(ClassDecl),
77    Record(RecordDecl),
78    Fn(FnDecl),
79    Trait(TraitDecl),
80    Impl(ImplDecl),
81    Enum(EnumDecl),
82    Let(LetStmt),
83    Import(ImportDecl),
84    /// Compile-time constant: `const NAME: Type = expr;`
85    Const(ConstDecl),
86    /// Top-level statement (expression statement, if, while, etc.)
87    Stmt(Stmt),
88}
89
90/// A compile-time constant declaration: `const NAME: Type = expr;`
91#[derive(Debug, Clone)]
92pub struct ConstDecl {
93    pub name: Ident,
94    pub ty: TypeExpr,
95    pub value: Box<Expr>,
96    pub span: Span,
97}
98
99// ── Struct & Class ──────────────────────────────────────────────
100
101#[derive(Debug, Clone)]
102pub struct StructDecl {
103    pub name: Ident,
104    pub type_params: Vec<TypeParam>,
105    pub fields: Vec<FieldDecl>,
106    pub vis: Visibility,
107}
108
109#[derive(Debug, Clone)]
110pub struct ClassDecl {
111    pub name: Ident,
112    pub type_params: Vec<TypeParam>,
113    pub fields: Vec<FieldDecl>,
114    pub vis: Visibility,
115}
116
117/// Record declaration: immutable value type.
118/// `record Point { x: f64, y: f64 }`
119/// Records are like structs but always immutable — field reassignment is a type error.
120#[derive(Debug, Clone)]
121pub struct RecordDecl {
122    pub name: Ident,
123    pub type_params: Vec<TypeParam>,
124    pub fields: Vec<FieldDecl>,
125    pub vis: Visibility,
126}
127
128// ── Enums ───────────────────────────────────────────────────
129
130#[derive(Debug, Clone)]
131pub struct EnumDecl {
132    pub name: Ident,
133    pub type_params: Vec<TypeParam>,
134    pub variants: Vec<VariantDecl>,
135}
136
137#[derive(Debug, Clone)]
138pub struct VariantDecl {
139    pub name: Ident,
140    /// Payload types for tuple-like variants. Empty for unit variants.
141    pub fields: Vec<TypeExpr>,
142    pub span: Span,
143}
144
145#[derive(Debug, Clone)]
146pub struct FieldDecl {
147    pub name: Ident,
148    pub ty: TypeExpr,
149    pub default: Option<Expr>,
150    pub vis: Visibility,
151    pub span: Span,
152}
153
154// ── Functions ───────────────────────────────────────────────────
155
156/// A decorator applied to a function declaration.
157///
158/// Syntax: `@decorator_name` or `@decorator_name(args...)`
159#[derive(Debug, Clone)]
160pub struct Decorator {
161    pub name: Ident,
162    pub args: Vec<Expr>,
163    pub span: Span,
164}
165
166#[derive(Debug, Clone)]
167pub struct FnDecl {
168    pub name: Ident,
169    pub type_params: Vec<TypeParam>,
170    pub params: Vec<Param>,
171    pub return_type: Option<TypeExpr>,
172    pub body: Block,
173    pub is_nogc: bool,
174    /// Effect annotation: `fn foo() -> i64 / pure { ... }`
175    /// None means "any effect" (backward compatible).
176    pub effect_annotation: Option<Vec<String>>,
177    /// Decorators applied to this function (e.g., `@log`, `@timed`).
178    pub decorators: Vec<Decorator>,
179    pub vis: Visibility,
180}
181
182#[derive(Debug, Clone)]
183pub struct FnSig {
184    pub name: Ident,
185    pub type_params: Vec<TypeParam>,
186    pub params: Vec<Param>,
187    pub return_type: Option<TypeExpr>,
188    pub span: Span,
189}
190
191#[derive(Debug, Clone)]
192pub struct Param {
193    pub name: Ident,
194    pub ty: TypeExpr,
195    /// Optional default value expression (e.g., `fn f(x: f64 = 1.0)`).
196    pub default: Option<Expr>,
197    /// Variadic parameter: `fn f(...args: f64)` collects remaining args into an array.
198    /// Only the last parameter may be variadic.
199    pub is_variadic: bool,
200    pub span: Span,
201}
202
203// ── Traits & Impls ──────────────────────────────────────────────
204
205#[derive(Debug, Clone)]
206pub struct TraitDecl {
207    pub name: Ident,
208    pub type_params: Vec<TypeParam>,
209    pub super_traits: Vec<TypeExpr>,
210    pub methods: Vec<FnSig>,
211}
212
213#[derive(Debug, Clone)]
214pub struct ImplDecl {
215    pub type_params: Vec<TypeParam>,
216    pub target: TypeExpr,
217    pub trait_ref: Option<TypeExpr>,
218    pub methods: Vec<FnDecl>,
219    pub span: Span,
220}
221
222// ── Import ──────────────────────────────────────────────────────
223
224#[derive(Debug, Clone)]
225pub struct ImportDecl {
226    pub path: Vec<Ident>,
227    pub alias: Option<Ident>,
228}
229
230// ── Type Expressions ────────────────────────────────────────────
231
232#[derive(Debug, Clone)]
233pub struct TypeExpr {
234    pub kind: TypeExprKind,
235    pub span: Span,
236}
237
238#[derive(Debug, Clone)]
239pub enum TypeExprKind {
240    /// Named type: `f64`, `Tensor<f32>`, etc.
241    Named {
242        name: Ident,
243        args: Vec<TypeArg>,
244    },
245    /// Array type: `[T; N]`
246    Array {
247        elem: Box<TypeExpr>,
248        size: Box<Expr>,
249    },
250    /// Tuple type: `(T, U)`
251    Tuple(Vec<TypeExpr>),
252    /// Function type: `fn(T, U) -> V`
253    Fn {
254        params: Vec<TypeExpr>,
255        ret: Box<TypeExpr>,
256    },
257    /// Shape literal in type position: `[M, N]`
258    ShapeLit(Vec<ShapeDim>),
259}
260
261/// A type argument can be a type or an expression (for shape params).
262#[derive(Debug, Clone)]
263pub enum TypeArg {
264    Type(TypeExpr),
265    Expr(Expr),
266    Shape(Vec<ShapeDim>),
267}
268
269/// A shape dimension: either a symbolic name or a literal integer.
270#[derive(Debug, Clone)]
271pub enum ShapeDim {
272    Name(Ident),
273    Lit(i64),
274}
275
276#[derive(Debug, Clone)]
277pub struct TypeParam {
278    pub name: Ident,
279    pub bounds: Vec<TypeExpr>,
280    pub span: Span,
281}
282
283// ── Statements ──────────────────────────────────────────────────
284
285#[derive(Debug, Clone)]
286pub struct Block {
287    pub stmts: Vec<Stmt>,
288    pub expr: Option<Box<Expr>>,
289    pub span: Span,
290}
291
292#[derive(Debug, Clone)]
293pub struct Stmt {
294    pub kind: StmtKind,
295    pub span: Span,
296}
297
298#[derive(Debug, Clone)]
299pub enum StmtKind {
300    Let(LetStmt),
301    Expr(Expr),
302    Return(Option<Expr>),
303    Break,
304    Continue,
305    If(IfStmt),
306    While(WhileStmt),
307    For(ForStmt),
308    NoGcBlock(Block),
309}
310
311#[derive(Debug, Clone)]
312pub struct LetStmt {
313    pub name: Ident,
314    pub mutable: bool,
315    pub ty: Option<TypeExpr>,
316    pub init: Box<Expr>,
317}
318
319#[derive(Debug, Clone)]
320pub struct IfStmt {
321    pub condition: Expr,
322    pub then_block: Block,
323    pub else_branch: Option<ElseBranch>,
324}
325
326#[derive(Debug, Clone)]
327pub enum ElseBranch {
328    ElseIf(Box<IfStmt>),
329    Else(Block),
330}
331
332#[derive(Debug, Clone)]
333pub struct WhileStmt {
334    pub condition: Expr,
335    pub body: Block,
336}
337
338#[derive(Debug, Clone)]
339pub struct ForStmt {
340    pub ident: Ident,
341    pub iter: ForIter,
342    pub body: Block,
343}
344
345/// The iteration source for a `for` loop.
346#[derive(Debug, Clone)]
347pub enum ForIter {
348    /// Range form: `start..end` (exclusive end)
349    Range { start: Box<Expr>, end: Box<Expr> },
350    /// Expression form: `for x in expr` (array/tensor iteration)
351    Expr(Box<Expr>),
352}
353
354// ── Expressions ─────────────────────────────────────────────────
355
356#[derive(Debug, Clone)]
357pub struct Expr {
358    pub kind: ExprKind,
359    pub span: Span,
360}
361
362#[derive(Debug, Clone)]
363pub enum ExprKind {
364    /// Integer literal: `42`
365    IntLit(i64),
366    /// Float literal: `3.14`
367    FloatLit(f64),
368    /// String literal: `"hello"`
369    StringLit(String),
370    /// Byte string literal: `b"hello"` — produces ByteSlice
371    ByteStringLit(Vec<u8>),
372    /// Byte char literal: `b'A'` — produces u8
373    ByteCharLit(u8),
374    /// Raw string literal: `r"hello\n"` — produces String (no escape processing)
375    RawStringLit(String),
376    /// Raw byte string literal: `br"hello\n"` — produces ByteSlice (no escape processing)
377    RawByteStringLit(Vec<u8>),
378    /// Format string literal: `f"hello {name}!"` — desugared into concat at parse time.
379    /// Stored as alternating literal segments and expression strings to format.
380    /// Each segment: `(literal_text, Option<expr>)` — literal then optional interp.
381    FStringLit(Vec<(String, Option<Box<Expr>>)>),
382    /// Regex literal: `/pattern/flags` — produces Regex
383    RegexLit { pattern: String, flags: String },
384    /// Tensor literal: `[| 1.0, 2.0; 3.0, 4.0 |]` — produces Tensor
385    /// `rows` contains each row as a Vec of expressions.
386    /// A 1-D tensor has a single row. `;` separates rows for 2-D.
387    TensorLit { rows: Vec<Vec<Expr>> },
388    /// Bool literal: `true`, `false`
389    BoolLit(bool),
390    /// Identifier: `x`, `foo`
391    Ident(Ident),
392    /// Binary operation: `a + b`
393    Binary {
394        op: BinOp,
395        left: Box<Expr>,
396        right: Box<Expr>,
397    },
398    /// Unary operation: `-x`, `!b`
399    Unary {
400        op: UnaryOp,
401        operand: Box<Expr>,
402    },
403    /// Function/method call: `foo(a, b)`
404    Call {
405        callee: Box<Expr>,
406        args: Vec<CallArg>,
407    },
408    /// Field access / method access: `x.foo`
409    Field {
410        object: Box<Expr>,
411        name: Ident,
412    },
413    /// Index: `a[i]`
414    Index {
415        object: Box<Expr>,
416        index: Box<Expr>,
417    },
418    /// Multi-index: `a[i, j]`
419    MultiIndex {
420        object: Box<Expr>,
421        indices: Vec<Expr>,
422    },
423    /// Assignment: `x = expr`
424    Assign {
425        target: Box<Expr>,
426        value: Box<Expr>,
427    },
428    /// Compound assignment: `x += e`, `x -= e`, etc.
429    /// Desugars to `x = x op e` during evaluation.
430    CompoundAssign {
431        op: BinOp,
432        target: Box<Expr>,
433        value: Box<Expr>,
434    },
435    /// If expression: `if cond { a } else { b }` used as a value
436    IfExpr {
437        condition: Box<Expr>,
438        then_block: Block,
439        else_branch: Option<ElseBranch>,
440    },
441    /// Pipe: `a |> f(b)`
442    Pipe {
443        left: Box<Expr>,
444        right: Box<Expr>,
445    },
446    /// Block expression: `{ stmts; expr }`
447    Block(Block),
448    /// Struct literal: `Foo { x: 1, y: 2 }`
449    StructLit {
450        name: Ident,
451        fields: Vec<FieldInit>,
452    },
453    /// Array literal: `[1, 2, 3]`
454    ArrayLit(Vec<Expr>),
455    /// Column reference in data DSL: `col("name")`
456    Col(String),
457    /// Lambda expression: `|x, y| x + y`
458    Lambda {
459        params: Vec<Param>,
460        body: Box<Expr>,
461    },
462    /// Match expression: `match expr { pat => expr, ... }`
463    Match {
464        scrutinee: Box<Expr>,
465        arms: Vec<MatchArm>,
466    },
467    /// Tuple literal: `(a, b, c)`
468    TupleLit(Vec<Expr>),
469    /// Try operator: `expr?` — desugars to match on Result
470    Try(Box<Expr>),
471    /// Enum variant constructor: `Some(42)` or `None`
472    VariantLit {
473        enum_name: Option<Ident>,
474        variant: Ident,
475        fields: Vec<Expr>,
476    },
477}
478
479// ── Match Arms & Patterns ───────────────────────────────────────
480
481/// A single arm of a match expression: `pattern => body`
482#[derive(Debug, Clone)]
483pub struct MatchArm {
484    pub pattern: Pattern,
485    pub body: Expr,
486    pub span: Span,
487}
488
489/// A pattern for use in match arms.
490#[derive(Debug, Clone)]
491pub struct Pattern {
492    pub kind: PatternKind,
493    pub span: Span,
494}
495
496#[derive(Debug, Clone)]
497pub enum PatternKind {
498    /// Wildcard pattern: `_`
499    Wildcard,
500    /// Binding pattern: `x` (binds the matched value to `x`)
501    Binding(Ident),
502    /// Literal pattern: `42`, `3.14`, `true`, `"hello"`
503    LitInt(i64),
504    LitFloat(f64),
505    LitBool(bool),
506    LitString(String),
507    /// Tuple destructuring: `(a, b, c)`
508    Tuple(Vec<Pattern>),
509    /// Struct destructuring: `Point { x, y }` or `Point { x: px, y: py }`
510    Struct {
511        name: Ident,
512        fields: Vec<PatternField>,
513    },
514    /// Enum variant pattern: `Some(x)`, `None`, `Ok(v)`, `Err(e)`
515    Variant {
516        /// Optional enum name qualification (not needed for prelude enums)
517        enum_name: Option<Ident>,
518        variant: Ident,
519        fields: Vec<Pattern>,
520    },
521}
522
523/// A field pattern inside a struct pattern: `x` or `x: pat`
524#[derive(Debug, Clone)]
525pub struct PatternField {
526    pub name: Ident,
527    pub pattern: Option<Pattern>,
528    pub span: Span,
529}
530
531#[derive(Debug, Clone)]
532pub struct CallArg {
533    pub name: Option<Ident>,
534    pub value: Expr,
535    pub span: Span,
536}
537
538#[derive(Debug, Clone)]
539pub struct FieldInit {
540    pub name: Ident,
541    pub value: Expr,
542    pub span: Span,
543}
544
545// ── Operators ───────────────────────────────────────────────────
546
547#[derive(Debug, Clone, Copy, PartialEq, Eq)]
548pub enum BinOp {
549    Add,
550    Sub,
551    Mul,
552    Div,
553    Mod,
554    Pow,       // **
555    Eq,
556    Ne,
557    Lt,
558    Gt,
559    Le,
560    Ge,
561    And,
562    Or,
563    Match,     // ~=  (regex binding)
564    NotMatch,  // !~  (negative regex binding)
565    // Bitwise operators
566    BitAnd,    // &
567    BitOr,     // |
568    BitXor,    // ^
569    Shl,       // <<
570    Shr,       // >>
571}
572
573impl fmt::Display for BinOp {
574    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
575        match self {
576            BinOp::Add => write!(f, "+"),
577            BinOp::Sub => write!(f, "-"),
578            BinOp::Mul => write!(f, "*"),
579            BinOp::Div => write!(f, "/"),
580            BinOp::Mod => write!(f, "%"),
581            BinOp::Pow => write!(f, "**"),
582            BinOp::Eq => write!(f, "=="),
583            BinOp::Ne => write!(f, "!="),
584            BinOp::Lt => write!(f, "<"),
585            BinOp::Gt => write!(f, ">"),
586            BinOp::Le => write!(f, "<="),
587            BinOp::Ge => write!(f, ">="),
588            BinOp::And => write!(f, "&&"),
589            BinOp::Or => write!(f, "||"),
590            BinOp::Match => write!(f, "~="),
591            BinOp::NotMatch => write!(f, "!~"),
592            BinOp::BitAnd => write!(f, "&"),
593            BinOp::BitOr => write!(f, "|"),
594            BinOp::BitXor => write!(f, "^"),
595            BinOp::Shl => write!(f, "<<"),
596            BinOp::Shr => write!(f, ">>"),
597        }
598    }
599}
600
601#[derive(Debug, Clone, Copy, PartialEq, Eq)]
602pub enum UnaryOp {
603    Neg,
604    Not,
605    BitNot,  // ~ (bitwise NOT)
606}
607
608impl fmt::Display for UnaryOp {
609    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
610        match self {
611            UnaryOp::Neg => write!(f, "-"),
612            UnaryOp::Not => write!(f, "!"),
613            UnaryOp::BitNot => write!(f, "~"),
614        }
615    }
616}
617
618// ── Identifier ──────────────────────────────────────────────────
619
620#[derive(Debug, Clone, PartialEq, Eq, Hash)]
621pub struct Ident {
622    pub name: String,
623    pub span: Span,
624}
625
626impl Ident {
627    pub fn new(name: impl Into<String>, span: Span) -> Self {
628        Self {
629            name: name.into(),
630            span,
631        }
632    }
633
634    pub fn dummy(name: impl Into<String>) -> Self {
635        Self {
636            name: name.into(),
637            span: Span::dummy(),
638        }
639    }
640}
641
642impl fmt::Display for Ident {
643    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
644        write!(f, "{}", self.name)
645    }
646}
647
648// ── Pretty Printer ──────────────────────────────────────────────
649
650pub struct PrettyPrinter {
651    indent: usize,
652    output: String,
653}
654
655impl PrettyPrinter {
656    pub fn new() -> Self {
657        Self {
658            indent: 0,
659            output: String::new(),
660        }
661    }
662
663    pub fn print_program(mut self, program: &Program) -> String {
664        for decl in &program.declarations {
665            self.print_decl(decl);
666            self.output.push('\n');
667        }
668        self.output
669    }
670
671    fn indent_str(&self) -> String {
672        "    ".repeat(self.indent)
673    }
674
675    fn print_decl(&mut self, decl: &Decl) {
676        match &decl.kind {
677            DeclKind::Struct(s) => self.print_struct(s),
678            DeclKind::Class(c) => self.print_class(c),
679            DeclKind::Record(r) => self.print_record(r),
680            DeclKind::Fn(f) => self.print_fn(f),
681            DeclKind::Trait(t) => self.print_trait(t),
682            DeclKind::Impl(i) => self.print_impl(i),
683            DeclKind::Enum(e) => self.print_enum(e),
684            DeclKind::Let(l) => {
685                self.output.push_str(&self.indent_str());
686                self.print_let(l);
687            }
688            DeclKind::Import(i) => self.print_import(i),
689            DeclKind::Const(c) => {
690                self.output.push_str(&self.indent_str());
691                self.output.push_str("const ");
692                self.output.push_str(&c.name.name);
693                self.output.push_str(": ");
694                self.print_type_expr(&c.ty);
695                self.output.push_str(" = ");
696                self.print_expr(&c.value);
697                self.output.push(';');
698            }
699            DeclKind::Stmt(s) => {
700                self.output.push_str(&self.indent_str());
701                self.print_stmt(s);
702            }
703        }
704    }
705
706    fn print_struct(&mut self, s: &StructDecl) {
707        self.output.push_str(&self.indent_str());
708        self.output.push_str(&format!("struct {}", s.name));
709        self.print_type_params(&s.type_params);
710        self.output.push_str(" {\n");
711        self.indent += 1;
712        for field in &s.fields {
713            self.output
714                .push_str(&format!("{}{}: ", self.indent_str(), field.name));
715            self.print_type_expr(&field.ty);
716            self.output.push('\n');
717        }
718        self.indent -= 1;
719        self.output.push_str(&format!("{}}}", self.indent_str()));
720    }
721
722    fn print_class(&mut self, c: &ClassDecl) {
723        self.output.push_str(&self.indent_str());
724        self.output.push_str(&format!("class {}", c.name));
725        self.print_type_params(&c.type_params);
726        self.output.push_str(" {\n");
727        self.indent += 1;
728        for field in &c.fields {
729            self.output
730                .push_str(&format!("{}{}: ", self.indent_str(), field.name));
731            self.print_type_expr(&field.ty);
732            self.output.push('\n');
733        }
734        self.indent -= 1;
735        self.output.push_str(&format!("{}}}", self.indent_str()));
736    }
737
738    fn print_record(&mut self, r: &RecordDecl) {
739        self.output.push_str(&self.indent_str());
740        self.output.push_str(&format!("record {}", r.name));
741        self.print_type_params(&r.type_params);
742        self.output.push_str(" {\n");
743        self.indent += 1;
744        for field in &r.fields {
745            self.output
746                .push_str(&format!("{}{}: ", self.indent_str(), field.name));
747            self.print_type_expr(&field.ty);
748            self.output.push('\n');
749        }
750        self.indent -= 1;
751        self.output.push_str(&format!("{}}}", self.indent_str()));
752    }
753
754    fn print_fn(&mut self, f: &FnDecl) {
755        self.output.push_str(&self.indent_str());
756        if f.is_nogc {
757            self.output.push_str("nogc ");
758        }
759        self.output.push_str(&format!("fn {}", f.name));
760        self.print_type_params(&f.type_params);
761        self.output.push('(');
762        for (i, param) in f.params.iter().enumerate() {
763            if i > 0 {
764                self.output.push_str(", ");
765            }
766            if param.is_variadic {
767                self.output.push_str("...");
768            }
769            self.output.push_str(&format!("{}: ", param.name));
770            self.print_type_expr(&param.ty);
771        }
772        self.output.push(')');
773        if let Some(ref ret) = f.return_type {
774            self.output.push_str(" -> ");
775            self.print_type_expr(ret);
776        }
777        self.output.push(' ');
778        self.print_block(&f.body);
779    }
780
781    fn print_trait(&mut self, t: &TraitDecl) {
782        self.output.push_str(&self.indent_str());
783        self.output.push_str(&format!("trait {}", t.name));
784        self.print_type_params(&t.type_params);
785        if !t.super_traits.is_empty() {
786            self.output.push_str(": ");
787            for (i, st) in t.super_traits.iter().enumerate() {
788                if i > 0 {
789                    self.output.push_str(" + ");
790                }
791                self.print_type_expr(st);
792            }
793        }
794        self.output.push_str(" {\n");
795        self.indent += 1;
796        for method in &t.methods {
797            self.output.push_str(&self.indent_str());
798            self.output.push_str(&format!("fn {}", method.name));
799            self.print_type_params(&method.type_params);
800            self.output.push('(');
801            for (i, p) in method.params.iter().enumerate() {
802                if i > 0 {
803                    self.output.push_str(", ");
804                }
805                self.output.push_str(&format!("{}: ", p.name));
806                self.print_type_expr(&p.ty);
807            }
808            self.output.push(')');
809            if let Some(ref ret) = method.return_type {
810                self.output.push_str(" -> ");
811                self.print_type_expr(ret);
812            }
813            self.output.push_str(";\n");
814        }
815        self.indent -= 1;
816        self.output.push_str(&format!("{}}}", self.indent_str()));
817    }
818
819    fn print_impl(&mut self, i: &ImplDecl) {
820        self.output.push_str(&self.indent_str());
821        self.output.push_str("impl");
822        self.print_type_params(&i.type_params);
823        self.output.push(' ');
824        self.print_type_expr(&i.target);
825        if let Some(ref tr) = i.trait_ref {
826            self.output.push_str(" : ");
827            self.print_type_expr(tr);
828        }
829        self.output.push_str(" {\n");
830        self.indent += 1;
831        for method in &i.methods {
832            self.print_fn(method);
833            self.output.push('\n');
834        }
835        self.indent -= 1;
836        self.output.push_str(&format!("{}}}", self.indent_str()));
837    }
838
839    fn print_import(&mut self, i: &ImportDecl) {
840        self.output.push_str(&self.indent_str());
841        self.output.push_str("import ");
842        let path: Vec<&str> = i.path.iter().map(|id| id.name.as_str()).collect();
843        self.output.push_str(&path.join("."));
844        if let Some(ref alias) = i.alias {
845            self.output.push_str(&format!(" as {}", alias));
846        }
847    }
848
849    fn print_enum(&mut self, e: &EnumDecl) {
850        self.output.push_str(&self.indent_str());
851        self.output.push_str(&format!("enum {}", e.name));
852        self.print_type_params(&e.type_params);
853        self.output.push_str(" {\n");
854        self.indent += 1;
855        for variant in &e.variants {
856            self.output.push_str(&self.indent_str());
857            self.output.push_str(&variant.name.name);
858            if !variant.fields.is_empty() {
859                self.output.push('(');
860                for (i, f) in variant.fields.iter().enumerate() {
861                    if i > 0 {
862                        self.output.push_str(", ");
863                    }
864                    self.print_type_expr(f);
865                }
866                self.output.push(')');
867            }
868            self.output.push_str(",\n");
869        }
870        self.indent -= 1;
871        self.output.push_str(&format!("{}}}", self.indent_str()));
872    }
873
874    fn print_type_params(&mut self, params: &[TypeParam]) {
875        if params.is_empty() {
876            return;
877        }
878        self.output.push('<');
879        for (i, param) in params.iter().enumerate() {
880            if i > 0 {
881                self.output.push_str(", ");
882            }
883            self.output.push_str(&param.name.name);
884            if !param.bounds.is_empty() {
885                self.output.push_str(": ");
886                for (j, bound) in param.bounds.iter().enumerate() {
887                    if j > 0 {
888                        self.output.push_str(" + ");
889                    }
890                    self.print_type_expr(bound);
891                }
892            }
893        }
894        self.output.push('>');
895    }
896
897    fn print_type_expr(&mut self, ty: &TypeExpr) {
898        match &ty.kind {
899            TypeExprKind::Named { name, args } => {
900                self.output.push_str(&name.name);
901                if !args.is_empty() {
902                    self.output.push('<');
903                    for (i, arg) in args.iter().enumerate() {
904                        if i > 0 {
905                            self.output.push_str(", ");
906                        }
907                        match arg {
908                            TypeArg::Type(t) => self.print_type_expr(t),
909                            TypeArg::Expr(e) => self.print_expr(e),
910                            TypeArg::Shape(dims) => self.print_shape(dims),
911                        }
912                    }
913                    self.output.push('>');
914                }
915            }
916            TypeExprKind::Array { elem, size } => {
917                self.output.push('[');
918                self.print_type_expr(elem);
919                self.output.push_str("; ");
920                self.print_expr(size);
921                self.output.push(']');
922            }
923            TypeExprKind::Tuple(elems) => {
924                self.output.push('(');
925                for (i, elem) in elems.iter().enumerate() {
926                    if i > 0 {
927                        self.output.push_str(", ");
928                    }
929                    self.print_type_expr(elem);
930                }
931                self.output.push(')');
932            }
933            TypeExprKind::Fn { params, ret } => {
934                self.output.push_str("fn(");
935                for (i, p) in params.iter().enumerate() {
936                    if i > 0 {
937                        self.output.push_str(", ");
938                    }
939                    self.print_type_expr(p);
940                }
941                self.output.push_str(") -> ");
942                self.print_type_expr(ret);
943            }
944            TypeExprKind::ShapeLit(dims) => {
945                self.print_shape(dims);
946            }
947        }
948    }
949
950    fn print_shape(&mut self, dims: &[ShapeDim]) {
951        self.output.push('[');
952        for (i, dim) in dims.iter().enumerate() {
953            if i > 0 {
954                self.output.push_str(", ");
955            }
956            match dim {
957                ShapeDim::Name(n) => self.output.push_str(&n.name),
958                ShapeDim::Lit(v) => self.output.push_str(&v.to_string()),
959            }
960        }
961        self.output.push(']');
962    }
963
964    fn print_block(&mut self, block: &Block) {
965        self.output.push_str("{\n");
966        self.indent += 1;
967        for stmt in &block.stmts {
968            self.print_stmt(stmt);
969        }
970        if let Some(ref expr) = block.expr {
971            self.output.push_str(&self.indent_str());
972            self.print_expr(expr);
973            self.output.push('\n');
974        }
975        self.indent -= 1;
976        self.output.push_str(&format!("{}}}", self.indent_str()));
977    }
978
979    fn print_stmt(&mut self, stmt: &Stmt) {
980        match &stmt.kind {
981            StmtKind::Let(l) => {
982                self.output.push_str(&self.indent_str());
983                self.print_let(l);
984            }
985            StmtKind::Expr(e) => {
986                self.output.push_str(&self.indent_str());
987                self.print_expr(e);
988                self.output.push_str(";\n");
989            }
990            StmtKind::Return(e) => {
991                self.output.push_str(&self.indent_str());
992                self.output.push_str("return");
993                if let Some(expr) = e {
994                    self.output.push(' ');
995                    self.print_expr(expr);
996                }
997                self.output.push_str(";\n");
998            }
999            StmtKind::Break => {
1000                self.output.push_str(&self.indent_str());
1001                self.output.push_str("break;\n");
1002            }
1003            StmtKind::Continue => {
1004                self.output.push_str(&self.indent_str());
1005                self.output.push_str("continue;\n");
1006            }
1007            StmtKind::If(if_stmt) => {
1008                self.output.push_str(&self.indent_str());
1009                self.print_if(if_stmt);
1010                self.output.push('\n');
1011            }
1012            StmtKind::While(w) => {
1013                self.output.push_str(&self.indent_str());
1014                self.output.push_str("while ");
1015                self.print_expr(&w.condition);
1016                self.output.push(' ');
1017                self.print_block(&w.body);
1018                self.output.push('\n');
1019            }
1020            StmtKind::For(f) => {
1021                self.output.push_str(&self.indent_str());
1022                self.output.push_str("for ");
1023                self.output.push_str(&f.ident.name);
1024                self.output.push_str(" in ");
1025                match &f.iter {
1026                    ForIter::Range { start, end } => {
1027                        self.print_expr(start);
1028                        self.output.push_str("..");
1029                        self.print_expr(end);
1030                    }
1031                    ForIter::Expr(expr) => {
1032                        self.print_expr(expr);
1033                    }
1034                }
1035                self.output.push(' ');
1036                self.print_block(&f.body);
1037                self.output.push('\n');
1038            }
1039            StmtKind::NoGcBlock(block) => {
1040                self.output.push_str(&self.indent_str());
1041                self.output.push_str("nogc ");
1042                self.print_block(block);
1043                self.output.push('\n');
1044            }
1045        }
1046    }
1047
1048    fn print_let(&mut self, l: &LetStmt) {
1049        self.output.push_str("let ");
1050        if l.mutable {
1051            self.output.push_str("mut ");
1052        }
1053        self.output.push_str(&l.name.name);
1054        if let Some(ref ty) = l.ty {
1055            self.output.push_str(": ");
1056            self.print_type_expr(ty);
1057        }
1058        self.output.push_str(" = ");
1059        self.print_expr(&l.init);
1060        self.output.push_str(";\n");
1061    }
1062
1063    fn print_if(&mut self, if_stmt: &IfStmt) {
1064        self.output.push_str("if ");
1065        self.print_expr(&if_stmt.condition);
1066        self.output.push(' ');
1067        self.print_block(&if_stmt.then_block);
1068        if let Some(ref else_branch) = if_stmt.else_branch {
1069            self.output.push_str(" else ");
1070            match else_branch {
1071                ElseBranch::ElseIf(elif) => self.print_if(elif),
1072                ElseBranch::Else(block) => self.print_block(block),
1073            }
1074        }
1075    }
1076
1077    fn print_expr(&mut self, expr: &Expr) {
1078        match &expr.kind {
1079            ExprKind::IntLit(v) => self.output.push_str(&v.to_string()),
1080            ExprKind::FloatLit(v) => {
1081                let s = v.to_string();
1082                self.output.push_str(&s);
1083                if !s.contains('.') {
1084                    self.output.push_str(".0");
1085                }
1086            }
1087            ExprKind::StringLit(s) => {
1088                self.output.push('"');
1089                self.output.push_str(s);
1090                self.output.push('"');
1091            }
1092            ExprKind::ByteStringLit(bytes) => {
1093                self.output.push_str("b\"");
1094                for &b in bytes {
1095                    if b.is_ascii_graphic() || b == b' ' {
1096                        self.output.push(b as char);
1097                    } else {
1098                        self.output.push_str(&format!("\\x{:02x}", b));
1099                    }
1100                }
1101                self.output.push('"');
1102            }
1103            ExprKind::ByteCharLit(b) => {
1104                self.output.push_str(&format!("b'\\x{:02x}'", b));
1105            }
1106            ExprKind::RawStringLit(s) => {
1107                self.output.push_str("r\"");
1108                self.output.push_str(s);
1109                self.output.push('"');
1110            }
1111            ExprKind::RawByteStringLit(bytes) => {
1112                self.output.push_str("br\"");
1113                for &b in bytes {
1114                    self.output.push(b as char);
1115                }
1116                self.output.push('"');
1117            }
1118            ExprKind::FStringLit(segments) => {
1119                // Pretty-print as f"..."
1120                self.output.push_str("f\"");
1121                for (lit, interp) in segments {
1122                    self.output.push_str(&lit.replace('"', "\\\""));
1123                    if let Some(expr) = interp {
1124                        self.output.push('{');
1125                        self.print_expr(expr);
1126                        self.output.push('}');
1127                    }
1128                }
1129                self.output.push('"');
1130            }
1131            ExprKind::RegexLit { pattern, flags } => {
1132                self.output.push('/');
1133                self.output.push_str(pattern);
1134                self.output.push('/');
1135                self.output.push_str(flags);
1136            }
1137            ExprKind::TensorLit { rows } => {
1138                self.output.push_str("[| ");
1139                for (ri, row) in rows.iter().enumerate() {
1140                    if ri > 0 {
1141                        self.output.push_str("; ");
1142                    }
1143                    for (ci, expr) in row.iter().enumerate() {
1144                        if ci > 0 {
1145                            self.output.push_str(", ");
1146                        }
1147                        self.print_expr(expr);
1148                    }
1149                }
1150                self.output.push_str(" |]");
1151            }
1152            ExprKind::BoolLit(b) => self.output.push_str(if *b { "true" } else { "false" }),
1153            ExprKind::Ident(id) => self.output.push_str(&id.name),
1154            ExprKind::Binary { op, left, right } => {
1155                self.output.push('(');
1156                self.print_expr(left);
1157                self.output.push_str(&format!(" {} ", op));
1158                self.print_expr(right);
1159                self.output.push(')');
1160            }
1161            ExprKind::Unary { op, operand } => {
1162                self.output.push_str(&format!("{}", op));
1163                self.print_expr(operand);
1164            }
1165            ExprKind::Call { callee, args } => {
1166                self.print_expr(callee);
1167                self.output.push('(');
1168                for (i, arg) in args.iter().enumerate() {
1169                    if i > 0 {
1170                        self.output.push_str(", ");
1171                    }
1172                    if let Some(ref name) = arg.name {
1173                        self.output.push_str(&format!("{}: ", name));
1174                    }
1175                    self.print_expr(&arg.value);
1176                }
1177                self.output.push(')');
1178            }
1179            ExprKind::Field { object, name } => {
1180                self.print_expr(object);
1181                self.output.push('.');
1182                self.output.push_str(&name.name);
1183            }
1184            ExprKind::Index { object, index } => {
1185                self.print_expr(object);
1186                self.output.push('[');
1187                self.print_expr(index);
1188                self.output.push(']');
1189            }
1190            ExprKind::MultiIndex { object, indices } => {
1191                self.print_expr(object);
1192                self.output.push('[');
1193                for (i, idx) in indices.iter().enumerate() {
1194                    if i > 0 {
1195                        self.output.push_str(", ");
1196                    }
1197                    self.print_expr(idx);
1198                }
1199                self.output.push(']');
1200            }
1201            ExprKind::Assign { target, value } => {
1202                self.print_expr(target);
1203                self.output.push_str(" = ");
1204                self.print_expr(value);
1205            }
1206            ExprKind::CompoundAssign { op, target, value } => {
1207                self.print_expr(target);
1208                self.output.push_str(&format!(" {}= ", op));
1209                self.print_expr(value);
1210            }
1211            ExprKind::IfExpr { condition, then_block, else_branch } => {
1212                self.output.push_str("if ");
1213                self.print_expr(condition);
1214                self.output.push_str(" ");
1215                self.print_block(then_block);
1216                if let Some(eb) = else_branch {
1217                    self.output.push_str(" else ");
1218                    match eb {
1219                        ElseBranch::ElseIf(elif) => {
1220                            // Print as if statement
1221                            self.output.push_str("if ...");
1222                        }
1223                        ElseBranch::Else(block) => {
1224                            self.print_block(block);
1225                        }
1226                    }
1227                }
1228            }
1229            ExprKind::Pipe { left, right } => {
1230                self.print_expr(left);
1231                self.output.push_str(" |> ");
1232                self.print_expr(right);
1233            }
1234            ExprKind::Block(block) => {
1235                self.print_block(block);
1236            }
1237            ExprKind::StructLit { name, fields } => {
1238                self.output.push_str(&format!("{} {{ ", name));
1239                for (i, field) in fields.iter().enumerate() {
1240                    if i > 0 {
1241                        self.output.push_str(", ");
1242                    }
1243                    self.output.push_str(&format!("{}: ", field.name));
1244                    self.print_expr(&field.value);
1245                }
1246                self.output.push_str(" }");
1247            }
1248            ExprKind::ArrayLit(elems) => {
1249                self.output.push('[');
1250                for (i, elem) in elems.iter().enumerate() {
1251                    if i > 0 {
1252                        self.output.push_str(", ");
1253                    }
1254                    self.print_expr(elem);
1255                }
1256                self.output.push(']');
1257            }
1258            ExprKind::Col(name) => {
1259                self.output.push_str(&format!("col(\"{}\")", name));
1260            }
1261            ExprKind::Lambda { params, body } => {
1262                self.output.push('|');
1263                for (i, p) in params.iter().enumerate() {
1264                    if i > 0 {
1265                        self.output.push_str(", ");
1266                    }
1267                    self.output.push_str(&format!("{}: ", p.name));
1268                    self.print_type_expr(&p.ty);
1269                }
1270                self.output.push_str("| ");
1271                self.print_expr(body);
1272            }
1273            ExprKind::Match { scrutinee, arms } => {
1274                self.output.push_str("match ");
1275                self.print_expr(scrutinee);
1276                self.output.push_str(" {\n");
1277                self.indent += 1;
1278                for arm in arms {
1279                    self.output.push_str(&self.indent_str());
1280                    self.print_pattern(&arm.pattern);
1281                    self.output.push_str(" => ");
1282                    self.print_expr(&arm.body);
1283                    self.output.push_str(",\n");
1284                }
1285                self.indent -= 1;
1286                self.output.push_str(&format!("{}}}", self.indent_str()));
1287            }
1288            ExprKind::TupleLit(elems) => {
1289                self.output.push('(');
1290                for (i, elem) in elems.iter().enumerate() {
1291                    if i > 0 {
1292                        self.output.push_str(", ");
1293                    }
1294                    self.print_expr(elem);
1295                }
1296                self.output.push(')');
1297            }
1298            ExprKind::Try(inner) => {
1299                self.print_expr(inner);
1300                self.output.push('?');
1301            }
1302            ExprKind::VariantLit {
1303                enum_name,
1304                variant,
1305                fields,
1306            } => {
1307                if let Some(ref en) = enum_name {
1308                    self.output.push_str(&en.name);
1309                    self.output.push_str("::");
1310                }
1311                self.output.push_str(&variant.name);
1312                if !fields.is_empty() {
1313                    self.output.push('(');
1314                    for (i, f) in fields.iter().enumerate() {
1315                        if i > 0 {
1316                            self.output.push_str(", ");
1317                        }
1318                        self.print_expr(f);
1319                    }
1320                    self.output.push(')');
1321                }
1322            }
1323        }
1324    }
1325
1326    fn print_pattern(&mut self, pattern: &Pattern) {
1327        match &pattern.kind {
1328            PatternKind::Wildcard => self.output.push('_'),
1329            PatternKind::Binding(id) => self.output.push_str(&id.name),
1330            PatternKind::LitInt(v) => self.output.push_str(&v.to_string()),
1331            PatternKind::LitFloat(v) => self.output.push_str(&v.to_string()),
1332            PatternKind::LitBool(b) => {
1333                self.output.push_str(if *b { "true" } else { "false" })
1334            }
1335            PatternKind::LitString(s) => {
1336                self.output.push('"');
1337                self.output.push_str(s);
1338                self.output.push('"');
1339            }
1340            PatternKind::Tuple(pats) => {
1341                self.output.push('(');
1342                for (i, p) in pats.iter().enumerate() {
1343                    if i > 0 {
1344                        self.output.push_str(", ");
1345                    }
1346                    self.print_pattern(p);
1347                }
1348                self.output.push(')');
1349            }
1350            PatternKind::Struct { name, fields } => {
1351                self.output.push_str(&name.name);
1352                self.output.push_str(" { ");
1353                for (i, f) in fields.iter().enumerate() {
1354                    if i > 0 {
1355                        self.output.push_str(", ");
1356                    }
1357                    self.output.push_str(&f.name.name);
1358                    if let Some(ref pat) = f.pattern {
1359                        self.output.push_str(": ");
1360                        self.print_pattern(pat);
1361                    }
1362                }
1363                self.output.push_str(" }");
1364            }
1365            PatternKind::Variant {
1366                enum_name,
1367                variant,
1368                fields,
1369            } => {
1370                if let Some(ref en) = enum_name {
1371                    self.output.push_str(&en.name);
1372                    self.output.push_str("::");
1373                }
1374                self.output.push_str(&variant.name);
1375                if !fields.is_empty() {
1376                    self.output.push('(');
1377                    for (i, p) in fields.iter().enumerate() {
1378                        if i > 0 {
1379                            self.output.push_str(", ");
1380                        }
1381                        self.print_pattern(p);
1382                    }
1383                    self.output.push(')');
1384                }
1385            }
1386        }
1387    }
1388}
1389
1390impl Default for PrettyPrinter {
1391    fn default() -> Self {
1392        Self::new()
1393    }
1394}