Updated lcalc example for 0.12
Getty Ritter
11 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 | } |