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:
449
kr/src/ast.rs
449
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<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| {
|
||||
|
||||
@@ -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),
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user