Rust: apply improvements in stepA to other steps.
authorJoel Martin <github@martintribe.org>
Thu, 5 Mar 2015 19:15:12 +0000 (13:15 -0600)
committerJoel Martin <github@martintribe.org>
Thu, 5 Mar 2015 19:15:12 +0000 (13:15 -0600)
rust/src/bin/step0_repl.rs
rust/src/bin/step1_read_print.rs
rust/src/bin/step2_eval.rs
rust/src/bin/step3_env.rs
rust/src/bin/step4_if_fn_do.rs
rust/src/bin/step5_tco.rs
rust/src/bin/step6_file.rs
rust/src/bin/step7_quote.rs
rust/src/bin/step8_macros.rs
rust/src/bin/step9_try.rs
rust/src/bin/stepA_mal.rs

index 030c551..ba5f5fe 100644 (file)
@@ -1,6 +1,6 @@
 extern crate mal;
 
-use mal::readline::mal_readline;
+use mal::readline;
 
 // read
 fn read(str: String) -> String {
@@ -19,7 +19,7 @@ fn print(exp: String) -> String {
 
 fn main() {
     loop {
-        let line = mal_readline("user> ");
+        let line = readline::mal_readline("user> ");
         match line { None => break, _ => () }
         println!("{}", print(eval(read(line.unwrap()))));
     }
index 8be7e0d..02b2da7 100644 (file)
@@ -19,24 +19,18 @@ fn print(exp: MalVal) -> String {
     exp.pr_str(true)
 }
 
-fn rep(str: String) -> Result<String,MalError> {
-    match read(str) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+fn rep(str: &str) -> Result<String,MalError> {
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast));
+    Ok(print(exp))
 }
 
 fn main() {
     loop {
         let line = readline::mal_readline("user> ");
         match line { None => break, _ => () }
-        match rep(line.unwrap()) {
+        match rep(&line.unwrap()) {
             Ok(str)  => println!("{}", str),
             Err(ErrMalVal(_)) => (),  // Blank line
             Err(ErrString(s)) => println!("Error: {}", s),
index 3efa51e..fcf0383 100644 (file)
@@ -2,10 +2,10 @@ extern crate mal;
 
 use std::collections::HashMap;
 
-use mal::types::{MalVal, MalRet, MalError, err_str};
-use mal::types::{_nil, list, vector, hash_map, _int, func};
-use mal::types::MalType::{Sym, List, Vector, Hash_Map, Int};
+use mal::types::{MalVal, MalRet, MalError, err_str, err_string};
+use mal::types::{list, vector, hash_map, _int, func};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Sym, List, Vector, Hash_Map, Int};
 use mal::{readline, reader};
 
 // read
@@ -19,55 +19,45 @@ fn eval_ast(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet {
         Sym(ref sym) => {
             match env.get(sym) {
                 Some(mv) => Ok(mv.clone()),
-                None     => Ok(_nil()),
+                //None     => Ok(_nil()),
+                None     => err_string(format!("'{}' not found", sym)),
             }
         },
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
-                match eval(mv.clone(), env) {
-                    Ok(mv) => ast_vec.push(mv),
-                    Err(e) => return Err(e),
-                }
+                let mv2 = mv.clone();
+                ast_vec.push(try!(eval(mv2, env)));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env)));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast.clone())
         }
+        _ => Ok(ast.clone()),
     }
 }
 
 fn eval(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
+    //println!("eval: {}", ast);
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match eval_ast(ast, env) {
-        Err(e) => Err(e),
-        Ok(el) => {
-            match *el {
-                List(ref args,_) => {
-                    let ref f = args.clone()[0];
-                    f.apply(args[1..].to_vec())
-                }
-                _ => err_str("Invalid apply"),
-            }
-        }
+    match *try!(eval_ast(ast, env)) {
+        List(ref args,_) => {
+            let ref f = args.clone()[0];
+            f.apply(args[1..].to_vec())
+        },
+        _ => return err_str("Expected list"),
     }
 }
 
@@ -77,16 +67,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: &HashMap<String,MalVal>) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn int_op<F>(f: F, a:Vec<MalVal>) -> MalRet
index 0e75b26..afadc17 100644 (file)
@@ -6,8 +6,9 @@ use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _int, list, vector, hash_map, func};
 use mal::types::MalError::{ErrString, ErrMalVal};
 use mal::types::MalType::{Int, Sym, List, Vector, Hash_Map};
-use mal::env::{Env, env_new, env_set, env_get};
 use mal::{readline, reader};
+use mal::env::{Env, env_new, env_set, env_get};
+
 
 // read
 fn read(str: String) -> MalRet {
@@ -16,59 +17,48 @@ fn read(str: String) -> MalRet {
 
 // eval
 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
-    //match *ast {
-        Sym(_) => {
-            env_get(&env, &ast)
-        },
+    match *ast {
+        Sym(_) => env_get(&env, &ast),
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
                 let mv2 = mv.clone();
-                match eval(mv2, env.clone()) {
-                    Ok(mv) => { ast_vec.push(mv); },
-                    Err(e) => { return Err(e); },
-                }
+                ast_vec.push(try!(eval(mv2, env.clone())));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env.clone()) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env.clone())));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast)
         }
+        _ => Ok(ast.clone()),
     }
 }
 
 fn eval(ast: MalVal, env: Env) -> MalRet {
     //println!("eval: {}, {}", ast, env.borrow());
     //println!("eval: {}", ast);
-    let ast2 = ast.clone();
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return Ok(ast2),
+        _ => return Ok(ast),
     }
 
-    let (args, a0sym) = match *ast2 {
+    let tmp = ast;
+    let (args, a0sym) = match *tmp {
         List(ref args,_) => {
             if args.len() == 0 {
-                return Ok(ast);
+                return Ok(tmp.clone());
             }
             let ref a0 = *args[0];
             match *a0 {
@@ -83,20 +73,13 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
         "def!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            let res = eval(a2, env.clone());
-            match res {
-                Ok(r) => {
-                    match *a1 {
-                        Sym(_) => {
-                            env_set(&env.clone(), a1.clone(), r.clone());
-                            return Ok(r);
-                        },
-                        _ => {
-                            return err_str("def! of non-symbol")
-                        }
-                    }
+            let r = try!(eval(a2, env.clone()));
+            match *a1 {
+                Sym(_) => {
+                    env_set(&env.clone(), a1, r.clone());
+                    return Ok(r);
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "let*" => {
@@ -111,18 +94,10 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
                         let exp = it.next().unwrap();
                         match **b {
                             Sym(_) => {
-                                match eval(exp.clone(), let_env.clone()) {
-                                    Ok(r) => {
-                                        env_set(&let_env, b.clone(), r);
-                                    },
-                                    Err(e) => {
-                                        return Err(e);
-                                    },
-                                }
-                            },
-                            _ => {
-                                return err_str("let* with non-symbol binding");
+                                let r = try!(eval(exp.clone(), let_env.clone()));
+                                env_set(&let_env, b.clone(), r);
                             },
+                            _ => return err_str("let* with non-symbol binding"),
                         }
                     }
                 },
@@ -131,17 +106,13 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
             return eval(a2, let_env.clone());
         },
         _ => { // function call
-            return match eval_ast(ast, env) {
-                Err(e) => Err(e),
-                Ok(el) => {
-                    let args = match *el {
-                        List(ref args,_) => args,
-                        _ => return err_str("Invalid apply"),
-                    };
-                    let ref f = args.clone()[0];
-                    f.apply(args[1..].to_vec())
-                }
+            let el = try!(eval_ast(tmp.clone(), env.clone()));
+            let args = match *el {
+                List(ref args,_) => args,
+                _ => return err_str("Invalid apply"),
             };
+            let ref f = args.clone()[0];
+            f.apply(args[1..].to_vec())
         },
     }
 }
@@ -152,16 +123,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: Env) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn int_op<F>(f: F, a:Vec<MalVal>) -> MalRet
@@ -187,6 +152,7 @@ fn main() {
     env_set(&repl_env, symbol("*"), func(mul));
     env_set(&repl_env, symbol("/"), func(div));
 
+    // repl loop
     loop {
         let line = readline::mal_readline("user> ");
         match line { None => break, _ => () }
index afbf69a..2be0f6b 100644 (file)
@@ -4,11 +4,12 @@ use std::collections::HashMap;
 
 use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _nil, list, vector, hash_map, malfunc};
-use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map};
 use mal::{readline, reader, core};
 use mal::env::{env_set, env_get, env_new, Env};
 
+
 // read
 fn read(str: String) -> MalRet {
     reader::read_str(str)
@@ -16,57 +17,48 @@ fn read(str: String) -> MalRet {
 
 // eval
 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
-    //match *ast {
+    match *ast {
         Sym(_) => env_get(&env, &ast),
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
                 let mv2 = mv.clone();
-                match eval(mv2, env.clone()) {
-                    Ok(mv) => { ast_vec.push(mv); },
-                    Err(e) => { return Err(e); },
-                }
+                ast_vec.push(try!(eval(mv2, env.clone())));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env.clone()) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env.clone())));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast)
         }
+        _ => Ok(ast.clone()),
     }
 }
 
 fn eval(ast: MalVal, env: Env) -> MalRet {
     //println!("eval: {}, {}", ast, env.borrow());
     //println!("eval: {}", ast);
-    let ast2 = ast.clone();
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return Ok(ast2),
+        _ => return Ok(ast),
     }
 
