f20999da62
Turns out we want the backtrack triggering effects to have priority. Consider the following test case. process main { backtrack_point() pointA; println("A"); sleep("1"); If ("true") { backtrack_point() pointB; println("B"); pointA->rgo(); pointB->go(); }; } The result of this would originally have been "A B B B B...". The reason is that the If process would be caught in an infinite loop, and the main process would never get a chance to backtrack past the If statement. With this change, the result is "A B A B...", since the rgo() deinitialization immediately causes backtracking in main. This is actually a nice example about a design bug regarding the subtle ways in which a process call (If, in this case) is not equivalent to embedding the statements in place. Without the If, there would not be an infinite loop in any case.
64 lines
1.2 KiB
Plaintext
64 lines
1.2 KiB
Plaintext
process main {
|
|
value({}) list;
|
|
var("0") i;
|
|
backtrack_point() point;
|
|
num_lesser(i, "100") do_more;
|
|
If (do_more) {
|
|
list->insert(i);
|
|
num_add(i, "1") new_i;
|
|
i->set(new_i);
|
|
point->go();
|
|
};
|
|
val_equal(list.length, "100") a;
|
|
assert(a);
|
|
|
|
value({}) list;
|
|
var("0") i;
|
|
blocker() blk;
|
|
blk->up();
|
|
blk->use();
|
|
num_lesser(i, "100") do_more;
|
|
If (do_more) {
|
|
list->insert(i);
|
|
num_add(i, "1") new_i;
|
|
i->set(new_i);
|
|
blk->downup();
|
|
};
|
|
val_equal(list.length, "100") a;
|
|
assert(a);
|
|
|
|
var("true") start;
|
|
var("false") flag;
|
|
backtrack_point() point;
|
|
If (start) {
|
|
blocker() blk;
|
|
blk->up();
|
|
spawn("helper1", {});
|
|
imperative("<none>", {}, "helper3", {}, "1000");
|
|
start->set("false");
|
|
blk->down();
|
|
if("false");
|
|
} Else {
|
|
assert(flag);
|
|
};
|
|
|
|
exit("0");
|
|
}
|
|
|
|
template helper1 {
|
|
_caller.blk->use();
|
|
imperative("<none>", {}, "helper2", {}, "1000");
|
|
_caller.point->rgo();
|
|
}
|
|
|
|
template helper2 {
|
|
val_equal(_caller._caller.flag, "true") a;
|
|
assert(a);
|
|
}
|
|
|
|
template helper3 {
|
|
val_equal(_caller.flag, "false") a;
|
|
assert(a);
|
|
_caller.flag->set("true");
|
|
}
|