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);
         }

Reply via email to