summaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-17 00:10:30 +0000
committerZuhaitz Méndez Fernández de Aránguiz <zuhaitz@debian>2026-01-17 00:10:30 +0000
commitea160abc678e9578b5e140121a6d7c59a3b9dd06 (patch)
tree0ae4d0ed1449f74d6cc361a5f8787892c0789168 /src/codegen
parenta5d5a97818fb4fbd26c4fb25a5c410b1a60a1b18 (diff)
Improved struct pointer codegen, template instantiation and docs...
Diffstat (limited to 'src/codegen')
-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
4 files changed, 150 insertions, 51 deletions
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, ")");
+}