Download Game! Currently 74 players and visitors. Last logged in:DefaultCorrelPaziIberiamssp

Blitzer's Blog >> 72244

Back to blogs index
Posted: 10 Sep 2026 11:09 [ permalink ]
Good morning. Yes  mvp2.js is currently a monolith with four distinct
responsibilities:

Core runtime primitives: Opcodes, StateBuffer, Env

Compiler: AST  bytecode

VM: bytecode execution in worker

Main/worker bootstrap: payload, worker spawn, polling, termination

It also contains duplicated compiler blocks and a few integration bugs that
become harder to see when everything lives in one file. Splitting it into
small, single-purpose modules will make it much safer for both human and
AI-assisted development.

Recommended file structure
text
mvp2/
  package.json
  README.md
  src/
    index.js
    core/
      opcodes.js
      state-buffer.js
      env.js
    compiler/
      compiler.js
      special-forms.js        # optional, if compiler grows
    analyzer/
      analyzer.js
      type-env.js
    vm/
      vm.js
      worker-entry.js
    runtime/
      main.js
      payloads/
        heavy-payload.js
  test/
    compiler.test.js
    vm.test.js
    analyzer.test.js
    state-buffer.test.js
    env.test.js
Keep CommonJS unless you have a strong reason to switch to ESM. The current
code uses require, and worker_threads works cleanly with CommonJS.

Dependency graph
text
core/opcodes
   core/state-buffer
   core/env
   compiler/compiler
   analyzer/analyzer
   vm/vm

core/env
   vm/vm

compiler/compiler
   core/opcodes

vm/vm
   core/opcodes
   core/env

vm/worker-entry
   core/state-buffer
   vm/vm

runtime/main
   compiler/compiler
   core/state-buffer
   runtime/payloads/heavy-payload
No circular dependencies. That is important for AI-assisted edits because the
model can reason about one file at a time.

Migration steps
Create the folder structure.

Move Opcodes into core/opcodes.js.

Move StateBuffer into core/state-buffer.js and add STATUS.

Move Env into core/env.js.

Move compile into compiler/compiler.js. Remove duplicated blocks and fix def
options propagation.

Move executeVMWorker into vm/vm.js as executeVM. Parameterize stateBuffer and
gasLimit.

Create vm/worker-entry.js to read workerData and call executeVM.

Move main-thread logic into runtime/main.js.

Move heavyPayload into runtime/payloads/heavy-payload.js.

Create src/index.js for public exports.

Add tests under test/.

Update the new Worker(...) path to point at vm/worker-entry.js.

Safety and maintenance practices for AI development
Keep every file under ~300 lines. If a file grows beyond that, split by
special form or opcode family.

One concept per file. Opcodes, Env, StateBuffer, Compiler, VM, Analyzer should
never be mixed.

Use JSDoc for every exported function. AI models use signatures and comments
heavily.

Freeze constant objects with Object.freeze.

Inject dependencies. The VM should receive stateBuffer, gasLimit, and
telemetry hooks rather than importing them directly.

Write tests before refactoring. At minimum:

compiler.test.js: AST  expected bytecode.

vm.test.js: bytecode  expected result.

env.test.js: scope, shadowing, set.

state-buffer.test.js: atomic read/write consistency.

analyzer.test.js: type errors and valid programs.

Use node --test and assert. No need for a heavy test framework.

Add a README.md with the opcode table and a small AST example. That becomes
the shared context for future AI prompts.

Avoid global mutable state. The current Opcodes object is fine as a frozen
module export.

Keep the worker entry file tiny. It is the boundary between Nodes worker
system and your VM.

Specific issues to fix during the split
Duplicate array, record, get, and set-idx blocks in compile.

Unreachable fallback operators after mathOps and logicalOps already handle
them.