summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--uscript/parser.c51
-rw-r--r--uscript/us_debug.c6
-rw-r--r--uscript/uscript.c5
-rw-r--r--uscript/vm.c19
-rw-r--r--uscript/vm.h13
-rw-r--r--uscript/xbytecode.h2
6 files changed, 91 insertions, 5 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);
diff --git a/uscript/us_debug.c b/uscript/us_debug.c
index 496b191..6b981a4 100644
--- a/uscript/us_debug.c
+++ b/uscript/us_debug.c
@@ -56,6 +56,12 @@ int print_instruction(struct us_proto *proto, int idx)
);
return idx + 2;
}
+ case BC_GET_GLOBAL:
+ case BC_SET_GLOBAL: {
+ u16 loc = (u16)(proto->bytecode[idx + 1] << 8) | proto->bytecode[idx + 2];
+ fprintf(stderr, "%d\n", loc);
+ return idx + 3;
+ }
case BC_JMP:
case BC_FALSEY_JMP:
case BC_LOOP: {
diff --git a/uscript/uscript.c b/uscript/uscript.c
index 5ec43a1..2b32110 100644
--- a/uscript/uscript.c
+++ b/uscript/uscript.c
@@ -32,3 +32,8 @@ void us_load_src(const char *src)
return;
us_exec(create_func(proto));
}
+
+int us_declare_global(const char *name)
+{
+ return declare_global(copy_str(name, -1));
+}
diff --git a/uscript/vm.c b/uscript/vm.c
index 7c2d85e..363912a 100644
--- a/uscript/vm.c
+++ b/uscript/vm.c
@@ -12,6 +12,7 @@ struct vm vm;
void init_vm(void)
{
vm.objs = da_create(struct us_val, 128);
+ vm.gstack = da_create(struct global, 128);
vm.cf = vm.cf_stack;
vm.stacktop = vm.stack;
}
@@ -23,6 +24,8 @@ void deinit_vm(void)
}
da_clear(vm.objs); // not needed, but makes me feel better :)
da_free(vm.objs);
+
+ da_free(vm.gstack);
}
static
@@ -154,6 +157,12 @@ void us_exec(struct us_func *func)
case BC_SET_LOCAL:
vm.cf->stackbot[read_byte()] = vm_peek();
break;
+ case BC_GET_GLOBAL:
+ vm_push(vm.gstack[read_short(func->proto, &i)].val);
+ break;
+ case BC_SET_GLOBAL:
+ vm.gstack[read_short(func->proto, &i)].val = vm_peek();
+ break;
case BC_GET_UPVAL:
vm_push(*func->upvals[read_byte()]->loc);
break;
@@ -366,3 +375,13 @@ void us_exec(struct us_func *func)
}
}
}
+
+int declare_global(struct us_str *name)
+{
+ int idx = da_len(vm.gstack);
+ struct global global;
+ global.name = name;
+ global.val = create_zilch();
+ da_append(struct global, &vm.gstack, global);
+ return idx;
+}
diff --git a/uscript/vm.h b/uscript/vm.h
index 15c21a0..2911d01 100644
--- a/uscript/vm.h
+++ b/uscript/vm.h
@@ -11,6 +11,8 @@
#define vm_peek() (vm.stacktop[-1])
#define vm_push(v) (*vm.stacktop++ = (v))
+#define set_global(idx, v) (vm.gstack[idx].val = (v))
+
enum bytecode {
#define BC(name) BC_##name,
#include "xbytecode.h"
@@ -22,16 +24,23 @@ struct call_frame {
struct us_val *stackbot;
};
+struct global {
+ struct us_str *name;
+ struct us_val val;
+};
+
struct vm {
struct us_val *objs;
struct call_frame cf_stack[MAX_CALL_FRAMES];
struct call_frame *cf;
- struct us_val *global_stack; // dyn_arr
struct us_val stack[STACK_SIZE];
struct us_val *stacktop;
+ struct global *gstack; // dynarr
+ struct global *gstacktop;
+
struct us_upval *open_upvals;
};
@@ -41,4 +50,6 @@ void init_vm(void);
void deinit_vm(void);
void print_func(struct us_proto *proto);
+int declare_global(struct us_str *name);
+
#endif // __USCRIPT_VM_H__
diff --git a/uscript/xbytecode.h b/uscript/xbytecode.h
index 16ad7a3..95f1440 100644
--- a/uscript/xbytecode.h
+++ b/uscript/xbytecode.h
@@ -7,6 +7,8 @@ BC(ZILCH)
BC(ARR)
BC(GET_LOCAL)
BC(SET_LOCAL)
+BC(GET_GLOBAL)
+BC(SET_GLOBAL)
BC(GET_UPVAL)
BC(SET_UPVAL)
BC(GET_INDEX)