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:29 UTC
[1/4] lucy-clownfish git commit: Don't allow to subclass final classes
Repository: lucy-clownfish
Updated Branches:
refs/heads/master 8bfda8334 -> 5e2478048
Don't allow to subclass final classes
Fixes CLOWNFISH-45.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/5e247804
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/5e247804
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/5e247804
Branch: refs/heads/master
Commit: 5e2478048ffc5062dc0a191087e6dfb1e5b87f57
Parents: 5c7144b
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 24 14:50:36 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Mon Jul 27 18:26:18 2015 +0200
----------------------------------------------------------------------
compiler/src/CFCBindCore.c | 1 +
compiler/src/CFCBindSpecs.c | 12 ++++++++++--
runtime/core/Clownfish/Class.c | 7 +++++++
runtime/perl/t/binding/019-obj.t | 9 ++++++++-
4 files changed, 26 insertions(+), 3 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5e247804/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindCore.c b/compiler/src/CFCBindCore.c
index d5f59d7..ce0f9f7 100644
--- a/compiler/src/CFCBindCore.c
+++ b/compiler/src/CFCBindCore.c
@@ -299,6 +299,7 @@ S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) {
"\n"
"/* Flags for internal use. */\n"
"#define CFISH_fREFCOUNTSPECIAL 0x00000001\n"
+ "#define CFISH_fFINAL 0x00000002\n"
;
const char *cfish_defs_2 =
"#ifdef CFISH_USE_SHORT_NAMES\n"
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5e247804/compiler/src/CFCBindSpecs.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindSpecs.c b/compiler/src/CFCBindSpecs.c
index f3b377d..4db517b 100644
--- a/compiler/src/CFCBindSpecs.c
+++ b/compiler/src/CFCBindSpecs.c
@@ -116,6 +116,10 @@ CFCBindSpecs_get_typedefs() {
" size_t *parent_offset;\n"
"} cfish_InheritedMethSpec;\n"
"\n"
+ "typedef enum {\n"
+ " cfish_ClassSpec_FINAL = 1\n"
+ "} cfish_ClassSpecFlags;\n"
+ "\n"
"typedef struct cfish_ClassSpec {\n"
" cfish_Class **klass;\n"
" cfish_Class **parent;\n"
@@ -125,6 +129,7 @@ CFCBindSpecs_get_typedefs() {
" uint32_t num_novel_meths;\n"
" uint32_t num_overridden_meths;\n"
" uint32_t num_inherited_meths;\n"
+ " uint32_t flags;\n"
"} cfish_ClassSpec;\n"
"\n";
}
@@ -137,6 +142,8 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
const char *class_var = CFCClass_full_class_var(klass);
const char *ivars_offset_name = CFCClass_full_ivars_offset(klass);
+ const char *flags = CFCClass_final(klass) ? "cfish_ClassSpec_FINAL" : "0";
+
char *ivars_size = S_ivars_size(klass);
char *parent_ptr = NULL;
@@ -200,12 +207,13 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
" &%s, /* ivars_offset_ptr */\n"
" %d, /* num_novel */\n"
" %d, /* num_overridden */\n"
- " %d /* num_inherited */\n"
+ " %d, /* num_inherited */\n"
+ " %s /* flags */\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);
+ num_new_overridden, num_new_inherited, flags);
const char *sep = self->num_specs == 0 ? "" : ",\n";
self->class_specs = CFCUtil_cat(self->class_specs, sep, class_spec, NULL);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5e247804/runtime/core/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c
index 474e8a2..5f30de2 100644
--- a/runtime/core/Clownfish/Class.c
+++ b/runtime/core/Clownfish/Class.c
@@ -155,6 +155,9 @@ Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs,
) {
klass->flags |= CFISH_fREFCOUNTSPECIAL;
}
+ if (spec->flags & cfish_ClassSpec_FINAL) {
+ klass->flags |= CFISH_fFINAL;
+ }
if (parent) {
// Copy parent vtable.
@@ -266,6 +269,10 @@ Class_init_registry() {
static Class*
S_simple_subclass(Class *parent, String *name) {
+ if (parent->flags & CFISH_fFINAL) {
+ THROW(ERR, "Can't subclass final class %o", Class_Get_Name(parent));
+ }
+
Class *subclass
= (Class*)Memory_wrapped_calloc(parent->class_alloc_size, 1);
Class_Init_Obj(parent->klass, subclass);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5e247804/runtime/perl/t/binding/019-obj.t
----------------------------------------------------------------------
diff --git a/runtime/perl/t/binding/019-obj.t b/runtime/perl/t/binding/019-obj.t
index 5de41df..545b235 100644
--- a/runtime/perl/t/binding/019-obj.t
+++ b/runtime/perl/t/binding/019-obj.t
@@ -16,7 +16,7 @@
use strict;
use warnings;
-use Test::More tests => 24;
+use Test::More tests => 25;
package TestObj;
use base qw( Clownfish::Obj );
@@ -57,6 +57,9 @@ use base qw( Clownfish::Test::AliasTestObj );
sub perl_alias {"Perl"}
}
+package SubclassFinalTestObj;
+use base qw( Clownfish::Vector );
+
package main;
use Storable qw( freeze thaw );
use Clownfish::Test;
@@ -152,3 +155,7 @@ my $overridden_alias_test = OverriddenAliasTestObj->new;
is( $overridden_alias_test->call_aliased_from_c, 'Perl',
'Overriding aliased methods works' );
+eval { SubclassFinalTestObj->new; };
+like( $@, qr/Can't subclass final class Clownfish::Vector/,
+ "Final class can't be subclassed" );
+
[4/4] lucy-clownfish git commit: CFCBindSpecs class
Posted by nw...@apache.org.
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**
[3/4] lucy-clownfish git commit: Store MethSpecs in a single array
Posted by nw...@apache.org.
Store MethSpecs in a single array
Reduces size of ClassSpec struct and number of relocations.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/5c7144b6
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/5c7144b6
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/5c7144b6
Branch: refs/heads/master
Commit: 5c7144b6a63ef6d483496ce713c7f4a0184a1d1c
Parents: 05068aa
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 24 14:06:13 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Mon Jul 27 18:26:18 2015 +0200
----------------------------------------------------------------------
compiler/src/CFCBindSpecs.c | 209 +++++++++++++---------------------
runtime/core/Clownfish/Class.c | 21 +++-
runtime/core/Clownfish/Class.cfh | 5 +-
3 files changed, 101 insertions(+), 134 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5c7144b6/compiler/src/CFCBindSpecs.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindSpecs.c b/compiler/src/CFCBindSpecs.c
index ff64eca..f3b377d 100644
--- a/compiler/src/CFCBindSpecs.c
+++ b/compiler/src/CFCBindSpecs.c
@@ -43,21 +43,21 @@ struct CFCBindSpecs {
static char*
S_ivars_size(CFCClass *klass);
-static char*
-S_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
- int meth_index);
+static void
+S_add_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index);
static char*
S_parent_offset(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
const char *meth_type, int meth_index);
-static char*
-S_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
- int meth_index);
+static void
+S_add_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index);
-static char*
-S_inherited_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
- int meth_index);
+static void
+S_add_inherited_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index);
static const CFCMeta CFCBINDSPECS_META = {
"Clownfish::CFC::Binding::Core::Specs",
@@ -125,9 +125,6 @@ CFCBindSpecs_get_typedefs() {
" 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";
}
@@ -167,9 +164,6 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
}
}
- 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;
@@ -180,91 +174,23 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
if (CFCMethod_is_fresh(method, klass)) {
if (CFCMethod_novel(method)) {
- const char *sep = num_new_novel == 0 ? "" : ",\n";
- char *def = S_novel_meth(self, method, klass, num_new_novel);
- novel_specs = CFCUtil_cat(novel_specs, sep, def, NULL);
- FREEMEM(def);
+ int meth_index = self->num_novel + num_new_novel;
+ S_add_novel_meth(self, method, klass, meth_index);
++num_new_novel;
}
else {
- const char *sep = num_new_overridden == 0 ? "" : ",\n";
- char *def = S_overridden_meth(self, method, klass,
- num_new_overridden);
- overridden_specs = CFCUtil_cat(overridden_specs, sep, def,
- NULL);
- FREEMEM(def);
+ int meth_index = self->num_overridden + num_new_overridden;
+ S_add_overridden_meth(self, method, klass, meth_index);
++num_new_overridden;
}
}
else {
- const char *sep = num_new_inherited == 0 ? "" : ",\n";
- char *def = S_inherited_meth(self, method, klass,
- num_new_inherited);
- inherited_specs = CFCUtil_cat(inherited_specs, sep, def, NULL);
- FREEMEM(def);
+ int meth_index = self->num_inherited + num_new_inherited;
+ S_add_inherited_meth(self, method, klass, meth_index);
++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"
@@ -274,20 +200,12 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
" &%s, /* ivars_offset_ptr */\n"
" %d, /* num_novel */\n"
" %d, /* num_overridden */\n"
- " %d, /* num_inherited */\n"
- " %s,\n"
- " %s,\n"
- " %s\n"
+ " %d /* num_inherited */\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);
+ ivars_size, ivars_offset_name, num_new_novel,
+ num_new_overridden, num_new_inherited);
const char *sep = self->num_specs == 0 ? "" : ",\n";
self->class_specs = CFCUtil_cat(self->class_specs, sep, class_spec, NULL);
@@ -298,16 +216,42 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
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(""); }
+ if (self->num_specs == 0) { return CFCUtil_strdup(""); }
+
+ const char *novel_pattern =
+ "static cfish_NovelMethSpec novel_specs[] = {\n"
+ "%s\n"
+ "};\n"
+ "\n";
+ char *novel_specs = self->num_novel == 0
+ ? CFCUtil_strdup("")
+ : CFCUtil_sprintf(novel_pattern, self->novel_specs);
+
+ const char *overridden_pattern =
+ "static cfish_OverriddenMethSpec overridden_specs[] = {\n"
+ "%s\n"
+ "};\n"
+ "\n";
+ char *overridden_specs = self->num_overridden == 0
+ ? CFCUtil_strdup("")
+ : CFCUtil_sprintf(overridden_pattern,
+ self->overridden_specs);
+
+ const char *inherited_pattern =
+ "static cfish_InheritedMethSpec inherited_specs[] = {\n"
+ "%s\n"
+ "};\n"
+ "\n";
+ char *inherited_specs = self->num_inherited == 0
+ ? CFCUtil_strdup("")
+ : CFCUtil_sprintf(inherited_pattern,
+ self->inherited_specs);
const char *pattern =
"%s"
@@ -316,9 +260,13 @@ CFCBindSpecs_defs(CFCBindSpecs *self) {
"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 *defs = CFCUtil_sprintf(pattern, novel_specs, overridden_specs,
+ inherited_specs, self->class_specs);
+
+ FREEMEM(inherited_specs);
+ FREEMEM(overridden_specs);
+ FREEMEM(novel_specs);
+ return defs;
}
char*
@@ -328,7 +276,8 @@ CFCBindSpecs_init_func_def(CFCBindSpecs *self) {
"S_bootstrap_specs() {\n"
"%s"
"\n"
- " cfish_Class_bootstrap(class_specs, %d);\n"
+ " cfish_Class_bootstrap(class_specs, %d, novel_specs,\n"
+ " overridden_specs, inherited_specs);\n"
"}\n";
return CFCUtil_sprintf(pattern, self->init_code, self->num_specs);
}
@@ -359,12 +308,11 @@ S_ivars_size(CFCClass *klass) {
return ivars_size;
}
-static char*
-S_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
- int meth_index) {
- CHY_UNUSED_VAR(self);
- CHY_UNUSED_VAR(meth_index);
+static void
+S_add_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index) {
const char *meth_name = CFCMethod_get_name(method);
+ const char *sep = meth_index == 0 ? "" : ",\n";
char *full_override_sym;
if (!CFCMethod_final(method)) {
@@ -387,11 +335,12 @@ S_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
char *def
= CFCUtil_sprintf(pattern, full_offset_sym, meth_name, imp_func,
full_override_sym);
+ self->novel_specs = CFCUtil_cat(self->novel_specs, sep, def, NULL);
+ FREEMEM(def);
FREEMEM(full_offset_sym);
FREEMEM(imp_func);
FREEMEM(full_override_sym);
- return def;
}
static char*
@@ -412,9 +361,8 @@ S_parent_offset(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
else {
parent_offset = CFCUtil_strdup("NULL");
- const char *class_var = CFCClass_full_class_var(klass);
- char pattern[] = " %s_%s_METHS[%d].parent_offset = &%s;\n";
- char *code = CFCUtil_sprintf(pattern, class_var, meth_type, meth_index,
+ char pattern[] = " %s_specs[%d].parent_offset = &%s;\n";
+ char *code = CFCUtil_sprintf(pattern, meth_type, meth_index,
parent_offset_sym);
self->init_code = CFCUtil_cat(self->init_code, code, NULL);
FREEMEM(code);
@@ -425,12 +373,14 @@ S_parent_offset(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
return parent_offset;
}
-static char*
-S_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
- int meth_index) {
+static void
+S_add_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index) {
+ const char *sep = meth_index == 0 ? "" : ",\n";
+
char *imp_func = CFCMethod_imp_func(method, klass);
char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
- char *parent_offset = S_parent_offset(self, method, klass, "OVERRIDDEN",
+ char *parent_offset = S_parent_offset(self, method, klass, "overridden",
meth_index);
char pattern[] =
@@ -441,18 +391,22 @@ S_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
" }";
char *def
= CFCUtil_sprintf(pattern, full_offset_sym, parent_offset, imp_func);
+ self->overridden_specs
+ = CFCUtil_cat(self->overridden_specs, sep, def, NULL);
+ FREEMEM(def);
FREEMEM(parent_offset);
FREEMEM(full_offset_sym);
FREEMEM(imp_func);
- return def;
}
-static char*
-S_inherited_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
- int meth_index) {
+static void
+S_add_inherited_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index) {
+ const char *sep = meth_index == 0 ? "" : ",\n";
+
char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
- char *parent_offset = S_parent_offset(self, method, klass, "INHERITED",
+ char *parent_offset = S_parent_offset(self, method, klass, "inherited",
meth_index);
char pattern[] =
@@ -461,9 +415,10 @@ S_inherited_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
" %s /* parent_offset */\n"
" }";
char *def = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset);
+ self->inherited_specs = CFCUtil_cat(self->inherited_specs, sep, def, NULL);
+ FREEMEM(def);
FREEMEM(full_offset_sym);
FREEMEM(parent_offset);
- return def;
}
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5c7144b6/runtime/core/Clownfish/Class.c
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.c b/runtime/core/Clownfish/Class.c
index 47ada81..474e8a2 100644
--- a/runtime/core/Clownfish/Class.c
+++ b/runtime/core/Clownfish/Class.c
@@ -56,8 +56,10 @@ S_claim_parcel_id(void);
static LockFreeRegistry *Class_registry;
void
-Class_bootstrap(const ClassSpec *specs, size_t num_specs)
-{
+Class_bootstrap(const cfish_ClassSpec *specs, size_t num_specs,
+ const cfish_NovelMethSpec *novel_specs,
+ const cfish_OverriddenMethSpec *overridden_specs,
+ const cfish_InheritedMethSpec *inherited_specs) {
int32_t parcel_id = S_claim_parcel_id();
/* Pass 1:
@@ -99,6 +101,9 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs)
* - Assign parcel_id.
* - Initialize method pointers and offsets.
*/
+ uint32_t num_novel = 0;
+ uint32_t num_overridden = 0;
+ uint32_t num_inherited = 0;
for (size_t i = 0; i < num_specs; ++i) {
const ClassSpec *spec = &specs[i];
Class *klass = *spec->klass;
@@ -159,18 +164,19 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs)
}
for (size_t i = 0; i < spec->num_inherited_meths; ++i) {
- const InheritedMethSpec *mspec = &spec->inherited_meth_specs[i];
+ const InheritedMethSpec *mspec = &inherited_specs[num_inherited++];
*mspec->offset = *mspec->parent_offset;
}
for (size_t i = 0; i < spec->num_overridden_meths; ++i) {
- const OverriddenMethSpec *mspec = &spec->overridden_meth_specs[i];
+ const OverriddenMethSpec *mspec
+ = &overridden_specs[num_overridden++];
*mspec->offset = *mspec->parent_offset;
Class_Override_IMP(klass, mspec->func, *mspec->offset);
}
for (size_t i = 0; i < spec->num_novel_meths; ++i) {
- const NovelMethSpec *mspec = &spec->novel_meth_specs[i];
+ const NovelMethSpec *mspec = &novel_specs[num_novel++];
*mspec->offset = novel_offset;
novel_offset += sizeof(cfish_method_t);
Class_Override_IMP(klass, mspec->func, *mspec->offset);
@@ -183,6 +189,9 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs)
* - Inititalize name and method array.
* - Register class.
*/
+ num_novel = 0;
+ num_overridden = 0;
+ num_inherited = 0;
for (size_t i = 0; i < num_specs; ++i) {
const ClassSpec *spec = &specs[i];
Class *klass = *spec->klass;
@@ -193,7 +202,7 @@ Class_bootstrap(const ClassSpec *specs, size_t num_specs)
// Only store novel methods for now.
for (size_t i = 0; i < spec->num_novel_meths; ++i) {
- const NovelMethSpec *mspec = &spec->novel_meth_specs[i];
+ const NovelMethSpec *mspec = &novel_specs[num_novel++];
String *name = SSTR_WRAP_UTF8(mspec->name, strlen(mspec->name));
Method *method = Method_new(name, mspec->callback_func,
*mspec->offset);
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5c7144b6/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index be8520e..733e06e 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -38,7 +38,10 @@ final class Clownfish::Class inherits Clownfish::Obj {
inert size_t offset_of_parent;
inert void
- bootstrap(const cfish_ClassSpec *specs, size_t num_specs);
+ bootstrap(const cfish_ClassSpec *specs, size_t num_specs,
+ const cfish_NovelMethSpec *novel_specs,
+ const cfish_OverriddenMethSpec *overridden_specs,
+ const cfish_InheritedMethSpec *inherited_specs);
/** Return a singleton. If a Class can be found in the registry based on
* the supplied class name, it will be returned. Otherwise, a new Class
[2/4] lucy-clownfish git commit: Don't use cross-DLL pointers in
global initialization
Posted by nw...@apache.org.
Don't use cross-DLL pointers in global initialization
Initialize global pointers to objects from other DLLs manually at runtime.
Fixes build of Clownfish projects with MSVC in C mode.
Fixes CLOWNFISH-53.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/05068aab
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/05068aab
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/05068aab
Branch: refs/heads/master
Commit: 05068aabc4425d91f62de6f0205e6a892c954ac0
Parents: 2b3ed29
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Fri Jul 24 13:32:39 2015 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Mon Jul 27 18:26:18 2015 +0200
----------------------------------------------------------------------
compiler/src/CFCBindSpecs.c | 82 ++++++++++++++++++++++++++++++++--------
1 file changed, 66 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/05068aab/compiler/src/CFCBindSpecs.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindSpecs.c b/compiler/src/CFCBindSpecs.c
index 513806b..ff64eca 100644
--- a/compiler/src/CFCBindSpecs.c
+++ b/compiler/src/CFCBindSpecs.c
@@ -32,6 +32,7 @@ struct CFCBindSpecs {
char *overridden_specs;
char *inherited_specs;
char *class_specs;
+ char *init_code;
int num_novel;
int num_overridden;
@@ -43,16 +44,20 @@ static char*
S_ivars_size(CFCClass *klass);
static char*
-S_novel_meth(CFCMethod *method, CFCClass *klass);
+S_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index);
static char*
-S_parent_offset(CFCMethod *method, CFCClass *klass);
+S_parent_offset(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ const char *meth_type, int meth_index);
static char*
-S_overridden_meth(CFCMethod *method, CFCClass *klass);
+S_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index);
static char*
-S_inherited_meth(CFCMethod *method, CFCClass *klass);
+S_inherited_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index);
static const CFCMeta CFCBINDSPECS_META = {
"Clownfish::CFC::Binding::Core::Specs",
@@ -72,6 +77,7 @@ CFCBindSpecs_init(CFCBindSpecs *self) {
self->overridden_specs = CFCUtil_strdup("");
self->inherited_specs = CFCUtil_strdup("");
self->class_specs = CFCUtil_strdup("");
+ self->init_code = CFCUtil_strdup("");
return self;
}
@@ -82,6 +88,7 @@ CFCBindSpecs_destroy(CFCBindSpecs *self) {
FREEMEM(self->overridden_specs);
FREEMEM(self->inherited_specs);
FREEMEM(self->class_specs);
+ FREEMEM(self->init_code);
CFCBase_destroy((CFCBase*)self);
}
@@ -141,7 +148,23 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
parent_ptr = CFCUtil_strdup("NULL");
}
else {
- parent_ptr = CFCUtil_sprintf("&%s", CFCClass_full_class_var(parent));
+ if (CFCClass_get_parcel(klass) == CFCClass_get_parcel(parent)) {
+ parent_ptr
+ = CFCUtil_sprintf("&%s", CFCClass_full_class_var(parent));
+ }
+ else {
+ parent_ptr = CFCUtil_strdup("NULL");
+
+ const char *class_name = CFCClass_get_name(klass);
+ const char *parent_var = CFCClass_full_class_var(parent);
+ const char *pattern =
+ " /* %s */\n"
+ " class_specs[%d].parent = &%s;\n";
+ char *init_code = CFCUtil_sprintf(pattern, class_name,
+ self->num_specs, parent_var);
+ self->init_code = CFCUtil_cat(self->init_code, init_code, NULL);
+ FREEMEM(init_code);
+ }
}
char *novel_specs = CFCUtil_strdup("");
@@ -158,14 +181,15 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
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);
+ char *def = S_novel_meth(self, method, klass, num_new_novel);
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);
+ char *def = S_overridden_meth(self, method, klass,
+ num_new_overridden);
overridden_specs = CFCUtil_cat(overridden_specs, sep, def,
NULL);
FREEMEM(def);
@@ -174,7 +198,8 @@ CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
}
else {
const char *sep = num_new_inherited == 0 ? "" : ",\n";
- char *def = S_inherited_meth(method, klass);
+ char *def = S_inherited_meth(self, method, klass,
+ num_new_inherited);
inherited_specs = CFCUtil_cat(inherited_specs, sep, def, NULL);
FREEMEM(def);
++num_new_inherited;
@@ -301,9 +326,11 @@ CFCBindSpecs_init_func_def(CFCBindSpecs *self) {
const char *pattern =
"static void\n"
"S_bootstrap_specs() {\n"
+ "%s"
+ "\n"
" cfish_Class_bootstrap(class_specs, %d);\n"
"}\n";
- return CFCUtil_sprintf(pattern, self->num_specs);
+ return CFCUtil_sprintf(pattern, self->init_code, self->num_specs);
}
static char*
@@ -333,7 +360,10 @@ S_ivars_size(CFCClass *klass) {
}
static char*
-S_novel_meth(CFCMethod *method, CFCClass *klass) {
+S_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index) {
+ CHY_UNUSED_VAR(self);
+ CHY_UNUSED_VAR(meth_index);
const char *meth_name = CFCMethod_get_name(method);
char *full_override_sym;
@@ -365,25 +395,43 @@ S_novel_meth(CFCMethod *method, CFCClass *klass) {
}
static char*
-S_parent_offset(CFCMethod *method, CFCClass *klass) {
+S_parent_offset(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ const char *meth_type, int meth_index) {
CFCClass *parent = CFCClass_get_parent(klass);
if (!parent) {
return CFCUtil_strdup("NULL");
}
+ char *parent_offset = NULL;
char *parent_offset_sym = CFCMethod_full_offset_sym(method, parent);
- char *parent_offset = CFCUtil_sprintf("&%s", parent_offset_sym);
+
+ if (CFCClass_get_parcel(parent) == CFCClass_get_parcel(klass)) {
+ parent_offset = CFCUtil_sprintf("&%s", parent_offset_sym);
+ }
+ else {
+ parent_offset = CFCUtil_strdup("NULL");
+
+ const char *class_var = CFCClass_full_class_var(klass);
+ char pattern[] = " %s_%s_METHS[%d].parent_offset = &%s;\n";
+ char *code = CFCUtil_sprintf(pattern, class_var, meth_type, meth_index,
+ parent_offset_sym);
+ self->init_code = CFCUtil_cat(self->init_code, code, NULL);
+ FREEMEM(code);
+ }
+
FREEMEM(parent_offset_sym);
return parent_offset;
}
static char*
-S_overridden_meth(CFCMethod *method, CFCClass *klass) {
+S_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index) {
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 *parent_offset = S_parent_offset(self, method, klass, "OVERRIDDEN",
+ meth_index);
char pattern[] =
" {\n"
@@ -401,9 +449,11 @@ S_overridden_meth(CFCMethod *method, CFCClass *klass) {
}
static char*
-S_inherited_meth(CFCMethod *method, CFCClass *klass) {
+S_inherited_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
+ int meth_index) {
char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
- char *parent_offset = S_parent_offset(method, klass);
+ char *parent_offset = S_parent_offset(self, method, klass, "INHERITED",
+ meth_index);
char pattern[] =
" {\n"