1use super::sterm::{Comb, SComb, STerm};
4
5impl<'s, 't> STerm<'s, 't> {
6 pub fn apply_subst<S>(&mut self, subst: &S, k: usize) -> bool
7 where
8 S: Fn(usize, usize) -> STerm<'s, 't>,
9 {
10 match self {
11 Self::Var(n) if *n >= k => *self = subst(*n, k),
12 Self::LComb(c) => {
13 let mut c = SComb::from(*c);
14 let change = c.apply_subst(subst, k);
15 *self = Self::SComb(c.into());
16 return change;
17 }
18 Self::SComb(c) => match alloc::rc::Rc::get_mut(c) {
19 Some(c) => return c.apply_subst(subst, k),
20 None => {
21 let mut c2: SComb = (**c).clone();
22 if c2.apply_subst(subst, k) {
23 *c = c2.into();
24 } else {
25 return false;
26 }
27 }
28 },
29 _ => return false,
30 }
31 true
32 }
33
34 pub fn subst(mut self, u: &Self) -> Self {
35 self.apply_subst(&u.psubst_single(), 0);
36 self
37 }
38
39 fn psubst_single<'a>(&'a self) -> impl Fn(usize, usize) -> STerm<'s, 't> + 'a {
40 move |n: usize, k: usize| {
41 if n == k {
42 self.clone().shift(k)
43 } else {
44 Self::Var(n - 1)
45 }
46 }
47 }
48
49 pub fn shift(mut self, rhs: usize) -> Self {
50 if rhs != 0 {
51 self.shift_mut(rhs);
52 }
53 self
54 }
55
56 pub fn shift_mut(&mut self, rhs: usize) {
57 self.apply_subst(&|n, _k| Self::Var(n + rhs), 0);
58 }
59}
60
61impl<'s, 't> SComb<'s, 't> {
62 pub fn apply_subst<S>(&mut self, subst: &S, k: usize) -> bool
63 where
64 S: Fn(usize, usize) -> STerm<'s, 't>,
65 {
66 let sub = |tm: &mut STerm<'s, 't>| tm.apply_subst(subst, k);
67 let mut change;
68 match self {
69 Comb::Appl(f, args) => {
70 change = sub(f);
71 args.iter_mut().for_each(|x| change = sub(x) || change);
72 }
73 Comb::Abst(_, ty, f) => {
74 change = f.apply_subst(subst, k + 1);
75 ty.iter_mut().for_each(|x| change = sub(x) || change);
76 }
77 Comb::Prod(_, ty, f) => {
78 change = sub(ty);
79 change = f.apply_subst(subst, k + 1) || change;
80 }
81 }
82 change
83 }
84}