You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucy.apache.org by nw...@apache.org on 2015/12/23 13:24:40 UTC

[1/7] lucy-clownfish git commit: Autogenerate Perl subroutine code samples

Repository: lucy-clownfish
Updated Branches:
  refs/heads/master fe23648e7 -> 2a7728094


Autogenerate Perl subroutine code samples

Resolves CLOWNFISH-64.


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

Branch: refs/heads/master
Commit: 5e7c5ceaa56e900417c67550fab2573598cb8eb4
Parents: fe23648
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Dec 12 15:34:03 2015 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat Dec 12 15:34:03 2015 +0100

----------------------------------------------------------------------
 compiler/src/CFCPerlPod.c | 220 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 217 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5e7c5cea/compiler/src/CFCPerlPod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c
index add7bfa..5d1ecc4 100644
--- a/compiler/src/CFCPerlPod.c
+++ b/compiler/src/CFCPerlPod.c
@@ -34,6 +34,8 @@
 #include "CFCDocuComment.h"
 #include "CFCUri.h"
 #include "CFCDocument.h"
+#include "CFCType.h"
+#include "CFCVariable.h"
 
 #ifndef true
   #define true 1
@@ -64,6 +66,24 @@ static const CFCMeta CFCPERLPOD_META = {
 };
 
 static char*
+S_gen_code_sample(CFCFunction *func, const char *alias, CFCClass *klass,
+                  int is_constructor);
+
+static char*
+S_gen_positional_sample(const char *invocant, const char *alias,
+                        CFCParamList *param_list, size_t start);
+
+static char*
+S_gen_labeled_sample(const char *invocant, const char *alias,
+                     CFCParamList *param_list, size_t start);
+
+static char*
+S_perl_var_name(CFCVariable *var);
+
+static char*
+S_camel_to_lower(const char *camel);
+
+static char*
 S_nodes_to_pod(cmark_node *node, CFCClass *klass, int header_level);
 
 static char*
@@ -124,7 +144,7 @@ CFCPerlPod_add_method(CFCPerlPod *self, const char *alias, const char *method,
     NamePod *slot = &self->methods[self->num_methods - 1];
     slot->alias  = CFCUtil_strdup(alias);
     slot->func   = method ? CFCUtil_strdup(method) : NULL;
-    slot->sample = CFCUtil_strdup(sample ? sample : "");
+    slot->sample = sample ? CFCUtil_strdup(sample) : NULL;
     slot->pod    = pod ? CFCUtil_strdup(pod) : NULL;
 }
 
@@ -138,7 +158,7 @@ CFCPerlPod_add_constructor(CFCPerlPod *self, const char *alias,
     NamePod *slot = &self->constructors[self->num_constructors - 1];
     slot->alias  = CFCUtil_strdup(alias ? alias : "new");
     slot->func   = CFCUtil_strdup(initializer ? initializer : "init");
-    slot->sample = CFCUtil_strdup(sample ? sample : "");
+    slot->sample = sample ? CFCUtil_strdup(sample) : NULL;
     slot->pod    = pod ? CFCUtil_strdup(pod) : NULL;
 }
 
@@ -323,7 +343,13 @@ CFCPerlPod_gen_subroutine_pod(CFCFunction *func,
     }
 
     // Add code sample.
