✨ begin blocks.
parent
73b051f6cc
commit
789ad9657f
|
@ -3,3 +3,4 @@
|
||||||
*\#*
|
*\#*
|
||||||
build
|
build
|
||||||
doc/build
|
doc/build
|
||||||
|
vgcore.*
|
||||||
|
|
|
@ -4,6 +4,9 @@ EXPR ::=
|
||||||
| ASSERT
|
| ASSERT
|
||||||
| DECL
|
| DECL
|
||||||
| ASSIGN
|
| ASSIGN
|
||||||
|
| BEGIN
|
||||||
|
BEGIN ::= begin BLOCK end
|
||||||
|
BLOCK ::= EXPR*
|
||||||
ASSIGN ::= (ident|INDEX) assign EXPR
|
ASSIGN ::= (ident|INDEX) assign EXPR
|
||||||
DECL ::= (var|const) ident assign EXPR
|
DECL ::= (var|const) ident assign EXPR
|
||||||
ASSERT ::= (assert_eq|assert_ne) tuple
|
ASSERT ::= (assert_eq|assert_ne) tuple
|
||||||
|
|
|
@ -32,6 +32,24 @@ void compiler_compile(compiler_t* self,
|
||||||
|
|
||||||
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: {
|
case NODE_ASSIGN: {
|
||||||
node_t* target = node->children.data[0];
|
node_t* target = node->children.data[0];
|
||||||
node_t* expr = node->children.data[1];
|
node_t* expr = node->children.data[1];
|
||||||
|
@ -125,8 +143,17 @@ void compiler_compile(compiler_t* self,
|
||||||
|
|
||||||
case NODE_IDENT: {
|
case NODE_IDENT: {
|
||||||
char const* name = node->value;
|
char const* name = node->value;
|
||||||
sym_entry_t* entry = sym_try_get_value(sym, name);
|
sym_entry_t const* entry = sym_try_get_value(
|
||||||
assert(entry);
|
sym,
|
||||||
|
name
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!entry) {
|
||||||
|
err_push(&self->err, node->line,
|
||||||
|
"undefined '%s'", name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
prog_add_instr(prog, OP_LOCAL_LOAD, entry->local_addr);
|
prog_add_instr(prog, OP_LOCAL_LOAD, entry->local_addr);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
|
@ -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("var", NODE_VAR, 0);
|
||||||
CCM_KEYWORD("const", NODE_CONST, 0);
|
CCM_KEYWORD("const", NODE_CONST, 0);
|
||||||
CCM_KEYWORD("assert_eq", NODE_ASSERT_EQ, 0);
|
CCM_KEYWORD("assert_eq", NODE_ASSERT_EQ, 0);
|
||||||
|
|
|
@ -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_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_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);
|
CCM_ENUM_H(NodeKind, NODE_KIND);
|
||||||
|
|
||||||
|
|
50
lib/parser.c
50
lib/parser.c
|
@ -147,12 +147,62 @@ node_t* parser_try_new_expr(parser_t* self)
|
||||||
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);
|
node_t* assign = CCM_TRY(parser_try_new_assign);
|
||||||
if (assign) { return 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)
|
node_t* parser_try_new_assign(parser_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
|
@ -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_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_assign(parser_t* self);
|
||||||
node_t* parser_try_new_decl(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);
|
||||||
|
|
14
lib/sym.c
14
lib/sym.c
|
@ -15,6 +15,7 @@ void sym_free(sym_t* self)
|
||||||
sym_free_env(self, self->env);
|
sym_free_env(self, self->env);
|
||||||
free(self->env);
|
free(self->env);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sym_free_env(sym_t* self, env_t* 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);
|
||||||
assert(self->env);
|
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);
|
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(self->env);
|
||||||
assert(name);
|
assert(name);
|
||||||
|
|
||||||
if (sym_try_get_value(self, name) != NULL)
|
if (sym_try_get_env_value(self,self->env, name) != NULL)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue