Exemplo n.º 1
0
char*
CFCBindMeth_abstract_method_def(CFCMethod *method) {
    CFCParamList *param_list = CFCMethod_get_param_list(method);
    const char *params = CFCParamList_to_c(param_list);
    const char *full_func_sym = CFCMethod_imp_func(method);
    const char *vtable_var
        = CFCType_get_vtable_var(CFCMethod_self_type(method));
    CFCType    *return_type  = CFCMethod_get_return_type(method);
    const char *ret_type_str = CFCType_to_c(return_type);
    const char *macro_sym    = CFCMethod_get_macro_sym(method);

    // Thwart compiler warnings.
    CFCVariable **param_vars = CFCParamList_get_variables(param_list);
    char *unused = S_build_unused_vars(param_vars + 1);
    char *return_statement = S_maybe_unreachable(return_type);

    char pattern[] =
        "%s\n"
        "%s(%s) {\n"
        "    cfish_String *klass = self ? CFISH_Obj_Get_Class_Name((cfish_Obj*)self) : %s->name;%s\n"
        "    CFISH_THROW(CFISH_ERR, \"Abstract method '%s' not defined by %%o\", klass);%s\n"
        "}\n";
    char *abstract_def
        = CFCUtil_sprintf(pattern, ret_type_str, full_func_sym, params,
                          vtable_var, unused, macro_sym, return_statement);

    FREEMEM(unused);
    FREEMEM(return_statement);
    return abstract_def;
}
Exemplo n.º 2
0
char*
CFCBindMeth_novel_spec_def(CFCMethod *method) {
    const char *macro_sym = CFCMethod_get_macro_sym(method);
    const char *imp_func  = CFCMethod_imp_func(method);

    const char *full_override_sym = "NULL";
    if (!CFCMethod_final(method)) {
        full_override_sym = CFCMethod_full_override_sym(method);
    }

    char *full_offset_sym = CFCMethod_full_offset_sym(method, NULL);

    char pattern[] =
        "    {\n"
        "        &%s, /* offset */\n"
        "        \"%s\", /* name */\n"
        "        (cfish_method_t)%s, /* func */\n"
        "        (cfish_method_t)%s /* callback_func */\n"
        "    }";
    char *def
        = CFCUtil_sprintf(pattern, full_offset_sym, macro_sym, imp_func,
                          full_override_sym);

    FREEMEM(full_offset_sym);
    return def;
}
Exemplo n.º 3
0
static void
S_add_overridden_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
                      int meth_index) {
    const char *sep = meth_index == 0 ? "" : ",\n";

    char *imp_func        = CFCMethod_imp_func(method, klass);
    char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
    char *parent_offset   = S_parent_offset(self, method, klass, "overridden",
                                            meth_index);

    char pattern[] =
        "    {\n"
        "        &%s, /* offset */\n"
        "        %s, /* parent_offset */\n"
        "        (cfish_method_t)%s /* func */\n"
        "    }";
    char *def
        = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset, imp_func);
    self->overridden_specs
        = CFCUtil_cat(self->overridden_specs, sep, def, NULL);

    FREEMEM(def);
    FREEMEM(parent_offset);
    FREEMEM(full_offset_sym);
    FREEMEM(imp_func);
}
Exemplo n.º 4
0
static void
S_add_novel_meth(CFCBindSpecs *self, CFCMethod *method, CFCClass *klass,
                 int meth_index) {
    const char *meth_name = CFCMethod_get_name(method);
    const char *sep = meth_index == 0 ? "" : ",\n";

    char *full_override_sym;
    if (!CFCMethod_final(method) && !CFCMethod_excluded_from_host(method)) {
        full_override_sym = CFCMethod_full_override_sym(method, klass);
    }
    else {
        full_override_sym = CFCUtil_strdup("NULL");
    }

    char *imp_func        = CFCMethod_imp_func(method, klass);
    char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);

    char pattern[] =
        "    {\n"
        "        &%s, /* offset */\n"
        "        \"%s\", /* name */\n"
        "        (cfish_method_t)%s, /* func */\n"
        "        (cfish_method_t)%s /* callback_func */\n"
        "    }";
    char *def
        = CFCUtil_sprintf(pattern, full_offset_sym, meth_name, imp_func,
                          full_override_sym);
    self->novel_specs = CFCUtil_cat(self->novel_specs, sep, def, NULL);

    FREEMEM(def);
    FREEMEM(full_offset_sym);
    FREEMEM(imp_func);
    FREEMEM(full_override_sym);
}
Exemplo n.º 5
0
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;
}
Exemplo n.º 6
0
char*
CFCBindMeth_imp_declaration(CFCMethod *method) {
    CFCType      *return_type    = CFCMethod_get_return_type(method);
    CFCParamList *param_list     = CFCMethod_get_param_list(method);
    const char   *ret_type_str   = CFCType_to_c(return_type);
    const char   *full_imp_sym   = CFCMethod_imp_func(method);
    const char   *param_list_str = CFCParamList_to_c(param_list);
    char *buf = CFCUtil_sprintf("%s\n%s(%s);", ret_type_str,
                                full_imp_sym, param_list_str);
    return buf;
}
Exemplo n.º 7
0
char*
CFCBindMeth_abstract_method_def(CFCMethod *method, CFCClass *klass) {
    CFCType    *ret_type      = CFCMethod_get_return_type(method);
    const char *ret_type_str  = CFCType_to_c(ret_type);
    CFCType    *type          = CFCMethod_self_type(method);
    const char *class_var     = CFCType_get_class_var(type);
    const char *meth_name     = CFCMethod_get_name(method);
    CFCParamList *param_list  = CFCMethod_get_param_list(method);
    const char *params        = CFCParamList_to_c(param_list);
    CFCVariable **vars        = CFCParamList_get_variables(param_list);
    const char *invocant      = CFCVariable_get_name(vars[0]);

    // All variables other than the invocant are unused, and the return is
    // unreachable.
    char *unused = CFCUtil_strdup("");
    for (int i = 1; vars[i] != NULL; i++) {
        const char *var_name = CFCVariable_get_name(vars[i]);
        size_t size = strlen(unused) + strlen(var_name) + 80;
        unused = (char*)REALLOCATE(unused, size);
        strcat(unused, "\n    CFISH_UNUSED_VAR(");
        strcat(unused, var_name);
        strcat(unused, ");");
    }
    char *unreachable;
    if (!CFCType_is_void(ret_type)) {
        unreachable = CFCUtil_sprintf("    CFISH_UNREACHABLE_RETURN(%s);\n",
                                      ret_type_str);
    }
    else {
        unreachable = CFCUtil_strdup("");
    }

    char *full_func_sym = CFCMethod_imp_func(method, klass);

    char pattern[] =
        "%s\n"
        "%s(%s) {\n"
        "%s"
        "    cfish_Err_abstract_method_call((cfish_Obj*)%s, %s, \"%s\");\n"
        "%s"
        "}\n";
    char *abstract_def
        = CFCUtil_sprintf(pattern, ret_type_str, full_func_sym, params,
                          unused, invocant, class_var, meth_name,
                          unreachable);

    FREEMEM(unused);
    FREEMEM(unreachable);
    FREEMEM(full_func_sym);
    return abstract_def;
}
Exemplo n.º 8
0
/* Create a macro definition that aliases to a function name directly, since
 * this method may not be overridden. */
