117 lines
3.0 KiB
C
117 lines
3.0 KiB
C
|
#include "compiler.h"
|
||
|
|
||
|
void compiler_init(compiler_t* self, module_t* module)
|
||
|
{
|
||
|
assert(self);
|
||
|
err_init(&self->err);
|
||
|
self->module = module;
|
||
|
}
|
||
|
|
||
|
void compiler_free(compiler_t* self)
|
||
|
{
|
||
|
assert(self);
|
||
|
err_free(&self->err);
|
||
|
}
|
||
|
|
||
|
void compiler_compile(compiler_t* self,
|
||
|
node_t* node,
|
||
|
prog_t* prog)
|
||
|
{
|
||
|
assert(self);
|
||
|
assert(node);
|
||
|
assert(prog);
|
||
|
|
||
|
if (!err_is_ok(&self->err))
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
switch (node->kind)
|
||
|
{
|
||
|
case NODE_ASSERT_EQ: {
|
||
|
compiler_compile(self, node->children.data[0], prog);
|
||
|
prog_add_instr(prog, OP_ASSERT_EQ, CCM_NO_PARAM);
|
||
|
} break;
|
||
|
|
||
|
case NODE_ASSERT_NE: {
|
||
|
compiler_compile(self, node->children.data[0], prog);
|
||
|
prog_add_instr(prog, OP_ASSERT_NE, CCM_NO_PARAM);
|
||
|
} break;
|
||
|
|
||
|
case NODE_MODULE: {
|
||
|
for (size_t i=0; i<node->children.size; i++)
|
||
|
{
|
||
|
compiler_compile(self,
|
||
|
node->children.data[i],
|
||
|
prog);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case NODE_NUM: {
|
||
|
size_t id = prog_add_new_constant(
|
||
|
prog,
|
||
|
ccm_to_num(&self->module->ccm,
|
||
|
atof(node->value),
|
||
|
node->line)
|
||
|
);
|
||
|
|
||
|
prog_add_instr(prog, OP_PUSH, id);
|
||
|
} break;
|
||
|
|
||
|
case NODE_TUPLE: {
|
||
|
for (size_t i=0; i<node->children.size; i++)
|
||
|
{
|
||
|
size_t k = node->children.size - 1 - i;
|
||
|
|
||
|
compiler_compile(self,
|
||
|
node->children.data[k],
|
||
|
prog);
|
||
|
}
|
||
|
|
||
|
prog_add_instr(prog, OP_MK_TUPLE, node->children.size);
|
||
|
} break;
|
||
|
|
||
|
case NODE_SUB: {
|
||
|
compiler_compile(self, node->children.data[0], prog);
|
||
|
|
||
|
if (node->children.size == 2)
|
||
|
{
|
||
|
compiler_compile(self, node->children.data[1], prog);
|
||
|
prog_add_instr(prog, OP_SUB, CCM_NO_PARAM);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
prog_add_instr(prog, OP_USUB, CCM_NO_PARAM);
|
||
|
}
|
||
|
} break;
|
||
|
|
||
|
case NODE_ADD:
|
||
|
case NODE_MUL:
|
||
|
case NODE_DIV:
|
||
|
case NODE_MOD:
|
||
|
case NODE_POW: {
|
||
|
compiler_compile(self, node->children.data[0], prog);
|
||
|
compiler_compile(self, node->children.data[1], prog);
|
||
|
Opcode op;
|
||
|
|
||
|
switch (node->kind)
|
||
|
{
|
||
|
case NODE_ADD: op = OP_ADD; break;
|
||
|
case NODE_MUL: op = OP_MUL; break;
|
||
|
case NODE_DIV: op = OP_DIV; break;
|
||
|
case NODE_MOD: op = OP_MOD; break;
|
||
|
case NODE_POW: op = OP_POW; break;
|
||
|
default: abort();
|
||
|
}
|
||
|
|
||
|
prog_add_instr(prog, op, CCM_NO_PARAM);
|
||
|
} break;
|
||
|
|
||
|
default: {
|
||
|
fprintf(stderr, "cannot compile node %s\n",
|
||
|
NodeKindStr[node->kind]);
|
||
|
abort();
|
||
|
}
|
||
|
}
|
||
|
}
|