the var keyword allows greater control over what scope a particular variable exists in. it clarifies whether a new variable is being defined or an existing variable is being assigned to. it will also facilitate the implementation of global variables.
129 lines
3.0 KiB
C
129 lines
3.0 KiB
C
#include "../debug.h"
|
|
#include "codegen.h"
|
|
|
|
#include <stdio.h>
|
|
|
|
struct expr_codegen_state {
|
|
struct code_generator_state s_base;
|
|
struct ivy_ast_node *s_expr_root;
|
|
};
|
|
|
|
static struct code_generator_result check_expr_root(
|
|
struct ivy_codegen *gen, struct code_generator_state *state,
|
|
struct ivy_ast_node *node)
|
|
{
|
|
struct expr_codegen_state *expr = (struct expr_codegen_state *)state;
|
|
if (!expr->s_expr_root) {
|
|
expr->s_expr_root = node;
|
|
}
|
|
|
|
return CODEGEN_RESULT_OK(0);
|
|
}
|
|
|
|
static struct code_generator_result gen_int(
|
|
struct ivy_codegen *gen, struct code_generator_state *state,
|
|
struct ivy_ast_node *node)
|
|
{
|
|
struct expr_codegen_state *expr = (struct expr_codegen_state *)state;
|
|
|
|
debug_printf("codegen: got int\n");
|
|
|
|
struct ivy_ast_int_node *int_node = (struct ivy_ast_int_node *)node;
|
|
struct mie_value *value
|
|
= mie_ctx_get_int(gen->c_ctx, int_node->n_value->t_int, 32);
|
|
|
|
codegen_push_value(gen, value);
|
|
|
|
if (node == expr->s_expr_root) {
|
|
codegen_pop_generator(gen);
|
|
}
|
|
|
|
return CODEGEN_RESULT_OK(0);
|
|
}
|
|
|
|
static struct code_generator_result gen_op(
|
|
struct ivy_codegen *gen, struct code_generator_state *state,
|
|
struct ivy_ast_node *node)
|
|
{
|
|
struct expr_codegen_state *expr = (struct expr_codegen_state *)state;
|
|
|
|
debug_printf("codegen: got operator\n");
|
|
|
|
struct mie_value *left = codegen_pop_value(gen);
|
|
struct mie_value *right = codegen_pop_value(gen);
|
|
|
|
if (!left || !right) {
|
|
return CODEGEN_RESULT_ERR(IVY_ERR_INVALID_VALUE);
|
|
}
|
|
|
|
struct ivy_ast_op_node *op_node = (struct ivy_ast_op_node *)node;
|
|
const struct ivy_operator *op = op_node->n_op;
|
|
struct mie_value *op_instr = NULL;
|
|
|
|
switch (op->op_id) {
|
|
case IVY_OP_ADD:
|
|
op_instr
|
|
= mie_builder_add(gen->c_builder, left, right, "addtmp");
|
|
break;
|
|
case IVY_OP_SUBTRACT:
|
|
op_instr
|
|
= mie_builder_sub(gen->c_builder, left, right, "subtmp");
|
|
break;
|
|
case IVY_OP_MULTIPLY:
|
|
op_instr
|
|
= mie_builder_mul(gen->c_builder, left, right, "multmp");
|
|
break;
|
|
case IVY_OP_DIVIDE:
|
|
op_instr
|
|
= mie_builder_div(gen->c_builder, left, right, "divtmp");
|
|
break;
|
|
default:
|
|
mie_value_destroy(left);
|
|
mie_value_destroy(right);
|
|
return CODEGEN_RESULT_ERR(IVY_ERR_NOT_SUPPORTED);
|
|
}
|
|
|
|
if (!op_instr) {
|
|
mie_value_destroy(left);
|
|
mie_value_destroy(right);
|
|
return CODEGEN_RESULT_ERR(IVY_ERR_NO_MEMORY);
|
|
}
|
|
|
|
codegen_push_value(gen, op_instr);
|
|
|
|
if (node == expr->s_expr_root) {
|
|
codegen_pop_generator(gen);
|
|
}
|
|
|
|
return CODEGEN_RESULT_OK(0);
|
|
}
|
|
|
|
static enum ivy_status state_init(
|
|
struct ivy_codegen *gen, struct code_generator_state *state)
|
|
{
|
|
debug_printf("codegen: start of expression\n");
|
|
return IVY_OK;
|
|
}
|
|
|
|
static enum ivy_status state_fini(
|
|
struct ivy_codegen *gen, struct code_generator_state *state)
|
|
{
|
|
debug_printf("codegen: end of expression\n");
|
|
return IVY_OK;
|
|
}
|
|
|
|
struct code_generator expr_generator = {
|
|
.g_type = CODE_GENERATOR_UNIT,
|
|
.g_state_size = sizeof(struct expr_codegen_state),
|
|
.g_state_init = state_init,
|
|
.g_state_fini = state_fini,
|
|
.g_node_generators_pre = {
|
|
[IVY_AST_INT] = check_expr_root,
|
|
[IVY_AST_OP] = check_expr_root,
|
|
},
|
|
.g_node_generators_post = {
|
|
[IVY_AST_INT] = gen_int,
|
|
[IVY_AST_OP] = gen_op,
|
|
},
|
|
};
|