Jelajahi Sumber

ncd: Implement lazy evaluation in If clause.
The embcall2_multif statement is replaced with embcall, which only takes a template name. The selection of the template name is done using the ifel function, generated during desugaring.

Ambroz Bizjak 11 tahun lalu
induk
melakukan
9f1067e51a
2 mengubah file dengan 55 tambahan dan 57 penghapusan
  1. 39 12
      ncd/NCDSugar.c
  2. 16 45
      ncd/modules/call2.c

+ 39 - 12
ncd/NCDSugar.c

@@ -132,37 +132,63 @@ static int desugar_if (struct desugar_state *state, NCDBlock *block, NCDStatemen
         if (!NCDValue_ListAppend(&args, if_cond)) {
             NCDValue_Free(&if_cond);
             NCDBlock_Free(&if_block);
-            goto fail;
+            goto fail_args;
         }
         
         NCDValue action_arg;
         if (!add_template(state, if_block, &action_arg)) {
-            goto fail;
+            goto fail_args;
         }
         
         if (!NCDValue_ListAppend(&args, action_arg)) {
             NCDValue_Free(&action_arg);
-            goto fail;
+            goto fail_args;
         }
     }
     
+    NCDValue action_arg;
+    
     if (NCDStatement_IfElse(stmt)) {
         NCDBlock else_block = NCDStatement_IfGrabElse(stmt);
         
-        NCDValue action_arg;
         if (!add_template(state, else_block, &action_arg)) {
-            goto fail;
+            goto fail_args;
         }
-        
-        if (!NCDValue_ListAppend(&args, action_arg)) {
-            NCDValue_Free(&action_arg);
-            goto fail;
+    } else {
+        if (!NCDValue_InitString(&action_arg, "<none>")) {
+            goto fail_args;
         }
     }
     
+    if (!NCDValue_ListAppend(&args, action_arg)) {
+        NCDValue_Free(&action_arg);
+        goto fail_args;
+    }
+    
+    NCDValue func;
+    if (!NCDValue_InitString(&func, "ifel")) {
+        goto fail_args;
+    }
+    
+    NCDValue invoc;
+    if (!NCDValue_InitInvoc(&invoc, func, args)) {
+        NCDValue_Free(&func);
+        goto fail_args;
+    }
+    
+    NCDValue stmt_args;
+    NCDValue_InitList(&stmt_args);
+    
+    if (!NCDValue_ListAppend(&stmt_args, invoc)) {
+        NCDValue_Free(&stmt_args);
+        NCDValue_Free(&invoc);
+        goto fail0;
+    }
+    
     NCDStatement new_stmt;
-    if (!NCDStatement_InitReg(&new_stmt, NCDStatement_Name(stmt), NULL, "embcall2_multif", args)) {
-        goto fail;
+    if (!NCDStatement_InitReg(&new_stmt, NCDStatement_Name(stmt), NULL, "embcall", stmt_args)) {
+        NCDValue_Free(&stmt_args);
+        goto fail0;
     }
     
     stmt = NCDBlock_ReplaceStatement(block, stmt, new_stmt);
@@ -170,8 +196,9 @@ static int desugar_if (struct desugar_state *state, NCDBlock *block, NCDStatemen
     *out_next = NCDBlock_NextStatement(block, stmt);
     return 1;
     
-fail:
+fail_args:
     NCDValue_Free(&args);
+fail0:
     return 0;
 }
 

+ 16 - 45
ncd/modules/call2.c

@@ -80,15 +80,12 @@
  * 
  * 
  * Synopsis:
- *   embcall2_multif(string cond1, string template1, ..., [string else_template])
+ *   embcall(string template)
  * 
  * Description:
- *   This is an internal command used to implement the 'If' clause. The arguments
- *   are pairs of (cond, template), where 'cond' is a condition in form of a string,
- *   and 'template' is the name of the process template for this condition. The
- *   template corresponding to the first condition equal to "true" is called; if
- *   there is no true condition, either the template 'else_template' is called,
- *   if it is provided, or nothing is performed, if 'else_template' is not provided.
+ *   Like call, but makes its own scope directly available in the called
+ *   template process, instead of via _caller. Also, doesn not provide any
+ *   arguments to the template process.
  * 
  * 
  * Synopsis:
@@ -375,45 +372,19 @@ static void call_with_caller_target_extra_free (struct instance *bo)
     NCDFastNames_Free(&o->names);
 }
 
-static void func_new_embcall_multif (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
+static void func_new_embcall (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
 {
-    NCDValRef args = params->args;
-    
-    NCDValRef template_value = NCDVal_NewInvalid();
-    
-    size_t count = NCDVal_ListCount(args);
-    size_t j = 0;
-    
-    while (j < count) {
-        NCDValRef arg = NCDVal_ListGet(args, j);
-        
-        if (j == count - 1) {
-            if (!NCDVal_IsString(arg)) {
-                ModuleLog(i, BLOG_ERROR, "bad arguments");
-                goto fail0;
-            }
-            
-            template_value = arg;
-            break;
-        }
-        
-        NCDValRef arg2 = NCDVal_ListGet(args, j + 1);
-        
-        int arg_val;
-        if (!ncd_read_boolean(arg, &arg_val) || !NCDVal_IsString(arg2)) {
-            ModuleLog(i, BLOG_ERROR, "bad arguments");
-            goto fail0;
-        }
-        
-        if (arg_val) {
-            template_value = arg2;
-            break;
-        }
-        
-        j += 2;
+    NCDValRef template_arg;
+    if (!NCDVal_ListRead(params->args, 1, &template_arg)) {
+        ModuleLog(i, BLOG_ERROR, "wrong arity");
+        goto fail0;
+    }
+    if (!NCDVal_IsString(template_arg)) {
+        ModuleLog(i, BLOG_ERROR, "wrong type");
+        goto fail0;
     }
     
-    func_new_templ(vo, i, template_value, NCDVal_NewInvalid(), process_func_getspecialobj_embed, NULL);
+    func_new_templ(vo, i, template_arg, NCDVal_NewInvalid(), process_func_getspecialobj_embed, NULL);
     return;
     
 fail0:
@@ -566,8 +537,8 @@ static struct NCDModule modules[] = {
         .flags = NCDMODULE_FLAG_CAN_RESOLVE_WHEN_DOWN,
         .alloc_size = sizeof(struct instance_with_caller_target)
     }, {
-        .type = "embcall2_multif",
-        .func_new2 = func_new_embcall_multif,
+        .type = "embcall",
+        .func_new2 = func_new_embcall,
         .func_die = func_die,
         .func_clean = func_clean,
         .func_getobj = func_getobj,