Compare commits
No commits in common. "789ad9657feaf25bba42a71dd7caa910ff8facd1" and "2d277d338102ebd700e99c3dc44a04c3c2b97d3b" have entirely different histories.
789ad9657f
...
2d277d3381
|
@ -3,4 +3,3 @@
|
||||||
*\#*
|
*\#*
|
||||||
build
|
build
|
||||||
doc/build
|
doc/build
|
||||||
vgcore.*
|
|
||||||
|
|
|
@ -11,10 +11,9 @@ int main(int argc, char** argv)
|
||||||
module_t module;
|
module_t module;
|
||||||
module_init(&module);
|
module_init(&module);
|
||||||
|
|
||||||
status = module_load(&module, argv[1]);
|
module_load(&module, argv[1]);
|
||||||
|
|
||||||
|
if (!err_is_ok(&module.err))
|
||||||
if (status != 0 || !err_is_ok(&module.err))
|
|
||||||
{
|
{
|
||||||
err_print_stack_trace(&module.err);
|
err_print_stack_trace(&module.err);
|
||||||
status = 1;
|
status = 1;
|
||||||
|
|
|
@ -2,13 +2,6 @@ MODULE ::= EXPR*
|
||||||
EXPR ::=
|
EXPR ::=
|
||||||
| OR
|
| OR
|
||||||
| ASSERT
|
| ASSERT
|
||||||
| DECL
|
|
||||||
| ASSIGN
|
|
||||||
| BEGIN
|
|
||||||
BEGIN ::= begin BLOCK end
|
|
||||||
BLOCK ::= EXPR*
|
|
||||||
ASSIGN ::= (ident|INDEX) assign EXPR
|
|
||||||
DECL ::= (var|const) ident assign EXPR
|
|
||||||
ASSERT ::= (assert_eq|assert_ne) tuple
|
ASSERT ::= (assert_eq|assert_ne) tuple
|
||||||
OR ::= AND (or AND)*
|
OR ::= AND (or AND)*
|
||||||
AND ::= EQNE (and EQNE)*
|
AND ::= EQNE (and EQNE)*
|
||||||
|
@ -28,7 +21,7 @@ LITERAL ::=
|
||||||
| opar EXPR cpar
|
| opar EXPR cpar
|
||||||
ARRAY ::= osquare (EXPR (comma EXPR)*)? csquare
|
ARRAY ::= osquare (EXPR (comma EXPR)*)? csquare
|
||||||
INDEX ::=
|
INDEX ::=
|
||||||
| (TUPLE|str|ident|ARRAY) osquare (EXPR (comma EXPR)*)? csquare
|
| (TUPLE|str|ARRAY) osquare (EXPR (comma EXPR)*)? csquare
|
||||||
TUPLE ::=
|
TUPLE ::=
|
||||||
| opar EXPR+ cpar
|
| opar EXPR+ cpar
|
||||||
BUILTIN ::= num | bool | str | ident
|
BUILTIN ::= num | bool | str
|
||||||
|
|
|
@ -17,7 +17,6 @@ add_library(ccm_lib
|
||||||
prog.c
|
prog.c
|
||||||
compiler.c
|
compiler.c
|
||||||
exec.c
|
exec.c
|
||||||
sym.c
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set_property(TARGET ccm_lib PROPERTY C_STANDARD 99)
|
set_property(TARGET ccm_lib PROPERTY C_STANDARD 99)
|
||||||
|
|
|
@ -9,8 +9,7 @@ G(OP_ADD), G(OP_SUB), G(OP_USUB), G(OP_MUL), \
|
||||||
G(OP_DIV), G(OP_POW), G(OP_MOD), G(OP_MK_TUPLE), \
|
G(OP_DIV), G(OP_POW), G(OP_MOD), G(OP_MK_TUPLE), \
|
||||||
G(OP_ASSERT_EQ), G(OP_ASSERT_NE), G(OP_BRF), G(OP_BR), \
|
G(OP_ASSERT_EQ), G(OP_ASSERT_NE), G(OP_BRF), G(OP_BR), \
|
||||||
G(OP_NOT), G(OP_IN), G(OP_INDEX), G(OP_EQ), G(OP_LT), \
|
G(OP_NOT), G(OP_IN), G(OP_INDEX), G(OP_EQ), G(OP_LT), \
|
||||||
G(OP_GT), G(OP_MK_ARRAY), G(OP_LOCAL_STORE), \
|
G(OP_GT), G(OP_MK_ARRAY)
|
||||||
G(OP_LOCAL_LOAD), G(OP_ASTORE)
|
|
||||||
|
|
||||||
CCM_ENUM_H(Opcode, OPCODES);
|
CCM_ENUM_H(Opcode, OPCODES);
|
||||||
|
|
||||||
|
|
24
lib/ccm.c
24
lib/ccm.c
|
@ -4,14 +4,11 @@
|
||||||
void ccm_init(ccm_t* self)
|
void ccm_init(ccm_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
sym_init(&self->sym);
|
|
||||||
vec_init(&self->values);
|
vec_init(&self->values);
|
||||||
vec_init(&self->stack);
|
vec_init(&self->stack);
|
||||||
vec_init(&self->globals);
|
vec_init(&self->globals);
|
||||||
err_init(&self->err);
|
err_init(&self->err);
|
||||||
self->id_counter = 0;
|
self->id_counter = 0;
|
||||||
|
|
||||||
sym_open_scope(&self->sym);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ccm_entry_free(ccm_entry_t* self)
|
void ccm_entry_free(ccm_entry_t* self)
|
||||||
|
@ -23,7 +20,6 @@ void ccm_entry_free(ccm_entry_t* self)
|
||||||
void ccm_free(ccm_t* self)
|
void ccm_free(ccm_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
sym_free(&self->sym);
|
|
||||||
err_free(&self->err);
|
err_free(&self->err);
|
||||||
vec_free_elements(&self->values, (void*) ccm_entry_free);
|
vec_free_elements(&self->values, (void*) ccm_entry_free);
|
||||||
vec_free(&self->values);
|
vec_free(&self->values);
|
||||||
|
@ -336,26 +332,6 @@ CCM ccm_top(ccm_t* self, int depth)
|
||||||
return (CCM) self->stack.data[self->stack.size - 1 - depth];
|
return (CCM) self->stack.data[self->stack.size - 1 - depth];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ccm_set(ccm_t* self, CCM value, int addr)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
while (addr >= (ssize_t) self->stack.size)
|
|
||||||
{
|
|
||||||
ccm_push(self, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
self->stack.data[addr] = (void*) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
CCM ccm_get(ccm_t* self, int addr)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(addr < (ssize_t) self->stack.size);
|
|
||||||
assert(addr >= 0);
|
|
||||||
|
|
||||||
return (CCM) self->stack.data[addr];
|
|
||||||
}
|
|
||||||
|
|
||||||
void ccm_in(ccm_t* self)
|
void ccm_in(ccm_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "vec.h"
|
#include "vec.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "sym.h"
|
|
||||||
|
|
||||||
typedef size_t CCM;
|
typedef size_t CCM;
|
||||||
|
|
||||||
|
@ -15,7 +14,6 @@ typedef struct {
|
||||||
} ccm_entry_t;
|
} ccm_entry_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
sym_t sym;
|
|
||||||
err_t err;
|
err_t err;
|
||||||
vec_t values;
|
vec_t values;
|
||||||
vec_t stack;
|
vec_t stack;
|
||||||
|
@ -64,8 +62,6 @@ CCM ccm_to_ref(ccm_t* self, size_t value, int line);
|
||||||
void ccm_push(ccm_t* self, CCM value);
|
void ccm_push(ccm_t* self, CCM value);
|
||||||
CCM ccm_pop(ccm_t* self);
|
CCM ccm_pop(ccm_t* self);
|
||||||
CCM ccm_top(ccm_t* self, int depth);
|
CCM ccm_top(ccm_t* self, int depth);
|
||||||
void ccm_set(ccm_t* self, CCM value, int addr);
|
|
||||||
CCM ccm_get(ccm_t* self, int addr);
|
|
||||||
|
|
||||||
void ccm_in(ccm_t* self);
|
void ccm_in(ccm_t* self);
|
||||||
void ccm_add(ccm_t* self);
|
void ccm_add(ccm_t* self);
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#define CCM_STRLEN 4096
|
#define CCM_STRLEN 256
|
||||||
#define CCM_ENUM_ENUM(X) X
|
#define CCM_ENUM_ENUM(X) X
|
||||||
#define CCM_ENUM_STR(X) #X
|
#define CCM_ENUM_STR(X) #X
|
||||||
|
|
||||||
|
|
127
lib/compiler.c
127
lib/compiler.c
|
@ -5,7 +5,6 @@ void compiler_init(compiler_t* self, module_t* module)
|
||||||
assert(self);
|
assert(self);
|
||||||
err_init(&self->err);
|
err_init(&self->err);
|
||||||
self->module = module;
|
self->module = module;
|
||||||
self->loc_counter = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void compiler_free(compiler_t* self)
|
void compiler_free(compiler_t* self)
|
||||||
|
@ -28,135 +27,9 @@ void compiler_compile(compiler_t* self,
|
||||||
}
|
}
|
||||||
|
|
||||||
ccm_t* ccm = &self->module->ccm;
|
ccm_t* ccm = &self->module->ccm;
|
||||||
sym_t* sym = &self->module->sym;
|
|
||||||
|
|
||||||
switch (node->kind)
|
switch (node->kind)
|
||||||
{
|
{
|
||||||
case NODE_BLOCK: {
|
|
||||||
|
|
||||||
sym_open_scope(sym);
|
|
||||||
for (size_t i=0; i<node->children.size; i++)
|
|
||||||
{
|
|
||||||
compiler_compile(
|
|
||||||
self,
|
|
||||||
node->children.data[i],
|
|
||||||
prog
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
sym_close_scope(sym);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_BEGIN: {
|
|
||||||
compiler_compile(self, node->children.data[0], prog);
|
|
||||||
} break;
|
|
||||||
case NODE_ASSIGN: {
|
|
||||||
node_t* target = node->children.data[0];
|
|
||||||
node_t* expr = node->children.data[1];
|
|
||||||
|
|
||||||
if (target->kind == NODE_INDEX) {
|
|
||||||
node_t* ident = target->children.data[0];
|
|
||||||
|
|
||||||
sym_entry_t const* entry = sym_try_get_value(
|
|
||||||
sym,
|
|
||||||
ident->value
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
if (!entry) {
|
|
||||||
err_push(&self->err, ident->line,
|
|
||||||
"undefined array '%s'", ident->value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry->is_const) {
|
|
||||||
err_push(&self->err, ident->line,
|
|
||||||
"cannot assign value to constant '%s'",
|
|
||||||
ident->value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
compiler_compile(self, expr, prog);
|
|
||||||
size_t indexes_count = target->children.size - 1;
|
|
||||||
|
|
||||||
for (size_t i=1; i<target->children.size; i++) {
|
|
||||||
compiler_compile(
|
|
||||||
self,
|
|
||||||
target->children.data[i],
|
|
||||||
prog
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
prog_add_instr(prog, OP_PUSH, entry->local_addr);
|
|
||||||
prog_add_instr(prog, OP_ASTORE, indexes_count);
|
|
||||||
} else {
|
|
||||||
compiler_compile(self, expr, prog);
|
|
||||||
int status =
|
|
||||||
sym_try_assign(
|
|
||||||
sym,
|
|
||||||
target->value, self->loc_counter
|
|
||||||
);
|
|
||||||
|
|
||||||
sym_entry_t* entry = sym_try_get_value(
|
|
||||||
sym,
|
|
||||||
target->value
|
|
||||||
);
|
|
||||||
|
|
||||||
assert(entry);
|
|
||||||
|
|
||||||
if (entry->is_const) {
|
|
||||||
err_push(&self->err, target->line,
|
|
||||||
"cannot assign value to constant '%s'",
|
|
||||||
target->value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!status)
|
|
||||||
{
|
|
||||||
err_push(&self->err, target->line,
|
|
||||||
"cannot assign value to '%s'",
|
|
||||||
target->value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
prog_add_instr(prog, OP_LOCAL_STORE, self->loc_counter);
|
|
||||||
|
|
||||||
self->loc_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_CONSTDECL:
|
|
||||||
case NODE_VARDECL: {
|
|
||||||
node_t const* ident = node->children.data[0];
|
|
||||||
node_t* expr = node->children.data[1];
|
|
||||||
|
|
||||||
compiler_compile(self, expr, prog);
|
|
||||||
int status =
|
|
||||||
sym_declare(
|
|
||||||
sym, ident->value,
|
|
||||||
self->loc_counter,
|
|
||||||
node->kind == NODE_CONSTDECL
|
|
||||||
);
|
|
||||||
assert(status);
|
|
||||||
prog_add_instr(prog, OP_LOCAL_STORE, self->loc_counter);
|
|
||||||
self->loc_counter++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_IDENT: {
|
|
||||||
char const* name = node->value;
|
|
||||||
sym_entry_t const* entry = sym_try_get_value(
|
|
||||||
sym,
|
|
||||||
name
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!entry) {
|
|
||||||
err_push(&self->err, node->line,
|
|
||||||
"undefined '%s'", name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
prog_add_instr(prog, OP_LOCAL_LOAD, entry->local_addr);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case NODE_ARRAY: {
|
case NODE_ARRAY: {
|
||||||
for (size_t i=0; i<node->children.size; i++)
|
for (size_t i=0; i<node->children.size; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
module_t* module;
|
module_t* module;
|
||||||
err_t err;
|
err_t err;
|
||||||
int loc_counter;
|
|
||||||
} compiler_t;
|
} compiler_t;
|
||||||
|
|
||||||
void compiler_init(compiler_t* self, module_t* module);
|
void compiler_init(compiler_t* self, module_t* module);
|
||||||
|
|
73
lib/exec.c
73
lib/exec.c
|
@ -44,22 +44,6 @@ void exec_instr(exec_t* self,
|
||||||
|
|
||||||
switch (op)
|
switch (op)
|
||||||
{
|
{
|
||||||
case OP_LOCAL_STORE: {
|
|
||||||
CCM value = ccm_pop(ccm);
|
|
||||||
int addr = param;
|
|
||||||
|
|
||||||
ccm_set(ccm, value, addr);
|
|
||||||
ccm_push(ccm, value);
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_LOCAL_LOAD: {
|
|
||||||
int addr = param;
|
|
||||||
CCM value = ccm_get(ccm, addr);
|
|
||||||
ccm_push(ccm, value);
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_MK_ARRAY: {
|
case OP_MK_ARRAY: {
|
||||||
vec_t* vec = malloc(sizeof(vec_t));
|
vec_t* vec = malloc(sizeof(vec_t));
|
||||||
vec_init(vec);
|
vec_init(vec);
|
||||||
|
@ -70,11 +54,7 @@ void exec_instr(exec_t* self,
|
||||||
vec_push(vec, ccm_to_value(ccm, element));
|
vec_push(vec, ccm_to_value(ccm, element));
|
||||||
}
|
}
|
||||||
|
|
||||||
int line = 0;
|
int line = ((value_t*) vec->data[0])->line;
|
||||||
|
|
||||||
if (vec->size > 0) {
|
|
||||||
line = ((value_t*) vec->data[0])->line;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t addr = ccm_store_global(
|
size_t addr = ccm_store_global(
|
||||||
ccm,
|
ccm,
|
||||||
|
@ -100,36 +80,6 @@ void exec_instr(exec_t* self,
|
||||||
self->pc++;
|
self->pc++;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case OP_ASTORE: {
|
|
||||||
int addr = ccm_pop(ccm);
|
|
||||||
CCM ccm_gaddr = ccm_get(ccm, addr);
|
|
||||||
int gaddr = ccm_from_ref(ccm, ccm_gaddr);
|
|
||||||
|
|
||||||
CCM ccm_target = ccm_load_global(ccm, gaddr);
|
|
||||||
value_t* target = ccm_to_value(ccm, ccm_target);
|
|
||||||
|
|
||||||
int indexes[param];
|
|
||||||
memset(indexes, 0, param * sizeof(int));
|
|
||||||
|
|
||||||
for (int i=0; i<param; i++) {
|
|
||||||
CCM ccm_idx = ccm_pop(ccm);
|
|
||||||
int idx = ccm_from_num(ccm, ccm_idx);
|
|
||||||
indexes[param - 1 - i] = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<param-1; i++)
|
|
||||||
{
|
|
||||||
target = target->data.array->data[indexes[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
CCM ccm_expr = ccm_pop(ccm);
|
|
||||||
value_t* expr = ccm_to_value(ccm, ccm_expr);
|
|
||||||
target->data.array->data[indexes[param - 1]]
|
|
||||||
= expr;
|
|
||||||
ccm_push(ccm, ccm_expr);
|
|
||||||
self->pc++;
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case OP_INDEX: {
|
case OP_INDEX: {
|
||||||
CCM ccm_target = ccm_pop(ccm);
|
CCM ccm_target = ccm_pop(ccm);
|
||||||
|
|
||||||
|
@ -215,21 +165,16 @@ void exec_instr(exec_t* self,
|
||||||
CCM ccm_result = ccm_from_value(ccm, result);
|
CCM ccm_result = ccm_from_value(ccm, result);
|
||||||
|
|
||||||
if (ccm_is_array(ccm, ccm_result)) {
|
if (ccm_is_array(ccm, ccm_result)) {
|
||||||
CCM ref = ccm_to_ref(
|
CCM ref = ccm_to_ref(ccm,
|
||||||
ccm,
|
|
||||||
ccm_store_global(ccm, ccm_result),
|
ccm_store_global(ccm, ccm_result),
|
||||||
result->line
|
result->line);
|
||||||
);
|
|
||||||
ccm_push(ccm, ref);
|
ccm_push(ccm, ref);
|
||||||
} else {
|
} else {
|
||||||
ccm_push(ccm, ccm_result);
|
ccm_push(ccm, ccm_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
value_t const* val = ccm_to_value(ccm, ccm_target);
|
assert(0);
|
||||||
err_push(&self->err, val->line,
|
|
||||||
"not an array");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self->pc++;
|
self->pc++;
|
||||||
|
@ -265,6 +210,9 @@ void exec_instr(exec_t* self,
|
||||||
|
|
||||||
case OP_ASSERT_NE:
|
case OP_ASSERT_NE:
|
||||||
case OP_ASSERT_EQ: {
|
case OP_ASSERT_EQ: {
|
||||||
|
// TODO: bug here
|
||||||
|
// [1] == [1] -> OK
|
||||||
|
// assert_eq ([1], [1]) -> Failed
|
||||||
CCM val = ccm_pop(ccm);
|
CCM val = ccm_pop(ccm);
|
||||||
vec_t* values = ccm_from_tuple(ccm, val);
|
vec_t* values = ccm_from_tuple(ccm, val);
|
||||||
assert(values->size == 2);
|
assert(values->size == 2);
|
||||||
|
@ -307,13 +255,6 @@ void exec_instr(exec_t* self,
|
||||||
"assertion failed: <%s> %s <%s>",
|
"assertion failed: <%s> %s <%s>",
|
||||||
lhs, operator, rhs
|
lhs, operator, rhs
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
ccm_push(ccm,
|
|
||||||
ccm_to_boolean(
|
|
||||||
ccm, 1,
|
|
||||||
((value_t*) values->data[0])->line
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self->pc++;
|
self->pc++;
|
||||||
|
|
55
lib/lexer.c
55
lib/lexer.c
|
@ -32,7 +32,6 @@ void lexer_init(lexer_t* self)
|
||||||
lexer_add_text(self, "%", NODE_MOD);
|
lexer_add_text(self, "%", NODE_MOD);
|
||||||
lexer_add_text(self, "[", NODE_OSQUARE);
|
lexer_add_text(self, "[", NODE_OSQUARE);
|
||||||
lexer_add_text(self, "]", NODE_CSQUARE);
|
lexer_add_text(self, "]", NODE_CSQUARE);
|
||||||
lexer_add_text(self, "=", NODE_ASSIGN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void lexer_free(lexer_t* self)
|
void lexer_free(lexer_t* self)
|
||||||
|
@ -171,10 +170,6 @@ node_t* lexer_try_new_next(lexer_t* self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CCM_KEYWORD("begin", NODE_BEGIN, 0);
|
|
||||||
CCM_KEYWORD("end", NODE_END, 0);
|
|
||||||
CCM_KEYWORD("var", NODE_VAR, 0);
|
|
||||||
CCM_KEYWORD("const", NODE_CONST, 0);
|
|
||||||
CCM_KEYWORD("assert_eq", NODE_ASSERT_EQ, 0);
|
CCM_KEYWORD("assert_eq", NODE_ASSERT_EQ, 0);
|
||||||
CCM_KEYWORD("assert_ne", NODE_ASSERT_NE, 0);
|
CCM_KEYWORD("assert_ne", NODE_ASSERT_NE, 0);
|
||||||
CCM_KEYWORD("true", NODE_BOOL, 1);
|
CCM_KEYWORD("true", NODE_BOOL, 1);
|
||||||
|
@ -184,13 +179,7 @@ node_t* lexer_try_new_next(lexer_t* self)
|
||||||
CCM_KEYWORD("not", NODE_NOT, 0);
|
CCM_KEYWORD("not", NODE_NOT, 0);
|
||||||
CCM_KEYWORD("in", NODE_IN, 0);
|
CCM_KEYWORD("in", NODE_IN, 0);
|
||||||
|
|
||||||
if ( (node = lexer_try_new_ident(self)) )
|
|
||||||
{
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self->cursor < (ssize_t) strlen(self->source))
|
if (self->cursor < (ssize_t) strlen(self->source))
|
||||||
|
|
||||||
{
|
{
|
||||||
str_t s;
|
str_t s;
|
||||||
str_init(&s);
|
str_init(&s);
|
||||||
|
@ -452,47 +441,3 @@ node_t* lexer_try_new_str(lexer_t* self)
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t* lexer_try_new_ident(lexer_t* self)
|
|
||||||
{
|
|
||||||
int cursor = self->cursor;
|
|
||||||
str_t value;
|
|
||||||
str_init(&value);
|
|
||||||
|
|
||||||
if (cursor >= (ssize_t) strlen(self->source)
|
|
||||||
|| !lexer_is_ident_start(self, self->source[cursor]))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
str_push(&value, self->source[cursor]);
|
|
||||||
cursor++;
|
|
||||||
|
|
||||||
while (cursor < (ssize_t) strlen(self->source)
|
|
||||||
&& lexer_is_ident(self, self->source[cursor]))
|
|
||||||
{
|
|
||||||
str_push(&value, self->source[cursor]);
|
|
||||||
cursor++;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* node = malloc(sizeof(node_t));
|
|
||||||
node_init(node, NODE_IDENT, value.value, self->line);
|
|
||||||
str_free(&value);
|
|
||||||
self->cursor = cursor;
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
int lexer_is_ident_start(lexer_t* lexer, char c)
|
|
||||||
{
|
|
||||||
assert(lexer);
|
|
||||||
|
|
||||||
return isalpha(c)
|
|
||||||
|| c == '_'
|
|
||||||
|| c == '?'
|
|
||||||
|| c == '!';
|
|
||||||
}
|
|
||||||
|
|
||||||
int lexer_is_ident(lexer_t* lexer, char c)
|
|
||||||
{
|
|
||||||
return isdigit(c)
|
|
||||||
|| lexer_is_ident_start(lexer, c);
|
|
||||||
}
|
|
||||||
|
|
|
@ -54,8 +54,4 @@ node_t* lexer_try_new_text(lexer_t* self,
|
||||||
|
|
||||||
node_t* lexer_try_new_num(lexer_t* self);
|
node_t* lexer_try_new_num(lexer_t* self);
|
||||||
node_t* lexer_try_new_str(lexer_t* self);
|
node_t* lexer_try_new_str(lexer_t* self);
|
||||||
node_t* lexer_try_new_ident(lexer_t* self);
|
|
||||||
int lexer_is_ident_start(lexer_t* lexer, char c);
|
|
||||||
int lexer_is_ident(lexer_t* lexer, char c);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
19
lib/module.c
19
lib/module.c
|
@ -10,16 +10,12 @@ void module_init(module_t* self)
|
||||||
prog_init(&self->prog);
|
prog_init(&self->prog);
|
||||||
err_init(&self->err);
|
err_init(&self->err);
|
||||||
ccm_init(&self->ccm);
|
ccm_init(&self->ccm);
|
||||||
sym_init(&self->sym);
|
|
||||||
sym_open_scope(&self->sym);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void module_free(module_t* self)
|
void module_free(module_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
sym_free(&self->sym);
|
|
||||||
|
|
||||||
if (self->source)
|
if (self->source)
|
||||||
{
|
{
|
||||||
free(self->source);
|
free(self->source);
|
||||||
|
@ -34,7 +30,6 @@ int module_load(module_t* self, char const* path)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(path);
|
assert(path);
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
if (module_load_source(self, path) != 0)
|
if (module_load_source(self, path) != 0)
|
||||||
{
|
{
|
||||||
|
@ -50,33 +45,25 @@ int module_load(module_t* self, char const* path)
|
||||||
parser_init(&parser, &lexer);
|
parser_init(&parser, &lexer);
|
||||||
|
|
||||||
node_t* ast = parser_try_new_parse(&parser);
|
node_t* ast = parser_try_new_parse(&parser);
|
||||||
|
|
||||||
if (!err_is_ok(&lexer.err) || !err_is_ok(&parser.err))
|
if (!err_is_ok(&lexer.err) || !err_is_ok(&parser.err))
|
||||||
{
|
{
|
||||||
err_print_stack_trace(&lexer.err);
|
err_print_stack_trace(&lexer.err);
|
||||||
err_print_stack_trace(&parser.err);
|
err_print_stack_trace(&parser.err);
|
||||||
err_push(&self->err, lexer.line, "invalid module");
|
err_push(&self->err, lexer.line, "invalid module");
|
||||||
status = 1;
|
|
||||||
goto free_parser;
|
goto free_parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ast)
|
if (!ast)
|
||||||
{
|
{
|
||||||
status = 1;
|
|
||||||
goto free_parser;
|
goto free_parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
compiler_t compiler;
|
compiler_t compiler;
|
||||||
compiler_init(&compiler, self);
|
compiler_init(&compiler, self);
|
||||||
|
|
||||||
compiler_compile(&compiler, ast, &self->prog);
|
compiler_compile(&compiler, ast, &self->prog);
|
||||||
|
|
||||||
if (!err_is_ok(&compiler.err))
|
|
||||||
{
|
|
||||||
err_print_stack_trace(&compiler.err);
|
|
||||||
status = 1;
|
|
||||||
goto free_compiler;
|
|
||||||
}
|
|
||||||
|
|
||||||
free_compiler:
|
|
||||||
compiler_free(&compiler);
|
compiler_free(&compiler);
|
||||||
node_free(ast);
|
node_free(ast);
|
||||||
free(ast);
|
free(ast);
|
||||||
|
@ -84,7 +71,7 @@ free_parser:
|
||||||
parser_free(&parser);
|
parser_free(&parser);
|
||||||
lexer_free(&lexer);
|
lexer_free(&lexer);
|
||||||
|
|
||||||
return status;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int module_load_source(module_t* self, char const* path)
|
int module_load_source(module_t* self, char const* path)
|
||||||
|
|
|
@ -5,14 +5,12 @@
|
||||||
#include "prog.h"
|
#include "prog.h"
|
||||||
#include "err.h"
|
#include "err.h"
|
||||||
#include "ccm.h"
|
#include "ccm.h"
|
||||||
#include "sym.h"
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
err_t err;
|
err_t err;
|
||||||
char* source;
|
char* source;
|
||||||
prog_t prog;
|
prog_t prog;
|
||||||
ccm_t ccm;
|
ccm_t ccm;
|
||||||
sym_t sym;
|
|
||||||
} module_t;
|
} module_t;
|
||||||
|
|
||||||
void module_init(module_t* self);
|
void module_init(module_t* self);
|
||||||
|
|
|
@ -13,10 +13,7 @@ G(NODE_ASSERT_EQ), G(NODE_ASSERT_NE), G(NODE_BOOL), \
|
||||||
G(NODE_AND), G(NODE_OR), G(NODE_NOT), G(NODE_IN), \
|
G(NODE_AND), G(NODE_OR), G(NODE_NOT), G(NODE_IN), \
|
||||||
G(NODE_OSQUARE), G(NODE_CSQUARE), G(NODE_INDEX), \
|
G(NODE_OSQUARE), G(NODE_CSQUARE), G(NODE_INDEX), \
|
||||||
G(NODE_STR), G(NODE_LT), G(NODE_LE), G(NODE_GT), \
|
G(NODE_STR), G(NODE_LT), G(NODE_LE), G(NODE_GT), \
|
||||||
G(NODE_GE), G(NODE_EQ), G(NODE_NE), G(NODE_ARRAY), \
|
G(NODE_GE), G(NODE_EQ), G(NODE_NE), G(NODE_ARRAY)
|
||||||
G(NODE_VAR), G(NODE_IDENT), G(NODE_ASSIGN), \
|
|
||||||
G(NODE_VARDECL), G(NODE_CONST), G(NODE_CONSTDECL), \
|
|
||||||
G(NODE_BEGIN), G(NODE_BLOCK), G(NODE_END)
|
|
||||||
|
|
||||||
CCM_ENUM_H(NodeKind, NODE_KIND);
|
CCM_ENUM_H(NodeKind, NODE_KIND);
|
||||||
|
|
||||||
|
|
240
lib/parser.c
240
lib/parser.c
|
@ -26,21 +26,7 @@ node_t* parser_try_new_parse(parser_t* self)
|
||||||
|
|
||||||
if (self->lexer->cursor < (ssize_t)strlen(self->lexer->source))
|
if (self->lexer->cursor < (ssize_t)strlen(self->lexer->source))
|
||||||
{
|
{
|
||||||
str_t s;
|
err_push(&self->err, res ? res->line : 0, "unexpected end");
|
||||||
str_init(&s);
|
|
||||||
|
|
||||||
while (self->lexer->cursor
|
|
||||||
< (ssize_t)strlen(self->lexer->source)
|
|
||||||
&& !isspace(self->lexer->source[self->lexer->cursor]))
|
|
||||||
{
|
|
||||||
str_push(&s, self->lexer->source[self->lexer->cursor]);
|
|
||||||
self->lexer->cursor++;
|
|
||||||
}
|
|
||||||
|
|
||||||
err_push(&self->err, res ? res->line : 0,
|
|
||||||
"unexpected end after '%s'", s.value);
|
|
||||||
str_free(&s);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -135,155 +121,15 @@ node_t* parser_try_new_expr(parser_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
if (lexer_peek_kind(self->lexer, NODE_VAR, 0)
|
|
||||||
|| lexer_peek_kind(self->lexer, NODE_CONST, 0))
|
|
||||||
{
|
|
||||||
return CCM_TRY(parser_try_new_decl);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (lexer_peek_kind(self->lexer, NODE_ASSERT_EQ, 0)
|
if (lexer_peek_kind(self->lexer, NODE_ASSERT_EQ, 0)
|
||||||
|| lexer_peek_kind(self->lexer, NODE_ASSERT_NE, 0))
|
|| lexer_peek_kind(self->lexer, NODE_ASSERT_NE, 0))
|
||||||
{
|
{
|
||||||
return CCM_TRY(parser_try_new_assert);
|
return CCM_TRY(parser_try_new_assert);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lexer_peek_kind(self->lexer, NODE_BEGIN, 0))
|
|
||||||
{
|
|
||||||
return CCM_TRY(parser_try_new_begin);
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* assign = CCM_TRY(parser_try_new_assign);
|
|
||||||
if (assign) { return assign; }
|
|
||||||
|
|
||||||
return CCM_TRY(parser_try_new_or);
|
return CCM_TRY(parser_try_new_or);
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t* parser_try_new_begin(parser_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_BEGIN, 0))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_BEGIN);
|
|
||||||
|
|
||||||
node_t* node = malloc(sizeof(node_t));
|
|
||||||
node_init(node, NODE_BEGIN, "", self->lexer->line);
|
|
||||||
|
|
||||||
node_t* block = CCM_TRY(parser_try_new_block);
|
|
||||||
node_push_new_child(node, block);
|
|
||||||
|
|
||||||
if (!block || !lexer_peek_kind(self->lexer, NODE_END, 0))
|
|
||||||
{
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_END);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* parser_try_new_block(parser_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
node_t* node = malloc(sizeof(node_t));
|
|
||||||
node_init(node, NODE_BLOCK, "", self->lexer->line);
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
node_t* expr = CCM_TRY(parser_try_new_expr);
|
|
||||||
if (!expr) { break; }
|
|
||||||
|
|
||||||
node_push_new_child(node, expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* parser_try_new_assign(parser_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
node_t* target = CCM_TRY(parser_try_new_index);
|
|
||||||
|
|
||||||
if (!target && lexer_peek_kind(self->lexer, NODE_IDENT, 0)) {
|
|
||||||
target = lexer_try_new_next(self->lexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_ASSIGN, 0))
|
|
||||||
{
|
|
||||||
node_free(target); free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_ASSIGN);
|
|
||||||
node_t* expr = CCM_TRY(parser_try_new_expr);
|
|
||||||
|
|
||||||
if (!expr)
|
|
||||||
{
|
|
||||||
node_free(target); free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* node = malloc(sizeof(node_t));
|
|
||||||
node_init(node, NODE_ASSIGN, "", self->lexer->line);
|
|
||||||
node_push_new_child(node, target);
|
|
||||||
node_push_new_child(node, expr);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* parser_try_new_decl(parser_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
int is_const = 0;
|
|
||||||
|
|
||||||
if (lexer_peek_kind(self->lexer, NODE_VAR, 0)) {
|
|
||||||
lexer_consume_next(self->lexer, NODE_VAR);
|
|
||||||
} else if (lexer_peek_kind(self->lexer, NODE_CONST, 0)) {
|
|
||||||
lexer_consume_next(self->lexer, NODE_CONST);
|
|
||||||
is_const = 1;
|
|
||||||
} else {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_IDENT, 0))
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* ident = lexer_try_new_next(self->lexer);
|
|
||||||
|
|
||||||
if (!lexer_consume_next(self->lexer, NODE_ASSIGN))
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* expr = CCM_TRY(parser_try_new_expr);
|
|
||||||
if (!expr)
|
|
||||||
{
|
|
||||||
node_free(ident); free(ident);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* node = malloc(sizeof(node_t));
|
|
||||||
node_init(node, is_const ? NODE_CONSTDECL : NODE_VARDECL,
|
|
||||||
"", self->lexer->line);
|
|
||||||
|
|
||||||
node_push_new_child(node, ident);
|
|
||||||
node_push_new_child(node, expr);
|
|
||||||
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
node_t* parser_try_new_assert(parser_t* self)
|
node_t* parser_try_new_assert(parser_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -632,12 +478,15 @@ node_t* parser_try_new_literal(parser_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
node_t* index = CCM_TRY(parser_try_new_index);
|
|
||||||
if (index) { return index; }
|
|
||||||
|
|
||||||
if (lexer_peek_kind(self->lexer, NODE_OSQUARE, 0))
|
if (lexer_peek_kind(self->lexer, NODE_OSQUARE, 0))
|
||||||
{
|
{
|
||||||
node_t* array = CCM_TRY(parser_try_new_array);
|
node_t* array = CCM_TRY(parser_try_new_array);
|
||||||
|
|
||||||
|
if (lexer_peek_kind(self->lexer, NODE_OSQUARE, 0))
|
||||||
|
{
|
||||||
|
return CCM_TRY_LL1(parser_try_new_index, array);
|
||||||
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,6 +496,11 @@ node_t* parser_try_new_literal(parser_t* self)
|
||||||
|
|
||||||
if (tuple)
|
if (tuple)
|
||||||
{
|
{
|
||||||
|
if (lexer_peek_kind(self->lexer, NODE_OSQUARE, 0))
|
||||||
|
{
|
||||||
|
return CCM_TRY_LL1(parser_try_new_index, tuple);
|
||||||
|
}
|
||||||
|
|
||||||
return tuple;
|
return tuple;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -672,6 +526,13 @@ node_t* parser_try_new_literal(parser_t* self)
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lexer_peek_kind(self->lexer, NODE_STR, 0)
|
||||||
|
&& lexer_peek_kind(self->lexer, NODE_OSQUARE, 1))
|
||||||
|
{
|
||||||
|
node_t* target = CCM_TRY(parser_try_new_builtin);
|
||||||
|
return CCM_TRY_LL1(parser_try_new_index, target);
|
||||||
|
}
|
||||||
|
|
||||||
return CCM_TRY(parser_try_new_builtin);
|
return CCM_TRY(parser_try_new_builtin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,12 +543,6 @@ node_t* parser_try_new_array(parser_t* self)
|
||||||
node_t* node = malloc(sizeof(node_t));
|
node_t* node = malloc(sizeof(node_t));
|
||||||
node_init(node, NODE_ARRAY, "", self->lexer->line);
|
node_init(node, NODE_ARRAY, "", self->lexer->line);
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_OSQUARE, 0))
|
|
||||||
{
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_OSQUARE);
|
lexer_consume_next(self->lexer, NODE_OSQUARE);
|
||||||
|
|
||||||
int first = 1;
|
int first = 1;
|
||||||
|
@ -712,50 +567,15 @@ node_t* parser_try_new_array(parser_t* self)
|
||||||
first = 0;
|
first = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_CSQUARE, 0))
|
|
||||||
{
|
|
||||||
node_free(node); free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_CSQUARE);
|
lexer_consume_next(self->lexer, NODE_CSQUARE);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t* parser_try_new_index(parser_t* self)
|
node_t* parser_try_new_index(parser_t* self, node_t* target)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
node_t* target = NULL;
|
|
||||||
|
|
||||||
if (lexer_peek_kind(self->lexer, NODE_STR, 0)
|
|
||||||
|| lexer_peek_kind(self->lexer, NODE_IDENT, 0))
|
|
||||||
{
|
|
||||||
target = lexer_try_new_next(self->lexer);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target)
|
|
||||||
{
|
|
||||||
target = CCM_TRY(parser_try_new_tuple);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!target)
|
|
||||||
{
|
|
||||||
target = CCM_TRY(parser_try_new_array);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target == NULL)
|
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_OSQUARE, 0))
|
|
||||||
{
|
|
||||||
node_free(target); free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_OSQUARE);
|
lexer_consume_next(self->lexer, NODE_OSQUARE);
|
||||||
|
|
||||||
node_t* node = malloc(sizeof(node_t));
|
node_t* node = malloc(sizeof(node_t));
|
||||||
|
@ -769,7 +589,6 @@ node_t* parser_try_new_index(parser_t* self)
|
||||||
if (!element)
|
if (!element)
|
||||||
{
|
{
|
||||||
node_free(node); free(node);
|
node_free(node); free(node);
|
||||||
node_free(target); free(target);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -781,13 +600,6 @@ node_t* parser_try_new_index(parser_t* self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_CSQUARE, 0))
|
|
||||||
{
|
|
||||||
node_free(node); free(node);
|
|
||||||
node_free(target); free(target);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_CSQUARE);
|
lexer_consume_next(self->lexer, NODE_CSQUARE);
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
@ -799,15 +611,13 @@ node_t* parser_try_new_tuple(parser_t* self)
|
||||||
node_t* node = malloc(sizeof(node_t));
|
node_t* node = malloc(sizeof(node_t));
|
||||||
node_init(node, NODE_TUPLE, "", self->lexer->line);
|
node_init(node, NODE_TUPLE, "", self->lexer->line);
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_OPAR, 0))
|
if (!lexer_consume_next(self->lexer, NODE_OPAR))
|
||||||
{
|
{
|
||||||
node_free(node);
|
node_free(node);
|
||||||
free(node);
|
free(node);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_OPAR);
|
|
||||||
|
|
||||||
node_t* lhs = CCM_TRY(parser_try_new_expr);
|
node_t* lhs = CCM_TRY(parser_try_new_expr);
|
||||||
|
|
||||||
if (!lhs)
|
if (!lhs)
|
||||||
|
@ -838,13 +648,6 @@ node_t* parser_try_new_tuple(parser_t* self)
|
||||||
contains_more_than_one_expr = 1;
|
contains_more_than_one_expr = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!lexer_peek_kind(self->lexer, NODE_CPAR, 0))
|
|
||||||
{
|
|
||||||
node_free(node);
|
|
||||||
free(node);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
lexer_consume_next(self->lexer, NODE_CPAR);
|
lexer_consume_next(self->lexer, NODE_CPAR);
|
||||||
|
|
||||||
if (!contains_more_than_one_expr)
|
if (!contains_more_than_one_expr)
|
||||||
|
@ -868,7 +671,6 @@ node_t* parser_try_new_builtin(parser_t* self)
|
||||||
node->kind == NODE_NUM
|
node->kind == NODE_NUM
|
||||||
|| node->kind == NODE_BOOL
|
|| node->kind == NODE_BOOL
|
||||||
|| node->kind == NODE_STR
|
|| node->kind == NODE_STR
|
||||||
|| node->kind == NODE_IDENT
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,10 +25,6 @@ int parser_ensure(parser_t* self, node_t* node, NodeKind kind);
|
||||||
|
|
||||||
node_t* parser_try_new_module(parser_t* self);
|
node_t* parser_try_new_module(parser_t* self);
|
||||||
node_t* parser_try_new_expr(parser_t* self);
|
node_t* parser_try_new_expr(parser_t* self);
|
||||||
node_t* parser_try_new_begin(parser_t* self);
|
|
||||||
node_t* parser_try_new_block(parser_t* self);
|
|
||||||
node_t* parser_try_new_assign(parser_t* self);
|
|
||||||
node_t* parser_try_new_decl(parser_t* self);
|
|
||||||
node_t* parser_try_new_assert(parser_t* self);
|
node_t* parser_try_new_assert(parser_t* self);
|
||||||
node_t* parser_try_new_or(parser_t* self);
|
node_t* parser_try_new_or(parser_t* self);
|
||||||
node_t* parser_try_new_and(parser_t* self);
|
node_t* parser_try_new_and(parser_t* self);
|
||||||
|
@ -42,7 +38,7 @@ node_t* parser_try_new_pow(parser_t* self);
|
||||||
node_t* parser_try_new_in(parser_t* self);
|
node_t* parser_try_new_in(parser_t* self);
|
||||||
node_t* parser_try_new_literal(parser_t* self);
|
node_t* parser_try_new_literal(parser_t* self);
|
||||||
node_t* parser_try_new_array(parser_t* self);
|
node_t* parser_try_new_array(parser_t* self);
|
||||||
node_t* parser_try_new_index(parser_t* self);
|
node_t* parser_try_new_index(parser_t* self, node_t* target);
|
||||||
node_t* parser_try_new_tuple(parser_t* self);
|
node_t* parser_try_new_tuple(parser_t* self);
|
||||||
node_t* parser_try_new_builtin(parser_t* self);
|
node_t* parser_try_new_builtin(parser_t* self);
|
||||||
|
|
||||||
|
|
157
lib/sym.c
157
lib/sym.c
|
@ -1,157 +0,0 @@
|
||||||
#include "sym.h"
|
|
||||||
|
|
||||||
void sym_init(sym_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
self->env = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_free(sym_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
|
|
||||||
if (self->env)
|
|
||||||
{
|
|
||||||
sym_free_env(self, self->env);
|
|
||||||
free(self->env);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_free_env(sym_t* self, env_t* env)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(env);
|
|
||||||
|
|
||||||
if (env->parent)
|
|
||||||
{
|
|
||||||
sym_free_env(self, env->parent);
|
|
||||||
free(env->parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i=0; i<env->entries.size; i++)
|
|
||||||
{
|
|
||||||
sym_entry_t* entry = env->entries.data[i];
|
|
||||||
free(entry->name);
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec_free(&env->entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_open_scope(sym_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
env_t* env = malloc(sizeof(env_t));
|
|
||||||
env->parent = NULL;
|
|
||||||
vec_init(&env->entries);
|
|
||||||
|
|
||||||
if (self->env == NULL) {
|
|
||||||
self->env = env;
|
|
||||||
} else {
|
|
||||||
env->parent = self->env;
|
|
||||||
self->env = env;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void sym_close_scope(sym_t* self)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(self->env);
|
|
||||||
|
|
||||||
for (size_t i=0; i<self->env->entries.size; i++)
|
|
||||||
{
|
|
||||||
sym_entry_t* entry = self->env->entries.data[i];
|
|
||||||
free(entry->name);
|
|
||||||
free(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec_free(&self->env->entries);
|
|
||||||
env_t* parent = self->env->parent;
|
|
||||||
free(self->env);
|
|
||||||
self->env = parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int sym_declare(sym_t* self,
|
|
||||||
char const* name,
|
|
||||||
int addr,
|
|
||||||
int is_const)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(self->env);
|
|
||||||
assert(name);
|
|
||||||
|
|
||||||
if (sym_try_get_env_value(self,self->env, name) != NULL)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
sym_entry_t* entry = malloc(sizeof(sym_entry_t));
|
|
||||||
entry->name = strdup(name);
|
|
||||||
entry->local_addr = addr;
|
|
||||||
entry->is_const = is_const;
|
|
||||||
vec_push(&self->env->entries, entry);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int sym_try_assign(sym_t* self,
|
|
||||||
char const* name,
|
|
||||||
int addr)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(name);
|
|
||||||
sym_entry_t* entry = sym_try_get_value(self, name);
|
|
||||||
|
|
||||||
if (!entry) { return 0; }
|
|
||||||
|
|
||||||
entry->local_addr = addr;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
sym_entry_t* sym_try_get_value(sym_t* self, char const* name)
|
|
||||||
{
|
|
||||||
assert(self);
|
|
||||||
assert(name);
|
|
||||||
|
|
||||||
env_t* env = self->env;
|
|
||||||
|
|
||||||
while (env)
|
|
||||||
{
|
|
||||||
sym_entry_t* entry = sym_try_get_env_value(
|
|
||||||
self,
|
|
||||||
env,
|
|
||||||
name
|
|
||||||
);
|
|
||||||
|
|
||||||
if (entry)
|
|
||||||
{
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
env = env->parent;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sym_entry_t* sym_try_get_env_value(sym_t* self,
|
|
||||||
env_t* env,
|
|
||||||
char const* name)
|
|
||||||
{
|
|
||||||
assert(self); assert(env); assert(name);
|
|
||||||
|
|
||||||
for (size_t i=0; i<env->entries.size; i++)
|
|
||||||
{
|
|
||||||
sym_entry_t const* entry =
|
|
||||||
((sym_entry_t*) env->entries.data[i]);
|
|
||||||
|
|
||||||
if (strcmp(entry->name, name) == 0)
|
|
||||||
{
|
|
||||||
return env->entries.data[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
44
lib/sym.h
44
lib/sym.h
|
@ -1,44 +0,0 @@
|
||||||
#ifndef CCM_SYM_H
|
|
||||||
#define CCM_SYM_H
|
|
||||||
|
|
||||||
#include "commons.h"
|
|
||||||
#include "vec.h"
|
|
||||||
#include "value.h"
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char* name;
|
|
||||||
int local_addr;
|
|
||||||
int is_const;
|
|
||||||
} sym_entry_t;
|
|
||||||
|
|
||||||
typedef struct env {
|
|
||||||
vec_t entries;
|
|
||||||
struct env* parent;
|
|
||||||
} env_t;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
env_t* env;
|
|
||||||
} sym_t;
|
|
||||||
|
|
||||||
void sym_init(sym_t* self);
|
|
||||||
void sym_free(sym_t* self);
|
|
||||||
void sym_free_env(sym_t* self, env_t* env);
|
|
||||||
|
|
||||||
void sym_open_scope(sym_t* self);
|
|
||||||
void sym_close_scope(sym_t* self);
|
|
||||||
|
|
||||||
int sym_declare(sym_t* self,
|
|
||||||
char const* name,
|
|
||||||
int addr,
|
|
||||||
int is_const);
|
|
||||||
|
|
||||||
int sym_try_assign(sym_t* self,
|
|
||||||
char const* name,
|
|
||||||
int addr);
|
|
||||||
|
|
||||||
sym_entry_t* sym_try_get_value(sym_t* self, char const* name);
|
|
||||||
sym_entry_t* sym_try_get_env_value(sym_t* self,
|
|
||||||
env_t* env,
|
|
||||||
char const* name);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,36 +0,0 @@
|
||||||
var a = 12
|
|
||||||
|
|
||||||
begin
|
|
||||||
a = 32
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_eq (32, a)
|
|
||||||
|
|
||||||
# SHADOWING
|
|
||||||
# =========
|
|
||||||
|
|
||||||
var b = 34
|
|
||||||
|
|
||||||
begin
|
|
||||||
var b = "bim"
|
|
||||||
assert_eq ("bim", b)
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_eq(34, b)
|
|
||||||
|
|
||||||
# NESTED BLOCKS
|
|
||||||
# =============
|
|
||||||
var c = "hello"
|
|
||||||
|
|
||||||
begin
|
|
||||||
var c = "world"
|
|
||||||
begin
|
|
||||||
var c = "pizza"
|
|
||||||
c = "cat"
|
|
||||||
assert_eq ("cat", c)
|
|
||||||
end
|
|
||||||
assert_eq ("world", c)
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_eq ("hello", c)
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
# DECLARATION
|
|
||||||
# ===========
|
|
||||||
var a = 32
|
|
||||||
assert_eq (32, a)
|
|
||||||
|
|
||||||
var b = a + 1
|
|
||||||
assert_eq(33, b)
|
|
||||||
|
|
||||||
var c = (var d = 3)
|
|
||||||
assert_eq(3, c)
|
|
||||||
assert_eq(3, d)
|
|
||||||
|
|
||||||
var e = [1, 2]
|
|
||||||
assert_eq (2, e[-1])
|
|
||||||
|
|
||||||
var f = [2, 3]
|
|
||||||
var g = 1
|
|
||||||
|
|
||||||
assert_eq (3, f[g])
|
|
||||||
|
|
||||||
# ASSIGN
|
|
||||||
# ======
|
|
||||||
var h = 34
|
|
||||||
h = 37
|
|
||||||
assert_eq (37, h)
|
|
||||||
|
|
||||||
var i = [2, 3, 4]
|
|
||||||
i[2] = 7
|
|
||||||
assert_eq ([2, 3, 7], i)
|
|
||||||
|
|
||||||
var j = [[1, 2], [3, 4]]
|
|
||||||
j[1, 0] = 99
|
|
||||||
assert_eq ([[1, 2], [99, 4]], j)
|
|
Loading…
Reference in New Issue