lang: codegen: redesign again to use purely pre-order ast traversal
This commit is contained in:
@@ -212,6 +212,11 @@ token_parse_function get_token_parser(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct ivy_ast_node *ivy_ast_node_create(enum ivy_ast_node_type type)
|
||||
{
|
||||
return ast_node_create(type);
|
||||
}
|
||||
|
||||
struct ivy_ast_node *ast_node_create(enum ivy_ast_node_type type)
|
||||
{
|
||||
const struct ast_node_type *type_info = get_ast_node_type(type);
|
||||
@@ -296,3 +301,18 @@ const char *ivy_ast_node_type_to_string(enum ivy_ast_node_type v)
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
void ivy_ast_unit_add_node(struct ivy_ast_unit_node *unit, struct ivy_ast_node *child)
|
||||
{
|
||||
b_queue_push_back(&unit->n_children, &child->n_entry);
|
||||
}
|
||||
|
||||
struct ivy_ast_node *ivy_ast_unit_dequeue_node(struct ivy_ast_unit_node *unit)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_pop_front(&unit->n_children);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return b_unbox(struct ivy_ast_node, entry, n_entry);
|
||||
}
|
||||
|
||||
@@ -7,6 +7,17 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* new codegen layout:
|
||||
* - traverse the AST in pre-order (i.e. in the order it's displayed by debug)
|
||||
* - each node type (var, msg, expr) gets its own code generator type
|
||||
* - expr code generator is limited to simple operator arithmetic.
|
||||
* - when a code generator encounters a node of an equal or lower depth than
|
||||
* the node that started it, it has reached the end of its subtree.
|
||||
* - depth is supplied by the ast iterator.
|
||||
* - need to devise a way for expression code generator to "return" a
|
||||
* mie_value for its parent generator to use.
|
||||
*/
|
||||
|
||||
enum ivy_status codegen_push_generator(
|
||||
struct ivy_codegen *gen, enum code_generator_type gen_type, void *arg)
|
||||
{
|
||||
@@ -45,7 +56,8 @@ enum ivy_status codegen_push_generator(
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
enum ivy_status codegen_pop_generator(struct ivy_codegen *gen)
|
||||
enum ivy_status codegen_pop_generator(
|
||||
struct ivy_codegen *gen, struct mie_value **result)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_pop_back(&gen->c_state);
|
||||
if (!entry) {
|
||||
@@ -58,7 +70,7 @@ enum ivy_status codegen_pop_generator(struct ivy_codegen *gen)
|
||||
enum ivy_status status = IVY_OK;
|
||||
|
||||
if (state->s_gen->g_state_fini) {
|
||||
status = state->s_gen->g_state_fini(gen, state);
|
||||
status = state->s_gen->g_state_fini(gen, state, result);
|
||||
}
|
||||
|
||||
if (status != IVY_OK) {
|
||||
@@ -69,19 +81,148 @@ enum ivy_status codegen_pop_generator(struct ivy_codegen *gen)
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
void codegen_push_value(struct ivy_codegen *gen, struct mie_value *value)
|
||||
static struct codegen_var *code_generator_scope_get_variable(
|
||||
struct code_generator_scope *scope, const char *ident)
|
||||
{
|
||||
b_queue_push_back(&gen->c_ir_values, &value->v_entry);
|
||||
b_queue_iterator it;
|
||||
b_queue_foreach (&it, &scope->s_vars) {
|
||||
struct codegen_var *var
|
||||
= b_unbox(struct codegen_var, it.entry, v_entry);
|
||||
|
||||
if (!strcmp(var->v_ident->n_content->t_str, ident)) {
|
||||
return var;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct mie_value *codegen_pop_value(struct ivy_codegen *gen)
|
||||
static bool code_generator_scope_is_top_level(struct code_generator_scope *scope)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_pop_back(&gen->c_ir_values);
|
||||
switch (scope->s_type) {
|
||||
case CODE_GENERATOR_SCOPE_FUNC:
|
||||
case CODE_GENERATOR_SCOPE_UNIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void code_generator_scope_destroy(struct code_generator_scope *scope)
|
||||
{
|
||||
/* TODO clean up variables */
|
||||
free(scope);
|
||||
}
|
||||
|
||||
struct code_generator_scope *codegen_push_scope(struct ivy_codegen *gen)
|
||||
{
|
||||
struct code_generator_scope *scope = malloc(sizeof *scope);
|
||||
if (!scope) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(scope, 0x0, sizeof *scope);
|
||||
b_queue_push_back(&gen->c_scope, &scope->s_entry);
|
||||
|
||||
return scope;
|
||||
}
|
||||
|
||||
void codegen_pop_scope(struct ivy_codegen *gen)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_pop_back(&gen->c_scope);
|
||||
if (!entry) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct code_generator_scope *scope
|
||||
= b_unbox(struct code_generator_scope, entry, s_entry);
|
||||
code_generator_scope_destroy(scope);
|
||||
}
|
||||
|
||||
struct code_generator_scope *codegen_get_current_scope(struct ivy_codegen *gen)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_last(&gen->c_scope);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return b_unbox(struct mie_value, entry, v_entry);
|
||||
return b_unbox(struct code_generator_scope, entry, s_entry);
|
||||
}
|
||||
|
||||
struct codegen_value *codegen_value_create(
|
||||
struct ivy_ast_node *node, struct mie_value *val)
|
||||
{
|
||||
struct codegen_value *out = malloc(sizeof *out);
|
||||
if (!out) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(out, 0x0, sizeof *out);
|
||||
|
||||
out->v_node = node;
|
||||
out->v_value = val;
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void codegen_value_destroy(struct codegen_value *val)
|
||||
{
|
||||
free(val);
|
||||
}
|
||||
|
||||
void codegen_push_value(struct ivy_codegen *gen, struct codegen_value *value)
|
||||
{
|
||||
b_queue_push_back(&gen->c_values, &value->v_entry);
|
||||
}
|
||||
|
||||
struct codegen_value *codegen_pop_value(struct ivy_codegen *gen)
|
||||
{
|
||||
b_queue_entry *entry = b_queue_pop_back(&gen->c_values);
|
||||
if (!entry) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return b_unbox(struct codegen_value, entry, v_entry);
|
||||
}
|
||||
|
||||
struct codegen_var *codegen_resolve_variable(
|
||||
struct ivy_codegen *gen, const char *ident)
|
||||
{
|
||||
b_queue_entry *cur = b_queue_last(&gen->c_scope);
|
||||
while (cur) {
|
||||
struct code_generator_scope *scope
|
||||
= b_unbox(struct code_generator_scope, cur, s_entry);
|
||||
struct codegen_var *var
|
||||
= code_generator_scope_get_variable(scope, ident);
|
||||
|
||||
if (var) {
|
||||
return var;
|
||||
}
|
||||
|
||||
if (code_generator_scope_is_top_level(scope)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
enum ivy_status code_generator_scope_put_variable(
|
||||
struct code_generator_scope *scope, struct ivy_ast_ident_node *ident,
|
||||
struct mie_value *ptr)
|
||||
{
|
||||
struct codegen_var *var = malloc(sizeof *var);
|
||||
if (!var) {
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(var, 0x0, sizeof *var);
|
||||
|
||||
var->v_ident = ident;
|
||||
var->v_ptr = ptr;
|
||||
|
||||
b_queue_push_back(&scope->s_vars, &var->v_entry);
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static struct code_generator_state *get_current_generator_state(
|
||||
@@ -106,8 +247,6 @@ enum ivy_status ivy_codegen_create(struct ivy_codegen **out)
|
||||
|
||||
gen->c_ctx = mie_ctx_create();
|
||||
|
||||
codegen_push_generator(gen, CODE_GENERATOR_UNIT, NULL);
|
||||
|
||||
*out = gen;
|
||||
return IVY_OK;
|
||||
}
|
||||
@@ -164,14 +303,46 @@ struct mie_module *ivy_codegen_get_current_module(struct ivy_codegen *gen)
|
||||
return gen->c_module;
|
||||
}
|
||||
|
||||
static enum ivy_status pop_generator_recurse(struct ivy_codegen *gen)
|
||||
{
|
||||
while (1) {
|
||||
struct mie_value *value = NULL;
|
||||
codegen_pop_generator(gen, &value);
|
||||
struct code_generator_state *state
|
||||
= get_current_generator_state(gen);
|
||||
|
||||
if (!state || !state->s_gen->g_value_received) {
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
struct code_generator_result result
|
||||
= state->s_gen->g_value_received(gen, state, value);
|
||||
|
||||
if (!(result.r_flags & CODEGEN_POP_GENERATOR)) {
|
||||
return result.r_status;
|
||||
}
|
||||
}
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_codegen_push_node(
|
||||
struct ivy_codegen *gen, struct ivy_ast_node *node,
|
||||
enum ivy_ast_iteration_type node_type)
|
||||
struct ivy_codegen *gen, struct ivy_ast_node *node, size_t node_depth)
|
||||
{
|
||||
if (!gen->c_builder) {
|
||||
return IVY_ERR_BAD_STATE;
|
||||
}
|
||||
|
||||
if (b_queue_empty(&gen->c_state)) {
|
||||
const struct code_generator *generator
|
||||
= get_root_code_generator(node->n_type);
|
||||
if (!generator) {
|
||||
return IVY_ERR_BAD_SYNTAX;
|
||||
}
|
||||
|
||||
codegen_push_generator(gen, generator->g_type, 0);
|
||||
}
|
||||
|
||||
while (true) {
|
||||
struct code_generator_state *state
|
||||
= get_current_generator_state(gen);
|
||||
@@ -180,25 +351,32 @@ enum ivy_status ivy_codegen_push_node(
|
||||
return IVY_ERR_BAD_STATE;
|
||||
}
|
||||
|
||||
enum ivy_status status = IVY_OK;
|
||||
struct code_generator_result result = {};
|
||||
|
||||
if (!state->s_root) {
|
||||
state->s_root = node;
|
||||
state->s_depth = node_depth;
|
||||
} else if (node_depth <= state->s_depth) {
|
||||
status = pop_generator_recurse(gen);
|
||||
}
|
||||
|
||||
if (status != IVY_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
state = get_current_generator_state(gen);
|
||||
const struct code_generator *generator = state->s_gen;
|
||||
|
||||
code_generator_node_callback func;
|
||||
switch (node_type) {
|
||||
case IVY_AST_ITERATION_PRE:
|
||||
func = generator->g_node_generators_pre[node->n_type];
|
||||
break;
|
||||
case IVY_AST_ITERATION_POST:
|
||||
func = generator->g_node_generators_post[node->n_type];
|
||||
break;
|
||||
default:
|
||||
return IVY_ERR_INVALID_VALUE;
|
||||
}
|
||||
code_generator_node_callback func
|
||||
= generator->g_node_generators[node->n_type];
|
||||
|
||||
if (!func) {
|
||||
return IVY_ERR_INVALID_VALUE;
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
struct code_generator_result result = func(gen, state, node);
|
||||
result = func(gen, state, node, node_depth);
|
||||
|
||||
if (result.r_flags & CODEGEN_REPEAT_NODE) {
|
||||
continue;
|
||||
}
|
||||
@@ -208,3 +386,27 @@ enum ivy_status ivy_codegen_push_node(
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
enum ivy_status ivy_codegen_push_eof(struct ivy_codegen *gen)
|
||||
{
|
||||
struct code_generator_result result;
|
||||
|
||||
while (!b_queue_empty(&gen->c_state)) {
|
||||
struct mie_value *value = NULL;
|
||||
codegen_pop_generator(gen, &value);
|
||||
struct code_generator_state *state
|
||||
= get_current_generator_state(gen);
|
||||
|
||||
if (!state || !state->s_gen->g_value_received) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = state->s_gen->g_value_received(gen, state, value);
|
||||
|
||||
if (result.r_status != IVY_OK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result.r_status;
|
||||
}
|
||||
|
||||
@@ -23,10 +23,30 @@ struct ivy_ast_node;
|
||||
struct mie_value;
|
||||
struct mie_func;
|
||||
|
||||
struct codegen_value {
|
||||
b_queue_entry v_entry;
|
||||
struct ivy_ast_node *v_node;
|
||||
struct mie_value *v_value;
|
||||
};
|
||||
|
||||
struct codegen_var {
|
||||
b_queue_entry v_entry;
|
||||
struct ivy_ast_ident_node *v_ident;
|
||||
struct mie_value *v_ptr;
|
||||
};
|
||||
|
||||
enum code_generator_type {
|
||||
CODE_GENERATOR_NONE = 0,
|
||||
CODE_GENERATOR_UNIT,
|
||||
CODE_GENERATOR_EXPR,
|
||||
CODE_GENERATOR_VAR,
|
||||
};
|
||||
|
||||
enum code_generator_scope_type {
|
||||
CODE_GENERATOR_SCOPE_NONE = 0,
|
||||
CODE_GENERATOR_SCOPE_UNIT,
|
||||
CODE_GENERATOR_SCOPE_FUNC,
|
||||
CODE_GENERATOR_SCOPE_BLOCK,
|
||||
};
|
||||
|
||||
struct code_generator_result {
|
||||
@@ -34,6 +54,7 @@ struct code_generator_result {
|
||||
|
||||
enum code_generator_result_flags {
|
||||
CODEGEN_REPEAT_NODE = 0x01u,
|
||||
CODEGEN_POP_GENERATOR = 0x02u,
|
||||
} r_flags;
|
||||
};
|
||||
|
||||
@@ -42,11 +63,14 @@ struct code_generator_state;
|
||||
typedef enum ivy_status (*code_generator_state_init_callback)(
|
||||
struct ivy_codegen *, struct code_generator_state *);
|
||||
typedef enum ivy_status (*code_generator_state_fini_callback)(
|
||||
struct ivy_codegen *, struct code_generator_state *);
|
||||
struct ivy_codegen *, struct code_generator_state *, struct mie_value **);
|
||||
typedef struct code_generator_result (*code_generator_callback)(
|
||||
struct ivy_codegen *);
|
||||
typedef struct code_generator_result (*code_generator_node_callback)(
|
||||
struct ivy_codegen *, struct code_generator_state *, struct ivy_ast_node *);
|
||||
struct ivy_codegen *, struct code_generator_state *,
|
||||
struct ivy_ast_node *, size_t);
|
||||
typedef struct code_generator_result (*code_generator_value_received_callback)(
|
||||
struct ivy_codegen *, struct code_generator_state *, struct mie_value *);
|
||||
|
||||
struct code_generator {
|
||||
enum code_generator_type g_type;
|
||||
@@ -54,19 +78,29 @@ struct code_generator {
|
||||
|
||||
code_generator_state_init_callback g_state_init;
|
||||
code_generator_state_fini_callback g_state_fini;
|
||||
code_generator_node_callback g_node_generators_pre[IVY_AST_TYPE_COUNT];
|
||||
code_generator_node_callback g_node_generators_post[IVY_AST_TYPE_COUNT];
|
||||
code_generator_node_callback g_node_generators[IVY_AST_TYPE_COUNT];
|
||||
code_generator_value_received_callback g_value_received;
|
||||
};
|
||||
|
||||
struct code_generator_state {
|
||||
b_queue_entry s_entry;
|
||||
void *s_arg;
|
||||
const struct code_generator *s_gen;
|
||||
struct ivy_ast_node *s_root;
|
||||
size_t s_depth;
|
||||
};
|
||||
|
||||
struct code_generator_scope {
|
||||
enum code_generator_scope_type s_type;
|
||||
b_queue_entry s_entry;
|
||||
/* TODO turn this into a bst */
|
||||
b_queue s_vars;
|
||||
};
|
||||
|
||||
struct ivy_codegen {
|
||||
b_queue c_ir_values;
|
||||
b_queue c_values;
|
||||
b_queue c_state;
|
||||
b_queue c_scope;
|
||||
struct mie_builder *c_builder;
|
||||
struct mie_ctx *c_ctx;
|
||||
struct mie_module *c_module;
|
||||
@@ -74,12 +108,31 @@ struct ivy_codegen {
|
||||
|
||||
extern const struct code_generator *get_code_generator(
|
||||
enum code_generator_type type);
|
||||
extern const struct code_generator *get_root_code_generator(
|
||||
enum ivy_ast_node_type type);
|
||||
|
||||
extern enum ivy_status codegen_push_generator(
|
||||
struct ivy_codegen *gen, enum code_generator_type gen_type, void *arg);
|
||||
extern enum ivy_status codegen_pop_generator(struct ivy_codegen *gen);
|
||||
extern enum ivy_status codegen_pop_generator(
|
||||
struct ivy_codegen *gen, struct mie_value **result);
|
||||
|
||||
extern void codegen_push_value(struct ivy_codegen *gen, struct mie_value *value);
|
||||
extern struct mie_value *codegen_pop_value(struct ivy_codegen *gen);
|
||||
extern struct code_generator_scope *codegen_push_scope(struct ivy_codegen *gen);
|
||||
extern void codegen_pop_scope(struct ivy_codegen *gen);
|
||||
extern struct code_generator_scope *codegen_get_current_scope(
|
||||
struct ivy_codegen *gen);
|
||||
|
||||
extern struct codegen_value *codegen_value_create(
|
||||
struct ivy_ast_node *node, struct mie_value *val);
|
||||
extern void codegen_value_destroy(struct codegen_value *val);
|
||||
|
||||
extern void codegen_push_value(struct ivy_codegen *gen, struct codegen_value *val);
|
||||
extern struct codegen_value *codegen_pop_value(struct ivy_codegen *gen);
|
||||
|
||||
extern struct codegen_var *codegen_resolve_variable(
|
||||
struct ivy_codegen *gen, const char *ident);
|
||||
|
||||
extern enum ivy_status code_generator_scope_put_variable(
|
||||
struct code_generator_scope *scope, struct ivy_ast_ident_node *ident,
|
||||
struct mie_value *ptr);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -2,15 +2,32 @@
|
||||
#include "codegen.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
enum expr_item_type {
|
||||
EXPR_NONE = 0,
|
||||
EXPR_OPERATOR,
|
||||
EXPR_OPERAND,
|
||||
};
|
||||
|
||||
struct expr_item {
|
||||
b_queue_entry i_entry;
|
||||
enum expr_item_type i_type;
|
||||
struct ivy_ast_node *i_node;
|
||||
struct mie_value *i_value;
|
||||
};
|
||||
|
||||
struct expr_codegen_state {
|
||||
struct code_generator_state s_base;
|
||||
struct ivy_ast_node *s_expr_root;
|
||||
b_queue s_item_queue;
|
||||
};
|
||||
|
||||
#if 0
|
||||
static struct code_generator_result check_expr_root(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node)
|
||||
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) {
|
||||
@@ -19,23 +36,57 @@ static struct code_generator_result check_expr_root(
|
||||
|
||||
return CODEGEN_RESULT_OK(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum ivy_status push_operand(
|
||||
struct expr_codegen_state *expr, struct ivy_ast_node *node,
|
||||
struct mie_value *value)
|
||||
{
|
||||
struct expr_item *item = malloc(sizeof *item);
|
||||
if (!item) {
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(item, 0x0, sizeof *item);
|
||||
|
||||
item->i_type = EXPR_OPERAND;
|
||||
item->i_node = node;
|
||||
item->i_value = value;
|
||||
|
||||
b_queue_push_back(&expr->s_item_queue, &item->i_entry);
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status push_operator(
|
||||
struct expr_codegen_state *expr, struct ivy_ast_node *node)
|
||||
{
|
||||
struct expr_item *item = malloc(sizeof *item);
|
||||
if (!item) {
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
memset(item, 0x0, sizeof *item);
|
||||
|
||||
item->i_type = EXPR_OPERATOR;
|
||||
item->i_node = node;
|
||||
|
||||
b_queue_push_back(&expr->s_item_queue, &item->i_entry);
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static struct code_generator_result gen_int(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node)
|
||||
struct ivy_ast_node *node, size_t depth)
|
||||
{
|
||||
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);
|
||||
enum ivy_status status = push_operand(expr, node, value);
|
||||
if (status != IVY_OK) {
|
||||
return CODEGEN_RESULT_ERR(status);
|
||||
}
|
||||
|
||||
return CODEGEN_RESULT_OK(0);
|
||||
@@ -43,53 +94,148 @@ static struct code_generator_result gen_int(
|
||||
|
||||
static struct code_generator_result gen_op(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node)
|
||||
struct ivy_ast_node *node, size_t depth)
|
||||
{
|
||||
struct expr_codegen_state *expr = (struct expr_codegen_state *)state;
|
||||
|
||||
debug_printf("codegen: got op\n");
|
||||
enum ivy_status status = push_operator(expr, node);
|
||||
if (status != IVY_OK) {
|
||||
return CODEGEN_RESULT_ERR(status);
|
||||
}
|
||||
|
||||
return CODEGEN_RESULT_OK(0);
|
||||
}
|
||||
|
||||
static struct code_generator_result gen_var_reference(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node, size_t depth)
|
||||
{
|
||||
debug_printf("codegen: got var reference\n");
|
||||
|
||||
struct expr_codegen_state *expr = (struct expr_codegen_state *)state;
|
||||
struct mie_value *var_ptr = NULL;
|
||||
|
||||
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 is a local variable */
|
||||
var_ptr = var->v_ptr;
|
||||
} else {
|
||||
/* this is a global variable, and needs to be loaded via a data ptr */
|
||||
/* TODO */
|
||||
}
|
||||
|
||||
struct mie_type *id = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID);
|
||||
struct mie_value *var_value
|
||||
= mie_builder_load(gen->c_builder, id, var_ptr, NULL);
|
||||
|
||||
enum ivy_status status = push_operand(expr, node, var_value);
|
||||
|
||||
if (status != IVY_OK) {
|
||||
return CODEGEN_RESULT_ERR(status);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
struct codegen_value *left = codegen_pop_value(gen);
|
||||
struct codegen_value *right = codegen_pop_value(gen);
|
||||
|
||||
if (!left || !right) {
|
||||
return CODEGEN_RESULT_ERR(IVY_ERR_INVALID_VALUE);
|
||||
}
|
||||
|
||||
struct mie_value *left_value = left->v_value;
|
||||
struct mie_value *right_value = right->v_value;
|
||||
|
||||
struct mie_type *left_type = mie_value_get_type(left_value);
|
||||
struct mie_type *right_type = mie_value_get_type(right_value);
|
||||
struct mie_type *i32 = mie_ctx_get_int_type(gen->c_ctx, 32);
|
||||
|
||||
if (left_type && left_type->t_id == MIE_TYPE_PTR) {
|
||||
left_value
|
||||
= mie_builder_load(gen->c_builder, i32, left_value, NULL);
|
||||
}
|
||||
|
||||
if (right_type && right_type->t_id == MIE_TYPE_PTR) {
|
||||
right_value = mie_builder_load(
|
||||
gen->c_builder, i32, right_value, NULL);
|
||||
}
|
||||
|
||||
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);
|
||||
case IVY_OP_ADD:
|
||||
op_instr = mie_builder_add(
|
||||
gen->c_builder, left_value, right_value, "addtmp");
|
||||
break;
|
||||
case IVY_OP_SUBTRACT:
|
||||
op_instr = mie_builder_sub(
|
||||
gen->c_builder, left_value, right_value, "subtmp");
|
||||
break;
|
||||
case IVY_OP_MULTIPLY:
|
||||
op_instr = mie_builder_mul(
|
||||
gen->c_builder, left_value, right_value, "multmp");
|
||||
break;
|
||||
case IVY_OP_DIVIDE:
|
||||
op_instr = mie_builder_div(
|
||||
gen->c_builder, left_value, right_value, "divtmp");
|
||||
break;
|
||||
default:
|
||||
mie_value_destroy(left->v_value);
|
||||
mie_value_destroy(right->v_value);
|
||||
codegen_value_destroy(left);
|
||||
codegen_value_destroy(right);
|
||||
return CODEGEN_RESULT_ERR(IVY_ERR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (!op_instr) {
|
||||
mie_value_destroy(left);
|
||||
mie_value_destroy(right);
|
||||
mie_value_destroy(left->v_value);
|
||||
mie_value_destroy(right->v_value);
|
||||
codegen_value_destroy(left);
|
||||
codegen_value_destroy(right);
|
||||
return CODEGEN_RESULT_ERR(IVY_ERR_NO_MEMORY);
|
||||
}
|
||||
|
||||
codegen_push_value(gen, op_instr);
|
||||
struct codegen_value *op_value = codegen_value_create(node, op_instr);
|
||||
codegen_push_value(gen, op_value);
|
||||
|
||||
if (node == expr->s_expr_root) {
|
||||
codegen_pop_generator(gen);
|
||||
@@ -98,6 +244,18 @@ static struct code_generator_result gen_op(
|
||||
return CODEGEN_RESULT_OK(0);
|
||||
}
|
||||
|
||||
static struct code_generator_result cancel_expr(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node)
|
||||
{
|
||||
debug_printf(
|
||||
"codegen: expression stopped by %s\n",
|
||||
ivy_ast_node_type_to_string(node->n_type));
|
||||
codegen_pop_generator(gen);
|
||||
return CODEGEN_RESULT_OK(CODEGEN_REPEAT_NODE);
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum ivy_status state_init(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state)
|
||||
{
|
||||
@@ -106,23 +264,89 @@ static enum ivy_status state_init(
|
||||
}
|
||||
|
||||
static enum ivy_status state_fini(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state)
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct mie_value **result)
|
||||
{
|
||||
debug_printf("codegen: end of expression\n");
|
||||
|
||||
struct expr_codegen_state *expr = (struct expr_codegen_state *)state;
|
||||
b_queue stack = B_QUEUE_INIT;
|
||||
|
||||
b_queue_entry *cur = NULL;
|
||||
while ((cur = b_queue_pop_back(&expr->s_item_queue))) {
|
||||
struct expr_item *item = b_unbox(struct expr_item, cur, i_entry);
|
||||
|
||||
if (item->i_type == EXPR_OPERAND) {
|
||||
b_queue_push_back(&stack, &item->i_entry);
|
||||
continue;
|
||||
}
|
||||
|
||||
struct ivy_ast_op_node *op = (struct ivy_ast_op_node *)item->i_node;
|
||||
b_queue_entry *left_entry = b_queue_pop_back(&stack);
|
||||
b_queue_entry *right_entry = b_queue_pop_back(&stack);
|
||||
struct expr_item *left
|
||||
= b_unbox(struct expr_item, left_entry, i_entry);
|
||||
struct expr_item *right
|
||||
= b_unbox(struct expr_item, right_entry, i_entry);
|
||||
|
||||
struct mie_value *op_value = NULL;
|
||||
|
||||
switch (op->n_op->op_id) {
|
||||
case IVY_OP_ADD:
|
||||
op_value = mie_builder_add(
|
||||
gen->c_builder, left->i_value, right->i_value,
|
||||
"addtmp");
|
||||
break;
|
||||
case IVY_OP_SUBTRACT:
|
||||
op_value = mie_builder_sub(
|
||||
gen->c_builder, left->i_value, right->i_value,
|
||||
"subtmp");
|
||||
break;
|
||||
case IVY_OP_MULTIPLY:
|
||||
op_value = mie_builder_mul(
|
||||
gen->c_builder, left->i_value, right->i_value,
|
||||
"multmp");
|
||||
break;
|
||||
case IVY_OP_DIVIDE:
|
||||
op_value = mie_builder_div(
|
||||
gen->c_builder, left->i_value, right->i_value,
|
||||
"divtmp");
|
||||
break;
|
||||
default:
|
||||
return IVY_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
if (!op_value) {
|
||||
return IVY_ERR_NO_MEMORY;
|
||||
}
|
||||
|
||||
free(left);
|
||||
free(right);
|
||||
|
||||
item->i_value = op_value;
|
||||
b_queue_push_back(&stack, &item->i_entry);
|
||||
}
|
||||
|
||||
cur = b_queue_pop_back(&stack);
|
||||
if (!cur) {
|
||||
return IVY_ERR_INTERNAL_FAILURE;
|
||||
}
|
||||
|
||||
struct expr_item *result_item = b_unbox(struct expr_item, cur, i_entry);
|
||||
*result = result_item->i_value;
|
||||
free(result_item);
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
struct code_generator expr_generator = {
|
||||
.g_type = CODE_GENERATOR_UNIT,
|
||||
.g_type = CODE_GENERATOR_EXPR,
|
||||
.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 = {
|
||||
.g_node_generators = {
|
||||
[IVY_AST_INT] = gen_int,
|
||||
[IVY_AST_OP] = gen_op,
|
||||
[IVY_AST_IDENT] = gen_var_reference,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -2,14 +2,25 @@
|
||||
|
||||
extern const struct code_generator unit_generator;
|
||||
extern const struct code_generator expr_generator;
|
||||
extern const struct code_generator var_generator;
|
||||
|
||||
static const struct code_generator *code_generators[] = {
|
||||
[CODE_GENERATOR_UNIT] = &unit_generator,
|
||||
[CODE_GENERATOR_EXPR] = &expr_generator,
|
||||
[CODE_GENERATOR_VAR] = &var_generator,
|
||||
};
|
||||
static const size_t nr_code_generators
|
||||
= sizeof code_generators / sizeof code_generators[0];
|
||||
|
||||
static const struct code_generator *root_code_generators[] = {
|
||||
[IVY_AST_UNIT] = &unit_generator,
|
||||
[IVY_AST_OP] = &expr_generator,
|
||||
[IVY_AST_INT] = &expr_generator,
|
||||
[IVY_AST_IDENT] = &expr_generator,
|
||||
};
|
||||
static const size_t nr_root_code_generators
|
||||
= sizeof root_code_generators / sizeof root_code_generators[0];
|
||||
|
||||
const struct code_generator *get_code_generator(enum code_generator_type type)
|
||||
{
|
||||
if (type >= nr_code_generators) {
|
||||
@@ -18,3 +29,12 @@ const struct code_generator *get_code_generator(enum code_generator_type type)
|
||||
|
||||
return code_generators[type];
|
||||
}
|
||||
|
||||
const struct code_generator *get_root_code_generator(enum ivy_ast_node_type type)
|
||||
{
|
||||
if (type >= nr_root_code_generators) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return root_code_generators[type];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
|
||||
struct unit_codegen_state {
|
||||
struct code_generator_state s_base;
|
||||
struct code_generator_scope *s_scope;
|
||||
/* function for top-level statements */
|
||||
// struct mie_block *s_immediate_alloca;
|
||||
struct mie_func *s_immediate;
|
||||
};
|
||||
|
||||
@@ -27,7 +29,18 @@ static enum ivy_status switch_to_immediate_func(
|
||||
}
|
||||
|
||||
struct mie_block *block = mie_func_get_last_block(unit->s_immediate);
|
||||
if (!block || mie_block_is_terminated(block)) {
|
||||
if (!block) {
|
||||
#if 0
|
||||
unit->s_immediate_alloca
|
||||
= mie_func_create_block(unit->s_immediate, "alloca");
|
||||
mie_func_insert_block(
|
||||
unit->s_immediate, unit->s_immediate_alloca, NULL);
|
||||
#endif
|
||||
block = mie_func_create_block(unit->s_immediate, "entry");
|
||||
mie_func_insert_block(unit->s_immediate, block, NULL);
|
||||
}
|
||||
|
||||
if (mie_block_is_terminated(block)) {
|
||||
block = mie_func_create_block(unit->s_immediate, NULL);
|
||||
mie_func_insert_block(unit->s_immediate, block, NULL);
|
||||
}
|
||||
@@ -37,9 +50,25 @@ static enum ivy_status switch_to_immediate_func(
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static enum ivy_status switch_to_immediate_alloca(
|
||||
struct ivy_codegen *gen, struct unit_codegen_state *unit)
|
||||
{
|
||||
enum ivy_status status = switch_to_immediate_func(gen, unit);
|
||||
|
||||
if (status != IVY_OK) {
|
||||
return status;
|
||||
}
|
||||
|
||||
mie_builder_set_insert_point(gen->c_builder, unit->s_immediate_alloca);
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
static struct code_generator_result gen_expr(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node)
|
||||
struct ivy_ast_node *node, size_t depth)
|
||||
{
|
||||
struct unit_codegen_state *unit = (struct unit_codegen_state *)state;
|
||||
struct mie_builder *builder = gen->c_builder;
|
||||
@@ -58,11 +87,91 @@ static struct code_generator_result gen_expr(
|
||||
return CODEGEN_RESULT_OK(CODEGEN_REPEAT_NODE);
|
||||
}
|
||||
|
||||
static struct code_generator_result gen_var_declaration(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node, size_t depth)
|
||||
{
|
||||
struct unit_codegen_state *unit = (struct unit_codegen_state *)state;
|
||||
struct mie_builder *builder = gen->c_builder;
|
||||
struct mie_func *current = mie_builder_get_current_func(builder);
|
||||
|
||||
enum ivy_status status = IVY_OK;
|
||||
if (!current || current != unit->s_immediate) {
|
||||
status = switch_to_immediate_func(gen, unit);
|
||||
}
|
||||
|
||||
if (status != IVY_OK) {
|
||||
return CODEGEN_RESULT_ERR(status);
|
||||
}
|
||||
|
||||
codegen_push_generator(gen, CODE_GENERATOR_VAR, NULL);
|
||||
return CODEGEN_RESULT_OK(CODEGEN_REPEAT_NODE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static struct code_generator_result gen_var_declaration(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct ivy_ast_node *node)
|
||||
{
|
||||
struct unit_codegen_state *unit = (struct unit_codegen_state *)state;
|
||||
struct mie_builder *builder = gen->c_builder;
|
||||
|
||||
struct mie_block *current_block
|
||||
= mie_builder_get_current_block(gen->c_builder);
|
||||
|
||||
enum ivy_status status = IVY_OK;
|
||||
if (!current_block || current_block != unit->s_immediate_alloca) {
|
||||
status = switch_to_immediate_alloca(gen, unit);
|
||||
}
|
||||
|
||||
struct codegen_value *value = codegen_pop_value(gen);
|
||||
struct codegen_value *dest = codegen_pop_value(gen);
|
||||
|
||||
if (!dest) {
|
||||
return CODEGEN_RESULT_ERR(IVY_ERR_BAD_SYNTAX);
|
||||
}
|
||||
|
||||
struct mie_type *id_type = mie_ctx_get_type(gen->c_ctx, MIE_TYPE_ID);
|
||||
struct mie_value *var_ptr = mie_builder_alloca(builder, id_type, NULL);
|
||||
|
||||
if (value) {
|
||||
mie_builder_store(builder, value->v_value, var_ptr);
|
||||
}
|
||||
|
||||
code_generator_scope_put_variable(
|
||||
unit->s_scope, (struct ivy_ast_ident_node *)dest->v_node, var_ptr);
|
||||
|
||||
return CODEGEN_RESULT_OK(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
static enum ivy_status state_init(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state)
|
||||
{
|
||||
struct unit_codegen_state *unit = (struct unit_codegen_state *)state;
|
||||
unit->s_scope = codegen_push_scope(gen);
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
static enum ivy_status state_fini(
|
||||
struct ivy_codegen *gen, struct code_generator_state *state,
|
||||
struct mie_value **result)
|
||||
{
|
||||
codegen_pop_scope(gen);
|
||||
|
||||
return IVY_OK;
|
||||
}
|
||||
|
||||
struct code_generator unit_generator = {
|
||||
.g_type = CODE_GENERATOR_UNIT,
|
||||
.g_state_size = sizeof(struct unit_codegen_state),
|
||||
.g_node_generators_pre = {
|
||||
.g_state_init = state_init,
|
||||
.g_state_fini = state_fini,
|
||||
.g_node_generators = {
|
||||
[IVY_AST_INT] = gen_expr,
|
||||
[IVY_AST_OP] = gen_expr,
|
||||
[IVY_AST_IDENT] = gen_expr,
|
||||
[IVY_AST_VAR] = gen_var_declaration,
|
||||
},
|
||||
};
|
||||
|
||||
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,
|
||||
},
|
||||
};
|
||||
@@ -339,6 +339,7 @@ IVY_API struct ivy_ast_node *ivy_parser_dequeue_node(struct ivy_parser *parser);
|
||||
IVY_API enum ivy_status ivy_parser_push_token(
|
||||
struct ivy_parser *parser, struct ivy_token *tok);
|
||||
|
||||
IVY_API struct ivy_ast_node *ivy_ast_node_create(enum ivy_ast_node_type type);
|
||||
IVY_API enum ivy_status ivy_ast_node_iterate(
|
||||
struct ivy_ast_node *node, struct ivy_ast_node_iterator *it,
|
||||
ivy_ast_node_iteration_callback callback, void *arg);
|
||||
@@ -347,4 +348,9 @@ IVY_API void ivy_ast_node_destroy(struct ivy_ast_node *node);
|
||||
|
||||
IVY_API const char *ivy_ast_node_type_to_string(enum ivy_ast_node_type v);
|
||||
|
||||
IVY_API void ivy_ast_unit_add_node(
|
||||
struct ivy_ast_unit_node *unit, struct ivy_ast_node *child);
|
||||
IVY_API struct ivy_ast_node *ivy_ast_unit_dequeue_node(
|
||||
struct ivy_ast_unit_node *unit);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <ivy/misc.h>
|
||||
#include <ivy/status.h>
|
||||
#include <stddef.h>
|
||||
|
||||
struct ivy_codegen;
|
||||
struct ivy_ast_node;
|
||||
@@ -19,7 +20,7 @@ IVY_API enum ivy_status ivy_codegen_end_module(
|
||||
IVY_API struct mie_module *ivy_codegen_get_current_module(struct ivy_codegen *gen);
|
||||
|
||||
IVY_API enum ivy_status ivy_codegen_push_node(
|
||||
struct ivy_codegen *gen, struct ivy_ast_node *node,
|
||||
enum ivy_ast_iteration_type node_type);
|
||||
struct ivy_codegen *gen, struct ivy_ast_node *node, size_t node_depth);
|
||||
IVY_API enum ivy_status ivy_codegen_push_eof(struct ivy_codegen *gen);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user