コード例 #1
0
char*
CFCBindMeth_method_def(CFCMethod *method, CFCClass *klass) {
    // If the method is final and the class where it is declared final is in
    // the same parcel as the invocant, we can optimize the call by resolving
    // to the implementing function directly.
    if (CFCMethod_final(method)) {
        CFCClass *ancestor = klass;
        while (ancestor && !CFCMethod_is_fresh(method, ancestor)) {
            ancestor = CFCClass_get_parent(ancestor);
        }
        if (CFCClass_get_parcel(ancestor) == CFCClass_get_parcel(klass)) {
            return S_optimized_final_method_def(method, klass);
        }
    }

    return S_virtual_method_def(method, klass);
}
コード例 #2
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;
}
コード例 #3
0
ファイル: CFCBindSpecs.c プロジェクト: apache/lucy-clownfish
void
CFCBindSpecs_add_class(CFCBindSpecs *self, CFCClass *klass) {
    if (CFCClass_inert(klass)) { return; }

    const char *class_name        = CFCClass_get_name(klass);
    const char *class_var         = CFCClass_full_class_var(klass);
    const char *ivars_offset_name = CFCClass_full_ivars_offset(klass);

    const char *flags = CFCClass_final(klass) ? "cfish_ClassSpec_FINAL" : "0";

    char *ivars_size = S_ivars_size(klass);

    char *parent_ptr = NULL;
    CFCClass *parent = CFCClass_get_parent(klass);
    if (!parent) {
        parent_ptr = CFCUtil_strdup("NULL");
    }
    else {
        if (CFCClass_in_same_parcel(klass, parent)) {
            parent_ptr
                = CFCUtil_sprintf("&%s", CFCClass_full_class_var(parent));
        }
        else {
            parent_ptr = CFCUtil_strdup("NULL");

            const char *class_name = CFCClass_get_name(klass);
            const char *parent_var = CFCClass_full_class_var(parent);
            const char *pattern =
                "    /* %s */\n"
                "    class_specs[%d].parent = &%s;\n";
            char *init_code = CFCUtil_sprintf(pattern, class_name,
                                              self->num_specs, parent_var);
            self->init_code = CFCUtil_cat(self->init_code, init_code, NULL);
            FREEMEM(init_code);
        }
    }

    int num_new_novel      = 0;
    int num_new_overridden = 0;
    int num_new_inherited  = 0;
    CFCMethod **methods = CFCClass_methods(klass);

    for (int meth_num = 0; methods[meth_num] != NULL; meth_num++) {
        CFCMethod *method = methods[meth_num];

        if (CFCMethod_is_fresh(method, klass)) {
            if (CFCMethod_novel(method)) {
                int meth_index = self->num_novel + num_new_novel;
                S_add_novel_meth(self, method, klass, meth_index);
                ++num_new_novel;
            }
            else {
                int meth_index = self->num_overridden + num_new_overridden;
                S_add_overridden_meth(self, method, klass, meth_index);
                ++num_new_overridden;
            }
        }
        else {
            int meth_index = self->num_inherited + num_new_inherited;
            S_add_inherited_meth(self, method, klass, meth_index);
            ++num_new_inherited;
        }
    }

    char pattern[] =
        "    {\n"
        "        &%s, /* class */\n"
        "        %s, /* parent */\n"
        "        \"%s\", /* name */\n"
        "        %s, /* ivars_size */\n"
        "        &%s, /* ivars_offset_ptr */\n"
        "        %d, /* num_novel */\n"
        "        %d, /* num_overridden */\n"
        "        %d, /* num_inherited */\n"
        "        %s /* flags */\n"
        "    }";
    char *class_spec
        = CFCUtil_sprintf(pattern, class_var, parent_ptr, class_name,
                          ivars_size, ivars_offset_name, num_new_novel,
                          num_new_overridden, num_new_inherited, flags);

    const char *sep = self->num_specs == 0 ? "" : ",\n";
    self->class_specs = CFCUtil_cat(self->class_specs, sep, class_spec, NULL);

    self->num_novel      += num_new_novel;
    self->num_overridden += num_new_overridden;
    self->num_inherited  += num_new_inherited;
    self->num_specs      += 1;

    FREEMEM(class_spec);
    FREEMEM(parent_ptr);
    FREEMEM(ivars_size);
}