Add rec-hash-stopping for SuspendedPair calls
This commit is contained in:
@@ -123,7 +123,7 @@ impl Form {
|
|||||||
let sequence_params = vec![];
|
let sequence_params = vec![];
|
||||||
let rest_params = Some(params);
|
let rest_params = Some(params);
|
||||||
//
|
//
|
||||||
let inner_dctx = dctx.copy_push_frame(id.clone(), &se, &de, None, &rest_params, None);
|
let inner_dctx = dctx.copy_push_frame(id.clone(), &se, &de, None, &rest_params, None, &body).unwrap();
|
||||||
let (bctx, body) = partial_eval(bctx, inner_dctx, Rc::clone(&body))?;
|
let (bctx, body) = partial_eval(bctx, inner_dctx, Rc::clone(&body))?;
|
||||||
Ok((bctx, PossibleMarkedTailCall::Result(MarkedForm::new_deri_comb( se, de, id, wrap_level, sequence_params, rest_params, body ))))
|
Ok((bctx, PossibleMarkedTailCall::Result(MarkedForm::new_deri_comb( se, de, id, wrap_level, sequence_params, rest_params, body ))))
|
||||||
}}),
|
}}),
|
||||||
@@ -323,6 +323,13 @@ impl fmt::Display for Form {
|
|||||||
pub struct EnvID(i32);
|
pub struct EnvID(i32);
|
||||||
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd)]
|
||||||
pub struct MFHash(u64);
|
pub struct MFHash(u64);
|
||||||
|
impl MFHash {
|
||||||
|
pub fn combine(&self, other: &MFHash) -> Self {
|
||||||
|
let mut h = DefaultHasher::new();
|
||||||
|
"combine/".hash(&mut h); self.0.hash(&mut h); other.hash(&mut h);
|
||||||
|
MFHash(h.finish())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
|
||||||
pub enum NeededIds {
|
pub enum NeededIds {
|
||||||
@@ -434,7 +441,7 @@ 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), 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), force: self.force, current: Rc::clone(&self.current), ident: self.ident+1 }
|
DCtx { e: Rc::clone(e), 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), force: self.force, current: Rc::clone(&self.current), 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>>) -> Self {
|
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,MFHash> {
|
||||||
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 = Rc::clone(&self.real_set);
|
let mut real_set = Rc::clone(&self.real_set);
|
||||||
@@ -460,9 +467,15 @@ impl DCtx {
|
|||||||
};
|
};
|
||||||
massoc(p, p_val, inner_env)
|
massoc(p, p_val, inner_env)
|
||||||
} else { inner_env };
|
} else { inner_env };
|
||||||
// Push on current frame hash?!
|
// Push on current frame hash
|
||||||
let new_current = Rc::clone(&self.current);
|
let new_hash = inner_env.hash().combine(&body.hash());
|
||||||
DCtx { e: inner_env, sus_env_stack, sus_prm_stack, real_set, force: self.force, current: new_current, ident: self.ident+1 }
|
if self.current.contains(&new_hash) {
|
||||||
|
println!("Hash Rec Stop!");
|
||||||
|
Err(new_hash)
|
||||||
|
} else {
|
||||||
|
let new_current = Rc::new(self.current.iter().cloned().chain(iter::once(new_hash)).collect());
|
||||||
|
Ok(DCtx { e: inner_env, sus_env_stack, sus_prm_stack, real_set, force: self.force, current: new_current, ident: self.ident+1 })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_progress(&self, ids: NeededIds) -> bool {
|
pub fn can_progress(&self, ids: NeededIds) -> bool {
|
||||||
@@ -581,6 +594,7 @@ pub fn partial_eval(bctx: BCtx, dctx: DCtx, x: Rc<MarkedForm>) -> Result<(BCtx,R
|
|||||||
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 new_attempted = attempted.clone();
|
||||||
|
let mut maybe_rec_hash = None;
|
||||||
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> {
|
fn map_unval_peval(bctx: BCtx, dctx: DCtx, x: Rc<MarkedForm>) -> Result<(BCtx,Rc<MarkedForm>),String> {
|
||||||
@@ -636,14 +650,18 @@ pub fn partial_eval(bctx: BCtx, dctx: DCtx, x: Rc<MarkedForm>) -> Result<(BCtx,R
|
|||||||
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 });
|
||||||
// not yet supporting sequence params
|
// not yet supporting sequence params
|
||||||
// needs to check hash
|
// needs to check hash
|
||||||
let inner_dctx = dctx.copy_push_frame(id.clone(), &se, &de, Some(Rc::clone(&dctx.e)), &rest_params, Some(Rc::clone(&cdr)));
|
match dctx.copy_push_frame(id.clone(), &se, &de, Some(Rc::clone(&dctx.e)), &rest_params, Some(Rc::clone(&cdr)), body) {
|
||||||
// check for id in it?
|
Ok(inner_dctx) => {
|
||||||
// needs to check return OK
|
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);
|
if let Ok((bctx, r)) = partial_eval(bctx.clone(), inner_dctx, Rc::clone(body)) {
|
||||||
if let Ok((bctx, r)) = partial_eval(bctx.clone(), inner_dctx, Rc::clone(body)) {
|
if combiner_return_ok(Rc::clone(&r), id.clone()) {
|
||||||
if combiner_return_ok(Rc::clone(&r), id.clone()) {
|
return Ok((bctx, r));
|
||||||
return Ok((bctx, r));
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
Err(rec_stop_hash) => {
|
||||||
|
maybe_rec_hash = Some(rec_stop_hash);
|
||||||
|
},
|
||||||
}
|
}
|
||||||
break; // failed call for one reason or the other
|
break; // failed call for one reason or the other
|
||||||
},
|
},
|
||||||
@@ -651,7 +669,7 @@ pub fn partial_eval(bctx: BCtx, dctx: DCtx, x: Rc<MarkedForm>) -> Result<(BCtx,R
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok((bctx, MarkedForm::new_suspended_pair( new_attempted, car, cdr )))
|
Ok((bctx, MarkedForm::new_suspended_pair( new_attempted, car, cdr, maybe_rec_hash )))
|
||||||
},
|
},
|
||||||
MarkedForm::Pair(h,ids,car,cdr) => {
|
MarkedForm::Pair(h,ids,car,cdr) => {
|
||||||
let (bctx, car) = partial_eval(bctx, dctx.clone(), Rc::clone(car))?;
|
let (bctx, car) = partial_eval(bctx, dctx.clone(), Rc::clone(car))?;
|
||||||
@@ -662,7 +680,7 @@ pub fn partial_eval(bctx: BCtx, dctx: DCtx, x: Rc<MarkedForm>) -> Result<(BCtx,R
|
|||||||
if !se.ids().needs_nothing() {
|
if !se.ids().needs_nothing() {
|
||||||
// the current env is our new se
|
// the current env is our new se
|
||||||
let se = Rc::clone(&dctx.e);
|
let se = Rc::clone(&dctx.e);
|
||||||
let inner_dctx = dctx.copy_push_frame(id.clone(), &se, &de, None, &rest_params, None);
|
let inner_dctx = dctx.copy_push_frame(id.clone(), &se, &de, None, &rest_params, None, body).expect("Not sure if this can ever fail or not... maybe for Y comb recursion?");
|
||||||
let (bctx, body) = partial_eval(bctx, inner_dctx, Rc::clone(&body))?;
|
let (bctx, body) = partial_eval(bctx, inner_dctx, Rc::clone(&body))?;
|
||||||
Ok((bctx, MarkedForm::new_deri_comb( se, de.clone(), id.clone(), *wrap_level, sequence_params.clone(), rest_params.clone(), body )))
|
Ok((bctx, MarkedForm::new_deri_comb( se, de.clone(), id.clone(), *wrap_level, sequence_params.clone(), rest_params.clone(), body )))
|
||||||
} else {
|
} else {
|
||||||
@@ -701,7 +719,7 @@ impl MarkedForm {
|
|||||||
"Pair(ids,car,cdr)".hash(&mut h); car.hash().hash(&mut h); cdr.hash().hash(&mut h);
|
"Pair(ids,car,cdr)".hash(&mut h); car.hash().hash(&mut h); cdr.hash().hash(&mut h);
|
||||||
Rc::new(MarkedForm::Pair(MFHash(h.finish()), car.ids().union(&cdr.ids()), car, cdr))
|
Rc::new(MarkedForm::Pair(MFHash(h.finish()), car.ids().union(&cdr.ids()), car, cdr))
|
||||||
}
|
}
|
||||||
pub fn new_suspended_pair(attempted: Attempted, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
pub fn new_suspended_pair(attempted: Attempted, car: Rc<MarkedForm>, cdr: Rc<MarkedForm>, rec_hash: Option<MFHash>) -> Rc<MarkedForm> {
|
||||||
let mut h = DefaultHasher::new();
|
let mut h = DefaultHasher::new();
|
||||||
"SuspendedPair".hash(&mut h); attempted.hash(&mut h); car.hash().hash(&mut h); cdr.hash().hash(&mut h);
|
"SuspendedPair".hash(&mut h); attempted.hash(&mut h); car.hash().hash(&mut h); cdr.hash().hash(&mut h);
|
||||||
let ids = car.ids().union(&cdr.ids());
|
let ids = car.ids().union(&cdr.ids());
|
||||||
@@ -714,6 +732,9 @@ impl MarkedForm {
|
|||||||
},
|
},
|
||||||
NeededIds::Some(_,_) => ids,
|
NeededIds::Some(_,_) => ids,
|
||||||
};
|
};
|
||||||
|
if let Some(rec_hash) = rec_hash {
|
||||||
|
ids.add_hash(rec_hash);
|
||||||
|
}
|
||||||
Rc::new(MarkedForm::SuspendedPair{ hash: MFHash(h.finish()), attempted, ids, car, cdr })
|
Rc::new(MarkedForm::SuspendedPair{ hash: MFHash(h.finish()), attempted, ids, car, cdr })
|
||||||
}
|
}
|
||||||
pub fn new_deri_comb(se: Rc<MarkedForm>, de: Option<String>, id: EnvID, wrap_level: i32, sequence_params: Vec<String>, rest_params: Option<String>, body: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
pub fn new_deri_comb(se: Rc<MarkedForm>, de: Option<String>, id: EnvID, wrap_level: i32, sequence_params: Vec<String>, rest_params: Option<String>, body: Rc<MarkedForm>) -> Rc<MarkedForm> {
|
||||||
@@ -798,7 +819,7 @@ impl MarkedForm {
|
|||||||
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(s.clone()))),
|
||||||
MarkedForm::Pair(hash,ids,car,cdr) => Ok(MarkedForm::new_suspended_pair( Attempted::False, car.unval()?, Rc::clone(cdr))),
|
MarkedForm::Pair(hash,ids,car,cdr) => Ok(MarkedForm::new_suspended_pair( Attempted::False, car.unval()?, Rc::clone(cdr), None)),
|
||||||
MarkedForm::SuspendedSymbol(name) => Err("trying to unval a suspended symbol"),
|
MarkedForm::SuspendedSymbol(name) => Err("trying to unval a suspended symbol"),
|
||||||
MarkedForm::SuspendedEnvLookup { .. } => Err("trying to unval a suspended env lookup"),
|
MarkedForm::SuspendedEnvLookup { .. } => Err("trying to unval a suspended env lookup"),
|
||||||
MarkedForm::SuspendedParamLookup { .. } => Err("trying to unval a suspended param lookup"),
|
MarkedForm::SuspendedParamLookup { .. } => Err("trying to unval a suspended param lookup"),
|
||||||
|
|||||||
Reference in New Issue
Block a user