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