Keep array of fresh member variables in CFCClass

Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/e7d70dd7
Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/e7d70dd7
Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/e7d70dd7

Branch: refs/heads/markdown_v2
Commit: e7d70dd766539b19255c23e56c80e60f4018be14
Parents: 17c9ce3
Author: Nick Wellnhofer <[email protected]>
Authored: Fri Dec 12 18:52:14 2014 +0100
Committer: Nick Wellnhofer <[email protected]>
Committed: Wed Dec 24 14:56:52 2014 +0100

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC.xs |   1 -
 compiler/src/CFCClass.c            | 103 ++++++++++++++++----------------
 compiler/src/CFCTestClass.c        |  10 ++--
 compiler/src/CFCTestFile.c         |   2 +-
 4 files changed, 58 insertions(+), 58 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e7d70dd7/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.xs 
b/compiler/perl/lib/Clownfish/CFC.xs
index 65442a3..a27e193 100644
--- a/compiler/perl/lib/Clownfish/CFC.xs
+++ b/compiler/perl/lib/Clownfish/CFC.xs
@@ -401,7 +401,6 @@ PPCODE:
         case 46: {
                 CFCVariable **fresh = CFCClass_fresh_member_vars(self);
                 retval = S_array_of_cfcbase_to_av((CFCBase**)fresh);
-                FREEMEM(fresh);
                 break;
             }
         case 48: {

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e7d70dd7/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.c b/compiler/src/CFCClass.c
index ff20715..71108f5 100644
--- a/compiler/src/CFCClass.c
+++ b/compiler/src/CFCClass.c
@@ -57,9 +57,11 @@ struct CFCClass {
     CFCFunction **functions;
     size_t num_functions;
     CFCMethod **fresh_methods;
-    size_t num_fresh;
+    size_t num_fresh_meths;
     CFCMethod **methods;
     size_t num_methods;
+    CFCVariable **fresh_vars;
+    size_t num_fresh_vars;
     CFCVariable **member_vars;
     size_t num_member_vars;
     CFCVariable **inert_vars;
@@ -135,9 +137,11 @@ CFCClass_do_create(CFCClass *self, struct CFCParcel 
*parcel,
     self->functions       = (CFCFunction**)CALLOCATE(1, sizeof(CFCFunction*));
     self->num_functions   = 0;
     self->fresh_methods   = (CFCMethod**)CALLOCATE(1, sizeof(CFCMethod*));
-    self->num_fresh       = 0;
+    self->num_fresh_meths = 0;
     self->methods         = (CFCMethod**)CALLOCATE(1, sizeof(CFCMethod*));
     self->num_methods     = 0;
+    self->fresh_vars      = (CFCVariable**)CALLOCATE(1, sizeof(CFCVariable*));
+    self->num_fresh_vars  = 0;
     self->member_vars     = (CFCVariable**)CALLOCATE(1, sizeof(CFCVariable*));
     self->num_member_vars = 0;
     self->inert_vars      = (CFCVariable**)CALLOCATE(1, sizeof(CFCVariable*));
@@ -231,6 +235,7 @@ CFCClass_destroy(CFCClass *self) {
     S_free_cfcbase_array((CFCBase**)self->functions);
     S_free_cfcbase_array((CFCBase**)self->fresh_methods);
     S_free_cfcbase_array((CFCBase**)self->methods);
+    S_free_cfcbase_array((CFCBase**)self->fresh_vars);
     S_free_cfcbase_array((CFCBase**)self->member_vars);
     S_free_cfcbase_array((CFCBase**)self->inert_vars);
     FREEMEM(self->parent_class_name);
@@ -406,12 +411,12 @@ CFCClass_add_method(CFCClass *self, CFCMethod *method) {
     if (self->is_inert) {
         CFCUtil_die("Can't add_method to an inert class");
     }
-    self->num_fresh++;
-    size_t size = (self->num_fresh + 1) * sizeof(CFCMethod*);
+    self->num_fresh_meths++;
+    size_t size = (self->num_fresh_meths + 1) * sizeof(CFCMethod*);
     self->fresh_methods = (CFCMethod**)REALLOCATE(self->fresh_methods, size);
-    self->fresh_methods[self->num_fresh - 1]
+    self->fresh_methods[self->num_fresh_meths - 1]
         = (CFCMethod*)CFCBase_incref((CFCBase*)method);
-    self->fresh_methods[self->num_fresh] = NULL;
+    self->fresh_methods[self->num_fresh_meths] = NULL;
 }
 
 void
@@ -420,12 +425,12 @@ CFCClass_add_member_var(CFCClass *self, CFCVariable *var) 
{
     if (self->tree_grown) {
         CFCUtil_die("Can't call add_member_var after grow_tree");
     }
-    self->num_member_vars++;
-    size_t size = (self->num_member_vars + 1) * sizeof(CFCVariable*);
-    self->member_vars = (CFCVariable**)REALLOCATE(self->member_vars, size);
-    self->member_vars[self->num_member_vars - 1]
+    self->num_fresh_vars++;
+    size_t size = (self->num_fresh_vars + 1) * sizeof(CFCVariable*);
+    self->fresh_vars = (CFCVariable**)REALLOCATE(self->fresh_vars, size);
+    self->fresh_vars[self->num_fresh_vars - 1]
         = (CFCVariable*)CFCBase_incref((CFCBase*)var);
-    self->member_vars[self->num_member_vars] = NULL;
+    self->fresh_vars[self->num_fresh_vars] = NULL;
 }
 
 void
@@ -488,8 +493,8 @@ CFCClass_resolve_types(CFCClass *self) {
     for (size_t i = 0; self->fresh_methods[i] != NULL; i++) {
         CFCMethod_resolve_types(self->fresh_methods[i]);
     }
-    for (size_t i = 0; self->member_vars[i] != NULL; i++) {
-        CFCVariable_resolve_type(self->member_vars[i]);
+    for (size_t i = 0; self->fresh_vars[i] != NULL; i++) {
+        CFCVariable_resolve_type(self->fresh_vars[i]);
     }
     for (size_t i = 0; self->inert_vars[i] != NULL; i++) {
         CFCVariable_resolve_type(self->inert_vars[i]);
@@ -501,16 +506,16 @@ static void
 S_bequeath_member_vars(CFCClass *self) {
     for (size_t i = 0; self->children[i] != NULL; i++) {
         CFCClass *child = self->children[i];
-        size_t num_vars = self->num_member_vars + child->num_member_vars;
+        size_t num_vars = self->num_member_vars + child->num_fresh_vars;
         size_t size = (num_vars + 1) * sizeof(CFCVariable*);
         child->member_vars
             = (CFCVariable**)REALLOCATE(child->member_vars, size);
-        memmove(child->member_vars + self->num_member_vars,
-                child->member_vars,
-                child->num_member_vars * sizeof(CFCVariable*));
         memcpy(child->member_vars, self->member_vars,
                self->num_member_vars * sizeof(CFCVariable*));
-        for (size_t j = 0; self->member_vars[j] != NULL; j++) {
+        memcpy(child->member_vars + self->num_member_vars,
+               child->fresh_vars,
+               child->num_fresh_vars * sizeof(CFCVariable*));
+        for (size_t j = 0; child->member_vars[j] != NULL; j++) {
             CFCBase_incref((CFCBase*)child->member_vars[j]);
         }
         child->num_member_vars = num_vars;
@@ -526,7 +531,7 @@ S_bequeath_methods(CFCClass *self) {
 
         // Create array of methods, preserving exact order so vtables match up.
         size_t num_methods = 0;
-        size_t max_methods = self->num_methods + child->num_fresh;
+        size_t max_methods = self->num_methods + child->num_fresh_meths;
         CFCMethod **methods = (CFCMethod**)MALLOCATE(
                                   (max_methods + 1) * sizeof(CFCMethod*));
 
@@ -546,7 +551,7 @@ S_bequeath_methods(CFCClass *self) {
 
         // Append novel child methods to array.  Child methods which were just
         // marked via CFCMethod_override() a moment ago are skipped.
-        for (size_t i = 0; i < child->num_fresh; i++) {
+        for (size_t i = 0; i < child->num_fresh_meths; i++) {
             CFCMethod *method = child->fresh_methods[i];
             if (CFCMethod_novel(method)) {
                 methods[num_methods++] = method;
@@ -601,25 +606,36 @@ S_family_tree_size(CFCClass *self) {
     return count;
 }
 
+static CFCBase**
+S_copy_cfcbase_array(CFCBase **array, size_t num_elems) {
+    CFCBase **copy = (CFCBase**)MALLOCATE((num_elems + 1) * sizeof(CFCBase*));
+    for (size_t i = 0; i < num_elems; i++) {
+        copy[i] = CFCBase_incref(array[i]);
+    }
+    copy[num_elems] = NULL;
+    return copy;
+}
+
 void
 CFCClass_grow_tree(CFCClass *self) {
     if (self->tree_grown) {
         CFCUtil_die("Can't call grow_tree more than once");
     }
     S_establish_ancestry(self);
+
+    // Copy fresh variabless for root class.
+    self->member_vars
+        = (CFCVariable**)S_copy_cfcbase_array((CFCBase**)self->fresh_vars,
+                                              self->num_fresh_vars);
+    self->num_member_vars = self->num_fresh_vars;
+
     S_bequeath_member_vars(self);
 
     // Copy fresh methods for root class.
-    size_t num_fresh = self->num_fresh;
-    CFCMethod **methods
-        = (CFCMethod**)MALLOCATE((num_fresh + 1) * sizeof(CFCMethod*));
-    for (size_t i = 0; i < num_fresh; i++) {
-        methods[i] = self->fresh_methods[i];
-        CFCBase_incref((CFCBase*)methods[i]);
-    }
-    methods[num_fresh] = NULL;
-    self->methods     = methods;
-    self->num_methods = num_fresh;
+    self->methods
+        = (CFCMethod**)S_copy_cfcbase_array((CFCBase**)self->fresh_methods,
+                                            self->num_fresh_meths);
+    self->num_methods = self->num_fresh_meths;
 
     S_bequeath_methods(self);
 
@@ -646,25 +662,6 @@ CFCClass_tree_to_ladder(CFCClass *self) {
     return ladder;
 }
 
-static CFCSymbol**
-S_fresh_syms(CFCClass *self, CFCSymbol **syms) {
-    const char *class_name = CFCClass_get_class_name(self);
-    size_t count = 0;
-    while (syms[count] != NULL) { count++; }
-    size_t amount = (count + 1) * sizeof(CFCSymbol*);
-    CFCSymbol **fresh = (CFCSymbol**)MALLOCATE(amount);
-    size_t num_fresh = 0;
-    for (size_t i = 0; i < count; i++) {
-        CFCSymbol *sym = syms[i];
-        const char *sym_class_name = CFCSymbol_get_class_name(sym);
-        if (strcmp(sym_class_name, class_name) == 0) {
-            fresh[num_fresh++] = sym;
-        }
-    }
-    fresh[num_fresh] = NULL;
-    return fresh;
-}
-
 CFCMethod**
 CFCClass_fresh_methods(CFCClass *self) {
     return self->fresh_methods;
@@ -672,7 +669,7 @@ CFCClass_fresh_methods(CFCClass *self) {
 
 CFCVariable**
 CFCClass_fresh_member_vars(CFCClass *self) {
-    return (CFCVariable**)S_fresh_syms(self, (CFCSymbol**)self->member_vars);
+    return self->fresh_vars;
 }
 
 CFCClass**
@@ -703,11 +700,17 @@ CFCClass_num_methods(CFCClass *self) {
 
 CFCVariable**
 CFCClass_member_vars(CFCClass *self) {
+    if (!self->tree_grown) {
+        CFCUtil_die("Can't call 'member_vars' before 'grow_tree'");
+    }
     return self->member_vars;
 }
 
 size_t
 CFCClass_num_member_vars(CFCClass *self) {
+    if (!self->tree_grown) {
+        CFCUtil_die("Can't call 'num_member_vars' before 'grow_tree'");
+    }
     return self->num_member_vars;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e7d70dd7/compiler/src/CFCTestClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestClass.c b/compiler/src/CFCTestClass.c
index 1bdc5e4..762180a 100644
--- a/compiler/src/CFCTestClass.c
+++ b/compiler/src/CFCTestClass.c
@@ -168,8 +168,6 @@ S_run_tests(CFCTest *test) {
         CFCVariable **fresh_member_vars = CFCClass_fresh_member_vars(foo);
         OK(test, fresh_member_vars[0] == thing, "fresh_member_vars[0]");
         OK(test, fresh_member_vars[1] == NULL, "fresh_member_vars[1]");
-
-        FREEMEM(fresh_member_vars);
     }
 
     {
@@ -185,8 +183,6 @@ S_run_tests(CFCTest *test) {
 
         CFCVariable **inert_vars = CFCClass_inert_vars(foo_jr);
         OK(test, inert_vars[0] == NULL, "inert_vars[0]");
-
-        FREEMEM(fresh_member_vars);
     }
 
     {
@@ -235,7 +231,8 @@ S_run_tests(CFCTest *test) {
             "    int num;\n"
             "}\n";
         CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
-        CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+        CFCSymbol **member_vars
+            = (CFCSymbol**)CFCClass_fresh_member_vars(klass);
         OK(test, S_has_symbol(member_vars, "num"),
            "parsed member var");
 
@@ -275,7 +272,8 @@ S_run_tests(CFCTest *test) {
         CFCClass *klass = CFCTest_parse_class(test, parser, class_src);
 
         CFCSymbol **inert_vars  = (CFCSymbol**)CFCClass_inert_vars(klass);
-        CFCSymbol **member_vars = (CFCSymbol**)CFCClass_member_vars(klass);
+        CFCSymbol **member_vars
+            = (CFCSymbol**)CFCClass_fresh_member_vars(klass);
         CFCSymbol **functions   = (CFCSymbol**)CFCClass_functions(klass);
         CFCSymbol **methods     = (CFCSymbol**)CFCClass_fresh_methods(klass);
         OK(test, S_has_symbol(inert_vars, "num_dogs"), "parsed inert var");

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e7d70dd7/compiler/src/CFCTestFile.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestFile.c b/compiler/src/CFCTestFile.c
index 4be6cef..921eaf4 100644
--- a/compiler/src/CFCTestFile.c
+++ b/compiler/src/CFCTestFile.c
@@ -95,7 +95,7 @@ S_run_tests(CFCTest *test) {
            classes[0] != NULL && classes[1] != NULL && classes[2] != NULL
            && classes[3] == NULL,
            "classes() filters blocks");
-        CFCVariable **member_vars = CFCClass_member_vars(classes[0]);
+        CFCVariable **member_vars = CFCClass_fresh_member_vars(classes[0]);
         CFCType *foo_type = CFCVariable_get_type(member_vars[0]);
         CFCType_resolve(foo_type);
         STR_EQ(test, CFCType_get_specifier(foo_type), "stuff_Foo",

Reply via email to