SearchA-ZB › Befunge-93 Interpreter

Befunge-93 Interpreter

1993 Open source · Public domain Online

A clean, from-scratch Befunge-93 interpreter written for emulators.org and running entirely in your browser. Befunge-93 is the two-dimensional stack esolang created by Chris Pressey in 1993: a program is an 80×25 torus of instruction cells, an instruction pointer walks it in one of four directions executing each cell, and a single integer stack holds the data. The p and g commands write and read the grid itself, so a program can rewrite its own code as it runs.

The view is the whole machine at once - the 80×25 playfield with the current instruction-pointer cell highlighted, its direction, the stack, and the output line. It boots running the classic "Hello World!", and plugs into the shared debugger so you can pause, single-step one grid cell at a time, set breakpoints on any (x,y) cell, and watch the stack or a self-modified cell.

Befunge-93 language specification ↗

Visit the official site ↗

Runs on: Web browser

Befunge-93 Interpreter Online Emulator

Play Befunge-93 Interpreter using JavaScript directly in your browser.

Configurations

ConfigurationEmulatorMachineOSLegal
Hello World!Befunge-93 InterpreteropenOpen ⛶
Number outputBefunge-93 InterpreteropenOpen ⛶

Chips

Notes

Embedding

Befunge-93 is authored here from scratch, so embedding is just three small files: the VM (befunge93.js), the canvas view (befunge-render.js), and a boot shim that owns the loop. There is no CPU and no ROM - the "machine" is an 80×25 grid of instruction cells plus one integer stack.

Boot. Create the VM, load a program, wire a renderer, and run your own loop built on vm.step() (execute exactly one grid cell):

var vm = new Befunge93();
vm.load('"!dlroW olleH">:#,_@');        // the classic Hello World!
var view = new BefungeRender(canvas, vm);
(function loop(){
  for (var i = 0; i < 200 && !vm.halted; i++) vm.step();  // one cell each
  view.draw();
  if (!vm.halted) requestAnimationFrame(loop);
})();

The machine is plain objects. Everything the debugger needs is a live field; there is no wasm heap:

MemberKindWhat it does
vm.step()methodExecute exactly one grid cell (the current IP cell), then move the IP. The single-step primitive; returns {ok}, {halted} or {waiting}.
vm.gridfieldThe 80×25 playfield as a Uint8Array (row-major, y*80 + x). Poke it to edit the program live.
vm.stackfieldThe integer stack (a JS array; top is the last element).
vm.ip / vm.dirfieldThe instruction pointer {x,y} and its travel direction {x,y}.
vm.stringModefieldTrue while between " quotes (each cell is pushed as its ASCII value instead of executed).
vm.queueInput(v)methodFeed stdin for & (integer) and ~ (character): pass a string or a number.
vm.load(text) / vm.reset()methodParse a program into the grid / clear the machine to its initial state.

Debugger integration

Because the VM is ordinary JavaScript and vm.step() is one grid cell, the debugger drives it directly. The boot shim publishes window.EMU_BOOT with a transport whose stepInsn(n) runs n cells, and a run loop that checks the current IP against a breakpoint set every cell:

function runBatch(){
  for (var i = 0; i < speed; i++){
    var idx = vm.ip.y * 80 + vm.ip.x;                // linear cell address
    if (bps.has(idx) && !justResumed) return 'bp';   // break when IP reaches (x,y)
    var ev = vm.step();
    if (ev.halted) return 'halt';
    if (ev.waiting) return 'wait';                // blocked on & / ~ input
  }
}

Breakpoints are (x,y) cells, stored as the linear address y*80 + x - the same address pc() returns and the disasm/hex views use, so clicking the gutter next to a cell sets a breakpoint there. Watchpoints cover a written grid cell (via the p path) and the stack (any push/pop). The "registers" are the real machine state: IPX, IPY, direction, string mode and stack depth.

The disassembler is unusual: Befunge has no linear instruction stream, so /debugger/src/cpus/befunge.js decodes each grid byte as its one-cell command (with the cell's (x,y) and a description). That annotates the playfield-as-memory view without pretending the grid is executed top-to-bottom.

Architecture

Befunge-93 (Chris Pressey, Cat's Eye Technologies, 1993) is a deliberately hard-to-compile two-dimensional esolang:

  • The playfield - an 80×25 torus of character cells. The instruction pointer walks it in one of four directions and wraps at every edge.
  • The stack - a single stack of integers; every operator pushes and pops it.
  • Flow - > < ^ v steer, ? picks a random direction, _ and | are horizontal/vertical branches, # bridges over the next cell.
  • String mode - " toggles pushing each cell's ASCII value instead of executing it.
  • Self-modification - p (put) writes a cell and g (get) reads one, so a program can rewrite its own code as it runs. That is why the playfield is the memory the debugger shows.
  • I/O - ./, output an integer/character, &/~ read one, @ halts.

This interpreter is a faithful clean-room implementation of that public specification. The language spec is public domain; the reference distribution is BSD-2-Clause. There is no external code to trust - the entire machine is a couple of hundred lines of readable JavaScript, which is exactly what makes it a clear debugging target.