gorf_gen_core/
lib.rs

1use std::convert::Infallible;
2
3use chumsky::Parser;
4use gorf_core::GTerm;
5use proc_macro2::TokenStream;
6// use proc_macro::TokenStream;
7use quasiquote::quasiquote;
8use quote::{format_ident, quote};
9use syn::{parse_macro_input, LitStr};
10pub struct Opts {
11    pub path: TokenStream,
12}
13pub fn emit(a: &GTerm<String, Infallible>, opts: &Opts) -> proc_macro2::TokenStream {
14    let rt = &opts.path;
15    let n = {
16        if let Some(s) = a.scott() {
17            let mut v = quote! {
18                let mut _tv = ::alloc::vec::Vec::new();
19            };
20            for a in s.with {
21                let a = emit(&a, opts);
22                v = quote! {
23                    #v;
24                    _tv.push(#a)
25                }
26            }
27            let i = s.current_case;
28            let n = s.cases.len();
29            v = quote! {
30                {
31                #v;
32                #rt::scott(#i,#n,_tv.into())
33                }
34            };
35            return v;
36        }
37        match a {
38            GTerm::Undef => quote! {
39                unreachable!()
40            },
41            GTerm::Var(v) => {
42                let v = format_ident!("{v}");
43                quote! {
44                    (#v).clone()
45                }
46            }
47            GTerm::Abs(b) => {
48                let (b, v) = b.as_ref();
49                let w = v.frees();
50                let f = w.iter().map(|a| format_ident!("{a}"));
51                let mut t = quote! {
52                    #(let #f = #f.clone());*
53                };
54                let v = emit(v, opts);
55                quote! {
56                    {
57                        #t;
58                       #rt::B(::alloc::sync::Arc::new(move|#b|{
59                            #t;
60                            return #v;
61                        }))
62                    }
63                }
64            }
65            GTerm::App(a) => {
66                let (a, b) = a.as_ref();
67                let a = emit(a, opts);
68                match b {
69                    GTerm::Var(v) => {
70                        let v = format_ident!("{v}");
71                        quote! {
72                            (#a.0)(&#v)
73                        }
74                    }
75                    _ => quasiquote! {
76                        {
77                            let _0 = #{emit(b,opts)};
78                            (#a.0)(&_0)
79                        }
80                    },
81                }
82            }
83            GTerm::Mix(_) => todo!(),
84        }
85    };
86    let w = a.frees();
87    let f = w.iter().map(|a| format_ident!("{a}"));
88    let mut t = quote! {
89        #(let #f = #f.clone());*
90    };
91    return quote! {
92        {#t;
93        #rt::l(move||#n)
94        }
95    };
96}
97
98#[cfg(test)]
99mod tests {
100    use super::*;
101}