-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
use std::collections::HashSet;
#[derive(PartialEq, Clone, Debug)]
enum E {
L(i64, Box<E>),
A(Box<E>, Box<E>),
I(i64),
}
fn sub(term: E, var: i64, rep: &E, offset: i64, bound: &mut HashSet<i64>) -> E {
match term {
E::L(var, body) => {
bound.insert(var);
let x = E::L(var + offset, Box::new(sub(*body, var, rep, offset, bound)));
bound.remove(&var);
x
}
E::A(func, arg) => E::A(
Box::new(sub(*func, var, rep, offset, bound)),
Box::new(sub(*arg, var, rep, offset, bound)),
),
x => {
if x == E::I(var) {
rep.clone()
} else {
x
}
}
}
}
fn red(term: E) -> E {
match term {
E::L(var, body) => E::L(var, Box::new(red(*body))),
E::A(func, arg) => {
let rfunc = red(*func);
match rfunc {
E::L(var, body) => red(sub(
*body,
var,
&arg,
rand::random_range(0..1 << 32),
&mut HashSet::<i64>::new(),
)),
x => x,
}
}
x => x,
}
}
fn main() {
// Prints nothing?
println!(
"{:?}",
red(E::A(
Box::new(E::L(1, Box::new(E::L(2, Box::new(E::I(1)))))),
Box::new(E::I(2))
))
);
}