You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by ma...@apache.org on 2016/02/25 23:40:16 UTC

[01/17] lucy-clownfish git commit: Add missing `static` modifier.

Repository: lucy-clownfish
Updated Branches:
  refs/heads/master 7c80fb818 -> b9f22d149


Add missing `static` modifier.


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

Branch: refs/heads/master
Commit: 4b8d87bcbe098f92e7148ab84e27b619c089218e
Parents: 7c80fb8
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Wed Feb 24 15:19:18 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:19:18 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/4b8d87bc/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index a2b13a4..e17feeb 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -39,7 +39,7 @@ struct CFCPython {
     char *footer;
 };
 
-void
+static void
 S_destroy(CFCPython *self);
 
 static const CFCMeta CFCPYTHON_META = {
@@ -58,7 +58,7 @@ CFCPython_new(CFCHierarchy *hierarchy) {
     return self;
 }
 
-void
+static void
 S_destroy(CFCPython *self) {
     CFCBase_decref((CFCBase*)self->hierarchy);
     FREEMEM(self->header);


[03/17] lucy-clownfish git commit: Create mapping from Py type to CF Class.

Posted by ma...@apache.org.
Create mapping from Py type to CF Class.

Before initializing Clownfish Class objects, create a mapping which
mates the addresses of Clownfish Class objects to their corresponding
PyTypeObjects.


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

Branch: refs/heads/master
Commit: d7133b8d149e2090331b767c1f54d5bf118d1a43
Parents: def4923
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 14:37:58 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c      |  2 +-
 runtime/python/cfext/CFBind.c | 63 ++++++++++++++++++++++++++++++++++++++
 runtime/python/cfext/CFBind.h |  7 +++++
 3 files changed, 71 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d7133b8d/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index de19a9c..15f835f 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -398,7 +398,7 @@ S_gen_type_linkups(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
         "    PyTypeObject **py_types = (PyTypeObject**)CFISH_MALLOCATE(py_types_size);\n"
         "%s\n"
         "%s\n"
-        "    //CFBind_assoc_py_types(handles, py_types, num_items);\n"
+        "    CFBind_assoc_py_types(handles, py_types, num_items);\n"
         "    CFISH_FREEMEM(handles);\n"
         "    CFISH_FREEMEM(py_types);\n"
         "}\n"

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d7133b8d/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 48743a7..2f8d657 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -36,6 +36,7 @@
 #include "Clownfish/Num.h"
 #include "Clownfish/String.h"
 #include "Clownfish/TestHarness/TestUtils.h"
+#include "Clownfish/Util/Atomic.h"
 #include "Clownfish/Util/Memory.h"
 #include "Clownfish/Util/StringHelper.h"
 #include "Clownfish/Vector.h"
@@ -767,6 +768,68 @@ CFBind_maybe_convert_bool(PyObject *py_obj, bool *ptr) {
     return S_convert_bool(py_obj, ptr, true);
 }
 
+typedef struct ClassMapElem {
+    cfish_Class **klass_handle;
+    PyTypeObject *py_type;
+} ClassMapElem;
+
+typedef struct ClassMap {
+    int32_t size;
+    ClassMapElem *elems;
+} ClassMap;
+
+/* Before we can invoke methods on any Clownfish object safely, we must know
+ * about its corresponding Python type object.  This association must be made
+ * early in the bootstrapping process, which is tricky.  We can't use any
+ * of Clownfish's convenient data structures yet!
+ */
+static ClassMap *klass_map = NULL;
+
+static ClassMap*
+S_revise_class_map(ClassMap *current, cfish_Class ***klass_handles,
+                   PyTypeObject **py_types, int32_t num_items) {
+    int32_t num_current = current ? current->size : 0;
+    int32_t total = num_current + num_items;
+    ClassMap *revised = (ClassMap*)malloc(sizeof(ClassMap));
+    revised->elems = (ClassMapElem*)malloc(total * sizeof(ClassMapElem));
+    if (current) {
+        size_t size = num_current * sizeof(ClassMapElem);
+        memcpy(revised->elems, current->elems, size);
+    }
+    for (int32_t i = 0; i < num_items; i++) {
+        revised->elems[i + num_current].klass_handle = klass_handles[i];
+        revised->elems[i + num_current].py_type      = py_types[i];
+    }
+    revised->size = total;
+    return revised;
+}
+
+void
+CFBind_assoc_py_types(cfish_Class ***klass_handles, PyTypeObject **py_types,
+                      int32_t num_items) {
+    while (1) {
+        ClassMap *current = klass_map;
+        ClassMap *revised = S_revise_class_map(current, klass_handles,
+                                               py_types, num_items);
+        if (cfish_Atomic_cas_ptr((void*volatile*)&klass_map, current, revised)) {
+            if (current) {
+                // TODO: Use read locking.  For now we have to leak this
+                // memory to avoid memory errors in case another thread isn't
+                // done reading it yet.
+
+                //free(current->elems);
+                //free(current);
+            }
+            break;
+        }
+        else {
+            // Another thread beat us to it.  Try again.
+            free(revised->elems);
+            free(revised);
+        }
+    }
+}
+
 /**** refcounting **********************************************************/
 
 uint32_t

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/d7133b8d/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index 9279510..0064985 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -112,6 +112,13 @@ cfish_Obj*
 CFBind_py_to_cfish_noinc(PyObject *py_obj, cfish_Class *klass,
                          void *allocation);
 
+/** Associate Clownfish classes with Python type objects.  (Internal-only,
+  * used during bootstrapping.)
+  */
+void
+CFBind_assoc_py_types(struct cfish_Class ***klass_handles,
+                      PyTypeObject **py_types, int32_t num_items);
+
 typedef struct CFBindArg {
     cfish_Class *klass;
     void        *ptr;


[10/17] lucy-clownfish git commit: Invoke `PyType_Ready` for inert classes.

Posted by ma...@apache.org.
Invoke `PyType_Ready` for inert classes.


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

Branch: refs/heads/master
Commit: c9cbb2dcfd3e9435134bf89812f8d0dad363ae10
Parents: 50c98b1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 17:03:13 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c9cbb2dc/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 7921fbe..a2d28df 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -457,14 +457,26 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *type_linkups       = S_gen_type_linkups(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
+    char *pytype_ready_calls = CFCUtil_strdup("");
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
         if (CFCClass_included(klass)) { continue; }
+        const char *struct_sym = CFCClass_get_struct_sym(klass);
 
         const char *include_h  = CFCClass_include_h(klass);
         pound_includes = CFCUtil_cat(pound_includes, "#include \"",
                                      include_h, "\"\n", NULL);
+
+        // The PyType_Ready invocations for instantiable classes are handled
+        // via bootstrapping of Clownfish Class objects.  Since inert classes
+        // do not at present have Class objects, we need to handle their
+        // PyType_Ready calls independently.
+        if (CFCClass_inert(klass)) {
+            pytype_ready_calls = CFCUtil_cat(pytype_ready_calls,
+                "    if (PyType_Ready(&", struct_sym,
+                "_pytype_struct) < 0) { return NULL; }\n", NULL);
+        }
     }
 
     const char pattern[] =
@@ -492,6 +504,9 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
         "    cfish_Class_bootstrap_hook1 = CFBind_class_bootstrap_hook1;\n"
+        "\n"
+        "%s\n" // PyType_Ready calls
+        "\n"
         "    S_link_py_types();\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"
@@ -503,7 +518,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
                           helper_mod_name, class_bindings, type_linkups,
-                          last_component, self->footer);
+                          last_component, pytype_ready_calls, self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -511,6 +526,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(filepath);
 
     FREEMEM(content);
+    FREEMEM(pytype_ready_calls);
     FREEMEM(class_bindings);
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);


[12/17] lucy-clownfish git commit: Bootstrap Clownfish parcels in Python build.

Posted by ma...@apache.org.
Bootstrap Clownfish parcels in Python build.

Finally, the Python implementation is complete enough that we can run
the bootstrapping for the Clownfish parcel.


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

Branch: refs/heads/master
Commit: 67b76306dd136fe88a392d4d489bfd26f0f2f750
Parents: c9cbb2d
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 17:08:27 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/67b76306/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index a2d28df..068c9c4 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -457,8 +457,18 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *type_linkups       = S_gen_type_linkups(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
+    char *parcel_boots       = CFCUtil_strdup("");
     char *pytype_ready_calls = CFCUtil_strdup("");
 
+    // Add parcel bootstrapping calls.
+    for (size_t i = 0; parcels[i]; ++i) {
+        if (!CFCParcel_included(parcels[i])) {
+            const char *prefix = CFCParcel_get_prefix(parcels[i]);
+            parcel_boots = CFCUtil_cat(parcel_boots, "    ", prefix,
+                                       "bootstrap_parcel();\n", NULL);
+        }
+    }
+
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
         if (CFCClass_included(klass)) { continue; }
@@ -508,6 +518,9 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "%s\n" // PyType_Ready calls
         "\n"
         "    S_link_py_types();\n"
+        "\n"
+        "%s\n" // parcel boots
+        "\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"
         "}\n"
@@ -518,7 +531,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
                           helper_mod_name, class_bindings, type_linkups,
-                          last_component, pytype_ready_calls, self->footer);
+                          last_component, pytype_ready_calls, parcel_boots,
+                          self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -527,6 +541,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
 
     FREEMEM(content);
     FREEMEM(pytype_ready_calls);
+    FREEMEM(parcel_boots);
     FREEMEM(class_bindings);
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);


[06/17] lucy-clownfish git commit: Gen list of Py types.

Posted by ma...@apache.org.
Gen list of Py types.

Generate a function which creates two arrays: one of Clownfish Class
objects, and one of their corresponding Python type objects.


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

Branch: refs/heads/master
Commit: def49238ff3a86cda15baee6cca567d552770be1
Parents: cd5438b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 14:12:13 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c | 57 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 55 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/def49238/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index c7ae4c2..de19a9c 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -363,6 +363,54 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
 }
 
 static char*
