diff --git a/kv/src/ast.rs b/kv/src/ast.rs index 7e295a9..c9c3bc4 100644 --- a/kv/src/ast.rs +++ b/kv/src/ast.rs @@ -4,6 +4,40 @@ 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 + + +#[derive(Debug, Eq, PartialEq)] +pub enum Form { + 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), +} + // todo, strings not symbols? impl From for Form { fn from(item: String) -> Self { Form::Symbol(item) } } impl From<&str> for Form { fn from(item: &str) -> Self { Form::Symbol(item.to_owned()) } } @@ -15,40 +49,63 @@ impl, B: Into> From<(A, B)> for Form { } } -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 prim_comb(&self) -> Option<(i32, PrimCombI)>; - fn deri_comb(&self) -> Option<(Rc, Option, String, Rc)>; - fn cont_comb(&self) -> Option>; - 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; +impl fmt::Display for Form { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Form::Nil => write!(f, "nil"), + Form::Int(i) => write!(f, "{i}"), + Form::Bool(b) => write!(f, "{b}"), + Form::Symbol(s) => write!(f, "{s}"), + Form::Cell(c) => write!(f, "@{}", c.borrow()), + Form::Pair(car, cdr) => { + write!(f, "({}", car)?; + let mut traverse: Rc = Rc::clone(cdr); + loop { + match &*traverse { + Form::Pair(ref carp, ref cdrp) => { + write!(f, " {}", carp)?; + traverse = Rc::clone(cdrp); + }, + Form::Nil => { + write!(f, ")")?; + return Ok(()); + }, + x => { + write!(f, ". {x})")?; + return Ok(()); + }, + } + } + }, + Form::PrimComb { eval_limit, ins } => write!(f, "<{eval_limit}> - {ins:?}"), + Form::DeriComb { se: _, de, params, body } => { + write!(f, "<{} {} {}>", de.as_ref().unwrap_or(&"".to_string()), params, body) + }, + Form::ContComb(_) => write!(f, ""), + } + } } impl FormT for Form { - fn prim_comb(&self) -> Option<(i32, PrimCombI)> { + fn call(&self, p: Rc, e: Rc, nc: Box>, metac: Cont) -> Cursor { match self { - Form::PrimComb{ eval_limit, ins } => Some((*eval_limit,*ins)), - _ => None, - } - } - fn deri_comb(&self) -> Option<(Rc, Option, String, Rc)> { - match self { - Form::DeriComb{ se, de, params, body } => Some((Rc::clone(se), de.clone(), params.clone(), Rc::clone(body))), - _ => None, - } - } - fn cont_comb(&self) -> Option> { - match self { - Form::ContComb(c) => Some(c.clone()), - _ => None, + 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 { @@ -176,9 +233,9 @@ impl FormT for Form { PrimCombI::Xor => Cursor { f: Rc::new(Form::Int(ps.car().unwrap().int().unwrap() ^ ps.cdr().unwrap().car().unwrap().int().unwrap())), c, metac }, PrimCombI::CombP => Cursor { f: Rc::new(Form::Bool(match &*ps.car().unwrap() { - Form::PrimComb { eval_limit, ins } => true, - Form::DeriComb { .. } => true, - _ => false, + Form::PrimComb { .. } => true, + Form::DeriComb { .. } => true, + _ => false, })), c, metac }, PrimCombI::CellP => Cursor { f: Rc::new(Form::Bool(match &*ps.car().unwrap() { Form::Cell(_c) => true, @@ -204,55 +261,6 @@ impl FormT for Form { } } } -impl fmt::Display for Form { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Form::Nil => write!(f, "nil"), - Form::Int(i) => write!(f, "{i}"), - Form::Bool(b) => write!(f, "{b}"), - Form::Symbol(s) => write!(f, "{s}"), - Form::Cell(c) => write!(f, "@{}", c.borrow()), - Form::Pair(car, cdr) => { - write!(f, "({}", car)?; - let mut traverse: Rc = Rc::clone(cdr); - loop { - match &*traverse { - Form::Pair(ref carp, ref cdrp) => { - write!(f, " {}", carp)?; - traverse = Rc::clone(cdrp); - }, - Form::Nil => { - write!(f, ")")?; - return Ok(()); - }, - x => { - write!(f, ". {x})")?; - return Ok(()); - }, - } - } - }, - Form::PrimComb { eval_limit, ins } => write!(f, "<{eval_limit}> - {ins:?}"), - Form::DeriComb { se, de, params, body } => { - write!(f, "<{} {} {}>", de.as_ref().unwrap_or(&"".to_string()), params, body) - }, - Form::ContComb(_) => write!(f, ""), - } - } -} - -#[derive(Debug, Eq, PartialEq)] -pub enum Form { - 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), -} //#[derive(Debug, Eq, PartialEq, Clone)] #[derive(Debug, Eq, PartialEq)] pub enum Cont { @@ -315,10 +323,8 @@ pub fn eval(e: Rc, f: Rc) -> Rc { 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); - let mut dist = 0; while s != t.car().unwrap().car().unwrap().sym().unwrap() { t = t.cdr().unwrap(); - dist += 1; } cursor = Cursor { f: t.car().unwrap().cdr().unwrap(), c: *nc, metac }; } else { @@ -326,20 +332,7 @@ pub fn eval(e: Rc, f: Rc) -> Rc { } }, Cont::Call { p, e, nc } => { - if let Some((eval_limit, ins)) = f.prim_comb() { - cursor = Cursor { f: F::nil(), c: Cont::PramEval { eval_limit, to_eval: p, collected: None, e, ins, nc: nc }, metac }; - } else if let Some((se, de, params, body)) = f.deri_comb() { - let mut new_e = se; - if let Some(de) = de { - new_e = F::assoc(&de, Rc::clone(&e), new_e); - } - new_e = F::assoc(¶ms, p, new_e); - cursor = Cursor { f: body, c: Cont::Eval { e: new_e, nc: nc }, metac }; - } else if let Some(c) = f.cont_comb() { - cursor = Cursor { f: p.car().unwrap(), c: Cont::Eval { e, nc: Box::new(c.clone()) }, metac: Cont::CatchRet { nc: nc, restore_meta: Box::new(metac) } }; - } else { - panic!("Tried to call not a Prim/DeriComb/ContComb {:?}, nc was {:?}", f, nc); - } + cursor = f.call(p, e, nc, metac); }, } } diff --git a/kv/src/main.rs b/kv/src/main.rs index a4e960d..9bb7b8e 100644 --- a/kv/src/main.rs +++ b/kv/src/main.rs @@ -5,15 +5,15 @@ use std::rc::Rc; mod ast; use crate::ast::{eval,root_env}; -//mod opt; -//use crate::opt::opt_eval; + +#[cfg(test)] mod test; fn main() { //let input = "(= 17 ((vau d p (+ (eval (car p) d) 13)) (+ 1 3)))"; //let input = "(+ 1 3)"; let input = "(= (+ 1 3) (* 2 2))"; - let parsed_input = Rc::new(grammar::TermParser::new().parse(input).unwrap()); + let parsed_input = grammar::TermParser::new().parse(input).unwrap(); //println!("Parsed input is {} - {:?}", parsed_input, parsed_input); let root = root_env(); let result = eval(Rc::clone(&root), Rc::clone(&parsed_input)); diff --git a/kv/src/test.rs b/kv/src/test.rs index 2bc6d0b..5cb4fa6 100644 --- a/kv/src/test.rs +++ b/kv/src/test.rs @@ -20,7 +20,7 @@ fn parse_test() { fn eval_test>(also_pe: bool, gram: &grammar::TermParser, e: &Rc, code: &str, expected: T) { println!("Doing test {}", code); - let parsed = Rc::new(gram.parse(code).unwrap()); + let parsed = gram.parse(code).unwrap(); let basic_result = eval(Rc::clone(e), Rc::clone(&parsed)); assert_eq!(*basic_result, expected.into()); if also_pe {