1use std::{collections::BTreeMap, convert::Infallible};
2
3use gorf_core::{brujin, debrijun, Id};
4use gorf_kiselyov::{RealSki, Ski};
5
6use crate::{Obj, Symbol};
7
8pub fn bake_ski(a: &Ski, x: &mut Obj<Id, Infallible>) -> Id {
9 let i: Id = format!("__{a:?}").into();
10 if x.syms.contains_key(&i) {
11 return i;
12 };
13 let s = match a {
14 Ski::S => Symbol {
15 r#impl: debrijun(lambda_calculus::combinators::S()),
16 deps: vec![],
17 },
18 Ski::K => Symbol {
19 r#impl: debrijun(lambda_calculus::combinators::K()),
20 deps: vec![],
21 },
22 Ski::B => Symbol {
23 r#impl: debrijun(lambda_calculus::combinators::B()),
24 deps: vec![],
25 },
26 Ski::R => Symbol {
27 r#impl: debrijun(lambda_calculus::combinators::R()),
28 deps: vec![],
29 },
30 Ski::U => Symbol {
31 deps: vec![],
32 r#impl: debrijun(lambda_calculus::app(
33 lambda_calculus::app(
34 lambda_calculus::combinators::S(),
35 lambda_calculus::combinators::I(),
36 ),
37 lambda_calculus::combinators::I(),
38 )),
39 },
40 Ski::I => Symbol {
41 r#impl: debrijun(lambda_calculus::combinators::I()),
42 deps: vec![],
43 },
44 Ski::App(ski, ski1) => Symbol {
45 deps: vec![bake_ski(ski.as_ref(), &mut *x), bake_ski(ski1.as_ref(), x)],
46 r#impl: debrijun(lambda_calculus::combinators::I()),
47 },
48 };
49 x.syms.insert(i.clone(), s);
50 return i;
51}
52pub fn bake(a: &Symbol<Id, Infallible>, p: &str, x: &mut Obj<Id, Infallible>) {
53 let s = bake_ski(&Ski::convert_default(brujin(a.r#impl.clone())), x);
54 x.syms.insert(
55 Id(format!("{p}")),
56 Symbol {
57 deps: [s].into_iter().chain(a.deps.iter().cloned()).collect(),
58 r#impl: debrijun(lambda_calculus::combinators::I()),
59 },
60 );
61}
62pub fn cache(a: &Obj<Id, Infallible>) -> Obj<Id, Infallible> {
63 return a.syms.iter().fold(
64 Obj {
65 syms: BTreeMap::new(),
66 },
67 |mut x, (si, s)| {
68 bake(s, &si.0, &mut x);
69 return x;
70 },
71 );
72}