moka/lib/compiler.c

117 lines
3.9 KiB
C

#include "compiler.h"
void compiler_init(struct compiler* self,
struct status* status)
{
assert(self);
self->status = status;
}
void compiler_free(struct compiler* self)
{
assert(self);
}
void compiler_compile(struct compiler* self,
struct node* node,
struct prog* prog,
struct symtable* symtable)
{
assert(self); assert(node); assert(prog);
switch (node->kind)
{
case NODE_ROOT: {
for (size_t i=0; i<node->children.size; i++)
{
struct node* child = node->children.data[i];
compiler_compile(self, child, prog, symtable);
}
} break;
case NODE_CALL: {
for (size_t i=0; i<node->children.size - 1; i++)
{
// size_t k = node->children.size - 1 - i;
// struct node* child = node->children.data[k];
// compiler_compile(self, child, prog, symtable);
size_t k = node->children.size - 1 - i;
struct node* child = node->children.data[k];
struct value* val = malloc(sizeof(struct value));
value_init_lazy(val, child, child->line);
size_t addr = prog_add_new_value(prog, val);
prog_add_instruction(prog, OP_PUSH, addr);
}
struct node* child = node->children.data[0];
compiler_compile(self, child, prog, symtable);
prog_add_instruction(prog, OP_CALL, node->children.size - 1);
} break;
case NODE_INT: {
struct value* value = malloc(sizeof(struct value));
int val = atoi(node->token->value);
value_init_int(value, val, node->line);
ssize_t addr = prog_add_new_value(prog, value);
prog_add_instruction(prog, OP_PUSH, addr);
} break;
case NODE_FLOAT: {
struct value* value = malloc(sizeof(struct value));
float val = atof(node->token->value);
value_init_float(value, val, node->line);
ssize_t addr = prog_add_new_value(prog, value);
prog_add_instruction(prog, OP_PUSH, addr);
} break;
case NODE_BOOL: {
struct value* value = malloc(sizeof(struct value));
bool val = strcmp("true", node->token->value) == 0;
value_init_bool(value, val, node->line);
ssize_t addr = prog_add_new_value(prog, value);
prog_add_instruction(prog, OP_PUSH, addr);
} break;
case NODE_STRING: {
struct value* value = malloc(sizeof(struct value));
value_init_string(value, node->token->value, node->line);
ssize_t addr = prog_add_new_value(prog, value);
prog_add_instruction(prog, OP_PUSH, addr);
} break;
case NODE_SYMBOL: {
struct value* value = malloc(sizeof(struct value));
value_init_symbol(value, node->token->value, node->line);
ssize_t addr = prog_add_new_value(prog, value);
prog_add_instruction(prog, OP_PUSH, addr);
} break;
case NODE_IDENT: {
struct entry const* entry = symtable_try_get(symtable,
node->token->value);
if (!entry)
{
status_push(self->status, STATUS_ERROR, node->line,
"undefined <%s>", node->token->value);
return;
}
if (entry->is_local)
{
prog_add_instruction(prog, OP_LOCAL_LOAD, entry->addr);
}
else
{
prog_add_instruction(prog, OP_GLOBAL_LOAD, entry->addr);
}
} break;
default: {
fprintf(stderr, "cannot compile node %s\n",
NodeKindStr[node->kind]);
abort();
} break;
}
}