begin blocks.

main
bog 2024-03-22 08:57:44 +01:00
parent 73b051f6cc
commit 789ad9657f
9 changed files with 137 additions and 5 deletions

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
*\#*
build
doc/build
vgcore.*

View File

@ -4,6 +4,9 @@ EXPR ::=
| 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

View File

@ -32,6 +32,24 @@ void compiler_compile(compiler_t* self,
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];
@ -125,8 +143,17 @@ void compiler_compile(compiler_t* self,
case NODE_IDENT: {
char const* name = node->value;
sym_entry_t* entry = sym_try_get_value(sym, name);
assert(entry);
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;

View File

@ -171,6 +171,8 @@ 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);

View File

@ -15,7 +15,8 @@ G(NODE_OSQUARE), G(NODE_CSQUARE), G(NODE_INDEX), \
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_VAR), G(NODE_IDENT), G(NODE_ASSIGN), \
G(NODE_VARDECL), G(NODE_CONST), G(NODE_CONSTDECL)
G(NODE_VARDECL), G(NODE_CONST), G(NODE_CONSTDECL), \
G(NODE_BEGIN), G(NODE_BLOCK), G(NODE_END)
CCM_ENUM_H(NodeKind, NODE_KIND);

View File

@ -147,12 +147,62 @@ node_t* parser_try_new_expr(parser_t* self)
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);
}
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);

View File

@ -25,6 +25,8 @@ 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_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);

View File

@ -15,6 +15,7 @@ void sym_free(sym_t* self)
sym_free_env(self, self->env);
free(self->env);
}
}
void sym_free_env(sym_t* self, env_t* env)
@ -58,8 +59,17 @@ 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);
self->env = self->env->parent;
env_t* parent = self->env->parent;
free(self->env);
self->env = parent;
}
@ -72,7 +82,7 @@ int sym_declare(sym_t* self,
assert(self->env);
assert(name);
if (sym_try_get_value(self, name) != NULL)
if (sym_try_get_env_value(self,self->env, name) != NULL)
{
return 0;
}

36
tests/block.ccm Normal file
View File

@ -0,0 +1,36 @@
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)