gorf_core/
lib.rs

1// pub mod rat;
2use std::{
3    collections::{BTreeMap, BTreeSet},
4    convert::Infallible,
5    fmt::Display,
6    hash::Hash,
7    marker::PhantomData,
8    ops::Index,
9};
10
11use chumsky::{prelude::*, text::keyword, Error};
12use either::Either::{self, Left, Right};
13use lambda_calculus::Term::{self, Abs, App, Var};
14use num_bigint::{BigUint, ToBigUint};
15use num_traits::{One, Zero};
16use serde::{Deserialize, Serialize};
17// pub fn scott_bn() -> lambda_calculus::Term {
18//     return lambda_calculus::parse(
19//         "\\bn.bn (\\n.\\z.\\o.n) (\\x.\\n.\\z.\\o.z x) (\\x.\\n.\\z.\\o.o x)",
20//         lambda_calculus::term::Notation::Classic,
21//     )
22//     .unwrap();
23// }
24// pub fn unscott_bn() -> lambda_calculus::Term {
25//     return lambda_calculus::app(
26//         lambda_calculus::combinators::Y(),
27//         lambda_calculus::parse(
28//             "\\go.\\m.\\n.\\z.\\o.m n (\\x.z (go x n z o)) (\\x.o (go x n z o))",
29//             lambda_calculus::term::Notation::Classic,
30//         )
31//         .unwrap(),
32//     );
33// }
34// pub fn bit() -> lambda_calculus::Term {
35//     return lambda_calculus::parse(
36//         "\\n.\\z.\\b.n z (\\a.\\b. a (\\a.\\b.a)) (\\a.\\b. a (\\a.\\b.b))",
37//         lambda_calculus::term::Notation::Classic,
38//     )
39//     .unwrap();
40// }
41// pub fn bsucc() -> lambda_calculus::Term {
42//     return lambda_calculus::app(
43//         lambda_calculus::combinators::Y(),
44//         lambda_calculus::parse(
45//             "\\go.\\m.m (\\n.\\z.\\o.o (\\n.\\z.\\o.n)) (\\zv.\\n.\\z.\\o.o zv) (\\ov.\\n.\\z.\\o.z (go ov))",
46//             lambda_calculus::term::Notation::Classic,
47//         )
48//         .unwrap(),
49//     );
50// }
51// pub fn bpre() -> lambda_calculus::Term {
52//     return lambda_calculus::app(
53//         lambda_calculus::combinators::Y(),
54//         lambda_calculus::parse(
55//             "\\go.\\m.m (\\n.\\z.\\o.n) (\\ov.\\n.\\z.\\o.o (go ov)) (\\zv.\\n.\\z.\\o.z zv)",
56//             lambda_calculus::term::Notation::Classic,
57//         )
58//         .unwrap(),
59//     );
60// }
61// pub fn baddsub() -> lambda_calculus::Term {
62//     return lambda_calculus::app(
63//         lambda_calculus::combinators::Y(),
64//         lambda_calculus::app(lambda_calculus::parse(
65//             "\\bit.\\go.\\d.\\s.\\m.\\n.\\c.bit m (c (d n) n) (\\a.\\at.bit n (c (d m) m) (\\b.\\bt.\\n.\\z.\\o.(\\h.h z o (go d s at bt ((\\aob.\\aab.(\\caaob.aab aab caoab) (c aob c)) (a a (s b)) (a (s b) a)))) ((\\aneb.aneb (\\e.\\f.c f e) c) (a (\\c.\\d.s b d c) (s b)))))",
66//             lambda_calculus::term::Notation::Classic,
67//         )
68//         .unwrap(),bit()),
69//     );
70// }
71// pub fn badd() -> lambda_calculus::Term {
72//     return lambda_calculus::app(
73//         lambda_calculus::app(baddsub(), bsucc()),
74//         lambda_calculus::combinators::I(),
75//     );
76// }
77// pub fn bsub() -> lambda_calculus::Term {
78//     return lambda_calculus::app(
79//         lambda_calculus::app(baddsub(), bpre()),
80//         lambda_calculus::data::boolean::not(),
81//     );
82// }
83// pub fn beq() -> lambda_calculus::Term {
84//     return lambda_calculus::app(
85//         lambda_calculus::combinators::Y(),
86//         lambda_calculus::app(lambda_calculus::parse(
87//             "\\bit.\\go.\\m.\\n.bit m (bit n (\\a.\\b.a) (\\_.\\_.\\a.\\b.b)) (\\a.\\at.bit n (\\a.\\b.b) (\\b.\\bt.b (a (go at bt) a) b))",
88//             lambda_calculus::term::Notation::Classic,
89//         )
90//         .unwrap(),bit()),
91//     );
92// }
93// pub fn patch() -> lambda_calculus::Term {
94//     return lambda_calculus::app(
95//         lambda_calculus::parse(
96//             "\\eq.\\k.\\v.\\f.\\w.eq k w v (f w)",
97//             lambda_calculus::term::Notation::Classic,
98//         )
99//         .unwrap(),
100//         beq(),
101//     );
102// }
103// pub fn bc(x: num_bigint::BigUint) -> lambda_calculus::Term {
104//     if x == Zero::zero() {
105//         return lambda_calculus::parse("\\n.\\z.\\o.n", lambda_calculus::term::Notation::Classic)
106//             .unwrap();
107//     }
108//     let two: BigUint = BigUint::one() + BigUint::one();
109//     let b = x.clone() % two.clone() == One::one();
110//     let b = if b {
111//         lambda_calculus::data::boolean::tru()
112//     } else {
113//         lambda_calculus::data::boolean::fls()
114//     };
115//     let d = bc(x / two);
116//     return lambda_calculus::app(
117//         lambda_calculus::app(
118//             lambda_calculus::parse(
119//                 "\\b.\\d.\\n.\\z.\\o.b o z d",
120//                 lambda_calculus::term::Notation::Classic,
121//             )
122//             .unwrap(),
123//             b,
124//         ),
125//         d,
126//     );
127// }
128// pub fn bcc(x: usize) -> lambda_calculus::Term {
129//     return bc(x.to_biguint().unwrap());
130// }
131// pub fn bc64(x: u64) -> lambda_calculus::Term {
132//     return bc(x.to_biguint().unwrap());
133// }
134
135pub struct Ref<'a, V: Binder, M> {
136    pub current: &'a mut GTerm<V, M>,
137}
138impl<'a, V: Binder, M> Ref<'a, V, M> {
139    pub fn app(&mut self, x: GTerm<V, M>) {
140        let mut b = Box::new((x, GTerm::Undef));
141        let c = unsafe { std::mem::transmute::<_, &'a mut (GTerm<V, M>, GTerm<V, M>)>(&mut *b) };
142
143        *self.current = GTerm::App(b);
144        self.current = &mut c.1;
145    }
146    pub fn abs(&mut self, x: V) {
147        let mut b = Box::new((x, GTerm::Undef));
148        let c = unsafe { std::mem::transmute::<_, &'a mut (V, GTerm<V, M>)>(&mut *b) };
149
150        *self.current = GTerm::Abs(b);
151        self.current = &mut c.1;
152    }
153    pub fn wrap(&mut self, v: V, x: GTerm<V, M>)
154    where
155        V: Clone,
156    {
157        self.app(app(x, var(v.clone().get_var())));
158        self.abs(v.clone());
159    }
160}
161
162pub trait Binder {
163    type Var: Binder<Var = Self::Var>;
164    type Wrap<X: Binder>: Binder<Var = X::Var>;
165    fn get_var(self) -> Self::Var;
166    fn get_var_ref(&self) -> &Self::Var;
167    fn get_var_mut(&mut self) -> &mut Self::Var;
168    fn inside<X: Binder<Var = X>>(self, f: &mut impl FnMut(Self::Var) -> X) -> Self::Wrap<X>;
169}
170pub trait Backend<V: Binder + Clone + Eq, M: Eq + Clone>
171where
172    V::Var: Eq + Ord + Clone,
173{
174    type Output;
175    fn undef(&mut self) -> Self::Output;
176    fn var(&mut self, v: V::Var) -> Self::Output;
177    fn selfreference(&mut self, v: Self::Output) -> Self::Output;
178    fn abs(&mut self, b: V, o: Self::Output) -> Self::Output;
179    fn app(&mut self, a: Self::Output, b: Self::Output) -> Self::Output;
180    fn mix(&mut self, x: M) -> Self::Output;
181    fn compile(&mut self, a: GTerm<V, M>) -> Self::Output {
182        if let Some(b) = a.is_sapp() {
183            let c = self.compile(b);
184            return self.selfreference(c);
185        }
186        match a {
187            GTerm::Undef => self.undef(),
188            GTerm::Var(v) => self.var(v),
189            GTerm::Abs(b) => {
190                let (a, b) = *b;
191                let b = self.compile(b);
192                return self.abs(a, b);
193            }
194            GTerm::App(b) => {
195                let (a, b) = *b;
196                let a = self.compile(a);
197                let b = self.compile(b);
198                return self.app(a, b);
199            }
200            GTerm::Mix(m) => self.mix(m),
201        }
202    }
203}
204pub struct Lam {}
205impl<V: Binder + Clone + Eq, M: Clone + Eq> Backend<V, M> for Lam
206where
207    V::Var: Eq + Ord + Clone,
208{
209    type Output = GTerm<V, M>;
210    fn undef(&mut self) -> Self::Output {
211        GTerm::Undef
212    }
213
214    fn var(&mut self, v: V::Var) -> Self::Output {
215        crate::var(v)
216    }
217
218    fn selfreference(&mut self, v: Self::Output) -> Self::Output {
219        crate::app(v.clone(), v.clone())
220    }
221
222    fn abs(&mut self, b: V, o: Self::Output) -> Self::Output {
223        crate::abs(b, o)
224    }
225
226    fn app(&mut self, a: Self::Output, b: Self::Output) -> Self::Output {
227        crate::app(a, b)
228    }
229    fn mix(&mut self, x: M) -> Self::Output {
230        return GTerm::Mix(x);
231    }
232}
233pub trait Incr {
234    fn incr(&mut self);
235}
236impl Incr for usize {
237    fn incr(&mut self) {
238        *self += 1;
239    }
240}
241impl Incr for String {
242    fn incr(&mut self) {
243        *self = format!("%${self}")
244    }
245}
246#[derive(Eq, Ord, Clone, PartialEq, PartialOrd, Hash, Serialize, Deserialize)]
247#[repr(transparent)]
248#[serde(transparent)]
249pub struct Id(pub String);
250impl Incr for Id {
251    fn incr(&mut self) {
252        self.0.incr();
253    }
254}
255impl From<usize> for Id {
256    fn from(value: usize) -> Self {
257        return Id(format!("%{value}"));
258    }
259}
260impl From<String> for Id {
261    fn from(value: String) -> Self {
262        return Id(value);
263    }
264}
265impl Display for Id {
266    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267        write!(f, "{}", self.0)
268    }
269}
270// pub trait SimpleBinder {}
271macro_rules! simple_binder {
272    ($x:ty) => {
273        impl $crate::Binder for $x {
274            type Var = $x;
275            type Wrap<X: $crate::Binder> = X;
276            fn get_var(self) -> Self::Var {
277                return self;
278            }
279            fn get_var_ref(&self) -> &Self::Var {
280                return self;
281            }
282            fn get_var_mut(&mut self) -> &mut Self::Var {
283                return self;
284            }
285            fn inside<X: $crate::Binder<Var = X>>(
286                self,
287                f: &mut impl FnMut(Self::Var) -> X,
288            ) -> Self::Wrap<X> {
289                return f(self);
290            }
291        }
292        // impl SimpleBinder for $x {}
293    };
294}
295simple_binder!(usize);
296simple_binder!(String);
297simple_binder!(Id);
298
299#[derive(Eq, Ord, Clone, PartialEq, PartialOrd, Hash, Debug, Serialize, Deserialize)]
300pub enum GTerm<V: Binder, M> {
301    Undef,
302    Var(V::Var),
303    Abs(Box<(V, GTerm<V, M>)>),
304    App(Box<(GTerm<V, M>, GTerm<V, M>)>),
305    Mix(M),
306}
307
308pub fn parser<'a, Y: 'a + 'static, X: 'a + 'static + Binder, E: Error<char> + 'a + 'static>(
309    x: impl Parser<char, X, Error = E> + 'a + 'static + Clone,
310    v: impl Parser<char, X::Var, Error = E> + 'a + 'static + Clone,
311    y: impl Parser<char, Y, Error = E> + 'a + 'static + Clone,
312    splice: impl Parser<char, GTerm<X, Y>, Error = E> + 'a + 'static + Clone,
313) -> impl Parser<char, GTerm<X, Y>, Error = E> + 'a + 'static + Clone
314where
315    <X as Binder>::Var: 'a + 'static,
316    GTerm<X, Y>: 'a + 'static,
317{
318    return recursive(|go| {
319        let var = v
320            .clone()
321            .map(|v| GTerm::Var(v))
322            .then_ignore(text::whitespace());
323        let fun = just('\\')
324            .then(x.then_ignore(just('.')).separated_by(text::whitespace()))
325            .then(go.clone())
326            .map(|((_, k), v)| {
327                k.into_iter()
328                    .rev()
329                    .fold(v, |a, b| GTerm::Abs(Box::new((b, a))))
330            });
331        let b = choice((
332            var.clone(),
333            fun.clone(),
334            go.clone().delimited_by(just('('), just(')')),
335            y.map(|x| GTerm::Mix(x)),
336        ));
337        choice((b
338            .clone()
339            .then_ignore(text::whitespace())
340            .repeated()
341            .at_least(1)
342            .map(|x| x.into_iter().reduce(|acc, e| app(acc, e)).unwrap()),))
343    });
344}
345// pub fn let_parser<
346//     'a,
347//     Y: 'a + 'static + Clone,
348//     X: 'a + 'static + Binder + Clone + Eq + Ord,
349//     E: Error<char> + 'a + 'static,
350// >(
351//     x: impl Parser<char, X, Error = E> + 'a + 'static + Clone,
352//     v: impl Parser<char, X::Var, Error = E> + 'a + 'static + Clone,
353//     y: impl Parser<char, Y, Error = E> + 'a + 'static + Clone,
354//     splice: impl Parser<char, GTerm<X, Y>, Error = E> + 'a + 'static + Clone,
355//     into: &'static impl Fn(usize) -> X,
356// ) -> impl Parser<char, GTerm<X, Y>, Error = E> + 'a + 'static + Clone
357// where
358//     GTerm<X, Y>: Clone,
359//     X::Var: Eq + Ord + Clone,
360// {
361//     return recursive(move |go: Recursive<'_, char, GTerm<X, Y>, E>| {
362//         parser(
363//             x.clone(),
364//             v.clone(),
365//             y,
366//             keyword("let")
367//                 .then_ignore(text::whitespace())
368//                 .then(x.clone())
369//                 .then_ignore(text::whitespace())
370//                 .then_ignore(just('='))
371//                 .then_ignore(text::whitespace())
372//                 .then(go.clone())
373//                 .then_ignore(text::whitespace())
374//                 .then_ignore(keyword("in"))
375//                 .then_ignore(text::whitespace())
376//                 .then(go.clone())
377//                 .map(move |(((_, a), b), c)| {
378//                     let body = debrijun::<usize, Infallible>(lambda_calculus::combinators::Y());
379//                     let y = brujin_map_f(body, &muinto);
380//                     let mut body = b;
381//                     if body.frees().contains(&a.clone().get_var()) {
382//                         body = app(y, abs(a.clone(), body));
383//                     }
384//                     return app(abs(a, c), body);
385//                 })
386//                 .or(splice),
387//         )
388//     });
389// }
390pub fn void<I: Clone + Hash + Eq, O>() -> impl Parser<I, O, Error = Simple<I>> + Clone {
391    return end().try_map(|a, b| Err(Simple::custom(b, "")));
392}
393pub fn str_parser() -> impl Parser<char, GTerm<String, Infallible>, Error = Simple<char>> + Clone {
394    return parser(
395        chumsky::text::ident(),
396        chumsky::text::ident(),
397        void(),
398        void(),
399    );
400}
401
402#[derive(Eq, Ord, Clone, PartialEq, PartialOrd, Hash)]
403#[repr(transparent)]
404pub struct Scope<T: Binder>(pub BTreeMap<T::Var, T>);
405
406impl<V: Binder, M> GTerm<V, M> {
407    pub fn to_args<'a>(&'a self, args: &mut Vec<&'a GTerm<V, M>>) -> &'a GTerm<V, M> {
408        let GTerm::App(k) = self else {
409            return self;
410        };
411        let (a, b) = k.as_ref();
412        let a = a.to_args(args);
413        args.push(b);
414        return a;
415    }
416    pub fn map_vars<X: Binder<Var = X>>(
417        self,
418        f: &mut impl FnMut(V::Var) -> X,
419    ) -> GTerm<V::Wrap<X>, M> {
420        match self {
421            GTerm::Undef => GTerm::Undef,
422            GTerm::Var(v) => GTerm::Var(f(v)),
423            GTerm::Abs(k) => {
424                let (k, w) = *k;
425                let k = k.inside(f);
426                let w = w.map_vars(f);
427                return abs(k, w);
428            }
429            GTerm::App(a) => {
430                let (a, b) = *a;
431                return app(a.map_vars(f), b.map_vars(f));
432            }
433            GTerm::Mix(m) => GTerm::Mix(m),
434        }
435    }
436    pub fn map_all<X: Binder>(
437        self,
438        f: &mut impl FnMut(V::Var) -> X::Var,
439        g: &mut impl FnMut(V) -> X,
440    ) -> GTerm<X, M> {
441        match self {
442            GTerm::Undef => GTerm::Undef,
443            GTerm::Var(v) => GTerm::Var(f(v)),
444            GTerm::Abs(k) => {
445                let (k, w) = *k;
446                let k = g(k);
447                let w = w.map_all(f, g);
448                return abs(k, w);
449            }
450            GTerm::App(a) => {
451                let (a, b) = *a;
452                return app(a.map_all(f, g), b.map_all(f, g));
453            }
454            GTerm::Mix(m) => GTerm::Mix(m),
455        }
456    }
457    pub fn map_mix<N>(self, f: &mut impl FnMut(M) -> N) -> GTerm<V, N> {
458        return self.lower_mix(&mut |a| GTerm::Mix(f(a)));
459    }
460    pub fn lower_mix<N>(self, f: &mut impl FnMut(M) -> GTerm<V, N>) -> GTerm<V, N> {
461        match self {
462            GTerm::Undef => GTerm::Undef,
463            GTerm::Var(v) => GTerm::Var(v),
464            GTerm::Abs(k) => {
465                let (k, w) = *k;
466                return abs(k, w.lower_mix(f));
467            }
468            GTerm::App(a) => {
469                let (a, b) = *a;
470                return app(a.lower_mix(f), b.lower_mix(f));
471            }
472            GTerm::Mix(m) => f(m),
473        }
474    }
475    pub fn subst(self, f: &mut impl FnMut(&V::Var) -> Option<GTerm<V, M>>) -> GTerm<V, M> {
476        match self {
477            GTerm::Undef => GTerm::Undef,
478            GTerm::Var(v) => match f(&v) {
479                Some(a) => a,
480                None => GTerm::Var(v),
481            },
482            GTerm::Abs(k) => {
483                let (k, w) = *k;
484                match f(k.get_var_ref()) {
485                    Some(_) => abs(k, w),
486                    None => abs(k, w.subst(f)),
487                }
488            }
489            GTerm::App(b) => {
490                let (a, b) = *b;
491                return app(a.subst(f), b.subst(f));
492            }
493            GTerm::Mix(m) => GTerm::Mix(m),
494        }
495    }
496}
497impl<V: Binder, M> GTerm<V, M>
498where
499    V::Var: Eq,
500{
501    pub fn subst_var_fun(self, v: &V::Var, f: &mut impl FnMut() -> GTerm<V, M>) -> GTerm<V, M> {
502        return self.subst(&mut |x| if x == v { Some(f()) } else { None });
503    }
504}
505impl<V: Binder + Clone, M: Clone> GTerm<V, M>
506where
507    V::Var: Eq + Clone,
508{
509    pub fn subst_var(self, v: &V::Var, f: GTerm<V, M>) -> GTerm<V, M> {
510        return self.subst_var_fun(v, &mut || f.clone());
511    }
512    pub fn apply(&mut self, o: GTerm<V, M>) {
513        if let GTerm::Abs(a) = self {
514            let (ref mut k, ref mut w) = **a;
515            *self = w.clone().subst_var(k.get_var_mut(), o);
516            return;
517        }
518        *self = app(self.clone(), o);
519    }
520}
521#[derive(Eq, Ord, Clone, PartialEq, PartialOrd, Hash)]
522pub struct Scott<V: Binder, M> {
523    pub cases: Vec<V::Var>,
524    pub current_case: usize,
525    pub with: Vec<GTerm<V, M>>,
526}
527#[derive(Eq, Ord, Clone, PartialEq, PartialOrd, Hash)]
528pub struct Let<V: Binder<Var: Ord>, M> {
529    pub vars: BTreeMap<V::Var, GTerm<V, M>>,
530    pub body: GTerm<V, M>,
531}
532impl<V: Binder + Clone, M: Clone> Scott<V, M>
533where
534    V::Var: Eq + Ord + Clone,
535{
536    pub fn apply(mut self, mut other: GTerm<V, M>) -> Either<GTerm<V, M>, Scott<V, M>> {
537        if self.current_case == 0 {
538            for x in self.with.into_iter() {
539                other.apply(x);
540            }
541            return Left(other);
542        }
543        self.current_case -= 1;
544        self.cases.pop();
545        return Right(self);
546    }
547    pub fn render(mut self) -> GTerm<V, M>
548    where
549        V: Binder<Var = V>,
550    {
551        let mut r = var(self.cases[self.current_case].clone());
552        for w in self.with.into_iter() {
553            r = app(r, w);
554        }
555        for c in self.cases.into_iter().rev() {
556            r = abs(c, r);
557        }
558        return r;
559    }
560}
561impl<V: Binder + Clone + Eq, M: Clone + Eq> GTerm<V, M>
562where
563    V::Var: Eq + Ord + Clone,
564{
565    pub fn is_sapp(&self) -> Option<GTerm<V, M>> {
566        if let GTerm::App(a) = self {
567            let (ref a, ref b) = **a;
568            if a.clone() == b.clone() {
569                return Some(a.clone());
570            }
571        }
572        None
573    }
574}
575impl<V: Binder + Clone, M: Clone> GTerm<V, M>
576where
577    V::Var: Eq + Ord + Clone,
578{
579    pub fn frees_internal(&self, o: &mut BTreeSet<V::Var>) {
580        match self {
581            GTerm::Undef => {}
582            GTerm::Var(s) => {
583                o.insert(s.clone());
584            }
585            GTerm::Abs(a) => {
586                let (ref k, ref w) = **a;
587                let mut r = w.frees();
588                r.remove(k.get_var_ref());
589                o.append(&mut r);
590            }
591            GTerm::App(a) => {
592                let (ref a, ref b) = **a;
593                a.frees_internal(o);
594                b.frees_internal(o);
595            }
596            GTerm::Mix(m) => {}
597        }
598    }
599    pub fn frees(&self) -> BTreeSet<V::Var> {
600        let mut r = BTreeSet::new();
601        self.frees_internal(&mut r);
602        return r;
603    }
604    pub fn r#let(self) -> Let<V, M> {
605        let mut l = Let {
606            body: self,
607            vars: BTreeMap::new(),
608        };
609        loop {
610            let GTerm::App(a) = l.body.clone() else {
611                return l;
612            };
613            let GTerm::Abs(b) = a.0 else {
614                return l;
615            };
616            l.vars.insert(b.0.get_var(), a.1);
617            l.body = b.1;
618        }
619    }
620    pub fn scott(&self) -> Option<Scott<V, M>> {
621        let mut this = self;
622        let mut v = vec![];
623        while let GTerm::Abs(k) = this {
624            let (ref k, ref w) = **k;
625            v.push(k.clone().get_var());
626            this = w;
627        }
628        let mut args = vec![];
629        loop {
630            if let GTerm::App(b) = this {
631                let (ref a, ref b) = **b;
632                // if let GTerm::Var(r) = a {
633                //     // if v{
634                //     //     return Some((v.len(),args));
635                //     // }else{
636                //     //     return None;
637                //     // }
638                //     match v.iter().enumerate().find(|a| a.1 == r.get_var_ref()) {
639                //         Some((a, b)) => {
640                //             return Some(Scott {
641                //                 case_count: v.len(),
642                //                 current_case: a,
643                //                 with: args.into_iter().rev().collect(),
644                //                 pda: PhantomData,
645                //             })
646                //         }
647                //         None => return None,
648                //     }
649                // }
650                for f in b.frees() {
651                    if !v.contains(&f) {
652                        return None;
653                    }
654                }
655                args.push(b.clone());
656                this = a;
657            } else {
658                break;
659            }
660        }
661        if let GTerm::Var(r) = this {
662            match v.iter().enumerate().find(|a| a.1 == r.get_var_ref()) {
663                Some((a, b)) => {
664                    return Some(Scott {
665                        cases: v,
666                        current_case: a,
667                        with: args.into_iter().rev().collect(),
668                    })
669                }
670                None => return None,
671            }
672        }
673        return None;
674    }
675}
676
677pub fn var<V: Binder, M>(a: V::Var) -> GTerm<V, M> {
678    return GTerm::Var(a);
679}
680
681pub fn abs<V: Binder, M>(a: V, b: GTerm<V, M>) -> GTerm<V, M> {
682    return GTerm::Abs(Box::new((a, b)));
683}
684
685pub fn app<V: Binder, M>(a: GTerm<V, M>, b: GTerm<V, M>) -> GTerm<V, M> {
686    return GTerm::App(Box::new((a, b)));
687}
688
689pub fn debrijun_internal<X: From<usize> + Binder, Y>(x: Term, depth: usize) -> GTerm<X, Y>
690where
691    <X as Binder>::Var: From<usize>,
692{
693    match x {
694        Var(0) => GTerm::Undef,
695        Var(v) => GTerm::Var((depth - v).into()),
696        Abs(a) => GTerm::Abs(Box::new((depth.into(), debrijun_internal(*a, depth + 1)))),
697        App(b) => {
698            let (a, b) = *b;
699            let a = debrijun_internal(a, depth);
700            let b = debrijun_internal(b, depth);
701            return GTerm::App(Box::new((a, b)));
702        }
703    }
704}
705pub fn debrijun<X: From<usize> + Binder, Y>(x: Term) -> GTerm<X, Y>
706where
707    <X as Binder>::Var: From<usize>,
708{
709    return debrijun_internal(x, 1);
710}
711pub fn brujin_internal<X: Binder>(
712    t: GTerm<X, Infallible>,
713    m: &BTreeMap<<X as Binder>::Var, usize>,
714) -> Term
715where
716    <X as Binder>::Var: Eq + Ord + Clone,
717{
718    match t {
719        GTerm::Undef => Var(0),
720        GTerm::Var(a) => Var(m[&a]),
721        GTerm::Abs(a) => {
722            let (k, w) = *a;
723            let mut n = BTreeMap::new();
724            for (a, b) in m.iter() {
725                n.insert(a.clone(), *b + 1);
726            }
727            n.insert(k.get_var(), 1);
728            return Abs(Box::new(brujin_internal(w, &n)));
729        }
730        GTerm::App(b) => {
731            let (a, b) = *b;
732            let a = brujin_internal(a, m);
733            let b = brujin_internal(b, m);
734            return App(Box::new((a, b)));
735        }
736        GTerm::Mix(x) => match x {},
737    }
738}
739pub fn brujin<X: Binder>(t: GTerm<X, Infallible>) -> Term
740where
741    <X as Binder>::Var: Eq + Ord + Clone,
742{
743    return brujin_internal(t, &BTreeMap::new());
744}
745pub fn brujin_map_f_internal<X: Binder, Y: Binder, M>(
746    t: GTerm<X, Infallible>,
747    m: &BTreeMap<<X as Binder>::Var, usize>,
748    depth: usize,
749    into: &mut impl FnMut(usize) -> Y,
750) -> GTerm<Y, M>
751where
752    <X as Binder>::Var: Eq + Ord + Clone,
753{
754    match t {
755        GTerm::Undef => GTerm::Undef,
756        GTerm::Var(a) => GTerm::Var(into(depth - m[&a]).get_var()),
757        GTerm::Abs(a) => {
758            let (k, w) = *a;
759            let mut n = BTreeMap::new();
760            for (a, b) in m.iter() {
761                n.insert(a.clone(), *b + 1);
762            }
763            n.insert(k.get_var(), 1);
764            return abs(into(depth), brujin_map_f_internal(w, &n, depth + 1, into));
765        }
766        GTerm::App(b) => {
767            let (a, b) = *b;
768            let a = brujin_map_f_internal(a, m, depth, into);
769            let b = brujin_map_f_internal(b, m, depth, into);
770            return app(a, b);
771        }
772        GTerm::Mix(x) => match x {},
773    }
774}
775pub fn brujin_map<X: Binder, Y: Binder + From<usize>, M>(t: GTerm<X, Infallible>) -> GTerm<Y, M>
776where
777    <X as Binder>::Var: Eq + Ord + Clone,
778    <Y as Binder>::Var: From<usize>,
779{
780    return brujin_map_f_internal(t, &BTreeMap::new(), 1, &mut |a| a.into());
781}
782pub fn brujin_map_f<X: Binder, Y: Binder, M>(
783    t: GTerm<X, Infallible>,
784    into: &mut impl FnMut(usize) -> Y,
785) -> GTerm<Y, M>
786where
787    <X as Binder>::Var: Eq + Ord + Clone,
788{
789    return brujin_map_f_internal(t, &BTreeMap::new(), 1, into);
790}
791
792#[cfg(test)]
793mod tests {
794    use chumsky::Stream;
795
796    use super::*;
797    #[test]
798    fn rtrip() {
799        let a = lambda_calculus::parse(
800            "\\a.\\b.\\c.c a b (\\d.d c b a)",
801            lambda_calculus::term::Notation::Classic,
802        )
803        .unwrap();
804        assert_eq!(
805            brujin::<usize>(brujin_map(debrijun::<usize, Infallible>(a.clone()))),
806            a
807        );
808    }
809    #[test]
810    fn parse() {
811        let s = "\\a.\\b.\\c.c a b (\\d.d c b a)";
812        let a = lambda_calculus::parse(s, lambda_calculus::term::Notation::Classic).unwrap();
813        let b = str_parser().map(|x| brujin(x)).parse(Stream::from(s));
814        assert_eq!(b.unwrap(), a);
815    }
816    #[test]
817    fn r#let() {
818        let s = "let a = \\b.a in \\c.c a";
819        let b = str_parser().parse(s);
820        assert!(b.is_ok());
821    }
822    #[test]
823    fn scott_simple() {
824        let a = debrijun::<usize, Infallible>(
825            lambda_calculus::parse("\\a.a", lambda_calculus::term::Notation::Classic).unwrap(),
826        );
827        // assert_eq!(
828        //     a.scott().unwrap(),
829        //     Scott {
830        //         case_count: 1,
831        //         current_case: 0,
832        //         with: vec![]
833        //     }
834        // )
835        let a = a.scott().unwrap();
836        // assert_eq!(a.case_count, 1);
837        assert_eq!(a.current_case, 0);
838        assert_eq!(a.with, vec![]);
839    }
840    #[test]
841    fn scott_field() {
842        let ab = debrijun::<usize, Infallible>(
843            lambda_calculus::parse(
844                "\\c.\\a.a (\\b.b)",
845                lambda_calculus::term::Notation::Classic,
846            )
847            .unwrap(),
848        );
849        let b = debrijun::<usize, Infallible>(
850            lambda_calculus::parse("\\a.a", lambda_calculus::term::Notation::Classic).unwrap(),
851        );
852        // assert_eq!(
853        //     a.scott().unwrap(),
854        //     Scott {
855        //         case_count: 1,
856        //         current_case: 0,
857        //         with: vec![]
858        //     }
859        // )
860        let a = ab.scott().unwrap();
861        assert_eq!(brujin(a.clone().render()), brujin(ab.clone()));
862        // assert_eq!(a.case_count, 2);
863        assert_eq!(a.current_case, 1);
864        assert_eq!(a.with.len(), 1);
865        assert_eq!(brujin(b), brujin(a.with[0].clone()))
866    }
867    #[test]
868    fn scott_bool() {
869        let ab = debrijun::<usize, Infallible>(
870            lambda_calculus::parse("\\b.\\a.a", lambda_calculus::term::Notation::Classic).unwrap(),
871        );
872        // assert_eq!(
873        //     a.scott().unwrap(),
874        //     Scott {
875        //         case_count: 1,
876        //         current_case: 0,
877        //         with: vec![]
878        //     }
879        // )
880        let a = ab.scott().unwrap();
881        assert_eq!(brujin(a.clone().render()), brujin(ab.clone()));
882        // assert_eq!(a.case_count, 2);
883        assert_eq!(a.current_case, 1);
884        assert_eq!(a.with, vec![]);
885    }
886}