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:20 UTC

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

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);