gdritter repos rust-examples / 0978894
Updated lcalc example for 0.12 Getty Ritter 10 years ago
1 changed file(s) with 42 addition(s) and 35 deletion(s). Collapse all Expand all
1 use std::str::eq_slice;
2
3 #[deriving(Eq,Clone)]
1 #[deriving(Eq,PartialEq,Clone,Show)]
42 enum Term {
53 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>),
108 }
119
12 #[deriving(Eq,Clone)]
10 #[deriving(Eq,PartialEq,Clone,Show)]
1311 enum Val {
1412 VNum(int),
15 VLam(~str, ~Term, ~Env),
13 VLam(String, Box<Term>, Box<Env>),
1614 }
1715
18 #[deriving(Eq,Clone)]
16 #[deriving(Eq,PartialEq,Clone,Show)]
1917 enum Env {
2018 Empty,
21 Binding(~str, ~Val, ~Env),
19 Binding(String, Box<Val>, Box<Env>),
2220 }
2321
24 fn lookup(s: &str, e: &Env) -> ~Val {
22 fn lookup(s: &String, e: &Env) -> Box<Val> {
2523 match *e {
2624 Empty => { fail!(format!("Couldn't find {} in environment", s)) }
2725 Binding(ref n, ref v, ref p) => {
28 if eq_slice(*n, s) {
26 if n == s {
2927 v.clone()
3028 } else {
31 lookup(s, *p)
29 lookup(s, &**p)
3230 }
3331 }
3432 }
3533 }
3634
37 fn eval(t: &Term, e: &Env) -> ~Val {
35 fn lcalc_eval(t: &Term, e: &Env) -> Box<Val> {
3836 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) => {
4543 let newEnv = Binding(arg.clone(),
46 eval(*x, e),
47 env.clone());
48 eval(*body, &newEnv)
44 lcalc_eval(x, e),
45 box env.clone());
46 lcalc_eval(body, &newEnv)
4947 }
5048 _ => fail!()
5149 }
5250 }
53 &Let(ref s, ref t, ref b) => {
51 &Let(ref s, box ref t, box ref b) => {
5452 let newEnv = Binding(s.clone(),
55 eval(*t, e),
56 ~e.clone());
57 eval(*b, &newEnv)
53 lcalc_eval(t, e),
54 box e.clone());
55 lcalc_eval(b, &newEnv)
5856 }
5957 }
6058 }
6159
6260 fn main() {
6361 // (λx.λy.x)(5)(6)
64 let s1 = ~App(~App(~Lam(~"x",~Lam(~"y", ~Var(~"x"))),~Num(5)),~Num(8));
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));
6567 // 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 );
7077 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));
7380 }