diff --git a/kr/src/ast.rs b/kr/src/ast.rs index e0bec78..aa56977 100644 --- a/kr/src/ast.rs +++ b/kr/src/ast.rs @@ -105,11 +105,14 @@ impl fmt::Display for Form { } } +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub struct EnvID(i32); + #[derive(Debug, Clone, Eq, PartialEq)] pub enum NeededIds { True, None, - Some(BTreeSet), + Some(BTreeSet), } impl NeededIds { fn union(&self, other: &NeededIds) -> Self { @@ -128,38 +131,70 @@ pub enum PossibleMarkedTailCall { Result(Rc), TailCall(Rc, Rc), } +pub struct Ctx { + e : Rc, +} +impl Default for Ctx { + fn default() -> Ctx { + Ctx { e: Rc::new(MarkedForm::Value(root_env())) } + } +} +pub fn partial_eval(ctx: Ctx, x: Rc) -> Result<(Ctx,Rc), String> { + //Err("Not implemented".into()) + match &*x { + MarkedForm::SuspendedSymbol { name, crdi_carb } => { + // (EnvID, i32, bool) + if let Some((id, idx, rest)) = crdi_carb { + // lookup in stack + Ok((ctx, x)) + } else { + // lookup in current env, replace with value (might be it's own SuspendedSymbol - maybe path should be split out?) + Ok((ctx, x)) + } + }, + MarkedForm::SuspendedPair(ids, car, cdr) => { + let (ctx, car) = partial_eval(ctx, Rc::clone(car))?; + let (ctx, cdr) = partial_eval(ctx, Rc::clone(cdr))?; + // update IDs + Ok((ctx, Rc::new(MarkedForm::SuspendedPair(ids.clone(), car, cdr)))) + }, + MarkedForm::PrimComb { .. } => Ok((ctx, x)), + MarkedForm::DeriComb { .. } => Ok((ctx, x)), + MarkedForm::Value(form) => Ok((ctx, x)), + } +} #[derive(Debug, Clone, Eq, PartialEq)] pub enum MarkedForm { Value(Rc
), - SuspendedSymbol { ids: NeededIds, name: String, crdi_carb: Option<(i32, bool)> }, + SuspendedSymbol { name: String, crdi_carb: Option<(EnvID, i32, bool)> }, SuspendedPair(NeededIds, Rc, Rc), PrimComb { name: String, wrap_level: i32, f: fn(Rc, Rc) -> PossibleMarkedTailCall }, - DeriComb { ids: NeededIds, se: Rc, de: Option, id: i32, wrap_level: i32, sequence_params: Vec, rest_params: Option, body: Rc }, + DeriComb { ids: NeededIds, se: Rc, de: Option, id: EnvID, wrap_level: i32, sequence_params: Vec, rest_params: Option, body: Rc }, } impl MarkedForm { pub fn unval(self: &Rc) -> Result, &'static str> { match &**self { MarkedForm::Value(form) => { match &**form { - Form::Nil => Ok(Rc::clone(self)), - Form::Int(i)=> Ok(Rc::clone(self)), - Form::Bool(b)=> Ok(Rc::clone(self)), - Form::PrimComb(n, f)=> Err("tried to unval a PrimComb that was the simpler version, need to figure this out"), - Form::DeriComb { se, de, params, body }=> Ok(Rc::clone(self)), + Form::Nil => Ok(Rc::clone(self)), + Form::Int(i) => Ok(Rc::clone(self)), + Form::Bool(b) => Ok(Rc::clone(self)), + Form::PrimComb(n, f) => Err("tried to unval a PrimComb that was the simpler version, need to figure this out"), + Form::DeriComb { .. }=> Ok(Rc::clone(self)), - Form::Symbol(s) => Ok(Rc::new(MarkedForm::SuspendedSymbol { ids: NeededIds::True, name: s.clone(), crdi_carb: None })), - Form::Pair(car,cdr) => Ok(Rc::new(MarkedForm::SuspendedPair( NeededIds::True, + Form::Symbol(s) => Ok(Rc::new(MarkedForm::SuspendedSymbol { name: s.clone(), crdi_carb: None })), + Form::Pair(car,cdr) => Ok(Rc::new(MarkedForm::SuspendedPair(NeededIds::True, Rc::new(MarkedForm::Value(Rc::clone(car))).unval()?, Rc::new(MarkedForm::Value(Rc::clone(cdr))).unval()? ))), } }, - MarkedForm::SuspendedSymbol { ids, name, crdi_carb } => Err("trying to unval a suspended symbol"), + MarkedForm::SuspendedSymbol { .. } => Err("trying to unval a suspended symbol"), MarkedForm::SuspendedPair(ids, car, cdr) => Err("trying to unval a suspended pair"), - MarkedForm::PrimComb { name, wrap_level, f } => Ok(Rc::clone(self)), - MarkedForm::DeriComb { ids, se, de, id, wrap_level, sequence_params, rest_params, body } => Ok(Rc::clone(self)), + MarkedForm::PrimComb { .. } => Ok(Rc::clone(self)), + MarkedForm::DeriComb { .. } => Ok(Rc::clone(self)), } } } @@ -167,10 +202,10 @@ impl fmt::Display for MarkedForm { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { MarkedForm::Value(form) => write!(f, "{}", form), - MarkedForm::SuspendedSymbol { ids, name, crdi_carb } => write!(f, "{:?}#{}({:?})", ids, name, crdi_carb), + MarkedForm::SuspendedSymbol { name, crdi_carb } => write!(f, "{}({:?})", name, crdi_carb), MarkedForm::PrimComb { name, wrap_level, .. } => write!(f, "<{}{}>", name, wrap_level), - MarkedForm::DeriComb { ids, se, de, id, wrap_level, sequence_params, rest_params, body } => write!(f, "{:?}#<{}/{:?}/{}/{}/{:?}/{:?}/{}>", ids, se, de, id, wrap_level, sequence_params, rest_params, body), + MarkedForm::DeriComb { ids, se, de, id, wrap_level, sequence_params, rest_params, body } => write!(f, "{:?}#<{}/{:?}/{:?}/{}/{:?}/{:?}/{}>", ids, se, de, id, wrap_level, sequence_params, rest_params, body), MarkedForm::SuspendedPair(ids, car, cdr) => { write!(f, "{:?}#{{{}", ids, car)?; @@ -195,3 +230,233 @@ impl fmt::Display for MarkedForm { } } } + +pub fn eval(e: Rc, f: Rc) -> Rc { + let mut e = e; + let mut x = Option::Some(f); + loop { + let cur = x.take().unwrap(); + //println!("Evaluating {:?} in {:?}", cur, e); + match *cur { + Form::Symbol(ref s) => { + let mut t = e; + //println!("Looking up {} in {:?}", s, t); + //println!("Looking up {}", s); + while s != t.car().unwrap().car().unwrap().sym().unwrap() { + t = t.cdr().unwrap(); + } + return t.car().unwrap().cdr().unwrap(); + }, + Form::Pair(ref c, ref p) => { + let comb = eval(Rc::clone(&e), Rc::clone(c)); + match *comb { + Form::PrimComb(ref _n, ref f) => match f(e, Rc::clone(p)) { + PossibleTailCall::Result(r) => return r, + PossibleTailCall::TailCall(ne, nx) => { + e = ne; + x = Some(nx); + }, + }, + Form::DeriComb{ref se, ref de, ref params, ref 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(params, Rc::clone(p), new_e); + // always a tail call + e = new_e; + x = Some(Rc::clone(body)); + }, + _ => panic!("Tried to call not a Prim/DeriComb {:?}", comb), + } + }, + _ => return cur, + } + } +} +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 assoc_vec(kvs: Vec<(&str, Rc)>) -> Rc { + let mut to_ret = Rc::new(Form::Nil); + for (k, v) in kvs { + to_ret = assoc(k, v, to_ret); + } + to_ret +} + +pub fn root_env() -> Rc { + assoc_vec(vec![ + // TODO: Should be properly tail recursive + ("eval", Rc::new(Form::PrimComb("eval".to_owned(), |e, p| { + //println!("To get eval body, evaluating {:?} in {:?}", p.car(), e); + let b = eval(Rc::clone(&e), p.car().unwrap()); + let e = if let Some(ne) = p.cdr().unwrap().car() { + //println!("To get eval env, evaluating {:?} in {:?}", ne, e); + eval(e, ne) + } else { e }; + //println!("Evaling {:?} in {:?}", b, e); + PossibleTailCall::TailCall(e, b) + }))), + // (vau de params body) + ("vau", Rc::new(Form::PrimComb("vau".to_owned(), |e, p| { + let de = p.car().unwrap().sym().map(|s| s.to_owned()); + let params = p.cdr().unwrap().car().unwrap().sym().unwrap().to_owned(); + let body = p.cdr().unwrap().cdr().unwrap().car().unwrap(); + + PossibleTailCall::Result(Rc::new(Form::DeriComb { se: e, de, params, body })) + }))), + ("=", Rc::new(Form::PrimComb("=".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()); + let b = eval(e, p.cdr().unwrap().car().unwrap()); + PossibleTailCall::Result(Rc::new(Form::Bool(a == b))) + }))), + ("<", Rc::new(Form::PrimComb("<".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()); + let b = eval(e, p.cdr().unwrap().car().unwrap()); + PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() < b.int().unwrap()))) + }))), + (">", Rc::new(Form::PrimComb(">".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()); + let b = eval(e, p.cdr().unwrap().car().unwrap()); + PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() > b.int().unwrap()))) + }))), + ("<=", Rc::new(Form::PrimComb("<=".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()); + let b = eval(e, p.cdr().unwrap().car().unwrap()); + PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() <= b.int().unwrap()))) + }))), + (">=", Rc::new(Form::PrimComb(">=".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()); + let b = eval(e, p.cdr().unwrap().car().unwrap()); + PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() >= b.int().unwrap()))) + }))), + ("if", Rc::new(Form::PrimComb("if".to_owned(), |e, p| { + if eval(Rc::clone(&e), p.car().unwrap()).truthy() { + PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap()) + } else if let Some(els) = p.cdr().unwrap().cdr().and_then(|x| x.car()) { + PossibleTailCall::TailCall(e, els) + } else { + // should we really allow this? (2 arg if with no else) + PossibleTailCall::Result(Rc::new(Form::Nil)) + } + }))), + ("cons", Rc::new(Form::PrimComb("cons".to_owned(), |e, p| { + let h = eval(Rc::clone(&e), p.car().unwrap()); + let t = eval(e, p.cdr().unwrap().car().unwrap()); + PossibleTailCall::Result(Rc::new(Form::Pair(h, t))) + }))), + ("car", Rc::new(Form::PrimComb("car".to_owned(), |e, p| { + PossibleTailCall::Result(eval(Rc::clone(&e), p.car().unwrap()).car().unwrap()) + }))), + ("cdr", Rc::new(Form::PrimComb("cdr".to_owned(), |e, p| { + PossibleTailCall::Result(eval(Rc::clone(&e), p.car().unwrap()).cdr().unwrap()) + }))), + ("quote", Rc::new(Form::PrimComb("quote".to_owned(), |_e, p| { + PossibleTailCall::Result(p.car().unwrap()) + }))), + + ("debug", Rc::new(Form::PrimComb("debug".to_owned(), |e, p| { + //println!("Debug: {:?}", eval(Rc::clone(&e), p.car().unwrap())); + println!("Debug: {}", eval(Rc::clone(&e), p.car().unwrap())); + PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap()) + }))), + ("assert", Rc::new(Form::PrimComb("assert".to_owned(), |e, p| { + let thing = eval(Rc::clone(&e), p.car().unwrap()); + if !thing.truthy() { + println!("Assert failed: {:?}", thing); + } + assert!(thing.truthy()); + PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap()) + }))), + + ("+", Rc::new(Form::PrimComb("+".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a + b))) + }))), + ("-", Rc::new(Form::PrimComb("-".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a - b))) + }))), + ("*", Rc::new(Form::PrimComb("*".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a * b))) + }))), + ("/", Rc::new(Form::PrimComb("/".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a / b))) + }))), + ("%", Rc::new(Form::PrimComb("%".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a % b))) + }))), + ("&", Rc::new(Form::PrimComb("&".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a & b))) + }))), + ("|", Rc::new(Form::PrimComb("|".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a | b))) + }))), + ("^", Rc::new(Form::PrimComb("^".to_owned(), |e, p| { + let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); + let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); + PossibleTailCall::Result(Rc::new(Form::Int(a ^ b))) + }))), + + ("comb?", Rc::new(Form::PrimComb("comb?".to_owned(), |e, p| { + PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { + Form::PrimComb(_n, _f) => true, + Form::DeriComb { .. } => true, + _ => false, + }))) + }))), + ("pair?", Rc::new(Form::PrimComb("pair?".to_owned(), |e, p| { + PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { + Form::Pair(_a,_b) => true, + _ => false, + }))) + }))), + ("symbol?", Rc::new(Form::PrimComb("symbol?".to_owned(), |e, p| { + PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { + Form::Symbol(_) => true, + _ => false, + }))) + }))), + ("int?", Rc::new(Form::PrimComb("int?".to_owned(), |e, p| { + PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { + Form::Int(_) => true, + _ => false, + }))) + }))), + // maybe bool? but also could be derived. Nil def + ("bool?", Rc::new(Form::PrimComb("bool?".to_owned(), |e, p| { + PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { + Form::Bool(_) => true, + _ => false, + }))) + }))), + ("nil?", Rc::new(Form::PrimComb("nil?".to_owned(), |e, p| { + PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { + Form::Nil => true, + _ => false, + }))) + }))), + + // consts + ("true", Rc::new(Form::Bool(true))), + ("false", Rc::new(Form::Bool(false))), + ("nil", Rc::new(Form::Nil)), + ]) +} diff --git a/kr/src/main.rs b/kr/src/main.rs index a86c026..66f33e8 100644 --- a/kr/src/main.rs +++ b/kr/src/main.rs @@ -4,243 +4,19 @@ lalrpop_mod!(pub grammar); use std::rc::Rc; mod ast; -use crate::ast::{MarkedForm,Form,PossibleTailCall}; +use crate::ast::{partial_eval,Ctx,eval,root_env,MarkedForm,Form,PossibleTailCall}; -fn eval(e: Rc, f: Rc) -> Rc { - let mut e = e; - let mut x = Option::Some(f); - loop { - let cur = x.take().unwrap(); - //println!("Evaluating {:?} in {:?}", cur, e); - match *cur { - Form::Symbol(ref s) => { - let mut t = e; - //println!("Looking up {} in {:?}", s, t); - //println!("Looking up {}", s); - while s != t.car().unwrap().car().unwrap().sym().unwrap() { - t = t.cdr().unwrap(); - } - return t.car().unwrap().cdr().unwrap(); - }, - Form::Pair(ref c, ref p) => { - let comb = eval(Rc::clone(&e), Rc::clone(c)); - match *comb { - Form::PrimComb(ref _n, ref f) => match f(e, Rc::clone(p)) { - PossibleTailCall::Result(r) => return r, - PossibleTailCall::TailCall(ne, nx) => { - e = ne; - x = Some(nx); - }, - }, - Form::DeriComb{ref se, ref de, ref params, ref 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(params, Rc::clone(p), new_e); - // always a tail call - e = new_e; - x = Some(Rc::clone(body)); - }, - _ => panic!("Tried to call not a Prim/DeriComb {:?}", comb), - } - }, - _ => return cur, - } - } -} -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 assoc_vec(kvs: Vec<(&str, Rc)>) -> Rc { - let mut to_ret = Rc::new(Form::Nil); - for (k, v) in kvs { - to_ret = assoc(k, v, to_ret); - } - to_ret -} - -fn root_env() -> Rc { - assoc_vec(vec![ - // TODO: Should be properly tail recursive - ("eval", Rc::new(Form::PrimComb("eval".to_owned(), |e, p| { - //println!("To get eval body, evaluating {:?} in {:?}", p.car(), e); - let b = eval(Rc::clone(&e), p.car().unwrap()); - let e = if let Some(ne) = p.cdr().unwrap().car() { - //println!("To get eval env, evaluating {:?} in {:?}", ne, e); - eval(e, ne) - } else { e }; - //println!("Evaling {:?} in {:?}", b, e); - PossibleTailCall::TailCall(e, b) - }))), - // (vau de params body) - ("vau", Rc::new(Form::PrimComb("vau".to_owned(), |e, p| { - let de = p.car().unwrap().sym().map(|s| s.to_owned()); - let params = p.cdr().unwrap().car().unwrap().sym().unwrap().to_owned(); - let body = p.cdr().unwrap().cdr().unwrap().car().unwrap(); - - PossibleTailCall::Result(Rc::new(Form::DeriComb { se: e, de, params, body })) - }))), - ("=", Rc::new(Form::PrimComb("=".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()); - let b = eval(e, p.cdr().unwrap().car().unwrap()); - PossibleTailCall::Result(Rc::new(Form::Bool(a == b))) - }))), - ("<", Rc::new(Form::PrimComb("<".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()); - let b = eval(e, p.cdr().unwrap().car().unwrap()); - PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() < b.int().unwrap()))) - }))), - (">", Rc::new(Form::PrimComb(">".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()); - let b = eval(e, p.cdr().unwrap().car().unwrap()); - PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() > b.int().unwrap()))) - }))), - ("<=", Rc::new(Form::PrimComb("<=".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()); - let b = eval(e, p.cdr().unwrap().car().unwrap()); - PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() <= b.int().unwrap()))) - }))), - (">=", Rc::new(Form::PrimComb(">=".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()); - let b = eval(e, p.cdr().unwrap().car().unwrap()); - PossibleTailCall::Result(Rc::new(Form::Bool(a.int().unwrap() >= b.int().unwrap()))) - }))), - ("if", Rc::new(Form::PrimComb("if".to_owned(), |e, p| { - if eval(Rc::clone(&e), p.car().unwrap()).truthy() { - PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap()) - } else if let Some(els) = p.cdr().unwrap().cdr().and_then(|x| x.car()) { - PossibleTailCall::TailCall(e, els) - } else { - // should we really allow this? (2 arg if with no else) - PossibleTailCall::Result(Rc::new(Form::Nil)) - } - }))), - ("cons", Rc::new(Form::PrimComb("cons".to_owned(), |e, p| { - let h = eval(Rc::clone(&e), p.car().unwrap()); - let t = eval(e, p.cdr().unwrap().car().unwrap()); - PossibleTailCall::Result(Rc::new(Form::Pair(h, t))) - }))), - ("car", Rc::new(Form::PrimComb("car".to_owned(), |e, p| { - PossibleTailCall::Result(eval(Rc::clone(&e), p.car().unwrap()).car().unwrap()) - }))), - ("cdr", Rc::new(Form::PrimComb("cdr".to_owned(), |e, p| { - PossibleTailCall::Result(eval(Rc::clone(&e), p.car().unwrap()).cdr().unwrap()) - }))), - ("quote", Rc::new(Form::PrimComb("quote".to_owned(), |_e, p| { - PossibleTailCall::Result(p.car().unwrap()) - }))), - - ("debug", Rc::new(Form::PrimComb("debug".to_owned(), |e, p| { - //println!("Debug: {:?}", eval(Rc::clone(&e), p.car().unwrap())); - println!("Debug: {}", eval(Rc::clone(&e), p.car().unwrap())); - PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap()) - }))), - ("assert", Rc::new(Form::PrimComb("assert".to_owned(), |e, p| { - let thing = eval(Rc::clone(&e), p.car().unwrap()); - if !thing.truthy() { - println!("Assert failed: {:?}", thing); - } - assert!(thing.truthy()); - PossibleTailCall::TailCall(e, p.cdr().unwrap().car().unwrap()) - }))), - - ("+", Rc::new(Form::PrimComb("+".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a + b))) - }))), - ("-", Rc::new(Form::PrimComb("-".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a - b))) - }))), - ("*", Rc::new(Form::PrimComb("*".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a * b))) - }))), - ("/", Rc::new(Form::PrimComb("/".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a / b))) - }))), - ("%", Rc::new(Form::PrimComb("%".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a % b))) - }))), - ("&", Rc::new(Form::PrimComb("&".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a & b))) - }))), - ("|", Rc::new(Form::PrimComb("|".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a | b))) - }))), - ("^", Rc::new(Form::PrimComb("^".to_owned(), |e, p| { - let a = eval(Rc::clone(&e), p.car().unwrap()).int().unwrap(); - let b = eval(e, p.cdr().unwrap().car().unwrap()).int().unwrap(); - PossibleTailCall::Result(Rc::new(Form::Int(a ^ b))) - }))), - - ("comb?", Rc::new(Form::PrimComb("comb?".to_owned(), |e, p| { - PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { - Form::PrimComb(_n, _f) => true, - Form::DeriComb { .. } => true, - _ => false, - }))) - }))), - ("pair?", Rc::new(Form::PrimComb("pair?".to_owned(), |e, p| { - PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { - Form::Pair(_a,_b) => true, - _ => false, - }))) - }))), - ("symbol?", Rc::new(Form::PrimComb("symbol?".to_owned(), |e, p| { - PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { - Form::Symbol(_) => true, - _ => false, - }))) - }))), - ("int?", Rc::new(Form::PrimComb("int?".to_owned(), |e, p| { - PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { - Form::Int(_) => true, - _ => false, - }))) - }))), - // maybe bool? but also could be derived. Nil def - ("bool?", Rc::new(Form::PrimComb("bool?".to_owned(), |e, p| { - PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { - Form::Bool(_) => true, - _ => false, - }))) - }))), - ("nil?", Rc::new(Form::PrimComb("nil?".to_owned(), |e, p| { - PossibleTailCall::Result(Rc::new(Form::Bool(match &*eval(e, p.car().unwrap()) { - Form::Nil => true, - _ => false, - }))) - }))), - - // consts - ("true", Rc::new(Form::Bool(true))), - ("false", Rc::new(Form::Bool(false))), - ("nil", Rc::new(Form::Nil)), - ]) -} fn main() { let input = "(= 17 ((vau d p (+ (eval (car p) d) 13)) (+ 1 3)))"; let parsed_input = Rc::new(grammar::TermParser::new().parse(input).unwrap()); println!("Parsed input is {} - {:?}", parsed_input, parsed_input); - println!("Parsed unvaled that is {}", Rc::new(MarkedForm::Value(Rc::clone(&parsed_input))).unval().unwrap()); + let unvaled = Rc::new(MarkedForm::Value(Rc::clone(&parsed_input))).unval().unwrap(); + println!("Parsed unvaled that is {}", unvaled); + match partial_eval(Ctx::default(), unvaled) { + Ok((ctx, ped)) => println!("Parsed unvaled pe that is {}", ped), + Err(e) => println!("Partial evaluation error {}", e), + }; let result = eval(root_env(), parsed_input); println!("Result is {} - {:?}", result, result); }