From b885629239d04d2860a8853799a3d335d8bec154 Mon Sep 17 00:00:00 2001 From: Zuhaitz Méndez Fernández de Aránguiz Date: Sat, 17 Jan 2026 15:33:18 +0000 Subject: Add support for mixin method dispatch. --- src/parser/parser_utils.c | 114 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 112 insertions(+), 2 deletions(-) (limited to 'src/parser/parser_utils.c') diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index d2214eb..87cf24e 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -2298,7 +2298,63 @@ char *rewrite_expr_methods(ParserContext *ctx, char *raw) } } - dest += sprintf(dest, "%s__%s(%s%s", ptr_check, method, is_ptr ? "" : "&", acc); + // Mixin Lookup Logic + char target_func[128]; + sprintf(target_func, "%s__%s", ptr_check, method); + + char *final_cast = NULL; + char *final_method = xstrdup(method); + char *final_struct = xstrdup(ptr_check); + + // Check if method exists on primary struct + if (!find_func(ctx, target_func)) + { + // Not found, check mixins + ASTNode *def = find_struct_def(ctx, ptr_check); + if (def && def->type == NODE_STRUCT && def->strct.used_structs) + { + for (int k = 0; k < def->strct.used_struct_count; k++) + { + char mixin_func[128]; + sprintf(mixin_func, "%s__%s", def->strct.used_structs[k], method); + if (find_func(ctx, mixin_func)) + { + // Found in mixin! + free(final_struct); + final_struct = xstrdup(def->strct.used_structs[k]); + + // Create cast string: (Mixin*) or (Mixin*)& + char cast_buf[128]; + if (is_ptr) + { + sprintf(cast_buf, "(%s*)", final_struct); + } + else + { + sprintf(cast_buf, "(%s*)&", final_struct); + } + final_cast = xstrdup(cast_buf); + break; + } + } + } + } + + if (final_cast) + { + // Mixin call: Foo__method((Foo*)&obj + dest += + sprintf(dest, "%s__%s(%s%s", final_struct, final_method, final_cast, acc); + free(final_cast); + } + else + { + // Standard call + dest += sprintf(dest, "%s__%s(%s%s", final_struct, final_method, + is_ptr ? "" : "&", acc); + } + free(final_struct); + free(final_method); int has_args = 0; while (*src && paren_depth > 0) @@ -2348,7 +2404,61 @@ char *rewrite_expr_methods(ParserContext *ctx, char *raw) *p = 0; } } - dest += sprintf(dest, "%s__%s(%s%s)", ptr_check, method, is_ptr ? "" : "&", acc); + // Mixin Lookup Logic (No Parens) + char target_func[128]; + sprintf(target_func, "%s__%s", ptr_check, method); + + char *final_cast = NULL; + char *final_method = xstrdup(method); + char *final_struct = xstrdup(ptr_check); + + // Check if method exists on primary struct + if (!find_func(ctx, target_func)) + { + // Not found, check mixins + ASTNode *def = find_struct_def(ctx, ptr_check); + if (def && def->type == NODE_STRUCT && def->strct.used_structs) + { + for (int k = 0; k < def->strct.used_struct_count; k++) + { + char mixin_func[128]; + sprintf(mixin_func, "%s__%s", def->strct.used_structs[k], method); + if (find_func(ctx, mixin_func)) + { + // Found in mixin! + free(final_struct); + final_struct = xstrdup(def->strct.used_structs[k]); + + // Create cast string: (Mixin*) or (Mixin*)& + char cast_buf[128]; + if (is_ptr) + { + sprintf(cast_buf, "(%s*)", final_struct); + } + else + { + sprintf(cast_buf, "(%s*)&", final_struct); + } + final_cast = xstrdup(cast_buf); + break; + } + } + } + } + + if (final_cast) + { + dest += + sprintf(dest, "%s__%s(%s%s)", final_struct, final_method, final_cast, acc); + free(final_cast); + } + else + { + dest += sprintf(dest, "%s__%s(%s%s)", final_struct, final_method, + is_ptr ? "" : "&", acc); + } + free(final_struct); + free(final_method); continue; } } -- cgit v1.2.3