...
 
Commits (3)
......@@ -2,7 +2,7 @@
name = "strs"
version = "0.1.0"
dependencies = [
"aterm 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
"aterm 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)",
"fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -29,7 +29,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "aterm"
version = "0.19.1"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
......@@ -307,7 +307,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum aterm 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1cafec35b5dd56b9cd172b525d8b9bc7b454f7c24739d18b41e92e79c96a6ec8"
"checksum aterm 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6aa2928524c9bf20c6a14f9659cbfc535d92867a2a5163982601e3448e5aee7e"
"checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159"
"checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4"
"checksum clap 2.23.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f57e9b63057a545ad2ecd773ea61e49422ed1b1d63d74d5da5ecaee55b3396cd"
......
......@@ -13,7 +13,7 @@ version = "0.1.0"
phf_codegen = "0.7.21"
[dependencies]
aterm = "0.19.1"
aterm = "0.20.0"
fnv = "1.0.5"
linked-hash-map = "0.4.2"
phf = "0.7.21"
......
This diff is collapsed.
......@@ -91,6 +91,7 @@ pub fn interpret<'f>(
) -> result::Result<ATermRef<'f>, TracedError> {
use context::Scope;
use ctree::match_;
use std::iter;
let program = match match_(&program).and_then(preprocess) {
Ok(v) => v,
......@@ -100,13 +101,16 @@ pub fn interpret<'f>(
.libs
.into_iter()
.map(|l| match_(&l).and_then(preprocess))
.collect::<Result<Vec<_>>>() {
.collect::<Result<Vec<_>>>()
{
Ok(v) => v,
Err(e) => return Err(TracedError(e, String::new())),
};
let base_scopes = libs.iter().map(Scope::from_defs).collect();
let base_scopes = libs.iter()
.map(Scope::from_defs)
.chain(iter::once(Scope::from_defs(&program)))
.collect();
let context = MutContext::new(factory, base_scopes, libraries.prims);
context.push_scope(Scope::from_defs(&program));
let main = match context.get_strategy(strategy) {
Ok(v) => v,
Err(e) => {
......@@ -136,12 +140,16 @@ impl<'d, 'f: 'd> Eval<'d, 'f> for preprocess::Strategy<'f> {
use context;
match *self {
Let(ref defs, ref body) => {
use context::Scope;
let term_scope_offset = context.term.borrow().len();
// note the + 1, because `let`s allow recursive definitions
let no_of_scopes = context.scopes.borrow().len() + 1;
context.push_scope(context::Scope::from_let_defs(no_of_scopes, defs.iter()));
let result = body.eval(context, current);
context.pop_scope();
result
let strat_scope_offset = context.strategy.borrow().len() + 1;
let scope = Scope::from_let_defs(term_scope_offset, strat_scope_offset, defs.iter());
context.in_scope(scope, || {
body.eval(context, current)
})
}
CallT(name, ref sargs, ref targs) => {
let sdeft = context.get_strategy(name)?;
......@@ -196,12 +204,10 @@ impl<'d, 'f: 'd> Eval<'d, 'f> for preprocess::Strategy<'f> {
}
Build(ref term) => build_term::build(term, context),
Scope(ref fresh_names, ref body) => {
context.push_scope(context::Scope::from_fresh_variables(
fresh_names.iter().cloned(),
));
let result = body.eval(context, current);
context.pop_scope();
result
context.in_scope(
context::Scope::from_fresh_variables(fresh_names.iter().cloned()),
|| body.eval(context, current),
)
}
Seq(ref strats) => {
let mut current = current;
......@@ -688,19 +694,47 @@ pub fn eval_sdef<'d, 'f: 'd>(
Err(Error::UndefinedStrategy(String::from(name)))
} else {
context.stack_tracer.borrow_mut().push(name);
let popped_scopes = strategy_def.no_of_scopes().map_or_else(Vec::new, |n| {
context.scopes.borrow_mut().split_off(n)
});
context.push_scope(strategy_def.build_scope(actual_sargs, actual_targs));
let result = match *strategy_def {
StrategyDef::TopLevel(def) |
StrategyDef::Predefined { def, .. } => def.body.eval(context, current),
StrategyDef::Anonymous { body, .. } => body.eval(context, current),
let (term_popped, strat_popped, mut overlay_popped) = if let Some((t, s)) = strategy_def.scope_offsets() {
let mut olays = context.overlays.borrow_mut();
let mut olays_popped = Vec::new();
while let Some(&(n, _)) = olays.last() {
if n >= t {
olays_popped.push(olays.pop().unwrap());
} else {
break;
}
}
(
context.term.borrow_mut().split_off(t),
context.strategy.borrow_mut().split_off(s),
olays_popped,
)
} else {
(Vec::new(), Vec::new(), Vec::new())
};
context.pop_scope();
context.scopes.borrow_mut().extend_from_slice(
&popped_scopes,
let result = context.in_scope(strategy_def.build_scope(actual_sargs, actual_targs), || {
match *strategy_def {
StrategyDef::TopLevel(def) |
StrategyDef::Predefined { def, .. } => def.body.eval(context, current),
StrategyDef::Anonymous { body, .. } => body.eval(context, current),
}
});
context.term.borrow_mut().extend_from_slice(
&term_popped,
);
context.strategy.borrow_mut().extend_from_slice(
&strat_popped,
);
{
let mut overlays = context.overlays.borrow_mut();
while let Some(pair) = overlay_popped.pop() {
overlays.push(pair);
}
}
if result.is_ok() {
context.stack_tracer.borrow_mut().pop_on_success();
} else {
......@@ -717,7 +751,8 @@ pub fn strategy_def_from_strategy<'d, 'f: 'd>(
body: &'d preprocess::Strategy<'f>,
) -> Result<StrategyDef<'d, 'f>> {
use preprocess::Strategy;
let no_of_scopes = context.scopes.borrow().len();
let term_scope_offset = context.term.borrow().len();
let strat_scope_offset = context.strategy.borrow().len();
// NOTE: this is not an optimisation but a necessary semantic distinction to allow
// strategies that take arguments to be passed as strategy arguments!
match *body {
......@@ -731,7 +766,8 @@ pub fn strategy_def_from_strategy<'d, 'f: 'd>(
Ok(StrategyDef::Anonymous {
artificial_name: artificial_name,
body: body,
no_of_scopes: no_of_scopes,
term_scope_offset: term_scope_offset,
strat_scope_offset: strat_scope_offset,
})
}
}
......
......@@ -39,21 +39,23 @@ pub enum StrategyDef<'d, 'f: 'd> {
TopLevel(&'d Def<'f>),
Predefined {
def: &'d Def<'f>,
no_of_scopes: usize,
term_scope_offset: usize,
strat_scope_offset: usize,
},
Anonymous {
artificial_name: InternedString<'f>,
body: &'d Strategy<'f>,
no_of_scopes: usize,
term_scope_offset: usize,
strat_scope_offset: usize,
},
}
impl<'d, 'f> StrategyDef<'d, 'f> {
pub fn no_of_scopes(&self) -> Option<usize> {
pub fn scope_offsets(&self) -> Option<(usize, usize)> {
match *self {
StrategyDef::TopLevel(_) => None,
StrategyDef::Predefined { no_of_scopes, .. } |
StrategyDef::Anonymous { no_of_scopes, .. } => Some(no_of_scopes),
StrategyDef::Predefined { term_scope_offset, strat_scope_offset, .. } |
StrategyDef::Anonymous { term_scope_offset, strat_scope_offset, .. } => Some((term_scope_offset, strat_scope_offset)),
}
}
......@@ -96,10 +98,11 @@ impl<'d, 'f> StrategyDef<'d, 'f> {
StrategyDef::TopLevel(def)
}
pub fn from_let_def(def: &'d Def<'f>, no_of_scopes: usize) -> Self {
pub fn from_let_def(def: &'d Def<'f>, term_scope_offset: usize, strat_scope_offset: usize) -> Self {
StrategyDef::Predefined {
def: def,
no_of_scopes: no_of_scopes,
term_scope_offset: term_scope_offset,
strat_scope_offset: strat_scope_offset,
}
}
}
......@@ -291,7 +294,11 @@ impl<'a> TryFrom<ctree::Strategy<'a>> for Strategy<'a> {
match value {
I::Let(defs, body) => {
let defs = try_into_vec(defs)?;
try_into_box(body).map(|s| O::Let(defs, s))
if defs.is_empty() {
(*body).try_into()
} else {
try_into_box(body).map(|s| O::Let(defs, s))
}
}
I::CallT(ctree::SVar(svar), sargs, targs) => {
let targs = try_into_vec(targs)?;
......