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