diff options
| author | Joel Martin <github@martintribe.org> | 2014-12-18 20:33:49 -0600 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-01-09 16:16:50 -0600 |
| commit | b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c (patch) | |
| tree | f4d977ed220e9a3f665cfbf4f68770a81e4c2095 /rust/src | |
| parent | aaba249304b184e12e2445ab22d66df1f39a51a5 (diff) | |
| download | mal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.tar.gz mal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.zip | |
All: add keywords.
Also, fix nth and count to match cloure.
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/core.rs | 6 | ||||
| -rw-r--r-- | rust/src/env.rs | 57 | ||||
| -rw-r--r-- | rust/src/reader.rs | 2 | ||||
| -rw-r--r-- | rust/src/step3_env.rs | 22 | ||||
| -rw-r--r-- | rust/src/step4_if_fn_do.rs | 18 | ||||
| -rw-r--r-- | rust/src/step5_tco.rs | 18 | ||||
| -rw-r--r-- | rust/src/step6_file.rs | 22 | ||||
| -rw-r--r-- | rust/src/step7_quote.rs | 22 | ||||
| -rw-r--r-- | rust/src/step8_macros.rs | 40 | ||||
| -rw-r--r-- | rust/src/step9_try.rs | 47 | ||||
| -rw-r--r-- | rust/src/stepA_interop.rs | 45 | ||||
| -rw-r--r-- | rust/src/types.rs | 50 |
12 files changed, 213 insertions, 136 deletions
diff --git a/rust/src/core.rs b/rust/src/core.rs index e751f88..2bc3c39 100644 --- a/rust/src/core.rs +++ b/rust/src/core.rs @@ -281,7 +281,7 @@ pub fn nth(a:Vec<MalVal>) -> MalRet { _ => return err_str("nth called with non-integer index"), }; if idx >= seq.len() { - Ok(_nil()) + return err_str("nth: index out of range") } else { Ok(seq[idx].clone()) } @@ -342,6 +342,7 @@ pub fn count(a:Vec<MalVal>) -> MalRet { List(ref v,_) | Vector(ref v,_) => { Ok(_int(v.len().to_int().unwrap())) }, + Nil => Ok(_int(0)), _ => err_str("count called on non-sequence"), } } @@ -500,7 +501,10 @@ pub fn ns() -> HashMap<String,MalVal> { ns.insert("nil?".to_string(), func(types::nil_q)); ns.insert("true?".to_string(), func(types::true_q)); ns.insert("false?".to_string(), func(types::false_q)); + ns.insert("symbol".to_string(), func(types::_symbol)); ns.insert("symbol?".to_string(), func(types::symbol_q)); + ns.insert("keyword".to_string(), func(types::_keyword)); + ns.insert("keyword?".to_string(), func(types::keyword_q)); ns.insert("pr-str".to_string(), func(pr_str)); ns.insert("str".to_string(), func(str)); diff --git a/rust/src/env.rs b/rust/src/env.rs index cf8aa0f..e9af154 100644 --- a/rust/src/env.rs +++ b/rust/src/env.rs @@ -34,7 +34,7 @@ pub fn env_bind(env: &Env, variadic = true; break; } else { - env_set(env, strn.clone(), exprs[i].clone()); + env_set(env, b.clone(), exprs[i].clone()); } } _ => return Err("non-symbol bind".to_string()), @@ -43,9 +43,9 @@ pub fn env_bind(env: &Env, if variadic { let (i, sym) = it.next().unwrap(); match **sym { - Sym(ref s) => { + Sym(_) => { let rest = exprs.slice(i-1,exprs.len()).to_vec(); - env_set(env, s.clone(), list(rest)); + env_set(env, sym.clone(), list(rest)); } _ => return Err("& bind to non-symbol".to_string()), } @@ -59,14 +59,19 @@ pub fn env_bind(env: &Env, } } -pub fn env_find(env: Env, key: String) -> Option<Env> { - if env.borrow().data.contains_key(&key) { - Some(env) - } else { - match env.borrow().outer { - Some(ref e) => env_find(e.clone(), key), - None => None, - } +pub fn env_find(env: Env, key: MalVal) -> Option<Env> { + match *key { + Sym(ref k) => { + if env.borrow().data.contains_key(k) { + Some(env) + } else { + match env.borrow().outer { + Some(ref e) => env_find(e.clone(), key.clone()), + None => None, + } + } + }, + _ => None } } @@ -77,19 +82,29 @@ pub fn env_root(env: &Env) -> Env { } } -pub fn env_set(env: &Env, key: String, val: MalVal) { - env.borrow_mut().data.insert(key, val.clone()); +pub fn env_set(env: &Env, key: MalVal, val: MalVal) { + match *key { + Sym(ref k) => { + env.borrow_mut().data.insert(k.to_string(), val.clone()); + }, + _ => {}, + } } -pub fn env_get(env: Env, key: String) -> MalRet { - match env_find(env, key.clone()) { - Some(e) => { - match e.borrow().data.find_copy(&key) { - Some(v) => Ok(v), - None => Ok(_nil()), +pub fn env_get(env: Env, key: MalVal) -> MalRet { + match *key { + Sym(ref k) => { + match env_find(env, key.clone()) { + Some(e) => { + match e.borrow().data.find_copy(k) { + Some(v) => Ok(v), + None => Ok(_nil()), + } + }, + None => err_string("'".to_string() + k.to_string() + "' not found".to_string()), } - }, - None => err_string("'".to_string() + key + "' not found".to_string()), + } + _ => err_string("env_get called with non-symbol key".to_string()), } } diff --git a/rust/src/reader.rs b/rust/src/reader.rs index af496ff..d7b2b4c 100644 --- a/rust/src/reader.rs +++ b/rust/src/reader.rs @@ -68,6 +68,8 @@ fn read_atom(rdr : &mut Reader) -> MalRet { } else if regex!(r#"^".*"$"#).is_match(token) { let new_str = token.slice(1,token.len()-1); Ok(string(unescape_str(new_str))) + } else if regex!(r#"^:"#).is_match(token) { + Ok(string("\u029e".to_string() + token.slice(1,token.len()))) } else if token == "nil" { Ok(_nil()) } else if token == "true" { diff --git a/rust/src/step3_env.rs b/rust/src/step3_env.rs index cb80947..b2d49cd 100644 --- a/rust/src/step3_env.rs +++ b/rust/src/step3_env.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Int,Sym,List,Vector,Hash_Map, - _int,list,vector,hash_map,func}; + symbol,_int,list,vector,hash_map,func}; use env::{Env,env_new,env_set,env_get}; mod readline; mod types; @@ -26,8 +26,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -94,8 +94,8 @@ fn eval(ast: MalVal, env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -117,10 +117,10 @@ fn eval(ast: MalVal, env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -187,10 +187,10 @@ fn div(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i/j }, a) } fn main() { let repl_env = env_new(None); - env_set(&repl_env, "+".to_string(), func(add)); - env_set(&repl_env, "-".to_string(), func(sub)); - env_set(&repl_env, "*".to_string(), func(mul)); - env_set(&repl_env, "/".to_string(), func(div)); + env_set(&repl_env, symbol("+"), func(add)); + env_set(&repl_env, symbol("-"), func(sub)); + env_set(&repl_env, symbol("*"), func(mul)); + env_set(&repl_env, symbol("/"), func(div)); loop { let line = readline::mal_readline("user> "); diff --git a/rust/src/step4_if_fn_do.rs b/rust/src/step4_if_fn_do.rs index 1a8d271..92abf92 100644 --- a/rust/src/step4_if_fn_do.rs +++ b/rust/src/step4_if_fn_do.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Nil,False,Sym,List,Vector,Hash_Map, - _nil,list,vector,hash_map,malfunc}; + symbol,_nil,list,vector,hash_map,malfunc}; use env::{Env,env_new,env_set,env_get}; mod readline; mod types; @@ -27,8 +27,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -95,8 +95,8 @@ fn eval(ast: MalVal, env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -118,10 +118,10 @@ fn eval(ast: MalVal, env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -216,7 +216,9 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> { fn main() { // core.rs: defined using rust let repl_env = env_new(None); - for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); } + for (k, v) in core::ns().into_iter() { + env_set(&repl_env, symbol(k.as_slice()), v); + } // core.mal: defined using the language itself let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone()); diff --git a/rust/src/step5_tco.rs b/rust/src/step5_tco.rs index 0fdc597..9223cbf 100644 --- a/rust/src/step5_tco.rs +++ b/rust/src/step5_tco.rs @@ -8,7 +8,7 @@ use std::collections::HashMap; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc, - _nil,list,vector,hash_map,malfunc}; + symbol,_nil,list,vector,hash_map,malfunc}; use env::{Env,env_new,env_bind,env_set,env_get}; mod readline; mod types; @@ -27,8 +27,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -98,8 +98,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -121,10 +121,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -238,7 +238,9 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> { fn main() { // core.rs: defined using rust let repl_env = env_new(None); - for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); } + for (k, v) in core::ns().into_iter() { + env_set(&repl_env, symbol(k.as_slice()), v); + } // core.mal: defined using the language itself let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone()); diff --git a/rust/src/step6_file.rs b/rust/src/step6_file.rs index e1198bb..1e87116 100644 --- a/rust/src/step6_file.rs +++ b/rust/src/step6_file.rs @@ -9,7 +9,7 @@ use std::os; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc, - _nil,string,list,vector,hash_map,malfunc}; + symbol,_nil,string,list,vector,hash_map,malfunc}; use env::{Env,env_new,env_bind,env_root,env_set,env_get}; mod readline; mod types; @@ -28,8 +28,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -99,8 +99,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -122,10 +122,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -250,9 +250,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> { fn main() { // core.rs: defined using rust let repl_env = env_new(None); - for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); } + for (k, v) in core::ns().into_iter() { + env_set(&repl_env, symbol(k.as_slice()), v); + } // see eval() for definition of "eval" - env_set(&repl_env, "*ARGV*".to_string(), list(vec![])); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![])); // core.mal: defined using the language itself let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone()); @@ -264,7 +266,7 @@ fn main() { let mv_args = args.slice(2,args.len()).iter() .map(|a| string(a.to_string())) .collect::<Vec<MalVal>>(); - env_set(&repl_env, "*ARGV*".to_string(), list(mv_args)); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args)); let lf = "(load-file \"".to_string() + args[1] + "\")".to_string(); match rep(lf.as_slice(), repl_env.clone()) { Ok(_) => { diff --git a/rust/src/step7_quote.rs b/rust/src/step7_quote.rs index a46f548..b113920 100644 --- a/rust/src/step7_quote.rs +++ b/rust/src/step7_quote.rs @@ -9,7 +9,7 @@ use std::os; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc, - _nil,symbol,string,list,vector,hash_map,malfunc}; + symbol,_nil,string,list,vector,hash_map,malfunc}; use env::{Env,env_new,env_bind,env_root,env_set,env_get}; mod readline; mod types; @@ -79,8 +79,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -150,8 +150,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -173,10 +173,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -309,9 +309,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> { fn main() { // core.rs: defined using rust let repl_env = env_new(None); - for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); } + for (k, v) in core::ns().into_iter() { + env_set(&repl_env, symbol(k.as_slice()), v); + } // see eval() for definition of "eval" - env_set(&repl_env, "*ARGV*".to_string(), list(vec![])); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![])); // core.mal: defined using the language itself let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone()); @@ -323,7 +325,7 @@ fn main() { let mv_args = args.slice(2,args.len()).iter() .map(|a| string(a.to_string())) .collect::<Vec<MalVal>>(); - env_set(&repl_env, "*ARGV*".to_string(), list(mv_args)); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args)); let lf = "(load-file \"".to_string() + args[1] + "\")".to_string(); match rep(lf.as_slice(), repl_env.clone()) { Ok(_) => { diff --git a/rust/src/step8_macros.rs b/rust/src/step8_macros.rs index fbbaf35..7450de8 100644 --- a/rust/src/step8_macros.rs +++ b/rust/src/step8_macros.rs @@ -9,7 +9,7 @@ use std::os; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc, - _nil,symbol,string,list,vector,hash_map,malfunc,malfuncd}; + symbol,_nil,string,list,vector,hash_map,malfunc,malfuncd}; use env::{Env,env_new,env_bind,env_root,env_find,env_set,env_get}; mod readline; mod types; @@ -78,11 +78,10 @@ fn quasiquote(ast: MalVal) -> MalVal { fn is_macro_call(ast: MalVal, env: Env) -> bool { match *ast { List(ref lst,_) => { - let ref a0 = *lst[0]; - match *a0 { - Sym(ref a0sym) => { - if env_find(env.clone(), a0sym.to_string()).is_some() { - match env_get(env, a0sym.to_string()) { + match *lst[0] { + Sym(_) => { + if env_find(env.clone(), lst[0].clone()).is_some() { + match env_get(env, lst[0].clone()) { Ok(f) => { match *f { MalFunc(ref mfd,_) => { @@ -113,8 +112,8 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet { }; let ref a0 = args[0]; let mf = match **a0 { - Sym(ref s) => { - match env_get(env.clone(), s.to_string()) { + Sym(_) => { + match env_get(env.clone(), a0.clone()) { Ok(mf) => mf, Err(e) => return Err(e), } @@ -138,8 +137,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -215,8 +214,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -238,10 +237,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -276,11 +275,11 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match *r { MalFunc(ref mfd,_) => { match *a1 { - Sym(ref s) => { + Sym(_) => { let mut new_mfd = mfd.clone(); new_mfd.is_macro = true; let mf = malfuncd(new_mfd,_nil()); - env_set(&env.clone(), s.clone(), mf.clone()); + env_set(&env.clone(), a1.clone(), mf.clone()); return Ok(mf); }, _ => return err_str("def! of non-symbol"), @@ -402,9 +401,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> { fn main() { // core.rs: defined using rust let repl_env = env_new(None); - for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); } + for (k, v) in core::ns().into_iter() { + env_set(&repl_env, symbol(k.as_slice()), v); + } // see eval() for definition of "eval" - env_set(&repl_env, "*ARGV*".to_string(), list(vec![])); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![])); // core.mal: defined using the language itself let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone()); @@ -418,7 +419,7 @@ fn main() { let mv_args = args.slice(2,args.len()).iter() .map(|a| string(a.to_string())) .collect::<Vec<MalVal>>(); - env_set(&repl_env, "*ARGV*".to_string(), list(mv_args)); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args)); let lf = "(load-file \"".to_string() + args[1] + "\")".to_string(); match rep(lf.as_slice(), repl_env.clone()) { Ok(_) => { @@ -433,6 +434,7 @@ fn main() { } } + // repl loop loop { let line = readline::mal_readline("user> "); match line { None => break, _ => () } diff --git a/rust/src/step9_try.rs b/rust/src/step9_try.rs index 4449661..0f6bd88 100644 --- a/rust/src/step9_try.rs +++ b/rust/src/step9_try.rs @@ -9,7 +9,7 @@ use std::os; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc, - _nil,symbol,string,list,vector,hash_map,malfunc,malfuncd}; + symbol,_nil,string,list,vector,hash_map,malfunc,malfuncd}; use env::{Env,env_new,env_bind,env_root,env_find,env_set,env_get}; mod readline; mod types; @@ -78,11 +78,10 @@ fn quasiquote(ast: MalVal) -> MalVal { fn is_macro_call(ast: MalVal, env: Env) -> bool { match *ast { List(ref lst,_) => { - let ref a0 = *lst[0]; - match *a0 { - Sym(ref a0sym) => { - if env_find(env.clone(), a0sym.to_string()).is_some() { - match env_get(env, a0sym.to_string()) { + match *lst[0] { + Sym(_) => { + if env_find(env.clone(), lst[0].clone()).is_some() { + match env_get(env, lst[0].clone()) { Ok(f) => { match *f { MalFunc(ref mfd,_) => { @@ -113,8 +112,8 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet { }; let ref a0 = args[0]; let mf = match **a0 { - Sym(ref s) => { - match env_get(env.clone(), s.to_string()) { + Sym(_) => { + match env_get(env.clone(), a0.clone()) { Ok(mf) => mf, Err(e) => return Err(e), } @@ -138,8 +137,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -215,8 +214,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -238,10 +237,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -276,11 +275,11 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match *r { MalFunc(ref mfd,_) => { match *a1 { - Sym(ref s) => { + Sym(_) => { let mut new_mfd = mfd.clone(); new_mfd.is_macro = true; let mf = malfuncd(new_mfd,_nil()); - env_set(&env.clone(), s.clone(), mf.clone()); + env_set(&env.clone(), a1.clone(), mf.clone()); return Ok(mf); }, _ => return err_str("def! of non-symbol"), @@ -311,8 +310,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { return err_str("wrong arity to catch* clause"); } let c1 = (*cat)[1].clone(); - let bstr = match *c1 { - Sym(ref s) => s, + match *c1 { + Sym(_) => {}, _ => return err_str("invalid catch* binding"), }; let exc = match err { @@ -320,7 +319,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { ErrString(s) => string(s), }; let bind_env = env_new(Some(env.clone())); - env_set(&bind_env, bstr.to_string(), exc); + env_set(&bind_env, c1.clone(), exc); let c2 = (*cat)[2].clone(); return eval(c2, bind_env); }, @@ -432,12 +431,13 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> { fn main() { // core.rs: defined using rust let repl_env = env_new(None); - for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); } + for (k, v) in core::ns().into_iter() { + env_set(&repl_env, symbol(k.as_slice()), v); + } // see eval() for definition of "eval" - env_set(&repl_env, "*ARGV*".to_string(), list(vec![])); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![])); // core.mal: defined using the language itself - let _ = rep("(def! *host-language* \"rust\")", repl_env.clone()); let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone()); let _ = rep("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))", repl_env.clone()); let _ = rep("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))", repl_env.clone()); @@ -449,7 +449,7 @@ fn main() { let mv_args = args.slice(2,args.len()).iter() .map(|a| string(a.to_string())) .collect::<Vec<MalVal>>(); - env_set(&repl_env, "*ARGV*".to_string(), list(mv_args)); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args)); let lf = "(load-file \"".to_string() + args[1] + "\")".to_string(); match rep(lf.as_slice(), repl_env.clone()) { Ok(_) => { @@ -465,7 +465,6 @@ fn main() { } // repl loop - let _ = rep("(println (str \"Mal [\" *host-language* \"]\"))", repl_env.clone()); loop { let line = readline::mal_readline("user> "); match line { None => break, _ => () } diff --git a/rust/src/stepA_interop.rs b/rust/src/stepA_interop.rs index 4449661..8e30867 100644 --- a/rust/src/stepA_interop.rs +++ b/rust/src/stepA_interop.rs @@ -9,7 +9,7 @@ use std::os; use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str, Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc, - _nil,symbol,string,list,vector,hash_map,malfunc,malfuncd}; + symbol,_nil,string,list,vector,hash_map,malfunc,malfuncd}; use env::{Env,env_new,env_bind,env_root,env_find,env_set,env_get}; mod readline; mod types; @@ -78,11 +78,10 @@ fn quasiquote(ast: MalVal) -> MalVal { fn is_macro_call(ast: MalVal, env: Env) -> bool { match *ast { List(ref lst,_) => { - let ref a0 = *lst[0]; - match *a0 { - Sym(ref a0sym) => { - if env_find(env.clone(), a0sym.to_string()).is_some() { - match env_get(env, a0sym.to_string()) { + match *lst[0] { + Sym(_) => { + if env_find(env.clone(), lst[0].clone()).is_some() { + match env_get(env, lst[0].clone()) { Ok(f) => { match *f { MalFunc(ref mfd,_) => { @@ -113,8 +112,8 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet { }; let ref a0 = args[0]; let mf = match **a0 { - Sym(ref s) => { - match env_get(env.clone(), s.to_string()) { + Sym(_) => { + match env_get(env.clone(), a0.clone()) { Ok(mf) => mf, Err(e) => return Err(e), } @@ -138,8 +137,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { let ast2 = ast.clone(); match *ast2 { //match *ast { - Sym(ref sym) => { - env_get(env.clone(), sym.clone()) + Sym(_) => { + env_get(env.clone(), ast) }, List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; @@ -215,8 +214,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match res { Ok(r) => { match *a1 { - Sym(ref s) => { - env_set(&env.clone(), s.clone(), r.clone()); + Sym(_) => { + env_set(&env.clone(), a1.clone(), r.clone()); return Ok(r); }, _ => { @@ -238,10 +237,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let b = it.next().unwrap(); let exp = it.next().unwrap(); match **b { - Sym(ref bstr) => { + Sym(_) => { match eval(exp.clone(), let_env.clone()) { Ok(r) => { - env_set(&let_env, bstr.clone(), r); + env_set(&let_env, b.clone(), r); }, Err(e) => { return Err(e); @@ -276,11 +275,11 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match *r { MalFunc(ref mfd,_) => { match *a1 { - Sym(ref s) => { + Sym(_) => { let mut new_mfd = mfd.clone(); new_mfd.is_macro = true; let mf = malfuncd(new_mfd,_nil()); - env_set(&env.clone(), s.clone(), mf.clone()); + env_set(&env.clone(), a1.clone(), mf.clone()); return Ok(mf); }, _ => return err_str("def! of non-symbol"), @@ -311,8 +310,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { return err_str("wrong arity to catch* clause"); } let c1 = (*cat)[1].clone(); - let bstr = match *c1 { - Sym(ref s) => s, + match *c1 { + Sym(_) => {}, _ => return err_str("invalid catch* binding"), }; let exc = match err { @@ -320,7 +319,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { ErrString(s) => string(s), }; let bind_env = env_new(Some(env.clone())); - env_set(&bind_env, bstr.to_string(), exc); + env_set(&bind_env, c1.clone(), exc); let c2 = (*cat)[2].clone(); return eval(c2, bind_env); }, @@ -432,9 +431,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> { fn main() { // core.rs: defined using rust let repl_env = env_new(None); - for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); } + for (k, v) in core::ns().into_iter() { + env_set(&repl_env, symbol(k.as_slice()), v); + } // see eval() for definition of "eval" - env_set(&repl_env, "*ARGV*".to_string(), list(vec![])); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![])); // core.mal: defined using the language itself let _ = rep("(def! *host-language* \"rust\")", repl_env.clone()); @@ -449,7 +450,7 @@ fn main() { let mv_args = args.slice(2,args.len()).iter() .map(|a| string(a.to_string())) .collect::<Vec<MalVal>>(); - env_set(&repl_env, "*ARGV*".to_string(), list(mv_args)); + env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args)); let lf = "(load-file \"".to_string() + args[1] + "\")".to_string(); match rep(lf.as_slice(), repl_env.clone()) { Ok(_) => { diff --git a/rust/src/types.rs b/rust/src/types.rs index 0b59716..141c3db 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -78,7 +78,10 @@ impl MalType { Int(v) => res.push_str(v.to_string().as_slice()), Sym(ref v) => res.push_str((*v).as_slice()), Strn(ref v) => { - if print_readably { + if v.as_slice().starts_with("\u029e") { + res.push_str(":"); + res.push_str(v.as_slice().slice(2,v.len())) + } else if print_readably { res.push_str(escape_str((*v).as_slice()).as_slice()) } else { res.push_str(v.as_slice()) @@ -95,7 +98,10 @@ impl MalType { res.push_str("{"); for (key, value) in v.iter() { if first { first = false; } else { res.push_str(" "); } - if print_readably { + if key.as_slice().starts_with("\u029e") { + res.push_str(":"); + res.push_str(key.as_slice().slice(2,key.len())) + } else if print_readably { res.push_str(escape_str(key.as_slice()).as_slice()) } else { res.push_str(key.as_slice()) @@ -205,6 +211,17 @@ pub fn _int(i: int) -> MalVal { Rc::new(Int(i)) } // Symbols pub fn symbol(strn: &str) -> MalVal { Rc::new(Sym(strn.to_string())) } +pub fn _symbol(a: Vec<MalVal>) -> MalRet { + if a.len() != 1 { + return err_str("Wrong arity to symbol call"); + } + match *a[0].clone() { + Strn(ref s) => { + Ok(Rc::new(Sym(s.to_string()))) + }, + _ => return err_str("symbol called on non-string"), + } +} pub fn symbol_q(a:Vec<MalVal>) -> MalRet { if a.len() != 1 { return err_str("Wrong arity to symbol? call"); @@ -215,6 +232,35 @@ pub fn symbol_q(a:Vec<MalVal>) -> MalRet { } } +// Keywords +pub fn _keyword(a: Vec<MalVal>) -> MalRet { + if a.len() != 1 { + return err_str("Wrong arity to keyword call"); + } + match *a[0].clone() { + Strn(ref s) => { + Ok(Rc::new(Strn("\u029e".to_string() + s.to_string()))) + }, + _ => return err_str("keyword called on non-string"), + } +} +pub fn keyword_q(a:Vec<MalVal>) -> MalRet { + if a.len() != 1 { + return err_str("Wrong arity to keyword? call"); + } + match *a[0].clone() { + Strn(ref s) => { + if s.as_slice().starts_with("\u029e") { + Ok(_true()) + } else { + Ok(_false()) + } + }, + _ => Ok(_false()), + } +} + + // Strings pub fn strn(strn: &str) -> MalVal { Rc::new(Strn(strn.to_string())) } pub fn string(strn: String) -> MalVal { Rc::new(Strn(strn)) } |
