1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-11 13:55:55 +03:00

rust: add atom support. Fix vector params.

This commit is contained in:
Joel Martin 2014-10-27 21:42:46 -05:00
parent b12d98e4e3
commit 06fef9b518
6 changed files with 96 additions and 9 deletions

1
.gitignore vendored
View File

@ -28,5 +28,6 @@ go/mal
java/target/
java/dependency-reduced-pom.xml
rust/target/
rust/mal
rust/Cargo.lock
rust/.cargo

View File

@ -5,7 +5,7 @@ use std::collections::HashMap;
use std::io::File;
use types::{MalVal,MalRet,err_val,err_str,err_string,
Nil,Int,Strn,List,Vector,Hash_Map,
Nil,Int,Strn,List,Vector,Hash_Map,Atom,
_nil,_true,_false,_int,string,list,func};
use types;
use readline;
@ -382,6 +382,59 @@ pub fn map(a:Vec<MalVal>) -> MalRet {
}
// Atom funcions
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())
},
_ => err_str("deref called on non-atom"),
}
}
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() {
Atom(ref val) => {
let mut val_cell = val.borrow_mut();
let atm_mv = val_cell.deref_mut();
*atm_mv = a1.clone();
Ok(a1)
},
_ => err_str("reset! called on non-atom"),
}
}
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() {
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),
}
},
_ => err_str("swap! called on non-atom"),
}
}
pub fn ns() -> HashMap<String,MalVal> {
let mut ns: HashMap<String,MalVal> = HashMap::new();;
@ -435,5 +488,10 @@ pub fn ns() -> HashMap<String,MalVal> {
ns.insert("apply".to_string(), func(apply));
ns.insert("map".to_string(), func(map));
ns.insert("atom".to_string(), func(types::atom));
ns.insert("deref".to_string(), func(deref));
ns.insert("reset!".to_string(), func(reset_bang));
ns.insert("swap!".to_string(), func(swap_bang));
return ns;
}

View File

@ -5,7 +5,7 @@ use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use types::{MalVal,MalRet,Sym,List,_nil,list,err_string};
use types::{MalVal,MalRet,Sym,List,Vector,_nil,list,err_string};
struct EnvType {
data: HashMap<String,MalVal>,
@ -23,9 +23,9 @@ pub fn env_bind(env: &Env,
mexprs: MalVal) -> Result<Env,String> {
let mut variadic = false;
match *mbinds {
List(ref binds) => {
List(ref binds) | Vector(ref binds) => {
match *mexprs {
List(ref exprs) => {
List(ref exprs) | Vector(ref exprs) => {
let mut it = binds.iter().enumerate();
for (i, b) in it {
match **b {

View File

@ -166,6 +166,13 @@ fn read_form(rdr : &mut Reader) -> MalRet {
Err(e) => Err(e),
}
},
"@" => {
let _ = rdr.next();
match read_form(rdr) {
Ok(f) => Ok(list(vec![symbol("deref"), f])),
Err(e) => Err(e),
}
},
")" => err_str("unexected ')'"),
"(" => read_list(rdr),

View File

@ -1,6 +1,7 @@
#![allow(dead_code)]
use std::rc::Rc;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use super::printer::{escape_str,pr_list};
@ -22,6 +23,7 @@ pub enum MalType {
//Func(fn(&[MalVal]) -> MalRet),
//Func(|Vec<MalVal>|:'a -> MalRet),
MalFunc(MalFuncData),
Atom(RefCell<MalVal>),
}
pub type MalVal = Rc<MalType>;
@ -63,6 +65,7 @@ pub struct MalFuncData {
pub env: Env,
pub params: MalVal,
pub is_macro: bool,
pub meta: MalVal,
}
impl MalType {
@ -110,9 +113,9 @@ impl MalType {
MalFunc(ref mf) => {
res.push_str(format!("(fn* {} {})", mf.params, mf.exp).as_slice())
},
/*
Atom(ref v) => v.fmt(f),
*/
Atom(ref v) => {
res = format!("(atom {})", v.borrow());
},
};
res
}
@ -299,14 +302,27 @@ pub fn func(f: fn(Vec<MalVal>) -> MalRet ) -> MalVal {
}
pub fn malfunc(eval: fn(MalVal, Env) -> MalRet,
exp: MalVal, env: Env, params: MalVal) -> MalVal {
Rc::new(MalFunc(MalFuncData{eval: eval, exp: exp, env: env,
params: params, is_macro: false}))
Rc::new(MalFunc(MalFuncData{eval: eval,
exp: exp,
env: env,
params: params,
is_macro: false,
meta: _nil()}))
}
pub fn malfuncd(mfd: MalFuncData) -> MalVal {
Rc::new(MalFunc(mfd))
}
// Atoms
pub fn atom(a:Vec<MalVal>) -> MalRet {
if a.len() != 1 {
return err_str("Wrong arity to atom call");
}
Ok(Rc::new(Atom(RefCell::new(a[0].clone()))))
}
// General functions
pub fn sequential_q(a:Vec<MalVal>) -> MalRet {
if a.len() != 1 {

View File

@ -353,3 +353,8 @@ a
(= "" [])
;=>false
;; Testing vector parameter lists
( (fn* [] 4) )
;=>4
( (fn* [f x] (f x)) (fn* [a] (+ 1 a)) 7)
;=>8