Files
ivy/lang/codegen/var.c

164 lines
4.6 KiB
C
Raw Normal View History

#include "../debug.h"
#include "codegen.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct var_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_var(
struct ivy_codegen *gen, struct code_generator_state *state,
struct ivy_ast_node *node, size_t depth)
{
struct var_codegen_state *var = (struct var_codegen_state *)state;
if (var->s_prev_node != 0) {
return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX);
}
var->s_prev_node = IVY_AST_VAR;
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 var_codegen_state *var = (struct var_codegen_state *)state;
if (var->s_prev_node != IVY_AST_IDENT && var->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 var_codegen_state *var = (struct var_codegen_state *)state;
if (var->s_prev_node != IVY_AST_VAR) {
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);
var->s_var_ident = (struct ivy_ast_ident_node *)node;
var->s_var_ptr = var_ptr;
var->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 var decl\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 var decl\n");
struct var_codegen_state *var = (struct var_codegen_state *)state;
const char *ident = var->s_var_ident->n_content->t_str;
struct mie_type *type = NULL;
if (var->s_value) {
type = mie_value_get_type(var->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 *)var->s_var_ident,
.v_type = type,
.v_flags = CODEGEN_VAR_F_PTR,
.v_value = var->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 (var->s_value) {
mie_builder_store(gen->c_builder, var->s_value, var->s_var_ptr);
}
return IVY_OK;
}
static struct code_generator_result value_received(
struct ivy_codegen *gen, struct code_generator_state *state,
struct mie_value *value)
{
debug_printf("codegen: var decl value received\n");
struct var_codegen_state *var = (struct var_codegen_state *)state;
if (!var->s_var_ptr) {
return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX);
}
var->s_value = value;
return CODEGEN_RESULT_OK(CODEGEN_R_POP_GENERATOR);
}
struct code_generator var_generator = {
.g_type = CODE_GENERATOR_VAR,
.g_state_size = sizeof(struct var_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_VAR] = gen_var,
[IVY_AST_IDENT] = gen_ident,
},
};