diff --git a/lang/codegen/codegen.c b/lang/codegen/codegen.c index 79fa06d..38e60ac 100644 --- a/lang/codegen/codegen.c +++ b/lang/codegen/codegen.c @@ -18,6 +18,24 @@ * mie_value for its parent generator to use. */ +static struct code_generator_state *get_current_generator_state( + struct ivy_codegen *gen) +{ + b_queue_entry *entry = b_queue_last(&gen->c_state); + if (!entry) { + return NULL; + } + + return b_unbox(struct code_generator_state, entry, s_entry); +} + +static void code_generator_state_inherit( + struct code_generator_state *parent, struct code_generator_state *child) +{ + child->s_loop_break_target = parent->s_loop_break_target; + child->s_loop_repeat_target = parent->s_loop_repeat_target; +} + enum ivy_status codegen_push_generator( struct ivy_codegen *gen, enum code_generator_type gen_type, uintptr_t argv, void *argp) @@ -42,6 +60,13 @@ enum ivy_status codegen_push_generator( enum ivy_status status = IVY_OK; + struct code_generator_state *parent_state + = get_current_generator_state(gen); + + if (parent_state) { + code_generator_state_inherit(parent_state, state); + } + if (generator->g_state_init) { status = generator->g_state_init(gen, state, argv, argp); } @@ -111,6 +136,7 @@ enum ivy_status codegen_define_variable( return IVY_ERR_NOT_SUPPORTED; } +#if 0 enum ivy_status resolve_global_variable( struct ivy_codegen *gen, const char *ident, struct codegen_var *out) { @@ -124,6 +150,7 @@ enum ivy_status resolve_global_variable( return IVY_OK; } +#endif enum ivy_status codegen_resolve_variable( struct ivy_codegen *gen, const char *ident, struct codegen_var *out) @@ -153,9 +180,11 @@ enum ivy_status codegen_resolve_variable( entry = b_queue_prev(entry); } +#if 0 if (!resolved) { return resolve_global_variable(gen, ident, out); } +#endif if (entry) { entry = b_queue_next(entry); @@ -192,15 +221,14 @@ struct mie_value *codegen_load_variable( return var->v_value; } -static struct code_generator_state *get_current_generator_state( - struct ivy_codegen *gen) +void codegen_store_variable( + struct ivy_codegen *gen, struct codegen_var *var, struct mie_value *val) { - b_queue_entry *entry = b_queue_last(&gen->c_state); - if (!entry) { - return NULL; + if (!(var->v_flags & CODEGEN_VAR_F_PTR)) { + return; } - return b_unbox(struct code_generator_state, entry, s_entry); + mie_builder_store(gen->c_builder, val, var->v_value); } enum ivy_status ivy_codegen_create(struct mie_ctx *ctx, struct ivy_codegen **out) @@ -317,6 +345,9 @@ static bool node_is_expr(struct ivy_ast_node *node) case IVY_AST_DISCARD: case IVY_AST_INT: case IVY_AST_DOUBLE: + case IVY_AST_C_TRUE: + case IVY_AST_C_FALSE: + case IVY_AST_C_NULL: case IVY_AST_STRING: case IVY_AST_FSTRING: case IVY_AST_ATOM: @@ -389,6 +420,10 @@ enum ivy_status ivy_codegen_push_node( result = func(gen, state, node, node_depth); + if (result.r_status != IVY_OK) { + return result.r_status; + } + if (result.r_flags & CODEGEN_R_REPEAT_NODE) { continue; } diff --git a/lang/codegen/codegen.h b/lang/codegen/codegen.h index be837b5..cf4af4c 100644 --- a/lang/codegen/codegen.h +++ b/lang/codegen/codegen.h @@ -48,6 +48,7 @@ enum code_generator_type { CODE_GENERATOR_COND_GROUP, CODE_GENERATOR_COND, CODE_GENERATOR_FOR_LOOP, + CODE_GENERATOR_WHILE_LOOP, }; enum code_generator_scope_type { @@ -127,6 +128,8 @@ struct code_generator_state { const struct code_generator *s_gen; struct ivy_ast_node *s_root; size_t s_depth; + + struct mie_block *s_loop_break_target, *s_loop_repeat_target; }; struct ivy_codegen { diff --git a/lang/codegen/for-loop.c b/lang/codegen/for-loop.c index 4729079..d82875c 100644 --- a/lang/codegen/for-loop.c +++ b/lang/codegen/for-loop.c @@ -6,8 +6,18 @@ struct for_codegen_state { struct code_generator_state s_base; - struct mie_value *s_iterator; + struct ivy_ast_ident_node *s_it_ident; struct mie_value *s_container; + struct mie_value *s_iterator; + struct mie_value *s_it_value, *s_it_value_inner; + struct mie_value *s_it_finished; + + struct { + struct mie_block *b_cond; + struct mie_block *b_body; + struct mie_block *b_inc; + struct mie_block *b_end; + } s_blocks; }; static struct code_generator_result gen_expr( @@ -20,10 +30,37 @@ static struct code_generator_result gen_expr( return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } +static struct code_generator_result gen_ident( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct for_codegen_state *for_loop = (struct for_codegen_state *)state; + if (!for_loop->s_it_ident) { + for_loop->s_it_ident = (struct ivy_ast_ident_node *)node; + return CODEGEN_RESULT_OK(0); + } + + return gen_expr(gen, state, node, depth); +} + +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) +{ + return CODEGEN_RESULT_OK(0); +} + static struct code_generator_result gen_block( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) { + struct for_codegen_state *for_loop = (struct for_codegen_state *)state; + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + + // mie_builder_br(gen->c_builder, for_loop->s_blocks.b_cond); + // mie_func_insert_block(func, for_loop->s_blocks.b_cond, NULL); + // mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_cond); + codegen_push_generator(gen, CODE_GENERATOR_BLOCK, 0, NULL); return CODEGEN_RESULT_OK(0); } @@ -32,6 +69,99 @@ static enum ivy_status state_init( struct ivy_codegen *gen, struct code_generator_state *state, uintptr_t argv, void *argp) { + struct for_codegen_state *for_loop = (struct for_codegen_state *)state; + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + + for_loop->s_blocks.b_cond = mie_func_create_block(func, "for.cond"); + for_loop->s_blocks.b_body = mie_func_create_block(func, "for.body"); + for_loop->s_blocks.b_inc = mie_func_create_block(func, "for.inc"); + for_loop->s_blocks.b_end = mie_func_create_block(func, "for.end"); + + state->s_loop_break_target = for_loop->s_blocks.b_end; + state->s_loop_repeat_target = for_loop->s_blocks.b_inc; + + return IVY_OK; +} + +static enum ivy_status gen_iterator_start( + struct ivy_codegen *gen, struct for_codegen_state *for_loop) +{ + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + + struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M8iteratorE"); + for_loop->s_iterator = mie_builder_msg( + gen->c_builder, id, for_loop->s_container, sel, NULL, 0, 0, + "for.it"); + mie_builder_br(gen->c_builder, for_loop->s_blocks.b_cond); + return IVY_OK; +} + +static enum ivy_status gen_cond_block( + struct ivy_codegen *gen, struct for_codegen_state *for_loop) +{ + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + mie_func_insert_block(func, for_loop->s_blocks.b_cond, NULL); + mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_cond); + + struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M5valueE"); + struct mie_value *null_value = mie_ctx_get_null(gen->c_ctx); + for_loop->s_it_value = mie_builder_msg( + gen->c_builder, id, for_loop->s_iterator, sel, NULL, 0, 0, + "for.value"); + for_loop->s_it_finished = mie_builder_cmp_eq( + gen->c_builder, for_loop->s_it_value, null_value, + "for.finished"); + + mie_builder_br_if( + gen->c_builder, for_loop->s_it_finished, + for_loop->s_blocks.b_end, for_loop->s_blocks.b_body); + + return IVY_OK; +} + +static enum ivy_status gen_body( + struct ivy_codegen *gen, struct for_codegen_state *for_loop) +{ + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + mie_func_insert_block(func, for_loop->s_blocks.b_body, NULL); + mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_body); + + struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + for_loop->s_it_value_inner = mie_builder_alloca( + gen->c_builder, id, for_loop->s_it_ident->n_content->t_str); + mie_builder_store( + gen->c_builder, for_loop->s_it_value, for_loop->s_it_value_inner); + + return IVY_OK; +} + +static enum ivy_status gen_inc_block( + struct ivy_codegen *gen, struct for_codegen_state *for_loop) +{ + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + mie_builder_br(gen->c_builder, for_loop->s_blocks.b_inc); + + mie_func_insert_block(func, for_loop->s_blocks.b_inc, NULL); + mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_inc); + + struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M8moveNextE"); + mie_builder_msg( + gen->c_builder, id, for_loop->s_iterator, sel, NULL, 0, 0, NULL); + mie_builder_br(gen->c_builder, for_loop->s_blocks.b_cond); + + return IVY_OK; +} + +static enum ivy_status gen_end_block( + struct ivy_codegen *gen, struct for_codegen_state *for_loop) +{ + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); + mie_func_insert_block(func, for_loop->s_blocks.b_end, NULL); + mie_builder_set_insert_point(gen->c_builder, for_loop->s_blocks.b_end); + return IVY_OK; } @@ -39,6 +169,9 @@ static enum ivy_status state_fini( struct ivy_codegen *gen, struct code_generator_state *state, struct code_generator_value *result) { + struct for_codegen_state *for_loop = (struct for_codegen_state *)state; + gen_inc_block(gen, for_loop); + gen_end_block(gen, for_loop); return IVY_OK; } @@ -47,24 +180,48 @@ static struct code_generator_result value_received( struct code_generator_value *value) { struct for_codegen_state *for_loop = (struct for_codegen_state *)state; + struct mie_func *func = mie_builder_get_current_func(gen->c_builder); - if (!for_loop->s_iterator) { - for_loop->s_iterator = value; - } else if (!for_loop->s_container) { - for_loop->s_container = value; + if (!for_loop->s_container) { + for_loop->s_container = code_generator_value_get_mie_value(value); + gen_iterator_start(gen, for_loop); + gen_cond_block(gen, for_loop); + gen_body(gen, for_loop); + return CODEGEN_RESULT_OK(0); } return CODEGEN_RESULT_OK(0); } +static enum ivy_status resolve_var( + struct ivy_codegen *gen, struct code_generator_state *state, + const char *ident, struct codegen_var *var) +{ + struct for_codegen_state *for_loop = (struct for_codegen_state *)state; + + if (strcmp(ident, for_loop->s_it_ident->n_content->t_str) != 0) { + return IVY_ERR_NO_ENTRY; + } + + var->v_node = (struct ivy_ast_node *)for_loop->s_it_ident; + var->v_type = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + var->v_value = for_loop->s_it_value_inner; + var->v_flags = CODEGEN_VAR_F_PTR; + + return IVY_OK; +} + struct code_generator for_loop_generator = { .g_type = CODE_GENERATOR_FOR_LOOP, .g_state_size = sizeof(struct for_codegen_state), .g_state_init = state_init, .g_state_fini = state_fini, + .g_resolve_var = resolve_var, .g_value_received = value_received, .g_expr_generator = gen_expr, .g_node_generators = { + NODE_CODEGEN(FOR_LOOP, gen_for_loop), + NODE_CODEGEN(IDENT, gen_ident), NODE_CODEGEN(BLOCK, gen_block), }, }; diff --git a/lang/codegen/unit.c b/lang/codegen/unit.c index c1f90ba..ef9853f 100644 --- a/lang/codegen/unit.c +++ b/lang/codegen/unit.c @@ -98,6 +98,28 @@ static struct code_generator_result gen_expr( return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); } +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 unit_codegen_state *unit = (struct unit_codegen_state *)state; + struct mie_builder *builder = gen->c_builder; + struct mie_func *current = mie_builder_get_current_func(builder); + + enum ivy_status status = IVY_OK; + if (!current || current != unit->s_immediate) { + status = switch_to_immediate_func(gen, unit, ENSURE_OPEN_BLOCK); + } + + if (status != IVY_OK) { + return CODEGEN_RESULT_ERR(status); + } + + codegen_push_generator( + gen, CODE_GENERATOR_FOR_LOOP, CODEGEN_F_IGNORE_RESULT, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + static void serialise_package_name(b_queue *parts, b_stringstream *out) { b_stringstream_add(out, "_ZN"); @@ -251,6 +273,7 @@ struct code_generator unit_generator = { .g_state_fini = state_fini, .g_node_generators = { NODE_CODEGEN(RETURN, gen_return), + NODE_CODEGEN(FOR_LOOP, gen_for_loop), NODE_CODEGEN(UNIT_PACKAGE, gen_unit_package), NODE_CODEGEN(UNIT_IMPORT, gen_unit_import), },