diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ast/ast.c | 125 | ||||
| -rw-r--r-- | src/ast/ast.h | 2 | ||||
| -rw-r--r-- | src/codegen/codegen.c | 91 | ||||
| -rw-r--r-- | src/codegen/codegen.h | 2 | ||||
| -rw-r--r-- | src/codegen/codegen_decl.c | 12 | ||||
| -rw-r--r-- | src/codegen/codegen_utils.c | 96 | ||||
| -rw-r--r-- | src/main.c | 1 | ||||
| -rw-r--r-- | src/parser/parser.h | 8 | ||||
| -rw-r--r-- | src/parser/parser_expr.c | 10 | ||||
| -rw-r--r-- | src/parser/parser_type.c | 10 | ||||
| -rw-r--r-- | src/parser/parser_utils.c | 55 |
11 files changed, 338 insertions, 74 deletions
diff --git a/src/ast/ast.c b/src/ast/ast.c index 4a34c7c..dee2eed 100644 --- a/src/ast/ast.c +++ b/src/ast/ast.c @@ -288,3 +288,128 @@ char *type_to_string(Type *t) return xstrdup("unknown"); } } + +// C-compatible type stringifier. +// Strictly uses 'struct T' for explicit structs to support external types. +// Does NOT mangle pointers to 'Ptr'. +char *type_to_c_string(Type *t) +{ + if (!t) + { + return xstrdup("void"); + } + + switch (t->kind) + { + case TYPE_VOID: + return xstrdup("void"); + case TYPE_STRUCT: + { + // Only prepend 'struct' if explicitly requested (e.g. "struct Foo") + // otherwise assume it's a typedef/alias (e.g. "Foo"). + if (t->is_explicit_struct) + { + char *res = xmalloc(strlen(t->name) + 8); + sprintf(res, "struct %s", t->name); + return res; + } + else + { + return xstrdup(t->name); + } + } + case TYPE_BOOL: + return xstrdup("bool"); + case TYPE_STRING: + return xstrdup("string"); + case TYPE_CHAR: + return xstrdup("char"); + case TYPE_I8: + return xstrdup("int8_t"); + case TYPE_U8: + return xstrdup("uint8_t"); + case TYPE_I16: + return xstrdup("int16_t"); + case TYPE_U16: + return xstrdup("uint16_t"); + case TYPE_I32: + return xstrdup("int32_t"); + case TYPE_U32: + return xstrdup("uint32_t"); + case TYPE_I64: + return xstrdup("int64_t"); + case TYPE_U64: + return xstrdup("uint64_t"); + case TYPE_F32: + return xstrdup("float"); + case TYPE_F64: + return xstrdup("double"); + case TYPE_USIZE: + return xstrdup("size_t"); + case TYPE_ISIZE: + return xstrdup("ptrdiff_t"); + case TYPE_BYTE: + return xstrdup("uint8_t"); + case TYPE_I128: + return xstrdup("__int128"); + case TYPE_U128: + return xstrdup("unsigned __int128"); + case TYPE_RUNE: + return xstrdup("int32_t"); + case TYPE_UINT: + return xstrdup("unsigned int"); + case TYPE_INT: + return xstrdup("int"); + case TYPE_FLOAT: + return xstrdup("float"); + + case TYPE_POINTER: + { + char *inner = type_to_c_string(t->inner); + if (t->is_restrict) + { + char *res = xmalloc(strlen(inner) + 16); + sprintf(res, "%s* __restrict", inner); + return res; + } + else + { + char *res = xmalloc(strlen(inner) + 2); + sprintf(res, "%s*", inner); + return res; + } + } + + case TYPE_ARRAY: + { + char *inner = type_to_c_string(t->inner); + + if (t->array_size > 0) + { + char *res = xmalloc(strlen(inner) + 20); + sprintf(res, "%s[%d]", inner, t->array_size); + return res; + } + + char *res = xmalloc(strlen(inner) + 7); + sprintf(res, "Slice_%s", inner); + return res; + } + + case TYPE_FUNCTION: + if (t->inner) + { + free(type_to_c_string(t->inner)); + } + return xstrdup("z_closure_T"); + + case TYPE_GENERIC: + return xstrdup(t->name); + + case TYPE_ENUM: + return xstrdup(t->name); + + default: + return xstrdup("unknown"); + } +} diff --git a/src/ast/ast.h b/src/ast/ast.h index 1b83a91..e9270c8 100644 --- a/src/ast/ast.h +++ b/src/ast/ast.h @@ -54,6 +54,7 @@ typedef struct Type struct Type **args; // For GENERIC args. int arg_count; int is_const; + int is_explicit_struct; // e.g. "struct Foo" vs "Foo" union { int array_size; // For fixed-size arrays [T; N]. @@ -548,5 +549,6 @@ Type *type_new_ptr(Type *inner); int type_eq(Type *a, Type *b); int is_integer_type(Type *t); char *type_to_string(Type *t); +char *type_to_c_string(Type *t); #endif diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index d308662..62f3126 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -596,7 +596,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) fprintf(out, "; "); Type *ft = node->call.callee->type_info; - char *ret = type_to_string(ft->inner); + char *ret = codegen_type_to_string(ft->inner); if (strcmp(ret, "string") == 0) { free(ret); @@ -606,7 +606,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) fprintf(out, "((%s (*)(void*", ret); for (int i = 0; i < ft->arg_count; i++) { - char *as = type_to_string(ft->args[i]); + char *as = codegen_type_to_string(ft->args[i]); fprintf(out, ", %s", as); free(as); } @@ -792,7 +792,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) char *tname = "unknown"; if (node->type_info && node->type_info->inner) { - tname = type_to_string(node->type_info->inner); + tname = codegen_type_to_string(node->type_info->inner); } fprintf(out, "({ "); @@ -1021,7 +1021,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) Type *t = node->reflection.target_type; if (node->reflection.kind == 0) { // @type_name - char *s = type_to_string(t); + char *s = codegen_type_to_string(t); fprintf(out, "\"%s\"", s); free(s); } @@ -1112,7 +1112,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) int free_ret = 0; if (node->type_info) { - char *t = type_to_string(node->type_info); + char *t = codegen_type_to_string(node->type_info); if (t) { ret_type = t; @@ -1378,7 +1378,8 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) { fprintf(out, "inline "); } - fprintf(out, "%s %s(%s)\n", node->func.ret_type, node->func.name, node->func.args); + emit_func_signature(out, node, NULL); + fprintf(out, "\n"); fprintf(out, "{\n"); char *prev_ret = g_current_func_ret_type; g_current_func_ret_type = node->func.ret_type; @@ -1527,10 +1528,10 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) } { char *tname = NULL; - Type *tinfo = node->var_decl.type_info; - if (tinfo && tinfo->name) + // Use type_info with codegen_type_to_string if available + if (node->type_info) { - tname = tinfo->name; + tname = codegen_type_to_string(node->type_info); } else if (node->var_decl.type_str && strcmp(node->var_decl.type_str, "__auto_type") != 0) { @@ -1539,55 +1540,61 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) if (tname) { + // Cleanup attribute ASTNode *def = find_struct_def(ctx, tname); if (def && def->type_info && def->type_info->has_drop) { fprintf(out, "__attribute__((cleanup(%s__Drop_glue))) ", tname); } - } - } - if (node->var_decl.type_str && strcmp(node->var_decl.type_str, "__auto_type") != 0) - { - emit_var_decl_type(ctx, out, node->var_decl.type_str, node->var_decl.name); - add_symbol(ctx, node->var_decl.name, node->var_decl.type_str, node->var_decl.type_info); - if (node->var_decl.init_expr) - { - fprintf(out, " = "); - codegen_expression(ctx, node->var_decl.init_expr, out); - } - fprintf(out, ";\n"); - } - else - { - char *inferred = NULL; - if (node->var_decl.init_expr) - { - inferred = infer_type(ctx, node->var_decl.init_expr); - } - if (inferred && strcmp(inferred, "__auto_type") != 0) - { - emit_var_decl_type(ctx, out, inferred, node->var_decl.name); - add_symbol(ctx, node->var_decl.name, inferred, NULL); + // Emit Variable with Type + emit_var_decl_type(ctx, out, tname, node->var_decl.name); + add_symbol(ctx, node->var_decl.name, tname, node->type_info); + + if (node->var_decl.init_expr) + { + fprintf(out, " = "); + codegen_expression(ctx, node->var_decl.init_expr, out); + } + fprintf(out, ";\n"); + + if (node->type_info) + { + free(tname); // Free if allocated by codegen_type_to_string + } } else { - emit_auto_type(ctx, node->var_decl.init_expr, node->token, out); - fprintf(out, " %s", node->var_decl.name); + // Inference Fallback + char *inferred = NULL; + if (node->var_decl.init_expr) + { + inferred = infer_type(ctx, node->var_decl.init_expr); + } - if (inferred) + if (inferred && strcmp(inferred, "__auto_type") != 0) { + emit_var_decl_type(ctx, out, inferred, node->var_decl.name); add_symbol(ctx, node->var_decl.name, inferred, NULL); + fprintf(out, " = "); + codegen_expression(ctx, node->var_decl.init_expr, out); + fprintf(out, ";\n"); } else { - // Here we are cooked. + emit_auto_type(ctx, node->var_decl.init_expr, node->token, out); + fprintf(out, " %s", node->var_decl.name); + + if (inferred) + { + add_symbol(ctx, node->var_decl.name, inferred, NULL); + } + + fprintf(out, " = "); + codegen_expression(ctx, node->var_decl.init_expr, out); + fprintf(out, ";\n"); } } - - fprintf(out, " = "); - codegen_expression(ctx, node->var_decl.init_expr, out); - fprintf(out, ";\n"); } break; case NODE_CONST: @@ -1981,7 +1988,7 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) int free_ret = 0; if (node->type_info) { - char *t = type_to_string(node->type_info); + char *t = codegen_type_to_string(node->type_info); if (t) { ret_type = t; diff --git a/src/codegen/codegen.h b/src/codegen/codegen.h index 4b66f99..45a00ed 100644 --- a/src/codegen/codegen.h +++ b/src/codegen/codegen.h @@ -22,6 +22,8 @@ void emit_var_decl_type(ParserContext *ctx, FILE *out, const char *type_str, con char *replace_string_type(const char *args); const char *parse_original_method_name(const char *mangled); void emit_auto_type(ParserContext *ctx, ASTNode *init_expr, Token t, FILE *out); +char *codegen_type_to_string(Type *t); +void emit_func_signature(FILE *out, ASTNode *func, const char *name_override); // Declaration emission (codegen_decl.c). void emit_preamble(ParserContext *ctx, FILE *out); diff --git a/src/codegen/codegen_decl.c b/src/codegen/codegen_decl.c index fe2829e..18e6987 100644 --- a/src/codegen/codegen_decl.c +++ b/src/codegen/codegen_decl.c @@ -170,7 +170,7 @@ void emit_enum_protos(ASTNode *node, FILE *out) { if (v->variant.payload) { - char *tstr = type_to_string(v->variant.payload); + char *tstr = codegen_type_to_string(v->variant.payload); fprintf(out, "%s %s_%s(%s v);\n", node->enm.name, node->enm.name, v->variant.name, tstr); free(tstr); @@ -306,7 +306,7 @@ void emit_struct_defs(ParserContext *ctx, ASTNode *node, FILE *out) { if (v->variant.payload) { - char *tstr = type_to_string(v->variant.payload); + char *tstr = codegen_type_to_string(v->variant.payload); fprintf(out, "%s %s; ", tstr, v->variant.name); free(tstr); } @@ -318,7 +318,7 @@ void emit_struct_defs(ParserContext *ctx, ASTNode *node, FILE *out) { if (v->variant.payload) { - char *tstr = type_to_string(v->variant.payload); + char *tstr = codegen_type_to_string(v->variant.payload); fprintf(out, "%s %s_%s(%s v) { return (%s){.tag=%s_%s_Tag, " ".data.%s=v}; }\n", @@ -498,7 +498,8 @@ void emit_protos(ASTNode *node, FILE *out) } else { - fprintf(out, "%s %s(%s);\n", f->func.ret_type, f->func.name, f->func.args); + emit_func_signature(out, f, NULL); + fprintf(out, ";\n"); } } else if (f->type == NODE_IMPL) @@ -574,7 +575,8 @@ void emit_protos(ASTNode *node, FILE *out) } else { - fprintf(out, "%s %s(%s);\n", m->func.ret_type, proto, m->func.args); + emit_func_signature(out, m, proto); + fprintf(out, ";\n"); } free(proto); diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c index acb09fe..392557f 100644 --- a/src/codegen/codegen_utils.c +++ b/src/codegen/codegen_utils.c @@ -137,7 +137,7 @@ char *infer_type(ParserContext *ctx, ASTNode *node) } if (sym->type_info) { - return type_to_string(sym->type_info); + return codegen_type_to_string(sym->type_info); } } } @@ -155,7 +155,7 @@ char *infer_type(ParserContext *ctx, ASTNode *node) } if (sig->ret_type) { - return type_to_string(sig->ret_type); + return codegen_type_to_string(sig->ret_type); } } @@ -198,7 +198,7 @@ char *infer_type(ParserContext *ctx, ASTNode *node) FuncSig *sig = find_func(ctx, func_name); if (sig && sig->ret_type) { - return type_to_string(sig->ret_type); + return codegen_type_to_string(sig->ret_type); } } } @@ -368,7 +368,7 @@ char *infer_type(ParserContext *ctx, ASTNode *node) FuncSig *sig = find_func(ctx, node->unary.operand->call.callee->var_ref.name); if (sig && sig->ret_type) { - return type_to_string(sig->ret_type); + return codegen_type_to_string(sig->ret_type); } } @@ -519,3 +519,91 @@ void emit_auto_type(ParserContext *ctx, ASTNode *init_expr, Token t, FILE *out) } } } +// C-compatible type stringifier for codegen. +// Identical to type_to_string but strictly uses 'struct T' for structs to support +// external/non-typedef'd types. +char *codegen_type_to_string(Type *t) +{ + return type_to_c_string(t); +} + +// Emit function signature using Type info for correct C codegen +void emit_func_signature(FILE *out, ASTNode *func, const char *name_override) +{ + if (!func || func->type != NODE_FUNCTION) + { + return; + } + + // Return type + char *ret_str; + if (func->func.ret_type_info) + { + ret_str = codegen_type_to_string(func->func.ret_type_info); + } + else if (func->func.ret_type) + { + ret_str = xstrdup(func->func.ret_type); + } + else + { + ret_str = xstrdup("void"); + } + + fprintf(out, "%s %s(", ret_str, name_override ? name_override : func->func.name); + free(ret_str); + + // Args + if (func->func.arg_count == 0 && !func->func.is_varargs) + { + fprintf(out, "void"); + } + else + { + for (int i = 0; i < func->func.arg_count; i++) + { + if (i > 0) + { + fprintf(out, ", "); + } + + char *type_str = NULL; + if (func->func.arg_types && func->func.arg_types[i]) + { + type_str = codegen_type_to_string(func->func.arg_types[i]); + } + else + { + type_str = xstrdup("void*"); // Fallback + } + + const char *name = ""; + if (func->func.param_names && func->func.param_names[i]) + { + name = func->func.param_names[i]; + } + + // check if array type + char *bracket = strchr(type_str, '['); + if (bracket) + { + int base_len = bracket - type_str; + fprintf(out, "%.*s %s%s", base_len, type_str, name, bracket); + } + else + { + fprintf(out, "%s %s", type_str, name); + } + free(type_str); + } + if (func->func.is_varargs) + { + if (func->func.arg_count > 0) + { + fprintf(out, ", "); + } + fprintf(out, "..."); + } + } + fprintf(out, ")"); +} @@ -51,7 +51,6 @@ void print_usage() int main(int argc, char **argv) { - // Defaults memset(&g_config, 0, sizeof(g_config)); strcpy(g_config.cc, "gcc"); diff --git a/src/parser/parser.h b/src/parser/parser.h index ca8c447..3f2e763 100644 --- a/src/parser/parser.h +++ b/src/parser/parser.h @@ -116,6 +116,7 @@ typedef struct Instantiation char *name; char *template_name; char *concrete_arg; + char *unmangled_arg; // For code substitution (e.g. "struct T*") ASTNode *struct_node; struct Instantiation *next; } Instantiation; @@ -320,7 +321,8 @@ void add_to_impl_list(ParserContext *ctx, ASTNode *node); void add_to_global_list(ParserContext *ctx, ASTNode *node); void register_builtins(ParserContext *ctx); void add_instantiated_func(ParserContext *ctx, ASTNode *fn); -void instantiate_generic(ParserContext *ctx, const char *name, const char *concrete_type, Token t); +void instantiate_generic(ParserContext *ctx, const char *name, const char *concrete_type, + const char *unmangled_type, Token t); void instantiate_generic_multi(ParserContext *ctx, const char *name, char **args, int arg_count, Token t); char *sanitize_mangled_name(const char *name); @@ -390,8 +392,8 @@ void init_builtins(); // Expression rewriting char *rewrite_expr_methods(ParserContext *ctx, char *raw); char *process_fstring(ParserContext *ctx, const char *content, char ***used_syms, int *count); -char *instantiate_function_template(ParserContext *ctx, const char *name, - const char *concrete_type); +char *instantiate_function_template(ParserContext *ctx, const char *name, const char *concrete_type, + const char *unmangled_type); FuncSig *find_func(ParserContext *ctx, const char *name); Type *parse_type_formal(ParserContext *ctx, Lexer *l); diff --git a/src/parser/parser_expr.c b/src/parser/parser_expr.c index d0f3337..975d237 100644 --- a/src/parser/parser_expr.c +++ b/src/parser/parser_expr.c @@ -1464,7 +1464,10 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) if (lexer_peek(&lookahead).type == TOK_RANGLE) { lexer_next(l); - char *concrete_type = parse_type(ctx, l); + Type *formal_type = parse_type_formal(ctx, l); + char *concrete_type = type_to_string(formal_type); // mangled for naming + char *unmangled_type = + type_to_c_string(formal_type); // C-compatible for substitution lexer_next(l); int is_struct = 0; @@ -1485,7 +1488,7 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) if (is_struct) { - instantiate_generic(ctx, acc, concrete_type, t); + instantiate_generic(ctx, acc, concrete_type, unmangled_type, t); char *clean_type = sanitize_mangled_name(concrete_type); @@ -1498,7 +1501,8 @@ ASTNode *parse_primary(ParserContext *ctx, Lexer *l) } else { - char *m = instantiate_function_template(ctx, acc, concrete_type); + char *m = + instantiate_function_template(ctx, acc, concrete_type, unmangled_type); if (m) { free(acc); diff --git a/src/parser/parser_type.c b/src/parser/parser_type.c index 7dded00..b966a4d 100644 --- a/src/parser/parser_type.c +++ b/src/parser/parser_type.c @@ -12,10 +12,15 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) if (t.type == TOK_IDENT) { + int explicit_struct = 0; // Handle "struct Name" or "enum Name" if ((t.len == 6 && strncmp(t.start, "struct", 6) == 0) || (t.len == 4 && strncmp(t.start, "enum", 4) == 0)) { + if (strncmp(t.start, "struct", 6) == 0) + { + explicit_struct = 1; + } lexer_next(l); // consume keyword t = lexer_peek(l); if (t.type != TOK_IDENT) @@ -381,6 +386,7 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) Type *ty = type_new(TYPE_STRUCT); ty->name = name; + ty->is_explicit_struct = explicit_struct; // Handle Generics <T> or <K, V> if (lexer_peek(l).type == TOK_LANGLE) @@ -463,7 +469,9 @@ Type *parse_type_base(ParserContext *ctx, Lexer *l) zpanic_at(t, "Expected > after generic"); } - instantiate_generic(ctx, name, first_arg_str, t); + char *unmangled_arg = type_to_c_string(first_arg); + instantiate_generic(ctx, name, first_arg_str, unmangled_arg, t); + free(unmangled_arg); char *clean_arg = sanitize_mangled_name(first_arg_str); char mangled[256]; diff --git a/src/parser/parser_utils.c b/src/parser/parser_utils.c index 51d89d7..7c45178 100644 --- a/src/parser/parser_utils.c +++ b/src/parser/parser_utils.c @@ -8,7 +8,8 @@ #include <string.h> void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, - const char *mangled_struct_name, const char *arg); + const char *mangled_struct_name, const char *arg, + const char *unmangled_arg); Token expect(Lexer *l, TokenType type, const char *msg) { @@ -388,7 +389,7 @@ void register_impl_template(ParserContext *ctx, const char *sname, const char *p { if (inst->template_name && strcmp(inst->template_name, sname) == 0) { - instantiate_methods(ctx, t, inst->name, inst->concrete_arg); + instantiate_methods(ctx, t, inst->name, inst->concrete_arg, inst->unmangled_arg); } inst = inst->next; } @@ -1578,7 +1579,8 @@ FuncSig *find_func(ParserContext *ctx, const char *name) return NULL; } -char *instantiate_function_template(ParserContext *ctx, const char *name, const char *concrete_type) +char *instantiate_function_template(ParserContext *ctx, const char *name, const char *concrete_type, + const char *unmangled_type) { GenericFuncTemplate *tpl = find_func_template(ctx, name); if (!tpl) @@ -1596,8 +1598,8 @@ char *instantiate_function_template(ParserContext *ctx, const char *name, const return mangled; } - ASTNode *new_fn = - copy_ast_replacing(tpl->func_node, tpl->generic_param, concrete_type, NULL, NULL); + const char *subst_arg = unmangled_type ? unmangled_type : concrete_type; + ASTNode *new_fn = copy_ast_replacing(tpl->func_node, tpl->generic_param, subst_arg, NULL, NULL); if (!new_fn || new_fn->type != NODE_FUNCTION) { return NULL; @@ -1820,7 +1822,20 @@ ASTNode *copy_fields_replacing(ParserContext *ctx, ASTNode *fields, const char * if (found) { - instantiate_generic(ctx, template_name, concrete_arg, fields->token); + char *unmangled = xstrdup(concrete_arg); + size_t alen = strlen(concrete_arg); + if (alen > 3 && strcmp(concrete_arg + alen - 3, "Ptr") == 0) + { + char *base = xstrdup(concrete_arg); + base[alen - 3] = '\0'; + // heuristic: Ptr likely maps to struct T* + free(unmangled); + unmangled = xmalloc(strlen(base) + 16); + sprintf(unmangled, "struct %s*", base); + free(base); + } + instantiate_generic(ctx, template_name, concrete_arg, unmangled, fields->token); + free(unmangled); } } free(type_copy); @@ -1832,7 +1847,8 @@ ASTNode *copy_fields_replacing(ParserContext *ctx, ASTNode *fields, const char * } void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, - const char *mangled_struct_name, const char *arg) + const char *mangled_struct_name, const char *arg, + const char *unmangled_arg) { if (check_impl(ctx, "Methods", mangled_struct_name)) { @@ -1841,8 +1857,9 @@ void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, ASTNode *backup_next = it->impl_node->next; it->impl_node->next = NULL; // Break link to isolate node - ASTNode *new_impl = copy_ast_replacing(it->impl_node, it->generic_param, arg, it->struct_name, - mangled_struct_name); + const char *subst_arg = unmangled_arg ? unmangled_arg : arg; + ASTNode *new_impl = copy_ast_replacing(it->impl_node, it->generic_param, subst_arg, + it->struct_name, mangled_struct_name); it->impl_node->next = backup_next; // Restore new_impl->impl.struct_name = xstrdup(mangled_struct_name); @@ -1878,7 +1895,8 @@ void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, if (strcmp(gt->name, template_name) == 0) { // Found matching template, instantiate it - instantiate_generic(ctx, template_name, arg, meth->token); + const char *subst_arg = unmangled_arg ? unmangled_arg : arg; + instantiate_generic(ctx, template_name, arg, subst_arg, meth->token); break; } gt = gt->next; @@ -1892,7 +1910,8 @@ void instantiate_methods(ParserContext *ctx, GenericImplTemplate *it, add_instantiated_func(ctx, new_impl); } -void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, Token token) +void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, + const char *unmangled_arg, Token token) { // Ignore generic placeholders if (strlen(arg) == 1 && isupper(arg[0])) @@ -1937,8 +1956,11 @@ void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, T ni->name = xstrdup(m); ni->template_name = xstrdup(tpl); ni->concrete_arg = xstrdup(arg); - ni->struct_node = NULL; // Placeholder to break cycles + ni->unmangled_arg = unmangled_arg ? xstrdup(unmangled_arg) + : xstrdup(arg); // Fallback to arg if unmangled is generic + ni->struct_node = NULL; // Placeholder to break cycles ni->next = ctx->instantiations; + ni->struct_node = NULL; // Duplicate assignment, ignore. ctx->instantiations = ni; ASTNode *struct_node_copy = NULL; @@ -1952,7 +1974,8 @@ void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, T const char *gp = (t->struct_node->strct.generic_param_count > 0) ? t->struct_node->strct.generic_params[0] : "T"; - i->strct.fields = copy_fields_replacing(ctx, t->struct_node->strct.fields, gp, arg); + const char *subst_arg = unmangled_arg ? unmangled_arg : arg; + i->strct.fields = copy_fields_replacing(ctx, t->struct_node->strct.fields, gp, subst_arg); struct_node_copy = i; register_struct_def(ctx, m, i); } @@ -1968,8 +1991,9 @@ void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, T ASTNode *nv = ast_create(NODE_ENUM_VARIANT); nv->variant.name = xstrdup(v->variant.name); nv->variant.tag_id = v->variant.tag_id; + const char *subst_arg = unmangled_arg ? unmangled_arg : arg; nv->variant.payload = replace_type_formal( - v->variant.payload, t->struct_node->enm.generic_param, arg, NULL, NULL); + v->variant.payload, t->struct_node->enm.generic_param, subst_arg, NULL, NULL); char mangled_var[512]; sprintf(mangled_var, "%s_%s", m, nv->variant.name); register_enum_variant(ctx, m, mangled_var, nv->variant.tag_id); @@ -2001,7 +2025,8 @@ void instantiate_generic(ParserContext *ctx, const char *tpl, const char *arg, T { if (strcmp(it->struct_name, tpl) == 0) { - instantiate_methods(ctx, it, m, arg); + const char *subst_arg = unmangled_arg ? unmangled_arg : arg; + instantiate_methods(ctx, it, m, arg, subst_arg); } it = it->next; } |
