diff options
Diffstat (limited to 'rust/src')
| -rw-r--r-- | rust/src/core.rs | 60 | ||||
| -rw-r--r-- | rust/src/env.rs | 6 | ||||
| -rw-r--r-- | rust/src/reader.rs | 7 | ||||
| -rw-r--r-- | rust/src/types.rs | 26 |
4 files changed, 90 insertions, 9 deletions
diff --git a/rust/src/core.rs b/rust/src/core.rs index 5eafa4c..b4abd2f 100644 --- a/rust/src/core.rs +++ b/rust/src/core.rs @@ -5,7 +5,7 @@ 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, + Nil,Int,Strn,List,Vector,Hash_Map,Atom, _nil,_true,_false,_int,string,list,func}; use types; use readline; @@ -382,6 +382,59 @@ pub fn map(a:Vec<MalVal>) -> MalRet { } +// Atom funcions +fn deref(a:Vec<MalVal>) -> MalRet { + if a.len() != 1 { + return err_str("Wrong arity to deref call"); + } + match *a[0].clone() { + Atom(ref val) => { + let val_cell = val.borrow(); + Ok(val_cell.clone()) + }, + _ => err_str("deref called on non-atom"), + } +} + +fn reset_bang(a:Vec<MalVal>) -> MalRet { + if a.len() != 2 { + return err_str("Wrong arity to map call"); + } + let a1 = a[1].clone(); + match *a[0].clone() { + Atom(ref val) => { + let mut val_cell = val.borrow_mut(); + let atm_mv = val_cell.deref_mut(); + *atm_mv = a1.clone(); + Ok(a1) + }, + _ => err_str("reset! called on non-atom"), + } +} + +fn swap_bang(a:Vec<MalVal>) -> MalRet { + if a.len() < 2 { + return err_str("Wrong arity to swap_q call"); + } + let f = a[1].clone(); + match *a[0].clone() { + Atom(ref val) => { + let mut val_cell = val.borrow_mut(); + let atm_mv = val_cell.deref_mut(); + let mut args = a.slice(2,a.len()).to_vec(); + args.insert(0, atm_mv.clone()); + match f.apply(args) { + Ok(new_mv) => { + *atm_mv = new_mv.clone(); + Ok(new_mv) + } + Err(e) => Err(e), + } + }, + _ => err_str("swap! called on non-atom"), + } +} + pub fn ns() -> HashMap<String,MalVal> { let mut ns: HashMap<String,MalVal> = HashMap::new();; @@ -435,5 +488,10 @@ pub fn ns() -> HashMap<String,MalVal> { ns.insert("apply".to_string(), func(apply)); ns.insert("map".to_string(), func(map)); + ns.insert("atom".to_string(), func(types::atom)); + ns.insert("deref".to_string(), func(deref)); + ns.insert("reset!".to_string(), func(reset_bang)); + ns.insert("swap!".to_string(), func(swap_bang)); + return ns; } diff --git a/rust/src/env.rs b/rust/src/env.rs index 0d72e62..7ffc319 100644 --- a/rust/src/env.rs +++ b/rust/src/env.rs @@ -5,7 +5,7 @@ use std::cell::RefCell; use std::collections::HashMap; use std::fmt; -use types::{MalVal,MalRet,Sym,List,_nil,list,err_string}; +use types::{MalVal,MalRet,Sym,List,Vector,_nil,list,err_string}; struct EnvType { data: HashMap<String,MalVal>, @@ -23,9 +23,9 @@ pub fn env_bind(env: &Env, mexprs: MalVal) -> Result<Env,String> { let mut variadic = false; match *mbinds { - List(ref binds) => { + List(ref binds) | Vector(ref binds) => { match *mexprs { - List(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 652a7d7..e3ec55e 100644 --- a/rust/src/reader.rs +++ b/rust/src/reader.rs @@ -166,6 +166,13 @@ fn read_form(rdr : &mut Reader) -> MalRet { Err(e) => Err(e), } }, + "@" => { + let _ = rdr.next(); + match read_form(rdr) { + Ok(f) => Ok(list(vec![symbol("deref"), f])), + Err(e) => Err(e), + } + }, ")" => err_str("unexected ')'"), "(" => read_list(rdr), diff --git a/rust/src/types.rs b/rust/src/types.rs index 80079ce..7c74894 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] use std::rc::Rc; +use std::cell::RefCell; use std::collections::HashMap; use std::fmt; use super::printer::{escape_str,pr_list}; @@ -22,6 +23,7 @@ pub enum MalType { //Func(fn(&[MalVal]) -> MalRet), //Func(|Vec<MalVal>|:'a -> MalRet), MalFunc(MalFuncData), + Atom(RefCell<MalVal>), } pub type MalVal = Rc<MalType>; @@ -63,6 +65,7 @@ pub struct MalFuncData { pub env: Env, pub params: MalVal, pub is_macro: bool, + pub meta: MalVal, } impl MalType { @@ -110,9 +113,9 @@ impl MalType { MalFunc(ref mf) => { res.push_str(format!("(fn* {} {})", mf.params, mf.exp).as_slice()) }, - /* - Atom(ref v) => v.fmt(f), - */ + Atom(ref v) => { + res = format!("(atom {})", v.borrow()); + }, }; res } @@ -299,14 +302,27 @@ pub fn func(f: fn(Vec<MalVal>) -> MalRet ) -> MalVal { } pub fn malfunc(eval: fn(MalVal, Env) -> MalRet, exp: MalVal, env: Env, params: MalVal) -> MalVal { - Rc::new(MalFunc(MalFuncData{eval: eval, exp: exp, env: env, - params: params, is_macro: false})) + Rc::new(MalFunc(MalFuncData{eval: eval, + exp: exp, + env: env, + params: params, + is_macro: false, + meta: _nil()})) } pub fn malfuncd(mfd: MalFuncData) -> MalVal { Rc::new(MalFunc(mfd)) } +// Atoms +pub fn atom(a:Vec<MalVal>) -> MalRet { + if a.len() != 1 { + return err_str("Wrong arity to atom call"); + } + Ok(Rc::new(Atom(RefCell::new(a[0].clone())))) +} + + // General functions pub fn sequential_q(a:Vec<MalVal>) -> MalRet { if a.len() != 1 { |
