✨ constant declaration.
parent
d67466cad6
commit
73b051f6cc
|
@ -5,7 +5,7 @@ EXPR ::=
|
||||||
| DECL
|
| DECL
|
||||||
| ASSIGN
|
| ASSIGN
|
||||||
ASSIGN ::= (ident|INDEX) assign EXPR
|
ASSIGN ::= (ident|INDEX) assign EXPR
|
||||||
DECL ::= var ident 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)*
|
||||||
|
|
|
@ -44,12 +44,19 @@ void compiler_compile(compiler_t* self,
|
||||||
ident->value
|
ident->value
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
err_push(&self->err, ident->line,
|
err_push(&self->err, ident->line,
|
||||||
"undefined array '%s'", ident->value);
|
"undefined array '%s'", ident->value);
|
||||||
return;
|
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);
|
compiler_compile(self, expr, prog);
|
||||||
size_t indexes_count = target->children.size - 1;
|
size_t indexes_count = target->children.size - 1;
|
||||||
|
|
||||||
|
@ -66,8 +73,24 @@ void compiler_compile(compiler_t* self,
|
||||||
} else {
|
} else {
|
||||||
compiler_compile(self, expr, prog);
|
compiler_compile(self, expr, prog);
|
||||||
int status =
|
int status =
|
||||||
sym_try_assign(sym, target->value, self->loc_counter);
|
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)
|
if (!status)
|
||||||
{
|
{
|
||||||
err_push(&self->err, target->line,
|
err_push(&self->err, target->line,
|
||||||
|
@ -83,13 +106,18 @@ void compiler_compile(compiler_t* self,
|
||||||
|
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case NODE_CONSTDECL:
|
||||||
case NODE_VARDECL: {
|
case NODE_VARDECL: {
|
||||||
node_t const* ident = node->children.data[0];
|
node_t const* ident = node->children.data[0];
|
||||||
node_t* expr = node->children.data[1];
|
node_t* expr = node->children.data[1];
|
||||||
|
|
||||||
compiler_compile(self, expr, prog);
|
compiler_compile(self, expr, prog);
|
||||||
int status =
|
int status =
|
||||||
sym_declare(sym, ident->value, self->loc_counter);
|
sym_declare(
|
||||||
|
sym, ident->value,
|
||||||
|
self->loc_counter,
|
||||||
|
node->kind == NODE_CONSTDECL
|
||||||
|
);
|
||||||
assert(status);
|
assert(status);
|
||||||
prog_add_instr(prog, OP_LOCAL_STORE, self->loc_counter);
|
prog_add_instr(prog, OP_LOCAL_STORE, self->loc_counter);
|
||||||
self->loc_counter++;
|
self->loc_counter++;
|
||||||
|
|
|
@ -172,6 +172,7 @@ node_t* lexer_try_new_next(lexer_t* self)
|
||||||
}
|
}
|
||||||
|
|
||||||
CCM_KEYWORD("var", NODE_VAR, 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);
|
||||||
|
|
|
@ -15,7 +15,7 @@ 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_VARDECL), G(NODE_CONST), G(NODE_CONSTDECL)
|
||||||
|
|
||||||
CCM_ENUM_H(NodeKind, NODE_KIND);
|
CCM_ENUM_H(NodeKind, NODE_KIND);
|
||||||
|
|
||||||
|
|
17
lib/parser.c
17
lib/parser.c
|
@ -135,7 +135,8 @@ node_t* parser_try_new_expr(parser_t* self)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
if (lexer_peek_kind(self->lexer, NODE_VAR, 0))
|
if (lexer_peek_kind(self->lexer, NODE_VAR, 0)
|
||||||
|
|| lexer_peek_kind(self->lexer, NODE_CONST, 0))
|
||||||
{
|
{
|
||||||
return CCM_TRY(parser_try_new_decl);
|
return CCM_TRY(parser_try_new_decl);
|
||||||
}
|
}
|
||||||
|
@ -191,8 +192,15 @@ 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)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
if (!lexer_consume_next(self->lexer, NODE_VAR))
|
|
||||||
{
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -217,7 +225,8 @@ node_t* parser_try_new_decl(parser_t* self)
|
||||||
}
|
}
|
||||||
|
|
||||||
node_t* node = malloc(sizeof(node_t));
|
node_t* node = malloc(sizeof(node_t));
|
||||||
node_init(node, NODE_VARDECL, "", self->lexer->line);
|
node_init(node, is_const ? NODE_CONSTDECL : NODE_VARDECL,
|
||||||
|
"", self->lexer->line);
|
||||||
|
|
||||||
node_push_new_child(node, ident);
|
node_push_new_child(node, ident);
|
||||||
node_push_new_child(node, expr);
|
node_push_new_child(node, expr);
|
||||||
|
|
|
@ -65,7 +65,8 @@ void sym_close_scope(sym_t* self)
|
||||||
|
|
||||||
int sym_declare(sym_t* self,
|
int sym_declare(sym_t* self,
|
||||||
char const* name,
|
char const* name,
|
||||||
int addr)
|
int addr,
|
||||||
|
int is_const)
|
||||||
{
|
{
|
||||||
assert(self);
|
assert(self);
|
||||||
assert(self->env);
|
assert(self->env);
|
||||||
|
@ -79,7 +80,7 @@ int sym_declare(sym_t* self,
|
||||||
sym_entry_t* entry = malloc(sizeof(sym_entry_t));
|
sym_entry_t* entry = malloc(sizeof(sym_entry_t));
|
||||||
entry->name = strdup(name);
|
entry->name = strdup(name);
|
||||||
entry->local_addr = addr;
|
entry->local_addr = addr;
|
||||||
|
entry->is_const = is_const;
|
||||||
vec_push(&self->env->entries, entry);
|
vec_push(&self->env->entries, entry);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* name;
|
char* name;
|
||||||
int local_addr;
|
int local_addr;
|
||||||
|
int is_const;
|
||||||
} sym_entry_t;
|
} sym_entry_t;
|
||||||
|
|
||||||
typedef struct env {
|
typedef struct env {
|
||||||
|
@ -28,7 +29,8 @@ void sym_close_scope(sym_t* self);
|
||||||
|
|
||||||
int sym_declare(sym_t* self,
|
int sym_declare(sym_t* self,
|
||||||
char const* name,
|
char const* name,
|
||||||
int addr);
|
int addr,
|
||||||
|
int is_const);
|
||||||
|
|
||||||
int sym_try_assign(sym_t* self,
|
int sym_try_assign(sym_t* self,
|
||||||
char const* name,
|
char const* name,
|
||||||
|
|
Loading…
Reference in New Issue