diff options
| author | Joel Martin <github@martintribe.org> | 2014-10-27 22:39:31 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-01-06 21:59:00 -0600 |
| commit | bd3067230dcbd18fb1f0db7abb52c4ea1c2e227b (patch) | |
| tree | 08c01aaacbc469ea4d1ad950852bf67aeb4cdcae /rust/src | |
| parent | 06fef9b51830a2aa696f3e108c56f306967ce465 (diff) | |
| download | mal-bd3067230dcbd18fb1f0db7abb52c4ea1c2e227b.tar.gz mal-bd3067230dcbd18fb1f0db7abb52c4ea1c2e227b.zip | |
rust: add metadata support.
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/core.rs | 70 | ||||
| -rw-r--r-- | rust/src/env.rs | 4 | ||||
| -rw-r--r-- | rust/src/reader.rs | 12 | ||||
| -rw-r--r-- | rust/src/step2_eval.rs | 10 | ||||
| -rw-r--r-- | rust/src/step3_env.rs | 16 | ||||
| -rw-r--r-- | rust/src/step4_if_fn_do.rs | 20 | ||||
| -rw-r--r-- | rust/src/step5_tco.rs | 22 | ||||
| -rw-r--r-- | rust/src/step6_file.rs | 22 | ||||
| -rw-r--r-- | rust/src/step7_quote.rs | 28 | ||||
| -rw-r--r-- | rust/src/step8_macros.rs | 40 | ||||
| -rw-r--r-- | rust/src/step9_try.rs | 42 | ||||
| -rw-r--r-- | rust/src/types.rs | 89 |
12 files changed, 218 insertions, 157 deletions
diff --git a/rust/src/core.rs b/rust/src/core.rs index b4abd2f..c1abaf6 100644 --- a/rust/src/core.rs +++ b/rust/src/core.rs @@ -5,8 +5,9 @@ use std::collections::HashMap; use std::io::File; use types::{MalVal,MalRet,err_val,err_str,err_string, - Nil,Int,Strn,List,Vector,Hash_Map,Atom, - _nil,_true,_false,_int,string,list,func}; + Nil,Int,Strn,List,Vector,Hash_Map,Func,MalFunc,Atom, + _nil,_true,_false,_int,string, + list,listm,vectorm,hash_mapm,func,funcm,malfuncd}; use types; use readline; use reader; @@ -131,7 +132,7 @@ pub fn assoc(a:Vec<MalVal>) -> MalRet { return err_str("Wrong arity to assoc call"); } match *a[0] { - Hash_Map(ref hm) => { + Hash_Map(ref hm,_) => { types::_assoc(hm, a.slice(1,a.len()).to_vec()) }, Nil => { @@ -146,7 +147,7 @@ pub fn dissoc(a:Vec<MalVal>) -> MalRet { return err_str("Wrong arity to dissoc call"); } match *a[0] { - Hash_Map(ref hm) => { + Hash_Map(ref hm,_) => { types::_dissoc(hm, a.slice(1,a.len()).to_vec()) }, Nil => { @@ -162,7 +163,7 @@ pub fn get(a:Vec<MalVal>) -> MalRet { } let a0 = a[0].clone(); let hm: &HashMap<String,MalVal> = match *a0 { - Hash_Map(ref hm) => hm, + Hash_Map(ref hm,_) => hm, Nil => return Ok(_nil()), _ => return err_str("get on non-hash map"), }; @@ -183,7 +184,7 @@ pub fn contains_q(a:Vec<MalVal>) -> MalRet { } let a0 = a[0].clone(); let hm: &HashMap<String,MalVal> = match *a0 { - Hash_Map(ref hm) => hm, + Hash_Map(ref hm,_) => hm, Nil => return Ok(_false()), _ => return err_str("contains? on non-hash map"), }; @@ -204,7 +205,7 @@ pub fn keys(a:Vec<MalVal>) -> MalRet { } let a0 = a[0].clone(); let hm: &HashMap<String,MalVal> = match *a0 { - Hash_Map(ref hm) => hm, + Hash_Map(ref hm,_) => hm, Nil => return Ok(_nil()), _ => return err_str("contains? on non-hash map"), }; @@ -222,7 +223,7 @@ pub fn vals(a:Vec<MalVal>) -> MalRet { } let a0 = a[0].clone(); let hm: &HashMap<String,MalVal> = match *a0 { - Hash_Map(ref hm) => hm, + Hash_Map(ref hm,_) => hm, Nil => return Ok(_nil()), _ => return err_str("contains? on non-hash map"), }; @@ -238,7 +239,7 @@ pub fn vals(a:Vec<MalVal>) -> MalRet { // Sequence functions pub fn cons(a:Vec<MalVal>) -> MalRet { match *a[1] { - List(ref v) | Vector(ref v) => { + List(ref v,_) | Vector(ref v,_) => { let mut new_v = v.clone(); new_v.insert(0, a[0].clone()); Ok(list(new_v)) @@ -251,7 +252,7 @@ pub fn concat(a:Vec<MalVal>) -> MalRet { let mut new_v:Vec<MalVal> = vec![]; for lst in a.iter() { match **lst { - List(ref l) | Vector(ref l) => { + List(ref l,_) | Vector(ref l,_) => { new_v.push_all(l.as_slice()); }, _ => return err_str("concat called with non-sequence"), @@ -267,7 +268,7 @@ pub fn nth(a:Vec<MalVal>) -> MalRet { let a0 = a[0].clone(); let a1 = a[1].clone(); let seq = match *a0 { - List(ref v) | Vector(ref v) => v, + List(ref v,_) | Vector(ref v,_) => v, _ => return err_str("nth called with non-sequence"), }; let idx = match *a1 { @@ -292,7 +293,7 @@ pub fn first(a:Vec<MalVal>) -> MalRet { } let a0 = a[0].clone(); let seq = match *a0 { - List(ref v) | Vector(ref v) => v, + List(ref v,_) | Vector(ref v,_) => v, _ => return err_str("first called with non-sequence"), }; if seq.len() == 0 { @@ -308,7 +309,7 @@ pub fn rest(a:Vec<MalVal>) -> MalRet { } let a0 = a[0].clone(); let seq = match *a0 { - List(ref v) | Vector(ref v) => v, + List(ref v,_) | Vector(ref v,_) => v, _ => return err_str("rest called with non-sequence"), }; if seq.len() == 0 { @@ -323,7 +324,7 @@ pub fn empty_q(a:Vec<MalVal>) -> MalRet { return err_str("Wrong arity to empty? call"); } match *a[0].clone() { - List(ref v) | Vector(ref v) => { + List(ref v,_) | Vector(ref v,_) => { match v.len() { 0 => Ok(_true()), _ => Ok(_false()), @@ -338,7 +339,7 @@ pub fn count(a:Vec<MalVal>) -> MalRet { return err_str("Wrong arity to count call"); } match *a[0].clone() { - List(ref v) | Vector(ref v) => { + List(ref v,_) | Vector(ref v,_) => { Ok(_int(v.len().to_int().unwrap())) }, _ => err_str("count called on non-sequence"), @@ -352,7 +353,7 @@ pub fn apply(a:Vec<MalVal>) -> MalRet { let ref f = a[0]; let mut args = a.slice(1,a.len()-1).to_vec(); match *a[a.len()-1] { - List(ref v) | Vector(ref v) => { + List(ref v,_) | Vector(ref v,_) => { args.push_all(v.as_slice()); f.apply(args) }, @@ -368,7 +369,7 @@ pub fn map(a:Vec<MalVal>) -> MalRet { let ref f = a[0].clone(); let seq = a[1].clone(); match *seq { - List(ref v) | Vector(ref v) => { + List(ref v,_) | Vector(ref v,_) => { for mv in v.iter() { match f.apply(vec![mv.clone()]) { Ok(res) => results.push(res), @@ -382,7 +383,38 @@ pub fn map(a:Vec<MalVal>) -> MalRet { } -// Atom funcions +// Metadata functions +fn with_meta(a:Vec<MalVal>) -> MalRet { + if a.len() != 2 { + return err_str("Wrong arity to with-meta call"); + } + let mv = a[0].clone(); + let meta = a[1].clone(); + match *mv { + List(ref v,_) => Ok(listm(v.clone(),meta)), + Vector(ref v,_) => Ok(vectorm(v.clone(),meta)), + Hash_Map(ref hm,_) => Ok(hash_mapm(hm.clone(),meta)), + MalFunc(ref mfd,_) => Ok(malfuncd(mfd.clone(),meta)), + Func(f,_) => Ok(funcm(f,meta)), + _ => err_str("type does not support metadata"), + } +} + +fn meta(a:Vec<MalVal>) -> MalRet { + if a.len() != 1 { + return err_str("Wrong arity to meta call"); + } + match *a[0].clone() { + List(_,ref meta) | + Vector(_,ref meta) | + Hash_Map(_,ref meta) | + MalFunc(_,ref meta) | + Func(_,ref meta) => Ok(meta.clone()), + _ => err_str("type does not support metadata"), + } +} + +// Atom functions fn deref(a:Vec<MalVal>) -> MalRet { if a.len() != 1 { return err_str("Wrong arity to deref call"); @@ -488,6 +520,8 @@ pub fn ns() -> HashMap<String,MalVal> { ns.insert("apply".to_string(), func(apply)); ns.insert("map".to_string(), func(map)); + ns.insert("with-meta".to_string(), func(with_meta)); + ns.insert("meta".to_string(), func(meta)); ns.insert("atom".to_string(), func(types::atom)); ns.insert("deref".to_string(), func(deref)); ns.insert("reset!".to_string(), func(reset_bang)); diff --git a/rust/src/env.rs b/rust/src/env.rs index 7ffc319..cf8aa0f 100644 --- a/rust/src/env.rs +++ b/rust/src/env.rs @@ -23,9 +23,9 @@ pub fn env_bind(env: &Env, mexprs: MalVal) -> Result<Env,String> { let mut variadic = false; match *mbinds { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { match *mexprs { - List(ref exprs) | Vector(ref exprs) => { + List(ref exprs,_) | Vector(ref exprs,_) => { let mut it = binds.iter().enumerate(); for (i, b) in it { match **b { diff --git a/rust/src/reader.rs b/rust/src/reader.rs index e3ec55e..af496ff 100644 --- a/rust/src/reader.rs +++ b/rust/src/reader.rs @@ -166,6 +166,18 @@ fn read_form(rdr : &mut Reader) -> MalRet { Err(e) => Err(e), } }, + "^" => { + let _ = rdr.next(); + match read_form(rdr) { + Ok(meta) => { + match read_form(rdr) { + Ok(f) => Ok(list(vec![symbol("with-meta"), f, meta])), + Err(e) => Err(e), + } + }, + Err(e) => Err(e), + } + }, "@" => { let _ = rdr.next(); match read_form(rdr) { diff --git a/rust/src/step2_eval.rs b/rust/src/step2_eval.rs index 29c53d9..9e33042 100644 --- a/rust/src/step2_eval.rs +++ b/rust/src/step2_eval.rs @@ -29,7 +29,7 @@ fn eval_ast(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { None => Ok(_nil()), } }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { match eval(mv.clone(), env) { @@ -37,10 +37,10 @@ fn eval_ast(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { Err(e) => return Err(e), } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + Hash_Map(ref hm,_) => { let mut new_hm: HashMap<String,MalVal> = HashMap::new(); for (key, value) in hm.iter() { match eval(value.clone(), env) { @@ -59,7 +59,7 @@ fn eval_ast(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { fn eval(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { let ast2 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } @@ -68,7 +68,7 @@ fn eval(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet { Err(e) => Err(e), Ok(el) => { match *el { - List(ref args) => { + List(ref args,_) => { let ref f = args.clone()[0]; f.apply(args.slice(1,args.len()).to_vec()) } diff --git a/rust/src/step3_env.rs b/rust/src/step3_env.rs index ac7199c..820f21d 100644 --- a/rust/src/step3_env.rs +++ b/rust/src/step3_env.rs @@ -29,7 +29,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Sym(ref sym) => { env_get(env.clone(), sym.clone()) }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { let mv2 = mv.clone(); @@ -38,10 +38,10 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Err(e) => { return Err(e); }, } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + 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()) { @@ -62,18 +62,18 @@ fn eval(ast: MalVal, env: Env) -> MalRet { //println!("eval: {}", ast); let ast2 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } // apply list match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return Ok(ast2), } let (args, a0sym) = match *ast2 { - List(ref args) => { + List(ref args,_) => { if args.len() == 0 { return Ok(ast); } @@ -111,7 +111,7 @@ fn eval(ast: MalVal, env: Env) -> MalRet { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); match *a1 { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { let mut it = binds.iter(); while it.len() >= 2 { let b = it.next().unwrap(); @@ -142,7 +142,7 @@ fn eval(ast: MalVal, env: Env) -> MalRet { Err(e) => Err(e), Ok(el) => { let args = match *el { - List(ref args) => args, + List(ref args,_) => args, _ => return err_str("Invalid apply"), }; let ref f = args.clone()[0]; diff --git a/rust/src/step4_if_fn_do.rs b/rust/src/step4_if_fn_do.rs index c5c9413..7fc8b51 100644 --- a/rust/src/step4_if_fn_do.rs +++ b/rust/src/step4_if_fn_do.rs @@ -30,7 +30,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Sym(ref sym) => { env_get(env.clone(), sym.clone()) }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { let mv2 = mv.clone(); @@ -39,10 +39,10 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Err(e) => { return Err(e); }, } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + 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()) { @@ -63,18 +63,18 @@ fn eval(ast: MalVal, env: Env) -> MalRet { //println!("eval: {}", ast); let ast2 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } // apply list match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return Ok(ast2), } let (args, a0sym) = match *ast2 { - List(ref args) => { + List(ref args,_) => { if args.len() == 0 { return Ok(ast); } @@ -112,7 +112,7 @@ fn eval(ast: MalVal, env: Env) -> MalRet { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); match *a1 { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { let mut it = binds.iter(); while it.len() >= 2 { let b = it.next().unwrap(); @@ -144,7 +144,7 @@ fn eval(ast: MalVal, env: Env) -> MalRet { Err(e) => return Err(e), Ok(el) => { match *el { - List(ref lst) => { + List(ref lst,_) => { let ref last = lst[lst.len()-1]; return Ok(last.clone()); } @@ -177,14 +177,14 @@ fn eval(ast: MalVal, env: Env) -> MalRet { "fn*" => { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); - return Ok(malfunc(eval, a2, env.clone(), a1)); + return Ok(malfunc(eval, a2, env.clone(), 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, + List(ref args,_) => args, _ => return err_str("Invalid apply"), }; let ref f = args.clone()[0]; diff --git a/rust/src/step5_tco.rs b/rust/src/step5_tco.rs index c86e249..0a51cdd 100644 --- a/rust/src/step5_tco.rs +++ b/rust/src/step5_tco.rs @@ -30,7 +30,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Sym(ref sym) => { env_get(env.clone(), sym.clone()) }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { let mv2 = mv.clone(); @@ -39,10 +39,10 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Err(e) => { return Err(e); }, } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + 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()) { @@ -66,18 +66,18 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let ast2 = ast.clone(); let ast3 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } // apply list match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return Ok(ast2), } let (args, a0sym) = match *ast2 { - List(ref args) => { + List(ref args,_) => { if args.len() == 0 { return Ok(ast3); } @@ -115,7 +115,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); match *a1 { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { let mut it = binds.iter(); while it.len() >= 2 { let b = it.next().unwrap(); @@ -182,19 +182,19 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { "fn*" => { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); - return Ok(malfunc(eval, a2, env.clone(), a1)); + return Ok(malfunc(eval, a2, env.clone(), 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, + List(ref args,_) => args, _ => return err_str("Invalid apply"), }; match *args.clone()[0] { - Func(f) => f(args.slice(1,args.len()).to_vec()), - MalFunc(ref mf) => { + Func(f,_) => f(args.slice(1,args.len()).to_vec()), + MalFunc(ref mf,_) => { let mfc = mf.clone(); let alst = list(args.slice(1,args.len()).to_vec()); let new_env = env_new(Some(mfc.env.clone())); diff --git a/rust/src/step6_file.rs b/rust/src/step6_file.rs index 86e0672..3503653 100644 --- a/rust/src/step6_file.rs +++ b/rust/src/step6_file.rs @@ -31,7 +31,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Sym(ref sym) => { env_get(env.clone(), sym.clone()) }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { let mv2 = mv.clone(); @@ -40,10 +40,10 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Err(e) => { return Err(e); }, } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + 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()) { @@ -67,18 +67,18 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let ast2 = ast.clone(); let ast3 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } // apply list match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return Ok(ast2), } let (args, a0sym) = match *ast2 { - List(ref args) => { + List(ref args,_) => { if args.len() == 0 { return Ok(ast3); } @@ -116,7 +116,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); match *a1 { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { let mut it = binds.iter(); while it.len() >= 2 { let b = it.next().unwrap(); @@ -183,7 +183,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { "fn*" => { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); - return Ok(malfunc(eval, a2, env.clone(), a1)); + return Ok(malfunc(eval, a2, env.clone(), a1, _nil())); }, "eval" => { let a1 = (*args)[1].clone(); @@ -201,12 +201,12 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { Err(e) => Err(e), Ok(el) => { let args = match *el { - List(ref args) => args, + List(ref args,_) => args, _ => return err_str("Invalid apply"), }; match *args.clone()[0] { - Func(f) => f(args.slice(1,args.len()).to_vec()), - MalFunc(ref mf) => { + Func(f,_) => f(args.slice(1,args.len()).to_vec()), + MalFunc(ref mf,_) => { let mfc = mf.clone(); let alst = list(args.slice(1,args.len()).to_vec()); let new_env = env_new(Some(mfc.env.clone())); diff --git a/rust/src/step7_quote.rs b/rust/src/step7_quote.rs index ac0634d..acd487c 100644 --- a/rust/src/step7_quote.rs +++ b/rust/src/step7_quote.rs @@ -26,7 +26,7 @@ fn read(str: String) -> MalRet { // eval fn is_pair(x: MalVal) -> bool { match *x { - List(ref lst) => lst.len() > 0, + List(ref lst,_) => lst.len() > 0, _ => false, } } @@ -37,7 +37,7 @@ fn quasiquote(ast: MalVal) -> MalVal { } match *ast.clone() { - List(ref args) => { + List(ref args,_) => { let ref a0 = args[0]; match **a0 { Sym(ref s) => { @@ -50,7 +50,7 @@ fn quasiquote(ast: MalVal) -> MalVal { } if is_pair(a0.clone()) { match **a0 { - List(ref a0args) => { + List(ref a0args,_) => { let a00 = a0args[0].clone(); match *a00 { Sym(ref s) => { @@ -82,7 +82,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Sym(ref sym) => { env_get(env.clone(), sym.clone()) }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { let mv2 = mv.clone(); @@ -91,10 +91,10 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Err(e) => { return Err(e); }, } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + 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()) { @@ -117,19 +117,19 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { //println!("eval: {}", ast); let ast2 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } // apply list match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return Ok(ast2), } let ast3 = ast2.clone(); let (args, a0sym) = match *ast2 { - List(ref args) => { + List(ref args,_) => { if args.len() == 0 { return Ok(ast3); } @@ -167,7 +167,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); match *a1 { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { let mut it = binds.iter(); while it.len() >= 2 { let b = it.next().unwrap(); @@ -242,7 +242,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { "fn*" => { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); - return Ok(malfunc(eval, a2, env.clone(), a1)); + return Ok(malfunc(eval, a2, env.clone(), a1, _nil())); }, "eval" => { let a1 = (*args)[1].clone(); @@ -260,12 +260,12 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { Err(e) => Err(e), Ok(el) => { let args = match *el { - List(ref args) => args, + List(ref args,_) => args, _ => return err_str("Invalid apply"), }; match *args.clone()[0] { - Func(f) => f(args.slice(1,args.len()).to_vec()), - MalFunc(ref mf) => { + Func(f,_) => f(args.slice(1,args.len()).to_vec()), + MalFunc(ref mf,_) => { let mfc = mf.clone(); let alst = list(args.slice(1,args.len()).to_vec()); let new_env = env_new(Some(mfc.env.clone())); diff --git a/rust/src/step8_macros.rs b/rust/src/step8_macros.rs index a79df33..a4a1f75 100644 --- a/rust/src/step8_macros.rs +++ b/rust/src/step8_macros.rs @@ -26,7 +26,7 @@ fn read(str: String) -> MalRet { // eval fn is_pair(x: MalVal) -> bool { match *x { - List(ref lst) => lst.len() > 0, + List(ref lst,_) => lst.len() > 0, _ => false, } } @@ -37,7 +37,7 @@ fn quasiquote(ast: MalVal) -> MalVal { } match *ast.clone() { - List(ref args) => { + List(ref args,_) => { let ref a0 = args[0]; match **a0 { Sym(ref s) => { @@ -50,7 +50,7 @@ fn quasiquote(ast: MalVal) -> MalVal { } if is_pair(a0.clone()) { match **a0 { - List(ref a0args) => { + List(ref a0args,_) => { let a00 = a0args[0].clone(); match *a00 { Sym(ref s) => { @@ -77,7 +77,7 @@ fn quasiquote(ast: MalVal) -> MalVal { fn is_macro_call(ast: MalVal, env: Env) -> bool { match *ast { - List(ref lst) => { + List(ref lst,_) => { let ref a0 = *lst[0]; match *a0 { Sym(ref a0sym) => { @@ -85,7 +85,7 @@ fn is_macro_call(ast: MalVal, env: Env) -> bool { match env_get(env, a0sym.to_string()) { Ok(f) => { match *f { - MalFunc(ref mfd) => { + MalFunc(ref mfd,_) => { mfd.is_macro }, _ => false, @@ -108,7 +108,7 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet { while is_macro_call(ast.clone(), env.clone()) { let ast2 = ast.clone(); let args = match *ast2 { - List(ref args) => args, + List(ref args,_) => args, _ => break, }; let ref a0 = args[0]; @@ -122,7 +122,7 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet { _ => break, }; match *mf { - MalFunc(_) => { + MalFunc(_,_) => { match mf.apply(args.slice(1,args.len()).to_vec()) { Ok(r) => ast = r, Err(e) => return Err(e), @@ -141,7 +141,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Sym(ref sym) => { env_get(env.clone(), sym.clone()) }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { let mv2 = mv.clone(); @@ -150,10 +150,10 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Err(e) => { return Err(e); }, } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + 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()) { @@ -176,7 +176,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { //println!("eval: {}", ast); let mut ast2 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } @@ -188,13 +188,13 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { Err(e) => return Err(e), } match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return Ok(ast2), } let ast3 = ast2.clone(); let (args, a0sym) = match *ast2 { - List(ref args) => { + List(ref args,_) => { if args.len() == 0 { return Ok(ast3); } @@ -232,7 +232,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); match *a1 { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { let mut it = binds.iter(); while it.len() >= 2 { let b = it.next().unwrap(); @@ -274,12 +274,12 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match eval(a2, env.clone()) { Ok(r) => { match *r { - MalFunc(ref mfd) => { + MalFunc(ref mfd,_) => { match *a1 { Sym(ref s) => { let mut new_mfd = mfd.clone(); new_mfd.is_macro = true; - let mf = malfuncd(new_mfd); + let mf = malfuncd(new_mfd,_nil()); env_set(&env.clone(), s.clone(), mf.clone()); return Ok(mf); }, @@ -335,7 +335,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { "fn*" => { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); - return Ok(malfunc(eval, a2, env.clone(), a1)); + return Ok(malfunc(eval, a2, env.clone(), a1, _nil())); }, "eval" => { let a1 = (*args)[1].clone(); @@ -353,12 +353,12 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { Err(e) => Err(e), Ok(el) => { let args = match *el { - List(ref args) => args, + List(ref args,_) => args, _ => return err_str("Invalid apply"), }; match *args.clone()[0] { - Func(f) => f(args.slice(1,args.len()).to_vec()), - MalFunc(ref mf) => { + Func(f,_) => f(args.slice(1,args.len()).to_vec()), + MalFunc(ref mf,_) => { let mfc = mf.clone(); let alst = list(args.slice(1,args.len()).to_vec()); let new_env = env_new(Some(mfc.env.clone())); diff --git a/rust/src/step9_try.rs b/rust/src/step9_try.rs index f6dde04..6e3cf29 100644 --- a/rust/src/step9_try.rs +++ b/rust/src/step9_try.rs @@ -26,7 +26,7 @@ fn read(str: String) -> MalRet { // eval fn is_pair(x: MalVal) -> bool { match *x { - List(ref lst) => lst.len() > 0, + List(ref lst,_) => lst.len() > 0, _ => false, } } @@ -37,7 +37,7 @@ fn quasiquote(ast: MalVal) -> MalVal { } match *ast.clone() { - List(ref args) => { + List(ref args,_) => { let ref a0 = args[0]; match **a0 { Sym(ref s) => { @@ -50,7 +50,7 @@ fn quasiquote(ast: MalVal) -> MalVal { } if is_pair(a0.clone()) { match **a0 { - List(ref a0args) => { + List(ref a0args,_) => { let a00 = a0args[0].clone(); match *a00 { Sym(ref s) => { @@ -77,7 +77,7 @@ fn quasiquote(ast: MalVal) -> MalVal { fn is_macro_call(ast: MalVal, env: Env) -> bool { match *ast { - List(ref lst) => { + List(ref lst,_) => { let ref a0 = *lst[0]; match *a0 { Sym(ref a0sym) => { @@ -85,7 +85,7 @@ fn is_macro_call(ast: MalVal, env: Env) -> bool { match env_get(env, a0sym.to_string()) { Ok(f) => { match *f { - MalFunc(ref mfd) => { + MalFunc(ref mfd,_) => { mfd.is_macro }, _ => false, @@ -108,7 +108,7 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet { while is_macro_call(ast.clone(), env.clone()) { let ast2 = ast.clone(); let args = match *ast2 { - List(ref args) => args, + List(ref args,_) => args, _ => break, }; let ref a0 = args[0]; @@ -122,7 +122,7 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet { _ => break, }; match *mf { - MalFunc(_) => { + MalFunc(_,_) => { match mf.apply(args.slice(1,args.len()).to_vec()) { Ok(r) => ast = r, Err(e) => return Err(e), @@ -141,7 +141,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Sym(ref sym) => { env_get(env.clone(), sym.clone()) }, - List(ref a) | Vector(ref a) => { + List(ref a,_) | Vector(ref a,_) => { let mut ast_vec : Vec<MalVal> = vec![]; for mv in a.iter() { let mv2 = mv.clone(); @@ -150,10 +150,10 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet { Err(e) => { return Err(e); }, } } - Ok(match *ast { List(_) => list(ast_vec), + Ok(match *ast { List(_,_) => list(ast_vec), _ => vector(ast_vec) }) }, - Hash_Map(ref hm) => { + 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()) { @@ -176,7 +176,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { //println!("eval: {}", ast); let mut ast2 = ast.clone(); match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return eval_ast(ast2, env), } @@ -188,13 +188,13 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { Err(e) => return Err(e), } match *ast2 { - List(_) => (), // continue + List(_,_) => (), // continue _ => return Ok(ast2), } let ast3 = ast2.clone(); let (args, a0sym) = match *ast2 { - List(ref args) => { + List(ref args,_) => { if args.len() == 0 { return Ok(ast3); } @@ -232,7 +232,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); match *a1 { - List(ref binds) | Vector(ref binds) => { + List(ref binds,_) | Vector(ref binds,_) => { let mut it = binds.iter(); while it.len() >= 2 { let b = it.next().unwrap(); @@ -274,12 +274,12 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { match eval(a2, env.clone()) { Ok(r) => { match *r { - MalFunc(ref mfd) => { + MalFunc(ref mfd,_) => { match *a1 { Sym(ref s) => { let mut new_mfd = mfd.clone(); new_mfd.is_macro = true; - let mf = malfuncd(new_mfd); + let mf = malfuncd(new_mfd,_nil()); env_set(&env.clone(), s.clone(), mf.clone()); return Ok(mf); }, @@ -304,7 +304,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { if args.len() < 3 { return Err(err); } let a2 = (*args)[2].clone(); let cat = match *a2 { - List(ref cat) => cat, + List(ref cat,_) => cat, _ => return err_str("invalid catch* clause"), }; if cat.len() != 3 { @@ -365,7 +365,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { "fn*" => { let a1 = (*args)[1].clone(); let a2 = (*args)[2].clone(); - return Ok(malfunc(eval, a2, env.clone(), a1)); + return Ok(malfunc(eval, a2, env.clone(), a1, _nil())); }, "eval" => { let a1 = (*args)[1].clone(); @@ -383,12 +383,12 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet { Err(e) => Err(e), Ok(el) => { let args = match *el { - List(ref args) => args, + List(ref args,_) => args, _ => return err_str("Invalid apply"), }; match *args.clone()[0] { - Func(f) => f(args.slice(1,args.len()).to_vec()), - MalFunc(ref mf) => { + Func(f,_) => f(args.slice(1,args.len()).to_vec()), + MalFunc(ref mf,_) => { let mfc = mf.clone(); let alst = list(args.slice(1,args.len()).to_vec()); let new_env = env_new(Some(mfc.env.clone())); diff --git a/rust/src/types.rs b/rust/src/types.rs index 7c74894..e7e60f9 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -16,13 +16,13 @@ pub enum MalType { Int(int), Strn(String), Sym(String), - List(Vec<MalVal>), - Vector(Vec<MalVal>), - Hash_Map(HashMap<String, MalVal>), - Func(fn(Vec<MalVal>) -> MalRet), + List(Vec<MalVal>, MalVal), + Vector(Vec<MalVal>, MalVal), + Hash_Map(HashMap<String, MalVal>, MalVal), + Func(fn(Vec<MalVal>) -> MalRet, MalVal), //Func(fn(&[MalVal]) -> MalRet), //Func(|Vec<MalVal>|:'a -> MalRet), - MalFunc(MalFuncData), + MalFunc(MalFuncData, MalVal), Atom(RefCell<MalVal>), } @@ -65,7 +65,6 @@ pub struct MalFuncData { pub env: Env, pub params: MalVal, pub is_macro: bool, - pub meta: MalVal, } impl MalType { @@ -85,13 +84,13 @@ impl MalType { res.push_str(v.as_slice()) } }, - List(ref v) => { + List(ref v,_) => { res = pr_list(v, _r, "(", ")", " ") }, - Vector(ref v) => { + Vector(ref v,_) => { res = pr_list(v, _r, "[", "]", " ") }, - Hash_Map(ref v) => { + Hash_Map(ref v,_) => { let mut first = true; res.push_str("{"); for (key, value) in v.iter() { @@ -107,10 +106,10 @@ impl MalType { res.push_str("}") }, // TODO: better native function representation - Func(_) => { + Func(_,_) => { res.push_str(format!("#<function ...>").as_slice()) }, - MalFunc(ref mf) => { + MalFunc(ref mf,_) => { res.push_str(format!("(fn* {} {})", mf.params, mf.exp).as_slice()) }, Atom(ref v) => { @@ -122,8 +121,8 @@ impl MalType { pub fn apply(&self, args:Vec<MalVal>) -> MalRet { match *self { - Func(f) => f(args), - MalFunc(ref mf) => { + Func(f,_) => f(args), + MalFunc(ref mf,_) => { let mfc = mf.clone(); let alst = list(args); let new_env = env_new(Some(mfc.env.clone())); @@ -147,14 +146,14 @@ impl PartialEq for MalType { (&Int(ref a), &Int(ref b)) => a == b, (&Strn(ref a), &Strn(ref b)) => a == b, (&Sym(ref a), &Sym(ref b)) => a == b, - (&List(ref a), &List(ref b)) | - (&Vector(ref a), &Vector(ref b)) | - (&List(ref a), &Vector(ref b)) | - (&Vector(ref a), &List(ref b)) => a == b, - (&Hash_Map(ref a), &Hash_Map(ref b)) => a == b, + (&List(ref a,_), &List(ref b,_)) | + (&Vector(ref a,_), &Vector(ref b,_)) | + (&List(ref a,_), &Vector(ref b,_)) | + (&Vector(ref a,_), &List(ref b,_)) => a == b, + (&Hash_Map(ref a,_), &Hash_Map(ref b,_)) => a == b, // TODO: fix this - (&Func(_), &Func(_)) => false, - (&MalFunc(_), &MalFunc(_)) => false, + (&Func(_,_), &Func(_,_)) => false, + (&MalFunc(_,_), &MalFunc(_,_)) => false, _ => return false, } } @@ -221,33 +220,44 @@ pub fn strn(strn: &str) -> MalVal { Rc::new(Strn(strn.to_string())) } pub fn string(strn: String) -> MalVal { Rc::new(Strn(strn)) } // Lists -pub fn list(seq: Vec<MalVal>) -> MalVal { Rc::new(List(seq)) } +pub fn list(seq: Vec<MalVal>) -> MalVal { Rc::new(List(seq,_nil())) } +pub fn listm(seq: Vec<MalVal>, meta: MalVal) -> MalVal { + Rc::new(List(seq,meta)) +} pub fn listv(seq:Vec<MalVal>) -> MalRet { Ok(list(seq)) } pub fn list_q(a:Vec<MalVal>) -> MalRet { if a.len() != 1 { return err_str("Wrong arity to list? call"); } match *a[0].clone() { - List(_) => Ok(_true()), + List(_,_) => Ok(_true()), _ => Ok(_false()), } } // Vectors -pub fn vector(seq: Vec<MalVal>) -> MalVal { Rc::new(Vector(seq)) } +pub fn vector(seq: Vec<MalVal>) -> MalVal { Rc::new(Vector(seq,_nil())) } +pub fn vectorm(seq: Vec<MalVal>, meta: MalVal) -> MalVal { + Rc::new(Vector(seq,meta)) +} pub fn vectorv(seq: Vec<MalVal>) -> MalRet { Ok(vector(seq)) } pub fn vector_q(a:Vec<MalVal>) -> MalRet { if a.len() != 1 { return err_str("Wrong arity to vector? call"); } match *a[0].clone() { - Vector(_) => Ok(_true()), + Vector(_,_) => Ok(_true()), _ => Ok(_false()), } } // Hash Maps -pub fn hash_map(hm: HashMap<String,MalVal>) -> MalVal { Rc::new(Hash_Map(hm)) } +pub fn hash_map(hm: HashMap<String,MalVal>) -> MalVal { + Rc::new(Hash_Map(hm,_nil())) +} +pub fn hash_mapm(hm: HashMap<String,MalVal>, meta: MalVal) -> MalVal { + Rc::new(Hash_Map(hm,meta)) +} pub fn _assoc(hm: &HashMap<String,MalVal>, a:Vec<MalVal>) -> MalRet { if a.len() % 2 == 1 { return err_str("odd number of hash-map keys/values"); @@ -265,7 +275,7 @@ pub fn _assoc(hm: &HashMap<String,MalVal>, a:Vec<MalVal>) -> MalRet { let v = it.next().unwrap(); new_hm.insert(k, v.clone()); } - Ok(Rc::new(Hash_Map(new_hm))) + Ok(Rc::new(Hash_Map(new_hm,_nil()))) } pub fn _dissoc(hm: &HashMap<String,MalVal>, a:Vec<MalVal>) -> MalRet { let mut new_hm = hm.clone(); @@ -280,7 +290,7 @@ pub fn _dissoc(hm: &HashMap<String,MalVal>, a:Vec<MalVal>) -> MalRet { }; new_hm.remove(&k); } - Ok(Rc::new(Hash_Map(new_hm))) + Ok(Rc::new(Hash_Map(new_hm,_nil()))) } pub fn hash_mapv(seq: Vec<MalVal>) -> MalRet { let new_hm: HashMap<String,MalVal> = HashMap::new(); @@ -291,26 +301,31 @@ pub fn hash_map_q(a:Vec<MalVal>) -> MalRet { return err_str("Wrong arity to map? call"); } match *a[0].clone() { - Hash_Map(_) => Ok(_true()), - _ => Ok(_false()), + Hash_Map(_,_) => Ok(_true()), + _ => Ok(_false()), } } // Functions -pub fn func(f: fn(Vec<MalVal>) -> MalRet ) -> MalVal { - Rc::new(Func(f)) +pub fn func(f: fn(Vec<MalVal>) -> MalRet) -> MalVal { + Rc::new(Func(f, _nil())) +} +pub fn funcm(f: fn(Vec<MalVal>) -> MalRet, meta: MalVal) -> MalVal { + Rc::new(Func(f, meta)) } pub fn malfunc(eval: fn(MalVal, Env) -> MalRet, - exp: MalVal, env: Env, params: MalVal) -> MalVal { + exp: MalVal, + env: Env, + params: MalVal, + meta: MalVal) -> MalVal { Rc::new(MalFunc(MalFuncData{eval: eval, exp: exp, env: env, params: params, - is_macro: false, - meta: _nil()})) + is_macro: false},meta)) } -pub fn malfuncd(mfd: MalFuncData) -> MalVal { - Rc::new(MalFunc(mfd)) +pub fn malfuncd(mfd: MalFuncData, meta: MalVal) -> MalVal { + Rc::new(MalFunc(mfd,meta)) } @@ -329,7 +344,7 @@ pub fn sequential_q(a:Vec<MalVal>) -> MalRet { return err_str("Wrong arity to sequential? call"); } match *a[0].clone() { - List(_) | Vector(_) => Ok(_true()), + List(_,_) | Vector(_,_) => Ok(_true()), _ => Ok(_false()), } } |
