Пример #1
0
static CFCClass*
S_class_by_struct_sym_prereq(CFCParcel *self, const char *struct_sym,
                             size_t prefix_len) {
    CFCClass *klass = S_class_by_struct_sym(self, struct_sym, prefix_len);
    if (klass && prefix_len != 0) { return klass; }

    for (size_t i = 0; self->prereqs[i]; ++i) {
        const char *prereq_name   = CFCPrereq_get_name(self->prereqs[i]);
        CFCParcel  *prereq_parcel = CFCParcel_fetch(prereq_name);
        CFCClass *candidate
            = S_class_by_struct_sym(prereq_parcel, struct_sym, prefix_len);

        if (candidate) {
            if (prefix_len != 0) { return candidate; }
            if (klass) {
                CFCUtil_warn("Type '%s' is ambiguous. Do you mean %s or %s?",
                             struct_sym, CFCClass_full_struct_sym(klass),
                             CFCClass_full_struct_sym(candidate));
                return NULL;
            }
            klass = candidate;
        }
    }

    return klass;
}
Пример #2
0
static CFCClass*
S_fetch_class(CFCParcel *self, const char *class_name, int level) {
    // level == 0: Only search parcel.
    // level == 1: Search parcel and direct prereqs.
    // level == 2: Search parcel an indirect prereqs.

    for (size_t i = 0; self->classes[i]; ++i) {
        CFCClass *klass = self->classes[i];
        if (strcmp(CFCClass_get_name(klass), class_name) == 0) {
            return klass;
        }
    }

    if (level == 0) { return NULL; }
    if (level == 1) { level = 0; }

    for (size_t i = 0; self->prereqs[i]; ++i) {
        const char *prereq_name   = CFCPrereq_get_name(self->prereqs[i]);
        CFCParcel  *prereq_parcel = CFCParcel_fetch(prereq_name);

        CFCClass *klass = S_fetch_class(prereq_parcel, class_name, level);
        if (klass) { return klass; }
    }

    return NULL;
}
Пример #3
0
void
CFCPython_write_bindings(CFCPython *self, const char *parcel_name, const char *dest) {
    CFCParcel *parcel = CFCParcel_fetch(parcel_name);
    if (parcel == NULL) {
        CFCUtil_die("Unknown parcel: %s", parcel_name);
    }
    S_write_hostdefs(self);
    S_write_module_file(self, parcel, dest);
}
Пример #4
0
CFCParcel*
CFCParcel_clownfish_parcel(void) {
    CFCParcel *parcel = CFCParcel_fetch("Lucy");
    if (!parcel) {
        CFCVersion *version = CFCVersion_new("v0.3.0");
        parcel = CFCParcel_new("Lucy", "Lucy", version);
        CFCParcel_register(parcel);
        CFCBase_decref((CFCBase*)version);
        CFCBase_decref((CFCBase*)parcel);
    }
    return parcel;
}
Пример #5
0
void
CFCParcel_register(CFCParcel *self) {
    CFCParcel *existing = CFCParcel_fetch(self->name);
    if (existing) {
        CFCUtil_die("Parcel '%s' already registered", self->name);
    }
    if (!num_registered) {
        // Init default parcel as first.
        registry = (CFCParcel**)CALLOCATE(3, sizeof(CFCParcel*));
        CFCParcel *def = CFCParcel_default_parcel();
        registry[0] = (CFCParcel*)CFCBase_incref((CFCBase*)def);
        num_registered++;
    }
    size_t size = (num_registered + 2) * sizeof(CFCParcel*);
    registry = (CFCParcel**)REALLOCATE(registry, size);
    registry[num_registered++] = (CFCParcel*)CFCBase_incref((CFCBase*)self);
    registry[num_registered]   = NULL;
}
Пример #6
0
static void
S_parse_source_cfp_files(CFCHierarchy *self, const char *source_dir) {
    CFCFindFilesContext context;
    context.ext       = ".cfp";
    context.paths     = (char**)CALLOCATE(1, sizeof(char*));
    context.num_paths = 0;
    CFCUtil_walk(source_dir, S_find_files, &context);

    // Parse .cfp files and register the parcels they define.
    for (int i = 0; context.paths[i] != NULL; i++) {
        const char *path = context.paths[i];
        char *path_part = S_extract_path_part(path, source_dir, ".cfp");
        CFCFileSpec *file_spec
            = CFCFileSpec_new(source_dir, path_part, ".cfp", false);
        CFCParcel *parcel = CFCParcel_new_from_file(file_spec);

        const char *name = CFCParcel_get_name(parcel);
        CFCParcel *existing = CFCParcel_fetch(name);
        if (existing) {
            CFCUtil_die("Parcel '%s' defined twice in %s and %s",
                        CFCParcel_get_name(parcel),
                        CFCParcel_get_cfp_path(existing), path);
        }

        // Make sure to register prereq parcels first, so that prereq
        // parent classes precede subclasses.
        S_find_prereqs(self, parcel);

        CFCParcel_register(parcel);

        CFCBase_decref((CFCBase*)parcel);
        CFCBase_decref((CFCBase*)file_spec);
        FREEMEM(path_part);
    }

    CFCUtil_free_string_array(context.paths);
}
Пример #7
0
static void
S_run_include_tests(CFCTest *test) {
    {
        CFCHierarchy *hierarchy = CFCHierarchy_new(T_CFDEST);
        CFCHierarchy_add_source_dir(hierarchy, T_CFEXT);
        CFCHierarchy_add_include_dir(hierarchy, T_CFBASE);
        const char **include_dirs = CFCHierarchy_get_include_dirs(hierarchy);
        STR_EQ(test, include_dirs[0], T_CFBASE, "include_dirs[0]");
        OK(test, include_dirs[1] == NULL, "include_dirs[1]");

        CFCHierarchy_build(hierarchy);

        CFCClass **classes    = CFCHierarchy_ordered_classes(hierarchy);
        CFCClass  *rottweiler = NULL;;
        int num_classes;
        int num_source_classes = 0;
        for (num_classes = 0; classes[num_classes]; ++num_classes) {
            CFCClass *klass = classes[num_classes];
            int expect_included = 1;
            const char *class_name = CFCClass_get_name(klass);
            if (strcmp(class_name, "Animal::Rottweiler") == 0) {
                rottweiler      = klass;
                expect_included = 0;
                ++num_source_classes;
            }
            INT_EQ(test, CFCClass_included(klass), expect_included,
                   "included");
        }
        INT_EQ(test, num_classes, 5, "class count");
        INT_EQ(test, num_source_classes, 1, "source class count");
        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(rottweiler)),
               "Animal::Dog", "parent of included class");

        FREEMEM(classes);
        CFCBase_decref((CFCBase*)hierarchy);
        CFCClass_clear_registry();
        CFCParcel_reap_singletons();
    }

    {
        CFCHierarchy *hierarchy = CFCHierarchy_new(T_CFDEST);
        CFCHierarchy_add_source_dir(hierarchy, T_CFBASE);
        CFCHierarchy_add_source_dir(hierarchy, T_CFEXT);

        CFCHierarchy_build(hierarchy);

        CFCClass **classes    = CFCHierarchy_ordered_classes(hierarchy);
        CFCClass  *rottweiler = NULL;;
        int num_classes;
        for (num_classes = 0; classes[num_classes]; ++num_classes) {
            CFCClass *klass = classes[num_classes];
            const char *class_name = CFCClass_get_name(klass);
            if (strcmp(class_name, "Animal::Rottweiler") == 0) {
                rottweiler = klass;
            }
            OK(test, !CFCClass_included(klass), "not included");
        }
        INT_EQ(test, num_classes, 5, "class count");
        OK(test, rottweiler != NULL, "found rottweiler");
        STR_EQ(test, CFCClass_get_name(CFCClass_get_parent(rottweiler)),
               "Animal::Dog", "parent of class from second source");

        FREEMEM(classes);
        CFCBase_decref((CFCBase*)hierarchy);
        CFCClass_clear_registry();
        CFCParcel_reap_singletons();
    }

    {
        CFCHierarchy *hierarchy = CFCHierarchy_new(T_CFDEST);
        CFCHierarchy_add_include_dir(hierarchy, T_CFBASE);
        CFCHierarchy_add_include_dir(hierarchy, T_CFEXT);
        CFCHierarchy_add_prereq(hierarchy, "AnimalExtension");

        CFCHierarchy_build(hierarchy);

        CFCParcel *animal = CFCParcel_fetch("Animal");
        OK(test, animal != NULL, "parcel Animal registered");
        OK(test, CFCParcel_required(animal), "parcel Animal required");
        CFCParcel *animal_ext = CFCParcel_fetch("AnimalExtension");
        OK(test, animal_ext != NULL, "parcel AnimalExtension registered");
        OK(test, CFCParcel_required(animal_ext),
           "parcel AnimalExtension required");

        CFCClass **classes = CFCHierarchy_ordered_classes(hierarchy);
        int num_classes = 0;
        while (classes[num_classes]) {
            ++num_classes;
        }
        INT_EQ(test, num_classes, 5, "class count");

        FREEMEM(classes);
        CFCBase_decref((CFCBase*)hierarchy);
        CFCClass_clear_registry();
        CFCParcel_reap_singletons();
    }

    rmdir(T_CFDEST_INCLUDE);
    rmdir(T_CFDEST_SOURCE);
    rmdir(T_CFDEST);
}