Commit f100043f by Jeff Smits

Put common patterns such as chained Seq and LGChoice into lists, which speeds things up nicely

parent cfd4c0ca
......@@ -142,6 +142,18 @@ impl<'d, 'f : 'd> MutContext<'d, 'f> {
);
}
pub fn clear_overlay(&self) {
let mut scopes = self.scopes.borrow_mut();
let last_scope = scopes.last_mut().expect(
"clear_overlay: Interpreter bug, unexpected end of stack",
);
debug_assert!(
last_scope.is_overlay,
"clear_overlay: Interpreter bug, unexpected normal scope"
);
last_scope.term.clear();
}
pub fn pop_scope(&self) {
let scope = self.scopes.borrow_mut().pop().expect(
"pop_scope: Interpreter bug, unexpected end of stack",
......
......@@ -198,27 +198,32 @@ impl<'d, 'f : 'd> Eval<'d, 'f> for preprocess::Strategy {
context.pop_scope();
result
}
Seq(ref strat1, ref strat2) => {
let current = strat1.eval(context, current)?;
strat2.eval(context, current)
Seq(ref strats) => {
let mut current = current;
for strat in strats.iter() {
current = strat.eval(context, current)?;
}
Ok(current)
}
GuardedLChoice(ref s_if, ref s_then, ref s_else) => {
GuardedLChoice(ref s_if_then, ref s_else) => {
context.push_overlay();
match s_if.eval(context, current.clone()) {
Ok(current) => {
context.apply_overlay();
s_then.eval(context, current)
}
Err(Error::StrategyFailed) => {
// TODO: pull off the overlay, apply it after the s_else branch, but only where the s_else branch left variables unbound. This is the semantics that strc and strj use.
context.drop_overlay();
s_else.eval(context, current)
}
Err(e) => {
context.drop_overlay();
Err(e)
for &(ref s_if, ref s_then) in s_if_then.iter() {
match s_if.eval(context, current.clone()) {
Ok(current) => {
context.apply_overlay();
return s_then.eval(context, current);
}
Err(Error::StrategyFailed) => {
context.clear_overlay();
}
Err(e) => {
context.drop_overlay();
return Err(e);
}
}
}
context.drop_overlay();
s_else.eval(context, current)
}
PrimT(ref name, ref sargs, ref targs) => {
let sargs = sargs
......
......@@ -161,8 +161,8 @@ pub enum Strategy {
Match(MatchTerm),
Build(BuildTerm),
Scope(Vec<String>, Box<Strategy>),
Seq(Box<Strategy>, Box<Strategy>),
GuardedLChoice(Box<Strategy>, Box<Strategy>, Box<Strategy>),
Seq(Box<[Strategy]>),
GuardedLChoice(Box<[(Strategy, Strategy)]>, Box<Strategy>),
PrimT(String, Vec<Strategy>, Vec<BuildTerm>),
Some(Box<Strategy>),
One(Box<Strategy>),
......@@ -204,13 +204,26 @@ impl TryFrom<ctree::Strategy> for Strategy {
I::Build(build_term) => build_term.try_into().map(O::Build),
I::Scope(fresh_vars, body) => try_into_box(body).map(|body| O::Scope(fresh_vars, body)),
I::Seq(first, second) => {
let first = try_into_box(first)?;
try_into_box(second).map(|second| O::Seq(first, second))
let mut children = Vec::new();
children.push((*first).try_into()?);
let mut value = *second;
while let I::Seq(first, second) = value {
children.push((*first).try_into()?);
value = *second;
}
children.push(value.try_into()?);
Ok(O::Seq(children.into_boxed_slice()))
}
I::GuardedLChoice(s_if, s_then, s_else) => {
let s_if = try_into_box(s_if)?;
let s_then = try_into_box(s_then)?;
try_into_box(s_else).map(|s_else| O::GuardedLChoice(s_if, s_then, s_else))
let mut children = Vec::new();
children.push(((*s_if).try_into()?, (*s_then).try_into()?));
let mut value = *s_else;
while let I::GuardedLChoice(s_if, s_then, s_else) = value {
children.push(((*s_if).try_into()?, (*s_then).try_into()?));
value = *s_else;
}
let s_else = Box::new(value.try_into()?);
Ok(O::GuardedLChoice(children.into_boxed_slice(), s_else))
}
I::PrimT(prim_name, sargs, targs) => {
let t = try_into_vec(targs)?;
......
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