Updated lcalc to use Cargo
Getty Ritter
10 years ago
1 | #[deriving(Eq,PartialEq,Clone,Show)] | |
2 | enum Term { | |
3 | Num(int), | |
4 | Var(String), | |
5 | Lam(String, Box<Term>), | |
6 | App(Box<Term>, Box<Term>), | |
7 | Let(String, Box<Term>, Box<Term>), | |
8 | } | |
9 | ||
10 | #[deriving(Eq,PartialEq,Clone,Show)] | |
11 | enum Val { | |
12 | VNum(int), | |
13 | VLam(String, Box<Term>, Box<Env>), | |
14 | } | |
15 | ||
16 | #[deriving(Eq,PartialEq,Clone,Show)] | |
17 | enum Env { | |
18 | Empty, | |
19 | Binding(String, Box<Val>, Box<Env>), | |
20 | } | |
21 | ||
22 | fn lookup(s: &String, e: &Env) -> Box<Val> { | |
23 | match *e { | |
24 | Empty => { fail!(format!("Couldn't find {} in environment", s)) } | |
25 | Binding(ref n, ref v, ref p) => { | |
26 | if n == s { | |
27 | v.clone() | |
28 | } else { | |
29 | lookup(s, &**p) | |
30 | } | |
31 | } | |
32 | } | |
33 | } | |
34 | ||
35 | fn lcalc_eval(t: &Term, e: &Env) -> Box<Val> { | |
36 | match t { | |
37 | &Num(num) => { box VNum(num) } | |
38 | &Var(ref str) => { lookup(str, e) } | |
39 | &Lam(ref s, ref b) => { box VLam(s.clone(), b.clone(), box e.clone()) } | |
40 | &App(box ref f, box ref x) => { | |
41 | match *lcalc_eval(f, e) { | |
42 | VLam(ref arg, box ref body, box ref env) => { | |
43 | let newEnv = Binding(arg.clone(), | |
44 | lcalc_eval(x, e), | |
45 | box env.clone()); | |
46 | lcalc_eval(body, &newEnv) | |
47 | } | |
48 | _ => fail!() | |
49 | } | |
50 | } | |
51 | &Let(ref s, box ref t, box ref b) => { | |
52 | let newEnv = Binding(s.clone(), | |
53 | lcalc_eval(t, e), | |
54 | box e.clone()); | |
55 | lcalc_eval(b, &newEnv) | |
56 | } | |
57 | } | |
58 | } | |
59 | ||
60 | fn main() { | |
61 | // (λx.λy.x)(5)(6) | |
62 | let s1 = box App(box App(box Lam("x".to_string(), | |
63 | box Lam("y".to_string(), | |
64 | box Var("x".to_string()))), | |
65 | box Num(5)), | |
66 | box Num(8)); | |
67 | // let f = (λx.λy.x)(2) in f 4 | |
68 | let s2 = box | |
69 | Let("f".to_string(), | |
70 | box App(box Lam("x".to_string(), | |
71 | box Lam("y".to_string(), | |
72 | box Var("x".to_string()))), | |
73 | box Num(2)), | |
74 | box App(box Var("f".to_string()), | |
75 | box Num(4)) | |
76 | ); | |
77 | let e = Empty; | |
78 | println!("s1: {:}", lcalc_eval(&*s1, &e)); | |
79 | println!("s2: {:}", lcalc_eval(&*s2, &e)); | |
80 | } |
1 | #[deriving(Eq,PartialEq,Clone,Show)] | |
2 | enum Term { | |
3 | Num(int), | |
4 | Var(String), | |
5 | Lam(String, Box<Term>), | |
6 | App(Box<Term>, Box<Term>), | |
7 | Let(String, Box<Term>, Box<Term>), | |
8 | } | |
9 | ||
10 | #[deriving(Eq,PartialEq,Clone,Show)] | |
11 | enum Val { | |
12 | VNum(int), | |
13 | VLam(String, Box<Term>, Box<Env>), | |
14 | } | |
15 | ||
16 | #[deriving(Eq,PartialEq,Clone,Show)] | |
17 | enum Env { | |
18 | Empty, | |
19 | Binding(String, Box<Val>, Box<Env>), | |
20 | } | |
21 | ||
22 | fn lookup(s: &String, e: &Env) -> Box<Val> { | |
23 | match *e { | |
24 | Empty => { fail!(format!("Couldn't find {} in environment", s)) } | |
25 | Binding(ref n, ref v, ref p) => { | |
26 | if n == s { | |
27 | v.clone() | |
28 | } else { | |
29 | lookup(s, &**p) | |
30 | } | |
31 | } | |
32 | } | |
33 | } | |
34 | ||
35 | fn lcalc_eval(t: &Term, e: &Env) -> Box<Val> { | |
36 | match t { | |
37 | &Num(num) => { box VNum(num) } | |
38 | &Var(ref str) => { lookup(str, e) } | |
39 | &Lam(ref s, ref b) => { box VLam(s.clone(), b.clone(), box e.clone()) } | |
40 | &App(box ref f, box ref x) => { | |
41 | match *lcalc_eval(f, e) { | |
42 | VLam(ref arg, box ref body, box ref env) => { | |
43 | let newEnv = Binding(arg.clone(), | |
44 | lcalc_eval(x, e), | |
45 | box env.clone()); | |
46 | lcalc_eval(body, &newEnv) | |
47 | } | |
48 | _ => fail!() | |
49 | } | |
50 | } | |
51 | &Let(ref s, box ref t, box ref b) => { | |
52 | let newEnv = Binding(s.clone(), | |
53 | lcalc_eval(t, e), | |
54 | box e.clone()); | |
55 | lcalc_eval(b, &newEnv) | |
56 | } | |
57 | } | |
58 | } | |
59 | ||
60 | fn main() { | |
61 | // (λx.λy.x)(5)(6) | |
62 | let s1 = box App(box App(box Lam("x".to_string(), | |
63 | box Lam("y".to_string(), | |
64 | box Var("x".to_string()))), | |
65 | box Num(5)), | |
66 | box Num(8)); | |
67 | // let f = (λx.λy.x)(2) in f 4 | |
68 | let s2 = box | |
69 | Let("f".to_string(), | |
70 | box App(box Lam("x".to_string(), | |
71 | box Lam("y".to_string(), | |
72 | box Var("x".to_string()))), | |
73 | box Num(2)), | |
74 | box App(box Var("f".to_string()), | |
75 | box Num(4)) | |
76 | ); | |
77 | let e = Empty; | |
78 | println!("s1: {:}", lcalc_eval(&*s1, &e)); | |
79 | println!("s2: {:}", lcalc_eval(&*s2, &e)); | |
80 | } |