summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorubq323 <ubq323@ubq323.website>2024-06-20 18:43:01 +0100
committerubq323 <ubq323@ubq323.website>2024-06-20 18:45:35 +0100
commit9a7d1b1d41f4b3bb3387e7bbe77105d0089803d0 (patch)
tree984e8648448ee75fe2bed9f9616ba295fc1b81f7
parent600eaef90f9f0507635fec4cf98f7fa1d1779bd1 (diff)
globals are now variable
-rw-r--r--com.c56
-rw-r--r--dis.c9
-rw-r--r--todo4
-rw-r--r--vm.c19
-rw-r--r--vm.h3
5 files changed, 67 insertions, 24 deletions
diff --git a/com.c b/com.c
index ba45975..4252ecd 100644
--- a/com.c
+++ b/com.c
@@ -35,26 +35,44 @@ static void compile_node(State *S, Chunk *ch, AstNode a) {
CK(l.len == 2, "print requires exactly 1 argument");
compile_node(S, ch, l.vals[1]);
chunk_wbc(S, ch, OP_PRINT);
- break;
- }
- CK(l.len == 3, "can only compile binary ops");
- char opchar = l.vals[0].as.str[0];
- Op op;
- switch (opchar) {
- #define OP(char, code) case char: op = code; break;
- OP('+', OP_ADD)
- OP('-', OP_SUB)
- OP('*', OP_MUL)
- OP('/', OP_DIV)
- #undef OP
- default:
- printf("unkown op %s\n",l.vals[0].as.str);
- exit(1);
- break;
+ } else if (0 == strcmp(l.vals[0].as.str, "set")) {
+ CK(l.len == 3, "set requires exactly 2 arguments");
+ AstNode ident = l.vals[1];
+ CK(ident.ty == AST_IDENT, "set's first argument must be identifier");
+
+ size_t len = strlen(ident.as.str);
+ ObjString *o = objstring_copy(S, ident.as.str, len);
+
+ compile_node(S, ch, l.vals[2]);
+ chunk_wbc(S, ch, OP_SETGLOBAL);
+ chunk_wbc(S, ch, chunk_wconst(S, ch, VAL_OBJ(o)));
+ } else if (0 == strcmp(l.vals[0].as.str, "do")) {
+ for (int i = 1; i < l.len - 1; i++) {
+ compile_node(S, ch, l.vals[i]);
+ chunk_wbc(S, ch, OP_DROP);
+ }
+ compile_node(S, ch, l.vals[l.len - 1]);
+ } else {
+
+ CK(l.len == 3, "can only compile binary ops");
+ char opchar = l.vals[0].as.str[0];
+ Op op;
+ switch (opchar) {
+ #define OP(char, code) case char: op = code; break;
+ OP('+', OP_ADD)
+ OP('-', OP_SUB)
+ OP('*', OP_MUL)
+ OP('/', OP_DIV)
+ #undef OP
+ default:
+ printf("unkown op %s\n",l.vals[0].as.str);
+ exit(1);
+ break;
+ }
+ compile_node(S, ch, l.vals[1]);
+ compile_node(S, ch, l.vals[2]);
+ chunk_wbc(S, ch, op);
}
- compile_node(S, ch, l.vals[1]);
- compile_node(S, ch, l.vals[2]);
- chunk_wbc(S, ch, op);
#undef CK
}
}
diff --git a/dis.c b/dis.c
index 16c5b0e..0fb23f8 100644
--- a/dis.c
+++ b/dis.c
@@ -30,7 +30,16 @@ void disasm_chunk(Chunk *ch) {
println_val(k);
break;
}
+ case OP_SETGLOBAL: {
+ uint8_t ix = ch->bc.d[ip++];
+ printf("setglobal #%d\t; ",ix);
+ Val k = ch->consts.d[ix];
+ printf("%-4s : ",typename_str(k));
+ println_val(k);
+ break;
+ }
SIMPLE_INSTR(OP_PRINT, "print")
+ SIMPLE_INSTR(OP_DROP, "drop")
SIMPLE_INSTR(OP_ADD, "add")
SIMPLE_INSTR(OP_SUB, "sub")
SIMPLE_INSTR(OP_MUL, "mul")
diff --git a/todo b/todo
index 0dbc87d..2e920ed 100644
--- a/todo
+++ b/todo
@@ -1,7 +1,3 @@
-string interning
- pass state through all allocation things
- decide on state vs global state, terminology
-globals, getting and setting
functions, returning
locals, lexical scoping, closures, upvalues
lists, hashes, other useful types
diff --git a/vm.c b/vm.c
index 00ba397..9f6ece6 100644
--- a/vm.c
+++ b/vm.c
@@ -56,6 +56,7 @@ void runvm(State *S) {
#define PUSH(v) th->stack[th->sp++] = v;
#define POP() (th->stack[--th->sp])
+#define PEEK() (th->stack[th->sp-1])
puts("---");
while (1) {
@@ -75,7 +76,10 @@ void runvm(State *S) {
break;
}
case OP_PRINT:
- println_val(POP());
+ println_val(PEEK());
+ break;
+ case OP_DROP:
+ --th->sp;
break;
case OP_GETGLOBAL: {
@@ -90,6 +94,19 @@ void runvm(State *S) {
PUSH(v);
break;
}
+ case OP_SETGLOBAL: {
+ uint8_t cix = RBYTE();
+ Val varname = ch->consts.d[cix];
+ if (!IS_STRING(varname)) {
+ printf("global names must be string, not %s\n",
+ typename_str(varname));
+ goto done;
+ }
+ Val v = PEEK();
+
+ ht_put(S, &S->globals, AS_STRING(varname), v);
+ break;
+ }
#define ARITH_OP(opcode, OP) \
case opcode: { \
diff --git a/vm.h b/vm.h
index bce1923..859e207 100644
--- a/vm.h
+++ b/vm.h
@@ -45,7 +45,10 @@ typedef enum {
OP_MUL,
OP_DIV,
+ OP_DROP,
+
OP_GETGLOBAL,
+ OP_SETGLOBAL,
} Op;
void runvm(State *S);