Disentangle CFCClass from CFCSymbol

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

Branch: refs/heads/master
Commit: a35d347ac04f51f5ad3cbe768793de6d6d745221
Parents: ad6e089
Author: Nick Wellnhofer <[email protected]>
Authored: Fri Dec 12 14:57:22 2014 +0100
Committer: Nick Wellnhofer <[email protected]>
Committed: Thu May 7 21:19:37 2015 +0200

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC.pm |   6 +-
 compiler/perl/lib/Clownfish/CFC.xs |  29 ++--
 compiler/perl/t/500-hierarchy.t    |   4 +-
 compiler/perl/t/501-include_dir.t  |   8 +-
 compiler/perl/t/600-parser.t       |   2 +-
 compiler/src/CFCBindClass.c        |   4 +-
 compiler/src/CFCC.c                |   3 +-
 compiler/src/CFCCHtml.c            |  24 ++--
 compiler/src/CFCCMan.c             |  14 +-
 compiler/src/CFCClass.c            | 242 ++++++++++++++++++++------------
 compiler/src/CFCClass.h            |  46 ++++--
 compiler/src/CFCGo.c               |   2 +-
 compiler/src/CFCHierarchy.c        |  10 +-
 compiler/src/CFCParseHeader.y      |   6 +-
 compiler/src/CFCPerl.c             |   4 +-
 compiler/src/CFCPerlClass.c        |   4 +-
 compiler/src/CFCPerlConstructor.c  |   2 +-
 compiler/src/CFCPerlPod.c          |  12 +-
 compiler/src/CFCSymbol.c           |  40 +-----
 compiler/src/CFCSymbol.h           |   7 -
 compiler/src/CFCTestClass.c        |  12 +-
 compiler/src/CFCTestDocuComment.c  |   4 +-
 compiler/src/CFCTestHierarchy.c    |  10 +-
 compiler/src/CFCTestParser.c       |   2 +-
 compiler/src/CFCTestSymbol.c       |   2 +-
 compiler/src/CFCTestType.c         |   6 +-
 compiler/src/CFCTestVariable.c     |   2 +-
 compiler/src/CFCType.c             |   3 +-
 compiler/src/CFCUri.c              |   4 +-
 29 files changed, 278 insertions(+), 236 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/perl/lib/Clownfish/CFC.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.pm 
