Commit 343e70f0 by Jeff Smits

Turned overlays into a hacky transaction system, added those to closure execution and matching

parent c1604af2
Specification([Signature([Constructors([OpDecl("Nil",ConstType(Sort("List",[SortVar("a")]))),OpDecl("Cons",FunType([ConstType(SortVar("a")),ConstType(Sort("List",[SortVar("a")]))],ConstType(Sort("List",[SortVar("a")])))),OpDecl("",FunType([ConstType(SortVar("a")),ConstType(SortVar("b"))],ConstType(Sort("Tuple",[Sort("Cons",[SortVar("a"),Sort("Cons",[SortVar("b"),Sort("Nil",[])])])])))),OpDecl("Var",FunType([ConstType(Sort("String",[]))],ConstType(Sort("Expr",[])))),OpDecl("Plus",FunType([ConstType(Sort("Expr",[])),ConstType(Sort("Expr",[]))],ConstType(Sort("Expr",[]))))])]),Strategies([SDefT("eval_0_1",[],[VarDec("l_0",ConstType(Sort("ATerm",[])))],Let([SDefT("m_63",[VarDec("o_63",FunType([ConstType(Sort("ATerm",[]))],ConstType(Sort("ATerm",[]))))],[],Seq(All(CallT(SVar("m_63"),[CallT(SVar("o_63"),[],[])],[])),CallT(SVar("o_63"),[],[]))),SDefT("n_63",[],[],GuardedLChoice(GuardedLChoice(Scope(["e_63","f_63","g_63","h_63","i_63"],Seq(Match(Var("i_63")),Seq(Build(Var("l_0")),Seq(Match(Var("e_63")),Seq(Build(Var("i_63")),Seq(Match(Anno(Op("Var",[Var("f_63")]),Wld)),Seq(Match(Var("h_63")),Seq(Build(Var("e_63")),Seq(CallT(SVar("fetch_1_0"),[Match(Anno(Op("",[Var("f_63"),Var("g_63")]),Wld))],[]),Seq(Build(Var("h_63")),Seq(Build(Var("g_63")),CallT(SVar("m_63"),[CallT(SVar("n_63"),[],[])],[])))))))))))),Id,Scope(["j_63","k_63","l_63"],Seq(Match(Anno(Op("Plus",[Var("j_63"),Var("k_63")]),Wld)),Seq(Match(Var("l_63")),Seq(Build(Var("j_63")),Seq(CallT(SVar("is_int_0_0"),[],[]),Seq(Build(Var("k_63")),Seq(CallT(SVar("is_int_0_0"),[],[]),Seq(Build(Var("l_63")),Seq(Build(Anno(Op("",[Var("j_63"),Var("k_63")]),Op("Nil",[]))),Seq(CallT(SVar("add_0_0"),[],[]),CallT(SVar("m_63"),[CallT(SVar("n_63"),[],[])],[])))))))))))),Id,Id))],CallT(SVar("m_63"),[CallT(SVar("n_63"),[],[])],[]))),SDefT("main_0_0",[],[],Scope(["m_0","n_0"],Seq(Build(Anno(Op("Plus",[Anno(Op("Var",[Anno(Str("a"),Op("Nil",[]))]),Op("Nil",[])),Anno(Op("Plus",[Anno(Op("Var",[Anno(Str("b"),Op("Nil",[]))]),Op("Nil",[])),Anno(Op("Var",[Anno(Str("c"),Op("Nil",[]))]),Op("Nil",[]))]),Op("Nil",[]))]),Op("Nil",[]))),Seq(Match(Var("n_0")),Seq(Build(Anno(Op("Cons",[Anno(Op("",[Anno(Str("a"),Op("Nil",[])),Anno(Int("1"),Op("Nil",[]))]),Op("Nil",[])),Anno(Op("Cons",[Anno(Op("",[Anno(Str("b"),Op("Nil",[])),Anno(Int("2"),Op("Nil",[]))]),Op("Nil",[])),Anno(Op("Cons",[Anno(Op("",[Anno(Str("c"),Op("Nil",[])),Anno(Int("3"),Op("Nil",[]))]),Op("Nil",[])),Anno(Op("Nil",[]),Op("Nil",[]))]),Op("Nil",[]))]),Op("Nil",[]))]),Op("Nil",[]))),Seq(Match(Var("m_0")),Seq(Build(Var("n_0")),Seq(CallT(SVar("eval_0_1"),[],[Var("m_0")]),Seq(CallT(SVar("debug_0_0"),[],[]),Match(Anno(Int("6"),Wld))))))))))),ExtSDef("is_int_0_0",[],[]),ExtSDef("add_0_0",[],[]),ExtSDef("debug_0_0",[],[]),ExtSDef("fetch_1_0",[VarDec("b_42",FunType([ConstType(Sort("ATerm",[]))],ConstType(Sort("ATerm",[]))))],[])])])
\ No newline at end of file
module test95
imports libstratego-lib
signature
constructors
: a * b -> (a, b)
Nil : List(a)
Cons : a * List(a) -> List(a)
Var : String -> Expr
Plus : Expr * Expr -> Expr
rules
A(|env) :
Var(x) -> i
where
<fetch(?(x, i))> env
B :
Plus(i, j) -> <add> (i, j)
where
<is-int> i
; <is-int> j
strategies
eval(|env) =
innermost(A(|env) + B)
main =
!Plus(Var("a"), Plus(Var("b"), Var("c")))
; eval(| [("a", 1), ("b", 2), ("c", 3)])
; debug
; ?6
......@@ -145,8 +145,6 @@ impl<'a> Eval<'a> for preprocess::Strategy {
result
}
CallT(ref name, ref sargs, ref targs) => {
println!("Calling: {}", name);
println!("Env: {:?}", &context.scopes.borrow()[2..]);
let sdeft = context.get_strategy(name)?;
let sargs = sargs
.into_iter()
......@@ -160,9 +158,7 @@ impl<'a> Eval<'a> for preprocess::Strategy {
.into_iter()
.map(|build_term| build_term.build(context))
.collect::<Result<_>>()?;
let result = sdeft.eval(context, sargs, targs, current);
println!("Returning from: {} with {:?}", name, &result);
result
sdeft.eval(context, sargs, targs, current)
}
CallDynamic(ref term_name, ref sargs, ref targs) => {
let strategy_name = context.get_term(term_name)?;
......@@ -193,7 +189,19 @@ impl<'a> Eval<'a> for preprocess::Strategy {
}
Fail => Err(Error::StrategyFailed),
Id => Ok(current),
Match(ref term) => eval_match(context, term, &current).map(|()| current),
Match(ref term) => {
context.push_overlay();
match eval_match(context, term, &current) {
Ok(()) => {
context.apply_overlay();
Ok(current)
}
Err(e) => {
context.drop_overlay();
Err(e)
}
}
},
Build(ref term) => term.build(context),
Scope(ref fresh_names, ref body) => {
context.push_scope(context::Scope::from_fresh_variables(fresh_names.clone()));
......@@ -206,18 +214,17 @@ impl<'a> Eval<'a> for preprocess::Strategy {
strat2.eval(context, current)
}
GuardedLChoice(ref s_if, ref s_then, ref s_else) => {
context.push_scope(context::Scope::overlay());
context.push_overlay();
match s_if.eval(context, current.clone()) {
Ok(current) => {
context.apply_overlay()?;
s_then.eval(context, current)
}
Err(Error::StrategyFailed) => {
context.pop_scope();
context.drop_overlay();
s_else.eval(context, current)
}
Err(e) => {
context.pop_scope();
context.drop_overlay();
Err(e)
}
}
......
......@@ -70,25 +70,36 @@ impl StrategyDef {
// closure was made.
// This works because closure cannot be returned, so the number of scopes always
// reflects the environment in which the closure was made.
// Only problem complicating matters is that an overlay may be popped off here,
// but it's supposed to catch variable bindings. Therefore after popping things
// off, we always add an overlay. After the call the overlay is put on top of
// the entire stack and then applied, to get the desired effect.
// Only problem complicating matters is that an overlay may be temporarily
// popped off here, but it's supposed to catch variable bindings. Therefore
// after popping things off, we always add another overlay.
context.stack_tracer.borrow_mut().push(name.clone());
let popped_scopes = context.scopes.borrow_mut().split_off(no_of_scopes);
context.push_scope(Scope::overlay());
context.push_overlay();
context.push_scope(Scope::new(targs.iter().cloned().zip(actual_targs),
sargs.iter().cloned().zip(actual_sargs)));
let result = body.eval(context, current);
context.pop_scope();
let overlay = context.scopes.borrow_mut().pop().expect("Interpreter bug, too many scopes popped somewhere. ");
let empty_overlay = context.scopes.borrow().last().expect("Where did my overlay go?").term.is_empty();
if result.is_ok() && empty_overlay {
context.apply_overlay();
} else if result.is_err() {
context.drop_overlay();
}
context
.scopes
.borrow_mut()
.extend_from_slice(&popped_scopes);
if result.is_ok() {
context.scopes.borrow_mut().push(overlay);
context.apply_overlay()?;
// we're leaving an extra scope on the stack, so now we need to fix up the
// no_of_scopes numbers of everything else :(
if !empty_overlay {
for mut scope in context.scopes.borrow_mut().iter_mut().skip(no_of_scopes) {
for (_, mut sdef) in scope.strategy.iter_mut() {
sdef.inc_no_of_scopes();
}
}
}
context.stack_tracer.borrow_mut().pop_on_success();
} else {
context.stack_tracer.borrow_mut().pop_on_failure();
......@@ -119,12 +130,28 @@ impl StrategyDef {
} else {
context.stack_tracer.borrow_mut().push(name);
let popped_scopes = context.scopes.borrow_mut().split_off(no_of_scopes);
context.push_overlay();
let result = body.eval(context, current);
let empty_overlay = context.scopes.borrow().last().expect("Where did my overlay go?").term.is_empty();
if result.is_ok() && empty_overlay {
context.apply_overlay();
} else if result.is_err() {
context.drop_overlay();
}
context
.scopes
.borrow_mut()
.extend_from_slice(&popped_scopes);
if result.is_ok() {
// we're leaving an extra scope on the stack, so now we need to fix up the
// no_of_scopes numbers of everything else :(
if !empty_overlay {
for mut scope in context.scopes.borrow_mut().iter_mut().skip(no_of_scopes) {
for (_, mut sdef) in scope.strategy.iter_mut() {
sdef.inc_no_of_scopes();
}
}
}
context.stack_tracer.borrow_mut().pop_on_success();
} else {
context.stack_tracer.borrow_mut().pop_on_failure();
......@@ -185,6 +212,18 @@ impl StrategyDef {
} => format!("{}.{}", argument_of, argument_no),
}
}
fn inc_no_of_scopes(&mut self) {
match *self {
StrategyDef::Predefined { no_of_scopes: None, .. } => {},
StrategyDef::Predefined { no_of_scopes: Some(ref mut n), .. } => {
*n += 1;
},
StrategyDef::Anonymous { ref mut no_of_scopes, .. } => {
*no_of_scopes += 1;
}
}
}
}
impl TryFrom<ctree::Def> for StrategyDef {
......@@ -475,17 +514,7 @@ impl BuildTerm {
#[allow(dead_code)]
pub fn build_static(&self, f: &ATermFactory) -> Result<ATermRef> {
use context::StackTracer;
use primitives::ssl::State;
use std::cell::RefCell;
let dummy_context = MutContext {
stack_tracer: RefCell::new(StackTracer::default()),
factory: f,
primitives: Vec::new(),
scopes: RefCell::new(Vec::new()),
ssl_state: RefCell::new(State::new()),
};
let dummy_context = MutContext::new(f, Vec::new(), Vec::new());
self.build(&dummy_context).map_err(|e| {
match e {
Error::UndefinedVariable(_) =>
......
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