diff options
| author | Joel Martin <github@martintribe.org> | 2014-10-25 14:02:42 -0500 |
|---|---|---|
| committer | Joel Martin <github@martintribe.org> | 2015-01-06 21:58:57 -0600 |
| commit | 0a4d62f2f8362290dfc956ba5c948794a77a6e4d (patch) | |
| tree | edf2cd63393da7c4f27068e236d13a3a4e32d530 /rust/src/env.rs | |
| parent | 8f5b0f1040de849da3fb5ade645308e7bbe7f025 (diff) | |
| download | mal-0a4d62f2f8362290dfc956ba5c948794a77a6e4d.tar.gz mal-0a4d62f2f8362290dfc956ba5c948794a77a6e4d.zip | |
rust: add step4_if_fn_do
Diffstat (limited to 'rust/src/env.rs')
| -rw-r--r-- | rust/src/env.rs | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/rust/src/env.rs b/rust/src/env.rs index 9c98f23..1471d20 100644 --- a/rust/src/env.rs +++ b/rust/src/env.rs @@ -1,9 +1,11 @@ use std::rc::Rc; use std::cell::RefCell; use std::collections::HashMap; +use std::fmt; -use types::{MalVal,MalRet,Nil}; +use types::{MalVal,MalRet,Nil,Sym,List}; +#[allow(dead_code)] struct EnvType { data: HashMap<String,MalVal>, outer: Option<Env>, @@ -11,10 +13,54 @@ struct EnvType { pub type Env = Rc<RefCell<EnvType>>; +#[allow(dead_code)] pub fn env_new(outer: Option<Env>) -> Env { Rc::new(RefCell::new(EnvType{data: HashMap::new(), outer: outer})) } +#[allow(dead_code)] +pub fn env_bind(env: &Env, + mbinds: MalVal, + mexprs: MalVal) -> Result<Env,String> { + let mut variadic = false; + match *mbinds { + List(ref binds) => { + match *mexprs { + List(ref exprs) => { + let mut it = binds.iter().enumerate(); + for (i, b) in it { + match **b { + Sym(ref strn) => { + if *strn == "&".to_string() { + variadic = true; + break; + } else { + env_set(env, strn.clone(), exprs[i].clone()); + } + } + _ => return Err("non-symbol bind".to_string()), + } + } + if variadic { + let (i, sym) = it.next().unwrap(); + match **sym { + Sym(ref s) => { + let rest = exprs.slice(i-1,exprs.len()).to_vec(); + env_set(env, s.clone(), Rc::new(List(rest))); + } + _ => return Err("& bind to non-symbol".to_string()), + } + } + Ok(env.clone()) + }, + _ => Err("exprs must be a list".to_string()), + } + }, + _ => Err("binds must be a list".to_string()), + } +} + +#[allow(dead_code)] pub fn env_find(env: Env, key: String) -> Option<Env> { if env.borrow().data.contains_key(&key) { Some(env) @@ -26,10 +72,12 @@ pub fn env_find(env: Env, key: String) -> Option<Env> { } } +#[allow(dead_code)] pub fn env_set(env: &Env, key: String, val: MalVal) { env.borrow_mut().data.insert(key, val.clone()); } +#[allow(dead_code)] pub fn env_get(env: Env, key: String) -> MalRet { match env_find(env, key.clone()) { Some(e) => { @@ -42,3 +90,11 @@ pub fn env_get(env: Env, key: String) -> MalRet { } } +impl fmt::Show for EnvType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.outer { + Some(ref o) => write!(f, "[{}/outer:{}]", self.data, o.borrow()), + _ => write!(f, "{}", self.data) + } + } +} |
