summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/codegen/codegen.c26
-rw-r--r--src/parser/parser_decl.c30
-rw-r--r--src/parser/parser_expr.c56
-rw-r--r--src/parser/parser_struct.c56
4 files changed, 152 insertions, 16 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c
index b375bbb..689c4dc 100644
--- a/src/codegen/codegen.c
+++ b/src/codegen/codegen.c
@@ -464,6 +464,32 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out)
ref = ref->next;
}
+ if (!resolved_method_suffix)
+ {
+ GenericImplTemplate *it = ctx->impl_templates;
+ while (it)
+ {
+ char *tname = NULL;
+ if (it->impl_node && it->impl_node->type == NODE_IMPL_TRAIT)
+ {
+ tname = it->impl_node->impl_trait.trait_name;
+ }
+ if (tname)
+ {
+ char trait_mangled[512];
+ sprintf(trait_mangled, "%s__%s_%s", base, tname, method);
+ if (find_func(ctx, trait_mangled))
+ {
+ char *suffix = xmalloc(strlen(tname) + strlen(method) + 2);
+ sprintf(suffix, "%s_%s", tname, method);
+ resolved_method_suffix = suffix;
+ break;
+ }
+ }
+ it = it->next;
+ }
+ }
+
if (resolved_method_suffix)
{
method = resolved_method_suffix;
diff --git a/src/parser/parser_decl.c b/src/parser/parser_decl.c
index bd56350..5d5af1e 100644
--- a/src/parser/parser_decl.c
+++ b/src/parser/parser_decl.c
@@ -207,17 +207,43 @@ char *patch_self_args(const char *args, const char *struct_name)
{
return NULL;
}
- char *new_args = xmalloc(strlen(args) + strlen(struct_name) + 10);
+
+ // Sanitize struct name for C usage (Vec<T> -> Vec_T)
+ char *safe_name = xmalloc(strlen(struct_name) + 1);
+ int j = 0;
+ for (int i = 0; struct_name[i]; i++)
+ {
+ if (struct_name[i] == '<')
+ {
+ safe_name[j++] = '_';
+ }
+ else if (struct_name[i] == '>')
+ {
+ // skip
+ }
+ else if (struct_name[i] == ' ')
+ {
+ // skip
+ }
+ else
+ {
+ safe_name[j++] = struct_name[i];
+ }
+ }
+ safe_name[j] = 0;
+
+ char *new_args = xmalloc(strlen(args) + strlen(safe_name) + 10);
// Check if it starts with "void* self"
if (strncmp(args, "void* self", 10) == 0)
{
- sprintf(new_args, "%s* self%s", struct_name, args + 10);
+ sprintf(new_args, "%s* self%s", safe_name, args + 10);
}
else
{
strcpy(new_args, args);
}
+ free(safe_name);
return new_args;
}
// Helper for Value-Returning Defer
diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c
index 07f133e..b07b544 100644
--- a/src/parser/parser_expr.c
+++ b/src/parser/parser_expr.c
@@ -1646,13 +1646,59 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l)
v = v->next;
}
}
+ int resolved = 0;
if (is_variant)
{
sprintf(tmp, "%s_%.*s", acc, suffix.len, suffix.start);
+ resolved = 1;
}
else
{
- sprintf(tmp, "%s__%.*s", acc, suffix.len, suffix.start);
+ char inherent_name[256];
+ sprintf(inherent_name, "%s__%.*s", acc, suffix.len,
+ suffix.start);
+
+ if (find_func(ctx, inherent_name))
+ {
+ strcpy(tmp, inherent_name);
+ resolved = 1;
+ }
+ else
+ {
+ GenericImplTemplate *it = ctx->impl_templates;
+ while (it)
+ {
+ if (strcmp(it->struct_name, gname) == 0)
+ {
+ char *tname = NULL;
+ if (it->impl_node &&
+ it->impl_node->type == NODE_IMPL_TRAIT)
+ {
+ tname = it->impl_node->impl_trait
+ .trait_name;
+ }
+ if (tname)
+ {
+ char cand[512];
+ sprintf(cand, "%s__%s_%.*s", acc, tname,
+ suffix.len, suffix.start);
+
+ if (find_func(ctx, cand))
+ {
+ strcpy(tmp, cand);
+ resolved = 1;
+ break;
+ }
+ }
+ }
+ it = it->next;
+ }
+ }
+ if (!resolved)
+ {
+ sprintf(tmp, "%s__%.*s", acc, suffix.len,
+ suffix.start);
+ }
}
handled_as_generic = 1;
break; // Found and handled
@@ -5588,14 +5634,6 @@ ASTNode *parse_arrow_lambda_single(ParserContext *ctx, Lexer *l, char *param_nam
}
t->inner = ret_val->type_info;
}
- else
- {
- if (param_name[0] == 'x')
- {
- fprintf(stderr, "DEBUG: Return type unknown/null! ret=%p kind=%d\n",
- ret_val->type_info, ret_val->type_info ? ret_val->type_info->kind : -1);
- }
- }
}
// Update parameter types from symbol table (in case inference happened)
diff --git a/src/parser/parser_struct.c b/src/parser/parser_struct.c
index 3e5c73d..8eed017 100644
--- a/src/parser/parser_struct.c
+++ b/src/parser/parser_struct.c
@@ -187,6 +187,19 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
Token t2 = lexer_next(l);
char *name2 = token_strdup(t2);
+ char *target_gen_param = NULL;
+ if (lexer_peek(l).type == TOK_LANGLE)
+ {
+ lexer_next(l); // eat <
+ Token gt = lexer_next(l);
+ target_gen_param = token_strdup(gt);
+ if (lexer_next(l).type != TOK_RANGLE)
+ {
+ zpanic_at(lexer_peek(l), "Expected > in impl struct generic");
+ }
+ register_generic(ctx, target_gen_param);
+ }
+
register_impl(ctx, name1, name2);
// RAII: Check for "Drop" trait implementation
@@ -231,6 +244,18 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
lexer_next(l); // eat {
ASTNode *h = 0, *tl = 0;
+
+ char *full_target_name = name2;
+ if (target_gen_param)
+ {
+ full_target_name = xmalloc(strlen(name2) + strlen(target_gen_param) + 3);
+ sprintf(full_target_name, "%s<%s>", name2, target_gen_param);
+ }
+ else
+ {
+ full_target_name = xstrdup(name2);
+ }
+
while (1)
{
skip_comments(l);
@@ -247,7 +272,9 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
sprintf(mangled, "%s__%s_%s", name2, name1, f->func.name);
free(f->func.name);
f->func.name = mangled;
- char *na = patch_self_args(f->func.args, name2);
+
+ // Use full_target_name (Vec<T>) for self patching
+ char *na = patch_self_args(f->func.args, full_target_name);
free(f->func.args);
f->func.args = na;
@@ -286,7 +313,8 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
sprintf(mangled, "%s__%s_%s", name2, name1, f->func.name);
free(f->func.name);
f->func.name = mangled;
- char *na = patch_self_args(f->func.args, name2);
+
+ char *na = patch_self_args(f->func.args, full_target_name);
free(f->func.args);
f->func.args = na;
@@ -322,6 +350,16 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
lexer_next(l);
}
}
+
+ if (target_gen_param)
+ {
+ free(full_target_name);
+ }
+ else
+ {
+ free(full_target_name); // It was strdup/ref. Wait, xstrdup needs free.
+ }
+
ctx->current_impl_struct = NULL; // Restore context
ASTNode *n = ast_create(NODE_IMPL_TRAIT);
n->impl_trait.trait_name = name1;
@@ -331,11 +369,15 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
// If target struct is generic, register this impl as a template
ASTNode *def = find_struct_def(ctx, name2);
- if (def && ((def->type == NODE_STRUCT && def->strct.is_template) ||
- (def->type == NODE_ENUM && def->enm.is_template)))
+ if (target_gen_param || (def && ((def->type == NODE_STRUCT && def->strct.is_template) ||
+ (def->type == NODE_ENUM && def->enm.is_template))))
{
const char *gp = "T";
- if (def->type == NODE_STRUCT && def->strct.generic_param_count > 0)
+ if (target_gen_param)
+ {
+ gp = target_gen_param;
+ }
+ else if (def && def->type == NODE_STRUCT && def->strct.generic_param_count > 0)
{
gp = def->strct.generic_params[0];
}
@@ -347,6 +389,10 @@ ASTNode *parse_impl(ParserContext *ctx, Lexer *l)
{
ctx->known_generics_count--;
}
+ if (target_gen_param)
+ {
+ ctx->known_generics_count--;
+ }
return n;
}
else