Cache novel method in CFCMethod
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/7744424b Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/7744424b Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/7744424b Branch: refs/heads/master Commit: 7744424b8fbc383fda910fc34c8def46e0b26c44 Parents: 811d2ef Author: Nick Wellnhofer <[email protected]> Authored: Sat Jul 26 20:20:00 2014 +0200 Committer: Nick Wellnhofer <[email protected]> Committed: Tue Jul 29 00:21:20 2014 +0200 ---------------------------------------------------------------------- compiler/src/CFCClass.c | 15 --------------- compiler/src/CFCClass.h | 6 ------ compiler/src/CFCMethod.c | 26 +++++++++++++++++++++++--- compiler/src/CFCMethod.h | 6 ++++++ compiler/src/CFCPerlClass.c | 16 ++-------------- 5 files changed, 31 insertions(+), 38 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7744424b/compiler/src/CFCClass.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCClass.c b/compiler/src/CFCClass.c index e896818..7322e22 100644 --- a/compiler/src/CFCClass.c +++ b/compiler/src/CFCClass.c @@ -664,21 +664,6 @@ CFCClass_fresh_member_vars(CFCClass *self) { return (CFCVariable**)S_fresh_syms(self, (CFCSymbol**)self->member_vars); } -CFCMethod* -CFCClass_find_novel_method(CFCClass *self, const char *sym) { - if (!self->tree_grown) { - CFCUtil_die("Can't call original_method before grow_tree"); - } - CFCClass *ancestor = self; - do { - CFCMethod *method = CFCClass_method(ancestor, sym); - if (method && CFCMethod_novel(method)) { - return method; - } - } while (NULL != (ancestor = CFCClass_get_parent(ancestor))); - return NULL; -} - CFCClass** CFCClass_children(CFCClass *self) { return self->children; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7744424b/compiler/src/CFCClass.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCClass.h b/compiler/src/CFCClass.h index 9dde5b4..78eefd0 100644 --- a/compiler/src/CFCClass.h +++ b/compiler/src/CFCClass.h @@ -133,12 +133,6 @@ CFCClass_method(CFCClass *self, const char *sym); struct CFCMethod* CFCClass_fresh_method(CFCClass *self, const char *sym); -/** Traverse all ancestors to find the first class which declared the method - * and return it. Cannot be called before grow_tree(). - */ -struct CFCMethod* -CFCClass_find_novel_method(CFCClass *self, const char *sym); - /** Find the actual class of all object variables without prefix. */ void http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7744424b/compiler/src/CFCMethod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCMethod.c b/compiler/src/CFCMethod.c index 9335577..0c89f68 100644 --- a/compiler/src/CFCMethod.c +++ b/compiler/src/CFCMethod.c @@ -36,6 +36,7 @@ struct CFCMethod { CFCFunction function; + CFCMethod *novel_method; char *macro_sym; char *full_override_sym; char *host_alias; @@ -127,6 +128,7 @@ CFCMethod_init(CFCMethod *self, CFCParcel *parcel, const char *exposure, } } + self->novel_method = NULL; self->macro_sym = CFCUtil_strdup(macro_sym); self->full_override_sym = NULL; self->host_alias = NULL; @@ -155,6 +157,7 @@ CFCMethod_resolve_types(CFCMethod *self) { void CFCMethod_destroy(CFCMethod *self) { + CFCBase_decref((CFCBase*)self->novel_method); FREEMEM(self->macro_sym); FREEMEM(self->full_override_sym); FREEMEM(self->host_alias); @@ -234,6 +237,10 @@ CFCMethod_override(CFCMethod *self, CFCMethod *orig) { // Mark the Method as no longer novel. self->is_novel = false; + + // Cache novel method. + CFCMethod *novel_method = orig->is_novel ? orig : orig->novel_method; + self->novel_method = (CFCMethod*)CFCBase_incref((CFCBase*)novel_method); } CFCMethod* @@ -248,7 +255,8 @@ CFCMethod_finalize(CFCMethod *self) { self->function.param_list, self->function.docucomment, true, self->is_abstract); - finalized->is_novel = self->is_novel; + finalized->novel_method = self->novel_method; + finalized->is_novel = self->is_novel; return finalized; } @@ -272,7 +280,8 @@ CFCMethod_set_host_alias(CFCMethod *self, const char *alias) { const char* CFCMethod_get_host_alias(CFCMethod *self) { - return self->host_alias; + CFCMethod *novel_method = CFCMethod_find_novel_method(self); + return novel_method->host_alias; } void @@ -286,7 +295,18 @@ CFCMethod_exclude_from_host(CFCMethod *self) { int CFCMethod_excluded_from_host(CFCMethod *self) { - return self->is_excluded; + CFCMethod *novel_method = CFCMethod_find_novel_method(self); + return novel_method->is_excluded; +} + +CFCMethod* +CFCMethod_find_novel_method(CFCMethod *self) { + if (self->is_novel) { + return self; + } + else { + return self->novel_method; + } } static char* http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7744424b/compiler/src/CFCMethod.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCMethod.h b/compiler/src/CFCMethod.h index 54d7e38..dd39203 100644 --- a/compiler/src/CFCMethod.h +++ b/compiler/src/CFCMethod.h @@ -108,6 +108,12 @@ CFCMethod* CFCMethod_finalize(CFCMethod *self); /** + * Find the first declaration of the method in the class hierarchy. + */ +CFCMethod* +CFCMethod_find_novel_method(CFCMethod *self); + +/** * Create the symbol used to invoke the method without the parcel Prefix, e.g. * "LobClaw_Pinch". * @param invoker Class for which the symbol is created. If invoker is NULL, http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/7744424b/compiler/src/CFCPerlClass.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCPerlClass.c b/compiler/src/CFCPerlClass.c index 9d52b16..db6edfc 100644 --- a/compiler/src/CFCPerlClass.c +++ b/compiler/src/CFCPerlClass.c @@ -258,20 +258,8 @@ CFCPerlClass_method_bindings(CFCClass *klass) { // Skip private methods. if (CFCSymbol_private((CFCSymbol*)method)) { continue; } - CFCMethod *novel_method; - if (CFCMethod_novel(method)) { - novel_method = method; - } - else { - const char *meth_name = CFCMethod_get_macro_sym(method); - novel_method = CFCClass_find_novel_method(parent, meth_name); - if (!novel_method) { - CFCUtil_die("Novel method not found"); - } - } - // Skip methods which have been explicitly excluded. - if (CFCMethod_excluded_from_host(novel_method)) { + if (CFCMethod_excluded_from_host(method)) { continue; } @@ -283,7 +271,7 @@ CFCPerlClass_method_bindings(CFCClass *klass) { } // See if the user wants the method to have a specific alias. - const char *alias = CFCMethod_get_host_alias(novel_method); + const char *alias = CFCMethod_get_host_alias(method); if (!alias) { alias = CFCMethod_micro_sym(method); }
