diff options
| author | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-19 14:14:35 +0000 |
|---|---|---|
| committer | Zuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian> | 2026-01-19 14:14:35 +0000 |
| commit | 59a6975e2f62cb8ebc4893d021f1f11cf4389385 (patch) | |
| tree | 1c55b4b5050a95e5e0d2f63ed1df0cfbdb30eefa /src/parser | |
| parent | dca83c5f7cd410c36dae609e0a67461bf067161c (diff) | |
Fix for #75
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/parser.h | 1 | ||||
| -rw-r--r-- | src/parser/parser_expr.c | 88 | ||||
| -rw-r--r-- | src/parser/parser_stmt.c | 46 | ||||
| -rw-r--r-- | src/parser/parser_utils.c | 39 |
4 files changed, 171 insertions, 3 deletions
diff --git a/src/parser/parser.h b/src/parser/parser.h index cfe486d..b3837eb 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -243,6 +243,7 @@ struct ParserContext // Config/State char *current_impl_struct; + ASTNode *current_impl_methods; // Head of method list for current impl block // Internal tracking DeprecatedFunc *deprecated_funcs; diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index ef3980c..f7590e3 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -2497,16 +2497,102 @@ char *resolve_struct_name_from_type(ParserContext *ctx, Type *t, int *is_ptr_out } else { + Type *struct_type = NULL; if (t->kind == TYPE_STRUCT) { + struct_type = t; struct_name = t->name; *is_ptr_out = 0; } else if (t->kind == TYPE_POINTER && t->inner->kind == TYPE_STRUCT) { - struct_name = t->inner->name; + struct_type = t->inner; *is_ptr_out = 1; } + + if (struct_type) + { + if (struct_type->args && struct_type->arg_count > 0 && struct_type->name) + { + // It's a generic type instance (e.g. Foo<T>). + // We must construct Foo_T, ensuring we measure SANITIZED length. + int len = strlen(struct_type->name) + 1; + + // Pass 1: Calculate Length + for (int i = 0; i < struct_type->arg_count; i++) + { + Type *arg = struct_type->args[i]; + if (arg) + { + char *s = type_to_string(arg); + if (s) + { + char *clean = sanitize_mangled_name(s); + if (clean) + { + len += strlen(clean) + 1; // +1 for '_' + free(clean); + } + free(s); + } + } + } + + char *mangled = xmalloc(len + 1); + strcpy(mangled, struct_type->name); + + // Pass 2: Build String + for (int i = 0; i < struct_type->arg_count; i++) + { + Type *arg = struct_type->args[i]; + if (arg) + { + char *arg_str = type_to_string(arg); + if (arg_str) + { + char *clean = sanitize_mangled_name(arg_str); + if (clean) + { + strcat(mangled, "_"); + strcat(mangled, clean); + free(clean); + } + free(arg_str); + } + } + } + struct_name = mangled; + *allocated_out = mangled; + } + else if (struct_type->name && strchr(struct_type->name, '<')) + { + // Fallback: It's a generic type string. We need to mangle it. + char *tpl = xstrdup(struct_type->name); + char *args_ptr = strchr(tpl, '<'); + if (args_ptr) + { + *args_ptr = 0; + args_ptr++; + char *end = strrchr(args_ptr, '>'); + if (end) + { + *end = 0; + } + + char *clean = sanitize_mangled_name(args_ptr); + char *mangled = xmalloc(strlen(tpl) + strlen(clean) + 2); + sprintf(mangled, "%s_%s", tpl, clean); + struct_name = mangled; + *allocated_out = mangled; + free(clean); + } + free(tpl); + } + else + { + struct_name = struct_type->name; + } + } } return struct_name; } diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c index df490b7..699b9fc 100644 --- a/src/parser/parser_stmt.c +++ b/src/parser/parser_stmt.c @@ -3415,9 +3415,14 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) { zpanic_at(lexer_peek(l), "Expected {"); } + char *full_struct_name = xmalloc(strlen(name1) + strlen(gen_param) + 3); + sprintf(full_struct_name, "%s<%s>", name1, gen_param); + ASTNode *h = 0, *tl = 0; + ctx->current_impl_methods = NULL; while (1) { + ctx->current_impl_methods = h; skip_comments(l); if (lexer_peek(l).type == TOK_RBRACE) { @@ -3433,10 +3438,28 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) free(f->func.name); f->func.name = mangled; - char *na = patch_self_args(f->func.args, name1); + // Update args string + char *na = patch_self_args(f->func.args, full_struct_name); free(f->func.args); f->func.args = na; + // Manual Type construction for self: Foo<T>* + if (f->func.arg_count > 0 && f->func.param_names && + strcmp(f->func.param_names[0], "self") == 0) + { + Type *t_struct = type_new(TYPE_STRUCT); + t_struct->name = xstrdup(name1); + t_struct->arg_count = 1; + t_struct->args = xmalloc(sizeof(Type *)); + t_struct->args[0] = type_new(TYPE_GENERIC); + t_struct->args[0]->name = xstrdup(gen_param); + + Type *t_ptr = type_new(TYPE_POINTER); + t_ptr->inner = t_struct; + + f->func.arg_types[0] = t_ptr; + } + if (!h) { h = f; @@ -3459,9 +3482,27 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) sprintf(mangled, "%s__%s", name1, f->func.name); free(f->func.name); f->func.name = mangled; - char *na = patch_self_args(f->func.args, name1); + + char *na = patch_self_args(f->func.args, full_struct_name); free(f->func.args); f->func.args = na; + + if (f->func.arg_count > 0 && f->func.param_names && + strcmp(f->func.param_names[0], "self") == 0) + { + Type *t_struct = type_new(TYPE_STRUCT); + t_struct->name = xstrdup(name1); + t_struct->arg_count = 1; + t_struct->args = xmalloc(sizeof(Type *)); + t_struct->args[0] = type_new(TYPE_GENERIC); + t_struct->args[0]->name = xstrdup(gen_param); + + Type *t_ptr = type_new(TYPE_POINTER); + t_ptr->inner = t_struct; + + f->func.arg_types[0] = t_ptr; + } + if (!h) { h = f; @@ -3482,6 +3523,7 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l) lexer_next(l); } } + free(full_struct_name); // Register Template ASTNode *n = ast_create(NODE_IMPL); n->impl.struct_name = name1; diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 29407b5..1f881b7 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -1415,6 +1415,18 @@ ASTNode *copy_ast_replacing(ASTNode *n, const char *p, const char *c, const char free(n1); n1 = n2; } + if (os && ns) + { + int os_len = strlen(os); + if (strncmp(n1, os, os_len) == 0 && n1[os_len] == '_' && n1[os_len + 1] == '_') + { + char *suffix = n1 + os_len; + char *n3 = xmalloc(strlen(ns) + strlen(suffix) + 1); + sprintf(n3, "%s%s", ns, suffix); + free(n1); + n1 = n3; + } + } new_node->var_ref.name = n1; } break; @@ -1554,6 +1566,33 @@ FuncSig *find_func(ParserContext *ctx, const char *name) } c = c->next; } + + // Fallback: Check current_impl_methods (siblings in the same impl block) + if (ctx && ctx->current_impl_methods) + { + ASTNode *n = ctx->current_impl_methods; + while (n) + { + if (n->type == NODE_FUNCTION && strcmp(n->func.name, name) == 0) + { + // Found sibling method. Construct a temporary FuncSig. + FuncSig *sig = xmalloc(sizeof(FuncSig)); + sig->name = n->func.name; + sig->decl_token = n->token; + sig->total_args = n->func.arg_count; + sig->defaults = n->func.defaults; + sig->arg_types = n->func.arg_types; + sig->ret_type = n->func.ret_type_info; + sig->is_varargs = n->func.is_varargs; + sig->is_async = n->func.is_async; + sig->must_use = 0; + sig->next = NULL; + return sig; + } + n = n->next; + } + } + return NULL; } |
