1pub mod core_forms;
11pub mod expander;
12pub mod parser;
13pub mod source_map;
14
15pub use core_forms::{CoreForm, NodeId};
16pub use expander::Expander;
17pub use parser::Parser;
18pub use source_map::SourceMap;
19
20pub type Result<T> = std::result::Result<T, Error>;
22
23#[derive(Debug, thiserror::Error)]
25pub enum Error {
26 #[error("Parse error at {location}: {message}")]
27 Parse { message: String, location: Location },
28
29 #[error("Expansion error at node {node_id}: {message}")]
30 Expand { message: String, node_id: NodeId },
31
32 #[error("Invalid syntax: {0}")]
33 Syntax(String),
34}
35
36#[derive(Debug, Clone, Copy)]
38pub struct Location {
39 pub line: usize,
40 pub column: usize,
41}
42
43impl std::fmt::Display for Location {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 write!(f, "{}:{}", self.line, self.column)
46 }
47}
48
49#[cfg(test)]
50mod tests {
51 use super::*;
52
53 #[test]
54 fn test_location_display() {
55 let loc = Location { line: 10, column: 25 };
56 assert_eq!(format!("{}", loc), "10:25");
57 }
58
59 #[test]
60 fn test_parse_error_display() {
61 let err = Error::Parse {
62 message: "unexpected token".to_string(),
63 location: Location { line: 1, column: 5 },
64 };
65 let msg = format!("{}", err);
66 assert!(msg.contains("Parse error"));
67 assert!(msg.contains("1:5"));
68 assert!(msg.contains("unexpected token"));
69 }
70
71 #[test]
72 fn test_expand_error_display() {
73 let err = Error::Expand {
74 message: "macro expansion failed".to_string(),
75 node_id: NodeId::new(42),
76 };
77 let msg = format!("{}", err);
78 assert!(msg.contains("Expansion error"));
79 assert!(msg.contains("#42"));
80 assert!(msg.contains("macro expansion failed"));
81 }
82
83 #[test]
84 fn test_syntax_error_display() {
85 let err = Error::Syntax("invalid syntax".to_string());
86 let msg = format!("{}", err);
87 assert!(msg.contains("Invalid syntax"));
88 assert!(msg.contains("invalid syntax"));
89 }
90}