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);
