Publish abstract method backing functions. Declare the implementing functions for abstract methods. Have the implementations match the method signatures rather than abuse C function pointer casting.
Having implementing functions hidden was a latent bug: the method invocation symbol for a `final` class which fails to implement the method is a macro alias for the implementing func, and if such a method were ever used in source code, the symbol would have been missing at link time. Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/b30e855a Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/b30e855a Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/b30e855a Branch: refs/heads/master Commit: b30e855a7a1b5281273d24bca34aaceeb416fe93 Parents: 9811a28 Author: Marvin Humphrey <[email protected]> Authored: Thu Apr 9 19:46:49 2015 -0700 Committer: Marvin Humphrey <[email protected]> Committed: Wed May 6 14:28:16 2015 -0700 ---------------------------------------------------------------------- compiler/src/CFCBindClass.c | 1 - compiler/src/CFCBindMethod.c | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 5 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b30e855a/compiler/src/CFCBindClass.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCBindClass.c b/compiler/src/CFCBindClass.c index 35b4efb..b5df350 100644 --- a/compiler/src/CFCBindClass.c +++ b/compiler/src/CFCBindClass.c @@ -616,7 +616,6 @@ S_sub_declarations(CFCBindClass *self) { } for (int i = 0; fresh_methods[i] != NULL; i++) { CFCMethod *method = fresh_methods[i]; - if (CFCMethod_abstract(method)) { continue; } char *dec = CFCBindMeth_imp_declaration(method); if (CFCMethod_final(method)) { declarations = CFCUtil_cat(declarations, PREFIX, "VISIBLE ", NULL); http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/b30e855a/compiler/src/CFCBindMethod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCBindMethod.c b/compiler/src/CFCBindMethod.c index e907332..47ab90b 100644 --- a/compiler/src/CFCBindMethod.c +++ b/compiler/src/CFCBindMethod.c @@ -206,19 +206,47 @@ CFCBindMeth_inherited_spec_def(CFCMethod *method, CFCClass *klass) { char* CFCBindMeth_abstract_method_def(CFCMethod *method) { + 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 *full_func_sym = CFCMethod_imp_func(method); const char *class_var = CFCType_get_class_var(type); const char *macro_sym = CFCMethod_get_macro_sym(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_micro_sym(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_micro_sym(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 = CFCUtil_strdup(""); + if (!CFCType_is_void(ret_type)) { + unreachable = CFCUtil_sprintf(" CFISH_UNREACHABLE_RETURN(%s);\n", + ret_type_str); + } char pattern[] = - "void\n" - "%s(cfish_Obj *self) {\n" - " cfish_Err_abstract_method_call(self, %s, \"%s\");\n" + "%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, full_func_sym, class_var, macro_sym); + = CFCUtil_sprintf(pattern, ret_type_str, full_func_sym, params, + unused, invocant, class_var, macro_sym, + unreachable); + FREEMEM(unused); return abstract_def; }
