From 4a258e25804a6af1121a3a8f1060fa39bd081192 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Fri, 18 Apr 2025 23:17:39 +0100 Subject: [PATCH] lang: codegen: implement fstring generation --- lang/codegen/codegen.h | 1 + lang/codegen/expr.c | 13 ++++++ lang/codegen/fstring.c | 96 ++++++++++++++++++++++++++++++++++++++++ lang/codegen/generator.c | 9 ++-- 4 files changed, 115 insertions(+), 4 deletions(-) create mode 100644 lang/codegen/fstring.c diff --git a/lang/codegen/codegen.h b/lang/codegen/codegen.h index 56807b7..951687e 100644 --- a/lang/codegen/codegen.h +++ b/lang/codegen/codegen.h @@ -49,6 +49,7 @@ enum code_generator_type { CODE_GENERATOR_EXPR, CODE_GENERATOR_VAR, CODE_GENERATOR_MSG, + CODE_GENERATOR_FSTRING, }; enum code_generator_scope_type { diff --git a/lang/codegen/expr.c b/lang/codegen/expr.c index d950577..b8b7ece 100644 --- a/lang/codegen/expr.c +++ b/lang/codegen/expr.c @@ -117,6 +117,18 @@ static struct code_generator_result gen_string( return CODEGEN_RESULT_OK(0); } +static struct code_generator_result gen_fstring( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + debug_printf("codegen: got fstring\n"); + struct expr_codegen_state *expr = (struct expr_codegen_state *)state; + + codegen_push_generator(gen, CODE_GENERATOR_FSTRING, 0, NULL); + + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + static struct code_generator_result gen_op( struct ivy_codegen *gen, struct code_generator_state *state, struct ivy_ast_node *node, size_t depth) @@ -404,6 +416,7 @@ struct code_generator expr_generator = { NODE_CODEGEN(OP, gen_op), NODE_CODEGEN(MSG, gen_msg), NODE_CODEGEN(STRING, gen_string), + NODE_CODEGEN(FSTRING, gen_fstring), NODE_CODEGEN(IDENT, gen_var_reference), }, }; diff --git a/lang/codegen/fstring.c b/lang/codegen/fstring.c new file mode 100644 index 0000000..fd963a4 --- /dev/null +++ b/lang/codegen/fstring.c @@ -0,0 +1,96 @@ +#include "../debug.h" +#include "codegen.h" + +#include +#include +#include + +struct fstring_codegen_state { + struct code_generator_state s_base; + struct mie_value *s_stringbuilder; +}; + +static struct code_generator_result gen_fstring( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct fstring_codegen_state *fstring + = (struct fstring_codegen_state *)state; + + struct mie_value *stringbuilder_ptr + = mie_builder_get_data_ptr(gen->c_builder, "StringBuilder"); + + struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + struct mie_value *stringbuilder_class + = mie_builder_load(gen->c_builder, id, stringbuilder_ptr, NULL); + struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M3newE"); + + fstring->s_stringbuilder = mie_builder_msg( + gen->c_builder, id, stringbuilder_class, sel, NULL, 0, 0, NULL); + + return CODEGEN_RESULT_OK(0); +} + +static struct code_generator_result gen_expr( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + codegen_push_generator(gen, CODE_GENERATOR_EXPR, 0, NULL); + return CODEGEN_RESULT_OK(CODEGEN_R_REPEAT_NODE); +} + +static enum ivy_status state_init( + struct ivy_codegen *gen, struct code_generator_state *state, + uintptr_t argv, void *argp) +{ + debug_printf("codegen: start of fstring\n"); + return IVY_OK; +} + +static enum ivy_status state_fini( + struct ivy_codegen *gen, struct code_generator_state *state, + struct mie_value **result) +{ + debug_printf("codegen: end of fstring\n"); + struct fstring_codegen_state *fstring + = (struct fstring_codegen_state *)state; + + 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, "_M8toStringE"); + + struct mie_value *str = mie_builder_msg( + gen->c_builder, id, fstring->s_stringbuilder, sel, NULL, 0, 0, + NULL); + + *result = str; + return IVY_OK; +} + +static struct code_generator_result value_received( + struct ivy_codegen *gen, struct code_generator_state *state, + struct mie_value *value) +{ + struct fstring_codegen_state *fstring + = (struct fstring_codegen_state *)state; + + struct mie_type *void_type = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_VOID); + struct mie_value *sel = mie_ctx_get_selector(gen->c_ctx, "_M06appendE"); + + mie_builder_msg( + gen->c_builder, void_type, fstring->s_stringbuilder, sel, + &value, 1, MIE_BUILDER_IGNORE_RESULT, NULL); + + return CODEGEN_RESULT_OK(0); +} + +struct code_generator fstring_generator = { + .g_type = CODE_GENERATOR_FSTRING, + .g_state_size = sizeof(struct fstring_codegen_state), + .g_state_init = state_init, + .g_state_fini = state_fini, + .g_value_received = value_received, + .g_expr_generator = gen_expr, + .g_node_generators = { + NODE_CODEGEN(FSTRING, gen_fstring), + }, +}; diff --git a/lang/codegen/generator.c b/lang/codegen/generator.c index 2261cd9..6c3e7e3 100644 --- a/lang/codegen/generator.c +++ b/lang/codegen/generator.c @@ -1,15 +1,19 @@ #include "codegen.h" +#include + extern const struct code_generator unit_generator; extern const struct code_generator expr_generator; extern const struct code_generator var_generator; extern const struct code_generator msg_generator; +extern const struct code_generator fstring_generator; static const struct code_generator *code_generators[] = { [CODE_GENERATOR_UNIT] = &unit_generator, [CODE_GENERATOR_EXPR] = &expr_generator, [CODE_GENERATOR_VAR] = &var_generator, [CODE_GENERATOR_MSG] = &msg_generator, + [CODE_GENERATOR_FSTRING] = &fstring_generator, }; static const size_t nr_code_generators = sizeof code_generators / sizeof code_generators[0]; @@ -25,10 +29,7 @@ static const size_t nr_root_code_generators const struct code_generator *get_code_generator(enum code_generator_type type) { - if (type >= nr_code_generators) { - return NULL; - } - + assert(type >= 0 && type < nr_code_generators); return code_generators[type]; }