+S_gen_type_linkups(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
+    char *handles  = CFCUtil_strdup("");
+    char *py_types = CFCUtil_strdup("");
+    int num_items = 0;
+
+    for (size_t i = 0; ordered[i] != NULL; i++) {
+        CFCClass *klass = ordered[i];
+        if (CFCClass_included(klass) || CFCClass_inert(klass)) {
+            continue;
+        }
+        const char *class_var = CFCClass_full_class_var(klass);
+        const char *struct_sym = CFCClass_get_struct_sym(klass);
+        char *handles_temp
+            = CFCUtil_sprintf("%s    handles[%d]  = &%s;\n",
+                              handles, num_items, class_var);
+        char *py_types_temp
+            = CFCUtil_sprintf("%s    py_types[%d] = &%s_pytype_struct;\n",
+                              py_types, num_items, struct_sym);
+        FREEMEM(handles);
+        FREEMEM(py_types);
+        handles  = handles_temp;
+        py_types = py_types_temp;
+        num_items++;
+    }
+
+    char pattern[] =
+        "static void\n"
+        "S_link_py_types(void) {\n"
+        "    const int num_items = %d;\n"
+        "    size_t handles_size  = num_items * sizeof(cfish_Class**);\n"
+        "    size_t py_types_size = num_items * sizeof(PyTypeObject*);\n"
+        "    cfish_Class ***handles  = (cfish_Class***)CFISH_MALLOCATE(handles_size);\n"
+        "    PyTypeObject **py_types = (PyTypeObject**)CFISH_MALLOCATE(py_types_size);\n"
+        "%s\n"
+        "%s\n"
+        "    //CFBind_assoc_py_types(handles, py_types, num_items);\n"
+        "    CFISH_FREEMEM(handles);\n"
+        "    CFISH_FREEMEM(py_types);\n"
+        "}\n"
+        ;
+    char *content = CFCUtil_sprintf(pattern, num_items, handles, py_types);
+
+    FREEMEM(handles);
+    FREEMEM(py_types);
+    return content;
+}
+
+static char*
 S_gen_class_bindings(CFCPython *self, CFCParcel *parcel,
                      const char *pymod_name, CFCClass **ordered) {
     char *bindings = CFCUtil_strdup("");
@@ -406,6 +454,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     CFCClass  **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
     CFCParcel **parcels = CFCParcel_all_parcels();
     char *callbacks          = S_gen_callbacks(self, parcel, ordered);
+    char *type_linkups       = S_gen_type_linkups(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
 
@@ -438,8 +487,11 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "\n"
         "%s" // class bindings
         "\n"
+        "%s" // S_link_py_types function
+        "\n"
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
+        "    S_link_py_types();\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"
         "}\n"
@@ -449,8 +501,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
 
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
-                          helper_mod_name, class_bindings, last_component,
-                          self->footer);
+                          helper_mod_name, class_bindings, type_linkups,
+                          last_component, self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -462,6 +514,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);
     FREEMEM(pound_includes);
+    FREEMEM(type_linkups);
     FREEMEM(callbacks);
     FREEMEM(ordered);
 }


[11/17] lucy-clownfish git commit: Add classes to Python module object.

Posted by ma...@apache.org.
Add classes to Python module object.