static char*
S_final_method_def(CFCMethod *method, CFCClass *klass) {
    const char *self_type = CFCType_to_c(CFCMethod_self_type(method));
    const char *full_func_sym = CFCMethod_imp_func(method);
    const char *arg_names 
        = CFCParamList_name_list(CFCMethod_get_param_list(method));

    char *full_meth_sym   = CFCMethod_full_method_sym(method, klass);
    char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);

    const char pattern[] =
        "extern size_t %s;\n"
        "#define %s(%s) \\\n"
        "    %s((%s)%s)\n";
    char *method_def
        = CFCUtil_sprintf(pattern, full_offset_sym, full_meth_sym, arg_names,
                          full_func_sym, self_type, arg_names);

    FREEMEM(full_offset_sym);
    FREEMEM(full_meth_sym);
    return method_def;
}
Exemplo n.º 9
0
char*
CFCBindMeth_overridden_spec_def(CFCMethod *method, CFCClass *klass) {
    const char *imp_func  = CFCMethod_imp_func(method);

    char *full_offset_sym = CFCMethod_full_offset_sym(method, NULL);

    CFCClass *parent = CFCClass_get_parent(klass);
    char *parent_offset_sym = CFCMethod_full_offset_sym(method, parent);

    char pattern[] =
        "    {\n"
        "        &%s, /* offset */\n"
        "        &%s, /* parent_offset */\n"
        "        (cfish_method_t)%s /* func */\n"
        "    }";
    char *def
        = CFCUtil_sprintf(pattern, full_offset_sym, parent_offset_sym,
                          imp_func);

    FREEMEM(full_offset_sym);
    FREEMEM(parent_offset_sym);
    return def;
}
Exemplo n.º 10
0
static char*
S_method_def(CFCMethod *method, CFCClass *klass, int optimized_final_meth) {
    CFCParamList *param_list = CFCMethod_get_param_list(method);
    const char *PREFIX         = CFCClass_get_PREFIX(klass);
    const char *invoker_struct = CFCClass_full_struct_sym(klass);
    const char *self_name      = CFCParamList_param_name(param_list, 0);

    char *full_meth_sym   = CFCMethod_full_method_sym(method, klass);
    char *full_offset_sym = CFCMethod_full_offset_sym(method, klass);
    char *full_typedef    = CFCMethod_full_typedef(method, klass);
    char *full_imp_sym    = CFCMethod_imp_func(method, klass);

    // Prepare parameter lists, minus the type of the invoker.
    if (CFCParamList_variadic(param_list)) {
        CFCUtil_die("Variadic methods not supported");
    }
    const char *arg_names  = CFCParamList_name_list(param_list);
    const char *params_end = CFCParamList_to_c(param_list);
    while (*params_end && *params_end != '*') {
        params_end++;
    }

    // Prepare a return statement... or not.
    CFCType *return_type = CFCMethod_get_return_type(method);
    const char *ret_type_str = CFCType_to_c(return_type);
    const char *maybe_return = CFCType_is_void(return_type) ? "" : "return ";

    const char innards_pattern[] =
        "    const %s method = (%s)cfish_obj_method(%s, %s);\n"
        "    %smethod(%s);\n"
        ;
    char *innards = CFCUtil_sprintf(innards_pattern, full_typedef,
                                    full_typedef, self_name, full_offset_sym,
                                    maybe_return, arg_names);
    if (optimized_final_meth) {
        CFCParcel  *parcel = CFCClass_get_parcel(klass);
        const char *privacy_sym = CFCParcel_get_privacy_sym(parcel);
        char *invoker_cast = CFCUtil_strdup("");
        if (!CFCMethod_is_fresh(method, klass)) {
            CFCType *self_type = CFCMethod_self_type(method);
            invoker_cast = CFCUtil_cat(invoker_cast, "(",
                                       CFCType_to_c(self_type), ")", NULL);
        }
        const char pattern[] =
            "#ifdef %s\n"
            "    %s%s(%s%s);\n"
            "#else\n"
            "%s"
            "#endif\n"
            ;
        char *temp = CFCUtil_sprintf(pattern, privacy_sym,
                                     maybe_return, full_imp_sym,
                                     invoker_cast, arg_names, innards);
        FREEMEM(innards);
        innards = temp;
        FREEMEM(invoker_cast);
    }

    const char pattern[] =
        "extern %sVISIBLE uint32_t %s;\n"
        "static CFISH_INLINE %s\n"
        "%s(%s%s) {\n"
        "%s"
        "}\n";
    char *method_def
        = CFCUtil_sprintf(pattern, PREFIX, full_offset_sym, ret_type_str,
                          full_meth_sym, invoker_struct, params_end, innards);

    FREEMEM(innards);
    FREEMEM(full_imp_sym);
    FREEMEM(full_offset_sym);
    FREEMEM(full_meth_sym);
    FREEMEM(full_typedef);
    return method_def;
}