diff --git a/lang/codegen/global.c b/lang/codegen/global.c new file mode 100644 index 0000000..8703152 --- /dev/null +++ b/lang/codegen/global.c @@ -0,0 +1,165 @@ +#include "../debug.h" +#include "codegen.h" + +#include +#include +#include + +struct global_codegen_state { + struct code_generator_state s_base; + unsigned int s_prev_node; + /* TODO support multiple idents (for tuples) */ + struct ivy_ast_ident_node *s_var_ident; + struct mie_value *s_var_ptr; + struct mie_value *s_value; +}; + +static struct code_generator_result gen_global( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct global_codegen_state *global = (struct global_codegen_state *)state; + if (global->s_prev_node != 0) { + return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX); + } + + global->s_prev_node = IVY_AST_GLOBAL; + return CODEGEN_RESULT_OK(0); +} + +static struct code_generator_result gen_value_expr( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node, size_t depth) +{ + struct global_codegen_state *global = (struct global_codegen_state *)state; + if (global->s_prev_node != IVY_AST_IDENT + && global->s_prev_node != IVY_AST_TUPLE) { + return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX); + } + + codegen_push_generator(gen, CODE_GENERATOR_EXPR, 0, NULL); + + 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 global_codegen_state *global = (struct global_codegen_state *)state; + if (global->s_prev_node != IVY_AST_GLOBAL) { + return gen_value_expr(gen, state, node, depth); + } + + struct ivy_ast_ident_node *ident = (struct ivy_ast_ident_node *)node; + const char *var_name = ident->n_content->t_str; + + /* TODO get type from expression */ + struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + struct mie_value *var_ptr + = mie_builder_alloca(gen->c_builder, id, var_name); + + global->s_var_ident = (struct ivy_ast_ident_node *)node; + global->s_var_ptr = var_ptr; + global->s_prev_node = IVY_AST_IDENT; + + return CODEGEN_RESULT_OK(0); +} + +#if 0 +static struct code_generator_result gen_var_ref( + struct ivy_codegen *gen, struct code_generator_state *state, + struct ivy_ast_node *node) +{ + struct ivy_ast_ident_node *ident = (struct ivy_ast_ident_node *)node; + struct codegen_var *var + = codegen_resolve_variable(gen, ident->n_content->t_str); + + if (var) { + /* this variable has been defined previously, and we have a + * mie_value representing its location on the stack */ + struct codegen_value *var_value + = codegen_value_create(node, var->v_ptr); + codegen_push_value(gen, var_value); + return CODEGEN_RESULT_OK(0); + } + + /* this variable either doesn't exist, or is a global variable */ + struct codegen_value *var_value = codegen_value_create(node, NULL); + codegen_push_value(gen, var_value); + + return CODEGEN_RESULT_OK(0); +} +#endif + +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 global decl\n"); + return IVY_OK; +} + +static enum ivy_status state_fini( + struct ivy_codegen *gen, struct code_generator_state *state, + struct code_generator_value *result) +{ + debug_printf("codegen: end of global decl\n"); + struct global_codegen_state *global = (struct global_codegen_state *)state; + + const char *ident = global->s_var_ident->n_content->t_str; + struct mie_type *type = NULL; + if (global->s_value) { + type = mie_value_get_type(global->s_value, gen->c_ctx); + } else { + type = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID); + } + + struct codegen_var var_info = { + .v_node = (struct ivy_ast_node *)global->s_var_ident, + .v_type = type, + .v_flags = CODEGEN_VAR_F_PTR, + .v_value = global->s_var_ptr, + }; + + codegen_define_variable(gen, ident, &var_info); + + // struct code_generator_scope *scope = codegen_get_current_scope(gen); + // code_generator_scope_put_variable(scope, var->s_var_ident, var->s_var_ptr); + + if (global->s_value) { + mie_builder_store( + gen->c_builder, global->s_value, global->s_var_ptr); + } + + return IVY_OK; +} + +static struct code_generator_result value_received( + struct ivy_codegen *gen, struct code_generator_state *state, + struct code_generator_value *value) +{ + debug_printf("codegen: global decl value received\n"); + + struct global_codegen_state *global = (struct global_codegen_state *)state; + if (!global->s_var_ptr) { + return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX); + } + + global->s_value = value->v_value.mie_value; + + return CODEGEN_RESULT_OK(CODEGEN_R_POP_GENERATOR); +} + +struct code_generator global_generator = { + .g_type = CODE_GENERATOR_GLOBAL, + .g_state_size = sizeof(struct global_codegen_state), + .g_state_init = state_init, + .g_state_fini = state_fini, + .g_value_received = value_received, + .g_expr_generator = gen_value_expr, + .g_node_generators = { + [IVY_AST_GLOBAL] = gen_global, + [IVY_AST_IDENT] = gen_ident, + }, +};