1#ifndef STACK_VM_H
2#define STACK_VM_H
3
4#include <stddef.h>
5#include <stdint.h>
6
7#define VM_STACK_MAX 1024
8#define VM_CALL_STACK_MAX 256
9#define VM_LOCALS_PER_FRAME 16
10
11typedef enum VmOpcode {
12 OP_PUSH = 1,
13 OP_POP,
14 OP_DUP,
15 OP_SWAP,
16 OP_ADD,
17 OP_SUB,
18 OP_MUL,
19 OP_DIV,
20 OP_MOD,
21 OP_NEG,
22 OP_EQ,
23 OP_LT,
24 OP_GT,
25 OP_JMP,
26 OP_JZ,
27 OP_JNZ,
28 OP_CALL,
29 OP_RET,
30 OP_LOAD,
31 OP_STORE,
32 OP_PRINT,
33 OP_HALT
34} VmOpcode;
35
36typedef enum VmError {
37 VM_OK = 0,
38 VM_ERR_STACK_UNDERFLOW,
39 VM_ERR_STACK_OVERFLOW,
40 VM_ERR_CALL_UNDERFLOW,
41 VM_ERR_CALL_OVERFLOW,
42 VM_ERR_DIVISION_BY_ZERO,
43 VM_ERR_BAD_OPCODE,
44 VM_ERR_BAD_OPERAND,
45 VM_ERR_BAD_LOCAL,
46 VM_ERR_BAD_JUMP,
47 VM_ERR_TRUNCATED_INSTRUCTION,
48 VM_ERR_NO_HALT,
49 VM_ERR_OUT_OF_MEMORY,
50 VM_ERR_OUTPUT
51} VmError;
52
53typedef struct Bytecode {
54 int64_t *words;
55 size_t count;
56 size_t capacity;
57} Bytecode;
58
59typedef struct VmFrame {
60 size_t return_ip;
61 int64_t locals[VM_LOCALS_PER_FRAME];
62} VmFrame;
63
64typedef int (*VmOutputFn)(int64_t value, void *userdata);
65
66typedef struct VM {
67 const Bytecode *code;
68 size_t ip;
69 int64_t stack[VM_STACK_MAX];
70 size_t sp;
71 VmFrame frames[VM_CALL_STACK_MAX];
72 size_t frame_count;
73 VmOutputFn output;
74 void *output_userdata;
75 VmError last_error;
76} VM;
77
78typedef struct AsmError {
79 int line;
80 char message[256];
81} AsmError;
82
83void bytecode_init(Bytecode *bc);
84void bytecode_free(Bytecode *bc);
85VmError bytecode_emit(Bytecode *bc, int64_t word);
86
87void vm_init(VM *vm, const Bytecode *code);
88void vm_set_output(VM *vm, VmOutputFn output, void *userdata);
89VmError vm_run(VM *vm);
90const char *vm_error_string(VmError error);
91
92int assembler_compile_string(const char *source, Bytecode *out, AsmError *error);
93int assembler_compile_file(const char *path, Bytecode *out, AsmError *error);
94
95#endif
96
Discussion
No comments yet. Start the discussion. Recorded by @patrick-toulme.