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
|
#include "us_debug.h"
#include <assert.h>
#include "dyn_arr.h"
#include "vm.h"
static
char *bc_names[] = {
#define BC(name) "BC_" #name,
#include "xbytecode.h"
#undef BC
};
int print_instruction(struct us_proto *proto, int idx)
{
enum bytecode instruction = proto->bytecode[idx];
fprintf(stderr, "%04d %-15s ", idx, bc_names[instruction]);
switch (instruction) {
case BC_LOAD: {
int const_idx = proto->bytecode[idx + 1];
char *const_str = val_to_str(proto->constants[const_idx], NULL);
fprintf(
stderr,
"%d (%s)\n",
const_idx,
const_str
);
mem_free(const_str);
return idx + 2;
}
case BC_LOAD_FUNC: {
int const_idx = proto->bytecode[idx + 1];
assert(proto->constants[const_idx].type == VAL_PROTO);
struct us_proto *p = get_proto(proto->constants[const_idx]);
int upvalc = p->upvalc;
fprintf(
stderr,
"%.*s() %d\n",
(int)p->name->len, p->name->chars,
upvalc
);
return idx + 2 + upvalc * 2;
}
case BC_SMALL_INT:
case BC_ARR:
case BC_GET_UPVAL:
case BC_SET_UPVAL:
case BC_GET_LOCAL:
case BC_SET_LOCAL:
case BC_CALL: {
fprintf(
stderr,
"%d\n",
proto->bytecode[idx + 1]
);
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: {
u16 jmp = (u16)(proto->bytecode[idx + 1] << 8) | proto->bytecode[idx + 2];
int dst = idx + jmp + 3;
if (instruction == BC_LOOP) {
dst = idx + 3 - jmp;
}
fprintf(
stderr,
"-> %04d\n",
dst
);
return idx + 3;
}
case BC_FALSE:
case BC_TRUE:
case BC_ZILCH:
case BC_PUSH_INDEX:
case BC_GET_INDEX:
case BC_SET_INDEX:
case BC_POP:
case BC_POP_UPVAL:
case BC_ADD:
case BC_SUB:
case BC_MULT:
case BC_DIV:
case BC_MOD:
case BC_GT:
case BC_GTE:
case BC_LT:
case BC_LTE:
case BC_NEG:
case BC_NOT:
case BC_EQL:
case BC_NEQL:
case BC_CONCAT:
case BC_RET:
putc('\n', stderr);
return idx + 1;
}
// unreachable
return idx + 1;
}
void print_func(struct us_proto *func)
{
fprintf(stderr, "%s():\n", func->name->chars);
for (int i = 0; i < da_len(func->bytecode);) {
putc('\t', stderr);
i = print_instruction(func, i);
}
}
|