1pub use oxur_smap::NodeId;
9
10#[derive(Debug, Clone)]
12pub enum CoreForm {
13 Symbol {
15 id: NodeId,
16 name: String,
17 },
18 Number {
19 id: NodeId,
20 value: i64,
21 },
22 String {
23 id: NodeId,
24 value: String,
25 },
26
27 List {
29 id: NodeId,
30 elements: Vec<CoreForm>,
31 },
32
33 DefineFunc {
35 id: NodeId,
36 name: String,
37 params: Vec<String>,
38 body: Box<CoreForm>,
39 },
40
41 IfExpr {
42 id: NodeId,
43 condition: Box<CoreForm>,
44 then_branch: Box<CoreForm>,
45 else_branch: Option<Box<CoreForm>>,
46 },
47
48 MatchExpr {
49 id: NodeId,
50 scrutinee: Box<CoreForm>,
51 arms: Vec<MatchArm>,
52 },
53}
54
55#[derive(Debug, Clone)]
56pub struct MatchArm {
57 pub pattern: CoreForm,
58 pub body: CoreForm,
59}
60
61impl CoreForm {
62 pub fn node_id(&self) -> NodeId {
63 match self {
64 CoreForm::Symbol { id, .. } => *id,
65 CoreForm::Number { id, .. } => *id,
66 CoreForm::String { id, .. } => *id,
67 CoreForm::List { id, .. } => *id,
68 CoreForm::DefineFunc { id, .. } => *id,
69 CoreForm::IfExpr { id, .. } => *id,
70 CoreForm::MatchExpr { id, .. } => *id,
71 }
72 }
73}
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78
79 #[test]
80 fn test_node_id() {
81 let id = NodeId::from_raw(42);
82 assert_eq!(id.as_raw(), 42);
83 }
84
85 #[test]
86 fn test_core_form_node_id() {
87 let form = CoreForm::Number { id: NodeId::from_raw(1), value: 42 };
88 assert_eq!(form.node_id().as_raw(), 1);
89 }
90
91 #[test]
92 fn test_node_id_display() {
93 let id = NodeId::from_raw(123);
94 assert_eq!(format!("{}", id), "NodeId(123)");
95 }
96
97 #[test]
98 fn test_node_id_equality() {
99 let id1 = NodeId::from_raw(42);
100 let id2 = NodeId::from_raw(42);
101 let id3 = NodeId::from_raw(43);
102 assert_eq!(id1, id2);
103 assert_ne!(id1, id3);
104 }
105
106 #[test]
107 fn test_symbol_node_id() {
108 let form = CoreForm::Symbol { id: NodeId::from_raw(10), name: "foo".to_string() };
109 assert_eq!(form.node_id().as_raw(), 10);
110 }
111
112 #[test]
113 fn test_string_node_id() {
114 let form = CoreForm::String { id: NodeId::from_raw(20), value: "hello".to_string() };
115 assert_eq!(form.node_id().as_raw(), 20);
116 }
117
118 #[test]
119 fn test_list_node_id() {
120 let form = CoreForm::List { id: NodeId::from_raw(30), elements: vec![] };
121 assert_eq!(form.node_id().as_raw(), 30);
122 }
123
124 #[test]
125 fn test_define_func_node_id() {
126 let form = CoreForm::DefineFunc {
127 id: NodeId::from_raw(40),
128 name: "test".to_string(),
129 params: vec![],
130 body: Box::new(CoreForm::Number { id: NodeId::from_raw(41), value: 0 }),
131 };
132 assert_eq!(form.node_id().as_raw(), 40);
133 }
134
135 #[test]
136 fn test_if_expr_node_id() {
137 let form = CoreForm::IfExpr {
138 id: NodeId::from_raw(50),
139 condition: Box::new(CoreForm::Symbol {
140 id: NodeId::from_raw(51),
141 name: "true".to_string(),
142 }),
143 then_branch: Box::new(CoreForm::Number { id: NodeId::from_raw(52), value: 1 }),
144 else_branch: None,
145 };
146 assert_eq!(form.node_id().as_raw(), 50);
147 }
148
149 #[test]
150 fn test_match_expr_node_id() {
151 let form = CoreForm::MatchExpr {
152 id: NodeId::from_raw(60),
153 scrutinee: Box::new(CoreForm::Symbol {
154 id: NodeId::from_raw(61),
155 name: "x".to_string(),
156 }),
157 arms: vec![],
158 };
159 assert_eq!(form.node_id().as_raw(), 60);
160 }
161
162 #[test]
163 fn test_match_arm_creation() {
164 let arm = MatchArm {
165 pattern: CoreForm::Symbol { id: NodeId::from_raw(70), name: "pattern".to_string() },
166 body: CoreForm::Number { id: NodeId::from_raw(71), value: 42 },
167 };
168 assert_eq!(arm.pattern.node_id().as_raw(), 70);
169 assert_eq!(arm.body.node_id().as_raw(), 71);
170 }
171}