-    let (args, a0sym) = match *ast2 {
+    let tmp = ast;
+    let (args, a0sym) = match *tmp {
         List(ref args,_) => {
             if args.len() == 0 {
-                return Ok(ast);
+                return Ok(tmp.clone());
             }
             let ref a0 = *args[0];
             match *a0 {
@@ -81,20 +73,13 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
         "def!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            let res = eval(a2, env.clone());
-            match res {
-                Ok(r) => {
-                    match *a1 {
-                        Sym(_) => {
-                            env_set(&env.clone(), a1.clone(), r.clone());
-                            return Ok(r);
-                        },
-                        _ => {
-                            return err_str("def! of non-symbol")
-                        }
-                    }
+            let r = try!(eval(a2, env.clone()));
+            match *a1 {
+                Sym(_) => {
+                    env_set(&env.clone(), a1, r.clone());
+                    return Ok(r);
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "let*" => {
@@ -109,18 +94,10 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
                         let exp = it.next().unwrap();
                         match **b {
                             Sym(_) => {
-                                match eval(exp.clone(), let_env.clone()) {
-                                    Ok(r) => {
-                                        env_set(&let_env, b.clone(), r);
-                                    },
-                                    Err(e) => {
-                                        return Err(e);
-                                    },
-                                }
-                            },
-                            _ => {
-                                return err_str("let* with non-symbol binding");
+                                let r = try!(eval(exp.clone(), let_env.clone()));
+                                env_set(&let_env, b.clone(), r);
                             },
+                            _ => return err_str("let* with non-symbol binding"),
                         }
                     }
                 },
@@ -130,57 +107,45 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
         },
         "do" => {
             let el = list(args[1..].to_vec());
-            return match eval_ast(el, env.clone()) {
-                Err(e) => return Err(e),
-                Ok(el) => {
-                    match *el {
-                        List(ref lst,_) => {
-                            let ref last = lst[lst.len()-1];
-                            return Ok(last.clone());
-                        }
-                        _ => return err_str("invalid do call"),
-                    }
-                },
-            };
+            match *try!(eval_ast(el, env.clone())) {
+                List(ref lst,_) => {
+                    let ref last = lst[lst.len()-1];
+                    return Ok(last.clone());
+                }
+                _ => return err_str("invalid do call"),
+            }
         },
         "if" => {
             let a1 = (*args)[1].clone();
-            let cond = eval(a1, env.clone());
-            match cond {
-                Err(e) => return Err(e),
-                Ok(c) => match *c {
-                    False | Nil => {
-                        if args.len() >= 4 {
-                            let a3 = (*args)[3].clone();
-                            return eval(a3, env.clone());
-                        } else {
-                            return Ok(_nil());
-                        }
-                    },
-                    _ => {
-                        let a2 = (*args)[2].clone();
-                        return eval(a2, env.clone());
-                    },
-                }
+            let c = try!(eval(a1, env.clone()));
+            match *c {
+                False | Nil => {
+                    if args.len() >= 4 {
+                        let a3 = (*args)[3].clone();
+                        return eval(a3, env.clone());
+                    } else {
+                        return Ok(_nil());
+                    }
+                },
+                _ => {
+                    let a2 = (*args)[2].clone();
+                    return eval(a2, env.clone());
+                },
             }
         },
         "fn*" => {
-            let a1 = (*args)[1].clone();
-            let a2 = (*args)[2].clone();
-            return Ok(malfunc(eval, a2, env.clone(), a1, _nil()));
+            let a1 = args[1].clone();
+            let a2 = args[2].clone();
+            return Ok(malfunc(eval, a2, env, a1, _nil()));
         },
         _ => { // function call
-            return match eval_ast(ast, env.clone()) {
-                Err(e) => Err(e),
-                Ok(el) => {
-                    let args = match *el {
-                        List(ref args,_) => args,
-                        _ => return err_str("Invalid apply"),
-                    };
-                    let ref f = args.clone()[0];
-                    f.apply(args[1..].to_vec())
-                }
+            let el = try!(eval_ast(tmp.clone(), env.clone()));
+            let args = match *el {
+                List(ref args,_) => args,
+                _ => return err_str("Invalid apply"),
             };
+            let ref f = args.clone()[0];
+            f.apply(args[1..].to_vec())
         },
     }
 }
@@ -191,16 +156,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: Env) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn main() {
@@ -213,6 +172,7 @@ fn main() {
     // core.mal: defined using the language itself
     let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
 
+    // repl loop
     loop {
         let line = readline::mal_readline("user> ");
         match line { None => break, _ => () }
index 4117634..9a2a4ce 100644 (file)
@@ -4,8 +4,8 @@ use std::collections::HashMap;
 
 use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _nil, list, vector, hash_map, malfunc};
-use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::{readline, reader, core};
 use mal::env::{env_set, env_get, env_new, env_bind, Env};
 
@@ -17,35 +17,26 @@ fn read(str: String) -> MalRet {
 
 // eval
 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
-    //match *ast {
+    match *ast {
         Sym(_) => env_get(&env, &ast),
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
                 let mv2 = mv.clone();
-                match eval(mv2, env.clone()) {
-                    Ok(mv) => { ast_vec.push(mv); },
-                    Err(e) => { return Err(e); },
-                }
+                ast_vec.push(try!(eval(mv2, env.clone())));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env.clone()) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env.clone())));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast)
         }
+        _ => Ok(ast.clone()),
     }
 }
 
@@ -54,23 +45,22 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
 
     //println!("eval: {}, {}", ast, env.borrow());
     //println!("eval: {}", ast);
-    let ast2 = ast.clone();
-    let ast3 = ast.clone();
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return Ok(ast2),
+        _ => return Ok(ast),
     }
 
