CFCPerlConstructor* CFCPerlConstructor_init(CFCPerlConstructor *self, CFCClass *klass, const char *alias, const char *initializer) { CFCUTIL_NULL_CHECK(alias); CFCUTIL_NULL_CHECK(klass); const char *class_name = CFCClass_get_class_name(klass); initializer = initializer ? initializer : "init"; // Find the implementing function. self->init_func = NULL; CFCFunction **funcs = CFCClass_functions(klass); for (size_t i = 0; funcs[i] != NULL; i++) { CFCFunction *func = funcs[i]; const char *func_name = CFCFunction_micro_sym(func); if (strcmp(initializer, func_name) == 0) { self->init_func = (CFCFunction*)CFCBase_incref((CFCBase*)func); break; } } if (!self->init_func) { CFCUtil_die("Missing or invalid '%s' function for '%s'", initializer, class_name); } CFCParamList *param_list = CFCFunction_get_param_list(self->init_func); CFCPerlSub_init((CFCPerlSub*)self, param_list, class_name, alias, true); return self; }
static char* S_gen_code_sample(CFCFunction *func, const char *alias, CFCClass *klass, int is_constructor) { char *invocant = NULL; if (is_constructor) { invocant = CFCUtil_strdup(CFCClass_get_name(klass)); } else { char *lower = S_camel_to_lower(CFCClass_get_struct_sym(klass)); invocant = CFCUtil_sprintf("$%s", lower); FREEMEM(lower); } CFCParamList *param_list = CFCFunction_get_param_list(func); size_t num_vars = CFCParamList_num_vars(param_list); size_t start = is_constructor ? 0 : 1; char *sample = NULL; if (start == num_vars) { sample = CFCUtil_sprintf(" %s->%s();\n", invocant, alias); } else if (is_constructor || num_vars - start >= 2) { sample = S_gen_labeled_sample(invocant, alias, param_list, start); } else { sample = S_gen_positional_sample(invocant, alias, param_list, start); } return sample; }
char* CFCPyMethod_constructor_wrapper(CFCFunction *init_func, CFCClass *invoker) { CFCParamList *param_list = CFCFunction_get_param_list(init_func); const char *self_type = CFCType_to_c(CFCFunction_get_return_type(init_func)); char *func_sym = CFCFunction_full_func_sym(init_func, invoker); char *decs = S_gen_decs(param_list, 1); char *increfs = S_gen_arg_increfs(param_list, 1); char *decrefs = S_gen_decrefs(param_list, 1); const char *class_var = CFCClass_full_class_var(invoker); const char *struct_sym = CFCClass_full_struct_sym(invoker); char *error = NULL; char *arg_parsing = S_gen_arg_parsing(param_list, 1, &error); if (error) { CFCUtil_die("%s in constructor for %s", error, CFCClass_get_name(invoker)); } if (!arg_parsing) { CFCUtil_die("Unexpected arg parsing error for %s", CFCClass_get_name(invoker)); } char *first_arg = CFCUtil_sprintf("(%s)CFISH_Class_Make_Obj(%s)", self_type, class_var); char *arg_list = S_gen_arg_list(param_list, first_arg); char pattern[] = "static PyObject*\n" "S_%s_PY_NEW(PyTypeObject *type, PyObject *args, PyObject *kwargs) {\n" "%s" // decs "%s" // arg_parsing "%s" // increfs " %s self = NULL;\n" " CFBIND_TRY(self = %s(%s));\n" "%s" // decrefs " if (CFBind_migrate_cferr()) {\n" " return NULL;\n" " }\n" " return (PyObject*)self;\n" "}\n" ; char *wrapper = CFCUtil_sprintf(pattern, struct_sym, decs, arg_parsing, increfs, self_type, func_sym, arg_list, decrefs); FREEMEM(arg_list); FREEMEM(first_arg); FREEMEM(func_sym); FREEMEM(decrefs); FREEMEM(increfs); FREEMEM(decs); FREEMEM(arg_parsing); return wrapper; }
char* CFCGoClass_gen_ctors(CFCGoClass *self) { CFCFunction *ctor_func = CFCClass_function(self->client, "new"); if (self->suppress_ctor || !ctor_func || !CFCFunction_can_be_bound(ctor_func) ) { return CFCUtil_strdup(""); } CFCParcel *parcel = CFCClass_get_parcel(self->client); CFCParamList *param_list = CFCFunction_get_param_list(ctor_func); CFCType *ret_type = CFCFunction_get_return_type(ctor_func); const char *struct_sym = CFCClass_get_struct_sym(self->client); char *name = CFCUtil_sprintf("New%s", struct_sym); char *cfunc = CFCFunction_full_func_sym(ctor_func, self->client); char *cfargs = CFCGoFunc_ctor_cfargs(parcel, param_list); char *first_line = CFCGoFunc_ctor_start(parcel, name, param_list, ret_type); char *ret_statement = CFCGoFunc_return_statement(parcel, ret_type, "retvalCF"); char pattern[] = "%s" "\tretvalCF := C.%s(%s)\n" "%s" "}\n" ; char *content = CFCUtil_sprintf(pattern, first_line, cfunc, cfargs, ret_statement); FREEMEM(ret_statement); FREEMEM(cfargs); FREEMEM(cfunc); FREEMEM(first_line); FREEMEM(name); return content; }
CFCParamList* CFCMethod_get_param_list(CFCMethod *self) { return CFCFunction_get_param_list((CFCFunction*)self); }
char* CFCPerlPod_gen_subroutine_pod(CFCPerlPod *self, CFCFunction *func, const char *alias, CFCClass *klass, const char *code_sample, const char *class_name, int is_constructor) { // Only allow "public" subs to be exposed as part of the public API. if (!CFCFunction_public(func)) { CFCUtil_die("%s#%s is not public", class_name, alias); } CFCParamList *param_list = CFCFunction_get_param_list(func); int num_vars = (int)CFCParamList_num_vars(param_list); char *pod = CFCUtil_sprintf("=head2 %s", alias); // Get documentation, which may be inherited. CFCDocuComment *docucomment = CFCFunction_get_docucomment(func); if (!docucomment) { const char *micro_sym = CFCFunction_micro_sym(func); CFCClass *parent = klass; while (NULL != (parent = CFCClass_get_parent(parent))) { CFCFunction *parent_func = (CFCFunction*)CFCClass_method(parent, micro_sym); if (!parent_func) { break; } docucomment = CFCFunction_get_docucomment(parent_func); if (docucomment) { break; } } } if (!docucomment) { CFCUtil_die("No DocuComment for '%s' in '%s'", alias, class_name); } // Build string summarizing arguments to use in header. if (num_vars > 2 || (is_constructor && num_vars > 1)) { pod = CFCUtil_cat(pod, "( I<[labeled params]> )\n\n", NULL); } else if (num_vars == 2) { // Kill self param. const char *name_list = CFCParamList_name_list(param_list); const char *after_comma = strchr(name_list, ',') + 1; while (isspace(*after_comma)) { after_comma++; } pod = CFCUtil_cat(pod, "(", after_comma, ")\n\n", NULL); } else { // num_args == 1, leave off 'self'. pod = CFCUtil_cat(pod, "()\n\n", NULL); } // Add code sample. if (code_sample && strlen(code_sample)) { pod = CFCUtil_cat(pod, code_sample, "\n", NULL); } // Incorporate "description" text from DocuComment. const char *long_doc = CFCDocuComment_get_description(docucomment); if (long_doc && strlen(long_doc)) { char *perlified = CFCPerlPod_md_to_pod(self, klass, long_doc); pod = CFCUtil_cat(pod, perlified, NULL); FREEMEM(perlified); } // Add params in a list. const char**param_names = CFCDocuComment_get_param_names(docucomment); const char**param_docs = CFCDocuComment_get_param_docs(docucomment); if (param_names[0]) { pod = CFCUtil_cat(pod, "=over\n\n", NULL); for (size_t i = 0; param_names[i] != NULL; i++) { char *perlified = CFCPerlPod_md_to_pod(self, klass, param_docs[i]); pod = CFCUtil_cat(pod, "=item *\n\nB<", param_names[i], "> - ", perlified, NULL); FREEMEM(perlified); } pod = CFCUtil_cat(pod, "=back\n\n", NULL); } // Add return value description, if any. const char *retval_doc = CFCDocuComment_get_retval(docucomment); if (retval_doc && strlen(retval_doc)) { char *perlified = CFCPerlPod_md_to_pod(self, klass, retval_doc); pod = CFCUtil_cat(pod, "Returns: ", perlified, NULL); FREEMEM(perlified); } return pod; }