diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-21 22:50:20 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-21 22:50:31 +0000 |
| commit | 260f01af1d3c19827d175740e30da57a288a6e86 (patch) | |
| tree | e81e36c0297c22eefa6988c0306ea87211d78314 /src/parser/parser_utils.c | |
| parent | a552bd6b8175fe833e8a77dfb051bf3481df6851 (diff) | |
Fix for #74
Diffstat (limited to 'src/parser/parser_utils.c')
| -rw-r--r-- | src/parser/parser_utils.c | 560 |
1 files changed, 395 insertions, 165 deletions
diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index afd6f33..f1345ba 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -858,6 +858,57 @@ char *replace_in_string(const char *src, const char *old_w, const char *new_w) return src ? xstrdup(src) : NULL; } + // Check for multiple parameters (comma separated) + if (strchr(old_w, ',')) + { + char *running_src = xstrdup(src); + + char *p_ptr = (char *)old_w; + char *c_ptr = (char *)new_w; + + while (*p_ptr && *c_ptr) + { + char *p_end = strchr(p_ptr, ','); + int p_len = p_end ? (p_end - p_ptr) : strlen(p_ptr); + + char *c_end = strchr(c_ptr, ','); + int c_len = c_end ? (c_end - c_ptr) : strlen(c_ptr); + + char *curr_p = xmalloc(p_len + 1); + strncpy(curr_p, p_ptr, p_len); + curr_p[p_len] = 0; + + char *curr_c = xmalloc(c_len + 1); + strncpy(curr_c, c_ptr, c_len); + curr_c[c_len] = 0; + + char *next_src = replace_in_string(running_src, curr_p, curr_c); + free(running_src); + running_src = next_src; + + free(curr_p); + free(curr_c); + + if (p_end) + { + p_ptr = p_end + 1; + } + else + { + break; + } + if (c_end) + { + c_ptr = c_end + 1; + } + else + { + break; + } + } + return running_src; + } + char *result; int i, cnt = 0; int newWlen = strlen(new_w); @@ -940,8 +991,50 @@ char *replace_type_str(const char *src, const char *param, const char *concrete, return NULL; } - if (strcmp(src, param) == 0) + // Handle multi-param match + if (param && concrete && strchr(param, ',')) + { + char *p_ptr = (char *)param; + char *c_ptr = (char *)concrete; + + while (*p_ptr && *c_ptr) + { + char *p_end = strchr(p_ptr, ','); + int p_len = p_end ? (p_end - p_ptr) : strlen(p_ptr); + + char *c_end = strchr(c_ptr, ','); + int c_len = c_end ? (c_end - c_ptr) : strlen(c_ptr); + + if (strlen(src) == p_len && strncmp(src, p_ptr, p_len) == 0) + { + char *ret = xmalloc(c_len + 1); + strncpy(ret, c_ptr, c_len); + ret[c_len] = 0; + return ret; + } + + if (p_end) + { + p_ptr = p_end + 1; + } + else + { + break; + } + if (c_end) + { + c_ptr = c_end + 1; + } + else + { + break; + } + } + } + + if (param && strcmp(src, param) == 0) { + return xstrdup(concrete); } @@ -964,21 +1057,46 @@ char *replace_type_str(const char *src, const char *param, const char *concrete, if (param && concrete && src) { - char suffix[256]; - sprintf(suffix, "_%s", param); + // Construct mangled suffix from param ("F,S" -> "_F_S") + char p_suffix[1024]; + p_suffix[0] = 0; + + char *p_temp = xstrdup(param); + char *tok = strtok(p_temp, ","); + while (tok) + { + strcat(p_suffix, "_"); + strcat(p_suffix, tok); + tok = strtok(NULL, ","); + } + free(p_temp); + size_t slen = strlen(src); - size_t plen = strlen(suffix); - if (slen > plen && strcmp(src + slen - plen, suffix) == 0) + size_t plen = strlen(p_suffix); + + if (slen >= plen && strcmp(src + slen - plen, p_suffix) == 0) { - // Ends with _T -> Replace suffix with _int (sanitize for pointers like - // JsonValue*) - char *clean_concrete = sanitize_mangled_name(concrete); - char *ret = xmalloc(slen - plen + strlen(clean_concrete) + 2); + // Construct replacement suffix from concrete ("int,float" -> "_int_float") + char c_suffix[1024]; + c_suffix[0] = 0; + + char *c_temp = xstrdup(concrete); + tok = strtok(c_temp, ","); + while (tok) + { + strcat(c_suffix, "_"); + char *clean = sanitize_mangled_name(tok); + strcat(c_suffix, clean); + free(clean); + tok = strtok(NULL, ","); + } + free(c_temp); + + // Perform replacement + char *ret = xmalloc(slen - plen + strlen(c_suffix) + 1); strncpy(ret, src, slen - plen); ret[slen - plen] = 0; - strcat(ret, "_"); - strcat(ret, clean_concrete); - free(clean_concrete); + strcat(ret, c_suffix); return ret; } } @@ -1025,6 +1143,111 @@ char *replace_type_str(const char *src, const char *param, const char *concrete, ASTNode *copy_ast_replacing(ASTNode *n, const char *p, const char *c, const char *os, const char *ns); +// Helper to create type from string (primitives or struct) +Type *type_from_string_helper(const char *c) +{ + if (strcmp(c, "int") == 0) + { + return type_new(TYPE_INT); + } + if (strcmp(c, "float") == 0) + { + return type_new(TYPE_FLOAT); + } + if (strcmp(c, "void") == 0) + { + return type_new(TYPE_VOID); + } + if (strcmp(c, "string") == 0) + { + return type_new(TYPE_STRING); + } + if (strcmp(c, "bool") == 0) + { + return type_new(TYPE_BOOL); + } + if (strcmp(c, "char") == 0) + { + return type_new(TYPE_CHAR); + } + if (strcmp(c, "I8") == 0 || strcmp(c, "i8") == 0) + { + return type_new(TYPE_I8); + } + if (strcmp(c, "U8") == 0 || strcmp(c, "u8") == 0) + { + return type_new(TYPE_U8); + } + if (strcmp(c, "I16") == 0 || strcmp(c, "i16") == 0) + { + return type_new(TYPE_I16); + } + if (strcmp(c, "U16") == 0 || strcmp(c, "u16") == 0) + { + return type_new(TYPE_U16); + } + if (strcmp(c, "I32") == 0 || strcmp(c, "i32") == 0 || strcmp(c, "int32_t") == 0) + { + return type_new(TYPE_I32); + } + if (strcmp(c, "U32") == 0 || strcmp(c, "u32") == 0 || strcmp(c, "uint32_t") == 0) + { + return type_new(TYPE_U32); + } + if (strcmp(c, "I64") == 0 || strcmp(c, "i64") == 0 || strcmp(c, "int64_t") == 0) + { + return type_new(TYPE_I64); + } + if (strcmp(c, "U64") == 0 || strcmp(c, "u64") == 0 || strcmp(c, "uint64_t") == 0) + { + return type_new(TYPE_U64); + } + if (strcmp(c, "float") == 0 || strcmp(c, "f32") == 0) + { + return type_new(TYPE_F32); + } + if (strcmp(c, "double") == 0 || strcmp(c, "f64") == 0) + { + return type_new(TYPE_F64); + } + if (strcmp(c, "I128") == 0 || strcmp(c, "i128") == 0) + { + return type_new(TYPE_I128); + } + if (strcmp(c, "U128") == 0 || strcmp(c, "u128") == 0) + { + return type_new(TYPE_U128); + } + if (strcmp(c, "rune") == 0) + { + return type_new(TYPE_RUNE); + } + if (strcmp(c, "uint") == 0) + { + return type_new(TYPE_UINT); + } + if (strcmp(c, "double") == 0) + { + return type_new(TYPE_F64); + } + if (strcmp(c, "byte") == 0) + { + return type_new(TYPE_BYTE); + } + if (strcmp(c, "usize") == 0) + { + return type_new(TYPE_USIZE); + } + if (strcmp(c, "isize") == 0) + { + return type_new(TYPE_ISIZE); + } + + Type *n = type_new(TYPE_STRUCT); + n->name = sanitize_mangled_name(c); + return n; +} + Type *replace_type_formal(Type *t, const char *p, const char *c, const char *os, const char *ns) { if (!t) @@ -1032,155 +1255,54 @@ Type *replace_type_formal(Type *t, const char *p, const char *c, const char *os, return NULL; } - if ((t->kind == TYPE_STRUCT || t->kind == TYPE_GENERIC) && t->name && strcmp(t->name, p) == 0) + // Exact Match Logic (with multi-param splitting) + if ((t->kind == TYPE_STRUCT || t->kind == TYPE_GENERIC) && t->name) { - if (strcmp(c, "int") == 0) - { - return type_new(TYPE_INT); - } - if (strcmp(c, "float") == 0) - { - return type_new(TYPE_FLOAT); - } - if (strcmp(c, "void") == 0) - { - return type_new(TYPE_VOID); - } - if (strcmp(c, "string") == 0) - { - return type_new(TYPE_STRING); - } - if (strcmp(c, "bool") == 0) - { - return type_new(TYPE_BOOL); - } - if (strcmp(c, "char") == 0) - { - return type_new(TYPE_CHAR); - } - if (strcmp(c, "I8") == 0) - { - return type_new(TYPE_I8); - } - if (strcmp(c, "U8") == 0) - { - return type_new(TYPE_U8); - } - if (strcmp(c, "I16") == 0) - { - return type_new(TYPE_I16); - } - if (strcmp(c, "U16") == 0) - { - return type_new(TYPE_U16); - } - if (strcmp(c, "I32") == 0) - { - return type_new(TYPE_I32); - } - if (strcmp(c, "U32") == 0) - { - return type_new(TYPE_U32); - } - if (strcmp(c, "I64") == 0) - { - return type_new(TYPE_I64); - } - if (strcmp(c, "U64") == 0) - { - return type_new(TYPE_U64); - } - if (strcmp(c, "F32") == 0) - { - return type_new(TYPE_F32); - } - if (strcmp(c, "f32") == 0) + if (p && c && strchr(p, ',')) { - return type_new(TYPE_F32); - } - if (strcmp(c, "F64") == 0) - { - return type_new(TYPE_F64); - } - if (strcmp(c, "f64") == 0) - { - return type_new(TYPE_F64); - } + char *p_ptr = (char *)p; + char *c_ptr = (char *)c; + while (*p_ptr && *c_ptr) + { + char *p_end = strchr(p_ptr, ','); + int p_len = p_end ? (p_end - p_ptr) : strlen(p_ptr); + char *c_end = strchr(c_ptr, ','); + int c_len = c_end ? (c_end - c_ptr) : strlen(c_ptr); - if (strcmp(c, "usize") == 0) - { - return type_new(TYPE_USIZE); - } - if (strcmp(c, "isize") == 0) - { - return type_new(TYPE_ISIZE); - } - if (strcmp(c, "byte") == 0) - { - return type_new(TYPE_BYTE); - } - if (strcmp(c, "I128") == 0) - { - return type_new(TYPE_I128); - } - if (strcmp(c, "U128") == 0) - { - return type_new(TYPE_U128); - } - if (strcmp(c, "i8") == 0) - { - return type_new(TYPE_I8); - } - if (strcmp(c, "u8") == 0) - { - return type_new(TYPE_U8); - } - if (strcmp(c, "i16") == 0) - { - return type_new(TYPE_I16); - } - if (strcmp(c, "u16") == 0) - { - return type_new(TYPE_U16); - } - if (strcmp(c, "i32") == 0) - { - return type_new(TYPE_I32); - } - if (strcmp(c, "u32") == 0) - { - return type_new(TYPE_U32); - } - if (strcmp(c, "i64") == 0) - { - return type_new(TYPE_I64); - } - if (strcmp(c, "u64") == 0) - { - return type_new(TYPE_U64); - } - if (strcmp(c, "i128") == 0) - { - return type_new(TYPE_I128); - } - if (strcmp(c, "u128") == 0) - { - return type_new(TYPE_U128); - } + if (strlen(t->name) == p_len && strncmp(t->name, p_ptr, p_len) == 0) + { + char *c_part = xmalloc(c_len + 1); + strncpy(c_part, c_ptr, c_len); + c_part[c_len] = 0; - if (strcmp(c, "rune") == 0) - { - return type_new(TYPE_RUNE); + Type *res = type_from_string_helper(c_part); + free(c_part); + return res; + } + if (p_end) + { + p_ptr = p_end + 1; + } + else + { + break; + } + if (c_end) + { + c_ptr = c_end + 1; + } + else + { + break; + } + } } - if (strcmp(c, "uint") == 0) + else if (strcmp(t->name, p) == 0) { - return type_new(TYPE_UINT); - } - Type *n = type_new(TYPE_STRUCT); - n->name = sanitize_mangled_name(c); - return n; + return type_from_string_helper(c); + } } Type *n = xmalloc(sizeof(Type)); @@ -1195,26 +1317,46 @@ Type *replace_type_formal(Type *t, const char *p, const char *c, const char *os, n->arg_count = 0; n->args = NULL; } - else if (p && c) { - char suffix[256]; - sprintf(suffix, "_%s", p); // e.g. "_T" + // Suffix Match Logic (with multi-param splitting) + char p_suffix[1024]; + p_suffix[0] = 0; + + char *p_temp = xstrdup(p); + char *tok = strtok(p_temp, ","); + while (tok) + { + strcat(p_suffix, "_"); + strcat(p_suffix, tok); + tok = strtok(NULL, ","); + } + free(p_temp); + size_t nlen = strlen(t->name); - size_t slen = strlen(suffix); + size_t slen = strlen(p_suffix); - if (nlen > slen && strcmp(t->name + nlen - slen, suffix) == 0) + if (nlen >= slen && strcmp(t->name + nlen - slen, p_suffix) == 0) { - // It ends in _T. Replace with _int (c), sanitizing for pointers - char *clean_c = sanitize_mangled_name(c); - char *new_name = xmalloc(nlen - slen + strlen(clean_c) + 2); + char c_suffix[1024]; + c_suffix[0] = 0; + char *c_temp = xstrdup(c); + tok = strtok(c_temp, ","); + while (tok) + { + strcat(c_suffix, "_"); + char *clean = sanitize_mangled_name(tok); + strcat(c_suffix, clean); + free(clean); + tok = strtok(NULL, ","); + } + free(c_temp); + + char *new_name = xmalloc(nlen - slen + strlen(c_suffix) + 1); strncpy(new_name, t->name, nlen - slen); new_name[nlen - slen] = 0; - strcat(new_name, "_"); - strcat(new_name, clean_c); - free(clean_c); + strcat(new_name, c_suffix); n->name = new_name; - // Ensure it's concrete to prevent double mangling later n->kind = TYPE_STRUCT; n->arg_count = 0; n->args = NULL; @@ -1622,6 +1764,92 @@ char *instantiate_function_template(ParserContext *ctx, const char *name, const } const char *subst_arg = unmangled_type ? unmangled_type : concrete_type; + + // Scan the original return type for generic struct patterns like "Triple_X_Y_Z" + // and instantiate them with the concrete types + if (tpl->func_node && tpl->func_node->func.ret_type) + { + const char *ret = tpl->func_node->func.ret_type; + + // Build the param suffix (e.g., for "X,Y,Z" -> "_X_Y_Z") + char param_suffix[256]; + param_suffix[0] = 0; + char *tmp = xstrdup(tpl->generic_param); + char *tokp = strtok(tmp, ","); + while (tokp) + { + strcat(param_suffix, "_"); + strcat(param_suffix, tokp); + tokp = strtok(NULL, ","); + } + free(tmp); + + // Check if ret_type ends with param_suffix (e.g., "Triple_X_Y_Z" ends with "_X_Y_Z") + size_t ret_len = strlen(ret); + size_t suffix_len = strlen(param_suffix); + if (ret_len > suffix_len && strcmp(ret + ret_len - suffix_len, param_suffix) == 0) + { + // Extract base struct name (e.g., "Triple" from "Triple_X_Y_Z") + size_t base_len = ret_len - suffix_len; + char *struct_base = xmalloc(base_len + 1); + strncpy(struct_base, ret, base_len); + struct_base[base_len] = 0; + + // Check if it's a known generic template + GenericTemplate *gt = ctx->templates; + while (gt && strcmp(gt->name, struct_base) != 0) + { + gt = gt->next; + } + if (gt) + { + // Parse the concrete types from unmangled_type or concrete_type + const char *types_src = unmangled_type ? unmangled_type : concrete_type; + + // Count params in template + int template_param_count = 1; + for (const char *p = tpl->generic_param; *p; p++) + { + if (*p == ',') + { + template_param_count++; + } + } + + // Split concrete types + char **args = xmalloc(sizeof(char *) * template_param_count); + int arg_count = 0; + char *types_copy = xstrdup(types_src); + char *tok = strtok(types_copy, ","); + while (tok && arg_count < template_param_count) + { + args[arg_count++] = xstrdup(tok); + tok = strtok(NULL, ","); + } + free(types_copy); + + // Now instantiate the struct with these args + Token dummy_tok = {0}; + if (arg_count == 1) + { + instantiate_generic(ctx, struct_base, args[0], args[0], dummy_tok); + } + else if (arg_count > 1) + { + instantiate_generic_multi(ctx, struct_base, args, arg_count, dummy_tok); + } + + // Cleanup + for (int i = 0; i < arg_count; i++) + { + free(args[i]); + } + free(args); + } + free(struct_base); + } + } + ASTNode *new_fn = copy_ast_replacing(tpl->func_node, tpl->generic_param, subst_arg, NULL, NULL); if (!new_fn || new_fn->type != NODE_FUNCTION) { @@ -2157,12 +2385,14 @@ void instantiate_generic_multi(ParserContext *ctx, const char *tpl, char **args, if (param_count > 0 && arg_count > 0) { // First substitution + i->strct.fields = copy_fields_replacing( ctx, fields, t->struct_node->strct.generic_params[0], args[0]); // Subsequent substitutions (for params B, C, etc.) for (int j = 1; j < param_count && j < arg_count; j++) { + ASTNode *tmp = copy_fields_replacing( ctx, i->strct.fields, t->struct_node->strct.generic_params[j], args[j]); // This leaks prev fields, but that's acceptable for now, still, TODO. |
