aboutsummaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-10-27 21:42:46 -0500
committerJoel Martin <github@martintribe.org>2015-01-06 21:59:00 -0600
commit06fef9b51830a2aa696f3e108c56f306967ce465 (patch)
treed3568abe85505a7c825ad96ffabd44adc7b4d456 /rust/src
parentb12d98e4e3424be6b1e851c9450e9532910996ec (diff)
downloadmal-06fef9b51830a2aa696f3e108c56f306967ce465.tar.gz
mal-06fef9b51830a2aa696f3e108c56f306967ce465.zip
rust: add atom support. Fix vector params.
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/core.rs60
-rw-r--r--rust/src/env.rs6
-rw-r--r--rust/src/reader.rs7
-rw-r--r--rust/src/types.rs26
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 {