#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, }, };