diff options
author | Ambroz Bizjak <ambrop7@gmail.com> | 2014-12-05 23:16:11 +0300 |
---|---|---|
committer | Ambroz Bizjak <ambrop7@gmail.com> | 2014-12-06 00:18:01 +0300 |
commit | f662d54df72ca71c307dd9a783886508a463de89 (patch) | |
tree | e29bfbcde5a03b6c5153e1b9e8bd6414369f219f | |
parent | e5206baa26ea2c6a355d967573feee4eaa9c0c7d (diff) |
ncd: Implement backtrack_point::rgo.
-rw-r--r-- | ncd/modules/backtrack.c | 58 | ||||
-rw-r--r-- | ncd/tests/backtracking.ncd | 30 |
2 files changed, 88 insertions, 0 deletions
diff --git a/ncd/modules/backtrack.c b/ncd/modules/backtrack.c index 7b75744..468315c 100644 --- a/ncd/modules/backtrack.c +++ b/ncd/modules/backtrack.c @@ -31,6 +31,7 @@ * Synopsis: * backtrack_point() * backtrack_point::go() + * backtrack_point::rgo() * * Description: * The backtrack_point() statement creates a backtrack point, going up immedietely. @@ -38,12 +39,20 @@ * backtrack_point() statement go down and back up at atomically. The go() method * itself goes up immedietely, but side effects of triggering backtracking have * priority. + * The rgo() method triggers backtracking when it deinitializes. In this case, + * the immediate effects of rgo() deinitialization happen before the immediate + * effects of triggering backtracking in the backtrack_point(). */ #include <ncd/module_common.h> #include <generated/blog_channel_ncd_backtrack.h> +struct rgo_instance { + NCDModuleInst *i; + NCDObjRef bp_ref; +}; + static void func_new (void *unused, NCDModuleInst *i, const struct NCDModuleInst_new_params *params) { // check arguments @@ -82,6 +91,50 @@ fail0: NCDModuleInst_Backend_DeadError(i); } +static void rgo_func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params) +{ + struct rgo_instance *o = vo; + o->i = i; + + // check arguments + if (!NCDVal_ListRead(params->args, 0)) { + ModuleLog(i, BLOG_ERROR, "wrong arity"); + goto fail0; + } + + // get backtrack point + NCDModuleInst *backtrack_point_inst = params->method_user; + + // init object reference to the backtrack_point + NCDObject obj = NCDModuleInst_Object(backtrack_point_inst); + NCDObjRef_Init(&o->bp_ref, NCDObject_Pobj(&obj)); + + // go up + NCDModuleInst_Backend_Up(i); + return; + +fail0: + NCDModuleInst_Backend_DeadError(i); +} + +static void rgo_func_die (void *vo) +{ + struct rgo_instance *o = vo; + + // toggle backtrack point + NCDObject rgo_obj; + if (NCDObjRef_Deref(&o->bp_ref, &rgo_obj)) { + NCDModuleInst *backtrack_point_inst = NCDObject_MethodUser(&rgo_obj); + NCDModuleInst_Backend_DownUp(backtrack_point_inst); + } + + // free object reference + NCDObjRef_Free(&o->bp_ref); + + // die + NCDModuleInst_Backend_Dead(o->i); +} + static struct NCDModule modules[] = { { .type = "backtrack_point", @@ -90,6 +143,11 @@ static struct NCDModule modules[] = { .type = "backtrack_point::go", .func_new2 = go_func_new }, { + .type = "backtrack_point::rgo", + .func_new2 = rgo_func_new, + .func_die = rgo_func_die, + .alloc_size = sizeof(struct rgo_instance) + }, { .type = NULL } }; diff --git a/ncd/tests/backtracking.ncd b/ncd/tests/backtracking.ncd index 1faf3b7..c239df8 100644 --- a/ncd/tests/backtracking.ncd +++ b/ncd/tests/backtracking.ncd @@ -27,5 +27,35 @@ process main { 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 { + _caller._caller.flag->set("true"); +} + +template helper3 { + val_equal(_caller.flag, "true") a; + assert(a); +} |