lucy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nwelln...@apache.org
Subject [16/20] lucy-clownfish git commit: Simplify URI handling
Date Thu, 06 Aug 2015 16:19:53 GMT
Simplify URI handling


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

Branch: refs/heads/master
Commit: 37504e4cb19bc94fc801ef511a621d475022a813
Parents: 7973bf5
Author: Nick Wellnhofer <wellnhofer@aevum.de>
Authored: Sun Jul 26 18:29:53 2015 +0200
Committer: Nick Wellnhofer <wellnhofer@aevum.de>
Committed: Thu Aug 6 18:19:19 2015 +0200

----------------------------------------------------------------------
 compiler/src/CFCC.c       |  90 +++-----------
 compiler/src/CFCC.h       |   2 +-
 compiler/src/CFCCHtml.c   |  98 +++++++--------
 compiler/src/CFCCMan.c    |   2 +-
 compiler/src/CFCPerlPod.c |  98 ++++++---------
 compiler/src/CFCUri.c     | 276 +++++++++++++++++++++++------------------
 compiler/src/CFCUri.h     |  21 ++--
 7 files changed, 274 insertions(+), 313 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/37504e4c/compiler/src/CFCC.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCC.c b/compiler/src/CFCC.c
index aa1e267..6fba122 100644
--- a/compiler/src/CFCC.c
+++ b/compiler/src/CFCC.c
@@ -172,89 +172,35 @@ CFCC_write_hostdefs(CFCC *self) {
 }
 
 char*
