Use idiomatic Go argument names when possible. * Single-letter method receievers. * lowerCamelCase for parameters.
Project: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/repo Commit: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/commit/2bf2a05c Tree: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/tree/2bf2a05c Diff: http://git-wip-us.apache.org/repos/asf/lucy-clownfish/diff/2bf2a05c Branch: refs/heads/master Commit: 2bf2a05cac2e7eb86ed98dc9c0c359ed4246307c Parents: 6002adc Author: Marvin Humphrey <[email protected]> Authored: Wed Apr 8 15:03:41 2015 -0700 Committer: Marvin Humphrey <[email protected]> Committed: Wed May 6 14:28:15 2015 -0700 ---------------------------------------------------------------------- compiler/src/CFCGoFunc.c | 14 +++++-- compiler/src/CFCGoMethod.c | 23 +++++++++--- compiler/src/CFCGoTypeMap.c | 81 ++++++++++++++++++++++++++++++++++++++++ compiler/src/CFCGoTypeMap.h | 19 ++++++++++ 4 files changed, 127 insertions(+), 10 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2bf2a05c/compiler/src/CFCGoFunc.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCGoFunc.c b/compiler/src/CFCGoFunc.c index 88a887e..59ac1ed 100644 --- a/compiler/src/CFCGoFunc.c +++ b/compiler/src/CFCGoFunc.c @@ -33,6 +33,8 @@ #define false 0 #endif +#define GO_NAME_BUF_SIZE 128 + char* CFCGoFunc_go_meth_name(const char *orig) { char *go_name = CFCUtil_strdup(orig); @@ -50,9 +52,13 @@ CFCGoFunc_func_start(CFCParcel *parcel, const char *name, CFCClass *invoker, int is_method) { CFCVariable **param_vars = CFCParamList_get_variables(param_list); char *invocant; + char go_name[GO_NAME_BUF_SIZE]; + if (is_method) { - invocant = CFCUtil_sprintf("(self *%sIMP) ", - CFCClass_get_struct_sym(invoker)); + const char *struct_sym = CFCClass_get_struct_sym(invoker); + CFCGoTypeMap_go_meth_receiever(struct_sym, param_list, go_name, + GO_NAME_BUF_SIZE); + invocant = CFCUtil_sprintf("(%s *%sIMP) ", go_name, struct_sym); } else { invocant = CFCUtil_strdup(""); @@ -64,11 +70,11 @@ CFCGoFunc_func_start(CFCParcel *parcel, const char *name, CFCClass *invoker, CFCVariable *var = param_vars[i]; CFCType *type = CFCVariable_get_type(var); char *go_type_name = CFCGoTypeMap_go_type_name(type, parcel); + CFCGoTypeMap_go_arg_name(param_list, i, go_name, GO_NAME_BUF_SIZE); if (i > start) { params = CFCUtil_cat(params, ", ", NULL); } - params = CFCUtil_cat(params, CFCVariable_micro_sym(var), " ", - go_type_name, NULL); + params = CFCUtil_cat(params, go_name, " ", go_type_name, NULL); FREEMEM(go_type_name); } http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2bf2a05c/compiler/src/CFCGoMethod.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCGoMethod.c b/compiler/src/CFCGoMethod.c index 05ac230..b15243f 100644 --- a/compiler/src/CFCGoMethod.c +++ b/compiler/src/CFCGoMethod.c @@ -104,22 +104,33 @@ CFCGoMethod_iface_sig(CFCGoMethod *self) { return sig; } +#define GO_NAME_BUF_SIZE 128 + static char* -S_prep_cfargs(CFCParamList *param_list) { +S_prep_cfargs(CFCClass *invoker, CFCParamList *param_list) { CFCVariable **vars = CFCParamList_get_variables(param_list); + char go_name[GO_NAME_BUF_SIZE]; char *cfargs = CFCUtil_strdup(""); + for (int i = 0; vars[i] != NULL; i++) { CFCVariable *var = vars[i]; CFCType *type = CFCVariable_get_type(var); - const char *name = CFCVariable_micro_sym(var); - if (i > 0) { + if (i == 0) { + CFCGoTypeMap_go_meth_receiever(CFCClass_get_struct_sym(invoker), + param_list, go_name, + GO_NAME_BUF_SIZE); + } + else { cfargs = CFCUtil_cat(cfargs, ", ", NULL); + CFCGoTypeMap_go_arg_name(param_list, i, go_name, GO_NAME_BUF_SIZE); } + if (CFCType_is_primitive(type)) { cfargs = CFCUtil_cat(cfargs, "C.", CFCType_get_specifier(type), - "(", name, ")", NULL); + "(", go_name, ")", NULL); } else if (CFCType_is_object(type)) { + char *obj_pattern; if (CFCType_decremented(type)) { obj_pattern = "(*C.%s)(unsafe.Pointer(C.cfish_inc_refcount(unsafe.Pointer(%s.TOPTR()))))"; @@ -128,7 +139,7 @@ S_prep_cfargs(CFCParamList *param_list) { obj_pattern = "(*C.%s)(unsafe.Pointer(%s.TOPTR()))"; } char *temp = CFCUtil_sprintf(obj_pattern, - CFCType_get_specifier(type), name); + CFCType_get_specifier(type), go_name); cfargs = CFCUtil_cat(cfargs, temp, NULL); FREEMEM(temp); } @@ -147,7 +158,7 @@ CFCGoMethod_func_def(CFCGoMethod *self, CFCClass *invoker) { param_list, ret_type, true); char *full_meth_sym = CFCMethod_full_method_sym(novel_method, NULL); - char *cfargs = S_prep_cfargs(param_list); + char *cfargs = S_prep_cfargs(invoker, param_list); char *ret_type_str; char *maybe_retval; http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2bf2a05c/compiler/src/CFCGoTypeMap.c ---------------------------------------------------------------------- diff --git a/compiler/src/CFCGoTypeMap.c b/compiler/src/CFCGoTypeMap.c index 516f42b..50aaa32 100644 --- a/compiler/src/CFCGoTypeMap.c +++ b/compiler/src/CFCGoTypeMap.c @@ -20,9 +20,16 @@ #include "CFCGoTypeMap.h" #include "CFCParcel.h" +#include "CFCParamList.h" +#include "CFCVariable.h" #include "CFCType.h" #include "CFCUtil.h" +#ifndef true + #define true 1 + #define false 0 +#endif + /* Integer types with implementation-specific widths are tricky to convert. * If a C `int` and a Go `int` are not the same width, it is potentially * dangerous to map between them. For example, if a function takes a 32-bit C @@ -144,3 +151,77 @@ CFCGoTypeMap_go_short_package(CFCParcel *parcel) { return go_short_package; } + +void +CFCGoTypeMap_go_meth_receiever(const char *struct_name, + CFCParamList *param_list, + char *buf, size_t buf_len) { + size_t max_required = 2; + if (param_list != NULL && CFCParamList_num_vars(param_list) > 0) { + CFCVariable **vars = CFCParamList_get_variables(param_list); + const char *orig = CFCVariable_micro_sym(vars[0]); + max_required = strlen(orig) + 1; + } + if (buf_len < max_required) { + CFCUtil_die("Buffer length too short: %d", buf_len); + } + + // Find the first letter of the type and lowercase it. + for (size_t i = 0, max = strlen(struct_name); i < max; i++) { + if (isupper(struct_name[i])) { + buf[0] = tolower(struct_name[i]); + buf[1] = '\0'; + break; + } + } + + // Check for another argument with the same name. + if (param_list != NULL) { + CFCVariable **vars = CFCParamList_get_variables(param_list); + size_t num_vars = CFCParamList_num_vars(param_list); + for (int i = 1; i < num_vars; i++) { + const char *name = CFCVariable_micro_sym(vars[i]); + if (strcmp(name, buf) == 0) { + // Bah, a clash. Use the original name, even though it's + // probably "self" which isn't good Go style. + CFCGoTypeMap_go_arg_name(param_list, 0, buf, buf_len); + break; + } + } + } +} + +void +CFCGoTypeMap_go_arg_name(CFCParamList *param_list, size_t tick, char *buf, + size_t buf_len) { + size_t num_vars = CFCParamList_num_vars(param_list); + if (tick >= num_vars) { + CFCUtil_die("Index out of range: %d >= %d", (int)tick, (int)num_vars); + } + CFCVariable **vars = CFCParamList_get_variables(param_list); + const char *orig = CFCVariable_micro_sym(vars[tick]); + size_t max_required = strlen(orig) + 2; + if (buf_len < max_required || buf_len < 5) { + CFCUtil_die("Buffer length too short: %d", buf_len); + } + size_t dest_tick = 0; + int last_was_underscore = 0; + for (size_t i = 0; i <= strlen(orig); i++) { + if (i > buf_len) { + CFCUtil_die("Name too long for buffer of size %d: '%s'", buf_len, + orig); + } + if (orig[i] == '_') { + last_was_underscore = 1; + continue; + } + else if (last_was_underscore) { + buf[dest_tick] = toupper(orig[i]); + } + else { + buf[dest_tick] = orig[i]; + } + last_was_underscore = 0; + dest_tick++; + } +} http://git-wip-us.apache.org/repos/asf/lucy-clownfish/blob/2bf2a05c/compiler/src/CFCGoTypeMap.h ---------------------------------------------------------------------- diff --git a/compiler/src/CFCGoTypeMap.h b/compiler/src/CFCGoTypeMap.h index f0b3929..da20c26 100644 --- a/compiler/src/CFCGoTypeMap.h +++ b/compiler/src/CFCGoTypeMap.h @@ -23,6 +23,7 @@ extern "C" { struct CFCType; struct CFCParcel; +struct CFCParamList; char* CFCGoTypeMap_go_type_name(struct CFCType *type, @@ -33,6 +34,24 @@ CFCGoTypeMap_go_type_name(struct CFCType *type, char* CFCGoTypeMap_go_short_package(struct CFCParcel *parcel); +/** Convert param names to lowerCamelCase, storing the result in `buf`. + */ +void +CFCGoTypeMap_go_arg_name(struct CFCParamList *param_list, size_t tick, + char *buf, size_t buf_len); + +/** For the name of the method receiver, default to lower case letter derived + * from type, e.g. `f` for `Foo`. + * + * `param_list` may be NULL. If it is not, check to see whether the + * single-letter name is already taken by another parameter. In the event of + * a clash, use the result of `CFCGoTypeMap_go_arg_name` instead. + */ +void +CFCGoTypeMap_go_meth_receiever(const char *struct_name, + struct CFCParamList *param_list, + char *buf, size_t buf_len); + #ifdef __cplusplus } #endif
