Start to use CFCParcel_get_classes

Replace CFCHierarchy_ordered_classes with CFCParcel_get_classes.


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

Branch: refs/heads/master
Commit: e82ee761678b6c60730a819f6f55b09e0a68c898
Parents: e5b8900
Author: Nick Wellnhofer <[email protected]>
Authored: Mon Feb 27 00:58:43 2017 +0100
Committer: Nick Wellnhofer <[email protected]>
Committed: Thu Mar 2 20:08:03 2017 +0100

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC.xs |   6 ++
 compiler/perl/t/500-hierarchy.t    |   6 +-
 compiler/src/CFCBindCore.c         |  28 ++----
 compiler/src/CFCC.c                |  70 +++++++++------
 compiler/src/CFCCHtml.c            |  83 ++++++++++--------
 compiler/src/CFCClass.c            |   7 --
 compiler/src/CFCClass.h            |   3 -
 compiler/src/CFCGo.c               |  18 ++--
 compiler/src/CFCParcel.c           |   4 +-
 compiler/src/CFCPerl.c             | 146 +++++++++++++++-----------------
 compiler/src/CFCPerlTypeMap.c      |  58 +++++++------
 compiler/src/CFCPython.c           |  31 ++-----
 compiler/src/CFCRuby.c             |   4 +-
 compiler/src/CFCTestHierarchy.c    |  96 ++++++++++++---------
 14 files changed, 287 insertions(+), 273 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.xs 
b/compiler/perl/lib/Clownfish/CFC.xs
index 588e585..d174ecd 100644
--- a/compiler/perl/lib/Clownfish/CFC.xs
+++ b/compiler/perl/lib/Clownfish/CFC.xs
@@ -1193,6 +1193,7 @@ ALIAS:
     prereq_parcels    = 20
     inherited_parcels = 22
     get_xs_module     = 24
+    get_classes       = 26
 PPCODE:
 {
     START_SET_OR_GET_SWITCH
@@ -1251,6 +1252,11 @@ PPCODE:
                 retval = newSVpvn(xs_module, strlen(xs_module));
             }
             break;
+        case 26: {
+                CFCClass **classes = CFCParcel_get_classes(self);
+                retval = S_array_of_cfcbase_to_av((CFCBase**)classes);
+            }
+            break;
     END_SET_OR_GET_SWITCH
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/perl/t/500-hierarchy.t
----------------------------------------------------------------------
diff --git a/compiler/perl/t/500-hierarchy.t b/compiler/perl/t/500-hierarchy.t
index 24abbc1..07feeb9 100644
--- a/compiler/perl/t/500-hierarchy.t
+++ b/compiler/perl/t/500-hierarchy.t
@@ -17,7 +17,7 @@ use strict;
 use warnings;
 use lib 'buildlib';
 
-use Test::More tests => 21;
+use Test::More tests => 22;
 
 use Clownfish::CFC::Model::Hierarchy;
 use Clownfish::CFC::Util qw( a_isa_b );
@@ -70,7 +70,9 @@ my $animal = $files{'Animal'}       or die "No Animal";
 my $dog    = $files{'Animal::Dog'}  or die "No Dog";
 my $util   = $files{'Animal::Util'} or die "No Util";
 
