1use crate::core_forms::CoreForm;
7use crate::parser::SurfaceForm;
8use crate::Result;
9use oxur_smap::SourceMap;
10
11pub struct Expander {
13 source_map: SourceMap,
14}
15
16impl Expander {
17 pub fn new() -> Self {
18 Self { source_map: SourceMap::new() }
19 }
20
21 pub fn expand(&mut self, forms: Vec<SurfaceForm>) -> Result<Vec<CoreForm>> {
23 let mut core_forms = Vec::new();
24
25 for form in forms {
26 core_forms.push(self.expand_form(form)?);
27 }
28
29 Ok(core_forms)
30 }
31
32 fn expand_form(&mut self, form: SurfaceForm) -> Result<CoreForm> {
33 match form {
34 SurfaceForm::Symbol { name, span } => {
35 let id = oxur_smap::new_node_id();
36 let pos = Self::span_to_source_pos(&span);
37 self.source_map.record_surface_node(id, pos);
38 Ok(CoreForm::Symbol { id, name })
39 }
40 SurfaceForm::Number { value, span } => {
41 let id = oxur_smap::new_node_id();
42 let pos = Self::span_to_source_pos(&span);
43 self.source_map.record_surface_node(id, pos);
44 Ok(CoreForm::Number { id, value })
45 }
46 SurfaceForm::String { value, span } => {
47 let id = oxur_smap::new_node_id();
48 let pos = Self::span_to_source_pos(&span);
49 self.source_map.record_surface_node(id, pos);
50 Ok(CoreForm::String { id, value })
51 }
52 SurfaceForm::List { elements, span } => {
53 if !elements.is_empty() {
55 if let SurfaceForm::Symbol { ref name, .. } = elements[0] {
56 if name == "deffn" {
57 return self.expand_deffn(elements, span);
58 }
59 }
60 }
61
62 self.expand_list(elements, span)
64 }
65 }
66 }
67
68 fn span_to_source_pos(span: &oxur_smap::Span) -> oxur_smap::SourcePos {
70 oxur_smap::SourcePos::new(
72 span.file.clone(),
73 span.start_line,
74 span.start_column,
75 1, )
77 }
78
79 fn expand_deffn(
80 &mut self,
81 elements: Vec<SurfaceForm>,
82 span: oxur_smap::Span,
83 ) -> Result<CoreForm> {
84 if elements.len() < 4 {
86 return Err(crate::Error::Syntax(
87 "deffn requires at least name, params, and body".to_string(),
88 ));
89 }
90
91 let id = oxur_smap::new_node_id();
92 let pos = Self::span_to_source_pos(&span);
93 self.source_map.record_surface_node(id, pos);
94
95 let name = match &elements[1] {
97 SurfaceForm::Symbol { name, .. } => name.clone(),
98 _ => return Err(crate::Error::Syntax("deffn name must be a symbol".to_string())),
99 };
100
101 let params = match &elements[2] {
103 SurfaceForm::List { elements: param_list, .. } => {
104 let mut params = Vec::new();
105 for param in param_list {
106 if let SurfaceForm::Symbol { name, .. } = param {
107 params.push(name.clone());
108 } else {
109 return Err(crate::Error::Syntax("Parameter must be a symbol".to_string()));
110 }
111 }
112 params
113 }
114 _ => return Err(crate::Error::Syntax("deffn params must be a list".to_string())),
115 };
116
117 let body = if elements.len() > 3 {
119 Box::new(self.expand_form(elements[3].clone())?)
120 } else {
121 return Err(crate::Error::Syntax("deffn requires a body".to_string()));
122 };
123
124 Ok(CoreForm::DefineFunc { id, name, params, body })
125 }
126
127 fn expand_list(
128 &mut self,
129 elements: Vec<SurfaceForm>,
130 span: oxur_smap::Span,
131 ) -> Result<CoreForm> {
132 let id = oxur_smap::new_node_id();
133 let pos = Self::span_to_source_pos(&span);
134 self.source_map.record_surface_node(id, pos);
135
136 let mut expanded_elements = Vec::new();
137 for element in elements {
138 expanded_elements.push(self.expand_form(element)?);
139 }
140
141 Ok(CoreForm::List { id, elements: expanded_elements })
142 }
143
144 pub fn source_map(&self) -> &SourceMap {
146 &self.source_map
147 }
148
149 pub fn is_empty(&self) -> bool {
151 let stats = self.source_map.stats();
152 stats.surface_nodes == 0 && stats.expansions == 0 && stats.lowerings == 0
153 }
154}
155
156impl Default for Expander {
157 fn default() -> Self {
158 Self::new()
159 }
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn test_expander_creation() {
168 let expander = Expander::new();
169 assert!(expander.is_empty());
170 }
171
172 #[test]
173 fn test_expander_default() {
174 let expander = Expander::default();
175 assert!(expander.is_empty());
176 }
177
178 #[test]
179 fn test_expand_empty() {
180 let mut expander = Expander::new();
181 let result = expander.expand(vec![]);
182 assert!(result.is_ok());
183 assert_eq!(result.unwrap().len(), 0);
184 }
185
186 #[test]
187 fn test_source_map_access() {
188 let expander = Expander::new();
189 let _map = expander.source_map();
190 assert!(expander.is_empty());
191 }
192
193 #[test]
194 fn test_expand_deffn_hello_world() {
195 use crate::parser::Parser;
196
197 let source = r#"(deffn main ()
198 (println! "Hello, world!"))"#;
199
200 let mut parser = Parser::new(source.to_string());
201 let surface_forms = parser.parse().unwrap();
202
203 let mut expander = Expander::new();
204 let core_forms = expander.expand(surface_forms).unwrap();
205
206 assert_eq!(core_forms.len(), 1);
207
208 if let CoreForm::DefineFunc { name, params, body, .. } = &core_forms[0] {
210 assert_eq!(name, "main");
211 assert_eq!(params.len(), 0); if let CoreForm::List { elements, .. } = &**body {
215 assert_eq!(elements.len(), 2);
216
217 if let CoreForm::Symbol { name, .. } = &elements[0] {
219 assert_eq!(name, "println!");
220 } else {
221 panic!("Expected Symbol(println!)");
222 }
223
224 if let CoreForm::String { value, .. } = &elements[1] {
226 assert_eq!(value, "Hello, world!");
227 } else {
228 panic!("Expected String");
229 }
230 } else {
231 panic!("Expected List as body");
232 }
233 } else {
234 panic!("Expected DefineFunc");
235 }
236 }
237
238 #[test]
239 fn test_expand_symbol() {
240 use oxur_smap::Span;
241
242 let mut expander = Expander::new();
243 let span = Span::repl(1, 1, 1, 5);
244 let surface = SurfaceForm::Symbol { span, name: "test".to_string() };
245 let result = expander.expand_form(surface).unwrap();
246
247 if let CoreForm::Symbol { name, .. } = result {
248 assert_eq!(name, "test");
249 } else {
250 panic!("Expected Symbol");
251 }
252 }
253
254 #[test]
255 fn test_expand_number() {
256 use oxur_smap::Span;
257
258 let mut expander = Expander::new();
259 let span = Span::repl(1, 1, 1, 3);
260 let surface = SurfaceForm::Number { span, value: 42 };
261 let result = expander.expand_form(surface).unwrap();
262
263 if let CoreForm::Number { value, .. } = result {
264 assert_eq!(value, 42);
265 } else {
266 panic!("Expected Number");
267 }
268 }
269
270 #[test]
271 fn test_expand_string() {
272 use oxur_smap::Span;
273
274 let mut expander = Expander::new();
275 let span = Span::repl(1, 1, 1, 7);
276 let surface = SurfaceForm::String { span, value: "hello".to_string() };
277 let result = expander.expand_form(surface).unwrap();
278
279 if let CoreForm::String { value, .. } = result {
280 assert_eq!(value, "hello");
281 } else {
282 panic!("Expected String");
283 }
284 }
285
286 #[test]
287 fn test_source_map_symbol() {
288 use crate::parser::Parser;
289
290 let source = "hello";
291 let mut parser = Parser::new(source.to_string());
292 let forms = parser.parse().unwrap();
293
294 let mut expander = Expander::new();
295 let core_forms = expander.expand(forms).unwrap();
296
297 if let CoreForm::Symbol { id, .. } = &core_forms[0] {
299 let source_map = expander.source_map();
301 let pos = source_map.get_surface_position(id);
302
303 assert!(pos.is_some(), "Mapping should be recorded");
304 let pos = pos.unwrap();
305 assert_eq!(pos.line, 1);
306 assert_eq!(pos.column, 1);
307 } else {
308 panic!("Expected Symbol");
309 }
310 }
311
312 #[test]
313 fn test_source_map_number() {
314 use crate::parser::Parser;
315
316 let source = "42";
317 let mut parser = Parser::new(source.to_string());
318 let forms = parser.parse().unwrap();
319
320 let mut expander = Expander::new();
321 let core_forms = expander.expand(forms).unwrap();
322
323 if let CoreForm::Number { id, .. } = &core_forms[0] {
324 let source_map = expander.source_map();
325 let pos = source_map.get_surface_position(id);
326
327 assert!(pos.is_some());
328 let pos = pos.unwrap();
329 assert_eq!(pos.line, 1);
330 assert_eq!(pos.column, 1);
331 } else {
332 panic!("Expected Number");
333 }
334 }
335
336 #[test]
337 fn test_source_map_list() {
338 use crate::parser::Parser;
339
340 let source = "(+ 1 2)";
341 let mut parser = Parser::new(source.to_string());
342 let forms = parser.parse().unwrap();
343
344 let mut expander = Expander::new();
345 let core_forms = expander.expand(forms).unwrap();
346
347 if let CoreForm::List { id, elements, .. } = &core_forms[0] {
348 let source_map = expander.source_map();
349
350 let list_pos = source_map.get_surface_position(id);
352 assert!(list_pos.is_some());
353 assert_eq!(list_pos.unwrap().line, 1);
354
355 if let CoreForm::Symbol { id: elem_id, .. } = &elements[0] {
357 let elem_pos = source_map.get_surface_position(elem_id);
358 assert!(elem_pos.is_some());
359 assert_eq!(elem_pos.unwrap().column, 2); } else {
361 panic!("Expected Symbol");
362 }
363 } else {
364 panic!("Expected List");
365 }
366 }
367
368 #[test]
369 fn test_source_map_deffn() {
370 use crate::parser::Parser;
371
372 let source = "(deffn main () 42)";
373 let mut parser = Parser::new(source.to_string());
374 let forms = parser.parse().unwrap();
375
376 let mut expander = Expander::new();
377 let core_forms = expander.expand(forms).unwrap();
378
379 if let CoreForm::DefineFunc { id, .. } = &core_forms[0] {
380 let source_map = expander.source_map();
381 let pos = source_map.get_surface_position(id);
382
383 assert!(pos.is_some());
384 assert_eq!(pos.unwrap().line, 1);
385 assert_eq!(pos.unwrap().column, 1);
386 } else {
387 panic!("Expected DefineFunc");
388 }
389 }
390
391 #[test]
392 fn test_source_map_stats() {
393 use crate::parser::Parser;
394
395 let source = "(+ 1 2)"; let mut parser = Parser::new(source.to_string());
397 let forms = parser.parse().unwrap();
398
399 let mut expander = Expander::new();
400 let _core_forms = expander.expand(forms).unwrap();
401
402 let source_map = expander.source_map();
403 let stats = source_map.stats();
404
405 assert_eq!(stats.surface_nodes, 4);
407 assert_eq!(stats.expansions, 0); assert_eq!(stats.lowerings, 0); }
410}