✨ constant declaration.
parent
d67466cad6
commit
73b051f6cc
|
@ -5,7 +5,7 @@ EXPR ::=
|
|||
| DECL
|
||||
| ASSIGN
|
||||
ASSIGN ::= (ident|INDEX) assign EXPR
|
||||
DECL ::= var ident assign EXPR
|
||||
DECL ::= (var|const) ident assign EXPR
|
||||
ASSERT ::= (assert_eq|assert_ne) tuple
|
||||
OR ::= AND (or AND)*
|
||||
AND ::= EQNE (and EQNE)*
|
||||
|
|
|
@ -44,12 +44,19 @@ void compiler_compile(compiler_t* self,
|
|||
ident->value
|
||||
);
|
||||
|
||||
|
||||
if (!entry) {
|
||||
err_push(&self->err, ident->line,
|
||||
"undefined array '%s'", ident->value);
|
||||
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);
|
||||
size_t indexes_count = target->children.size - 1;
|
||||
|
||||
|
@ -66,8 +73,24 @@ void compiler_compile(compiler_t* self,
|
|||
} else {
|
||||
compiler_compile(self, expr, prog);
|
||||
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)
|
||||
{
|
||||
err_push(&self->err, target->line,
|
||||
|
@ -83,13 +106,18 @@ void compiler_compile(compiler_t* self,
|
|||
|
||||
} break;
|
||||
|
||||
case NODE_CONSTDECL:
|
||||
case NODE_VARDECL: {
|
||||
node_t const* ident = node->children.data[0];
|
||||
node_t* expr = node->children.data[1];
|
||||
|
||||
compiler_compile(self, expr, prog);
|
||||
int status =
|
||||
sym_declare(sym, ident->value, self->loc_counter);
|
||||
sym_declare(
|
||||
sym, ident->value,
|
||||
self->loc_counter,
|
||||
node->kind == NODE_CONSTDECL
|
||||
);
|
||||
assert(status);
|
||||
prog_add_instr(prog, OP_LOCAL_STORE, self->loc_counter);
|
||||
self->loc_counter++;
|
||||
|
|
|
@ -71,7 +71,7 @@ void exec_instr(exec_t* self,
|
|||
}
|
||||
|
||||
int line = 0;
|
||||
|
||||
|
||||
if (vec->size > 0) {
|
||||
line = ((value_t*) vec->data[0])->line;
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ void exec_instr(exec_t* self,
|
|||
int idx = ccm_from_num(ccm, ccm_idx);
|
||||
indexes[param - 1 - i] = idx;
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<param-1; i++)
|
||||
{
|
||||
target = target->data.array->data[indexes[i]];
|
||||
|
@ -124,7 +124,7 @@ void exec_instr(exec_t* self,
|
|||
|
||||
CCM ccm_expr = ccm_pop(ccm);
|
||||
value_t* expr = ccm_to_value(ccm, ccm_expr);
|
||||
target->data.array->data[indexes[param - 1]]
|
||||
target->data.array->data[indexes[param - 1]]
|
||||
= expr;
|
||||
ccm_push(ccm, ccm_expr);
|
||||
self->pc++;
|
||||
|
|
|
@ -172,6 +172,7 @@ node_t* lexer_try_new_next(lexer_t* self)
|
|||
}
|
||||
|
||||
CCM_KEYWORD("var", NODE_VAR, 0);
|
||||
CCM_KEYWORD("const", NODE_CONST, 0);
|
||||
CCM_KEYWORD("assert_eq", NODE_ASSERT_EQ, 0);
|
||||
CCM_KEYWORD("assert_ne", NODE_ASSERT_NE, 0);
|
||||
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_GE), G(NODE_EQ), G(NODE_NE), G(NODE_ARRAY), \
|
||||
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);
|
||||
|
||||
|
|
17
lib/parser.c
17
lib/parser.c
|
@ -135,7 +135,8 @@ node_t* parser_try_new_expr(parser_t* 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);
|
||||
}
|
||||
|
@ -191,8 +192,15 @@ node_t* parser_try_new_assign(parser_t* self)
|
|||
node_t* parser_try_new_decl(parser_t* 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;
|
||||
}
|
||||
|
||||
|
@ -217,7 +225,8 @@ node_t* parser_try_new_decl(parser_t* self)
|
|||
}
|
||||
|
||||
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, expr);
|
||||
|
|
|
@ -64,8 +64,9 @@ void sym_close_scope(sym_t* self)
|
|||
|
||||
|
||||
int sym_declare(sym_t* self,
|
||||
char const* name,
|
||||
int addr)
|
||||
char const* name,
|
||||
int addr,
|
||||
int is_const)
|
||||
{
|
||||
assert(self);
|
||||
assert(self->env);
|
||||
|
@ -79,7 +80,7 @@ int sym_declare(sym_t* self,
|
|||
sym_entry_t* entry = malloc(sizeof(sym_entry_t));
|
||||
entry->name = strdup(name);
|
||||
entry->local_addr = addr;
|
||||
|
||||
entry->is_const = is_const;
|
||||
vec_push(&self->env->entries, entry);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
typedef struct {
|
||||
char* name;
|
||||
int local_addr;
|
||||
int is_const;
|
||||
} sym_entry_t;
|
||||
|
||||
typedef struct env {
|
||||
|
@ -27,15 +28,16 @@ void sym_open_scope(sym_t* self);
|
|||
void sym_close_scope(sym_t* self);
|
||||
|
||||
int sym_declare(sym_t* self,
|
||||
char const* name,
|
||||
int addr);
|
||||
char const* name,
|
||||
int addr,
|
||||
int is_const);
|
||||
|
||||
int sym_try_assign(sym_t* self,
|
||||
char const* name,
|
||||
int addr);
|
||||
|
||||
sym_entry_t* sym_try_get_value(sym_t* self, char const* name);
|
||||
sym_entry_t* sym_try_get_env_value(sym_t* self,
|
||||
sym_entry_t* sym_try_get_env_value(sym_t* self,
|
||||
env_t* env,
|
||||
char const* name);
|
||||
|
||||
|
|
Loading…
Reference in New Issue