sbpf_assembler/
macros.rs

1#[macro_export]
2macro_rules! define_compile_errors {
3    (
4        $(
5            $variant:ident {
6                error = $error_msg:literal,
7                label = $label_msg:literal,
8                fields = { $( $field_name:ident : $field_ty:ty ),* $(,)? }
9            }
10        ),* $(,)?
11    ) => {
12        #[derive(Debug, thiserror::Error)]
13        pub enum CompileError {
14            $(
15                #[error($error_msg)]
16                $variant { $( $field_name: $field_ty ),*, custom_label: Option<String> }
17            ),*
18        }
19
20        impl CompileError {
21            pub fn label(&self) -> &str {
22                match self {
23                    $(
24                        Self::$variant { custom_label, .. } => custom_label.as_deref().unwrap_or($label_msg),
25                    )*
26                }
27            }
28
29            pub fn span(&self) -> &Range<usize> {
30                match self {
31                    $(
32                        Self::$variant { span, .. } => span,
33                    )*
34                }
35            }
36        }
37    };
38}
39
40// TODO: make it a hyper link
41#[macro_export]
42macro_rules! bug {
43    ($($arg:tt)*) => {{
44        eprintln!(
45            "\n{}\n{}",
46            "Thanks for abusing the compiler <3 you've hunted a bug!",
47            format!("Please file a bug report at: {}", "https://github.com/blueshift-gg/sbpf/issues/new")
48        );
49
50        panic!("{}", format!("Internal error: {}\n", format!($($arg)*)));
51    }};
52}
53
54#[cfg(test)]
55mod tests {
56    use std::ops::Range;
57
58    #[test]
59    fn test_define_compile_errors_macro() {
60        define_compile_errors! {
61            TestError1 {
62                error = "Test error 1",
63                label = "test label 1",
64                fields = { span: Range<usize> }
65            },
66            TestError2 {
67                error = "Test error 2",
68                label = "test label 2",
69                fields = { span: Range<usize>, message: String }
70            }
71        }
72
73        // Test creating errors
74        let err1 = CompileError::TestError1 {
75            span: 0..10,
76            custom_label: None,
77        };
78        assert_eq!(err1.label(), "test label 1");
79        assert_eq!(err1.span(), &(0..10));
80        assert_eq!(err1.to_string(), "Test error 1");
81
82        let err2 = CompileError::TestError2 {
83            span: 5..15,
84            message: "custom message".to_string(),
85            custom_label: Some("custom".to_string()),
86        };
87        assert_eq!(err2.label(), "custom");
88        assert_eq!(err2.span(), &(5..15));
89    }
90}