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 <[email protected]>
Authored: Sat Mar 19 19:59:42 2016 +0100
Committer: Nick Wellnhofer <[email protected]>
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);
 

Reply via email to