diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/codegen.c | 90 | ||||
| -rw-r--r-- | src/codegen/codegen_utils.c | 36 |
2 files changed, 98 insertions, 28 deletions
diff --git a/src/codegen/codegen.c b/src/codegen/codegen.c index 1592806..17b0816 100644 --- a/src/codegen/codegen.c +++ b/src/codegen/codegen.c @@ -11,14 +11,15 @@ #include "zprep_plugin.h" // static function for internal use. -static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out) +static char *g_current_func_ret_type = NULL; +static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out, int use_result) { int id = tmp_counter++; int is_self = (node->match_stmt.expr->type == NODE_EXPR_VAR && strcmp(node->match_stmt.expr->var_ref.name, "self") == 0); char *ret_type = infer_type(ctx, node); - int is_expr = (ret_type && strcmp(ret_type, "void") != 0); + int is_expr = (use_result && ret_type && strcmp(ret_type, "void") != 0); fprintf(out, "({ "); emit_auto_type(ctx, node->match_stmt.expr, node->token, out); @@ -151,6 +152,11 @@ static void codegen_match_internal(ParserContext *ctx, ASTNode *node, FILE *out) // Numeric pattern fprintf(out, "_m_%d == %s", id, c->match_case.pattern); } + else if (c->match_case.pattern[0] == '\'') + { + // Char literal pattern + fprintf(out, "_m_%d == %s", id, c->match_case.pattern); + } else { fprintf(out, "1"); @@ -290,7 +296,7 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) switch (node->type) { case NODE_MATCH: - codegen_match_internal(ctx, node, out); + codegen_match_internal(ctx, node, out, 1); break; case NODE_EXPR_BINARY: if (strncmp(node->binary.op, "??", 2) == 0 && strlen(node->binary.op) == 2) @@ -848,13 +854,13 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) case NODE_TRY: { char *type_name = "Result"; - if (node->try_stmt.expr->type_info && node->try_stmt.expr->type_info->name) + if (g_current_func_ret_type) { - type_name = node->try_stmt.expr->type_info->name; + type_name = g_current_func_ret_type; } - else if (node->try_stmt.expr->resolved_type) + else if (node->try_stmt.expr->type_info && node->try_stmt.expr->type_info->name) { - type_name = node->try_stmt.expr->resolved_type; + type_name = node->try_stmt.expr->type_info->name; } if (strcmp(type_name, "__auto_type") == 0 || strcmp(type_name, "unknown") == 0) @@ -862,14 +868,57 @@ void codegen_expression(ParserContext *ctx, ASTNode *node, FILE *out) type_name = "Result"; } + char *search_name = type_name; + if (strncmp(search_name, "struct ", 7) == 0) + { + search_name += 7; + } + + int is_enum = 0; + StructRef *er = ctx->parsed_enums_list; + while (er) + { + if (er->node && er->node->type == NODE_ENUM && + strcmp(er->node->enm.name, search_name) == 0) + { + is_enum = 1; + break; + } + er = er->next; + } + if (!is_enum) + { + ASTNode *ins = ctx->instantiated_structs; + while (ins) + { + if (ins->type == NODE_ENUM && strcmp(ins->enm.name, search_name) == 0) + { + is_enum = 1; + break; + } + ins = ins->next; + } + } + fprintf(out, "({ "); emit_auto_type(ctx, node->try_stmt.expr, node->token, out); fprintf(out, " _try = "); codegen_expression(ctx, node->try_stmt.expr, out); - fprintf(out, - "; if (_try.tag == %s_Err_Tag) return (%s_Err(_try.data.Err)); " - "_try.data.Ok; })", - type_name, type_name); + + if (is_enum) + { + fprintf(out, + "; if (_try.tag == %s_Err_Tag) return (%s_Err(_try.data.Err)); " + "_try.data.Ok; })", + search_name, search_name); + } + else + { + fprintf(out, + "; if (!_try.is_ok) return %s_Err(_try.err); " + "_try.val; })", + search_name); + } break; } case NODE_RAW_STMT: @@ -1149,6 +1198,10 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) } switch (node->type) { + case NODE_MATCH: + codegen_match_internal(ctx, node, out, 0); // 0 = statement context + fprintf(out, ";\n"); + break; case NODE_FUNCTION: if (!node->func.body) { @@ -1320,11 +1373,14 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) } fprintf(out, "%s %s(%s)\n", node->func.ret_type, node->func.name, node->func.args); fprintf(out, "{\n"); + char *prev_ret = g_current_func_ret_type; + g_current_func_ret_type = node->func.ret_type; codegen_walker(ctx, node->func.body, out); for (int i = defer_count - 1; i >= 0; i--) { codegen_node_single(ctx, defer_stack[i], out); } + g_current_func_ret_type = prev_ret; fprintf(out, "}\n"); break; @@ -1500,8 +1556,6 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) if (node->var_decl.init_expr) { inferred = infer_type(ctx, node->var_decl.init_expr); - fprintf(stderr, "DEBUG: var '%s' inferred = '%s'\n", node->var_decl.name, - inferred ? inferred : "(null)"); } if (inferred && strcmp(inferred, "__auto_type") != 0) @@ -1682,14 +1736,18 @@ void codegen_node_single(ParserContext *ctx, ASTNode *node, FILE *out) fprintf(out, "for ("); if (strstr(g_config.cc, "tcc")) { - fprintf(out, "__typeof__((%s)) %s = ", node->for_range.start, node->for_range.var_name); + fprintf(out, "__typeof__(("); + codegen_expression(ctx, node->for_range.start, out); + fprintf(out, ")) %s = ", node->for_range.var_name); } else { fprintf(out, "__auto_type %s = ", node->for_range.var_name); } - fprintf(out, "%s; %s < %s; %s", node->for_range.start, node->for_range.var_name, - node->for_range.end, node->for_range.var_name); + codegen_expression(ctx, node->for_range.start, out); + fprintf(out, "; %s < ", node->for_range.var_name); + codegen_expression(ctx, node->for_range.end, out); + fprintf(out, "; %s", node->for_range.var_name); if (node->for_range.step) { fprintf(out, " += %s) ", node->for_range.step); diff --git a/src/codegen/codegen_utils.c b/src/codegen/codegen_utils.c index 5dcbf19..8969276 100644 --- a/src/codegen/codegen_utils.c +++ b/src/codegen/codegen_utils.c @@ -194,26 +194,38 @@ char *infer_type(ParserContext *ctx, ASTNode *node) } } - // Check if it's a function pointer or built-in registered as a symbol. if (node->call.callee->type == NODE_EXPR_VAR) { Symbol *sym = find_symbol_entry(ctx, node->call.callee->var_ref.name); - if (sym && sym->type_info) + if (sym && sym->type_info && sym->type_info->kind == TYPE_FUNCTION && + sym->type_info->inner) { - // If it's a function pointer type, return return type. - if (sym->type_info->kind == TYPE_FUNCTION && sym->type_info->inner) - { - return type_to_string(sym->type_info->inner); - } - if (sym->type_info->kind == TYPE_POINTER && sym->type_info->inner && - sym->type_info->inner->kind == TYPE_FUNCTION && sym->type_info->inner->inner) + return type_to_string(sym->type_info->inner); + } + } + } + + if (node->type == NODE_TRY) + { + char *inner_type = infer_type(ctx, node->try_stmt.expr); + if (inner_type) + { + // Extract T from Result<T> or Option<T> + char *start = strchr(inner_type, '<'); + if (start) + { + start++; // Skip < + char *end = strrchr(inner_type, '>'); + if (end && end > start) { - return type_to_string(sym->type_info->inner->inner); + int len = end - start; + char *extracted = xmalloc(len + 1); + strncpy(extracted, start, len); + extracted[len] = 0; + return extracted; } } } - - return NULL; } if (node->type == NODE_EXPR_MEMBER) |