-    if (code_sample && strlen(code_sample)) {
+    if (!code_sample) {
+        char *auto_sample
+            = S_gen_code_sample(func, alias, klass, is_constructor);
+        pod = CFCUtil_cat(pod, auto_sample, "\n", NULL);
+        FREEMEM(auto_sample);
+    }
+    else {
         pod = CFCUtil_cat(pod, code_sample, "\n", NULL);
     }
 
@@ -377,6 +403,194 @@ CFCPerlPod_gen_subroutine_pod(CFCFunction *func,
     return pod;
 }
 
+static char*
+S_gen_code_sample(CFCFunction *func, const char *alias, CFCClass *klass,
+                  int is_constructor) {
+    char *invocant = NULL;
+
+    if (is_constructor) {
+        invocant = CFCUtil_strdup(CFCClass_get_name(klass));
+    }
+    else {
+        char *lower = S_camel_to_lower(CFCClass_get_struct_sym(klass));
+        invocant = CFCUtil_sprintf("$%s", lower);
+        FREEMEM(lower);
+    }
+
+    CFCParamList *param_list = CFCFunction_get_param_list(func);
+    size_t        num_vars   = CFCParamList_num_vars(param_list);
+    size_t        start      = is_constructor ? 0 : 1;
+    char         *sample     = NULL;
+
+    if (start == num_vars) {
+        sample = CFCUtil_sprintf("    %s->%s();\n", invocant, alias);
+    }
+    else if (is_constructor || num_vars - start >= 2) {
+        sample = S_gen_labeled_sample(invocant, alias, param_list, start);
+    }
+    else {
+        sample = S_gen_positional_sample(invocant, alias, param_list, start);
+    }
+
+    return sample;
+}
+
+static char*
+S_gen_positional_sample(const char *invocant, const char *alias,
+                        CFCParamList *param_list, size_t start) {
+    size_t        num_vars = CFCParamList_num_vars(param_list);
+    CFCVariable **vars     = CFCParamList_get_variables(param_list);
+    const char  **inits    = CFCParamList_get_initial_values(param_list);
+
+    if (num_vars - start != 1) {
+        CFCUtil_die("Code samples with multiple positional parameters"
+                    " are not supported yet.");
+    }
+
+    const char *name = CFCVariable_get_name(vars[start]);
+    char *sample
+        = CFCUtil_sprintf("    %s->%s($%s);\n", invocant, alias, name);
+
+    const char *init = inits[start];
+    if (init) {
+        if (strcmp(init, "NULL") == 0) { init = "undef"; }
+        char *def_sample = CFCUtil_sprintf("    %s->%s();  # default: %s\n",
+                                           invocant, alias, init);
+        sample = CFCUtil_cat(sample, def_sample, NULL);
+        FREEMEM(def_sample);
+    }
+
+    return sample;
+}
+
+static char*
+S_gen_labeled_sample(const char *invocant, const char *alias,
+                     CFCParamList *param_list, size_t start) {
+    size_t        num_vars = CFCParamList_num_vars(param_list);
+    CFCVariable **vars     = CFCParamList_get_variables(param_list);
+    const char  **inits    = CFCParamList_get_initial_values(param_list);
+
+    size_t max_label_len = 0;
+    size_t max_var_len   = 0;
+
+    // Find maximum length of label and Perl variable.
+    for (size_t i = start; i < num_vars; i++) {
+        CFCVariable *var = vars[i];
+
+        const char *label = CFCVariable_get_name(var);
+        size_t label_len = strlen(label);
+        if (label_len > max_label_len) { max_label_len = label_len; }
+
+        char *perl_var = S_perl_var_name(var);
+        size_t perl_var_len = strlen(perl_var);
+        if (perl_var_len > max_var_len) { max_var_len = perl_var_len; }
+        FREEMEM(perl_var);
+    }
+
+    char *params = CFCUtil_strdup("");
+
+    for (size_t i = start; i < num_vars; i++) {
+        CFCVariable *var      = vars[i];
+        const char  *label    = CFCVariable_get_name(var);
+        char        *perl_var = S_perl_var_name(var);
+        perl_var = CFCUtil_cat(perl_var, ",", NULL);
+
+        char       *comment = NULL;
+        const char *init    = inits[i];
+
+        if (init) {
+            if (strcmp(init, "NULL") == 0) { init = "undef"; }
+            comment = CFCUtil_sprintf("default: %s", init);
+        }
+        else {
+            comment = CFCUtil_strdup("required");
+        }
+
+        char *line = CFCUtil_sprintf("        %-*s => $%-*s  # %s\n",
+                                     max_label_len, label,
+                                     max_var_len + 1, perl_var,
+                                     comment);
+        params = CFCUtil_cat(params, line, NULL);
+        FREEMEM(line);
+        FREEMEM(comment);
+        FREEMEM(perl_var);
+    }
+
+    const char pattern[] =
+        "    %s->%s(\n"
+        "%s"
+        "    );\n";
+    char *sample = CFCUtil_sprintf(pattern, invocant, alias, params);
+
+    FREEMEM(params);
+    return sample;
+}
+
+static char*
+S_perl_var_name(CFCVariable *var) {
+    CFCType    *type      = CFCVariable_get_type(var);
+    const char *specifier = CFCType_get_specifier(type);
+    char       *perl_name = NULL;
+
+    if (CFCType_is_object(type)) {
+        // Skip parcel prefix.
+        if (islower(*specifier)) {
+            for (specifier++; *specifier; specifier++) {
+                if (*specifier == '_') {
+                    specifier++;
+                    break;
+                }
+            }
+        }
+
+        perl_name = S_camel_to_lower(specifier);
+    }
+    else if (CFCType_is_integer(type)) {
+        if (strcmp(specifier, "bool") == 0) {
+            perl_name = CFCUtil_strdup("bool");
+        }
+        else {
+            perl_name = CFCUtil_strdup("int");
+        }
+    }
+    else if (CFCType_is_floating(type)) {
+        perl_name = CFCUtil_strdup("float");
+    }
+    else {
+        CFCUtil_die("Don't know how to create code sample for type '%s'",
+                    specifier);
+    }
+
+    return perl_name;
+}
+
+static char*
+S_camel_to_lower(const char *camel) {
+    if (camel[0] == '\0') { return CFCUtil_strdup(""); }
+
+    size_t alloc = 1;
+    for (size_t i = 1; camel[i]; i++) {
+        if (isupper(camel[i]) && islower(camel[i+1])) {
+            alloc += 1;
+        }
+        alloc += 1;
+    }
+    char *lower = MALLOCATE(alloc + 1);
+
+    lower[0] = tolower(camel[0]);
+    size_t j = 1;
+    for (size_t i = 1; camel[i]; i++) {
+        // Only insert underscore if next char is lowercase.
+        if (isupper(camel[i]) && islower(camel[i+1])) {
+            lower[j++] = '_';
+        }
+        lower[j++] = tolower(camel[i]);
+    }
+    lower[j] = '\0';
+
+    return lower;
+}
+
 char*
 CFCPerlPod_md_to_pod(const char *md, CFCClass *klass, int header_level) {
     int options = CMARK_OPT_NORMALIZE


[2/7] lucy-clownfish git commit: Remove argument summary from =head2 in POD

Posted by nw...@apache.org.
Remove argument summary from =head2 in POD


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

Branch: refs/heads/master
Commit: e2626d979b25c9a8f4bb8af9d48f104cdae99aeb
Parents: 5e7c5ce
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Dec 12 15:37:40 2015 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat Dec 12 15:54:18 2015 +0100

----------------------------------------------------------------------
 compiler/src/CFCPerlPod.c | 20 +-------------------
 1 file changed, 1 insertion(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/e2626d97/compiler/src/CFCPerlPod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c
index 5d1ecc4..7388cea 100644
--- a/compiler/src/CFCPerlPod.c
+++ b/compiler/src/CFCPerlPod.c
@@ -322,25 +322,7 @@ CFCPerlPod_gen_subroutine_pod(CFCFunction *func,
         CFCUtil_die("%s#%s is not public", class_name, alias);
     }
 
-    CFCParamList *param_list = CFCFunction_get_param_list(func);
-    int num_vars = (int)CFCParamList_num_vars(param_list);
-    char *pod = CFCUtil_sprintf("=head2 %s", alias);
-
-    // Build string summarizing arguments to use in header.
-    if (num_vars > 2 || (is_constructor && num_vars > 1)) {
-        pod = CFCUtil_cat(pod, "( I<[labeled params]> )\n\n", NULL);
-    }
-    else if (num_vars == 2) {
-        // Kill self param.
-        const char *name_list = CFCParamList_name_list(param_list);
-        const char *after_comma = strchr(name_list, ',') + 1;
-        while (isspace(*after_comma)) { after_comma++; }
-        pod = CFCUtil_cat(pod, "(", after_comma, ")\n\n", NULL);
-    }
-    else {
-        // num_args == 1, leave off 'self'.
-        pod = CFCUtil_cat(pod, "()\n\n", NULL);
-    }
+    char *pod = CFCUtil_sprintf("=head2 %s\n\n", alias);
 
     // Add code sample.
     if (!code_sample) {


[6/7] lucy-clownfish git commit: Fix links to methods in POD

Posted by nw...@apache.org.
Fix links to methods in POD

The Perl POD only contains sections for novel methods. Link to the class
where the method is declared first.


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

Branch: refs/heads/master
Commit: b35885f1c65b89608765312a6c09e9f54db9f256
Parents: 39a6685
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Dec 12 16:43:36 2015 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat Dec 12 16:43:36 2015 +0100

----------------------------------------------------------------------
 compiler/src/CFCPerlPod.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b35885f1/compiler/src/CFCPerlPod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c
index 6c2a638..97f93c8 100644
--- a/compiler/src/CFCPerlPod.c
+++ b/compiler/src/CFCPerlPod.c
@@ -876,6 +876,16 @@ S_convert_link(cmark_node *link, CFCClass *doc_class, int header_level) {
                 perl_name[i] = tolower(perl_name[i]);
             }
 
+            // The Perl POD only contains sections for novel methods. Link
+            // to the class where the method is declared first.
+            if (type == CFC_URI_METHOD) {
+                CFCClass *parent = CFCClass_get_parent(klass);
+                while (parent && CFCClass_method(parent, name)) {
+                    klass = parent;
+                    parent = CFCClass_get_parent(klass);
+                }
+            }
+
             if (klass == doc_class) {
                 new_uri = CFCUtil_sprintf("/%s", perl_name);
             }


[4/7] lucy-clownfish git commit: Fix C++ build

Posted by nw...@apache.org.
Fix C++ build


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

Branch: refs/heads/master
Commit: 5bb52446a547d8caff9652904f19d11ecaa577c4
Parents: 18007a3
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Dec 12 16:19:17 2015 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat Dec 12 16:19:17 2015 +0100

----------------------------------------------------------------------
 compiler/src/CFCPerlPod.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5bb52446/compiler/src/CFCPerlPod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c
index 153072d..6c2a638 100644
--- a/compiler/src/CFCPerlPod.c
+++ b/compiler/src/CFCPerlPod.c
@@ -557,7 +557,7 @@ S_camel_to_lower(const char *camel) {
         }
         alloc += 1;
     }
-    char *lower = MALLOCATE(alloc + 1);
+    char *lower = (char*)MALLOCATE(alloc + 1);
 
     lower[0] = tolower(camel[0]);
     size_t j = 1;


[7/7] lucy-clownfish git commit: Merge branch 'CLOWNFISH-64-autogenerate-code-samples'

Posted by nw...@apache.org.
Merge branch 'CLOWNFISH-64-autogenerate-code-samples'

Resolves CLOWNFISH-64.


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

Branch: refs/heads/master
Commit: 2a772809471f6168f3124421bddeef7ada9be4b9
Parents: fe23648 b35885f
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed Dec 23 13:23:39 2015 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Wed Dec 23 13:23:39 2015 +0100

----------------------------------------------------------------------
 compiler/src/CFCPerlPod.c        | 268 ++++++++++++++++++++++++++++++----
 runtime/core/Clownfish/Class.cfh |   5 +-
 2 files changed, 240 insertions(+), 33 deletions(-)
----------------------------------------------------------------------



[5/7] lucy-clownfish git commit: Fix unresolved link in POD

Posted by nw...@apache.org.
Fix unresolved link in POD


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

Branch: refs/heads/master
Commit: 39a6685700fd4db62ff7c873aea77f9d7d9d0a04
Parents: 5bb5244
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Dec 12 16:23:41 2015 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat Dec 12 16:42:29 2015 +0100

----------------------------------------------------------------------
 runtime/core/Clownfish/Class.cfh | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/39a66857/runtime/core/Clownfish/Class.cfh
----------------------------------------------------------------------
diff --git a/runtime/core/Clownfish/Class.cfh b/runtime/core/Clownfish/Class.cfh
index 704704d..f72d1a3 100644
--- a/runtime/core/Clownfish/Class.cfh
+++ b/runtime/core/Clownfish/Class.cfh
@@ -47,9 +47,8 @@ public final class Clownfish::Class inherits Clownfish::Obj {
      * the supplied class name, it will be returned.  Otherwise, a new Class
      * will be created using [parent] as a base.
      *
-     * If [parent] is NULL, an attempt will be made to find it using
-     * [](.find_parent_class).  If the attempt fails, an error will
-     * result.
+     * If [parent] is NULL, an attempt will be made to find it.  If the
+     * attempt fails, an error will result.
      */
     public inert Class*
     singleton(String *class_name, Class *parent);


[3/7] lucy-clownfish git commit: Make Clownfish URIs link to relevant POD section

Posted by nw...@apache.org.
Make Clownfish URIs link to relevant POD section


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

Branch: refs/heads/master
Commit: 18007a3a085fe51ebc12cd6b991770a0d6a17974
Parents: e2626d9
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Dec 12 15:56:31 2015 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Sat Dec 12 15:56:31 2015 +0100

----------------------------------------------------------------------
 compiler/src/CFCPerlPod.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/18007a3a/compiler/src/CFCPerlPod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerlPod.c b/compiler/src/CFCPerlPod.c
index 7388cea..153072d 100644
--- a/compiler/src/CFCPerlPod.c
+++ b/compiler/src/CFCPerlPod.c
@@ -871,22 +871,24 @@ S_convert_link(cmark_node *link, CFCClass *doc_class, int header_level) {
                 break;
             }
 
-            // TODO: Link to relevant POD section. This isn't easy because
-            // the section headers for functions also contain a description
-            // of the parameters.
+            char *perl_name = CFCUtil_strdup(name);
+            for (size_t i = 0; perl_name[i] != '\0'; ++i) {
+                perl_name[i] = tolower(perl_name[i]);
+            }
 
-            if (klass != doc_class) {
+            if (klass == doc_class) {
+                new_uri = CFCUtil_sprintf("/%s", perl_name);
+            }
+            else {
                 const char *class_name = CFCClass_get_name(klass);
-                new_uri = CFCUtil_strdup(class_name);
+                new_uri = CFCUtil_sprintf("%s/%s", class_name, perl_name);
             }
 
             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]);
-                }
+                new_text = CFCUtil_sprintf("%s()", perl_name);
             }
 
+            FREEMEM(perl_name);
             break;
         }