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 2016/08/01 11:40:10 UTC

[1/5] lucy-clownfish git commit: Derive XS prereqs from parcel prereqs

Repository: lucy-clownfish
Updated Branches:
  refs/heads/master 6b9abca6f -> dba8fd508


Derive XS prereqs from parcel prereqs

Add "host_module_name" to host-specific JSON and use it to derive
XS prereqs automatically.


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

Branch: refs/heads/master
Commit: 9bcba44b6a6cf5b0332ed33c9da7ac81e079692f
Parents: 9e1d783
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Wed Jul 20 14:36:33 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 22 16:06:48 2016 +0200

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC.xs            |  6 +++
 compiler/perl/lib/Clownfish/CFC/Perl/Build.pm | 53 ++++++++++++++++++----
 compiler/src/CFCBindCore.c                    | 27 +++++++++--
 compiler/src/CFCParcel.c                      | 46 +++++++++++++++----
 compiler/src/CFCParcel.h                      |  6 +++
 compiler/src/CFCPerl.c                        | 11 ++++-
 runtime/perl/buildlib/Clownfish/Build.pm      |  1 -
 7 files changed, 126 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bcba44b/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.xs b/compiler/perl/lib/Clownfish/CFC.xs
index 6292f01..8caa0b7 100644
--- a/compiler/perl/lib/Clownfish/CFC.xs
+++ b/compiler/perl/lib/Clownfish/CFC.xs
@@ -1192,6 +1192,7 @@ ALIAS:
     included          = 16
     prereq_parcels    = 20
     inherited_parcels = 22
+    get_xs_module     = 24
 PPCODE:
 {
     START_SET_OR_GET_SWITCH
@@ -1245,6 +1246,11 @@ PPCODE:
                 FREEMEM(parcels);
             }
             break;
+        case 24: {
+                const char *xs_module = CFCParcel_get_host_module_name(self);
+                retval = newSVpvn(xs_module, strlen(xs_module));
+            }
+            break;
     END_SET_OR_GET_SWITCH
 }
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bcba44b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
index 96d1d88..58b9296 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
@@ -399,8 +399,8 @@ sub _compile_custom_xs {
         push @$c_files, @{ $self->rscan_dir( $source_dir, qr/\.c$/ ) };
     }
     my $autogen_src_dir = catdir( $AUTOGEN_DIR, 'source' );
