aboutsummaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
authorJoel Martin <github@martintribe.org>2014-12-18 20:33:49 -0600
committerJoel Martin <github@martintribe.org>2015-01-09 16:16:50 -0600
commitb8ee29b22fbaa7a01f2754b4d6dd9af52e02017c (patch)
treef4d977ed220e9a3f665cfbf4f68770a81e4c2095 /rust/src
parentaaba249304b184e12e2445ab22d66df1f39a51a5 (diff)
downloadmal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.tar.gz
mal-b8ee29b22fbaa7a01f2754b4d6dd9af52e02017c.zip
All: add keywords.
Also, fix nth and count to match cloure.
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/core.rs6
-rw-r--r--rust/src/env.rs57
-rw-r--r--rust/src/reader.rs2
-rw-r--r--rust/src/step3_env.rs22
-rw-r--r--rust/src/step4_if_fn_do.rs18
-rw-r--r--rust/src/step5_tco.rs18
-rw-r--r--rust/src/step6_file.rs22
-rw-r--r--rust/src/step7_quote.rs22
-rw-r--r--rust/src/step8_macros.rs40
-rw-r--r--rust/src/step9_try.rs47
-rw-r--r--rust/src/stepA_interop.rs45
-rw-r--r--rust/src/types.rs50
12 files changed, 213 insertions, 136 deletions
diff --git a/rust/src/core.rs b/rust/src/core.rs
index e751f88..2bc3c39 100644
--- a/rust/src/core.rs
+++ b/rust/src/core.rs
@@ -281,7 +281,7 @@ pub fn nth(a:Vec<MalVal>) -> MalRet {
_ => return err_str("nth called with non-integer index"),
};
if idx >= seq.len() {
- Ok(_nil())
+ return err_str("nth: index out of range")
} else {
Ok(seq[idx].clone())
}
@@ -342,6 +342,7 @@ pub fn count(a:Vec<MalVal>) -> MalRet {
List(ref v,_) | Vector(ref v,_) => {
Ok(_int(v.len().to_int().unwrap()))
},
+ Nil => Ok(_int(0)),
_ => err_str("count called on non-sequence"),
}
}
@@ -500,7 +501,10 @@ pub fn ns() -> HashMap<String,MalVal> {
ns.insert("nil?".to_string(), func(types::nil_q));
ns.insert("true?".to_string(), func(types::true_q));
ns.insert("false?".to_string(), func(types::false_q));
+ ns.insert("symbol".to_string(), func(types::_symbol));
ns.insert("symbol?".to_string(), func(types::symbol_q));
+ ns.insert("keyword".to_string(), func(types::_keyword));
+ ns.insert("keyword?".to_string(), func(types::keyword_q));
ns.insert("pr-str".to_string(), func(pr_str));
ns.insert("str".to_string(), func(str));
diff --git a/rust/src/env.rs b/rust/src/env.rs
index cf8aa0f..e9af154 100644
--- a/rust/src/env.rs
+++ b/rust/src/env.rs
@@ -34,7 +34,7 @@ pub fn env_bind(env: &Env,
variadic = true;
break;
} else {
- env_set(env, strn.clone(), exprs[i].clone());
+ env_set(env, b.clone(), exprs[i].clone());
}
}
_ => return Err("non-symbol bind".to_string()),
@@ -43,9 +43,9 @@ pub fn env_bind(env: &Env,
if variadic {
let (i, sym) = it.next().unwrap();
match **sym {
- Sym(ref s) => {
+ Sym(_) => {
let rest = exprs.slice(i-1,exprs.len()).to_vec();
- env_set(env, s.clone(), list(rest));
+ env_set(env, sym.clone(), list(rest));
}
_ => return Err("& bind to non-symbol".to_string()),
}
@@ -59,14 +59,19 @@ pub fn env_bind(env: &Env,
}
}
-pub fn env_find(env: Env, key: String) -> Option<Env> {
- if env.borrow().data.contains_key(&key) {
- Some(env)
- } else {
- match env.borrow().outer {
- Some(ref e) => env_find(e.clone(), key),
- None => None,
- }
+pub fn env_find(env: Env, key: MalVal) -> Option<Env> {
+ match *key {
+ Sym(ref k) => {
+ if env.borrow().data.contains_key(k) {
+ Some(env)
+ } else {
+ match env.borrow().outer {
+ Some(ref e) => env_find(e.clone(), key.clone()),
+ None => None,
+ }
+ }
+ },
+ _ => None
}
}
@@ -77,19 +82,29 @@ pub fn env_root(env: &Env) -> Env {
}
}
-pub fn env_set(env: &Env, key: String, val: MalVal) {
- env.borrow_mut().data.insert(key, val.clone());
+pub fn env_set(env: &Env, key: MalVal, val: MalVal) {
+ match *key {
+ Sym(ref k) => {
+ env.borrow_mut().data.insert(k.to_string(), val.clone());
+ },
+ _ => {},
+ }
}
-pub fn env_get(env: Env, key: String) -> MalRet {
- match env_find(env, key.clone()) {
- Some(e) => {
- match e.borrow().data.find_copy(&key) {
- Some(v) => Ok(v),
- None => Ok(_nil()),
+pub fn env_get(env: Env, key: MalVal) -> MalRet {
+ match *key {
+ Sym(ref k) => {
+ match env_find(env, key.clone()) {
+ Some(e) => {
+ match e.borrow().data.find_copy(k) {
+ Some(v) => Ok(v),
+ None => Ok(_nil()),
+ }
+ },
+ None => err_string("'".to_string() + k.to_string() + "' not found".to_string()),
}
- },
- None => err_string("'".to_string() + key + "' not found".to_string()),
+ }
+ _ => err_string("env_get called with non-symbol key".to_string()),
}
}
diff --git a/rust/src/reader.rs b/rust/src/reader.rs
index af496ff..d7b2b4c 100644
--- a/rust/src/reader.rs
+++ b/rust/src/reader.rs
@@ -68,6 +68,8 @@ fn read_atom(rdr : &mut Reader) -> MalRet {
} else if regex!(r#"^".*"$"#).is_match(token) {
let new_str = token.slice(1,token.len()-1);
Ok(string(unescape_str(new_str)))
+ } else if regex!(r#"^:"#).is_match(token) {
+ Ok(string("\u029e".to_string() + token.slice(1,token.len())))
} else if token == "nil" {
Ok(_nil())
} else if token == "true" {
diff --git a/rust/src/step3_env.rs b/rust/src/step3_env.rs
index cb80947..b2d49cd 100644
--- a/rust/src/step3_env.rs
+++ b/rust/src/step3_env.rs
@@ -8,7 +8,7 @@ use std::collections::HashMap;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Int,Sym,List,Vector,Hash_Map,
- _int,list,vector,hash_map,func};
+ symbol,_int,list,vector,hash_map,func};
use env::{Env,env_new,env_set,env_get};
mod readline;
mod types;
@@ -26,8 +26,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -94,8 +94,8 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -117,10 +117,10 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -187,10 +187,10 @@ fn div(a:Vec<MalVal>) -> MalRet { int_op(|i,j| { i/j }, a) }
fn main() {
let repl_env = env_new(None);
- env_set(&repl_env, "+".to_string(), func(add));
- env_set(&repl_env, "-".to_string(), func(sub));
- env_set(&repl_env, "*".to_string(), func(mul));
- env_set(&repl_env, "/".to_string(), func(div));
+ env_set(&repl_env, symbol("+"), func(add));
+ env_set(&repl_env, symbol("-"), func(sub));
+ env_set(&repl_env, symbol("*"), func(mul));
+ env_set(&repl_env, symbol("/"), func(div));
loop {
let line = readline::mal_readline("user> ");
diff --git a/rust/src/step4_if_fn_do.rs b/rust/src/step4_if_fn_do.rs
index 1a8d271..92abf92 100644
--- a/rust/src/step4_if_fn_do.rs
+++ b/rust/src/step4_if_fn_do.rs
@@ -8,7 +8,7 @@ use std::collections::HashMap;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Nil,False,Sym,List,Vector,Hash_Map,
- _nil,list,vector,hash_map,malfunc};
+ symbol,_nil,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_set,env_get};
mod readline;
mod types;
@@ -27,8 +27,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -95,8 +95,8 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -118,10 +118,10 @@ fn eval(ast: MalVal, env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -216,7 +216,9 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> {
fn main() {
// core.rs: defined using rust
let repl_env = env_new(None);
- for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
+ for (k, v) in core::ns().into_iter() {
+ env_set(&repl_env, symbol(k.as_slice()), v);
+ }
// core.mal: defined using the language itself
let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
diff --git a/rust/src/step5_tco.rs b/rust/src/step5_tco.rs
index 0fdc597..9223cbf 100644
--- a/rust/src/step5_tco.rs
+++ b/rust/src/step5_tco.rs
@@ -8,7 +8,7 @@ use std::collections::HashMap;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc,
- _nil,list,vector,hash_map,malfunc};
+ symbol,_nil,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_bind,env_set,env_get};
mod readline;
mod types;
@@ -27,8 +27,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -98,8 +98,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -121,10 +121,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -238,7 +238,9 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> {
fn main() {
// core.rs: defined using rust
let repl_env = env_new(None);
- for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
+ for (k, v) in core::ns().into_iter() {
+ env_set(&repl_env, symbol(k.as_slice()), v);
+ }
// core.mal: defined using the language itself
let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
diff --git a/rust/src/step6_file.rs b/rust/src/step6_file.rs
index e1198bb..1e87116 100644
--- a/rust/src/step6_file.rs
+++ b/rust/src/step6_file.rs
@@ -9,7 +9,7 @@ use std::os;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc,
- _nil,string,list,vector,hash_map,malfunc};
+ symbol,_nil,string,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_bind,env_root,env_set,env_get};
mod readline;
mod types;
@@ -28,8 +28,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -99,8 +99,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -122,10 +122,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -250,9 +250,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> {
fn main() {
// core.rs: defined using rust
let repl_env = env_new(None);
- for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
+ for (k, v) in core::ns().into_iter() {
+ env_set(&repl_env, symbol(k.as_slice()), v);
+ }
// see eval() for definition of "eval"
- env_set(&repl_env, "*ARGV*".to_string(), list(vec![]));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![]));
// core.mal: defined using the language itself
let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
@@ -264,7 +266,7 @@ fn main() {
let mv_args = args.slice(2,args.len()).iter()
.map(|a| string(a.to_string()))
.collect::<Vec<MalVal>>();
- env_set(&repl_env, "*ARGV*".to_string(), list(mv_args));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args));
let lf = "(load-file \"".to_string() + args[1] + "\")".to_string();
match rep(lf.as_slice(), repl_env.clone()) {
Ok(_) => {
diff --git a/rust/src/step7_quote.rs b/rust/src/step7_quote.rs
index a46f548..b113920 100644
--- a/rust/src/step7_quote.rs
+++ b/rust/src/step7_quote.rs
@@ -9,7 +9,7 @@ use std::os;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc,
- _nil,symbol,string,list,vector,hash_map,malfunc};
+ symbol,_nil,string,list,vector,hash_map,malfunc};
use env::{Env,env_new,env_bind,env_root,env_set,env_get};
mod readline;
mod types;
@@ -79,8 +79,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -150,8 +150,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -173,10 +173,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -309,9 +309,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> {
fn main() {
// core.rs: defined using rust
let repl_env = env_new(None);
- for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
+ for (k, v) in core::ns().into_iter() {
+ env_set(&repl_env, symbol(k.as_slice()), v);
+ }
// see eval() for definition of "eval"
- env_set(&repl_env, "*ARGV*".to_string(), list(vec![]));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![]));
// core.mal: defined using the language itself
let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
@@ -323,7 +325,7 @@ fn main() {
let mv_args = args.slice(2,args.len()).iter()
.map(|a| string(a.to_string()))
.collect::<Vec<MalVal>>();
- env_set(&repl_env, "*ARGV*".to_string(), list(mv_args));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args));
let lf = "(load-file \"".to_string() + args[1] + "\")".to_string();
match rep(lf.as_slice(), repl_env.clone()) {
Ok(_) => {
diff --git a/rust/src/step8_macros.rs b/rust/src/step8_macros.rs
index fbbaf35..7450de8 100644
--- a/rust/src/step8_macros.rs
+++ b/rust/src/step8_macros.rs
@@ -9,7 +9,7 @@ use std::os;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc,
- _nil,symbol,string,list,vector,hash_map,malfunc,malfuncd};
+ symbol,_nil,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;
@@ -78,11 +78,10 @@ fn quasiquote(ast: MalVal) -> MalVal {
fn is_macro_call(ast: MalVal, env: Env) -> bool {
match *ast {
List(ref lst,_) => {
- let ref a0 = *lst[0];
- match *a0 {
- Sym(ref a0sym) => {
- if env_find(env.clone(), a0sym.to_string()).is_some() {
- match env_get(env, a0sym.to_string()) {
+ match *lst[0] {
+ Sym(_) => {
+ if env_find(env.clone(), lst[0].clone()).is_some() {
+ match env_get(env, lst[0].clone()) {
Ok(f) => {
match *f {
MalFunc(ref mfd,_) => {
@@ -113,8 +112,8 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet {
};
let ref a0 = args[0];
let mf = match **a0 {
- Sym(ref s) => {
- match env_get(env.clone(), s.to_string()) {
+ Sym(_) => {
+ match env_get(env.clone(), a0.clone()) {
Ok(mf) => mf,
Err(e) => return Err(e),
}
@@ -138,8 +137,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -215,8 +214,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -238,10 +237,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -276,11 +275,11 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match *r {
MalFunc(ref mfd,_) => {
match *a1 {
- Sym(ref s) => {
+ Sym(_) => {
let mut new_mfd = mfd.clone();
new_mfd.is_macro = true;
let mf = malfuncd(new_mfd,_nil());
- env_set(&env.clone(), s.clone(), mf.clone());
+ env_set(&env.clone(), a1.clone(), mf.clone());
return Ok(mf);
},
_ => return err_str("def! of non-symbol"),
@@ -402,9 +401,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> {
fn main() {
// core.rs: defined using rust
let repl_env = env_new(None);
- for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
+ for (k, v) in core::ns().into_iter() {
+ env_set(&repl_env, symbol(k.as_slice()), v);
+ }
// see eval() for definition of "eval"
- env_set(&repl_env, "*ARGV*".to_string(), list(vec![]));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![]));
// core.mal: defined using the language itself
let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
@@ -418,7 +419,7 @@ fn main() {
let mv_args = args.slice(2,args.len()).iter()
.map(|a| string(a.to_string()))
.collect::<Vec<MalVal>>();
- env_set(&repl_env, "*ARGV*".to_string(), list(mv_args));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args));
let lf = "(load-file \"".to_string() + args[1] + "\")".to_string();
match rep(lf.as_slice(), repl_env.clone()) {
Ok(_) => {
@@ -433,6 +434,7 @@ fn main() {
}
}
+ // repl loop
loop {
let line = readline::mal_readline("user> ");
match line { None => break, _ => () }
diff --git a/rust/src/step9_try.rs b/rust/src/step9_try.rs
index 4449661..0f6bd88 100644
--- a/rust/src/step9_try.rs
+++ b/rust/src/step9_try.rs
@@ -9,7 +9,7 @@ use std::os;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc,
- _nil,symbol,string,list,vector,hash_map,malfunc,malfuncd};
+ symbol,_nil,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;
@@ -78,11 +78,10 @@ fn quasiquote(ast: MalVal) -> MalVal {
fn is_macro_call(ast: MalVal, env: Env) -> bool {
match *ast {
List(ref lst,_) => {
- let ref a0 = *lst[0];
- match *a0 {
- Sym(ref a0sym) => {
- if env_find(env.clone(), a0sym.to_string()).is_some() {
- match env_get(env, a0sym.to_string()) {
+ match *lst[0] {
+ Sym(_) => {
+ if env_find(env.clone(), lst[0].clone()).is_some() {
+ match env_get(env, lst[0].clone()) {
Ok(f) => {
match *f {
MalFunc(ref mfd,_) => {
@@ -113,8 +112,8 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet {
};
let ref a0 = args[0];
let mf = match **a0 {
- Sym(ref s) => {
- match env_get(env.clone(), s.to_string()) {
+ Sym(_) => {
+ match env_get(env.clone(), a0.clone()) {
Ok(mf) => mf,
Err(e) => return Err(e),
}
@@ -138,8 +137,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -215,8 +214,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -238,10 +237,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -276,11 +275,11 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match *r {
MalFunc(ref mfd,_) => {
match *a1 {
- Sym(ref s) => {
+ Sym(_) => {
let mut new_mfd = mfd.clone();
new_mfd.is_macro = true;
let mf = malfuncd(new_mfd,_nil());
- env_set(&env.clone(), s.clone(), mf.clone());
+ env_set(&env.clone(), a1.clone(), mf.clone());
return Ok(mf);
},
_ => return err_str("def! of non-symbol"),
@@ -311,8 +310,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
return err_str("wrong arity to catch* clause");
}
let c1 = (*cat)[1].clone();
- let bstr = match *c1 {
- Sym(ref s) => s,
+ match *c1 {
+ Sym(_) => {},
_ => return err_str("invalid catch* binding"),
};
let exc = match err {
@@ -320,7 +319,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
ErrString(s) => string(s),
};
let bind_env = env_new(Some(env.clone()));
- env_set(&bind_env, bstr.to_string(), exc);
+ env_set(&bind_env, c1.clone(), exc);
let c2 = (*cat)[2].clone();
return eval(c2, bind_env);
},
@@ -432,12 +431,13 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> {
fn main() {
// core.rs: defined using rust
let repl_env = env_new(None);
- for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
+ for (k, v) in core::ns().into_iter() {
+ env_set(&repl_env, symbol(k.as_slice()), v);
+ }
// see eval() for definition of "eval"
- env_set(&repl_env, "*ARGV*".to_string(), list(vec![]));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![]));
// core.mal: defined using the language itself
- let _ = rep("(def! *host-language* \"rust\")", repl_env.clone());
let _ = rep("(def! not (fn* (a) (if a false true)))", repl_env.clone());
let _ = rep("(def! load-file (fn* (f) (eval (read-string (str \"(do \" (slurp f) \")\")))))", repl_env.clone());
let _ = rep("(defmacro! cond (fn* (& xs) (if (> (count xs) 0) (list 'if (first xs) (if (> (count xs) 1) (nth xs 1) (throw \"odd number of forms to cond\")) (cons 'cond (rest (rest xs)))))))", repl_env.clone());
@@ -449,7 +449,7 @@ fn main() {
let mv_args = args.slice(2,args.len()).iter()
.map(|a| string(a.to_string()))
.collect::<Vec<MalVal>>();
- env_set(&repl_env, "*ARGV*".to_string(), list(mv_args));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args));
let lf = "(load-file \"".to_string() + args[1] + "\")".to_string();
match rep(lf.as_slice(), repl_env.clone()) {
Ok(_) => {
@@ -465,7 +465,6 @@ fn main() {
}
// repl loop
- let _ = rep("(println (str \"Mal [\" *host-language* \"]\"))", repl_env.clone());
loop {
let line = readline::mal_readline("user> ");
match line { None => break, _ => () }
diff --git a/rust/src/stepA_interop.rs b/rust/src/stepA_interop.rs
index 4449661..8e30867 100644
--- a/rust/src/stepA_interop.rs
+++ b/rust/src/stepA_interop.rs
@@ -9,7 +9,7 @@ use std::os;
use types::{MalVal,MalRet,MalError,ErrString,ErrMalVal,err_str,
Nil,False,Sym,List,Vector,Hash_Map,Func,MalFunc,
- _nil,symbol,string,list,vector,hash_map,malfunc,malfuncd};
+ symbol,_nil,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;
@@ -78,11 +78,10 @@ fn quasiquote(ast: MalVal) -> MalVal {
fn is_macro_call(ast: MalVal, env: Env) -> bool {
match *ast {
List(ref lst,_) => {
- let ref a0 = *lst[0];
- match *a0 {
- Sym(ref a0sym) => {
- if env_find(env.clone(), a0sym.to_string()).is_some() {
- match env_get(env, a0sym.to_string()) {
+ match *lst[0] {
+ Sym(_) => {
+ if env_find(env.clone(), lst[0].clone()).is_some() {
+ match env_get(env, lst[0].clone()) {
Ok(f) => {
match *f {
MalFunc(ref mfd,_) => {
@@ -113,8 +112,8 @@ fn macroexpand(mut ast: MalVal, env: Env) -> MalRet {
};
let ref a0 = args[0];
let mf = match **a0 {
- Sym(ref s) => {
- match env_get(env.clone(), s.to_string()) {
+ Sym(_) => {
+ match env_get(env.clone(), a0.clone()) {
Ok(mf) => mf,
Err(e) => return Err(e),
}
@@ -138,8 +137,8 @@ fn eval_ast(ast: MalVal, env: Env) -> MalRet {
let ast2 = ast.clone();
match *ast2 {
//match *ast {
- Sym(ref sym) => {
- env_get(env.clone(), sym.clone())
+ Sym(_) => {
+ env_get(env.clone(), ast)
},
List(ref a,_) | Vector(ref a,_) => {
let mut ast_vec : Vec<MalVal> = vec![];
@@ -215,8 +214,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match res {
Ok(r) => {
match *a1 {
- Sym(ref s) => {
- env_set(&env.clone(), s.clone(), r.clone());
+ Sym(_) => {
+ env_set(&env.clone(), a1.clone(), r.clone());
return Ok(r);
},
_ => {
@@ -238,10 +237,10 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
let b = it.next().unwrap();
let exp = it.next().unwrap();
match **b {
- Sym(ref bstr) => {
+ Sym(_) => {
match eval(exp.clone(), let_env.clone()) {
Ok(r) => {
- env_set(&let_env, bstr.clone(), r);
+ env_set(&let_env, b.clone(), r);
},
Err(e) => {
return Err(e);
@@ -276,11 +275,11 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
match *r {
MalFunc(ref mfd,_) => {
match *a1 {
- Sym(ref s) => {
+ Sym(_) => {
let mut new_mfd = mfd.clone();
new_mfd.is_macro = true;
let mf = malfuncd(new_mfd,_nil());
- env_set(&env.clone(), s.clone(), mf.clone());
+ env_set(&env.clone(), a1.clone(), mf.clone());
return Ok(mf);
},
_ => return err_str("def! of non-symbol"),
@@ -311,8 +310,8 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
return err_str("wrong arity to catch* clause");
}
let c1 = (*cat)[1].clone();
- let bstr = match *c1 {
- Sym(ref s) => s,
+ match *c1 {
+ Sym(_) => {},
_ => return err_str("invalid catch* binding"),
};
let exc = match err {
@@ -320,7 +319,7 @@ fn eval(mut ast: MalVal, mut env: Env) -> MalRet {
ErrString(s) => string(s),
};
let bind_env = env_new(Some(env.clone()));
- env_set(&bind_env, bstr.to_string(), exc);
+ env_set(&bind_env, c1.clone(), exc);
let c2 = (*cat)[2].clone();
return eval(c2, bind_env);
},
@@ -432,9 +431,11 @@ fn rep(str: &str, env: Env) -> Result<String,MalError> {
fn main() {
// core.rs: defined using rust
let repl_env = env_new(None);
- for (k, v) in core::ns().into_iter() { env_set(&repl_env, k, v); }
+ for (k, v) in core::ns().into_iter() {
+ env_set(&repl_env, symbol(k.as_slice()), v);
+ }
// see eval() for definition of "eval"
- env_set(&repl_env, "*ARGV*".to_string(), list(vec![]));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(vec![]));
// core.mal: defined using the language itself
let _ = rep("(def! *host-language* \"rust\")", repl_env.clone());
@@ -449,7 +450,7 @@ fn main() {
let mv_args = args.slice(2,args.len()).iter()
.map(|a| string(a.to_string()))
.collect::<Vec<MalVal>>();
- env_set(&repl_env, "*ARGV*".to_string(), list(mv_args));
+ env_set(&repl_env, symbol("*ARGV*".as_slice()), list(mv_args));
let lf = "(load-file \"".to_string() + args[1] + "\")".to_string();
match rep(lf.as_slice(), repl_env.clone()) {
Ok(_) => {
diff --git a/rust/src/types.rs b/rust/src/types.rs
index 0b59716..141c3db 100644
--- a/rust/src/types.rs
+++ b/rust/src/types.rs
@@ -78,7 +78,10 @@ impl MalType {
Int(v) => res.push_str(v.to_string().as_slice()),
Sym(ref v) => res.push_str((*v).as_slice()),
Strn(ref v) => {
- if print_readably {
+ if v.as_slice().starts_with("\u029e") {
+ res.push_str(":");
+ res.push_str(v.as_slice().slice(2,v.len()))
+ } else if print_readably {
res.push_str(escape_str((*v).as_slice()).as_slice())
} else {
res.push_str(v.as_slice())
@@ -95,7 +98,10 @@ impl MalType {
res.push_str("{");
for (key, value) in v.iter() {
if first { first = false; } else { res.push_str(" "); }
- if print_readably {
+ if key.as_slice().starts_with("\u029e") {
+ res.push_str(":");
+ res.push_str(key.as_slice().slice(2,key.len()))
+ } else if print_readably {
res.push_str(escape_str(key.as_slice()).as_slice())
} else {
res.push_str(key.as_slice())
@@ -205,6 +211,17 @@ pub fn _int(i: int) -> MalVal { Rc::new(Int(i)) }
// Symbols
pub fn symbol(strn: &str) -> MalVal { Rc::new(Sym(strn.to_string())) }
+pub fn _symbol(a: Vec<MalVal>) -> MalRet {
+ if a.len() != 1 {
+ return err_str("Wrong arity to symbol call");
+ }
+ match *a[0].clone() {
+ Strn(ref s) => {
+ Ok(Rc::new(Sym(s.to_string())))
+ },
+ _ => return err_str("symbol called on non-string"),
+ }
+}
pub fn symbol_q(a:Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to symbol? call");
@@ -215,6 +232,35 @@ pub fn symbol_q(a:Vec<MalVal>) -> MalRet {
}
}
+// Keywords
+pub fn _keyword(a: Vec<MalVal>) -> MalRet {
+ if a.len() != 1 {
+ return err_str("Wrong arity to keyword call");
+ }
+ match *a[0].clone() {
+ Strn(ref s) => {
+ Ok(Rc::new(Strn("\u029e".to_string() + s.to_string())))
+ },
+ _ => return err_str("keyword called on non-string"),
+ }
+}
+pub fn keyword_q(a:Vec<MalVal>) -> MalRet {
+ if a.len() != 1 {
+ return err_str("Wrong arity to keyword? call");
+ }
+ match *a[0].clone() {
+ Strn(ref s) => {
+ if s.as_slice().starts_with("\u029e") {
+ Ok(_true())
+ } else {
+ Ok(_false())
+ }
+ },
+ _ => Ok(_false()),
+ }
+}
+
+
// Strings
pub fn strn(strn: &str) -> MalVal { Rc::new(Strn(strn.to_string())) }
pub fn string(strn: String) -> MalVal { Rc::new(Strn(strn)) }