For instance, make `clownfish.String` available on the Python
`clownfish` module object.


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

Branch: refs/heads/master
Commit: 49972c1cbc6b6f9ae4ad55c6d26b69e491e63741
Parents: 67b7630
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 17:13:37 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c              | 10 +++++++++-
 runtime/python/test/test_clownfish.py |  2 ++
 2 files changed, 11 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/49972c1c/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 068c9c4..d108b69 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -459,6 +459,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
     char *parcel_boots       = CFCUtil_strdup("");
     char *pytype_ready_calls = CFCUtil_strdup("");
+    char *module_adds        = CFCUtil_strdup("");
 
     // Add parcel bootstrapping calls.
     for (size_t i = 0; parcels[i]; ++i) {
@@ -487,6 +488,10 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
                 "    if (PyType_Ready(&", struct_sym,
                 "_pytype_struct) < 0) { return NULL; }\n", NULL);
         }
+
+        module_adds = CFCUtil_cat(module_adds, "    PyModule_AddObject(module, \"",
+                                  struct_sym, "\", (PyObject*)&", struct_sym,
+                                  "_pytype_struct);\n", NULL);
     }
 
     const char pattern[] =
@@ -522,6 +527,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "%s\n" // parcel boots
         "\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
+        "%s\n" // Add types to module
+        "\n"
         "    return module;\n"
         "}\n"
         "\n"
@@ -532,7 +539,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
                           helper_mod_name, class_bindings, type_linkups,
                           last_component, pytype_ready_calls, parcel_boots,
-                          self->footer);
+                          module_adds, self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -540,6 +547,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(filepath);
 
     FREEMEM(content);
+    FREEMEM(module_adds);
     FREEMEM(pytype_ready_calls);
     FREEMEM(parcel_boots);
     FREEMEM(class_bindings);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/49972c1c/runtime/python/test/test_clownfish.py
----------------------------------------------------------------------
diff --git a/runtime/python/test/test_clownfish.py b/runtime/python/test/test_clownfish.py
index fd124d3..d8f2594 100644
--- a/runtime/python/test/test_clownfish.py
+++ b/runtime/python/test/test_clownfish.py
@@ -21,6 +21,8 @@ class MyTest(unittest.TestCase):
     def testTrue(self):
         self.assertTrue(True, "True should be true")
 
+    def testClassesPresent(self):
+        self.assertIsInstance(clownfish.Hash, type)
 
 if __name__ == '__main__':
     unittest.main()


[08/17] lucy-clownfish git commit: Given a Class, find its PyTypeObject.

Posted by ma...@apache.org.
Given a Class, find its PyTypeObject.

Cache the PyTypeObject inside the Clownfish Class object, in a
`host_type` member.


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

