compile_time_lisp/
lib.rs

1mod parse_utils;
2
3use crate::parse_utils::parse_value;
4use proc_macro::TokenStream;
5use std::{cell::RefCell, rc::Rc};
6
7#[proc_macro]
8pub fn lisp(input: TokenStream) -> TokenStream {
9    let env = Rc::new(RefCell::new(rust_lisp::default_env()));
10
11    let mut input = input.to_string();
12
13    if input.is_empty() {
14        return "()".parse().unwrap();
15    }
16
17    input = input.replace("_ @ ", "'");
18
19    macro_rules! replace_question_mark {
20        ($($ident:literal),*) => {
21            $(input = input.replace(concat!($ident, " ?"), concat!($ident, "?"));)*
22        }
23    }
24
25    replace_question_mark!("null", "number", "symbol", "boolean", "procedure", "pair");
26
27    if !input.starts_with('\'') {
28        input.insert(0, '(');
29        input.push(')');
30    }
31
32    let mut ast = rust_lisp::parse(&input);
33
34    if let Some(expr) = ast.next() {
35        match expr {
36            Ok(expr) => {
37                match rust_lisp::eval(env, &expr) {
38                    Ok(value) => {
39                        return parse_value(&value, false)
40                            .parse()
41                            .expect("Couldn't parse type in macro");
42                    }
43
44                    Err(e) => panic!("Couldn't evaluate expression (evaluation error):\n{}", e),
45                };
46            }
47
48            Err(e) => panic!("Couldn't evaluate expression (parse error):\n{}", e),
49        }
50    }
51
52    "()".parse().unwrap()
53}