Introduce `Unwrap`, `UnwrapNullable`. Replace `UnwrapClownfish` with new functions that perform valid nil-checking. For nullable parameters, perform better error checking in Go in order to throw better errors.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/7988b5ff Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/7988b5ff Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/7988b5ff Branch: refs/heads/master Commit: 7988b5ffd869afe613ab7becc3805a219b2f5c2f Parents: 699a22b Author: Marvin Humphrey <[email protected]> Authored: Thu Aug 27 19:39:19 2015 -0700 Committer: Marvin Humphrey <[email protected]> Committed: Tue Sep 8 19:09:24 2015 -0700 ---------------------------------------------------------------------- compiler/src/CFCGoFunc.c | 34 +++++++++++++++++---------- runtime/go/clownfish/clownfish.go | 43 ++++++++++++++++++++-------------- 2 files changed, 48 insertions(+), 29 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7988b5ff/compiler/src/CFCGoFunc.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCGoFunc.c b/compiler/src/CFCGoFunc.c index 34d3d48..0528c11 100644 --- a/compiler/src/CFCGoFunc.c +++ b/compiler/src/CFCGoFunc.c @@ -109,11 +109,11 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass *invoker, // 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"; + int nullable = CFCType_nullable(type); if (default_values[i] != NULL && strcmp(default_values[i], "NULL") == 0 ) { - nullable = "true"; + nullable = true; } const char *class_var = NULL; @@ -136,20 +136,29 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass *invoker, 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"; + char *unwrapped; + if (nullable) { + unwrapped = CFCUtil_sprintf("%sUnwrapNullable(%s)", + clownfish_dot, go_name); } else { - pattern = - "\t%sCF := (*C.%s)(%sUnwrapClownfish(%s, \"%s\", %s))\n"; + unwrapped = CFCUtil_sprintf("%sUnwrap(%s, \"%s\")", + clownfish_dot, go_name, go_name); + } + + if (CFCType_decremented(type)) { + char *pattern = "unsafe.Pointer(C.cfish_incref(%s))"; + char *temp = CFCUtil_sprintf(pattern, unwrapped); + FREEMEM(unwrapped); + unwrapped = temp; } - char *conversion = CFCUtil_sprintf(pattern, go_name, struct_name, - clownfish_dot, go_name, - go_name, nullable); + + char *conversion + = CFCUtil_sprintf("\t%sCF := (*C.%s)(%s)\n", go_name, + struct_name, unwrapped); converted = CFCUtil_cat(converted, conversion, NULL); FREEMEM(conversion); + FREEMEM(unwrapped); continue; } @@ -157,7 +166,8 @@ S_prep_start(CFCParcel *parcel, const char *name, CFCClass *invoker, "\t%sCF := (*C.%s)(%sGoToClownfish(%s, unsafe.Pointer(C.%s), %s))\n"; char *conversion = CFCUtil_sprintf(pattern, go_name, struct_name, clownfish_dot, go_name, - class_var, nullable); + class_var, + nullable ? "true" : "false"); converted = CFCUtil_cat(converted, conversion, NULL); FREEMEM(conversion); if (CFCType_decremented(type)) { http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7988b5ff/runtime/go/clownfish/clownfish.go ---------------------------------------------------------------------- diff --git a/runtime/go/clownfish/clownfish.go b/runtime/go/clownfish/clownfish.go index b5a9401..b31ed5f 100644 --- a/runtime/go/clownfish/clownfish.go +++ b/runtime/go/clownfish/clownfish.go @@ -66,6 +66,7 @@ GoCfish_RunRoutine(CFISH_Err_Attempt_t routine, void *context) { import "C" import "runtime" import "unsafe" +import "reflect" import "fmt" import "math" import "sync" @@ -124,7 +125,7 @@ type ObjIMP struct { } func GetClass(o Obj) Class { - objCF := (*C.cfish_Obj)(unsafe.Pointer(o.TOPTR())) + objCF := (*C.cfish_Obj)(Unwrap(o, "o")) classCF := C.cfish_Obj_get_class(objCF) return WRAPClass(unsafe.Pointer(classCF)) } @@ -137,7 +138,7 @@ func FetchClass(className string) Class { } func (c *ClassIMP) GetMethods() []Method { - self := (*C.cfish_Class)(unsafe.Pointer(c.TOPTR())) + self := (*C.cfish_Class)(Unwrap(c, "c")) methsVec := C.CFISH_Class_Get_Methods(self) size := C.CFISH_Vec_Get_Size(methsVec) meths := make([]Method, 0, int(size)) @@ -149,7 +150,7 @@ func (c *ClassIMP) GetMethods() []Method { } func (c *ClassIMP) MakeObj() Obj { - self := (*C.cfish_Class)(unsafe.Pointer(c.TOPTR())) + self := (*C.cfish_Class)(Unwrap(c, "c")) retvalCF := C.CFISH_Class_Make_Obj_IMP(self) return WRAPAny(unsafe.Pointer(retvalCF)) } @@ -170,7 +171,7 @@ func NewString(goString string) String { } func NewStringIterator(str String, offset uintptr) StringIterator { - strCF := (*C.cfish_String)(unsafe.Pointer(str.TOPTR())) + strCF := (*C.cfish_String)(Unwrap(str, "str")) iter := C.cfish_StrIter_new(strCF, C.size_t(offset)) return WRAPStringIterator(unsafe.Pointer(iter)) } @@ -192,13 +193,13 @@ func NewHash(size int) Hash { } func NewHashIterator(hash Hash) HashIterator { - hashCF := (*C.cfish_Hash)(unsafe.Pointer(hash.TOPTR())) + hashCF := (*C.cfish_Hash)(Unwrap(hash, "hash")) cfObj := C.cfish_HashIter_new(hashCF) return WRAPHashIterator(unsafe.Pointer(cfObj)) } func (h *HashIMP) Keys() []string { - self := (*C.cfish_Hash)(unsafe.Pointer(h.TOPTR())) + self := (*C.cfish_Hash)(Unwrap(h, "h")) keysCF := C.CFISH_Hash_Keys(self) numKeys := C.CFISH_Vec_Get_Size(keysCF) keys := make([]string, 0, int(numKeys)) @@ -224,7 +225,7 @@ func (o *ObjIMP) TOPTR() uintptr { } func (o *ObjIMP)Clone() Obj { - self := (*C.cfish_Obj)(unsafe.Pointer(o.TOPTR())) + self := (*C.cfish_Obj)(Unwrap(o, "o")) dupe := C.CFISH_Obj_Clone(self) return WRAPAny(unsafe.Pointer(dupe)).(Obj) } @@ -310,17 +311,25 @@ func GoToClownfish(value interface{}, class unsafe.Pointer, nullable bool) unsaf panic(NewErr(fmt.Sprintf("Can't convert a %T to %s", value, className))) } -func UnwrapClownfish(value Obj, name string, nullable bool) unsafe.Pointer { +func UnwrapNullable(value Obj) unsafe.Pointer { if value == nil { - if nullable { - return nil - } else { - panic(NewErr(fmt.Sprintf("%s cannot be nil", name))) - } + return nil + } + val := reflect.ValueOf(value) + if val.IsNil() { + return nil } return unsafe.Pointer(value.TOPTR()) } +func Unwrap(value Obj, name string) unsafe.Pointer { + ptr := UnwrapNullable(value) + if ptr == nil { + panic(NewErr(fmt.Sprintf("%s cannot be nil", name))) + } + return ptr +} + func goToString(value interface{}) unsafe.Pointer { switch v := value.(type) { case string: @@ -628,19 +637,19 @@ func TrapErr(routine func()) (trapped error) { } func (s *StringIMP) CodePointAt(tick uintptr) rune { - self := ((*C.cfish_String)(unsafe.Pointer(s.TOPTR()))) + self := ((*C.cfish_String)(Unwrap(s, "s"))) retvalCF := C.CFISH_Str_Code_Point_At(self, C.size_t(tick)) return rune(retvalCF) } func (s *StringIMP) CodePointFrom(tick uintptr) rune { - self := ((*C.cfish_String)(unsafe.Pointer(s.TOPTR()))) + self := ((*C.cfish_String)(Unwrap(s, "s"))) retvalCF := C.CFISH_Str_Code_Point_From(self, C.size_t(tick)) return rune(retvalCF) } func (s *StringIMP) SwapChars(match, replacement rune) string { - self := ((*C.cfish_String)(unsafe.Pointer(s.TOPTR()))) + self := ((*C.cfish_String)(Unwrap(s, "s"))) retvalCF := C.CFISH_Str_Swap_Chars(self, C.int32_t(match), C.int32_t(replacement)) defer C.cfish_dec_refcount(unsafe.Pointer(retvalCF)) return CFStringToGo(unsafe.Pointer(retvalCF)) @@ -665,6 +674,6 @@ func NewBlob(content []byte) Blob { } func (b *BlobIMP) GetBuf() uintptr { - self := (*C.cfish_Blob)(unsafe.Pointer(b.TOPTR())) + self := (*C.cfish_Blob)(Unwrap(b, "b")) return uintptr(unsafe.Pointer(C.CFISH_Blob_Get_Buf(self))) }
