Repository: lucy-clownfish
Updated Branches:
  refs/heads/master d28ce6ee4 -> 2e66aac98


Handle nil args in Go method wrappers.

Parameters which have a default value of `NULL` map to a `nil` value in
Go.  We can't call TOPTR() on them, so we need to use `UnwrapClownfish`.

To prevent the generated invocation statement from getting ridiculously
long, convert/unwrap *all* object types to temp variables.


Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/f3ed7660
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/f3ed7660
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/f3ed7660

Branch: refs/heads/master
Commit: f3ed7660fb43abc67c3f7025b067115e9362517e
Parents: 8172d40
Author: Marvin Humphrey <[email protected]>
Authored: Wed Aug 12 20:01:20 2015 -0700
Committer: Marvin Humphrey <[email protected]>
Committed: Fri Aug 14 15:36:17 2015 -0700

----------------------------------------------------------------------
 compiler/src/CFCGoFunc.c | 92 +++++++++++++++++++++++++------------------
 1 file changed, 53 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f3ed7660/compiler/src/CFCGoFunc.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCGoFunc.c b/compiler/src/CFCGoFunc.c
index a1e3bb5..34d3d48 100644
--- a/compiler/src/CFCGoFunc.c
+++ b/compiler/src/CFCGoFunc.c
@@ -58,6 +58,7 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass 
*invoker,
     const char *clownfish_dot = CFCParcel_is_cfish(parcel)
                                 ? "" : "clownfish.";
     CFCVariable **param_vars = CFCParamList_get_variables(param_list);
+    const char  **default_values = CFCParamList_get_initial_values(param_list);
     char *invocant;
     char go_name[GO_NAME_BUF_SIZE];
 
@@ -84,10 +85,39 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass 
*invoker,
         }
         params = CFCUtil_cat(params, go_name, " ", go_type_name, NULL);
         FREEMEM(go_type_name);
