move towards just MarkedForm (with no Value(Form)), with Attempted and MarkedIDs, and sketch out the MarkedForm::PrimComb versions of all the primitives with translation from PrimComb

This commit is contained in:
2023-02-18 19:32:59 -05:00
parent 8b59d5a16a
commit b893787a1b
2 changed files with 389 additions and 66 deletions

View File

@@ -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<i32> for Form { fn from(item: i32) -> Self { Form::Int(item) } }
impl From<bool> 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<MarkedForm>) {
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<EnvID>),
True(BTreeSet<Hash>),
None(BTreeSet<Hash>),
Some(BTreeSet<EnvID>,BTreeSet<Hash>),
}
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<Hash> {
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<Hash>) -> 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<MarkedForm>),
@@ -133,93 +366,189 @@ pub enum PossibleMarkedTailCall {
}
pub struct Ctx {
e : Rc<MarkedForm>,
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<MarkedForm>) -> Result<(Ctx,Rc<MarkedForm>), 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<EnvID>),
False,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum MarkedForm {
Value(Rc<Form>),
Nil,
Int(i32),
Bool(bool),
Symbol(String),
Pair(NeededIds, Rc<MarkedForm>,Rc<MarkedForm>),
SuspendedSymbol { name: String, crdi_carb: Option<(EnvID, i32, bool)> },
SuspendedPair(NeededIds, Rc<MarkedForm>, Rc<MarkedForm>),
PrimComb { name: String, wrap_level: i32, f: fn(Rc<MarkedForm>, Rc<MarkedForm>) -> PossibleMarkedTailCall },
SuspendedSymbol(String),
SuspendedLookup { name: Option<String>, id: EnvID, cdr_num: i32, car: bool },
// resume hash is folded into ids
SuspendedPair { ids: NeededIds, attempted: Attempted, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>},
PrimComb { name: String, wrap_level: i32, f: fn(Ctx,Rc<MarkedForm>) -> Result<(Ctx,PossibleMarkedTailCall),String> },
DeriComb { ids: NeededIds, se: Rc<MarkedForm>, de: Option<String>, id: EnvID, wrap_level: i32, sequence_params: Vec<String>, rest_params: Option<String>, body: Rc<MarkedForm> },
}
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<MarkedForm>) -> Result<Rc<MarkedForm>, &'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<bool,&'static str> {
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<i32,&'static str> {
match self {
MarkedForm::Int(i) => Ok(*i),
_ => Err("not a int"),
}
}
pub fn car(&self) -> Result<Rc<MarkedForm>, &'static str> {
match self {
MarkedForm::Pair(ids,car,cdr) => Ok(Rc::clone(car)),
_ => Err("not a pair"),
}
}
pub fn cdr(&self) -> Result<Rc<MarkedForm>, &'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<MarkedForm> = 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<MarkedForm> = 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<Form> {
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<Form> {
("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| {

View File

@@ -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),
};