Some steps forward, some back - add sanity testing that eval(e,x) == parial_eval(ctx, x.unval()), start fixing the bugs it reveals, split SuspendedLookup into SuspendedEnvLookup and SuspendedParamLookup

This commit is contained in:
2023-02-19 01:18:59 -05:00
parent fdaca7f807
commit 283c0232b0
2 changed files with 68 additions and 38 deletions

View File

@@ -105,25 +105,36 @@ impl Form {
let de = p.car()?.sym().map(|s| s.to_owned()).ok(); let de = p.car()?.sym().map(|s| s.to_owned()).ok();
let params = p.cdr()?.car()?.sym()?.to_owned(); let params = p.cdr()?.car()?.sym()?.to_owned();
let body = p.cdr()?.cdr()?.car()?.unval()?; let body = p.cdr()?.cdr()?.car()?.unval()?;
// TODO: pe-body, figure out wrap level, sequence params, etc let se = Rc::clone(&ctx.e);
let (ctx, id) = ctx.new_id();
// TODO: figure out wrap level, sequence params, etc
let wrap_level = 0; let wrap_level = 0;
let sequence_params = vec![]; let sequence_params = vec![];
let rest_params = Some(params); let rest_params = Some(params);
//
let inner_env = if let Some(de) = &de {
massoc(de, Rc::new(MarkedForm::SuspendedEnvLookup { name: Some(de.clone()), id: id.clone() }), Rc::clone(&se))
} else { Rc::clone(&se) };
// not yet supporting sequence params
let inner_env = if let Some(p) = &rest_params {
massoc(p, Rc::new(MarkedForm::SuspendedParamLookup { name: Some(p.clone()), id: id.clone(), cdr_num: 0, car: false }), inner_env)
} else { inner_env };
let (ctx, body) = partial_eval(ctx.copy_with(&inner_env), Rc::clone(&body)).map(|(ictx, res)| { (ictx.copy_with(&ctx.e), res) })?;
//
//
let ids = ctx.e.ids().union(&body.ids()); 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( Ok((ctx, PossibleMarkedTailCall::Result(Rc::new(
MarkedForm::DeriComb { ids, se: e, de, id, wrap_level, sequence_params, rest_params, body }, MarkedForm::DeriComb { ids, se, de, id, wrap_level, sequence_params, rest_params, body },
)))) ))))
}}), }}),
// TODO: handle vif etc // TODO: handle vif etc
"if" => Rc::new(MarkedForm::PrimComb { name: "if".to_owned(), wrap_level: 0, f: |ctx, p| { "if" => Rc::new(MarkedForm::PrimComb { name: "if".to_owned(), wrap_level: 0, f: |ctx, p| {
let (ctx, cond) = partial_eval(ctx, p.car()?)?; let (ctx, cond) = partial_eval(ctx, p.car()?.unval()?)?;
let e = Rc::clone(&ctx.e); let e = Rc::clone(&ctx.e);
if cond.truthy()? { if cond.truthy()? {
Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.car()?))) Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.car()?.unval()?)))
} else { } else {
Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.cdr()?.car()?))) Ok((ctx, PossibleMarkedTailCall::TailCall(e, p.cdr()?.cdr()?.car()?.unval()?)))
} }
}}), }}),
// TODO: handle these in the context of paritals // TODO: handle these in the context of paritals
@@ -398,7 +409,11 @@ pub fn partial_eval(ctx: Ctx, x: Rc<MarkedForm>) -> Result<(Ctx,Rc<MarkedForm>),
} }
return Ok((ctx, t.car()?.cdr()?)); return Ok((ctx, t.car()?.cdr()?));
}, },
MarkedForm::SuspendedLookup { name, id, cdr_num, car } => { MarkedForm::SuspendedEnvLookup { name, id } => {
// lookup in stack
Ok((ctx, x))
},
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } => {
// lookup in stack // lookup in stack
Ok((ctx, x)) Ok((ctx, x))
}, },
@@ -446,7 +461,7 @@ pub fn partial_eval(ctx: Ctx, x: Rc<MarkedForm>) -> Result<(Ctx,Rc<MarkedForm>),
PossibleMarkedTailCall::Result(result) => return Ok((ctx, result)), PossibleMarkedTailCall::Result(result) => return Ok((ctx, result)),
// Sigh, no tail-callin right now // Sigh, no tail-callin right now
PossibleMarkedTailCall::TailCall(new_env, next) => { PossibleMarkedTailCall::TailCall(new_env, next) => {
println!("Doing tail call of {} in {}", new_env, next); println!("Doing tail call of {} in {}", next, new_env);
if let Ok((new_ctx, res)) = partial_eval(ctx.copy_with(&new_env), Rc::clone(&next)) { if let Ok((new_ctx, res)) = partial_eval(ctx.copy_with(&new_env), Rc::clone(&next)) {
println!("Doing tail call result is {}", res); println!("Doing tail call result is {}", res);
return Ok((new_ctx.copy_with(&ctx.e), res)); return Ok((new_ctx.copy_with(&ctx.e), res));
@@ -499,7 +514,8 @@ pub enum MarkedForm {
Pair(NeededIds, Rc<MarkedForm>,Rc<MarkedForm>), Pair(NeededIds, Rc<MarkedForm>,Rc<MarkedForm>),
SuspendedSymbol(String), SuspendedSymbol(String),
SuspendedLookup { name: Option<String>, id: EnvID, cdr_num: i32, car: bool }, SuspendedParamLookup { name: Option<String>, id: EnvID, cdr_num: i32, car: bool },
SuspendedEnvLookup { name: Option<String>, id: EnvID },
// resume hash is folded into ids // resume hash is folded into ids
SuspendedPair { ids: NeededIds, attempted: Attempted, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>}, SuspendedPair { ids: NeededIds, attempted: Attempted, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>},
@@ -529,7 +545,8 @@ impl MarkedForm {
MarkedForm::Symbol(s) => NeededIds::new_none(), MarkedForm::Symbol(s) => NeededIds::new_none(),
MarkedForm::Pair(ids,car,cdr) => ids.clone(), MarkedForm::Pair(ids,car,cdr) => ids.clone(),
MarkedForm::SuspendedSymbol(name) => NeededIds::new_true(), MarkedForm::SuspendedSymbol(name) => NeededIds::new_true(),
MarkedForm::SuspendedLookup { id, .. } => NeededIds::new_single(id.clone()), MarkedForm::SuspendedEnvLookup { id, .. } => NeededIds::new_single(id.clone()),
MarkedForm::SuspendedParamLookup { id, .. } => NeededIds::new_single(id.clone()),
MarkedForm::SuspendedPair{ ids, .. } => ids.clone(), MarkedForm::SuspendedPair{ ids, .. } => ids.clone(),
MarkedForm::PrimComb { .. } => NeededIds::new_none(), MarkedForm::PrimComb { .. } => NeededIds::new_none(),
MarkedForm::DeriComb { ids, .. } => ids.clone(), MarkedForm::DeriComb { ids, .. } => ids.clone(),
@@ -542,7 +559,8 @@ impl MarkedForm {
MarkedForm::Bool(b) => return true, MarkedForm::Bool(b) => return true,
MarkedForm::Symbol(s) => return true, MarkedForm::Symbol(s) => return true,
MarkedForm::SuspendedSymbol(name) => return false, MarkedForm::SuspendedSymbol(name) => return false,
MarkedForm::SuspendedLookup { id, .. } => return false, MarkedForm::SuspendedEnvLookup { id, .. } => return false,
MarkedForm::SuspendedParamLookup { id, .. } => return false,
MarkedForm::SuspendedPair{ ids, .. } => return false, MarkedForm::SuspendedPair{ ids, .. } => return false,
MarkedForm::PrimComb { .. } => return true, MarkedForm::PrimComb { .. } => return true,
MarkedForm::Pair(ids,car,cdr) => ids.clone(), MarkedForm::Pair(ids,car,cdr) => ids.clone(),
@@ -561,7 +579,8 @@ impl MarkedForm {
MarkedForm::Symbol(s) => Ok(Rc::new(MarkedForm::SuspendedSymbol(s.clone()))), 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::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::SuspendedSymbol(name) => Err("trying to unval a suspended symbol"),
MarkedForm::SuspendedLookup { .. } => Err("trying to unval a suspended lookup"), MarkedForm::SuspendedEnvLookup { .. } => Err("trying to unval a suspended env lookup"),
MarkedForm::SuspendedParamLookup { .. } => Err("trying to unval a suspended param lookup"),
MarkedForm::SuspendedPair{ ids, .. } => Err("trying to unval a suspended pair"), MarkedForm::SuspendedPair{ ids, .. } => Err("trying to unval a suspended pair"),
MarkedForm::PrimComb { .. } => Ok(Rc::clone(self)), MarkedForm::PrimComb { .. } => Ok(Rc::clone(self)),
MarkedForm::DeriComb { .. } => Ok(Rc::clone(self)), MarkedForm::DeriComb { .. } => Ok(Rc::clone(self)),
@@ -575,7 +594,8 @@ impl MarkedForm {
MarkedForm::Symbol(s) => Ok(true), MarkedForm::Symbol(s) => Ok(true),
MarkedForm::Pair(ids,car,cdr) => Ok(true), MarkedForm::Pair(ids,car,cdr) => Ok(true),
MarkedForm::SuspendedSymbol(name) => Err("trying to truthy a suspended symbol"), MarkedForm::SuspendedSymbol(name) => Err("trying to truthy a suspended symbol"),
MarkedForm::SuspendedLookup { .. } => Err("trying to truthy a suspended lookup"), MarkedForm::SuspendedEnvLookup { .. } => Err("trying to truthy a suspended env lookup"),
MarkedForm::SuspendedParamLookup { .. } => Err("trying to truthy a suspended param lookup"),
MarkedForm::SuspendedPair{ ids, .. } => Err("trying to truthy a suspended pair"), MarkedForm::SuspendedPair{ ids, .. } => Err("trying to truthy a suspended pair"),
MarkedForm::PrimComb { .. } => Ok(true), MarkedForm::PrimComb { .. } => Ok(true),
MarkedForm::DeriComb { .. } => Ok(true), MarkedForm::DeriComb { .. } => Ok(true),
@@ -635,7 +655,8 @@ impl fmt::Display for MarkedForm {
} }
}, },
MarkedForm::SuspendedSymbol(name) => write!(f, "{}", name), MarkedForm::SuspendedSymbol(name) => write!(f, "{}", name),
MarkedForm::SuspendedLookup { name, id, cdr_num, car } => write!(f, "{:?}({:?}{}{})", name, id, cdr_num, car), MarkedForm::SuspendedEnvLookup { name, id } => write!(f, "{:?}({:?}env)", name, id),
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } => write!(f, "{:?}({:?}{}{})", name, id, cdr_num, car),
MarkedForm::PrimComb { name, wrap_level, .. } => write!(f, "<{}{}>", name, wrap_level), 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),

View File

@@ -39,11 +39,20 @@ fn parse_test() {
} }
fn eval_test<T: Into<Form>>(gram: &grammar::TermParser, e: &Rc<Form>, code: &str, expected: T) { fn eval_test<T: Into<Form>>(gram: &grammar::TermParser, e: &Rc<Form>, code: &str, expected: T) {
assert_eq!(*eval(Rc::clone(e), Rc::new(gram.parse(code).unwrap())), expected.into()); println!("Doing {}", code);
let parsed = Rc::new(gram.parse(code).unwrap());
let basic_result = eval(Rc::clone(e), Rc::clone(&parsed));
assert_eq!(*basic_result, expected.into());
let ctx = Ctx::default();
let (ctx, marked) = parsed.marked(ctx);
let unvaled = marked.unval().unwrap();
let (ctx, ped) = partial_eval(ctx, unvaled).unwrap();
let (ctx, marked_basic_result) = basic_result.marked(ctx);
println!("pe got {}", ped);
assert_eq!(*ped, *marked_basic_result);
} }
fn partial_eval_test<T: Into<Form>>(gram: &grammar::TermParser, e: &Rc<Form>, code: &str, expected: T) { fn partial_eval_test(gram: &grammar::TermParser, ctx: &Ctx, code: &str, expected: &str) {
assert_eq!(*eval(Rc::clone(e), Rc::new(gram.parse(code).unwrap())), expected.into());
} }
#[test] #[test]