diff --git a/kr/src/ast.rs b/kr/src/ast.rs index aa56977..b54174b 100644 --- a/kr/src/ast.rs +++ b/kr/src/ast.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use std::convert::From; use std::collections::BTreeSet; use std::result::Result; +use std::iter; impl From for Form { fn from(item: i32) -> Self { Form::Int(item) } } impl From for Form { fn from(item: bool) -> Self { Form::Bool(item) } } @@ -69,6 +70,204 @@ impl Form { _ => None, } } + + pub fn marked(&self, ctx: Ctx) -> (Ctx, Rc) { + match &*self { + Form::Nil => (ctx, Rc::new(MarkedForm::Nil)), + Form::Int(i) => (ctx, Rc::new(MarkedForm::Int(*i))), + Form::Bool(b) => (ctx, Rc::new(MarkedForm::Bool(*b))), + Form::Symbol(s) => (ctx, Rc::new(MarkedForm::Symbol(s.clone()))), + Form::Pair(car, cdr) => { + let (ctx, car) = car.marked(ctx); + let (ctx, cdr) = cdr.marked(ctx); + (ctx, Rc::new(MarkedForm::Pair(NeededIds::new_none(), car, cdr))) + }, + Form::DeriComb { se, de, params, body } => { + let (ctx, se) = se.marked(ctx); + let (ctx, body) = body.marked(ctx); + let (ctx, new_id) = ctx.new_id(); + (ctx, Rc::new(MarkedForm::DeriComb { ids: NeededIds::new_none(), se, de: de.clone(), + id: new_id, wrap_level: 0, sequence_params: vec![], + rest_params: Some(params.clone()), body })) + }, + Form::PrimComb(name, _f) => { + (ctx, match &name[..] { + // should be able to take in wrap_level != 1 and do stuff + "eval" => Rc::new(MarkedForm::PrimComb { name: "eval".to_owned(), wrap_level: 1, f: |ctx, p| { + // put in partial eval logic, maybe? + let b = p.car()?; + let e = p.cdr()?.car()?; + Ok((ctx, PossibleMarkedTailCall::TailCall(e, b))) + }}), + // (vau de params body), should be able to take in wrap_level != 1 and do stuff + "vau" => Rc::new(MarkedForm::PrimComb { name: "vau".to_owned(), wrap_level: 0, f: |ctx, p| { + let de = p.car()?.sym().map(|s| s.to_owned()).ok(); + let params = p.cdr()?.car()?.sym()?.to_owned(); + let body = p.cdr()?.cdr()?.car()?.unval()?; + // TODO: pe-body, figure out wrap level, sequence params, etc + let wrap_level = 0; + let sequence_params = vec![]; + let rest_params = Some(params); + let ids = ctx.e.ids().union(&body.ids()); + let (ctx, id) = ctx.new_id(); + let e = Rc::clone(&ctx.e); + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new( + MarkedForm::DeriComb { ids, se: e, de, id, wrap_level, sequence_params, rest_params, body }, + )))) + }}), + // TODO: handle vif etc + "if" => Rc::new(MarkedForm::PrimComb { name: "if".to_owned(), wrap_level: 0, f: |ctx, p| { + let (ctx, cond) = partial_eval(ctx, p.car()?)?; + let e = Rc::clone(&ctx.e); + if cond.truthy()? { + Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.car()?))) + } else { + Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.cdr()?.car()?))) + } + }}), + // TODO: handle these in the context of paritals + "cons" => Rc::new(MarkedForm::PrimComb { name: "cons".to_owned(), wrap_level: 1, f: |ctx, p| { + let h = p.car()?; + let t = p.cdr()?.car()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Pair(h.ids().union(&t.ids()), h, t))))) + }}), + "car" => Rc::new(MarkedForm::PrimComb { name: "car".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(p.car()?.car()?))) + }}), + "cdr" => Rc::new(MarkedForm::PrimComb { name: "cdr".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(p.car()?.cdr()?))) + }}), + "quote" => Rc::new(MarkedForm::PrimComb { name: "quote".to_owned(), wrap_level: 0, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(p.car()?))) + }}), + // This one needs to control eval to print debug before continuint + // which is werid to PE + "debug" => Rc::new(MarkedForm::PrimComb { name: "debug".to_owned(), wrap_level: 0, f: |ctx, p| { + let e = Rc::clone(&ctx.e); + Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.car()?))) + }}), + // ditto + "assert" => Rc::new(MarkedForm::PrimComb { name: "assert".to_owned(), wrap_level: 0, f: |ctx, p| { + let (ctx, cond) = partial_eval(ctx, p.car()?)?; + if !cond.truthy()? { + println!("Assert failed: {:?}", cond); + } + assert!(cond.truthy()?); + let e = Rc::clone(&ctx.e); + Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.car()?))) + }}), + // (vau de params body), should be able to take in wrap_level != 1 and do stuff + "=" => Rc::new(MarkedForm::PrimComb { name: "=".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?; + let b = p.cdr()?.car()?; + // TODO: double check that this ignores ids etc. It should, since + // wrap_level=1 should mean that everything's a value + // also, it should just check by hash then? + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(a == b))))) + }}), + "<" => Rc::new(MarkedForm::PrimComb { name: "<".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?; + let b = p.cdr()?.car()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(a.int()? < b.int()?))))) + }}), + ">" => Rc::new(MarkedForm::PrimComb { name: ">".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?; + let b = p.cdr()?.car()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(a.int()? > b.int()?))))) + }}), + "<=" => Rc::new(MarkedForm::PrimComb { name: "<=".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?; + let b = p.cdr()?.car()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(a.int()? <= b.int()?))))) + }}), + ">=" => Rc::new(MarkedForm::PrimComb { name: ">=".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?; + let b = p.cdr()?.car()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(a.int()? >= b.int()?))))) + }}), + "+" => Rc::new(MarkedForm::PrimComb { name: "+".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a + b))))) + }}), + "-" => Rc::new(MarkedForm::PrimComb { name: "-".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a - b))))) + }}), + "*" => Rc::new(MarkedForm::PrimComb { name: "*".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a * b))))) + }}), + "/" => Rc::new(MarkedForm::PrimComb { name: "/".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a / b))))) + }}), + "%" => Rc::new(MarkedForm::PrimComb { name: "%".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a % b))))) + }}), + "&" => Rc::new(MarkedForm::PrimComb { name: "&".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a & b))))) + }}), + "|" => Rc::new(MarkedForm::PrimComb { name: "|".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a | b))))) + }}), + "^" => Rc::new(MarkedForm::PrimComb { name: "^".to_owned(), wrap_level: 1, f: |ctx, p| { + let a = p.car()?.int()?; + let b = p.cdr()?.car()?.int()?; + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Int(a ^ b))))) + }}), + "comb?" => Rc::new(MarkedForm::PrimComb { name: "comb?".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(match &* p.car()? { + MarkedForm::PrimComb { .. } => true, + MarkedForm::DeriComb { .. } => true, + _ => false, + }))))) + }}), + "pair?" => Rc::new(MarkedForm::PrimComb { name: "pair?".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(match &* p.car()? { + MarkedForm::Pair(_i, _a,_b) => true, + _ => false, + }))))) + }}), + "symbol?" => Rc::new(MarkedForm::PrimComb { name: "symbol?".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(match &* p.car()? { + MarkedForm::Symbol(_) => true, + _ => false, + }))))) + }}), + "int?" => Rc::new(MarkedForm::PrimComb { name: "int?".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(match &* p.car()? { + MarkedForm::Int(_) => true, + _ => false, + }))))) + }}), + // maybe bool? but also could be derived. Nil def + "bool?" => Rc::new(MarkedForm::PrimComb { name: "bool?".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(match &* p.car()? { + MarkedForm::Bool(_) => true, + _ => false, + }))))) + }}), + "nil?" => Rc::new(MarkedForm::PrimComb { name: "nil?".to_owned(), wrap_level: 1, f: |ctx, p| { + Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(MarkedForm::Bool(match &* p.car()? { + MarkedForm::Nil => true, + _ => false, + }))))) + }}), + _ => panic!("gah! don't have partial eval version of {}", name), + }) + }, + } + } } impl fmt::Display for Form { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -107,25 +306,59 @@ impl fmt::Display for Form { #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] pub struct EnvID(i32); +#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)] +pub struct Hash(u64); #[derive(Debug, Clone, Eq, PartialEq)] pub enum NeededIds { - True, - None, - Some(BTreeSet), + True(BTreeSet), + None(BTreeSet), + Some(BTreeSet,BTreeSet), } impl NeededIds { + fn new_true() -> Self { NeededIds::True( BTreeSet::new()) } + fn new_none() -> Self { NeededIds::None( BTreeSet::new()) } + fn new_single(i: EnvID) -> Self { NeededIds::Some(iter::once(i).collect(), BTreeSet::new()) } + fn hashes(&self) -> &BTreeSet { + match self { + NeededIds::True(hashes) => hashes, + NeededIds::None(hashes) => hashes, + NeededIds::Some(set,hashes) => hashes, + } + + } fn union(&self, other: &NeededIds) -> Self { match self { - NeededIds::True => NeededIds::True, - NeededIds::None => other.clone(), - NeededIds::Some(set) => match other { - NeededIds::True => NeededIds::True, - NeededIds::None => self.clone(), - NeededIds::Some(oset) => NeededIds::Some(set.union(oset).cloned().collect()), + NeededIds::True(hashes) => NeededIds::True(hashes.union(other.hashes()).cloned().collect()), + NeededIds::None(hashes) => other.union_hashes(hashes), + NeededIds::Some(set, hashes) => match other { + NeededIds::True(ohashes) => NeededIds::True(hashes.union(ohashes).cloned().collect()), + NeededIds::None(ohashes) => NeededIds::Some(set.clone(), hashes.union(ohashes).cloned().collect()), + NeededIds::Some(oset,ohashes) => NeededIds::Some(set.union(oset).cloned().collect(), hashes.union(ohashes).cloned().collect()), }, } } + fn union_hashes(&self, other: &BTreeSet) -> Self { + match self { + NeededIds::True(hashes) => NeededIds::True( other.union(hashes).cloned().collect()), + NeededIds::None(hashes) => NeededIds::None( other.union(hashes).cloned().collect()), + NeededIds::Some(set, hashes) => NeededIds::Some(set.clone(), other.union(hashes).cloned().collect()), + } + } + fn add_hash(&self, h: Hash) -> Self { + match self { + NeededIds::True(hashes) => NeededIds::True( hashes.iter().cloned().chain(iter::once(h)).collect()), + NeededIds::None(hashes) => NeededIds::None( hashes.iter().cloned().chain(iter::once(h)).collect()), + NeededIds::Some(set, hashes) => NeededIds::Some(set.clone(), hashes.iter().cloned().chain(iter::once(h)).collect()), + } + } + fn add_id(&self, i: EnvID) -> Self { + match self { + NeededIds::True(hashes) => NeededIds::True( hashes.clone()), + NeededIds::None(hashes) => NeededIds::Some(iter::once(i).collect(), hashes.clone()), + NeededIds::Some(set, hashes) => NeededIds::Some(set.iter().cloned().chain(iter::once(i)).collect(), hashes.clone()), + } + } } pub enum PossibleMarkedTailCall { Result(Rc), @@ -133,93 +366,189 @@ pub enum PossibleMarkedTailCall { } pub struct Ctx { e : Rc, + id_counter: i32 +} +impl Ctx { + pub fn new_id(mut self) -> (Self, EnvID) { + let new_id = EnvID(self.id_counter); + self.id_counter += 1; + (self, new_id) + } } impl Default for Ctx { fn default() -> Ctx { - Ctx { e: Rc::new(MarkedForm::Value(root_env())) } + let tmp_ctx = Ctx { e: Rc::new(MarkedForm::Nil), id_counter: 0 }; + let (tmp_ctx, root_env) = root_env().marked(tmp_ctx); + Ctx { e: root_env, id_counter: tmp_ctx.id_counter } } } 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::SuspendedSymbol(name) => { + let mut t = Rc::clone(&ctx.e); + while name != t.car()?.car()?.sym()? { + t = t.cdr()?; } + return Ok((ctx, t.car()?.cdr()?)); }, - MarkedForm::SuspendedPair(ids, car, cdr) => { + MarkedForm::SuspendedLookup { name, id, cdr_num, car } => { + // lookup in stack + Ok((ctx, x)) + }, + MarkedForm::SuspendedPair { ids, attempted, car, cdr } => { let (ctx, car) = partial_eval(ctx, Rc::clone(car))?; let (ctx, cdr) = partial_eval(ctx, Rc::clone(cdr))?; + // check to see if can do call // update IDs - Ok((ctx, Rc::new(MarkedForm::SuspendedPair(ids.clone(), car, cdr)))) + let new_ids = car.ids().union(&cdr.ids()); + let new_ids = if let Attempted::True(Some(id)) = attempted { new_ids.add_id(id.clone()) } else { new_ids }; + // This would come from trying it again + //let new_ids = if let Some(hash) = resume_hash { new_ids.add_hash(hash) } else { new_ids }; + let new_attempted = attempted.clone(); + Ok((ctx, Rc::new(MarkedForm::SuspendedPair{ ids: new_ids, attempted: new_attempted, car, cdr }))) + }, + MarkedForm::Pair(ids,car,cdr) => { + let (ctx, car) = partial_eval(ctx, Rc::clone(car))?; + let (ctx, cdr) = partial_eval(ctx, Rc::clone(cdr))?; + Ok((ctx, Rc::new(MarkedForm::Pair(car.ids().union(&cdr.ids()),car, cdr)))) }, MarkedForm::PrimComb { .. } => Ok((ctx, x)), + // Sub stuff MarkedForm::DeriComb { .. } => Ok((ctx, x)), - MarkedForm::Value(form) => Ok((ctx, x)), + _ => Ok((ctx, x)), } } #[derive(Debug, Clone, Eq, PartialEq)] +pub enum Attempted { + True(Option), + False, +} +#[derive(Debug, Clone, Eq, PartialEq)] pub enum MarkedForm { - Value(Rc
), + Nil, + Int(i32), + Bool(bool), + Symbol(String), + Pair(NeededIds, Rc,Rc), - SuspendedSymbol { name: String, crdi_carb: Option<(EnvID, i32, bool)> }, - SuspendedPair(NeededIds, Rc, Rc), - - PrimComb { name: String, wrap_level: i32, f: fn(Rc, Rc) -> PossibleMarkedTailCall }, + SuspendedSymbol(String), + SuspendedLookup { name: Option, id: EnvID, cdr_num: i32, car: bool }, + // resume hash is folded into ids + SuspendedPair { ids: NeededIds, attempted: Attempted, car: Rc, cdr: Rc}, + PrimComb { name: String, wrap_level: i32, f: fn(Ctx,Rc) -> Result<(Ctx,PossibleMarkedTailCall),String> }, DeriComb { ids: NeededIds, se: Rc, de: Option, id: EnvID, wrap_level: i32, sequence_params: Vec, rest_params: Option, body: Rc }, } impl MarkedForm { + pub fn ids(&self) -> NeededIds { + match self { + MarkedForm::Nil => NeededIds::new_none(), + MarkedForm::Int(i) => NeededIds::new_none(), + MarkedForm::Bool(b) => NeededIds::new_none(), + MarkedForm::Symbol(s) => NeededIds::new_none(), + MarkedForm::Pair(ids,car,cdr) => ids.clone(), + MarkedForm::SuspendedSymbol(name) => NeededIds::new_true(), + MarkedForm::SuspendedLookup { id, .. } => NeededIds::new_single(id.clone()), + MarkedForm::SuspendedPair{ ids, .. } => ids.clone(), + MarkedForm::PrimComb { .. } => NeededIds::new_none(), + MarkedForm::DeriComb { ids, .. } => ids.clone(), + } + } 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 { .. }=> Ok(Rc::clone(self)), - - 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 { .. } => Err("trying to unval a suspended symbol"), - MarkedForm::SuspendedPair(ids, car, cdr) => Err("trying to unval a suspended pair"), + MarkedForm::Nil => Ok(Rc::clone(self)), + MarkedForm::Int(i) => Ok(Rc::clone(self)), + MarkedForm::Bool(b) => Ok(Rc::clone(self)), + MarkedForm::Symbol(s) => Ok(Rc::new(MarkedForm::SuspendedSymbol(s.clone()))), + MarkedForm::Pair(ids,car,cdr) => Ok(Rc::new(MarkedForm::SuspendedPair { ids: NeededIds::new_true(), attempted: Attempted::False, car: car.unval()?, cdr: Rc::clone(cdr)})), + MarkedForm::SuspendedSymbol(name) => Err("trying to unval a suspended symbol"), + MarkedForm::SuspendedLookup { .. } => Err("trying to unval a suspended lookup"), + MarkedForm::SuspendedPair{ ids, .. } => Err("trying to unval a suspended pair"), MarkedForm::PrimComb { .. } => Ok(Rc::clone(self)), MarkedForm::DeriComb { .. } => Ok(Rc::clone(self)), } } + pub fn truthy(&self) -> Result { + match self { + MarkedForm::Nil => Ok(false), + MarkedForm::Int(i) => Ok(true), + MarkedForm::Bool(b) => Ok(*b), + MarkedForm::Symbol(s) => Ok(true), + MarkedForm::Pair(ids,car,cdr) => Ok(true), + MarkedForm::SuspendedSymbol(name) => Err("trying to truthy a suspended symbol"), + MarkedForm::SuspendedLookup { .. } => Err("trying to truthy a suspended lookup"), + MarkedForm::SuspendedPair{ ids, .. } => Err("trying to truthy a suspended pair"), + MarkedForm::PrimComb { .. } => Ok(true), + MarkedForm::DeriComb { .. } => Ok(true), + } + } + pub fn sym(&self) -> Result<&str,&'static str> { + match self { + MarkedForm::Symbol(s) => Ok(s), + _ => Err("not a symbol"), + } + } + pub fn int(&self) -> Result { + match self { + MarkedForm::Int(i) => Ok(*i), + _ => Err("not a int"), + } + } + pub fn car(&self) -> Result, &'static str> { + match self { + MarkedForm::Pair(ids,car,cdr) => Ok(Rc::clone(car)), + _ => Err("not a pair"), + } + } + pub fn cdr(&self) -> Result, &'static str> { + match self { + MarkedForm::Pair(ids,car,cdr) => Ok(Rc::clone(cdr)), + _ => Err("not a pair"), + } + } } impl fmt::Display for MarkedForm { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - MarkedForm::Value(form) => write!(f, "{}", form), - 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::SuspendedPair(ids, car, cdr) => { - write!(f, "{:?}#{{{}", ids, car)?; + MarkedForm::Nil => write!(f, "nil"), + MarkedForm::Int(i) => write!(f, "{}", i), + MarkedForm::Bool(b) => write!(f, "{}", b), + MarkedForm::Symbol(s) => write!(f, "{}", s), + MarkedForm::Pair(ids, car, cdr) => { + write!(f, "{:?}#({}", ids, car)?; let mut traverse: Rc = Rc::clone(cdr); loop { match &*traverse { - MarkedForm::SuspendedPair(ref _ids, ref carp, ref cdrp) => { + MarkedForm::Pair(ref ids, ref carp, ref cdrp) => { write!(f, " {}", carp)?; traverse = Rc::clone(cdrp); }, - MarkedForm::Value(form) if match &**form { Form::Nil => true, _ => false } => { - write!(f, "}}")?; + MarkedForm::Nil => { + write!(f, ")")?; return Ok(()); }, + x => { + write!(f, ". {})", x)?; + return Ok(()); + }, + } + } + }, + MarkedForm::SuspendedSymbol(name) => write!(f, "{}", name), + MarkedForm::SuspendedLookup { name, id, cdr_num, car } => write!(f, "{:?}({:?}{}{})", name, id, cdr_num, car), + 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::SuspendedPair{ ids, attempted, car, cdr } => { + write!(f, "{:?}{:?}#{{{}", ids, attempted, car)?; + let mut traverse: Rc = Rc::clone(cdr); + loop { + match &*traverse { + MarkedForm::Pair(ref ids, ref carp, ref cdrp) => { + write!(f, " {}", carp)?; + traverse = Rc::clone(cdrp); + }, x => { write!(f, ". {}}}", x)?; return Ok(()); @@ -293,13 +622,8 @@ 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); + let e = eval(e, p.cdr().unwrap().car().unwrap()); PossibleTailCall::TailCall(e, b) }))), // (vau de params body) @@ -338,11 +662,8 @@ pub fn root_env() -> Rc { ("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)) + PossibleTailCall::TailCall(e, p.cdr().unwrap().cdr().unwrap().car().unwrap()) } }))), ("cons", Rc::new(Form::PrimComb("cons".to_owned(), |e, p| { diff --git a/kr/src/main.rs b/kr/src/main.rs index 66f33e8..6905f37 100644 --- a/kr/src/main.rs +++ b/kr/src/main.rs @@ -11,9 +11,11 @@ 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); - let unvaled = Rc::new(MarkedForm::Value(Rc::clone(&parsed_input))).unval().unwrap(); + let ctx = Ctx::default(); + let (ctx, marked) = parsed_input.marked(ctx); + let unvaled = marked.unval().unwrap(); println!("Parsed unvaled that is {}", unvaled); - match partial_eval(Ctx::default(), unvaled) { + match partial_eval(ctx, unvaled) { Ok((ctx, ped)) => println!("Parsed unvaled pe that is {}", ped), Err(e) => println!("Partial evaluation error {}", e), };