diff options
Diffstat (limited to 'src/parser')
| -rw-r--r-- | src/parser/parser_stmt.c | 12 | ||||
| -rw-r--r-- | src/parser/parser_utils.c | 114 |
2 files changed, 124 insertions, 2 deletions
diff --git a/src/parser/parser_stmt.c b/src/parser/parser_stmt.c index c9b144d..ca8cd8f 100644 --- a/src/parser/parser_stmt.c +++ b/src/parser/parser_stmt.c @@ -3268,6 +3268,10 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union) lexer_next(l); // eat { ASTNode *h = 0, *tl = 0; + // Temp storage for used structs + char **temp_used_structs = NULL; + int temp_used_count = 0; + while (1) { skip_comments(l); @@ -3308,6 +3312,12 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union) if (def && def->type == NODE_STRUCT) { + if (!temp_used_structs) + { + temp_used_structs = xmalloc(sizeof(char *) * 8); + } + temp_used_structs[temp_used_count++] = xstrdup(use_name); + ASTNode *f = def->strct.fields; while (f) { @@ -3410,6 +3420,8 @@ ASTNode *parse_struct(ParserContext *ctx, Lexer *l, int is_union) node->strct.generic_params = gps; node->strct.generic_param_count = gp_count; node->strct.is_union = is_union; + node->strct.used_structs = temp_used_structs; + node->strct.used_struct_count = temp_used_count; if (gp_count > 0) { 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; } } |
