예제 #1
0
파일: CFCMethod.c 프로젝트: hernan604/lucy
void
CFCMethod_set_host_alias(CFCMethod *self, const char *alias) {
    if (!alias || !alias[0]) {
        CFCUtil_die("Missing required param 'alias'");
    }
    if (!self->is_novel) {
        CFCUtil_die("Can't set_host_alias %s -- method %s not novel in %s",
                    alias, self->macro_sym, CFCMethod_get_class_name(self));
    }
    if (self->host_alias) {
        if (strcmp(self->host_alias, alias) == 0) { return; }
        CFCUtil_die("Can't set_host_alias %s -- already set to %s for method"
                    " %s in %s", alias, self->host_alias, self->macro_sym,
                    CFCMethod_get_class_name(self));
    }
    self->host_alias = CFCUtil_strdup(alias);
}
예제 #2
0
파일: CFCMethod.c 프로젝트: hernan604/lucy
void
CFCMethod_exclude_from_host(CFCMethod *self) {
    if (!self->is_novel) {
        CFCUtil_die("Can't exclude_from_host -- method %s not novel in %s",
                    self->macro_sym, CFCMethod_get_class_name(self));
    }
    self->is_excluded = true;
}
예제 #3
0
파일: CFCMethod.c 프로젝트: hernan604/lucy
void
CFCMethod_override(CFCMethod *self, CFCMethod *orig) {
    // Check that the override attempt is legal.
    if (CFCMethod_final(orig)) {
        const char *orig_class = CFCMethod_get_class_name(orig);
        const char *my_class   = CFCMethod_get_class_name(self);
        CFCUtil_die("Attempt to override final method '%s' from '%s' by '%s'",
                    orig->macro_sym, orig_class, my_class);
    }
    if (!CFCMethod_compatible(self, orig)) {
        const char *func      = CFCMethod_imp_func(self);
        const char *orig_func = CFCMethod_imp_func(orig);
        CFCUtil_die("Non-matching signatures for %s and %s", func, orig_func);
    }

    // Mark the Method as no longer novel.
    self->is_novel = false;
}
예제 #4
0
파일: CFCClass.c 프로젝트: hernan604/lucy
CFCMethod*
CFCClass_fresh_method(CFCClass *self, const char *sym) {
    CFCMethod *method = CFCClass_method(self, sym);
    if (method) {
        const char *class_name = CFCClass_get_class_name(self);
        const char *meth_class_name = CFCMethod_get_class_name(method);
        if (strcmp(class_name, meth_class_name) == 0) {
            return method;
        }
    }
    return NULL;
}
예제 #5
0
파일: CFCMethod.c 프로젝트: hernan604/lucy
CFCMethod*
CFCMethod_finalize(CFCMethod *self) {
    CFCParcel  *parcel      = CFCMethod_get_parcel(self);
    const char *exposure    = CFCMethod_get_exposure(self);
    const char *class_name  = CFCMethod_get_class_name(self);
    const char *class_cnick = CFCMethod_get_class_cnick(self);
    CFCMethod  *finalized
        = CFCMethod_new(parcel, exposure, class_name, class_cnick,
                        self->macro_sym, self->function.return_type,
                        self->function.param_list,
                        self->function.docucomment, true,
                        self->is_abstract);
    finalized->is_novel = self->is_novel;
    return finalized;
}
예제 #6
0
void
CFCPerlClass_exclude_method(CFCPerlClass *self, const char *meth_name) {
    if (!self->client) {
        CFCUtil_die("Can't exclude_method %s -- can't find client for %s",
                    meth_name, self->class_name);
    }
    CFCMethod *method = CFCClass_method(self->client, meth_name);
    if (!method) {
        CFCUtil_die("Can't exclude_method %s -- method not found in %s",
                    meth_name, self->class_name);
    }
    if (strcmp(CFCMethod_get_class_name(method), self->class_name) != 0) {
        CFCUtil_die("Can't exclude_method %s -- method not fresh in %s",
                    meth_name, self->class_name);
    }
    CFCMethod_exclude_from_host(method);
}
예제 #7
0
void
CFCPerlClass_bind_method(CFCPerlClass *self, const char *alias,
                         const char *meth_name) {
    if (!self->client) {
        CFCUtil_die("Can't bind_method %s -- can't find client for %s",
                    alias, self->class_name);
    }
    CFCMethod *method = CFCClass_method(self->client, meth_name);
    if (!method) {
        CFCUtil_die("Can't bind_method %s -- can't find method %s in %s",
                    alias, meth_name, self->class_name);
    }
    if (strcmp(CFCMethod_get_class_name(method), self->class_name) != 0) {
        CFCUtil_die("Can't bind_method %s -- method %s not fresh in %s",
                    alias, meth_name, self->class_name);
    }
    CFCMethod_set_host_alias(method, alias);
}
예제 #8
0
파일: CFCPerlMethod.c 프로젝트: theory/lucy
CFCPerlMethod*
CFCPerlMethod_init(CFCPerlMethod *self, CFCMethod *method,
                   const char *alias) {
    CFCParamList *param_list = CFCMethod_get_param_list(method);
    const char *class_name = CFCMethod_get_class_name(method);
    int use_labeled_params = CFCParamList_num_vars(param_list) > 2
                             ? 1 : 0;

    // The Clownfish destructor needs to be spelled DESTROY for Perl.
    if (!alias) {
        alias = CFCMethod_micro_sym(method);
    }
    static const char destroy_uppercase[] = "DESTROY";
    if (strcmp(alias, "destroy") == 0) {
        alias = destroy_uppercase;
    }

    CFCPerlSub_init((CFCPerlSub*)self, param_list, class_name, alias,
                    use_labeled_params);
    self->method = (CFCMethod*)CFCBase_incref((CFCBase*)method);
    return self;
}
예제 #9
0
파일: CFCPerlMethod.c 프로젝트: theory/lucy
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;
}