WASM tail-call instruction wired into every tail position:
if branches, eval_begin last expression, all special-form dispatchers
(cond/when/unless/case/let/let*/letrec/begin/and/or), function
application's $apply, and apply's closure-body $eval_begin.
wat2wasm + wasm-validate now use --enable-tail-call.
Reader fixes:
- Dotted pair syntax: (a b . rest) parses as a real dotted list.
Without this, variadic params and other dotted-cdr forms parsed
as 4-element proper lists.
- Stray ) at top level advances source_ptr instead of spinning
forever. Found via bisection of functional.lsp under TCO.
- eval_args guards against non-pair tails so a misplaced dotted
argument (e.g. an unexpanded macro template) can't deref garbage.
Cross-tier numbers (wasm-test-functional-cross):
before: 93/111 reached, stack overflow on (ack 3 4)
now: progresses through the full TCO section, deep let, named-let
to 100k, mutual recursion to 200k. Still climbing.
Bend gpu demo:
6th playground option ("bend (gpu dispatch) ⚡") ships a SHAKE256
fan-out at 1M inputs via (bend!-call ...). Run button is GUARDED:
if no bend URL is configured, refuses with
"set a bend URL first — this demo is GPU-only by design".
Protects customer machines from burning minutes on a workload the
local tiers cannot finish in reasonable time.
107 lines
4.9 KiB
HTML
107 lines
4.9 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>lumbda repl — three tiers, persistent sessions</title>
|
|
<link rel="stylesheet" href="style.css">
|
|
<link rel="stylesheet" href="repl.css">
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"@codemirror/state": "https://esm.sh/*@codemirror/state@6.4.1",
|
|
"@codemirror/view": "https://esm.sh/*@codemirror/view@6.34.1",
|
|
"@codemirror/commands": "https://esm.sh/*@codemirror/commands@6.6.2",
|
|
"@codemirror/language": "https://esm.sh/*@codemirror/language@6.10.3",
|
|
"@codemirror/legacy-modes/mode/scheme": "https://esm.sh/*@codemirror/legacy-modes@6.4.1/mode/scheme",
|
|
"@codemirror/theme-one-dark": "https://esm.sh/*@codemirror/theme-one-dark@6.1.2",
|
|
"@lezer/highlight": "https://esm.sh/*@lezer/highlight@1.2.1",
|
|
"@lezer/common": "https://esm.sh/*@lezer/common@1.2.3",
|
|
"style-mod": "https://esm.sh/*style-mod@4.1.2",
|
|
"crelt": "https://esm.sh/*crelt@1.0.6",
|
|
"w3c-keyname": "https://esm.sh/*w3c-keyname@2.2.8"
|
|
}
|
|
}
|
|
</script>
|
|
</head>
|
|
<body class="repl">
|
|
|
|
<header>
|
|
<a class="brand" href="../" aria-label="lumbda home">
|
|
<img class="logo" src="lumbda-logo-green.png" alt="" aria-hidden="true">
|
|
<h1 aria-label="lumbda.">lumbda<span class="period" aria-hidden="true">.</span></h1>
|
|
</a>
|
|
<p class="tagline">three tiers, persistent sessions</p>
|
|
</header>
|
|
|
|
<div id="lock-screen" class="lock-screen">
|
|
<div class="lock-card">
|
|
<h2>unlock</h2>
|
|
<p>type a password to unlock or create a vault. every keystroke and
|
|
transcript line stays inside your browser — nothing leaves
|
|
this tab.</p>
|
|
<details class="lock-explain">
|
|
<summary>how the encryption works</summary>
|
|
<ul>
|
|
<li>your password is run through <strong>PBKDF2</strong> (200,000
|
|
iterations, SHA-256) with a random 32-byte salt generated
|
|
once per device and stored in <code>localStorage</code>.</li>
|
|
<li>that derives an <strong>AES-GCM 256-bit key</strong>. all
|
|
transcripts are encrypted with this key before any
|
|
<code>localStorage.setItem()</code> call.</li>
|
|
<li>the <strong>vault id</strong> is
|
|
<code>SHA-256(password || salt)</code> — different
|
|
passwords on the same device address completely independent
|
|
vaults. wrong password = decryption fails, you don't see
|
|
other vaults' contents.</li>
|
|
<li>same protocol as <a href="https://unsandbox.com/blog/vault-encryption-design"
|
|
target="_blank">unsandbox's vault design</a>, implemented
|
|
on the native <code>crypto.subtle</code> API instead of a
|
|
shipped CryptoJS bundle. source:
|
|
<a href="crypto.js" target="_blank"><code>crypto.js</code></a>.</li>
|
|
<li>passwords are never sent anywhere — not to lumbda.com,
|
|
not to a backend, not to a worker. nothing to leak in
|
|
transit because nothing transits.</li>
|
|
<li><strong>ephemeral</strong> skips the vault entirely —
|
|
nothing is written to disk; closing the tab loses everything.
|
|
use this on a shared machine when persistence would be a
|
|
footgun.</li>
|
|
</ul>
|
|
</details>
|
|
<input id="password" type="password" autocomplete="off" autofocus placeholder="password">
|
|
<div class="lock-row">
|
|
<button id="unlock" class="primary">unlock vault</button>
|
|
<button id="fresh" class="secondary" title="skip the vault, run ephemerally — transcripts vanish on reload">ephemeral</button>
|
|
</div>
|
|
<p class="lock-note" id="lock-note"></p>
|
|
</div>
|
|
</div>
|
|
|
|
<main id="repl-stream" class="repl-stream" hidden>
|
|
<section class="tabbar" id="tabbar">
|
|
<div class="tabs" id="tabs"></div>
|
|
<button id="new-tab" class="ghost" title="new repl session">+</button>
|
|
<span class="spacer"></span>
|
|
<button id="reset-tier" class="ghost" title="reboot the worker for the current tab — state lost">↻ reboot tier</button>
|
|
<button id="clear-log" class="ghost" title="clear the transcript">clear log</button>
|
|
<button id="cancel" class="ghost" disabled>cancel</button>
|
|
<button id="lock" class="ghost" title="lock vault — passes back to lock screen">lock</button>
|
|
</section>
|
|
<div id="transcript" class="transcript"></div>
|
|
<div class="prompt-bar" id="prompt-bar">
|
|
<span class="prompt-sigil">λ></span>
|
|
<textarea id="input" rows="1" spellcheck="false"
|
|
placeholder="(+ 1 2)"></textarea>
|
|
<select id="tier-select" title="which tier evaluates this input">
|
|
<option value="python">python (pyodide)</option>
|
|
<option value="c" selected>c (emcc)</option>
|
|
<option value="asm">asm (wat)</option>
|
|
<option value="all">all three (race)</option>
|
|
</select>
|
|
<button id="send" class="primary">send</button>
|
|
</div>
|
|
</main>
|
|
|
|
<script type="module" src="repl.js"></script>
|
|
</body>
|
|
</html>
|