1use std::fmt;
38
39#[derive(Debug, Clone, PartialEq)]
43pub enum Literal {
44 Int(i64),
46 Float(f64),
48 Bool(bool),
50 Str(String),
52 Unit,
54}
55
56impl fmt::Display for Literal {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 Literal::Int(n) => write!(f, "{}", n),
60 Literal::Float(n) => write!(f, "{}", n),
61 Literal::Bool(b) => write!(f, "{}", b),
62 Literal::Str(s) => write!(f, "\"{}\"", s),
63 Literal::Unit => write!(f, "()"),
64 }
65 }
66}
67
68#[derive(Debug, Clone, Copy, PartialEq, Eq)]
72pub enum BinOp {
73 Add,
76 Sub,
78 Mul,
80 Div,
82 Concat,
84
85 Eq,
88 Neq,
90 Lt,
92 Lte,
94 Gt,
96 Gte,
98
99 And,
102 Or,
104}
105
106impl fmt::Display for BinOp {
107 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108 let s = match self {
109 BinOp::Add => "+",
110 BinOp::Sub => "-",
111 BinOp::Mul => "*",
112 BinOp::Div => "/",
113 BinOp::Concat => "++",
114 BinOp::Eq => "=",
115 BinOp::Neq => "<>",
116 BinOp::Lt => "<",
117 BinOp::Lte => "<=",
118 BinOp::Gt => ">",
119 BinOp::Gte => ">=",
120 BinOp::And => "&&",
121 BinOp::Or => "||",
122 };
123 write!(f, "{}", s)
124 }
125}
126
127impl BinOp {
128 pub fn is_arithmetic(&self) -> bool {
130 matches!(self, BinOp::Add | BinOp::Sub | BinOp::Mul | BinOp::Div)
131 }
132
133 pub fn is_comparison(&self) -> bool {
135 matches!(
136 self,
137 BinOp::Eq | BinOp::Neq | BinOp::Lt | BinOp::Lte | BinOp::Gt | BinOp::Gte
138 )
139 }
140
141 pub fn is_logical(&self) -> bool {
143 matches!(self, BinOp::And | BinOp::Or)
144 }
145}
146
147#[derive(Debug, Clone, PartialEq, Eq)]
151pub enum TypeExpr {
152 Named(String),
154 Tuple(Vec<TypeExpr>),
156 Function(Box<TypeExpr>, Box<TypeExpr>),
158}
159
160impl fmt::Display for TypeExpr {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 match self {
163 TypeExpr::Named(name) => write!(f, "{}", name),
164 TypeExpr::Tuple(types) => {
165 for (i, ty) in types.iter().enumerate() {
166 if i > 0 {
167 write!(f, " * ")?;
168 }
169 write!(f, "{}", ty)?;
170 }
171 Ok(())
172 }
173 TypeExpr::Function(arg, ret) => write!(f, "{} -> {}", arg, ret),
174 }
175 }
176}
177
178#[derive(Debug, Clone, PartialEq)]
183pub struct RecordTypeDef {
184 pub name: String,
186 pub fields: Vec<(String, TypeExpr)>,
188}
189
190impl fmt::Display for RecordTypeDef {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 write!(f, "type {} = {{ ", self.name)?;
193 for (i, (field_name, field_type)) in self.fields.iter().enumerate() {
194 if i > 0 {
195 write!(f, "; ")?;
196 }
197 write!(f, "{}: {}", field_name, field_type)?;
198 }
199 write!(f, " }}")
200 }
201}
202
203#[derive(Debug, Clone, PartialEq)]
208pub struct VariantDef {
209 pub name: String,
211 pub fields: Vec<TypeExpr>,
213}
214
215impl fmt::Display for VariantDef {
216 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
217 write!(f, "{}", self.name)?;
218 if !self.fields.is_empty() {
219 write!(f, " of ")?;
220 for (i, field) in self.fields.iter().enumerate() {
221 if i > 0 {
222 write!(f, " * ")?;
223 }
224 write!(f, "{}", field)?;
225 }
226 }
227 Ok(())
228 }
229}
230
231impl VariantDef {
232 pub fn new_simple(name: String) -> Self {
234 VariantDef {
235 name,
236 fields: vec![],
237 }
238 }
239
240 pub fn new(name: String, fields: Vec<TypeExpr>) -> Self {
242 VariantDef { name, fields }
243 }
244
245 pub fn is_simple(&self) -> bool {
247 self.fields.is_empty()
248 }
249
250 pub fn field_count(&self) -> usize {
252 self.fields.len()
253 }
254}
255
256#[derive(Debug, Clone, PartialEq)]
261pub struct DuTypeDef {
262 pub name: String,
264 pub variants: Vec<VariantDef>,
266}
267
268impl fmt::Display for DuTypeDef {
269 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
270 write!(f, "type {} = ", self.name)?;
271 for (i, variant) in self.variants.iter().enumerate() {
272 if i > 0 {
273 write!(f, " | ")?;
274 }
275 write!(f, "{}", variant)?;
276 }
277 Ok(())
278 }
279}
280
281impl DuTypeDef {
282 pub fn variant_names(&self) -> Vec<&str> {
284 self.variants.iter().map(|v| v.name.as_str()).collect()
285 }
286
287 pub fn find_variant(&self, name: &str) -> Option<&VariantDef> {
289 self.variants.iter().find(|v| v.name == name)
290 }
291
292 pub fn is_simple_enum(&self) -> bool {
294 self.variants.iter().all(|v| v.is_simple())
295 }
296
297 pub fn variant_count(&self) -> usize {
299 self.variants.len()
300 }
301}
302
303#[derive(Debug, Clone, PartialEq)]
305pub enum TypeDefinition {
306 Record(RecordTypeDef),
308 Du(DuTypeDef),
310}
311
312impl fmt::Display for TypeDefinition {
313 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
314 match self {
315 TypeDefinition::Record(r) => write!(f, "{}", r),
316 TypeDefinition::Du(du) => write!(f, "{}", du),
317 }
318 }
319}
320
321#[derive(Debug, Clone, PartialEq)]
325pub enum Declaration {
326 TypeDef(TypeDefinition),
328 LetBinding {
330 name: String,
331 params: Vec<String>,
332 body: Box<Expr>,
333 },
334}
335
336impl fmt::Display for Declaration {
337 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
338 match self {
339 Declaration::TypeDef(typedef) => write!(f, "{}", typedef),
340 Declaration::LetBinding { name, params, body } => {
341 write!(f, "let {}", name)?;
342 for param in params {
343 write!(f, " {}", param)?;
344 }
345 write!(f, " = {}", body)
346 }
347 }
348 }
349}
350
351#[derive(Debug, Clone, PartialEq)]
355pub struct Module {
356 pub declarations: Vec<Declaration>,
358}
359
360impl fmt::Display for Module {
361 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
362 for (i, decl) in self.declarations.iter().enumerate() {
363 if i > 0 {
364 writeln!(f)?;
365 }
366 write!(f, "{}", decl)?;
367 }
368 Ok(())
369 }
370}
371
372#[derive(Debug, Clone, PartialEq)]
377pub enum Pattern {
378 Wildcard,
380 Var(String),
382 Literal(Literal),
384 Tuple(Vec<Pattern>),
386 Variant {
388 variant: String,
390 patterns: Vec<Pattern>,
392 },
393}
394
395impl fmt::Display for Pattern {
396 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
397 match self {
398 Pattern::Wildcard => write!(f, "_"),
399 Pattern::Var(name) => write!(f, "{}", name),
400 Pattern::Literal(lit) => write!(f, "{}", lit),
401 Pattern::Tuple(patterns) => {
402 write!(f, "(")?;
403 for (i, pat) in patterns.iter().enumerate() {
404 if i > 0 {
405 write!(f, ", ")?;
406 }
407 write!(f, "{}", pat)?;
408 }
409 write!(f, ")")
410 }
411 Pattern::Variant { variant, patterns } => {
412 write!(f, "{}", variant)?;
413 if !patterns.is_empty() {
414 write!(f, "(")?;
415 for (i, pat) in patterns.iter().enumerate() {
416 if i > 0 {
417 write!(f, ", ")?;
418 }
419 write!(f, "{}", pat)?;
420 }
421 write!(f, ")")?;
422 }
423 Ok(())
424 }
425 }
426 }
427}
428
429impl Pattern {
430 pub fn is_wildcard(&self) -> bool {
432 matches!(self, Pattern::Wildcard)
433 }
434
435 pub fn is_var(&self) -> bool {
437 matches!(self, Pattern::Var(_))
438 }
439
440 pub fn is_literal(&self) -> bool {
442 matches!(self, Pattern::Literal(_))
443 }
444
445 pub fn is_tuple(&self) -> bool {
447 matches!(self, Pattern::Tuple(_))
448 }
449
450 pub fn as_var(&self) -> Option<&str> {
452 match self {
453 Pattern::Var(name) => Some(name),
454 _ => None,
455 }
456 }
457
458 pub fn as_literal(&self) -> Option<&Literal> {
460 match self {
461 Pattern::Literal(lit) => Some(lit),
462 _ => None,
463 }
464 }
465
466 pub fn as_tuple(&self) -> Option<&Vec<Pattern>> {
468 match self {
469 Pattern::Tuple(patterns) => Some(patterns),
470 _ => None,
471 }
472 }
473
474 pub fn is_variant(&self) -> bool {
476 matches!(self, Pattern::Variant { .. })
477 }
478
479 pub fn as_variant(&self) -> Option<(&str, &Vec<Pattern>)> {
481 match self {
482 Pattern::Variant { variant, patterns } => Some((variant, patterns)),
483 _ => None,
484 }
485 }
486}
487
488#[derive(Debug, Clone, PartialEq)]
492pub struct MatchArm {
493 pub pattern: Pattern,
495 pub body: Box<Expr>,
497}
498
499impl fmt::Display for MatchArm {
500 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
501 write!(f, "{} -> {}", self.pattern, self.body)
502 }
503}
504
505impl MatchArm {
506 pub fn new(pattern: Pattern, body: Expr) -> Self {
508 MatchArm {
509 pattern,
510 body: Box::new(body),
511 }
512 }
513
514 pub fn is_wildcard(&self) -> bool {
516 self.pattern.is_wildcard()
517 }
518
519 pub fn is_var(&self) -> bool {
521 self.pattern.is_var()
522 }
523}
524
525#[derive(Debug, Clone, PartialEq)]
527pub enum CEStatement {
528 Let { name: String, value: Box<Expr> },
530 LetBang { name: String, value: Box<Expr> },
532 DoBang { value: Box<Expr> },
534 Return { value: Box<Expr> },
536 ReturnBang { value: Box<Expr> },
538 Yield { value: Box<Expr> },
540 YieldBang { value: Box<Expr> },
542 Expr { value: Box<Expr> },
544}
545
546impl fmt::Display for CEStatement {
547 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
548 match self {
549 CEStatement::Let { name, value } => write!(f, "let {} = {}", name, value),
550 CEStatement::LetBang { name, value } => write!(f, "let! {} = {}", name, value),
551 CEStatement::DoBang { value } => write!(f, "do! {}", value),
552 CEStatement::Return { value } => write!(f, "return {}", value),
553 CEStatement::ReturnBang { value } => write!(f, "return! {}", value),
554 CEStatement::Yield { value } => write!(f, "yield {}", value),
555 CEStatement::YieldBang { value } => write!(f, "yield! {}", value),
556 CEStatement::Expr { value } => write!(f, "{}", value),
557 }
558 }
559}
560
561#[derive(Debug, Clone, PartialEq)]
565pub enum Expr {
566 Var(String),
568
569 Lit(Literal),
571
572 BinOp {
574 op: BinOp,
575 left: Box<Expr>,
576 right: Box<Expr>,
577 },
578
579 Let {
581 name: String,
582 value: Box<Expr>,
583 body: Box<Expr>,
584 },
585
586 LetRec {
588 name: String,
589 value: Box<Expr>,
590 body: Box<Expr>,
591 },
592
593 LetRecMutual {
595 bindings: Vec<(String, Expr)>,
596 body: Box<Expr>,
597 },
598
599 Lambda { param: String, body: Box<Expr> },
601
602 App { func: Box<Expr>, arg: Box<Expr> },
604
605 If {
607 cond: Box<Expr>,
608 then_branch: Box<Expr>,
609 else_branch: Box<Expr>,
610 },
611
612 Match {
614 scrutinee: Box<Expr>,
615 arms: Vec<MatchArm>,
616 },
617
618 Tuple(Vec<Expr>),
621
622 List(Vec<Expr>),
624
625 Cons { head: Box<Expr>, tail: Box<Expr> },
627
628 Array(Vec<Expr>),
630
631 ArrayIndex { array: Box<Expr>, index: Box<Expr> },
633
634 ArrayUpdate {
636 array: Box<Expr>,
637 index: Box<Expr>,
638 value: Box<Expr>,
639 },
640
641 ArrayLength(Box<Expr>),
643
644 RecordLiteral {
646 type_name: String, fields: RecordFields, },
649
650 RecordAccess { record: Box<Expr>, field: String },
652
653 RecordUpdate {
655 record: Box<Expr>,
656 fields: RecordFields, },
658
659 VariantConstruct {
661 type_name: String,
663 variant: String,
665 fields: Vec<Box<Expr>>,
667 },
668
669 MethodCall {
671 receiver: Box<Expr>,
673 method_name: String,
675 args: Vec<Expr>,
677 },
678
679 While {
681 cond: Box<Expr>,
683 body: Box<Expr>,
685 },
686
687 Break,
689
690 Continue,
692
693 ComputationExpr {
695 builder: String,
697 body: Vec<CEStatement>,
699 },
700}
701
702pub type RecordFields = Vec<(String, Box<Expr>)>;
704
705impl Expr {
706 pub fn is_literal(&self) -> bool {
708 matches!(self, Expr::Lit(_))
709 }
710
711 pub fn is_var(&self) -> bool {
713 matches!(self, Expr::Var(_))
714 }
715
716 pub fn is_binop(&self) -> bool {
718 matches!(self, Expr::BinOp { .. })
719 }
720
721 pub fn is_let(&self) -> bool {
723 matches!(self, Expr::Let { .. })
724 }
725
726 pub fn is_let_rec(&self) -> bool {
728 matches!(self, Expr::LetRec { .. })
729 }
730
731 pub fn is_let_rec_mutual(&self) -> bool {
733 matches!(self, Expr::LetRecMutual { .. })
734 }
735
736 pub fn is_lambda(&self) -> bool {
738 matches!(self, Expr::Lambda { .. })
739 }
740
741 pub fn is_app(&self) -> bool {
743 matches!(self, Expr::App { .. })
744 }
745
746 pub fn is_if(&self) -> bool {
748 matches!(self, Expr::If { .. })
749 }
750
751 pub fn is_match(&self) -> bool {
753 matches!(self, Expr::Match { .. })
754 }
755
756 pub fn is_tuple(&self) -> bool {
758 matches!(self, Expr::Tuple(_))
759 }
760
761 pub fn is_list(&self) -> bool {
763 matches!(self, Expr::List(_))
764 }
765
766 pub fn is_cons(&self) -> bool {
768 matches!(self, Expr::Cons { .. })
769 }
770
771 pub fn is_array(&self) -> bool {
773 matches!(self, Expr::Array(_))
774 }
775
776 pub fn is_array_index(&self) -> bool {
778 matches!(self, Expr::ArrayIndex { .. })
779 }
780
781 pub fn is_array_update(&self) -> bool {
783 matches!(self, Expr::ArrayUpdate { .. })
784 }
785
786 pub fn is_array_length(&self) -> bool {
788 matches!(self, Expr::ArrayLength(_))
789 }
790
791 pub fn is_record_literal(&self) -> bool {
793 matches!(self, Expr::RecordLiteral { .. })
794 }
795
796 pub fn is_record_access(&self) -> bool {
798 matches!(self, Expr::RecordAccess { .. })
799 }
800
801 pub fn is_record_update(&self) -> bool {
803 matches!(self, Expr::RecordUpdate { .. })
804 }
805
806 pub fn is_variant_construct(&self) -> bool {
808 matches!(self, Expr::VariantConstruct { .. })
809 }
810
811 pub fn is_method_call(&self) -> bool {
813 matches!(self, Expr::MethodCall { .. })
814 }
815
816 pub fn is_while(&self) -> bool {
818 matches!(self, Expr::While { .. })
819 }
820
821 pub fn is_break(&self) -> bool {
823 matches!(self, Expr::Break)
824 }
825
826 pub fn is_continue(&self) -> bool {
828 matches!(self, Expr::Continue)
829 }
830
831 pub fn is_computation_expr(&self) -> bool {
833 matches!(self, Expr::ComputationExpr { .. })
834 }
835
836 pub fn as_var(&self) -> Option<&str> {
838 match self {
839 Expr::Var(name) => Some(name),
840 _ => None,
841 }
842 }
843
844 pub fn as_literal(&self) -> Option<&Literal> {
846 match self {
847 Expr::Lit(lit) => Some(lit),
848 _ => None,
849 }
850 }
851
852 pub fn as_tuple(&self) -> Option<&Vec<Expr>> {
854 match self {
855 Expr::Tuple(elements) => Some(elements),
856 _ => None,
857 }
858 }
859
860 pub fn as_list(&self) -> Option<&Vec<Expr>> {
862 match self {
863 Expr::List(elements) => Some(elements),
864 _ => None,
865 }
866 }
867
868 pub fn as_cons(&self) -> Option<(&Expr, &Expr)> {
870 match self {
871 Expr::Cons { head, tail } => Some((head, tail)),
872 _ => None,
873 }
874 }
875
876 pub fn as_array(&self) -> Option<&Vec<Expr>> {
878 match self {
879 Expr::Array(elements) => Some(elements),
880 _ => None,
881 }
882 }
883
884 pub fn as_record_literal(&self) -> Option<(&str, &RecordFields)> {
886 match self {
887 Expr::RecordLiteral { type_name, fields } => Some((type_name, fields)),
888 _ => None,
889 }
890 }
891
892 pub fn as_match(&self) -> Option<(&Expr, &Vec<MatchArm>)> {
894 match self {
895 Expr::Match { scrutinee, arms } => Some((scrutinee, arms)),
896 _ => None,
897 }
898 }
899
900 pub fn as_computation_expr(&self) -> Option<(&str, &Vec<CEStatement>)> {
902 match self {
903 Expr::ComputationExpr { builder, body } => Some((builder, body)),
904 _ => None,
905 }
906 }
907}
908
909impl fmt::Display for Expr {
910 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
911 match self {
912 Expr::Var(name) => write!(f, "{}", name),
913 Expr::Lit(lit) => write!(f, "{}", lit),
914 Expr::BinOp { op, left, right } => {
915 write!(f, "({} {} {})", left, op, right)
916 }
917 Expr::Let { name, value, body } => {
918 write!(f, "(let {} = {} in {})", name, value, body)
919 }
920 Expr::LetRec { name, value, body } => {
921 write!(f, "(let rec {} = {} in {})", name, value, body)
922 }
923 Expr::LetRecMutual { bindings, body } => {
924 write!(f, "(let rec ")?;
925 for (i, (name, value)) in bindings.iter().enumerate() {
926 if i > 0 {
927 write!(f, " and ")?;
928 }
929 write!(f, "{} = {}", name, value)?;
930 }
931 write!(f, " in {})", body)
932 }
933 Expr::Lambda { param, body } => {
934 write!(f, "(fun {} -> {})", param, body)
935 }
936 Expr::App { func, arg } => {
937 write!(f, "({} {})", func, arg)
938 }
939 Expr::If {
940 cond,
941 then_branch,
942 else_branch,
943 } => {
944 write!(f, "(if {} then {} else {})", cond, then_branch, else_branch)
945 }
946 Expr::Match { scrutinee, arms } => {
947 write!(f, "(match {} with", scrutinee)?;
948 for arm in arms {
949 write!(f, " | {}", arm)?;
950 }
951 write!(f, ")")
952 }
953 Expr::Tuple(elements) => {
954 write!(f, "(")?;
955 for (i, element) in elements.iter().enumerate() {
956 if i > 0 {
957 write!(f, ", ")?;
958 }
959 write!(f, "{}", element)?;
960 }
961 write!(f, ")")
962 }
963 Expr::List(elements) => {
964 write!(f, "[")?;
965 for (i, element) in elements.iter().enumerate() {
966 if i > 0 {
967 write!(f, "; ")?;
968 }
969 write!(f, "{}", element)?;
970 }
971 write!(f, "]")
972 }
973 Expr::Cons { head, tail } => {
974 write!(f, "({} :: {})", head, tail)
975 }
976 Expr::Array(elements) => {
977 write!(f, "[|")?;
978 for (i, element) in elements.iter().enumerate() {
979 if i > 0 {
980 write!(f, "; ")?;
981 }
982 write!(f, "{}", element)?;
983 }
984 write!(f, "|]")
985 }
986 Expr::ArrayIndex { array, index } => {
987 write!(f, "({}.[{}])", array, index)
988 }
989 Expr::ArrayUpdate {
990 array,
991 index,
992 value,
993 } => {
994 write!(f, "({}.[{}] <- {})", array, index, value)
995 }
996 Expr::ArrayLength(arr) => {
997 write!(f, "(Array.length {})", arr)
998 }
999 Expr::RecordLiteral { type_name, fields } => {
1000 if !type_name.is_empty() {
1001 write!(f, "({} ", type_name)?;
1002 }
1003 write!(f, "{{ ")?;
1004 for (i, (field_name, field_expr)) in fields.iter().enumerate() {
1005 if i > 0 {
1006 write!(f, "; ")?;
1007 }
1008 write!(f, "{} = {}", field_name, field_expr)?;
1009 }
1010 write!(f, " }}")?;
1011 if !type_name.is_empty() {
1012 write!(f, ")")?;
1013 }
1014 Ok(())
1015 }
1016 Expr::RecordAccess { record, field } => {
1017 write!(f, "({}.{})", record, field)
1018 }
1019 Expr::RecordUpdate { record, fields } => {
1020 write!(f, "({{ {} with ", record)?;
1021 for (i, (field_name, field_expr)) in fields.iter().enumerate() {
1022 if i > 0 {
1023 write!(f, "; ")?;
1024 }
1025 write!(f, "{} = {}", field_name, field_expr)?;
1026 }
1027 write!(f, " }})")
1028 }
1029 Expr::VariantConstruct {
1030 type_name: _,
1031 variant,
1032 fields,
1033 } => {
1034 write!(f, "{}", variant)?;
1035 if !fields.is_empty() {
1036 write!(f, "(")?;
1037 for (i, field_expr) in fields.iter().enumerate() {
1038 if i > 0 {
1039 write!(f, ", ")?;
1040 }
1041 write!(f, "{}", field_expr)?;
1042 }
1043 write!(f, ")")?;
1044 }
1045 Ok(())
1046 }
1047 Expr::MethodCall {
1048 receiver,
1049 method_name,
1050 args,
1051 } => {
1052 write!(f, "({}.{}(", receiver, method_name)?;
1053 for (i, arg) in args.iter().enumerate() {
1054 if i > 0 {
1055 write!(f, ", ")?;
1056 }
1057 write!(f, "{}", arg)?;
1058 }
1059 write!(f, "))")
1060 }
1061 Expr::While { cond, body } => {
1062 write!(f, "(while {} do {})", cond, body)
1063 }
1064 Expr::Break => write!(f, "break"),
1065 Expr::Continue => write!(f, "continue"),
1066 Expr::ComputationExpr { builder, body } => {
1067 write!(f, "{} {{ ... ({} statements) }}", builder, body.len())
1068 }
1069 }
1070 }
1071}
1072#[derive(Debug, Clone, PartialEq)]
1081pub struct ModuleDef {
1082 pub name: String,
1084 pub items: Vec<ModuleItem>,
1086}
1087
1088impl fmt::Display for ModuleDef {
1089 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1090 write!(f, "module {} = ", self.name)?;
1091 for (i, item) in self.items.iter().enumerate() {
1092 if i > 0 {
1093 writeln!(f)?;
1094 }
1095 write!(f, "{}", item)?;
1096 }
1097 Ok(())
1098 }
1099}
1100
1101#[derive(Debug, Clone, PartialEq)]
1103pub enum ModuleItem {
1104 Let(Option<String>, Expr),
1106 LetRec(Vec<(String, Expr)>),
1108 TypeDef(TypeDefinition),
1110 Module(Box<ModuleDef>),
1112}
1113
1114impl fmt::Display for ModuleItem {
1115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1116 match self {
1117 ModuleItem::Let(name, expr) => {
1118 write!(f, "let {} = {}", name.as_deref().unwrap_or("_"), expr)
1119 }
1120 ModuleItem::LetRec(bindings) => {
1121 write!(f, "let rec ")?;
1122 for (i, (name, expr)) in bindings.iter().enumerate() {
1123 if i > 0 {
1124 write!(f, " and ")?;
1125 }
1126 write!(f, "{} = {}", name, expr)?;
1127 }
1128 Ok(())
1129 }
1130 ModuleItem::TypeDef(typedef) => write!(f, "{}", typedef),
1131 ModuleItem::Module(module_def) => write!(f, "{}", module_def),
1132 }
1133 }
1134}
1135
1136#[derive(Debug, Clone, PartialEq)]
1141pub struct Import {
1142 pub module_path: Vec<String>,
1144 pub is_qualified: bool,
1146}
1147
1148impl fmt::Display for Import {
1149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1150 if self.is_qualified {
1151 write!(f, "// qualified import: {}", self.module_path.join("."))
1152 } else {
1153 write!(f, "open {}", self.module_path.join("."))
1154 }
1155 }
1156}
1157
1158#[derive(Debug, Clone, PartialEq)]
1163pub struct LoadDirective {
1164 pub path: String,
1166}
1167
1168impl fmt::Display for LoadDirective {
1169 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1170 write!(f, "#load \"{}\"", self.path)
1171 }
1172}
1173
1174#[derive(Debug, Clone, PartialEq)]
1179pub struct Program {
1180 pub directives: Vec<LoadDirective>,
1182 pub modules: Vec<ModuleDef>,
1184 pub imports: Vec<Import>,
1186 pub items: Vec<ModuleItem>,
1188 pub main_expr: Option<Expr>,
1190}
1191
1192impl fmt::Display for Program {
1193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1194 for directive in &self.directives {
1195 writeln!(f, "{}", directive)?;
1196 }
1197 if !self.directives.is_empty() && (!self.imports.is_empty() || !self.modules.is_empty()) {
1198 writeln!(f)?;
1199 }
1200 for import in &self.imports {
1201 writeln!(f, "{}", import)?;
1202 }
1203 if !self.imports.is_empty() && !self.modules.is_empty() {
1204 writeln!(f)?;
1205 }
1206 for (i, module) in self.modules.iter().enumerate() {
1207 if i > 0 {
1208 writeln!(f)?;
1209 writeln!(f)?;
1210 }
1211 write!(f, "{}", module)?;
1212 }
1213 if !self.modules.is_empty() && !self.items.is_empty() {
1214 writeln!(f)?;
1215 writeln!(f)?;
1216 }
1217 for (i, item) in self.items.iter().enumerate() {
1218 if i > 0 {
1219 writeln!(f)?;
1220 }
1221 write!(f, "{}", item)?;
1222 }
1223 if let Some(ref expr) = self.main_expr {
1224 if !self.modules.is_empty() || !self.items.is_empty() {
1225 writeln!(f)?;
1226 writeln!(f)?;
1227 }
1228 write!(f, "{}", expr)?;
1229 }
1230 Ok(())
1231 }
1232}
1233
1234#[cfg(test)]
1235mod tests {
1236 use super::*;
1237
1238 #[test]
1243 fn test_literal_int() {
1244 let lit = Literal::Int(42);
1245 assert_eq!(lit, Literal::Int(42));
1246 assert_eq!(format!("{}", lit), "42");
1247 }
1248
1249 #[test]
1250 fn test_literal_float() {
1251 let lit = Literal::Float(2.5);
1252 assert_eq!(lit, Literal::Float(2.5));
1253 assert_eq!(format!("{}", lit), "2.5");
1254 }
1255
1256 #[test]
1257 fn test_literal_bool() {
1258 let lit_true = Literal::Bool(true);
1259 let lit_false = Literal::Bool(false);
1260 assert_eq!(lit_true, Literal::Bool(true));
1261 assert_eq!(lit_false, Literal::Bool(false));
1262 assert_eq!(format!("{}", lit_true), "true");
1263 assert_eq!(format!("{}", lit_false), "false");
1264 }
1265
1266 #[test]
1267 fn test_literal_str() {
1268 let lit = Literal::Str("hello".to_string());
1269 assert_eq!(lit, Literal::Str("hello".to_string()));
1270 assert_eq!(format!("{}", lit), "\"hello\"");
1271 }
1272
1273 #[test]
1274 fn test_literal_unit() {
1275 let lit = Literal::Unit;
1276 assert_eq!(lit, Literal::Unit);
1277 assert_eq!(format!("{}", lit), "()");
1278 }
1279
1280 #[test]
1281 fn test_literal_clone() {
1282 let lit = Literal::Int(42);
1283 let cloned = lit.clone();
1284 assert_eq!(lit, cloned);
1285 }
1286
1287 #[test]
1292 fn test_binop_arithmetic() {
1293 assert!(BinOp::Add.is_arithmetic());
1294 assert!(BinOp::Sub.is_arithmetic());
1295 assert!(BinOp::Mul.is_arithmetic());
1296 assert!(BinOp::Div.is_arithmetic());
1297 assert!(!BinOp::Eq.is_arithmetic());
1298 assert!(!BinOp::And.is_arithmetic());
1299 }
1300
1301 #[test]
1302 fn test_binop_comparison() {
1303 assert!(BinOp::Eq.is_comparison());
1304 assert!(BinOp::Neq.is_comparison());
1305 assert!(BinOp::Lt.is_comparison());
1306 assert!(BinOp::Lte.is_comparison());
1307 assert!(BinOp::Gt.is_comparison());
1308 assert!(BinOp::Gte.is_comparison());
1309 assert!(!BinOp::Add.is_comparison());
1310 assert!(!BinOp::And.is_comparison());
1311 }
1312
1313 #[test]
1314 fn test_binop_logical() {
1315 assert!(BinOp::And.is_logical());
1316 assert!(BinOp::Or.is_logical());
1317 assert!(!BinOp::Add.is_logical());
1318 assert!(!BinOp::Eq.is_logical());
1319 }
1320
1321 #[test]
1322 fn test_binop_display() {
1323 assert_eq!(format!("{}", BinOp::Add), "+");
1324 assert_eq!(format!("{}", BinOp::Sub), "-");
1325 assert_eq!(format!("{}", BinOp::Mul), "*");
1326 assert_eq!(format!("{}", BinOp::Div), "/");
1327 assert_eq!(format!("{}", BinOp::Eq), "=");
1328 assert_eq!(format!("{}", BinOp::Neq), "<>");
1329 assert_eq!(format!("{}", BinOp::Lt), "<");
1330 assert_eq!(format!("{}", BinOp::Lte), "<=");
1331 assert_eq!(format!("{}", BinOp::Gt), ">");
1332 assert_eq!(format!("{}", BinOp::Gte), ">=");
1333 assert_eq!(format!("{}", BinOp::And), "&&");
1334 assert_eq!(format!("{}", BinOp::Or), "||");
1335 }
1336
1337 #[test]
1342 fn test_type_expr_named() {
1343 let ty = TypeExpr::Named("int".to_string());
1344 assert_eq!(ty, TypeExpr::Named("int".to_string()));
1345 assert_eq!(format!("{}", ty), "int");
1346 }
1347
1348 #[test]
1349 fn test_type_expr_tuple() {
1350 let ty = TypeExpr::Tuple(vec![
1351 TypeExpr::Named("int".to_string()),
1352 TypeExpr::Named("string".to_string()),
1353 ]);
1354 assert_eq!(format!("{}", ty), "int * string");
1355 }
1356
1357 #[test]
1358 fn test_type_expr_function() {
1359 let ty = TypeExpr::Function(
1360 Box::new(TypeExpr::Named("int".to_string())),
1361 Box::new(TypeExpr::Named("string".to_string())),
1362 );
1363 assert_eq!(format!("{}", ty), "int -> string");
1364 }
1365
1366 #[test]
1367 fn test_type_expr_complex() {
1368 let ty = TypeExpr::Function(
1370 Box::new(TypeExpr::Tuple(vec![
1371 TypeExpr::Named("int".to_string()),
1372 TypeExpr::Named("string".to_string()),
1373 ])),
1374 Box::new(TypeExpr::Named("bool".to_string())),
1375 );
1376 assert_eq!(format!("{}", ty), "int * string -> bool");
1377 }
1378
1379 #[test]
1380 fn test_type_expr_clone() {
1381 let ty1 = TypeExpr::Named("int".to_string());
1382 let ty2 = ty1.clone();
1383 assert_eq!(ty1, ty2);
1384 }
1385
1386 #[test]
1391 fn test_record_typedef_empty() {
1392 let typedef = RecordTypeDef {
1393 name: "Empty".to_string(),
1394 fields: vec![],
1395 };
1396 assert_eq!(typedef.name, "Empty");
1397 assert_eq!(typedef.fields.len(), 0);
1398 assert_eq!(format!("{}", typedef), "type Empty = { }");
1399 }
1400
1401 #[test]
1402 fn test_record_typedef_single_field() {
1403 let typedef = RecordTypeDef {
1404 name: "Age".to_string(),
1405 fields: vec![("age".to_string(), TypeExpr::Named("int".to_string()))],
1406 };
1407 assert_eq!(typedef.name, "Age");
1408 assert_eq!(typedef.fields.len(), 1);
1409 assert_eq!(format!("{}", typedef), "type Age = { age: int }");
1410 }
1411
1412 #[test]
1413 fn test_record_typedef_multiple_fields() {
1414 let typedef = RecordTypeDef {
1415 name: "Person".to_string(),
1416 fields: vec![
1417 ("name".to_string(), TypeExpr::Named("string".to_string())),
1418 ("age".to_string(), TypeExpr::Named("int".to_string())),
1419 ("active".to_string(), TypeExpr::Named("bool".to_string())),
1420 ],
1421 };
1422 assert_eq!(typedef.name, "Person");
1423 assert_eq!(typedef.fields.len(), 3);
1424 assert_eq!(
1425 format!("{}", typedef),
1426 "type Person = { name: string; age: int; active: bool }"
1427 );
1428 }
1429
1430 #[test]
1431 fn test_record_typedef_with_tuple_type() {
1432 let typedef = RecordTypeDef {
1433 name: "Point".to_string(),
1434 fields: vec![(
1435 "coords".to_string(),
1436 TypeExpr::Tuple(vec![
1437 TypeExpr::Named("int".to_string()),
1438 TypeExpr::Named("int".to_string()),
1439 ]),
1440 )],
1441 };
1442 assert_eq!(format!("{}", typedef), "type Point = { coords: int * int }");
1443 }
1444
1445 #[test]
1446 fn test_record_typedef_with_function_type() {
1447 let typedef = RecordTypeDef {
1448 name: "Processor".to_string(),
1449 fields: vec![(
1450 "process".to_string(),
1451 TypeExpr::Function(
1452 Box::new(TypeExpr::Named("int".to_string())),
1453 Box::new(TypeExpr::Named("string".to_string())),
1454 ),
1455 )],
1456 };
1457 assert_eq!(
1458 format!("{}", typedef),
1459 "type Processor = { process: int -> string }"
1460 );
1461 }
1462
1463 #[test]
1464 fn test_record_typedef_clone() {
1465 let typedef1 = RecordTypeDef {
1466 name: "Person".to_string(),
1467 fields: vec![("name".to_string(), TypeExpr::Named("string".to_string()))],
1468 };
1469 let typedef2 = typedef1.clone();
1470 assert_eq!(typedef1, typedef2);
1471 }
1472
1473 #[test]
1478 fn test_declaration_typedef() {
1479 let decl = Declaration::TypeDef(TypeDefinition::Record(RecordTypeDef {
1480 name: "Person".to_string(),
1481 fields: vec![("name".to_string(), TypeExpr::Named("string".to_string()))],
1482 }));
1483 assert!(matches!(decl, Declaration::TypeDef(_)));
1484 assert_eq!(format!("{}", decl), "type Person = { name: string }");
1485 }
1486
1487 #[test]
1488 fn test_declaration_let_binding_simple() {
1489 let decl = Declaration::LetBinding {
1490 name: "x".to_string(),
1491 params: vec![],
1492 body: Box::new(Expr::Lit(Literal::Int(42))),
1493 };
1494 assert!(matches!(decl, Declaration::LetBinding { .. }));
1495 assert_eq!(format!("{}", decl), "let x = 42");
1496 }
1497
1498 #[test]
1499 fn test_declaration_let_binding_with_params() {
1500 let decl = Declaration::LetBinding {
1501 name: "add".to_string(),
1502 params: vec!["x".to_string(), "y".to_string()],
1503 body: Box::new(Expr::BinOp {
1504 op: BinOp::Add,
1505 left: Box::new(Expr::Var("x".to_string())),
1506 right: Box::new(Expr::Var("y".to_string())),
1507 }),
1508 };
1509 assert_eq!(format!("{}", decl), "let add x y = (x + y)");
1510 }
1511
1512 #[test]
1513 fn test_declaration_clone() {
1514 let decl1 = Declaration::TypeDef(TypeDefinition::Record(RecordTypeDef {
1515 name: "Person".to_string(),
1516 fields: vec![],
1517 }));
1518 let decl2 = decl1.clone();
1519 assert_eq!(decl1, decl2);
1520 }
1521
1522 #[test]
1527 fn test_module_empty() {
1528 let module = Module {
1529 declarations: vec![],
1530 };
1531 assert_eq!(module.declarations.len(), 0);
1532 assert_eq!(format!("{}", module), "");
1533 }
1534
1535 #[test]
1536 fn test_module_single_typedef() {
1537 let module = Module {
1538 declarations: vec![Declaration::TypeDef(TypeDefinition::Record(
1539 RecordTypeDef {
1540 name: "Person".to_string(),
1541 fields: vec![("name".to_string(), TypeExpr::Named("string".to_string()))],
1542 },
1543 ))],
1544 };
1545 assert_eq!(module.declarations.len(), 1);
1546 assert_eq!(format!("{}", module), "type Person = { name: string }");
1547 }
1548
1549 #[test]
1550 fn test_module_multiple_declarations() {
1551 let module = Module {
1552 declarations: vec![
1553 Declaration::TypeDef(TypeDefinition::Record(RecordTypeDef {
1554 name: "Person".to_string(),
1555 fields: vec![("name".to_string(), TypeExpr::Named("string".to_string()))],
1556 })),
1557 Declaration::LetBinding {
1558 name: "john".to_string(),
1559 params: vec![],
1560 body: Box::new(Expr::RecordLiteral {
1561 type_name: String::new(),
1562 fields: vec![(
1563 "name".to_string(),
1564 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1565 )],
1566 }),
1567 },
1568 ],
1569 };
1570 assert_eq!(module.declarations.len(), 2);
1571 }
1572
1573 #[test]
1574 fn test_module_clone() {
1575 let module1 = Module {
1576 declarations: vec![],
1577 };
1578 let module2 = module1.clone();
1579 assert_eq!(module1, module2);
1580 }
1581
1582 #[test]
1587 fn test_expr_record_literal_empty() {
1588 let expr = Expr::RecordLiteral {
1589 type_name: String::new(),
1590 fields: vec![],
1591 };
1592 assert!(expr.is_record_literal());
1593 assert!(!expr.is_literal());
1594 assert_eq!(format!("{}", expr), "{ }");
1595 }
1596
1597 #[test]
1598 fn test_expr_record_literal_single_field() {
1599 let expr = Expr::RecordLiteral {
1600 type_name: String::new(),
1601 fields: vec![(
1602 "name".to_string(),
1603 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1604 )],
1605 };
1606 assert!(expr.is_record_literal());
1607 assert_eq!(format!("{}", expr), "{ name = \"John\" }");
1608 }
1609
1610 #[test]
1611 fn test_expr_record_literal_multiple_fields() {
1612 let expr = Expr::RecordLiteral {
1613 type_name: String::new(),
1614 fields: vec![
1615 (
1616 "name".to_string(),
1617 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1618 ),
1619 ("age".to_string(), Box::new(Expr::Lit(Literal::Int(30)))),
1620 (
1621 "active".to_string(),
1622 Box::new(Expr::Lit(Literal::Bool(true))),
1623 ),
1624 ],
1625 };
1626 assert!(expr.is_record_literal());
1627 assert_eq!(
1628 format!("{}", expr),
1629 "{ name = \"John\"; age = 30; active = true }"
1630 );
1631 }
1632
1633 #[test]
1634 fn test_expr_record_literal_with_type_name() {
1635 let expr = Expr::RecordLiteral {
1636 type_name: "Person".to_string(),
1637 fields: vec![(
1638 "name".to_string(),
1639 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1640 )],
1641 };
1642 assert_eq!(format!("{}", expr), "(Person { name = \"John\" })");
1643 }
1644
1645 #[test]
1646 fn test_expr_record_access_simple() {
1647 let expr = Expr::RecordAccess {
1648 record: Box::new(Expr::Var("person".to_string())),
1649 field: "name".to_string(),
1650 };
1651 assert!(expr.is_record_access());
1652 assert!(!expr.is_record_literal());
1653 assert_eq!(format!("{}", expr), "(person.name)");
1654 }
1655
1656 #[test]
1657 fn test_expr_record_access_nested() {
1658 let expr = Expr::RecordAccess {
1659 record: Box::new(Expr::RecordAccess {
1660 record: Box::new(Expr::Var("company".to_string())),
1661 field: "employee".to_string(),
1662 }),
1663 field: "name".to_string(),
1664 };
1665 assert!(expr.is_record_access());
1666 assert_eq!(format!("{}", expr), "((company.employee).name)");
1667 }
1668
1669 #[test]
1670 fn test_expr_record_update_single_field() {
1671 let expr = Expr::RecordUpdate {
1672 record: Box::new(Expr::Var("person".to_string())),
1673 fields: vec![("age".to_string(), Box::new(Expr::Lit(Literal::Int(31))))],
1674 };
1675 assert!(expr.is_record_update());
1676 assert!(!expr.is_record_literal());
1677 assert_eq!(format!("{}", expr), "({ person with age = 31 })");
1678 }
1679
1680 #[test]
1681 fn test_expr_record_update_multiple_fields() {
1682 let expr = Expr::RecordUpdate {
1683 record: Box::new(Expr::Var("person".to_string())),
1684 fields: vec![
1685 ("age".to_string(), Box::new(Expr::Lit(Literal::Int(31)))),
1686 (
1687 "active".to_string(),
1688 Box::new(Expr::Lit(Literal::Bool(false))),
1689 ),
1690 ],
1691 };
1692 assert!(expr.is_record_update());
1693 assert_eq!(
1694 format!("{}", expr),
1695 "({ person with age = 31; active = false })"
1696 );
1697 }
1698
1699 #[test]
1700 fn test_expr_record_as_record_literal() {
1701 let expr = Expr::RecordLiteral {
1702 type_name: "Person".to_string(),
1703 fields: vec![(
1704 "name".to_string(),
1705 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1706 )],
1707 };
1708 let result = expr.as_record_literal();
1709 assert!(result.is_some());
1710 let (type_name, fields) = result.unwrap();
1711 assert_eq!(type_name, "Person");
1712 assert_eq!(fields.len(), 1);
1713 }
1714
1715 #[test]
1716 fn test_expr_record_clone() {
1717 let expr1 = Expr::RecordLiteral {
1718 type_name: String::new(),
1719 fields: vec![(
1720 "name".to_string(),
1721 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1722 )],
1723 };
1724 let expr2 = expr1.clone();
1725 assert_eq!(expr1, expr2);
1726 }
1727
1728 #[test]
1729 fn test_expr_record_equality() {
1730 let expr1 = Expr::RecordLiteral {
1731 type_name: String::new(),
1732 fields: vec![(
1733 "name".to_string(),
1734 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1735 )],
1736 };
1737 let expr2 = Expr::RecordLiteral {
1738 type_name: String::new(),
1739 fields: vec![(
1740 "name".to_string(),
1741 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1742 )],
1743 };
1744 assert_eq!(expr1, expr2);
1745 }
1746
1747 #[test]
1748 fn test_expr_record_inequality_different_fields() {
1749 let expr1 = Expr::RecordLiteral {
1750 type_name: String::new(),
1751 fields: vec![(
1752 "name".to_string(),
1753 Box::new(Expr::Lit(Literal::Str("John".to_string()))),
1754 )],
1755 };
1756 let expr2 = Expr::RecordLiteral {
1757 type_name: String::new(),
1758 fields: vec![(
1759 "name".to_string(),
1760 Box::new(Expr::Lit(Literal::Str("Jane".to_string()))),
1761 )],
1762 };
1763 assert_ne!(expr1, expr2);
1764 }
1765
1766 #[test]
1767 fn test_expr_record_literal_with_expressions() {
1768 let expr = Expr::RecordLiteral {
1769 type_name: String::new(),
1770 fields: vec![
1771 (
1772 "x".to_string(),
1773 Box::new(Expr::BinOp {
1774 op: BinOp::Add,
1775 left: Box::new(Expr::Lit(Literal::Int(1))),
1776 right: Box::new(Expr::Lit(Literal::Int(2))),
1777 }),
1778 ),
1779 (
1780 "y".to_string(),
1781 Box::new(Expr::BinOp {
1782 op: BinOp::Mul,
1783 left: Box::new(Expr::Lit(Literal::Int(3))),
1784 right: Box::new(Expr::Lit(Literal::Int(4))),
1785 }),
1786 ),
1787 ],
1788 };
1789 assert_eq!(format!("{}", expr), "{ x = (1 + 2); y = (3 * 4) }");
1790 }
1791
1792 #[test]
1793 fn test_expr_record_update_with_expression() {
1794 let expr = Expr::RecordUpdate {
1795 record: Box::new(Expr::Var("person".to_string())),
1796 fields: vec![(
1797 "age".to_string(),
1798 Box::new(Expr::BinOp {
1799 op: BinOp::Add,
1800 left: Box::new(Expr::RecordAccess {
1801 record: Box::new(Expr::Var("person".to_string())),
1802 field: "age".to_string(),
1803 }),
1804 right: Box::new(Expr::Lit(Literal::Int(1))),
1805 }),
1806 )],
1807 };
1808 assert_eq!(
1809 format!("{}", expr),
1810 "({ person with age = ((person.age) + 1) })"
1811 );
1812 }
1813
1814 #[test]
1815 fn test_expr_record_nested_literal() {
1816 let expr = Expr::RecordLiteral {
1818 type_name: String::new(),
1819 fields: vec![(
1820 "outer".to_string(),
1821 Box::new(Expr::RecordLiteral {
1822 type_name: String::new(),
1823 fields: vec![("inner".to_string(), Box::new(Expr::Lit(Literal::Int(42))))],
1824 }),
1825 )],
1826 };
1827 assert_eq!(format!("{}", expr), "{ outer = { inner = 42 } }");
1828 }
1829
1830 #[test]
1834 fn test_expr_var() {
1835 let expr = Expr::Var("x".to_string());
1836 assert!(expr.is_var());
1837 assert!(!expr.is_literal());
1838 assert_eq!(expr.as_var(), Some("x"));
1839 assert_eq!(format!("{}", expr), "x");
1840 }
1841
1842 #[test]
1843 fn test_expr_lit() {
1844 let expr = Expr::Lit(Literal::Int(42));
1845 assert!(expr.is_literal());
1846 assert!(!expr.is_var());
1847 assert_eq!(expr.as_literal(), Some(&Literal::Int(42)));
1848 assert_eq!(format!("{}", expr), "42");
1849 }
1850
1851 #[test]
1852 fn test_expr_tuple_pair() {
1853 let expr = Expr::Tuple(vec![Expr::Lit(Literal::Int(1)), Expr::Lit(Literal::Int(2))]);
1854 assert!(expr.is_tuple());
1855 assert!(!expr.is_literal());
1856 assert_eq!(format!("{}", expr), "(1, 2)");
1857 }
1858
1859 #[test]
1860 fn test_list_empty() {
1861 let expr = Expr::List(vec![]);
1862 assert!(expr.is_list());
1863 assert_eq!(format!("{}", expr), "[]");
1864 }
1865
1866 #[test]
1867 fn test_array_empty() {
1868 let expr = Expr::Array(vec![]);
1869 assert!(expr.is_array());
1870 assert_eq!(format!("{}", expr), "[||]");
1871 }
1872}
1873
1874#[test]
1879fn test_pattern_wildcard() {
1880 let pat = Pattern::Wildcard;
1881 assert!(pat.is_wildcard());
1882 assert!(!pat.is_var());
1883 assert!(!pat.is_literal());
1884 assert!(!pat.is_tuple());
1885 assert_eq!(format!("{}", pat), "_");
1886}
1887
1888#[test]
1889fn test_pattern_var() {
1890 let pat = Pattern::Var("x".to_string());
1891 assert!(pat.is_var());
1892 assert!(!pat.is_wildcard());
1893 assert!(!pat.is_literal());
1894 assert_eq!(pat.as_var(), Some("x"));
1895 assert_eq!(format!("{}", pat), "x");
1896}
1897
1898#[test]
1899fn test_pattern_literal_int() {
1900 let pat = Pattern::Literal(Literal::Int(42));
1901 assert!(pat.is_literal());
1902 assert!(!pat.is_var());
1903 assert!(!pat.is_wildcard());
1904 assert_eq!(pat.as_literal(), Some(&Literal::Int(42)));
1905 assert_eq!(format!("{}", pat), "42");
1906}
1907
1908#[test]
1909fn test_pattern_literal_bool() {
1910 let pat_true = Pattern::Literal(Literal::Bool(true));
1911 let pat_false = Pattern::Literal(Literal::Bool(false));
1912 assert!(pat_true.is_literal());
1913 assert!(pat_false.is_literal());
1914 assert_eq!(format!("{}", pat_true), "true");
1915 assert_eq!(format!("{}", pat_false), "false");
1916}
1917
1918#[test]
1919fn test_pattern_literal_string() {
1920 let pat = Pattern::Literal(Literal::Str("hello".to_string()));
1921 assert!(pat.is_literal());
1922 assert_eq!(format!("{}", pat), "\"hello\"");
1923}
1924
1925#[test]
1926fn test_pattern_tuple_empty() {
1927 let pat = Pattern::Tuple(vec![]);
1928 assert!(pat.is_tuple());
1929 assert!(!pat.is_literal());
1930 assert_eq!(pat.as_tuple(), Some(&vec![]));
1931 assert_eq!(format!("{}", pat), "()");
1932}
1933
1934#[test]
1935fn test_pattern_tuple_simple() {
1936 let pat = Pattern::Tuple(vec![
1937 Pattern::Var("x".to_string()),
1938 Pattern::Var("y".to_string()),
1939 ]);
1940 assert!(pat.is_tuple());
1941 assert_eq!(format!("{}", pat), "(x, y)");
1942}
1943
1944#[test]
1945fn test_pattern_tuple_mixed() {
1946 let pat = Pattern::Tuple(vec![
1947 Pattern::Literal(Literal::Int(0)),
1948 Pattern::Var("y".to_string()),
1949 Pattern::Wildcard,
1950 ]);
1951 assert!(pat.is_tuple());
1952 assert_eq!(format!("{}", pat), "(0, y, _)");
1953}
1954
1955#[test]
1956fn test_pattern_tuple_nested() {
1957 let pat = Pattern::Tuple(vec![
1958 Pattern::Var("x".to_string()),
1959 Pattern::Tuple(vec![
1960 Pattern::Var("y".to_string()),
1961 Pattern::Var("z".to_string()),
1962 ]),
1963 ]);
1964 assert!(pat.is_tuple());
1965 assert_eq!(format!("{}", pat), "(x, (y, z))");
1966}
1967
1968#[test]
1969fn test_pattern_clone() {
1970 let pat1 = Pattern::Var("x".to_string());
1971 let pat2 = pat1.clone();
1972 assert_eq!(pat1, pat2);
1973}
1974
1975#[test]
1976fn test_pattern_equality() {
1977 let pat1 = Pattern::Var("x".to_string());
1978 let pat2 = Pattern::Var("x".to_string());
1979 let pat3 = Pattern::Var("y".to_string());
1980 assert_eq!(pat1, pat2);
1981 assert_ne!(pat1, pat3);
1982}
1983
1984#[test]
1985fn test_pattern_as_var_none() {
1986 let pat = Pattern::Wildcard;
1987 assert_eq!(pat.as_var(), None);
1988}
1989
1990#[test]
1991fn test_pattern_as_literal_none() {
1992 let pat = Pattern::Var("x".to_string());
1993 assert_eq!(pat.as_literal(), None);
1994}
1995
1996#[test]
1997fn test_pattern_as_tuple_none() {
1998 let pat = Pattern::Wildcard;
1999 assert_eq!(pat.as_tuple(), None);
2000}
2001
2002#[test]
2003fn test_pattern_all_variants() {
2004 let patterns = [
2005 Pattern::Wildcard,
2006 Pattern::Var("x".to_string()),
2007 Pattern::Literal(Literal::Int(42)),
2008 Pattern::Tuple(vec![Pattern::Wildcard]),
2009 ];
2010 assert_eq!(patterns.len(), 4);
2011}
2012
2013#[test]
2018fn test_match_arm_simple() {
2019 let arm = MatchArm::new(Pattern::Wildcard, Expr::Lit(Literal::Int(42)));
2020 assert!(arm.is_wildcard());
2021 assert!(!arm.is_var());
2022 assert_eq!(format!("{}", arm), "_ -> 42");
2023}
2024
2025#[test]
2026fn test_match_arm_with_var() {
2027 let arm = MatchArm::new(Pattern::Var("x".to_string()), Expr::Var("x".to_string()));
2028 assert!(arm.is_var());
2029 assert!(!arm.is_wildcard());
2030 assert_eq!(format!("{}", arm), "x -> x");
2031}
2032
2033#[test]
2034fn test_match_arm_with_literal() {
2035 let arm = MatchArm::new(
2036 Pattern::Literal(Literal::Int(0)),
2037 Expr::Lit(Literal::Str("zero".to_string())),
2038 );
2039 assert!(!arm.is_wildcard());
2040 assert!(!arm.is_var());
2041 assert_eq!(format!("{}", arm), "0 -> \"zero\"");
2042}
2043
2044#[test]
2045fn test_match_arm_with_tuple_pattern() {
2046 let arm = MatchArm::new(
2047 Pattern::Tuple(vec![
2048 Pattern::Var("x".to_string()),
2049 Pattern::Var("y".to_string()),
2050 ]),
2051 Expr::BinOp {
2052 op: BinOp::Add,
2053 left: Box::new(Expr::Var("x".to_string())),
2054 right: Box::new(Expr::Var("y".to_string())),
2055 },
2056 );
2057 assert_eq!(format!("{}", arm), "(x, y) -> (x + y)");
2058}
2059
2060#[test]
2061fn test_match_arm_clone() {
2062 let arm1 = MatchArm::new(Pattern::Wildcard, Expr::Lit(Literal::Int(42)));
2063 let arm2 = arm1.clone();
2064 assert_eq!(arm1, arm2);
2065}
2066
2067#[test]
2068fn test_match_arm_equality() {
2069 let arm1 = MatchArm::new(Pattern::Wildcard, Expr::Lit(Literal::Int(42)));
2070 let arm2 = MatchArm::new(Pattern::Wildcard, Expr::Lit(Literal::Int(42)));
2071 assert_eq!(arm1, arm2);
2072}
2073
2074#[test]
2079fn test_expr_match_simple() {
2080 let expr = Expr::Match {
2081 scrutinee: Box::new(Expr::Var("x".to_string())),
2082 arms: vec![
2083 MatchArm::new(
2084 Pattern::Literal(Literal::Int(0)),
2085 Expr::Lit(Literal::Str("zero".to_string())),
2086 ),
2087 MatchArm::new(
2088 Pattern::Wildcard,
2089 Expr::Lit(Literal::Str("nonzero".to_string())),
2090 ),
2091 ],
2092 };
2093 assert!(expr.is_match());
2094 assert!(!expr.is_if());
2095 assert_eq!(
2096 format!("{}", expr),
2097 "(match x with | 0 -> \"zero\" | _ -> \"nonzero\")"
2098 );
2099}
2100
2101#[test]
2102fn test_expr_match_multiple_arms() {
2103 let expr = Expr::Match {
2104 scrutinee: Box::new(Expr::Var("n".to_string())),
2105 arms: vec![
2106 MatchArm::new(
2107 Pattern::Literal(Literal::Int(0)),
2108 Expr::Lit(Literal::Str("zero".to_string())),
2109 ),
2110 MatchArm::new(
2111 Pattern::Literal(Literal::Int(1)),
2112 Expr::Lit(Literal::Str("one".to_string())),
2113 ),
2114 MatchArm::new(
2115 Pattern::Literal(Literal::Int(2)),
2116 Expr::Lit(Literal::Str("two".to_string())),
2117 ),
2118 MatchArm::new(
2119 Pattern::Wildcard,
2120 Expr::Lit(Literal::Str("many".to_string())),
2121 ),
2122 ],
2123 };
2124 assert!(expr.is_match());
2125 assert_eq!(expr.as_match().unwrap().1.len(), 4);
2126}
2127
2128#[test]
2129fn test_expr_match_with_var_binding() {
2130 let expr = Expr::Match {
2131 scrutinee: Box::new(Expr::Var("x".to_string())),
2132 arms: vec![
2133 MatchArm::new(
2134 Pattern::Literal(Literal::Int(0)),
2135 Expr::Lit(Literal::Str("zero".to_string())),
2136 ),
2137 MatchArm::new(Pattern::Var("n".to_string()), Expr::Var("n".to_string())),
2138 ],
2139 };
2140 assert!(expr.is_match());
2141 let (scrutinee, arms) = expr.as_match().unwrap();
2142 assert_eq!(scrutinee.as_var(), Some("x"));
2143 assert_eq!(arms.len(), 2);
2144 assert!(arms[1].is_var());
2145}
2146
2147#[test]
2148fn test_expr_match_with_tuple_pattern() {
2149 let expr = Expr::Match {
2150 scrutinee: Box::new(Expr::Var("pair".to_string())),
2151 arms: vec![
2152 MatchArm::new(
2153 Pattern::Tuple(vec![
2154 Pattern::Literal(Literal::Int(0)),
2155 Pattern::Literal(Literal::Int(0)),
2156 ]),
2157 Expr::Lit(Literal::Str("origin".to_string())),
2158 ),
2159 MatchArm::new(
2160 Pattern::Tuple(vec![
2161 Pattern::Var("x".to_string()),
2162 Pattern::Var("y".to_string()),
2163 ]),
2164 Expr::Lit(Literal::Str("point".to_string())),
2165 ),
2166 ],
2167 };
2168 assert!(expr.is_match());
2169 let (_, arms) = expr.as_match().unwrap();
2170 assert_eq!(arms.len(), 2);
2171 assert!(arms[0].pattern.is_tuple());
2172}
2173
2174#[test]
2175fn test_expr_match_nested_in_let() {
2176 let expr = Expr::Let {
2177 name: "result".to_string(),
2178 value: Box::new(Expr::Match {
2179 scrutinee: Box::new(Expr::Var("x".to_string())),
2180 arms: vec![
2181 MatchArm::new(
2182 Pattern::Literal(Literal::Int(0)),
2183 Expr::Lit(Literal::Int(1)),
2184 ),
2185 MatchArm::new(Pattern::Wildcard, Expr::Lit(Literal::Int(0))),
2186 ],
2187 }),
2188 body: Box::new(Expr::Var("result".to_string())),
2189 };
2190 assert!(expr.is_let());
2191 if let Expr::Let { value, .. } = &expr {
2192 assert!(value.is_match());
2193 }
2194}
2195
2196#[test]
2197fn test_expr_match_with_bool_patterns() {
2198 let expr = Expr::Match {
2199 scrutinee: Box::new(Expr::Var("flag".to_string())),
2200 arms: vec![
2201 MatchArm::new(
2202 Pattern::Literal(Literal::Bool(true)),
2203 Expr::Lit(Literal::Str("yes".to_string())),
2204 ),
2205 MatchArm::new(
2206 Pattern::Literal(Literal::Bool(false)),
2207 Expr::Lit(Literal::Str("no".to_string())),
2208 ),
2209 ],
2210 };
2211 assert!(expr.is_match());
2212}
2213
2214#[test]
2215fn test_expr_match_as_match() {
2216 let expr = Expr::Match {
2217 scrutinee: Box::new(Expr::Var("x".to_string())),
2218 arms: vec![MatchArm::new(
2219 Pattern::Wildcard,
2220 Expr::Lit(Literal::Int(42)),
2221 )],
2222 };
2223 let result = expr.as_match();
2224 assert!(result.is_some());
2225 let (scrutinee, arms) = result.unwrap();
2226 assert_eq!(scrutinee.as_var(), Some("x"));
2227 assert_eq!(arms.len(), 1);
2228}
2229
2230#[test]
2231fn test_expr_match_as_match_none() {
2232 let expr = Expr::Lit(Literal::Int(42));
2233 assert_eq!(expr.as_match(), None);
2234}
2235
2236#[test]
2237fn test_expr_match_clone() {
2238 let expr1 = Expr::Match {
2239 scrutinee: Box::new(Expr::Var("x".to_string())),
2240 arms: vec![MatchArm::new(
2241 Pattern::Wildcard,
2242 Expr::Lit(Literal::Int(42)),
2243 )],
2244 };
2245 let expr2 = expr1.clone();
2246 assert_eq!(expr1, expr2);
2247}
2248
2249#[test]
2250fn test_expr_match_equality() {
2251 let expr1 = Expr::Match {
2252 scrutinee: Box::new(Expr::Var("x".to_string())),
2253 arms: vec![MatchArm::new(
2254 Pattern::Wildcard,
2255 Expr::Lit(Literal::Int(42)),
2256 )],
2257 };
2258 let expr2 = Expr::Match {
2259 scrutinee: Box::new(Expr::Var("x".to_string())),
2260 arms: vec![MatchArm::new(
2261 Pattern::Wildcard,
2262 Expr::Lit(Literal::Int(42)),
2263 )],
2264 };
2265 assert_eq!(expr1, expr2);
2266}
2267
2268#[test]
2269fn test_expr_match_complex_body() {
2270 let expr = Expr::Match {
2271 scrutinee: Box::new(Expr::Var("x".to_string())),
2272 arms: vec![
2273 MatchArm::new(
2274 Pattern::Literal(Literal::Int(0)),
2275 Expr::BinOp {
2276 op: BinOp::Add,
2277 left: Box::new(Expr::Lit(Literal::Int(1))),
2278 right: Box::new(Expr::Lit(Literal::Int(2))),
2279 },
2280 ),
2281 MatchArm::new(Pattern::Wildcard, Expr::Lit(Literal::Int(0))),
2282 ],
2283 };
2284 assert!(expr.is_match());
2285}