|
|
|
@ -2,6 +2,7 @@
|
|
|
|
|
#include "commons.h"
|
|
|
|
|
#include "node.h"
|
|
|
|
|
#include "opcodes.h"
|
|
|
|
|
#include "program.h"
|
|
|
|
|
#include "syms.h"
|
|
|
|
|
#include "value.h"
|
|
|
|
|
#include "vec.h"
|
|
|
|
@ -11,6 +12,7 @@ void compiler_init(struct compiler* self, struct syms* syms)
|
|
|
|
|
assert(self);
|
|
|
|
|
self->syms = syms;
|
|
|
|
|
memset(self->error_msg, 0, GUX_STR_SIZE);
|
|
|
|
|
self->stack_size = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void compiler_free(struct compiler* self)
|
|
|
|
@ -28,6 +30,26 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
|
|
|
|
|
switch (node->type)
|
|
|
|
|
{
|
|
|
|
|
case NODE_BLOCK: {
|
|
|
|
|
int stack_base = self->stack_size;
|
|
|
|
|
|
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
|
{
|
|
|
|
|
if (compiler_compile(self, node->children.data[i], program) != 0)
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int top = self->stack_size - stack_base;
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<top; i++)
|
|
|
|
|
{
|
|
|
|
|
compiler_gen_instr(self, program, OP_POP, NO_PARAM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_ASSIGN: {
|
|
|
|
|
struct node* ident = node->children.data[0];
|
|
|
|
|
struct node* expr = node->children.data[1];
|
|
|
|
@ -40,7 +62,7 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
program_push_instr(program, OP_STORE, entry->addr);
|
|
|
|
|
compiler_gen_instr(self, program, OP_STORE, entry->addr);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_IDENT: {
|
|
|
|
@ -56,7 +78,7 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
program_push_instr(program, OP_LOAD, entry->addr);
|
|
|
|
|
compiler_gen_instr(self, program, OP_LOAD, entry->addr);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_CONSTDECL:
|
|
|
|
@ -76,7 +98,7 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
node);
|
|
|
|
|
assert(entry);
|
|
|
|
|
|
|
|
|
|
program_push_instr(program, OP_STORE, entry->addr);
|
|
|
|
|
compiler_gen_instr(self, program, OP_STORE, entry->addr);
|
|
|
|
|
} break;
|
|
|
|
|
case NODE_BOOL: {
|
|
|
|
|
struct value* val = malloc(sizeof(struct value));
|
|
|
|
@ -84,28 +106,28 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
strcmp(node->value, "true") == 0 ? 1 : 0,
|
|
|
|
|
node->line);
|
|
|
|
|
size_t addr = program_push_constant(program, val);
|
|
|
|
|
program_push_instr(program, OP_PUSH, addr);
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_INT: {
|
|
|
|
|
struct value* val = malloc(sizeof(struct value));
|
|
|
|
|
value_init_int(val, atoi(node->value), node->line);
|
|
|
|
|
size_t addr = program_push_constant(program, val);
|
|
|
|
|
program_push_instr(program, OP_PUSH, addr);
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_FLOAT: {
|
|
|
|
|
struct value* val = malloc(sizeof(struct value));
|
|
|
|
|
value_init_float(val, atof(node->value), node->line);
|
|
|
|
|
size_t addr = program_push_constant(program, val);
|
|
|
|
|
program_push_instr(program, OP_PUSH, addr);
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_STRING: {
|
|
|
|
|
struct value* val = malloc(sizeof(struct value));
|
|
|
|
|
value_init_string(val, node->value, node->line);
|
|
|
|
|
size_t addr = program_push_constant(program, val);
|
|
|
|
|
program_push_instr(program, OP_PUSH, addr);
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_ASSERT: {
|
|
|
|
@ -114,21 +136,21 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t brt = program_push_instr(program, OP_BRT, NO_PARAM);
|
|
|
|
|
program_push_instr(program, OP_PUSH, GUX_RET_ASSERT);
|
|
|
|
|
size_t halt = program_push_instr(program, OP_HALT, node->line);
|
|
|
|
|
size_t brt = compiler_gen_instr(self, program, OP_BRT, NO_PARAM);
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH, GUX_RET_ASSERT);
|
|
|
|
|
size_t halt = compiler_gen_instr(self, program, OP_HALT, node->line);
|
|
|
|
|
|
|
|
|
|
struct instruction* instr = program->instructions.data[brt];
|
|
|
|
|
instr->param = halt + 1;
|
|
|
|
|
|
|
|
|
|
if (halt + 1 >= program->instructions.size)
|
|
|
|
|
{
|
|
|
|
|
program_push_instr(program, OP_NOP, NO_PARAM);
|
|
|
|
|
compiler_gen_instr(self, program, OP_NOP, NO_PARAM);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct value* value = malloc(sizeof(struct value));
|
|
|
|
|
value_init_bool(value, VAL_TRUE, node->line);
|
|
|
|
|
program_push_instr(program, OP_PUSH,
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH,
|
|
|
|
|
program_push_constant(program, value));
|
|
|
|
|
|
|
|
|
|
} break;
|
|
|
|
@ -140,7 +162,7 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
{
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
program_push_instr(program, OP_EQ, NO_PARAM);
|
|
|
|
|
compiler_gen_instr(self, program, OP_EQ, NO_PARAM);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_NE: {
|
|
|
|
@ -152,8 +174,8 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
program_push_instr(program, OP_EQ, NO_PARAM);
|
|
|
|
|
program_push_instr(program, OP_NOT, NO_PARAM);
|
|
|
|
|
compiler_gen_instr(self, program, OP_EQ, NO_PARAM);
|
|
|
|
|
compiler_gen_instr(self, program, OP_NOT, NO_PARAM);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_NOT: {
|
|
|
|
@ -162,7 +184,7 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
program_push_instr(program, OP_NOT, NO_PARAM);
|
|
|
|
|
compiler_gen_instr(self, program, OP_NOT, NO_PARAM);
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
|
|
case NODE_AND: {
|
|
|
|
@ -177,17 +199,17 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t* addr = malloc(sizeof(size_t));
|
|
|
|
|
*addr = program_push_instr(program, OP_BRF, NO_PARAM); // to pivot
|
|
|
|
|
*addr = compiler_gen_instr(self, program, OP_BRF, NO_PARAM); // to pivot
|
|
|
|
|
vec_push(&to_pivot, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// true case
|
|
|
|
|
struct value* true_val = malloc(sizeof(struct value));
|
|
|
|
|
value_init_bool(true_val, VAL_TRUE, node->line);
|
|
|
|
|
program_push_instr(program, OP_PUSH,
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH,
|
|
|
|
|
program_push_constant(program, true_val));
|
|
|
|
|
|
|
|
|
|
size_t to_end = program_push_instr(program, OP_BR, NO_PARAM); // to end
|
|
|
|
|
size_t to_end = compiler_gen_instr(self, program, OP_BR, NO_PARAM); // to end
|
|
|
|
|
|
|
|
|
|
// pivot
|
|
|
|
|
size_t pivot_point = program->instructions.size;
|
|
|
|
@ -195,7 +217,7 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
// false case
|
|
|
|
|
struct value* false_val = malloc(sizeof(struct value));
|
|
|
|
|
value_init_bool(false_val, VAL_FALSE, node->line);
|
|
|
|
|
program_push_instr(program, OP_PUSH,
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH,
|
|
|
|
|
program_push_constant(program, false_val));
|
|
|
|
|
|
|
|
|
|
// end
|
|
|
|
@ -229,17 +251,17 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t* addr = malloc(sizeof(size_t));
|
|
|
|
|
*addr = program_push_instr(program, OP_BRT, NO_PARAM); // to pivot
|
|
|
|
|
*addr = compiler_gen_instr(self, program, OP_BRT, NO_PARAM); // to pivot
|
|
|
|
|
vec_push(&to_pivot, addr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// false case
|
|
|
|
|
struct value* false_val = malloc(sizeof(struct value));
|
|
|
|
|
value_init_bool(false_val, VAL_FALSE, node->line);
|
|
|
|
|
program_push_instr(program, OP_PUSH,
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH,
|
|
|
|
|
program_push_constant(program, false_val));
|
|
|
|
|
|
|
|
|
|
size_t to_end = program_push_instr(program, OP_BR, NO_PARAM); // to end
|
|
|
|
|
size_t to_end = compiler_gen_instr(self, program, OP_BR, NO_PARAM); // to end
|
|
|
|
|
|
|
|
|
|
// pivot
|
|
|
|
|
size_t pivot_point = program->instructions.size;
|
|
|
|
@ -247,7 +269,7 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
// false case
|
|
|
|
|
struct value* true_val = malloc(sizeof(struct value));
|
|
|
|
|
value_init_bool(true_val, VAL_TRUE, node->line);
|
|
|
|
|
program_push_instr(program, OP_PUSH,
|
|
|
|
|
compiler_gen_instr(self, program, OP_PUSH,
|
|
|
|
|
program_push_constant(program, true_val));
|
|
|
|
|
|
|
|
|
|
// end
|
|
|
|
@ -291,16 +313,16 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
|
|
|
|
|
switch (node->type)
|
|
|
|
|
{
|
|
|
|
|
case NODE_ADD: program_push_instr(program, OP_ADD, NO_PARAM); break;
|
|
|
|
|
case NODE_SUB: program_push_instr(program, OP_SUB, NO_PARAM); break;
|
|
|
|
|
case NODE_MUL: program_push_instr(program, OP_MUL, NO_PARAM); break;
|
|
|
|
|
case NODE_DIV: program_push_instr(program, OP_DIV, NO_PARAM); break;
|
|
|
|
|
case NODE_MOD: program_push_instr(program, OP_MOD, NO_PARAM); break;
|
|
|
|
|
case NODE_POW: program_push_instr(program, OP_POW, NO_PARAM); break;
|
|
|
|
|
case NODE_LT: program_push_instr(program, OP_LT, NO_PARAM); break;
|
|
|
|
|
case NODE_LE: program_push_instr(program, OP_LE, NO_PARAM); break;
|
|
|
|
|
case NODE_GT: program_push_instr(program, OP_GT, NO_PARAM); break;
|
|
|
|
|
case NODE_GE: program_push_instr(program, OP_GE, NO_PARAM); break;
|
|
|
|
|
case NODE_ADD: compiler_gen_instr(self, program, OP_ADD, NO_PARAM); break;
|
|
|
|
|
case NODE_SUB: compiler_gen_instr(self, program, OP_SUB, NO_PARAM); break;
|
|
|
|
|
case NODE_MUL: compiler_gen_instr(self, program, OP_MUL, NO_PARAM); break;
|
|
|
|
|
case NODE_DIV: compiler_gen_instr(self, program, OP_DIV, NO_PARAM); break;
|
|
|
|
|
case NODE_MOD: compiler_gen_instr(self, program, OP_MOD, NO_PARAM); break;
|
|
|
|
|
case NODE_POW: compiler_gen_instr(self, program, OP_POW, NO_PARAM); break;
|
|
|
|
|
case NODE_LT: compiler_gen_instr(self, program, OP_LT, NO_PARAM); break;
|
|
|
|
|
case NODE_LE: compiler_gen_instr(self, program, OP_LE, NO_PARAM); break;
|
|
|
|
|
case NODE_GT: compiler_gen_instr(self, program, OP_GT, NO_PARAM); break;
|
|
|
|
|
case NODE_GE: compiler_gen_instr(self, program, OP_GE, NO_PARAM); break;
|
|
|
|
|
default: break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -320,3 +342,45 @@ int compiler_compile(struct compiler* self,
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
size_t compiler_gen_instr(struct compiler* self,
|
|
|
|
|
struct program* program,
|
|
|
|
|
enum Opcodes op,
|
|
|
|
|
int param)
|
|
|
|
|
{
|
|
|
|
|
assert(self);
|
|
|
|
|
assert(program);
|
|
|
|
|
|
|
|
|
|
size_t addr = program_push_instr(program, op, param);
|
|
|
|
|
|
|
|
|
|
switch (op)
|
|
|
|
|
{
|
|
|
|
|
case OP_LOAD:
|
|
|
|
|
case OP_PUSH: self->stack_size += 1; break;
|
|
|
|
|
|
|
|
|
|
case OP_LT:
|
|
|
|
|
case OP_LE:
|
|
|
|
|
case OP_GT:
|
|
|
|
|
case OP_GE:
|
|
|
|
|
case OP_ADD:
|
|
|
|
|
case OP_SUB:
|
|
|
|
|
case OP_MUL:
|
|
|
|
|
case OP_DIV:
|
|
|
|
|
case OP_MOD:
|
|
|
|
|
case OP_POW:
|
|
|
|
|
case OP_EQ:
|
|
|
|
|
case OP_POP:
|
|
|
|
|
case OP_HALT:
|
|
|
|
|
case OP_BRF:
|
|
|
|
|
case OP_BRT:
|
|
|
|
|
self->stack_size -= 1; break;
|
|
|
|
|
|
|
|
|
|
case OP_SWAP:
|
|
|
|
|
case OP_BR:
|
|
|
|
|
case OP_NOT:
|
|
|
|
|
case OP_NOP:
|
|
|
|
|
case OP_STORE: break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return addr;
|
|
|
|
|
}
|
|
|
|
|