roza/lib/compiler.c

148 lines
3.6 KiB
C

#include "compiler.h"
#include "lib/commons.h"
void compiler_init(compiler_t* compiler, mod_t* mod, tysy_t* tysy, err_t* err)
{
assert(compiler);
assert(err);
compiler->mod = mod;
compiler->tysy = tysy;
compiler->err = err;
}
void compiler_free(compiler_t* compiler)
{
assert(compiler);
}
void compiler_run(compiler_t* compiler, node_t* node)
{
assert(compiler);
assert(node);
switch (node->type)
{
case NODE_MOD: {
for (size_t i=0; i<node->children.size; i++)
{
compiler_run(compiler, (node_t*) node->children.data[i]);
}
} break;
case NODE_NUM: {
double value = atof(node->value.data);
value_t* val = tysy_new_num(compiler->tysy, value, node->line);
Opcode op = OP_PUSH;
param_t param = (param_t) mod_push_new_value(compiler->mod, val);
mod_push_instr(compiler->mod, op, param);
} break;
case NODE_BOOL: {
int value = strcmp(node->value.data, "true") == 0;
value_t* val = tysy_new_bool(compiler->tysy, value, node->line);
Opcode op = OP_PUSH;
param_t param = (param_t) mod_push_new_value(compiler->mod, val);
mod_push_instr(compiler->mod, op, param);
} break;
case NODE_STR: {
char* value = node->value.data;
value_t* val = tysy_new_str(compiler->tysy, value, node->line);
Opcode op = OP_PUSH;
param_t param = (param_t) mod_push_new_value(compiler->mod, val);
mod_push_instr(compiler->mod, op, param);
} break;
case NODE_ASSERT: {
assert(node->children.size == 1);
compiler_run(compiler, node_child(node, 0));
mod_push_instr(compiler->mod, OP_ASSERT, RZ_NO_PARAM);
} break;
case NODE_NE:
case NODE_EQ: {
assert(node->children.size == 2);
for (size_t i=0; i<node->children.size; i++)
{
compiler_run(compiler, node_child(node, i));
}
mod_push_instr(compiler->mod,
node->type == NODE_EQ ? OP_EQ : OP_NE, RZ_NO_PARAM);
} break;
case NODE_LT:
case NODE_LE:
case NODE_GT:
case NODE_GE: {
assert(node->children.size == 2);
for (size_t i=0; i<node->children.size; i++)
{
compiler_run(compiler, node_child(node, i));
}
Opcode op;
switch (node->type)
{
case NODE_LT: op = OP_LT; break;
case NODE_LE: op = OP_LE; break;
case NODE_GT: op = OP_GT; break;
case NODE_GE: op = OP_GE; break;
default: assert(0);
}
mod_push_instr(compiler->mod, op, RZ_NO_PARAM);
} break;
case NODE_ADD:
case NODE_SUB:
case NODE_MUL:
case NODE_DIV:
case NODE_MODULO:
case NODE_POW: {
for (size_t i=0; i<node->children.size; i++)
{
compiler_run(compiler, node_child(node, i));
}
Opcode op;
if (node->type == NODE_SUB
&& node->children.size == 1)
{
op = OP_USUB;
}
else
{
switch (node->type)
{
case NODE_ADD: op = OP_ADD; break;
case NODE_SUB: op = OP_SUB; break;
case NODE_MUL: op = OP_MUL; break;
case NODE_DIV: op = OP_DIV; break;
case NODE_MODULO: op = OP_MODULO; break;
case NODE_POW: op = OP_POW; break;
default: assert(0);
}
}
mod_push_instr(compiler->mod, op, RZ_NO_PARAM);
} break;
default: {
fprintf(stderr, "Cannot compile unknown node '%s'",
NodeTypeStr[node->type]);
abort();
} break;
}
}