✨ clear blocks.
parent
75987d9780
commit
bb300a1a93
|
@ -2,6 +2,7 @@
|
||||||
#include "commons.h"
|
#include "commons.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "opcodes.h"
|
#include "opcodes.h"
|
||||||
|
#include "program.h"
|
||||||
#include "syms.h"
|
#include "syms.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
|
@ -11,6 +12,7 @@ void compiler_init(struct compiler* self, struct syms* syms)
|
||||||
assert(self);
|
assert(self);
|
||||||
self->syms = syms;
|
self->syms = syms;
|
||||||
memset(self->error_msg, 0, GUX_STR_SIZE);
|
memset(self->error_msg, 0, GUX_STR_SIZE);
|
||||||
|
self->stack_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler_free(struct compiler* self)
|
void compiler_free(struct compiler* self)
|
||||||
|
@ -28,6 +30,26 @@ int compiler_compile(struct compiler* self,
|
||||||
|
|
||||||
switch (node->type)
|
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: {
|
case NODE_ASSIGN: {
|
||||||
struct node* ident = node->children.data[0];
|
struct node* ident = node->children.data[0];
|
||||||
struct node* expr = node->children.data[1];
|
struct node* expr = node->children.data[1];
|
||||||
|
@ -40,7 +62,7 @@ int compiler_compile(struct compiler* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
program_push_instr(program, OP_STORE, entry->addr);
|
compiler_gen_instr(self, program, OP_STORE, entry->addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_IDENT: {
|
case NODE_IDENT: {
|
||||||
|
@ -56,7 +78,7 @@ int compiler_compile(struct compiler* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
program_push_instr(program, OP_LOAD, entry->addr);
|
compiler_gen_instr(self, program, OP_LOAD, entry->addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_CONSTDECL:
|
case NODE_CONSTDECL:
|
||||||
|
@ -76,7 +98,7 @@ int compiler_compile(struct compiler* self,
|
||||||
node);
|
node);
|
||||||
assert(entry);
|
assert(entry);
|
||||||
|
|
||||||
program_push_instr(program, OP_STORE, entry->addr);
|
compiler_gen_instr(self, program, OP_STORE, entry->addr);
|
||||||
} break;
|
} break;
|
||||||
case NODE_BOOL: {
|
case NODE_BOOL: {
|
||||||
struct value* val = malloc(sizeof(struct value));
|
struct value* val = malloc(sizeof(struct value));
|
||||||
|
@ -84,28 +106,28 @@ int compiler_compile(struct compiler* self,
|
||||||
strcmp(node->value, "true") == 0 ? 1 : 0,
|
strcmp(node->value, "true") == 0 ? 1 : 0,
|
||||||
node->line);
|
node->line);
|
||||||
size_t addr = program_push_constant(program, val);
|
size_t addr = program_push_constant(program, val);
|
||||||
program_push_instr(program, OP_PUSH, addr);
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_INT: {
|
case NODE_INT: {
|
||||||
struct value* val = malloc(sizeof(struct value));
|
struct value* val = malloc(sizeof(struct value));
|
||||||
value_init_int(val, atoi(node->value), node->line);
|
value_init_int(val, atoi(node->value), node->line);
|
||||||
size_t addr = program_push_constant(program, val);
|
size_t addr = program_push_constant(program, val);
|
||||||
program_push_instr(program, OP_PUSH, addr);
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_FLOAT: {
|
case NODE_FLOAT: {
|
||||||
struct value* val = malloc(sizeof(struct value));
|
struct value* val = malloc(sizeof(struct value));
|
||||||
value_init_float(val, atof(node->value), node->line);
|
value_init_float(val, atof(node->value), node->line);
|
||||||
size_t addr = program_push_constant(program, val);
|
size_t addr = program_push_constant(program, val);
|
||||||
program_push_instr(program, OP_PUSH, addr);
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_STRING: {
|
case NODE_STRING: {
|
||||||
struct value* val = malloc(sizeof(struct value));
|
struct value* val = malloc(sizeof(struct value));
|
||||||
value_init_string(val, node->value, node->line);
|
value_init_string(val, node->value, node->line);
|
||||||
size_t addr = program_push_constant(program, val);
|
size_t addr = program_push_constant(program, val);
|
||||||
program_push_instr(program, OP_PUSH, addr);
|
compiler_gen_instr(self, program, OP_PUSH, addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_ASSERT: {
|
case NODE_ASSERT: {
|
||||||
|
@ -114,21 +136,21 @@ int compiler_compile(struct compiler* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t brt = program_push_instr(program, OP_BRT, NO_PARAM);
|
size_t brt = compiler_gen_instr(self, program, OP_BRT, NO_PARAM);
|
||||||
program_push_instr(program, OP_PUSH, GUX_RET_ASSERT);
|
compiler_gen_instr(self, program, OP_PUSH, GUX_RET_ASSERT);
|
||||||
size_t halt = program_push_instr(program, OP_HALT, node->line);
|
size_t halt = compiler_gen_instr(self, program, OP_HALT, node->line);
|
||||||
|
|
||||||
struct instruction* instr = program->instructions.data[brt];
|
struct instruction* instr = program->instructions.data[brt];
|
||||||
instr->param = halt + 1;
|
instr->param = halt + 1;
|
||||||
|
|
||||||
if (halt + 1 >= program->instructions.size)
|
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));
|
struct value* value = malloc(sizeof(struct value));
|
||||||
value_init_bool(value, VAL_TRUE, node->line);
|
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));
|
program_push_constant(program, value));
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
@ -140,7 +162,7 @@ int compiler_compile(struct compiler* self,
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
program_push_instr(program, OP_EQ, NO_PARAM);
|
compiler_gen_instr(self, program, OP_EQ, NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_NE: {
|
case NODE_NE: {
|
||||||
|
@ -152,8 +174,8 @@ int compiler_compile(struct compiler* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
program_push_instr(program, OP_EQ, NO_PARAM);
|
compiler_gen_instr(self, program, OP_EQ, NO_PARAM);
|
||||||
program_push_instr(program, OP_NOT, NO_PARAM);
|
compiler_gen_instr(self, program, OP_NOT, NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_NOT: {
|
case NODE_NOT: {
|
||||||
|
@ -162,7 +184,7 @@ int compiler_compile(struct compiler* self,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
program_push_instr(program, OP_NOT, NO_PARAM);
|
compiler_gen_instr(self, program, OP_NOT, NO_PARAM);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NODE_AND: {
|
case NODE_AND: {
|
||||||
|
@ -177,17 +199,17 @@ int compiler_compile(struct compiler* self,
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t* addr = malloc(sizeof(size_t));
|
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);
|
vec_push(&to_pivot, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// true case
|
// true case
|
||||||
struct value* true_val = malloc(sizeof(struct value));
|
struct value* true_val = malloc(sizeof(struct value));
|
||||||
value_init_bool(true_val, VAL_TRUE, node->line);
|
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));
|
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
|
// pivot
|
||||||
size_t pivot_point = program->instructions.size;
|
size_t pivot_point = program->instructions.size;
|
||||||
|
@ -195,7 +217,7 @@ int compiler_compile(struct compiler* self,
|
||||||
// false case
|
// false case
|
||||||
struct value* false_val = malloc(sizeof(struct value));
|
struct value* false_val = malloc(sizeof(struct value));
|
||||||
value_init_bool(false_val, VAL_FALSE, node->line);
|
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));
|
program_push_constant(program, false_val));
|
||||||
|
|
||||||
// end
|
// end
|
||||||
|
@ -229,17 +251,17 @@ int compiler_compile(struct compiler* self,
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t* addr = malloc(sizeof(size_t));
|
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);
|
vec_push(&to_pivot, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// false case
|
// false case
|
||||||
struct value* false_val = malloc(sizeof(struct value));
|
struct value* false_val = malloc(sizeof(struct value));
|
||||||
value_init_bool(false_val, VAL_FALSE, node->line);
|
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));
|
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
|
// pivot
|
||||||
size_t pivot_point = program->instructions.size;
|
size_t pivot_point = program->instructions.size;
|
||||||
|
@ -247,7 +269,7 @@ int compiler_compile(struct compiler* self,
|
||||||
// false case
|
// false case
|
||||||
struct value* true_val = malloc(sizeof(struct value));
|
struct value* true_val = malloc(sizeof(struct value));
|
||||||
value_init_bool(true_val, VAL_TRUE, node->line);
|
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));
|
program_push_constant(program, true_val));
|
||||||
|
|
||||||
// end
|
// end
|
||||||
|
@ -291,16 +313,16 @@ int compiler_compile(struct compiler* self,
|
||||||
|
|
||||||
switch (node->type)
|
switch (node->type)
|
||||||
{
|
{
|
||||||
case NODE_ADD: program_push_instr(program, OP_ADD, NO_PARAM); break;
|
case NODE_ADD: compiler_gen_instr(self, program, OP_ADD, NO_PARAM); break;
|
||||||
case NODE_SUB: program_push_instr(program, OP_SUB, NO_PARAM); break;
|
case NODE_SUB: compiler_gen_instr(self, program, OP_SUB, NO_PARAM); break;
|
||||||
case NODE_MUL: program_push_instr(program, OP_MUL, NO_PARAM); break;
|
case NODE_MUL: compiler_gen_instr(self, program, OP_MUL, NO_PARAM); break;
|
||||||
case NODE_DIV: program_push_instr(program, OP_DIV, NO_PARAM); break;
|
case NODE_DIV: compiler_gen_instr(self, program, OP_DIV, NO_PARAM); break;
|
||||||
case NODE_MOD: program_push_instr(program, OP_MOD, NO_PARAM); break;
|
case NODE_MOD: compiler_gen_instr(self, program, OP_MOD, NO_PARAM); break;
|
||||||
case NODE_POW: program_push_instr(program, OP_POW, NO_PARAM); break;
|
case NODE_POW: compiler_gen_instr(self, program, OP_POW, NO_PARAM); break;
|
||||||
case NODE_LT: program_push_instr(program, OP_LT, NO_PARAM); break;
|
case NODE_LT: compiler_gen_instr(self, program, OP_LT, NO_PARAM); break;
|
||||||
case NODE_LE: program_push_instr(program, OP_LE, NO_PARAM); break;
|
case NODE_LE: compiler_gen_instr(self, program, OP_LE, NO_PARAM); break;
|
||||||
case NODE_GT: program_push_instr(program, OP_GT, NO_PARAM); break;
|
case NODE_GT: compiler_gen_instr(self, program, OP_GT, NO_PARAM); break;
|
||||||
case NODE_GE: program_push_instr(program, OP_GE, NO_PARAM); break;
|
case NODE_GE: compiler_gen_instr(self, program, OP_GE, NO_PARAM); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,3 +342,45 @@ int compiler_compile(struct compiler* self,
|
||||||
|
|
||||||
return 0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ struct compiler {
|
||||||
char error_msg[GUX_STR_SIZE];
|
char error_msg[GUX_STR_SIZE];
|
||||||
struct syms* syms;
|
struct syms* syms;
|
||||||
int error_line;
|
int error_line;
|
||||||
|
int stack_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
void compiler_init(struct compiler* self, struct syms* syms);
|
void compiler_init(struct compiler* self, struct syms* syms);
|
||||||
|
@ -19,4 +20,9 @@ int compiler_compile(struct compiler* self,
|
||||||
struct node* node,
|
struct node* node,
|
||||||
struct program* program);
|
struct program* program);
|
||||||
|
|
||||||
|
size_t compiler_gen_instr(struct compiler* self,
|
||||||
|
struct program* program,
|
||||||
|
enum Opcodes op,
|
||||||
|
int param);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,7 +5,8 @@
|
||||||
G(OP_PUSH), G(OP_POP), G(OP_BRF), G(OP_BR), G(OP_HALT), \
|
G(OP_PUSH), G(OP_POP), G(OP_BRF), G(OP_BR), G(OP_HALT), \
|
||||||
G(OP_BRT), G(OP_NOP), G(OP_NOT), G(OP_EQ), \
|
G(OP_BRT), G(OP_NOP), G(OP_NOT), G(OP_EQ), \
|
||||||
G(OP_ADD), G(OP_SUB), G(OP_MUL), G(OP_DIV), G(OP_MOD), G(OP_POW), \
|
G(OP_ADD), G(OP_SUB), G(OP_MUL), G(OP_DIV), G(OP_MOD), G(OP_POW), \
|
||||||
G(OP_LT), G(OP_LE), G(OP_GT),G(OP_GE), G(OP_LOAD), G(OP_STORE)
|
G(OP_LT), G(OP_LE), G(OP_GT),G(OP_GE), G(OP_LOAD), G(OP_STORE),\
|
||||||
|
G(OP_SWAP)
|
||||||
|
|
||||||
#include <commons.h>
|
#include <commons.h>
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ int type_resolver_resolve(struct type_resolver* self,
|
||||||
case NODE_IDENT: {
|
case NODE_IDENT: {
|
||||||
struct syms_entry* entry = syms_try_get(self->syms,
|
struct syms_entry* entry = syms_try_get(self->syms,
|
||||||
node->value,
|
node->value,
|
||||||
node_depth(node));
|
node);
|
||||||
|
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define GUX_STR_SIZE 256
|
#define GUX_STR_SIZE 512
|
||||||
#define GUX_ENUM_IDENT(X) X
|
#define GUX_ENUM_IDENT(X) X
|
||||||
#define GUX_ENUM_STR(X) #X
|
#define GUX_ENUM_STR(X) #X
|
||||||
#define GUX_ENUM_H(Prefix, Types) \
|
#define GUX_ENUM_H(Prefix, Types) \
|
||||||
|
|
|
@ -124,6 +124,14 @@ int vm_exec(struct vm* self, struct program* program)
|
||||||
|
|
||||||
switch (opcode)
|
switch (opcode)
|
||||||
{
|
{
|
||||||
|
case OP_SWAP: {
|
||||||
|
assert(frame->sp > 1);
|
||||||
|
int tmp = frame->stack[frame->sp - 1];
|
||||||
|
frame->stack[frame->sp - 1] = frame->stack[frame->sp - 2];
|
||||||
|
frame->stack[frame->sp - 2] = tmp;
|
||||||
|
self->pc++;
|
||||||
|
} break;
|
||||||
|
|
||||||
case OP_LOAD: {
|
case OP_LOAD: {
|
||||||
int stack_addr = vm_load(self, param);
|
int stack_addr = vm_load(self, param);
|
||||||
struct frame* myframe = self->stack[self->fp - 1];
|
struct frame* myframe = self->stack[self->fp - 1];
|
||||||
|
|
Loading…
Reference in New Issue