Implement basic derived calls, and fix eval not unvaling bug
This commit is contained in:
@@ -95,8 +95,9 @@ impl Form {
|
|||||||
// should be able to take in wrap_level != 1 and do stuff
|
// 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| {
|
"eval" => Rc::new(MarkedForm::PrimComb { name: "eval".to_owned(), wrap_level: 1, f: |ctx, p| {
|
||||||
// put in partial eval logic, maybe?
|
// put in partial eval logic, maybe?
|
||||||
let b = p.car()?;
|
let b = p.car()?.unval()?;
|
||||||
let e = p.cdr()?.car()?;
|
let e = p.cdr()?.car()?;
|
||||||
|
println!("Doing Eval (via tail call) of {} in {}", b, e);
|
||||||
Ok((ctx, PossibleMarkedTailCall::TailCall(e, b)))
|
Ok((ctx, PossibleMarkedTailCall::TailCall(e, b)))
|
||||||
}}),
|
}}),
|
||||||
// (vau de params body), should be able to take in wrap_level != 1 and do stuff
|
// (vau de params body), should be able to take in wrap_level != 1 and do stuff
|
||||||
@@ -160,6 +161,7 @@ impl Form {
|
|||||||
"=" => Rc::new(MarkedForm::PrimComb { name: "=".to_owned(), wrap_level: 1, f: |ctx, p| {
|
"=" => Rc::new(MarkedForm::PrimComb { name: "=".to_owned(), wrap_level: 1, f: |ctx, p| {
|
||||||
let a = p.car()?;
|
let a = p.car()?;
|
||||||
let b = p.cdr()?.car()?;
|
let b = p.cdr()?.car()?;
|
||||||
|
println!("DOing (= {} {}) = {}", a, b, a==b);
|
||||||
// TODO: double check that this ignores ids etc. It should, since
|
// TODO: double check that this ignores ids etc. It should, since
|
||||||
// wrap_level=1 should mean that everything's a value
|
// wrap_level=1 should mean that everything's a value
|
||||||
// also, it should just check by hash then?
|
// also, it should just check by hash then?
|
||||||
@@ -387,6 +389,7 @@ impl Default for Ctx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn partial_eval(ctx: Ctx, x: Rc<MarkedForm>) -> Result<(Ctx,Rc<MarkedForm>), String> {
|
pub fn partial_eval(ctx: Ctx, x: Rc<MarkedForm>) -> Result<(Ctx,Rc<MarkedForm>), String> {
|
||||||
|
println!("PE: {}", x);
|
||||||
match &*x {
|
match &*x {
|
||||||
MarkedForm::SuspendedSymbol(name) => {
|
MarkedForm::SuspendedSymbol(name) => {
|
||||||
let mut t = Rc::clone(&ctx.e);
|
let mut t = Rc::clone(&ctx.e);
|
||||||
@@ -424,18 +427,31 @@ pub fn partial_eval(ctx: Ctx, x: Rc<MarkedForm>) -> Result<(Ctx,Rc<MarkedForm>),
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// check to see if can do call
|
// check to see if can do call
|
||||||
|
if !cdr.is_value() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
if let Ok((ctx, r)) = match &*car {
|
if let Ok((ctx, r)) = match &*car {
|
||||||
MarkedForm::PrimComb { name, wrap_level, f} => f(ctx.clone(), Rc::clone(&cdr)),
|
MarkedForm::PrimComb { name, wrap_level, f} => f(ctx.clone(), Rc::clone(&cdr)),
|
||||||
MarkedForm::DeriComb { ids, se, de, id, wrap_level, sequence_params, rest_params, body } => break,
|
MarkedForm::DeriComb { ids, se, de, id, wrap_level, sequence_params, rest_params, body } => {
|
||||||
|
//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> },
|
||||||
|
let inner_env = if let Some(de) = de { massoc(de, Rc::clone(&ctx.e), Rc::clone(se)) } else { Rc::clone(se) };
|
||||||
|
// not yet supporting sequence params
|
||||||
|
let inner_env = if let Some(p) = rest_params { massoc(p, Rc::clone(&cdr), inner_env) } else { inner_env };
|
||||||
|
// check for id in it?
|
||||||
|
partial_eval(ctx.copy_with(&inner_env), Rc::clone(body)).map(|(ictx, res)| { (ictx.copy_with(&ctx.e), PossibleMarkedTailCall::Result(res)) })
|
||||||
|
},
|
||||||
_ => break,
|
_ => break,
|
||||||
} {
|
} {
|
||||||
match r {
|
match r {
|
||||||
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);
|
||||||
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);
|
||||||
return Ok((new_ctx.copy_with(&ctx.e), res));
|
return Ok((new_ctx.copy_with(&ctx.e), res));
|
||||||
} else {
|
} else {
|
||||||
|
println!("Tail call failed");
|
||||||
if new_env == ctx.e {
|
if new_env == ctx.e {
|
||||||
return Ok((ctx, next));
|
return Ok((ctx, next));
|
||||||
} else {
|
} else {
|
||||||
@@ -519,6 +535,24 @@ impl MarkedForm {
|
|||||||
MarkedForm::DeriComb { ids, .. } => ids.clone(),
|
MarkedForm::DeriComb { ids, .. } => ids.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn is_value(&self) -> bool {
|
||||||
|
match match self {
|
||||||
|
MarkedForm::Nil => return true,
|
||||||
|
MarkedForm::Int(i) => return true,
|
||||||
|
MarkedForm::Bool(b) => return true,
|
||||||
|
MarkedForm::Symbol(s) => return true,
|
||||||
|
MarkedForm::SuspendedSymbol(name) => return false,
|
||||||
|
MarkedForm::SuspendedLookup { id, .. } => return false,
|
||||||
|
MarkedForm::SuspendedPair{ ids, .. } => return false,
|
||||||
|
MarkedForm::PrimComb { .. } => return true,
|
||||||
|
MarkedForm::Pair(ids,car,cdr) => ids.clone(),
|
||||||
|
MarkedForm::DeriComb { ids, .. } => ids.clone(),
|
||||||
|
} {
|
||||||
|
NeededIds::True(hashes) => false,
|
||||||
|
NeededIds::None(hashes) => true,
|
||||||
|
NeededIds::Some(ids,hashes) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
pub fn unval(self: &Rc<MarkedForm>) -> Result<Rc<MarkedForm>, &'static str> {
|
pub fn unval(self: &Rc<MarkedForm>) -> Result<Rc<MarkedForm>, &'static str> {
|
||||||
match &**self {
|
match &**self {
|
||||||
MarkedForm::Nil => Ok(Rc::clone(self)),
|
MarkedForm::Nil => Ok(Rc::clone(self)),
|
||||||
@@ -674,6 +708,15 @@ pub fn eval(e: Rc<Form>, f: Rc<Form>) -> Rc<Form> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn massoc(k: &str, v: Rc<MarkedForm>, l: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
||||||
|
Rc::new(MarkedForm::Pair(
|
||||||
|
l.ids().union(&v.ids()),
|
||||||
|
Rc::new(MarkedForm::Pair(
|
||||||
|
v.ids(),
|
||||||
|
Rc::new(MarkedForm::Symbol(k.to_owned())),
|
||||||
|
v)),
|
||||||
|
l))
|
||||||
|
}
|
||||||
fn assoc(k: &str, v: Rc<Form>, l: Rc<Form>) -> Rc<Form> {
|
fn assoc(k: &str, v: Rc<Form>, l: Rc<Form>) -> Rc<Form> {
|
||||||
Rc::new(Form::Pair(
|
Rc::new(Form::Pair(
|
||||||
Rc::new(Form::Pair(
|
Rc::new(Form::Pair(
|
||||||
|
|||||||
@@ -37,10 +37,15 @@ fn parse_test() {
|
|||||||
}
|
}
|
||||||
assert!(g.parse("((22)").is_err());
|
assert!(g.parse("((22)").is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
assert_eq!(*eval(Rc::clone(e), Rc::new(gram.parse(code).unwrap())), expected.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn partial_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());
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn basic_eval_test() { let g = grammar::TermParser::new(); let e = root_env();
|
fn basic_eval_test() { let g = grammar::TermParser::new(); let e = root_env();
|
||||||
eval_test(&g, &e, "(+ 2 (car (cons 4 '(1 2))))", 6);
|
eval_test(&g, &e, "(+ 2 (car (cons 4 '(1 2))))", 6);
|
||||||
|
|||||||
Reference in New Issue
Block a user