From b077daf12e4bf565547e2d59aa16ebf3e8dfa072 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 6 Jul 2023 01:11:56 -0400 Subject: [PATCH] Split eval.rs out of ast.rs, and rename ast.rs to basic.rs. Copy it over to opt.rs, and hook up a From<> impl and a congruent(x)->bool function, and add to main.rs and test.rs. Now we actually have to make opt.rs optimize... --- kv/src/{ast.rs => basic.rs} | 232 +++++++------------------------ kv/src/eval.rs | 141 +++++++++++++++++++ kv/src/grammar.lalrpop | 3 +- kv/src/main.rs | 16 ++- kv/src/opt.rs | 267 ++++++++++++++++++++++++++++++++++++ kv/src/test.rs | 15 +- 6 files changed, 479 insertions(+), 195 deletions(-) rename kv/src/{ast.rs => basic.rs} (70%) create mode 100644 kv/src/eval.rs create mode 100644 kv/src/opt.rs diff --git a/kv/src/ast.rs b/kv/src/basic.rs similarity index 70% rename from kv/src/ast.rs rename to kv/src/basic.rs index c9c3bc4..0f6bf18 100644 --- a/kv/src/ast.rs +++ b/kv/src/basic.rs @@ -4,26 +4,7 @@ use std::rc::Rc; use std::cell::RefCell; use std::convert::From; -pub trait FormT: std::fmt::Debug { - fn nil() -> Rc; - fn truthy(&self) -> bool; - fn int(&self) -> Option; - fn sym(&self) -> Option<&str>; - fn pair(&self) -> Option<(Rc,Rc)>; - fn car(&self) -> Option>; - fn cdr(&self) -> Option>; - fn call(&self, p: Rc, e: Rc, nc: Box>, metac: Cont) -> Cursor; - fn is_nil(&self) -> bool; - fn append(&self, x: Rc) -> Option>; - fn assoc(k: &str, v: Rc, l: Rc) -> Rc; - fn impl_prim(ins: PrimCombI, e: Rc, ps: Rc, c: Cont, metac: Cont) -> Cursor; -} - -// Idea: -// Call of DeriComb starts a trace -// Every form wrapped -// wrapped contains value for this run as well as reference? into trace for code version - +use crate::eval::{FormT,Cont,Cursor,PrimCombI}; #[derive(Debug, Eq, PartialEq)] pub enum Form { @@ -87,27 +68,6 @@ impl fmt::Display for Form { } impl FormT for Form { - fn call(&self, p: Rc, e: Rc, nc: Box>, metac: Cont) -> Cursor { - match self { - Form::PrimComb{eval_limit, ins} => { - Cursor { f: Self::nil(), c: Cont::PramEval { eval_limit: *eval_limit, to_eval: p, collected: None, e, ins: *ins, nc: nc }, metac } - } - Form::DeriComb {se, de, params, body} => { - let mut new_e = Rc::clone(se); - if let Some(de) = de { - new_e = Self::assoc(&de, Rc::clone(&e), new_e); - } - new_e = Self::assoc(¶ms, p, new_e); - Cursor { f: Rc::clone(body), c: Cont::Eval { e: new_e, nc: nc }, metac } - } - Form::ContComb(c) => { - Cursor { f: p.car().unwrap(), c: Cont::Eval { e, nc: Box::new(c.clone()) }, metac: Cont::CatchRet { nc: nc, restore_meta: Box::new(metac) } } - } - _ => { - panic!("Tried to call not a Prim/DeriComb/ContComb {:?}, nc was {:?}", self, nc); - } - } - } fn nil() -> Rc { Rc::new(Form::Nil) } @@ -161,14 +121,28 @@ impl FormT for Form { _ => None, } } - fn assoc(k: &str, v: Rc
, l: Rc) -> Rc { - Rc::new(Form::Pair( - Rc::new(Form::Pair( - Rc::new(Form::Symbol(k.to_owned())), - v)), - l)) + fn call(&self, p: Rc, e: Rc, nc: Box>, metac: Cont) -> Cursor { + match self { + Form::PrimComb{eval_limit, ins} => { + Cursor { f: Self::nil(), c: Cont::PramEval { eval_limit: *eval_limit, to_eval: p, collected: None, e, ins: *ins, nc: nc }, metac } + } + Form::DeriComb {se, de, params, body} => { + let mut new_e = Rc::clone(se); + if let Some(de) = de { + new_e = assoc(&de, Rc::clone(&e), new_e); + } + new_e = assoc(¶ms, p, new_e); + Cursor { f: Rc::clone(body), c: Cont::Eval { e: new_e, nc: nc }, metac } + } + Form::ContComb(c) => { + Cursor { f: p.car().unwrap(), c: Cont::Eval { e, nc: Box::new(c.clone()) }, metac: Cont::CatchRet { nc: nc, restore_meta: Box::new(metac) } } + } + _ => { + panic!("Tried to call not a Prim/DeriComb/ContComb {:?}, nc was {:?}", self, nc); + } + } } - fn impl_prim(ins: PrimCombI, e: Rc, ps: Rc, c: Cont, metac: Cont) -> Cursor { + fn impl_prim(ins: PrimCombI, e: Rc, ps: Rc, c: Cont, metac: Cont) -> Cursor { match ins { PrimCombI::Eval => Cursor { f: ps.car().unwrap(), c: Cont::Eval { e: ps.cdr().unwrap().car().unwrap(), nc: Box::new(c) }, metac }, PrimCombI::Vau => { @@ -176,7 +150,7 @@ impl FormT for Form { let params = ps.cdr().unwrap().car().unwrap().sym().unwrap().to_owned(); let body = ps.cdr().unwrap().cdr().unwrap().car().unwrap(); - Cursor { f: Rc::new(Form::DeriComb { se: e, de, params, body }), c: c, metac: metac } + Cursor { f: Rc::new(Form::DeriComb { se: e, de, params, body }), c, metac } }, PrimCombI::If => if ps.car().unwrap().truthy() { Cursor { f: ps.cdr().unwrap().car().unwrap(), c: Cont::Eval { e: e, nc: Box::new(c) }, metac } @@ -193,21 +167,6 @@ impl FormT for Form { e: e, nc: Box::new(Cont::MetaRet) }, metac: Cont::CatchRet { nc: Box::new(metac.clone()), restore_meta: Box::new(metac) } }, - - PrimCombI::Cell => Cursor { f: Rc::new(Form::Cell(RefCell::new(ps.car().unwrap()))), c, metac }, - PrimCombI::Set => match &*ps.car().unwrap() { - Form::Cell(cell) => Cursor { f: cell.replace(ps.cdr().unwrap().car().unwrap()), c: c, metac }, - _ => panic!("set on not cell"), - }, - PrimCombI::Get => match &*ps.car().unwrap() { - Form::Cell(cell) => Cursor { f: Rc::clone(&cell.borrow()), c: c, metac }, - _ => panic!("get on not cell"), - }, - - PrimCombI::Cons => Cursor { f: Rc::new(Form::Pair(ps.car().unwrap(), ps.cdr().unwrap().car().unwrap())), c: c, metac }, - PrimCombI::Car => Cursor { f: ps.car().unwrap().car().unwrap(), c: c, metac }, - PrimCombI::Cdr => Cursor { f: ps.car().unwrap().cdr().unwrap(), c: c, metac }, - PrimCombI::Quote => Cursor { f: ps.car().unwrap(), c: c, metac: metac }, PrimCombI::Assert => { let thing = ps.car().unwrap(); if !thing.truthy() { @@ -217,7 +176,22 @@ impl FormT for Form { Cursor { f: ps.cdr().unwrap().car().unwrap(), c: Cont::Eval { e: e, nc: Box::new(c) }, metac } }, - PrimCombI::Eq => Cursor { f: Rc::new(Form::Bool(ps.car().unwrap() == ps.cdr().unwrap().car().unwrap())), c, metac }, + PrimCombI::Cell => Cursor { f: Rc::new(Form::Cell(RefCell::new(ps.car().unwrap()))), c, metac }, + PrimCombI::Set => match &*ps.car().unwrap() { + Form::Cell(cell) => Cursor { f: cell.replace(ps.cdr().unwrap().car().unwrap()), c, metac }, + _ => panic!("set on not cell"), + }, + PrimCombI::Get => match &*ps.car().unwrap() { + Form::Cell(cell) => Cursor { f: Rc::clone(&cell.borrow()), c, metac }, + _ => panic!("get on not cell"), + }, + + PrimCombI::Cons => Cursor { f: Rc::new(Form::Pair(ps.car().unwrap(), ps.cdr().unwrap().car().unwrap())), c, metac }, + PrimCombI::Car => Cursor { f: ps.car().unwrap().car().unwrap(), c, metac }, + PrimCombI::Cdr => Cursor { f: ps.car().unwrap().cdr().unwrap(), c, metac }, + PrimCombI::Quote => Cursor { f: ps.car().unwrap(), c, metac }, + + PrimCombI::Eq => Cursor { f: Rc::new(Form::Bool(ps.car().unwrap() == ps.cdr().unwrap().car().unwrap())), c, metac }, PrimCombI::Lt => Cursor { f: Rc::new(Form::Bool(ps.car().unwrap().int().unwrap() < ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, PrimCombI::LEq => Cursor { f: Rc::new(Form::Bool(ps.car().unwrap().int().unwrap() <= ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, PrimCombI::Gt => Cursor { f: Rc::new(Form::Bool(ps.car().unwrap().int().unwrap() > ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, @@ -261,136 +235,22 @@ impl FormT for Form { } } } -//#[derive(Debug, Eq, PartialEq, Clone)] -#[derive(Debug, Eq, PartialEq)] -pub enum Cont { - Exit, - MetaRet, - CatchRet { nc: Box>, restore_meta: Box> }, - Eval { e: Rc, nc: Box> }, - Call { p: Rc, e: Rc, nc: Box> }, - PramEval { eval_limit: i32, to_eval: Rc, collected: Option>, e: Rc, ins: PrimCombI, nc: Box> }, -} -impl Clone for Cont { - fn clone(&self) -> Self { - match self { - Cont::Exit => Cont::Exit, - Cont::MetaRet => Cont::MetaRet, - Cont::CatchRet { nc, restore_meta } => Cont::CatchRet { nc: nc.clone(), restore_meta: restore_meta.clone() }, - Cont::Eval { e, nc } => Cont::Eval { e: Rc::clone(e), nc: nc.clone() }, - Cont::Call { p, e, nc } => Cont::Call { p: Rc::clone(p), e: Rc::clone(e), nc: nc.clone() }, - Cont::PramEval { eval_limit, to_eval, collected, e, ins, nc} => Cont::PramEval { eval_limit: *eval_limit, to_eval: Rc::clone(to_eval), collected: collected.as_ref().map(|x| Rc::clone(x)), e: Rc::clone(e), ins: ins.clone(), nc: nc.clone() }, - } - } -} -pub struct Cursor { f: Rc, c: Cont, metac: Cont } -pub fn eval(e: Rc, f: Rc) -> Rc { - let mut cursor = Cursor:: { f, c: Cont::Eval { e, nc: Box::new(Cont::MetaRet) }, metac: Cont::Exit }; - loop { - let Cursor { f, c, metac } = cursor; - match c { - Cont::Exit => { - return f; - }, - Cont::MetaRet => { - cursor = Cursor { f: f, c: metac.clone(), metac: metac }; - }, - Cont::CatchRet { nc, restore_meta } => { - cursor = Cursor { f: f, c: *nc, metac: *restore_meta }; - }, - Cont::PramEval { eval_limit, to_eval, collected, e, ins, nc } => { - let next_collected = if let Some(collected) = collected { - collected.append(f).unwrap() - } else { F::nil() }; - if eval_limit == 0 || to_eval.is_nil() { - let mut traverse = to_eval; - let mut next_collected = next_collected; - while !traverse.is_nil() { - next_collected = next_collected.append(traverse.car().unwrap()).unwrap(); - traverse = traverse.cdr().unwrap(); - } - cursor = F::impl_prim(ins, e, next_collected, *nc, metac); - } else { - cursor = Cursor { f: to_eval.car().unwrap(), c: Cont::Eval { e: Rc::clone(&e), nc: Box::new(Cont::PramEval { eval_limit: eval_limit - 1, - to_eval: to_eval.cdr().unwrap(), - collected: Some(next_collected), - e, ins, nc }) }, metac }; - } - }, - Cont::Eval { e, nc } => { - if let Some((comb, p)) = f.pair() { - cursor = Cursor { f: comb, c: Cont::Eval { e: Rc::clone(&e), nc: Box::new(Cont::Call { p, e, nc }) }, metac } - } else if let Some(s) = f.sym() { - let mut t = Rc::clone(&e); - while s != t.car().unwrap().car().unwrap().sym().unwrap() { - t = t.cdr().unwrap(); - } - cursor = Cursor { f: t.car().unwrap().cdr().unwrap(), c: *nc, metac }; - } else { - cursor = Cursor { f: Rc::clone(&f), c: *nc, metac }; - } - }, - Cont::Call { p, e, nc } => { - cursor = f.call(p, e, nc, metac); - }, - } - } +fn assoc(k: &str, v: Rc, l: Rc) -> Rc { + Rc::new(Form::Pair( + Rc::new(Form::Pair( + Rc::new(Form::Symbol(k.to_owned())), + v)), + l)) } - pub fn assoc_vec(kvs: Vec<(&str, Rc)>) -> Rc { let mut to_ret = Rc::new(Form::Nil); for (k, v) in kvs { - to_ret = Form::assoc(k, v, to_ret); + to_ret = assoc(k, v, to_ret); } to_ret } -#[derive(Debug, Eq, PartialEq, Clone, Copy)] -pub enum PrimCombI { - Eval, - Vau, - If, - - Reset, - Shift, - - Cell, - Set, - Get, - - Cons, - Car, - Cdr, - Quote, - Assert, - - Eq, - Lt, - LEq, - Gt, - GEq, - - Plus, - Minus, - Mult, - Div, - Mod, - And, - Or, - Xor, - - CombP, - CellP, - PairP, - SymbolP, - IntP, - BoolP, - NilP, -} - - - // Have eval?/maybe Cont?/maybe Cursor? parameterized on value type? // Parameterized on prim implementation? // Should opt impl use same prim implementation but trace values through accessors/constructors? diff --git a/kv/src/eval.rs b/kv/src/eval.rs new file mode 100644 index 0000000..b7f71b1 --- /dev/null +++ b/kv/src/eval.rs @@ -0,0 +1,141 @@ +use std::fmt; +use std::boxed::Box; +use std::rc::Rc; +use std::cell::RefCell; +use std::convert::From; + +pub trait FormT: std::fmt::Debug { + fn nil() -> Rc; + fn truthy(&self) -> bool; + fn int(&self) -> Option; + fn sym(&self) -> Option<&str>; + fn pair(&self) -> Option<(Rc,Rc)>; + fn car(&self) -> Option>; + fn cdr(&self) -> Option>; + fn call(&self, p: Rc, e: Rc, nc: Box>, metac: Cont) -> Cursor; + fn is_nil(&self) -> bool; + fn append(&self, x: Rc) -> Option>; + fn impl_prim(ins: PrimCombI, e: Rc, ps: Rc, c: Cont, metac: Cont) -> Cursor; +} + +#[derive(Debug, Eq, PartialEq)] +pub enum Cont { + Exit, + MetaRet, + CatchRet { nc: Box>, restore_meta: Box> }, + Eval { e: Rc, nc: Box> }, + Call { p: Rc, e: Rc, nc: Box> }, + PramEval { eval_limit: i32, to_eval: Rc, collected: Option>, e: Rc, ins: PrimCombI, nc: Box> }, +} +impl Clone for Cont { + fn clone(&self) -> Self { + match self { + Cont::Exit => Cont::Exit, + Cont::MetaRet => Cont::MetaRet, + Cont::CatchRet { nc, restore_meta } => Cont::CatchRet { nc: nc.clone(), restore_meta: restore_meta.clone() }, + Cont::Eval { e, nc } => Cont::Eval { e: Rc::clone(e), nc: nc.clone() }, + Cont::Call { p, e, nc } => Cont::Call { p: Rc::clone(p), e: Rc::clone(e), nc: nc.clone() }, + Cont::PramEval { eval_limit, to_eval, collected, e, ins, nc} => Cont::PramEval { eval_limit: *eval_limit, to_eval: Rc::clone(to_eval), + collected: collected.as_ref().map(|x| Rc::clone(x)), + e: Rc::clone(e), ins: ins.clone(), nc: nc.clone() }, + } + } +} +pub struct Cursor { pub f: Rc, pub c: Cont, pub metac: Cont } + +pub fn eval(e: Rc, f: Rc) -> Rc { + let mut cursor = Cursor:: { f, c: Cont::Eval { e, nc: Box::new(Cont::MetaRet) }, metac: Cont::Exit }; + loop { + let Cursor { f, c, metac } = cursor; + match c { + Cont::Exit => { + return f; + }, + Cont::MetaRet => { + cursor = Cursor { f: f, c: metac.clone(), metac: metac }; + }, + Cont::CatchRet { nc, restore_meta } => { + cursor = Cursor { f: f, c: *nc, metac: *restore_meta }; + }, + Cont::Eval { e, nc } => { + if let Some((comb, p)) = f.pair() { + cursor = Cursor { f: comb, c: Cont::Eval { e: Rc::clone(&e), nc: Box::new(Cont::Call { p, e, nc }) }, metac } + } else if let Some(s) = f.sym() { + let mut t = Rc::clone(&e); + while s != t.car().unwrap().car().unwrap().sym().unwrap() { + t = t.cdr().unwrap(); + } + cursor = Cursor { f: t.car().unwrap().cdr().unwrap(), c: *nc, metac }; + } else { + cursor = Cursor { f: Rc::clone(&f), c: *nc, metac }; + } + }, + Cont::PramEval { eval_limit, to_eval, collected, e, ins, nc } => { + let next_collected = if let Some(collected) = collected { + collected.append(f).unwrap() + } else { F::nil() }; + if eval_limit == 0 || to_eval.is_nil() { + let mut traverse = to_eval; + let mut next_collected = next_collected; + while !traverse.is_nil() { + next_collected = next_collected.append(traverse.car().unwrap()).unwrap(); + traverse = traverse.cdr().unwrap(); + } + cursor = F::impl_prim(ins, e, next_collected, *nc, metac); + } else { + cursor = Cursor { f: to_eval.car().unwrap(), c: Cont::Eval { e: Rc::clone(&e), nc: Box::new(Cont::PramEval { eval_limit: eval_limit - 1, + to_eval: to_eval.cdr().unwrap(), + collected: Some(next_collected), + e, ins, nc }) }, metac }; + } + }, + Cont::Call { p, e, nc } => { + cursor = f.call(p, e, nc, metac); + }, + } + } +} + +#[derive(Debug, Eq, PartialEq, Clone, Copy)] +pub enum PrimCombI { + Eval, + Vau, + If, + + Reset, + Shift, + + Cell, + Set, + Get, + + Cons, + Car, + Cdr, + Quote, + Assert, + + Eq, + Lt, + LEq, + Gt, + GEq, + + Plus, + Minus, + Mult, + Div, + Mod, + And, + Or, + Xor, + + CombP, + CellP, + PairP, + SymbolP, + IntP, + BoolP, + NilP, +} + diff --git a/kv/src/grammar.lalrpop b/kv/src/grammar.lalrpop index ea425d8..1e0c12d 100644 --- a/kv/src/grammar.lalrpop +++ b/kv/src/grammar.lalrpop @@ -1,6 +1,7 @@ use std::str::FromStr; use std::rc::Rc; -use crate::ast::{Form,FormT}; +use crate::basic::Form; +use crate::eval::FormT; grammar; diff --git a/kv/src/main.rs b/kv/src/main.rs index 9bb7b8e..e97901e 100644 --- a/kv/src/main.rs +++ b/kv/src/main.rs @@ -3,8 +3,12 @@ lalrpop_mod!(pub grammar); use std::rc::Rc; -mod ast; -use crate::ast::{eval,root_env}; +mod basic; +use crate::basic::{root_env,Form}; +mod eval; +use crate::eval::{eval}; +mod opt; +use crate::opt::{OptForm}; #[cfg(test)] mod test; @@ -17,9 +21,11 @@ fn main() { //println!("Parsed input is {} - {:?}", parsed_input, parsed_input); let root = root_env(); let result = eval(Rc::clone(&root), Rc::clone(&parsed_input)); - //let opt_result = opt_eval(root, parsed_input); + let opt_root: Rc = (&*root).into(); + let opt_input: Rc = (&*parsed_input).into(); + let opt_result = eval(opt_root, opt_input); println!("Result is {} - {:?}", result, result); - //println!("Opt Result is {} - {:?}", opt_result, opt_result); - //assert!(opt_result.congruent(result)); + println!("Opt Result is {} - {:?}", opt_result, opt_result); + assert!(opt_result.congruent(&*result)); } diff --git a/kv/src/opt.rs b/kv/src/opt.rs new file mode 100644 index 0000000..32b4e54 --- /dev/null +++ b/kv/src/opt.rs @@ -0,0 +1,267 @@ +use std::fmt; +use std::boxed::Box; +use std::rc::Rc; +use std::cell::RefCell; +use std::convert::From; + +use crate::eval::{FormT,Cont,Cursor,PrimCombI}; +use crate::basic::Form; + +#[derive(Debug, Eq, PartialEq)] +pub enum OptForm { + Nil, + Int(i32), + Bool(bool), + Symbol(String), + Cell(RefCell>), + Pair(Rc,Rc), + PrimComb { eval_limit: i32, ins: PrimCombI }, + DeriComb { se: Rc, de: Option, params: String, body: Rc }, + ContComb(Cont), +} + +impl fmt::Display for OptForm { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + OptForm::Nil => write!(f, "nil"), + OptForm::Int(i) => write!(f, "{i}"), + OptForm::Bool(b) => write!(f, "{b}"), + OptForm::Symbol(s) => write!(f, "{s}"), + OptForm::Cell(c) => write!(f, "@{}", c.borrow()), + OptForm::Pair(car, cdr) => { + write!(f, "({}", car)?; + let mut traverse: Rc = Rc::clone(cdr); + loop { + match &*traverse { + OptForm::Pair(ref carp, ref cdrp) => { + write!(f, " {}", carp)?; + traverse = Rc::clone(cdrp); + }, + OptForm::Nil => { + write!(f, ")")?; + return Ok(()); + }, + x => { + write!(f, ". {x})")?; + return Ok(()); + }, + } + } + }, + OptForm::PrimComb { eval_limit, ins } => write!(f, "<{eval_limit}> - {ins:?}"), + OptForm::DeriComb { se: _, de, params, body } => { + write!(f, "<{} {} {}>", de.as_ref().unwrap_or(&"".to_string()), params, body) + }, + OptForm::ContComb(_) => write!(f, ""), + } + } +} + +impl From<&Form> for Rc { + fn from(x: &Form) -> Self { + Rc::new(match x { + Form::Nil => OptForm::Nil, + Form::Int(i) => OptForm::Int(*i), + Form::Bool(b) => OptForm::Bool(*b), + Form::Symbol(s) => OptForm::Symbol(s.to_owned()), + Form::Cell(cell) => panic!("bad"), + Form::Pair(car,cdr) => OptForm::Pair((&**car).into(), (&**cdr).into()), + Form::PrimComb { eval_limit, ins } => OptForm::PrimComb { eval_limit: *eval_limit, ins: *ins }, + Form::DeriComb { .. } => panic!("bad"), + Form::ContComb(c) => panic!("bad"), + }) + } +} + +impl OptForm { + pub fn congruent(&self, other: &Form) -> bool { + match other { + Form::Nil => *self == OptForm::Nil, + Form::Int(i) => *self == OptForm::Int(*i), + Form::Bool(b) => *self == OptForm::Bool(*b), + Form::Symbol(s) => *self == OptForm::Symbol(s.to_owned()), + Form::Cell(cell) => panic!("bad"), + Form::Pair(car,cdr) => match self { OptForm::Pair(carp, cdrp) => carp.congruent(car) && cdrp.congruent(cdr), _ => false }, + Form::PrimComb { eval_limit, ins } => *self == OptForm::PrimComb { eval_limit: *eval_limit, ins: *ins }, + Form::DeriComb { .. } => panic!("bad"), + Form::ContComb(c) => panic!("bad"), + } + } +} + +impl FormT for OptForm { + fn nil() -> Rc { + Rc::new(OptForm::Nil) + } + fn truthy(&self) -> bool { + match self { + OptForm::Bool(b) => *b, + OptForm::Nil => false, + _ => true, + } + } + fn int(&self) -> Option { + match self { + OptForm::Int(i) => Some(*i), + _ => None, + } + } + fn sym(&self) -> Option<&str> { + match self { + OptForm::Symbol(s) => Some(s), + _ => None, + } + } + fn pair(&self) -> Option<(Rc,Rc)> { + match self { + OptForm::Pair(car, cdr) => Some((Rc::clone(car),Rc::clone(cdr))), + _ => None, + } + } + fn car(&self) -> Option> { + match self { + OptForm::Pair(car, _cdr) => Some(Rc::clone(car)), + _ => None, + } + } + fn cdr(&self) -> Option> { + match self { + OptForm::Pair(_car, cdr) => Some(Rc::clone(cdr)), + _ => None, + } + } + fn is_nil(&self) -> bool { + match self { + OptForm::Nil => true, + _ => false, + } + } + fn append(&self, x: Rc) -> Option> { + match self { + OptForm::Pair(car, cdr) => cdr.append(x).map(|x| Rc::new(OptForm::Pair(Rc::clone(car), x))), + OptForm::Nil => Some(Rc::new(OptForm::Pair(x, Rc::new(OptForm::Nil)))), + _ => None, + } + } + fn call(&self, p: Rc, e: Rc, nc: Box>, metac: Cont) -> Cursor { + match self { + OptForm::PrimComb{eval_limit, ins} => { + Cursor { f: Self::nil(), c: Cont::PramEval { eval_limit: *eval_limit, to_eval: p, collected: None, e, ins: *ins, nc: nc }, metac } + } + OptForm::DeriComb {se, de, params, body} => { + let mut new_e = Rc::clone(se); + if let Some(de) = de { + new_e = assoc(&de, Rc::clone(&e), new_e); + } + new_e = assoc(¶ms, p, new_e); + Cursor { f: Rc::clone(body), c: Cont::Eval { e: new_e, nc: nc }, metac } + } + OptForm::ContComb(c) => { + Cursor { f: p.car().unwrap(), c: Cont::Eval { e, nc: Box::new(c.clone()) }, metac: Cont::CatchRet { nc: nc, restore_meta: Box::new(metac) } } + } + _ => { + panic!("Tried to call not a Prim/DeriComb/ContComb {:?}, nc was {:?}", self, nc); + } + } + } + fn impl_prim(ins: PrimCombI, e: Rc, ps: Rc, c: Cont, metac: Cont) -> Cursor { + match ins { + PrimCombI::Eval => Cursor { f: ps.car().unwrap(), c: Cont::Eval { e: ps.cdr().unwrap().car().unwrap(), nc: Box::new(c) }, metac }, + PrimCombI::Vau => { + let de = ps.car().unwrap().sym().map(|s| s.to_owned()); + let params = ps.cdr().unwrap().car().unwrap().sym().unwrap().to_owned(); + let body = ps.cdr().unwrap().cdr().unwrap().car().unwrap(); + + Cursor { f: Rc::new(OptForm::DeriComb { se: e, de, params, body }), c, metac } + }, + PrimCombI::If => if ps.car().unwrap().truthy() { + Cursor { f: ps.cdr().unwrap().car().unwrap(), c: Cont::Eval { e: e, nc: Box::new(c) }, metac } + } else { + Cursor { f: ps.cdr().unwrap().cdr().unwrap().car().unwrap(), c: Cont::Eval { e: e, nc: Box::new(c) }, metac } + }, + + PrimCombI::Reset => Cursor { f: ps.car().unwrap(), + c: Cont::Eval { e: e, nc: Box::new(Cont::MetaRet) }, + metac: Cont::CatchRet { nc: Box::new(c), restore_meta: Box::new(metac) } }, + PrimCombI::Shift => Cursor { f: ps.car().unwrap(), + c: Cont::Call { p: Rc::new(OptForm::Pair(Rc::new(OptForm::ContComb(c)), + Rc::new(OptForm::Nil))), + e: e, + nc: Box::new(Cont::MetaRet) }, + metac: Cont::CatchRet { nc: Box::new(metac.clone()), restore_meta: Box::new(metac) } }, + PrimCombI::Assert => { + let thing = ps.car().unwrap(); + if !thing.truthy() { + println!("Assert failed: {:?}", thing); + } + assert!(thing.truthy()); + Cursor { f: ps.cdr().unwrap().car().unwrap(), c: Cont::Eval { e: e, nc: Box::new(c) }, metac } + }, + + PrimCombI::Cell => Cursor { f: Rc::new(OptForm::Cell(RefCell::new(ps.car().unwrap()))), c, metac }, + PrimCombI::Set => match &*ps.car().unwrap() { + OptForm::Cell(cell) => Cursor { f: cell.replace(ps.cdr().unwrap().car().unwrap()), c, metac }, + _ => panic!("set on not cell"), + }, + PrimCombI::Get => match &*ps.car().unwrap() { + OptForm::Cell(cell) => Cursor { f: Rc::clone(&cell.borrow()), c, metac }, + _ => panic!("get on not cell"), + }, + + PrimCombI::Cons => Cursor { f: Rc::new(OptForm::Pair(ps.car().unwrap(), ps.cdr().unwrap().car().unwrap())), c, metac }, + PrimCombI::Car => Cursor { f: ps.car().unwrap().car().unwrap(), c, metac }, + PrimCombI::Cdr => Cursor { f: ps.car().unwrap().cdr().unwrap(), c, metac }, + PrimCombI::Quote => Cursor { f: ps.car().unwrap(), c, metac }, + + PrimCombI::Eq => Cursor { f: Rc::new(OptForm::Bool(ps.car().unwrap() == ps.cdr().unwrap().car().unwrap())), c, metac }, + PrimCombI::Lt => Cursor { f: Rc::new(OptForm::Bool(ps.car().unwrap().int().unwrap() < ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::LEq => Cursor { f: Rc::new(OptForm::Bool(ps.car().unwrap().int().unwrap() <= ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::Gt => Cursor { f: Rc::new(OptForm::Bool(ps.car().unwrap().int().unwrap() > ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::GEq => Cursor { f: Rc::new(OptForm::Bool(ps.car().unwrap().int().unwrap() >= ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + + PrimCombI::Plus => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() + ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::Minus => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() - ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::Mult => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() * ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::Div => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() / ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::Mod => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() % ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::And => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() & ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::Or => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() | ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + PrimCombI::Xor => Cursor { f: Rc::new(OptForm::Int(ps.car().unwrap().int().unwrap() ^ ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, + + PrimCombI::CombP => Cursor { f: Rc::new(OptForm::Bool(match &*ps.car().unwrap() { + OptForm::PrimComb { .. } => true, + OptForm::DeriComb { .. } => true, + _ => false, + })), c, metac }, + PrimCombI::CellP => Cursor { f: Rc::new(OptForm::Bool(match &*ps.car().unwrap() { + OptForm::Cell(_c) => true, + _ => false, + })), c, metac }, + PrimCombI::PairP => Cursor { f: Rc::new(OptForm::Bool(match &*ps.car().unwrap() { + OptForm::Pair(_a,_b) => true, + _ => false, + })), c, metac }, + PrimCombI::SymbolP => Cursor { f: Rc::new(OptForm::Bool(match &*ps.car().unwrap() { + OptForm::Symbol(_) => true, + _ => false, + })), c, metac }, + PrimCombI::IntP => Cursor { f: Rc::new(OptForm::Bool(match &*ps.car().unwrap() { + OptForm::Int(_) => true, + _ => false, + })), c, metac }, + PrimCombI::BoolP => Cursor { f: Rc::new(OptForm::Bool(match &*ps.car().unwrap() { + OptForm::Bool(_) => true, + _ => false, + })), c, metac }, + PrimCombI::NilP => Cursor { f: Rc::new(OptForm::Bool(ps.car().unwrap().is_nil())), c, metac }, + } + } +} + +fn assoc(k: &str, v: Rc, l: Rc) -> Rc { + Rc::new(OptForm::Pair( + Rc::new(OptForm::Pair( + Rc::new(OptForm::Symbol(k.to_owned())), + v)), + l)) +} diff --git a/kv/src/test.rs b/kv/src/test.rs index 5cb4fa6..6a5bdc4 100644 --- a/kv/src/test.rs +++ b/kv/src/test.rs @@ -1,7 +1,9 @@ use std::rc::Rc; use crate::grammar; -use crate::ast::{eval,root_env,Form}; +use crate::basic::{root_env,Form}; +use crate::opt::{OptForm}; +use crate::eval::{eval}; #[test] fn parse_test() { @@ -23,8 +25,15 @@ fn eval_test>(also_pe: bool, gram: &grammar::TermParser, e: &Rc = (&**e).into(); + let opt_input: Rc = (&*parsed).into(); + let opt_result = eval(opt_root, opt_input); + assert!(opt_result.congruent(&*basic_result)); + + + //if also_pe { + //} } #[test]