diff options
| author | Joel Martin <github@martintribe.org> | 2015-03-05 13:15:12 -0600 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-03-05 13:15:12 -0600 |
| commit | fb439f3cdfea0d68aa2240d436a873bc43648087 (patch) | |
| tree | 0025159ebdbceb7dc48f93d545124545569e9f25 | |
| parent | 35012ea4d59764ab3744f56b5fb5684e86e80422 (diff) | |
| download | mal-fb439f3cdfea0d68aa2240d436a873bc43648087.tar.gz mal-fb439f3cdfea0d68aa2240d436a873bc43648087.zip | |
Rust: apply improvements in stepA to other steps.
| -rw-r--r-- | rust/src/bin/step0_repl.rs | 4 | ||||
| -rw-r--r-- | rust/src/bin/step1_read_print.rs | 18 | ||||
| -rw-r--r-- | rust/src/bin/step2_eval.rs | 64 | ||||
| -rw-r--r-- | rust/src/bin/step3_env.rs | 106 | ||||
| -rw-r--r-- | rust/src/bin/step4_if_fn_do.rs | 158 | ||||
| -rw-r--r-- | rust/src/bin/step5_tco.rs | 178 | ||||
| -rw-r--r-- | rust/src/bin/step6_file.rs | 190 | ||||
| -rw-r--r-- | rust/src/bin/step7_quote.rs | 213 | ||||
| -rw-r--r-- | rust/src/bin/step8_macros.rs | 286 | ||||
| -rw-r--r-- | rust/src/bin/step9_try.rs | 306 | ||||
| -rw-r--r-- | rust/src/bin/stepA_mal.rs | 3 |
11 files changed, 555 insertions, 971 deletions
diff --git a/rust/src/bin/step0_repl.rs b/rust/src/bin/step0_repl.rs index 030c551..ba5f5fe 100644 --- a/rust/src/bin/step0_repl.rs +++ b/rust/src/bin/step0_repl.rs @@ -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())))); } diff --git a/rust/src/bin/step1_read_print.rs b/rust/src/bin/step1_read_print.rs index 8be7e0d..02b2da7 100644 --- a/rust/src/bin/step1_read_print.rs +++ b/rust/src/bin/step1_read_print.rs @@ -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), diff --git a/rust/src/bin/step2_eval.rs b/rust/src/bin/step2_eval.rs index 3efa51e..fcf0383 100644 --- a/rust/src/bin/step2_eval.rs +++ b/rust/src/bin/step2_eval.rs @@ -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 diff --git a/rust/src/bin/step3_env.rs b/rust/src/bin/step3_env.rs index 0e75b26..afadc17 100644 --- a/rust/src/bin/step3_env.rs +++ b/rust/src/bin/step3_env.rs @@ -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, _ => () } diff --git a/rust/src/bin/step4_if_fn_do.rs b/rust/src/bin/step4_if_fn_do.rs index afbf69a..2be0f6b 100644 --- a/rust/src/bin/step4_if_fn_do.rs +++ b/rust/src/bin/step4_if_fn_do.rs @@ -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, _ => () } diff --git a/rust/src/bin/step5_tco.rs b/rust/src/bin/step5_tco.rs index 4117634..9a2a4ce 100644 --- a/rust/src/bin/step5_tco.rs +++ b/rust/src/bin/step5_tco.rs @@ -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, _ => () } diff --git a/rust/src/bin/step6_file.rs b/rust/src/bin/step6_file.rs index 8d9a26c..e25608b 100644 --- a/rust/src/bin/step6_file.rs +++ b/rust/src/bin/step6_file.rs @@ -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, _ => () } diff --git a/rust/src/bin/step7_quote.rs b/rust/src/bin/step7_quote.rs index 77d5d33..0c88225 100644 --- a/rust/src/bin/step7_quote.rs +++ b/rust/src/bin/step7_quote.rs @@ -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, _ => () } diff --git a/rust/src/bin/step8_macros.rs b/rust/src/bin/step8_macros.rs index a808926..770ff8c 100644 --- a/rust/src/bin/step8_macros.rs +++ b/rust/src/bin/step8_macros.rs @@ -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() { diff --git a/rust/src/bin/step9_try.rs b/rust/src/bin/step9_try.rs index f6c5dbf..871af2e 100644 --- a/rust/src/bin/step9_try.rs +++ b/rust/src/bin/step9_try.rs @@ -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() { diff --git a/rust/src/bin/stepA_mal.rs b/rust/src/bin/stepA_mal.rs index b84a079..cab2a06 100644 --- a/rust/src/bin/stepA_mal.rs +++ b/rust/src/bin/stepA_mal.rs @@ -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) |
