Ejemplo n.º 1
0
void
CFCPerlTypeMap_write_xs_typemap(CFCHierarchy *hierarchy) {
    CFCClass **classes = CFCHierarchy_ordered_classes(hierarchy);
    char *start  = CFCUtil_strdup("");
    char *input  = CFCUtil_strdup("");
    char *output = CFCUtil_strdup("");
    for (int i = 0; classes[i] != NULL; i++) {
        CFCClass *klass = classes[i];
        if (CFCClass_included(klass)) { continue; }

        const char *full_struct_sym = CFCClass_full_struct_sym(klass);
        const char *vtable_var      = CFCClass_full_vtable_var(klass);

        start = CFCUtil_cat(start, full_struct_sym, "*\t", vtable_var, "_\n",
                            NULL);
        input = CFCUtil_cat(input, vtable_var, "_\n"
                            "    $var = (", full_struct_sym,
                            "*)XSBind_sv_to_cfish_obj($arg, ", vtable_var,
                            ", NULL);\n\n", NULL);

        output = CFCUtil_cat(output, vtable_var, "_\n"
                             "    $arg = (SV*)Cfish_Obj_To_Host((cfish_Obj*)$var);\n"
                             "    CFISH_DECREF($var);\n"
                             "\n", NULL);
    }

    char *content = CFCUtil_strdup("");
    content = CFCUtil_cat(content, typemap_start, start, "\n\n",
                          typemap_input, input, "\n\n",
                          typemap_output, output, "\n\n", NULL);
    CFCUtil_write_if_changed("typemap", content, strlen(content));

    FREEMEM(content);
    FREEMEM(output);
    FREEMEM(input);
    FREEMEM(start);
    FREEMEM(classes);
}
Ejemplo n.º 2
0
static void
S_add_load_method(CFCClass *klass) {
    CFCMethod *method = S_make_method_obj(klass, "Load");
    CFCClass_add_method(klass, method);
    CFCBase_decref((CFCBase*)method);
    const char *full_func_sym = CFCMethod_implementing_func_sym(method);
    const char *full_struct   = CFCClass_full_struct_sym(klass);
    const char *vtable_var    = CFCClass_full_vtable_var(klass);
    CFCClass   *parent        = CFCClass_get_parent(klass);
    const char *prefix        = CFCClass_get_prefix(klass);
    const char *class_cnick   = CFCClass_get_cnick(klass);
    char buf[BUF_SIZE];

    if (parent && CFCClass_has_attribute(parent, "dumpable")) {
        char *full_typedef = CFCMethod_full_typedef(method, klass);
        char *full_meth    = CFCMethod_full_method_sym(method, klass);

        const char pattern[] =
            "cfish_Obj*\n"
            "%s(%s *self, cfish_Obj *dump)\n"
            "{\n"
            "    cfish_Hash *source = (cfish_Hash*)CFISH_CERTIFY(dump, CFISH_HASH);\n"
            "    %s super_load = CFISH_SUPER_METHOD_PTR(%s, %s);\n"
            "    %s *loaded = (%s*)super_load(self, dump);\n"
            "    %sIVARS *ivars = %s%s_IVARS(loaded);\n";
        char *autocode
            = CFCUtil_sprintf(pattern, full_func_sym, full_struct,
                              full_typedef, vtable_var, full_meth, full_struct,
                              full_struct, full_struct, prefix, class_cnick);
        CFCClass_append_autocode(klass, autocode);
        FREEMEM(full_meth);
        FREEMEM(full_typedef);
        FREEMEM(autocode);

        CFCVariable **fresh = CFCClass_fresh_member_vars(klass);
        for (size_t i = 0; fresh[i] != NULL; i++) {
            S_process_load_member(klass, fresh[i], buf, BUF_SIZE);
        }
        FREEMEM(fresh);
    }
    else {
        const char pattern[] =
            "cfish_Obj*\n"
            "%s(%s *self, cfish_Obj *dump)\n"
            "{\n"
            "    cfish_Hash *source = (cfish_Hash*)CFISH_CERTIFY(dump, CFISH_HASH);\n"
            "    cfish_CharBuf *class_name = (cfish_CharBuf*)CFISH_CERTIFY(\n"
            "        Cfish_Hash_Fetch_Str(source, \"_class\", 6), CFISH_CHARBUF);\n"
            "    cfish_VTable *vtable = cfish_VTable_singleton(class_name, NULL);\n"
            "    %s *loaded = (%s*)Cfish_VTable_Make_Obj(vtable);\n"
            "    %sIVARS *ivars = %s%s_IVARS(loaded);\n"
            "    CHY_UNUSED_VAR(self);\n";
        char *autocode
            = CFCUtil_sprintf(pattern, full_func_sym, full_struct, full_struct,
                              full_struct,
                              full_struct, prefix, class_cnick);
        CFCClass_append_autocode(klass, autocode);
        FREEMEM(autocode);
        CFCVariable **members = CFCClass_member_vars(klass);
        for (size_t i = 0; members[i] != NULL; i++) {
            S_process_load_member(klass, members[i], buf, BUF_SIZE);
        }
    }

    CFCClass_append_autocode(klass, "    return (cfish_Obj*)loaded;\n}\n\n");
}
Ejemplo n.º 3
0
static void
S_add_dump_method(CFCClass *klass) {
    CFCMethod *method = S_make_method_obj(klass, "Dump");
    CFCClass_add_method(klass, method);
    CFCBase_decref((CFCBase*)method);
    const char *full_func_sym = CFCMethod_implementing_func_sym(method);
    const char *full_struct   = CFCClass_full_struct_sym(klass);
    const char *vtable_var    = CFCClass_full_vtable_var(klass);
    const char *prefix        = CFCClass_get_prefix(klass);
    const char *class_cnick   = CFCClass_get_cnick(klass);
    CFCClass   *parent        = CFCClass_get_parent(klass);
    char buf[BUF_SIZE];

    if (parent && CFCClass_has_attribute(parent, "dumpable")) {
        char *full_typedef = CFCMethod_full_typedef(method, klass);
        char *full_meth    = CFCMethod_full_method_sym(method, klass);

        const char pattern[] =
            "cfish_Obj*\n"
            "%s(%s *self)\n"
            "{\n"
            "    %sIVARS *ivars = %s%s_IVARS(self);\n"
            "    %s super_dump = CFISH_SUPER_METHOD_PTR(%s, %s);\n"
            "    cfish_Hash *dump = (cfish_Hash*)super_dump(self);\n";
        char *autocode
            = CFCUtil_sprintf(pattern, full_func_sym, full_struct,
                              full_struct, prefix, class_cnick,
                              full_typedef, vtable_var, full_meth);
        CFCClass_append_autocode(klass, autocode);
        FREEMEM(full_meth);
        FREEMEM(full_typedef);
        FREEMEM(autocode);

        CFCVariable **fresh = CFCClass_fresh_member_vars(klass);
        for (size_t i = 0; fresh[i] != NULL; i++) {
            S_process_dump_member(klass, fresh[i], buf, BUF_SIZE);
        }
        FREEMEM(fresh);
    }
    else {
        const char pattern[] =
            "cfish_Obj*\n"
            "%s(%s *self)\n"
            "{\n"
            "    %sIVARS *ivars = %s%s_IVARS(self);\n"
            "    cfish_Hash *dump = cfish_Hash_new(0);\n"
            "    Cfish_Hash_Store_Str(dump, \"_class\", 6,\n"
            "        (cfish_Obj*)Cfish_CB_Clone(Cfish_Obj_Get_Class_Name((cfish_Obj*)self)));\n";
        char *autocode
            = CFCUtil_sprintf(pattern, full_func_sym, full_struct,
                              full_struct, prefix, class_cnick);
        CFCClass_append_autocode(klass, autocode);
        FREEMEM(autocode);
        CFCVariable **members = CFCClass_member_vars(klass);
        for (size_t i = 0; members[i] != NULL; i++) {
            S_process_dump_member(klass, members[i], buf, BUF_SIZE);
        }
    }

    CFCClass_append_autocode(klass, "    return (cfish_Obj*)dump;\n}\n\n");
}
Ejemplo n.º 4
0
static char*
S_xsub_body(CFCPerlMethod *self) {
    CFCMethod    *method        = self->method;
    CFCParamList *param_list    = CFCMethod_get_param_list(method);
    CFCVariable **arg_vars      = CFCParamList_get_variables(param_list);
    const char   *name_list     = CFCParamList_name_list(param_list);
    char *body = CFCUtil_strdup("");

    CFCParcel *parcel = CFCMethod_get_parcel(method);
    const char *class_name = CFCMethod_get_class_name(method);
    CFCClass *klass = CFCClass_fetch_singleton(parcel, class_name);
    if (!klass) {
        CFCUtil_die("Can't find a CFCClass for '%s'", class_name);
    }

    // Extract the method function pointer.
    char *full_typedef = CFCMethod_full_typedef(method, klass);
    char *full_meth    = CFCMethod_full_method_sym(method, klass);
    char *method_ptr
        = CFCUtil_sprintf("%s method = CFISH_METHOD_PTR(%s, %s);\n    ",
                          full_typedef, CFCClass_full_vtable_var(klass),
                          full_meth);
    body = CFCUtil_cat(body, method_ptr, NULL);
    FREEMEM(full_typedef);
    FREEMEM(full_meth);
    FREEMEM(method_ptr);

    // Compensate for functions which eat refcounts.
    for (int i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var = arg_vars[i];
        CFCType     *type = CFCVariable_get_type(var);
        if (CFCType_is_object(type) && CFCType_decremented(type)) {
            body = CFCUtil_cat(body, "CFISH_INCREF(",
                               CFCVariable_micro_sym(var), ");\n    ", NULL);
        }
    }

    if (CFCType_is_void(CFCMethod_get_return_type(method))) {
        // Invoke method in void context.
        body = CFCUtil_cat(body, "method(", name_list,
                           ");\n    XSRETURN(0);", NULL);
    }
    else {
        // Return a value for method invoked in a scalar context.
        CFCType *return_type = CFCMethod_get_return_type(method);
        const char *type_str = CFCType_to_c(return_type);
        char *assignment = CFCPerlTypeMap_to_perl(return_type, "retval");
        if (!assignment) {
            CFCUtil_die("Can't find typemap for '%s'", type_str);
        }
        body = CFCUtil_cat(body, type_str, " retval = method(",
                           name_list, ");\n    ST(0) = ", assignment, ";",
                           NULL);
        if (CFCType_is_object(return_type)
            && CFCType_incremented(return_type)
           ) {
            body = CFCUtil_cat(body, "\n    CFISH_DECREF(retval);", NULL);
        }
        body = CFCUtil_cat(body, "\n    sv_2mortal( ST(0) );\n    XSRETURN(1);",
                           NULL);
        FREEMEM(assignment);
    }

    return body;
}
Ejemplo n.º 5
0
static void
S_write_boot_c(CFCPerl *self) {
    CFCClass  **ordered   = CFCHierarchy_ordered_classes(self->hierarchy);
    CFCParcel **parcels   = CFCParcel_all_parcels();
    char *pound_includes  = CFCUtil_strdup("");
    char *bootstrap_code  = CFCUtil_strdup("");
    char *alias_adds      = CFCUtil_strdup("");
    char *isa_pushes      = CFCUtil_strdup("");

    for (size_t i = 0; parcels[i]; ++i) {
        if (!CFCParcel_included(parcels[i])) {
            const char *prefix = CFCParcel_get_prefix(parcels[i]);
            bootstrap_code = CFCUtil_cat(bootstrap_code, "    ", prefix,
                                         "bootstrap_parcel();\n", NULL);
        }
    }

    for (size_t i = 0; ordered[i] != NULL; i++) {
        CFCClass *klass = ordered[i];
        if (CFCClass_included(klass)) { continue; }

        const char *class_name = CFCClass_get_class_name(klass);
        const char *include_h  = CFCClass_include_h(klass);
        pound_includes = CFCUtil_cat(pound_includes, "#include \"",
                                     include_h, "\"\n", NULL);

        if (CFCClass_inert(klass)) { continue; }

        // Add aliases for selected KinoSearch classes which allow old indexes
        // to be read.
        CFCPerlClass *class_binding = CFCPerlClass_singleton(class_name);
        if (class_binding) {
            const char *vtable_var = CFCClass_full_vtable_var(klass);
            const char **aliases
                = CFCPerlClass_get_class_aliases(class_binding);
            for (size_t j = 0; aliases[j] != NULL; j++) {
                const char *alias = aliases[j];
                size_t alias_len  = strlen(alias);
                const char pattern[] =
                    "    cfish_VTable_add_alias_to_registry("
                    "%s, \"%s\", %u);\n";
                char *alias_add
                    = CFCUtil_sprintf(pattern, vtable_var, alias,
                                      (unsigned)alias_len);
                alias_adds = CFCUtil_cat(alias_adds, alias_add, NULL);
                FREEMEM(alias_add);
            }

            char *metadata_code
                = CFCPerlClass_method_metadata_code(class_binding);
            alias_adds = CFCUtil_cat(alias_adds, metadata_code, NULL);
            FREEMEM(metadata_code);
        }

        CFCClass *parent = CFCClass_get_parent(klass);
        if (parent) {
            const char *parent_class_name = CFCClass_get_class_name(parent);
            isa_pushes
                = CFCUtil_cat(isa_pushes, "    isa = get_av(\"",
                              class_name, "::ISA\", 1);\n", NULL);
            isa_pushes
                = CFCUtil_cat(isa_pushes, "    av_push(isa, newSVpv(\"", 
                              parent_class_name, "\", 0));\n", NULL);
        }
    }

    const char pattern[] =
        "%s\n"
        "\n"
        "#include \"cfish_parcel.h\"\n"
        "#include \"EXTERN.h\"\n"
        "#include \"perl.h\"\n"
        "#include \"XSUB.h\"\n"
        "#include \"boot.h\"\n"
        "#include \"Clownfish/String.h\"\n"
        "#include \"Clownfish/VTable.h\"\n"
        "%s\n"
        "\n"
        "void\n"
        "%s() {\n"
        "%s"
        "\n"
        "%s"
        "\n"
        "    AV *isa;\n"
        "%s"
        "}\n"
        "\n"
        "%s\n"
        "\n";
    char *content
        = CFCUtil_sprintf(pattern, self->header, pound_includes,
                          self->boot_func, bootstrap_code, alias_adds,
                          isa_pushes, self->footer);

    const char *src_dest = CFCHierarchy_get_source_dest(self->hierarchy);
    char *boot_c_path = CFCUtil_sprintf("%s" CHY_DIR_SEP "boot.c", src_dest);
    CFCUtil_write_file(boot_c_path, content, strlen(content));
    FREEMEM(boot_c_path);

    FREEMEM(content);
    FREEMEM(isa_pushes);
    FREEMEM(alias_adds);
    FREEMEM(bootstrap_code);
    FREEMEM(pound_includes);
    FREEMEM(parcels);
    FREEMEM(ordered);
}