aboutsummaryrefslogtreecommitdiff
path: root/rust/src/env.rs
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-10-25 14:02:42 -0500
committerJoel Martin <github@martintribe.org>2015-01-06 21:58:57 -0600
commit0a4d62f2f8362290dfc956ba5c948794a77a6e4d (patch)
treeedf2cd63393da7c4f27068e236d13a3a4e32d530 /rust/src/env.rs
parent8f5b0f1040de849da3fb5ade645308e7bbe7f025 (diff)
downloadmal-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.rs58
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)
+ }
+ }
+}