Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
CFCParamList*
CFCMethod_get_param_list(CFCMethod *self) {
    return CFCFunction_get_param_list((CFCFunction*)self);
}
Beispiel #6
0
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;
}