summaryrefslogtreecommitdiff
path: root/src/codegen/codegen_stmt.c
diff options
context:
space:
mode:
authoriryuken <eshwarsajja20@gmail.com>2026-01-25 23:29:00 +0530
committerGitHub <noreply@github.com>2026-01-25 23:29:00 +0530
commit1c4a6e1cf58503499b1c8245c1d15bd70efe0048 (patch)
tree71b952ad455bf17d5bdea01472f0e2297f25eabe /src/codegen/codegen_stmt.c
parent863118c95caac0d69a35f6ae4d2e83844734a8a1 (diff)
parentebc8b94baa6bc694cb4829e2eb2934a1f17fa6a1 (diff)
Merge pull request
fix merge conflicts and #105
Diffstat (limited to 'src/codegen/codegen_stmt.c')
-rw-r--r--src/codegen/codegen_stmt.c249
1 files changed, 146 insertions, 103 deletions
diff --git a/src/codegen/codegen_stmt.c b/src/codegen/codegen_stmt.c
index 54c6a14..ff8ea46 100644
--- a/src/codegen/codegen_stmt.c
+++ b/src/codegen/codegen_stmt.c
@@ -177,9 +177,19 @@ void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, int us
ASTNode *ref_check = node->match_stmt.cases;
while (ref_check)
{
- if (ref_check->match_case.is_ref)
+ if (ref_check->match_case.binding_refs)
+ {
+ for (int i = 0; i < ref_check->match_case.binding_count; i++)
+ {
+ if (ref_check->match_case.binding_refs[i])
+ {
+ has_ref_binding = 1;
+ break;
+ }
+ }
+ }
+ if (has_ref_binding)
{
- has_ref_binding = 1;
break;
}
ref_check = ref_check->next;
@@ -325,157 +335,131 @@ void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, int us
emit_pattern_condition(ctx, c->match_case.pattern, id, has_ref_binding, out);
}
fprintf(out, ") { ");
- if (c->match_case.binding_name)
+ if (c->match_case.binding_count > 0)
{
- if (is_option)
+ for (int i = 0; i < c->match_case.binding_count; i++)
{
- if (strstr(g_config.cc, "tcc"))
+ char *bname = c->match_case.binding_names[i];
+ int is_r = c->match_case.binding_refs ? c->match_case.binding_refs[i] : 0;
+
+ if (is_option)
{
- if (c->match_case.is_ref)
+ if (strstr(g_config.cc, "tcc"))
{
- fprintf(out, "__typeof__(&_m_%d.val) %s = &_m_%d.val; ", id,
- c->match_case.binding_name, id);
+ if (is_r)
+ {
+ fprintf(out, "__typeof__(&_m_%d.val) %s = &_m_%d.val; ", id, bname, id);
+ }
+ else
+ {
+ fprintf(out, "__typeof__(_m_%d.val) %s = _m_%d.val; ", id, bname, id);
+ }
}
else
{
- fprintf(out, "__typeof__(_m_%d.val) %s = _m_%d.val; ", id,
- c->match_case.binding_name, id);
+ if (is_r)
+ {
+ fprintf(out, "ZC_AUTO %s = &_m_%d->val; ", bname, id);
+ }
+ else if (has_ref_binding)
+ {
+ fprintf(out, "ZC_AUTO %s = _m_%d->val; ", bname, id);
+ }
+ else
+ {
+ fprintf(out, "ZC_AUTO %s = _m_%d.val; ", bname, id);
+ }
}
}
- else
+ else if (is_result)
{
- if (c->match_case.is_ref)
- {
- // _m is pointer when has_ref_binding, use ->
- fprintf(out, "ZC_AUTO %s = &_m_%d->val; ", c->match_case.binding_name, id);
- }
- else if (has_ref_binding)
+ char *field = "val";
+ if (strcmp(c->match_case.pattern, "Err") == 0)
{
- // _m is pointer, use -> but don't take address
- fprintf(out, "ZC_AUTO %s = _m_%d->val; ", c->match_case.binding_name, id);
+ field = "err";
}
- else
- {
- // _m is value, use .
- fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name, id);
- }
- }
- }
- else if (is_result) // FIX: Changed 'if' to 'else if' to match original logic structure
- // if needed, but original code had implicit fallthrough checks? No,
- // checks match pattern.
- {
- if (strcmp(c->match_case.pattern, "Ok") == 0)
- {
+
if (strstr(g_config.cc, "tcc"))
{
- if (c->match_case.is_ref)
+ if (is_r)
{
- fprintf(out, "__typeof__(&_m_%d->val) %s = &_m_%d->val; ", id,
- c->match_case.binding_name, id);
+ fprintf(out, "__typeof__(&_m_%d->%s) %s = &_m_%d->%s; ", id, field,
+ bname, id, field);
}
else
{
- fprintf(out, "__typeof__(_m_%d->val) %s = _m_%d->val; ", id,
- c->match_case.binding_name, id);
+ fprintf(out, "__typeof__(_m_%d->%s) %s = _m_%d->%s; ", id, field, bname,
+ id, field);
}
}
else
{
- if (c->match_case.is_ref)
+ if (is_r)
{
- // _m is pointer when has_ref_binding, use ->
- fprintf(out, "ZC_AUTO %s = &_m_%d->val; ", c->match_case.binding_name,
- id);
+ fprintf(out, "ZC_AUTO %s = &_m_%d->%s; ", bname, id, field);
}
else if (has_ref_binding)
{
- // _m is pointer, use -> but don't take address
- fprintf(out, "ZC_AUTO %s = _m_%d->val; ", c->match_case.binding_name,
- id);
+ fprintf(out, "ZC_AUTO %s = _m_%d->%s; ", bname, id, field);
}
else
{
- // _m is value, use .
- fprintf(out, "ZC_AUTO %s = _m_%d.val; ", c->match_case.binding_name,
- id);
+ fprintf(out, "ZC_AUTO %s = _m_%d.%s; ", bname, id, field);
}
}
}
else
{
- if (strstr(g_config.cc, "tcc"))
+ char *v = strrchr(c->match_case.pattern, '_');
+ if (v)
{
- if (c->match_case.is_ref)
+ v++;
+ }
+ else
+ {
+ v = c->match_case.pattern;
+ }
+
+ if (c->match_case.binding_count > 1)
+ {
+ // Tuple destructuring: data.Variant.vI
+ if (is_r)
+ {
+ fprintf(out, "ZC_AUTO %s = &_m_%d->data.%s.v%d; ", bname, id, v, i);
+ }
+ else if (has_ref_binding)
{
- fprintf(out, "__typeof__(&_m_%d->err) %s = &_m_%d->err; ", id,
- c->match_case.binding_name, id);
+ fprintf(out, "ZC_AUTO %s = _m_%d->data.%s.v%d; ", bname, id, v, i);
}
else
{
- fprintf(out, "__typeof__(_m_%d->err) %s = _m_%d->err; ", id,
- c->match_case.binding_name, id);
+ fprintf(out, "ZC_AUTO %s = _m_%d.data.%s.v%d; ", bname, id, v, i);
}
}
else
{
- if (c->match_case.is_ref)
+ // Single destructuring: data.Variant
+ if (is_r)
{
- // _m is pointer when has_ref_binding, use ->
- fprintf(out, "ZC_AUTO %s = &_m_%d->err; ", c->match_case.binding_name,
- id);
+ fprintf(out, "ZC_AUTO %s = &_m_%d->data.%s; ", bname, id, v);
}
else if (has_ref_binding)
{
- // _m is pointer, use -> but don't take address
- fprintf(out, "ZC_AUTO %s = _m_%d->err; ", c->match_case.binding_name,
- id);
+ fprintf(out, "ZC_AUTO %s = _m_%d->data.%s; ", bname, id, v);
}
else
{
- // _m is value, use .
- fprintf(out, "ZC_AUTO %s = _m_%d.err; ", c->match_case.binding_name,
- id);
+ fprintf(out, "ZC_AUTO %s = _m_%d.data.%s; ", bname, id, v);
}
}
}
}
- else
- {
- char *f = strrchr(c->match_case.pattern, '_');
- if (f)
- {
- f++;
- }
- else
- {
- f = c->match_case.pattern;
- }
- // Generic struct destructuring (for example, MyStruct_Variant)
- // Assuming data union or accessible field.
- if (c->match_case.is_ref)
- {
- // _m is pointer when has_ref_binding, use ->
- fprintf(out, "ZC_AUTO %s = &_m_%d->data.%s; ", c->match_case.binding_name, id,
- f);
- }
- else if (has_ref_binding)
- {
- // _m is pointer, use -> but don't take address
- fprintf(out, "ZC_AUTO %s = _m_%d->data.%s; ", c->match_case.binding_name, id,
- f);
- }
- else
- {
- // _m is value, use .
- fprintf(out, "ZC_AUTO %s = _m_%d.data.%s; ", c->match_case.binding_name, id, f);
- }
- }
}
// Check if body is a string literal (should auto-print).
ASTNode *body = c->match_case.body;
- int is_string_literal = (body->type == NODE_EXPR_LITERAL && body->literal.type_kind == 2);
+ int is_string_literal =
+ (body->type == NODE_EXPR_LITERAL && body->literal.type_kind == LITERAL_STRING);
if (is_expr)
{
@@ -514,9 +498,10 @@ void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, int us
{
if (is_string_literal)
{
- fprintf(out, "({ printf(\"%%s\", ");
- codegen_expression(ctx, body, out);
- fprintf(out, "); printf(\"\\n\"); 0; })");
+ char *inner = body->literal.string_val;
+ char *code = process_printf_sugar(ctx, inner, 1, "stdout", NULL, NULL, 0);
+ fprintf(out, "%s;", code);
+ free(code);
}
else
{
@@ -902,9 +887,27 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
}
ASTNode *def = find_struct_def(ctx, clean_type);
- if (def && def->type_info && def->type_info->traits.has_drop)
+ int has_drop = (def && def->type_info && def->type_info->traits.has_drop);
+
+ if (has_drop)
{
- fprintf(out, "__attribute__((cleanup(%s__Drop_glue))) ", clean_type);
+ // Drop Flag: int __z_drop_flag_name = 1;
+ fprintf(out, "int __z_drop_flag_%s = 1; ", node->var_decl.name);
+
+ // Synthesize Defer: if (__z_drop_flag_name) Name__Drop_drop(&name);
+ ASTNode *defer_node = xmalloc(sizeof(ASTNode));
+ defer_node->type = NODE_RAW_STMT;
+ char *stmt_str =
+ xmalloc(256 + strlen(node->var_decl.name) * 2 + strlen(clean_type));
+ sprintf(stmt_str, "if (__z_drop_flag_%s) %s__Drop_glue(&%s);",
+ node->var_decl.name, clean_type, node->var_decl.name);
+ defer_node->raw_stmt.content = stmt_str;
+ defer_node->line = node->line;
+
+ if (defer_count < MAX_DEFER)
+ {
+ defer_stack[defer_count++] = defer_node;
+ }
}
// Emit Variable with Type
@@ -917,6 +920,11 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
codegen_expression(ctx, node->var_decl.init_expr, out);
}
fprintf(out, ";\n");
+ if (node->var_decl.init_expr &&
+ emit_move_invalidation(ctx, node->var_decl.init_expr, out))
+ {
+ fprintf(out, ";\n");
+ }
if (node->type_info)
{
@@ -941,9 +949,29 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
}
ASTNode *def = find_struct_def(ctx, clean_type);
- if (def && def->type_info && def->type_info->traits.has_drop)
+ int has_drop = (def && def->type_info && def->type_info->traits.has_drop);
+
+ if (has_drop)
{
- fprintf(out, "__attribute__((cleanup(%s__Drop_glue))) ", clean_type);
+ // Drop Flag: int __z_drop_flag_name = 1;
+ fprintf(out, "int __z_drop_flag_%s = 1; ", node->var_decl.name);
+
+ // Synthesize Defer: if (__z_drop_flag_name) Name__Drop_drop(&name);
+ ASTNode *defer_node = xmalloc(sizeof(ASTNode));
+ defer_node->type = NODE_RAW_STMT;
+ // Build string
+ char *stmt_str =
+ xmalloc(256 + strlen(node->var_decl.name) * 2 + strlen(clean_type));
+ sprintf(stmt_str, "if (__z_drop_flag_%s) %s__Drop_glue(&%s);",
+ node->var_decl.name, clean_type, node->var_decl.name);
+ defer_node->raw_stmt.content = stmt_str;
+ defer_node->line = node->line;
+
+ // Push to defer stack
+ if (defer_count < MAX_DEFER)
+ {
+ defer_stack[defer_count++] = defer_node;
+ }
}
emit_var_decl_type(ctx, out, inferred, node->var_decl.name);
@@ -951,6 +979,12 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, " = ");
codegen_expression(ctx, node->var_decl.init_expr, out);
fprintf(out, ";\n");
+
+ if (node->var_decl.init_expr &&
+ emit_move_invalidation(ctx, node->var_decl.init_expr, out))
+ {
+ fprintf(out, ";\n");
+ }
}
else
{
@@ -965,6 +999,11 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, " = ");
codegen_expression(ctx, node->var_decl.init_expr, out);
fprintf(out, ";\n");
+ if (node->var_decl.init_expr &&
+ emit_move_invalidation(ctx, node->var_decl.init_expr, out))
+ {
+ fprintf(out, ";\n");
+ }
}
}
}
@@ -1475,6 +1514,7 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
}
case NODE_REPL_PRINT:
{
+ // Safe block for printing
fprintf(out, "{ ");
emit_auto_type(ctx, node->repl_print.expr, node->token, out);
fprintf(out, " _zval = (");
@@ -1576,7 +1616,7 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
}
case NODE_EXPR_LITERAL:
// String literal statement should auto-print
- if (node->literal.type_kind == 2 || node->literal.type_kind == TOK_STRING)
+ if (node->literal.type_kind == LITERAL_STRING)
{
fprintf(out, " printf(\"%%s\\n\", ");
codegen_expression(ctx, node, out);
@@ -1653,6 +1693,9 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out)
fprintf(out, ");\n");
break;
}
+ case NODE_RAW_STMT:
+ fprintf(out, " %s\n", node->raw_stmt.content);
+ break;
default:
codegen_expression(ctx, node, out);
fprintf(out, ";\n");