diff options
| author | iryuken <eshwarsajja20@gmail.com> | 2026-01-25 23:29:00 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-01-25 23:29:00 +0530 |
| commit | 1c4a6e1cf58503499b1c8245c1d15bd70efe0048 (patch) | |
| tree | 71b952ad455bf17d5bdea01472f0e2297f25eabe /src/codegen/codegen_stmt.c | |
| parent | 863118c95caac0d69a35f6ae4d2e83844734a8a1 (diff) | |
| parent | ebc8b94baa6bc694cb4829e2eb2934a1f17fa6a1 (diff) | |
Merge pull request
fix merge conflicts and #105
Diffstat (limited to 'src/codegen/codegen_stmt.c')
| -rw-r--r-- | src/codegen/codegen_stmt.c | 249 |
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"); |