-    let (args, a0sym) = match *ast2 {
+    let tmp = ast;
+    let (args, a0sym) = match *tmp {
         List(ref args,_) => {
             if args.len() == 0 {
-                return Ok(ast3);
+                return Ok(tmp.clone());
             }
             let ref a0 = *args[0];
             match *a0 {
@@ -85,20 +75,13 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         "def!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            let res = eval(a2, env.clone());
-            match res {
-                Ok(r) => {
-                    match *a1 {
-                        Sym(_) => {
-                            env_set(&env.clone(), a1.clone(), r.clone());
-                            return Ok(r);
-                        },
-                        _ => {
-                            return err_str("def! of non-symbol")
-                        }
-                    }
+            let r = try!(eval(a2, env.clone()));
+            match *a1 {
+                Sym(_) => {
+                    env_set(&env.clone(), a1, r.clone());
+                    return Ok(r);
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "let*" => {
@@ -113,18 +96,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
                         let exp = it.next().unwrap();
                         match **b {
                             Sym(_) => {
-                                match eval(exp.clone(), let_env.clone()) {
-                                    Ok(r) => {
-                                        env_set(&let_env, b.clone(), r);
-                                    },
-                                    Err(e) => {
-                                        return Err(e);
-                                    },
-                                }
-                            },
-                            _ => {
-                                return err_str("let* with non-symbol binding");
+                                let r = try!(eval(exp.clone(), let_env.clone()));
+                                env_set(&let_env, b.clone(), r);
                             },
+                            _ => return err_str("let* with non-symbol binding"),
                         }
                     }
                 },
@@ -136,71 +111,55 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         },
         "do" => {
             let el = list(args[1..args.len()-1].to_vec());
-            match eval_ast(el, env.clone()) {
-                Err(e) => return Err(e),
-                Ok(_) => {
-                    let ref last = args[args.len()-1];
-                    ast = last.clone();
-                    continue 'tco;
-                },
-            }
+            try!(eval_ast(el, env.clone()));
+            ast = args[args.len() - 1].clone();
+            continue 'tco;
         },
         "if" => {
             let a1 = (*args)[1].clone();
-            let cond = eval(a1, env.clone());
-            match cond {
-                Err(e) => return Err(e),
-                Ok(c) => match *c {
-                    False | Nil => {
-                        if args.len() >= 4 {
-                            let a3 = (*args)[3].clone();
-                            ast = a3;
-                            env = env.clone();
-                            continue 'tco;
-                        } else {
-                            return Ok(_nil());
-                        }
-                    },
-                    _ => {
-                        let a2 = (*args)[2].clone();
-                        ast = a2;
-                        env = env.clone();
+            let c = try!(eval(a1, env.clone()));
+            match *c {
+                False | Nil => {
+                    if args.len() >= 4 {
+                        ast = args[3].clone();
                         continue 'tco;
-                    },
-                }
+                    } else {
+                        return Ok(_nil());
+                    }
+                },
+                _ => {
+                    ast = args[2].clone();
+                    continue 'tco;
+                },
             }
         },
         "fn*" => {
-            let a1 = (*args)[1].clone();
-            let a2 = (*args)[2].clone();
-            return Ok(malfunc(eval, a2, env.clone(), a1, _nil()));
+            let a1 = args[1].clone();
+            let a2 = args[2].clone();
+            return Ok(malfunc(eval, a2, env, a1, _nil()));
         },
         _ => { // function call
-            return match eval_ast(ast3, env.clone()) {
-                Err(e) => Err(e),
-                Ok(el) => {
-                    let args = match *el {
-                        List(ref args,_) => args,
-                        _ => return err_str("Invalid apply"),
-                    };
-                    match *args.clone()[0] {
-                        Func(f,_) => f(args[1..].to_vec()),
-                        MalFunc(ref mf,_) => {
-                            let mfc = mf.clone();
-                            let alst = list(args[1..].to_vec());
-                            let new_env = env_new(Some(mfc.env.clone()));
-                            match env_bind(&new_env, mfc.params, alst) {
-                                Ok(_) => {
-                                    ast = mfc.exp;
-                                    env = new_env;
-                                    continue 'tco;
-                                },
-                                Err(e) => err_str(&e),
-                            }
+            let el = try!(eval_ast(tmp.clone(), env.clone()));
+            let args = match *el {
+                List(ref args,_) => args,
+                _ => return err_str("Invalid apply"),
+            };
+            return match *args.clone()[0] {
+                Func(f,_) => f(args[1..].to_vec()),
+                MalFunc(ref mf,_) => {
+                    let mfc = mf.clone();
+                    let alst = list(args[1..].to_vec());
+                    let new_env = env_new(Some(mfc.env.clone()));
+                    match env_bind(&new_env, mfc.params, alst) {
+                        Ok(_) => {
+                            ast = mfc.exp;
+                            env = new_env;
+                            continue 'tco;
                         },
-                        _ => err_str("attempt to call non-function"),
+                        Err(e) => err_str(&e),
                     }
-                }
+                },
+                _ => err_str("attempt to call non-function"),
             }
         },
     }
@@ -214,16 +173,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: Env) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn main() {
@@ -236,6 +189,7 @@ fn main() {
     // core.mal: defined using the language itself
     let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
 
+    // repl loop
     loop {
         let line = readline::mal_readline("user> ");
         match line { None => break, _ => () }
index 8d9a26c..e25608b 100644 (file)
@@ -7,11 +7,12 @@ use std::env as stdenv;
 
 use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _nil, string, list, vector, hash_map, malfunc};
-use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::{readline, reader, core};
 use mal::env::{env_set, env_get, env_new, env_bind, env_root, Env};
 
+
 // read
 fn read(str: String) -> MalRet {
     reader::read_str(str)
@@ -19,35 +20,26 @@ fn read(str: String) -> MalRet {
 
 // eval
 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
-    //match *ast {
+    match *ast {
         Sym(_) => env_get(&env, &ast),
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
                 let mv2 = mv.clone();
-                match eval(mv2, env.clone()) {
-                    Ok(mv) => { ast_vec.push(mv); },
-                    Err(e) => { return Err(e); },
-                }
+                ast_vec.push(try!(eval(mv2, env.clone())));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env.clone()) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env.clone())));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast)
         }
+        _ => Ok(ast.clone()),
     }
 }
 
@@ -56,23 +48,22 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
 
     //println!("eval: {}, {}", ast, env.borrow());
     //println!("eval: {}", ast);
-    let ast2 = ast.clone();
-    let ast3 = ast.clone();
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return Ok(ast2),
+        _ => return Ok(ast),
     }
 
-    let (args, a0sym) = match *ast2 {
+    let tmp = ast;
+    let (args, a0sym) = match *tmp {
         List(ref args,_) => {
             if args.len() == 0 {
-                return Ok(ast3);
+                return Ok(tmp.clone());
             }
             let ref a0 = *args[0];
             match *a0 {
@@ -87,20 +78,13 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         "def!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            let res = eval(a2, env.clone());
-            match res {
-                Ok(r) => {
-                    match *a1 {
-                        Sym(_) => {
-                            env_set(&env.clone(), a1.clone(), r.clone());
-                            return Ok(r);
-                        },
-                        _ => {
-                            return err_str("def! of non-symbol")
-                        }
-                    }
+            let r = try!(eval(a2, env.clone()));
+            match *a1 {
+                Sym(_) => {
+                    env_set(&env.clone(), a1, r.clone());
+                    return Ok(r);
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "let*" => {
@@ -115,18 +99,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
                         let exp = it.next().unwrap();
                         match **b {
                             Sym(_) => {
-                                match eval(exp.clone(), let_env.clone()) {
-                                    Ok(r) => {
-                                        env_set(&let_env, b.clone(), r);
-                                    },
-                                    Err(e) => {
-                                        return Err(e);
-                                    },
-                                }
-                            },
-                            _ => {
-                                return err_str("let* with non-symbol binding");
+                                let r = try!(eval(exp.clone(), let_env.clone()));
+                                env_set(&let_env, b.clone(), r);
                             },
+                            _ => return err_str("let* with non-symbol binding"),
                         }
                     }
                 },
@@ -138,82 +114,61 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         },
         "do" => {
             let el = list(args[1..args.len()-1].to_vec());
-            match eval_ast(el, env.clone()) {
-                Err(e) => return Err(e),
-                Ok(_) => {
-                    let ref last = args[args.len()-1];
-                    ast = last.clone();
-                    continue 'tco;
-                },
-            }
+            try!(eval_ast(el, env.clone()));
+            ast = args[args.len() - 1].clone();
+            continue 'tco;
         },
         "if" => {
             let a1 = (*args)[1].clone();
-            let cond = eval(a1, env.clone());
-            match cond {
-                Err(e) => return Err(e),
-                Ok(c) => match *c {
-                    False | Nil => {
-                        if args.len() >= 4 {
-                            let a3 = (*args)[3].clone();
-                            ast = a3;
-                            env = env.clone();
-                            continue 'tco;
-                        } else {
-                            return Ok(_nil());
-                        }
-                    },
-                    _ => {
-                        let a2 = (*args)[2].clone();
-                        ast = a2;
-                        env = env.clone();
+            let c = try!(eval(a1, env.clone()));
+            match *c {
+                False | Nil => {
+                    if args.len() >= 4 {
+                        ast = args[3].clone();
                         continue 'tco;
-                    },
-                }
+                    } else {
+                        return Ok(_nil());
+                    }
+                },
+                _ => {
+                    ast = args[2].clone();
+                    continue 'tco;
+                },
             }
         },
         "fn*" => {
-            let a1 = (*args)[1].clone();
-            let a2 = (*args)[2].clone();
-            return Ok(malfunc(eval, a2, env.clone(), a1, _nil()));
+            let a1 = args[1].clone();
+            let a2 = args[2].clone();
+            return Ok(malfunc(eval, a2, env, a1, _nil()));
         },
         "eval" => {
             let a1 = (*args)[1].clone();
-            match eval(a1, env.clone()) {
-                Ok(exp) => {
-                    ast = exp;
-                    env = env_root(&env);
-                    continue 'tco;
-                },
-                Err(e) => return Err(e),
-            }
+            ast = try!(eval(a1, env.clone()));
+            env = env_root(&env);
+            continue 'tco;
         },
         _ => { // function call
-            return match eval_ast(ast3, env.clone()) {
-                Err(e) => Err(e),
-                Ok(el) => {
-                    let args = match *el {
-                        List(ref args,_) => args,
-                        _ => return err_str("Invalid apply"),
-                    };
-                    match *args.clone()[0] {
-                        Func(f,_) => f(args[1..].to_vec()),
-                        MalFunc(ref mf,_) => {
-                            let mfc = mf.clone();
-                            let alst = list(args[1..].to_vec());
-                            let new_env = env_new(Some(mfc.env.clone()));
-                            match env_bind(&new_env, mfc.params, alst) {
-                                Ok(_) => {
-                                    ast = mfc.exp;
-                                    env = new_env;
-                                    continue 'tco;
-                                },
-                                Err(e) => err_str(&e),
-                            }
+            let el = try!(eval_ast(tmp.clone(), env.clone()));
+            let args = match *el {
+                List(ref args,_) => args,
+                _ => return err_str("Invalid apply"),
+            };
+            return match *args.clone()[0] {
+                Func(f,_) => f(args[1..].to_vec()),
+                MalFunc(ref mf,_) => {
+                    let mfc = mf.clone();
+                    let alst = list(args[1..].to_vec());
+                    let new_env = env_new(Some(mfc.env.clone()));
+                    match env_bind(&new_env, mfc.params, alst) {
+                        Ok(_) => {
+                            ast = mfc.exp;
+                            env = new_env;
+                            continue 'tco;
                         },
-                        _ => err_str("attempt to call non-function"),
+                        Err(e) => err_str(&e),
                     }
-                }
+                },
+                _ => err_str("attempt to call non-function"),
             }
         },
     }
@@ -227,16 +182,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: Env) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn main() {
@@ -270,6 +219,7 @@ fn main() {
         };
     }
 
+    // repl loop
     loop {
         let line = readline::mal_readline("user> ");
         match line { None => break, _ => () }
index 77d5d33..0c88225 100644 (file)
@@ -7,8 +7,8 @@ use std::env as stdenv;
 
 use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _nil, string, list, vector, hash_map, malfunc};
-use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::{readline, reader, core};
 use mal::env::{env_set, env_get, env_new, env_bind, env_root, Env};
 
@@ -35,25 +35,17 @@ fn quasiquote(ast: MalVal) -> MalVal {
         List(ref args,_) | Vector(ref args,_) => {
             let ref a0 = args[0];
             match **a0 {
-                Sym(ref s) => {
-                    if s.to_string() == "unquote".to_string() {
-                        let ref a1 = args[1];
-                        return a1.clone();
-                    }
-                },
+                Sym(ref s) if *s == "unquote" => return args[1].clone(),
                 _ => (),
             }
             if is_pair(a0.clone()) {
                 match **a0 {
                     List(ref a0args,_) | Vector(ref a0args,_) => {
-                        let a00 = a0args[0].clone();
-                        match *a00 {
-                            Sym(ref s) => {
-                                if s.to_string() == "splice-unquote".to_string() {
-                                    return list(vec![symbol("concat"),
-                                                     a0args[1].clone(),
-                                                     quasiquote(list(args[1..].to_vec()))])
-                                }
+                        match *a0args[0] {
+                            Sym(ref s) if *s == "splice-unquote" => {
+                                return list(vec![symbol("concat"),
+                                                 a0args[1].clone(),
+                                                 quasiquote(list(args[1..].to_vec()))])
                             },
                             _ => (),
                         }
@@ -71,35 +63,26 @@ fn quasiquote(ast: MalVal) -> MalVal {
 }
 
 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
-    //match *ast {
+    match *ast {
         Sym(_) => env_get(&env, &ast),
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
                 let mv2 = mv.clone();
-                match eval(mv2, env.clone()) {
-                    Ok(mv) => { ast_vec.push(mv); },
-                    Err(e) => { return Err(e); },
-                }
+                ast_vec.push(try!(eval(mv2, env.clone())));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env.clone()) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env.clone())));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast)
         }
+        _ => Ok(ast.clone()),
     }
 }
 
@@ -108,23 +91,22 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
 
     //println!("eval: {}, {}", ast, env.borrow());
     //println!("eval: {}", ast);
-    let ast2 = ast.clone();
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return Ok(ast2),
+        _ => return Ok(ast),
     }
-    let ast3 = ast2.clone();
 
-    let (args, a0sym) = match *ast2 {
+    let tmp = ast;
+    let (args, a0sym) = match *tmp {
         List(ref args,_) => {
             if args.len() == 0 {
-                return Ok(ast3);
+                return Ok(tmp.clone());
             }
             let ref a0 = *args[0];
             match *a0 {
@@ -139,20 +121,13 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         "def!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            let res = eval(a2, env.clone());
-            match res {
-                Ok(r) => {
-                    match *a1 {
-                        Sym(_) => {
-                            env_set(&env.clone(), a1.clone(), r.clone());
-                            return Ok(r);
-                        },
-                        _ => {
-                            return err_str("def! of non-symbol")
-                        }
-                    }
+            let r = try!(eval(a2, env.clone()));
+            match *a1 {
+                Sym(_) => {
+                    env_set(&env.clone(), a1, r.clone());
+                    return Ok(r);
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "let*" => {
@@ -167,18 +142,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
                         let exp = it.next().unwrap();
                         match **b {
                             Sym(_) => {
-                                match eval(exp.clone(), let_env.clone()) {
-                                    Ok(r) => {
-                                        env_set(&let_env, b.clone(), r);
-                                    },
-                                    Err(e) => {
-                                        return Err(e);
-                                    },
-                                }
-                            },
-                            _ => {
-                                return err_str("let* with non-symbol binding");
+                                let r = try!(eval(exp.clone(), let_env.clone()));
+                                env_set(&let_env, b.clone(), r);
                             },
+                            _ => return err_str("let* with non-symbol binding"),
                         }
                     }
                 },
@@ -188,9 +155,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
             env = let_env.clone();
             continue 'tco;
         },
-        "quote" => {
-            return Ok((*args)[1].clone());
-        },
+        "quote" => return Ok((*args)[1].clone()),
         "quasiquote" => {
             let a1 = (*args)[1].clone();
             ast = quasiquote(a1);
@@ -198,82 +163,61 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         },
         "do" => {
             let el = list(args[1..args.len()-1].to_vec());
-            match eval_ast(el, env.clone()) {
-                Err(e) => return Err(e),
-                Ok(_) => {
-                    let ref last = args[args.len()-1];
-                    ast = last.clone();
-                    continue 'tco;
-                },
-            }
+            try!(eval_ast(el, env.clone()));
+            ast = args[args.len() - 1].clone();
+            continue 'tco;
         },
         "if" => {
             let a1 = (*args)[1].clone();
-            let cond = eval(a1, env.clone());
-            match cond {
-                Err(e) => return Err(e),
-                Ok(c) => match *c {
-                    False | Nil => {
-                        if args.len() >= 4 {
-                            let a3 = (*args)[3].clone();
-                            ast = a3;
-                            env = env.clone();
-                            continue 'tco;
-                        } else {
-                            return Ok(_nil());
-                        }
-                    },
-                    _ => {
-                        let a2 = (*args)[2].clone();
-                        ast = a2;
-                        env = env.clone();
+            let c = try!(eval(a1, env.clone()));
+            match *c {
+                False | Nil => {
+                    if args.len() >= 4 {
+                        ast = args[3].clone();
                         continue 'tco;
-                    },
-                }
+                    } else {
+                        return Ok(_nil());
+                    }
+                },
+                _ => {
+                    ast = args[2].clone();
+                    continue 'tco;
+                },
             }
         },
         "fn*" => {
-            let a1 = (*args)[1].clone();
-            let a2 = (*args)[2].clone();
-            return Ok(malfunc(eval, a2, env.clone(), a1, _nil()));
+            let a1 = args[1].clone();
+            let a2 = args[2].clone();
+            return Ok(malfunc(eval, a2, env, a1, _nil()));
         },
         "eval" => {
             let a1 = (*args)[1].clone();
-            match eval(a1, env.clone()) {
-                Ok(exp) => {
-                    ast = exp;
-                    env = env_root(&env);
-                    continue 'tco;
-                },
-                Err(e) => return Err(e),
-            }
+            ast = try!(eval(a1, env.clone()));
+            env = env_root(&env);
+            continue 'tco;
         },
         _ => { // function call
-            return match eval_ast(ast3, env.clone()) {
-                Err(e) => Err(e),
-                Ok(el) => {
-                    let args = match *el {
-                        List(ref args,_) => args,
-                        _ => return err_str("Invalid apply"),
-                    };
-                    match *args.clone()[0] {
-                        Func(f,_) => f(args[1..].to_vec()),
-                        MalFunc(ref mf,_) => {
-                            let mfc = mf.clone();
-                            let alst = list(args[1..].to_vec());
-                            let new_env = env_new(Some(mfc.env.clone()));
-                            match env_bind(&new_env, mfc.params, alst) {
-                                Ok(_) => {
-                                    ast = mfc.exp;
-                                    env = new_env;
-                                    continue 'tco;
-                                },
-                                Err(e) => err_str(&e),
-                            }
+            let el = try!(eval_ast(tmp.clone(), env.clone()));
+            let args = match *el {
+                List(ref args,_) => args,
+                _ => return err_str("Invalid apply"),
+            };
+            return match *args.clone()[0] {
+                Func(f,_) => f(args[1..].to_vec()),
+                MalFunc(ref mf,_) => {
+                    let mfc = mf.clone();
+                    let alst = list(args[1..].to_vec());
+                    let new_env = env_new(Some(mfc.env.clone()));
+                    match env_bind(&new_env, mfc.params, alst) {
+                        Ok(_) => {
+                            ast = mfc.exp;
+                            env = new_env;
+                            continue 'tco;
                         },
-                        _ => err_str("attempt to call non-function"),
+                        Err(e) => err_str(&e),
                     }
-                }
+                },
+                _ => err_str("attempt to call non-function"),
             }
         },
     }
@@ -287,16 +231,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: Env) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn main() {
@@ -330,6 +268,7 @@ fn main() {
         };
     }
 
+    // repl loop
     loop {
         let line = readline::mal_readline("user> ");
         match line { None => break, _ => () }
index a808926..770ff8c 100644 (file)
@@ -7,11 +7,12 @@ use std::env as stdenv;
 
 use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _nil, string, list, vector, hash_map, malfunc, malfuncd};
-use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::{readline, reader, core};
 use mal::env::{env_set, env_get, env_new, env_bind, env_find, env_root, Env};
 
+
 // read
 fn read(str: String) -> MalRet {
     reader::read_str(str)
@@ -34,25 +35,17 @@ fn quasiquote(ast: MalVal) -> MalVal {
         List(ref args,_) | Vector(ref args,_) => {
             let ref a0 = args[0];
             match **a0 {
-                Sym(ref s) => {
-                    if s.to_string() == "unquote".to_string() {
-                        let ref a1 = args[1];
-                        return a1.clone();
-                    }
-                },
+                Sym(ref s) if *s == "unquote" => return args[1].clone(),
                 _ => (),
             }
             if is_pair(a0.clone()) {
                 match **a0 {
                     List(ref a0args,_) | Vector(ref a0args,_) => {
-                        let a00 = a0args[0].clone();
-                        match *a00 {
-                            Sym(ref s) => {
-                                if s.to_string() == "splice-unquote".to_string() {
-                                    return list(vec![symbol("concat"),
-                                                     a0args[1].clone(),
-                                                     quasiquote(list(args[1..].to_vec()))])
-                                }
+                        match *a0args[0] {
+                            Sym(ref s) if *s == "splice-unquote" => {
+                                return list(vec![symbol("concat"),
+                                                 a0args[1].clone(),
+                                                 quasiquote(list(args[1..].to_vec()))])
                             },
                             _ => (),
                         }
@@ -70,29 +63,23 @@ fn quasiquote(ast: MalVal) -> MalVal {
 }
 
 fn is_macro_call(ast: MalVal, env: Env) -> bool {
-    match *ast {
-        List(ref lst,_) => {
-            match *lst[0] {
-                Sym(_) => {
-                    if env_find(&env, &lst[0]).is_some() {
-                        match env_get(&env, &lst[0]) {
-                            Ok(f) => {
-                                match *f {
-                                    MalFunc(ref mfd,_) => {
-                                        mfd.is_macro
-                                    },
-                                    _ => false,
-                                }
-                            },
-                            _ => false,
-                        }
-                    } else {
-                        false
-                    }
-                },
-                _ => false,
-            }
-        },
+    let lst = match *ast {
+        List(ref lst,_) => &lst[0],
+        _ => return false
+    };
+    match **lst {
+        Sym(_) => {},
+        _ => return false
+    }
+    if env_find(&env, lst).is_none() {
+        return false
+    }
+    let f = match env_get(&env, lst) {
+        Ok(f) => f,
+        _ => return false
+    };
+    match *f {
+        MalFunc(ref mfd,_) => mfd.is_macro,
         _ => false,
     }
 }
@@ -118,35 +105,26 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet {
 }
 
 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
-    //match *ast {
+    match *ast {
         Sym(_) => env_get(&env, &ast),
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
                 let mv2 = mv.clone();
-                match eval(mv2, env.clone()) {
-                    Ok(mv) => { ast_vec.push(mv); },
-                    Err(e) => { return Err(e); },
-                }
+                ast_vec.push(try!(eval(mv2, env.clone())));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env.clone()) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env.clone())));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast)
         }
+        _ => Ok(ast.clone()),
     }
 }
 
@@ -155,29 +133,23 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
 
     //println!("eval: {}, {}", ast, env.borrow());
     //println!("eval: {}", ast);
-    let mut ast2 = ast.clone();
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match macroexpand(ast2, env.clone()) {
-        Ok(a) => {
-            ast2 = a;
-        },
-        Err(e) => return Err(e),
-    }
-    match *ast2 {
+    ast = try!(macroexpand(ast, env.clone()));
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return Ok(ast2),
+        _ => return Ok(ast),
     }
-    let ast3 = ast2.clone();
 
-    let (args, a0sym) = match *ast2 {
+    let tmp = ast;
+    let (args, a0sym) = match *tmp {
         List(ref args,_) => {
             if args.len() == 0 {
-                return Ok(ast3);
+                return Ok(tmp.clone());
             }
             let ref a0 = *args[0];
             match *a0 {
@@ -192,20 +164,13 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         "def!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            let res = eval(a2, env.clone());
-            match res {
-                Ok(r) => {
-                    match *a1 {
-                        Sym(_) => {
-                            env_set(&env.clone(), a1.clone(), r.clone());
-                            return Ok(r);
-                        },
-                        _ => {
-                            return err_str("def! of non-symbol")
-                        }
-                    }
+            let r = try!(eval(a2, env.clone()));
+            match *a1 {
+                Sym(_) => {
+                    env_set(&env.clone(), a1, r.clone());
+                    return Ok(r);
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "let*" => {
@@ -220,18 +185,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
                         let exp = it.next().unwrap();
                         match **b {
                             Sym(_) => {
-                                match eval(exp.clone(), let_env.clone()) {
-                                    Ok(r) => {
-                                        env_set(&let_env, b.clone(), r);
-                                    },
-                                    Err(e) => {
-                                        return Err(e);
-                                    },
-                                }
-                            },
-                            _ => {
-                                return err_str("let* with non-symbol binding");
+                                let r = try!(eval(exp.clone(), let_env.clone()));
+                                env_set(&let_env, b.clone(), r);
                             },
+                            _ => return err_str("let* with non-symbol binding"),
                         }
                     }
                 },
@@ -241,9 +198,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
             env = let_env.clone();
             continue 'tco;
         },
-        "quote" => {
-            return Ok((*args)[1].clone());
-        },
+        "quote" => return Ok((*args)[1].clone()),
         "quasiquote" => {
             let a1 = (*args)[1].clone();
             ast = quasiquote(a1);
@@ -252,25 +207,21 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         "defmacro!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            match eval(a2, env.clone()) {
-                Ok(r) => {
-                    match *r {
-                        MalFunc(ref mfd,_) => {
-                            match *a1 {
-                                Sym(_) => {
-                                    let mut new_mfd = mfd.clone();
-                                    new_mfd.is_macro = true;
-                                    let mf = malfuncd(new_mfd,_nil());
-                                    env_set(&env.clone(), a1.clone(), mf.clone());
-                                    return Ok(mf);
-                                },
-                                _ => return err_str("def! of non-symbol"),
-                            }
+            let r = try!(eval(a2, env.clone()));
+            match *r {
+                MalFunc(ref mfd,_) => {
+                    match *a1 {
+                        Sym(_) => {
+                            let mut new_mfd = mfd.clone();
+                            new_mfd.is_macro = true;
+                            let mf = malfuncd(new_mfd,_nil());
+                            env_set(&env.clone(), a1.clone(), mf.clone());
+                            return Ok(mf);
                         },
                         _ => return err_str("def! of non-symbol"),
                     }
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "macroexpand" => {
@@ -279,82 +230,61 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         },
         "do" => {
             let el = list(args[1..args.len()-1].to_vec());
-            match eval_ast(el, env.clone()) {
-                Err(e) => return Err(e),
-                Ok(_) => {
-                    let ref last = args[args.len()-1];
-                    ast = last.clone();
-                    continue 'tco;
-                },
-            }
+            try!(eval_ast(el, env.clone()));
+            ast = args[args.len() - 1].clone();
+            continue 'tco;
         },
         "if" => {
             let a1 = (*args)[1].clone();
-            let cond = eval(a1, env.clone());
-            match cond {
-                Err(e) => return Err(e),
-                Ok(c) => match *c {
-                    False | Nil => {
-                        if args.len() >= 4 {
-                            let a3 = (*args)[3].clone();
-                            ast = a3;
-                            env = env.clone();
-                            continue 'tco;
-                        } else {
-                            return Ok(_nil());
-                        }
-                    },
-                    _ => {
-                        let a2 = (*args)[2].clone();
-                        ast = a2;
-                        env = env.clone();
+            let c = try!(eval(a1, env.clone()));
+            match *c {
+                False | Nil => {
+                    if args.len() >= 4 {
+                        ast = args[3].clone();
                         continue 'tco;
-                    },
-                }
+                    } else {
+                        return Ok(_nil());
+                    }
+                },
+                _ => {
+                    ast = args[2].clone();
+                    continue 'tco;
+                },
             }
         },
         "fn*" => {
-            let a1 = (*args)[1].clone();
-            let a2 = (*args)[2].clone();
-            return Ok(malfunc(eval, a2, env.clone(), a1, _nil()));
+            let a1 = args[1].clone();
+            let a2 = args[2].clone();
+            return Ok(malfunc(eval, a2, env, a1, _nil()));
         },
         "eval" => {
             let a1 = (*args)[1].clone();
-            match eval(a1, env.clone()) {
-                Ok(exp) => {
-                    ast = exp;
-                    env = env_root(&env);
-                    continue 'tco;
-                },
-                Err(e) => return Err(e),
-            }
+            ast = try!(eval(a1, env.clone()));
+            env = env_root(&env);
+            continue 'tco;
         },
         _ => { // function call
-            return match eval_ast(ast3, env.clone()) {
-                Err(e) => Err(e),
-                Ok(el) => {
-                    let args = match *el {
-                        List(ref args,_) => args,
-                        _ => return err_str("Invalid apply"),
-                    };
-                    match *args.clone()[0] {
-                        Func(f,_) => f(args[1..].to_vec()),
-                        MalFunc(ref mf,_) => {
-                            let mfc = mf.clone();
-                            let alst = list(args[1..].to_vec());
-                            let new_env = env_new(Some(mfc.env.clone()));
-                            match env_bind(&new_env, mfc.params, alst) {
-                                Ok(_) => {
-                                    ast = mfc.exp;
-                                    env = new_env;
-                                    continue 'tco;
-                                },
-                                Err(e) => err_str(&e),
-                            }
+            let el = try!(eval_ast(tmp.clone(), env.clone()));
+            let args = match *el {
+                List(ref args,_) => args,
+                _ => return err_str("Invalid apply"),
+            };
+            return match *args.clone()[0] {
+                Func(f,_) => f(args[1..].to_vec()),
+                MalFunc(ref mf,_) => {
+                    let mfc = mf.clone();
+                    let alst = list(args[1..].to_vec());
+                    let new_env = env_new(Some(mfc.env.clone()));
+                    match env_bind(&new_env, mfc.params, alst) {
+                        Ok(_) => {
+                            ast = mfc.exp;
+                            env = new_env;
+                            continue 'tco;
                         },
-                        _ => err_str("attempt to call non-function"),
+                        Err(e) => err_str(&e),
                     }
-                }
+                },
+                _ => err_str("attempt to call non-function"),
             }
         },
     }
@@ -368,16 +298,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: Env) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn main() {
index f6c5dbf..871af2e 100644 (file)
@@ -7,11 +7,12 @@ use std::env as stdenv;
 
 use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _nil, string, list, vector, hash_map, malfunc, malfuncd};
-use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::{readline, reader, core};
 use mal::env::{env_set, env_get, env_new, env_bind, env_find, env_root, Env};
 
+
 // read
 fn read(str: String) -> MalRet {
     reader::read_str(str)
@@ -20,7 +21,7 @@ fn read(str: String) -> MalRet {
 // eval
 fn is_pair(x: MalVal) -> bool {
     match *x {
-        List(ref lst, _) | Vector(ref lst, _) => lst.len() > 0,
+        List(ref lst,_) | Vector(ref lst,_) => lst.len() > 0,
         _ => false,
     }
 }
@@ -34,25 +35,17 @@ fn quasiquote(ast: MalVal) -> MalVal {
         List(ref args,_) | Vector(ref args,_) => {
             let ref a0 = args[0];
             match **a0 {
-                Sym(ref s) => {
-                    if s.to_string() == "unquote".to_string() {
-                        let ref a1 = args[1];
-                        return a1.clone();
-                    }
-                },
+                Sym(ref s) if *s == "unquote" => return args[1].clone(),
                 _ => (),
             }
             if is_pair(a0.clone()) {
                 match **a0 {
                     List(ref a0args,_) | Vector(ref a0args,_) => {
-                        let a00 = a0args[0].clone();
-                        match *a00 {
-                            Sym(ref s) => {
-                                if s.to_string() == "splice-unquote".to_string() {
-                                    return list(vec![symbol("concat"),
-                                                     a0args[1].clone(),
-                                                     quasiquote(list(args[1..].to_vec()))])
-                                }
+                        match *a0args[0] {
+                            Sym(ref s) if *s == "splice-unquote" => {
+                                return list(vec![symbol("concat"),
+                                                 a0args[1].clone(),
+                                                 quasiquote(list(args[1..].to_vec()))])
                             },
                             _ => (),
                         }
@@ -70,29 +63,23 @@ fn quasiquote(ast: MalVal) -> MalVal {
 }
 
 fn is_macro_call(ast: MalVal, env: Env) -> bool {
-    match *ast {
-        List(ref lst,_) => {
-            match *lst[0] {
-                Sym(_) => {
-                    if env_find(&env, &lst[0]).is_some() {
-                        match env_get(&env, &lst[0]) {
-                            Ok(f) => {
-                                match *f {
-                                    MalFunc(ref mfd,_) => {
-                                        mfd.is_macro
-                                    },
-                                    _ => false,
-                                }
-                            },
-                            _ => false,
-                        }
-                    } else {
-                        false
-                    }
-                },
-                _ => false,
-            }
-        },
+    let lst = match *ast {
+        List(ref lst,_) => &lst[0],
+        _ => return false
+    };
+    match **lst {
+        Sym(_) => {},
+        _ => return false
+    }
+    if env_find(&env, lst).is_none() {
+        return false
+    }
+    let f = match env_get(&env, lst) {
+        Ok(f) => f,
+        _ => return false
+    };
+    match *f {
+        MalFunc(ref mfd,_) => mfd.is_macro,
         _ => false,
     }
 }
@@ -106,21 +93,11 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet {
         };
         let ref a0 = args[0];
         let mf = match **a0 {
-            Sym(_) => {
-                match env_get(&env, &a0) {
-                    Ok(mf) => mf,
-                    Err(e) => return Err(e),
-                }
-            },
+            Sym(_) => try!(env_get(&env, &a0)),
             _ => break,
         };
         match *mf {
-            MalFunc(_,_) => {
-                match mf.apply(args[1..].to_vec()) {
-                    Ok(r) => ast = r,
-                    Err(e) => return Err(e),
-                }
-            },
+            MalFunc(_,_) => ast = try!(mf.apply(args[1..].to_vec())),
             _ => break,
         }
     }
@@ -128,37 +105,26 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet {
 }
 
 fn eval_ast(ast: MalVal, env: Env) -> MalRet {
-    let ast2 = ast.clone();
-    match *ast2 {
-    //match *ast {
-        Sym(_) => {
-            env_get(&env, &ast)
-        },
+    match *ast {
+        Sym(_) => env_get(&env, &ast),
         List(ref a,_) | Vector(ref a,_) => {
             let mut ast_vec : Vec<MalVal> = vec![];
             for mv in a.iter() {
                 let mv2 = mv.clone();
-                match eval(mv2, env.clone()) {
-                    Ok(mv) => { ast_vec.push(mv); },
-                    Err(e) => { return Err(e); },
-                }
+                ast_vec.push(try!(eval(mv2, env.clone())));
             }
             Ok(match *ast { List(_,_) => list(ast_vec),
                             _         => vector(ast_vec) })
-        },
+        }
         Hash_Map(ref hm,_) => {
             let mut new_hm: HashMap<String,MalVal> = HashMap::new();
             for (key, value) in hm.iter() {
-                match eval(value.clone(), env.clone()) {
-                    Ok(mv) => { new_hm.insert(key.to_string(), mv); },
-                    Err(e) => return Err(e),
-                }
+                new_hm.insert(key.to_string(),
+                              try!(eval(value.clone(), env.clone())));
             }
             Ok(hash_map(new_hm))
-        },
-        _ => {
-            Ok(ast)
         }
+        _ => Ok(ast.clone()),
     }
 }
 
@@ -167,29 +133,23 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
 
     //println!("eval: {}, {}", ast, env.borrow());
     //println!("eval: {}", ast);
-    let mut ast2 = ast.clone();
-    match *ast2 {
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return eval_ast(ast2, env),
+        _ => return eval_ast(ast, env),
     }
 
     // apply list
-    match macroexpand(ast2, env.clone()) {
-        Ok(a) => {
-            ast2 = a;
-        },
-        Err(e) => return Err(e),
-    }
-    match *ast2 {
+    ast = try!(macroexpand(ast, env.clone()));
+    match *ast {
         List(_,_) => (),  // continue
-        _ => return Ok(ast2),
+        _ => return Ok(ast),
     }
-    let ast3 = ast2.clone();
 
-    let (args, a0sym) = match *ast2 {
+    let tmp = ast;
+    let (args, a0sym) = match *tmp {
         List(ref args,_) => {
             if args.len() == 0 {
-                return Ok(ast3);
+                return Ok(tmp.clone());
             }
             let ref a0 = *args[0];
             match *a0 {
@@ -204,20 +164,13 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         "def!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            let res = eval(a2, env.clone());
-            match res {
-                Ok(r) => {
-                    match *a1 {
-                        Sym(_) => {
-                            env_set(&env.clone(), a1.clone(), r.clone());
-                            return Ok(r);
-                        },
-                        _ => {
-                            return err_str("def! of non-symbol")
-                        }
-                    }
+            let r = try!(eval(a2, env.clone()));
+            match *a1 {
+                Sym(_) => {
+                    env_set(&env.clone(), a1, r.clone());
+                    return Ok(r);
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "let*" => {
@@ -232,18 +185,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
                         let exp = it.next().unwrap();
                         match **b {
                             Sym(_) => {
-                                match eval(exp.clone(), let_env.clone()) {
-                                    Ok(r) => {
-                                        env_set(&let_env, b.clone(), r);
-                                    },
-                                    Err(e) => {
-                                        return Err(e);
-                                    },
-                                }
-                            },
-                            _ => {
-                                return err_str("let* with non-symbol binding");
+                                let r = try!(eval(exp.clone(), let_env.clone()));
+                                env_set(&let_env, b.clone(), r);
                             },
+                            _ => return err_str("let* with non-symbol binding"),
                         }
                     }
                 },
@@ -253,9 +198,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
             env = let_env.clone();
             continue 'tco;
         },
-        "quote" => {
-            return Ok((*args)[1].clone());
-        },
+        "quote" => return Ok((*args)[1].clone()),
         "quasiquote" => {
             let a1 = (*args)[1].clone();
             ast = quasiquote(a1);
@@ -264,25 +207,21 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         "defmacro!" => {
             let a1 = (*args)[1].clone();
             let a2 = (*args)[2].clone();
-            match eval(a2, env.clone()) {
-                Ok(r) => {
-                    match *r {
-                        MalFunc(ref mfd,_) => {
-                            match *a1 {
-                                Sym(_) => {
-                                    let mut new_mfd = mfd.clone();
-                                    new_mfd.is_macro = true;
-                                    let mf = malfuncd(new_mfd,_nil());
-                                    env_set(&env.clone(), a1.clone(), mf.clone());
-                                    return Ok(mf);
-                                },
-                                _ => return err_str("def! of non-symbol"),
-                            }
+            let r = try!(eval(a2, env.clone()));
+            match *r {
+                MalFunc(ref mfd,_) => {
+                    match *a1 {
+                        Sym(_) => {
+                            let mut new_mfd = mfd.clone();
+                            new_mfd.is_macro = true;
+                            let mf = malfuncd(new_mfd,_nil());
+                            env_set(&env.clone(), a1.clone(), mf.clone());
+                            return Ok(mf);
                         },
                         _ => return err_str("def! of non-symbol"),
                     }
                 },
-                Err(e) => return Err(e),
+                _ => return err_str("def! of non-symbol"),
             }
         },
         "macroexpand" => {
@@ -321,82 +260,61 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
         }
         "do" => {
             let el = list(args[1..args.len()-1].to_vec());
-            match eval_ast(el, env.clone()) {
-                Err(e) => return Err(e),
-                Ok(_) => {
-                    let ref last = args[args.len()-1];
-                    ast = last.clone();
-                    continue 'tco;
-                },
-            }
+            try!(eval_ast(el, env.clone()));
+            ast = args[args.len() - 1].clone();
+            continue 'tco;
         },
         "if" => {
             let a1 = (*args)[1].clone();
-            let cond = eval(a1, env.clone());
-            match cond {
-                Err(e) => return Err(e),
-                Ok(c) => match *c {
-                    False | Nil => {
-                        if args.len() >= 4 {
-                            let a3 = (*args)[3].clone();
-                            ast = a3;
-                            env = env.clone();
-                            continue 'tco;
-                        } else {
-                            return Ok(_nil());
-                        }
-                    },
-                    _ => {
-                        let a2 = (*args)[2].clone();
-                        ast = a2;
-                        env = env.clone();
+            let c = try!(eval(a1, env.clone()));
+            match *c {
+                False | Nil => {
+                    if args.len() >= 4 {
+                        ast = args[3].clone();
                         continue 'tco;
-                    },
-                }
+                    } else {
+                        return Ok(_nil());
+                    }
+                },
+                _ => {
+                    ast = args[2].clone();
+                    continue 'tco;
+                },
             }
         },
         "fn*" => {
-            let a1 = (*args)[1].clone();
-            let a2 = (*args)[2].clone();
-            return Ok(malfunc(eval, a2, env.clone(), a1, _nil()));
+            let a1 = args[1].clone();
+            let a2 = args[2].clone();
+            return Ok(malfunc(eval, a2, env, a1, _nil()));
         },
         "eval" => {
             let a1 = (*args)[1].clone();
-            match eval(a1, env.clone()) {
-                Ok(exp) => {
-                    ast = exp;
-                    env = env_root(&env);
-                    continue 'tco;
-                },
-                Err(e) => return Err(e),
-            }
+            ast = try!(eval(a1, env.clone()));
+            env = env_root(&env);
+            continue 'tco;
         },
         _ => { // function call
-            return match eval_ast(ast3, env.clone()) {
-                Err(e) => Err(e),
-                Ok(el) => {
-                    let args = match *el {
-                        List(ref args,_) => args,
-                        _ => return err_str("Invalid apply"),
-                    };
-                    match *args.clone()[0] {
-                        Func(f,_) => f(args[1..].to_vec()),
-                        MalFunc(ref mf,_) => {
-                            let mfc = mf.clone();
-                            let alst = list(args[1..].to_vec());
-                            let new_env = env_new(Some(mfc.env.clone()));
-                            match env_bind(&new_env, mfc.params, alst) {
-                                Ok(_) => {
-                                    ast = mfc.exp;
-                                    env = new_env;
-                                    continue 'tco;
-                                },
-                                Err(e) => err_str(&e),
-                            }
+            let el = try!(eval_ast(tmp.clone(), env.clone()));
+            let args = match *el {
+                List(ref args,_) => args,
+                _ => return err_str("Invalid apply"),
+            };
+            return match *args.clone()[0] {
+                Func(f,_) => f(args[1..].to_vec()),
+                MalFunc(ref mf,_) => {
+                    let mfc = mf.clone();
+                    let alst = list(args[1..].to_vec());
+                    let new_env = env_new(Some(mfc.env.clone()));
+                    match env_bind(&new_env, mfc.params, alst) {
+                        Ok(_) => {
+                            ast = mfc.exp;
+                            env = new_env;
+                            continue 'tco;
                         },
-                        _ => err_str("attempt to call non-function"),
+                        Err(e) => err_str(&e),
                     }
-                }
+                },
+                _ => err_str("attempt to call non-function"),
             }
         },
     }
@@ -410,16 +328,10 @@ fn print(exp: MalVal) -> String {
 }
 
 fn rep(str: &str, env: Env) -> Result<String,MalError> {
-    match read(str.to_string()) {
-        Err(e) => Err(e),
-        Ok(ast) => {
-            //println!("read: {}", ast);
-            match eval(ast, env) {
-                Err(e)  => Err(e),
-                Ok(exp) => Ok(print(exp)),
-            }
-        }
-    }
+    let ast = try!(read(str.to_string()));
+    //println!("read: {}", ast);
+    let exp = try!(eval(ast, env));
+    Ok(print(exp))
 }
 
 fn main() {
index b84a079..cab2a06 100644 (file)
@@ -7,11 +7,12 @@ use std::env as stdenv;
 
 use mal::types::{MalVal, MalRet, MalError, err_str};
 use mal::types::{symbol, _nil, string, list, vector, hash_map, malfunc, malfuncd};
-use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::types::MalError::{ErrString, ErrMalVal};
+use mal::types::MalType::{Nil, False, Sym, List, Vector, Hash_Map, Func, MalFunc};
 use mal::{readline, reader, core};
 use mal::env::{env_set, env_get, env_new, env_bind, env_find, env_root, Env};
 
+
 // read
 fn read(str: String) -> MalRet {
     reader::read_str(str)