b/compiler/perl/lib/Clownfish/CFC.pm
index 21d41ed..6d9cd28 100644
--- a/compiler/perl/lib/Clownfish/CFC.pm
+++ b/compiler/perl/lib/Clownfish/CFC.pm
@@ -106,7 +106,7 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.4.0' ) }
 
 {
     package Clownfish::CFC::Model::Class;
-    BEGIN { push our @ISA, 'Clownfish::CFC::Model::Symbol' }
+    BEGIN { push our @ISA, 'Clownfish::CFC::Base' }
     use Carp;
     use Config;
     use Clownfish::CFC::Util qw(
@@ -156,8 +156,8 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.4.0' ) }
             = Clownfish::CFC::Model::Parcel->acquire( $args{parcel} );
         return _create(
             @args{
-                qw( parcel exposure class_name nickname name docucomment
-                    file_spec parent_class_name final inert abstract )
+                qw( parcel exposure class_name nickname docucomment
+                    file_spec parent_class_name final inert abstract)
                 }
         );
     }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.xs 
b/compiler/perl/lib/Clownfish/CFC.xs
index 0d0d83c..627e27a 100644
--- a/compiler/perl/lib/Clownfish/CFC.xs
+++ b/compiler/perl/lib/Clownfish/CFC.xs
@@ -155,12 +155,11 @@ PPCODE:
 MODULE = Clownfish::CFC   PACKAGE = Clownfish::CFC::Model::Class
 
 SV*
-_create(parcel, exposure_sv, class_name_sv, class_nickname_sv, name_sv, 
docucomment, file_spec, parent_class_name_sv, is_final, is_inert, is_abstract)
+_create(parcel, exposure_sv, class_name_sv, class_nickname_sv, docucomment, 
file_spec, parent_class_name_sv, is_final, is_inert, is_abstract)
     CFCParcel *parcel;
     SV *exposure_sv;
     SV *class_name_sv;
     SV *class_nickname_sv;
-    SV *name_sv;
     CFCDocuComment *docucomment;
     CFCFileSpec *file_spec;
     SV *parent_class_name_sv;
@@ -174,13 +173,11 @@ CODE:
         SvOK(class_name_sv) ? SvPV_nolen(class_name_sv) : NULL;
     const char *class_nickname =
         SvOK(class_nickname_sv) ? SvPV_nolen(class_nickname_sv) : NULL;
-    const char *name =
-        SvOK(name_sv) ? SvPV_nolen(name_sv) : NULL;
     const char *parent_class_name =
         SvOK(parent_class_name_sv) ? SvPV_nolen(parent_class_name_sv) : NULL;
     CFCClass *self
         = CFCClass_create(parcel, exposure, class_name, class_nickname,
-                          name, docucomment, file_spec, parent_class_name,
+                          docucomment, file_spec, parent_class_name,
                           is_final, is_inert, is_abstract);
     RETVAL = S_cfcbase_to_perlref(self);
     CFCBase_decref((CFCBase*)self);
@@ -279,9 +276,11 @@ void
 _set_or_get(self, ...)
     CFCClass *self;
 ALIAS:
-    get_nickname          = 2
-    set_parent            = 5
-    get_parent            = 6
+    get_exposure          = 2
+    get_name              = 4
+    get_nickname          = 6
+    set_parent            = 7
+    get_parent            = 8
     get_path_part         = 10
     get_parent_class_name = 12
     final                 = 14
@@ -306,11 +305,21 @@ PPCODE:
 {
     START_SET_OR_GET_SWITCH
         case 2: {
+                const char *value = CFCClass_get_exposure(self);
+                retval = newSVpvn(value, strlen(value));
+            }
+            break;
+        case 4: {
+                const char *value = CFCClass_get_name(self);
+                retval = newSVpvn(value, strlen(value));
+            }
+            break;
+        case 6: {
                 const char *value = CFCClass_get_nickname(self);
                 retval = newSVpvn(value, strlen(value));
             }
             break;
-        case 5: {
+        case 7: {
                 CFCClass *parent = NULL;
                 if (SvOK(ST(1))
                     && sv_derived_from(ST(1), "Clownfish::CFC::Model::Class")
@@ -321,7 +330,7 @@ PPCODE:
                 CFCClass_set_parent(self, parent);
                 break;
             }
-        case 6: {
+        case 8: {
                 CFCClass *parent = CFCClass_get_parent(self);
                 retval = S_cfcbase_to_perlref(parent);
                 break;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/perl/t/500-hierarchy.t
----------------------------------------------------------------------
diff --git a/compiler/perl/t/500-hierarchy.t b/compiler/perl/t/500-hierarchy.t
index 6c2a10c..20ced34 100644
--- a/compiler/perl/t/500-hierarchy.t
+++ b/compiler/perl/t/500-hierarchy.t
@@ -61,10 +61,10 @@ for my $file (@files) {
     ok( !$file->get_modified, "start off not modified" );
     my ($class) = grep {
         a_isa_b( $_, "Clownfish::CFC::Model::Class" )
-        && $_->get_class_name ne 'Clownfish::Obj'
+        && $_->get_name ne 'Clownfish::Obj'
     } @{ $file->blocks };
     die "no class" unless $class;
-    $files{ $class->get_class_name } = $file;
+    $files{ $class->get_name } = $file;
 }
 my $animal = $files{'Animal'}       or die "No Animal";
 my $dog    = $files{'Animal::Dog'}  or die "No Dog";

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/perl/t/501-include_dir.t
----------------------------------------------------------------------
diff --git a/compiler/perl/t/501-include_dir.t 
b/compiler/perl/t/501-include_dir.t
index 8f16f4a..13dccfa 100644
--- a/compiler/perl/t/501-include_dir.t
+++ b/compiler/perl/t/501-include_dir.t
@@ -49,9 +49,9 @@ my $dest_dir = catdir(qw( t cfdest ));
 
         my $expect;
 
-        if ($class->get_class_name eq "Animal::Rottweiler") {
+        if ($class->get_name eq "Animal::Rottweiler") {
             $expect = 0;
-            my $parent_name = $class->get_parent->get_class_name;
+            my $parent_name = $class->get_parent->get_name;
             is( $parent_name, "Animal::Dog", "parent of included class" );
         }
         else {
@@ -87,8 +87,8 @@ my $dest_dir = catdir(qw( t cfdest ));
     for my $class (@$classes) {
         die "not a Class" unless isa_ok( $class, 
"Clownfish::CFC::Model::Class" );
 
-        if ($class->get_class_name eq "Animal::Rottweiler") {
-            my $parent_name = $class->get_parent->get_class_name;
+        if ($class->get_name eq "Animal::Rottweiler") {
+            my $parent_name = $class->get_parent->get_name;
             is( $parent_name, "Animal::Dog", "parent of class from second 
source" );
         }
     }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/perl/t/600-parser.t
----------------------------------------------------------------------
diff --git a/compiler/perl/t/600-parser.t b/compiler/perl/t/600-parser.t
index 468c116..19508f9 100644
--- a/compiler/perl/t/600-parser.t
+++ b/compiler/perl/t/600-parser.t
@@ -142,7 +142,7 @@ SKIP: {
         for (qw( foo fooBar Foo_Bar FOOBAR 1Foo 1FOO ));
 }
 
-is( $parser->parse("class $_ { }")->get_class_name, $_, "class_name: $_" )
+is( $parser->parse("class $_ { }")->get_name, $_, "class_name: $_" )
     for (qw( Foo Foo::FooJr Foo::FooJr::FooIII Foo::FooJr::FooIII::Foo4th ));
 
 SKIP: {

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCBindClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindClass.c b/compiler/src/CFCBindClass.c
index a5ccfc2..2f2b563 100644
--- a/compiler/src/CFCBindClass.c
+++ b/compiler/src/CFCBindClass.c
@@ -268,7 +268,7 @@ S_to_c_header_dynamic(CFCBindClass *self) {
 char*
 CFCBindClass_to_c_data(CFCBindClass *self) {
     CFCClass *client = self->client;
-    const char *class_name = CFCClass_get_class_name(client);
+    const char *class_name = CFCClass_get_name(client);
 
     if (CFCClass_inert(client)) {
         return CFCUtil_strdup("");
@@ -475,7 +475,7 @@ CFCBindClass_spec_def(CFCBindClass *self) {
     CFCClass *client = self->client;
 
     CFCClass   *parent       = CFCClass_get_parent(client);
-    const char *class_name   = CFCClass_get_class_name(client);
+    const char *class_name   = CFCClass_get_name(client);
     const char *class_var    = CFCClass_full_class_var(client);
     const char *struct_sym   = CFCClass_full_struct_sym(client);
     const char *ivars_struct = CFCClass_full_ivars_struct(client);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCC.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCC.c b/compiler/src/CFCC.c
index f676ad3..4b5fb0f 100644
--- a/compiler/src/CFCC.c
+++ b/compiler/src/CFCC.c
@@ -216,8 +216,7 @@ CFCC_link_text(CFCUri *uri_obj, CFCClass *klass) {
                     CFCUtil_warn("URI class not found: %s", full_struct_sym);
                 }
                 else {
-                    const char *class_name
-                        = CFCClass_get_class_name(uri_class);
+                    const char *class_name = CFCClass_get_name(uri_class);
                     link_text = CFCUtil_strdup(class_name);
                 }
             }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCCHtml.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCHtml.c b/compiler/src/CFCCHtml.c
index 33ddd6e..571a0ae 100644
--- a/compiler/src/CFCCHtml.c
+++ b/compiler/src/CFCCHtml.c
@@ -242,7 +242,7 @@ CFCCHtml_write_html_docs(CFCCHtml *self) {
 
     for (size_t i = 0; ordered[i] != NULL; i++) {
         CFCClass *klass = ordered[i];
-        if (CFCClass_included(klass) || !CFCSymbol_public((CFCSymbol*)klass)) {
+        if (CFCClass_included(klass) || CFCClass_public(klass)) {
             continue;
         }
 
@@ -285,13 +285,13 @@ CFCCHtml_create_index_doc(CFCCHtml *self, CFCParcel 
*parcel,
     for (size_t i = 0; classes[i] != NULL; i++) {
         CFCClass *klass = classes[i];
         if (strcmp(CFCClass_get_prefix(klass), prefix) != 0
-            || !CFCSymbol_public((CFCSymbol*)klass)
+            || !CFCClass_public(klass)
         ) {
             continue;
         }
 
         const char *struct_sym = CFCClass_full_struct_sym(klass);
-        const char *class_name = CFCClass_get_class_name(klass);
+        const char *class_name = CFCClass_get_name(klass);
         class_list
             = CFCUtil_cat(class_list, "<li><a href=\"", struct_sym, ".html\">",
                           class_name, "</a></li>\n", NULL);
@@ -325,7 +325,7 @@ CFCCHtml_create_index_doc(CFCCHtml *self, CFCParcel *parcel,
 
 char*
 CFCCHtml_create_html_doc(CFCCHtml *self, CFCClass *klass) {
-    const char *class_name     = CFCClass_get_class_name(klass);
+    const char *class_name     = CFCClass_get_name(klass);
     char *title
         = CFCUtil_sprintf("%s " UTF8_NDASH " C API Documentation", class_name);
     char *header = CFCUtil_global_replace(self->header, "{title}", title);
@@ -343,7 +343,7 @@ char*
 CFCCHtml_create_html_body(CFCClass *klass) {
     CFCParcel  *parcel         = CFCClass_get_parcel(klass);
     const char *parcel_name    = CFCParcel_get_name(parcel);
-    const char *class_name     = CFCClass_get_class_name(klass);
+    const char *class_name     = CFCClass_get_name(klass);
     const char *class_nickname = CFCClass_get_nickname(klass);
     const char *class_var      = CFCClass_full_class_var(klass);
     const char *struct_sym     = CFCClass_full_struct_sym(klass);
@@ -418,8 +418,8 @@ CFCCHtml_create_html_body(CFCClass *klass) {
 
 static int
 S_compare_class_name(const void *va, const void *vb) {
-    const char *a = CFCClass_get_class_name(*(CFCClass**)va);
-    const char *b = CFCClass_get_class_name(*(CFCClass**)vb);
+    const char *a = CFCClass_get_name(*(CFCClass**)va);
+    const char *b = CFCClass_get_name(*(CFCClass**)vb);
 
     return strcmp(a, b);
 }
@@ -437,7 +437,7 @@ S_index_filename(CFCParcel *parcel) {
 
 static char*
 S_html_create_name(CFCClass *klass) {
-    const char     *class_name = CFCClass_get_class_name(klass);
+    const char     *class_name = CFCClass_get_name(klass);
     char           *md         = CFCUtil_strdup(class_name);
     CFCDocuComment *docucom    = CFCClass_get_docucomment(klass);
 
@@ -527,7 +527,7 @@ S_html_create_methods(CFCClass *klass) {
          ancestor;
          ancestor = CFCClass_get_parent(ancestor)
     ) {
-        const char *class_name = CFCClass_get_class_name(ancestor);
+        const char *class_name = CFCClass_get_name(ancestor);
         // Exclude methods inherited from Clownfish::Obj
         if (ancestor != klass && strcmp(class_name, "Clownfish::Obj") == 0) {
             break;
@@ -564,7 +564,7 @@ static char*
 S_html_create_fresh_methods(CFCClass *klass, CFCClass *ancestor) {
     CFCMethod  **fresh_methods = CFCClass_fresh_methods(klass);
     const char  *prefix        = CFCClass_get_prefix(klass);
-    const char  *ancestor_name = CFCClass_get_class_name(ancestor);
+    const char  *ancestor_name = CFCClass_get_name(ancestor);
     char        *result        = CFCUtil_strdup("");
 
     for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
@@ -741,11 +741,11 @@ S_html_create_inheritance(CFCClass *klass) {
 
     if (!ancestor) { return result; }
 
-    const char *class_name = CFCClass_get_class_name(klass);
+    const char *class_name = CFCClass_get_name(klass);
     result = CFCUtil_cat(result, "<h2>Inheritance</h2>\n<p>", class_name,
                          NULL);
     while (ancestor) {
-        const char *ancestor_name = CFCClass_get_class_name(ancestor);
+        const char *ancestor_name = CFCClass_get_name(ancestor);
         const char *ancestor_sym  = CFCClass_full_struct_sym(ancestor);
         result = CFCUtil_cat(result, " is a <a href=\"", ancestor_sym,
                              ".html\">", ancestor_name, "</a>", NULL);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCCMan.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCMan.c b/compiler/src/CFCCMan.c
index 7ba5fc6..9ebd086 100644
--- a/compiler/src/CFCCMan.c
+++ b/compiler/src/CFCCMan.c
@@ -76,9 +76,9 @@ S_man_escape(const char *content);
 
 char*
 CFCCMan_create_man_page(CFCClass *klass) {
-    if (!CFCSymbol_public((CFCSymbol*)klass)) { return NULL; }
+    if (!CFCClass_public(klass)) { return NULL; }
 
-    const char *class_name = CFCClass_get_class_name(klass);
+    const char *class_name = CFCClass_get_name(klass);
 
     // Create NAME.
     char *name = S_man_create_name(klass);
@@ -124,7 +124,7 @@ CFCCMan_create_man_page(CFCClass *klass) {
 static char*
 S_man_create_name(CFCClass *klass) {
     char *result = CFCUtil_strdup(".SH NAME\n");
-    result = CFCUtil_cat(result, CFCClass_get_class_name(klass), NULL);
+    result = CFCUtil_cat(result, CFCClass_get_name(klass), NULL);
 
     const char *raw_brief = NULL;
     CFCDocuComment *docucom = CFCClass_get_docucomment(klass);
@@ -201,7 +201,7 @@ S_man_create_methods(CFCClass *klass) {
          ancestor;
          ancestor = CFCClass_get_parent(ancestor)
     ) {
-        const char *class_name = CFCClass_get_class_name(ancestor);
+        const char *class_name = CFCClass_get_name(ancestor);
         // Exclude methods inherited from Clownfish::Obj
         if (ancestor != klass && strcmp(class_name, "Clownfish::Obj") == 0) {
             break;
@@ -235,7 +235,7 @@ S_man_create_methods(CFCClass *klass) {
 static char*
 S_man_create_fresh_methods(CFCClass *klass, CFCClass *ancestor) {
     CFCMethod  **fresh_methods = CFCClass_fresh_methods(klass);
-    const char  *ancestor_name = CFCClass_get_class_name(ancestor);
+    const char  *ancestor_name = CFCClass_get_name(ancestor);
     char        *result        = CFCUtil_strdup("");
 
     for (int meth_num = 0; fresh_methods[meth_num] != NULL; meth_num++) {
@@ -398,10 +398,10 @@ S_man_create_inheritance(CFCClass *klass) {
 
     if (!ancestor) { return result; }
 
-    const char *class_name = CFCClass_get_class_name(klass);
+    const char *class_name = CFCClass_get_name(klass);
     result = CFCUtil_cat(result, ".SH INHERITANCE\n", class_name, NULL);
     while (ancestor) {
-        const char *ancestor_name = CFCClass_get_class_name(ancestor);
+        const char *ancestor_name = CFCClass_get_name(ancestor);
         result = CFCUtil_cat(result, " is a ", ancestor_name, NULL);
         ancestor = CFCClass_get_parent(ancestor);
     }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.c b/compiler/src/CFCClass.c
index eb2ba7c..acbc22c 100644
--- a/compiler/src/CFCClass.c
+++ b/compiler/src/CFCClass.c
@@ -23,9 +23,10 @@
   #define false 0
 #endif
 
-#define CFC_NEED_SYMBOL_STRUCT_DEF
-#include "CFCSymbol.h"
+#define CFC_NEED_BASE_STRUCT_DEF
+#include "CFCBase.h"
 #include "CFCClass.h"
+#include "CFCSymbol.h"
 #include "CFCFunction.h"
 #include "CFCMethod.h"
 #include "CFCParcel.h"
@@ -48,8 +49,10 @@ static void
 S_register(CFCClass *self);
 
 struct CFCClass {
-    CFCSymbol symbol;
+    CFCBase base;
     struct CFCParcel *parcel;
+    char *exposure;
+    char *name;
     char *nickname;
     int tree_grown;
     CFCDocuComment *docucomment;
@@ -106,17 +109,67 @@ static const CFCMeta CFCCLASS_META = {
 
 CFCClass*
 CFCClass_create(struct CFCParcel *parcel, const char *exposure,
-                const char *class_name, const char *nickname,
-                const char *name, CFCDocuComment *docucomment,
-                CFCFileSpec *file_spec, const char *parent_class_name,
-                int is_final, int is_inert, int is_abstract) {
+                const char *name, const char *nickname,
+                CFCDocuComment *docucomment, CFCFileSpec *file_spec,
+                const char *parent_class_name, int is_final, int is_inert,
+                int is_abstract) {
     CFCClass *self = (CFCClass*)CFCBase_allocate(&CFCCLASS_META);
-    return CFCClass_do_create(self, parcel, exposure, class_name, nickname,
-                              name, docucomment, file_spec, parent_class_name,
+    return CFCClass_do_create(self, parcel, exposure, name, nickname,
+                              docucomment, file_spec, parent_class_name,
                               is_final, is_inert, is_abstract);
 }
 
 static int
+S_validate_exposure(const char *exposure) {
+    if (!exposure) { return false; }
+    if (strcmp(exposure, "public")
+        && strcmp(exposure, "parcel")
+        && strcmp(exposure, "private")
+       ) {
+        return false;
+    }
+    return true;
+}
+
+int
+CFCClass_validate_class_name(const char *class_name) {
+    // The last component must contain lowercase letters (for now).
+    const char *last_colon = strrchr(class_name, ':');
+    const char *substring = last_colon ? last_colon + 1 : class_name;
+    for (;;substring++) {
+        if (*substring == 0)          { return false; }
+        else if (*substring == ':')   { return false; }
+        else if (islower(*substring)) { break; }
+    }
+
+    // Must be UpperCamelCase, separated by "::".
+    const char *ptr = class_name;
+    if (!isupper(*ptr)) { return false; }
+    while (*ptr != 0) {
+        if (*ptr == 0) { break; }
+        else if (*ptr == ':') {
+            ptr++;
+            if (*ptr != ':') { return false; }
+            ptr++;
+            if (!isupper(*ptr)) { return false; }
+            ptr++;
+        }
+        else if (!isalnum(*ptr)) { return false; }
+        else { ptr++; }
+    }
+
+    return true;
+}
+
+int
+CFCClass_validate_class_name_component(const char *name) {
+    if (!name || !strlen(name)) { return false; }
+    if (!CFCClass_validate_class_name(name)) { return false; }
+    if (strchr(name, ':') != NULL) { return false; }
+    return true;
+}
+
+static int
 S_validate_nickname(const char *nickname) {
     // Allow all caps.
     const char *ptr;
@@ -129,53 +182,57 @@ S_validate_nickname(const char *nickname) {
     }
 
     // Same as one component of a class name.
-    return CFCSymbol_validate_class_name_component(nickname);
+    return CFCClass_validate_class_name_component(nickname);
 }
 
 CFCClass*
 CFCClass_do_create(CFCClass *self, struct CFCParcel *parcel,
-                   const char *exposure, const char *class_name,
-                   const char *nickname, const char *name,
-                   CFCDocuComment *docucomment, CFCFileSpec *file_spec,
-                   const char *parent_class_name, int is_final, int is_inert,
-                   int is_abstract) {
+                   const char *exposure, const char *name,
+                   const char *nickname, CFCDocuComment *docucomment,
+                   CFCFileSpec *file_spec, const char *parent_class_name,
+                   int is_final, int is_inert, int is_abstract) {
     CFCUTIL_NULL_CHECK(parcel);
-    CFCUTIL_NULL_CHECK(class_name);
-    exposure = exposure  ? exposure  : "parcel";
-    name     = name ? name : "class";
+    CFCUTIL_NULL_CHECK(name);
+    exposure = exposure ? exposure  : "parcel";
 
-    // Derive nickname if necessary, then validate.
-    const char *real_nickname = NULL;
-    if (class_name) {
-        if (nickname) {
-            real_nickname = nickname;
-        }
-        else {
-            const char *last_colon = strrchr(class_name, ':');
-            real_nickname = last_colon ? last_colon + 1 : class_name;
-        }
+    // Validate.
+    if (!S_validate_exposure(exposure)) {
+        CFCBase_decref((CFCBase*)self);
+        CFCUtil_die("Invalid exposure: '%s'", exposure);
     }
-    else if (nickname) {
-        // Sanity check nickname without class_name.
+    if (!CFCClass_validate_class_name(name)) {
         CFCBase_decref((CFCBase*)self);
-        CFCUtil_die("Can't supply nickname without class_name");
+        CFCUtil_die("Invalid name: '%s'", name);
+    }
+
+    const char *last_colon = strrchr(name, ':');
+    const char *struct_sym = last_colon ? last_colon + 1 : name;
+
+    // Derive nickname if necessary, then validate.
+    const char *real_nickname = NULL;
+    if (nickname) {
+        real_nickname = nickname;
     }
     else {
-        real_nickname = NULL;
+        real_nickname = struct_sym;
     }
-    if (real_nickname && !S_validate_nickname(real_nickname)) {
+    if (!S_validate_nickname(real_nickname)) {
         CFCBase_decref((CFCBase*)self);
         CFCUtil_die("Invalid nickname: '%s'", real_nickname);
     }
 
-    CFCSymbol_init((CFCSymbol*)self, exposure, class_name, name);
+    // Default parent class name is "Clownfish::Obj".
     if (!is_inert
         && !parent_class_name
-        && strcmp(class_name, "Clownfish::Obj") != 0
+        && strcmp(name, "Clownfish::Obj") != 0
        ) {
         parent_class_name = "Clownfish::Obj";
     }
+
+    // Assign.
     self->parcel          = (CFCParcel*)CFCBase_incref((CFCBase*)parcel);
+    self->exposure        = CFCUtil_strdup(exposure);
+    self->name            = CFCUtil_strdup(name);
     self->nickname        = CFCUtil_strdup(real_nickname);
     self->tree_grown      = false;
     self->parent          = NULL;
@@ -199,33 +256,30 @@ CFCClass_do_create(CFCClass *self, struct CFCParcel 
*parcel,
     self->file_spec = (CFCFileSpec*)CFCBase_incref((CFCBase*)file_spec);
 
     // Cache several derived symbols.
-    const char *last_colon = strrchr(class_name, ':');
-    self->struct_sym = last_colon
-                       ? CFCUtil_strdup(last_colon + 1)
-                       : CFCUtil_strdup(class_name);
+
     const char *prefix = CFCClass_get_prefix(self);
-    size_t struct_sym_len = strlen(self->struct_sym);
-    self->short_class_var = (char*)MALLOCATE(struct_sym_len + 1);
+    self->struct_sym        = CFCUtil_strdup(struct_sym);
+    self->full_struct_sym   = CFCUtil_sprintf("%s%s", prefix, struct_sym);
+    self->ivars_struct      = CFCUtil_sprintf("%sIVARS", struct_sym);
+    self->full_ivars_struct = CFCUtil_sprintf("%s%s", prefix,
+                                              self->ivars_struct);
+    self->ivars_func        = CFCUtil_sprintf("%s_IVARS", self->nickname);
+    self->full_ivars_func   = CFCUtil_sprintf("%s%s", prefix,
+                                              self->ivars_func);
+    self->full_ivars_offset = CFCUtil_sprintf("%s_OFFSET",
+                                              self->full_ivars_func);
+
+    const char *PREFIX = CFCClass_get_PREFIX(self);
+    size_t struct_sym_len = strlen(struct_sym);
+    char *short_class_var = (char*)MALLOCATE(struct_sym_len + 1);
     size_t i;
     for (i = 0; i < struct_sym_len; i++) {
-        self->short_class_var[i] = toupper(self->struct_sym[i]);
-    }
-    self->short_class_var[struct_sym_len] = '\0';
-    self->full_struct_sym   = CFCUtil_sprintf("%s%s", prefix, 
self->struct_sym);
-    self->ivars_struct      = CFCUtil_sprintf("%sIVARS", self->struct_sym);
-    self->full_ivars_struct = CFCUtil_sprintf("%sIVARS", 
self->full_struct_sym);
-    self->ivars_func        = CFCUtil_sprintf("%s_IVARS",
-                                              CFCClass_get_nickname(self));
-    self->full_ivars_func   = CFCUtil_sprintf("%s%s_IVARS", prefix,
-                                              CFCClass_get_nickname(self));
-    self->full_ivars_offset = CFCUtil_sprintf("%s_OFFSET", 
self->full_ivars_func);
-    size_t full_struct_sym_len = strlen(self->full_struct_sym);
-    self->full_class_var = (char*)MALLOCATE(full_struct_sym_len + 1);
-    for (i = 0; self->full_struct_sym[i] != '\0'; i++) {
-        self->full_class_var[i] = toupper(self->full_struct_sym[i]);
-    }
-    self->full_class_var[i] = '\0';
-    self->privacy_symbol = CFCUtil_sprintf("C_%s", self->full_class_var);
+        short_class_var[i] = toupper(struct_sym[i]);
+    }
+    short_class_var[struct_sym_len] = '\0';
+    self->short_class_var = short_class_var;
+    self->full_class_var  = CFCUtil_sprintf("%s%s", PREFIX, short_class_var);
+    self->privacy_symbol  = CFCUtil_sprintf("C_%s", self->full_class_var);
 
     // Build the relative path to the autogenerated C header file.
     if (file_spec) {
@@ -240,10 +294,11 @@ CFCClass_do_create(CFCClass *self, struct CFCParcel 
*parcel,
     self->is_inert    = !!is_inert;
     self->is_abstract = !!is_abstract;
 
+    // Check for include flag mismatch.
     if (!CFCClass_included(self) && CFCParcel_included(parcel)) {
         CFCUtil_die("Class %s from source dir found in parcel %s from"
                     " include dir",
-                    class_name, CFCParcel_get_name(parcel));
+                    name, CFCParcel_get_name(parcel));
     }
 
     // Skip class if it's from an include dir and the parcel was already
@@ -277,6 +332,8 @@ S_free_cfcbase_array(CFCBase **array) {
 void
 CFCClass_destroy(CFCClass *self) {
     CFCBase_decref((CFCBase*)self->parcel);
+    FREEMEM(self->exposure);
+    FREEMEM(self->name);
     FREEMEM(self->nickname);
     CFCBase_decref((CFCBase*)self->docucomment);
     CFCBase_decref((CFCBase*)self->parent);
@@ -300,7 +357,7 @@ CFCClass_destroy(CFCClass *self) {
     FREEMEM(self->full_class_var);
     FREEMEM(self->privacy_symbol);
     FREEMEM(self->include_h);
-    CFCSymbol_destroy((CFCSymbol*)self);
+    CFCBase_destroy((CFCBase*)self);
 }
 
 static void
@@ -317,31 +374,29 @@ S_register(CFCClass *self) {
         registry_cap = new_cap;
     }
 
-    CFCParcel  *parcel     = CFCClass_get_parcel(self);
-    const char *prefix     = CFCParcel_get_prefix(parcel);
-    const char *class_name = CFCClass_get_class_name(self);
-    const char *nickname   = CFCClass_get_nickname(self);
-    const char *key        = self->full_struct_sym;
+    const char *prefix   = CFCParcel_get_prefix(self->parcel);
+    const char *name     = self->name;
+    const char *nickname = self->nickname;
+    const char *key      = self->full_struct_sym;
 
     for (size_t i = 0; i < registry_size; i++) {
-        CFCClass   *other            = registry[i].klass;
-        CFCParcel  *other_parcel     = CFCClass_get_parcel(other);
-        const char *other_prefix     = CFCParcel_get_prefix(other_parcel);
-        const char *other_class_name = CFCClass_get_class_name(other);
-        const char *other_nickname   = CFCClass_get_nickname(other);
-
-        if (strcmp(class_name, other_class_name) == 0) {
-            CFCUtil_die("Two classes with name %s", class_name);
+        CFCClass   *other          = registry[i].klass;
+        const char *other_prefix   = CFCParcel_get_prefix(other->parcel);
+        const char *other_name     = other->name;
+        const char *other_nickname = other->nickname;
+
+        if (strcmp(name, other_name) == 0) {
+            CFCUtil_die("Two classes with name %s", name);
         }
         if (strcmp(registry[i].key, key) == 0) {
             CFCUtil_die("Class name conflict between %s and %s",
-                        class_name, other_class_name);
+                        name, other_name);
         }
         if (strcmp(prefix, other_prefix) == 0
             && strcmp(nickname, other_nickname) == 0
            ) {
             CFCUtil_die("Class nickname conflict between %s and %s",
-                        class_name, other_class_name);
+                        name, other_name);
         }
     }
 
@@ -410,12 +465,10 @@ CFCClass_add_child(CFCClass *self, CFCClass *child) {
         CFCUtil_die("Can't call add_child after grow_tree");
     }
     if (self->is_inert) {
-        CFCUtil_die("Can't inherit from inert class %s",
-                    CFCClass_get_class_name(self));
+        CFCUtil_die("Can't inherit from inert class %s", self->name);
     }
     if (child->is_inert) {
-        CFCUtil_die("Inert class %s can't inherit",
-                    CFCClass_get_class_name(child));
+        CFCUtil_die("Inert class %s can't inherit", child->name);
     }
     self->num_kids++;
     size_t size = (self->num_kids + 1) * sizeof(CFCClass*);
@@ -430,8 +483,7 @@ CFCClass_add_child(CFCClass *self, CFCClass *child) {
     if (!CFCParcel_has_prereq(child_parcel, parcel)) {
         CFCUtil_die("Class '%s' inherits from '%s', but parcel '%s' is not a"
                     " prerequisite of '%s'",
-                    CFCClass_get_class_name(child),
-                    CFCClass_get_class_name(self),
+                    child->name, self->name,
                     CFCParcel_get_name(parcel),
                     CFCParcel_get_name(child_parcel));
     }
@@ -872,9 +924,9 @@ CFCClass_include_h(CFCClass *self) {
     return self->include_h;
 }
 
-struct CFCDocuComment*
-CFCClass_get_docucomment(CFCClass *self) {
-    return self->docucomment;
+CFCParcel*
+CFCClass_get_parcel(CFCClass *self) {
+    return self->parcel;
 }
 
 const char*
@@ -893,12 +945,22 @@ CFCClass_get_PREFIX(CFCClass *self) {
 }
 
 const char*
-CFCClass_get_class_name(CFCClass *self) {
-    return CFCSymbol_get_class_name((CFCSymbol*)self);
+CFCClass_get_exposure(CFCClass *self) {
+    return self->exposure;
 }
 
-CFCParcel*
-CFCClass_get_parcel(CFCClass *self) {
-    return self->parcel;
+int
+CFCClass_public(CFCClass *self) {
+    return !strcmp(self->exposure, "public");
+}
+
+const char*
+CFCClass_get_name(CFCClass *self) {
+    return self->name;
+}
+
+struct CFCDocuComment*
+CFCClass_get_docucomment(CFCClass *self) {
+    return self->docucomment;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.h b/compiler/src/CFCClass.h
index a002663..68870bf 100644
--- a/compiler/src/CFCClass.h
+++ b/compiler/src/CFCClass.h
@@ -38,16 +38,27 @@ struct CFCMethod;
 struct CFCVariable;
 struct CFCFileSpec;
 
+/** Return true if the string is a valid class name.
+ */
+int
+CFCClass_validate_class_name(const char *class_name);
+
+/** Return true if the supplied string is comprised solely of alphanumeric
+ * characters, begins with an uppercase letter, and contains at least one
+ * lower case letter.
+ */
+int
+CFCClass_validate_class_name_component(const char *name);
+
 /** Create and register a quasi-singleton.  May only be called once for each
  * unique parcel/class_name combination.
  *
  * @param parcel A Clownfish::CFC::Model::Parcel.
- * @param exposure See Clownfish::CFC::Model::Symbol.
- * @param class_name See Clownfish::CFC::Model::Symbol.
- * @param class_nickname The C nickname associated with the supplied class
+ * @param exposure The scope of the class. May be NULL.
+ * @param name The class name.
+ * @param nickname The C nickname associated with the supplied class
  * name.  If not supplied, will be derived if possible from C<class_name> by
  * extracting the last class name component.
- * @param name Defaults to "class".
  * @param docucomment An optional Clownfish::CFC::Model::DocuComment attached
  * to this class.
  * @param file_spec - Clownfish::CFC::Model::FileSpec of the file in which
@@ -61,16 +72,15 @@ struct CFCFileSpec;
  */
 CFCClass*
 CFCClass_create(struct CFCParcel *parcel, const char *exposure,
-                const char *class_name, const char *nickname,
-                const char *name, struct CFCDocuComment *docucomment,
+                const char *name, const char *nickname,
+                struct CFCDocuComment *docucomment,
                 struct CFCFileSpec *file_spec, const char *parent_class_name,
                 int is_final, int is_inert, int is_abstract);
 
 CFCClass*
 CFCClass_do_create(CFCClass *self, struct CFCParcel *parcel,
-                   const char *exposure, const char *class_name,
-                   const char *nickname, const char *name,
-                   struct CFCDocuComment *docucomment,
+                   const char *exposure, const char *name,
+                   const char *nickname, struct CFCDocuComment *docucomment,
                    struct CFCFileSpec *file_spec, const char 
*parent_class_name,
                    int is_final, int is_inert, int is_abstract);
 
@@ -292,8 +302,8 @@ CFCClass_privacy_symbol(CFCClass *self);
 const char*
 CFCClass_include_h(CFCClass *self);
 
-struct CFCDocuComment*
-CFCClass_get_docucomment(CFCClass *self);
+struct CFCParcel*
+CFCClass_get_parcel(CFCClass *self);
 
 const char*
 CFCClass_get_prefix(CFCClass *self);
@@ -305,10 +315,18 @@ const char*
 CFCClass_get_PREFIX(CFCClass *self);
 
 const char*
-CFCClass_get_class_name(CFCClass *self);
+CFCClass_get_exposure(CFCClass *self);
 
-struct CFCParcel*
-CFCClass_get_parcel(CFCClass *self);
+/** Return true if the Class's exposure is "public".
+ */
+int
+CFCClass_public(CFCClass *self);
+
+const char*
+CFCClass_get_name(CFCClass *self);
+
+struct CFCDocuComment*
+CFCClass_get_docucomment(CFCClass *self);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCGo.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCGo.c b/compiler/src/CFCGo.c
index caf476d..e571cc5 100644
--- a/compiler/src/CFCGo.c
+++ b/compiler/src/CFCGo.c
@@ -167,7 +167,7 @@ S_register_classes(CFCGo *self, CFCParcel *parcel) {
            ) {
             continue;
         }
-        const char *class_name = CFCClass_get_class_name(klass);
+        const char *class_name = CFCClass_get_name(klass);
         if (!CFCGoClass_singleton(class_name)) {
             CFCGoClass *binding = CFCGoClass_new(parcel, class_name);
             CFCGoClass_register(binding);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCHierarchy.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCHierarchy.c b/compiler/src/CFCHierarchy.c
index 88cdb30..5dc2145 100644
--- a/compiler/src/CFCHierarchy.c
+++ b/compiler/src/CFCHierarchy.c
@@ -457,7 +457,7 @@ S_connect_classes(CFCHierarchy *self) {
                     CFCUtil_die("Parent class '%s' not defined", parent_name);
                 }
                 const char *maybe_parent_name
-                    = CFCClass_get_class_name(maybe_parent);
+                    = CFCClass_get_name(maybe_parent);
                 if (strcmp(parent_name, maybe_parent_name) == 0) {
                     CFCClass_add_child(maybe_parent, klass);
                     break;
@@ -515,8 +515,8 @@ S_do_propagate_modified(CFCHierarchy *self, CFCClass 
*klass, int modified) {
         CFCClass *kid = children[i];
         if (CFCClass_final(klass)) {
             CFCUtil_die("Attempt to inherit from final class '%s' by '%s'",
-                        CFCClass_get_class_name(klass),
-                        CFCClass_get_class_name(kid));
+                        CFCClass_get_name(klass),
+                        CFCClass_get_name(kid));
         }
         if (S_do_propagate_modified(self, kid, modified)) {
             somebody_is_modified = 1;
@@ -601,10 +601,10 @@ S_add_file(CFCHierarchy *self, CFCFile *file) {
         CFCFile *existing = self->files[i];
         CFCClass **existing_classes = CFCFile_classes(existing);
         for (size_t j = 0; classes[j] != NULL; j++) {
-            const char *new_class_name = CFCClass_get_class_name(classes[j]);
+            const char *new_class_name = CFCClass_get_name(classes[j]);
             for (size_t k = 0; existing_classes[k] != NULL; k++) {
                 const char *existing_class_name
-                    = CFCClass_get_class_name(existing_classes[k]);
+                    = CFCClass_get_name(existing_classes[k]);
                 if (strcmp(new_class_name, existing_class_name) == 0) {
                     CFCUtil_die("Class '%s' already registered",
                                 new_class_name);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCParseHeader.y
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParseHeader.y b/compiler/src/CFCParseHeader.y
index 7fa5304..064199b 100644
--- a/compiler/src/CFCParseHeader.y
+++ b/compiler/src/CFCParseHeader.y
@@ -52,9 +52,9 @@ S_start_class(CFCParser *state, CFCDocuComment *docucomment, 
char *exposure,
     CFCParser_set_class_name(state, class_name);
     CFCParser_set_class_final(state, is_final);
     CFCClass *klass = CFCClass_create(CFCParser_get_parcel(state), exposure,
-                                      class_name, class_nickname, NULL,
-                                      docucomment, file_spec, inheritance,
-                                      is_final, is_inert, is_abstract);
+                                      class_name, class_nickname, docucomment,
+                                      file_spec, inheritance, is_final,
+                                      is_inert, is_abstract);
     CFCBase_decref((CFCBase*)docucomment);
     return klass;
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCPerl.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerl.c b/compiler/src/CFCPerl.c
index e537226..18dee3c 100644
--- a/compiler/src/CFCPerl.c
+++ b/compiler/src/CFCPerl.c
@@ -249,7 +249,7 @@ S_write_boot_c(CFCPerl *self) {
         CFCClass *klass = ordered[i];
         if (CFCClass_included(klass) || CFCClass_inert(klass)) { continue; }
 
-        const char *class_name = CFCClass_get_class_name(klass);
+        const char *class_name = CFCClass_get_name(klass);
 
         // Add aliases for selected KinoSearch classes which allow old indexes
         // to be read.
@@ -279,7 +279,7 @@ S_write_boot_c(CFCPerl *self) {
 
         CFCClass *parent = CFCClass_get_parent(klass);
         if (parent) {
-            const char *parent_class_name = CFCClass_get_class_name(parent);
+            const char *parent_class_name = CFCClass_get_name(parent);
             isa_pushes
                 = CFCUtil_cat(isa_pushes, "    isa = get_av(\"",
                               class_name, "::ISA\", 1);\n", NULL);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCPerlClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlClass.c b/compiler/src/CFCPerlClass.c
index c185249..93bf6ae 100644
--- a/compiler/src/CFCPerlClass.c
+++ b/compiler/src/CFCPerlClass.c
@@ -272,7 +272,7 @@ static const char NEW[] = "new";
 
 CFCPerlConstructor**
 CFCPerlClass_constructor_bindings(CFCClass *klass) {
-    const char    *class_name = CFCClass_get_class_name(klass);
+    const char    *class_name = CFCClass_get_name(klass);
     CFCPerlClass  *perl_class = CFCPerlClass_singleton(class_name);
     CFCFunction  **functions  = CFCClass_functions(klass);
     size_t         num_bound  = 0;
@@ -394,7 +394,7 @@ CFCPerlClass_create_pod(CFCPerlClass *self) {
                                   class_name, NULL);
         CFCClass *ancestor = client;
         while (NULL != (ancestor = CFCClass_get_parent(ancestor))) {
-            const char *ancestor_klass = CFCClass_get_class_name(ancestor);
+            const char *ancestor_klass = CFCClass_get_name(ancestor);
             if (CFCPerlClass_singleton(ancestor_klass)) {
                 inheritance = CFCUtil_cat(inheritance, " isa L<",
                                           ancestor_klass, ">", NULL);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCPerlConstructor.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlConstructor.c 
b/compiler/src/CFCPerlConstructor.c
index cb7ebc8..8004ca4 100644
--- a/compiler/src/CFCPerlConstructor.c
+++ b/compiler/src/CFCPerlConstructor.c
@@ -57,7 +57,7 @@ CFCPerlConstructor_init(CFCPerlConstructor *self, CFCClass 
*klass,
                         const char *alias, const char *initializer) {
     CFCUTIL_NULL_CHECK(alias);
     CFCUTIL_NULL_CHECK(klass);
-    const char *class_name = CFCClass_get_class_name(klass);
+    const char *class_name = CFCClass_get_name(klass);
     initializer = initializer ? initializer : "init";
 
     // Find the implementing function.

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCPerlPod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c
index a192987..5a26ad5 100644
--- a/compiler/src/CFCPerlPod.c
+++ b/compiler/src/CFCPerlPod.c
@@ -162,7 +162,7 @@ CFCPerlPod_get_description(CFCPerlPod *self) {
 
 char*
 CFCPerlPod_methods_pod(CFCPerlPod *self, CFCClass *klass) {
-    const char *class_name = CFCClass_get_class_name(klass);
+    const char *class_name = CFCClass_get_name(klass);
     char *abstract_pod = CFCUtil_strdup("");
     char *methods_pod  = CFCUtil_strdup("");
     for (size_t i = 0; i < self->num_methods; i++) {
@@ -173,7 +173,7 @@ CFCPerlPod_methods_pod(CFCPerlPod *self, CFCClass *klass) {
         }
         if (!method) {
             CFCUtil_die("Can't find method '%s' in class '%s'",
-                        meth_spec.alias, CFCClass_get_class_name(klass));
+                        meth_spec.alias, CFCClass_get_name(klass));
         }
         char *meth_pod;
         if (meth_spec.pod) {
@@ -213,7 +213,7 @@ CFCPerlPod_constructors_pod(CFCPerlPod *self, CFCClass 
*klass) {
     if (!self->num_constructors) {
         return CFCUtil_strdup("");
     }
-    const char *class_name = CFCClass_get_class_name(klass);
+    const char *class_name = CFCClass_get_name(klass);
     char *pod = CFCUtil_strdup("=head1 CONSTRUCTORS\n\n");
     for (size_t i = 0; i < self->num_constructors; i++) {
         NamePod slot = self->constructors[i];
@@ -565,7 +565,7 @@ S_convert_link(CFCClass *klass, cmark_node *link) {
                 CFCUtil_warn("URI class not found: %s", full_struct_sym);
             }
             else if (uri_class != klass) {
-                const char *class_name = CFCClass_get_class_name(uri_class);
+                const char *class_name = CFCClass_get_name(uri_class);
                 new_uri = CFCUtil_strdup(class_name);
             }
 
@@ -588,7 +588,7 @@ S_convert_link(CFCClass *klass, cmark_node *link) {
                 }
                 else {
                     const char *class_name
-                        = CFCClass_get_class_name(uri_class);
+                        = CFCClass_get_name(uri_class);
                     new_text = CFCUtil_strdup(class_name);
                 }
             }
@@ -620,7 +620,7 @@ S_convert_link(CFCClass *klass, cmark_node *link) {
                 CFCUtil_warn("URI class not found: %s", full_struct_sym);
             }
             else if (uri_class != klass) {
-                const char *class_name = CFCClass_get_class_name(uri_class);
+                const char *class_name = CFCClass_get_name(uri_class);
                 new_uri = CFCUtil_strdup(class_name);
             }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCSymbol.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCSymbol.c b/compiler/src/CFCSymbol.c
index 20f06a7..6189c3b 100644
--- a/compiler/src/CFCSymbol.c
+++ b/compiler/src/CFCSymbol.c
@@ -54,44 +54,6 @@ S_validate_exposure(const char *exposure) {
 }
 
 static int
-S_validate_class_name(const char *class_name) {
-    // The last component must contain lowercase letters (for now).
-    const char *last_colon = strrchr(class_name, ':');
-    const char *substring = last_colon ? last_colon + 1 : class_name;
-    for (;;substring++) {
-        if (*substring == 0)          { return false; }
-        else if (*substring == ':')   { return false; }
-        else if (islower(*substring)) { break; }
-    }
-
-    // Must be UpperCamelCase, separated by "::".
-    const char *ptr = class_name;
-    if (!isupper(*ptr)) { return false; }
-    while (*ptr != 0) {
-        if (*ptr == 0) { break; }
-        else if (*ptr == ':') {
-            ptr++;
-            if (*ptr != ':') { return false; }
-            ptr++;
-            if (!isupper(*ptr)) { return false; }
-            ptr++;
-        }
-        else if (!isalnum(*ptr)) { return false; }
-        else { ptr++; }
-    }
-
-    return true;
-}
-
-int
-CFCSymbol_validate_class_name_component(const char *name) {
-    if (!name || !strlen(name)) { return false; }
-    if (!S_validate_class_name(name)) { return false; }
-    if (strchr(name, ':') != NULL) { return false; }
-    return true;
-}
-
-static int
 S_validate_identifier(const char *identifier) {
     const char *ptr = identifier;
     if (!isalpha(*ptr) && *ptr != '_') { return false; }
@@ -109,7 +71,7 @@ CFCSymbol_init(CFCSymbol *self, const char *exposure, const 
char *class_name,
         CFCBase_decref((CFCBase*)self);
         CFCUtil_die("Invalid exposure: '%s'", exposure ? exposure : "[NULL]");
     }
-    if (class_name && !S_validate_class_name(class_name)) {
+    if (class_name && !CFCClass_validate_class_name(class_name)) {
         CFCBase_decref((CFCBase*)self);
         CFCUtil_die("Invalid class_name: '%s'", class_name);
     }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCSymbol.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCSymbol.h b/compiler/src/CFCSymbol.h
index 599138c..397e016 100644
--- a/compiler/src/CFCSymbol.h
+++ b/compiler/src/CFCSymbol.h
@@ -43,13 +43,6 @@ struct CFCSymbol {
 };
 #endif
 
-/** Return true if the supplied string is comprised solely of alphanumeric
- * characters, begins with an uppercase letter, and contains at least one
- * lower case letter.
- */
-int
-CFCSymbol_validate_class_name_component(const char *name);
-
 /**
  * @param exposure The scope in which the symbol is exposed.  Must be
  * 'public', 'parcel', 'private', or 'local'.

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCTestClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestClass.c b/compiler/src/CFCTestClass.c
index 66d1cbc..9c41d66 100644
--- a/compiler/src/CFCTestClass.c
+++ b/compiler/src/CFCTestClass.c
@@ -84,8 +84,8 @@ S_run_tests(CFCTest *test) {
     }
 
     CFCClass *foo
-        = CFCClass_create(neato, NULL, "Foo", NULL, NULL, NULL, NULL, NULL,
-                          0, 0, 0);
+        = CFCClass_create(neato, NULL, "Foo", NULL, NULL, NULL, NULL, false,
+                          false, false);
     CFCClass_add_function(foo, tread_water);
     CFCClass_add_member_var(foo, thing);
     CFCClass_add_inert_var(foo, widget);
@@ -96,8 +96,8 @@ S_run_tests(CFCTest *test) {
     }
 
     CFCClass *foo_jr
-        = CFCClass_create(neato, NULL, "Foo::FooJr", NULL, NULL, NULL, NULL,
-                          "Foo", 0, 0, 0);
+        = CFCClass_create(neato, NULL, "Foo::FooJr", NULL, NULL, NULL, "Foo",
+                          false, false, false);
     STR_EQ(test, CFCClass_get_struct_sym(foo_jr), "FooJr",
            "get_struct_sym");
     STR_EQ(test, CFCClass_full_struct_sym(foo_jr), "neato_FooJr",
@@ -106,8 +106,8 @@ S_run_tests(CFCTest *test) {
            "derive class nickname from class name");
 
     CFCClass *final_foo
-        = CFCClass_create(neato, NULL, "Foo::FooJr::FinalFoo", NULL, NULL, 
NULL,
-                          file_spec, "Foo::FooJr", 1, 0, 0);
+        = CFCClass_create(neato, NULL, "Foo::FooJr::FinalFoo", NULL, NULL,
+                          file_spec, "Foo::FooJr", true, false, false);
     OK(test, CFCClass_final(final_foo), "final");
     STR_EQ(test, CFCClass_include_h(final_foo), "Foo/FooJr.h",
            "include_h uses path_part");

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCTestDocuComment.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestDocuComment.c 
b/compiler/src/CFCTestDocuComment.c
index 4d7296d..be970b4 100644
--- a/compiler/src/CFCTestDocuComment.c
+++ b/compiler/src/CFCTestDocuComment.c
@@ -141,8 +141,8 @@ S_test_generator(CFCTest *test) {
         " */\n"
     );
     CFCClass *klass
-        = CFCClass_create(parcel, "public", "Neato::Object", NULL, NULL,
-                          docu, NULL, NULL, 0, 0, 0);
+        = CFCClass_create(parcel, "public", "Neato::Object", NULL, docu, NULL,
+                          NULL, 0, 0, 0);
 
     char *man_page = CFCCMan_create_man_page(klass);
     const char *expected_man =

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCTestHierarchy.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestHierarchy.c b/compiler/src/CFCTestHierarchy.c
index 7e0de67..fa005aa 100644
--- a/compiler/src/CFCTestHierarchy.c
+++ b/compiler/src/CFCTestHierarchy.c
@@ -94,7 +94,7 @@ S_run_basic_tests(CFCTest *test) {
             const char *cfc_class_name = CFCBase_get_cfc_class(block);
             if (strcmp(cfc_class_name, "Clownfish::CFC::Model::Class") == 0) {
                 CFCClass *klass = (CFCClass*)block;
-                const char *class_name = CFCClass_get_class_name(klass);
+                const char *class_name = CFCClass_get_name(klass);
                 if (strcmp(class_name, "Animal") == 0) {
                     animal = file;
                 }
@@ -180,7 +180,7 @@ S_run_include_tests(CFCTest *test) {
         for (num_classes = 0; classes[num_classes]; ++num_classes) {
             CFCClass *klass = classes[num_classes];
             int expect_included = 1;
-            const char *class_name = CFCClass_get_class_name(klass);
+            const char *class_name = CFCClass_get_name(klass);
             if (strcmp(class_name, "Animal::Rottweiler") == 0) {
                 rottweiler      = klass;
                 expect_included = 0;
@@ -191,7 +191,7 @@ S_run_include_tests(CFCTest *test) {
         }
         INT_EQ(test, num_classes, 5, "class count");
         INT_EQ(test, num_source_classes, 1, "source class count");
-        STR_EQ(test, CFCClass_get_class_name(CFCClass_get_parent(rottweiler)),
+        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(rottweiler)),
                "Animal::Dog", "parent of included class");
 
         FREEMEM(classes);
@@ -212,7 +212,7 @@ S_run_include_tests(CFCTest *test) {
         int num_classes;
         for (num_classes = 0; classes[num_classes]; ++num_classes) {
             CFCClass *klass = classes[num_classes];
-            const char *class_name = CFCClass_get_class_name(klass);
+            const char *class_name = CFCClass_get_name(klass);
             if (strcmp(class_name, "Animal::Rottweiler") == 0) {
                 rottweiler = klass;
             }
@@ -220,7 +220,7 @@ S_run_include_tests(CFCTest *test) {
         }
         INT_EQ(test, num_classes, 5, "class count");
         OK(test, rottweiler != NULL, "found rottweiler");
-        STR_EQ(test, CFCClass_get_class_name(CFCClass_get_parent(rottweiler)),
+        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(rottweiler)),
                "Animal::Dog", "parent of class from second source");
 
         FREEMEM(classes);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCTestParser.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestParser.c b/compiler/src/CFCTestParser.c
index 879cff6..057d5d9 100644
--- a/compiler/src/CFCTestParser.c
+++ b/compiler/src/CFCTestParser.c
@@ -284,7 +284,7 @@ S_run_tests(CFCTest *test) {
             char *class_string = CFCUtil_sprintf("class %s { }", class_name);
             CFCClass *klass
                 = CFCTest_parse_class(test, parser, class_string);
-            STR_EQ(test, CFCClass_get_class_name(klass), class_name,
+            STR_EQ(test, CFCClass_get_name(klass), class_name,
                    "class_name: %s", class_name);
             FREEMEM(class_string);
             CFCBase_decref((CFCBase*)klass);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCTestSymbol.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestSymbol.c b/compiler/src/CFCTestSymbol.c
index bf267e4..12cf7f5 100644
--- a/compiler/src/CFCTestSymbol.c
+++ b/compiler/src/CFCTestSymbol.c
@@ -102,7 +102,7 @@ S_run_tests(CFCTest *test) {
         CFCParcel_register(eep_parcel);
         CFCClass *ork
             = CFCClass_create(eep_parcel, NULL, "Op::Ork", NULL, NULL, NULL,
-                              NULL, NULL, false, false, false);
+                              NULL, false, false, false);
         CFCSymbol *eep = CFCSymbol_new("parcel", "Op::Ork", "ah_ah");
         char *short_sym = CFCSymbol_short_sym(eep, ork);
         STR_EQ(test, short_sym, "Ork_ah_ah", "short_sym");

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCTestType.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestType.c b/compiler/src/CFCTestType.c
index fd39f58..c598f4c 100644
--- a/compiler/src/CFCTestType.c
+++ b/compiler/src/CFCTestType.c
@@ -331,7 +331,7 @@ S_run_object_tests(CFCTest *test) {
     CFCParcel *neato_parcel = CFCParcel_new("Neato", NULL, NULL, NULL);
     CFCClass *foo_class
         = CFCClass_create(neato_parcel, NULL, "Foo", NULL, NULL, NULL, NULL,
-                          NULL, false, false, false);
+                          false, false, false);
     CFCType *foo = CFCType_new_object(0, neato_parcel, "Foo", 1);
     CFCType_resolve(foo);
 
@@ -345,7 +345,7 @@ S_run_object_tests(CFCTest *test) {
     {
         CFCClass *bar_class
             = CFCClass_create(neato_parcel, NULL, "Bar", NULL, NULL, NULL,
-                              NULL, NULL, false, false, false);
+                              NULL, false, false, false);
         CFCType *bar = CFCType_new_object(0, neato_parcel, "Bar", 1);
         CFCType_resolve(bar);
         OK(test, !CFCType_equals(foo, bar),
@@ -359,7 +359,7 @@ S_run_object_tests(CFCTest *test) {
             = CFCParcel_new("Foreign", NULL, NULL, NULL);
         CFCClass *foreign_foo_class
             = CFCClass_create(foreign_parcel, NULL, "Foreign::Foo", NULL, NULL,
-                              NULL, NULL, NULL, false, false, false);
+                              NULL, NULL, false, false, false);
         CFCType *foreign_foo = CFCType_new_object(0, foreign_parcel, "Foo", 1);
         CFCType_resolve(foreign_foo);
         OK(test, !CFCType_equals(foo, foreign_foo),

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCTestVariable.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCTestVariable.c b/compiler/src/CFCTestVariable.c
index 203ac90..a8eec5a 100644
--- a/compiler/src/CFCTestVariable.c
+++ b/compiler/src/CFCTestVariable.c
@@ -79,7 +79,7 @@ S_run_tests(CFCTest *test) {
         CFCClass *ork
             = CFCClass_create(neato_parcel, NULL,
                               "Crustacean::Lobster::LobsterClaw", "LobClaw",
-                              NULL, NULL, NULL, NULL, false, false, false);
+                              NULL, NULL, NULL, false, false, false);
 
         char *global_c = CFCVariable_global_c(var, ork);
         STR_EQ(test, global_c, "neato_Foo* neato_LobClaw_foo", "global_c");

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCType.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCType.c b/compiler/src/CFCType.c
index fa9d756..5684f50 100644
--- a/compiler/src/CFCType.c
+++ b/compiler/src/CFCType.c
@@ -30,7 +30,6 @@
 #include "CFCType.h"
 #include "CFCClass.h"
 #include "CFCParcel.h"
-#include "CFCSymbol.h"
 #include "CFCUtil.h"
 
 struct CFCType {
@@ -199,7 +198,7 @@ CFCType_new_object(int flags, CFCParcel *parcel, const char 
*specifier,
         }
         small_specifier++;
     }
-    if (!CFCSymbol_validate_class_name_component(small_specifier)) {
+    if (!CFCClass_validate_class_name_component(small_specifier)) {
         CFCUtil_die("Invalid specifier: '%s'", specifier);
     }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/a35d347a/compiler/src/CFCUri.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCUri.c b/compiler/src/CFCUri.c
index 88f74b5..be3e8c8 100644
--- a/compiler/src/CFCUri.c
+++ b/compiler/src/CFCUri.c
@@ -84,14 +84,14 @@ CFCUri_init(CFCUri *self, const char *uri, CFCClass *klass) 
{
             }
             else if (self->type == CFC_URI_FUNCTION) {
                 if (!CFCClass_function(klass, self->func_sym)) {
-                    const char *class_name = CFCClass_get_class_name(klass);
+                    const char *class_name = CFCClass_get_name(klass);
                     CFCUtil_warn("No function found for URI %s in %s", uri,
                                  class_name);
                 }
             }
             else if (self->type == CFC_URI_METHOD) {
                 if (!CFCClass_method(klass, self->func_sym)) {
-                    const char *class_name = CFCClass_get_class_name(klass);
+                    const char *class_name = CFCClass_get_name(klass);
                     CFCUtil_warn("No method found for URI %s in %s", uri,
                                  class_name);
                 }

Reply via email to