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
62
63
64
65
66
67
68
69
70
use crate::exp::{Exp, Ident};
use std::hash::Hash;
pub fn app<T>(exps: Vec<Exp<T>>) -> Exp<T>
where
T: Clone + Eq + Hash + ToString,
{
let mut res = None;
for exp in exps {
res = match res {
Some(l) => Some(Exp::App(Box::new(l), Box::new(exp))),
None => Some(exp),
}
}
res.unwrap()
}
pub fn abs<T>(v: T, exp: Exp<T>) -> Exp<T>
where
T: Clone + Eq + Hash + ToString,
{
let mut exp = exp;
exp.bind(&v, 1); Exp::Abs(Ident(v, 0), Box::new(exp))
}
pub fn unbounded_var<T>(v: T) -> Exp<T>
where
T: Clone + Eq + Hash + ToString,
{
Exp::Var(Ident(v, 0))
}
#[doc(hidden)]
pub fn exp_var<T>(exp: &Exp<T>) -> Exp<T>
where
T: Clone + Eq + Hash + ToString,
{
exp.clone()
}
#[macro_export]
macro_rules! lambda {
[($( $t:tt )+)] => {
lambda![$( $t )+]
};
[{$v:expr}] => {
$crate::builder::exp_var(&$v)
};
[$v:ident] => {
$crate::builder::unbounded_var::<&str>(stringify!($v))
};
[$v:ident.$( $t:tt )+] => {
$crate::builder::abs(stringify!($v), lambda![$( $t )+])
};
[$l:tt $( $t:tt )+] => {
$crate::builder::app(vec![lambda![$l], $( lambda![$t] ),+])
};
}