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/py_exp13 Commit: f0048b30e37a52cc7257e6500306b2c00970ec57 Parents: 72102ab Author: Marvin Humphrey <[email protected]> Authored: Thu Jan 28 18:10:01 2016 -0800 Committer: Marvin Humphrey <[email protected]> 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);
