Finally finished sketching out the new version, lets get on the compile errors
This commit is contained in:
@@ -13,7 +13,7 @@ with partial evaluation during compilation to make it efficient.
|
|||||||
|
|
||||||
koka_bench: Licensed under Apache-2.0, as they are derived from the benchmarks of the Koka project, see the readme and license in koka_bench for more, or https://github.com/koka-lang/koka for the source project.
|
koka_bench: Licensed under Apache-2.0, as they are derived from the benchmarks of the Koka project, see the readme and license in koka_bench for more, or https://github.com/koka-lang/koka for the source project.
|
||||||
|
|
||||||
Kraken (everything else besides the benchmarks in koka_bench) Licensed under
|
Kraken (everything else besides the benchmarks in koka_bench, and Recursive/CodeJar/Highlight.js in website/) Licensed under
|
||||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
Note: This license is designed to provide: a) a simple permissive license; b) that is compatible with the GNU General Public License (GPL), version 2; and c) which also has an express patent grant included.
|
Note: This license is designed to provide: a) a simple permissive license; b) that is compatible with the GNU General Public License (GPL), version 2; and c) which also has an express patent grant included.
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ build = "build.rs"
|
|||||||
lalrpop-util = {version="0.19.7", features=["lexer"]}
|
lalrpop-util = {version="0.19.7", features=["lexer"]}
|
||||||
regex = "1"
|
regex = "1"
|
||||||
once_cell = "1.17.0"
|
once_cell = "1.17.0"
|
||||||
|
anyhow = "1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
lalrpop = "0.19.7"
|
lalrpop = "0.19.7"
|
||||||
|
|||||||
606
kr/src/pe_ast.rs
606
kr/src/pe_ast.rs
@@ -2,11 +2,13 @@ use std::fmt;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
use std::collections::{BTreeSet,BTreeMap};
|
use std::collections::{BTreeSet,BTreeMap};
|
||||||
use std::result::Result;
|
use std::result;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
|
||||||
use crate::ast::{root_env,Form};
|
use crate::ast::{root_env,Form};
|
||||||
|
|
||||||
|
use anyhow::{anyhow, bail, Result, Context};
|
||||||
|
|
||||||
|
|
||||||
fn massoc(k: &str, v: Rc<MarkedForm>, l: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
fn massoc(k: &str, v: Rc<MarkedForm>, l: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
||||||
MarkedForm::new_pair(
|
MarkedForm::new_pair(
|
||||||
@@ -61,15 +63,17 @@ fn massoc(k: &str, v: Rc<MarkedForm>, l: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
|||||||
* non values that would be looked up in the upper env are itneresting, as I don't think we can tell...
|
* non values that would be looked up in the upper env are itneresting, as I don't think we can tell...
|
||||||
* wait no it's always ok to unwrap suspended_eval unless there is a True remaining
|
* wait no it's always ok to unwrap suspended_eval unless there is a True remaining
|
||||||
* the Env or the subvalue would have been captured via partial eval
|
* the Env or the subvalue would have been captured via partial eval
|
||||||
|
* ALSO UNLESS BELOW
|
||||||
*
|
*
|
||||||
* Also, I think it can only have a true if it hasn't been evaluated yet
|
* Also, I think it can only have a true if it hasn't been evaluated yet
|
||||||
* technically, the env could end in a suspended-param or suspended-env
|
* technically, the env could end in a suspended-param or suspended-env
|
||||||
* make sure the lookup accounts for that, that's a *WEIRD* one
|
* make sure the lookup accounts for that, that's a *WEIRD* one
|
||||||
* <HERE>
|
* can't unwrap if it ends in a lookup, & that lookup ID is contained in the body
|
||||||
*
|
*
|
||||||
* ALL THE ENV reasoning only holds if ENVs are just cons chains with supsended params or suspended env params
|
* ALL THE ENV reasoning only holds if ENVs are just cons chains with supsended params or suspended env params
|
||||||
*
|
*
|
||||||
* suspended if needs special gating head|tail attention
|
* suspended if needs special gating head|tail attention
|
||||||
|
* mainly if rec-stopped, cond & rec takes head, relegating rest
|
||||||
*
|
*
|
||||||
* for suspended calls, the rec_mapping function needs to differentiate between a parameter
|
* for suspended calls, the rec_mapping function needs to differentiate between a parameter
|
||||||
* failing because of an error and failing because of a needed ID
|
* failing because of an error and failing because of a needed ID
|
||||||
@@ -83,7 +87,6 @@ fn massoc(k: &str, v: Rc<MarkedForm>, l: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
|||||||
* it's a bit trickey!
|
* it's a bit trickey!
|
||||||
* The result of a DeriCall's IDs, if not a value, needs to become (part of, depending on if non-val parameters are allowed) the SuspendedCall's head IDs
|
* The result of a DeriCall's IDs, if not a value, needs to become (part of, depending on if non-val parameters are allowed) the SuspendedCall's head IDs
|
||||||
* ditto for rec-stop, but the call-under bit
|
* ditto for rec-stop, but the call-under bit
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// 0 is equiv of true, -1 is equiv to runtime
|
// 0 is equiv of true, -1 is equiv to runtime
|
||||||
@@ -105,7 +108,6 @@ impl NeededIds {
|
|||||||
fn new_true() -> Self { NeededIds { heads: iter::once(true_id).collect(), tails: BTreeSet::new(), body_stopped: BTreeSet::new(), if_stopped: BTreeSet::new() }
|
fn new_true() -> Self { NeededIds { heads: iter::once(true_id).collect(), tails: BTreeSet::new(), body_stopped: BTreeSet::new(), if_stopped: BTreeSet::new() }
|
||||||
fn new_none() -> Self { NeededIds { heads: BTreeSet::new(), tails: BTreeSet::new(), body_stopped: BTreeSet::new(), if_stopped: BTreeSet::new() } }
|
fn new_none() -> Self { NeededIds { heads: BTreeSet::new(), tails: BTreeSet::new(), body_stopped: BTreeSet::new(), if_stopped: BTreeSet::new() } }
|
||||||
fn new_single(i: EnvID) -> Self { NeededIds { heads: iter::once(i).collect(), tails: BTreeSet::new(), body_stopped: BTreeSet::new(), if_stopped: BTreeSet::new() } }
|
fn new_single(i: EnvID) -> Self { NeededIds { heads: iter::once(i).collect(), tails: BTreeSet::new(), body_stopped: BTreeSet::new(), if_stopped: BTreeSet::new() } }
|
||||||
fn needs_nothing(&self) -> bool { heads.empty() && tails.empty() && body_stopped.empty() && if_stopped.empty() }
|
|
||||||
fn union(&self, other: &NeededIds) -> Self {
|
fn union(&self, other: &NeededIds) -> Self {
|
||||||
NeededIds {
|
NeededIds {
|
||||||
heads: self.heads.union(&other.heads).cloned().collect(),
|
heads: self.heads.union(&other.heads).cloned().collect(),
|
||||||
@@ -114,12 +116,12 @@ impl NeededIds {
|
|||||||
if_stopped: self.if_stopped.union(&other.if_stopped).cloned().collect(),
|
if_stopped: self.if_stopped.union(&other.if_stopped).cloned().collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn union_without(&self, other: &NeededIds, without: EnvID) -> Self {
|
fn union_without(&self, other: &NeededIds, without: &EnvID) -> Self {
|
||||||
NeededIds {
|
NeededIds {
|
||||||
heads: self.heads.union(&other.heads) .filter(|&x| x != without).cloned().collect(),
|
heads: self.heads.union(&other.heads) .filter(|x| x != without).cloned().collect(),
|
||||||
tails: self.tails.union(&other.tails) .filter(|&x| x != without).cloned().collect(),
|
tails: self.tails.union(&other.tails) .filter(|x| x != without).cloned().collect(),
|
||||||
body_stopped: self.body_stopped.union(&other.body_stopped).filter(|&x| x != without).cloned().collect(),
|
body_stopped: self.body_stopped.union(&other.body_stopped).filter(|x| x != without).cloned().collect(),
|
||||||
if_stopped: self.if_stopped.union(&other.if_stopped) .filter(|&x| x != without).cloned().collect(),
|
if_stopped: self.if_stopped.union(&other.if_stopped) .filter(|x| x != without).cloned().collect(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn union_into_tail(&self, ids: &NeededIds) -> Self {
|
fn union_into_tail(&self, ids: &NeededIds) -> Self {
|
||||||
@@ -169,6 +171,9 @@ impl NeededIds {
|
|||||||
fn may_contain_id(&self, i: EnvID) -> bool {
|
fn may_contain_id(&self, i: EnvID) -> bool {
|
||||||
self.heads.contains(&i) || self.tails.contains(&i)
|
self.heads.contains(&i) || self.tails.contains(&i)
|
||||||
}
|
}
|
||||||
|
fn contains_if_stop(&self, i: &EnvID) -> bool {
|
||||||
|
self.if_stopped.contains(i)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 is equiv of true, -1 is equiv to runtime
|
// 0 is equiv of true, -1 is equiv to runtime
|
||||||
@@ -184,6 +189,11 @@ impl BCtx {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum PushFrameResult {
|
||||||
|
Ok(Dctx),
|
||||||
|
UnderBody(EnvID),
|
||||||
|
UnderIf(EnvID),
|
||||||
|
}
|
||||||
|
|
||||||
// memo is only for recording currently executing hashes (calls and if's, current for us)
|
// memo is only for recording currently executing hashes (calls and if's, current for us)
|
||||||
// only_head is not currently used
|
// only_head is not currently used
|
||||||
@@ -200,16 +210,19 @@ pub struct DCtx {
|
|||||||
}
|
}
|
||||||
impl DCtx {
|
impl DCtx {
|
||||||
pub fn copy_set_env(&self, e: &Rc<MarkedForm>) -> Self {
|
pub fn copy_set_env(&self, e: &Rc<MarkedForm>) -> Self {
|
||||||
DCtx { e: Rc::clone(e), current_id: self.current_id.clone(), sus_env_stack: Rc::clone(&self.sus_env_stack), sus_prm_stack: Rc::clone(&self.sus_prm_stack), real_set: Rc::clone(&self.real_set), fake_set: Rc::clone(&self.fake_set), fake_if_set: Rc::clone(&self.fake_if_set), ident: self.ident+1 }
|
DCtx { e: Rc::clone(e), current_id: self.current_id.clone(),
|
||||||
|
sus_env_stack: Rc::clone(&self.sus_env_stack), sus_prm_stack: Rc::clone(&self.sus_prm_stack),
|
||||||
|
real_set: Rc::clone(&self.real_set), fake_set: Rc::clone(&self.fake_set), fake_if_set: Rc::clone(&self.fake_if_set), ident: self.ident+1 }
|
||||||
}
|
}
|
||||||
pub fn copy_push_frame(&self, id: EnvID, se: &Rc<MarkedForm>, de: &Option<String>, e: Option<Rc<MarkedForm>>, rest_params: &Option<String>, prms: Option<Rc<MarkedForm>>, body: &Rc<MarkedForm>) -> Result<Self,EnvID> {
|
pub fn copy_push_frame(&self, id: EnvID, se: &Rc<MarkedForm>, de: &Option<String>, e: Option<Rc<MarkedForm>>,
|
||||||
|
rest_params: &Option<String>, prms: Option<Rc<MarkedForm>>, body: &Rc<MarkedForm>) -> PushFrameResult {
|
||||||
let mut sus_env_stack = Rc::clone(&self.sus_env_stack);
|
let mut sus_env_stack = Rc::clone(&self.sus_env_stack);
|
||||||
let mut sus_prm_stack = Rc::clone(&self.sus_prm_stack);
|
let mut sus_prm_stack = Rc::clone(&self.sus_prm_stack);
|
||||||
let mut real_set = (*self.real_set).clone();
|
let mut real_set = (*self.real_set).clone();
|
||||||
let mut fake_set = (*self.fake_set).clone();
|
let mut fake_set = (*self.fake_set).clone();
|
||||||
if self.fake_if_set.contains(&id) {
|
if self.fake_if_set.contains(&id) {
|
||||||
println!("Fake if real rec stopper");
|
println!("Fake if real rec stopper");
|
||||||
return Err(id);
|
return PushFrameResult::UnderIf(id);
|
||||||
}
|
}
|
||||||
if (e.is_some() || prms.is_some()) {
|
if (e.is_some() || prms.is_some()) {
|
||||||
real_set.insert(id.clone());
|
real_set.insert(id.clone());
|
||||||
@@ -217,7 +230,7 @@ impl DCtx {
|
|||||||
//fake_set.remove(&id);
|
//fake_set.remove(&id);
|
||||||
} else {
|
} else {
|
||||||
if fake_set.contains(&id) {
|
if fake_set.contains(&id) {
|
||||||
return Err(id.clone());
|
return PushFrameResult::UnderBody(id.clone());
|
||||||
}
|
}
|
||||||
fake_set.insert(id.clone());
|
fake_set.insert(id.clone());
|
||||||
real_set.remove(&id);
|
real_set.remove(&id);
|
||||||
@@ -243,38 +256,33 @@ impl DCtx {
|
|||||||
};
|
};
|
||||||
massoc(p, p_val, inner_env)
|
massoc(p, p_val, inner_env)
|
||||||
} else { inner_env };
|
} else { inner_env };
|
||||||
Ok(DCtx { e: inner_env, current_id: Some(id), sus_env_stack, sus_prm_stack, real_set: Rc::new(real_set), fake_set: Rc::new(fake_set), fake_if_set: Rc::clone(&self.fake_if_set), ident: self.ident+1 })
|
PushFrameResult::Ok(DCtx { e: inner_env, current_id: Some(id), sus_env_stack, sus_prm_stack,
|
||||||
|
real_set: Rc::new(real_set), fake_set: Rc::new(fake_set), fake_if_set: Rc::clone(&self.fake_if_set), ident: self.ident+1 })
|
||||||
}
|
}
|
||||||
pub fn copy_push_fake_if(&self) -> Self {
|
pub fn copy_push_fake_if(&self) -> (Option<EnvID>, Self) {
|
||||||
let new_fake_if_set = if let Some(current_id) = self.current_id.as_ref() {
|
let (could_stop, new_fake_if_set) = if let Some(current_id) = self.current_id.as_ref() {
|
||||||
let mut x = (*self.fake_if_set).clone();
|
let mut x = (*self.fake_if_set).clone();
|
||||||
|
let could_stop = if !x.contains(current_id) { Some(current_id.clone()) } else { None };
|
||||||
x.insert(current_id.clone());
|
x.insert(current_id.clone());
|
||||||
Rc::new(x)
|
(could_stop, Rc::new(x))
|
||||||
} else { Rc::clone(&self.fake_if_set) };
|
} else { (None, Rc::clone(&self.fake_if_set)) };
|
||||||
DCtx { e: Rc::clone(&self.e), current_id: self.current_id.clone(), sus_env_stack: Rc::clone(&self.sus_env_stack), sus_prm_stack: Rc::clone(&self.sus_prm_stack), real_set: Rc::clone(&self.real_set), fake_set: Rc::clone(&self.fake_set), fake_if_set: new_fake_if_set, ident: self.ident+1 }
|
(could_stop, DCtx { e: Rc::clone(&self.e), current_id: self.current_id.clone(), sus_env_stack: Rc::clone(&self.sus_env_stack), sus_prm_stack: Rc::clone(&self.sus_prm_stack),
|
||||||
|
real_set: Rc::clone(&self.real_set), fake_set: Rc::clone(&self.fake_set), fake_if_set: new_fake_if_set, ident: self.ident+1 })
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_progress(&self, ids: NeededIds) -> bool {
|
pub fn can_progress(&self, ids: NeededIds) -> bool {
|
||||||
// check if ids is true || ids intersection EnvIDs in our stacks is non empty || ids.hashes - current is non empty
|
// check if ids is true || ids intersection EnvIDs in our stacks is non empty || ids.hashes - current is non empty
|
||||||
match ids {
|
ids.heads.contains(&true_id) || !self.real_set.is_disjoint(&ids.heads) || !self.fake_set.is_superset(&ids.body_stopped) || !self.fake_if_set.is_superset(&ids.if_stopped)
|
||||||
NeededIds::True( under) => under.is_empty() || (!(self.fake_set.union(&self.fake_if_set).cloned().collect::<BTreeSet<EnvID>>()).is_superset(&under)), //true, - if we have hashes, that means we don't know what's in but can't progress b/c hashes
|
|
||||||
NeededIds::None( under) => !(self.fake_set.union(&self.fake_if_set).cloned().collect::<BTreeSet<EnvID>>()).is_superset(&under),
|
|
||||||
NeededIds::Some(ids,under) => (!self.real_set.is_disjoint(&ids)) || (!(self.fake_set.union(&self.fake_if_set).cloned().collect::<BTreeSet<EnvID>>()).is_superset(&under)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_base_ctxs() -> (BCtx,DCtx) {
|
pub fn new_base_ctxs() -> (BCtx,DCtx) {
|
||||||
let bctx = BCtx { id_counter: true_id.0 + 1 };
|
let bctx = BCtx { id_counter: true_id.0 + 1 };
|
||||||
let (bctx, root_env) = mark(root_env(), bctx);
|
let (bctx, root_env) = mark(root_env(), bctx);
|
||||||
(bctx, DCtx { e: root_env, current_id: None, sus_env_stack: Rc::new(BTreeMap::new()), sus_prm_stack: Rc::new(BTreeMap::new()), real_set: Rc::new(BTreeSet::new()), fake_set: Rc::new(BTreeSet::new()), fake_if_set: Rc::new(BTreeSet::new()), ident: 0 } )
|
(bctx, DCtx { e: root_env, current_id: None, sus_env_stack: Rc::new(BTreeMap::new()), sus_prm_stack: Rc::new(BTreeMap::new()),
|
||||||
|
real_set: Rc::new(BTreeSet::new()), fake_set: Rc::new(BTreeSet::new()), fake_if_set: Rc::new(BTreeSet::new()), ident: 0 } )
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
|
||||||
pub enum Attempted {
|
|
||||||
True(Option<NeededIds>),
|
|
||||||
False,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub enum MarkedForm {
|
pub enum MarkedForm {
|
||||||
Nil,
|
Nil,
|
||||||
@@ -283,45 +291,41 @@ pub enum MarkedForm {
|
|||||||
Symbol(String),
|
Symbol(String),
|
||||||
Pair(NeededIds, Rc<MarkedForm>,Rc<MarkedForm>),
|
Pair(NeededIds, Rc<MarkedForm>,Rc<MarkedForm>),
|
||||||
|
|
||||||
SuspendedSymbol(String),
|
SuspendedSymbol(NeededIds, String), // Needs IDs if Env chains into suspended
|
||||||
SuspendedParamLookup { 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 },
|
SuspendedEnvLookup { name: Option<String>, id: EnvID },
|
||||||
SuspendedPair { ids: NeededIds, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>},
|
SuspendedPair { ids: NeededIds, call_ids: Option<NeededIds>, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>},
|
||||||
|
|
||||||
SuspendedEnvEval { ids: NeededIds, x: Rc<MarkedForm>, e: Rc<MarkedForm> },
|
SuspendedEnvEval { ids: NeededIds, x: Rc<MarkedForm>, e: Rc<MarkedForm> },
|
||||||
SuspendedIf { ids: NeededIds, c: Rc<MarkedForm>, t: Rc<MarkedForm>, e: Rc<MarkedForm> },
|
SuspendedIf { ids: NeededIds, c: Rc<MarkedForm>, t: Rc<MarkedForm>, e: Rc<MarkedForm> },
|
||||||
|
|
||||||
PrimComb { name: String, nonval_ok: bool, takes_de: bool, wrap_level: i32, f: fn(BCtx,DCtx,Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>),String> },
|
PrimComb { name: String, nonval_ok: bool, takes_de: bool, wrap_level: i32, f: fn(BCtx,DCtx,Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>)> },
|
||||||
DeriComb { lookup_name: Option<String>, ids: NeededIds, se: Rc<MarkedForm>, de: Option<String>, id: EnvID, wrap_level: i32, sequence_params: Vec<String>, rest_params: Option<String>, body: Rc<MarkedForm> },
|
DeriComb { lookup_name: Option<String>, 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 {
|
impl MarkedForm {
|
||||||
pub fn new_suspended_env_eval(x: Rc<MarkedForm>, e: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
pub fn new_suspended_env_eval(x: Rc<MarkedForm>, e: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
||||||
Rc::new(MarkedForm::SuspendedEnvEval { ids: e.ids(), x, e })
|
Rc::new(MarkedForm::SuspendedEnvEval { ids: e.ids(), x, e })
|
||||||
}
|
}
|
||||||
pub fn new_suspended_if(c: Rc<MarkedForm>, t: Rc<MarkedForm>, e: Rc<MarkedForm>, rec_under: Option<EnvID>) -> Rc<MarkedForm> {
|
|
||||||
let new_ids = c.ids().union(&t.ids()).union(&e.ids());
|
|
||||||
let new_ids = if let Some(rec_under) = rec_under { new_ids.add_if_under(rec_under) } else { new_ids };
|
|
||||||
Rc::new(MarkedForm::SuspendedIf{ ids: new_ids, c, t, e })
|
|
||||||
}
|
|
||||||
pub fn new_pair(car: Rc<MarkedForm>, cdr: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
pub fn new_pair(car: Rc<MarkedForm>, cdr: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
||||||
let new_ids = car.ids().union(&cdr.ids());
|
let new_ids = car.ids().union(&cdr.ids());
|
||||||
//println!("For new pair, union of {:?} and {:?} is {:?}", car.ids(), cdr.ids(), new_ids);
|
|
||||||
Rc::new(MarkedForm::Pair(new_ids, car, cdr))
|
Rc::new(MarkedForm::Pair(new_ids, car, cdr))
|
||||||
}
|
}
|
||||||
pub fn new_suspended_pair(attempted: Option<NeededIds>, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>, rec_under: Option<EnvID>) -> Rc<MarkedForm> {
|
pub fn new_suspended_pair(attempted: Option<NeededIds>, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>, under_body: Option<EnvID>, under_if: Option<EnvID>) -> Rc<MarkedForm> {
|
||||||
|
// differentiate between call and if rec_under
|
||||||
let ids = car.ids().union(&cdr.ids());
|
let ids = car.ids().union(&cdr.ids());
|
||||||
let ids = if let Some(attempted) = attempted {
|
let ids = if let Some(attempted) = attempted {
|
||||||
attempted.union_into_tail(ids)
|
attempted.union_into_tail(ids)
|
||||||
} else {
|
} else {
|
||||||
ids
|
ids
|
||||||
};
|
};
|
||||||
let ids = if let Some(rec_under) = rec_under { ids.add_body_under(rec_under) } else { ids };
|
let ids = if let Some(rec_under) = under_body { ids.add_body_under(rec_under) } else { ids };
|
||||||
|
let ids = if let Some(rec_under) = under_if { ids.add_if_under(rec_under) } else { ids };
|
||||||
|
|
||||||
Rc::new(MarkedForm::SuspendedPair{ ids, car, cdr })
|
Rc::new(MarkedForm::SuspendedPair{ ids, car, cdr })
|
||||||
}
|
}
|
||||||
pub fn new_deri_comb(se: Rc<MarkedForm>, lookup_name: Option<String>, de: Option<String>, id: EnvID, wrap_level: i32, sequence_params: Vec<String>, rest_params: Option<String>, body: Rc<MarkedForm>, rec_under: Option<EnvID>) -> Rc<MarkedForm> {
|
pub fn new_deri_comb(se: Rc<MarkedForm>, lookup_name: Option<String>, de: Option<String>, id: EnvID, wrap_level: i32, sequence_params: Vec<String>, rest_params: Option<String>, body: Rc<MarkedForm>, rec_under: Option<EnvID>) -> Rc<MarkedForm> {
|
||||||
let ids = se.ids().union_without(&body.ids(), id.clone());
|
let ids = se.ids().union_without(&body.ids(), &id);
|
||||||
let ids = if let Some(rec_under) = rec_under {
|
let ids = if let Some(rec_under) = rec_under {
|
||||||
ids.add_body_under(rec_under)
|
ids.add_body_under(rec_under)
|
||||||
} else {
|
} else {
|
||||||
@@ -348,7 +352,6 @@ impl MarkedForm {
|
|||||||
MarkedForm::PrimComb { name, nonval_ok, takes_de, wrap_level, f } => Some(Rc::new(MarkedForm::PrimComb { name: name.clone(), nonval_ok: *nonval_ok, takes_de: *takes_de, wrap_level: wrap_level-1, f: *f })),
|
MarkedForm::PrimComb { name, nonval_ok, takes_de, wrap_level, f } => Some(Rc::new(MarkedForm::PrimComb { name: name.clone(), nonval_ok: *nonval_ok, takes_de: *takes_de, wrap_level: wrap_level-1, f: *f })),
|
||||||
MarkedForm::DeriComb { lookup_name, ids, se, de, id, wrap_level, sequence_params, rest_params, body } =>
|
MarkedForm::DeriComb { lookup_name, ids, se, de, id, wrap_level, sequence_params, rest_params, body } =>
|
||||||
Some(Rc::new(MarkedForm::DeriComb { lookup_name: lookup_name.clone(), ids: ids.clone(), se: Rc::clone(se), de: de.clone(), id: id.clone(), wrap_level: *wrap_level-1, sequence_params: sequence_params.clone(), rest_params: rest_params.clone(), body: Rc::clone(body) })),
|
Some(Rc::new(MarkedForm::DeriComb { lookup_name: lookup_name.clone(), ids: ids.clone(), se: Rc::clone(se), de: de.clone(), id: id.clone(), wrap_level: *wrap_level-1, sequence_params: sequence_params.clone(), rest_params: rest_params.clone(), body: Rc::clone(body) })),
|
||||||
//Some(MarkedForm::new_deri_comb(Rc::clone(se), lookup_name.clone(), de.clone(), id.clone(), wrap_level-1, sequence_params.clone(), rest_params.clone(), Rc::clone(body))),
|
|
||||||
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
@@ -360,7 +363,7 @@ impl MarkedForm {
|
|||||||
MarkedForm::Bool(b) => NeededIds::new_none(),
|
MarkedForm::Bool(b) => NeededIds::new_none(),
|
||||||
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(ids, name) => ids.clone(),
|
||||||
MarkedForm::SuspendedEnvLookup { id, .. } => NeededIds::new_single(id.clone()),
|
MarkedForm::SuspendedEnvLookup { id, .. } => NeededIds::new_single(id.clone()),
|
||||||
MarkedForm::SuspendedParamLookup { id, .. } => NeededIds::new_single(id.clone()),
|
MarkedForm::SuspendedParamLookup { id, .. } => NeededIds::new_single(id.clone()),
|
||||||
MarkedForm::SuspendedEnvEval { ids, ..} => ids.clone(),
|
MarkedForm::SuspendedEnvEval { ids, ..} => ids.clone(),
|
||||||
@@ -370,91 +373,134 @@ impl MarkedForm {
|
|||||||
MarkedForm::DeriComb { ids, .. } => ids.clone(),
|
MarkedForm::DeriComb { ids, .. } => ids.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: this might be essentially the same as NeededIds.nothing_needed()
|
// note, this can be entirely ID based, but this should be more efficient
|
||||||
pub fn is_value(&self) -> bool {
|
pub fn is_value(&self) -> bool {
|
||||||
match match self {
|
let ids = match self {
|
||||||
MarkedForm::Nil => return true,
|
MarkedForm::Nil => return true,
|
||||||
MarkedForm::Int(i) => return true,
|
MarkedForm::Int(i) => return true,
|
||||||
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(ids, name) => return false,
|
||||||
MarkedForm::SuspendedEnvLookup { id, .. } => return false,
|
MarkedForm::SuspendedEnvLookup { id, .. } => return false,
|
||||||
MarkedForm::SuspendedParamLookup { id, .. } => return false,
|
MarkedForm::SuspendedParamLookup { id, .. } => return false,
|
||||||
MarkedForm::SuspendedEnvEval { ids, ..} => return false,
|
MarkedForm::SuspendedEnvEval { ids, ..} => return false,
|
||||||
MarkedForm::SuspendedIf { ids, ..} => return false,
|
MarkedForm::SuspendedIf { ids, ..} => return false,
|
||||||
MarkedForm::SuspendedPair{ ids, .. } => return false,
|
MarkedForm::SuspendedPair{ ids, .. } => return false,
|
||||||
MarkedForm::PrimComb { .. } => return true,
|
MarkedForm::PrimComb { .. } => return true,
|
||||||
// TODO ths might be wrong as it could have captured some suspended computation
|
|
||||||
// On the other hand, that would surely show up in ids, right?
|
|
||||||
MarkedForm::Pair(ids,car,cdr) => ids.clone(),
|
MarkedForm::Pair(ids,car,cdr) => ids.clone(),
|
||||||
MarkedForm::DeriComb { ids, .. } => ids.clone(),
|
MarkedForm::DeriComb { ids, .. } => ids.clone(),
|
||||||
} {
|
};
|
||||||
NeededIds::True(hashes) => false,
|
ids.heads.empty() && ids.tails.empty()
|
||||||
NeededIds::None(hashes) => true,
|
|
||||||
NeededIds::Some(ids,hashes) => false,
|
|
||||||
}
|
}
|
||||||
}
|
pub fn unval(self: &Rc<MarkedForm>) -> Result<Rc<MarkedForm>> {
|
||||||
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)),
|
||||||
MarkedForm::Int(i) => Ok(Rc::clone(self)),
|
MarkedForm::Int(i) => Ok(Rc::clone(self)),
|
||||||
MarkedForm::Bool(b) => Ok(Rc::clone(self)),
|
MarkedForm::Bool(b) => Ok(Rc::clone(self)),
|
||||||
MarkedForm::Symbol(s) => Ok(Rc::new(MarkedForm::SuspendedSymbol(s.clone()))),
|
MarkedForm::Symbol(s) => Ok(Rc::new(MarkedForm::SuspendedSymbol(NeededIds::new_true(), s.clone()))),
|
||||||
MarkedForm::Pair(ids,car,cdr) => Ok(MarkedForm::new_suspended_pair( Attempted::False, car.unval()?, Rc::clone(cdr), None)),
|
MarkedForm::Pair(ids,car,cdr) => Ok(MarkedForm::new_suspended_pair(None, car.unval()?, Rc::clone(cdr), None, None)),
|
||||||
MarkedForm::SuspendedSymbol(name) => Err("trying to unval a suspended symbol"),
|
MarkedForm::SuspendedSymbol(ids, name) => bail!("trying to unval a suspended symbol"),
|
||||||
MarkedForm::SuspendedEnvLookup { .. } => Err("trying to unval a suspended env lookup"),
|
MarkedForm::SuspendedEnvLookup { .. } => bail!("trying to unval a suspended env lookup"),
|
||||||
MarkedForm::SuspendedParamLookup { .. } => Err("trying to unval a suspended param lookup"),
|
MarkedForm::SuspendedParamLookup { .. } => bail!("trying to unval a suspended param lookup"),
|
||||||
MarkedForm::SuspendedEnvEval { .. } => Err("trying to unval a suspended env eval"),
|
MarkedForm::SuspendedEnvEval { .. } => bail!("trying to unval a suspended env eval"),
|
||||||
MarkedForm::SuspendedIf { .. } => Err("trying to unval a suspended if"),
|
MarkedForm::SuspendedIf { .. } => bail!("trying to unval a suspended if"),
|
||||||
MarkedForm::SuspendedPair{ ids, .. } => Err("trying to unval a suspended pair"),
|
MarkedForm::SuspendedPair{ ids, .. } => bail!("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)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn truthy(&self) -> Result<bool,&'static str> {
|
pub fn truthy(&self) -> Result<bool> {
|
||||||
match self {
|
match self {
|
||||||
MarkedForm::Nil => Ok(false),
|
MarkedForm::Nil => Ok(false),
|
||||||
MarkedForm::Int(i) => Ok(true),
|
MarkedForm::Int(i) => Ok(true),
|
||||||
MarkedForm::Bool(b) => Ok(*b),
|
MarkedForm::Bool(b) => Ok(*b),
|
||||||
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(ids, name) => bail!("trying to truthy a suspended symbol"),
|
||||||
MarkedForm::SuspendedEnvLookup { .. } => Err("trying to truthy a suspended env lookup"),
|
MarkedForm::SuspendedEnvLookup { .. } => bail!("trying to truthy a suspended env lookup"),
|
||||||
MarkedForm::SuspendedParamLookup { .. } => Err("trying to truthy a suspended param lookup"),
|
MarkedForm::SuspendedParamLookup { .. } => bail!("trying to truthy a suspended param lookup"),
|
||||||
MarkedForm::SuspendedEnvEval { .. } => Err("trying to truthy a suspended env eval"),
|
MarkedForm::SuspendedEnvEval { .. } => bail!("trying to truthy a suspended env eval"),
|
||||||
MarkedForm::SuspendedIf { .. } => Err("trying to truthy a suspended if"),
|
MarkedForm::SuspendedIf { .. } => bail!("trying to truthy a suspended if"),
|
||||||
MarkedForm::SuspendedPair{ ids, .. } => Err("trying to truthy a suspended pair"),
|
MarkedForm::SuspendedPair{ ids, .. } => bail!("trying to truthy a suspended pair"),
|
||||||
MarkedForm::PrimComb { .. } => Ok(true),
|
MarkedForm::PrimComb { .. } => Ok(true),
|
||||||
MarkedForm::DeriComb { .. } => Ok(true),
|
MarkedForm::DeriComb { .. } => Ok(true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn sym(&self) -> Result<&str,&'static str> {
|
pub fn sym(&self) -> Result<&str> {
|
||||||
match self {
|
match self {
|
||||||
MarkedForm::Symbol(s) => Ok(s),
|
MarkedForm::Symbol(s) => Ok(s),
|
||||||
_ => Err("not a symbol"),
|
_ => bail!("not a symbol"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn int(&self) -> Result<i32,&'static str> {
|
pub fn int(&self) -> Result<i32> {
|
||||||
match self {
|
match self {
|
||||||
MarkedForm::Int(i) => Ok(*i),
|
MarkedForm::Int(i) => Ok(*i),
|
||||||
_ => Err("not a int"),
|
_ => bail!("not a int"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn car(&self) -> Result<Rc<MarkedForm>, String> {
|
pub fn car(&self) -> Result<Rc<MarkedForm>> {
|
||||||
match self {
|
match self {
|
||||||
MarkedForm::Pair(ids,car,cdr) => Ok(Rc::clone(car)),
|
MarkedForm::Pair(ids,car,cdr) => Ok(Rc::clone(car)),
|
||||||
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } if !car => Ok(Rc::new(MarkedForm::SuspendedParamLookup { name: name.clone(), id: id.clone(), cdr_num: *cdr_num, car: true })),
|
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } if !car => Ok(Rc::new(MarkedForm::SuspendedParamLookup { name: name.clone(), id: id.clone(),
|
||||||
_ => Err(format!("not a pair for car: {}", self)),
|
cdr_num: *cdr_num, car: true })),
|
||||||
|
_ => bail!("not a pair for car: {}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub fn cdr(&self) -> Result<Rc<MarkedForm>, String> {
|
pub fn cdr(&self) -> Result<Rc<MarkedForm>> {
|
||||||
match self {
|
match self {
|
||||||
MarkedForm::Pair(ids,car,cdr) => Ok(Rc::clone(cdr)),
|
MarkedForm::Pair(ids,car,cdr) => Ok(Rc::clone(cdr)),
|
||||||
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } => Ok(Rc::new(MarkedForm::SuspendedParamLookup { name: name.clone(), id: id.clone(), cdr_num: *cdr_num+1, car: *car })),
|
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } if !car => Ok(Rc::new(MarkedForm::SuspendedParamLookup { name: name.clone(), id: id.clone(),
|
||||||
_ => Err(format!("not a pair for cdr: {}", self)),
|
cdr_num: *cdr_num+1, car: *car })),
|
||||||
|
_ => bail!("not a pair for cdr: {}", self),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
fn make_eval_prim() -> Rc<MarkedForm> {
|
||||||
|
Rc::new(MarkedForm::PrimComb { name: "eval".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: eval_func })
|
||||||
|
}
|
||||||
|
fn eval_func(bctx: BCtx, dctx: DCtx, p: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>)> {
|
||||||
|
//println!("Ok, this is inside eval looking at {}", p);
|
||||||
|
if !p.car()?.is_value() {
|
||||||
|
Ok( MarkedForm::new_suspended_pair( Some(p.car().unwrap().ids()), make_eval_prim(), p, None, None ))
|
||||||
|
} else {
|
||||||
|
//println!("Ok, returning new suspended env eval with");
|
||||||
|
//println!("\t{} {}", p.car()?.unval()?, p.cdr()?.car()?);
|
||||||
|
Ok((bctx, MarkedForm::new_suspended_env_eval(p.car()?.unval()?, p.cdr()?.car()?)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Implement the suspended param / suspended env traversal
|
||||||
|
fn make_cons_prim() -> Rc<MarkedForm> {
|
||||||
|
Rc::new(MarkedForm::PrimComb { name: "cons".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: cons_func})
|
||||||
|
}
|
||||||
|
fn cons_func(bctx: BCtx, dctx: DCtx, p: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>)> {
|
||||||
|
let h = p.car()?;
|
||||||
|
let t = p.cdr()?.car()?;
|
||||||
|
Ok((bctx, MarkedForm::new_pair(h, t)))
|
||||||
|
}
|
||||||
|
fn make_car_prim()-> Rc<MarkedForm> {
|
||||||
|
Rc::new(MarkedForm::PrimComb { name: "car".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: car_func})
|
||||||
|
}
|
||||||
|
fn car_func(bctx: BCtx, dctx: DCtx, p: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>)> {
|
||||||
|
Ok((bctx, p.car()?.car()?))
|
||||||
|
}
|
||||||
|
fn make_cdr_prim() -> Rc<MarkedForm> {
|
||||||
|
Rc::new(MarkedForm::PrimComb { name: "cdr".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: cdr_func})
|
||||||
|
}
|
||||||
|
fn cdr_func(bctx: BCtx, dctx: DCtx, p: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>)> {
|
||||||
|
Ok((bctx, p.car()?.cdr()?))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn make_debug_prim() -> Rc<MarkedForm> {
|
||||||
|
Rc::new(MarkedForm::PrimComb { name: "debug".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: debug_func})
|
||||||
|
}
|
||||||
|
fn debug_func(bctx: BCtx, dctx: DCtx, p: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>)> {
|
||||||
|
// This one is a bit weird - we put the wrap level at 1 so both sides are pe'd,
|
||||||
|
// and then return runtime
|
||||||
|
Ok(MarkedForm::new_suspended_pair( Some(runtime.clone()), make_debug_prim(), p, None, None ))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mark(form: Rc<Form>, bctx: BCtx) -> (BCtx, Rc<MarkedForm>) {
|
pub fn mark(form: Rc<Form>, bctx: BCtx) -> (BCtx, Rc<MarkedForm>) {
|
||||||
match &*form {
|
match &*form {
|
||||||
@@ -472,16 +518,6 @@ pub fn mark(form: Rc<Form>, bctx: BCtx) -> (BCtx, Rc<MarkedForm>) {
|
|||||||
},
|
},
|
||||||
Form::PrimComb(name, _f) => {
|
Form::PrimComb(name, _f) => {
|
||||||
(bctx, match &name[..] {
|
(bctx, match &name[..] {
|
||||||
"eval" => Rc::new(MarkedForm::PrimComb { name: "eval".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
|
||||||
println!("Ok, this is inside eval looking at {}", p);
|
|
||||||
if !p.car()?.is_value() {
|
|
||||||
Err("can't eval without form being a value, since we're changing the env".to_owned())
|
|
||||||
} else {
|
|
||||||
println!("Ok, returning new suspended env eval with");
|
|
||||||
println!("\t{} {}", p.car()?.unval()?, p.cdr()?.car()?);
|
|
||||||
Ok((bctx, MarkedForm::new_suspended_env_eval(p.car()?.unval()?, p.cdr()?.car()?)))
|
|
||||||
}
|
|
||||||
}}),
|
|
||||||
"vau" => Rc::new(MarkedForm::PrimComb { name: "vau".to_owned(), nonval_ok: false, takes_de: true, wrap_level: 0, f: |bctx, dctx, p| {
|
"vau" => Rc::new(MarkedForm::PrimComb { name: "vau".to_owned(), nonval_ok: false, takes_de: true, wrap_level: 0, f: |bctx, dctx, p| {
|
||||||
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();
|
||||||
@@ -493,44 +529,34 @@ pub fn mark(form: Rc<Form>, bctx: BCtx) -> (BCtx, Rc<MarkedForm>) {
|
|||||||
let rest_params = Some(params);
|
let rest_params = Some(params);
|
||||||
Ok((bctx, MarkedForm::new_deri_comb( se, None, de, id, wrap_level, sequence_params, rest_params, body, None )))
|
Ok((bctx, MarkedForm::new_deri_comb( se, None, de, id, wrap_level, sequence_params, rest_params, body, None )))
|
||||||
}}),
|
}}),
|
||||||
"if" => Rc::new(MarkedForm::PrimComb { name: "if".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 0, f: |bctx, dctx, p| {
|
"eval" => make_eval_prim(),
|
||||||
Ok((bctx, MarkedForm::new_suspended_if(p.car()?.unval()?, p.cdr()?.car()?.unval()?, p.cdr()?.cdr()?.car()?.unval()?, None)))
|
"cons" => make_cons_prim(),
|
||||||
}}),
|
"car" => make_car_prim(),
|
||||||
// TODO: handle these in the context of paritals
|
"cdr" => make_cdr_prim(),
|
||||||
"cons" => Rc::new(MarkedForm::PrimComb { name: "cons".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
"debug" => make_debug_prim(),
|
||||||
let h = p.car()?;
|
// Like Debug, listed as wrap_level 1 so bothe sides are pe'd, even though it would
|
||||||
//println!("Consing with head {}", h);
|
// be sequencing at runtime
|
||||||
let t = p.cdr()?.car()?;
|
|
||||||
//println!("Consing with tail {}", t);
|
|
||||||
Ok((bctx, MarkedForm::new_pair(h, t)))
|
|
||||||
}}),
|
|
||||||
"car" => Rc::new(MarkedForm::PrimComb { name: "car".to_owned(), nonval_ok: true, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
|
||||||
Ok((bctx, p.car()?.car()?))
|
|
||||||
}}),
|
|
||||||
"cdr" => Rc::new(MarkedForm::PrimComb { name: "cdr".to_owned(), nonval_ok: true, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
|
||||||
Ok((bctx, p.car()?.cdr()?))
|
|
||||||
}}),
|
|
||||||
"quote" => Rc::new(MarkedForm::PrimComb { name: "quote".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 0, f: |bctx, dctx, p| {
|
|
||||||
Ok((bctx, p.car()?))
|
|
||||||
}}),
|
|
||||||
"debug" => Rc::new(MarkedForm::PrimComb { name: "debug".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
|
||||||
// This one is a bit weird - we put the wrap level at 1 so both sides are pe'd,
|
|
||||||
// and always returns Err so that it's not optimized away
|
|
||||||
Err("debug can't be partial-evaluated away".to_owned())
|
|
||||||
}}),
|
|
||||||
// ditto
|
|
||||||
"assert" => Rc::new(MarkedForm::PrimComb { name: "assert".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
"assert" => Rc::new(MarkedForm::PrimComb { name: "assert".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
||||||
let cond = p.car()?;
|
let cond = p.car()?;
|
||||||
if !cond.truthy()? {
|
if !cond.truthy()? {
|
||||||
println!("Assert failed: {:?}", cond);
|
bail!("Assertion failed {}", cond)
|
||||||
}
|
}
|
||||||
assert!(cond.truthy()?);
|
|
||||||
Ok((bctx, p.cdr()?.car()?))
|
Ok((bctx, p.cdr()?.car()?))
|
||||||
}}),
|
}}),
|
||||||
|
"if" => Rc::new(MarkedForm::PrimComb { name: "if".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 0, f: |bctx, dctx, p| {
|
||||||
|
let c = p.car()?.unval()?;
|
||||||
|
let t = p.cdr()?.car()?.unval()?;
|
||||||
|
let e = p.cdr()?.cdr()?.car()?.unval()?;
|
||||||
|
let ids = c.ids().union(&t.ids()).union(&e.ids());
|
||||||
|
Ok((bctx, Rc::new(MarkedForm::SuspendedIf{ids, c, t, e})))
|
||||||
|
}}),
|
||||||
|
// Non val is actually fine
|
||||||
|
"quote" => Rc::new(MarkedForm::PrimComb { name: "quote".to_owned(), nonval_ok: true, takes_de: false, wrap_level: 0, f: |bctx, dctx, p| {
|
||||||
|
Ok((bctx, p.car()?))
|
||||||
|
}}),
|
||||||
"=" => Rc::new(MarkedForm::PrimComb { name: "=".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
"=" => Rc::new(MarkedForm::PrimComb { name: "=".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
||||||
let a = p.car()?;
|
let a = p.car()?;
|
||||||
let b = p.cdr()?.car()?;
|
let b = p.cdr()?.car()?;
|
||||||
// wrap_level=1 should mean that everything's a value
|
|
||||||
Ok((bctx, Rc::new(MarkedForm::Bool(a == b))))
|
Ok((bctx, Rc::new(MarkedForm::Bool(a == b))))
|
||||||
}}),
|
}}),
|
||||||
"<" => Rc::new(MarkedForm::PrimComb { name: "<".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
"<" => Rc::new(MarkedForm::PrimComb { name: "<".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
||||||
@@ -593,6 +619,7 @@ pub fn mark(form: Rc<Form>, bctx: BCtx) -> (BCtx, Rc<MarkedForm>) {
|
|||||||
let b = p.cdr()?.car()?.int()?;
|
let b = p.cdr()?.car()?.int()?;
|
||||||
Ok((bctx, Rc::new(MarkedForm::Int(a ^ b))))
|
Ok((bctx, Rc::new(MarkedForm::Int(a ^ b))))
|
||||||
}}),
|
}}),
|
||||||
|
// This could allow nonval with fallback
|
||||||
"comb?" => Rc::new(MarkedForm::PrimComb { name: "comb?".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
"comb?" => Rc::new(MarkedForm::PrimComb { name: "comb?".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
||||||
Ok((bctx, Rc::new(MarkedForm::Bool(match &* p.car()? {
|
Ok((bctx, Rc::new(MarkedForm::Bool(match &* p.car()? {
|
||||||
MarkedForm::PrimComb { .. } => true,
|
MarkedForm::PrimComb { .. } => true,
|
||||||
@@ -600,6 +627,7 @@ pub fn mark(form: Rc<Form>, bctx: BCtx) -> (BCtx, Rc<MarkedForm>) {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}))))
|
}))))
|
||||||
}}),
|
}}),
|
||||||
|
// This could allow nonval with fallback
|
||||||
"pair?" => Rc::new(MarkedForm::PrimComb { name: "pair?".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
"pair?" => Rc::new(MarkedForm::PrimComb { name: "pair?".to_owned(), nonval_ok: false, takes_de: false, wrap_level: 1, f: |bctx, dctx, p| {
|
||||||
Ok((bctx, Rc::new(MarkedForm::Bool(match &* p.car()? {
|
Ok((bctx, Rc::new(MarkedForm::Bool(match &* p.car()? {
|
||||||
MarkedForm::Pair(_i, _a,_b) => true,
|
MarkedForm::Pair(_i, _a,_b) => true,
|
||||||
@@ -638,139 +666,125 @@ pub fn mark(form: Rc<Form>, bctx: BCtx) -> (BCtx, Rc<MarkedForm>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn combiner_return_ok(x: &Rc<MarkedForm>, check_id: Option<EnvID>) -> bool {
|
pub fn combiner_return_ok(x: &Rc<MarkedForm>, check_id: Option<EnvID>) -> bool {
|
||||||
match match &**x {
|
let ids = x.ids();
|
||||||
MarkedForm::Nil => return true,
|
!ids.contains(&true_id) && check_id.map(|check_id| !ids.contains(&check_id)).unwrap_or(true)
|
||||||
MarkedForm::Int(_) => return true,
|
|
||||||
MarkedForm::Bool(_) => return true,
|
|
||||||
MarkedForm::Symbol(_) => return true,
|
|
||||||
// Hmm, we allow Pair to included suspended now...
|
|
||||||
// so now we have to be extra careful
|
|
||||||
MarkedForm::Pair(ids,car,cdr) => ids,
|
|
||||||
|
|
||||||
MarkedForm::SuspendedSymbol(_) => return false,
|
|
||||||
MarkedForm::SuspendedParamLookup { id, .. } => return check_id.map(|check_id| *id != check_id).unwrap_or(true),
|
|
||||||
MarkedForm::SuspendedEnvLookup { id, .. } => return check_id.map(|check_id| *id != check_id).unwrap_or(true),
|
|
||||||
|
|
||||||
MarkedForm::SuspendedEnvEval { e, .. } => return combiner_return_ok(e, check_id),
|
|
||||||
MarkedForm::SuspendedIf { c, t, e, .. } => return combiner_return_ok(c, check_id.clone()) &&
|
|
||||||
combiner_return_ok(t, check_id.clone()) &&
|
|
||||||
combiner_return_ok(e, check_id),
|
|
||||||
MarkedForm::SuspendedPair { car, cdr, .. } => {
|
|
||||||
// expand with (func ...params) | func doesn't take de and func+params are return ok
|
|
||||||
return false
|
|
||||||
},
|
|
||||||
|
|
||||||
MarkedForm::PrimComb { .. } => return true,
|
|
||||||
MarkedForm::DeriComb { ids, .. } => ids,
|
|
||||||
} {
|
|
||||||
NeededIds::True( _under) => false,
|
|
||||||
NeededIds::None( _under) => true,
|
|
||||||
NeededIds::Some(ids,_under) => check_id.map(|check_id| !ids.contains(&check_id)).unwrap_or(true),
|
|
||||||
}
|
|
||||||
//; Handles let 4.3 through macro level leaving it as (<comb wraplevel=1 (y) (+ y x 12)> 13)
|
|
||||||
//; need handling of symbols (which is illegal for eval but ok for calls) to push it farther
|
|
||||||
//(combiner_return_ok (rec-lambda combiner_return_ok (func_result env_id)
|
|
||||||
// (cond ((not (later_head? func_result)) (not (check_for_env_id_in_result env_id func_result)))
|
|
||||||
// ; special cases now
|
|
||||||
// ; *(veval body {env}) => (combiner_return_ok {env})
|
|
||||||
// ; The reason we don't have to check body is that this form is only creatable in ways that body was origionally a value and only need {env}
|
|
||||||
// ; Either it's created by eval, in which case it's fine, or it's created by something like (eval (array veval x de) de2) and the array has checked it,
|
|
||||||
// ; or it's created via literal vau invocation, in which case the body is a value.
|
|
||||||
// ((and (marked_array? func_result)
|
|
||||||
// (prim_comb? (idx (.marked_array_values func_result) 0))
|
|
||||||
// (= 'veval (.prim_comb_sym (idx (.marked_array_values func_result) 0)))
|
|
||||||
// (= 3 (len (.marked_array_values func_result)))
|
|
||||||
// (combiner_return_ok (idx (.marked_array_values func_result) 2) env_id)) true)
|
|
||||||
// ; (func ...params) => (and (doesn't take de func) (foldl combiner_return_ok (cons func params)))
|
|
||||||
// ;
|
|
||||||
// ((and (marked_array? func_result)
|
|
||||||
// (not (comb_takes_de? (idx (.marked_array_values func_result) 0) (len (.marked_array_values func_result))))
|
|
||||||
// (foldl (lambda (a x) (and a (combiner_return_ok x env_id))) true (.marked_array_values func_result))) true)
|
|
||||||
|
|
||||||
// ; So that's enough for macro like, but we would like to take it farther
|
|
||||||
// ; For like (let1 a 12 (wrap (vau (x) (let1 y (+ a 1) (+ y x a)))))
|
|
||||||
// ; we get to (+ 13 x 12) not being a value, and it reconstructs
|
|
||||||
// ; (<comb wraplevel=1 (y) (+ y x 12)> 13)
|
|
||||||
// ; and that's what eval gets, and eval then gives up as well.
|
|
||||||
|
|
||||||
// ; That will get caught by the above cases to remain the expansion (<comb wraplevel=1 (y) (+ y x 12)> 13),
|
|
||||||
// ; but ideally we really want another case to allow (+ 13 x 12) to bubble up
|
|
||||||
// ; I think it would be covered by the (func ...params) case if a case is added to allow symbols to be bubbled up if their
|
|
||||||
// ; needed for progress wasn't true or the current environment, BUT this doesn't work for eval, just for functions,
|
|
||||||
// ; since eval changes the entire env chain (but that goes back to case 1, and might be eliminated at compile if it's an env reachable from the func).
|
|
||||||
// ;
|
|
||||||
// ;
|
|
||||||
// ; Do note a key thing to be avoided is allowing any non-val inside a comb, since that can cause a fake env's ID to
|
|
||||||
// ; reference the wrong env/comb in the chain.
|
|
||||||
// ; We do allow calling eval with a fake env, but since it's only callable withbody value and is strict (by calling this)
|
|
||||||
// ; about it's return conditions, and the env it's called with must be ok in the chain, and eval doesn't introduce a new scope, it works ok.
|
|
||||||
// ; We do have to be careful about allowing returned later symbols from it though, since it could be an entirely different env chain.
|
|
||||||
|
|
||||||
// (true false)
|
|
||||||
// )
|
|
||||||
//))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn partial_eval(bctx_in: BCtx, dctx_in: DCtx, form: Rc<MarkedForm>) -> (BCtx,Rc<MarkedForm>) {
|
pub fn partial_eval(bctx_in: BCtx, dctx_in: DCtx, form: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>)> {
|
||||||
let mut bctx = bctx_in;
|
let mut bctx = bctx_in;
|
||||||
let mut dctx = dctx_in;
|
let mut dctx = dctx_in;
|
||||||
let mut next_form = Some(form);
|
let mut next_form = Some(form);
|
||||||
let mut force = false;
|
|
||||||
loop {
|
loop {
|
||||||
let x = next_form.take().unwrap();
|
let x = next_form.take().unwrap();
|
||||||
//println!("{:ident$}PE: {}", "", x, ident=dctx.ident*4);
|
//println!("{:ident$}PE: {}", "", x, ident=dctx.ident*4);
|
||||||
if !(force || dctx.can_progress(x.ids())) {
|
if !dctx.can_progress(x.ids()) {
|
||||||
//println!("{:ident$}Shouldn't go!", "", ident=dctx.ident*4);
|
//println!("{:ident$}Shouldn't go!", "", ident=dctx.ident*4);
|
||||||
return (bctx, x);
|
return Ok((bctx, x));
|
||||||
}
|
}
|
||||||
//println!("{:ident$}({}) PE(force:{}) {:?} (because of {:?})", "", dctx.ident, force, x, x.ids(), ident=dctx.ident*4);
|
//println!("{:ident$}({}) PE(force:{}) {:?} (because of {:?})", "", dctx.ident, force, x, x.ids(), ident=dctx.ident*4);
|
||||||
println!("{:ident$}({}) PE(force:{}) {} (because of {:?})", "", dctx.ident, force, x, x.ids(), ident=dctx.ident*4);
|
//println!("{:ident$}({}) PE {} (because of {:?})", "", dctx.ident, x, x.ids(), ident=dctx.ident*4);
|
||||||
match partial_eval_step(&x, force, bctx.clone(), &mut dctx) {
|
let (new_bctx, new_form) = partial_eval_step(&x, bctx.clone(), &mut dctx)?;
|
||||||
Ok((new_bctx,new_force,new_form)) => {
|
|
||||||
bctx = new_bctx; force = new_force; next_form = Some(new_form);
|
|
||||||
println!("{:ident$}({}) was ok, result was {}", "", dctx.ident, next_form.as_ref().unwrap(), ident=dctx.ident*4);
|
|
||||||
}
|
|
||||||
Err(msg) => {
|
|
||||||
println!("{:ident$}({}) was error, reconstructing (error was {})", "", dctx.ident, msg, ident=dctx.ident*4);
|
|
||||||
return (bctx, x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// basic Drop redundent veval
|
// basic Drop redundent veval
|
||||||
// Old one was recursive over parameters to combs, which we might need, since the redundent veval isn't captured by
|
// Old one was recursive over parameters to combs, which we might need, since the redundent veval isn't captured by
|
||||||
// ids. TODO!
|
// ids. TODO!
|
||||||
if let Some(form) = next_form.as_ref() {
|
//
|
||||||
if let MarkedForm::SuspendedEnvEval { x, e, .. } = &**form {
|
// Nowadays, dropping EnvEval is legal always *unless*
|
||||||
if (combiner_return_ok(&x, None) || *e == dctx.e) {
|
// - True is in ids
|
||||||
|
// - this current env ends in a suspended param/env, and that id is in ids (the *weird* case)
|
||||||
|
if let MarkedForm::SuspendedEnvEval { x, e, .. } = &new_form {
|
||||||
|
if !x.ids().may_contain_id(&true_id) {
|
||||||
next_form = Some(Rc::clone(x));
|
next_form = Some(Rc::clone(x));
|
||||||
force = true;
|
// do we still need force for drop redundent veval?
|
||||||
|
// Not while it's not recursive, at elaset
|
||||||
|
} else {
|
||||||
|
next_form = Some(new_form);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
enum MapUnvalPEvalResult {
|
||||||
|
Ok(BCtx,Rc<MarkedForm>),
|
||||||
|
NotYet(anyhow::Error),
|
||||||
|
BadError(anyhow::Error),
|
||||||
}
|
}
|
||||||
fn partial_eval_step(x: &Rc<MarkedForm>, forced: bool, bctx: BCtx, dctx: &mut DCtx) -> Result<(BCtx,bool,Rc<MarkedForm>), String> {
|
fn map_unval_peval(bctx: BCtx, dctx: DCtx, x: Rc<MarkedForm>) -> MapUnvalPEvalResult {
|
||||||
|
match &*x {
|
||||||
|
MarkedForm::Nil => MapUnvalPEvalResult::Ok(bctx,x),
|
||||||
|
MarkedForm::Pair(ids, x_car, x_cdr) => {
|
||||||
|
match x_car.unval() {
|
||||||
|
Ok(unval) => {
|
||||||
|
match partial_eval(bctx, dctx.clone(), unval) {
|
||||||
|
Ok((bctx, new_x_car)) => {
|
||||||
|
match map_unval_peval(bctx, dctx.clone(), Rc::clone(x_cdr)) {
|
||||||
|
MapUnvalPEvalResult::Ok(bctx, new_x_cdr) => MapUnvalPEvalResult::Ok(bctx, MarkedForm::new_pair(new_x_car, new_x_cdr)),
|
||||||
|
e => e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => MapUnvalPEvalResult::BadError(e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => MapUnvalPEvalResult::NotYet(e),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
MarkedForm::Int(i) => MapUnvalPEvalResult::BadError(anyhow!("map_unval_peval over not a list")),
|
||||||
|
MarkedForm::Bool(b) => MapUnvalPEvalResult::BadError(anyhow!("map_unval_peval over not a list")),
|
||||||
|
MarkedForm::Symbol(s) => MapUnvalPEvalResult::BadError(anyhow!("map_unval_peval over not a list")),
|
||||||
|
MarkedForm::PrimComb { .. } => MapUnvalPEvalResult::BadError(anyhow!("map_unval_peval over not a list")),
|
||||||
|
MarkedForm::Pair(ids,car,cdr) => MapUnvalPEvalResult::BadError(anyhow!("map_unval_peval over not a list")),
|
||||||
|
MarkedForm::DeriComb { ids, .. } => MapUnvalPEvalResult::BadError(anyhow!("map_unval_peval over not a list")),
|
||||||
|
|
||||||
|
MarkedForm::SuspendedSymbol(ids, name) => MapUnvalPEvalResult::NotYet(anyhow!("map_unval_peval over not (yet) a list")),
|
||||||
|
MarkedForm::SuspendedEnvLookup { id, .. } => MapUnvalPEvalResult::NotYet(anyhow!("map_unval_peval over not (yet) a list")),
|
||||||
|
MarkedForm::SuspendedParamLookup { id, .. } => MapUnvalPEvalResult::NotYet(anyhow!("map_unval_peval over not (yet) a list")),
|
||||||
|
MarkedForm::SuspendedEnvEval { ids, ..} => MapUnvalPEvalResult::NotYet(anyhow!("map_unval_peval over not (yet) a list")),
|
||||||
|
MarkedForm::SuspendedIf { ids, ..} => MapUnvalPEvalResult::NotYet(anyhow!("map_unval_peval over not (yet) a list")),
|
||||||
|
MarkedForm::SuspendedPair{ ids, .. } => MapUnvalPEvalResult::NotYet(anyhow!("map_unval_peval over not (yet) a list")),
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn partial_eval_step(x: &Rc<MarkedForm>, bctx: BCtx, dctx: &mut DCtx) -> Result<(BCtx,Rc<MarkedForm>)> {
|
||||||
//println!("{:ident$}({}) {}", "", dctx.ident, x, ident=dctx.ident*4);
|
//println!("{:ident$}({}) {}", "", dctx.ident, x, ident=dctx.ident*4);
|
||||||
match &**x {
|
match &**x {
|
||||||
MarkedForm::Pair(ids,car,cdr) => {
|
MarkedForm::Pair(ids,car,cdr) => {
|
||||||
//println!("{:ident$}pair ({}) {}", "", dctx.ident, x, ident=dctx.ident*4);
|
//println!("{:ident$}pair ({}) {}", "", dctx.ident, x, ident=dctx.ident*4);
|
||||||
let (bctx, car) = partial_eval(bctx, dctx.clone(), Rc::clone(car));
|
let (bctx, car) = partial_eval(bctx, dctx.clone(), Rc::clone(car));
|
||||||
let (bctx, cdr) = partial_eval(bctx, dctx.clone(), Rc::clone(cdr));
|
let (bctx, cdr) = partial_eval(bctx, dctx.clone(), Rc::clone(cdr));
|
||||||
Ok((bctx, false, MarkedForm::new_pair(car, cdr)))
|
Ok((bctx, MarkedForm::new_pair(car, cdr)))
|
||||||
},
|
},
|
||||||
MarkedForm::SuspendedSymbol(name) => {
|
MarkedForm::SuspendedSymbol(ids, name) => {
|
||||||
|
// Have to account for the *weird* case that the env chain ends in a suspended param / suspended env
|
||||||
println!("Lookin up symbol {}", name);
|
println!("Lookin up symbol {}", name);
|
||||||
let mut t = Rc::clone(&dctx.e);
|
let mut t = Rc::clone(&dctx.e);
|
||||||
while name != t.car()?.car()?.sym()? {
|
loop {
|
||||||
|
if let Some(cmp) = t.car().and_then(|kv| kv.car()).and_then(|s| s.sym()) {
|
||||||
|
if name == cmp {
|
||||||
|
return Ok((bctx, t.car()?.cdr()?.tag_name(name)));
|
||||||
|
} else {
|
||||||
t = t.cdr()?;
|
t = t.cdr()?;
|
||||||
}
|
}
|
||||||
println!("found it, pair is {}", t.car()?);
|
} else {
|
||||||
Ok((bctx, false, t.car()?.cdr()?.tag_name(name)))
|
// bad env
|
||||||
|
match &*t {
|
||||||
|
MarkedForm::Nil => bail!("Lookup for {} not found!", name),
|
||||||
|
MarkedForm::SuspendedSymbol(ids, name) => break,
|
||||||
|
MarkedForm::SuspendedEnvLookup { .. } => break,
|
||||||
|
MarkedForm::SuspendedParamLookup { .. } => break,
|
||||||
|
MarkedForm::SuspendedEnvEval { .. } => break,
|
||||||
|
MarkedForm::SuspendedIf { .. } => break,
|
||||||
|
MarkedForm::SuspendedPair { .. } => break,
|
||||||
|
MarkedForm::Pair(ids,car,cdr) => break,
|
||||||
|
_ => bail!("Illegal lookup for {}", name),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok((bctx, Rc::new(MarkedForm::SuspendedSymbol(t.ids(), name))));
|
||||||
},
|
},
|
||||||
MarkedForm::SuspendedEnvLookup { name, id } => {
|
MarkedForm::SuspendedEnvLookup { name, id } => {
|
||||||
if let Some(v) = dctx.sus_env_stack.get(id) {
|
if let Some(v) = dctx.sus_env_stack.get(id) {
|
||||||
Ok((bctx, false, if let Some(name) = name { v.tag_name(name) } else { Rc::clone(v) }))
|
Ok((bctx, if let Some(name) = name { v.tag_name(name) } else { Rc::clone(v) }))
|
||||||
} else {
|
} else {
|
||||||
Err("failed env lookup (forced)".to_owned())
|
panic!("failed env lookup (forced)");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } => {
|
MarkedForm::SuspendedParamLookup { name, id, cdr_num, car } => {
|
||||||
@@ -782,9 +796,9 @@ fn partial_eval_step(x: &Rc<MarkedForm>, forced: bool, bctx: BCtx, dctx: &mut DC
|
|||||||
if *car {
|
if *car {
|
||||||
translated_value = translated_value.car()?;
|
translated_value = translated_value.car()?;
|
||||||
}
|
}
|
||||||
Ok((bctx, false, translated_value))
|
Ok((bctx, translated_value))
|
||||||
} else {
|
} else {
|
||||||
Err("failed param lookup (forced)".to_owned())
|
panic!("failed param lookup (forced)");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MarkedForm::SuspendedEnvEval { x, e, .. } => {
|
MarkedForm::SuspendedEnvEval { x, e, .. } => {
|
||||||
@@ -793,89 +807,91 @@ fn partial_eval_step(x: &Rc<MarkedForm>, forced: bool, bctx: BCtx, dctx: &mut DC
|
|||||||
let (bctx, e) = partial_eval(bctx, dctx.clone(), Rc::clone(e));
|
let (bctx, e) = partial_eval(bctx, dctx.clone(), Rc::clone(e));
|
||||||
let (bctx, x) = partial_eval(bctx, dctx.copy_set_env(&e), Rc::clone(x));
|
let (bctx, x) = partial_eval(bctx, dctx.copy_set_env(&e), Rc::clone(x));
|
||||||
if x.is_value() {
|
if x.is_value() {
|
||||||
Ok((bctx, false, x))
|
Ok((bctx, x))
|
||||||
} else {
|
} else {
|
||||||
Ok((bctx, false, MarkedForm::new_suspended_env_eval(x, e)))
|
Ok((bctx, MarkedForm::new_suspended_env_eval(x, e)))
|
||||||
}
|
}
|
||||||
// Note also that we drop redundent vevals at the bottom of the loop tail-call loop
|
// Note also that we drop redundent vevals at the bottom of the loop tail-call loop
|
||||||
// with force
|
// with force
|
||||||
},
|
},
|
||||||
MarkedForm::SuspendedIf { c, t, e, .. } => {
|
MarkedForm::SuspendedIf { c, t, e, .. } => {
|
||||||
let (bctx, c) = partial_eval(bctx, dctx.clone(), Rc::clone(c));
|
let (bctx, c) = partial_eval(bctx, dctx.clone(), Rc::clone(c))?;
|
||||||
if let Ok(b) = c.truthy() {
|
if let Ok(b) = c.truthy() {
|
||||||
if b {
|
if b {
|
||||||
Ok((bctx, false, Rc::clone(t)))
|
Ok((bctx, Rc::clone(t)))
|
||||||
} else {
|
} else {
|
||||||
Ok((bctx, false, Rc::clone(e)))
|
Ok((bctx, Rc::clone(e)))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let dctx = dctx.copy_push_fake_if();
|
let (could_stop, dctx) = dctx.copy_push_fake_if();
|
||||||
let (bctx, t) = partial_eval(bctx, dctx.clone(), Rc::clone(t));
|
let (bctx, t) = partial_eval(bctx, dctx.clone(), Rc::clone(t))?;
|
||||||
let (bctx, e) = partial_eval(bctx, dctx.clone(), Rc::clone(e));
|
let (bctx, e) = partial_eval(bctx, dctx.clone(), Rc::clone(e))?;
|
||||||
Ok((bctx, false, MarkedForm::new_suspended_if(c,t,e, None)))
|
// if either t or e stopped because of our fake if (SO CHECK IF IT WAS US AT PUSH TIME),
|
||||||
|
// guard on our condition with that branch in tail
|
||||||
|
let c_ids = c.ids();
|
||||||
|
let t_ids = t.ids();
|
||||||
|
let e_ids = e.ids();
|
||||||
|
let ids = if let Some(this_id) = could_stop {
|
||||||
|
let ids = if t_ids.contains_if_stop(this_id) {
|
||||||
|
ids.union_into_tail(&t_ids)
|
||||||
|
} else { c_ids.union(&t_ids) };
|
||||||
|
if e_ids.contains_if_stop(this_id) {
|
||||||
|
ids.union_into_tail(&e_ids)
|
||||||
|
} else { ids.union(&e_ids) }
|
||||||
|
} else {
|
||||||
|
c_ids.union(&t_ids).union(&e_ids)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((bctx, Rc::new(MarkedForm::SuspendedIf {ids, c, t, e })))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MarkedForm::DeriComb { lookup_name, ids, se, de, id, wrap_level, sequence_params, rest_params, body } => {
|
MarkedForm::DeriComb { lookup_name, ids, se, de, id, wrap_level, sequence_params, rest_params, body } => {
|
||||||
// TODO: figure out wrap level, sequence params, etc
|
// TODO: figure out wrap level, sequence params, etc
|
||||||
if forced || !se.ids().needs_nothing() {
|
if !se.is_value() {
|
||||||
let old_se_ids = se.ids();
|
|
||||||
let se = if !se.ids().needs_nothing() {
|
|
||||||
// the current env is our new se
|
// the current env is our new se
|
||||||
Rc::clone(&dctx.e)
|
let se = Rc::clone(&dctx.e);
|
||||||
} else {
|
|
||||||
Rc::clone(se)
|
|
||||||
};
|
|
||||||
|
|
||||||
let ident_amount = dctx.ident*4;
|
let ident_amount = dctx.ident*4;
|
||||||
|
|
||||||
match dctx.copy_push_frame(id.clone(), &se, &de, None, &rest_params, None, body) {
|
match dctx.copy_push_frame(id.clone(), &se, &de, None, &rest_params, None, body) {
|
||||||
Ok(inner_dctx) => {
|
Ok(inner_dctx) => {
|
||||||
println!("{:ident$}Doing a body deri for {:?} because ({} || {:?}) which is {}", "", lookup_name, forced, old_se_ids, x, ident=ident_amount);
|
println!("{:ident$}Doing a body deri for {:?} because {:?} which is {}", "", lookup_name, old_se_ids, x, ident=ident_amount);
|
||||||
println!("{:ident$}and also body ids is {:?}", "", body.ids(), ident=ident_amount);
|
println!("{:ident$}and also body ids is {:?}", "", body.ids(), ident=ident_amount);
|
||||||
//println!("{:ident$}and fake is {:?} and fake_if is {:?}", "", , ident=ident_amount);
|
let (bctx, body) = partial_eval(bctx, inner_dctx, Rc::clone(&body))?;
|
||||||
let (bctx, body) = partial_eval(bctx, inner_dctx, Rc::clone(&body));
|
|
||||||
println!("{:ident$}result was {}", "", body, ident=ident_amount);
|
println!("{:ident$}result was {}", "", body, ident=ident_amount);
|
||||||
Ok((bctx, false, MarkedForm::new_deri_comb(se, lookup_name.clone(), de.clone(), id.clone(), *wrap_level, sequence_params.clone(), rest_params.clone(), body, None)))
|
Ok((bctx, MarkedForm::new_deri_comb(se, lookup_name.clone(), de.clone(), id.clone(), *wrap_level, sequence_params.clone(), rest_params.clone(), body, None)))
|
||||||
},
|
},
|
||||||
Err(rec_stop_under) => {
|
Err(rec_stop_under) => {
|
||||||
println!("{:ident$}call of {:?} failed b/c rec_stop_under", "", lookup_name, ident=dctx.ident*4);
|
println!("{:ident$}call of {:?} failed b/c rec_stop_under", "", lookup_name, ident=dctx.ident*4);
|
||||||
Ok((bctx, false, MarkedForm::new_deri_comb(se, lookup_name.clone(), de.clone(), id.clone(), *wrap_level, sequence_params.clone(), rest_params.clone(), Rc::clone(body), Some(rec_stop_under))))
|
Ok((bctx, MarkedForm::new_deri_comb(se, lookup_name.clone(), de.clone(), id.clone(), *wrap_level, sequence_params.clone(), rest_params.clone(), Rc::clone(body), Some(rec_stop_under))))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//panic!("impossible {}", x);
|
panic!("impossible {}", x);
|
||||||
Err("impossible!?".to_owned())
|
//bail!("impossible!?")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
MarkedForm::SuspendedPair { ids, attempted, car, cdr } => {
|
MarkedForm::SuspendedPair { ids, call_ids, car, cdr } => {
|
||||||
let ( bctx, mut car) = partial_eval(bctx, dctx.clone(), Rc::clone(car));
|
let ( bctx, mut car) = partial_eval(bctx, dctx.clone(), Rc::clone(car))?;
|
||||||
let (mut bctx, mut cdr) = partial_eval(bctx, dctx.clone(), Rc::clone(cdr));
|
let (mut bctx, mut cdr) = partial_eval(bctx, dctx.clone(), Rc::clone(cdr))?;
|
||||||
let mut new_attempted = attempted.clone();
|
|
||||||
let mut maybe_rec_under = None;
|
let mut maybe_rec_under = None;
|
||||||
let mut return_ok = false;
|
|
||||||
while let Some(wrap_level) = car.wrap_level() {
|
while let Some(wrap_level) = car.wrap_level() {
|
||||||
if wrap_level > 0 {
|
if wrap_level > 0 {
|
||||||
fn map_unval_peval(bctx: BCtx, dctx: DCtx, x: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>),String> {
|
// two types of errors here - real ones, and ones that just prevent evaluating
|
||||||
match &*x {
|
// the entire parameter list right now due to suspended
|
||||||
MarkedForm::Pair(ids, x_car, x_cdr) => {
|
match map_unval_peval(bctx.clone(), dctx.clone(), Rc::clone(&cdr))? {
|
||||||
let (bctx, new_x_car) = partial_eval(bctx, dctx.clone(), x_car.unval()?);
|
MapUnvalPEvalResult::Ok(new_bctx, new_cdr) => {
|
||||||
let (bctx, new_x_cdr) = map_unval_peval(bctx, dctx.clone(), Rc::clone(x_cdr))?;
|
|
||||||
return Ok((bctx, MarkedForm::new_pair(new_x_car, new_x_cdr)));
|
|
||||||
},
|
|
||||||
MarkedForm::Nil => return Ok((bctx,x)),
|
|
||||||
_ => return Err("not a list".to_owned()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
match map_unval_peval(bctx.clone(), dctx.clone(), Rc::clone(&cdr)) {
|
|
||||||
Ok((new_bctx, new_cdr)) => {
|
|
||||||
car = car.decrement_wrap_level().unwrap();
|
car = car.decrement_wrap_level().unwrap();
|
||||||
cdr = new_cdr;
|
cdr = new_cdr;
|
||||||
bctx = new_bctx;
|
bctx = new_bctx;
|
||||||
}
|
},
|
||||||
Err(msg) => {
|
MapUnvalPEvalResult::NotYet(e) => {
|
||||||
println!("{:ident$} evaling parameters failed b/c {}", "", msg, ident=dctx.ident*4);
|
println!("{:ident$} evaling parameters failed (for now) b/c {:?}", "", e, ident=dctx.ident*4);
|
||||||
break;
|
break;
|
||||||
}
|
},
|
||||||
|
MapUnvalPEvalResult::BadError(e) => {
|
||||||
|
println!("{:ident$} evaling parameters failed (FOREVER) b/c {:?}", "", e, ident=dctx.ident*4);
|
||||||
|
return Err(e);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// check to see if can do call
|
// check to see if can do call
|
||||||
@@ -885,37 +901,26 @@ fn partial_eval_step(x: &Rc<MarkedForm>, forced: bool, bctx: BCtx, dctx: &mut DC
|
|||||||
if !nonval_ok && !cdr.is_value() {
|
if !nonval_ok && !cdr.is_value() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
new_attempted = Attempted::True(if *takes_de { Some(dctx.e.ids()) } else { None });
|
println!("{:ident$}doing a call eval of {}", "", name, ident=dctx.ident*4);
|
||||||
let ident_amount = dctx.ident*4;
|
println!("{:ident$}parameters {} are? a val because {:?}", "", cdr, cdr.ids(), ident=dctx.ident*4);
|
||||||
println!("{:ident$}doing a call eval of {}", "", name, ident=ident_amount);
|
return f(bctx.clone(), dctx.clone(), Rc::clone(&cdr));
|
||||||
println!("{:ident$}parameters {} are? a val because {:?}", "", cdr, cdr.ids(), ident=ident_amount);
|
|
||||||
match f(bctx.clone(), dctx.clone(), Rc::clone(&cdr)) {
|
|
||||||
Ok((bctxp, r)) => {
|
|
||||||
// force true b/c might be a tail call
|
|
||||||
return Ok((bctx, true, r));
|
|
||||||
//return Ok((bctx, name == "eval" || name == "if", r));
|
|
||||||
},
|
|
||||||
Err(msg) => {
|
|
||||||
println!("{:ident$} call to {} failed {:?}", "", name, msg, ident=ident_amount);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
MarkedForm::DeriComb { lookup_name, ids, se, de, id, wrap_level, sequence_params, rest_params, body } => {
|
MarkedForm::DeriComb { lookup_name, ids, se, de, id, wrap_level, sequence_params, rest_params, body } => {
|
||||||
if !cdr.is_value() {
|
if !cdr.is_value() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
new_attempted = Attempted::True(if de.is_some() { Some(dctx.e.ids()) } else { None });
|
//new_attempted = Attempted::True(if de.is_some() { Some(dctx.e.ids()) } else { None });
|
||||||
if de.is_some() && dctx.e.ids().may_contain_id(id.clone()) {
|
if de.is_some() && dctx.e.ids().may_contain_id(id.clone()) {
|
||||||
// The current environment may contain a reference to our ID, which
|
// The current environment may contain a reference to our ID, which
|
||||||
// means if we take that environment, if we then PE that
|
// means if we take that environment, if we then PE that
|
||||||
// environment we will replace it with our real environment that
|
// environment we will replace it with our real environment that
|
||||||
// still has a dynamic reference to the current environment, which
|
// still has a dynamic reference to the current environment, which
|
||||||
// will be an infinate loop
|
// will be an infinate loop
|
||||||
break;
|
return Ok((bctx, MarkedForm::new_suspended_pair( Some(NeededIds::new_single(id.clone())), car, cdr, None, None)));
|
||||||
}
|
}
|
||||||
// not yet supporting sequence params
|
// not yet supporting sequence params
|
||||||
match dctx.copy_push_frame(id.clone(), &se, &de, Some(Rc::clone(&dctx.e)), &rest_params, Some(Rc::clone(&cdr)), body) {
|
match dctx.copy_push_frame(id.clone(), &se, &de, Some(Rc::clone(&dctx.e)), &rest_params, Some(Rc::clone(&cdr)), body) {
|
||||||
Ok(inner_dctx) => {
|
PushFrameResult::Ok(inner_dctx) => {
|
||||||
let ident_amount = inner_dctx.ident*4;
|
let ident_amount = inner_dctx.ident*4;
|
||||||
//println!("{:ident$}doing a call eval of {} in {}", "", body, inner_dctx.e, ident=inner_dctx.ident*4);
|
//println!("{:ident$}doing a call eval of {} in {}", "", body, inner_dctx.e, ident=inner_dctx.ident*4);
|
||||||
println!("{:ident$}doing a call eval of {:?}", "", lookup_name, ident=ident_amount);
|
println!("{:ident$}doing a call eval of {:?}", "", lookup_name, ident=ident_amount);
|
||||||
@@ -923,27 +928,42 @@ fn partial_eval_step(x: &Rc<MarkedForm>, forced: bool, bctx: BCtx, dctx: &mut DC
|
|||||||
|
|
||||||
//Here is where we could do a tail call instead, but there
|
//Here is where we could do a tail call instead, but there
|
||||||
//would be no recovery back into the call-form...
|
//would be no recovery back into the call-form...
|
||||||
let (bctx, r) = partial_eval(bctx.clone(), inner_dctx, Rc::clone(body));
|
let (bctx, r) = partial_eval(bctx.clone(), inner_dctx, Rc::clone(body))?;
|
||||||
if combiner_return_ok(&r, Some(id.clone())) {
|
if combiner_return_ok(&r, Some(id.clone())) {
|
||||||
return Ok((bctx, false, r));
|
return Ok((bctx, false, r));
|
||||||
|
} else {
|
||||||
|
return Ok((bctx, MarkedForm::new_suspended_pair( Some(r.ids()), car, cdr, None, None)));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(rec_stop_under) => {
|
PushFrameResult::UnderBody(rec_stop_under) => {
|
||||||
println!("{:ident$}call of {:?} failed b/c rec_stop_under", "", lookup_name, ident=dctx.ident*4);
|
println!("{:ident$}call of {:?} failed b/c rec_stop_under of body", "", lookup_name, ident=dctx.ident*4);
|
||||||
maybe_rec_under = Some(rec_stop_under);
|
return Ok((bctx, MarkedForm::new_suspended_pair( None, car, cdr, Some(rec_stop_under), None)));
|
||||||
|
},
|
||||||
|
PushFrameResult::UnderIf(rec_stop_under) => {
|
||||||
|
println!("{:ident$}call of {:?} failed b/c rec_stop_under of if", "", lookup_name, ident=dctx.ident*4);
|
||||||
|
return Ok((bctx, MarkedForm::new_suspended_pair( None, car, cdr, None, Some(rec_stop_under))));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {},
|
// These are illegal values
|
||||||
|
MarkedForm::Nil => bail("tried to call a bad value {:?}", car),
|
||||||
|
MarkedForm::Pair(ids, x_car, x_cdr) => bail("tried to call a bad value {:?}", car),
|
||||||
|
MarkedForm::Int(i) => bail("tried to call a bad value {:?}", car),
|
||||||
|
MarkedForm::Bool(b) => bail("tried to call a bad value {:?}", car),
|
||||||
|
MarkedForm::Symbol(s) => bail("tried to call a bad value {:?}", car),
|
||||||
|
MarkedForm::PrimComb { .. } => bail("tried to call a bad value {:?}", car),
|
||||||
|
MarkedForm::Pair(ids,car,cdr) => bail("tried to call a bad value {:?}", car),
|
||||||
|
MarkedForm::DeriComb { ids, .. } => bail("tried to call a bad value {:?}", car),
|
||||||
|
_ => {}, // suspended, so reform
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Call failed, do the re-wrap-up ourselves b/c of our possibly advanced wrap/params
|
// Didn't manage to call
|
||||||
Ok((bctx, false, MarkedForm::new_suspended_pair( new_attempted, car, cdr, maybe_rec_under )))
|
Ok((bctx, MarkedForm::new_suspended_pair( None, car, cdr, None, None)))
|
||||||
},
|
},
|
||||||
// Values should never get here b/c ids UNLESS FORCE HAH
|
// Values should never get here b/c ids UNLESS FORCE HAH
|
||||||
_ => Err("value evaled".to_owned()),
|
_ => panic!("value evaled! {}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -988,7 +1008,7 @@ impl fmt::Display for MarkedForm {
|
|||||||
write!(f, "{:?}#[{:?}/{:?}/{:?}/{}/{:?}/{:?}/{}]", ids, lookup_name, de, id, wrap_level, sequence_params, rest_params, body)
|
write!(f, "{:?}#[{:?}/{:?}/{:?}/{}/{:?}/{:?}/{}]", ids, lookup_name, de, id, wrap_level, sequence_params, rest_params, body)
|
||||||
},
|
},
|
||||||
|
|
||||||
MarkedForm::SuspendedPair{ ids, attempted, car, cdr } => {
|
MarkedForm::SuspendedPair{ ids, call_ids, car, cdr } => {
|
||||||
//write!(f, "{:?}{:?}#{{{}", ids, attempted, car)?;
|
//write!(f, "{:?}{:?}#{{{}", ids, attempted, car)?;
|
||||||
write!(f, "{{{}", car)?;
|
write!(f, "{{{}", car)?;
|
||||||
let mut traverse: Rc<MarkedForm> = Rc::clone(cdr);
|
let mut traverse: Rc<MarkedForm> = Rc::clone(cdr);
|
||||||
|
|||||||
Reference in New Issue
Block a user