Search › A-Z › B › Befunge-93 Interpreter
Befunge-93 Interpreter
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 ↗
Runs on: Web browser
Befunge-93 Interpreter Online Emulator
Play Befunge-93 Interpreter using JavaScript directly in your browser.
Controls
Configurations
| Configuration | Emulator | Machine | OS | Legal | |
|---|---|---|---|---|---|
| Hello World! | Befunge-93 Interpreter | open | Open ⛶ | ||
| Number output | Befunge-93 Interpreter | open | Open ⛶ |
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:
| Member | Kind | What it does |
|---|---|---|
vm.step() | method | Execute exactly one grid cell (the current IP cell), then move the IP. The single-step primitive; returns {ok}, {halted} or {waiting}. |
vm.grid | field | The 80×25 playfield as a Uint8Array (row-major, y*80 + x). Poke it to edit the program live. |
vm.stack | field | The integer stack (a JS array; top is the last element). |
vm.ip / vm.dir | field | The instruction pointer {x,y} and its travel direction {x,y}. |
vm.stringMode | field | True while between " quotes (each cell is pushed as its ASCII value instead of executed). |
vm.queueInput(v) | method | Feed stdin for & (integer) and ~ (character): pass a string or a number. |
vm.load(text) / vm.reset() | method | Parse 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 -
> < ^ vsteer,?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 andg(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.