gorf_core/
lib.rs

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