lang: codegen: add generator for global variable declarations
This commit is contained in:
165
lang/codegen/global.c
Normal file
165
lang/codegen/global.c
Normal file
@@ -0,0 +1,165 @@
|
||||
#include "../debug.h"
|
||||
#include "codegen.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user