Clownfish-CFC

 view release on metacpan or  search on metacpan

src/CFCGoTypeMap.c  view on Meta::CPAN

    if (CFCType_cfish_obj(type)) {
        return CFCUtil_strdup("interface{}");
    }
    else if (CFCType_cfish_string(type)) {
        return CFCUtil_strdup("string");
    }
    else if (CFCType_cfish_blob(type)) {
        return CFCUtil_strdup("[]byte");
    }
    else if (CFCType_cfish_vector(type)) {
        return CFCUtil_strdup("[]interface{}");
    }
    else if (CFCType_cfish_hash(type)) {
        return CFCUtil_strdup("map[string]interface{}");
    }
    else if (CFCType_is_object(type)) {
        // Divide the specifier into prefix and struct name.
        CFCClass   *klass      = CFCType_get_class(type);
        const char *struct_sym = CFCClass_get_struct_sym(klass);
        CFCParcel  *parcel     = CFCClass_get_parcel(klass);
        if (!parcel) {
            CFCUtil_die("Can't find parcel for type '%s'",
                        CFCType_get_specifier(type));
        }

        // If the type lives in this parcel, return only the struct sym
        // without a go package prefix.
        if (parcel == current_parcel) {
            return CFCUtil_strdup(struct_sym);
        }

        // The type lives in another parcel, so prefix its Go package name.
        // TODO: Stop downcasing once Clownfish parcel names are constrained
        // to lower case.
        const char *package_name = CFCParcel_get_name(parcel);
        if (strrchr(package_name, '.')) {
            package_name = strrchr(package_name, '.') + 1;
        }
        char *result = CFCUtil_sprintf("%s.%s", package_name, struct_sym);
        for (int i = 0; result[i] != '.'; i++) {
            result[i] = CFCUtil_tolower(result[i]);
        }
        return result;
    }
    else if (CFCType_is_primitive(type)) {
        const char *specifier = CFCType_get_specifier(type);
        for (int i = 0; i < num_conversions; i++) {
            if (strcmp(specifier, conversions[i].c) == 0) {
                return CFCUtil_strdup(conversions[i].go);
            }
        }
    }

    return NULL;
}

char*
CFCGoTypeMap_go_short_package(CFCParcel *parcel) {
    // The Go short package name is the last component of the dot-separated
    // Clownfish parcel name.
    const char *parcel_frag = strrchr(CFCParcel_get_name(parcel), '.');
    if (parcel_frag) {
        parcel_frag += 1;
    }
    else {
        parcel_frag = CFCParcel_get_name(parcel);
    }
    // TODO: Don't downcase package name once caps are forbidden in Clownfish
    // parcel names.
    char *go_short_package = CFCUtil_strdup(parcel_frag);
    for (int i = 0; go_short_package[i] != '\0'; i++) {
        go_short_package[i] = CFCUtil_tolower(go_short_package[i]);
    }
    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_get_name(vars[0]);
        max_required = strlen(orig) + 1;
    }
    if (buf_len < max_required) {
        CFCUtil_die("Buffer length too short: %d", (int)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 (CFCUtil_isupper(struct_name[i])) {
            buf[0] = CFCUtil_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);
        int num_vars = CFCParamList_num_vars(param_list);
        for (int i = 1; i < num_vars; i++) {
            const char *name = CFCVariable_get_name(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) {
    int num_vars = CFCParamList_num_vars(param_list);
    if (tick >= (size_t)num_vars) {
        CFCUtil_die("Index out of range: %d >= %d", (int)tick, num_vars);
    }
    CFCVariable **vars = CFCParamList_get_variables(param_list);
    const char *orig = CFCVariable_get_name(vars[tick]);
    size_t max_required = strlen(orig) + 2;
    if (buf_len < max_required || buf_len < 5) {
        CFCUtil_die("Buffer length too short: %d", (int)buf_len);
    }



( run in 1.780 second using v1.01-cache-2.11-cpan-364913b4093 )