aboutsummaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-10-27 20:07:29 -0500
committerJoel Martin <github@martintribe.org>2014-10-27 20:07:29 -0500
commit5939404b0fb822fd29a483dc0d0a4d716cef206e (patch)
tree8196739b701df4fb7b61fed967eaca28f61d4b57 /rust/src
parenta77e2b31de9d1c1f5767e6bff56062f8b3c71211 (diff)
downloadmal-5939404b0fb822fd29a483dc0d0a4d716cef206e.tar.gz
mal-5939404b0fb822fd29a483dc0d0a4d716cef206e.zip
rust: add vector and hash-map support.
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/core.rs20
-rw-r--r--rust/src/reader.rs49
-rw-r--r--rust/src/step1_read_print.rs6
-rw-r--r--rust/src/step2_eval.rs26
-rw-r--r--rust/src/step3_env.rs21
-rw-r--r--rust/src/step4_if_fn_do.rs22
-rw-r--r--rust/src/step5_tco.rs22
-rw-r--r--rust/src/step6_file.rs21
-rw-r--r--rust/src/step7_quote.rs21
-rw-r--r--rust/src/step8_macros.rs21
-rw-r--r--rust/src/types.rs48
11 files changed, 211 insertions, 66 deletions
diff --git a/rust/src/core.rs b/rust/src/core.rs
index 3e1889c..98eb32a 100644
--- a/rust/src/core.rs
+++ b/rust/src/core.rs
@@ -4,7 +4,7 @@ extern crate time;
use std::collections::HashMap;
use std::io::File;
-use types::{MalVal,MalRet,Int,Strn,List,
+use types::{MalVal,MalRet,Int,Strn,List,Vector,
_nil,_true,_false,_int,string,list,func};
use reader;
use printer;
@@ -120,7 +120,7 @@ pub fn list_q(a:Vec<MalVal>) -> MalRet {
pub fn cons(a:Vec<MalVal>) -> MalRet {
match *a[1] {
- List(ref v) => {
+ List(ref v) | Vector(ref v) => {
let mut new_v = v.clone();
new_v.insert(0, a[0].clone());
Ok(list(new_v))
@@ -133,7 +133,7 @@ pub fn concat(a:Vec<MalVal>) -> MalRet {
let mut new_v:Vec<MalVal> = vec![];
for lst in a.iter() {
match **lst {
- List(ref l) => {
+ List(ref l) | Vector(ref l) => {
new_v.push_all(l.as_slice());
},
_ => return Err("concat called with non-sequence".to_string()),
@@ -149,7 +149,7 @@ pub fn nth(a:Vec<MalVal>) -> MalRet {
let a0 = a[0].clone();
let a1 = a[1].clone();
let seq = match *a0 {
- List(ref v) => v,
+ List(ref v) | Vector(ref v) => v,
_ => return Err("nth called with non-sequence".to_string()),
};
let idx = match *a1 {
@@ -174,7 +174,7 @@ pub fn first(a:Vec<MalVal>) -> MalRet {
}
let a0 = a[0].clone();
let seq = match *a0 {
- List(ref v) => v,
+ List(ref v) | Vector(ref v) => v,
_ => return Err("first called with non-sequence".to_string()),
};
if seq.len() == 0 {
@@ -190,7 +190,7 @@ pub fn rest(a:Vec<MalVal>) -> MalRet {
}
let a0 = a[0].clone();
let seq = match *a0 {
- List(ref v) => v,
+ List(ref v) | Vector(ref v) => v,
_ => return Err("rest called with non-sequence".to_string()),
};
if seq.len() == 0 {
@@ -205,8 +205,8 @@ pub fn count(a:Vec<MalVal>) -> MalRet {
return Err("Wrong arity to count call".to_string());
}
match *a[0].clone() {
- List(ref lst) => {
- Ok(_int(lst.len().to_int().unwrap()))
+ List(ref v) | Vector(ref v) => {
+ Ok(_int(v.len().to_int().unwrap()))
},
_ => Err("count called on non-sequence".to_string()),
}
@@ -217,8 +217,8 @@ pub fn empty_q(a:Vec<MalVal>) -> MalRet {
return Err("Wrong arity to empty? call".to_string());
}
match *a[0].clone() {
- List(ref lst) => {
- match lst.len() {
+ List(ref v) | Vector(ref v) => {
+ match v.len() {
0 => Ok(_true()),
_ => Ok(_false()),
}
diff --git a/rust/src/reader.rs b/rust/src/reader.rs
index f0ef2e3..6a52dd2 100644
--- a/rust/src/reader.rs
+++ b/rust/src/reader.rs
@@ -6,7 +6,7 @@
extern crate pcre;
use types::{MalVal,MalRet,
- _nil,_true,_false,_int,symbol,string,list};
+ _nil,_true,_false,_int,symbol,string,list,vector,hash_mapv};
use self::pcre::Pcre;
use super::printer::unescape_str;
@@ -48,6 +48,7 @@ fn tokenize(str :String) -> Vec<String> {
if opt_m.is_none() { break; }
let m = opt_m.unwrap();
if m.group(1) == "" { break; }
+ if m.group(1).starts_with(";") { continue; }
results.push((*m.group(1)).to_string());
}
@@ -77,20 +78,26 @@ fn read_atom(rdr : &mut Reader) -> MalRet {
}
}
-fn read_list(rdr : &mut Reader) -> MalRet {
+fn read_seq(rdr : &mut Reader, start: &str, end: &str) -> Result<Vec<MalVal>,String> {
let otoken = rdr.next();
- if otoken.is_none() { return Err("read_atom underflow".to_string()); }
+ if otoken.is_none() {
+ return Err("read_atom underflow".to_string());
+ }
let stoken = otoken.unwrap();
let token = stoken.as_slice();
- if token != "(" { return Err("expected '('".to_string()); }
+ if token != start {
+ return Err("expected '".to_string() + start.to_string() + "'".to_string());
+ }
let mut ast_vec : Vec<MalVal> = vec![];
loop {
let otoken = rdr.peek();
- if otoken.is_none() { return Err("expected ')', got EOF".to_string()); }
+ if otoken.is_none() {
+ return Err("expected '".to_string() + end.to_string() + "', got EOF".to_string());
+ }
let stoken = otoken.unwrap();
let token = stoken.as_slice();
- if token == ")" { break; }
+ if token == end { break; }
match read_form(rdr) {
Ok(mv) => ast_vec.push(mv),
@@ -99,7 +106,28 @@ fn read_list(rdr : &mut Reader) -> MalRet {
}
rdr.next();
- Ok(list(ast_vec))
+ Ok(ast_vec)
+}
+
+fn read_list(rdr : &mut Reader) -> MalRet {
+ match read_seq(rdr, "(", ")") {
+ Ok(seq) => Ok(list(seq)),
+ Err(e) => Err(e),
+ }
+}
+
+fn read_vector(rdr : &mut Reader) -> MalRet {
+ match read_seq(rdr, "[", "]") {
+ Ok(seq) => Ok(vector(seq)),
+ Err(e) => Err(e),
+ }
+}
+
+fn read_hash_map(rdr : &mut Reader) -> MalRet {
+ match read_seq(rdr, "{", "}") {
+ Ok(seq) => hash_mapv(seq),
+ Err(e) => Err(e),
+ }
}
fn read_form(rdr : &mut Reader) -> MalRet {
@@ -139,6 +167,13 @@ fn read_form(rdr : &mut Reader) -> MalRet {
")" => Err("unexected ')'".to_string()),
"(" => read_list(rdr),
+
+ "]" => Err("unexected ']'".to_string()),
+ "[" => read_vector(rdr),
+
+ "}" => Err("unexected '}'".to_string()),
+ "{" => read_hash_map(rdr),
+
_ => read_atom(rdr)
}
}
diff --git a/rust/src/step1_read_print.rs b/rust/src/step1_read_print.rs
index 25ca9b5..d69ea6d 100644
--- a/rust/src/step1_read_print.rs
+++ b/rust/src/step1_read_print.rs
@@ -45,7 +45,11 @@ fn main() {
match line { None => break, _ => () }
match rep(line.unwrap()) {
Ok(str) => println!("{}", str),
- Err(str) => println!("Error: {}", str),
+ Err(str) => {
+ if str.as_slice() != "<empty line>" {
+ println!("Error: {}", str)
+ }
+ }
}
}
}
diff --git a/rust/src/step2_eval.rs b/rust/src/step2_eval.rs
index f8046b9..4a0fcb5 100644
--- a/rust/src/step2_eval.rs
+++ b/rust/src/step2_eval.rs
@@ -6,8 +6,8 @@ extern crate regex;
use std::collections::HashMap;
-use types::{MalVal,MalRet,Int,Sym,List,
- _nil,_int,list,func};
+use types::{MalVal,MalRet,Int,Sym,List,Vector,Hash_Map,
+ _nil,_int,list,vector,hash_map,func};
mod readline;
mod types;
mod env;
@@ -28,16 +28,26 @@ fn eval_ast(ast: MalVal, env: &HashMap<String,MalVal>) -> MalRet {
None => Ok(_nil()),
}
},
- List(ref a) => {
+ List(ref a) | Vector(ref a) => {
let mut ast_vec : Vec<MalVal> = vec![];
for mv in a.iter() {
- let mv2 = mv.clone();
- match eval(mv2, env) {
- Ok(mv) => { ast_vec.push(mv); },
- Err(e) => { return Err(e); },
+ match eval(mv.clone(), env) {
+ Ok(mv) => ast_vec.push(mv),
+ Err(e) => return Err(e),
}
}
- Ok(list(ast_vec))
+ Ok(match *ast { List(_) => list(ast_vec),
+ _ => vector(ast_vec) })
+ },
+ Hash_Map(ref hm) => {
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ for (key, value) in hm.iter() {
+ match eval(value.clone(), env) {
+ Ok(mv) => { new_hm.insert(key.to_string(), mv); },
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(hash_map(new_hm))
},
_ => {
Ok(ast.clone())
diff --git a/rust/src/step3_env.rs b/rust/src/step3_env.rs
index 4646a97..f9f79ea 100644
--- a/rust/src/step3_env.rs
+++ b/rust/src/step3_env.rs
@@ -4,8 +4,10 @@
extern crate regex_macros;
extern crate regex;
-use types::{MalVal,MalRet,Int,Sym,List,Vector,
- _int,list,func};
+use std::collections::HashMap;
+
+use types::{MalVal,MalRet,Int,Sym,List,Vector,Hash_Map,
+ _int,list,vector,hash_map,func};
use env::{Env,env_new,env_set,env_get};
mod readline;
mod types;
@@ -26,7 +28,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Sym(ref sym) => {
env_get(env.clone(), sym.clone())
},
- List(ref a) => {
+ List(ref a) | Vector(ref a) => {
let mut ast_vec : Vec<MalVal> = vec![];
for mv in a.iter() {
let mv2 = mv.clone();
@@ -35,7 +37,18 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Err(e) => { return Err(e); },
}
}
- Ok(list(ast_vec))
+ Ok(match *ast { List(_) => list(ast_vec),
+ _ => vector(ast_vec) })
+ },
+ Hash_Map(ref hm) => {
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ for (key, value) in hm.iter() {
+ match eval(value.clone(), env.clone()) {
+ Ok(mv) => { new_hm.insert(key.to_string(), mv); },
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(hash_map(new_hm))
},
_ => {
Ok(ast)
diff --git a/rust/src/step4_if_fn_do.rs b/rust/src/step4_if_fn_do.rs
index 175d1be..0f3603d 100644
--- a/rust/src/step4_if_fn_do.rs
+++ b/rust/src/step4_if_fn_do.rs
@@ -4,9 +4,10 @@
extern crate regex_macros;
extern crate regex;
-use types::{MalVal,MalRet,
- Nil,False,Sym,List,Vector,
- _nil,list,malfunc};
+use std::collections::HashMap;
+
+use types::{MalVal,MalRet,Nil,False,Sym,List,Vector,Hash_Map,
+ _nil,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_set,env_get};
mod readline;
mod types;
@@ -28,7 +29,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Sym(ref sym) => {
env_get(env.clone(), sym.clone())
},
- List(ref a) => {
+ List(ref a) | Vector(ref a) => {
let mut ast_vec : Vec<MalVal> = vec![];
for mv in a.iter() {
let mv2 = mv.clone();
@@ -37,7 +38,18 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Err(e) => { return Err(e); },
}
}
- Ok(list(ast_vec))
+ Ok(match *ast { List(_) => list(ast_vec),
+ _ => vector(ast_vec) })
+ },
+ Hash_Map(ref hm) => {
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ for (key, value) in hm.iter() {
+ match eval(value.clone(), env.clone()) {
+ Ok(mv) => { new_hm.insert(key.to_string(), mv); },
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(hash_map(new_hm))
},
_ => {
Ok(ast)
diff --git a/rust/src/step5_tco.rs b/rust/src/step5_tco.rs
index 345ec52..9c826c7 100644
--- a/rust/src/step5_tco.rs
+++ b/rust/src/step5_tco.rs
@@ -4,9 +4,10 @@
extern crate regex_macros;
extern crate regex;
-use types::{MalVal,MalRet,MalFunc,
- Nil,False,Sym,List,Vector,Func,
- _nil,list,malfunc};
+use std::collections::HashMap;
+
+use types::{MalVal,MalRet,MalFunc,Nil,False,Sym,List,Vector,Hash_Map,Func,
+ _nil,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_bind,env_set,env_get};
mod readline;
mod types;
@@ -28,7 +29,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Sym(ref sym) => {
env_get(env.clone(), sym.clone())
},
- List(ref a) => {
+ List(ref a) | Vector(ref a) => {
let mut ast_vec : Vec<MalVal> = vec![];
for mv in a.iter() {
let mv2 = mv.clone();
@@ -37,7 +38,18 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Err(e) => { return Err(e); },
}
}
- Ok(list(ast_vec))
+ Ok(match *ast { List(_) => list(ast_vec),
+ _ => vector(ast_vec) })
+ },
+ Hash_Map(ref hm) => {
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ for (key, value) in hm.iter() {
+ match eval(value.clone(), env.clone()) {
+ Ok(mv) => { new_hm.insert(key.to_string(), mv); },
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(hash_map(new_hm))
},
_ => {
Ok(ast)
diff --git a/rust/src/step6_file.rs b/rust/src/step6_file.rs
index 1b3427c..237b7f0 100644
--- a/rust/src/step6_file.rs
+++ b/rust/src/step6_file.rs
@@ -4,11 +4,11 @@
extern crate regex_macros;
extern crate regex;
+use std::collections::HashMap;
use std::os;
-use types::{MalVal,MalRet,MalFunc,
- Nil,False,Sym,List,Vector,Func,
- _nil,string,list,malfunc};
+use types::{MalVal,MalRet,MalFunc,Nil,False,Sym,List,Vector,Hash_Map,Func,
+ _nil,string,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_bind,env_root,env_set,env_get};
mod readline;
mod types;
@@ -30,7 +30,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Sym(ref sym) => {
env_get(env.clone(), sym.clone())
},
- List(ref a) => {
+ List(ref a) | Vector(ref a) => {
let mut ast_vec : Vec<MalVal> = vec![];
for mv in a.iter() {
let mv2 = mv.clone();
@@ -39,7 +39,18 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Err(e) => { return Err(e); },
}
}
- Ok(list(ast_vec))
+ Ok(match *ast { List(_) => list(ast_vec),
+ _ => vector(ast_vec) })
+ },
+ Hash_Map(ref hm) => {
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ for (key, value) in hm.iter() {
+ match eval(value.clone(), env.clone()) {
+ Ok(mv) => { new_hm.insert(key.to_string(), mv); },
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(hash_map(new_hm))
},
_ => {
Ok(ast)
diff --git a/rust/src/step7_quote.rs b/rust/src/step7_quote.rs
index c33d75b..3427eea 100644
--- a/rust/src/step7_quote.rs
+++ b/rust/src/step7_quote.rs
@@ -4,11 +4,11 @@
extern crate regex_macros;
extern crate regex;
+use std::collections::HashMap;
use std::os;
-use types::{MalVal,MalRet,MalFunc,
- Nil,False,Sym,List,Vector,Func,
- _nil,symbol,string,list,malfunc};
+use types::{MalVal,MalRet,MalFunc,Nil,False,Sym,List,Vector,Hash_Map,Func,
+ _nil,symbol,string,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_bind,env_root,env_set,env_get};
mod readline;
mod types;
@@ -81,7 +81,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Sym(ref sym) => {
env_get(env.clone(), sym.clone())
},
- List(ref a) => {
+ List(ref a) | Vector(ref a) => {
let mut ast_vec : Vec<MalVal> = vec![];
for mv in a.iter() {
let mv2 = mv.clone();
@@ -90,7 +90,18 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Err(e) => { return Err(e); },
}
}
- Ok(list(ast_vec))
+ Ok(match *ast { List(_) => list(ast_vec),
+ _ => vector(ast_vec) })
+ },
+ Hash_Map(ref hm) => {
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ for (key, value) in hm.iter() {
+ match eval(value.clone(), env.clone()) {
+ Ok(mv) => { new_hm.insert(key.to_string(), mv); },
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(hash_map(new_hm))
},
_ => {
Ok(ast)
diff --git a/rust/src/step8_macros.rs b/rust/src/step8_macros.rs
index c8cc9b3..1c84c58 100644
--- a/rust/src/step8_macros.rs
+++ b/rust/src/step8_macros.rs
@@ -4,11 +4,11 @@
extern crate regex_macros;
extern crate regex;
+use std::collections::HashMap;
use std::os;
-use types::{MalVal,MalRet,MalFunc,
- Nil,False,Sym,List,Vector,Func,
- _nil,symbol,string,list,malfunc,malfuncd};
+use types::{MalVal,MalRet,MalFunc,Nil,False,Sym,List,Vector,Hash_Map,Func,
+ _nil,symbol,string,list,vector,hash_map,malfunc,malfuncd};
use env::{Env,env_new,env_bind,env_root,env_find,env_set,env_get};
mod readline;
mod types;
@@ -141,7 +141,7 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Sym(ref sym) => {
env_get(env.clone(), sym.clone())
},
- List(ref a) => {
+ List(ref a) | Vector(ref a) => {
let mut ast_vec : Vec<MalVal> = vec![];
for mv in a.iter() {
let mv2 = mv.clone();
@@ -150,7 +150,18 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
Err(e) => { return Err(e); },
}
}
- Ok(list(ast_vec))
+ Ok(match *ast { List(_) => list(ast_vec),
+ _ => vector(ast_vec) })
+ },
+ Hash_Map(ref hm) => {
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ for (key, value) in hm.iter() {
+ match eval(value.clone(), env.clone()) {
+ Ok(mv) => { new_hm.insert(key.to_string(), mv); },
+ Err(e) => return Err(e),
+ }
+ }
+ Ok(hash_map(new_hm))
},
_ => {
Ok(ast)
diff --git a/rust/src/types.rs b/rust/src/types.rs
index b8e1de0..e540ff1 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -1,12 +1,13 @@
#![allow(dead_code)]
use std::rc::Rc;
-use std::collections;
+use std::collections::HashMap;
use std::fmt;
use super::printer::{escape_str,pr_list};
use super::env::{Env,env_new,env_bind};
#[deriving(Clone)]
+#[allow(non_camel_case_types)]
pub enum MalType {
Nil,
True,
@@ -16,7 +17,7 @@ pub enum MalType {
Sym(String),
List(Vec<MalVal>),
Vector(Vec<MalVal>),
- HashMap(collections::HashMap<String, MalVal>),
+ Hash_Map(HashMap<String, MalVal>),
Func(fn(Vec<MalVal>) -> MalRet),
//Func(fn(&[MalVal]) -> MalRet),
//Func(|Vec<MalVal>|:'a -> MalRet),
@@ -59,19 +60,22 @@ impl MalType {
Vector(ref v) => {
res = pr_list(v, _r, "[", "]", " ")
},
- HashMap(ref v) => {
+ Hash_Map(ref v) => {
let mut first = true;
res.push_str("{");
for (key, value) in v.iter() {
if first { first = false; } else { res.push_str(" "); }
- res.push_str(key.as_slice());
+ if print_readably {
+ res.push_str(escape_str(key.as_slice()).as_slice())
+ } else {
+ res.push_str(key.as_slice())
+ }
res.push_str(" ");
res.push_str(value.pr_str(_r).as_slice());
}
res.push_str("}")
},
// TODO: better native function representation
- //Func(ref v) => {
Func(_) => {
res.push_str(format!("#<function ...>").as_slice())
},
@@ -79,10 +83,8 @@ impl MalType {
res.push_str(format!("(fn* {} {})", mf.params, mf.exp).as_slice())
},
/*
-
-// Atom(ref v) => v.fmt(f),
+ Atom(ref v) => v.fmt(f),
*/
- //_ => { res.push_str("#<unknown type>") },
};
res
}
@@ -115,8 +117,10 @@ impl PartialEq for MalType {
(&Strn(ref a), &Strn(ref b)) => a == b,
(&Sym(ref a), &Sym(ref b)) => a == b,
(&List(ref a), &List(ref b)) |
- (&Vector(ref a), &Vector(ref b)) => a == b,
- (&HashMap(ref a), &HashMap(ref b)) => a == b,
+ (&Vector(ref a), &Vector(ref b)) |
+ (&List(ref a), &Vector(ref b)) |
+ (&Vector(ref a), &List(ref b)) => a == b,
+ (&Hash_Map(ref a), &Hash_Map(ref b)) => a == b,
// TODO: fix this
(&Func(_), &Func(_)) => false,
(&MalFunc(_), &MalFunc(_)) => false,
@@ -142,7 +146,29 @@ pub fn symbol(strn: &str) -> MalVal { Rc::new(Sym(strn.to_string())) }
pub fn strn(strn: &str) -> MalVal { Rc::new(Strn(strn.to_string())) }
pub fn string(strn: String) -> MalVal { Rc::new(Strn(strn)) }
-pub fn list(lst: Vec<MalVal>) -> MalVal { Rc::new(List(lst)) }
+pub fn list(seq: Vec<MalVal>) -> MalVal { Rc::new(List(seq)) }
+pub fn vector(seq: Vec<MalVal>) -> MalVal { Rc::new(Vector(seq)) }
+pub fn hash_map(hm: HashMap<String,MalVal>) -> MalVal { Rc::new(Hash_Map(hm)) }
+
+pub fn hash_mapv(seq: Vec<MalVal>) -> MalRet {
+ if seq.len() % 2 == 1 {
+ return Err("odd number of elements to hash-map".to_string());
+ }
+ let mut new_hm: HashMap<String,MalVal> = HashMap::new();
+ let mut it = seq.iter();
+ loop {
+ let k = match it.next() {
+ Some(mv) => match *mv.clone() {
+ Strn(ref s) => s.to_string(),
+ _ => return Err("key is not a string in hash-map call".to_string()),
+ },
+ None => break,
+ };
+ let v = it.next().unwrap();
+ new_hm.insert(k, v.clone());
+ }
+ Ok(Rc::new(Hash_Map(new_hm)))
+}
pub fn func(f: fn(Vec<MalVal>) -> MalRet ) -> MalVal {
Rc::new(Func(f))