#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; ichildren.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; ichildren.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(); } } }