-my $classes = $hierarchy->ordered_classes;
+my $parcel = Clownfish::CFC::Model::Parcel->fetch('Animal');
+ok( $parcel, "Fetch parcel Animal" );
+my $classes = $parcel->get_classes;
 is( scalar @$classes, 4, "all classes" );
 for my $class (@$classes) {
     die "not a Class" unless isa_ok( $class, "Clownfish::CFC::Model::Class" );

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindCore.c b/compiler/src/CFCBindCore.c
index ec0fdf2..35f107b 100644
--- a/compiler/src/CFCBindCore.c
+++ b/compiler/src/CFCBindCore.c
@@ -61,8 +61,8 @@ static void
 S_write_platform_h(CFCBindCore *self);
 
 static void
-S_write_host_data_json(CFCBindCore *self, CFCParcel *parcel,
-                       const char *dest_dir, const char *host_lang);
+S_write_host_data_json(CFCParcel *parcel, const char *dest_dir,
+                       const char *host_lang);
 
 static const CFCMeta CFCBINDCORE_META = {
     "Clownfish::CFC::Binding::Core",
@@ -149,11 +149,9 @@ S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) {
     // classes.
     char *typedefs    = CFCUtil_strdup("");
     char *class_decls = CFCUtil_strdup("");
-    CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
+    CFCClass **ordered = CFCParcel_get_classes(parcel);
     for (int i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        const char *class_prefix = CFCClass_get_prefix(klass);
-        if (strcmp(class_prefix, prefix) != 0) { continue; }
 
         if (!CFCClass_inert(klass)) {
             const char *full_struct = CFCClass_full_struct_sym(klass);
@@ -165,7 +163,6 @@ S_write_parcel_h(CFCBindCore *self, CFCParcel *parcel) {
                                       ";\n", NULL);
         }
     }
-    FREEMEM(ordered);
 
     // Special includes and macros for Clownfish parcel.
     const char *cfish_includes =
@@ -399,12 +396,10 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
     char *includes     = CFCUtil_strdup("");
     char *c_data       = CFCUtil_strdup("");
     CFCBindSpecs *specs = CFCBindSpecs_new();
-    CFCClass **ordered = CFCHierarchy_ordered_classes(hierarchy);
+    CFCClass **ordered = CFCParcel_get_classes(parcel);
 
     for (int i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        const char *class_prefix = CFCClass_get_prefix(klass);
-        if (strcmp(class_prefix, prefix) != 0) { continue; }
 
         const char *include_h = CFCClass_include_h(klass);
         includes = CFCUtil_cat(includes, "#include \"", include_h,
@@ -427,7 +422,6 @@ S_write_parcel_c(CFCBindCore *self, CFCParcel *parcel) {
 
     char *spec_defs      = CFCBindSpecs_defs(specs);
     char *spec_init_func = CFCBindSpecs_init_func_def(specs);
-    FREEMEM(ordered);
 
     char *prereq_bootstrap = CFCUtil_strdup("");
     CFCParcel **prereq_parcels = CFCParcel_prereq_parcels(parcel);
@@ -728,20 +722,20 @@ CFCBindCore_copy_headers(CFCBindCore *self, const char 
*dest_dir) {
 void
 CFCBindCore_write_host_data_json(CFCBindCore *self, const char *dest_dir,
                                  const char *host_lang) {
+    CHY_UNUSED_VAR(self);
     CFCParcel **parcels = CFCParcel_all_parcels();
 
     for (size_t i = 0; parcels[i] != NULL; i++) {
         CFCParcel *parcel = parcels[i];
         if (!CFCParcel_included(parcel) && CFCParcel_is_installed(parcel)) {
-            S_write_host_data_json(self, parcel, dest_dir, host_lang);
+            S_write_host_data_json(parcel, dest_dir, host_lang);
         }
     }
 }
 
 static void
-S_write_host_data_json(CFCBindCore *self, CFCParcel *parcel,
-                       const char *dest_dir, const char *host_lang) {
-    const char *prefix      = CFCParcel_get_prefix(parcel);
+S_write_host_data_json(CFCParcel *parcel, const char *dest_dir,
+                       const char *host_lang) {
     const char *parcel_name = CFCParcel_get_name(parcel);
     CFCVersion *version     = CFCParcel_get_version(parcel);
     const char *vstring     = CFCVersion_get_vstring(version);
@@ -756,13 +750,10 @@ S_write_host_data_json(CFCBindCore *self, CFCParcel 
*parcel,
     }
 
     char *classes_json = CFCUtil_strdup("");
-    CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
+    CFCClass **ordered = CFCParcel_get_classes(parcel);
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        const char *class_prefix = CFCClass_get_prefix(klass);
-        if (strcmp(class_prefix, prefix) != 0) { continue; }
-
         CFCBindClass *class_binding = CFCBindClass_new(klass);
 
         char *class_json = CFCBindClass_host_data_json(class_binding);
@@ -774,7 +765,6 @@ S_write_host_data_json(CFCBindCore *self, CFCParcel *parcel,
         FREEMEM(class_json);
         CFCBase_decref((CFCBase*)class_binding);
     }
-    FREEMEM(ordered);
 
     if (classes_json[0] != '\0') {
         const char *pattern =

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCC.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCC.c b/compiler/src/CFCC.c
index 10fec57..42d2856 100644
--- a/compiler/src/CFCC.c
+++ b/compiler/src/CFCC.c
@@ -28,6 +28,7 @@
 #include "CFCDocument.h"
 #include "CFCHierarchy.h"
 #include "CFCMethod.h"
+#include "CFCParcel.h"
 #include "CFCUri.h"
 #include "CFCUtil.h"
 
@@ -87,25 +88,37 @@ CFCC_write_html_docs(CFCC *self) {
 void
 CFCC_write_man_pages(CFCC *self) {
     CFCHierarchy  *hierarchy = self->hierarchy;
-    CFCClass     **ordered   = CFCHierarchy_ordered_classes(hierarchy);
+    CFCParcel    **parcels   = CFCParcel_all_parcels();
 
     size_t num_classes = 0;
-    for (size_t i = 0; ordered[i] != NULL; i++) {
-        CFCClass *klass = ordered[i];
-        if (!CFCClass_needs_documentation(klass)) { continue; }
-        ++num_classes;
+    for (size_t i = 0; parcels[i] != NULL; i++) {
+        CFCParcel *parcel = parcels[i];
+        if (!CFCParcel_is_installed(parcel)) { continue; }
+
+        CFCClass **ordered = CFCParcel_get_classes(parcel);
+        for (size_t j = 0; ordered[j] != NULL; j++) {
+            CFCClass *klass = ordered[j];
+            if (!CFCClass_public(klass)) { continue; }
+            ++num_classes;
+        }
     }
     char **man_pages = (char**)CALLOCATE(num_classes, sizeof(char*));
 
     // Generate man pages, but don't write.  That way, if there's an error
     // while generating the pages, we leak memory but don't clutter up the 
file 
     // system.
-    for (size_t i = 0, j = 0; ordered[i] != NULL; i++) {
-        CFCClass *klass = ordered[i];
-        if (!CFCClass_needs_documentation(klass)) { continue; }
+    for (size_t i = 0; parcels[i] != NULL; i++) {
+        CFCParcel *parcel = parcels[i];
+        if (!CFCParcel_is_installed(parcel)) { continue; }
+
+        CFCClass **ordered = CFCParcel_get_classes(parcel);
+        for (size_t j = 0, k = 0; ordered[j] != NULL; j++) {
+            CFCClass *klass = ordered[j];
+            if (!CFCClass_public(klass)) { continue; }
 
-        char *man_page = CFCCMan_create_man_page(klass);
-        man_pages[j++] = man_page;
+            char *man_page = CFCCMan_create_man_page(klass);
+            man_pages[k++] = man_page;
+        }
     }
 
     const char *dest = CFCHierarchy_get_dest(hierarchy);
@@ -113,26 +126,31 @@ CFCC_write_man_pages(CFCC *self) {
         = CFCUtil_sprintf("%s" CHY_DIR_SEP "man" CHY_DIR_SEP "man3", dest);
 
     // Write out any man pages that have changed.
-    for (size_t i = 0, j = 0; ordered[i] != NULL; i++) {
-        CFCClass *klass = ordered[i];
-        if (!CFCClass_needs_documentation(klass)) { continue; }
-
-        char *raw_man_page = man_pages[j++];
-        char *man_page = CFCUtil_sprintf("%s%s%s", self->man_header,
-                                         raw_man_page, self->man_footer);
-
-        const char *full_struct_sym = CFCClass_full_struct_sym(klass);
-        char *filename = CFCUtil_sprintf("%s" CHY_DIR_SEP "%s.3", man3_path,
-                                         full_struct_sym);
-        CFCUtil_write_if_changed(filename, man_page, strlen(man_page));
-        FREEMEM(filename);
-        FREEMEM(man_page);
-        FREEMEM(raw_man_page);
+    for (size_t i = 0; parcels[i] != NULL; i++) {
+        CFCParcel *parcel = parcels[i];
+        if (!CFCParcel_is_installed(parcel)) { continue; }
+
+        CFCClass **ordered = CFCParcel_get_classes(parcel);
+        for (size_t j = 0, k = 0; ordered[j] != NULL; j++) {
+            CFCClass *klass = ordered[j];
+            if (!CFCClass_public(klass)) { continue; }
+
+            char *raw_man_page = man_pages[k++];
+            char *man_page = CFCUtil_sprintf("%s%s%s", self->man_header,
+                                             raw_man_page, self->man_footer);
+
+            const char *full_struct_sym = CFCClass_full_struct_sym(klass);
+            char *filename = CFCUtil_sprintf("%s" CHY_DIR_SEP "%s.3", 
man3_path,
+                                             full_struct_sym);
+            CFCUtil_write_if_changed(filename, man_page, strlen(man_page));
+            FREEMEM(filename);
+            FREEMEM(man_page);
+            FREEMEM(raw_man_page);
+        }
     }
 
     FREEMEM(man3_path);
     FREEMEM(man_pages);
-    FREEMEM(ordered);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCCHtml.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCHtml.c b/compiler/src/CFCCHtml.c
index 6d5f908..016c15b 100644
--- a/compiler/src/CFCCHtml.c
+++ b/compiler/src/CFCCHtml.c
@@ -117,7 +117,7 @@ static const char footer_template[] =
     "{autogen_footer}";
 
 char*
-S_create_index_doc(CFCCHtml *self, CFCClass **classes, CFCDocument **docs);
+S_create_index_doc(CFCCHtml *self, CFCDocument **docs);
 
 char*
 S_create_standalone_doc(CFCCHtml *self, CFCDocument *doc);
@@ -227,14 +227,21 @@ CFCCHtml_destroy(CFCCHtml *self) {
 
 void
 CFCCHtml_write_html_docs(CFCCHtml *self) {
-    CFCHierarchy  *hierarchy    = self->hierarchy;
-    CFCClass     **ordered      = CFCHierarchy_ordered_classes(hierarchy);
+    CFCParcel    **parcels      = CFCParcel_all_parcels();
     CFCDocument  **doc_registry = CFCDocument_get_registry();
     const char    *doc_path     = self->doc_path;
 
     size_t num_classes = 0;
-    for (size_t i = 0; ordered[i] != NULL; i++) {
-        ++num_classes;
+    for (size_t i = 0; parcels[i] != NULL; i++) {
+        CFCParcel *parcel = parcels[i];
+        if (!CFCParcel_is_installed(parcel)) { continue; }
+
+        CFCClass **ordered = CFCParcel_get_classes(parcel);
+        for (size_t j = 0; ordered[j] != NULL; j++) {
+            CFCClass *klass = ordered[j];
+            if (!CFCClass_public(klass)) { continue; }
+            ++num_classes;
+        }
     }
 
     size_t num_md_docs = 0;
@@ -247,7 +254,6 @@ CFCCHtml_write_html_docs(CFCCHtml *self) {
     CFCDocument **md_docs = (CFCDocument**)MALLOCATE(bytes);
     memcpy(md_docs, doc_registry, bytes);
 
-    qsort(ordered, num_classes, sizeof(*ordered), S_compare_class_name);
     qsort(md_docs, num_md_docs, sizeof(*md_docs), S_compare_doc_path);
 
     size_t   max_docs  = 1 + num_classes + num_md_docs;
@@ -259,24 +265,30 @@ CFCCHtml_write_html_docs(CFCCHtml *self) {
     // while generating the pages, we leak memory but don't clutter up the file
     // system.
 
-    char *index_doc = S_create_index_doc(self, ordered, md_docs);
+    char *index_doc = S_create_index_doc(self, md_docs);
     if (index_doc != NULL) {
         filenames[num_docs] = CFCUtil_strdup(self->index_filename);
         html_docs[num_docs] = index_doc;
         num_docs++;
     }
 
-    for (size_t i = 0; ordered[i] != NULL; i++) {
-        CFCClass *klass = ordered[i];
-        if (!CFCClass_needs_documentation(klass)) { continue; }
+    for (size_t i = 0; parcels[i] != NULL; i++) {
+        CFCParcel *parcel = parcels[i];
+        if (!CFCParcel_is_installed(parcel)) { continue; }
 
-        const char *class_name = CFCClass_get_name(klass);
-        char *path = CFCUtil_global_replace(class_name, "::", CHY_DIR_SEP);
-        filenames[num_docs] = CFCUtil_sprintf("%s.html", path);
-        html_docs[num_docs] = CFCCHtml_create_html_doc(self, klass);
-        ++num_docs;
+        CFCClass **ordered = CFCParcel_get_classes(parcel);
+        for (size_t j = 0; ordered[j] != NULL; j++) {
+            CFCClass *klass = ordered[j];
+            if (!CFCClass_public(klass)) { continue; }
 
-        FREEMEM(path);
+            const char *class_name = CFCClass_get_name(klass);
+            char *path = CFCUtil_global_replace(class_name, "::", CHY_DIR_SEP);
+            filenames[num_docs] = CFCUtil_sprintf("%s.html", path);
+            html_docs[num_docs] = CFCCHtml_create_html_doc(self, klass);
+            ++num_docs;
+
+            FREEMEM(path);
+        }
     }
 
     for (size_t i = 0; md_docs[i] != NULL; i++) {
@@ -303,11 +315,10 @@ CFCCHtml_write_html_docs(CFCCHtml *self) {
     FREEMEM(html_docs);
     FREEMEM(filenames);
     FREEMEM(md_docs);
-    FREEMEM(ordered);
 }
 
 char*
-S_create_index_doc(CFCCHtml *self, CFCClass **classes, CFCDocument **docs) {
+S_create_index_doc(CFCCHtml *self, CFCDocument **docs) {
     CFCParcel **parcels = CFCParcel_all_parcels();
 
     // Compile standalone document list.
@@ -347,22 +358,24 @@ S_create_index_doc(CFCCHtml *self, CFCClass **classes, 
CFCDocument **docs) {
 
     for (size_t i = 0; parcels[i]; i++) {
         CFCParcel *parcel = parcels[i];
-        if (CFCParcel_included(parcel) || !CFCParcel_is_installed(parcel)) {
-            continue;
-        }
-
-        const char *prefix      = CFCParcel_get_prefix(parcel);
-        const char *parcel_name = CFCParcel_get_name(parcel);
+        if (!CFCParcel_is_installed(parcel)) { continue; }
 
         char *class_list = CFCUtil_strdup("");
+        CFCClass **classes = CFCParcel_get_classes(parcel);
 
-        for (size_t i = 0; classes[i] != NULL; i++) {
-            CFCClass *klass = classes[i];
-            if (strcmp(CFCClass_get_prefix(klass), prefix) != 0
-                || !CFCClass_public(klass)
-            ) {
-                continue;
-            }
+        // Copy class array.
+        size_t num_classes = 0;
+        while (classes[num_classes]) { num_classes += 1; }
+        size_t alloc_size = (num_classes + 1) * sizeof(CFCClass*);
+        CFCClass **sorted = (CFCClass**)MALLOCATE(alloc_size);
+        memcpy(sorted, classes, alloc_size);
+
+        // Sort by class name.
+        qsort(sorted, num_classes, sizeof(*sorted), S_compare_class_name);
+
+        for (size_t i = 0; sorted[i] != NULL; i++) {
+            CFCClass *klass = sorted[i];
+            if (!CFCClass_public(klass)) { continue; }
 
             const char *class_name = CFCClass_get_name(klass);
             char *url = S_class_to_url(klass, NULL, 0);
@@ -373,6 +386,8 @@ S_create_index_doc(CFCCHtml *self, CFCClass **classes, 
CFCDocument **docs) {
         }
 
         if (class_list[0] != '\0') {
+            const char *parcel_name = CFCParcel_get_name(parcel);
+
             const char *pattern =
                 "<h2>Classes in parcel %s</h2>\n"
                 "<ul>\n"
@@ -382,7 +397,6 @@ S_create_index_doc(CFCCHtml *self, CFCClass **classes, 
CFCDocument **docs) {
             class_lists = CFCUtil_cat(class_lists, html, NULL);
             FREEMEM(html);
 
-            const char *parcel_name = CFCParcel_get_name(parcel);
             const char *sep = parcel_names[0] == '\0' ? "" : ", ";
             parcel_names = CFCUtil_cat(parcel_names, sep, parcel_name, NULL);
 
@@ -390,6 +404,7 @@ S_create_index_doc(CFCCHtml *self, CFCClass **classes, 
CFCDocument **docs) {
             filename = CFCUtil_cat(filename, parcel_prefix, NULL);
         }
 
+        FREEMEM(sorted);
         FREEMEM(class_list);
     }
 
@@ -493,11 +508,9 @@ char*
 CFCCHtml_create_html_body(CFCCHtml *self, CFCClass *klass) {
     if (self->index_filename == NULL) {
         // Create index filename by creating index doc.
-        CFCClass    **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
         CFCDocument **docs    = CFCDocument_get_registry();
-        char *index_doc = S_create_index_doc(self, ordered, docs);
+        char *index_doc = S_create_index_doc(self, docs);
         FREEMEM(index_doc);
-        FREEMEM(ordered);
 
         if (self->index_filename == NULL) {
             CFCUtil_die("Empty hierarchy");

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.c b/compiler/src/CFCClass.c
index 501cf7a..685582e 100644
--- a/compiler/src/CFCClass.c
+++ b/compiler/src/CFCClass.c
@@ -864,13 +864,6 @@ CFCClass_abstract(CFCClass *self) {
 }
 
 int
-CFCClass_needs_documentation(CFCClass *self) {
-    return CFCClass_public(self)
-           && !CFCClass_included(self)
-           && CFCParcel_is_installed(self->parcel);
-}
-
-int
 CFCClass_in_parcel(CFCClass *self, struct CFCParcel *parcel) {
     return CFCClass_get_parcel(self) == parcel;
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.h b/compiler/src/CFCClass.h
index 223306d..fe8b40b 100644
--- a/compiler/src/CFCClass.h
+++ b/compiler/src/CFCClass.h
@@ -256,9 +256,6 @@ int
 CFCClass_abstract(CFCClass *self);
 
 int
-CFCClass_needs_documentation(CFCClass *self);
-
-int
 CFCClass_in_parcel(CFCClass *self, struct CFCParcel *parcel);
 
 int

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCGo.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCGo.c b/compiler/src/CFCGo.c
index 56c43bf..9502384 100644
--- a/compiler/src/CFCGo.c
+++ b/compiler/src/CFCGo.c
@@ -143,8 +143,8 @@ S_write_hostdefs(CFCGo *self) {
 
 // Pound-includes for generated headers.
 static char*
-S_gen_h_includes(CFCGo *self) {
-    CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
+S_gen_h_includes(CFCParcel *parcel) {
+    CFCClass **ordered = CFCParcel_get_classes(parcel);
     char *h_includes = CFCUtil_strdup("");
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
@@ -152,20 +152,14 @@ S_gen_h_includes(CFCGo *self) {
         h_includes = CFCUtil_cat(h_includes, "#include \"", include_h,
                                    "\"\n", NULL);
     }
-    FREEMEM(ordered);
     return h_includes;
 }
 
 static void
-S_register_classes(CFCGo *self, CFCParcel *parcel) {
-    CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
+S_register_classes(CFCParcel *parcel) {
+    CFCClass **ordered = CFCParcel_get_classes(parcel);
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        if (CFCClass_included(klass)
-            || CFCClass_get_parcel(klass) != parcel
-           ) {
-            continue;
-        }
         const char *class_name = CFCClass_get_name(klass);
         if (!CFCGoClass_singleton(class_name)) {
             CFCGoClass *binding = CFCGoClass_new(parcel, class_name);
@@ -365,9 +359,9 @@ S_write_cfbind_go(CFCGo *self, CFCParcel *parcel, const 
char *dest,
 
 void
 CFCGo_write_bindings(CFCGo *self, CFCParcel *parcel, const char *dest) {
-    char *h_includes = S_gen_h_includes(self);
+    char *h_includes = S_gen_h_includes(parcel);
 
-    S_register_classes(self, parcel);
+    S_register_classes(parcel);
     S_write_hostdefs(self);
     S_write_cfbind_go(self, parcel, dest, h_includes);
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.c b/compiler/src/CFCParcel.c
index 96d5de8..46ce377 100644
--- a/compiler/src/CFCParcel.c
+++ b/compiler/src/CFCParcel.c
@@ -297,7 +297,9 @@ S_new_from_json(const char *json, CFCFileSpec *file_spec) {
     }
     CFCParcel *self = CFCParcel_new(name, nickname, version, major_version,
                                     file_spec);
-    self->is_installed = installed;
+    if (!file_spec || !CFCFileSpec_included(file_spec)) {
+        self->is_installed = installed;
+    }
     if (prereqs) {
         S_set_prereqs(self, prereqs, path);
     }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCPerl.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerl.c b/compiler/src/CFCPerl.c
index e9ef8bd..f43bc47 100644
--- a/compiler/src/CFCPerl.c
+++ b/compiler/src/CFCPerl.c
@@ -288,7 +288,7 @@ S_write_host_h(CFCPerl *self, CFCParcel *parcel) {
 
 static void
 S_write_host_c(CFCPerl *self, CFCParcel *parcel) {
-    CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
+    CFCClass **ordered = CFCParcel_get_classes(parcel);
     const char  *prefix      = CFCParcel_get_prefix(parcel);
     const char  *privacy_sym = CFCParcel_get_privacy_sym(parcel);
     char        *includes    = CFCUtil_strdup("");
@@ -298,8 +298,6 @@ S_write_host_c(CFCPerl *self, CFCParcel *parcel) {
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
         if (CFCClass_inert(klass)) { continue; }
-        const char *class_prefix = CFCClass_get_prefix(klass);
-        if (strcmp(class_prefix, prefix) != 0) { continue; }
 
         const char *class_name = CFCClass_get_name(klass);
 
@@ -462,7 +460,6 @@ S_write_host_c(CFCPerl *self, CFCParcel *parcel) {
     FREEMEM(alias_adds);
     FREEMEM(cb_defs);
     FREEMEM(includes);
-    FREEMEM(ordered);
 }
 
 void
@@ -529,7 +526,6 @@ CFCPerl_write_bindings(CFCPerl *self, const char 
*boot_class,
     CFCUTIL_NULL_CHECK(boot_class);
     CFCUTIL_NULL_CHECK(parcels);
 
-    CFCClass     **ordered  = CFCHierarchy_ordered_classes(self->hierarchy);
     CFCPerlClass **registry = CFCPerlClass_registry();
     char *privacy_syms    = CFCUtil_strdup("");
     char *includes        = CFCUtil_strdup("");
@@ -559,86 +555,81 @@ CFCPerl_write_bindings(CFCPerl *self, const char 
*boot_class,
                                NULL);
         bootstrap_calls = CFCUtil_cat(bootstrap_calls, "    ", prefix,
                                       "bootstrap_perl();\n", NULL);
-    }
-
-    for (size_t i = 0; ordered[i] != NULL; i++) {
-        CFCClass *klass = ordered[i];
-
-        CFCParcel *parcel = CFCClass_get_parcel(klass);
-        int found = false;
-        for (size_t j = 0; parcels[j]; j++) {
-            if (parcel == parcels[j]) {
-                found = true;
-                break;
-            }
-        }
-        if (!found) { continue; }
 
-        // Pound-includes for generated headers.
-        const char *include_h = CFCClass_include_h(klass);
-        includes = CFCUtil_cat(includes, "#include \"", include_h, "\"\n",
-                               NULL);
+        CFCClass **ordered  = CFCParcel_get_classes(parcel);
+        for (size_t j = 0; ordered[j] != NULL; j++) {
+            CFCClass *klass = ordered[j];
 
-        if (CFCClass_inert(klass)) { continue; }
-        int num_xsubs = 0;
-
-        // Constructors.
-        CFCPerlConstructor **constructors
-            = CFCPerlClass_constructor_bindings(klass);
-        for (size_t j = 0; constructors[j] != NULL; j++) {
-            CFCPerlSub *xsub = (CFCPerlSub*)constructors[j];
-
-            // Add the XSUB function definition.
-            char *xsub_def
-                = CFCPerlConstructor_xsub_def(constructors[j], klass);
-            generated_xs = CFCUtil_cat(generated_xs, xsub_def, "\n",
-                                       NULL);
-            FREEMEM(xsub_def);
-
-            // Add XSUB initialization at boot.
-            xsub_specs = S_add_xsub_spec(xsub_specs, xsub);
-            num_xsubs += 1;
-
-            CFCBase_decref((CFCBase*)constructors[j]);
-        }
-        FREEMEM(constructors);
+            // Pound-includes for generated headers.
+            const char *include_h = CFCClass_include_h(klass);
+            includes = CFCUtil_cat(includes, "#include \"", include_h, "\"\n",
+                                   NULL);
 
-        // Methods.
-        CFCPerlMethod **methods = CFCPerlClass_method_bindings(klass);
-        for (size_t j = 0; methods[j] != NULL; j++) {
-            CFCPerlSub *xsub = (CFCPerlSub*)methods[j];
+            if (CFCClass_inert(klass)) { continue; }
+            int num_xsubs = 0;
 
-            // Add the XSUB function definition.
-            char *xsub_def = CFCPerlMethod_xsub_def(methods[j], klass);
-            generated_xs = CFCUtil_cat(generated_xs, xsub_def, "\n",
-                                       NULL);
-            FREEMEM(xsub_def);
+            // Constructors.
+            CFCPerlConstructor **constructors
+                = CFCPerlClass_constructor_bindings(klass);
+            for (size_t k = 0; constructors[k] != NULL; k++) {
+                CFCPerlSub *xsub = (CFCPerlSub*)constructors[k];
 
-            // Add XSUB initialization at boot.
-            xsub_specs = S_add_xsub_spec(xsub_specs, xsub);
-            num_xsubs += 1;
+                // Add the XSUB function definition.
+                char *xsub_def
+                    = CFCPerlConstructor_xsub_def(constructors[k], klass);
+                generated_xs = CFCUtil_cat(generated_xs, xsub_def, "\n",
+                                           NULL);
+                FREEMEM(xsub_def);
 
-            CFCBase_decref((CFCBase*)methods[j]);
-        }
-        FREEMEM(methods);
+                // Add XSUB initialization at boot.
+                xsub_specs = S_add_xsub_spec(xsub_specs, xsub);
+                num_xsubs += 1;
 
-        // Append XSBind_ClassSpec entry.
-        const char *class_name = CFCClass_get_name(klass);
-        CFCClass *parent = CFCClass_get_parent(klass);
-        char *parent_name;
-        if (parent) {
-            parent_name = CFCUtil_sprintf("\"%s\"", CFCClass_get_name(parent));
-        }
-        else {
-            parent_name = CFCUtil_strdup("NULL");
+                CFCBase_decref((CFCBase*)constructors[k]);
+            }
+            FREEMEM(constructors);
+
+            // Methods.
+            CFCPerlMethod **methods = CFCPerlClass_method_bindings(klass);
+            for (size_t k = 0; methods[k] != NULL; k++) {
+                CFCPerlSub *xsub = (CFCPerlSub*)methods[k];
+
+                // Add the XSUB function definition.
+                char *xsub_def = CFCPerlMethod_xsub_def(methods[k], klass);
+                if (xsub_def) {
+                    generated_xs = CFCUtil_cat(generated_xs, xsub_def, "\n",
+                                               NULL);
+                    FREEMEM(xsub_def);
+                }
+
+                // Add XSUB initialization at boot.
+                xsub_specs = S_add_xsub_spec(xsub_specs, xsub);
+                num_xsubs += 1;
+
+                CFCBase_decref((CFCBase*)methods[k]);
+            }
+            FREEMEM(methods);
+
+            // Append XSBind_ClassSpec entry.
+            const char *class_name = CFCClass_get_name(klass);
+            CFCClass *parent = CFCClass_get_parent(klass);
+            char *parent_name;
+            if (parent) {
+                parent_name = CFCUtil_sprintf("\"%s\"",
+                                              CFCClass_get_name(parent));
+            }
+            else {
+                parent_name = CFCUtil_strdup("NULL");
+            }
+            char *class_spec
+                = CFCUtil_sprintf("{ \"%s\", %s, %d }", class_name,
+                                  parent_name, num_xsubs);
+            const char *sep = class_specs[0] == '\0' ? "" : ",\n";
+            class_specs = CFCUtil_cat(class_specs, sep, "        ", class_spec,
+                                      NULL);
+            FREEMEM(class_spec);
+            FREEMEM(parent_name);
         }
-        char *class_spec = CFCUtil_sprintf("{ \"%s\", %s, %d }", class_name,
-                                           parent_name, num_xsubs);
-        const char *sep = class_specs[0] == '\0' ? "" : ",\n";
-        class_specs = CFCUtil_cat(class_specs, sep, "        ", class_spec,
-                                  NULL);
-        FREEMEM(class_spec);
-        FREEMEM(parent_name);
     }
 
     // Hand-rolled XS.
@@ -719,7 +710,6 @@ CFCPerl_write_bindings(CFCPerl *self, const char 
*boot_class,
     FREEMEM(generated_xs);
     FREEMEM(includes);
     FREEMEM(privacy_syms);
-    FREEMEM(ordered);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCPerlTypeMap.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlTypeMap.c b/compiler/src/CFCPerlTypeMap.c
index bc35ad9..022aa7f 100644
--- a/compiler/src/CFCPerlTypeMap.c
+++ b/compiler/src/CFCPerlTypeMap.c
@@ -21,6 +21,7 @@
 #include "CFCHierarchy.h"
 #include "CFCClass.h"
 #include "CFCType.h"
+#include "CFCParcel.h"
 
 #ifndef true
     #define true 1
@@ -247,35 +248,43 @@ static const char typemap_output[] =
 
 void
 CFCPerlTypeMap_write_xs_typemap(CFCHierarchy *hierarchy) {
-    CFCClass **classes = CFCHierarchy_ordered_classes(hierarchy);
+    (void)hierarchy;
+    CFCParcel **parcels = CFCParcel_all_parcels();
     char *start  = CFCUtil_strdup("");
     char *input  = CFCUtil_strdup("");
     char *output = CFCUtil_strdup("");
-    for (int i = 0; classes[i] != NULL; i++) {
-        CFCClass *klass = classes[i];
-        const char *full_struct_sym = CFCClass_full_struct_sym(klass);
-        const char *class_var       = CFCClass_full_class_var(klass);
 
-        start = CFCUtil_cat(start, full_struct_sym, "*\t", class_var, "_\n",
-                            NULL);
-        const char *allocation;
-        if (strcmp(full_struct_sym, "cfish_String") == 0) {
-            // Share buffers rather than copy between Perl scalars and
-            // Clownfish string types.
-            allocation = "CFISH_ALLOCA_OBJ(CFISH_STRING)";
-        }
-        else {
-            allocation = "NULL";
-        }
-        input = CFCUtil_cat(input, class_var, "_\n"
-                            "    $var = (", full_struct_sym,
-                            "*)XSBind_perl_to_cfish_noinc(aTHX_ $arg, ",
-                            class_var, ", ", allocation, ");\n\n", NULL);
+    for (size_t i = 0; parcels[i]; i++) {
+        CFCClass **classes = CFCParcel_get_classes(parcels[i]);
+
+        for (int j = 0; classes[j] != NULL; j++) {
+            CFCClass *klass = classes[j];
+            if (CFCClass_inert(klass)) { continue; }
 
-        output = CFCUtil_cat(output, class_var, "_\n"
-                             "    $arg = 
(SV*)CFISH_Obj_To_Host((cfish_Obj*)$var, NULL);\n"
-                             "    CFISH_DECREF($var);\n"
-                             "\n", NULL);
+            const char *full_struct_sym = CFCClass_full_struct_sym(klass);
+            const char *class_var       = CFCClass_full_class_var(klass);
+
+            start = CFCUtil_cat(start, full_struct_sym, "*\t", class_var, 
"_\n",
+                                NULL);
+            const char *allocation;
+            if (strcmp(full_struct_sym, "cfish_String") == 0) {
+                // Share buffers rather than copy between Perl scalars and
+                // Clownfish string types.
+                allocation = "CFISH_ALLOCA_OBJ(CFISH_STRING)";
+            }
+            else {
+                allocation = "NULL";
+            }
+            input = CFCUtil_cat(input, class_var, "_\n"
+                                "    $var = (", full_struct_sym,
+                                "*)XSBind_perl_to_cfish_noinc(aTHX_ $arg, ",
+                                class_var, ", ", allocation, ");\n\n", NULL);
+
+            output = CFCUtil_cat(output, class_var, "_\n"
+                                 "    $arg = 
(SV*)CFISH_Obj_To_Host((cfish_Obj*)$var, NULL);\n"
+                                 "    CFISH_DECREF($var);\n"
+                                 "\n", NULL);
+        }
     }
 
     char *content = CFCUtil_strdup("");
@@ -288,6 +297,5 @@ CFCPerlTypeMap_write_xs_typemap(CFCHierarchy *hierarchy) {
     FREEMEM(output);
     FREEMEM(input);
     FREEMEM(start);
-    FREEMEM(classes);
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCPython.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPython.c b/compiler/src/CFCPython.c
index cbc301c..66f2ea0 100644
--- a/compiler/src/CFCPython.c
+++ b/compiler/src/CFCPython.c
@@ -118,10 +118,7 @@ S_gen_callbacks(CFCPython *self, CFCParcel *parcel, 
CFCClass **ordered) {
     // Generate implementation files containing callback definitions.
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        if (CFCClass_included(klass)
-            || CFCClass_inert(klass)
-            //|| CFCClass_get_parcel(klass) != parcel
-           ) {
+        if (CFCClass_inert(klass)) {
             continue;
         }
 
@@ -373,7 +370,7 @@ S_gen_type_linkups(CFCPython *self, CFCParcel *parcel, 
CFCClass **ordered) {
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        if (CFCClass_included(klass) || CFCClass_inert(klass)) {
+        if (CFCClass_inert(klass)) {
             continue;
         }
         const char *class_var = CFCClass_full_class_var(klass);
@@ -422,9 +419,6 @@ S_gen_class_bindings(CFCPython *self, CFCParcel *parcel,
     char *bindings = CFCUtil_strdup("");
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        if (CFCClass_included(klass)) {
-            continue;
-        }
         const char *class_name = CFCClass_get_name(klass);
         CFCPyClass *class_binding = CFCPyClass_singleton(class_name);
         if (!class_binding) {
@@ -457,8 +451,7 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, 
const char *dest) {
         helper_mod_name[i] = CFCUtil_tolower(helper_mod_name[i]);
     }
 
-    CFCClass  **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
-    CFCParcel **parcels = CFCParcel_all_parcels();
+    CFCClass  **ordered = CFCParcel_get_classes(parcel);
     char *privacy_syms       = CFCUtil_strdup("");
     char *callbacks          = S_gen_callbacks(self, parcel, ordered);
     char *type_linkups       = S_gen_type_linkups(self, parcel, ordered);
@@ -469,20 +462,15 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, 
const char *dest) {
     char *module_adds        = CFCUtil_strdup("");
 
     // Add privacy defines and parcel bootstrapping calls.
-    for (size_t i = 0; parcels[i]; ++i) {
-        if (!CFCParcel_included(parcels[i])) {
-            const char *privacy_sym = CFCParcel_get_privacy_sym(parcels[i]);
-            privacy_syms = CFCUtil_cat(privacy_syms, "#define ", privacy_sym,
-                                       "\n", NULL);
-            const char *prefix = CFCParcel_get_prefix(parcels[i]);
-            parcel_boots = CFCUtil_cat(parcel_boots, "    ", prefix,
-                                       "bootstrap_parcel();\n", NULL);
-        }
-    }
+    const char *privacy_sym = CFCParcel_get_privacy_sym(parcel);
+    privacy_syms = CFCUtil_cat(privacy_syms, "#define ", privacy_sym,
+                               "\n", NULL);
+    const char *prefix = CFCParcel_get_prefix(parcel);
+    parcel_boots = CFCUtil_cat(parcel_boots, "    ", prefix,
+                               "bootstrap_parcel();\n", NULL);
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        if (CFCClass_included(klass)) { continue; }
         const char *struct_sym = CFCClass_get_struct_sym(klass);
 
         const char *include_h  = CFCClass_include_h(klass);
@@ -569,7 +557,6 @@ S_write_module_file(CFCPython *self, CFCParcel *parcel, 
const char *dest) {
     FREEMEM(type_linkups);
     FREEMEM(callbacks);
     FREEMEM(privacy_syms);
-    FREEMEM(ordered);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCRuby.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCRuby.c b/compiler/src/CFCRuby.c
index bf25b68..0e44a8b 100644
--- a/compiler/src/CFCRuby.c
+++ b/compiler/src/CFCRuby.c
@@ -171,13 +171,12 @@ S_write_boot_h(CFCRuby *self) {
 
 static void
 S_write_boot_c(CFCRuby *self) {
-    CFCClass **ordered   = CFCHierarchy_ordered_classes(self->hierarchy);
+    CFCClass **ordered   = CFCParcel_get_classes(self->parcel);
     char *pound_includes = CFCUtil_strdup("");
     const char *prefix   = CFCParcel_get_prefix(self->parcel);
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        if (CFCClass_included(klass)) { continue; }
 
         const char *include_h  = CFCClass_include_h(klass);
         pound_includes = CFCUtil_cat(pound_includes, "#include \"",
@@ -219,7 +218,6 @@ S_write_boot_c(CFCRuby *self) {
 
     FREEMEM(content);
     FREEMEM(pound_includes);
-    FREEMEM(ordered);
 }
 
 void

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e82ee761/compiler/src/CFCTestHierarchy.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestHierarchy.c b/compiler/src/CFCTestHierarchy.c
index 1b1a568..77a1ab8 100644
--- a/compiler/src/CFCTestHierarchy.c
+++ b/compiler/src/CFCTestHierarchy.c
@@ -55,7 +55,7 @@ S_run_clash_tests(CFCTest *test);
 
 const CFCTestBatch CFCTEST_BATCH_HIERARCHY = {
     "Clownfish::CFC::Model::Hierarchy",
-    41,
+    42,
     S_run_tests
 };
 
@@ -115,13 +115,18 @@ S_run_basic_tests(CFCTest *test) {
     OK(test, files[3] == NULL, "recursed and found all three files");
 
     {
-        CFCClass **ordered_classes = CFCHierarchy_ordered_classes(hierarchy);
-        OK(test, ordered_classes[0] != NULL, "ordered_classes[0]");
-        OK(test, ordered_classes[1] != NULL, "ordered_classes[1]");
-        OK(test, ordered_classes[2] != NULL, "ordered_classes[2]");
-        OK(test, ordered_classes[3] != NULL, "ordered_classes[3]");
-        OK(test, ordered_classes[4] == NULL, "all classes");
-        FREEMEM(ordered_classes);
+        CFCParcel *parcel = CFCParcel_fetch("Animal");
+        OK(test, parcel != NULL, "Fetch parcel Animal");
+        CFCClass **classes = CFCParcel_get_classes(parcel);
+        STR_EQ(test, CFCClass_get_name(classes[0]), "Animal::Util",
+               "classes[0]");
+        STR_EQ(test, CFCClass_get_name(classes[1]), "Clownfish::Obj",
+               "classes[1]");
+        STR_EQ(test, CFCClass_get_name(classes[2]), "Animal",
+               "classes[2]");
+        STR_EQ(test, CFCClass_get_name(classes[3]), "Animal::Dog",
+               "classes[3]");
+        OK(test, classes[4] == NULL, "all classes");
     }
 
     // Generate fake C files, with times set to two seconds ago.
@@ -180,28 +185,30 @@ S_run_include_tests(CFCTest *test) {
 
         CFCHierarchy_build(hierarchy);
 
-        CFCClass **classes    = CFCHierarchy_ordered_classes(hierarchy);
-        CFCClass  *rottweiler = NULL;;
+        CFCParcel *parcel;
+        CFCClass **classes;
+
+        parcel = CFCParcel_fetch("AnimalExtension");
+        OK(test, parcel != NULL, "Fetch parcel AnimalExtension");
+        classes = CFCParcel_get_classes(parcel);
+        STR_EQ(test, CFCClass_get_name(classes[0]), "Animal::Rottweiler",
+               "classes[0]");
+        OK(test, !CFCClass_included(classes[0]), "not included");
+        OK(test, classes[1] == NULL, "classes[1]");
+        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(classes[0])),
+               "Animal::Dog", "parent from different parcel");
+
+        parcel = CFCParcel_fetch("Animal");
+        OK(test, parcel != NULL, "Fetch parcel Animal");
+        classes = CFCParcel_get_classes(parcel);
+        int all_included = 1;
         int num_classes;
-        int num_source_classes = 0;
-        for (num_classes = 0; classes[num_classes]; ++num_classes) {
-            CFCClass *klass = classes[num_classes];
-            int expect_included = 1;
-            const char *class_name = CFCClass_get_name(klass);
-            if (strcmp(class_name, "Animal::Rottweiler") == 0) {
-                rottweiler      = klass;
-                expect_included = 0;
-                ++num_source_classes;
-            }
-            INT_EQ(test, CFCClass_included(klass), expect_included,
-                   "included");
+        for (num_classes = 0; classes[num_classes]; num_classes++) {
+            if (!CFCClass_included(classes[num_classes])) { all_included = 0; }
         }
-        INT_EQ(test, num_classes, 5, "class count");
-        INT_EQ(test, num_source_classes, 1, "source class count");
-        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(rottweiler)),
-               "Animal::Dog", "parent of included class");
+        INT_EQ(test, num_classes, 4, "4 classes in parcel Animal");
+        OK(test, all_included, "All classes included");
 
-        FREEMEM(classes);
         CFCBase_decref((CFCBase*)hierarchy);
         CFCClass_clear_registry();
         CFCParcel_reap_singletons();
@@ -214,23 +221,32 @@ S_run_include_tests(CFCTest *test) {
 
         CFCHierarchy_build(hierarchy);
 
-        CFCClass **classes    = CFCHierarchy_ordered_classes(hierarchy);
-        CFCClass  *rottweiler = NULL;;
+        CFCParcel *parcel;
+        CFCClass **classes;
+
+        parcel = CFCParcel_fetch("AnimalExtension");
+        OK(test, parcel != NULL, "Fetch parcel AnimalExtension");
+        classes = CFCParcel_get_classes(parcel);
+        STR_EQ(test, CFCClass_get_name(classes[0]), "Animal::Rottweiler",
+               "classes[0]");
+        OK(test, !CFCClass_included(classes[0]), "not included");
+        OK(test, classes[1] == NULL, "classes[1]");
+        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(classes[0])),
+               "Animal::Dog", "parent from different parcel");
+
+        parcel = CFCParcel_fetch("Animal");
+        OK(test, parcel != NULL, "Fetch parcel Animal");
+        classes = CFCParcel_get_classes(parcel);
+        int all_not_included = 1;
         int num_classes;
-        for (num_classes = 0; classes[num_classes]; ++num_classes) {
-            CFCClass *klass = classes[num_classes];
-            const char *class_name = CFCClass_get_name(klass);
-            if (strcmp(class_name, "Animal::Rottweiler") == 0) {
-                rottweiler = klass;
+        for (num_classes = 0; classes[num_classes]; num_classes++) {
+            if (CFCClass_included(classes[num_classes])) {
+                all_not_included = 0;
             }
-            OK(test, !CFCClass_included(klass), "not included");
         }
-        INT_EQ(test, num_classes, 5, "class count");
-        OK(test, rottweiler != NULL, "found rottweiler");
-        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(rottweiler)),
-               "Animal::Dog", "parent of class from second source");
+        INT_EQ(test, num_classes, 4, "4 classes in parcel Animal");
+        OK(test, all_not_included, "All classes not included");
 
-        FREEMEM(classes);
         CFCBase_decref((CFCBase*)hierarchy);
         CFCClass_clear_registry();
         CFCParcel_reap_singletons();

Reply via email to