Exemple #1
0
int
CFCType_equals(CFCType *self, CFCType *other) {
    if ((CFCType_const(self)           ^ CFCType_const(other))
        || (CFCType_nullable(self)     ^ CFCType_nullable(other))
        || (CFCType_is_void(self)      ^ CFCType_is_void(other))
        || (CFCType_is_object(self)    ^ CFCType_is_object(other))
        || (CFCType_is_primitive(self) ^ CFCType_is_primitive(other))
        || (CFCType_is_integer(self)   ^ CFCType_is_integer(other))
        || (CFCType_is_floating(self)  ^ CFCType_is_floating(other))
        || (CFCType_is_va_list(self)   ^ CFCType_is_va_list(other))
        || (CFCType_is_arbitrary(self) ^ CFCType_is_arbitrary(other))
        || (CFCType_is_composite(self) ^ CFCType_is_composite(other))
        || (CFCType_incremented(self)  ^ CFCType_incremented(other))
        || (CFCType_decremented(self)  ^ CFCType_decremented(other))
        || !!self->child ^ !!other->child
        || !!self->array ^ !!other->array
       ) {
        return false;
    }
    if (self->indirection != other->indirection) { return false; }
    if (strcmp(self->specifier, other->specifier) != 0) { return false; }
    if (self->child) {
        if (!CFCType_equals(self->child, other->child)) { return false; }
    }
    if (self->array) {
        if (strcmp(self->array, other->array) != 0) { return false; }
    }
    return true;
}
Exemple #2
0
int
CFCType_similar(CFCType *self, CFCType *other) {
    if (!CFCType_is_object(self)) {
        CFCUtil_die("Attempt to call 'similar' on a non-object type");
    }
    if ((CFCType_const(self)           ^ CFCType_const(other))
        || (CFCType_nullable(self)     ^ CFCType_nullable(other))
        || (CFCType_incremented(self)  ^ CFCType_incremented(other))
        || (CFCType_decremented(self)  ^ CFCType_decremented(other))
        || (CFCType_is_object(self)    ^ CFCType_is_object(other))
       ) {
        return false;
    }
    return true;
}
Exemple #3
0
static char*
S_callback_refcount_mods(CFCParamList *param_list) {
    char *refcount_mods = CFCUtil_strdup("");
    CFCVariable **arg_vars = CFCParamList_get_variables(param_list);

    // Adjust refcounts of arguments per method signature, so that Perl code
    // does not have to.
    for (int i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var  = arg_vars[i];
        CFCType     *type = CFCVariable_get_type(var);
        const char  *name = CFCVariable_get_name(var);
        if (!CFCType_is_object(type)) {
            continue;
        }
        else if (CFCType_incremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "    CFISH_INCREF(",
                                        name, ");\n", NULL);
        }
        else if (CFCType_decremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "    CFISH_DECREF(",
                                        name, ");\n", NULL);
        }
    }

    return refcount_mods;
}
Exemple #4
0
char*
CFCPerlConstructor_xsub_def(CFCPerlConstructor *self) {
    const char *c_name = self->sub.c_name;
    CFCParamList *param_list = self->sub.param_list;
    const char   *name_list  = CFCParamList_name_list(param_list);
    CFCVariable **arg_vars   = CFCParamList_get_variables(param_list);
    const char   *func_sym   = CFCFunction_full_func_sym(self->init_func);
    char *allot_params = CFCPerlSub_build_allot_params((CFCPerlSub*)self);
    CFCVariable *self_var       = arg_vars[0];
    CFCType     *self_type      = CFCVariable_get_type(self_var);
    const char  *self_type_str  = CFCType_to_c(self_type);

    // Compensate for swallowed refcounts.
    char *refcount_mods = CFCUtil_strdup("");
    for (size_t 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)) {
            const char *name = CFCVariable_micro_sym(var);
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_INCREF(",
                                        name, ");", NULL);
        }
    }

    const char pattern[] =
        "XS(%s);\n"
        "XS(%s) {\n"
        "    dXSARGS;\n"
        "    CFISH_UNUSED_VAR(cv);\n"
        "    if (items < 1) { CFISH_THROW(CFISH_ERR, \"Usage: %%s(class_name, ...)\",  GvNAME(CvGV(cv))); }\n"
        "    SP -= items;\n"
        "\n"
        "    %s\n"
        // Create "self" last, so that earlier exceptions while fetching
        // params don't trigger a bad invocation of DESTROY.
        "    %s self = (%s)XSBind_new_blank_obj(ST(0));%s\n"
        "\n"
        "    %s retval = %s(%s);\n"
        "    if (retval) {\n"
        "        ST(0) = (SV*)CFISH_Obj_To_Host((cfish_Obj*)retval);\n"
        "        CFISH_Obj_Dec_RefCount((cfish_Obj*)retval);\n"
        "    }\n"
        "    else {\n"
        "        ST(0) = newSV(0);\n"
        "    }\n"
        "    sv_2mortal(ST(0));\n"
        "    XSRETURN(1);\n"
        "}\n\n";
    char *xsub_def
        = CFCUtil_sprintf(pattern, c_name, c_name, allot_params, self_type_str,
                          self_type_str, refcount_mods, self_type_str,
                          func_sym, name_list);

    FREEMEM(refcount_mods);
    FREEMEM(allot_params);

    return xsub_def;
}
Exemple #5
0
static char*
S_gen_arg_increfs(CFCParamList *param_list, int first_tick) {
    CFCVariable **vars = CFCParamList_get_variables(param_list);
    int num_vars = CFCParamList_num_vars(param_list);
    char *content = CFCUtil_strdup("");
    for (int i = first_tick;i < num_vars; i++) {
        CFCType *type = CFCVariable_get_type(vars[i]);
        if (CFCType_decremented(type)) {
            const char *name = CFCVariable_get_name(vars[i]);
            const char *specifier = CFCType_get_specifier(type);
            char pattern[] =
                "    %s_ARG = (%s*)CFISH_INCREF(%s_ARG);\n";
            char *incref = CFCUtil_sprintf(pattern, name, specifier, name);
            content = CFCUtil_cat(content, incref, NULL);
            FREEMEM(incref);
        }
    }
    return content;
}
Exemple #6
0
static char*
S_callback_refcount_mods(CFCMethod *method) {
    char *refcount_mods = CFCUtil_strdup("");
    CFCType *return_type = CFCMethod_get_return_type(method);
    CFCParamList *param_list = CFCMethod_get_param_list(method);
    CFCVariable **arg_vars = CFCParamList_get_variables(param_list);

    // `XSBind_perl_to_cfish()` returns an incremented object.  If this method
    // does not return an incremented object, we must cancel out that
    // refcount.  (No function can return a decremented object.)
    if (CFCType_is_object(return_type) && !CFCType_incremented(return_type)) {
        refcount_mods = CFCUtil_cat(refcount_mods,
                                    "\n    CFISH_DECREF(retval);", NULL);
    }

    // Adjust refcounts of arguments per method signature, so that Perl code
    // does not have to.
    for (int i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var  = arg_vars[i];
        CFCType     *type = CFCVariable_get_type(var);
        const char  *name = CFCVariable_micro_sym(var);
        if (!CFCType_is_object(type)) {
            continue;
        }
        else if (CFCType_incremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_INCREF(",
                                        name, ");", NULL);
        }
        else if (CFCType_decremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_DECREF(",
                                        name, ");", NULL);
        }
    }

    return refcount_mods;
}
Exemple #7
0
static char*
S_callback_refcount_mods(CFCMethod *method) {
    char *refcount_mods = CFCUtil_strdup("");
    CFCType *return_type = CFCMethod_get_return_type(method);
    CFCParamList *param_list = CFCMethod_get_param_list(method);
    CFCVariable **arg_vars = CFCParamList_get_variables(param_list);

    // Host_callback_obj returns an incremented object.  If this method does
    // not return an incremented object, we must cancel out that refcount.
    // (No function can return a decremented object.)
    if (CFCType_is_object(return_type) && !CFCType_incremented(return_type)) {
        refcount_mods = CFCUtil_cat(refcount_mods,
                                    "\n    CFISH_DECREF(retval);", NULL);
    }

    // The Host_callback_xxx functions have no effect on the refcounts of
    // arguments, so we need to adjust them after the fact.
    for (int i = 0; arg_vars[i] != NULL; i++) {
        CFCVariable *var  = arg_vars[i];
        CFCType     *type = CFCVariable_get_type(var);
        const char  *name = CFCVariable_micro_sym(var);
        if (!CFCType_is_object(type)) {
            continue;
        }
        else if (CFCType_incremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_INCREF(",
                                        name, ");", NULL);
        }
        else if (CFCType_decremented(type)) {
            refcount_mods = CFCUtil_cat(refcount_mods, "\n    CFISH_DECREF(",
                                        name, ");", NULL);
        }
    }
    
    return refcount_mods;
}
Exemple #8
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;
}