+    }
+
+    // Convert certain types and defer their destruction until after the
+    // Clownfish call returns.
+    for (int i = 0; param_vars[i] != NULL; i++) {
+        CFCVariable *var = param_vars[i];
+        CFCType *type = CFCVariable_get_type(var);
+        if (!CFCType_is_object(type)) {
+            continue;
+        }
 
-        // Convert certain types and defer their destruction until after the
-        // Clownfish call returns.
-        const char *class_var;
+        if (targ == IS_METHOD && i == 0) {
+            CFCGoTypeMap_go_meth_receiever(CFCClass_get_struct_sym(invoker),
+                                           param_list, go_name,
+                                           GO_NAME_BUF_SIZE);
+        }
+        else {
+            CFCGoTypeMap_go_arg_name(param_list, i, go_name, GO_NAME_BUF_SIZE);
+        }
+
+        // A parameter may be marked with the nullable modifier.  It may also
+        // be nullable if it has a default value of "NULL".  (Since Go does
+        // not support default values for method parameters, this is the only
+        // default value we care about.)
+        const char *nullable = CFCType_nullable(type) ? "true" : "false";
+        if (default_values[i] != NULL
+            && strcmp(default_values[i], "NULL") == 0
+           ) {
+            nullable = "true";
+        }
+
+        const char *class_var = NULL;
+        const char *struct_name = CFCType_get_specifier(type);
         if (CFCType_cfish_obj(type)) {
             class_var = "CFISH_OBJ";
         }
@@ -103,11 +133,26 @@ S_prep_start(CFCParcel *parcel, const char *name, 
CFCClass *invoker,
         else if (CFCType_cfish_hash(type)) {
             class_var = "CFISH_HASH";
         }
-        else {
+
+        if (class_var == NULL || (targ == IS_METHOD && i == 0)) {
+            // Just unwrap -- don't convert.
+            char *pattern;
+            if (CFCType_decremented(type)) {
+                pattern =
+                    "\t%sCF := 
(*C.%s)(unsafe.Pointer(C.cfish_incref(%sUnwrapClownfish(%s, \"%s\", %s))))\n";
+            }
+            else {
+                pattern =
+                    "\t%sCF := (*C.%s)(%sUnwrapClownfish(%s, \"%s\", %s))\n";
+            }
+            char *conversion = CFCUtil_sprintf(pattern, go_name, struct_name,
+                                               clownfish_dot, go_name,
+                                               go_name, nullable);
+            converted = CFCUtil_cat(converted, conversion, NULL);
+            FREEMEM(conversion);
             continue;
         }
-        const char *struct_name = CFCType_get_specifier(type);
-        const char *nullable = CFCType_nullable(type) ? "true" : "false";
+
         char pattern[] =
             "\t%sCF := (*C.%s)(%sGoToClownfish(%s, unsafe.Pointer(C.%s), 
%s))\n";
         char *conversion = CFCUtil_sprintf(pattern, go_name, struct_name,
@@ -188,29 +233,8 @@ S_prep_cfargs(CFCParcel *parcel, CFCClass *invoker,
             cfargs = CFCUtil_cat(cfargs, "C.", CFCType_get_specifier(type),
                                  "(", go_name, ")", NULL);
         }
-        else if ((CFCType_cfish_obj(type)
-                  || CFCType_cfish_string(type)
-                  || CFCType_cfish_blob(type)
-                  || CFCType_cfish_vector(type)
-                  || CFCType_cfish_hash(type))
-                 // Don't convert an invocant.
-                 && (targ != IS_METHOD || i != 0)
-                ) {
-            cfargs = CFCUtil_cat(cfargs, go_name, "CF", NULL);
-        }
         else if (CFCType_is_object(type)) {
-
-            char *obj_pattern;
-            if (CFCType_decremented(type)) {
-                obj_pattern = 
"(*C.%s)(unsafe.Pointer(C.cfish_inc_refcount(unsafe.Pointer(%s.TOPTR()))))";
-            }
-            else {
-                obj_pattern = "(*C.%s)(unsafe.Pointer(%s.TOPTR()))";
-            }
-            char *temp = CFCUtil_sprintf(obj_pattern,
-                                         CFCType_get_specifier(type), go_name);
-            cfargs = CFCUtil_cat(cfargs, temp, NULL);
-            FREEMEM(temp);
+            cfargs = CFCUtil_cat(cfargs, go_name, "CF", NULL);
         }
     }
     return cfargs;
@@ -276,15 +300,6 @@ CFCGoFunc_return_statement(CFCParcel *parcel, CFCType 
*return_type,
         }
         else if (CFCType_is_object(return_type)) {
             char *go_type_name = CFCGoTypeMap_go_type_name(return_type, 
parcel);
-            char *struct_name  = go_type_name;
-            char *go_package   = CFCUtil_strdup(go_type_name);
-            for (int i = strlen(go_package) - 1; i >= 0; i--) {
-                if (go_package[i] == '.') {
-                    struct_name += i + 1;
-                    break;
-                }
-                go_package[i] = '\0';
-            }
             char *pattern;
             if (CFCType_incremented(return_type)) {
                 pattern = "\treturn 
%sWRAPAny(unsafe.Pointer(retvalCF)).(%s)\n";
@@ -292,9 +307,8 @@ CFCGoFunc_return_statement(CFCParcel *parcel, CFCType 
*return_type,
             else {
                 pattern = "\treturn 
%sWRAPAny(unsafe.Pointer(C.cfish_inc_refcount(unsafe.Pointer(retvalCF)))).(%s)\n";
             }
-            statement = CFCUtil_sprintf(pattern, go_package, struct_name);
+            statement = CFCUtil_sprintf(pattern, clownfish_dot, go_type_name);
             FREEMEM(go_type_name);
-            FREEMEM(go_package);
         }
         else {
             CFCUtil_die("Unexpected type: %s", CFCType_to_c(return_type));

Reply via email to