Commit 6d72c976 by Jeff Smits

Rudimentary "caching" (prebuilding) of MatchTerm

parent bd57bb10
......@@ -294,6 +294,8 @@ fn eval_match<'d, 'f: 'd>(
current: &ATermRef<'f>,
) -> Result<()> {
use preprocess::MatchTerm::*;
use preprocess::C;
match *match_term {
Var(s) => context.match_term(s, current),
Wld => Ok(()),
......@@ -404,6 +406,22 @@ fn eval_match<'d, 'f: 'd>(
}
Ok(())
}
Cached(C(ref cache), ref term) => {
if let Option::Some(ref cached_term) = *cache.borrow() {
if cached_term == current {
return Ok(())
} else {
return Err(Error::StrategyFailed)
}
}
let result = build_term::build(term, context)?;
*cache.borrow_mut() = Some(result.clone());
if result == *current {
return Ok(())
} else {
return Err(Error::StrategyFailed)
}
}
}
}
......
......@@ -365,7 +365,7 @@ impl<'a> TryFrom<ctree::Term<'a>> for BuildTerm<'a> {
type Err = Error;
fn try_from(value: ctree::Term) -> Result<BuildTerm> {
let (bt, est) = value.try_into()?;
let (bt, est) = btf(value)?;
if est.is_some() && est.unwrap() > BUILD_CACHED_THRESHOLD {
Ok(BuildTerm::Cached(C::new(), Box::new(bt)))
} else {
......@@ -374,6 +374,10 @@ impl<'a> TryFrom<ctree::Term<'a>> for BuildTerm<'a> {
}
}
fn btf(value: ctree::Term) -> Result<(BuildTerm, SizeEstimate)> {
value.try_into()
}
impl<'a> TryFrom<ctree::Term<'a>> for (BuildTerm<'a>, SizeEstimate) {
type Err = Error;
......@@ -458,59 +462,98 @@ pub enum MatchTerm<'a> {
Op(&'a str, Vec<MatchTerm<'a>>),
Explode(Box<MatchTerm<'a>>, Box<MatchTerm<'a>>),
As(&'a str, Box<MatchTerm<'a>>),
Cached(C<'a>, Box<BuildTerm<'a>>),
}
// After many thoughtful, reproducible experiments this is the empirically discovered sweet spot for
// caching MatchTerm. Yeah, if only, I just made an "educated guess"
const MATCH_CACHED_THRESHOLD: usize = 4;
impl<'a> TryFrom<ctree::Term<'a>> for MatchTerm<'a> {
type Err = Error;
fn try_from(value: ctree::Term) -> Result<MatchTerm> {
let (mt, est) = mtf(value.clone())?;
if est.is_some() && est.unwrap() > MATCH_CACHED_THRESHOLD {
if let Ok((bt, _)) = btf(value) {
return Ok(MatchTerm::Cached(C::new(), Box::new(bt)))
}
}
Ok(mt)
}
}
impl<'a> TryFrom<ctree::Term<'a>> for (MatchTerm<'a>, SizeEstimate) {
type Err = Error;
fn try_from(value: ctree::Term) -> Result<(MatchTerm, SizeEstimate)> {
use ctree::Term as I;
use self::MatchTerm as O;
use ctree::PreTerm as P;
match value {
I::Var(id) => Ok(O::Var(id)),
I::Var(id) => Ok((O::Var(id), None)),
I::Anno(term, annos) => {
match *annos {
P::Wld => (*term).try_into(),
_ => {
let pt1 = try_into_box(term)?;
let pt2 = try_into_box(annos)?;
Ok(O::Anno(pt1, pt2))
let (bt1, est1) = (*term).try_into()?;
let (bt2, est2) = (*annos).try_into()?;
let est = add_estimates_1(est1, est2);
Ok((O::Anno(Box::new(bt1), Box::new(bt2)), est))
}
}
}
I::Wld => Ok(O::Wld),
I::As(ctree::Var(v), t) => Ok(O::As(v, Box::new((*t).try_into()?))),
I::Wld => Ok((O::Wld, None)),
I::As(ctree::Var(v), t) => Ok((O::As(v, Box::new(mtf(*t)?.0)), None)),
}
}
}
fn mtf(value: ctree::Term) -> Result<(MatchTerm, SizeEstimate)> {
value.try_into()
}
impl<'a> TryFrom<ctree::PreTerm<'a>> for MatchTerm<'a> {
type Err = Error;
fn try_from(value: ctree::PreTerm) -> Result<MatchTerm> {
Ok(TryInto::<(MatchTerm, SizeEstimate)>::try_into(value)?.0)
}
}
impl<'a> TryFrom<ctree::PreTerm<'a>> for (MatchTerm<'a>, SizeEstimate) {
type Err = Error;
fn try_from(value: ctree::PreTerm) -> Result<(MatchTerm, SizeEstimate)> {
use self::MatchTerm as O;
use ctree::PreTerm as I;
match value {
I::Var(id) => Ok(O::Var(id)),
I::Int(i) => Ok(O::Int(i)),
I::Real(f) => Ok(O::Real(f)),
I::Str(s) => Ok(O::Str(s)),
I::Op(s, t) | I::OpQ(s, t) => {
let t = try_into_vec(t)?;
Ok(O::Op(s, t))
I::Var(id) => Ok((O::Var(id), None)),
I::Int(i) => Ok((O::Int(i), Some(1))),
I::Real(f) => Ok((O::Real(f), Some(1))),
I::Str(s) => Ok((O::Str(s), Some(1))),
I::Op(cons, children) |
I::OpQ(cons, children) => {
let (children, est): (Vec<_>, Vec<SizeEstimate>) = try_into_vec(children)?.into_iter().unzip();
let est = est.into_iter().fold(Some(1), add_estimates);
Ok((O::Op(cons, children), est))
}
I::Explode(t1, t2) => {
let t1 = t1.try_into()?;
let t2 = t2.try_into()?;
Ok(O::Explode(Box::new(t1), Box::new(t2)))
I::Explode(cons, children) => {
let (cons, est1) = cons.try_into()?;
let (children, est2) = children.try_into()?;
let est = add_estimates_1(est1, est2);
Ok((O::Explode(Box::new(cons), Box::new(children)), est))
}
I::Wld => Ok(O::Wld),
I::As(ctree::Var(v), t) => Ok(O::As(v, Box::new((*t).try_into()?))),
I::Wld => Ok((O::Wld, None)),
I::As(ctree::Var(v), t) => Ok((O::As(v, Box::new(mptf(*t)?.0)), None)),
}
}
}
fn mptf(value: ctree::PreTerm) -> Result<(MatchTerm, SizeEstimate)> {
value.try_into()
}
pub fn try_into_vec<T1, T2: TryFrom<T1>, I: IntoIterator<Item = T1>>(
v: I,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment