summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dis.c36
-rw-r--r--dis.h8
-rw-r--r--val.c21
-rw-r--r--val.h2
-rwxr-xr-xvmbin20840 -> 0 bytes
-rw-r--r--vm.c51
-rw-r--r--vm.h5
7 files changed, 109 insertions, 14 deletions
diff --git a/dis.c b/dis.c
new file mode 100644
index 0000000..09e7571
--- /dev/null
+++ b/dis.c
@@ -0,0 +1,36 @@
+#include "dis.h"
+
+#include <stdio.h>
+#include <stdint.h>
+
+
+
+void disasm_chunk(Chunk *ch) {
+ for (size_t ip = 0; ip < ch->blen; ) {
+ uint8_t instr = ch->b[ip];
+ printf("%04zd\t",ip);
+ ip ++;
+#define SIMPLE_INSTR(opcode, str) \
+ case opcode: puts(str); break;
+ switch (instr) {
+ SIMPLE_INSTR(OP_RET, "ret")
+ case OP_LOADK:;
+ uint8_t ix = ch->b[ip++];
+ printf("loadk #%d\t; ",ix);
+ Val k = ch->c[ix];
+ printf("%-4s : ",valty_str(k.ty));
+ println_val(k);
+ break;
+ SIMPLE_INSTR(OP_PRINT, "print")
+ SIMPLE_INSTR(OP_ADD, "add")
+ SIMPLE_INSTR(OP_SUB, "sub")
+ SIMPLE_INSTR(OP_MUL, "mul")
+ SIMPLE_INSTR(OP_DIV, "div")
+ }
+ }
+#undef SIMPLE_INSTR
+}
+
+
+
+
diff --git a/dis.h b/dis.h
new file mode 100644
index 0000000..47aff62
--- /dev/null
+++ b/dis.h
@@ -0,0 +1,8 @@
+#ifndef _dis_h
+#define _dis_h
+
+#include "vm.h"
+
+void disasm_chunk(Chunk *ch);
+
+#endif
diff --git a/val.c b/val.c
index 4456148..9e832a6 100644
--- a/val.c
+++ b/val.c
@@ -4,13 +4,28 @@
void print_val(Val v) {
switch (v.ty) {
case TY_NIL:
- printf("nil\n");
+ printf("nil");
break;
case TY_NUM:
- printf("%f\n",AS_NUM(v));
+ printf("%f",AS_NUM(v));
break;
case TY_BOOL:
- printf("%s\n",AS_BOOL(v) ? "true" : "false");
+ printf("%s",AS_BOOL(v) ? "true" : "false");
break;
}
}
+
+void println_val(Val v) {
+ print_val(v);
+ putchar('\n');
+}
+
+static const char *ty_names[] = {
+ "nil",
+ "num",
+ "bool",
+};
+
+const char *valty_str(ValTy ty) {
+ return ty_names[ty];
+}
diff --git a/val.h b/val.h
index 1f2bd8d..bf58c06 100644
--- a/val.h
+++ b/val.h
@@ -30,6 +30,8 @@ struct _obj {
};
void print_val(Val v);
+void println_val(Val v);
+const char *valty_str(ValTy ty);
#define IS_NUM(x) (x.ty == TY_NUM)
diff --git a/vm b/vm
deleted file mode 100755
index 9ecf078..0000000
--- a/vm
+++ /dev/null
Binary files differ
diff --git a/vm.c b/vm.c
index 00692b0..72f69fa 100644
--- a/vm.c
+++ b/vm.c
@@ -6,6 +6,7 @@
#include "val.h"
#include "vm.h"
+#include "dis.h"
void *M(void *p, size_t sz) {
if (sz == 0) {
@@ -61,22 +62,26 @@ Vm vm_new(Chunk *ch) {
static void runvm() {
Chunk ch = chunk_new();
+
chunk_wbc(&ch, OP_LOADK);
- chunk_wbc(&ch, 1);
- chunk_wbc(&ch, OP_PRINT);
- chunk_wbc(&ch, OP_LOADK);
- chunk_wbc(&ch, 2);
+ chunk_wbc(&ch, chunk_wconst(&ch, VAL_NUM(10.0)));
chunk_wbc(&ch, OP_LOADK);
- chunk_wbc(&ch, 0);
+ chunk_wbc(&ch, chunk_wconst(&ch, VAL_NUM(3.0)));
+ chunk_wbc(&ch, OP_DIV);
+ chunk_wbc(&ch, OP_PRINT);
+
chunk_wbc(&ch, OP_RET);
- chunk_wconst(&ch, VAL_BOOL(false));
- chunk_wconst(&ch, VAL_NIL);
- chunk_wconst(&ch, VAL_NUM(420.69));
+
+ disasm_chunk(&ch);
Vm vm = vm_new(&ch);
#define RBYTE() (vm.ch->b[vm.ip++])
+#define PUSH(v) vm.stack[vm.sp++] = v;
+#define POP() (vm.stack[--vm.sp])
+
+ puts("---");
while (1) {
uint8_t instr = RBYTE();
switch (instr) {
@@ -84,14 +89,38 @@ static void runvm() {
printf("done!\n");
goto done;
break;
- case OP_LOADK:
+ case OP_LOADK:;
uint8_t cix = RBYTE();
Val v = vm.ch->c[cix];
- print_val(v);
+ PUSH(v);
+ // printf(" (pushing ");
+ // print_val(v);
+ // printf(")\n");
break;
case OP_PRINT:
- printf("print\n");
+ println_val(POP());
+ break;
+
+#define ARITH_OP(opcode, OP) \
+ case opcode: { \
+ Val b = POP(); \
+ Val a = POP(); \
+ if (!IS_NUM(a) || !IS_NUM(b)) { \
+ printf("can't do arithmetic on %s and %s\n", \
+ valty_str(a.ty), valty_str(b.ty)); \
+ goto done; \
+ } \
+ PUSH(VAL_NUM(AS_NUM(a) OP AS_NUM(b))); \
+ } \
break;
+
+ ARITH_OP(OP_ADD, +)
+ ARITH_OP(OP_SUB, -)
+ ARITH_OP(OP_MUL, *)
+ ARITH_OP(OP_DIV, /)
+#undef ARITH_OP
+
+
}
}
done:;
diff --git a/vm.h b/vm.h
index 7f76e05..cfa3f6d 100644
--- a/vm.h
+++ b/vm.h
@@ -36,6 +36,11 @@ typedef enum {
OP_RET,
OP_LOADK,
OP_PRINT,
+
+ OP_ADD,
+ OP_SUB,
+ OP_MUL,
+ OP_DIV,
} Op;