R0 / S1 WebAssembly Demo

A standalone build (no Emscripten JS runtime, no libc/WASI) lives at docs/standalone.html.

Counter: 0

Application logic: R0 → WebAssembly
Browser plumbing: JavaScript

This application logic is R0 running inside WebAssembly. JavaScript only forwards browser events and performs the requested DOM update.

R0 application

counter: 0

on-click: [
    counter: + counter 1
    web-set-int 1 counter
]
Show low-level RAW/S1 host adapter

RAW is R0’s trapdoor to the tiny Forth-like S1 substrate. Application code normally stays above this layer.

web-set-int: raw 2 [
    LIT 16 DIV
    >R
    LIT 16 DIV
    LIT 1000000 MUL
    R> ADD
    PRINT
    ARITY 0 EXIT
]
Show browser JavaScript glue

This glue contains no counter state or increment logic; it only forwards clicks and performs the DOM update R0 requests.

/* web/glue.js -- the JavaScript half of the browser boundary.
 *
 * JavaScript responsibilities only:
 *   - capture the host's standard output (the WEB_SET_INT transport);
 *   - decode handle/value and update the mapped DOM element;
 *   - forward button clicks to the exported WASM entry `r0_click`.
 *
 * No counter state or application logic lives here.
 */

/* handle -> DOM element id (numeric DOM handle 1 = the counter display) */
var R0_DOM_HANDLES = { 1: 'counter' };

Module.print = function (line) {
    var s = String(line).replace(/^\s+|\s+$/g, '');
    if (s === '') return;
    var n = parseInt(s, 10);
    if (!isNaN(n) && n >= 1000000) {
        var handle = Math.floor(n / 1000000);
        var value = n % 1000000;
        var elId = R0_DOM_HANDLES[handle];
        if (elId) {
            var el = document.getElementById(elId);
            if (el) el.textContent = String(value);
        }
    } else {
        console.log('[R0]', s);   /* plain R0 output (e.g. the ready line) */
    }
};
Module.printErr = function (line) {
    console.log('[R0:err]', line);
};

Module.onRuntimeInitialized = function () {
    var btn = document.getElementById('increment');
    btn.addEventListener('click', function () {
        Module._r0_click();
    });
};