Переглянути джерело

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.
Ambroz Bizjak 11 роки тому
батько
коміт
f20999da62
2 змінених файлів з 14 додано та 7 видалено
  1. 10 5
      ncd/modules/backtrack.c
  2. 4 2
      ncd/tests/backtracking.ncd

+ 10 - 5
ncd/modules/backtrack.c

@@ -40,8 +40,8 @@
  *   itself goes up immedietely, but side effects of triggering backtracking have
  *   itself goes up immedietely, but side effects of triggering backtracking have
  *   priority.
  *   priority.
  *   The rgo() method triggers backtracking when it deinitializes. In this case,
  *   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().
+ *   the immediate effects of triggering backtracking in the backtrack_point() have
+ *   priority over the immediate effects of rgo() deinitialization completion.
  */
  */
 
 
 #include <ncd/module_common.h>
 #include <ncd/module_common.h>
@@ -121,11 +121,11 @@ static void rgo_func_die (void *vo)
 {
 {
     struct rgo_instance *o = vo;
     struct rgo_instance *o = vo;
     
     
-    // toggle backtrack point
+    // deref backtrack_point
+    NCDModuleInst *backtrack_point_inst = NULL;
     NCDObject rgo_obj;
     NCDObject rgo_obj;
     if (NCDObjRef_Deref(&o->bp_ref, &rgo_obj)) {
     if (NCDObjRef_Deref(&o->bp_ref, &rgo_obj)) {
-        NCDModuleInst *backtrack_point_inst = NCDObject_MethodUser(&rgo_obj);
-        NCDModuleInst_Backend_DownUp(backtrack_point_inst);
+        backtrack_point_inst = NCDObject_MethodUser(&rgo_obj);
     }
     }
     
     
     // free object reference
     // free object reference
@@ -133,6 +133,11 @@ static void rgo_func_die (void *vo)
     
     
     // die
     // die
     NCDModuleInst_Backend_Dead(o->i);
     NCDModuleInst_Backend_Dead(o->i);
+    
+    // toggle backtrack_point
+    if (backtrack_point_inst) {
+        NCDModuleInst_Backend_DownUp(backtrack_point_inst);
+    }
 }
 }
 
 
 static struct NCDModule modules[] = {
 static struct NCDModule modules[] = {

+ 4 - 2
ncd/tests/backtracking.ncd

@@ -52,10 +52,12 @@ template helper1 {
 }
 }
 
 
 template helper2 {
 template helper2 {
-    _caller._caller.flag->set("true");
+    val_equal(_caller._caller.flag, "true") a;
+    assert(a);
 }
 }
 
 
 template helper3 {
 template helper3 {
-    val_equal(_caller.flag, "true") a;
+    val_equal(_caller.flag, "false") a;
     assert(a);
     assert(a);
+    _caller.flag->set("true");
 }
 }