lang: codegen: redesign again to use purely pre-order ast traversal
This commit is contained in:
146
lang/codegen/var.c
Normal file
146
lang/codegen/var.c
Normal file
@@ -0,0 +1,146 @@
|
||||
#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_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) {
|
||||
/* TODO support tuple assignment */
|
||||
return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
return CODEGEN_RESULT_OK(CODEGEN_REPEAT_NODE);
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
printf("codegen: end of var decl\n");
|
||||
struct var_codegen_state *var = (struct var_codegen_state *)state;
|
||||
|
||||
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)
|
||||
{
|
||||
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_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_node_generators = {
|
||||
[IVY_AST_VAR] = gen_var,
|
||||
[IVY_AST_IDENT] = gen_ident,
|
||||
[IVY_AST_INT] = gen_value_expr,
|
||||
[IVY_AST_OP] = gen_value_expr,
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user