some initial supports for bytecode VM
authorcassowarii <cassowary@cassowary.me>
Sun, 28 Jun 2026 04:15:32 +0000 (21:15 -0700)
committercassowarii <cassowary@cassowary.me>
Sun, 28 Jun 2026 04:15:32 +0000 (21:15 -0700)
src/common.h
src/data/data.h [new file with mode: 0644]
src/vm/block.c [new file with mode: 0644]
src/vm/block.h [new file with mode: 0644]
src/vm/bytecode.h [new file with mode: 0644]
src/vm/exec.c [new file with mode: 0644]
src/vm/exec.h [new file with mode: 0644]
src/vm/vm.h [new file with mode: 0644]

index 75541ee..9855724 100644 (file)
@@ -3,7 +3,8 @@
 
 #include "global.h"
 #include "mem/mem.h"
-#include "data/value.h"
+#include "data/data.h"
+#include "vm/vm.h"
 #include <string.h> // for memcpy/memset
 
 #endif
diff --git a/src/data/data.h b/src/data/data.h
new file mode 100644 (file)
index 0000000..f3e3031
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __SARABANDE_DATA_H__
+#define __SARABANDE_DATA_H__
+
+#include "data/value.h"
+
+#endif
diff --git a/src/vm/block.c b/src/vm/block.c
new file mode 100644 (file)
index 0000000..e90c047
--- /dev/null
@@ -0,0 +1,73 @@
+#include "vm/block.h"
+
+#define INITIAL_PROGRAM_BLOCK_SIZE 32
+
+void sbVmProgram_init(sbVmProgram *pm, usize initial_arena_size) {
+  *pm = (sbVmProgram) {0};
+  sbArena_initialize(&pm->arena, initial_arena_size);
+}
+
+sbVmPartialBlock sbVmBlock_create(usize initial_bytecode_size, usize initial_constant_size) {
+  sbVmPartialBlock pb = {0};
+  sbBuffer_initialize(&pb.bytecode, initial_bytecode_size);
+  sbBuffer_initialize(&pb.constants, initial_constant_size);
+  return pb;
+}
+
+void sbVmBlock_reset(sbVmPartialBlock *pb) {
+  sbBuffer_reset(&pb->bytecode);
+  sbBuffer_reset(&pb->constants);
+}
+
+void sbVmBlock_deinitialize(sbVmPartialBlock *pb) {
+  sbBuffer_deinitialize(&pb->bytecode);
+  sbBuffer_deinitialize(&pb->constants);
+}
+
+void sbVmProgram_initialize(sbVmProgram *pm) {
+  pm->block_count = 0;
+  pm->block_capacity = INITIAL_PROGRAM_BLOCK_SIZE;
+  pm->blocks = malloc(pm->block_capacity * sizeof(sbVmBlock));
+}
+
+void sbVmProgram_deinitialize(sbVmProgram *pm) {
+  free(pm->blocks);
+  *pm = (sbVmProgram) {0};
+}
+
+sbBlockId sbVmProgram_add_block(sbVmProgram *pm, sbVmPartialBlock *pb) {
+  const usize bytecode_length = pb->bytecode.size;
+  char *bytecode = sbArena_alloc(&pm->arena, bytecode_length);
+  memcpy(bytecode, pb->bytecode.data, bytecode_length);
+
+  const usize constants_length = pb->constants.size;
+  char *constants = sbArena_alloc(&pm->arena, constants_length);
+  memcpy(constants, pb->constants.data, constants_length);
+
+  sbVmBlock bk = {
+    .bytecode = bytecode,
+    .bytecode_length = bytecode_length,
+    .constants = (hV*)constants,
+    .constants_count = constants_length / sizeof(hV),
+  };
+
+  if (pm->block_count >= pm->block_capacity) {
+    usize new_capacity = pm->block_capacity * 3 / 2;
+    if (new_capacity <= pm->block_capacity) new_capacity = pm->block_capacity + 1;
+    void *new_blocks = realloc(pm->blocks, new_capacity * sizeof(sbVmBlock));
+    if (new_blocks) {
+      pm->blocks = new_blocks;
+      pm->block_capacity = new_capacity;
+    } else {
+      PANIC("ran out of memory while compiling program!");
+    }
+  }
+
+  sbBlockId result = pm->block_count;
+
+  pm->blocks[pm->block_count] = bk;
+
+  pm->block_count ++;
+
+  return result;
+}
diff --git a/src/vm/block.h b/src/vm/block.h
new file mode 100644 (file)
index 0000000..3f3919b
--- /dev/null
@@ -0,0 +1,39 @@
+#include "common.h"
+
+/* dynamic sized block that we can more easily add
+ * things to while compiling */
+typedef struct sbVmPartialBlock {
+  sbBuffer bytecode;
+  sbBuffer constants;
+} sbVmPartialBlock;
+
+/* fixed size / frozen block of bytecode */
+typedef struct sbVmBlock {
+  const char *bytecode;
+  usize bytecode_length;
+  const hV *constants;
+  usize constants_count;
+} sbVmBlock;
+
+typedef struct sbVmProgram {
+  sbArena arena;
+  sbVmBlock *blocks;
+  usize block_count;
+  usize block_capacity;
+} sbVmProgram;
+
+typedef usize sbBlockId;
+
+void sbVmProgram_init(sbVmProgram *pm, usize initial_arena_size);
+
+sbVmPartialBlock sbVmBlock_create(usize initial_bytecode_size, usize initial_constant_size);
+
+void sbVmBlock_reset(sbVmPartialBlock *pb);
+
+void sbVmBlock_deinitialize(sbVmPartialBlock *pb);
+
+void sbVmProgram_initialize(sbVmProgram *pm);
+
+void sbVmProgram_deinitialize(sbVmProgram *pm);
+
+sbBlockId sbVmProgram_add_block(sbVmProgram *pm, sbVmPartialBlock *pb);
diff --git a/src/vm/bytecode.h b/src/vm/bytecode.h
new file mode 100644 (file)
index 0000000..5a206b1
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef __SARABANDE_BYTECODE_H__
+#define __SARABANDE_BYTECODE_H__
+
+#include "global.h"
+
+typedef enum sbOpcode {
+  BC_NOP = 0,
+  BC_LD_CONST,
+  BC_LD_IMM,
+  BC_LD_VAR,
+  BC_LD_CTX,
+  BC_LD_UPVAL,
+  BC_ST_VAR,
+  BC_ST_UPVAL,
+  BC_CALL,
+  BC_JMP,
+  BC_RET = 10,
+  BC_SEND,
+  BC_OP_ADD,
+  BC_OP_SUB,
+  BC_OP_MUL,
+  BC_OP_DIV,
+  BC_OP_NEG,
+  BC_OP_MOD,
+  BC_OP_POW,
+  BC_OP_DEREF,
+  BC_LIST_NEW = 20,
+  BC_HASH_NEW,
+  BC_LIST_ADD,
+  BC_HASH_ADD,
+  BC_LONG_NUM = 253,
+  BC_VLONG_NUM = 254,
+  BC_HALT = 255,
+} sbOpcode;
+
+#endif
diff --git a/src/vm/exec.c b/src/vm/exec.c
new file mode 100644 (file)
index 0000000..b39c709
--- /dev/null
@@ -0,0 +1 @@
+#include "vm/exec.h"
diff --git a/src/vm/exec.h b/src/vm/exec.h
new file mode 100644 (file)
index 0000000..67c02a2
--- /dev/null
@@ -0,0 +1 @@
+#include "common.h"
diff --git a/src/vm/vm.h b/src/vm/vm.h
new file mode 100644 (file)
index 0000000..24e3b76
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef __SARABANDE_VM_H__
+#define __SARABANDE_VM_H__
+
+#include "vm/bytecode.h"
+
+#endif