Commit f100043f authored by Jeff Smits's avatar 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> { ...@@ -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) { pub fn pop_scope(&self) {
let scope = self.scopes.borrow_mut().pop().expect( let scope = self.scopes.borrow_mut().pop().expect(
"pop_scope: Interpreter bug, unexpected end of stack", "pop_scope: Interpreter bug, unexpected end of stack",
......
...@@ -198,27 +198,32 @@ impl<'d, 'f : 'd> Eval<'d, 'f> for preprocess::Strategy { ...@@ -198,27 +198,32 @@ impl<'d, 'f : 'd> Eval<'d, 'f> for preprocess::Strategy {
context.pop_scope(); context.pop_scope();
result result
} }
Seq(ref strat1, ref strat2) => { Seq(ref strats) => {
let current = strat1.eval(context, current)?; let mut current = current;
strat2.eval(context, 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(); context.push_overlay();
match s_if.eval(context, current.clone()) { for &(ref s_if, ref s_then) in s_if_then.iter() {
Ok(current) => { match s_if.eval(context, current.clone()) {
context.apply_overlay(); Ok(current) => {
s_then.eval(context, current) context.apply_overlay();
} return 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. Err(Error::StrategyFailed) => {
context.drop_overlay(); context.clear_overlay();
s_else.eval(context, current) }
} Err(e) => {
Err(e) => { context.drop_overlay();
context.drop_overlay(); return Err(e);
Err(e) }
} }
} }
context.drop_overlay();
s_else.eval(context, current)
} }
PrimT(ref name, ref sargs, ref targs) => { PrimT(ref name, ref sargs, ref targs) => {
let sargs = sargs let sargs = sargs
......
...@@ -161,8 +161,8 @@ pub enum Strategy { ...@@ -161,8 +161,8 @@ pub enum Strategy {
Match(MatchTerm), Match(MatchTerm),
Build(BuildTerm), Build(BuildTerm),
Scope(Vec<String>, Box<Strategy>), Scope(Vec<String>, Box<Strategy>),
Seq(Box<Strategy>, Box<Strategy>), Seq(Box<[Strategy]>),
GuardedLChoice(Box<Strategy>, Box<Strategy>, Box<Strategy>), GuardedLChoice(Box<[(Strategy, Strategy)]>, Box<Strategy>),
PrimT(String, Vec<Strategy>, Vec<BuildTerm>), PrimT(String, Vec<Strategy>, Vec<BuildTerm>),
Some(Box<Strategy>), Some(Box<Strategy>),
One(Box<Strategy>), One(Box<Strategy>),
...@@ -204,13 +204,26 @@ impl TryFrom<ctree::Strategy> for Strategy { ...@@ -204,13 +204,26 @@ impl TryFrom<ctree::Strategy> for Strategy {
I::Build(build_term) => build_term.try_into().map(O::Build), 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::Scope(fresh_vars, body) => try_into_box(body).map(|body| O::Scope(fresh_vars, body)),
I::Seq(first, second) => { I::Seq(first, second) => {
let first = try_into_box(first)?; let mut children = Vec::new();
try_into_box(second).map(|second| O::Seq(first, second)) 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) => { I::GuardedLChoice(s_if, s_then, s_else) => {
let s_if = try_into_box(s_if)?; let mut children = Vec::new();
let s_then = try_into_box(s_then)?; children.push(((*s_if).try_into()?, (*s_then).try_into()?));
try_into_box(s_else).map(|s_else| O::GuardedLChoice(s_if, s_then, s_else)) 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) => { I::PrimT(prim_name, sargs, targs) => {
let t = try_into_vec(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