-    for my $parcel ( @{ $module->{parcels} } ) {
-        $parcel = Clownfish::CFC::Model::Parcel->acquire($parcel);
+    for my $parcel_name ( @{ $module->{parcels} } ) {
+        my $parcel = Clownfish::CFC::Model::Parcel->acquire($parcel_name);
         my $prefix = $parcel->get_prefix;
         # Assume *_parcel.c is built with make.
         push @$c_files, catfile( $autogen_src_dir, "${prefix}parcel.c" )
@@ -490,10 +490,8 @@ sub _compile_custom_xs {
     my $lib_file = catfile( $archdir, "$class_name.$Config{dlext}" );
     if ( !$self->up_to_date( [ @objects, $AUTOGEN_DIR ], $lib_file ) ) {
         my $linker_flags = $self->extra_linker_flags;
-        if ( $module->{xs_prereqs} ) {
-            push @$linker_flags,
-                 $self->cf_linker_flags( @{ $module->{xs_prereqs} } );
-        }
+        my @xs_prereqs = $self->_cf_find_xs_prereqs($module);
+        push @$linker_flags, $self->cf_linker_flags(@xs_prereqs);
         $cbuilder->link(
             module_name        => $module_name,
             objects            => \@objects,
@@ -512,6 +510,47 @@ sub _compile_custom_xs {
     }
 }
 
+sub _cf_find_xs_prereqs {
+    my ( $self, $module ) = @_;
+
+    my $modules = $self->clownfish_params('modules');
+    my @xs_prereqs;
+
+    for my $parcel_name ( @{ $module->{parcels} } ) {
+        my $parcel = Clownfish::CFC::Model::Parcel->acquire($parcel_name);
+
+        for my $prereq_parcel ( @{ $parcel->prereq_parcels } ) {
+            my $prereq_module;
+
+            if ($prereq_parcel->included) {
+                $prereq_module = $prereq_parcel->get_xs_module;
+            }
+            else {
+                my $prereq_parcel_name = $prereq_parcel->get_name;
+
+                for my $candidate (@$modules) {
+                    my @matches = grep {
+                        $_ eq $prereq_parcel_name
+                    } @{ $candidate->{parcels} };
+
+                    if (@matches) {
+                        $prereq_module = $candidate->{name};
+                        last;
+                    }
+                }
+            }
+
+            die("No XS module found for parcel $parcel_name")
+                if !defined($prereq_module);
+            push @xs_prereqs, $prereq_module
+                if $prereq_module ne $module->{name}
+                   && !grep { $_ eq $prereq_module } @xs_prereqs;
+        }
+    }
+
+    return @xs_prereqs;
+}
+
 sub ACTION_code {
     my $self = shift;
 
@@ -629,12 +668,10 @@ the Perl bindings for Clownfish modules.
                     name          => 'My::Module',
                     c_source_dirs => 'xs',
                     parcels       => [ 'MyModule' ],
-                    xs_prereqs    => [ 'Clownfish' ],
                 },
                 {
                     name          => 'My::Module::Test',
                     parcels       => [ 'TestMyModule' ],
-                    xs_prereqs    => [ 'Clownfish', 'My::Module' ],
                 },
             ],
         },

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bcba44b/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindCore.c b/compiler/src/CFCBindCore.c
index ecdc091..95e0206 100644
--- a/compiler/src/CFCBindCore.c
+++ b/compiler/src/CFCBindCore.c
@@ -783,6 +783,15 @@ S_write_host_data_json(CFCBindCore *self, CFCParcel *parcel,
     const char *parcel_name = CFCParcel_get_name(parcel);
     CFCVersion *version     = CFCParcel_get_version(parcel);
     const char *vstring     = CFCVersion_get_vstring(version);
+    char       *json_pairs  = CFCUtil_strdup("");
+
+    const char *host_module_name = CFCParcel_get_host_module_name(parcel);
+    if (host_module_name != NULL) {
+        const char *pattern = "    \"host_module\": \"%s\"";
+        char *pair = CFCUtil_sprintf(pattern, host_module_name);
+        json_pairs = CFCUtil_cat(json_pairs, pair, NULL);
+        FREEMEM(pair);
+    }
 
     char *classes_json = CFCUtil_strdup("");
     CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
@@ -805,25 +814,35 @@ S_write_host_data_json(CFCBindCore *self, CFCParcel *parcel,
     }
     FREEMEM(ordered);
 
+    if (classes_json[0] != '\0') {
+        const char *pattern =
+            "    \"classes\": {\n"
+            "%s\n"
+            "    }";
+        char *pair = CFCUtil_sprintf(pattern, classes_json);
+        const char *sep = json_pairs[0] == '\0' ? "" : ",\n";
+        json_pairs = CFCUtil_cat(json_pairs, sep, pair, NULL);
+        FREEMEM(pair);
+    }
+
     char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "%s" CHY_DIR_SEP "%s"
                                      CHY_DIR_SEP "parcel_%s.json", dest_dir,
                                      parcel_name, vstring, host_lang);
     remove(filepath);
 
-    if (classes_json[0] != '\0') {
+    if (json_pairs[0] != '\0') {
         const char *pattern =
             "{\n"
-            "    \"classes\": {\n"
             "%s\n"
-            "    }\n"
             "}\n";
-        char *json = CFCUtil_sprintf(pattern, classes_json);
+        char *json = CFCUtil_sprintf(pattern, json_pairs);
         CFCUtil_write_file(filepath, json, strlen(json));
         FREEMEM(json);
     }
 
     FREEMEM(filepath);
     FREEMEM(classes_json);
+    FREEMEM(json_pairs);
 }
 
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bcba44b/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.c b/compiler/src/CFCParcel.c
index c8e74f4..25cc77c 100644
--- a/compiler/src/CFCParcel.c
+++ b/compiler/src/CFCParcel.c
@@ -35,6 +35,7 @@ struct CFCParcel {
     CFCBase base;
     char *name;
     char *nickname;
+    char *host_module_name;
     CFCVersion *version;
     CFCVersion *major_version;
     CFCFileSpec *file_spec;
@@ -357,6 +358,7 @@ void
 CFCParcel_destroy(CFCParcel *self) {
     FREEMEM(self->name);
     FREEMEM(self->nickname);
+    FREEMEM(self->host_module_name);
     CFCBase_decref((CFCBase*)self->version);
     CFCBase_decref((CFCBase*)self->major_version);
     CFCBase_decref((CFCBase*)self->file_spec);
@@ -396,6 +398,24 @@ CFCParcel_get_nickname(CFCParcel *self) {
     return self->nickname;
 }
 
+const char*
+CFCParcel_get_host_module_name(CFCParcel *self) {
+    return self->host_module_name;
+}
+
+void
+CFCParcel_set_host_module_name(CFCParcel *self, const char *name) {
+    if (self->host_module_name != NULL) {
+        if (strcmp(self->host_module_name, name) != 0) {
+            CFCUtil_die("Conflicting host modules '%s' and '%s' for parcel %s",
+                        self->host_module_name, name, self->name);
+        }
+    }
+    else {
+        self->host_module_name = CFCUtil_strdup(name);
+    }
+}
+
 int
 CFCParcel_is_installed(CFCParcel *self) {
     return self->is_installed;
@@ -532,17 +552,25 @@ CFCParcel_read_host_data_json(CFCParcel *self, const char *host_lang) {
     if (!extra_data) {
         CFCUtil_die("Invalid JSON in file '%s'", path);
     }
+
+    CFCJson *host_module_json
+        = CFCJson_find_hash_elem(extra_data, "host_module");
+    if (host_module_json) {
+        const char *name = CFCJson_get_string(host_module_json);
+        CFCParcel_set_host_module_name(self, name);
+    }
+
     CFCJson *class_hash = CFCJson_find_hash_elem(extra_data, "classes");
-    if (!class_hash) { return; }
-
-    CFCJson **children = CFCJson_get_children(class_hash);
-    for (int i = 0; children[i]; i += 2) {
-        const char *class_name = CFCJson_get_string(children[i]);
-        CFCClass *klass = CFCClass_fetch_singleton(class_name);
-        if (!klass) {
-            CFCUtil_die("Class '%s' in '%s' not found", class_name, path);
+    if (class_hash) {
+        CFCJson **children = CFCJson_get_children(class_hash);
+        for (int i = 0; children[i]; i += 2) {
+            const char *class_name = CFCJson_get_string(children[i]);
+            CFCClass *klass = CFCClass_fetch_singleton(class_name);
+            if (!klass) {
+                CFCUtil_die("Class '%s' in '%s' not found", class_name, path);
+            }
+            CFCClass_read_host_data_json(klass, children[i+1], path);
         }
-        CFCClass_read_host_data_json(klass, children[i+1], path);
     }
 
     CFCJson_destroy(extra_data);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bcba44b/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.h b/compiler/src/CFCParcel.h
index da86703..d173079 100644
--- a/compiler/src/CFCParcel.h
+++ b/compiler/src/CFCParcel.h
@@ -90,6 +90,12 @@ CFCParcel_get_name(CFCParcel *self);
 const char*
 CFCParcel_get_nickname(CFCParcel *self);
 
+const char*
+CFCParcel_get_host_module_name(CFCParcel *self);
+
+void
+CFCParcel_set_host_module_name(CFCParcel *self, const char *name);
+
 int
 CFCParcel_is_installed(CFCParcel *self);
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bcba44b/compiler/src/CFCPerl.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCPerl.c b/compiler/src/CFCPerl.c
index 62a7f48..e9ef8bd 100644
--- a/compiler/src/CFCPerl.c
+++ b/compiler/src/CFCPerl.c
@@ -540,14 +540,21 @@ CFCPerl_write_bindings(CFCPerl *self, const char *boot_class,
     char *hand_rolled_xs  = CFCUtil_strdup("");
 
     for (size_t i = 0; parcels[i]; ++i) {
+        CFCParcel *parcel = parcels[i];
+
+        // Set host_module_name for parcel.
+        if (!CFCParcel_included(parcel) && CFCParcel_is_installed(parcel)) {
+            CFCParcel_set_host_module_name(parcel, boot_class);
+        }
+
         // Bake the parcel privacy defines into the XS, so it can be compiled
         // without any extra compiler flags.
-        const char *privacy_sym = CFCParcel_get_privacy_sym(parcels[i]);
+        const char *privacy_sym = CFCParcel_get_privacy_sym(parcel);
         privacy_syms = CFCUtil_cat(privacy_syms, "#define ", privacy_sym,
                                    "\n", NULL);
 
         // Bootstrap calls.
-        const char *prefix = CFCParcel_get_prefix(parcels[i]);
+        const char *prefix = CFCParcel_get_prefix(parcel);
         includes = CFCUtil_cat(includes, "#include \"", prefix, "perl.h\"\n",
                                NULL);
         bootstrap_calls = CFCUtil_cat(bootstrap_calls, "    ", prefix,

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9bcba44b/runtime/perl/buildlib/Clownfish/Build.pm
----------------------------------------------------------------------
diff --git a/runtime/perl/buildlib/Clownfish/Build.pm b/runtime/perl/buildlib/Clownfish/Build.pm
index 0efe35a..c038ebc 100644
--- a/runtime/perl/buildlib/Clownfish/Build.pm
+++ b/runtime/perl/buildlib/Clownfish/Build.pm
@@ -85,7 +85,6 @@ sub new {
                 name          => 'Clownfish::Test',
                 parcels       => [ 'TestClownfish' ],
                 make_target   => 'test_objects',
-                xs_prereqs    => [ 'Clownfish' ],
             },
         ],
     };


[2/5] lucy-clownfish git commit: Read host-specific data for included parcels from JSON

Posted by nw...@apache.org.
Read host-specific data for included parcels from JSON

Remove inherit_metadata hack.


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

Branch: refs/heads/master
Commit: 9e1d783a11c2c96a579f7546f25fd42c6223e457
Parents: bff120c
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Mar 19 19:59:42 2016 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 22 16:06:48 2016 +0200

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC.pm            | 33 ----------------------
 compiler/perl/lib/Clownfish/CFC.xs            |  6 ++++
 compiler/perl/lib/Clownfish/CFC/Perl/Build.pm |  1 +
 compiler/src/CFCClass.c                       | 17 +++++++++++
 compiler/src/CFCClass.h                       |  7 +++++
 compiler/src/CFCHierarchy.c                   | 19 +++++++++----
 compiler/src/CFCHierarchy.h                   |  5 ++++
 compiler/src/CFCMethod.c                      | 30 ++++++++++++++++++++
 compiler/src/CFCMethod.h                      |  7 +++++
 compiler/src/CFCParcel.c                      | 31 ++++++++++++++++++++
 compiler/src/CFCParcel.h                      |  5 ++++
 11 files changed, 123 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/perl/lib/Clownfish/CFC.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.pm b/compiler/perl/lib/Clownfish/CFC.pm
index c38c3c3..d869e00 100644
--- a/compiler/perl/lib/Clownfish/CFC.pm
+++ b/compiler/perl/lib/Clownfish/CFC.pm
@@ -237,39 +237,6 @@ BEGIN { XSLoader::load( 'Clownfish::CFC', '0.5.0' ) }
         verify_args( \%new_PARAMS, %args ) or confess $@;
         return _new( @args{qw( dest )} );
     }
-
-    # Recreate host language specific metadata of dependencies.
-    #
-    # TODO: This should be done automatically when building the hierarchy.
-    # But since the current approach relies on runtime introspection, the Perl
-    # modules for all dependencies must first be loaded.
-    sub inherit_metadata {
-        my $self = shift;
-
-        require Clownfish;
-
-        for my $class (@{ $self->ordered_classes }) {
-            next if !$class->included || $class->inert;
-
-            my $class_name = $class->get_name;
-            my $rt_class = Clownfish::Class->fetch_class($class_name)
-                or die("Class $class_name not found");
-
-            for my $rt_method (@{ $rt_class->get_methods }) {
-                if ($rt_method->is_excluded_from_host) {
-                    my $method = $class->method($rt_method->get_name);
-                    $method->exclude_from_host;
-                }
-                else {
-                    my $alias = $rt_method->get_host_alias;
-                    if (defined($alias)) {
-                        my $method = $class->method($rt_method->get_name);
-                        $method->set_host_alias($alias);
-                    }
-                }
-            }
-        }
-    }
 }
 
 {

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.xs b/compiler/perl/lib/Clownfish/CFC.xs
index 3fda1c7..6292f01 100644
--- a/compiler/perl/lib/Clownfish/CFC.xs
+++ b/compiler/perl/lib/Clownfish/CFC.xs
@@ -764,6 +764,12 @@ build(self)
 PPCODE:
     CFCHierarchy_build(self);
 
+void
+read_host_data_json(self)
+    CFCHierarchy *self;
+PPCODE:
+    CFCHierarchy_read_host_data_json(self, "perl");
+
 int
 propagate_modified(self, ...)
     CFCHierarchy *self;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
index ef0e0f3..96d1d88 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
@@ -223,6 +223,7 @@ sub _compile_clownfish {
         $hierarchy->add_include_dir($include_dir);
     }
     $hierarchy->build;
+    $hierarchy->read_host_data_json;
 
     # Process all Binding classes in buildlib.
     my $pm_filepaths = $self->rscan_dir( $BUILDLIB_DIR, qr/\.pm$/ );

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.c b/compiler/src/CFCClass.c
index 7fa7ff0..ea39848 100644
--- a/compiler/src/CFCClass.c
+++ b/compiler/src/CFCClass.c
@@ -33,6 +33,7 @@
 #include "CFCUtil.h"
 #include "CFCVariable.h"
 #include "CFCFileSpec.h"
+#include "CFCJson.h"
 
 static CFCClass **registry = NULL;
 static size_t registry_size = 0;
@@ -741,6 +742,22 @@ CFCClass_tree_to_ladder(CFCClass *self) {
     return ladder;
 }
 
+void
+CFCClass_read_host_data_json(CFCClass *self, CFCJson *hash, const char *path) {
+    CFCJson *method_hash = CFCJson_find_hash_elem(hash, "methods");
+    if (!method_hash) { return; }
+
+    CFCJson **children = CFCJson_get_children(method_hash);
+    for (int i = 0; children[i]; i += 2) {
+        const char *method_name = CFCJson_get_string(children[i]);
+        CFCMethod *method = CFCClass_method(self, method_name);
+        if (!method) {
+            CFCUtil_die("Method '%s' in '%s' not found", method_name, path);
+        }
+        CFCMethod_read_host_data_json(method, children[i+1], path);
+    }
+}
+
 CFCMethod**
 CFCClass_fresh_methods(CFCClass *self) {
     return self->fresh_methods;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCClass.h b/compiler/src/CFCClass.h
index 5da05f5..91fa0cf 100644
--- a/compiler/src/CFCClass.h
+++ b/compiler/src/CFCClass.h
@@ -37,6 +37,7 @@ struct CFCFunction;
 struct CFCMethod;
 struct CFCVariable;
 struct CFCFileSpec;
+struct CFCJson;
 
 /** Return true if the string is a valid class name.
  */
@@ -167,6 +168,12 @@ CFCClass_grow_tree(CFCClass *self);
 CFCClass**
 CFCClass_tree_to_ladder(CFCClass *self);
 
+/** Read host-specific data for the class from a JSON hash.
+ */
+void
+CFCClass_read_host_data_json(CFCClass *self, struct CFCJson *hash,
+                            const char *path);
+
 /** Return an array of all methods implemented in this class.
  * Must not be freed by the caller.
  */

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCHierarchy.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCHierarchy.c b/compiler/src/CFCHierarchy.c
index c33c4f8..19a45ec 100644
--- a/compiler/src/CFCHierarchy.c
+++ b/compiler/src/CFCHierarchy.c
@@ -528,11 +528,7 @@ S_extract_path_part(const char *path, const char *dir, const char *ext) {
         --path_part_len;
     }
 
-    char *path_part = (char*)MALLOCATE(path_part_len + 1);
-    memcpy(path_part, src, path_part_len);
-    path_part[path_part_len] = '\0';
-
-    return path_part;
+    return CFCUtil_strndup(src, path_part_len);
 }
 
 static void
@@ -561,6 +557,19 @@ S_connect_classes(CFCHierarchy *self) {
     }
 }
 
+void
+CFCHierarchy_read_host_data_json(CFCHierarchy *self, const char *host_lang) {
+    CHY_UNUSED_VAR(self);
+    CFCParcel **parcels = CFCParcel_all_parcels();
+
+    for (int i = 0; parcels[i]; ++i) {
+        CFCParcel *parcel = parcels[i];
+        if (CFCParcel_included(parcel)) {
+            CFCParcel_read_host_data_json(parcel, host_lang);
+        }
+    }
+}
+
 int
 CFCHierarchy_propagate_modified(CFCHierarchy *self, int modified) {
     // Seed the recursive write.

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCHierarchy.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCHierarchy.h b/compiler/src/CFCHierarchy.h
index ed9df25..4177cc4 100644
--- a/compiler/src/CFCHierarchy.h
+++ b/compiler/src/CFCHierarchy.h
@@ -68,6 +68,11 @@ CFCHierarchy_add_prereq(CFCHierarchy *self, const char *parcel);
 void
 CFCHierarchy_build(CFCHierarchy *self);
 
+/** Read host-specific data for included parcels.
+ */
+void
+CFCHierarchy_read_host_data_json(CFCHierarchy *self, const char *host_lang);
+
 /** Visit all File objects in the hierarchy.  If a parent node is modified, mark
  * all of its children as modified.
  *

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCMethod.c b/compiler/src/CFCMethod.c
index a8585fb..1d449e4 100644
--- a/compiler/src/CFCMethod.c
+++ b/compiler/src/CFCMethod.c
@@ -26,6 +26,7 @@
 #include "CFCParamList.h"
 #include "CFCDocuComment.h"
 #include "CFCVariable.h"
+#include "CFCJson.h"
 
 #ifndef true
     #define true 1
@@ -252,6 +253,35 @@ CFCMethod_can_be_bound(CFCMethod *method) {
 }
 
 void
+CFCMethod_read_host_data_json(CFCMethod *self, CFCJson *hash,
+                              const char *path) {
+    int         excluded = false;
+    const char *alias    = NULL;
+
+    CFCJson **children = CFCJson_get_children(hash);
+    for (int i = 0; children[i]; i += 2) {
+        const char *key = CFCJson_get_string(children[i]);
+
+        if (strcmp(key, "excluded") == 0) {
+            excluded = CFCJson_get_bool(children[i+1]);
+        }
+        else if (strcmp(key, "alias") == 0) {
+            alias = CFCJson_get_string(children[i+1]);
+        }
+        else {
+            CFCUtil_die("Unexpected key '%s' in '%s'", key, path);
+        }
+    }
+
+    if (excluded) {
+        CFCMethod_exclude_from_host(self);
+    }
+    else if (alias) {
+        CFCMethod_set_host_alias(self, alias);
+    }
+}
+
+void
 CFCMethod_set_host_alias(CFCMethod *self, const char *alias) {
     if (!alias || !alias[0]) {
         CFCUtil_die("Missing required param 'alias'");

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCMethod.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCMethod.h b/compiler/src/CFCMethod.h
index 643a10d..37c4773 100644
--- a/compiler/src/CFCMethod.h
+++ b/compiler/src/CFCMethod.h
@@ -37,6 +37,7 @@ struct CFCType;
 struct CFCClass;
 struct CFCParamList;
 struct CFCDocuComment;
+struct CFCJson;
 
 /**
  * @param exposure See Clownfish::CFC::Model::Symbol.  Defaults to "parcel"
@@ -106,6 +107,12 @@ CFCMethod_finalize(CFCMethod *self);
 int
 CFCMethod_can_be_bound(CFCMethod *method);
 
+/** Read host-specific data for the method from a JSON hash.
+ */
+void
+CFCMethod_read_host_data_json(CFCMethod *self, struct CFCJson *hash,
+                              const char *path);
+
 /**
  * Find the first declaration of the method in the class hierarchy.
  */

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCParcel.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.c b/compiler/src/CFCParcel.c
index 3b79d71..c8e74f4 100644
--- a/compiler/src/CFCParcel.c
+++ b/compiler/src/CFCParcel.c
@@ -29,6 +29,7 @@
 #include "CFCVersion.h"
 #include "CFCUtil.h"
 #include "CFCJson.h"
+#include "CFCClass.h"
 
 struct CFCParcel {
     CFCBase base;
@@ -520,6 +521,36 @@ CFCParcel_has_prereq(CFCParcel *self, CFCParcel *parcel) {
 }
 
 void
+CFCParcel_read_host_data_json(CFCParcel *self, const char *host_lang) {
+    const char *source_dir = CFCParcel_get_source_dir(self);
+    char *path = CFCUtil_sprintf("%s" CHY_DIR_SEP "parcel_%s.json", source_dir,
+                                 host_lang);
+
+    size_t len;
+    char *json = CFCUtil_slurp_text(path, &len);
+    CFCJson *extra_data = CFCJson_parse(json);
+    if (!extra_data) {
+        CFCUtil_die("Invalid JSON in file '%s'", path);
+    }
+    CFCJson *class_hash = CFCJson_find_hash_elem(extra_data, "classes");
+    if (!class_hash) { return; }
+
+    CFCJson **children = CFCJson_get_children(class_hash);
+    for (int i = 0; children[i]; i += 2) {
+        const char *class_name = CFCJson_get_string(children[i]);
+        CFCClass *klass = CFCClass_fetch_singleton(class_name);
+        if (!klass) {
+            CFCUtil_die("Class '%s' in '%s' not found", class_name, path);
+        }
+        CFCClass_read_host_data_json(klass, children[i+1], path);
+    }
+
+    CFCJson_destroy(extra_data);
+    FREEMEM(json);
+    FREEMEM(path);
+}
+
+void
 CFCParcel_add_struct_sym(CFCParcel *self, const char *struct_sym) {
     size_t num_struct_syms = self->num_struct_syms + 1;
     size_t size = (num_struct_syms + 1) * sizeof(char*);

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/9e1d783a/compiler/src/CFCParcel.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCParcel.h b/compiler/src/CFCParcel.h
index ddcc2bd..da86703 100644
--- a/compiler/src/CFCParcel.h
+++ b/compiler/src/CFCParcel.h
@@ -164,6 +164,11 @@ CFCParcel_prereq_parcels(CFCParcel *self);
 int
 CFCParcel_has_prereq(CFCParcel *self, CFCParcel *parcel);
 
+/** Read host-specific data for an included parcel from a JSON file.
+ */
+void
+CFCParcel_read_host_data_json(CFCParcel *self, const char *host_lang);
+
 void
 CFCParcel_add_struct_sym(CFCParcel *self, const char *struct_sym);
 


[4/5] lucy-clownfish git commit: Implement CFCJson_find_hash_elem

Posted by nw...@apache.org.
Implement CFCJson_find_hash_elem


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

Branch: refs/heads/master
Commit: bff120c521ce1f2ce09a438069a55cb077124efa
Parents: 8ac4a06
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Mar 19 19:58:50 2016 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 22 16:06:48 2016 +0200

----------------------------------------------------------------------
 compiler/src/CFCJson.c | 15 +++++++++++++++
 compiler/src/CFCJson.h |  3 +++
 2 files changed, 18 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bff120c5/compiler/src/CFCJson.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCJson.c b/compiler/src/CFCJson.c
index 262b943..1f3a396 100644
--- a/compiler/src/CFCJson.c
+++ b/compiler/src/CFCJson.c
@@ -277,3 +277,18 @@ CFCJson_get_children(CFCJson *self) {
     return self->kids;
 }
 
+CFCJson*
+CFCJson_find_hash_elem(CFCJson *self, const char *key) {
+    if (self->type != CFCJSON_HASH) {
+        CFCUtil_die("Not a JSON hash");
+    }
+
+    for (int i = 0; self->kids[i]; i += 2) {
+        if (strcmp(self->kids[i]->string, key) == 0) {
+            return self->kids[i+1];
+        }
+    }
+
+    return NULL;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/bff120c5/compiler/src/CFCJson.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCJson.h b/compiler/src/CFCJson.h
index 97d7081..052a1b8 100644
--- a/compiler/src/CFCJson.h
+++ b/compiler/src/CFCJson.h
@@ -49,6 +49,9 @@ CFCJson_get_num_children(CFCJson *self);
 CFCJson**
 CFCJson_get_children(CFCJson *self);
 
+CFCJson*
+CFCJson_find_hash_elem(CFCJson *self, const char *key);
+
 #ifdef __cplusplus
 }
 #endif


[5/5] lucy-clownfish git commit: Merge branch 'host-data-json'

Posted by nw...@apache.org.
Merge branch 'host-data-json'

Fixes CLOWNFISH-83.


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

Branch: refs/heads/master
Commit: dba8fd50867ecb2025f48c36e7882b8bc054fe46
Parents: 6b9abca 9bcba44
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Mon Aug 1 13:38:46 2016 +0200
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Mon Aug 1 13:38:46 2016 +0200

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC.pm            | 33 ---------
 compiler/perl/lib/Clownfish/CFC.xs            | 19 +++++
 compiler/perl/lib/Clownfish/CFC/Perl/Build.pm | 59 ++++++++++++---
 compiler/src/CFCBindClass.c                   | 38 ++++++++++
 compiler/src/CFCBindClass.h                   |  5 ++
 compiler/src/CFCBindCore.c                    | 86 ++++++++++++++++++++++
 compiler/src/CFCBindCore.h                    |  6 ++
 compiler/src/CFCBindMethod.c                  | 34 +++++++++
 compiler/src/CFCBindMethod.h                  |  6 ++
 compiler/src/CFCClass.c                       | 17 +++++
 compiler/src/CFCClass.h                       |  7 ++
 compiler/src/CFCHierarchy.c                   | 19 +++--
 compiler/src/CFCHierarchy.h                   |  5 ++
 compiler/src/CFCJson.c                        | 15 ++++
 compiler/src/CFCJson.h                        |  3 +
 compiler/src/CFCMethod.c                      | 30 ++++++++
 compiler/src/CFCMethod.h                      |  7 ++
 compiler/src/CFCParcel.c                      | 59 +++++++++++++++
 compiler/src/CFCParcel.h                      | 11 +++
 compiler/src/CFCPerl.c                        | 11 ++-
 runtime/perl/buildlib/Clownfish/Build.pm      |  1 -
 21 files changed, 420 insertions(+), 51 deletions(-)
----------------------------------------------------------------------



[3/5] lucy-clownfish git commit: Write host aliases and exclusions to parcel_perl.json

Posted by nw...@apache.org.
Write host aliases and exclusions to parcel_perl.json

Write host-specific data like method aliases and exclusions to a JSON
file for each parcel. This file is installed in the Clownfish include
directory.


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

Branch: refs/heads/master
Commit: 8ac4a0642e2b1d6bb694c9f84804d6ee99314870
Parents: 6b9abca
Author: Nick Wellnhofer <we...@aevum.de>
Authored: Sat Mar 12 17:23:49 2016 +0100
Committer: Nick Wellnhofer <we...@aevum.de>
Committed: Fri Jul 22 16:06:48 2016 +0200

----------------------------------------------------------------------
 compiler/perl/lib/Clownfish/CFC.xs            |  7 +++
 compiler/perl/lib/Clownfish/CFC/Perl/Build.pm |  5 +-
 compiler/src/CFCBindClass.c                   | 38 ++++++++++++
 compiler/src/CFCBindClass.h                   |  5 ++
 compiler/src/CFCBindCore.c                    | 67 ++++++++++++++++++++++
 compiler/src/CFCBindCore.h                    |  6 ++
 compiler/src/CFCBindMethod.c                  | 34 +++++++++++
 compiler/src/CFCBindMethod.h                  |  6 ++
 8 files changed, 166 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/perl/lib/Clownfish/CFC.xs
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC.xs b/compiler/perl/lib/Clownfish/CFC.xs
index 74bce9d..3fda1c7 100644
--- a/compiler/perl/lib/Clownfish/CFC.xs
+++ b/compiler/perl/lib/Clownfish/CFC.xs
@@ -1884,6 +1884,13 @@ copy_headers(self, dest_dir)
 PPCODE:
     CFCBindCore_copy_headers(self, dest_dir);
 
+void
+write_host_data_json(self, dest_dir)
+    CFCBindCore *self;
+    const char *dest_dir;
+PPCODE:
+    CFCBindCore_write_host_data_json(self, dest_dir, "perl");
+
 
 MODULE = Clownfish::CFC  PACKAGE = Clownfish::CFC::Binding::Core::Function
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
----------------------------------------------------------------------
diff --git a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
index f1c351f..ef0e0f3 100644
--- a/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
+++ b/compiler/perl/lib/Clownfish/CFC/Perl/Build.pm
@@ -288,14 +288,13 @@ sub ACTION_clownfish {
         footer    => '',
     );
     print "Writing Clownfish autogenerated files...\n";
+    my $inc_dir = catdir( $self->blib, 'arch', 'Clownfish', '_include' );
     my $cfh_modified = $core_binding->write_all_modified;
     if ($cfh_modified) {
         unlink('typemap');
         print "Writing typemap...\n";
         $self->add_to_cleanup('typemap');
         $perl_binding->write_xs_typemap;
-
-        my $inc_dir = catdir( $self->blib, 'arch', 'Clownfish', '_include' );
         $core_binding->copy_headers($inc_dir);
     }
 
@@ -316,6 +315,8 @@ sub ACTION_clownfish {
             );
         }
 
+        $core_binding->write_host_data_json($inc_dir);
+
         print "Writing POD...\n";
         my $pod_files = $perl_binding->write_pod;
         $self->add_to_cleanup($_) for @$pod_files;

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/src/CFCBindClass.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindClass.c b/compiler/src/CFCBindClass.c
index ac8b8fd..75b77e9 100644
--- a/compiler/src/CFCBindClass.c
+++ b/compiler/src/CFCBindClass.c
@@ -642,3 +642,41 @@ S_short_names(CFCBindClass *self) {
     return short_names;
 }
 
+char*
+CFCBindClass_host_data_json(CFCBindClass *self) {
+    if (CFCClass_final(self->client)) { return CFCUtil_strdup(""); }
+
+    CFCMethod **fresh_methods = CFCClass_fresh_methods(self->client);
+    char *methods_json = CFCUtil_strdup("");
+
+    for (int i = 0; fresh_methods[i] != NULL; i++) {
+        CFCMethod *method = fresh_methods[i];
+        char *method_json = CFCBindMeth_host_data_json(method);
+        if (method_json[0] != '\0') {
+            const char *sep = methods_json[0] == '\0' ? "" : ",\n";
+            methods_json = CFCUtil_cat(methods_json, sep, method_json, NULL);
+        }
+        FREEMEM(method_json);
+    }
+
+    char *json;
+
+    if (methods_json[0] == '\0') {
+        json = CFCUtil_strdup("");
+    }
+    else {
+        const char *class_name = CFCClass_get_name(self->client);
+
+        const char *pattern =
+            "        \"%s\": {\n"
+            "            \"methods\": {\n"
+            "%s\n"
+            "            }\n"
+            "        }";
+        json = CFCUtil_sprintf(pattern, class_name, methods_json);
+    }
+
+    FREEMEM(methods_json);
+    return json;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/src/CFCBindClass.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindClass.h b/compiler/src/CFCBindClass.h
index 4780bdc..450e0aa 100644
--- a/compiler/src/CFCBindClass.h
+++ b/compiler/src/CFCBindClass.h
@@ -54,6 +54,11 @@ CFCBindClass_to_c_header(CFCBindClass *self);
 char*
 CFCBindClass_to_c_data(CFCBindClass *self);
 
+/** Return host-specific data for the class as JSON fragment.
+ */
+char*
+CFCBindClass_host_data_json(CFCBindClass *self);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/src/CFCBindCore.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindCore.c b/compiler/src/CFCBindCore.c
index c835cc9..ecdc091 100644
--- a/compiler/src/CFCBindCore.c
+++ b/compiler/src/CFCBindCore.c
@@ -74,6 +74,10 @@ S_charmony_stdint_defines();
 static char*
 S_charmony_alloca_defines();
 
+static void
+S_write_host_data_json(CFCBindCore *self, CFCParcel *parcel,
+                       const char *dest_dir, const char *host_lang);
+
 static const CFCMeta CFCBINDCORE_META = {
     "Clownfish::CFC::Binding::Core",
     sizeof(CFCBindCore),
@@ -759,4 +763,67 @@ CFCBindCore_copy_headers(CFCBindCore *self, const char *dest_dir) {
     FREEMEM(default_dest);
 }
 
+void
+CFCBindCore_write_host_data_json(CFCBindCore *self, const char *dest_dir,
+                                 const char *host_lang) {
+    CFCParcel **parcels = CFCParcel_all_parcels();
+
+    for (size_t i = 0; parcels[i] != NULL; i++) {
+        CFCParcel *parcel = parcels[i];
+        if (!CFCParcel_included(parcel) && CFCParcel_is_installed(parcel)) {
+            S_write_host_data_json(self, parcel, dest_dir, host_lang);
+        }
+    }
+}
+
+static void
+S_write_host_data_json(CFCBindCore *self, CFCParcel *parcel,
+                       const char *dest_dir, const char *host_lang) {
+    const char *prefix      = CFCParcel_get_prefix(parcel);
+    const char *parcel_name = CFCParcel_get_name(parcel);
+    CFCVersion *version     = CFCParcel_get_version(parcel);
+    const char *vstring     = CFCVersion_get_vstring(version);
+
+    char *classes_json = CFCUtil_strdup("");
+    CFCClass **ordered = CFCHierarchy_ordered_classes(self->hierarchy);
+
+    for (size_t i = 0; ordered[i] != NULL; i++) {
+        CFCClass *klass = ordered[i];
+        const char *class_prefix = CFCClass_get_prefix(klass);
+        if (strcmp(class_prefix, prefix) != 0) { continue; }
+
+        CFCBindClass *class_binding = CFCBindClass_new(klass);
+
+        char *class_json = CFCBindClass_host_data_json(class_binding);
+        if (class_json[0] != '\0') {
+            const char *sep = classes_json[0] == '\0' ? "" : ",\n";
+            classes_json = CFCUtil_cat(classes_json, sep, class_json, NULL);
+        }
+
+        FREEMEM(class_json);
+        CFCBase_decref((CFCBase*)class_binding);
+    }
+    FREEMEM(ordered);
+
+    char *filepath = CFCUtil_sprintf("%s" CHY_DIR_SEP "%s" CHY_DIR_SEP "%s"
+                                     CHY_DIR_SEP "parcel_%s.json", dest_dir,
+                                     parcel_name, vstring, host_lang);
+    remove(filepath);
+
+    if (classes_json[0] != '\0') {
+        const char *pattern =
+            "{\n"
+            "    \"classes\": {\n"
+            "%s\n"
+            "    }\n"
+            "}\n";
+        char *json = CFCUtil_sprintf(pattern, classes_json);
+        CFCUtil_write_file(filepath, json, strlen(json));
+        FREEMEM(json);
+    }
+
+    FREEMEM(filepath);
+    FREEMEM(classes_json);
+}
+
 

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/src/CFCBindCore.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindCore.h b/compiler/src/CFCBindCore.h
index eff3efe..aa40bb2 100644
--- a/compiler/src/CFCBindCore.h
+++ b/compiler/src/CFCBindCore.h
@@ -66,6 +66,12 @@ CFCBindCore_write_all_modified(CFCBindCore *self, int modified);
 void
 CFCBindCore_copy_headers(CFCBindCore *self, const char *dest_dir);
 
+/* Write host-specific data to a JSON file for each source parcel.
+ */
+void
+CFCBindCore_write_host_data_json(CFCBindCore *self, const char *dest_dir,
+                                 const char *host_lang);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/src/CFCBindMethod.c
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindMethod.c b/compiler/src/CFCBindMethod.c
index 400d554..d57a29e 100644
--- a/compiler/src/CFCBindMethod.c
+++ b/compiler/src/CFCBindMethod.c
@@ -228,3 +228,37 @@ CFCBindMeth_imp_declaration(CFCMethod *method, CFCClass *klass) {
     return buf;
 }
 
+char*
+CFCBindMeth_host_data_json(CFCMethod *method) {
+    if (!CFCMethod_novel(method)) { return CFCUtil_strdup(""); }
+
+    int         excluded = CFCMethod_excluded_from_host(method);
+    const char *alias    = CFCMethod_get_host_alias(method);
+    char       *pair     = NULL;
+    char       *json     = NULL;
+
+    if (excluded) {
+        pair = CFCUtil_strdup("\"excluded\": true");
+    }
+    else if (alias) {
+        pair = CFCUtil_sprintf("\"alias\": \"%s\"", alias);
+    }
+
+    if (pair) {
+        const char *method_name = CFCMethod_get_name(method);
+
+        const char *pattern =
+            "                \"%s\": {\n"
+            "                    %s\n"
+            "                }";
+        json = CFCUtil_sprintf(pattern, method_name, pair);
+
+        FREEMEM(pair);
+    }
+    else {
+        json = CFCUtil_strdup("");
+    }
+
+    return json;
+}
+

http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/8ac4a064/compiler/src/CFCBindMethod.h
----------------------------------------------------------------------
diff --git a/compiler/src/CFCBindMethod.h b/compiler/src/CFCBindMethod.h
index 4928c70..f1b0bd4 100644
--- a/compiler/src/CFCBindMethod.h
+++ b/compiler/src/CFCBindMethod.h
@@ -57,6 +57,12 @@ CFCBindMeth_abstract_method_def(struct CFCMethod *method,
 char*
 CFCBindMeth_imp_declaration(struct CFCMethod *method, struct CFCClass *klass);
 
+/** Return a JSON fragment for method data specified by the host bindings
+ * (alias or excluded).
+ */
+char*
+CFCBindMeth_host_data_json(struct CFCMethod *method);
+
 #ifdef __cplusplus
 }
 #endif