aboutsummaryrefslogtreecommitdiff
path: root/rust/src/core.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/core.rs')
-rw-r--r--rust/src/core.rs285
1 files changed, 121 insertions, 164 deletions
diff --git a/rust/src/core.rs b/rust/src/core.rs
index 2bc3c39..f7257f3 100644
--- a/rust/src/core.rs
+++ b/rust/src/core.rs
@@ -1,31 +1,30 @@
#![allow(dead_code)]
-extern crate time;
use std::collections::HashMap;
-use std::io::File;
+use std::fs::File;
+use std::io::prelude::*;
+use std::num::ToPrimitive;
+use time;
use types::{MalVal,MalRet,err_val,err_str,err_string,
- Nil,Int,Strn,List,Vector,Hash_Map,Func,MalFunc,Atom,
_nil,_true,_false,_int,string,
list,vector,listm,vectorm,hash_mapm,func,funcm,malfuncd};
+use types::MalType::{Nil, Int, Strn, List, Vector, Hash_Map, Func, MalFunc, Atom};
use types;
use readline;
use reader;
use printer;
// General functions
-fn equal_q(a:Vec<MalVal>) -> MalRet {
+fn equal_q(a: Vec<MalVal>) -> MalRet {
if a.len() != 2 {
return err_str("Wrong arity to equal? call");
}
- match a[0] == a[1] {
- true => Ok(_true()),
- false => Ok(_false()),
- }
+ if a[0] == a[1] {Ok(_true())} else {Ok(_false())}
}
// Errors/Exceptions
-fn throw(a:Vec<MalVal>) -> MalRet {
+fn throw(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to throw call");
}
@@ -33,27 +32,27 @@ fn throw(a:Vec<MalVal>) -> MalRet {
}
// String routines
-fn pr_str(a:Vec<MalVal>) -> MalRet {
+fn pr_str(a: Vec<MalVal>) -> MalRet {
Ok(string(printer::pr_list(&a, true, "", "", " ")))
}
-fn str(a:Vec<MalVal>) -> MalRet {
+fn str(a: Vec<MalVal>) -> MalRet {
Ok(string(printer::pr_list(&a, false, "", "", "")))
}
-fn prn(a:Vec<MalVal>) -> MalRet {
- println!("{}", printer::pr_list(&a, true, "", "", " "))
+fn prn(a: Vec<MalVal>) -> MalRet {
+ println!("{}", printer::pr_list(&a, true, "", "", " "));
Ok(_nil())
}
-fn println(a:Vec<MalVal>) -> MalRet {
- println!("{}", printer::pr_list(&a, false, "", "", " "))
+fn println(a: Vec<MalVal>) -> MalRet {
+ println!("{}", printer::pr_list(&a, false, "", "", " "));
Ok(_nil())
}
-fn readline(a:Vec<MalVal>) -> MalRet {
+fn readline(a: Vec<MalVal>) -> MalRet {
match *a[0] {
- Strn(ref a0) => match readline::mal_readline(a0.as_slice()) {
+ Strn(ref a0) => match readline::mal_readline(&a0) {
Some(line) => Ok(string(line)),
None => err_val(_nil()),
},
@@ -61,18 +60,19 @@ fn readline(a:Vec<MalVal>) -> MalRet {
}
}
-fn read_string(a:Vec<MalVal>) -> MalRet {
+fn read_string(a: Vec<MalVal>) -> MalRet {
match *a[0] {
Strn(ref a0) => reader::read_str(a0.to_string()),
_ => err_str("read_string called with non-string"),
}
}
-fn slurp(a:Vec<MalVal>) -> MalRet {
+fn slurp(a: Vec<MalVal>) -> MalRet {
match *a[0] {
Strn(ref a0) => {
- match File::open(&Path::new(a0.as_slice())).read_to_string() {
- Ok(s) => Ok(string(s)),
+ let mut s = String::new();
+ match File::open(a0).and_then(|mut f| f.read_to_string(&mut s)) {
+ Ok(_) => Ok(string(s)),
Err(e) => err_string(e.to_string()),
}
},
@@ -82,7 +82,9 @@ fn slurp(a:Vec<MalVal>) -> MalRet {
// Numeric functions
-fn int_op(f: |i:int,j:int|-> int, a:Vec<MalVal>) -> MalRet {
+fn int_op<F>(f: F, a: Vec<MalVal>) -> MalRet
+ where F: FnOnce(isize, isize) -> isize
+{
match *a[0] {
Int(a0) => match *a[1] {
Int(a1) => Ok(_int(f(a0,a1))),
@@ -92,13 +94,15 @@ fn int_op(f: |i:int,j:int|-> int, a:Vec<MalVal>) -> MalRet {
}
}
-fn bool_op(f: |i:int,j:int|-> bool, a:Vec<MalVal>) -> MalRet {
+fn bool_op<F>(f: F, a: Vec<MalVal>) -> MalRet
+ where F: FnOnce(isize, isize) -> bool
+{
match *a[0] {
Int(a0) => match *a[1] {
Int(a1) => {
match f(a0,a1) {
true => Ok(_true()),
- false => Ok(_false()),
+ false => Ok(_false()),
}
},
_ => err_str("second arg must be an int"),
@@ -107,83 +111,73 @@ fn bool_op(f: |i:int,j:int|-> bool, a:Vec<MalVal>) -> MalRet {
}
}
-pub fn add(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i+j }, a) }
-pub fn sub(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i-j }, a) }
-pub fn mul(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i*j }, a) }
-pub fn div(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i/j }, a) }
+pub fn add(a: Vec<MalVal>) -> MalRet { int_op(|i,j| { i+j }, a) }
+pub fn sub(a: Vec<MalVal>) -> MalRet { int_op(|i,j| { i-j }, a) }
+pub fn mul(a: Vec<MalVal>) -> MalRet { int_op(|i,j| { i*j }, a) }
+pub fn div(a: Vec<MalVal>) -> MalRet { int_op(|i,j| { i/j }, a) }
-pub fn lt (a:Vec<MalVal>) -> MalRet { bool_op(|i,j| { i<j }, a) }
-pub fn lte(a:Vec<MalVal>) -> MalRet { bool_op(|i,j| { i<=j }, a) }
-pub fn gt (a:Vec<MalVal>) -> MalRet { bool_op(|i,j| { i>j }, a) }
-pub fn gte(a:Vec<MalVal>) -> MalRet { bool_op(|i,j| { i>=j }, a) }
+pub fn lt (a: Vec<MalVal>) -> MalRet { bool_op(|i,j| { i<j }, a) }
+pub fn lte(a: Vec<MalVal>) -> MalRet { bool_op(|i,j| { i<=j }, a) }
+pub fn gt (a: Vec<MalVal>) -> MalRet { bool_op(|i,j| { i>j }, a) }
+pub fn gte(a: Vec<MalVal>) -> MalRet { bool_op(|i,j| { i>=j }, a) }
-#[allow(unused_variable)]
-pub fn time_ms(a:Vec<MalVal>) -> MalRet {
+pub fn time_ms(_a: Vec<MalVal>) -> MalRet {
//let x = time::now();
let now = time::get_time();
- let now_ms = (now.sec * 1000).to_int().unwrap() + (now.nsec.to_int().unwrap() / 1000000);
+ let now_ms = (now.sec * 1000).to_isize().unwrap() +
+ (now.nsec.to_isize().unwrap() / 1000000);
Ok(_int(now_ms))
}
// Hash Map functions
-pub fn assoc(a:Vec<MalVal>) -> MalRet {
+pub fn assoc(a: Vec<MalVal>) -> MalRet {
if a.len() < 3 {
return err_str("Wrong arity to assoc call");
}
match *a[0] {
- Hash_Map(ref hm,_) => {
- types::_assoc(hm, a.slice(1,a.len()).to_vec())
- },
- Nil => {
- types::hash_mapv(a.slice(1,a.len()).to_vec())
- }
- _ => return err_str("assoc onto non-hash map"),
+ Hash_Map(ref hm,_) => types::_assoc(hm, a[1..].to_vec()),
+ Nil => types::hash_mapv(a[1..].to_vec()),
+ _ => err_str("assoc onto non-hash map"),
}
}
-pub fn dissoc(a:Vec<MalVal>) -> MalRet {
+pub fn dissoc(a: Vec<MalVal>) -> MalRet {
if a.len() < 2 {
return err_str("Wrong arity to dissoc call");
}
match *a[0] {
- Hash_Map(ref hm,_) => {
- types::_dissoc(hm, a.slice(1,a.len()).to_vec())
- },
- Nil => {
- Ok(_nil())
- }
- _ => return err_str("dissoc onto non-hash map"),
+ Hash_Map(ref hm,_) => types::_dissoc(hm, a[1..].to_vec()),
+ Nil => Ok(_nil()),
+ _ => err_str("dissoc onto non-hash map"),
}
}
-pub fn get(a:Vec<MalVal>) -> MalRet {
+pub fn get(a: Vec<MalVal>) -> MalRet {
if a.len() != 2 {
return err_str("Wrong arity to get call");
}
- let a0 = a[0].clone();
- let hm: &HashMap<String,MalVal> = match *a0 {
+ let hm = match *a[0] {
Hash_Map(ref hm,_) => hm,
Nil => return Ok(_nil()),
_ => return err_str("get on non-hash map"),
};
match *a[1] {
Strn(ref key) => {
- match hm.find_copy(key) {
- Some(v) => Ok(v),
+ match hm.get(key) {
+ Some(v) => Ok(v.clone()),
None => Ok(_nil()),
}
},
- _ => return err_str("get with non-string key"),
+ _ => err_str("get with non-string key"),
}
}
-pub fn contains_q(a:Vec<MalVal>) -> MalRet {
+pub fn contains_q(a: Vec<MalVal>) -> MalRet {
if a.len() != 2 {
return err_str("Wrong arity to contains? call");
}
- let a0 = a[0].clone();
- let hm: &HashMap<String,MalVal> = match *a0 {
+ let hm = match *a[0] {
Hash_Map(ref hm,_) => hm,
Nil => return Ok(_false()),
_ => return err_str("contains? on non-hash map"),
@@ -194,50 +188,37 @@ pub fn contains_q(a:Vec<MalVal>) -> MalRet {
true => Ok(_true()),
false => Ok(_false()),
}
- },
- _ => return err_str("contains? with non-string key"),
+ }
+ _ => err_str("contains? with non-string key"),
}
}
-pub fn keys(a:Vec<MalVal>) -> MalRet {
+pub fn keys(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to keys call");
}
- let a0 = a[0].clone();
- let hm: &HashMap<String,MalVal> = match *a0 {
+ let hm = match *a[0] {
Hash_Map(ref hm,_) => hm,
Nil => return Ok(_nil()),
_ => return err_str("contains? on non-hash map"),
};
- //if hm.len() == 0 { return Ok(_nil()); }
- let mut keys = vec![];
- for k in hm.keys() {
- keys.push(string(k.to_string()));
- }
- Ok(list(keys))
+ Ok(list(hm.keys().map(|s| string(s.to_string())).collect()))
}
-pub fn vals(a:Vec<MalVal>) -> MalRet {
+pub fn vals(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to values call");
}
- let a0 = a[0].clone();
- let hm: &HashMap<String,MalVal> = match *a0 {
+ let hm = match *a[0] {
Hash_Map(ref hm,_) => hm,
Nil => return Ok(_nil()),
_ => return err_str("contains? on non-hash map"),
};
- //if hm.len() == 0 { return Ok(_nil()); }
- let mut vals = vec![];
- for k in hm.values() {
- vals.push(k.clone());
- }
- Ok(list(vals))
+ Ok(list(hm.values().map(|s| s.clone()).collect()))
}
-
// Sequence functions
-pub fn cons(a:Vec<MalVal>) -> MalRet {
+pub fn cons(a: Vec<MalVal>) -> MalRet {
match *a[1] {
List(ref v,_) | Vector(ref v,_) => {
let mut new_v = v.clone();
@@ -248,32 +229,28 @@ pub fn cons(a:Vec<MalVal>) -> MalRet {
}
}
-pub fn concat(a:Vec<MalVal>) -> MalRet {
- let mut new_v:Vec<MalVal> = vec![];
+pub fn concat(a: Vec<MalVal>) -> MalRet {
+ let mut new_v: Vec<MalVal> = vec![];
for lst in a.iter() {
match **lst {
- List(ref l,_) | Vector(ref l,_) => {
- new_v.push_all(l.as_slice());
- },
+ List(ref l,_) | Vector(ref l,_) => new_v.push_all(l),
_ => return err_str("concat called with non-sequence"),
}
}
Ok(list(new_v))
}
-pub fn nth(a:Vec<MalVal>) -> MalRet {
+pub fn nth(a: Vec<MalVal>) -> MalRet {
if a.len() != 2 {
return err_str("Wrong arity to nth call");
}
- let a0 = a[0].clone();
- let a1 = a[1].clone();
- let seq = match *a0 {
+ let seq = match *a[0] {
List(ref v,_) | Vector(ref v,_) => v,
_ => return err_str("nth called with non-sequence"),
};
- let idx = match *a1 {
+ let idx = match *a[1] {
Int(i) => {
- match i.to_uint() {
+ match i.to_usize() {
Some(ui) => ui,
None => return Ok(_nil()),
}
@@ -281,18 +258,17 @@ pub fn nth(a:Vec<MalVal>) -> MalRet {
_ => return err_str("nth called with non-integer index"),
};
if idx >= seq.len() {
- return err_str("nth: index out of range")
+ err_str("nth: index out of range")
} else {
Ok(seq[idx].clone())
}
}
-pub fn first(a:Vec<MalVal>) -> MalRet {
+pub fn first(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to first call");
}
- let a0 = a[0].clone();
- let seq = match *a0 {
+ let seq = match *a[0] {
List(ref v,_) | Vector(ref v,_) => v,
_ => return err_str("first called with non-sequence"),
};
@@ -303,27 +279,26 @@ pub fn first(a:Vec<MalVal>) -> MalRet {
}
}
-pub fn rest(a:Vec<MalVal>) -> MalRet {
+pub fn rest(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to rest call");
}
- let a0 = a[0].clone();
- let seq = match *a0 {
+ let seq = match *a[0] {
List(ref v,_) | Vector(ref v,_) => v,
_ => return err_str("rest called with non-sequence"),
};
if seq.len() == 0 {
Ok(list(vec![]))
} else {
- Ok(list(seq.slice(1,seq.len()).to_vec()))
+ Ok(list(seq[1..].to_vec()))
}
}
-pub fn empty_q(a:Vec<MalVal>) -> MalRet {
+pub fn empty_q(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to empty? call");
}
- match *a[0].clone() {
+ match *a[0] {
List(ref v,_) | Vector(ref v,_) => {
match v.len() {
0 => Ok(_true()),
@@ -334,48 +309,42 @@ pub fn empty_q(a:Vec<MalVal>) -> MalRet {
}
}
-pub fn count(a:Vec<MalVal>) -> MalRet {
+pub fn count(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to count call");
}
- match *a[0].clone() {
- List(ref v,_) | Vector(ref v,_) => {
- Ok(_int(v.len().to_int().unwrap()))
- },
+ match *a[0] {
+ List(ref v,_) | Vector(ref v,_) => Ok(_int(v.len().to_isize().unwrap())),
Nil => Ok(_int(0)),
_ => err_str("count called on non-sequence"),
}
}
-pub fn apply(a:Vec<MalVal>) -> MalRet {
+pub fn apply(a: Vec<MalVal>) -> MalRet {
if a.len() < 2 {
return err_str("apply call needs 2 or more arguments");
}
let ref f = a[0];
- let mut args = a.slice(1,a.len()-1).to_vec();
+ let mut args = a[1..a.len()-1].to_vec();
match *a[a.len()-1] {
- List(ref v,_) | Vector(ref v,_) => {
- args.push_all(v.as_slice());
+ List(ref v, _) | Vector(ref v, _) => {
+ args.push_all(v);
f.apply(args)
},
_ => err_str("apply call with non-sequence"),
}
}
-pub fn map(a:Vec<MalVal>) -> MalRet {
+pub fn map(a: Vec<MalVal>) -> MalRet {
if a.len() != 2 {
return err_str("Wrong arity to map call");
}
let mut results:Vec<MalVal> = vec![];
- let ref f = a[0].clone();
- let seq = a[1].clone();
- match *seq {
+ match *a[1] {
List(ref v,_) | Vector(ref v,_) => {
for mv in v.iter() {
- match f.apply(vec![mv.clone()]) {
- Ok(res) => results.push(res),
- Err(e) => return Err(e),
- }
+ let res = try!(a[0].apply(vec![mv.clone()]));
+ results.push(res);
}
},
_ => return err_str("map call with non-sequence"),
@@ -383,53 +352,52 @@ pub fn map(a:Vec<MalVal>) -> MalRet {
Ok(list(results))
}
-pub fn conj(a:Vec<MalVal>) -> MalRet {
+pub fn conj(a: Vec<MalVal>) -> MalRet {
if a.len() < 2 {
return err_str("Wrong arity to conj call");
}
- let mut new_v:Vec<MalVal> = vec![];
- match *a[0].clone() {
+ let mut new_v: Vec<MalVal> = vec![];
+ match *a[0] {
List(ref l,_) => {
- new_v.push_all(l.as_slice());
+ new_v.push_all(l);
for mv in a.iter().skip(1) {
- new_v.insert(0,mv.clone());
+ new_v.insert(0, mv.clone());
}
Ok(list(new_v))
- },
+ }
Vector(ref l,_) => {
- new_v.push_all(l.as_slice());
+ new_v.push_all(l);
for mv in a.iter().skip(1) {
new_v.push(mv.clone());
}
Ok(vector(new_v))
- },
- _ => return err_str("conj called with non-sequence"),
+ }
+ _ => err_str("conj called with non-sequence"),
}
}
// Metadata functions
-fn with_meta(a:Vec<MalVal>) -> MalRet {
+fn with_meta(a: Vec<MalVal>) -> MalRet {
if a.len() != 2 {
return err_str("Wrong arity to with-meta call");
}
- let mv = a[0].clone();
let meta = a[1].clone();
- match *mv {
- List(ref v,_) => Ok(listm(v.clone(),meta)),
- Vector(ref v,_) => Ok(vectorm(v.clone(),meta)),
- Hash_Map(ref hm,_) => Ok(hash_mapm(hm.clone(),meta)),
- MalFunc(ref mfd,_) => Ok(malfuncd(mfd.clone(),meta)),
- Func(f,_) => Ok(funcm(f,meta)),
+ match *a[0] {
+ List(ref v,_) => Ok(listm(v.clone(), meta)),
+ Vector(ref v,_) => Ok(vectorm(v.clone(), meta)),
+ Hash_Map(ref hm,_) => Ok(hash_mapm(hm.clone(), meta)),
+ MalFunc(ref mfd,_) => Ok(malfuncd(mfd.clone(), meta)),
+ Func(f,_) => Ok(funcm(f, meta)),
_ => err_str("type does not support metadata"),
}
}
-fn meta(a:Vec<MalVal>) -> MalRet {
+fn meta(a: Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to meta call");
}
- match *a[0].clone() {
+ match *a[0] {
List(_,ref meta) |
Vector(_,ref meta) |
Hash_Map(_,ref meta) |
@@ -440,53 +408,42 @@ fn meta(a:Vec<MalVal>) -> MalRet {
}
// Atom functions
-fn deref(a:Vec<MalVal>) -> MalRet {
+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())
- },
+ match *a[0] {
+ Atom(ref val) => Ok(val.borrow().clone()),
_ => err_str("deref called on non-atom"),
}
}
-fn reset_bang(a:Vec<MalVal>) -> MalRet {
+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() {
+ match *a[0] {
Atom(ref val) => {
let mut val_cell = val.borrow_mut();
- let atm_mv = val_cell.deref_mut();
- *atm_mv = a1.clone();
- Ok(a1)
+ *val_cell = a[1].clone();
+ Ok(a[1].clone())
},
_ => err_str("reset! called on non-atom"),
}
}
-fn swap_bang(a:Vec<MalVal>) -> MalRet {
+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() {
+ match *a[0] {
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),
- }
+ let mut args = a[2..].to_vec();
+ args.insert(0, val_cell.clone());
+ *val_cell = try!(f.apply(args));
+ Ok(val_cell.clone())
},
_ => err_str("swap! called on non-atom"),
}
@@ -494,7 +451,7 @@ fn swap_bang(a:Vec<MalVal>) -> MalRet {
pub fn ns() -> HashMap<String,MalVal> {
- let mut ns: HashMap<String,MalVal> = HashMap::new();;
+ let mut ns = HashMap::new();;
ns.insert("=".to_string(), func(equal_q));
ns.insert("throw".to_string(), func(throw));