2023-12-09 17:24:41 +00:00
|
|
|
#include "compiler.h"
|
|
|
|
#include "lib/commons.h"
|
2023-12-16 18:12:20 +00:00
|
|
|
#include "lib/mod.h"
|
2023-12-20 19:54:58 +00:00
|
|
|
#include "lib/prepass.h"
|
2023-12-20 20:43:48 +00:00
|
|
|
#include "lib/program.h"
|
2023-12-20 19:54:58 +00:00
|
|
|
#include "lib/sym.h"
|
2023-12-20 20:43:48 +00:00
|
|
|
#include "lib/tysy.h"
|
2023-12-17 18:10:17 +00:00
|
|
|
#include "node.h"
|
2023-12-20 19:54:58 +00:00
|
|
|
#include "fun.h"
|
2023-12-23 20:17:12 +00:00
|
|
|
#include "locals.h"
|
2023-12-09 17:24:41 +00:00
|
|
|
|
2023-12-17 18:10:17 +00:00
|
|
|
void compiler_init(compiler_t* compiler,
|
2023-12-23 20:17:12 +00:00
|
|
|
int* id,
|
2023-12-17 18:10:17 +00:00
|
|
|
sym_t* sym,
|
|
|
|
tysy_t* tysy,
|
|
|
|
err_t* err)
|
2023-12-09 17:24:41 +00:00
|
|
|
{
|
|
|
|
assert(compiler);
|
2023-12-17 18:10:17 +00:00
|
|
|
assert(sym);
|
|
|
|
assert(tysy);
|
2023-12-09 17:24:41 +00:00
|
|
|
assert(err);
|
|
|
|
|
2023-12-23 20:17:12 +00:00
|
|
|
compiler->parent = NULL;
|
2023-12-17 18:10:17 +00:00
|
|
|
compiler->sym = sym;
|
2023-12-09 17:24:41 +00:00
|
|
|
compiler->tysy = tysy;
|
|
|
|
compiler->err = err;
|
2023-12-18 13:19:38 +00:00
|
|
|
|
|
|
|
compiler->scope = 0;
|
2023-12-23 20:17:12 +00:00
|
|
|
compiler->id = id;
|
2023-12-09 17:24:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void compiler_free(compiler_t* compiler)
|
|
|
|
{
|
|
|
|
assert(compiler);
|
|
|
|
}
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
int compiler_run(compiler_t* compiler, node_t* node, program_t* program)
|
2023-12-09 17:24:41 +00:00
|
|
|
{
|
|
|
|
assert(compiler);
|
|
|
|
assert(node);
|
|
|
|
|
|
|
|
switch (node->type)
|
|
|
|
{
|
|
|
|
case NODE_MOD: {
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[i], program);
|
2023-12-09 17:24:41 +00:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_NUM: {
|
|
|
|
double value = atof(node->value.data);
|
2023-12-11 17:01:22 +00:00
|
|
|
value_t* val = tysy_new_num(compiler->tysy, value, node->line);
|
2023-12-09 17:24:41 +00:00
|
|
|
Opcode op = OP_PUSH;
|
2023-12-20 19:54:58 +00:00
|
|
|
param_t param = (param_t) program_push_new_value(program,
|
|
|
|
(struct value*) val);
|
2023-12-09 17:24:41 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program, op, param);
|
2023-12-09 17:24:41 +00:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
2023-12-09 21:59:24 +00:00
|
|
|
case NODE_BOOL: {
|
|
|
|
int value = strcmp(node->value.data, "true") == 0;
|
2023-12-11 17:01:22 +00:00
|
|
|
value_t* val = tysy_new_bool(compiler->tysy, value, node->line);
|
2023-12-09 21:59:24 +00:00
|
|
|
Opcode op = OP_PUSH;
|
2023-12-20 19:54:58 +00:00
|
|
|
param_t param = (param_t) program_push_new_value(program,
|
|
|
|
(struct value*) val);
|
2023-12-09 21:59:24 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program, op, param);
|
2023-12-09 21:59:24 +00:00
|
|
|
} break;
|
|
|
|
|
2023-12-10 03:49:28 +00:00
|
|
|
case NODE_STR: {
|
|
|
|
char* value = node->value.data;
|
2023-12-11 17:01:22 +00:00
|
|
|
value_t* val = tysy_new_str(compiler->tysy, value, node->line);
|
2023-12-10 03:49:28 +00:00
|
|
|
Opcode op = OP_PUSH;
|
2023-12-20 19:54:58 +00:00
|
|
|
param_t param = (param_t) program_push_new_value(program,
|
|
|
|
(struct value*) val);
|
2023-12-10 03:49:28 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program, op, param);
|
2023-12-10 03:49:28 +00:00
|
|
|
} break;
|
|
|
|
|
2023-12-11 17:01:22 +00:00
|
|
|
case NODE_ASSERT: {
|
|
|
|
assert(node->children.size == 1);
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, node_child(node, 0), program);
|
|
|
|
program_push_instr(program, OP_ASSERT, RZ_NO_PARAM);
|
2023-12-11 17:01:22 +00:00
|
|
|
} break;
|
|
|
|
|
2023-12-15 18:30:20 +00:00
|
|
|
case NODE_NE:
|
|
|
|
case NODE_EQ: {
|
|
|
|
assert(node->children.size == 2);
|
|
|
|
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, node_child(node, i), program);
|
2023-12-15 18:30:20 +00:00
|
|
|
}
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program,
|
|
|
|
node->type == NODE_EQ ? OP_EQ : OP_NE, RZ_NO_PARAM);
|
2023-12-15 18:30:20 +00:00
|
|
|
} break;
|
|
|
|
|
2023-12-15 20:32:17 +00:00
|
|
|
case NODE_LT:
|
|
|
|
case NODE_LE:
|
|
|
|
case NODE_GT:
|
2023-12-15 21:31:01 +00:00
|
|
|
case NODE_GE: {
|
2023-12-15 20:32:17 +00:00
|
|
|
assert(node->children.size == 2);
|
|
|
|
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, node_child(node, i), program);
|
2023-12-15 20:32:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Opcode op;
|
|
|
|
switch (node->type)
|
|
|
|
{
|
|
|
|
case NODE_LT: op = OP_LT; break;
|
|
|
|
case NODE_LE: op = OP_LE; break;
|
|
|
|
case NODE_GT: op = OP_GT; break;
|
|
|
|
case NODE_GE: op = OP_GE; break;
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program, op, RZ_NO_PARAM);
|
2023-12-15 20:32:17 +00:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
2023-12-15 21:31:01 +00:00
|
|
|
case NODE_ADD:
|
|
|
|
case NODE_SUB:
|
|
|
|
case NODE_MUL:
|
|
|
|
case NODE_DIV:
|
|
|
|
case NODE_MODULO:
|
|
|
|
case NODE_POW: {
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, node_child(node, i), program);
|
2023-12-15 21:31:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Opcode op;
|
|
|
|
|
|
|
|
if (node->type == NODE_SUB
|
|
|
|
&& node->children.size == 1)
|
|
|
|
{
|
|
|
|
op = OP_USUB;
|
|
|
|
}
|
2023-12-16 18:42:26 +00:00
|
|
|
else if (node->type == NODE_ADD
|
|
|
|
&& node_find_first(node, NODE_STR))
|
|
|
|
{
|
|
|
|
op = OP_STRCAT;
|
|
|
|
}
|
|
|
|
else if (node->type == NODE_MUL
|
|
|
|
&& node_find_first(node, NODE_STR)
|
|
|
|
&& node_find_first(node, NODE_NUM))
|
|
|
|
{
|
|
|
|
op = OP_STRDUP;
|
|
|
|
}
|
2023-12-15 21:31:01 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (node->type)
|
|
|
|
{
|
|
|
|
case NODE_ADD: op = OP_ADD; break;
|
|
|
|
case NODE_SUB: op = OP_SUB; break;
|
|
|
|
case NODE_MUL: op = OP_MUL; break;
|
|
|
|
case NODE_DIV: op = OP_DIV; break;
|
|
|
|
case NODE_MODULO: op = OP_MODULO; break;
|
|
|
|
case NODE_POW: op = OP_POW; break;
|
|
|
|
default: assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program, op, RZ_NO_PARAM);
|
2023-12-15 21:31:01 +00:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
2023-12-16 18:12:20 +00:00
|
|
|
case NODE_AND: {
|
|
|
|
size_t const SZ = 512;
|
|
|
|
size_t to_false[SZ];
|
|
|
|
size_t sz = 0;
|
|
|
|
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, node_child(node, i), program);
|
|
|
|
size_t addr = program_push_instr(program, OP_BRF, RZ_NO_PARAM);
|
2023-12-16 18:12:20 +00:00
|
|
|
to_false[sz++] = addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// True case
|
|
|
|
value_t* t = tysy_new_bool(compiler->tysy, 1, node->line);
|
2023-12-20 19:54:58 +00:00
|
|
|
param_t t_param = program_push_new_value(program, (struct value*) t);
|
|
|
|
program_push_instr(program, OP_PUSH, t_param);
|
|
|
|
size_t to_end = program_push_instr(program, OP_BR, RZ_NO_PARAM);
|
2023-12-16 18:12:20 +00:00
|
|
|
|
|
|
|
// False case
|
2023-12-20 19:54:58 +00:00
|
|
|
size_t program_sz = program->size;
|
2023-12-16 18:12:20 +00:00
|
|
|
for (size_t i=0; i<sz; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
program->params[to_false[i]] = program_sz;
|
2023-12-16 18:12:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
value_t* f = tysy_new_bool(compiler->tysy, 0, node->line);
|
2023-12-20 19:54:58 +00:00
|
|
|
param_t f_param = program_push_new_value(program, (struct value*) f);
|
|
|
|
program_push_instr(program, OP_PUSH, f_param);
|
2023-12-16 18:12:20 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program->params[to_end] = program->size;
|
2023-12-16 18:12:20 +00:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_OR: {
|
|
|
|
size_t const SZ = 512;
|
|
|
|
size_t to_true[SZ];
|
|
|
|
size_t sz = 0;
|
|
|
|
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, node_child(node, i), program);
|
|
|
|
size_t addr = program_push_instr(program, OP_BRT, RZ_NO_PARAM);
|
2023-12-16 18:12:20 +00:00
|
|
|
to_true[sz++] = addr;
|
|
|
|
}
|
|
|
|
|
|
|
|
// False case
|
|
|
|
value_t* f = tysy_new_bool(compiler->tysy, 0, node->line);
|
2023-12-20 19:54:58 +00:00
|
|
|
param_t f_param = program_push_new_value(program, (struct value*) f);
|
|
|
|
program_push_instr(program, OP_PUSH, f_param);
|
|
|
|
size_t to_end = program_push_instr(program, OP_BR, RZ_NO_PARAM);
|
2023-12-16 18:12:20 +00:00
|
|
|
|
|
|
|
// True case
|
2023-12-20 19:54:58 +00:00
|
|
|
size_t program_sz = program->size;
|
2023-12-16 18:12:20 +00:00
|
|
|
for (size_t i=0; i<sz; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
program->params[to_true[i]] = program_sz;
|
2023-12-16 18:12:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
value_t* t = tysy_new_bool(compiler->tysy, 1, node->line);
|
2023-12-20 19:54:58 +00:00
|
|
|
param_t t_param = program_push_new_value(program, (struct value*) t);
|
|
|
|
program_push_instr(program, OP_PUSH, t_param);
|
2023-12-16 18:12:20 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program->params[to_end] = program->size;
|
2023-12-16 18:12:20 +00:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_NOT: {
|
|
|
|
assert(node->children.size > 0);
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[0], program);
|
|
|
|
program_push_instr(program, OP_NOT, RZ_NO_PARAM);
|
2023-12-16 18:12:20 +00:00
|
|
|
} break;
|
|
|
|
|
2023-12-17 18:10:17 +00:00
|
|
|
case NODE_VARDECL: {
|
|
|
|
char* name = ((node_t*) node->children.data[0])->value.data;
|
2023-12-18 13:19:38 +00:00
|
|
|
|
|
|
|
sym_entry_t* entry = NULL;
|
|
|
|
|
|
|
|
entry = sym_try_find_by_name(compiler->sym, name,
|
|
|
|
compiler->scope,
|
|
|
|
SYM_PRE,
|
2023-12-20 19:54:58 +00:00
|
|
|
node);
|
2023-12-18 13:19:38 +00:00
|
|
|
|
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
entry = sym_try_find_by_name(compiler->sym, name,
|
|
|
|
compiler->scope,
|
|
|
|
SYM_DECL,
|
2023-12-20 19:54:58 +00:00
|
|
|
node);
|
2023-12-18 13:19:38 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
char msg[RZ_STR_LIMIT];
|
|
|
|
snprintf(msg, RZ_STR_LIMIT, "unknown entry %s\n", name);
|
|
|
|
err_fatal(compiler->err, msg, node->line);
|
|
|
|
err_dump(compiler->err);
|
|
|
|
}
|
|
|
|
|
2023-12-17 18:10:17 +00:00
|
|
|
assert(entry);
|
2023-12-18 13:19:38 +00:00
|
|
|
entry->state = SYM_DECL;
|
|
|
|
|
2023-12-17 18:10:17 +00:00
|
|
|
int id = entry->id;
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[1], program);
|
|
|
|
program_push_instr(program, OP_STORE, id);
|
2023-12-18 13:19:38 +00:00
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_VARSET: {
|
|
|
|
char* name = ((node_t*) node->children.data[0])->value.data;
|
|
|
|
|
|
|
|
sym_entry_t* entry = sym_try_find_by_name(compiler->sym, name,
|
|
|
|
compiler->scope,
|
|
|
|
SYM_DECL,
|
2023-12-20 19:54:58 +00:00
|
|
|
node);
|
2023-12-18 13:19:38 +00:00
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
char msg[RZ_STR_LIMIT];
|
|
|
|
snprintf(msg, RZ_STR_LIMIT,
|
|
|
|
"cannot assign value"
|
|
|
|
" to undefined variable '%s'.", name);
|
|
|
|
err_fatal(compiler->err, msg, node->line);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int id = entry->id;
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[1], program);
|
|
|
|
program_push_instr(program, OP_STORE, id);
|
2023-12-18 13:19:38 +00:00
|
|
|
}
|
2023-12-17 18:10:17 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_IDENT: {
|
|
|
|
char* name = node->value.data;
|
2023-12-20 19:54:58 +00:00
|
|
|
|
2023-12-18 13:19:38 +00:00
|
|
|
sym_entry_t* entry = sym_try_find_by_name(compiler->sym, name,
|
|
|
|
compiler->scope,
|
|
|
|
SYM_DECL,
|
2023-12-20 19:54:58 +00:00
|
|
|
node);
|
2023-12-23 20:17:12 +00:00
|
|
|
|
|
|
|
if (0 && compiler->parent && !entry)
|
|
|
|
{
|
|
|
|
entry = sym_try_find_by_name(compiler->parent->sym, name,
|
|
|
|
compiler->scope,
|
|
|
|
SYM_DECL,
|
|
|
|
node);
|
|
|
|
}
|
|
|
|
|
2023-12-17 18:10:17 +00:00
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
char msg[RZ_STR_LIMIT];
|
2023-12-18 13:19:38 +00:00
|
|
|
snprintf(msg, RZ_STR_LIMIT, "undefined variable '%s'.",
|
2023-12-17 18:10:17 +00:00
|
|
|
name);
|
|
|
|
|
|
|
|
err_fatal(compiler->err, msg, node->line);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int id = entry->id;
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program, OP_LOAD, id);
|
2023-12-17 18:10:17 +00:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
2023-12-18 18:34:31 +00:00
|
|
|
case NODE_SCOPE: {
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[0], program);
|
2023-12-18 18:34:31 +00:00
|
|
|
} break;
|
|
|
|
|
2023-12-18 13:19:38 +00:00
|
|
|
case NODE_BLOCK: {
|
|
|
|
compiler->scope++;
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[i], program);
|
2023-12-18 13:19:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
compiler->scope--;
|
|
|
|
} break;
|
|
|
|
|
2023-12-18 18:34:31 +00:00
|
|
|
case NODE_IF: {
|
|
|
|
size_t const IF_LIMIT = 1024;
|
|
|
|
|
|
|
|
int end_points[IF_LIMIT];
|
|
|
|
size_t size = 0;
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run_if(compiler, node, program, end_points, &size);
|
2023-12-18 18:34:31 +00:00
|
|
|
assert(size < IF_LIMIT);
|
|
|
|
|
|
|
|
for (size_t i=0; i<size; i++)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
program->params[end_points[i]] = program->size;
|
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_FUNDECL: {
|
|
|
|
char* fun_name = ((node_t*) node->children.data[0])->value.data;
|
|
|
|
|
|
|
|
fun_t* fun = malloc(sizeof(fun_t));
|
|
|
|
fun_init(fun, (struct tysy*) compiler->tysy, compiler->err);
|
|
|
|
|
2023-12-20 20:43:48 +00:00
|
|
|
value_t* value = tysy_new_fun(compiler->tysy, fun, node->line);
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
sym_entry_t* entry = sym_try_find_by_name(compiler->sym,
|
|
|
|
fun_name,
|
|
|
|
compiler->scope,
|
|
|
|
SYM_PRE,
|
|
|
|
node);
|
|
|
|
assert(entry);
|
|
|
|
|
|
|
|
entry->state = SYM_DECL;
|
2023-12-23 20:17:12 +00:00
|
|
|
entry->id = *compiler->id;
|
2023-12-20 19:54:58 +00:00
|
|
|
|
|
|
|
// Compile function
|
|
|
|
{
|
|
|
|
compiler_t comp;
|
2023-12-23 20:17:12 +00:00
|
|
|
compiler_init(&comp, compiler->id, (sym_t*) fun->sym,
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler->tysy, compiler->err);
|
2023-12-23 20:17:12 +00:00
|
|
|
comp.parent = compiler;
|
|
|
|
comp.sym->parent = compiler->sym;
|
2023-12-20 19:54:58 +00:00
|
|
|
|
|
|
|
tysolver_t tysolver;
|
|
|
|
tysolver_init(&tysolver, (sym_t*) fun->sym, compiler->tysy);
|
|
|
|
|
|
|
|
prepass_t pre;
|
2023-12-23 20:17:12 +00:00
|
|
|
prepass_init(&pre, compiler->id, (sym_t*) fun->sym, compiler->tysy,
|
2023-12-20 19:54:58 +00:00
|
|
|
&tysolver, compiler->err);
|
|
|
|
|
2023-12-20 20:43:48 +00:00
|
|
|
|
|
|
|
// self
|
2023-12-23 20:17:12 +00:00
|
|
|
int id = sym_declare((sym_t*) fun->sym,
|
|
|
|
(*compiler->id)++,
|
|
|
|
fun_name,
|
|
|
|
tysy_try_find_type(comp.tysy, "fun"),
|
|
|
|
comp.scope,
|
|
|
|
SYM_DECL,
|
|
|
|
node);
|
|
|
|
|
|
|
|
|
|
|
|
fun->base = id;
|
|
|
|
|
|
|
|
prepass_run(&pre, (node_t*) node->children.data[2]);
|
|
|
|
|
|
|
|
fun->arg_base = *compiler->id;
|
2023-12-20 20:43:48 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(&comp, (node_t*) node->children.data[1], &fun->program);
|
|
|
|
compiler_run(&comp, (node_t*) node->children.data[2], &fun->program);
|
|
|
|
program_push_instr(&fun->program, OP_RET, RZ_NO_PARAM);
|
|
|
|
|
|
|
|
prepass_free(&pre);
|
|
|
|
tysolver_free(&tysolver);
|
|
|
|
compiler_free(&comp);
|
|
|
|
}
|
|
|
|
|
|
|
|
param_t param = program_push_new_value(program, (struct value*) value);
|
|
|
|
program_push_instr(program, OP_PUSH, param);
|
2023-12-23 20:17:12 +00:00
|
|
|
program_push_instr(program, OP_MKFUN, RZ_NO_PARAM);
|
2023-12-20 19:54:58 +00:00
|
|
|
program_push_instr(program, OP_STORE, entry->id);
|
2023-12-23 20:17:12 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_PARAMS: {
|
|
|
|
for (size_t i=0; i<node->children.size; i++)
|
|
|
|
{
|
|
|
|
node_t* child = (node_t*) node->children.data[i];
|
|
|
|
char* name = child->value.data;
|
2023-12-23 20:17:12 +00:00
|
|
|
sym_declare(compiler->sym, (*compiler->id)++, name, NULL,
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler->scope, SYM_DECL,
|
|
|
|
child);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_RETURN: {
|
|
|
|
compiler_run(compiler, (node_t*) node->children.data[0], program);
|
|
|
|
program_push_instr(program, OP_RET, RZ_NO_PARAM);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case NODE_FUNCALL: {
|
|
|
|
char* name = ((node_t*) node->children.data[0])->value.data;
|
|
|
|
node_t* args = (node_t*) node->children.data[1];
|
|
|
|
|
|
|
|
for (size_t i=0; i<args->children.size; i++)
|
|
|
|
{
|
|
|
|
compiler_run(compiler, (node_t*)args->children.data[i], program);
|
|
|
|
}
|
|
|
|
|
|
|
|
sym_entry_t* entry = sym_try_find_by_name(compiler->sym,
|
|
|
|
name,
|
|
|
|
compiler->scope,
|
|
|
|
SYM_DECL,
|
|
|
|
node);
|
2023-12-23 20:17:12 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
if (!entry)
|
|
|
|
{
|
|
|
|
char msg[RZ_STR_LIMIT];
|
|
|
|
snprintf(msg, RZ_STR_LIMIT, "undefined function '%s'", name);
|
|
|
|
err_fatal(compiler->err, msg, node->line);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
int id = entry->id;
|
|
|
|
program_push_instr(program, OP_LOAD, id);
|
|
|
|
program_push_instr(program, OP_CALL, args->children.size);
|
2023-12-18 18:34:31 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} break;
|
|
|
|
|
2023-12-09 17:24:41 +00:00
|
|
|
default: {
|
2023-12-11 17:01:22 +00:00
|
|
|
fprintf(stderr, "Cannot compile unknown node '%s'",
|
|
|
|
NodeTypeStr[node->type]);
|
|
|
|
abort();
|
2023-12-09 17:24:41 +00:00
|
|
|
} break;
|
|
|
|
}
|
2023-12-17 18:10:17 +00:00
|
|
|
|
|
|
|
return 0;
|
2023-12-09 17:24:41 +00:00
|
|
|
}
|
2023-12-18 18:34:31 +00:00
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
void compiler_run_if(compiler_t* compiler, node_t* node, program_t* program,
|
2023-12-18 18:34:31 +00:00
|
|
|
int* end_points, size_t* sz)
|
|
|
|
{
|
|
|
|
assert(compiler);
|
|
|
|
assert(node);
|
|
|
|
|
|
|
|
// if
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[0], program);
|
2023-12-18 18:34:31 +00:00
|
|
|
// if false goto next
|
2023-12-20 19:54:58 +00:00
|
|
|
int to_next = program_push_instr(program, OP_BRF, RZ_NO_PARAM);
|
2023-12-18 18:34:31 +00:00
|
|
|
|
|
|
|
// then
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, (node_t*) node->children.data[1], program);
|
2023-12-18 18:34:31 +00:00
|
|
|
// goto end
|
2023-12-20 19:54:58 +00:00
|
|
|
int to_end = program_push_instr(program, OP_BR, RZ_NO_PARAM);
|
2023-12-18 18:34:31 +00:00
|
|
|
end_points[*sz] = to_end;
|
|
|
|
(*sz)++;
|
|
|
|
|
2023-12-20 19:54:58 +00:00
|
|
|
program->params[to_next] = program->size;
|
2023-12-18 18:34:31 +00:00
|
|
|
|
|
|
|
if (node->children.size >= 3)
|
|
|
|
{
|
|
|
|
node_t* next = (node_t*) node->children.data[2];
|
|
|
|
|
|
|
|
if (next->type == NODE_BLOCK)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run(compiler, next, program);
|
2023-12-18 18:34:31 +00:00
|
|
|
}
|
|
|
|
else if (next->type == NODE_IF)
|
|
|
|
{
|
2023-12-20 19:54:58 +00:00
|
|
|
compiler_run_if(compiler, next, program, end_points, sz);
|
2023-12-18 18:34:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|