1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include "val.h"
#include "vm.h"
#include "mem.h"
#include "dis.h"
Chunk chunk_new(State *S) {
return (Chunk){ 0 };
}
size_t chunk_wbc(State *S, Chunk *ch, uint8_t byte) {
if (ch->bc.len == ch->bc.cap) {
size_t newsz = (ch->bc.cap == 0 ? 8 : ch->bc.cap * 2);
ch->bc.d = RENEW_ARR(S, ch->bc.d, uint8_t, ch->bc.cap, newsz);
ch->bc.cap = newsz;
}
size_t ix = ch->bc.len;
ch->bc.d[ix] = byte;
ch->bc.len ++;
return ix;
}
size_t chunk_wconst(State *S, Chunk *ch, Val v) {
if (ch->consts.len == ch->consts.cap) {
size_t newsz = (ch->consts.cap == 0 ? 8 : ch->consts.cap *2);
ch->consts.d = RENEW_ARR(S, ch->consts.d, Val, ch->consts.cap, newsz);
ch->consts.cap = newsz;
}
size_t ix = ch->consts.len;
ch->consts.d[ix] = v;
ch->consts.len ++;
return ix;
}
Thread thread_new(State *S) {
Thread th = (Thread){ 0 };
for (int i = 0; i < STACKSIZE; i++) {
th.stack[i] = VAL_NIL;
}
return th;
}
void runvm(State *S) {
Thread *th = S->th;
Chunk *ch = th->ch;
disasm_chunk(ch);
#define RBYTE() (ch->bc.d[th->ip++])
#define PUSH(v) th->stack[th->sp++] = v;
#define POP() (th->stack[--th->sp])
puts("---");
while (1) {
uint8_t instr = RBYTE();
switch (instr) {
case OP_RET:
printf("done!\n");
goto done;
break;
case OP_LOADK: {
uint8_t cix = RBYTE();
Val v = ch->consts.d[cix];
PUSH(v);
// printf(" (pushing ");
// print_val(v);
// printf(")\n");
break;
}
case OP_PRINT:
println_val(POP());
break;
case OP_GETGLOBAL: {
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 = ht_get(S, &S->globals, AS_STRING(varname));
PUSH(v);
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", \
typename_str(a), typename_str(b)); \
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:;
}
|