From 312e737f9fcccf933633d2d9d569051eea4990cd Mon Sep 17 00:00:00 2001 From: Max Wash Date: Mon, 8 Sep 2025 16:21:05 +0100 Subject: [PATCH] lang: codegen: implement returning the last value evaluated in a block --- lang/codegen/block.c | 74 +++++++++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 11 deletions(-) diff --git a/lang/codegen/block.c b/lang/codegen/block.c index a9af1e3..bad4349 100644 --- a/lang/codegen/block.c +++ b/lang/codegen/block.c @@ -8,6 +8,9 @@ struct block_codegen_state { struct code_generator_state s_base; struct code_generator_scope *s_scope; struct codegen_var_map s_vars; + + /* the value of the final expression in the block */ + struct mie_value *s_result; }; static struct code_generator_result gen_expr( @@ -23,21 +26,21 @@ static struct code_generator_result gen_expr( return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } -static struct code_generator_result gen_var_declaration( +static struct code_generator_result gen_for_loop( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) { - struct block_codegen_state *block = (struct block_codegen_state *)state; - struct mie_builder *builder = gen->c_builder; - struct mie_func *current = mie_builder_get_current_func(builder); + codegen_push_generator( + gen, CODE_GENERATOR_FOR_LOOP, CODEGEN_F_IGNORE_RESULT, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} - enum ivy_status status = IVY_OK; - - if (status != IVY_OK) { - return CODEGEN_RESULT_ERR(status); - } - - codegen_push_generator(gen, CODE_GENERATOR_VAR, 0, NULL); +static struct code_generator_result gen_while_loop( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + codegen_push_generator( + gen, CODE_GENERATOR_WHILE_LOOP, CODEGEN_F_IGNORE_RESULT, NULL); return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } @@ -59,6 +62,38 @@ static struct code_generator_result gen_return( return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } +static struct code_generator_result gen_loop_break( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct block_codegen_state *block = (struct block_codegen_state *)state; + + if (!state->s_loop_break_target) { + return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX); + } + + mie_builder_br(gen->c_builder, state->s_loop_break_target); + + block->s_result = mie_ctx_get_null(gen->c_ctx); + return CODEGEN_RESULT_OK(0); +} + +static struct code_generator_result gen_loop_repeat( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct block_codegen_state *block = (struct block_codegen_state *)state; + + if (!state->s_loop_repeat_target) { + return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX); + } + + mie_builder_br(gen->c_builder, state->s_loop_repeat_target); + + block->s_result = mie_ctx_get_null(gen->c_ctx); + return CODEGEN_RESULT_OK(0); +} + static enum ivy_status state_init( struct ivy_codegen *gen, struct code_generator_state *state, uintptr_t argv, void *argp) @@ -73,9 +108,21 @@ static enum ivy_status state_fini( struct ivy_codegen *gen, struct code_generator_state *state, struct code_generator_value *result) { + struct block_codegen_state *block = (struct block_codegen_state *)state; + code_generator_value_set_mie_value(result, block->s_result); + codegen_var_map_fini(&block->s_vars); return IVY_OK; } +static struct code_generator_result value_received( + struct ivy_codegen *gen, struct code_generator_state *state, + struct code_generator_value *value) +{ + struct block_codegen_state *block = (struct block_codegen_state *)state; + block->s_result = code_generator_value_get_mie_value(value); + return CODEGEN_RESULT_OK(0); +} + static enum ivy_status define_var( struct ivy_codegen *gen, struct code_generator_state *state, const char *ident, const struct codegen_var *var) @@ -106,8 +153,13 @@ struct code_generator block_generator = { .g_state_size = sizeof(struct block_codegen_state), .g_state_init = state_init, .g_state_fini = state_fini, + .g_value_received = value_received, .g_node_generators = { + NODE_CODEGEN(FOR_LOOP, gen_for_loop), + NODE_CODEGEN(WHILE_LOOP, gen_while_loop), NODE_CODEGEN(RETURN, gen_return), + NODE_CODEGEN(LOOP_BREAK, gen_loop_break), + NODE_CODEGEN(LOOP_REPEAT, gen_loop_repeat), }, .g_expr_generator = gen_expr, .g_define_var = define_var,