-CFCC_link_text(CFCUri *uri_obj, CFCClass *klass) {
+CFCC_link_text(CFCUri *uri_obj) {
     char *link_text = NULL;
     int   type      = CFCUri_get_type(uri_obj);
 
     switch (type) {
-        case CFC_URI_CLASS: {
-            const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
-            CFCClass *uri_class = full_struct_sym
-                ? CFCClass_fetch_by_struct_sym(full_struct_sym)
-                : NULL;
-
-            if (uri_class) {
-                if (klass
-                    && strcmp(CFCClass_get_prefix(uri_class),
-                              CFCClass_get_prefix(klass)) == 0
-                ) {
-                    // Same parcel.
-                    const char *struct_sym = CFCUri_get_struct_sym(uri_obj);
-                    link_text = CFCUtil_strdup(struct_sym);
-                }
-                else {
-                    // Other parcel.
-                    const char *class_name = CFCClass_get_name(uri_class);
-                    link_text = CFCUtil_strdup(class_name);
-                }
-
-                break;
-            }
-
-            const char *struct_sym = CFCUri_get_struct_sym(uri_obj);
-            CFCDocument *doc = CFCDocument_fetch(struct_sym);
-
-            if (doc) {
-                const char *name = CFCDocument_get_name(doc);
-                link_text = CFCUtil_strdup(name);
-                break;
-            }
+        case CFC_URI_NULL:
+            link_text = CFCUtil_strdup("NULL");
+            break;
 
-            CFCUtil_warn("Can't resolve Clownfish URI '%s'", struct_sym);
+        case CFC_URI_CLASS: {
+            CFCClass *klass = CFCUri_get_class(uri_obj);
+            const char *src = CFCClass_included(klass)
+                              ? CFCClass_get_name(klass)
+                              : CFCClass_get_struct_sym(klass);
+            link_text = CFCUtil_strdup(src);
             break;
         }
 
         case CFC_URI_FUNCTION:
         case CFC_URI_METHOD: {
-#if 1
-            const char *func_sym = CFCUri_get_func_sym(uri_obj);
-            link_text = CFCUtil_sprintf("%s()", func_sym);
-#else
-            // Full function sym.
-            const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
-            const char *func_sym        = CFCUri_get_func_sym(uri_obj);
-
-            if (strcmp(full_struct_sym,
-                       CFCClass_full_struct_sym(klass)) == 0
-            ) {
-                // Same class.
-                link_text = CFCUtil_sprintf("%s()", func_sym);
-            }
-            else {
-                CFCClass *uri_class
-                    = CFCClass_fetch_by_struct_sym(full_struct_sym);
-
-                if (!uri_class) {
-                    CFCUtil_warn("URI class not found: %s", full_struct_sym);
-                    link_text = CFCUtil_sprintf("%s()", func_sym);
-                }
-                else {
-                    const char *prefix   = CFCUri_get_prefix(uri_obj);
-                    const char *nickname = CFCClass_get_nickname(uri_class);
+            const char *name = CFCUri_get_callable_name(uri_obj);
+            link_text = CFCUtil_sprintf("%s()", name);
+            break;
+        }
 
-                    if (strcmp(prefix, CFCClass_get_prefix(klass)) == 0) {
-                        // Same parcel.
-                        link_text = CFCUtil_sprintf("%s_%s()", nickname,
-                                                    func_sym);
-                    }
-                    else {
-                        // Other parcel.
-                        link_text = CFCUtil_sprintf("%s%s_%s()", prefix,
-                                                    nickname, func_sym);
-                    }
-                }
-            }
-#endif
+        case CFC_URI_DOCUMENT: {
+            CFCDocument *doc = CFCUri_get_document(uri_obj);
+            const char *name = CFCDocument_get_name(doc);
+            link_text = CFCUtil_strdup(name);
             break;
         }
     }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/37504e4c/compiler/src/CFCC.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCC.h b/compiler/src/CFCC.h
index b8c6c73..8b98461 100644
--- a/compiler/src/CFCC.h
+++ b/compiler/src/CFCC.h
@@ -62,7 +62,7 @@ void
 CFCC_write_man_pages(CFCC *self);
 
 char*
-CFCC_link_text(struct CFCUri *uri_obj, struct CFCClass *klass);
+CFCC_link_text(struct CFCUri *uri_obj);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/37504e4c/compiler/src/CFCCHtml.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCHtml.c b/compiler/src/CFCCHtml.c
index aa240b0..52740f5 100644
--- a/compiler/src/CFCCHtml.c
+++ b/compiler/src/CFCCHtml.c
@@ -171,8 +171,7 @@ static char*
 S_type_to_html(CFCClass *klass, CFCType *type);
 
 static char*
-S_cfc_uri_to_url(CFCUri *uri_obj, const char *uri_string, CFCClass *base,
-                 int dir_level);
+S_cfc_uri_to_url(CFCUri *uri_obj, CFCClass *base, int dir_level);
 
 static char*
 S_struct_sym_to_url(const char *struct_sym, CFCClass *base, int dir_level);
@@ -181,6 +180,9 @@ static char*
 S_class_to_url(CFCClass *klass, CFCClass *base, int dir_level);
 
 static char*
+S_document_to_url(CFCDocument *doc, CFCClass *base, int dir_level);
+
+static char*
 S_relative_url(const char *url, CFCClass *base, int dir_level);
 
 CFCCHtml*
@@ -1007,39 +1009,21 @@ S_transform_code_block(cmark_node *code_block, int found_matching_code_block)
{
 }
 
 static void
-S_transform_link(cmark_node *link, CFCClass *klass, int dir_level) {
+S_transform_link(cmark_node *link, CFCClass *doc_class, int dir_level) {
     const char *uri_string = cmark_node_get_url(link);
     if (!uri_string || !CFCUri_is_clownfish_uri(uri_string)) {
         return;
     }
 
-    char   *new_uri = NULL;
-    CFCUri *uri_obj = CFCUri_new(uri_string, klass);
-    int     type    = CFCUri_get_type(uri_obj);
-
-    switch (type) {
-        case CFC_URI_CLASS: {
-            new_uri = S_cfc_uri_to_url(uri_obj, uri_string, klass, dir_level);
-            break;
-        }
-
-        case CFC_URI_FUNCTION:
-        case CFC_URI_METHOD: {
-            const char *func_sym = CFCUri_get_func_sym(uri_obj);
-            char *url = S_cfc_uri_to_url(uri_obj, uri_string, klass,
-                                         dir_level);
-            new_uri = CFCUtil_sprintf("%s#func_%s", url, func_sym);
-            FREEMEM(url);
-            break;
-        }
-    }
+    CFCUri *uri_obj = CFCUri_new(uri_string, doc_class);
+    char   *url     = S_cfc_uri_to_url(uri_obj, doc_class, dir_level);
 
-    if (new_uri) {
-        cmark_node_set_url(link, new_uri);
+    if (url) {
+        cmark_node_set_url(link, url);
 
         if (!cmark_node_first_child(link)) {
             // Empty link text.
-            char *link_text = CFCC_link_text(uri_obj, klass);
+            char *link_text = CFCC_link_text(uri_obj);
 
             if (link_text) {
                 cmark_node *text_node = cmark_node_new(CMARK_NODE_TEXT);
@@ -1061,7 +1045,7 @@ S_transform_link(cmark_node *link, CFCClass *klass, int dir_level) {
     }
 
     CFCBase_decref((CFCBase*)uri_obj);
-    FREEMEM(new_uri);
+    FREEMEM(url);
 }
 
 static char*
@@ -1103,34 +1087,35 @@ S_type_to_html(CFCClass *klass, CFCType *type) {
 
 // Return a relative URL for a CFCUri object.
 static char*
-S_cfc_uri_to_url(CFCUri *uri_obj, const char *uri_string, CFCClass *base,
-                 int dir_level) {
-    const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
-    CFCClass *klass = full_struct_sym
-                      ? CFCClass_fetch_by_struct_sym(full_struct_sym)
-                      : NULL;
-
-    if (klass) {
-        return S_struct_sym_to_url(full_struct_sym, base, dir_level);
-    }
+S_cfc_uri_to_url(CFCUri *uri_obj, CFCClass *doc_class, int dir_level) {
+    char *url = NULL;
+    int   type    = CFCUri_get_type(uri_obj);
 
-    const char *struct_sym = CFCUri_get_struct_sym(uri_obj);
-    CFCDocument *doc = CFCDocument_fetch(struct_sym);
+    switch (type) {
+        case CFC_URI_CLASS: {
+            CFCClass *klass = CFCUri_get_class(uri_obj);
+            url = S_class_to_url(klass, doc_class, dir_level);
+            break;
+        }
 
-    if (doc) {
-        const char *path_part = CFCDocument_get_path_part(doc);
-        char *slashy  = CFCUtil_global_replace(path_part, CHY_DIR_SEP, "/");
-        char *url     = CFCUtil_sprintf("%s.html", slashy);
-        char *rel_url = S_relative_url(url, base, dir_level);
+        case CFC_URI_FUNCTION:
+        case CFC_URI_METHOD: {
+            CFCClass *klass = CFCUri_get_class(uri_obj);
+            const char *name = CFCUri_get_callable_name(uri_obj);
+            char *class_url = S_class_to_url(klass, doc_class, dir_level);
+            url = CFCUtil_sprintf("%s#func_%s", class_url, name);
+            FREEMEM(class_url);
+            break;
+        }
 
-        FREEMEM(url);
-        FREEMEM(slashy);
-        return rel_url;
+        case CFC_URI_DOCUMENT: {
+            CFCDocument *doc = CFCUri_get_document(uri_obj);
+            url = S_document_to_url(doc, doc_class, dir_level);
+            break;
+        }
     }
 
-    CFCUtil_warn("No class or document found for URI '%s'",
-                 uri_string);
-    return CFCUtil_strdup("not_found.html");
+    return url;
 }
 
 // Return a relative URL to the class with full struct sym `struct_sym`.
@@ -1158,6 +1143,19 @@ S_class_to_url(CFCClass *klass, CFCClass *base, int dir_level) {
     return rel_url;
 }
 
+// Return a relative URL to a document.
+static char*
+S_document_to_url(CFCDocument *doc, CFCClass *base, int dir_level) {
+    const char *path_part = CFCDocument_get_path_part(doc);
+    char *slashy  = CFCUtil_global_replace(path_part, CHY_DIR_SEP, "/");
+    char *url     = CFCUtil_sprintf("%s.html", slashy);
+    char *rel_url = S_relative_url(url, base, dir_level);
+
+    FREEMEM(url);
+    FREEMEM(slashy);
+    return rel_url;
+}
+
 static char*
 S_relative_url(const char *url, CFCClass *base, int dir_level) {
     if (base) {

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/37504e4c/compiler/src/CFCCMan.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCCMan.c b/compiler/src/CFCCMan.c
index 6089ca3..d6ba04d 100644
--- a/compiler/src/CFCCMan.c
+++ b/compiler/src/CFCCMan.c
@@ -597,7 +597,7 @@ S_nodes_to_man(CFCClass *klass, cmark_node *node, int needs_indent) {
                     ) {
                         // Empty link text.
                         CFCUri *uri_obj = CFCUri_new(url, klass);
-                        char *link_text = CFCC_link_text(uri_obj, klass);
+                        char *link_text = CFCC_link_text(uri_obj);
                         if (link_text) {
                             result = CFCUtil_cat(result, link_text, NULL);
                             FREEMEM(link_text);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/37504e4c/compiler/src/CFCPerlPod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c
index fa221e4..ffa0f04 100644
--- a/compiler/src/CFCPerlPod.c
+++ b/compiler/src/CFCPerlPod.c
@@ -558,10 +558,10 @@ S_pod_escape(const char *content) {
 }
 
 static char*
-S_convert_link(cmark_node *link, CFCClass *klass, int header_level) {
+S_convert_link(cmark_node *link, CFCClass *doc_class, int header_level) {
     cmark_node *child = cmark_node_first_child(link);
     const char *uri   = cmark_node_get_url(link);
-    char       *text  = S_nodes_to_pod(child, klass, header_level);
+    char       *text  = S_nodes_to_pod(child, doc_class, header_level);
     char       *retval;
 
     if (!CFCUri_is_clownfish_uri(uri)) {
@@ -572,7 +572,7 @@ S_convert_link(cmark_node *link, CFCClass *klass, int header_level) {
 
     char   *new_uri  = NULL;
     char   *new_text = NULL;
-    CFCUri *uri_obj  = CFCUri_new(uri, klass);
+    CFCUri *uri_obj  = CFCUri_new(uri, doc_class);
     int     type     = CFCUri_get_type(uri_obj);
 
     switch (type) {
@@ -582,52 +582,18 @@ S_convert_link(cmark_node *link, CFCClass *klass, int header_level)
{
             break;
 
         case CFC_URI_CLASS: {
-            const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
-            CFCClass *uri_class
-                = full_struct_sym
-                ? CFCClass_fetch_by_struct_sym(full_struct_sym)
-                : NULL;
-
-            if (uri_class) {
-                if (uri_class != klass) {
-                    const char *class_name = CFCClass_get_name(uri_class);
-                    new_uri = CFCUtil_strdup(class_name);
-                }
-            }
-            else {
-                const char *doc_name = CFCUri_get_struct_sym(uri_obj);
-                CFCDocument *doc = CFCDocument_fetch(doc_name);
+            CFCClass *klass = CFCUri_get_class(uri_obj);
 
-                if (!doc) {
-                    CFCUtil_warn("No class or document found for URI '%s'",
-                                 uri);
-                }
-                else {
-                    const char *path_part = CFCDocument_get_path_part(doc);
-                    new_uri = CFCUtil_global_replace(path_part, CHY_DIR_SEP,
-                                                     "::");
-                }
-            }
-
-            if (text[0] != '\0') {
-                // Keep text.
-                break;
+            if (klass != doc_class) {
+                const char *class_name = CFCClass_get_name(klass);
+                new_uri = CFCUtil_strdup(class_name);
             }
 
-            if (!uri_class
-                || !klass
-                || strcmp(CFCUri_get_prefix(uri_obj),
-                          CFCClass_get_prefix(klass)) == 0
-            ) {
-                // Same parcel.
-                const char *struct_sym = CFCUri_get_struct_sym(uri_obj);
-                new_text = CFCUtil_strdup(struct_sym);
-            }
-            else {
-                // Other parcel.
-                const char *class_name
-                    = CFCClass_get_name(uri_class);
-                new_text = CFCUtil_strdup(class_name);
+            if (text[0] == '\0') {
+                const char *src = CFCClass_included(klass)
+                                  ? CFCClass_get_name(klass)
+                                  : CFCClass_get_struct_sym(klass);
+                new_text = CFCUtil_strdup(src);
             }
 
             break;
@@ -635,35 +601,45 @@ S_convert_link(cmark_node *link, CFCClass *klass, int header_level)
{
 
         case CFC_URI_FUNCTION:
         case CFC_URI_METHOD: {
-            const char *full_struct_sym = CFCUri_full_struct_sym(uri_obj);
-            const char *func_sym        = CFCUri_get_func_sym(uri_obj);
+            CFCClass   *klass = CFCUri_get_class(uri_obj);
+            const char *name  = CFCUri_get_callable_name(uri_obj);
 
             // Convert "Err_get_error" to "Clownfish->error".
-            if (strcmp(full_struct_sym, "cfish_Err") == 0
-                && strcmp(func_sym, "get_error") == 0
+            if (strcmp(CFCClass_full_struct_sym(klass), "cfish_Err") == 0
+                && strcmp(name, "get_error") == 0
             ) {
                 new_text = CFCUtil_strdup("Clownfish->error");
                 break;
             }
 
-            CFCClass *uri_class
-                = CFCClass_fetch_by_struct_sym(full_struct_sym);
-
             // TODO: Link to relevant POD section. This isn't easy because
             // the section headers for functions also contain a description
             // of the parameters.
 
-            if (!uri_class) {
-                CFCUtil_warn("URI class not found: %s", full_struct_sym);
-            }
-            else if (uri_class != klass) {
-                const char *class_name = CFCClass_get_name(uri_class);
+            if (klass != doc_class) {
+                const char *class_name = CFCClass_get_name(klass);
                 new_uri = CFCUtil_strdup(class_name);
             }
 
-            new_text = CFCUtil_sprintf("%s()", func_sym);
-            for (size_t i = 0; new_text[i] != '\0'; ++i) {
-                new_text[i] = tolower(new_text[i]);
+            if (text[0] == '\0') {
+                new_text = CFCUtil_sprintf("%s()", name);
+                for (size_t i = 0; new_text[i] != '\0'; ++i) {
+                    new_text[i] = tolower(new_text[i]);
+                }
+            }
+
+            break;
+        }
+
+        case CFC_URI_DOCUMENT: {
+            CFCDocument *doc = CFCUri_get_document(uri_obj);
+
+            const char *path_part = CFCDocument_get_path_part(doc);
+            new_uri = CFCUtil_global_replace(path_part, CHY_DIR_SEP, "::");
+
+            if (text[0] == '\0') {
+                const char *name = CFCDocument_get_name(doc);
+                new_text = CFCUtil_strdup(name);
             }
 
             break;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/37504e4c/compiler/src/CFCUri.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCUri.c b/compiler/src/CFCUri.c
index 4799d6a..fc6e8e8 100644
--- a/compiler/src/CFCUri.c
+++ b/compiler/src/CFCUri.c
@@ -22,15 +22,17 @@
 #include "CFCBase.h"
 #include "CFCUri.h"
 #include "CFCClass.h"
+#include "CFCDocument.h"
 #include "CFCUtil.h"
 
 struct CFCUri {
-    CFCBase base;
-    int   type;
-    char *prefix;
-    char *struct_sym;
-    char *full_struct_sym;
-    char *func_sym;
+    CFCBase      base;
+    char        *string;
+    CFCClass    *doc_class;
+    int          type;
+    CFCClass    *klass;
+    CFCDocument *document;
+    char        *callable;
 };
 
 static const CFCMeta CFCURI_META = {
@@ -40,10 +42,14 @@ static const CFCMeta CFCURI_META = {
 };
 
 static void
-S_parse_uri(CFCUri *self, const char *str, CFCClass *klass);
+S_parse(CFCUri *self);
 
-static char**
-S_split(const char *str, char c, size_t *num_parts_ptr);
+static void
+S_resolve(CFCUri *self, const char *prefix, const char *struct_sym,
+          const char *callable);
+
+static char*
+S_next_component(char **iter);
 
 int
 CFCUri_is_clownfish_uri(const char *uri) {
@@ -51,176 +57,210 @@ CFCUri_is_clownfish_uri(const char *uri) {
 }
 
 CFCUri*
-CFCUri_new(const char *uri, CFCClass *klass) {
+CFCUri_new(const char *uri, CFCClass *doc_class) {
     CFCUri *self = (CFCUri*)CFCBase_allocate(&CFCURI_META);
-    return CFCUri_init(self, uri, klass);
+    return CFCUri_init(self, uri, doc_class);
 }
 
 CFCUri*
-CFCUri_init(CFCUri *self, const char *uri, CFCClass *klass) {
+CFCUri_init(CFCUri *self, const char *uri, CFCClass *doc_class) {
     CFCUTIL_NULL_CHECK(uri);
 
     if (strncmp(uri, "cfish:", 6) != 0) {
         CFCUtil_die("Invalid clownfish URI: %s", uri);
     }
 
-    if (strcmp(uri + 6, "@null") == 0) {
-        self->type = CFC_URI_NULL;
-    }
-    else {
-        S_parse_uri(self, uri, klass);
-    }
-
-    if (self->prefix && self->struct_sym) {
-        self->full_struct_sym
-            = CFCUtil_sprintf("%s%s", self->prefix, self->struct_sym);
-
-        if (getenv("CFC_CHECK_LINKS")) {
-            CFCClass *klass
-                = CFCClass_fetch_by_struct_sym(self->full_struct_sym);
-
-            if (!klass) {
-                CFCUtil_warn("No class found for URI: %s", uri);
-            }
-            else if (self->type == CFC_URI_FUNCTION) {
-                if (!CFCClass_function(klass, self->func_sym)) {
-                    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_name(klass);
-                    CFCUtil_warn("No method found for URI %s in %s", uri,
-                                 class_name);
-                }
-            }
-        }
-    }
+    self->string    = CFCUtil_strdup(uri);
+    self->doc_class = (CFCClass*)CFCBase_incref((CFCBase*)doc_class);
 
     return self;
 }
 
 void
 CFCUri_destroy(CFCUri *self) {
-    FREEMEM(self->prefix);
-    FREEMEM(self->struct_sym);
-    FREEMEM(self->full_struct_sym);
-    FREEMEM(self->func_sym);
+    FREEMEM(self->string);
+    FREEMEM(self->callable);
+    CFCBase_decref((CFCBase*)self->doc_class);
+    CFCBase_decref((CFCBase*)self->klass);
+    CFCBase_decref((CFCBase*)self->document);
     CFCBase_destroy((CFCBase*)self);
 }
 
 static void
-S_parse_uri(CFCUri *self, const char *uri, CFCClass *klass) {
-    size_t num_components = 0;
-    char **components = S_split(uri + 6, '.', &num_components);
-    size_t i = 0;
+S_parse(CFCUri *self) {
+    const char *uri_part = self->string + sizeof("cfish:") - 1;
 
-    self->type = CFC_URI_PARCEL;
+    if (strcmp(uri_part, "@null") == 0) {
+        self->type = CFC_URI_NULL;
+        return;
+    }
 
-    if (islower(components[i][0])) {
+    const char *parcel     = NULL;
+    const char *struct_sym = NULL;
+    const char *callable   = NULL;
+
+    char       *buf  = CFCUtil_strdup(uri_part);
+    char       *iter = buf;
+    const char *component = S_next_component(&iter);
+
+    if (islower(component[0])) {
         // Parcel
-        self->prefix = CFCUtil_sprintf("%s_", components[i]);
-        ++i;
-    }
-    else if (klass) {
-        self->prefix = CFCUtil_strdup(CFCClass_get_prefix(klass));
+        parcel = component;
+        component = S_next_component(&iter);
     }
 
-    if (i < num_components) {
-        self->type = CFC_URI_CLASS;
-
-        if (isupper(components[i][0])) {
+    if (component) {
+        if (isupper(component[0])) {
             // Class
-            self->struct_sym = components[i];
-            components[i] = NULL;
+            struct_sym = component;
         }
-        else if (i == 0 && components[i][0] == '\0') {
-            if (!klass) {
-                CFCUtil_die("Class needed to complete URI: %s", uri);
-            }
-            self->struct_sym = CFCUtil_strdup(CFCClass_get_struct_sym(klass));
+        else if (component == buf && component[0] == '\0' && iter) {
+            // "cfish:.Method" style URL.
+            ;
         }
         else {
-            CFCUtil_die("Invalid clownfish URI: %s", uri);
+            CFCUtil_die("Invalid component in Clownfish URI: %s",
+                        self->string);
         }
 
-        ++i;
+        component = S_next_component(&iter);
+    }
+
+    if (component) {
+        callable = component;
+        component = S_next_component(&iter);
+    }
+
+    if (component) {
+        CFCUtil_die("Trailing components in Clownfish URI: %s", self->string);
     }
 
-    if (i < num_components) {
-        if (isupper(components[i][0])) {
-            self->type = CFC_URI_METHOD;
+    S_resolve(self, parcel, struct_sym, callable);
+
+    FREEMEM(buf);
+}
+
+static void
+S_resolve(CFCUri *self, const char *parcel, const char *struct_sym,
+          const char *callable) {
+
+    // Try to find a CFCClass.
+    if (struct_sym || callable) {
+        CFCClass *doc_class = self->doc_class;
+        CFCClass *klass     = NULL;
+
+        if (parcel) {
+            char *full_struct_sym = CFCUtil_sprintf("%s_%s", parcel, struct_sym);
+            klass = CFCClass_fetch_by_struct_sym(full_struct_sym);
+            FREEMEM(full_struct_sym);
         }
-        else if (islower(components[i][0])) {
-            self->type = CFC_URI_FUNCTION;
+        else if (struct_sym && doc_class) {
+            const char *prefix = CFCClass_get_prefix(doc_class);
+            char *full_struct_sym = CFCUtil_sprintf("%s%s", prefix, struct_sym);
+            klass = CFCClass_fetch_by_struct_sym(full_struct_sym);
+            FREEMEM(full_struct_sym);
         }
         else {
-            CFCUtil_die("Invalid clownfish URI: %s", uri);
+            klass = doc_class;
         }
 
-        self->func_sym = components[i];
-        components[i] = NULL;
-        ++i;
-    }
+        if (klass) {
+            self->type  = CFC_URI_CLASS;
+            self->klass = klass;
+            CFCBase_incref((CFCBase*)klass);
 
-    if (i != num_components) {
-        CFCUtil_die("Invalid clownfish URI: %s", uri);
+            if (callable) {
+                if (islower(callable[0])) {
+                    if (!CFCClass_function(klass, callable)) {
+                        CFCUtil_warn("Unknown function '%s' in Clownfish URI: %s",
+                                     callable, self->string);
+                    }
+
+                    self->type     = CFC_URI_FUNCTION;
+                    self->callable = CFCUtil_strdup(callable);
+                }
+                else {
+                    if (!CFCClass_method(klass, callable)) {
+                        CFCUtil_warn("Unknown method '%s' in Clownfish URI: %s",
+                                     callable, self->string);
+                    }
+
+                    self->type     = CFC_URI_METHOD;
+                    self->callable = CFCUtil_strdup(callable);
+                }
+            }
+        }
     }
 
-    CFCUtil_free_string_array(components);
-}
+    // Try to find a CFCDocument.
+    if (self->type == 0 && !parcel && struct_sym && !callable)
{
+        CFCDocument *doc = CFCDocument_fetch(struct_sym);
 
-static char**
-S_split(const char *str, char c, size_t *num_parts_ptr) {
-    const char *ptr;
-    int num_parts = 1;
+        if (doc) {
+            self->type     = CFC_URI_DOCUMENT;
+            self->document = doc;
+            CFCBase_incref((CFCBase*)doc);
+        }
+    }
 
-    for (ptr = str; *ptr != '\0'; ++ptr) {
-        if (*ptr == c) { ++num_parts; }
+    if (self->type == 0) {
+        CFCUtil_die("Couldn't resolve Clownfish URI: %s", self->string);
     }
+}
 
-    char **parts = (char**)MALLOCATE((num_parts + 1) * sizeof(char*));
-    const char *start = str;
-    size_t i = 0;
+static char*
+S_next_component(char **iter) {
+    char *component = *iter;
 
-    for (ptr = str; *ptr != '\0'; ++ptr) {
-        if (*ptr == c) {
-            parts[i++] = CFCUtil_strndup(start, ptr - start);
-            start = ptr + 1;
+    if (!component) { return NULL; }
+
+    for (char *ptr = component; *ptr != '\0'; ptr++) {
+        if (*ptr == '.') {
+            *ptr  = '\0';
+            *iter = ptr + 1;
+            return component;
         }
     }
-    parts[i++] = CFCUtil_strndup(start, ptr - start);
-    parts[i]   = NULL;
 
-    *num_parts_ptr = num_parts;
+    *iter = NULL;
+    return component;
+}
 
-    return parts;
+const char*
+CFCUri_get_string(CFCUri *self) {
+    return self->string;
 }
 
 int
 CFCUri_get_type(CFCUri *self) {
+    if (self->type == 0) { S_parse(self); }
     return self->type;
 }
 
-const char*
-CFCUri_get_prefix(CFCUri *self) {
-    return self->prefix;
-}
-
-const char*
-CFCUri_get_struct_sym(CFCUri *self) {
-    return self->struct_sym;
+CFCClass*
+CFCUri_get_class(CFCUri *self) {
+    if (self->type == 0) { S_parse(self); }
+    if (self->klass == NULL) {
+        CFCUtil_die("Not a class URI");
+    }
+    return self->klass;
 }
 
-const char*
-CFCUri_full_struct_sym(CFCUri *self) {
-    return self->full_struct_sym;
+CFCDocument*
+CFCUri_get_document(CFCUri *self) {
+    if (self->type == 0) { S_parse(self); }
+    if (self->document == NULL) {
+        CFCUtil_die("Not a document URI");
+    }
+    return self->document;
 }
 
 const char*
-CFCUri_get_func_sym(CFCUri *self) {
-    return self->func_sym;
+CFCUri_get_callable_name(CFCUri *self) {
+    if (self->type == 0) { S_parse(self); }
+    if (self->callable == NULL) {
+        CFCUtil_die("Not a callable URI");
+    }
+    return self->callable;
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/37504e4c/compiler/src/CFCUri.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCUri.h b/compiler/src/CFCUri.h
index 004fc3c..9e22d4e 100644
--- a/compiler/src/CFCUri.h
+++ b/compiler/src/CFCUri.h
@@ -21,14 +21,15 @@
 extern "C" {
 #endif
 
-#define CFC_URI_PARCEL      1
+#define CFC_URI_NULL        1
 #define CFC_URI_CLASS       2
 #define CFC_URI_FUNCTION    3
 #define CFC_URI_METHOD      4
-#define CFC_URI_NULL        5
+#define CFC_URI_DOCUMENT    5
 
 typedef struct CFCUri CFCUri;
 struct CFCClass;
+struct CFCDocument;
 
 int
 CFCUri_is_clownfish_uri(const char *uri);
@@ -42,20 +43,20 @@ CFCUri_init(CFCUri *self, const char *uri, struct CFCClass *klass);
 void
 CFCUri_destroy(CFCUri *self);
 
+const char*
+CFCUri_get_string(CFCUri *self);
+
 int
 CFCUri_get_type(CFCUri *self);
 
-const char*
-CFCUri_get_prefix(CFCUri *self);
-
-const char*
-CFCUri_get_struct_sym(CFCUri *self);
+struct CFCClass*
+CFCUri_get_class(CFCUri *self);
 
-const char*
-CFCUri_full_struct_sym(CFCUri *self);
+struct CFCDocument*
+CFCUri_get_document(CFCUri *self);
 
 const char*
-CFCUri_get_func_sym(CFCUri *self);
+CFCUri_get_callable_name(CFCUri *self);
 
 #ifdef __cplusplus
 }


Mime
View raw message