Skip to content

Commit 70434e7

Browse files
committed
feat: Add bytecode disassembler and tests for bytecode serialization, deserialization, and simple VM execution.
1 parent 153de07 commit 70434e7

4 files changed

Lines changed: 106 additions & 3 deletions

File tree

build_tests.bat

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
@echo off
2+
clang -o bytecode_tests.exe ^
3+
-Iinclude -Isrc -D_CRT_SECURE_NO_WARNINGS -DPROX_STATIC ^
4+
tests/bytecode_tests.c ^
5+
src/vm/bytecode.c ^
6+
src/vm/disasm.c ^
7+
src/vm/vm_dispatch.c ^
8+
src/runtime/value.c ^
9+
src/runtime/object.c ^
10+
src/runtime/memory.c ^
11+
src/runtime/table.c ^
12+
src/runtime/chunk.c ^
13+
src/compiler/parser/ast.c ^
14+
src/runtime/vm_helpers.c
15+
if %errorlevel% equ 0 (
16+
echo Build successful.
17+
.\bytecode_tests.exe
18+
) else (
19+
echo Build failed.
20+
)

compile_tests.bat

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
@echo off
2+
clang -o bytecode_tests.exe -Iinclude -Isrc -D_CRT_SECURE_NO_WARNINGS -DPROX_STATIC ^
3+
tests/bytecode_tests.c ^
4+
src/vm/bytecode.c ^
5+
src/vm/disasm.c ^
6+
src/vm/vm_dispatch.c ^
7+
src/runtime/value.c ^
8+
src/runtime/object.c ^
9+
src/runtime/memory.c ^
10+
src/runtime/table.c ^
11+
src/runtime/chunk.c ^
12+
src/compiler/parser/ast.c ^
13+
src/runtime/vm_helpers.c
14+
if %errorlevel% equ 0 echo Build complete.

src/vm/disasm.c

Lines changed: 71 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ void disasm_chunk(const Chunk *chunk) {
7878
case OP_CONSTANT:
7979
offset = constant_instruction("OP_CONSTANT", chunk, offset);
8080
break;
81+
case OP_NOP:
82+
offset = simple_instruction("OP_NOP", offset);
83+
break;
8184
case OP_NIL:
8285
offset = simple_instruction("OP_NIL", offset);
8386
break;
@@ -90,6 +93,21 @@ void disasm_chunk(const Chunk *chunk) {
9093
case OP_POP:
9194
offset = simple_instruction("OP_POP", offset);
9295
break;
96+
case OP_DUP:
97+
offset = simple_instruction("OP_DUP", offset);
98+
break;
99+
case OP_BUILD_LIST:
100+
offset = byte_instruction("OP_BUILD_LIST", chunk, offset);
101+
break;
102+
case OP_BUILD_MAP:
103+
offset = byte_instruction("OP_BUILD_MAP", chunk, offset);
104+
break;
105+
case OP_GET_INDEX:
106+
offset = simple_instruction("OP_GET_INDEX", offset);
107+
break;
108+
case OP_SET_INDEX:
109+
offset = simple_instruction("OP_SET_INDEX", offset);
110+
break;
93111
case OP_GET_LOCAL:
94112
offset = byte_instruction("OP_GET_LOCAL", chunk, offset);
95113
break;
@@ -105,6 +123,21 @@ void disasm_chunk(const Chunk *chunk) {
105123
case OP_SET_GLOBAL:
106124
offset = constant_instruction("OP_SET_GLOBAL", chunk, offset);
107125
break;
126+
case OP_GET_UPVALUE:
127+
offset = byte_instruction("OP_GET_UPVALUE", chunk, offset);
128+
break;
129+
case OP_SET_UPVALUE:
130+
offset = byte_instruction("OP_SET_UPVALUE", chunk, offset);
131+
break;
132+
case OP_GET_PROPERTY:
133+
offset = constant_instruction("OP_GET_PROPERTY", chunk, offset);
134+
break;
135+
case OP_SET_PROPERTY:
136+
offset = constant_instruction("OP_SET_PROPERTY", chunk, offset);
137+
break;
138+
case OP_GET_SUPER:
139+
offset = constant_instruction("OP_GET_SUPER", chunk, offset);
140+
break;
108141
case OP_EQUAL:
109142
offset = simple_instruction("OP_EQUAL", offset);
110143
break;
@@ -126,6 +159,9 @@ void disasm_chunk(const Chunk *chunk) {
126159
case OP_DIVIDE:
127160
offset = simple_instruction("OP_DIVIDE", offset);
128161
break;
162+
case OP_MODULO:
163+
offset = simple_instruction("OP_MODULO", offset);
164+
break;
129165
case OP_NOT:
130166
offset = simple_instruction("OP_NOT", offset);
131167
break;
@@ -145,19 +181,51 @@ void disasm_chunk(const Chunk *chunk) {
145181
offset = jump_instruction("OP_LOOP", -1, chunk, offset);
146182
break;
147183
case OP_CALL:
148-
offset = byte_instruction("OP_CALL", chunk, offset); // Assume 1 byte arg count?
184+
offset = byte_instruction("OP_CALL", chunk, offset);
185+
break;
186+
case OP_INVOKE:
187+
offset = constant_instruction("OP_INVOKE", chunk, offset);
188+
// Note: Invoke also has an arg count byte
189+
printf(" %d args\n", chunk->code[offset]);
190+
offset++;
191+
break;
192+
case OP_CLOSURE: {
193+
offset++;
194+
uint8_t constant = chunk->code[offset++];
195+
printf("%-16s %4d ", "OP_CLOSURE", constant);
196+
print_value(consttable_get(chunk, constant));
197+
printf("\n");
198+
break;
199+
}
200+
case OP_CLOSE_UPVALUE:
201+
offset = simple_instruction("OP_CLOSE_UPVALUE", offset);
202+
break;
203+
case OP_RETURN:
204+
offset = simple_instruction("OP_RETURN", offset);
149205
break;
150206
case OP_CLASS:
151207
offset = constant_instruction("OP_CLASS", chunk, offset);
152208
break;
209+
case OP_INHERIT:
210+
offset = simple_instruction("OP_INHERIT", offset);
211+
break;
153212
case OP_METHOD:
154213
offset = constant_instruction("OP_METHOD", chunk, offset);
155214
break;
156215
case OP_USE:
157216
offset = constant_instruction("OP_USE", chunk, offset);
158217
break;
159-
case OP_RETURN:
160-
offset = simple_instruction("OP_RETURN", offset);
218+
case OP_INTERFACE:
219+
offset = constant_instruction("OP_INTERFACE", chunk, offset);
220+
break;
221+
case OP_MAKE_FOREIGN:
222+
offset = simple_instruction("OP_MAKE_FOREIGN", offset);
223+
break;
224+
case OP_MAT_MUL:
225+
offset = simple_instruction("OP_MAT_MUL", offset);
226+
break;
227+
case OP_MAKE_TENSOR:
228+
offset = simple_instruction("OP_MAKE_TENSOR", offset);
161229
break;
162230
case OP_HALT:
163231
offset = simple_instruction("OP_HALT", offset);

tests/bytecode_tests.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ int vm_run_chunk_simple(const Chunk *chunk);
2727

2828
int main(void) {
2929
printf("ProXPL bytecode tests start\n");
30+
printf("OP_CONSTANT: %d, OP_NOP: %d\n", OP_CONSTANT, OP_NOP);
3031

3132
/* Create an example hello chunk and write to file */
3233
const char *outpath = "examples/hello.proxbc";

0 commit comments

Comments
 (0)