Wrap any Clownfish object from Go.

Produce a Go func for each Clownfish class, which, given a Clownfish
C-space object pointer, wraps it in the appropriate Go struct yet
returns a clownfish.Obj.  Register these funcs in the `clownfish` Go
package and make them accessible via `clownfish.WRAPAny`.


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

Branch: refs/heads/master
Commit: 56e4ab9c21f1b5a9db1cea38ca58cca8539f1a1f
Parents: 978a011
Author: Marvin Humphrey <[email protected]>
Authored: Mon Jul 27 19:49:59 2015 -0700
Committer: Marvin Humphrey <[email protected]>
Committed: Fri Jul 31 11:05:37 2015 -0700

----------------------------------------------------------------------
 compiler/src/CFCGo.c              | 29 ++++++++++++++++++++-
 compiler/src/CFCGoClass.c         | 23 +++++++++++++++--
 compiler/src/CFCGoClass.h         |  3 +++
 runtime/go/clownfish/clownfish.go | 46 ++++++++++++++++++++++++++++++++++
 4 files changed, 98 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/56e4ab9c/compiler/src/CFCGo.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCGo.c b/compiler/src/CFCGo.c
index 3b3af2e..a5812a3 100644
--- a/compiler/src/CFCGo.c
+++ b/compiler/src/CFCGo.c
@@ -223,17 +223,21 @@ S_gen_init_code(CFCGo *self, CFCParcel *parcel) {
     const char pattern[] =
         "func init() {\n"
         "    C.%sbootstrap_parcel()\n"
+        "    initWRAP()\n"
         "}\n";
     return CFCUtil_sprintf(pattern, prefix);
 }
 
 static char*
 S_gen_autogen_go(CFCGo *self, CFCParcel *parcel) {
+    const char *clownfish_dot = CFCParcel_is_cfish(parcel)
+                                ? "" : "clownfish.";
     CFCGoClass **registry = CFCGoClass_registry();
     char *type_decs   = CFCUtil_strdup("");
     char *boilerplate = CFCUtil_strdup("");
     char *ctors       = CFCUtil_strdup("");
     char *meth_defs   = CFCUtil_strdup("");
+    char *wrap_funcs  = CFCUtil_strdup("");
 
     for (int i = 0; registry[i] != NULL; i++) {
         CFCGoClass *class_binding = registry[i];
@@ -258,6 +262,22 @@ S_gen_autogen_go(CFCGo *self, CFCParcel *parcel) {
         char *glue = CFCGoClass_gen_meth_glue(class_binding);
         meth_defs = CFCUtil_cat(meth_defs, glue, "\n", NULL);
         FREEMEM(glue);
+
+        char *wrap_func = CFCGoClass_gen_wrap_func_reg(class_binding);
+        wrap_funcs = CFCUtil_cat(wrap_funcs, wrap_func, NULL);
+        FREEMEM(wrap_func);
+    }
+
+    if (strlen(wrap_funcs)) {
+        char pattern[] =
+            "\tnewEntries := map[unsafe.Pointer]%sWrapFunc{\n%s"
+            "\t}\n"
+            "\t%sRegisterWrapFuncs(newEntries)\n"
+            ;
+        char *temp = CFCUtil_sprintf(pattern, clownfish_dot, wrap_funcs,
+                                     clownfish_dot);
+        FREEMEM(wrap_funcs);
+        wrap_funcs = temp;
     }
 
     char pattern[] =
@@ -269,6 +289,11 @@ S_gen_autogen_go(CFCGo *self, CFCParcel *parcel) {
         "\n"
         "%s\n"
         "\n"
+        "// Register WRAP functions.\n"
+        "func initWRAP() {\n"
+        "%s"
+        "}\n"
+        "\n"
         "// Constructors.\n"
         "\n"
         "%s\n"
@@ -279,8 +304,10 @@ S_gen_autogen_go(CFCGo *self, CFCParcel *parcel) {
         "\n"
         ;
     char *content
-        = CFCUtil_sprintf(pattern, type_decs, boilerplate, ctors, meth_defs);
+        = CFCUtil_sprintf(pattern, type_decs, boilerplate, wrap_funcs,
+                          ctors, meth_defs);
 
+    FREEMEM(wrap_funcs);
     FREEMEM(meth_defs);
     FREEMEM(ctors);
     FREEMEM(boilerplate);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/56e4ab9c/compiler/src/CFCGoClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCGoClass.c b/compiler/src/CFCGoClass.c
index d02aeb8..4392b61 100644
--- a/compiler/src/CFCGoClass.c
+++ b/compiler/src/CFCGoClass.c
@@ -250,18 +250,24 @@ CFCGoClass_boilerplate_funcs(CFCGoClass *self) {
     else if (CFCClass_inert(self->client)) {
         content = CFCUtil_strdup("");
     } else {
+        const char *clownfish_dot = CFCParcel_is_cfish(self->parcel)
+                                    ? "" : "clownfish.";
         const char *short_struct = CFCClass_get_struct_sym(self->client);
-        const char *full_struct  = CFCClass_full_struct_sym(self->client);
         char pattern[] =
             "func WRAP%s(ptr unsafe.Pointer) %s {\n"
             "\tobj := &%sIMP{}\n"
             "\tobj.INITOBJ(ptr)\n"
             "\treturn obj\n"
             "}\n"
+            "\n"
+            "func WRAP%sASOBJ(ptr unsafe.Pointer) %sObj {\n"
+            "\treturn WRAP%s(ptr)\n"
+            "}\n"
             ;
 
         content = CFCUtil_sprintf(pattern, short_struct, short_struct,
-                                  short_struct, full_struct, short_struct);
+                                  short_struct, short_struct, clownfish_dot,
+                                  short_struct);
     }
     return content;
 }
@@ -368,6 +374,19 @@ CFCGoClass_gen_meth_glue(CFCGoClass *self) {
     return meth_defs;
 }
 
+char*
+CFCGoClass_gen_wrap_func_reg(CFCGoClass *self) {
+    if (CFCClass_inert(self->client)) {
+        return CFCUtil_strdup("");
+    }
+    char pattern[] =
+        "\t\tunsafe.Pointer(C.%s): WRAP%sASOBJ,\n";
+
+    const char *short_struct = CFCClass_get_struct_sym(self->client);
+    const char *class_var = CFCClass_full_class_var(self->client);
+    return CFCUtil_sprintf(pattern, class_var, short_struct);
+}
+
 void
 CFCGoClass_spec_method(CFCGoClass *self, const char *name, const char *sig) {
     CFCUTIL_NULL_CHECK(sig);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/56e4ab9c/compiler/src/CFCGoClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCGoClass.h b/compiler/src/CFCGoClass.h
index 6a2db34..4e2cacf 100644
--- a/compiler/src/CFCGoClass.h
+++ b/compiler/src/CFCGoClass.h
@@ -76,6 +76,9 @@ CFCGoClass_gen_ctors(CFCGoClass *self);
 char*
 CFCGoClass_gen_meth_glue(CFCGoClass *self);
 
+char*
+CFCGoClass_gen_wrap_func_reg(CFCGoClass *self);
+
 void
 CFCGoClass_spec_method(CFCGoClass *self, const char *name, const char *sig);
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/56e4ab9c/runtime/go/clownfish/clownfish.go
----------------------------------------------------------------------
diff --git a/runtime/go/clownfish/clownfish.go 
b/runtime/go/clownfish/clownfish.go
index 2c5f40e..0fb7e32 100644
--- a/runtime/go/clownfish/clownfish.go
+++ b/runtime/go/clownfish/clownfish.go
@@ -62,10 +62,56 @@ GoCfish_RunRoutine(CFISH_Err_Attempt_t routine, void 
*context) {
 import "C"
 import "runtime"
 import "unsafe"
+import "fmt"
+import "sync"
+
+const (
+       maxUint = ^uint(0)
+       minUint = 0
+       maxInt  = int(^uint(0) >> 1)
+       minInt  = -(maxInt - 1)
+)
+
+type WrapFunc func(unsafe.Pointer)Obj
+var wrapRegMutex sync.Mutex
+var wrapReg *map[unsafe.Pointer]WrapFunc
 
 func init() {
        C.GoCfish_glue_exported_symbols()
        C.cfish_bootstrap_parcel()
+       initWRAP()
+}
+
+func RegisterWrapFuncs(newEntries map[unsafe.Pointer]WrapFunc) {
+       wrapRegMutex.Lock()
+       newSize := len(newEntries)
+       if wrapReg != nil {
+               newSize += len(*wrapReg)
+       }
+       newReg := make(map[unsafe.Pointer]WrapFunc, newSize)
+       if wrapReg != nil {
+               for k, v := range *wrapReg {
+                       newReg[k] = v
+               }
+       }
+       for k, v := range newEntries {
+               newReg[k] = v
+       }
+       wrapReg = &newReg
+       wrapRegMutex.Unlock()
+}
+
+func WRAPAny(ptr unsafe.Pointer) Obj {
+       if ptr == nil {
+               return nil
+       }
+       class := C.cfish_Obj_get_class((*C.cfish_Obj)(ptr))
+       wrapFunc := (*wrapReg)[unsafe.Pointer(class)]
+       if wrapFunc == nil {
+               className := 
CFStringToGo(unsafe.Pointer(C.CFISH_Class_Get_Name((*C.cfish_Class)(class))))
+               panic(fmt.Sprintf("Failed to find WRAP function for %s", 
className))
+       }
+       return wrapFunc(ptr)
 }
 
 type ObjIMP struct {

Reply via email to