summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/parser/parser.h1
-rw-r--r--src/parser/parser_expr.c88
-rw-r--r--src/parser/parser_stmt.c46
-rw-r--r--src/parser/parser_utils.c39
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;
}