You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2015/07/27 18:35:32 UTC
[4/4] lucy-clownfish git commit: CFCBindSpecs class
CFCBindSpecs class
Handle ClassSpecs and MethSpecs in a single place.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/2b3ed29a
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/2b3ed29a
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/2b3ed29a
Branch: refs/heads/master
Commit: 2b3ed29a7cf05fd1c0ae6b23482cadcf445dbf03
Parents: 8bfda83
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Thu Jul 23 19:51:01 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Mon Jul 27 18:26:18 2015 +0200
----------------------------------------------------------------------
compiler/include/CFC.h | 1 +
compiler/perl/lib/Clownfish/CFC.xs | 24 --
compiler/src/CFCBindClass.c | 205 +---------------
compiler/src/CFCBindClass.h | 5 -
compiler/src/CFCBindCore.c | 89 +++----
compiler/src/CFCBindMethod.c | 75 ------
compiler/src/CFCBindMethod.h | 20 --
compiler/src/CFCBindSpecs.c | 419 ++++++++++++++++++++++++++++++++
compiler/src/CFCBindSpecs.h | 58 +++++
compiler/src/CFCClass.c | 18 ++
compiler/src/CFCClass.h | 6 +
11 files changed, 534 insertions(+), 386 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/include/CFC.h
----------------------------------------------------------------------
diff --git a/compiler/include/CFC.h b/compiler/include/CFC.h
index e57c873..9d1c222 100644
--- a/compiler/include/CFC.h
+++ b/compiler/include/CFC.h
@@ -44,6 +44,7 @@
#include "CFCBindFile.h"
#include "CFCBindFunction.h"
#include "CFCBindMethod.h"
+#include "CFCBindSpecs.h"
#include "CFCGo.h"
#include "CFCGoClass.h"
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.xs b/compiler/perl/lib/Clownfish/CFC.xs
index d9e28bf..c779c5b 100644
--- a/compiler/perl/lib/Clownfish/CFC.xs
+++ b/compiler/perl/lib/Clownfish/CFC.xs
@@ -1908,30 +1908,6 @@ CODE:
RETVAL = S_sv_eat_c_string(CFCBindMeth_method_def(meth, klass));
OUTPUT: RETVAL
-SV*
-_novel_spec_def(meth, klass)
- CFCMethod *meth;
- CFCClass *klass;
-CODE:
- RETVAL = S_sv_eat_c_string(CFCBindMeth_novel_spec_def(meth, klass));
-OUTPUT: RETVAL
-
-SV*
-_overridden_spec_def(meth, klass)
- CFCMethod *meth;
- CFCClass *klass;
-CODE:
- RETVAL = S_sv_eat_c_string(CFCBindMeth_overridden_spec_def(meth, klass));
-OUTPUT: RETVAL
-
-SV*
-_inherited_spec_def(meth, klass)
- CFCMethod *meth;
- CFCClass *klass;
-CODE:
- RETVAL = S_sv_eat_c_string(CFCBindMeth_inherited_spec_def(meth, klass));
-OUTPUT: RETVAL
-
MODULE = Clownfish::CFC PACKAGE = Clownfish::CFC::Binding::Core::Aliases
SV*
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCBindClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindClass.c b/compiler/src/CFCBindClass.c
index d1cebf6..f19a174 100644
--- a/compiler/src/CFCBindClass.c
+++ b/compiler/src/CFCBindClass.c
@@ -45,11 +45,6 @@ S_to_c_header_inert(CFCBindClass *self);
static char*
S_to_c_header_dynamic(CFCBindClass *self);
-// Count the number of member variables declared in ancestor classes
-// outside this package.
-static int
-S_count_non_package_members(CFCBindClass *self);
-
// Create the definition for the instantiable object struct.
static char*
S_struct_definition(CFCBindClass *self);
@@ -286,16 +281,12 @@ CFCBindClass_to_c_data(CFCBindClass *self) {
}
const char *ivars_offset = CFCClass_full_ivars_offset(client);
-
const char *class_var = CFCClass_full_class_var(client);
CFCMethod **methods = CFCClass_methods(client);
char *offsets = CFCUtil_strdup("");
char *method_defs = CFCUtil_strdup("");
- char *novel_ms_var = CFCUtil_strdup("");
- char *overridden_ms_var = CFCUtil_strdup("");
- char *inherited_ms_var = CFCUtil_strdup("");
for (int meth_num = 0; methods[meth_num] != NULL; meth_num++) {
CFCMethod *method = methods[meth_num];
@@ -314,69 +305,6 @@ CFCBindClass_to_c_data(CFCBindClass *self) {
method_defs = CFCUtil_cat(method_defs, method_def, "\n", NULL);
FREEMEM(method_def);
}
-
- if (is_fresh && CFCMethod_novel(method)) {
- if (novel_ms_var[0] == '\0') {
- // Start an array of cfish_NovelMethSpec structs. Since C89
- // doesn't allow us to initialize a pointer to an anonymous
- // array inside a global struct, we have to give it a real
- // symbol and then store a pointer to that symbol inside the
- // ClassSpec struct.
- novel_ms_var
- = CFCUtil_cat(novel_ms_var,
- "static const cfish_NovelMethSpec ",
- class_var, "_NOVEL_METHS[] = {\n", NULL);
- }
- else {
- novel_ms_var = CFCUtil_cat(novel_ms_var, ",\n", NULL);
- }
- char *ms_def = CFCBindMeth_novel_spec_def(method, client);
- novel_ms_var = CFCUtil_cat(novel_ms_var, ms_def, NULL);
- FREEMEM(ms_def);
- }
- else if (is_fresh) {
- if (overridden_ms_var[0] == '\0') {
- // Start an array of cfish_OverriddenMethSpec structs.
- overridden_ms_var
- = CFCUtil_cat(overridden_ms_var,
- "static const cfish_OverriddenMethSpec ",
- class_var, "_OVERRIDDEN_METHS[] = {\n",
- NULL);
- }
- else {
- overridden_ms_var
- = CFCUtil_cat(overridden_ms_var, ",\n", NULL);
- }
- char *ms_def = CFCBindMeth_overridden_spec_def(method, client);
- overridden_ms_var = CFCUtil_cat(overridden_ms_var, ms_def, NULL);
- FREEMEM(ms_def);
- }
- else {
- if (inherited_ms_var[0] == '\0') {
- // Start an array of cfish_InheritedMethSpec structs.
- inherited_ms_var
- = CFCUtil_cat(inherited_ms_var,
- "static const cfish_InheritedMethSpec ",
- class_var, "_INHERITED_METHS[] = {\n", NULL);
- }
- else {
- inherited_ms_var = CFCUtil_cat(inherited_ms_var, ",\n", NULL);
- }
- char *ms_def = CFCBindMeth_inherited_spec_def(method, client);
- inherited_ms_var = CFCUtil_cat(inherited_ms_var, ms_def, NULL);
- FREEMEM(ms_def);
- }
- }
-
- // Close MethSpec array definitions.
- if (novel_ms_var[0] != '\0') {
- novel_ms_var = CFCUtil_cat(novel_ms_var, "\n};\n\n", NULL);
- }
- if (overridden_ms_var[0] != '\0') {
- overridden_ms_var = CFCUtil_cat(overridden_ms_var, "\n};\n\n", NULL);
- }
- if (inherited_ms_var[0] != '\0') {
- inherited_ms_var = CFCUtil_cat(inherited_ms_var, "\n};\n\n", NULL);
}
const char pattern[] =
@@ -397,12 +325,6 @@ CFCBindClass_to_c_data(CFCBindClass *self) {
"\n"
"%s\n"
"\n"
- "/* Define the MethSpec structs used during Class initialization.\n"
- " */\n"
- "\n"
- "%s"
- "%s"
- "%s"
"/* Define the pointer to the Class singleton object.\n"
" */\n"
"\n"
@@ -410,36 +332,13 @@ CFCBindClass_to_c_data(CFCBindClass *self) {
"\n";
char *code
= CFCUtil_sprintf(pattern, ivars_offset, offsets, method_defs,
- novel_ms_var, overridden_ms_var, inherited_ms_var,
class_var);
FREEMEM(offsets);
FREEMEM(method_defs);
- FREEMEM(novel_ms_var);
- FREEMEM(overridden_ms_var);
- FREEMEM(inherited_ms_var);
return code;
}
-// Count the number of member variables declared in ancestor classes
-// outside this package.
-static int
-S_count_non_package_members(CFCBindClass *self) {
- CFCClass *const client = self->client;
- CFCParcel *parcel = CFCClass_get_parcel(client);
- CFCClass *ancestor = CFCClass_get_parent(client);
- int num_non_package_members = 0;
-
- while (ancestor && CFCClass_get_parcel(ancestor) == parcel) {
- ancestor = CFCClass_get_parent(ancestor);
- }
- if (ancestor) {
- num_non_package_members = CFCClass_num_member_vars(ancestor);
- }
-
- return num_non_package_members;
-}
-
// Create the definition for the instantiable object struct.
static char*
S_struct_definition(CFCBindClass *self) {
@@ -458,7 +357,7 @@ S_struct_definition(CFCBindClass *self) {
// Add all member variables declared by classes in this package.
CFCVariable **member_vars = CFCClass_member_vars(client);
- int num_non_package_members = S_count_non_package_members(self);
+ int num_non_package_members = CFCClass_num_non_package_ivars(client);
for (int i = num_non_package_members; member_vars[i] != NULL; i++) {
const char *member_dec = CFCVariable_local_declaration(member_vars[i]);
member_decs = CFCUtil_cat(member_decs, "\n ", member_dec, NULL);
@@ -479,108 +378,6 @@ S_struct_definition(CFCBindClass *self) {
return struct_def;
}
-// Return C definition of the class's ClassSpec.
-char*
-CFCBindClass_spec_def(CFCBindClass *self) {
- CFCClass *client = self->client;
-
- CFCParcel *parcel = CFCClass_get_parcel(client);
- CFCClass *parent = CFCClass_get_parent(client);
- const char *class_name = CFCClass_get_name(client);
- const char *class_var = CFCClass_full_class_var(client);
- const char *struct_sym = CFCClass_full_struct_sym(client);
- const char *ivars_struct = CFCClass_full_ivars_struct(client);
-
- // Create a pointer to the parent Class object.
- char *parent_ref;
- if (parent) {
- parent_ref = CFCUtil_sprintf("&%s", CFCClass_full_class_var(parent));
- }
- else {
- // No parent, e.g. Obj or inert classes.
- parent_ref = CFCUtil_strdup("NULL");
- }
-
- int num_novel = 0;
- int num_overridden = 0;
- int num_inherited = 0;
- CFCMethod **methods = CFCClass_methods(client);
-
- for (int meth_num = 0; methods[meth_num] != NULL; meth_num++) {
- CFCMethod *method = methods[meth_num];
-
- if (CFCMethod_is_fresh(method, client)) {
- if (CFCMethod_novel(method)) {
- ++num_novel;
- }
- else {
- ++num_overridden;
- }
- }
- else {
- ++num_inherited;
- }
- }
-
- char *novel_ms_var = num_novel
- ? CFCUtil_sprintf("%s_NOVEL_METHS", class_var)
- : CFCUtil_strdup("NULL");
- char *overridden_ms_var = num_overridden
- ? CFCUtil_sprintf("%s_OVERRIDDEN_METHS",
- class_var)
- : CFCUtil_strdup("NULL");
- char *inherited_ms_var = num_inherited
- ? CFCUtil_sprintf("%s_INHERITED_METHS",
- class_var)
- : CFCUtil_strdup("NULL");
-
- char *ivars_size = NULL;
-
- if (CFCParcel_is_cfish(parcel)) {
- ivars_size = CFCUtil_sprintf("sizeof(%s)", struct_sym);
- }
- else {
- int num_non_package_members = S_count_non_package_members(self);
- int num_members = CFCClass_num_member_vars(client);
-
- if (num_non_package_members == num_members) {
- // No members in this package.
- ivars_size = CFCUtil_strdup("0");
- }
- else {
- ivars_size = CFCUtil_sprintf("sizeof(%s)", ivars_struct);
- }
- }
- const char *ivars_offset_name = CFCClass_full_ivars_offset(client);
-
- char pattern[] =
- " {\n"
- " &%s, /* class */\n"
- " %s, /* parent */\n"
- " \"%s\", /* name */\n"
- " %s, /* ivars_size */\n"
- " &%s, /* ivars_offset_ptr */\n"
- " %d, /* num_novel */\n"
- " %d, /* num_overridden */\n"
- " %d, /* num_inherited */\n"
- " %s, /* novel_meth_specs */\n"
- " %s, /* overridden_meth_specs */\n"
- " %s /* inherited_meth_specs */\n"
- " }";
- char *code
- = CFCUtil_sprintf(pattern, class_var, parent_ref, class_name,
- ivars_size, ivars_offset_name, num_novel,
- num_overridden, num_inherited, novel_ms_var,
- overridden_ms_var, inherited_ms_var);
-
- FREEMEM(parent_ref);
- FREEMEM(novel_ms_var);
- FREEMEM(overridden_ms_var);
- FREEMEM(inherited_ms_var);
- FREEMEM(ivars_size);
- return code;
-}
-
// Declare typedefs for every method, to ease casting.
static char*
S_method_typedefs(CFCBindClass *self) {
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCBindClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindClass.h b/compiler/src/CFCBindClass.h
index c915c65..4780bdc 100644
--- a/compiler/src/CFCBindClass.h
+++ b/compiler/src/CFCBindClass.h
@@ -54,11 +54,6 @@ CFCBindClass_to_c_header(CFCBindClass *self);
char*
CFCBindClass_to_c_data(CFCBindClass *self);
-/** Return the autogenerated C definition of class's ClassSpec.
- */
-char*
-CFCBindClass_spec_def(CFCBindClass *self);
-
#ifdef __cplusplus
}
#endif
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindCore.c b/compiler/src/CFCBindCore.c
index 985f00c..d5f59d7 100644
--- a/compiler/src/CFCBindCore.c
+++ b/compiler/src/CFCBindCore.c
@@ -24,6 +24,7 @@
#include "CFCBindCore.h"
#include "CFCBindClass.h"
#include "CFCBindFile.h"
+#include "CFCBindSpecs.h"
#include "CFCClass.h"
#include "CFCFile.h"
#include "CFCHierarchy.h"
@@ -300,41 +301,6 @@ S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) {
"#define CFISH_fREFCOUNTSPECIAL 0x00000001\n"
;
const char *cfish_defs_2 =
- "/* Structs for Class initialization.\n"
- " */\n"
- "\n"
- "typedef struct cfish_NovelMethSpec {\n"
- " size_t *offset;\n"
- " const char *name;\n"
- " cfish_method_t func;\n"
- " cfish_method_t callback_func;\n"
- "} cfish_NovelMethSpec;\n"
- "\n"
- "typedef struct cfish_OverriddenMethSpec {\n"
- " size_t *offset;\n"
- " size_t *parent_offset;\n"
- " cfish_method_t func;\n"
- "} cfish_OverriddenMethSpec;\n"
- "\n"
- "typedef struct cfish_InheritedMethSpec {\n"
- " size_t *offset;\n"
- " size_t *parent_offset;\n"
- "} cfish_InheritedMethSpec;\n"
- "\n"
- "typedef struct cfish_ClassSpec {\n"
- " cfish_Class **klass;\n"
- " cfish_Class **parent;\n"
- " const char *name;\n"
- " size_t ivars_size;\n"
- " size_t *ivars_offset_ptr;\n"
- " uint32_t num_novel_meths;\n"
- " uint32_t num_overridden_meths;\n"
- " uint32_t num_inherited_meths;\n"
- " const cfish_NovelMethSpec *novel_meth_specs;\n"
- " const cfish_OverriddenMethSpec *overridden_meth_specs;\n"
- " const cfish_InheritedMethSpec *inherited_meth_specs;\n"
- "} cfish_ClassSpec;\n"
- "\n"
"#ifdef CFISH_USE_SHORT_NAMES\n"
" #define UNUSED_VAR CFISH_UNUSED_VAR\n"
" #define UNREACHABLE_RETURN CFISH_UNREACHABLE_RETURN\n"
@@ -352,7 +318,9 @@ S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) {
char *extra_defs;
char *extra_includes;
if (CFCParcel_is_cfish(parcel)) {
- extra_defs = CFCUtil_sprintf("%s%s", cfish_defs_1, cfish_defs_2);
+ const char *spec_typedefs = CFCBindSpecs_get_typedefs();
+ extra_defs = CFCUtil_sprintf("%s%s%s", cfish_defs_1, spec_typedefs,
+ cfish_defs_2);
extra_includes = CFCUtil_strdup(cfish_includes);
}
else {
@@ -439,10 +407,9 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
char *privacy_syms = CFCUtil_strdup("");
char *includes = CFCUtil_strdup("");
char *c_data = CFCUtil_strdup("");
- char *class_specs = CFCUtil_strdup(
- "static const cfish_ClassSpec class_specs[] = {\n");
- int num_specs = 0;
- CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
+ CFCBindSpecs *specs = CFCBindSpecs_new();
+ CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
+
for (int i = 0; ordered[i] != NULL; i++) {
CFCClass *klass = ordered[i];
const char *class_prefix = CFCClass_get_prefix(klass);
@@ -453,24 +420,22 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
"\"\n", NULL);
CFCBindClass *class_binding = CFCBindClass_new(klass);
+
char *class_c_data = CFCBindClass_to_c_data(class_binding);
c_data = CFCUtil_cat(c_data, class_c_data, "\n", NULL);
FREEMEM(class_c_data);
- if (!CFCClass_inert(klass)) {
- if (num_specs != 0) {
- class_specs = CFCUtil_cat(class_specs, ",\n", NULL);
- }
- char *class_spec = CFCBindClass_spec_def(class_binding);
- class_specs = CFCUtil_cat(class_specs, class_spec, NULL);
- FREEMEM(class_spec);
- ++num_specs;
- }
- CFCBase_decref((CFCBase*)class_binding);
+
+ CFCBindSpecs_add_class(specs, klass);
+
const char *privacy_sym = CFCClass_privacy_symbol(klass);
privacy_syms = CFCUtil_cat(privacy_syms, "#define ",
privacy_sym, "\n", NULL);
+
+ CFCBase_decref((CFCBase*)class_binding);
}
- class_specs = CFCUtil_cat(class_specs, "\n};\n", NULL);
+
+ char *spec_defs = CFCBindSpecs_defs(specs);
+ char *spec_init_func = CFCBindSpecs_init_func_def(specs);
FREEMEM(ordered);
// Bootstrapping code for prerequisite parcels.
@@ -514,9 +479,15 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
"\n"
"%s\n"
"\n"
- "/* ClassSpec structs for initialization.\n"
+ "/* ClassSpec and MethSpec structs for initialization.\n"
" */\n"
- "%s\n"
+ "\n"
+ "%s" // spec_defs
+ "\n"
+ "/* Code to initialize ClassSpec and MethSpec structs.\n"
+ " */\n"
+ "\n"
+ "%s" // spec_init_func
"\n"
"static int bootstrap_state = 0;\n"
"\n"
@@ -530,7 +501,7 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
" if (bootstrap_state >= 2) { return; }\n"
" bootstrap_state = 1;\n"
"%s" // Bootstrap inherited parcels.
- " cfish_Class_bootstrap(class_specs, %d);\n"
+ " S_bootstrap_specs();\n"
" bootstrap_state = 2;\n"
"}\n"
"\n"
@@ -546,9 +517,9 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
"%s\n";
char *file_content
= CFCUtil_sprintf(pattern, self->c_header, privacy_syms, includes,
- c_data, class_specs, prefix, inh_bootstrap,
- num_specs, prefix, prefix, prereq_bootstrap, prefix,
- self->c_footer);
+ c_data, spec_defs, spec_init_func, prefix,
+ inh_bootstrap, prefix, prefix, prereq_bootstrap,
+ prefix, self->c_footer);
// Unlink then open file.
const char *src_dest = CFCHierarchy_get_source_dest(hierarchy);
@@ -558,10 +529,12 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
CFCUtil_write_file(filepath, file_content, strlen(file_content));
FREEMEM(filepath);
+ CFCBase_decref((CFCBase*)specs);
FREEMEM(privacy_syms);
FREEMEM(includes);
FREEMEM(c_data);
- FREEMEM(class_specs);
+ FREEMEM(spec_defs);
+ FREEMEM(spec_init_func);
FREEMEM(inh_bootstrap);
FREEMEM(prereq_bootstrap);
FREEMEM(file_content);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCBindMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindMethod.c b/compiler/src/CFCBindMethod.c
index 925f481..e4d7301 100644
--- a/compiler/src/CFCBindMethod.c
+++ b/compiler/src/CFCBindMethod.c
@@ -162,81 +162,6 @@ CFCBindMeth_typedef_dec(struct CFCMethod *method, CFCClass *klass) {
}
char*
-CFCBindMeth_novel_spec_def(CFCMethod *method, CFCClass *klass) {
- const char *meth_name = CFCMethod_get_name(method);
-
- char *full_override_sym;
- if (!CFCMethod_final(method)) {
- full_override_sym = CFCMethod_full_override_sym(method, klass);
- }
- else {
- full_override_sym = CFCUtil_strdup("NULL");
- }
-
- char *imp_func = CFCMethod_imp_func(method, klass);
- char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
-
- char pattern[] =
- " {\n"
- " &%s, /* offset */\n"
- " \"%s\", /* name */\n"
- " (cfish_method_t)%s, /* func */\n"
- " (cfish_method_t)%s /* callback_func */\n"
- " }";
- char *def
- = CFCUtil_sprintf(pattern, full_offset_sym, meth_name, imp_func,
- full_override_sym);
-
- FREEMEM(full_offset_sym);
- FREEMEM(imp_func);
- FREEMEM(full_override_sym);
- return def;
-}
-
-char*
-CFCBindMeth_overridden_spec_def(CFCMethod *method, CFCClass *klass) {
- char *imp_func = CFCMethod_imp_func(method, klass);
- char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
-
- CFCClass *parent = CFCClass_get_parent(klass);
- char *parent_offset_sym = CFCMethod_full_offset_sym(method, parent);
-
- char pattern[] =
- " {\n"
- " &%s, /* offset */\n"
- " &%s, /* parent_offset */\n"
- " (cfish_method_t)%s /* func */\n"
- " }";
- char *def
- = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset_sym,
- imp_func);
-
- FREEMEM(parent_offset_sym);
- FREEMEM(full_offset_sym);
- FREEMEM(imp_func);
- return def;
-}
-
-char*
-CFCBindMeth_inherited_spec_def(CFCMethod *method, CFCClass *klass) {
- char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
-
- CFCClass *parent = CFCClass_get_parent(klass);
- char *parent_offset_sym = CFCMethod_full_offset_sym(method, parent);
-
- char pattern[] =
- " {\n"
- " &%s, /* offset */\n"
- " &%s /* parent_offset */\n"
- " }";
- char *def = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset_sym);
-
- FREEMEM(full_offset_sym);
- FREEMEM(parent_offset_sym);
- return def;
-}
-
-char*
CFCBindMeth_abstract_method_def(CFCMethod *method, CFCClass *klass) {
CFCType *ret_type = CFCMethod_get_return_type(method);
const char *ret_type_str = CFCType_to_c(ret_type);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCBindMethod.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindMethod.h b/compiler/src/CFCBindMethod.h
index 3bc16ab..4928c70 100644
--- a/compiler/src/CFCBindMethod.h
+++ b/compiler/src/CFCBindMethod.h
@@ -44,26 +44,6 @@ CFCBindMeth_method_def(struct CFCMethod *method, struct CFCClass *klass);
char*
CFCBindMeth_typedef_dec(struct CFCMethod *method, struct CFCClass *klass);
-/** Return C code defining the MethSpec object for a novel method, which
- * is used during Class initialization.
- */
-char*
-CFCBindMeth_novel_spec_def(struct CFCMethod *method, struct CFCClass *klass);
-
-/** Return C code defining the MethSpec object for an overridden method,
- * which is used during Class initialization.
- */
-char*
-CFCBindMeth_overridden_spec_def(struct CFCMethod *method,
- struct CFCClass *klass);
-
-/** Return C code defining the MethSpec object for an inherited method,
- * which is used during Class initialization.
- */
-char*
-CFCBindMeth_inherited_spec_def(struct CFCMethod *method,
- struct CFCClass *klass);
-
/** Return C code implementing a version of the method which throws an
* "abstract method" error at runtime, for methods which are declared as
* "abstract" in a Clownfish header file.
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCBindSpecs.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindSpecs.c b/compiler/src/CFCBindSpecs.c
new file mode 100644
index 0000000..513806b
--- /dev/null
+++ b/compiler/src/CFCBindSpecs.c
@@ -0,0 +1,419 @@
+/* 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.
+ */
+
+#include "charmony.h"
+
+#include "CFCBindSpecs.h"
+
+#define CFC_NEED_BASE_STRUCT_DEF
+#include "CFCBase.h"
+#include "CFCClass.h"
+#include "CFCMethod.h"
+#include "CFCParcel.h"
+#include "CFCUtil.h"
+
+struct CFCBindSpecs {
+ CFCBase base;
+
+ char *novel_specs;
+ char *overridden_specs;
+ char *inherited_specs;
+ char *class_specs;
+
+ int num_novel;
+ int num_overridden;
+ int num_inherited;
+ int num_specs;
+};
+
+static char*
+S_ivars_size(CFCClass *klass);
+
+static char*
+S_novel_meth(CFCMethod *method, CFCClass *klass);
+
+static char*
+S_parent_offset(CFCMethod *method, CFCClass *klass);
+
+static char*
+S_overridden_meth(CFCMethod *method, CFCClass *klass);
+
+static char*
+S_inherited_meth(CFCMethod *method, CFCClass *klass);
+
+static const CFCMeta CFCBINDSPECS_META = {
+ "Clownfish::CFC::Binding::Core::Specs",
+ sizeof(CFCBindSpecs),
+ (CFCBase_destroy_t)CFCBindSpecs_destroy
+};
+
+CFCBindSpecs*
+CFCBindSpecs_new() {
+ CFCBindSpecs *self = (CFCBindSpecs*)CFCBase_allocate(&CFCBINDSPECS_META);
+ return CFCBindSpecs_init(self);
+}
+
+CFCBindSpecs*
+CFCBindSpecs_init(CFCBindSpecs *self) {
+ self->novel_specs = CFCUtil_strdup("");
+ self->overridden_specs = CFCUtil_strdup("");
+ self->inherited_specs = CFCUtil_strdup("");
+ self->class_specs = CFCUtil_strdup("");
+
+ return self;
+}
+
+void
+CFCBindSpecs_destroy(CFCBindSpecs *self) {
+ FREEMEM(self->novel_specs);
+ FREEMEM(self->overridden_specs);
+ FREEMEM(self->inherited_specs);
+ FREEMEM(self->class_specs);
+ CFCBase_destroy((CFCBase*)self);
+}
+
+const char*
+CFCBindSpecs_get_typedefs() {
+ return
+ "/* Structs for Class initialization.\n"
+ " */\n"
+ "\n"
+ "typedef struct cfish_NovelMethSpec {\n"
+ " size_t *offset;\n"
+ " const char *name;\n"
+ " cfish_method_t func;\n"
+ " cfish_method_t callback_func;\n"
+ "} cfish_NovelMethSpec;\n"
+ "\n"
+ "typedef struct cfish_OverriddenMethSpec {\n"
+ " size_t *offset;\n"
+ " size_t *parent_offset;\n"
+ " cfish_method_t func;\n"
+ "} cfish_OverriddenMethSpec;\n"
+ "\n"
+ "typedef struct cfish_InheritedMethSpec {\n"
+ " size_t *offset;\n"
+ " size_t *parent_offset;\n"
+ "} cfish_InheritedMethSpec;\n"
+ "\n"
+ "typedef struct cfish_ClassSpec {\n"
+ " cfish_Class **klass;\n"
+ " cfish_Class **parent;\n"
+ " const char *name;\n"
+ " size_t ivars_size;\n"
+ " size_t *ivars_offset_ptr;\n"
+ " uint32_t num_novel_meths;\n"
+ " uint32_t num_overridden_meths;\n"
+ " uint32_t num_inherited_meths;\n"
+ " const cfish_NovelMethSpec *novel_meth_specs;\n"
+ " const cfish_OverriddenMethSpec *overridden_meth_specs;\n"
+ " const cfish_InheritedMethSpec *inherited_meth_specs;\n"
+ "} cfish_ClassSpec;\n"
+ "\n";
+}
+
+void
+CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
+ if (CFCClass_inert(klass)) { return; }
+
+ const char *class_name = CFCClass_get_name(klass);
+ const char *class_var = CFCClass_full_class_var(klass);
+ const char *ivars_offset_name = CFCClass_full_ivars_offset(klass);
+
+ char *ivars_size = S_ivars_size(klass);
+
+ char *parent_ptr = NULL;
+ CFCClass *parent = CFCClass_get_parent(klass);
+ if (!parent) {
+ parent_ptr = CFCUtil_strdup("NULL");
+ }
+ else {
+ parent_ptr = CFCUtil_sprintf("&%s", CFCClass_full_class_var(parent));
+ }
+
+ char *novel_specs = CFCUtil_strdup("");
+ char *overridden_specs = CFCUtil_strdup("");
+ char *inherited_specs = CFCUtil_strdup("");
+ int num_new_novel = 0;
+ int num_new_overridden = 0;
+ int num_new_inherited = 0;
+ CFCMethod **methods = CFCClass_methods(klass);
+
+ for (int meth_num = 0; methods[meth_num] != NULL; meth_num++) {
+ CFCMethod *method = methods[meth_num];
+
+ if (CFCMethod_is_fresh(method, klass)) {
+ if (CFCMethod_novel(method)) {
+ const char *sep = num_new_novel == 0 ? "" : ",\n";
+ char *def = S_novel_meth(method, klass);
+ novel_specs = CFCUtil_cat(novel_specs, sep, def, NULL);
+ FREEMEM(def);
+ ++num_new_novel;
+ }
+ else {
+ const char *sep = num_new_overridden == 0 ? "" : ",\n";
+ char *def = S_overridden_meth(method, klass);
+ overridden_specs = CFCUtil_cat(overridden_specs, sep, def,
+ NULL);
+ FREEMEM(def);
+ ++num_new_overridden;
+ }
+ }
+ else {
+ const char *sep = num_new_inherited == 0 ? "" : ",\n";
+ char *def = S_inherited_meth(method, klass);
+ inherited_specs = CFCUtil_cat(inherited_specs, sep, def, NULL);
+ FREEMEM(def);
+ ++num_new_inherited;
+ }
+ }
+
+ char *novel_spec_var;
+
+ if (num_new_novel) {
+ novel_spec_var = CFCUtil_sprintf("%s_NOVEL_METHS", class_var);
+
+ const char *pattern =
+ "static cfish_NovelMethSpec %s[] = {\n"
+ "%s\n"
+ "};\n"
+ "\n";
+ char *spec_def = CFCUtil_sprintf(pattern, novel_spec_var, novel_specs);
+ self->novel_specs = CFCUtil_cat(self->novel_specs, spec_def, NULL);
+ FREEMEM(spec_def);
+ }
+ else {
+ novel_spec_var = CFCUtil_strdup("NULL");
+ }
+
+ char *overridden_spec_var;
+
+ if (num_new_overridden) {
+ overridden_spec_var = CFCUtil_sprintf("%s_OVERRIDDEN_METHS",
+ class_var);
+
+ const char *pattern =
+ "static cfish_OverriddenMethSpec %s[] = {\n"
+ "%s\n"
+ "};\n"
+ "\n";
+ char *spec_def = CFCUtil_sprintf(pattern, overridden_spec_var,
+ overridden_specs);
+ self->overridden_specs = CFCUtil_cat(self->overridden_specs, spec_def,
+ NULL);
+ FREEMEM(spec_def);
+ }
+ else {
+ overridden_spec_var = CFCUtil_strdup("NULL");
+ }
+
+ char *inherited_spec_var;
+
+ if (num_new_inherited) {
+ inherited_spec_var = CFCUtil_sprintf("%s_INHERITED_METHS", class_var);
+
+ const char *pattern =
+ "static cfish_InheritedMethSpec %s[] = {\n"
+ "%s\n"
+ "};\n"
+ "\n";
+ char *spec_def = CFCUtil_sprintf(pattern, inherited_spec_var,
+ inherited_specs);
+ self->inherited_specs = CFCUtil_cat(self->inherited_specs, spec_def,
+ NULL);
+ FREEMEM(spec_def);
+ }
+ else {
+ inherited_spec_var = CFCUtil_strdup("NULL");
+ }
+
+ char pattern[] =
+ " {\n"
+ " &%s, /* class */\n"
+ " %s, /* parent */\n"
+ " \"%s\", /* name */\n"
+ " %s, /* ivars_size */\n"
+ " &%s, /* ivars_offset_ptr */\n"
+ " %d, /* num_novel */\n"
+ " %d, /* num_overridden */\n"
+ " %d, /* num_inherited */\n"
+ " %s,\n"
+ " %s,\n"
+ " %s\n"
+ " }";
+ char *class_spec
+ = CFCUtil_sprintf(pattern, class_var, parent_ptr, class_name,
+ ivars_size, ivars_offset_name,
+ num_new_novel,
+ num_new_overridden,
+ num_new_inherited,
+ novel_spec_var,
+ overridden_spec_var,
+ inherited_spec_var);
+
+ const char *sep = self->num_specs == 0 ? "" : ",\n";
+ self->class_specs = CFCUtil_cat(self->class_specs, sep, class_spec, NULL);
+
+ self->num_novel += num_new_novel;
+ self->num_overridden += num_new_overridden;
+ self->num_inherited += num_new_inherited;
+ self->num_specs += 1;
+
+ FREEMEM(class_spec);
+ FREEMEM(inherited_spec_var);
+ FREEMEM(overridden_spec_var);
+ FREEMEM(novel_spec_var);
+ FREEMEM(parent_ptr);
+ FREEMEM(ivars_size);
+}
+
+char*
+CFCBindSpecs_defs(CFCBindSpecs *self) {
+ if (!self->class_specs[0]) { return CFCUtil_strdup(""); }
+
+ const char *pattern =
+ "%s"
+ "%s"
+ "%s"
+ "static cfish_ClassSpec class_specs[] = {\n"
+ "%s\n"
+ "};\n";
+ return CFCUtil_sprintf(pattern, self->novel_specs,
+ self->overridden_specs, self->inherited_specs,
+ self->class_specs);
+}
+
+char*
+CFCBindSpecs_init_func_def(CFCBindSpecs *self) {
+ const char *pattern =
+ "static void\n"
+ "S_bootstrap_specs() {\n"
+ " cfish_Class_bootstrap(class_specs, %d);\n"
+ "}\n";
+ return CFCUtil_sprintf(pattern, self->num_specs);
+}
+
+static char*
+S_ivars_size(CFCClass *klass) {
+ CFCParcel *parcel = CFCClass_get_parcel(klass);
+ char *ivars_size = NULL;
+
+ if (CFCParcel_is_cfish(parcel)) {
+ const char *struct_sym = CFCClass_full_struct_sym(klass);
+ ivars_size = CFCUtil_sprintf("sizeof(%s)", struct_sym);
+ }
+ else {
+ int num_non_package_ivars = CFCClass_num_non_package_ivars(klass);
+ int num_ivars = CFCClass_num_member_vars(klass);
+
+ if (num_non_package_ivars == num_ivars) {
+ // No members in this package.
+ ivars_size = CFCUtil_strdup("0");
+ }
+ else {
+ const char *ivars_struct = CFCClass_full_ivars_struct(klass);
+ ivars_size = CFCUtil_sprintf("sizeof(%s)", ivars_struct);
+ }
+ }
+
+ return ivars_size;
+}
+
+static char*
+S_novel_meth(CFCMethod *method, CFCClass *klass) {
+ const char *meth_name = CFCMethod_get_name(method);
+
+ char *full_override_sym;
+ if (!CFCMethod_final(method)) {
+ full_override_sym = CFCMethod_full_override_sym(method, klass);
+ }
+ else {
+ full_override_sym = CFCUtil_strdup("NULL");
+ }
+
+ char *imp_func = CFCMethod_imp_func(method, klass);
+ char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
+
+ char pattern[] =
+ " {\n"
+ " &%s, /* offset */\n"
+ " \"%s\", /* name */\n"
+ " (cfish_method_t)%s, /* func */\n"
+ " (cfish_method_t)%s /* callback_func */\n"
+ " }";
+ char *def
+ = CFCUtil_sprintf(pattern, full_offset_sym, meth_name, imp_func,
+ full_override_sym);
+
+ FREEMEM(full_offset_sym);
+ FREEMEM(imp_func);
+ FREEMEM(full_override_sym);
+ return def;
+}
+
+static char*
+S_parent_offset(CFCMethod *method, CFCClass *klass) {
+ CFCClass *parent = CFCClass_get_parent(klass);
+
+ if (!parent) {
+ return CFCUtil_strdup("NULL");
+ }
+
+ char *parent_offset_sym = CFCMethod_full_offset_sym(method, parent);
+ char *parent_offset = CFCUtil_sprintf("&%s", parent_offset_sym);
+ FREEMEM(parent_offset_sym);
+
+ return parent_offset;
+}
+
+static char*
+S_overridden_meth(CFCMethod *method, CFCClass *klass) {
+ char *imp_func = CFCMethod_imp_func(method, klass);
+ char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
+ char *parent_offset = S_parent_offset(method, klass);
+
+ char pattern[] =
+ " {\n"
+ " &%s, /* offset */\n"
+ " %s, /* parent_offset */\n"
+ " (cfish_method_t)%s /* func */\n"
+ " }";
+ char *def
+ = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset, imp_func);
+
+ FREEMEM(parent_offset);
+ FREEMEM(full_offset_sym);
+ FREEMEM(imp_func);
+ return def;
+}
+
+static char*
+S_inherited_meth(CFCMethod *method, CFCClass *klass) {
+ char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
+ char *parent_offset = S_parent_offset(method, klass);
+
+ char pattern[] =
+ " {\n"
+ " &%s, /* offset */\n"
+ " %s /* parent_offset */\n"
+ " }";
+ char *def = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset);
+
+ FREEMEM(full_offset_sym);
+ FREEMEM(parent_offset);
+ return def;
+}
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCBindSpecs.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindSpecs.h b/compiler/src/CFCBindSpecs.h
new file mode 100644
index 0000000..d3f2b8c
--- /dev/null
+++ b/compiler/src/CFCBindSpecs.h
@@ -0,0 +1,58 @@
+/* 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.
+ */
+
+/** Clownfish::CFC::Binding::Core::Specs - Generate C code for class
+ * initialization.
+ */
+
+#ifndef H_CFCBINDSPECS
+#define H_CFCBINDSPECS
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct CFCBindSpecs CFCBindSpecs;
+
+struct CFCClass;
+
+CFCBindSpecs*
+CFCBindSpecs_new(void);
+
+CFCBindSpecs*
+CFCBindSpecs_init(CFCBindSpecs *specs);
+
+void
+CFCBindSpecs_destroy(CFCBindSpecs *specs);
+
+const char*
+CFCBindSpecs_get_typedefs(void);
+
+void
+CFCBindSpecs_add_class(CFCBindSpecs *specs, struct CFCClass *klass);
+
+char*
+CFCBindSpecs_defs(CFCBindSpecs *self);
+
+char*
+CFCBindSpecs_init_func_def(CFCBindSpecs *self);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_CFCBINDSPECS */
+
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.c b/compiler/src/CFCClass.c
index acbc22c..1d89de4 100644
--- a/compiler/src/CFCClass.c
+++ b/compiler/src/CFCClass.c
@@ -810,6 +810,24 @@ CFCClass_num_member_vars(CFCClass *self) {
return self->num_member_vars;
}
+// Count the number of member variables declared in ancestor classes
+// outside this package.
+size_t
+CFCClass_num_non_package_ivars(CFCClass *self) {
+ CFCParcel *parcel = CFCClass_get_parcel(self);
+ CFCClass *ancestor = CFCClass_get_parent(self);
+ int num_non_package_members = 0;
+
+ while (ancestor && CFCClass_get_parcel(ancestor) == parcel) {
+ ancestor = CFCClass_get_parent(ancestor);
+ }
+ if (ancestor) {
+ num_non_package_members = CFCClass_num_member_vars(ancestor);
+ }
+
+ return num_non_package_members;
+}
+
CFCVariable**
CFCClass_inert_vars(CFCClass *self) {
return self->inert_vars;
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2b3ed29a/compiler/src/CFCClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.h b/compiler/src/CFCClass.h
index 68870bf..e148500 100644
--- a/compiler/src/CFCClass.h
+++ b/compiler/src/CFCClass.h
@@ -208,6 +208,12 @@ CFCClass_member_vars(CFCClass *self);
size_t
CFCClass_num_member_vars(CFCClass *self);
+/** Count the number of member variables declared in ancestor classes
+ * outside this package.
+ */
+size_t
+CFCClass_num_non_package_ivars(CFCClass *self);
+
/** Return an array of all inert (shared, class) variables.
*/
struct CFCVariable**