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:
parent
b12d98e4e3
commit
06fef9b518
1
.gitignore
vendored
1
.gitignore
vendored
@ -28,5 +28,6 @@ go/mal
|
||||
java/target/
|
||||
java/dependency-reduced-pom.xml
|
||||
rust/target/
|
||||
rust/mal
|
||||
rust/Cargo.lock
|
||||
rust/.cargo
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
|
@ -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 {
|
||||
|
@ -353,3 +353,8 @@ a
|
||||
(= "" [])
|
||||
;=>false
|
||||
|
||||
;; Testing vector parameter lists
|
||||
( (fn* [] 4) )
|
||||
;=>4
|
||||
( (fn* [f x] (f x)) (fn* [a] (+ 1 a)) 7)
|
||||
;=>8
|
||||
|
Loading…
Reference in New Issue
Block a user