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}