badvpn/ncd/tests/backtracking.ncd
Ambroz Bizjak f20999da62 ncd: Reverse the immediate effect logic of backtrack_point::rgo().
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.
2014-12-07 00:30:12 +01:00

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");
}