Store CFCClass pointer in CFCMethod Store a weak pointer to the class containing the method.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/a0e051a0 Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/a0e051a0 Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/a0e051a0 Branch: refs/heads/master Commit: a0e051a0d15658574482b24d328e326c8389670c Parents: 1ff6ed0 Author: Nick Wellnhofer <wellnho...@aevum.de> Authored: Wed Mar 1 14:52:23 2017 +0100 Committer: Nick Wellnhofer <wellnho...@aevum.de> Committed: Thu Mar 2 20:08:04 2017 +0100 ---------------------------------------------------------------------- compiler/perl/lib/Clownfish/CFC.pm | 4 +- compiler/perl/lib/Clownfish/CFC.xs | 8 ++- compiler/perl/t/201-method.t | 25 ++-------- compiler/perl/t/202-overridden_method.t | 4 +- compiler/perl/t/203-final_method.t | 2 +- compiler/src/CFCMethod.c | 73 ++++++++++++++++------------ compiler/src/CFCMethod.h | 9 ++-- compiler/src/CFCParseHeader.y | 3 +- compiler/src/CFCTestMethod.c | 72 +++++++++++++-------------- 9 files changed, 91 insertions(+), 109 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/perl/lib/Clownfish/CFC.pm ---------------------------------------------------------------------- diff --git a/compiler/perl/lib/Clownfish/CFC.pm b/compiler/perl/lib/Clownfish/CFC.pm index 26cb4a4..cd6dae0 100644 --- a/compiler/perl/lib/Clownfish/CFC.pm +++ b/compiler/perl/lib/Clownfish/CFC.pm @@ -250,7 +250,7 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.6.0' ) } param_list => undef, name => undef, docucomment => undef, - class_name => undef, + class => undef, abstract => undef, final => undef, exposure => 'parcel', @@ -264,7 +264,7 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.6.0' ) } $args{final} ||= 0; return _new( @args{ - qw( exposure name return_type param_list docucomment class_name + qw( exposure name return_type param_list docucomment class final abstract ) } ); http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/perl/lib/Clownfish/CFC.xs ---------------------------------------------------------------------- diff --git a/compiler/perl/lib/Clownfish/CFC.xs b/compiler/perl/lib/Clownfish/CFC.xs index 9bae35d..b6b7939 100644 --- a/compiler/perl/lib/Clownfish/CFC.xs +++ b/compiler/perl/lib/Clownfish/CFC.xs @@ -826,23 +826,21 @@ PPCODE: MODULE = Clownfish::CFC PACKAGE = Clownfish::CFC::Model::Method SV* -_new(exposure_sv, name, return_type, param_list, docucomment, class_name_sv, is_final, is_abstract) +_new(exposure_sv, name, return_type, param_list, docucomment, klass, is_final, is_abstract) SV *exposure_sv; const char *name; CFCType *return_type; CFCParamList *param_list; CFCDocuComment *docucomment; - SV *class_name_sv; + CFCClass *klass; int is_final; int is_abstract; CODE: const char *exposure = SvOK(exposure_sv) ? SvPV_nolen(exposure_sv) : NULL; - const char *class_name = - SvOK(class_name_sv) ? SvPV_nolen(class_name_sv) : NULL; CFCMethod *self = CFCMethod_new(exposure, name, return_type, param_list, docucomment, - class_name, is_final, is_abstract); + klass, is_final, is_abstract); RETVAL = S_cfcbase_to_perlref(self); CFCBase_decref((CFCBase*)self); OUTPUT: RETVAL http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/perl/t/201-method.t ---------------------------------------------------------------------- diff --git a/compiler/perl/t/201-method.t b/compiler/perl/t/201-method.t index 3c8a74c..6caa3a2 100644 --- a/compiler/perl/t/201-method.t +++ b/compiler/perl/t/201-method.t @@ -16,7 +16,7 @@ use strict; use warnings; -use Test::More tests => 38; +use Test::More tests => 30; BEGIN { use_ok('Clownfish::CFC::Model::Method') } use Clownfish::CFC::Parser; @@ -24,10 +24,11 @@ use Clownfish::CFC::Parser; my $parser = Clownfish::CFC::Parser->new; $parser->parse('parcel Neato;') or die "failed to process parcel_definition"; +my $neato_foo = $parser->parse('class Neato::Foo {}'); my %args = ( return_type => $parser->parse('Obj*'), - class_name => 'Neato::Foo', + class => $neato_foo, param_list => $parser->parse('(Foo *self, int32_t count = 0)'), name => 'Return_An_Obj', ); @@ -48,24 +49,6 @@ eval { }; like( $@, qr/name/, "Invalid name kills constructor" ); -for (qw( foo 1Foo Foo_Bar 1FOOBAR )) { - eval { - Clownfish::CFC::Model::Method->new( - %args, - class_name => $_, - ); - }; - like( $@, qr/class_name/, "Reject invalid class name $_" ); - my $bogus_middle = "Foo::" . $_ . "::Bar"; - eval { - Clownfish::CFC::Model::Method->new( - %args, - class_name => $bogus_middle, - ); - }; - like( $@, qr/class_name/, "Reject invalid class name $bogus_middle" ); -} - my $dupe = Clownfish::CFC::Model::Method->new(%args); ok( $method->compatible($dupe), "compatible()" ); @@ -113,7 +96,7 @@ ok( !$param_type_differs->compatible($method), "... reversed" ); my $self_type_differs = Clownfish::CFC::Model::Method->new( %args, - class_name => 'Neato::Bar', + class => $parser->parse('class Neato::Bar {}'), param_list => $parser->parse('(Bar *self, int32_t count = 0)'), ); ok( $method->compatible($self_type_differs), http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/perl/t/202-overridden_method.t ---------------------------------------------------------------------- diff --git a/compiler/perl/t/202-overridden_method.t b/compiler/perl/t/202-overridden_method.t index c33c928..85e0f81 100644 --- a/compiler/perl/t/202-overridden_method.t +++ b/compiler/perl/t/202-overridden_method.t @@ -27,7 +27,7 @@ $parser->parse('parcel Neato;') my %args = ( return_type => $parser->parse('Obj*'), - class_name => 'Neato::Foo', + class => $parser->parse('class Neato::Foo {}'), param_list => $parser->parse('(Foo *self)'), name => 'Return_An_Obj', ); @@ -36,7 +36,7 @@ my $orig = Clownfish::CFC::Model::Method->new(%args); my $overrider = Clownfish::CFC::Model::Method->new( %args, param_list => $parser->parse('(FooJr *self)'), - class_name => 'Neato::Foo::FooJr', + class => $parser->parse('class Neato::Foo::FooJr {}'), ); $overrider->override($orig); ok( !$overrider->novel, "A Method which overrides another is not 'novel'" ); http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/perl/t/203-final_method.t ---------------------------------------------------------------------- diff --git a/compiler/perl/t/203-final_method.t b/compiler/perl/t/203-final_method.t index ea98ca5..53d2b36 100644 --- a/compiler/perl/t/203-final_method.t +++ b/compiler/perl/t/203-final_method.t @@ -26,7 +26,7 @@ $parser->parse('parcel Neato;') my %args = ( return_type => $parser->parse('Obj*'), - class_name => 'Neato::Foo', + class => $parser->parse('class Neato::Foo {}'), param_list => $parser->parse('(Foo* self)'), name => 'Return_An_Obj', ); http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/src/CFCMethod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCMethod.c b/compiler/src/CFCMethod.c index 1d449e4..1fd6557 100644 --- a/compiler/src/CFCMethod.c +++ b/compiler/src/CFCMethod.c @@ -36,7 +36,7 @@ struct CFCMethod { CFCCallable callable; CFCMethod *novel_method; - char *fresh_class_name; + CFCWeakPtr fresh_class; char *host_alias; int is_final; int is_abstract; @@ -44,6 +44,12 @@ struct CFCMethod { int is_excluded; }; +static CFCClass* +S_fresh_class(CFCMethod *self); + +static const char* +S_fresh_class_name(CFCMethod *self); + static const CFCMeta CFCMETHOD_META = { "Clownfish::CFC::Model::Method", sizeof(CFCMethod), @@ -53,10 +59,10 @@ static const CFCMeta CFCMETHOD_META = { CFCMethod* CFCMethod_new(const char *exposure, const char *name, CFCType *return_type, CFCParamList *param_list, CFCDocuComment *docucomment, - const char *class_name, int is_final, int is_abstract) { + CFCClass *klass, int is_final, int is_abstract) { CFCMethod *self = (CFCMethod*)CFCBase_allocate(&CFCMETHOD_META); return CFCMethod_init(self, exposure, name, return_type, param_list, - docucomment, class_name, is_final, is_abstract); + docucomment, klass, is_final, is_abstract); } static int @@ -84,14 +90,9 @@ S_validate_meth_name(const char *meth_name) { CFCMethod* CFCMethod_init(CFCMethod *self, const char *exposure, const char *name, CFCType *return_type, CFCParamList *param_list, - CFCDocuComment *docucomment, const char *class_name, + CFCDocuComment *docucomment, CFCClass *klass, int is_final, int is_abstract) { - // Validate class_name. - CFCUTIL_NULL_CHECK(class_name); - if (!CFCClass_validate_class_name(class_name)) { - CFCBase_decref((CFCBase*)self); - CFCUtil_die("Invalid class_name: '%s'", class_name); - } + CFCUTIL_NULL_CHECK(klass); // Validate name. if (!S_validate_meth_name(name)) { CFCBase_decref((CFCBase*)self); @@ -108,24 +109,21 @@ CFCMethod_init(CFCMethod *self, const char *exposure, const char *name, if (!args[0]) { CFCUtil_die("Missing 'self' argument"); } CFCType *type = CFCVariable_get_type(args[0]); const char *specifier = CFCType_get_specifier(type); - const char *last_colon = strrchr(class_name, ':'); - const char *struct_sym = last_colon ? last_colon + 1 : class_name; + const char *struct_sym = CFCClass_get_struct_sym(klass); if (strcmp(specifier, struct_sym) != 0) { - const char *first_underscore = strchr(specifier, '_'); - int mismatch = !first_underscore - || strcmp(first_underscore + 1, struct_sym) != 0; - if (mismatch) { + const char *full_struct_sym = CFCClass_full_struct_sym(klass); + if (strcmp(specifier, full_struct_sym) != 0) { CFCUtil_die("First arg type doesn't match class: '%s' '%s'", - class_name, specifier); + CFCClass_get_name(klass), specifier); } } - self->novel_method = NULL; - self->fresh_class_name = CFCUtil_strdup(class_name); - self->host_alias = NULL; - self->is_final = is_final; - self->is_abstract = is_abstract; - self->is_excluded = false; + self->novel_method = NULL; + self->fresh_class = CFCWeakPtr_new((CFCBase*)klass); + self->host_alias = NULL; + self->is_final = is_final; + self->is_abstract = is_abstract; + self->is_excluded = false; // Assume that this method is novel until we discover when applying // inheritance that it overrides another. @@ -142,7 +140,7 @@ CFCMethod_resolve_types(CFCMethod *self) { void CFCMethod_destroy(CFCMethod *self) { CFCBase_decref((CFCBase*)self->novel_method); - FREEMEM(self->fresh_class_name); + CFCWeakPtr_destroy(&self->fresh_class); FREEMEM(self->host_alias); CFCCallable_destroy((CFCCallable*)self); } @@ -209,12 +207,14 @@ CFCMethod_override(CFCMethod *self, CFCMethod *orig) { if (CFCMethod_final(orig)) { const char *orig_name = CFCMethod_get_name(orig); CFCUtil_die("Attempt to override final method '%s' from '%s' by '%s'", - orig_name, orig->fresh_class_name, self->fresh_class_name); + orig_name, S_fresh_class_name(orig), + S_fresh_class_name(self)); } if (!CFCMethod_compatible(self, orig)) { const char *orig_name = CFCMethod_get_name(orig); CFCUtil_die("Non-matching signatures for method '%s' in '%s' and '%s'", - orig_name, orig->fresh_class_name, self->fresh_class_name); + orig_name, S_fresh_class_name(orig), + S_fresh_class_name(self)); } // Mark the Method as no longer novel. @@ -234,7 +234,7 @@ CFCMethod_finalize(CFCMethod *self) { self->callable.return_type, self->callable.param_list, self->callable.docucomment, - self->fresh_class_name, true, self->is_abstract); + S_fresh_class(self), true, self->is_abstract); finalized->novel_method = (CFCMethod*)CFCBase_incref((CFCBase*)self->novel_method); finalized->is_novel = self->is_novel; @@ -289,14 +289,14 @@ CFCMethod_set_host_alias(CFCMethod *self, const char *alias) { if (!self->is_novel) { const char *name = CFCMethod_get_name(self); CFCUtil_die("Can't set_host_alias %s -- method %s not novel in %s", - alias, name, self->fresh_class_name); + alias, name, S_fresh_class_name(self)); } if (self->host_alias) { const char *name = CFCMethod_get_name(self); if (strcmp(self->host_alias, alias) == 0) { return; } CFCUtil_die("Can't set_host_alias %s -- already set to %s for method" " %s in %s", alias, self->host_alias, name, - self->fresh_class_name); + S_fresh_class_name(self)); } self->host_alias = CFCUtil_strdup(alias); } @@ -312,7 +312,7 @@ CFCMethod_exclude_from_host(CFCMethod *self) { if (!self->is_novel) { const char *name = CFCMethod_get_name(self); CFCUtil_die("Can't exclude_from_host -- method %s not novel in %s", - name, self->fresh_class_name); + name, S_fresh_class_name(self)); } self->is_excluded = true; } @@ -414,8 +414,7 @@ CFCMethod_get_exposure(CFCMethod *self) { int CFCMethod_is_fresh(CFCMethod *self, CFCClass *klass) { - const char *class_name = CFCClass_get_name(klass); - return strcmp(self->fresh_class_name, class_name) == 0; + return S_fresh_class(self) == klass; } int @@ -454,3 +453,13 @@ CFCMethod_short_imp_func(CFCMethod *self, CFCClass *klass) { return S_short_method_sym(self, klass, "_IMP"); } +static CFCClass* +S_fresh_class(CFCMethod *self) { + return (CFCClass*)CFCWeakPtr_deref(self->fresh_class); +} + +static const char* +S_fresh_class_name(CFCMethod *self) { + return CFCClass_get_name(S_fresh_class(self)); +} + http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/src/CFCMethod.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCMethod.h b/compiler/src/CFCMethod.h index 37c4773..3a97c7a 100644 --- a/compiler/src/CFCMethod.h +++ b/compiler/src/CFCMethod.h @@ -46,23 +46,22 @@ struct CFCJson; * method. * @param return_type See Clownfish::CFC::Model::Function. * @param param_list - A Clownfish::CFC::Model::ParamList. The first element - * must be an object of the class identified by C<class_name>. + * must be an object of C<klass>. * @param docucomment see Clownfish::CFC::Model::Function. May be NULL. - * @param class_name The full name of the class in whose namespace the - * method is fresh. + * @param klass The class in whose namespace the method is fresh. * @param is_final - Indicate whether the method is final. * @param is_abstract - Indicate whether the method is abstract. */ CFCMethod* CFCMethod_new(const char *exposure, const char *name, struct CFCType *return_type, struct CFCParamList *param_list, - struct CFCDocuComment *docucomment, const char *class_name, + struct CFCDocuComment *docucomment, struct CFCClass *klass, int is_final, int is_abstract); CFCMethod* CFCMethod_init(CFCMethod *self, const char *exposure, const char *name, struct CFCType *return_type, struct CFCParamList *param_list, - struct CFCDocuComment *docucomment, const char *class_name, + struct CFCDocuComment *docucomment, struct CFCClass *klass, int is_final, int is_abstract); void http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/src/CFCParseHeader.y ---------------------------------------------------------------------- diff --git a/compiler/src/CFCParseHeader.y b/compiler/src/CFCParseHeader.y index 14e5f1b..500b114 100644 --- a/compiler/src/CFCParseHeader.y +++ b/compiler/src/CFCParseHeader.y @@ -113,9 +113,8 @@ S_new_sub(CFCParser *state, CFCDocuComment *docucomment, CFCUtil_die("Methods must not be inline"); } CFCClass *klass = CFCParser_get_class(state); - const char *class_name = CFCClass_get_name(klass); sub = (CFCBase*)CFCMethod_new(exposure, name, type, param_list, - docucomment, class_name, is_final, + docucomment, klass, is_final, is_abstract); } http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a0e051a0/compiler/src/CFCTestMethod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCTestMethod.c b/compiler/src/CFCTestMethod.c index e927fe4..634e1de 100644 --- a/compiler/src/CFCTestMethod.c +++ b/compiler/src/CFCTestMethod.c @@ -50,7 +50,7 @@ S_run_final_tests(CFCTest *test); const CFCTestBatch CFCTEST_BATCH_METHOD = { "Clownfish::CFC::Model::Method", - 84, + 76, S_run_tests }; @@ -64,13 +64,13 @@ S_run_tests(CFCTest *test) { static char* S_try_new_method(const char *name, CFCType *return_type, - CFCParamList *param_list, const char *class_name) { + CFCParamList *param_list, CFCClass *klass) { CFCMethod *method = NULL; char *error; CFCUTIL_TRY { method = CFCMethod_new(NULL, name, return_type, param_list, NULL, - class_name, 0, 0); + klass, 0, 0); } CFCUTIL_CATCH(error); @@ -83,6 +83,12 @@ S_run_basic_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); + CFCClass *neato_foo + = CFCClass_create(neato_parcel, NULL, "Neato::Foo", NULL, NULL, NULL, + NULL, false, false, false); + CFCClass *neato_bar + = CFCClass_create(neato_parcel, NULL, "Neato::Bar", NULL, NULL, NULL, + NULL, false, false, false); CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list @@ -90,48 +96,23 @@ S_run_basic_tests(CFCTest *test) { "(Foo *self, int32_t count = 0)"); CFCMethod *method = CFCMethod_new(NULL, "Return_An_Obj", return_type, param_list, NULL, - "Neato::Foo", 0, 0); + neato_foo, 0, 0); OK(test, method != NULL, "new"); OK(test, CFCSymbol_parcel((CFCSymbol*)method), "parcel exposure by default"); { char *error = S_try_new_method("return_an_obj", return_type, - param_list, "Neato::Foo"); + param_list, neato_foo); OK(test, error && strstr(error, "name"), "invalid name kills constructor"); FREEMEM(error); } { - static const char *bad_class_names[4] = { - "foo", "1Foo", "Foo_Bar", "1FOOBAR" - }; - for (int i = 0; i < 4; i++) { - const char *bad_class_name = bad_class_names[i]; - char *error; - - error = S_try_new_method("Return_An_Obj", return_type, - param_list, bad_class_name); - OK(test, error && strstr(error, "class_name"), - "Reject invalid class name %s", bad_class_name); - FREEMEM(error); - - char *bogus_middle - = CFCUtil_sprintf("Foo::%s::Bar", bad_class_name); - error = S_try_new_method("Return_An_Obj", return_type, - param_list, bogus_middle); - OK(test, error && strstr(error, "class_name"), - "Reject invalid class name %s", bogus_middle); - FREEMEM(error); - FREEMEM(bogus_middle); - } - } - - { CFCMethod *dupe = CFCMethod_new(NULL, "Return_An_Obj", return_type, param_list, - NULL, "Neato::Foo", 0, 0); + NULL, neato_foo, 0, 0); OK(test, CFCMethod_compatible(method, dupe), "compatible"); CFCBase_decref((CFCBase*)dupe); } @@ -139,7 +120,7 @@ S_run_basic_tests(CFCTest *test) { { CFCMethod *name_differs = CFCMethod_new(NULL, "Eat", return_type, param_list, NULL, - "Neato::Foo", 0, 0); + neato_foo, 0, 0); OK(test, !CFCMethod_compatible(method, name_differs), "different name spoils compatible"); OK(test, !CFCMethod_compatible(name_differs, method), @@ -167,7 +148,7 @@ S_run_basic_tests(CFCTest *test) { = CFCTest_parse_param_list(test, parser, param_strings[i]); CFCMethod *other = CFCMethod_new(NULL, "Return_An_Obj", return_type, - other_param_list, NULL, "Neato::Foo", 0, 0); + other_param_list, NULL, neato_foo, 0, 0); OK(test, !CFCMethod_compatible(method, other), "%s spoils compatible", test_names[i]); OK(test, !CFCMethod_compatible(other, method), @@ -183,7 +164,7 @@ S_run_basic_tests(CFCTest *test) { "(Bar *self, int32_t count = 0)"); CFCMethod *self_differs = CFCMethod_new(NULL, "Return_An_Obj", return_type, - self_differs_list, NULL, "Neato::Bar", 0, 0); + self_differs_list, NULL, neato_bar, 0, 0); OK(test, CFCMethod_compatible(method, self_differs), "different self type still compatible()," " since can't test inheritance"); @@ -196,7 +177,7 @@ S_run_basic_tests(CFCTest *test) { { CFCMethod *aliased = CFCMethod_new(NULL, "Aliased", return_type, param_list, NULL, - "Neato::Foo", 0, 0); + neato_foo, 0, 0); OK(test, !CFCMethod_get_host_alias(aliased), "no host alias by default"); CFCMethod_set_host_alias(aliased, "Host_Alias"); @@ -208,7 +189,7 @@ S_run_basic_tests(CFCTest *test) { { CFCMethod *excluded = CFCMethod_new(NULL, "Excluded", return_type, param_list, NULL, - "Neato::Foo", 0, 0); + neato_foo, 0, 0); OK(test, !CFCMethod_excluded_from_host(excluded), "not excluded by default"); CFCMethod_exclude_from_host(excluded); @@ -218,10 +199,13 @@ S_run_basic_tests(CFCTest *test) { CFCBase_decref((CFCBase*)parser); CFCBase_decref((CFCBase*)neato_parcel); + CFCBase_decref((CFCBase*)neato_foo); + CFCBase_decref((CFCBase*)neato_bar); CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)method); + CFCClass_clear_registry(); CFCParcel_reap_singletons(); } @@ -261,6 +245,7 @@ S_run_parser_tests(CFCTest *test) { CFCBase_decref((CFCBase*)neato_parcel); CFCBase_decref((CFCBase*)parser); + CFCClass_clear_registry(); CFCParcel_reap_singletons(); } @@ -269,19 +254,25 @@ S_run_overridden_tests(CFCTest *test) { CFCParser *parser = CFCParser_new(); CFCParcel *neato_parcel = CFCTest_parse_parcel(test, parser, "parcel Neato;"); + CFCClass *neato_foo + = CFCClass_create(neato_parcel, NULL, "Neato::Foo", NULL, NULL, NULL, + NULL, false, false, false); + CFCClass *neato_foo_jr + = CFCClass_create(neato_parcel, NULL, "Neato::Foo::FooJr", NULL, NULL, + NULL, "Neato::Foo", false, false, false); CFCType *return_type = CFCTest_parse_type(test, parser, "Obj*"); CFCParamList *param_list = CFCTest_parse_param_list(test, parser, "(Foo *self)"); CFCMethod *orig = CFCMethod_new(NULL, "Return_An_Obj", return_type, param_list, NULL, - "Neato::Foo", 0, 0); + neato_foo, 0, 0); CFCParamList *overrider_param_list = CFCTest_parse_param_list(test, parser, "(FooJr *self)"); CFCMethod *overrider = CFCMethod_new(NULL, "Return_An_Obj", return_type, - overrider_param_list, NULL, "Neato::Foo::FooJr", 0, 0); + overrider_param_list, NULL, neato_foo_jr, 0, 0); CFCMethod_override(overrider, orig); OK(test, !CFCMethod_novel(overrider), @@ -289,12 +280,15 @@ S_run_overridden_tests(CFCTest *test) { CFCBase_decref((CFCBase*)parser); CFCBase_decref((CFCBase*)neato_parcel); + CFCBase_decref((CFCBase*)neato_foo); + CFCBase_decref((CFCBase*)neato_foo_jr); CFCBase_decref((CFCBase*)return_type); CFCBase_decref((CFCBase*)param_list); CFCBase_decref((CFCBase*)orig); CFCBase_decref((CFCBase*)overrider_param_list); CFCBase_decref((CFCBase*)overrider); + CFCClass_clear_registry(); CFCParcel_reap_singletons(); } @@ -313,7 +307,7 @@ S_run_final_tests(CFCTest *test) { CFCMethod *not_final = CFCMethod_new(NULL, "Return_An_Obj", return_type, param_list, NULL, - "Neato::Foo", 0, 0); + foo_class, 0, 0); CFCMethod_resolve_types(not_final); CFCMethod *final = CFCMethod_finalize(not_final); OK(test, CFCMethod_compatible(not_final, final),