Branch: refs/heads/master
Commit: 2b37cc17c94eabbb27efeb090fd5827eac74807a
Parents: d7133b8
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 14:47:34 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 runtime/core/Clownfish/Class.cfh |  1 +
 runtime/python/cfext/CFBind.c    | 43 +++++++++++++++++++++++++++++------
 2 files changed, 37 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b37cc17/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index dbb31cb..c87964f 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -32,6 +32,7 @@ public final class Clownfish::Class inherits Clownfish::Obj {
     int32_t             parcel_id;
     uint32_t            obj_alloc_size;
     uint32_t            class_alloc_size;
+    void               *host_type;
     Method            **methods;
     cfish_method_t[1]   vtable; /* flexible array */
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b37cc17/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 2f8d657..f73b76a 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -50,10 +50,8 @@ S_get_cached_py_type(cfish_Class *klass);
 
 static bool
 S_py_obj_is_a(PyObject *py_obj, cfish_Class *klass) {
-    CFISH_UNUSED_VAR(py_obj);
-    CFISH_UNUSED_VAR(klass);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(bool);
+    PyTypeObject *py_type = S_get_cached_py_type(klass);
+    return !!PyObject_TypeCheck(py_obj, py_type);
 }
 
 void
@@ -859,11 +857,42 @@ CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
 
 /**** Class ****************************************************************/
 
+/* Check the Class object for its associated PyTypeObject, which is stored in
+ * `klass->host_type`.  If it is not there yet, search the class mapping and
+ * cache it in the object.  Return the PyTypeObject.
+ */
 static PyTypeObject*
 S_get_cached_py_type(cfish_Class *self) {
-    // FIXME: dummy implementation
-    CFISH_UNUSED_VAR(self);
-    return NULL;
+    PyTypeObject *py_type = (PyTypeObject*)self->host_type;
+    if (py_type == NULL) {
+        ClassMap *current = klass_map;
+        for (int32_t i = 0; i < current->size; i++) {
+            cfish_Class **handle = current->elems[i].klass_handle;
+            if (handle == NULL || *handle != self) {
+                continue;
+            }
+            py_type = current->elems[i].py_type;
+            Py_INCREF(py_type);
+            if (!cfish_Atomic_cas_ptr((void*volatile*)&self->host_type, py_type, NULL)) {
+                // Lost the race to another thread, so get rid of the refcount.
+                Py_DECREF(py_type);
+            }
+            break;
+        }
+    }
+    if (py_type == NULL) {
+        if (Err_initialized) {
+            CFISH_THROW(CFISH_ERR,
+                        "Can't find a Python type object corresponding to %o",
+                        CFISH_Class_Get_Name(self));
+        }
+        else {
+            fprintf(stderr, "Can't find a Python type corresponding to a "
+                            "Clownfish class\n");
+            exit(1);
+        }
+    }
+    return py_type;
 }
 
 cfish_Obj*


[15/17] lucy-clownfish git commit: Add CFCPyMethod and CFCPyClass to CFC.h.

Posted by ma...@apache.org.
Add CFCPyMethod and CFCPyClass to CFC.h.


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

Branch: refs/heads/master
Commit: a15800378cb8f27b2a572961d67fc833a136ea08
Parents: 49972c1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 18:17:59 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:39 2016 -0800

----------------------------------------------------------------------
 compiler/include/CFC.h | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a1580037/compiler/include/CFC.h
----------------------------------------------------------------------
diff --git a/compiler/include/CFC.h b/compiler/include/CFC.h
index 1bdc968..fdd34c8 100644
--- a/compiler/include/CFC.h
+++ b/compiler/include/CFC.h
@@ -58,6 +58,8 @@
 #include "CFCPerlTypeMap.h"
 
 #include "CFCPython.h"
+#include "CFCPyClass.h"
+#include "CFCPyMethod.h"
 
 #include "CFCRuby.h"
 


[13/17] lucy-clownfish git commit: Tell Python about obj alloc sizes.

Posted by ma...@apache.org.
Tell Python about obj alloc sizes.

As a consequence of Clownfish using Python object allocation internally
under the Python bindings, bootstrapping Clownfish Classes and Python
type objects requires some intricate interplay.


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

Branch: refs/heads/master
Commit: c6c74d2718fdac87eb9c2330f75eca93dbaa94da
Parents: 3e9cd9e
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 16:43:49 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPython.c         |  1 +
 runtime/core/Clownfish/Class.c   |  4 ++++
 runtime/core/Clownfish/Class.cfh |  8 ++++++++
 runtime/python/cfext/CFBind.c    | 33 +++++++++++++++++++++++++++++++++
 runtime/python/cfext/CFBind.h    |  3 +++
 5 files changed, 49 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index 15f835f..7921fbe 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -491,6 +491,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "\n"
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
+        "    cfish_Class_bootstrap_hook1 = CFBind_class_bootstrap_hook1;\n"
         "    S_link_py_types();\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
         "    return module;\n"

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/core/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c
index ba83928..68258c6 100644
--- a/runtime/core/Clownfish/Class.c
+++ b/runtime/core/Clownfish/Class.c
@@ -54,6 +54,7 @@ static int32_t
 S_claim_parcel_id(void);
 
 static LockFreeRegistry *Class_registry;
+cfish_Class_bootstrap_hook1_t cfish_Class_bootstrap_hook1;
 
 void
 Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs,
@@ -146,6 +147,9 @@ Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs,
         else {
             klass->obj_alloc_size = ivars_offset + spec->ivars_size;
         }
+        if (cfish_Class_bootstrap_hook1 != NULL) {
+            cfish_Class_bootstrap_hook1(klass);
+        }
 
         klass->flags = 0;
         if (klass == CLASS

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index c87964f..a5c83ab 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -149,5 +149,13 @@ __C__
 #define CFISH_ALLOCA_OBJ(class) \
     cfish_alloca(CFISH_Class_Get_Obj_Alloc_Size(class))
 
+/** Bootstrapping hook/hack needed by the Python bindings.
+ *
+ * TODO: Refactor this away in favor of a more general solution.
+ */
+typedef void
+(*cfish_Class_bootstrap_hook1_t)(cfish_Class *self);
+extern cfish_Class_bootstrap_hook1_t cfish_Class_bootstrap_hook1;
+
 __END_C__
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 99ad069..2471487 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -857,6 +857,39 @@ CFISH_Obj_To_Host_IMP(cfish_Obj *self) {
 
 /**** Class ****************************************************************/
 
+/* Tell Python about the size of Clownfish objects, by copying
+ * `cfclass->obj_alloc_size` into `pytype->tp_basicsize`.
+ * **THIS MUST BE RUN BEFORE Class_Make_Obj IS CALLED** because under the
+ * Python bindings, Clownfish uses Python object allocation internally.
+ * Furthermore, `tp_basicsize` is supposed to be set before `PyType_Ready()`
+ * is called.
+ *
+ * Ideally we would set `tp_basicsize` from within `Class_register_with_host`,
+ * but it doesn't get called until too late.
+ */
+void
+CFBind_class_bootstrap_hook1(cfish_Class *self) {
+    PyTypeObject *py_type = S_get_cached_py_type(self);
+    if (PyType_HasFeature(py_type, Py_TPFLAGS_READY)) {
+        if (py_type->tp_basicsize != (Py_ssize_t)self->obj_alloc_size) {
+            fprintf(stderr, "PyType for %s readied with wrong alloc size\n",
+                    py_type->tp_name),
+            exit(1);
+        }
+    }
+    else {
+        if (self->parent) {
+            py_type->tp_base = S_get_cached_py_type(self->parent);
+        }
+        py_type->tp_basicsize = self->obj_alloc_size;
+        if (PyType_Ready(py_type) < 0) {
+            fprintf(stderr, "PyType_Ready failed for %s\n",
+                    py_type->tp_name),
+            exit(1);
+        }
+    }
+}
+
 /* Check the Class object for its associated PyTypeObject, which is stored in
  * `klass->host_type`.  If it is not there yet, search the class mapping and
  * cache it in the object.  Return the PyTypeObject.

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/c6c74d27/runtime/python/cfext/CFBind.h
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.h b/runtime/python/cfext/CFBind.h
index 0064985..9c8d53f 100644
--- a/runtime/python/cfext/CFBind.h
+++ b/runtime/python/cfext/CFBind.h
@@ -219,6 +219,9 @@ CFBind_maybe_convert_float(PyObject *input, float *ptr);
 int
 CFBind_maybe_convert_double(PyObject *input, double *ptr);
 
+void
+CFBind_class_bootstrap_hook1(struct cfish_Class *self);
+
 #ifdef __cplusplus
 }
 #endif


[14/17] lucy-clownfish git commit: Reuse lower_snake_case code for host aliases.

Posted by ma...@apache.org.
Reuse lower_snake_case code for host aliases.

Method host aliases for both Perl and Python use lower_snake_case, so
share the implementation.


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

Branch: refs/heads/master
Commit: 3e9cd9e45094eea32150622467b3061e5f3e0409
Parents: 33189df
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 16:13:09 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 runtime/core/Clownfish/Method.c   | 26 ++++++++++++++++++++++++++
 runtime/core/Clownfish/Method.cfh |  6 ++++++
 runtime/perl/xs/XSBind.c          | 24 +-----------------------
 runtime/python/cfext/CFBind.c     |  4 +---
 4 files changed, 34 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/core/Clownfish/Method.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Method.c b/runtime/core/Clownfish/Method.c
index c75bd4c..6bf1508 100644
--- a/runtime/core/Clownfish/Method.c
+++ b/runtime/core/Clownfish/Method.c
@@ -21,6 +21,7 @@
 #include "Clownfish/String.h"
 #include "Clownfish/Err.h"
 #include "Clownfish/Class.h"
+#include "Clownfish/CharBuf.h"
 
 Method*
 Method_new(String *name, cfish_method_t callback_func, uint32_t offset) {
@@ -81,4 +82,29 @@ Method_Is_Excluded_From_Host_IMP(Method *self) {
     return self->is_excluded;
 }
 
+String*
+Method_lower_snake_alias(cfish_Method *method) {
+    cfish_String *host_alias = CFISH_Method_Get_Host_Alias(method);
+    if (host_alias) {
+        return (cfish_String*)CFISH_INCREF(host_alias);
+    }
 
+    // Convert to lowercase.
+    cfish_String *name = CFISH_Method_Get_Name(method);
+    cfish_CharBuf *buf = cfish_CB_new(CFISH_Str_Get_Size(name));
+    cfish_StringIterator *iter = CFISH_Str_Top(name);
+    int32_t code_point;
+    while (CFISH_STR_OOB != (code_point = CFISH_StrIter_Next(iter))) {
+        if (code_point > 127) {
+            THROW(CFISH_ERR, "Can't lowercase '%o'", name);
+        }
+        else {
+            CFISH_CB_Cat_Char(buf, tolower(code_point));
+        }
+    }
+    cfish_String *retval = CFISH_CB_Yield_String(buf);
+    CFISH_DECREF(iter);
+    CFISH_DECREF(buf);
+
+    return retval;
+}

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/core/Clownfish/Method.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Method.cfh b/runtime/core/Clownfish/Method.cfh
index 3fa8633..2fc4314 100644
--- a/runtime/core/Clownfish/Method.cfh
+++ b/runtime/core/Clownfish/Method.cfh
@@ -53,6 +53,12 @@ final class Clownfish::Method inherits Clownfish::Obj {
 
     public void
     Destroy(Method *self);
+
+    /** Return either a specified host alias or a lower-snake-case version of
+      * the method name.
+      */
+    inert incremented String*
+    lower_snake_alias(Method *method);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/perl/xs/XSBind.c
----------------------------------------------------------------------
diff --git a/runtime/perl/xs/XSBind.c b/runtime/perl/xs/XSBind.c
index 813afe0..85bd85b 100644
--- a/runtime/perl/xs/XSBind.c
+++ b/runtime/perl/xs/XSBind.c
@@ -710,29 +710,7 @@ cfish_Class_find_parent_class(cfish_String *class_name) {
 
 cfish_String*
 CFISH_Method_Host_Name_IMP(cfish_Method *self) {
-    cfish_String *host_alias = CFISH_Method_Get_Host_Alias(self);
-    if (host_alias) {
-        return (cfish_String*)CFISH_INCREF(host_alias);
-    }
-
-    // Convert to lowercase.
-    cfish_String *name = CFISH_Method_Get_Name(self);
-    cfish_CharBuf *buf = cfish_CB_new(CFISH_Str_Get_Size(name));
-    cfish_StringIterator *iter = CFISH_Str_Top(name);
-    int32_t code_point;
-    while (CFISH_STR_OOB != (code_point = CFISH_StrIter_Next(iter))) {
-        if (code_point > 127) {
-            THROW(CFISH_ERR, "Can't lowercase '%o'", name);
-        }
-        else {
-            CFISH_CB_Cat_Char(buf, tolower(code_point));
-        }
-    }
-    cfish_String *retval = CFISH_CB_Yield_String(buf);
-    CFISH_DECREF(iter);
-    CFISH_DECREF(buf);
-
-    return retval;
+    return cfish_Method_lower_snake_alias(self);
 }
 
 /***************************** Clownfish::Err *******************************/

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/3e9cd9e4/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 69ab9bd..99ad069 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -938,9 +938,7 @@ cfish_Class_find_parent_class(cfish_String *class_name) {
 
 cfish_String*
 CFISH_Method_Host_Name_IMP(cfish_Method *self) {
-    CFISH_UNUSED_VAR(self);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_String*);
+    return cfish_Method_lower_snake_alias(self);
 }
 
 /**** Err ******************************************************************/


[04/17] lucy-clownfish git commit: Gen PyTypeObject structs and empty method lists.

Posted by ma...@apache.org.
Gen PyTypeObject structs and empty method lists.


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

Branch: refs/heads/master
Commit: cd5438b7e31dab8fdd00cb4da47529fa7e6b3614
Parents: f0048b3
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Jan 28 18:26:45 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c | 94 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 93 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/cd5438b7/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
index e79c2d4..9f46b60 100644
--- a/compiler/src/CFCPyClass.c
+++ b/compiler/src/CFCPyClass.c
@@ -15,6 +15,7 @@
  */
 
 #include <string.h>
+#include <ctype.h>
 #include <stdlib.h>
 
 #define CFC_NEED_BASE_STRUCT_DEF 1
@@ -44,6 +45,9 @@ static size_t registry_cap  = 0;
 static void
 S_CFCPyClass_destroy(CFCPyClass *self);
 
+static char*
+S_pytype_struct_def(CFCPyClass *self);
+
 static const CFCMeta CFCPERLCLASS_META = {
     "Clownfish::CFC::Binding::Python::Class",
     sizeof(CFCPyClass),
@@ -134,5 +138,93 @@ CFCPyClass_clear_registry(void) {
 
 char*
 CFCPyClass_gen_binding_code(CFCPyClass *self) {
-    return CFCUtil_strdup("");
+    if (!self->client) {
+        CFCUtil_die("No Clownfish class defined for %s", self->class_name);
+    }
+    CFCClass *klass = self->client;
+    char *bindings  = CFCUtil_strdup(self->pre_code ? self->pre_code : "");
+    char *meth_defs = CFCUtil_strdup(self->meth_defs);
+
+    // Complete the PyMethodDef array.
+    const char *struct_sym = CFCClass_get_struct_sym(klass);
+    char *meth_defs_pattern =
+        "static PyMethodDef %s_pymethods[] = {\n"
+        "%s"
+        "   {NULL}\n"
+        "};\n"
+        ;
+    char *meth_defs_array = CFCUtil_sprintf(meth_defs_pattern, struct_sym,
+                                            meth_defs);
+    bindings = CFCUtil_cat(bindings, meth_defs_array, NULL);
+    FREEMEM(meth_defs_array);
+    FREEMEM(meth_defs);
+
+    // PyTypeObject struct def.
+    char *struct_def = S_pytype_struct_def(self);
+    bindings = CFCUtil_cat(bindings, struct_def, NULL);
+    FREEMEM(struct_def);
+
+    return bindings;
+}
+
+static char*
+S_pytype_struct_def(CFCPyClass *self) {
+    CFCClass *klass = self->client;
+    const char *parcel_name = CFCParcel_get_name(self->parcel);
+    char *pymod_name = CFCUtil_strdup(parcel_name);
+    // TODO: Stop lowercasing when parcels are restricted to lowercase.
+    for (int i = 0; pymod_name[i] != '\0'; i++) {
+        pymod_name[i] = tolower(pymod_name[i]);
+    }
+
+    const char *struct_sym = CFCClass_get_struct_sym(klass);
+
+    char pattern[] =
+        "static PyTypeObject %s_pytype_struct = {\n"
+        "    PyVarObject_HEAD_INIT(NULL, 0)\n"
+        "    \"%s.%s\", // tp_name\n"
+        "    0,                                  // tp_basicsize THIS IS A LIE!\n"
+        "    0,                                  // tp_itemsize\n"
+        "    0,                                  // tp_dealloc\n"
+        "    0,                                  // tp_print\n"
+        "    0,                                  // tp_getattr\n"
+        "    0,                                  // tp_setattr\n"
+        "    0,                                  // tp_reserved\n"
+        "    0,                                  // tp_repr\n"
+        "    0,                                  // tp_as_number\n"
+        "    0,                                  // tp_as_sequence\n"
+        "    0,                                  // tp_as_mapping\n"
+        "    0,                                  // tp_hash\n"
+        "    0,                                  // tp_call\n"
+        "    0,                                  // tp_str\n"
+        "    0,                                  // tp_getattro\n"
+        "    0,                                  // tp_setattro\n"
+        "    0,                                  // tp_as_buffer\n"
+        "    Py_TPFLAGS_DEFAULT,                 // tp_flags\n"
+        "    0,                                  // tp_doc\n"
+        "    0,                                  // tp_traverse\n"
+        "    0,                                  // tp_clear\n"
+        "    0,                                  // tp_richcompare\n"
+        "    0,                                  // tp_weaklistoffset\n"
+        "    0,                                  // tp_iter\n"
+        "    0,                                  // tp_iternext\n"
+        "    %s_pymethods,                       // tp_methods\n"
+        "    0,                                  // tp_members\n"
+        "    0,                                  // tp_getset\n"
+        "    0,                                  // tp_base\n"
+        "    0,                                  // tp_dict\n"
+        "    0,                                  // tp_descr_get\n"
+        "    0,                                  // tp_descr_set\n"
+        "    0,                                  // tp_dictoffset\n"
+        "    0,                                  // tp_init\n"
+        "    0,                                  // tp_allow\n"
+        "    0,                                  // tp_new\n"
+        "};\n"
+        ;
+    char *content = CFCUtil_sprintf(pattern, struct_sym, pymod_name,
+                                    struct_sym, struct_sym);
+
+    FREEMEM(pymod_name);
+    return content;
 }
+


[16/17] lucy-clownfish git commit: Add missing C header for `tolower`.

Posted by ma...@apache.org.
Add missing C header for `tolower`.


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

Branch: refs/heads/master
Commit: 77ce74620a785d534b63a3ca890336009e79ac05
Parents: a158003
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Feb 25 14:18:47 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Thu Feb 25 14:18:47 2016 -0800

----------------------------------------------------------------------
 runtime/core/Clownfish/Method.c | 2 ++
 1 file changed, 2 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/77ce7462/runtime/core/Clownfish/Method.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Method.c b/runtime/core/Clownfish/Method.c
index 6bf1508..a044f35 100644
--- a/runtime/core/Clownfish/Method.c
+++ b/runtime/core/Clownfish/Method.c
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <ctype.h>
+
 #define C_CFISH_METHOD
 #define CFISH_USE_SHORT_NAMES
 


[17/17] lucy-clownfish git commit: Merge branch 'CLOWNFISH-66-py-glue2'

Posted by ma...@apache.org.
Merge branch 'CLOWNFISH-66-py-glue2'

Make PyTypeObjects and Clownfish Classes work together.

* Generate PyTypeObject def for each Clownfish class.
* Object allocation and initialization for Py glue.
* Make Clownfish classes aware of their corresponding PyTypeObjects.
* Bootstrap Clownfish parcels and Classes, Python type objects and
  modules.

This closes #59.


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

Branch: refs/heads/master
Commit: b9f22d1490540e1107f73c9fb7ea8715af8854ea
Parents: 7c80fb8 77ce746
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Feb 25 14:20:47 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Thu Feb 25 14:20:47 2016 -0800

----------------------------------------------------------------------
 compiler/include/CFC.h                |   2 +
 compiler/src/CFCPyClass.c             | 230 +++++++++++++++++++++++++++++
 compiler/src/CFCPyClass.h             |  64 ++++++++
 compiler/src/CFCPython.c              | 129 +++++++++++++++-
 runtime/core/Clownfish/Class.c        |   4 +
 runtime/core/Clownfish/Class.cfh      |   9 ++
 runtime/core/Clownfish/Method.c       |  28 ++++
 runtime/core/Clownfish/Method.cfh     |   6 +
 runtime/perl/xs/XSBind.c              |  24 +--
 runtime/python/cfext/CFBind.c         | 181 ++++++++++++++++++++---
 runtime/python/cfext/CFBind.h         |  10 ++
 runtime/python/test/test_clownfish.py |   2 +
 12 files changed, 641 insertions(+), 48 deletions(-)
----------------------------------------------------------------------



[02/17] lucy-clownfish git commit: Stub out CFCPyClass.

Posted by ma...@apache.org.
Stub out CFCPyClass.

Stub module for generating Python binding for a Clownfish Class.


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

Branch: refs/heads/master
Commit: 72102abf76bbf6b86af8fd6b261bf4d040524a64
Parents: 4b8d87b
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Jan 28 14:55:45 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:36 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c | 68 ++++++++++++++++++++++++++++++++++++++++++
 compiler/src/CFCPyClass.h | 40 +++++++++++++++++++++++++
 2 files changed, 108 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/72102abf/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
new file mode 100644
index 0000000..8eaa702
--- /dev/null
+++ b/compiler/src/CFCPyClass.c
@@ -0,0 +1,68 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define CFC_NEED_BASE_STRUCT_DEF 1
+
+#include "CFCBase.h"
+#include "CFCPyClass.h"
+#include "CFCPyMethod.h"
+#include "CFCParcel.h"
+#include "CFCUtil.h"
+#include "CFCClass.h"
+#include "CFCFunction.h"
+#include "CFCMethod.h"
+
+struct CFCPyClass {
+    CFCBase base;
+    CFCParcel *parcel;
+    char *class_name;
+    CFCClass *client;
+    char *pre_code;
+    char *meth_defs;
+};
+
+static void
+S_CFCPyClass_destroy(CFCPyClass *self);
+
+static const CFCMeta CFCPERLCLASS_META = {
+    "Clownfish::CFC::Binding::Python::Class",
+    sizeof(CFCPyClass),
+    (CFCBase_destroy_t)S_CFCPyClass_destroy
+};
+
+CFCPyClass*
+CFCPyClass_new(CFCClass *client) {
+    CFCUTIL_NULL_CHECK(client);
+    CFCPyClass *self = (CFCPyClass*)CFCBase_allocate(&CFCPERLCLASS_META);
+    CFCParcel *parcel = CFCClass_get_parcel(client);
+    self->parcel = (CFCParcel*)CFCBase_incref((CFCBase*)parcel);
+    self->class_name = CFCUtil_strdup(CFCClass_get_name(client));
+    self->client = (CFCClass*)CFCBase_incref((CFCBase*)client);
+    self->pre_code = NULL;
+    self->meth_defs = CFCUtil_strdup("");
+    return self;
+}
+
+static void
+S_CFCPyClass_destroy(CFCPyClass *self) {
+    CFCBase_decref((CFCBase*)self->parcel);
+    CFCBase_decref((CFCBase*)self->client);
+    FREEMEM(self->class_name);
+    FREEMEM(self->pre_code);
+    FREEMEM(self->meth_defs);
+    CFCBase_destroy((CFCBase*)self);
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/72102abf/compiler/src/CFCPyClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.h b/compiler/src/CFCPyClass.h
new file mode 100644
index 0000000..4803833
--- /dev/null
+++ b/compiler/src/CFCPyClass.h
@@ -0,0 +1,40 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef H_CFCPYCLASS
+#define H_CFCPYCLASS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CFCPyClass CFCPyClass;
+struct CFCParcel;
+struct CFCClass;
+
+/** Clownfish::CFC::Binding::Python::Class - Generate Python binding code for a
+ * Clownfish::CFC::Model::Class.
+ */
+
+CFCPyClass*
+CFCPyClass_new(struct CFCClass *client);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CFCPYCLASS */
+


[05/17] lucy-clownfish git commit: Add registry for CFCPyClass.

Posted by ma...@apache.org.
Add registry for CFCPyClass.

Register CFCPyClass singletons in a crude map.  Also prepare to generate
per-class glue code.


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

Branch: refs/heads/master
Commit: f0048b30e37a52cc7257e6500306b2c00970ec57
Parents: 72102ab
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Thu Jan 28 18:10:01 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 compiler/src/CFCPyClass.c | 70 ++++++++++++++++++++++++++++++++++++++++++
 compiler/src/CFCPyClass.h | 24 +++++++++++++++
 compiler/src/CFCPython.c  | 32 ++++++++++++++++++-
 3 files changed, 125 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f0048b30/compiler/src/CFCPyClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.c b/compiler/src/CFCPyClass.c
index 8eaa702..e79c2d4 100644
--- a/compiler/src/CFCPyClass.c
+++ b/compiler/src/CFCPyClass.c
@@ -14,6 +14,9 @@
  * limitations under the License.
  */
 
+#include <string.h>
+#include <stdlib.h>
+
 #define CFC_NEED_BASE_STRUCT_DEF 1
 
 #include "CFCBase.h"
@@ -34,6 +37,10 @@ struct CFCPyClass {
     char *meth_defs;
 };
 
+static CFCPyClass **registry = NULL;
+static size_t registry_size = 0;
+static size_t registry_cap  = 0;
+
 static void
 S_CFCPyClass_destroy(CFCPyClass *self);
 
@@ -66,3 +73,66 @@ S_CFCPyClass_destroy(CFCPyClass *self) {
     CFCBase_destroy((CFCBase*)self);
 }
 
+static int
+S_compare_cfcperlclass(const void *va, const void *vb) {
+    CFCPyClass *a = *(CFCPyClass**)va;
+    CFCPyClass *b = *(CFCPyClass**)vb;
+    return strcmp(a->class_name, b->class_name);
+}
+
+void
+CFCPyClass_add_to_registry(CFCPyClass *self) {
+    if (registry_size == registry_cap) {
+        size_t new_cap = registry_cap + 10;
+        registry = (CFCPyClass**)REALLOCATE(registry,
+                                            (new_cap + 1) * sizeof(CFCPyClass*));
+        for (size_t i = registry_cap; i <= new_cap; i++) {
+            registry[i] = NULL;
+        }
+        registry_cap = new_cap;
+    }
+    CFCPyClass *existing = CFCPyClass_singleton(self->class_name);
+    if (existing) {
+        CFCUtil_die("Class '%s' already registered", self->class_name);
+    }
+    registry[registry_size] = (CFCPyClass*)CFCBase_incref((CFCBase*)self);
+    registry_size++;
+    qsort(registry, registry_size, sizeof(CFCPyClass*),
+          S_compare_cfcperlclass);
+}
+
+CFCPyClass*
+CFCPyClass_singleton(const char *class_name) {
+    CFCUTIL_NULL_CHECK(class_name);
+    for (size_t i = 0; i < registry_size; i++) {
+        CFCPyClass *existing = registry[i];
+        if (strcmp(class_name, existing->class_name) == 0) {
+            return existing;
+        }
+    }
+    return NULL;
+}
+
+CFCPyClass**
+CFCPyClass_registry() {
+    if (!registry) {
+        registry = (CFCPyClass**)CALLOCATE(1, sizeof(CFCPyClass*));
+    }
+    return registry;
+}
+
+void
+CFCPyClass_clear_registry(void) {
+    for (size_t i = 0; i < registry_size; i++) {
+        CFCBase_decref((CFCBase*)registry[i]);
+    }
+    FREEMEM(registry);
+    registry_size = 0;
+    registry_cap  = 0;
+    registry      = NULL;
+}
+
+char*
+CFCPyClass_gen_binding_code(CFCPyClass *self) {
+    return CFCUtil_strdup("");
+}

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f0048b30/compiler/src/CFCPyClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPyClass.h b/compiler/src/CFCPyClass.h
index 4803833..b905502 100644
--- a/compiler/src/CFCPyClass.h
+++ b/compiler/src/CFCPyClass.h
@@ -32,6 +32,30 @@ struct CFCClass;
 CFCPyClass*
 CFCPyClass_new(struct CFCClass *client);
 
+/** Add a new class binding to the registry.  Each unique parcel/class-name
+  * combination may only be registered once.
+  */
+void
+CFCPyClass_add_to_registry(CFCPyClass *self);
+
+/** Given a class name, return a class binding if one exists.
+  */
+CFCPyClass*
+CFCPyClass_singleton(const char *class_name);
+
+/** All registered class bindings.
+  */
+CFCPyClass**
+CFCPyClass_registry();
+
+/** Release all memory and references held by the registry.
+  */
+void
+CFCPyClass_clear_registry(void);
+
+char*
+CFCPyClass_gen_binding_code(CFCPyClass *self);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/f0048b30/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index e17feeb..c7ae4c2 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -24,6 +24,7 @@
 #define CFC_NEED_BASE_STRUCT_DEF
 #include "CFCBase.h"
 #include "CFCPython.h"
+#include "CFCPyClass.h"
 #include "CFCPyMethod.h"
 #include "CFCParcel.h"
 #include "CFCClass.h"
@@ -361,6 +362,30 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, CFCClass **ordered) {
     return content;
 }
 
+static char*
+S_gen_class_bindings(CFCPython *self, CFCParcel *parcel,
+                     const char *pymod_name, CFCClass **ordered) {
+    char *bindings = CFCUtil_strdup("");
+    for (size_t i = 0; ordered[i] != NULL; i++) {
+        CFCClass *klass = ordered[i];
+        if (CFCClass_included(klass)) {
+            continue;
+        }
+        const char *class_name = CFCClass_get_name(klass);
+        CFCPyClass *class_binding = CFCPyClass_singleton(class_name);
+        if (!class_binding) {
+            // No binding spec'd out, so create one using defaults.
+            class_binding = CFCPyClass_new(klass);
+            CFCPyClass_add_to_registry(class_binding);
+        }
+
+        char *code = CFCPyClass_gen_binding_code(class_binding);
+        bindings = CFCUtil_cat(bindings, code, NULL);
+        FREEMEM(code);
+    }
+    return bindings;
+}
+
 static void
 S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     const char *parcel_name = CFCParcel_get_name(parcel);
@@ -382,6 +407,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     CFCParcel **parcels = CFCParcel_all_parcels();
     char *callbacks          = S_gen_callbacks(self, parcel, ordered);
     char *pound_includes     = CFCUtil_strdup("");
+    char *class_bindings     = S_gen_class_bindings(self, parcel, pymod_name, ordered);
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
@@ -410,6 +436,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
         "    NULL, NULL, NULL, NULL, NULL\n"
         "};\n"
         "\n"
+        "%s" // class bindings
+        "\n"
         "PyMODINIT_FUNC\n"
         "PyInit__%s(void) {\n"
         "    PyObject *module = PyModule_Create(&module_def);\n"
@@ -421,7 +449,8 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
 
     char *content
         = CFCUtil_sprintf(pattern, self->header, pound_includes, callbacks,
-                          helper_mod_name, last_component, self->footer);
+                          helper_mod_name, class_bindings, last_component,
+                          self->footer);
 
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "_%s.c", dest,
                                      last_component);
@@ -429,6 +458,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, const char *dest) {
     FREEMEM(filepath);
 
     FREEMEM(content);
+    FREEMEM(class_bindings);
     FREEMEM(helper_mod_name);
     FREEMEM(pymod_name);
     FREEMEM(pound_includes);


[09/17] lucy-clownfish git commit: Implement Make_Obj and Init_Obj for Python.

Posted by ma...@apache.org.
Implement Make_Obj and Init_Obj for Python.


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

Branch: refs/heads/master
Commit: 50c98b1faeb6f8966b769ac7dbff811e3808bc1e
Parents: c6c74d2
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 16:47:41 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:38 2016 -0800

----------------------------------------------------------------------
 runtime/python/cfext/CFBind.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/50c98b1f/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index 2471487..a1e47eb 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -930,17 +930,28 @@ S_get_cached_py_type(cfish_Class *self) {
 
 cfish_Obj*
 CFISH_Class_Make_Obj_IMP(cfish_Class *self) {
-    CFISH_UNUSED_VAR(self);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Obj*);
+    PyTypeObject *py_type = S_get_cached_py_type(self);
+    cfish_Obj *obj = (cfish_Obj*)py_type->tp_alloc(py_type, 0);
+    obj->klass = self;
+    return obj;
 }
 
 cfish_Obj*
 CFISH_Class_Init_Obj_IMP(cfish_Class *self, void *allocation) {
-    CFISH_UNUSED_VAR(self);
-    CFISH_UNUSED_VAR(allocation);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Obj*);
+    PyTypeObject *py_type = S_get_cached_py_type(self);
+    // It would be nice if we could call PyObject_Init() here and feel
+    // confident that we have performed all Python-specific initialization
+    // under all possible configurations, but that's not possible.  In
+    // addition to setting ob_refcnt and ob_type, PyObject_Init() performs
+    // tracking for heap allocated objects under special builds -- but
+    // Class_Init_Obj() may be called on non-heap memory, such as
+    // stack-allocated Clownfish Strings.  Therefore, we must perform a subset
+    // of tasks selected from PyObject_Init() manually.
+    cfish_Obj *obj = (cfish_Obj*)allocation;
+    obj->ob_base.ob_refcnt = 1;
+    obj->ob_base.ob_type = py_type;
+    obj->klass = self;
+    return obj;
 }
 
 void


[07/17] lucy-clownfish git commit: Stub out some placeholders for Py bindings.

Posted by ma...@apache.org.
Stub out some placeholders for Py bindings.

Subclassing from Python won't be supported until these are fully
implemented.


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

Branch: refs/heads/master
Commit: 33189df152305583c976b2701396eff940b992a1
Parents: 2b37cc1
Author: Marvin Humphrey <ma...@rectangular.com>
Authored: Mon Feb 1 15:49:29 2016 -0800
Committer: Marvin Humphrey <ma...@rectangular.com>
Committed: Wed Feb 24 15:20:37 2016 -0800

----------------------------------------------------------------------
 runtime/python/cfext/CFBind.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/33189df1/runtime/python/cfext/CFBind.c
----------------------------------------------------------------------
diff --git a/runtime/python/cfext/CFBind.c b/runtime/python/cfext/CFBind.c
index f73b76a..69ab9bd 100644
--- a/runtime/python/cfext/CFBind.c
+++ b/runtime/python/cfext/CFBind.c
@@ -912,23 +912,26 @@ CFISH_Class_Init_Obj_IMP(cfish_Class *self, void *allocation) {
 
 void
 cfish_Class_register_with_host(cfish_Class *singleton, cfish_Class *parent) {
+    // FIXME
     CFISH_UNUSED_VAR(singleton);
     CFISH_UNUSED_VAR(parent);
-    CFISH_THROW(CFISH_ERR, "TODO");
 }
 
 cfish_Vector*
 cfish_Class_fresh_host_methods(cfish_String *class_name) {
+    // FIXME Scan Python class for host methods which override.  Until this is
+    // implemented, it will be impossible to override Clownfish methods from
+    // Python.
     CFISH_UNUSED_VAR(class_name);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_Vector*);
+    return cfish_Vec_new(0);
 }
 
 cfish_String*
 cfish_Class_find_parent_class(cfish_String *class_name) {
+    // FIXME Until this is implemented, subclassing from Python will be
+    // impossible.
     CFISH_UNUSED_VAR(class_name);
-    CFISH_THROW(CFISH_ERR, "TODO");
-    CFISH_UNREACHABLE_RETURN(cfish_String*);
+    return NULL;
 }
 
 /**** Method ***************************************************************/