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