1pub mod inspect;
20pub mod metrics;
21pub mod node_utils;
22pub mod validate;
23pub mod visit;
24
25use std::fmt;
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
31pub struct Span {
32 pub start: usize,
33 pub end: usize,
34}
35
36impl Span {
37 pub fn new(start: usize, end: usize) -> Self {
39 Self { start, end }
40 }
41
42 pub fn merge(self, other: Span) -> Span {
46 Span {
47 start: self.start.min(other.start),
48 end: self.end.max(other.end),
49 }
50 }
51
52 pub fn dummy() -> Self {
54 Self { start: 0, end: 0 }
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub enum Visibility {
66 Public,
68 Private,
70}
71
72impl Default for Visibility {
73 fn default() -> Self {
74 Visibility::Private
75 }
76}
77
78#[derive(Debug, Clone)]
82pub struct Program {
83 pub declarations: Vec<Decl>,
84}
85
86#[derive(Debug, Clone)]
88pub struct Decl {
89 pub kind: DeclKind,
90 pub span: Span,
91}
92
93#[derive(Debug, Clone)]
98pub enum DeclKind {
99 Struct(StructDecl),
101 Class(ClassDecl),
103 Record(RecordDecl),
105 Fn(FnDecl),
107 Trait(TraitDecl),
109 Impl(ImplDecl),
111 Enum(EnumDecl),
113 Let(LetStmt),
115 Import(ImportDecl),
117 Const(ConstDecl),
119 Stmt(Stmt),
121}
122
123#[derive(Debug, Clone)]
128pub struct ConstDecl {
129 pub name: Ident,
131 pub ty: TypeExpr,
133 pub value: Box<Expr>,
135 pub span: Span,
137}
138
139#[derive(Debug, Clone)]
146pub struct StructDecl {
147 pub name: Ident,
149 pub type_params: Vec<TypeParam>,
151 pub fields: Vec<FieldDecl>,
153 pub vis: Visibility,
155}
156
157#[derive(Debug, Clone)]
162pub struct ClassDecl {
163 pub name: Ident,
165 pub type_params: Vec<TypeParam>,
167 pub fields: Vec<FieldDecl>,
169 pub vis: Visibility,
171}
172
173#[derive(Debug, Clone)]
177pub struct RecordDecl {
178 pub name: Ident,
179 pub type_params: Vec<TypeParam>,
180 pub fields: Vec<FieldDecl>,
181 pub vis: Visibility,
182}
183
184#[derive(Debug, Clone)]
191pub struct EnumDecl {
192 pub name: Ident,
194 pub type_params: Vec<TypeParam>,
196 pub variants: Vec<VariantDecl>,
198}
199
200#[derive(Debug, Clone)]
205pub struct VariantDecl {
206 pub name: Ident,
208 pub fields: Vec<TypeExpr>,
210 pub span: Span,
212}
213
214#[derive(Debug, Clone)]
218pub struct FieldDecl {
219 pub name: Ident,
221 pub ty: TypeExpr,
223 pub default: Option<Expr>,
225 pub vis: Visibility,
227 pub span: Span,
229}
230
231#[derive(Debug, Clone)]
237pub struct Decorator {
238 pub name: Ident,
239 pub args: Vec<Expr>,
240 pub span: Span,
241}
242
243#[derive(Debug, Clone)]
251pub struct FnDecl {
252 pub name: Ident,
254 pub type_params: Vec<TypeParam>,
256 pub params: Vec<Param>,
258 pub return_type: Option<TypeExpr>,
260 pub body: Block,
262 pub is_nogc: bool,
264 pub effect_annotation: Option<Vec<String>>,
267 pub decorators: Vec<Decorator>,
269 pub vis: Visibility,
271}
272
273#[derive(Debug, Clone)]
277pub struct FnSig {
278 pub name: Ident,
280 pub type_params: Vec<TypeParam>,
282 pub params: Vec<Param>,
284 pub return_type: Option<TypeExpr>,
286 pub span: Span,
288}
289
290#[derive(Debug, Clone)]
291pub struct Param {
292 pub name: Ident,
293 pub ty: TypeExpr,
294 pub default: Option<Expr>,
296 pub is_variadic: bool,
299 pub span: Span,
300}
301
302#[derive(Debug, Clone)]
309pub struct TraitDecl {
310 pub name: Ident,
312 pub type_params: Vec<TypeParam>,
314 pub super_traits: Vec<TypeExpr>,
316 pub methods: Vec<FnSig>,
318}
319
320#[derive(Debug, Clone)]
325pub struct ImplDecl {
326 pub type_params: Vec<TypeParam>,
328 pub target: TypeExpr,
330 pub trait_ref: Option<TypeExpr>,
332 pub methods: Vec<FnDecl>,
334 pub span: Span,
336}
337
338#[derive(Debug, Clone)]
345pub struct ImportDecl {
346 pub path: Vec<Ident>,
348 pub alias: Option<Ident>,
350}
351
352#[derive(Debug, Clone)]
360pub struct TypeExpr {
361 pub kind: TypeExprKind,
363 pub span: Span,
365}
366
367#[derive(Debug, Clone)]
372pub enum TypeExprKind {
373 Named {
375 name: Ident,
377 args: Vec<TypeArg>,
379 },
380 Array {
382 elem: Box<TypeExpr>,
384 size: Box<Expr>,
386 },
387 Tuple(Vec<TypeExpr>),
389 Fn {
391 params: Vec<TypeExpr>,
393 ret: Box<TypeExpr>,
395 },
396 ShapeLit(Vec<ShapeDim>),
398}
399
400#[derive(Debug, Clone)]
405pub enum TypeArg {
406 Type(TypeExpr),
408 Expr(Expr),
410 Shape(Vec<ShapeDim>),
412}
413
414#[derive(Debug, Clone)]
419pub enum ShapeDim {
420 Name(Ident),
422 Lit(i64),
424}
425
426#[derive(Debug, Clone)]
430pub struct TypeParam {
431 pub name: Ident,
433 pub bounds: Vec<TypeExpr>,
435 pub span: Span,
437}
438
439#[derive(Debug, Clone)]
447pub struct Block {
448 pub stmts: Vec<Stmt>,
450 pub expr: Option<Box<Expr>>,
452 pub span: Span,
454}
455
456#[derive(Debug, Clone)]
460pub struct Stmt {
461 pub kind: StmtKind,
463 pub span: Span,
465}
466
467#[derive(Debug, Clone)]
469pub enum StmtKind {
470 Let(LetStmt),
472 Expr(Expr),
474 Return(Option<Expr>),
476 Break,
478 Continue,
480 If(IfStmt),
482 While(WhileStmt),
484 For(ForStmt),
486 NoGcBlock(Block),
488}
489
490#[derive(Debug, Clone)]
492pub struct LetStmt {
493 pub name: Ident,
495 pub mutable: bool,
497 pub ty: Option<TypeExpr>,
499 pub init: Box<Expr>,
501}
502
503#[derive(Debug, Clone)]
507pub struct IfStmt {
508 pub condition: Expr,
510 pub then_block: Block,
512 pub else_branch: Option<ElseBranch>,
514}
515
516#[derive(Debug, Clone)]
518pub enum ElseBranch {
519 ElseIf(Box<IfStmt>),
521 Else(Block),
523}
524
525#[derive(Debug, Clone)]
527pub struct WhileStmt {
528 pub condition: Expr,
530 pub body: Block,
532}
533
534#[derive(Debug, Clone)]
538pub struct ForStmt {
539 pub ident: Ident,
541 pub iter: ForIter,
543 pub body: Block,
545}
546
547#[derive(Debug, Clone)]
549pub enum ForIter {
550 Range { start: Box<Expr>, end: Box<Expr> },
552 Expr(Box<Expr>),
554}
555
556#[derive(Debug, Clone)]
564pub struct Expr {
565 pub kind: ExprKind,
567 pub span: Span,
569}
570
571#[derive(Debug, Clone)]
576pub enum ExprKind {
577 IntLit(i64),
579 FloatLit(f64),
581 StringLit(String),
583 ByteStringLit(Vec<u8>),
585 ByteCharLit(u8),
587 RawStringLit(String),
589 RawByteStringLit(Vec<u8>),
591 FStringLit(Vec<(String, Option<Box<Expr>>)>),
595 RegexLit { pattern: String, flags: String },
597 TensorLit { rows: Vec<Vec<Expr>> },
601 BoolLit(bool),
603 NaLit,
605 Ident(Ident),
607 Binary {
609 op: BinOp,
610 left: Box<Expr>,
611 right: Box<Expr>,
612 },
613 Unary {
615 op: UnaryOp,
616 operand: Box<Expr>,
617 },
618 Call {
620 callee: Box<Expr>,
621 args: Vec<CallArg>,
622 },
623 Field {
625 object: Box<Expr>,
626 name: Ident,
627 },
628 Index {
630 object: Box<Expr>,
631 index: Box<Expr>,
632 },
633 MultiIndex {
635 object: Box<Expr>,
636 indices: Vec<Expr>,
637 },
638 Assign {
640 target: Box<Expr>,
641 value: Box<Expr>,
642 },
643 CompoundAssign {
646 op: BinOp,
647 target: Box<Expr>,
648 value: Box<Expr>,
649 },
650 IfExpr {
652 condition: Box<Expr>,
653 then_block: Block,
654 else_branch: Option<ElseBranch>,
655 },
656 Pipe {
658 left: Box<Expr>,
659 right: Box<Expr>,
660 },
661 Block(Block),
663 StructLit {
665 name: Ident,
666 fields: Vec<FieldInit>,
667 },
668 ArrayLit(Vec<Expr>),
670 Col(String),
672 Lambda {
674 params: Vec<Param>,
675 body: Box<Expr>,
676 },
677 Match {
679 scrutinee: Box<Expr>,
680 arms: Vec<MatchArm>,
681 },
682 TupleLit(Vec<Expr>),
684 Cast {
686 expr: Box<Expr>,
687 target_type: Ident,
688 },
689 Try(Box<Expr>),
691 VariantLit {
693 enum_name: Option<Ident>,
694 variant: Ident,
695 fields: Vec<Expr>,
696 },
697}
698
699#[derive(Debug, Clone)]
703pub struct MatchArm {
704 pub pattern: Pattern,
705 pub body: Expr,
706 pub span: Span,
707}
708
709#[derive(Debug, Clone)]
711pub struct Pattern {
712 pub kind: PatternKind,
713 pub span: Span,
714}
715
716#[derive(Debug, Clone)]
717pub enum PatternKind {
718 Wildcard,
720 Binding(Ident),
722 LitInt(i64),
724 LitFloat(f64),
725 LitBool(bool),
726 LitString(String),
727 Tuple(Vec<Pattern>),
729 Struct {
731 name: Ident,
732 fields: Vec<PatternField>,
733 },
734 Variant {
736 enum_name: Option<Ident>,
738 variant: Ident,
739 fields: Vec<Pattern>,
740 },
741}
742
743#[derive(Debug, Clone)]
745pub struct PatternField {
746 pub name: Ident,
747 pub pattern: Option<Pattern>,
748 pub span: Span,
749}
750
751#[derive(Debug, Clone)]
755pub struct CallArg {
756 pub name: Option<Ident>,
758 pub value: Expr,
760 pub span: Span,
762}
763
764#[derive(Debug, Clone)]
766pub struct FieldInit {
767 pub name: Ident,
769 pub value: Expr,
771 pub span: Span,
773}
774
775#[derive(Debug, Clone, Copy, PartialEq, Eq)]
782pub enum BinOp {
783 Add,
785 Sub,
787 Mul,
789 Div,
791 Mod,
793 Pow,
795 Eq,
797 Ne,
799 Lt,
801 Gt,
803 Le,
805 Ge,
807 And,
809 Or,
811 Match,
813 NotMatch,
815 BitAnd,
817 BitOr,
819 BitXor,
821 Shl,
823 Shr,
825}
826
827impl fmt::Display for BinOp {
828 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
829 match self {
830 BinOp::Add => write!(f, "+"),
831 BinOp::Sub => write!(f, "-"),
832 BinOp::Mul => write!(f, "*"),
833 BinOp::Div => write!(f, "/"),
834 BinOp::Mod => write!(f, "%"),
835 BinOp::Pow => write!(f, "**"),
836 BinOp::Eq => write!(f, "=="),
837 BinOp::Ne => write!(f, "!="),
838 BinOp::Lt => write!(f, "<"),
839 BinOp::Gt => write!(f, ">"),
840 BinOp::Le => write!(f, "<="),
841 BinOp::Ge => write!(f, ">="),
842 BinOp::And => write!(f, "&&"),
843 BinOp::Or => write!(f, "||"),
844 BinOp::Match => write!(f, "~="),
845 BinOp::NotMatch => write!(f, "!~"),
846 BinOp::BitAnd => write!(f, "&"),
847 BinOp::BitOr => write!(f, "|"),
848 BinOp::BitXor => write!(f, "^"),
849 BinOp::Shl => write!(f, "<<"),
850 BinOp::Shr => write!(f, ">>"),
851 }
852 }
853}
854
855#[derive(Debug, Clone, Copy, PartialEq, Eq)]
859pub enum UnaryOp {
860 Neg,
862 Not,
864 BitNot,
866}
867
868impl fmt::Display for UnaryOp {
869 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
870 match self {
871 UnaryOp::Neg => write!(f, "-"),
872 UnaryOp::Not => write!(f, "!"),
873 UnaryOp::BitNot => write!(f, "~"),
874 }
875 }
876}
877
878#[derive(Debug, Clone, PartialEq, Eq, Hash)]
884pub struct Ident {
885 pub name: String,
887 pub span: Span,
889}
890
891impl Ident {
892 pub fn new(name: impl Into<String>, span: Span) -> Self {
894 Self {
895 name: name.into(),
896 span,
897 }
898 }
899
900 pub fn dummy(name: impl Into<String>) -> Self {
902 Self {
903 name: name.into(),
904 span: Span::dummy(),
905 }
906 }
907}
908
909impl fmt::Display for Ident {
910 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
911 write!(f, "{}", self.name)
912 }
913}
914
915pub struct PrettyPrinter {
931 indent: usize,
932 output: String,
933}
934
935impl PrettyPrinter {
936 pub fn new() -> Self {
938 Self {
939 indent: 0,
940 output: String::new(),
941 }
942 }
943
944 pub fn print_program(mut self, program: &Program) -> String {
954 for decl in &program.declarations {
955 self.print_decl(decl);
956 self.output.push('\n');
957 }
958 self.output
959 }
960
961 fn indent_str(&self) -> String {
962 " ".repeat(self.indent)
963 }
964
965 fn print_decl(&mut self, decl: &Decl) {
966 match &decl.kind {
967 DeclKind::Struct(s) => self.print_struct(s),
968 DeclKind::Class(c) => self.print_class(c),
969 DeclKind::Record(r) => self.print_record(r),
970 DeclKind::Fn(f) => self.print_fn(f),
971 DeclKind::Trait(t) => self.print_trait(t),
972 DeclKind::Impl(i) => self.print_impl(i),
973 DeclKind::Enum(e) => self.print_enum(e),
974 DeclKind::Let(l) => {
975 self.output.push_str(&self.indent_str());
976 self.print_let(l);
977 }
978 DeclKind::Import(i) => self.print_import(i),
979 DeclKind::Const(c) => {
980 self.output.push_str(&self.indent_str());
981 self.output.push_str("const ");
982 self.output.push_str(&c.name.name);
983 self.output.push_str(": ");
984 self.print_type_expr(&c.ty);
985 self.output.push_str(" = ");
986 self.print_expr(&c.value);
987 self.output.push(';');
988 }
989 DeclKind::Stmt(s) => {
990 self.output.push_str(&self.indent_str());
991 self.print_stmt(s);
992 }
993 }
994 }
995
996 fn print_struct(&mut self, s: &StructDecl) {
997 self.output.push_str(&self.indent_str());
998 self.output.push_str(&format!("struct {}", s.name));
999 self.print_type_params(&s.type_params);
1000 self.output.push_str(" {\n");
1001 self.indent += 1;
1002 for field in &s.fields {
1003 self.output
1004 .push_str(&format!("{}{}: ", self.indent_str(), field.name));
1005 self.print_type_expr(&field.ty);
1006 self.output.push('\n');
1007 }
1008 self.indent -= 1;
1009 self.output.push_str(&format!("{}}}", self.indent_str()));
1010 }
1011
1012 fn print_class(&mut self, c: &ClassDecl) {
1013 self.output.push_str(&self.indent_str());
1014 self.output.push_str(&format!("class {}", c.name));
1015 self.print_type_params(&c.type_params);
1016 self.output.push_str(" {\n");
1017 self.indent += 1;
1018 for field in &c.fields {
1019 self.output
1020 .push_str(&format!("{}{}: ", self.indent_str(), field.name));
1021 self.print_type_expr(&field.ty);
1022 self.output.push('\n');
1023 }
1024 self.indent -= 1;
1025 self.output.push_str(&format!("{}}}", self.indent_str()));
1026 }
1027
1028 fn print_record(&mut self, r: &RecordDecl) {
1029 self.output.push_str(&self.indent_str());
1030 self.output.push_str(&format!("record {}", r.name));
1031 self.print_type_params(&r.type_params);
1032 self.output.push_str(" {\n");
1033 self.indent += 1;
1034 for field in &r.fields {
1035 self.output
1036 .push_str(&format!("{}{}: ", self.indent_str(), field.name));
1037 self.print_type_expr(&field.ty);
1038 self.output.push('\n');
1039 }
1040 self.indent -= 1;
1041 self.output.push_str(&format!("{}}}", self.indent_str()));
1042 }
1043
1044 fn print_fn(&mut self, f: &FnDecl) {
1045 self.output.push_str(&self.indent_str());
1046 if f.is_nogc {
1047 self.output.push_str("nogc ");
1048 }
1049 self.output.push_str(&format!("fn {}", f.name));
1050 self.print_type_params(&f.type_params);
1051 self.output.push('(');
1052 for (i, param) in f.params.iter().enumerate() {
1053 if i > 0 {
1054 self.output.push_str(", ");
1055 }
1056 if param.is_variadic {
1057 self.output.push_str("...");
1058 }
1059 self.output.push_str(&format!("{}: ", param.name));
1060 self.print_type_expr(¶m.ty);
1061 }
1062 self.output.push(')');
1063 if let Some(ref ret) = f.return_type {
1064 self.output.push_str(" -> ");
1065 self.print_type_expr(ret);
1066 }
1067 self.output.push(' ');
1068 self.print_block(&f.body);
1069 }
1070
1071 fn print_trait(&mut self, t: &TraitDecl) {
1072 self.output.push_str(&self.indent_str());
1073 self.output.push_str(&format!("trait {}", t.name));
1074 self.print_type_params(&t.type_params);
1075 if !t.super_traits.is_empty() {
1076 self.output.push_str(": ");
1077 for (i, st) in t.super_traits.iter().enumerate() {
1078 if i > 0 {
1079 self.output.push_str(" + ");
1080 }
1081 self.print_type_expr(st);
1082 }
1083 }
1084 self.output.push_str(" {\n");
1085 self.indent += 1;
1086 for method in &t.methods {
1087 self.output.push_str(&self.indent_str());
1088 self.output.push_str(&format!("fn {}", method.name));
1089 self.print_type_params(&method.type_params);
1090 self.output.push('(');
1091 for (i, p) in method.params.iter().enumerate() {
1092 if i > 0 {
1093 self.output.push_str(", ");
1094 }
1095 self.output.push_str(&format!("{}: ", p.name));
1096 self.print_type_expr(&p.ty);
1097 }
1098 self.output.push(')');
1099 if let Some(ref ret) = method.return_type {
1100 self.output.push_str(" -> ");
1101 self.print_type_expr(ret);
1102 }
1103 self.output.push_str(";\n");
1104 }
1105 self.indent -= 1;
1106 self.output.push_str(&format!("{}}}", self.indent_str()));
1107 }
1108
1109 fn print_impl(&mut self, i: &ImplDecl) {
1110 self.output.push_str(&self.indent_str());
1111 self.output.push_str("impl");
1112 self.print_type_params(&i.type_params);
1113 self.output.push(' ');
1114 self.print_type_expr(&i.target);
1115 if let Some(ref tr) = i.trait_ref {
1116 self.output.push_str(" : ");
1117 self.print_type_expr(tr);
1118 }
1119 self.output.push_str(" {\n");
1120 self.indent += 1;
1121 for method in &i.methods {
1122 self.print_fn(method);
1123 self.output.push('\n');
1124 }
1125 self.indent -= 1;
1126 self.output.push_str(&format!("{}}}", self.indent_str()));
1127 }
1128
1129 fn print_import(&mut self, i: &ImportDecl) {
1130 self.output.push_str(&self.indent_str());
1131 self.output.push_str("import ");
1132 let path: Vec<&str> = i.path.iter().map(|id| id.name.as_str()).collect();
1133 self.output.push_str(&path.join("."));
1134 if let Some(ref alias) = i.alias {
1135 self.output.push_str(&format!(" as {}", alias));
1136 }
1137 }
1138
1139 fn print_enum(&mut self, e: &EnumDecl) {
1140 self.output.push_str(&self.indent_str());
1141 self.output.push_str(&format!("enum {}", e.name));
1142 self.print_type_params(&e.type_params);
1143 self.output.push_str(" {\n");
1144 self.indent += 1;
1145 for variant in &e.variants {
1146 self.output.push_str(&self.indent_str());
1147 self.output.push_str(&variant.name.name);
1148 if !variant.fields.is_empty() {
1149 self.output.push('(');
1150 for (i, f) in variant.fields.iter().enumerate() {
1151 if i > 0 {
1152 self.output.push_str(", ");
1153 }
1154 self.print_type_expr(f);
1155 }
1156 self.output.push(')');
1157 }
1158 self.output.push_str(",\n");
1159 }
1160 self.indent -= 1;
1161 self.output.push_str(&format!("{}}}", self.indent_str()));
1162 }
1163
1164 fn print_type_params(&mut self, params: &[TypeParam]) {
1165 if params.is_empty() {
1166 return;
1167 }
1168 self.output.push('<');
1169 for (i, param) in params.iter().enumerate() {
1170 if i > 0 {
1171 self.output.push_str(", ");
1172 }
1173 self.output.push_str(¶m.name.name);
1174 if !param.bounds.is_empty() {
1175 self.output.push_str(": ");
1176 for (j, bound) in param.bounds.iter().enumerate() {
1177 if j > 0 {
1178 self.output.push_str(" + ");
1179 }
1180 self.print_type_expr(bound);
1181 }
1182 }
1183 }
1184 self.output.push('>');
1185 }
1186
1187 fn print_type_expr(&mut self, ty: &TypeExpr) {
1188 match &ty.kind {
1189 TypeExprKind::Named { name, args } => {
1190 self.output.push_str(&name.name);
1191 if !args.is_empty() {
1192 self.output.push('<');
1193 for (i, arg) in args.iter().enumerate() {
1194 if i > 0 {
1195 self.output.push_str(", ");
1196 }
1197 match arg {
1198 TypeArg::Type(t) => self.print_type_expr(t),
1199 TypeArg::Expr(e) => self.print_expr(e),
1200 TypeArg::Shape(dims) => self.print_shape(dims),
1201 }
1202 }
1203 self.output.push('>');
1204 }
1205 }
1206 TypeExprKind::Array { elem, size } => {
1207 self.output.push('[');
1208 self.print_type_expr(elem);
1209 self.output.push_str("; ");
1210 self.print_expr(size);
1211 self.output.push(']');
1212 }
1213 TypeExprKind::Tuple(elems) => {
1214 self.output.push('(');
1215 for (i, elem) in elems.iter().enumerate() {
1216 if i > 0 {
1217 self.output.push_str(", ");
1218 }
1219 self.print_type_expr(elem);
1220 }
1221 self.output.push(')');
1222 }
1223 TypeExprKind::Fn { params, ret } => {
1224 self.output.push_str("fn(");
1225 for (i, p) in params.iter().enumerate() {
1226 if i > 0 {
1227 self.output.push_str(", ");
1228 }
1229 self.print_type_expr(p);
1230 }
1231 self.output.push_str(") -> ");
1232 self.print_type_expr(ret);
1233 }
1234 TypeExprKind::ShapeLit(dims) => {
1235 self.print_shape(dims);
1236 }
1237 }
1238 }
1239
1240 fn print_shape(&mut self, dims: &[ShapeDim]) {
1241 self.output.push('[');
1242 for (i, dim) in dims.iter().enumerate() {
1243 if i > 0 {
1244 self.output.push_str(", ");
1245 }
1246 match dim {
1247 ShapeDim::Name(n) => self.output.push_str(&n.name),
1248 ShapeDim::Lit(v) => self.output.push_str(&v.to_string()),
1249 }
1250 }
1251 self.output.push(']');
1252 }
1253
1254 fn print_block(&mut self, block: &Block) {
1255 self.output.push_str("{\n");
1256 self.indent += 1;
1257 for stmt in &block.stmts {
1258 self.print_stmt(stmt);
1259 }
1260 if let Some(ref expr) = block.expr {
1261 self.output.push_str(&self.indent_str());
1262 self.print_expr(expr);
1263 self.output.push('\n');
1264 }
1265 self.indent -= 1;
1266 self.output.push_str(&format!("{}}}", self.indent_str()));
1267 }
1268
1269 fn print_stmt(&mut self, stmt: &Stmt) {
1270 match &stmt.kind {
1271 StmtKind::Let(l) => {
1272 self.output.push_str(&self.indent_str());
1273 self.print_let(l);
1274 }
1275 StmtKind::Expr(e) => {
1276 self.output.push_str(&self.indent_str());
1277 self.print_expr(e);
1278 self.output.push_str(";\n");
1279 }
1280 StmtKind::Return(e) => {
1281 self.output.push_str(&self.indent_str());
1282 self.output.push_str("return");
1283 if let Some(expr) = e {
1284 self.output.push(' ');
1285 self.print_expr(expr);
1286 }
1287 self.output.push_str(";\n");
1288 }
1289 StmtKind::Break => {
1290 self.output.push_str(&self.indent_str());
1291 self.output.push_str("break;\n");
1292 }
1293 StmtKind::Continue => {
1294 self.output.push_str(&self.indent_str());
1295 self.output.push_str("continue;\n");
1296 }
1297 StmtKind::If(if_stmt) => {
1298 self.output.push_str(&self.indent_str());
1299 self.print_if(if_stmt);
1300 self.output.push('\n');
1301 }
1302 StmtKind::While(w) => {
1303 self.output.push_str(&self.indent_str());
1304 self.output.push_str("while ");
1305 self.print_expr(&w.condition);
1306 self.output.push(' ');
1307 self.print_block(&w.body);
1308 self.output.push('\n');
1309 }
1310 StmtKind::For(f) => {
1311 self.output.push_str(&self.indent_str());
1312 self.output.push_str("for ");
1313 self.output.push_str(&f.ident.name);
1314 self.output.push_str(" in ");
1315 match &f.iter {
1316 ForIter::Range { start, end } => {
1317 self.print_expr(start);
1318 self.output.push_str("..");
1319 self.print_expr(end);
1320 }
1321 ForIter::Expr(expr) => {
1322 self.print_expr(expr);
1323 }
1324 }
1325 self.output.push(' ');
1326 self.print_block(&f.body);
1327 self.output.push('\n');
1328 }
1329 StmtKind::NoGcBlock(block) => {
1330 self.output.push_str(&self.indent_str());
1331 self.output.push_str("nogc ");
1332 self.print_block(block);
1333 self.output.push('\n');
1334 }
1335 }
1336 }
1337
1338 fn print_let(&mut self, l: &LetStmt) {
1339 self.output.push_str("let ");
1340 if l.mutable {
1341 self.output.push_str("mut ");
1342 }
1343 self.output.push_str(&l.name.name);
1344 if let Some(ref ty) = l.ty {
1345 self.output.push_str(": ");
1346 self.print_type_expr(ty);
1347 }
1348 self.output.push_str(" = ");
1349 self.print_expr(&l.init);
1350 self.output.push_str(";\n");
1351 }
1352
1353 fn print_if(&mut self, if_stmt: &IfStmt) {
1354 self.output.push_str("if ");
1355 self.print_expr(&if_stmt.condition);
1356 self.output.push(' ');
1357 self.print_block(&if_stmt.then_block);
1358 if let Some(ref else_branch) = if_stmt.else_branch {
1359 self.output.push_str(" else ");
1360 match else_branch {
1361 ElseBranch::ElseIf(elif) => self.print_if(elif),
1362 ElseBranch::Else(block) => self.print_block(block),
1363 }
1364 }
1365 }
1366
1367 fn print_expr(&mut self, expr: &Expr) {
1368 match &expr.kind {
1369 ExprKind::IntLit(v) => self.output.push_str(&v.to_string()),
1370 ExprKind::FloatLit(v) => {
1371 let s = v.to_string();
1372 self.output.push_str(&s);
1373 if !s.contains('.') {
1374 self.output.push_str(".0");
1375 }
1376 }
1377 ExprKind::StringLit(s) => {
1378 self.output.push('"');
1379 self.output.push_str(s);
1380 self.output.push('"');
1381 }
1382 ExprKind::ByteStringLit(bytes) => {
1383 self.output.push_str("b\"");
1384 for &b in bytes {
1385 if b.is_ascii_graphic() || b == b' ' {
1386 self.output.push(b as char);
1387 } else {
1388 self.output.push_str(&format!("\\x{:02x}", b));
1389 }
1390 }
1391 self.output.push('"');
1392 }
1393 ExprKind::ByteCharLit(b) => {
1394 self.output.push_str(&format!("b'\\x{:02x}'", b));
1395 }
1396 ExprKind::RawStringLit(s) => {
1397 self.output.push_str("r\"");
1398 self.output.push_str(s);
1399 self.output.push('"');
1400 }
1401 ExprKind::RawByteStringLit(bytes) => {
1402 self.output.push_str("br\"");
1403 for &b in bytes {
1404 self.output.push(b as char);
1405 }
1406 self.output.push('"');
1407 }
1408 ExprKind::FStringLit(segments) => {
1409 self.output.push_str("f\"");
1411 for (lit, interp) in segments {
1412 self.output.push_str(&lit.replace('"', "\\\""));
1413 if let Some(expr) = interp {
1414 self.output.push('{');
1415 self.print_expr(expr);
1416 self.output.push('}');
1417 }
1418 }
1419 self.output.push('"');
1420 }
1421 ExprKind::RegexLit { pattern, flags } => {
1422 self.output.push('/');
1423 self.output.push_str(pattern);
1424 self.output.push('/');
1425 self.output.push_str(flags);
1426 }
1427 ExprKind::TensorLit { rows } => {
1428 self.output.push_str("[| ");
1429 for (ri, row) in rows.iter().enumerate() {
1430 if ri > 0 {
1431 self.output.push_str("; ");
1432 }
1433 for (ci, expr) in row.iter().enumerate() {
1434 if ci > 0 {
1435 self.output.push_str(", ");
1436 }
1437 self.print_expr(expr);
1438 }
1439 }
1440 self.output.push_str(" |]");
1441 }
1442 ExprKind::BoolLit(b) => self.output.push_str(if *b { "true" } else { "false" }),
1443 ExprKind::NaLit => self.output.push_str("NA"),
1444 ExprKind::Ident(id) => self.output.push_str(&id.name),
1445 ExprKind::Binary { op, left, right } => {
1446 self.output.push('(');
1447 self.print_expr(left);
1448 self.output.push_str(&format!(" {} ", op));
1449 self.print_expr(right);
1450 self.output.push(')');
1451 }
1452 ExprKind::Unary { op, operand } => {
1453 self.output.push_str(&format!("{}", op));
1454 self.print_expr(operand);
1455 }
1456 ExprKind::Call { callee, args } => {
1457 self.print_expr(callee);
1458 self.output.push('(');
1459 for (i, arg) in args.iter().enumerate() {
1460 if i > 0 {
1461 self.output.push_str(", ");
1462 }
1463 if let Some(ref name) = arg.name {
1464 self.output.push_str(&format!("{}: ", name));
1465 }
1466 self.print_expr(&arg.value);
1467 }
1468 self.output.push(')');
1469 }
1470 ExprKind::Field { object, name } => {
1471 self.print_expr(object);
1472 self.output.push('.');
1473 self.output.push_str(&name.name);
1474 }
1475 ExprKind::Index { object, index } => {
1476 self.print_expr(object);
1477 self.output.push('[');
1478 self.print_expr(index);
1479 self.output.push(']');
1480 }
1481 ExprKind::MultiIndex { object, indices } => {
1482 self.print_expr(object);
1483 self.output.push('[');
1484 for (i, idx) in indices.iter().enumerate() {
1485 if i > 0 {
1486 self.output.push_str(", ");
1487 }
1488 self.print_expr(idx);
1489 }
1490 self.output.push(']');
1491 }
1492 ExprKind::Assign { target, value } => {
1493 self.print_expr(target);
1494 self.output.push_str(" = ");
1495 self.print_expr(value);
1496 }
1497 ExprKind::CompoundAssign { op, target, value } => {
1498 self.print_expr(target);
1499 self.output.push_str(&format!(" {}= ", op));
1500 self.print_expr(value);
1501 }
1502 ExprKind::IfExpr { condition, then_block, else_branch } => {
1503 self.output.push_str("if ");
1504 self.print_expr(condition);
1505 self.output.push_str(" ");
1506 self.print_block(then_block);
1507 if let Some(eb) = else_branch {
1508 self.output.push_str(" else ");
1509 match eb {
1510 ElseBranch::ElseIf(elif) => {
1511 self.output.push_str("if ...");
1513 }
1514 ElseBranch::Else(block) => {
1515 self.print_block(block);
1516 }
1517 }
1518 }
1519 }
1520 ExprKind::Pipe { left, right } => {
1521 self.print_expr(left);
1522 self.output.push_str(" |> ");
1523 self.print_expr(right);
1524 }
1525 ExprKind::Block(block) => {
1526 self.print_block(block);
1527 }
1528 ExprKind::StructLit { name, fields } => {
1529 self.output.push_str(&format!("{} {{ ", name));
1530 for (i, field) in fields.iter().enumerate() {
1531 if i > 0 {
1532 self.output.push_str(", ");
1533 }
1534 self.output.push_str(&format!("{}: ", field.name));
1535 self.print_expr(&field.value);
1536 }
1537 self.output.push_str(" }");
1538 }
1539 ExprKind::ArrayLit(elems) => {
1540 self.output.push('[');
1541 for (i, elem) in elems.iter().enumerate() {
1542 if i > 0 {
1543 self.output.push_str(", ");
1544 }
1545 self.print_expr(elem);
1546 }
1547 self.output.push(']');
1548 }
1549 ExprKind::Col(name) => {
1550 self.output.push_str(&format!("col(\"{}\")", name));
1551 }
1552 ExprKind::Lambda { params, body } => {
1553 self.output.push('|');
1554 for (i, p) in params.iter().enumerate() {
1555 if i > 0 {
1556 self.output.push_str(", ");
1557 }
1558 self.output.push_str(&format!("{}: ", p.name));
1559 self.print_type_expr(&p.ty);
1560 }
1561 self.output.push_str("| ");
1562 self.print_expr(body);
1563 }
1564 ExprKind::Match { scrutinee, arms } => {
1565 self.output.push_str("match ");
1566 self.print_expr(scrutinee);
1567 self.output.push_str(" {\n");
1568 self.indent += 1;
1569 for arm in arms {
1570 self.output.push_str(&self.indent_str());
1571 self.print_pattern(&arm.pattern);
1572 self.output.push_str(" => ");
1573 self.print_expr(&arm.body);
1574 self.output.push_str(",\n");
1575 }
1576 self.indent -= 1;
1577 self.output.push_str(&format!("{}}}", self.indent_str()));
1578 }
1579 ExprKind::TupleLit(elems) => {
1580 self.output.push('(');
1581 for (i, elem) in elems.iter().enumerate() {
1582 if i > 0 {
1583 self.output.push_str(", ");
1584 }
1585 self.print_expr(elem);
1586 }
1587 self.output.push(')');
1588 }
1589 ExprKind::Try(inner) => {
1590 self.print_expr(inner);
1591 self.output.push('?');
1592 }
1593 ExprKind::VariantLit {
1594 enum_name,
1595 variant,
1596 fields,
1597 } => {
1598 if let Some(ref en) = enum_name {
1599 self.output.push_str(&en.name);
1600 self.output.push_str("::");
1601 }
1602 self.output.push_str(&variant.name);
1603 if !fields.is_empty() {
1604 self.output.push('(');
1605 for (i, f) in fields.iter().enumerate() {
1606 if i > 0 {
1607 self.output.push_str(", ");
1608 }
1609 self.print_expr(f);
1610 }
1611 self.output.push(')');
1612 }
1613 }
1614 ExprKind::Cast { expr, target_type } => {
1615 self.print_expr(expr);
1616 self.output.push_str(" as ");
1617 self.output.push_str(&target_type.name);
1618 }
1619 }
1620 }
1621
1622 fn print_pattern(&mut self, pattern: &Pattern) {
1623 match &pattern.kind {
1624 PatternKind::Wildcard => self.output.push('_'),
1625 PatternKind::Binding(id) => self.output.push_str(&id.name),
1626 PatternKind::LitInt(v) => self.output.push_str(&v.to_string()),
1627 PatternKind::LitFloat(v) => self.output.push_str(&v.to_string()),
1628 PatternKind::LitBool(b) => {
1629 self.output.push_str(if *b { "true" } else { "false" })
1630 }
1631 PatternKind::LitString(s) => {
1632 self.output.push('"');
1633 self.output.push_str(s);
1634 self.output.push('"');
1635 }
1636 PatternKind::Tuple(pats) => {
1637 self.output.push('(');
1638 for (i, p) in pats.iter().enumerate() {
1639 if i > 0 {
1640 self.output.push_str(", ");
1641 }
1642 self.print_pattern(p);
1643 }
1644 self.output.push(')');
1645 }
1646 PatternKind::Struct { name, fields } => {
1647 self.output.push_str(&name.name);
1648 self.output.push_str(" { ");
1649 for (i, f) in fields.iter().enumerate() {
1650 if i > 0 {
1651 self.output.push_str(", ");
1652 }
1653 self.output.push_str(&f.name.name);
1654 if let Some(ref pat) = f.pattern {
1655 self.output.push_str(": ");
1656 self.print_pattern(pat);
1657 }
1658 }
1659 self.output.push_str(" }");
1660 }
1661 PatternKind::Variant {
1662 enum_name,
1663 variant,
1664 fields,
1665 } => {
1666 if let Some(ref en) = enum_name {
1667 self.output.push_str(&en.name);
1668 self.output.push_str("::");
1669 }
1670 self.output.push_str(&variant.name);
1671 if !fields.is_empty() {
1672 self.output.push('(');
1673 for (i, p) in fields.iter().enumerate() {
1674 if i > 0 {
1675 self.output.push_str(", ");
1676 }
1677 self.print_pattern(p);
1678 }
1679 self.output.push(')');
1680 }
1681 }
1682 }
1683 }
1684}
1685
1686impl Default for PrettyPrinter {
1687 fn default() -> Self {
1688 Self::new()
1689 }
1690}