On Wed, May 27, 2015 at 9:45 AM, nwellnhof <[email protected]> wrote:
> GitHub user nwellnhof opened a pull request:
>
>     https://github.com/apache/lucy-clownfish/pull/21
>
>     CLOWNFISH-50 Convert some Obj methods to inert functions
>
>     Make Obj_Get_Class, Obj_Get_Class_Name, and Obj_Is_A inert.
>
>     Changes to the Go bindings are untested.
>
>
> You can merge this pull request into a Git repository by running:
>
>     $ git pull https://github.com/nwellnhof/lucy-clownfish 
> CLOWNFISH-50-obj-method-to-inert
>
> Alternatively you can review and apply these changes as the patch at:
>
>     https://github.com/apache/lucy-clownfish/pull/21.patch
>
> To close this pull request, make a commit to your master/trunk branch
> with (at least) the following in the commit message:
>
>     This closes #21
>
> ----
> commit 6a8087c889bfb24db6dbc4aa306cf6d34b4d0423
> Author: Nick Wellnhofer <[email protected]>
> Date:   2015-05-27T15:23:59Z
>
>     Make Obj_Get_Class inert
>
> commit 2bec8bc4fa14f587ddc5b5e1ed52f6ff7ccd3d4b
> Author: Nick Wellnhofer <[email protected]>
> Date:   2015-05-27T15:47:31Z
>
>     Make Obj_Get_Class_Name inert
>
> commit fb12719d11db946293900a688ac3547e6ab75f17
> Author: Nick Wellnhofer <[email protected]>
> Date:   2015-05-27T16:34:31Z
>
>     Make Obj_Is_A inert
>
> ----

These patches look sound, but I think we will want to change some things -- +0
to merge.

In the Go bindings, I think it would be best not to implement these as methods
in the Obj interface, but instead as ordinary funcs.  The Obj interface is
already very large from a Go perspective.  See patch below my sig.

In the generated C headers, I think we should consider generating per-class
static inline wrappers instead of requiring users to cast.  For example, if we
generate this code...

    static CHY_INLINE bool
    LUCY_IXSEARCHER_IS_A(lucy_IndexSearcher *self, cfish_Class *ancestor) {
        return cfish_Obj_is_a((cfish_Obj*)self, ancestor);
    }

    static CHY_INLINE cfish_Class*
    LUCY_IXSEARCHER_GET_CLASS(lucy_IndexSearcher *self) {
        return cfish_Obj_get_class((cfish_Obj*)self);
    }

    static CHY_INLINE cfish_String*
    LUCY_IXSEARCHER_GET_CLASS_NAME(lucy_IndexSearcher *self) {
        return cfish_Obj_get_class_name((cfish_Obj*)self);
    }

... then client code can be type-safe:

    String *class_name = IXSEARCHER_GET_CLASS_NAME(searcher); // no cast

Finally, I think we should change the signature for is_a so that both `self`
and `ancestor` are `nullable`, and document it to return false in either case.
That's already the behavior of the implementation.

In contrast, `get_class` and `get_class_name` already have the proper
behavior: it should not be valid to supply a NULL self, and they should always
succeed.

Marvin Humphrey

diff --git a/runtime/go/build.go b/runtime/go/build.go
index 655b201..4a182c7 100644
--- a/runtime/go/build.go
+++ b/runtime/go/build.go
@@ -137,9 +137,6 @@ func runCFC() {
 func specMethods(parcel *cfc.Parcel) {
  objBinding := cfc.NewGoClass(parcel, "Clownfish::Obj")
  objBinding.SpecMethod("", "TOPTR() uintptr")
- objBinding.SpecMethod("", "GetClass() Class")
- objBinding.SpecMethod("", "GetClassName() string")
- objBinding.SpecMethod("", "IsA() bool")
  objBinding.Register()

  errBinding := cfc.NewGoClass(parcel, "Clownfish::Err")
diff --git a/runtime/go/clownfish/clownfish.go
b/runtime/go/clownfish/clownfish.go
index 2c446b9..f8016cc 100644
--- a/runtime/go/clownfish/clownfish.go
+++ b/runtime/go/clownfish/clownfish.go
@@ -92,21 +92,21 @@ func (o *ObjIMP) TOPTR() uintptr {
  return o.ref
 }

-func (o *ObjIMP) GetClass() Class {
- cfObj := (*C.cfish_Obj)(unsafe.Pointer(o.ref))
+func GetClass(o Obj) Class {
+ cfObj := (*C.cfish_Obj)(unsafe.Pointer(o.TOPTR()))
  class := C.cfish_Obj_get_class(cfObj)
  return WRAPClass(unsafe.Pointer(class))
 }

-func (o *ObjIMP) GetClassName() string {
- cfObj := (*C.cfish_Obj)(unsafe.Pointer(o.ref))
+func GetClassName(o Obj) string {
+ cfObj := (*C.cfish_Obj)(unsafe.Pointer(o.TOPTR()))
  className := C.cfish_Obj_get_class_name(cfObj)
  return CFStringToGo(unsafe.Pointer(className))
 }

-func (o *ObjIMP) IsA(class Class) bool {
- cfObj := (*C.cfish_Obj)(unsafe.Pointer(o.ref))
- cfClass := (*C.cfish_Class)(unsafe.Pointer(class.ref))
+func IsA(o Obj, class Class) bool {
+ cfObj := (*C.cfish_Obj)(unsafe.Pointer(o.TOPTR()))
+ cfClass := (*C.cfish_Class)(unsafe.Pointer(class.TOPTR()))
  retvalCF := C.cfish_Obj_is_a(cfObj, cfClass)
  return bool(retvalCF)
 }

Reply via email to