reorginze, start sketching partial eval

This commit is contained in:
2023-02-16 18:21:13 -05:00
parent 520e473415
commit 8b59d5a16a
2 changed files with 287 additions and 246 deletions

View File

@@ -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<i32>),
Some(BTreeSet<EnvID>),
}
impl NeededIds {
fn union(&self, other: &NeededIds) -> Self {
@@ -128,38 +131,70 @@ pub enum PossibleMarkedTailCall {
Result(Rc<MarkedForm>),
TailCall(Rc<MarkedForm>, Rc<MarkedForm>),
}
pub struct Ctx {
e : Rc<MarkedForm>,
}
impl Default for Ctx {
fn default() -> Ctx {
Ctx { e: Rc::new(MarkedForm::Value(root_env())) }
}
}
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::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<Form>),
SuspendedSymbol { ids: NeededIds, name: String, crdi_carb: Option<(i32, bool)> },
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 },
DeriComb { ids: NeededIds, se: Rc<MarkedForm>, de: Option<String>, id: i32, wrap_level: i32, sequence_params: Vec<String>, rest_params: Option<String>, body: Rc<MarkedForm> },
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 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 { 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<Form>, f: Rc<Form>) -> Rc<Form> {
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<Form>, l: Rc<Form>) -> Rc<Form> {
Rc::new(Form::Pair(
Rc::new(Form::Pair(
Rc::new(Form::Symbol(k.to_owned())),
v)),
l))
}
fn assoc_vec(kvs: Vec<(&str, Rc<Form>)>) -> Rc<Form> {
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<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);
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)),
])
}

View File

@@ -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<Form>, f: Rc<Form>) -> Rc<Form> {
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<Form>, l: Rc<Form>) -> Rc<Form> {
Rc::new(Form::Pair(
Rc::new(Form::Pair(
Rc::new(Form::Symbol(k.to_owned())),
v)),
l))
}
fn assoc_vec(kvs: Vec<(&str, Rc<Form>)>) -> Rc<Form> {
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<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);
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);
}