summaryrefslogtreecommitdiff
path: root/uscript/parser.c
diff options
context:
space:
mode:
authoriamcheeseman <[email protected]>2026-04-14 12:44:25 -0400
committeriamcheeseman <[email protected]>2026-04-14 12:44:25 -0400
commitca004156cbb1c525900f444994112fc17b71d63d (patch)
tree8d19ad7199044e4b11fde6725eb758917f317b4e /uscript/parser.c
parent752d7967f3cccb4f43e1df7fd99d4944884fc977 (diff)
microscript: add globals
Diffstat (limited to 'uscript/parser.c')
-rw-r--r--uscript/parser.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/uscript/parser.c b/uscript/parser.c
index 404e5e5..89a8883 100644
--- a/uscript/parser.c
+++ b/uscript/parser.c
@@ -185,6 +185,21 @@ int find_local(struct func_parser *fp, struct token name)
}
static
+int find_global(struct token name)
+{
+ for (int i = da_len(vm.gstack) - 1; i >= 0; i--) {
+ struct global global = vm.gstack[i];
+ if (
+ (size_t)name.len == global.name->len &&
+ memcmp(name.start, global.name->chars, name.len) == 0
+ )
+ return i;
+ }
+
+ return -1;
+}
+
+static
int find_upval(struct parser *p, struct func_parser *fp, struct token name)
{
if (fp == NULL)
@@ -383,6 +398,9 @@ void parse_ident(struct parser *p)
} else if ((var = find_upval(p, p->fp, ident)) != -1) {
setter = BC_SET_UPVAL;
getter = BC_GET_UPVAL;
+ } else if ((var = find_global(ident)) != -1) {
+ setter = BC_SET_GLOBAL;
+ getter = BC_GET_GLOBAL;
}
if (var == -1) {
@@ -396,7 +414,13 @@ void parse_ident(struct parser *p)
} else {
parser_add_byte(p, getter);
}
- parser_add_byte(p, (u8)var);
+
+ if (setter == BC_SET_GLOBAL) {
+ parser_add_byte(p, (var >> 8) & 0xFF);
+ parser_add_byte(p, var & 0xFF);
+ } else {
+ parser_add_byte(p, (u8)var);
+ }
}
static
@@ -576,7 +600,7 @@ void expr_stat(struct parser *p)
}
static
-void let_stat(struct parser *p)
+void var_def_stat(struct parser *p, bool is_global)
{
do {
expect(p, TOKEN_IDENT, "expected variable name");
@@ -587,7 +611,16 @@ void let_stat(struct parser *p)
else
parser_add_byte(p, BC_ZILCH);
- declare_variable(p, name);
+ if (is_global) {
+ struct us_str *ident = copy_str(name.start, name.len);
+ int idx = declare_global(ident);
+ parser_add_byte(p, BC_SET_GLOBAL);
+ parser_add_byte(p, (idx >> 8) & 0xFF);
+ parser_add_byte(p, idx & 0xFF);
+ parser_add_byte(p, BC_POP); // set global does not pop
+ } else {
+ declare_variable(p, name);
+ }
} while (consume(p, ','));
}
@@ -824,7 +857,17 @@ static
void stat(struct parser *p)
{
if (consume(p, TOKEN_LET)) {
- let_stat(p);
+ var_def_stat(p, false);
+ consume(p, ';');
+ } else if (consume(p, TOKEN_GLOBAL)) {
+ if (!p->fp->is_script) {
+ show_error(
+ p,
+ p->cur,
+ "can only define globals in the outermost scope"
+ );
+ }
+ var_def_stat(p, true);
consume(p, ';');
} else if (consume(p, TOKEN_FUN)) {
fun_stat(p);