1use std::convert::Infallible;
2
3use chumsky::Parser;
4use gorf_core::GTerm;
5use proc_macro2::TokenStream;
6use 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: >erm<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}