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 {
