1pub mod inspect;
7pub mod metrics;
8pub mod node_utils;
9pub mod validate;
10pub mod visit;
11
12use std::fmt;
13
14#[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#[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#[derive(Debug, Clone)]
62pub struct Program {
63 pub declarations: Vec<Decl>,
64}
65
66#[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 Const(ConstDecl),
86 Stmt(Stmt),
88}
89
90#[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#[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#[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#[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 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#[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 pub effect_annotation: Option<Vec<String>>,
177 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 pub default: Option<Expr>,
197 pub is_variadic: bool,
200 pub span: Span,
201}
202
203#[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#[derive(Debug, Clone)]
225pub struct ImportDecl {
226 pub path: Vec<Ident>,
227 pub alias: Option<Ident>,
228}
229
230#[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 {
242 name: Ident,
243 args: Vec<TypeArg>,
244 },
245 Array {
247 elem: Box<TypeExpr>,
248 size: Box<Expr>,
249 },
250 Tuple(Vec<TypeExpr>),
252 Fn {
254 params: Vec<TypeExpr>,
255 ret: Box<TypeExpr>,
256 },
257 ShapeLit(Vec<ShapeDim>),
259}
260
261#[derive(Debug, Clone)]
263pub enum TypeArg {
264 Type(TypeExpr),
265 Expr(Expr),
266 Shape(Vec<ShapeDim>),
267}
268
269#[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#[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#[derive(Debug, Clone)]
347pub enum ForIter {
348 Range { start: Box<Expr>, end: Box<Expr> },
350 Expr(Box<Expr>),
352}
353
354#[derive(Debug, Clone)]
357pub struct Expr {
358 pub kind: ExprKind,
359 pub span: Span,
360}
361
362#[derive(Debug, Clone)]
363pub enum ExprKind {
364 IntLit(i64),
366 FloatLit(f64),
368 StringLit(String),
370 ByteStringLit(Vec<u8>),
372 ByteCharLit(u8),
374 RawStringLit(String),
376 RawByteStringLit(Vec<u8>),
378 FStringLit(Vec<(String, Option<Box<Expr>>)>),
382 RegexLit { pattern: String, flags: String },
384 TensorLit { rows: Vec<Vec<Expr>> },
388 BoolLit(bool),
390 Ident(Ident),
392 Binary {
394 op: BinOp,
395 left: Box<Expr>,
396 right: Box<Expr>,
397 },
398 Unary {
400 op: UnaryOp,
401 operand: Box<Expr>,
402 },
403 Call {
405 callee: Box<Expr>,
406 args: Vec<CallArg>,
407 },
408 Field {
410 object: Box<Expr>,
411 name: Ident,
412 },
413 Index {
415 object: Box<Expr>,
416 index: Box<Expr>,
417 },
418 MultiIndex {
420 object: Box<Expr>,
421 indices: Vec<Expr>,
422 },
423 Assign {
425 target: Box<Expr>,
426 value: Box<Expr>,
427 },
428 CompoundAssign {
431 op: BinOp,
432 target: Box<Expr>,
433 value: Box<Expr>,
434 },
435 IfExpr {
437 condition: Box<Expr>,
438 then_block: Block,
439 else_branch: Option<ElseBranch>,
440 },
441 Pipe {
443 left: Box<Expr>,
444 right: Box<Expr>,
445 },
446 Block(Block),
448 StructLit {
450 name: Ident,
451 fields: Vec<FieldInit>,
452 },
453 ArrayLit(Vec<Expr>),
455 Col(String),
457 Lambda {
459 params: Vec<Param>,
460 body: Box<Expr>,
461 },
462 Match {
464 scrutinee: Box<Expr>,
465 arms: Vec<MatchArm>,
466 },
467 TupleLit(Vec<Expr>),
469 Try(Box<Expr>),
471 VariantLit {
473 enum_name: Option<Ident>,
474 variant: Ident,
475 fields: Vec<Expr>,
476 },
477}
478
479#[derive(Debug, Clone)]
483pub struct MatchArm {
484 pub pattern: Pattern,
485 pub body: Expr,
486 pub span: Span,
487}
488
489#[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,
500 Binding(Ident),
502 LitInt(i64),
504 LitFloat(f64),
505 LitBool(bool),
506 LitString(String),
507 Tuple(Vec<Pattern>),
509 Struct {
511 name: Ident,
512 fields: Vec<PatternField>,
513 },
514 Variant {
516 enum_name: Option<Ident>,
518 variant: Ident,
519 fields: Vec<Pattern>,
520 },
521}
522
523#[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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
548pub enum BinOp {
549 Add,
550 Sub,
551 Mul,
552 Div,
553 Mod,
554 Pow, Eq,
556 Ne,
557 Lt,
558 Gt,
559 Le,
560 Ge,
561 And,
562 Or,
563 Match, NotMatch, BitAnd, BitOr, BitXor, Shl, Shr, }
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, }
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#[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
648pub 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(¶m.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(¶m.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 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 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}