constant declaration.

main
bog 2024-03-22 08:20:31 +01:00
parent d67466cad6
commit 73b051f6cc
8 changed files with 58 additions and 17 deletions

View File

@ -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)*

View File

@ -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++;

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -64,8 +64,9 @@ 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;
} }

View File

@ -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 {
@ -27,8 +28,9 @@ void sym_open_scope(sym_t* self);
void sym_close_scope(sym_t* self); 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,