4 use std::collections::HashMap;
6 use super::printer::{escape_str,pr_list};
7 use super::env::{Env,env_new,env_bind};
10 #[allow(non_camel_case_types)]
20 Hash_Map(HashMap<String, MalVal>),
21 Func(fn(Vec<MalVal>) -> MalRet),
22 //Func(fn(&[MalVal]) -> MalRet),
23 //Func(|Vec<MalVal>|:'a -> MalRet),
27 pub type MalVal = Rc<MalType>;
29 pub type MalRet = Result<MalVal,String>;
32 pub struct MalFuncData {
33 pub eval: fn(MalVal, Env) -> MalRet,
41 pub fn pr_str(&self, print_readably: bool) -> String {
42 let _r = print_readably;
43 let mut res = String::new();
45 Nil => res.push_str("nil"),
46 True => res.push_str("true"),
47 False => res.push_str("false"),
48 Int(v) => res.push_str(v.to_string().as_slice()),
49 Sym(ref v) => res.push_str((*v).as_slice()),
52 res.push_str(escape_str((*v).as_slice()).as_slice())
54 res.push_str(v.as_slice())
58 res = pr_list(v, _r, "(", ")", " ")
61 res = pr_list(v, _r, "[", "]", " ")
66 for (key, value) in v.iter() {
67 if first { first = false; } else { res.push_str(" "); }
69 res.push_str(escape_str(key.as_slice()).as_slice())
71 res.push_str(key.as_slice())
74 res.push_str(value.pr_str(_r).as_slice());
78 // TODO: better native function representation
80 res.push_str(format!("#<function ...>").as_slice())
83 res.push_str(format!("(fn* {} {})", mf.params, mf.exp).as_slice())
86 Atom(ref v) => v.fmt(f),
92 pub fn apply(&self, args:Vec<MalVal>) -> MalRet {
97 let alst = list(args);
98 let new_env = env_new(Some(mfc.env.clone()));
99 match env_bind(&new_env, mfc.params, alst) {
100 Ok(_) => (mfc.eval)(mfc.exp, new_env),
104 _ => Err("attempt to call non-function".to_string()),
110 impl PartialEq for MalType {
111 fn eq(&self, other: &MalType) -> bool {
112 match (self, other) {
115 (&False, &False) => true,
116 (&Int(ref a), &Int(ref b)) => a == b,
117 (&Strn(ref a), &Strn(ref b)) => a == b,
118 (&Sym(ref a), &Sym(ref b)) => a == b,
119 (&List(ref a), &List(ref b)) |
120 (&Vector(ref a), &Vector(ref b)) |
121 (&List(ref a), &Vector(ref b)) |
122 (&Vector(ref a), &List(ref b)) => a == b,
123 (&Hash_Map(ref a), &Hash_Map(ref b)) => a == b,
125 (&Func(_), &Func(_)) => false,
126 (&MalFunc(_), &MalFunc(_)) => false,
132 impl fmt::Show for MalType {
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 write!(f, "{}", self.pr_str(true))
139 // Convenience constructor functions
140 pub fn _nil() -> MalVal { Rc::new(Nil) }
141 pub fn _true() -> MalVal { Rc::new(True) }
142 pub fn _false() -> MalVal { Rc::new(False) }
143 pub fn _int(i: int) -> MalVal { Rc::new(Int(i)) }
145 pub fn symbol(strn: &str) -> MalVal { Rc::new(Sym(strn.to_string())) }
146 pub fn strn(strn: &str) -> MalVal { Rc::new(Strn(strn.to_string())) }
147 pub fn string(strn: String) -> MalVal { Rc::new(Strn(strn)) }
149 pub fn list(seq: Vec<MalVal>) -> MalVal { Rc::new(List(seq)) }
150 pub fn vector(seq: Vec<MalVal>) -> MalVal { Rc::new(Vector(seq)) }
151 pub fn hash_map(hm: HashMap<String,MalVal>) -> MalVal { Rc::new(Hash_Map(hm)) }
153 pub fn hash_mapv(seq: Vec<MalVal>) -> MalRet {
154 if seq.len() % 2 == 1 {
155 return Err("odd number of elements to hash-map".to_string());
157 let mut new_hm: HashMap<String,MalVal> = HashMap::new();
158 let mut it = seq.iter();
160 let k = match it.next() {
161 Some(mv) => match *mv.clone() {
162 Strn(ref s) => s.to_string(),
163 _ => return Err("key is not a string in hash-map call".to_string()),
167 let v = it.next().unwrap();
168 new_hm.insert(k, v.clone());
170 Ok(Rc::new(Hash_Map(new_hm)))
173 pub fn func(f: fn(Vec<MalVal>) -> MalRet ) -> MalVal {
176 pub fn malfunc(eval: fn(MalVal, Env) -> MalRet,
177 exp: MalVal, env: Env, params: MalVal) -> MalVal {
178 Rc::new(MalFunc(MalFuncData{eval: eval, exp: exp, env: env,
179 params: params, is_macro: false}))
181 pub fn malfuncd(mfd: MalFuncData) -> MalVal {
182 Rc::new(MalFunc(mfd))