ADD: do blocks.
parent
502a31d5c9
commit
76497315da
|
@ -24,7 +24,14 @@ void compile_node(compiler* self, node* root, program* prog)
|
||||||
assert(root);
|
assert(root);
|
||||||
assert(prog);
|
assert(prog);
|
||||||
|
|
||||||
if (root->type == NODE_INDEX)
|
if (root->type == NODE_DO)
|
||||||
|
{
|
||||||
|
symtable_enter_scope(self->sym);
|
||||||
|
compile_children(self, root, prog);
|
||||||
|
symtable_leave_scope(self->sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (root->type == NODE_INDEX)
|
||||||
{
|
{
|
||||||
compile_children(self, root, prog);
|
compile_children(self, root, prog);
|
||||||
program_add_instr(prog, OP_ADEREF, NO_PARAM);
|
program_add_instr(prog, OP_ADEREF, NO_PARAM);
|
||||||
|
|
|
@ -43,6 +43,14 @@ type* cstatic_resolve_new(cstatic* self, symtable* sym, node* ast)
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ast->type == NODE_DO)
|
||||||
|
{
|
||||||
|
type* ty = cstatic_resolve_new(self,
|
||||||
|
sym,
|
||||||
|
ast->children.data[0]);
|
||||||
|
return ty;
|
||||||
|
}
|
||||||
|
|
||||||
if (ast->type == NODE_VARDECL)
|
if (ast->type == NODE_VARDECL)
|
||||||
{
|
{
|
||||||
type* ty = cstatic_resolve_new(self,
|
type* ty = cstatic_resolve_new(self,
|
||||||
|
@ -220,6 +228,28 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(ast);
|
assert(ast);
|
||||||
|
|
||||||
|
// DO BLOCK
|
||||||
|
if (ast->type == NODE_DO)
|
||||||
|
{
|
||||||
|
symtable_enter_scope(sym);
|
||||||
|
|
||||||
|
for (size_t i=0; i<ast->children.size; i++)
|
||||||
|
{
|
||||||
|
int status = cstatic_check(self,
|
||||||
|
ast->children.data[i],
|
||||||
|
sym, msg, size);
|
||||||
|
|
||||||
|
if (!status)
|
||||||
|
{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
symtable_leave_scope(sym);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// Children
|
// Children
|
||||||
for (size_t i=0; i<ast->children.size; i++)
|
for (size_t i=0; i<ast->children.size; i++)
|
||||||
{
|
{
|
||||||
|
@ -417,8 +447,9 @@ int cstatic_check(cstatic* self, node* ast, symtable* sym, char* msg, size_t siz
|
||||||
|| ast->type == NODE_CONSTDECL)
|
|| ast->type == NODE_CONSTDECL)
|
||||||
{
|
{
|
||||||
char const* name = ast->children.data[0]->value;
|
char const* name = ast->children.data[0]->value;
|
||||||
|
symentry* entry = symtable_find(sym, name);
|
||||||
|
|
||||||
if (symtable_find(sym, name))
|
if (entry && entry->scope >= sym->scope)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "E(%d): '%s' is already defined.\n",
|
fprintf(stderr, "E(%d): '%s' is already defined.\n",
|
||||||
ast->lineno,
|
ast->lineno,
|
||||||
|
|
|
@ -26,6 +26,8 @@ IDENT [_A-Za-z][_A-Za-z0-9]*
|
||||||
return TYPE;
|
return TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"do" { return DO; }
|
||||||
|
"end" { return END; }
|
||||||
"let!" { return LET_MUT; }
|
"let!" { return LET_MUT; }
|
||||||
"let" { return LET; }
|
"let" { return LET; }
|
||||||
"assert" { return ASSERT; }
|
"assert" { return ASSERT; }
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
G(NODE_MUL), G(NODE_DIV), G(NODE_MOD), G(NODE_POW), \
|
G(NODE_MUL), G(NODE_DIV), G(NODE_MOD), G(NODE_POW), \
|
||||||
G(NODE_ARRAY), G(NODE_INDEX), G(NODE_LT), G(NODE_LE), \
|
G(NODE_ARRAY), G(NODE_INDEX), G(NODE_LT), G(NODE_LE), \
|
||||||
G(NODE_GT), G(NODE_GE), G(NODE_VARDECL), G(NODE_IDENT), \
|
G(NODE_GT), G(NODE_GE), G(NODE_VARDECL), G(NODE_IDENT), \
|
||||||
G(NODE_CONSTDECL), G(NODE_ASSIGN)
|
G(NODE_CONSTDECL), G(NODE_ASSIGN), G(NODE_DO)
|
||||||
|
|
||||||
|
|
||||||
#include "mutils.h"
|
#include "mutils.h"
|
||||||
|
|
28
src/parser.y
28
src/parser.y
|
@ -35,7 +35,7 @@
|
||||||
%left NOT
|
%left NOT
|
||||||
%token OPAR CPAR
|
%token OPAR CPAR
|
||||||
%token OSQUARE CSQUARE COMMA
|
%token OSQUARE CSQUARE COMMA
|
||||||
%token LET LET_MUT ASSIGN
|
%token LET LET_MUT ASSIGN DO END
|
||||||
%type <n_children> expr_unop
|
%type <n_children> expr_unop
|
||||||
|
|
||||||
%%
|
%%
|
||||||
|
@ -78,8 +78,32 @@ exprs:
|
||||||
|
|
||||||
|
|
||||||
expr:
|
expr:
|
||||||
|
// BLOCK
|
||||||
|
DO exprs END {
|
||||||
|
node *n = malloc(sizeof(node));
|
||||||
|
node_init(n, NODE_DO, "", line);
|
||||||
|
|
||||||
|
size_t const SZ = $2;
|
||||||
|
node* all[SZ];
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
all[SZ - 1 - i] = stack_pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i=0; i<SZ; i++)
|
||||||
|
{
|
||||||
|
node_add_child(n, all[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack_push(n);
|
||||||
|
|
||||||
|
$$ = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// INDEX
|
// INDEX
|
||||||
expr array ASSIGN expr {
|
| expr array ASSIGN expr {
|
||||||
node* n = malloc(sizeof(node));
|
node* n = malloc(sizeof(node));
|
||||||
node_init(n, NODE_ASSIGN, "", line);
|
node_init(n, NODE_ASSIGN, "", line);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ void symtable_init(symtable* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
self->id = 0;
|
self->id = 0;
|
||||||
|
self->scope = 0;
|
||||||
self->entries.size = 0;
|
self->entries.size = 0;
|
||||||
self->entries.capacity = 1;
|
self->entries.capacity = 1;
|
||||||
self->entries.data = malloc(sizeof(symentry*)
|
self->entries.data = malloc(sizeof(symentry*)
|
||||||
|
@ -17,14 +17,9 @@ void symtable_free(symtable* self)
|
||||||
|
|
||||||
for (size_t i=0; i<self->entries.size; i++)
|
for (size_t i=0; i<self->entries.size; i++)
|
||||||
{
|
{
|
||||||
node_free(self->entries.data[i]->sym_node);
|
symentry_free(self->entries.data[i]);
|
||||||
free(self->entries.data[i]->sym_node);
|
|
||||||
self->entries.data[i]->sym_node = NULL;
|
|
||||||
|
|
||||||
free(self->entries.data[i]->name);
|
|
||||||
type_free(self->entries.data[i]->ty);
|
|
||||||
free(self->entries.data[i]->ty);
|
|
||||||
free(self->entries.data[i]);
|
free(self->entries.data[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(self->entries.data);
|
free(self->entries.data);
|
||||||
|
@ -34,6 +29,19 @@ void symtable_free(symtable* self)
|
||||||
self->entries.data = NULL;
|
self->entries.data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void symentry_free(symentry* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
node_free(self->sym_node);
|
||||||
|
free(self->sym_node);
|
||||||
|
self->sym_node = NULL;
|
||||||
|
|
||||||
|
free(self->name);
|
||||||
|
type_free(self->ty);
|
||||||
|
free(self->ty);
|
||||||
|
}
|
||||||
|
|
||||||
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node)
|
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
@ -67,6 +75,7 @@ size_t symtable_declare(symtable* self, char const* name, type* ty, node* sym_no
|
||||||
self->entries.data[self->entries.size]->ty = type_new_clone(ty);
|
self->entries.data[self->entries.size]->ty = type_new_clone(ty);
|
||||||
self->entries.data[self->entries.size]->id = self->id;
|
self->entries.data[self->entries.size]->id = self->id;
|
||||||
self->entries.data[self->entries.size]->is_mut = 0;
|
self->entries.data[self->entries.size]->is_mut = 0;
|
||||||
|
self->entries.data[self->entries.size]->scope = self->scope;
|
||||||
self->entries.data[self->entries.size]->sym_node = node_new_clone(sym_node);
|
self->entries.data[self->entries.size]->sym_node = node_new_clone(sym_node);
|
||||||
self->entries.size++;
|
self->entries.size++;
|
||||||
|
|
||||||
|
@ -76,14 +85,51 @@ size_t symtable_declare(symtable* self, char const* name, type* ty, node* sym_no
|
||||||
symentry* symtable_find(symtable* self, char const* name)
|
symentry* symtable_find(symtable* self, char const* name)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
int scope_max = 0;
|
||||||
|
symentry* entry = NULL;
|
||||||
|
|
||||||
for (size_t i=0; i<self->entries.size; i++)
|
for (size_t i=0; i<self->entries.size; i++)
|
||||||
{
|
{
|
||||||
if (strcmp(self->entries.data[i]->name, name) == 0)
|
if (strcmp(self->entries.data[i]->name, name) == 0)
|
||||||
{
|
{
|
||||||
return self->entries.data[i];
|
if (entry == NULL
|
||||||
|
|| self->entries.data[i]->scope > scope_max)
|
||||||
|
{
|
||||||
|
entry = self->entries.data[i];
|
||||||
|
scope_max = entry->scope;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
void symtable_enter_scope(symtable* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
self->scope++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void symtable_leave_scope(symtable* self)
|
||||||
|
{
|
||||||
|
assert(self);
|
||||||
|
|
||||||
|
for (size_t i=0; i<self->entries.size; i++)
|
||||||
|
{
|
||||||
|
if (self->entries.data[i]->scope >= self->scope)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (size_t j=i; j<self->entries.size - 1; j++)
|
||||||
|
{
|
||||||
|
self->entries.data[j] = self->entries.data[j + 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
symentry_free(self->entries.data[i]);
|
||||||
|
free(self->entries.data[i]);
|
||||||
|
|
||||||
|
self->entries.size--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self->scope--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ typedef struct {
|
||||||
char* name;
|
char* name;
|
||||||
type* ty;
|
type* ty;
|
||||||
node* sym_node;
|
node* sym_node;
|
||||||
|
int scope;
|
||||||
} symentry;
|
} symentry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -21,13 +22,18 @@ typedef struct {
|
||||||
} entries;
|
} entries;
|
||||||
|
|
||||||
size_t id;
|
size_t id;
|
||||||
|
int scope;
|
||||||
} symtable;
|
} symtable;
|
||||||
|
|
||||||
void symtable_init(symtable* self);
|
void symtable_init(symtable* self);
|
||||||
void symtable_free(symtable* self);
|
void symtable_free(symtable* self);
|
||||||
|
void symentry_free(symentry* self);
|
||||||
|
|
||||||
size_t symtable_declare(symtable* self, char const* name, type* ty, node* sym_node);
|
size_t symtable_declare(symtable* self, char const* name, type* ty, node* sym_node);
|
||||||
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node);
|
size_t symtable_declare_mut(symtable* self, char const* name, type* ty, node* sym_node);
|
||||||
symentry* symtable_find(symtable* self, char const* name);
|
symentry* symtable_find(symtable* self, char const* name);
|
||||||
|
|
||||||
|
void symtable_enter_scope(symtable* self);
|
||||||
|
void symtable_leave_scope(symtable* self);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
do let x = 3 end x
|
|
@ -0,0 +1,29 @@
|
||||||
|
do
|
||||||
|
let! a = 29
|
||||||
|
a = 31
|
||||||
|
assert 31 == a
|
||||||
|
end
|
||||||
|
|
||||||
|
let b = do
|
||||||
|
4 + 1
|
||||||
|
7
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 7 == b
|
||||||
|
|
||||||
|
let c = 3.2
|
||||||
|
|
||||||
|
do
|
||||||
|
let c = [47]
|
||||||
|
assert [47] == c
|
||||||
|
|
||||||
|
do
|
||||||
|
let c = "salut"
|
||||||
|
assert "salut" == c
|
||||||
|
end
|
||||||
|
|
||||||
|
assert [47] == c
|
||||||
|
end
|
||||||
|
|
||||||
|
assert 3.2 == c
|
||||||
|
|
Loading…
Reference in New Issue