Use static inline funcs for final methods. Instead of a macro which aliases to a specific implementing function, wrap a call to the implementing function in a static inline function. This encapsulates casting of the invocant, improving type safety. It is also more compatible with CGO, which did not understand the macros.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/5103537d Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/5103537d Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/5103537d Branch: refs/heads/master Commit: 5103537d1d16a6408edf5545de0c55623d6de2a7 Parents: 9cec34f Author: Marvin Humphrey <[email protected]> Authored: Wed May 20 16:23:37 2015 -0700 Committer: Marvin Humphrey <[email protected]> Committed: Wed May 27 15:28:12 2015 -0700 ---------------------------------------------------------------------- compiler/src/CFCBindMethod.c | 94 ++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/5103537d/compiler/src/CFCBindMethod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCBindMethod.c b/compiler/src/CFCBindMethod.c index 0b37408..567812b 100644 --- a/compiler/src/CFCBindMethod.c +++ b/compiler/src/CFCBindMethod.c @@ -25,14 +25,30 @@ #include "CFCVariable.h" #include "CFCSymbol.h" #include "CFCClass.h" +#include "CFCParcel.h" + +#ifndef true + #define true 1 + #define false 0 +#endif -/* 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); +S_method_def(CFCMethod *method, CFCClass *klass, int optimized_final_meth); +/* Create a method invocation routine that resolves to a function name + * directly, since this method may not be overridden. + */ static char* -S_virtual_method_def(CFCMethod *method, CFCClass *klass); +S_final_method_def(CFCMethod *method, CFCClass *klass) { + return S_method_def(method, klass, true); +} + +/* Create a method invocation routine which uses vtable dispatch. + */ +static char* +S_virtual_method_def(CFCMethod *method, CFCClass *klass) { + return S_method_def(method, klass, false); +} char* CFCBindMeth_method_def(CFCMethod *method, CFCClass *klass) { @@ -44,35 +60,8 @@ CFCBindMeth_method_def(CFCMethod *method, CFCClass *klass) { } } -/* 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 *PREFIX = CFCClass_get_PREFIX(klass); - const char *self_type = CFCType_to_c(CFCMethod_self_type(method)); - const char *arg_names - = CFCParamList_name_list(CFCMethod_get_param_list(method)); - - char *full_func_sym = CFCMethod_imp_func(method, klass); - char *full_meth_sym = CFCMethod_full_method_sym(method, klass); - char *full_offset_sym = CFCMethod_full_offset_sym(method, klass); - - const char pattern[] = - "extern %sVISIBLE size_t %s;\n" - "#define %s(%s) \\\n" - " %s((%s)%s)\n"; - char *method_def - = CFCUtil_sprintf(pattern, PREFIX, full_offset_sym, full_meth_sym, - arg_names, full_func_sym, self_type, arg_names); - - FREEMEM(full_offset_sym); - FREEMEM(full_meth_sym); - FREEMEM(full_func_sym); - return method_def; -} - static char* -S_virtual_method_def(CFCMethod *method, CFCClass *klass) { +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); @@ -81,6 +70,7 @@ S_virtual_method_def(CFCMethod *method, CFCClass *klass) { 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)) { @@ -97,19 +87,49 @@ S_virtual_method_def(CFCMethod *method, CFCClass *klass) { 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 size_t %s;\n" "static CFISH_INLINE %s\n" "%s(%s%s) {\n" - " const %s method = (%s)cfish_obj_method(%s, %s);\n" - " %smethod(%s);\n" + "%s" "}\n"; char *method_def = CFCUtil_sprintf(pattern, PREFIX, full_offset_sym, ret_type_str, - full_meth_sym, invoker_struct, params_end, - full_typedef, full_typedef, self_name, full_offset_sym, - maybe_return, arg_names); + 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);
