summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md13
-rw-r--r--src/ast/ast.c125
-rw-r--r--src/ast/ast.h2
-rw-r--r--src/codegen/codegen.c91
-rw-r--r--src/codegen/codegen.h2
-rw-r--r--src/codegen/codegen_decl.c12
-rw-r--r--src/codegen/codegen_utils.c96
-rw-r--r--src/main.c1
-rw-r--r--src/parser/parser.h8
-rw-r--r--src/parser/parser_expr.c10
-rw-r--r--src/parser/parser_type.c10
-rw-r--r--src/parser/parser_utils.c55
-rw-r--r--std/json.zc1
13 files changed, 352 insertions, 74 deletions
diff --git a/README.md b/README.md
index 4181108..c36cb56 100644
--- a/README.md
+++ b/README.md
@@ -154,6 +154,13 @@ union Data {
i: int;
f: float;
}
+
+#### Type Aliases
+Create a new name for an existing type.
+```zc
+alias ID = int;
+alias PointMap = Map<string, Point>;
+```
```
### 4. Functions & Lambdas
@@ -378,6 +385,12 @@ struct Box<T> {
fn identity<T>(val: T) -> T {
return val;
}
+
+// Multi-parameter Generics
+struct Pair<K, V> {
+ key: K;
+ value: V;
+}
```
### 11. Concurrency (Async/Await)
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, ")");
+}
diff --git a/src/main.c b/src/main.c
index 2c33a6b..4c91330 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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;
}
diff --git a/std/json.zc b/std/json.zc
index f1b008d..64d64ab 100644
--- a/std/json.zc
+++ b/std/json.zc
@@ -26,6 +26,7 @@ struct JsonValue {
}
raw {
+ typedef struct JsonValue* JsonValuePtr;
Vec_JsonValuePtr Vec_JsonValuePtr__new();
void Vec_JsonValuePtr__push(Vec_JsonValuePtr* self, JsonValue* item);
Map_JsonValuePtr Map_JsonValuePtr__new();