<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Lispix — A Lisp Test Bed for Computer Vision, Machine Learning &amp; Graphics Algorithms | The Rohans Limited on The Rohans</title>
		<link>https://therohans.com/lispix/</link>
		<description>Recent content in Lispix — A Lisp Test Bed for Computer Vision, Machine Learning &amp; Graphics Algorithms | The Rohans Limited on The Rohans</description>
		<generator>Hugo</generator>
		<language>en-GB</language>
		
		
		
		
			<lastBuildDate>Fri, 28 Aug 2026 00:00:00 +0000</lastBuildDate>
		
			<atom:link href="https://therohans.com/lispix/index.xml" rel="self" type="application/rss+xml" />
			<item>
				<title>Lispix - Graphic Algorithm Tester with Tensors (Desmos like but Lisp) | The Rohans</title>
				<link>https://therohans.com/lispix/app/</link>
				<pubDate>Fri, 28 Aug 2026 00:00:00 +0000</pubDate>
				<guid>https://therohans.com/lispix/app/</guid>
				<description>&lt;style&gt;&#xA;    html, body {&#xA;        height: 100%;&#xA;        margin: 0;&#xA;        font-family: system-ui, sans-serif;&#xA;        overflow: hidden;&#xA;    }&#xA;&#xA;    .app {&#xA;        display: flex;&#xA;        height: 100vh;&#xA;    }&#xA;&#xA;    .sidebar {&#xA;        width: 240px;&#xA;        min-width: 120px;&#xA;        max-width: 60vw;&#xA;        resize: horizontal;&#xA;        padding: 1rem;&#xA;        background: #f4f4f4;&#xA;        border-right: 1px solid #ccc;&#xA;        overflow: hidden;&#xA;        display: flex;&#xA;        flex-direction: column;&#xA;    }&#xA;&#xA;    .main {&#xA;        flex: 1;&#xA;        min-width: 0;&#xA;        min-height: 0;&#xA;        display: flex;&#xA;        flex-direction: column;&#xA;    }&#xA;&#xA;    .top {&#xA;        flex: 1;&#xA;        overflow: auto;&#xA;        padding: 1rem;&#xA;    }&#xA;&#xA;    .output {&#xA;        flex: 0 0 25%;&#xA;        min-height: 0;&#xA;        border-top: 1px solid #ccc;&#xA;        background: #fafafa;&#xA;        display: flex;&#xA;        flex-direction: column;&#xA;    }&#xA;&#xA;    .output.collapsed {&#xA;        flex: 0 0 auto;&#xA;    }&#xA;&#xA;    .output.collapsed .outputWrapper {&#xA;        display: none;&#xA;    }&#xA;&#xA;    .output-header {&#xA;        cursor: pointer;&#xA;        padding: .5rem 1rem;&#xA;        display: flex;&#xA;        align-items: center;&#xA;        gap: 1rem;&#xA;        user-select: none;&#xA;        flex-shrink: 0;&#xA;    }&#xA;&#xA;    .collapse-btn {&#xA;        display: inline-block;&#xA;        transition: transform .15s;&#xA;    }&#xA;&#xA;    .output.collapsed .collapse-btn {&#xA;        transform: rotate(-90deg);&#xA;    }&#xA;&#xA;    .tab-btn {&#xA;        font-weight: 600;&#xA;        color: #888;&#xA;        padding: .15rem 0;&#xA;        border-bottom: 2px solid transparent;&#xA;    }&#xA;&#xA;    .tab-btn.active {&#xA;        color: #111;&#xA;        border-bottom-color: #111;&#xA;    }&#xA;&#xA;    .build-hash {&#xA;        margin-left: auto;&#xA;        color: #aaa;&#xA;        font-family: monospace;&#xA;        font-size: .75rem;&#xA;    }&#xA;&#xA;    .output-body {&#xA;        height: 200px;&#xA;        overflow: auto;&#xA;        padding: 1rem;&#xA;        border-top: 1px solid #ccc;&#xA;    }&#xA;&#xA;    .tab-panel {&#xA;        display: none;&#xA;    }&#xA;&#xA;    .tab-panel.active {&#xA;        display: block;&#xA;        position: absolute;&#xA;        inset: 0;&#xA;        overflow-y: auto;&#xA;    }&#xA;&#xA;    #quickref-tab.active {&#xA;        padding: 0 1rem;&#xA;        box-sizing: border-box;&#xA;    }&#xA;&#xA;    .quickref-table {&#xA;        width: 100%;&#xA;        border-collapse: collapse;&#xA;        font-size: .9rem;&#xA;    }&#xA;&#xA;    .quickref-table caption {&#xA;        text-align: left;&#xA;        font-weight: 600;&#xA;        padding: .75rem 0 .25rem;&#xA;    }&#xA;&#xA;    .quickref-table th {&#xA;        text-align: left;&#xA;        padding: .25rem .5rem .25rem 0;&#xA;        border-bottom: 1px solid #ccc;&#xA;    }&#xA;&#xA;    .quickref-table td {&#xA;        padding: .25rem .5rem .25rem 0;&#xA;        border-bottom: 1px solid #eee;&#xA;        vertical-align: top;&#xA;    }&#xA;&#xA;    .quickref-table code {&#xA;        white-space: nowrap;&#xA;    }&#xA;    canvas {&#xA;        cursor: pointer;&#xA;        width: 100%;&#xA;        height: 100%;&#xA;        object-fit: contain;&#xA;    }&#xA;    .graph canvas {&#xA;        height: 100%;&#xA;        width: 100%;&#xA;        aspect-ratio: 16 / 9;&#xA;    }&#xA;    #code {&#xA;        flex: 1;&#xA;        min-height: 0;&#xA;        width: 100%;&#xA;        resize: none;&#xA;        tab-size: 4;&#xA;        -moz-tab-size: 4;&#xA;        box-sizing: border-box;&#xA;    }&#xA;&#xA;    #examples-select,&#xA;    #run-btn {&#xA;        flex-shrink: 0;&#xA;    }&#xA;    .outputWrapper {&#xA;        flex: 1;&#xA;        min-height: 0;&#xA;        position: relative;&#xA;    }&#xA;    #output {&#xA;        width: 98%;&#xA;        height: 90%;&#xA;        resize: none;&#xA;    }&#xA;&lt;/style&gt;&#xA;&#xA;&lt;div class=&#34;app&#34;&gt;&#xA;    &lt;aside class=&#34;sidebar&#34;&gt;&#xA;    &lt;select id=&#34;examples-select&#34; style=&#34;width: 100%; margin-bottom: 0.5rem; padding: 0.35rem;&#34;&gt;&#xA;        &lt;option value=&#34;&#34;&gt;Examples…&lt;/option&gt;&#xA;        &lt;option value=&#34;new&#34;&gt;New&lt;/option&gt;&#xA;        &lt;option value=&#34;axes&#34;&gt;Axes &amp;amp; Circle&lt;/option&gt;&#xA;        &lt;option value=&#34;sine&#34;&gt;Sine Wave&lt;/option&gt;&#xA;        &lt;option value=&#34;lineplot&#34;&gt;Line Plot (recursion)&lt;/option&gt;&#xA;        &lt;option value=&#34;matmul&#34;&gt;Matrix Multiply&lt;/option&gt;&#xA;        &lt;option value=&#34;cube&#34;&gt;Rotating Cube&lt;/option&gt;&#xA;        &lt;option value=&#34;wavepacket&#34;&gt;Wave Packet (ε σ ν)&lt;/option&gt;&#xA;    &lt;/select&gt;&#xA;    &lt;textarea name=&#34;code&#34; id=&#34;code&#34;&gt;&lt;/textarea&gt;&#xA;    &lt;button id=&#34;run-btn&#34; style=&#34;width: 100%; margin-top: 0.5rem; padding: 0.5rem;&#34;&gt;Run (Shift+Enter)&lt;/button&gt;&#xA;    &lt;/aside&gt;&#xA;    &lt;div class=&#34;main&#34;&gt;&#xA;    &lt;div class=&#34;top&#34;&gt;&#xA;        &lt;canvas id=&#34;screenCanvas&#34;&gt;&lt;/canvas&gt;&#xA;    &lt;/div&gt;&#xA;    &lt;div class=&#34;output&#34; id=&#34;output-panel&#34;&gt;&#xA;        &lt;div class=&#34;output-header&#34; id=&#34;output-header&#34;&gt;&#xA;        &lt;span class=&#34;collapse-btn&#34; id=&#34;collapse-btn&#34;&gt;▼&lt;/span&gt;&#xA;        &lt;span class=&#34;tab-btn active&#34; data-tab=&#34;output&#34;&gt;Output&lt;/span&gt;&#xA;        &lt;span class=&#34;tab-btn&#34; data-tab=&#34;quickref&#34;&gt;Quick Reference&lt;/span&gt;&#xA;        &lt;span class=&#34;build-hash&#34; title=&#34;build hash — check this if the page seems stale&#34;&gt;7c108641&lt;/span&gt;&#xA;        &lt;/div&gt;&#xA;        &lt;div class=&#34;outputWrapper&#34;&gt;&#xA;        &lt;div class=&#34;tab-panel active&#34; id=&#34;output-tab&#34;&gt;&#xA;            &lt;textarea name=&#34;output&#34; id=&#34;output&#34; readonly&gt;&lt;/textarea&gt;&#xA;        &lt;/div&gt;&#xA;        &lt;div class=&#34;tab-panel&#34; id=&#34;quickref-tab&#34;&gt;&#xA;            &lt;table class=&#34;quickref-table&#34;&gt;&#xA;            &lt;caption&gt;Core language&lt;/caption&gt;&#xA;            &lt;thead&gt;&#xA;                &lt;tr&gt;&lt;th&gt;Form&lt;/th&gt;&lt;th&gt;Does&lt;/th&gt;&lt;/tr&gt;&#xA;            &lt;/thead&gt;&#xA;            &lt;tbody&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(eval x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;evaluate x (e.g. after quote)&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(quote x)&lt;/code&gt; / &lt;code&gt;&#39;x&lt;/code&gt;&lt;/td&gt;&lt;td&gt;return x unevaluated, as-is&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(cons x y)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;construct pair (x . y)&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(car p)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;first element of pair/list p&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(cdr p)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;rest of list p&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(truncate n)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;integer part of n&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(&amp;lt; n1 n2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;#t if n1 &amp;lt; n2, else ()&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(&amp;gt; n1 n2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;#t if n1 &amp;gt; n2, else ()&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(consp x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;#t if x is a non-empty list, cons, or closure&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(or x1 x2 ...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;first x that is not (), else ()&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(and x1 x2 ...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;last x if all are not (), else ()&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(not x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;#t if x is (), else ()&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(cond (x1 y1) (x2 y2) ...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;the first yi whose xi is non-()&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(if x y z)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;y if x is non-(), else z&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(let* (v1 x1) (v2 x2) ... y)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;sequentially bind v1..vk, then evaluate y&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(lambda v x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;construct an anonymous closure&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(define v x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;bind v to x, globally&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(defparameter v x)&lt;/code&gt; / &lt;code&gt;(defvar v x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;bind v to x, globally (CL style)&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(defun name (args) body)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;define a named function, globally&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(setq v x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;update an existing binding in place&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(progn x1 x2 ... xk)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;evaluate in order, return the last&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(print x1 x2 ...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;print each value to the Output pane, return the last&lt;/td&gt;&lt;/tr&gt;&#xA;            &lt;/tbody&gt;&#xA;            &lt;/table&gt;&#xA;            &lt;table class=&#34;quickref-table&#34;&gt;&#xA;            &lt;caption&gt;Literals&lt;/caption&gt;&#xA;            &lt;tbody&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;#t&lt;/code&gt;&lt;/td&gt;&lt;td&gt;true&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;()&lt;/code&gt;&lt;/td&gt;&lt;td&gt;empty list / false&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;&#34;...&#34;&lt;/code&gt;&lt;/td&gt;&lt;td&gt;string literal&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;[1 2 3]&lt;/code&gt;, &lt;code&gt;[[1 2] [3 4]]&lt;/code&gt;&lt;/td&gt;&lt;td&gt;tensor literal, any rank&lt;/td&gt;&lt;/tr&gt;&#xA;            &lt;/tbody&gt;&#xA;            &lt;/table&gt;&#xA;            &lt;table class=&#34;quickref-table&#34;&gt;&#xA;            &lt;caption&gt;Math &amp;amp; tensors&lt;/caption&gt;&#xA;            &lt;tbody&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(+ ..)&lt;/code&gt; &lt;code&gt;(- ..)&lt;/code&gt; &lt;code&gt;(* ..)&lt;/code&gt; &lt;code&gt;(/ ..)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;arithmetic; elementwise over tensors&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(sqrt x)&lt;/code&gt; &lt;code&gt;(exp x)&lt;/code&gt; &lt;code&gt;(log x)&lt;/code&gt; &lt;code&gt;(tanh x)&lt;/code&gt; &lt;code&gt;(sin x)&lt;/code&gt; &lt;code&gt;(cos x)&lt;/code&gt; &lt;code&gt;(abs x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;elementwise math; scalar or tensor&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(pow t p)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;elementwise power&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(normalize v)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;unit vector&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(zero n)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;rank-1 tensor of n zeros&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(dot v1 v2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;dot product&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(norm v)&lt;/code&gt; / &lt;code&gt;(norm2 v)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;length / length²&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(dist v1 v2)&lt;/code&gt; / &lt;code&gt;(dist2 v1 v2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;distance / distance²&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(length lst)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;number of elements in a plain Lisp list&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(shape t)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;tensor of dimension sizes&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(rank t)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;number of dimensions (0 for scalars)&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(tensorp x)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;#t if x is a tensor&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(slice t i)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;element or row at index i&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(first t)&lt;/code&gt; / &lt;code&gt;(rest t)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;first row / all rows after the first&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(slice-range t start end)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;rows/elements in [start, end)&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(col-slice M j)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;column j of a matrix, as a vector&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(reshape t [d0 d1 ...])&lt;/code&gt;&lt;/td&gt;&lt;td&gt;reshape, same element count&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(matmul A B)&lt;/code&gt; / &lt;code&gt;(@ A B)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;matrix product&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(transpose M)&lt;/code&gt; / &lt;code&gt;(T M)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;swap rows and columns&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(vstack A B)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;stack A on top of B, row-wise&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(sum t)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;sum of all elements&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(amax t)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;maximum element&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(argmax t)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;index of the maximum element&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(softmax t)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;softmax; row-wise if rank 2&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(layer-norm t eps)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;layer normalization; row-wise if rank 2&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(causal-mask n)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;n&amp;times;n lower-triangular attention mask&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(equalp v1 v2)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;#t if same shape and elementwise equal&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(make-tensor e1 e2 ...)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;backend for &lt;code&gt;[ ]&lt;/code&gt; literals; rarely called directly&lt;/td&gt;&lt;/tr&gt;&#xA;            &lt;/tbody&gt;&#xA;            &lt;/table&gt;&#xA;            &lt;table class=&#34;quickref-table&#34;&gt;&#xA;            &lt;caption&gt;Drawing&lt;/caption&gt;&#xA;            &lt;tbody&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(point x y)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;draw a single point&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(line x0 y0 x1 y1)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;draw a line&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(circle x0 y0 r)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;draw a circle&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(color r g b)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;set the drawing color&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(background r g b)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;set the clear color&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(clear)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;fill the canvas with the background color&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(axes)&lt;/code&gt; / &lt;code&gt;(axes tick-spacing)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;draw X/Y axis lines, ticks, numeric labels, and X/Y letters&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(set-origin &#39;graph)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;(0,0) at canvas center, Y up, X/Y can go negative&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;(set-origin &#39;image)&lt;/code&gt;&lt;/td&gt;&lt;td&gt;(0,0) at top-left, Y down, X/Y stay non-negative&lt;/td&gt;&lt;/tr&gt;&#xA;            &lt;/tbody&gt;&#xA;            &lt;/table&gt;&#xA;            &lt;table class=&#34;quickref-table&#34;&gt;&#xA;            &lt;caption&gt;Animation (inside &lt;code&gt;draw&lt;/code&gt;)&lt;/caption&gt;&#xA;            &lt;tbody&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;dt&lt;/code&gt;&lt;/td&gt;&lt;td&gt;real seconds since the previous frame&lt;/td&gt;&lt;/tr&gt;&#xA;                &lt;tr&gt;&lt;td&gt;&lt;code&gt;⏱️&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;dt&lt;/code&gt; accumulated since page load — total elapsed seconds&lt;/td&gt;&lt;/tr&gt;&#xA;            &lt;/tbody&gt;&#xA;            &lt;/table&gt;&#xA;        &lt;/div&gt;&#xA;        &lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;    &lt;/div&gt;&#xA;&lt;/div&gt;&#xA;&#xA;&#xA;&lt;script type=&#34;module&#34;&gt;&#xA;    // TODO: export from C?&#xA;    const WEFX_KEYDOWN   = 0;&#xA;    const WEFX_KEYPRESS  = 1;&#xA;    const WEFX_KEYUP     = 2;&#xA;    const WEFX_MOUSEMOVE = 3;&#xA;    const WEFX_MOUSEDOWN = 4;&#xA;    const WEFX_MOUSEUP   = 5;&#xA;    const WEFX_CLICK     = 6;&#xA;&#xA;    const SIZE_OF_INT = 4;&#xA;    const canvas = document.getElementById(&#34;screenCanvas&#34;);&#xA;    const ctx = canvas.getContext(&#34;2d&#34;);&#xA;&#xA;    /* ─── Code persistence ─── */&#xA;    const CODE_STORAGE_KEY = &#34;lispix-code&#34;;&#xA;    const codeEl = document.getElementById(&#34;code&#34;);&#xA;    try {&#xA;    const savedCode = localStorage.getItem(CODE_STORAGE_KEY);&#xA;    if (savedCode !== null) {&#xA;        codeEl.value = savedCode;&#xA;    }&#xA;    } catch (err) {&#xA;    console.warn(&#34;Couldn&#39;t load code from localStorage:&#34;, err);&#xA;    }&#xA;&#xA;    /* ─── Examples ─── */&#xA;    const EXAMPLES = {&#xA;    new: `(set-origin &#39;image)&#xA;(clear)&#xA;(background 10 10 20)&#xA;(color 255 255 255)&#xA;(axes 20)&#xA;&#xA;`,&#xA;    axes: `(set-origin &#39;graph)&#xA;(background 10 10 20)&#xA;(clear)&#xA;(color 200 200 200)&#xA;(axes)&#xA;(color 255 80 80)&#xA;(circle 0 0 50)&#xA;(defun draw ()&#xA;(color 255 0 0)&#xA;(point (* 10 (cos ⏱️))&#xA;(* 10 (sin ⏱️)))&#xA;)`,&#xA;&#xA;    sine: `(set-origin &#39;graph)&#xA;(background 10 10 20)&#xA;(defun draw ()&#xA;(clear)&#xA;(color 255 255 0)&#xA;(circle 0&#xA;    (truncate (* 80 (sin ⏱️))) 15))`,&#xA;&#xA;    lineplot: `(set-origin &#39;graph)&#xA;(background 10 10 20)&#xA;(clear)&#xA;(color 127 127 127)&#xA;(axes 50)&#xA;(color 100 200 255)&#xA;(define m 0.3)&#xA;(define b 0)&#xA;(defun plot (x)&#xA;(if (&gt; x 300)&#xA;    #t&#xA;    (progn&#xA;        (point x (+ (* m x) b))&#xA;        (plot (+ x 1)))))&#xA;(plot -300)`,&#xA;&#xA;    matmul: `(clear)&#xA;(define Q [[1 2] [3 4]])&#xA;(print (@ Q Q))&#xA;(print (@ Q (T Q)))`,&#xA;&#xA;    cube: `;; Over the top with emojis&#xA;&#xA;(set-origin &#39;graph)&#xA;(background 10 10 20)&#xA;&#xA;;; rename builtin functions&#xA;(define ✂️ slice)&#xA;(define 🐘 truncate)&#xA;(define 💅 color)&#xA;&#xA;;; Draw a spinning cube&#xA;(define 🧊 [&#xA;[-1 -1 -1]&#xA;[ 1 -1 -1]&#xA;[ 1  1 -1]&#xA;[-1  1 -1]&#xA;[-1 -1  1]&#xA;[ 1 -1  1]&#xA;[ 1  1  1]&#xA;[-1  1  1]&#xA;])&#xA;&#xA;(defun 📽️ (v R)&#xA;(let*&#xA;    (r (@ v R))&#xA;    (x (✂️ r 0))&#xA;    (y (✂️ r 1))&#xA;    (z (✂️ r 2))&#xA;    (s (/ 280 (+ 4 z)))&#xA;    [(* x s) (* y s)]))&#xA;&#xA;(defun ⧄ (p0 p1)&#xA;    (line (🐘 (✂️ p0 0))&#xA;            (🐘 (✂️ p0 1))&#xA;            (🐘 (✂️ p1 0))&#xA;            (🐘 (✂️ p1 1))))&#xA;&#xA;(defun draw ()&#xA;(clear)&#xA;(let* (a ⏱️)&#xA;    (b (* ⏱️ 0.7))&#xA;    (ca (cos a)) (sa (sin a))&#xA;    (cb (cos b)) (sb (sin b))&#xA;&#xA;    (Ry [[ca 0 (- 0 sa)] [0 1 0] [sa 0 ca]])&#xA;    (Rx [[1 0 0] [0 cb sb] [0 (- 0 sb) cb]])&#xA;&#xA;    (R (@ Ry Rx))&#xA;&#xA;    (p0 (📽️ (✂️ 🧊 0) R))&#xA;    (p1 (📽️ (✂️ 🧊 1) R))&#xA;    (p2 (📽️ (✂️ 🧊 2) R))&#xA;    (p3 (📽️ (✂️ 🧊 3) R))&#xA;    (p4 (📽️ (✂️ 🧊 4) R))&#xA;    (p5 (📽️ (✂️ 🧊 5) R))&#xA;    (p6 (📽️ (✂️ 🧊 6) R))&#xA;    (p7 (📽️ (✂️ 🧊 7) R))&#xA;    (progn&#xA;        (💅 0 255 255)&#xA;        (⧄ p0 p1) (⧄ p1 p2)&#xA;        (⧄ p2 p3) (⧄ p3 p0)&#xA;        (⧄ p4 p5) (⧄ p5 p6)&#xA;        (⧄ p6 p7) (⧄ p7 p4)&#xA;        (⧄ p0 p4) (⧄ p1 p5)&#xA;        (⧄ p2 p6) (⧄ p3 p7))))`,&#xA;&#xA;    wavepacket: `(set-origin &#39;graph)&#xA;(clear)&#xA;(background 10 10 20)&#xA;(color 127 127 127)&#xA;(axes 50)&#xA;&#xA;(define σ 60)&#xA;(define ν 0.05)&#xA;(define ε 0.4)&#xA;&#xA;(defun ψ (x)&#xA;(* (exp (- 0 (/ (* x x) (* 2 (* σ σ)))))&#xA;    (sin (+ (* ν x) ε))))&#xA;&#xA;(color 100 200 255)&#xA;(defun plot (x)&#xA;(if (&gt; x 300)&#xA;    #t&#xA;    (progn&#xA;        (point x (* 180 (ψ x)))&#xA;        (plot (+ x 1)))))&#xA;(plot -300)`,&#xA;    };&#xA;&#xA;    document.getElementById(&#34;examples-select&#34;).addEventListener(&#34;change&#34;, (e) =&gt; {&#xA;    const code = EXAMPLES[e.target.value];&#xA;    if (code !== undefined) {&#xA;        codeEl.value = code;&#xA;    }&#xA;    e.target.value = &#34;&#34;; // reset so picking the same example again still fires &#39;change&#39;&#xA;    });&#xA;    ctx.imageSmoothingEnabled = false;&#xA;&#xA;    /* ─── Helpers ─── */&#xA;    function relativeXY(e, canvas) {&#xA;    const rect = canvas.getBoundingClientRect();&#xA;    return {&#xA;        x: (e.clientX - rect.left) | 0,&#xA;        y: (e.clientY - rect.top) | 0,&#xA;    };&#xA;    }&#xA;&#xA;    /* ─── Memory Access ─── */&#xA;    let wasmMemory = null;&#xA;&#xA;    function getMemory() {&#xA;    if (!wasmMemory) throw new Error(&#34;getMemory called before WASM is loaded&#34;);&#xA;    return wasmMemory.buffer;&#xA;    }&#xA;&#xA;    const utf8Decoder = new TextDecoder(&#34;utf-8&#34;);&#xA;&#xA;    function readCString(ptr) {&#xA;    if (!ptr) return &#34;&#34;;&#xA;    const mem = getMemory();&#xA;    const view = new Uint8Array(mem);&#xA;    let end = ptr;&#xA;    while (view[end] !== 0) end++;&#xA;    return utf8Decoder.decode(view.subarray(ptr, end));&#xA;    }&#xA;&#xA;    /* ─── WASM Imports ─── */&#xA;    // Build imports lazily to avoid TDZ issues with getMemory.&#xA;    // These functions close over getMemory/readCString which are function&#xA;    // declarations (hoisted), so they&#39;re available at definition time.&#xA;    function createImports() {&#xA;    return {&#xA;        print: function(strptr) {&#xA;        const str = readCString(strptr);&#xA;        const outputEl = document.getElementById(&#39;output&#39;);&#xA;        outputEl.value += str;&#xA;        outputEl.scrollTop = outputEl.scrollHeight;&#xA;        },&#xA;        console_log: function(strptr) {&#xA;        console.log(readCString(strptr));&#xA;        },&#xA;        strlen: function(ptr) {&#xA;        if (!ptr) return 0;&#xA;        const memory = getMemory();&#xA;        const view = new Uint8Array(memory);&#xA;        let len = 0;&#xA;        while (view[ptr + len] !== 0) {&#xA;            len++;&#xA;        }&#xA;        return len;&#xA;        },&#xA;        abort: function() { throw new Error(&#39;WASM abort called&#39;); },&#xA;        exit: function(code) { console.log(&#39;WASM exit(&#39; + code + &#39;)&#39;); },&#xA;        sscanf: function(strPtr, fmtPtr, vaBufPtr) {&#xA;        // Minimal sscanf for &#34;%lg%n&#34; format used by Lisp parser.&#xA;        // clang&#39;s wasm32 ABI for variadic calls doesn&#39;t pass each&#xA;        // variadic argument as its own wasm parameter — the caller packs&#xA;        // the real argument addresses sequentially into a small buffer&#xA;        // and passes ONE pointer to that buffer (vaBufPtr). Each 4-byte&#xA;        // word there is the address a conversion should write into.&#xA;        const mem = getMemory();&#xA;        const str = readCString(strPtr);&#xA;        const fmt = readCString(fmtPtr);&#xA;        const vaArgs = new Uint32Array(mem, vaBufPtr, 8);&#xA;&#xA;        let strIdx = 0;&#xA;        let fmtIdx = 0;&#xA;        let argIdx = 0;&#xA;        let matches = 0;&#xA;&#xA;        while (fmtIdx &lt; fmt.length &amp;&amp; argIdx &lt; vaArgs.length) {&#xA;            const argPtr = vaArgs[argIdx];&#xA;            // Skip whitespace in format&#xA;            while (fmtIdx &lt; fmt.length &amp;&amp; /\s/.test(fmt[fmtIdx])) {&#xA;            fmtIdx++;&#xA;            while (strIdx &lt; str.length &amp;&amp; /\s/.test(str[strIdx])) strIdx++;&#xA;            }&#xA;&#xA;            if (fmt[fmtIdx] !== &#39;%&#39;) {&#xA;            if (str[strIdx] === fmt[fmtIdx]) {&#xA;                strIdx++;&#xA;                fmtIdx++;&#xA;            } else {&#xA;                return matches;&#xA;            }&#xA;            continue;&#xA;            }&#xA;            fmtIdx++;&#xA;&#xA;            let spec = &#39;&#39;;&#xA;            while (fmtIdx &lt; fmt.length &amp;&amp; /[^%]/.test(fmt[fmtIdx])) {&#xA;            spec += fmt[fmtIdx];&#xA;            fmtIdx++;&#xA;            }&#xA;&#xA;            const baseSpec = spec.replace(/[hlL]/g, &#39;&#39;);&#xA;&#xA;            if (baseSpec === &#39;lg&#39; || baseSpec === &#39;lf&#39; || baseSpec === &#39;f&#39; || baseSpec === &#39;g&#39;) {&#xA;            const startIdx = strIdx;&#xA;            let numStr = &#39;&#39;;&#xA;            while (strIdx &lt; str.length &amp;&amp; /\s/.test(str[strIdx])) strIdx++;&#xA;            if (strIdx &lt; str.length &amp;&amp; (str[strIdx] === &#39;+&#39; || str[strIdx] === &#39;-&#39;)) {&#xA;                numStr += str[strIdx];&#xA;                strIdx++;&#xA;            }&#xA;            while (strIdx &lt; str.length &amp;&amp; /[0-9.eE+\-]/.test(str[strIdx])) {&#xA;                numStr += str[strIdx];&#xA;                strIdx++;&#xA;            }&#xA;            if (numStr.length &gt; 0 &amp;&amp; numStr !== &#39;.&#39; &amp;&amp; numStr !== &#39;+.&#39; &amp;&amp; numStr !== &#39;-.&#39;) {&#xA;                const val = parseFloat(numStr);&#xA;                if (!isNaN(val)) {&#xA;                const f64 = new Float64Array(mem, argPtr, 1);&#xA;                f64[0] = val;&#xA;                matches++;&#xA;                } else {&#xA;                strIdx = startIdx;&#xA;                }&#xA;            } else {&#xA;                strIdx = startIdx;&#xA;            }&#xA;            } else if (baseSpec === &#39;d&#39; || baseSpec === &#39;i&#39; || baseSpec === &#39;u&#39;) {&#xA;            const startIdx = strIdx;&#xA;            let numStr = &#39;&#39;;&#xA;            while (strIdx &lt; str.length &amp;&amp; /[0-9]/.test(str[strIdx])) {&#xA;                numStr += str[strIdx];&#xA;                strIdx++;&#xA;            }&#xA;            if (numStr.length &gt; 0) {&#xA;                const i32 = new Int32Array(mem, argPtr, 1);&#xA;                i32[0] = parseInt(numStr, 10);&#xA;                matches++;&#xA;            } else {&#xA;                strIdx = startIdx;&#xA;            }&#xA;            } else if (baseSpec === &#39;n&#39;) {&#xA;            const i32 = new Int32Array(mem, argPtr, 1);&#xA;            i32[0] = strIdx;&#xA;            }&#xA;&#xA;            argIdx++;&#xA;        }&#xA;&#xA;        return matches;&#xA;        }&#xA;    };&#xA;    }&#xA;&#xA;    let malloc, free, lisp_eval_string, lisp_get_state;&#xA;    let wasmReady = false;&#xA;&#xA;    /**&#xA;    * Bootstrap the WASM module and initialize the graphics system.&#xA;    * Returns a promise that resolves when startup is complete.&#xA;    */&#xA;    async function bootstrap() {&#xA;    try {&#xA;        console.log(&#34;Loading WASM module...&#34;);&#xA;        const { instance } = await WebAssembly.instantiateStreaming(&#xA;        fetch(&#34;/assets/wefx.wasm&#34;),&#xA;        {env: createImports()},&#xA;        );&#xA;&#xA;    const {&#xA;        memory,&#xA;        screen,&#xA;        init,&#xA;        main_loop,&#xA;        wefx_log,&#xA;        wefx_draw,&#xA;        wefx_xsize,&#xA;        wefx_ysize,&#xA;        wefx_add_queue_event,&#xA;        wefx_get_queue,&#xA;        lisp_eval_string: _lisp_eval_string,&#xA;        lisp_get_state: _lisp_get_state,&#xA;        malloc: wasmMalloc,&#xA;        free: wasmFree,&#xA;    } = instance.exports;&#xA;    malloc = wasmMalloc;&#xA;    free = wasmFree;&#xA;    lisp_eval_string = _lisp_eval_string;&#xA;    lisp_get_state = _lisp_get_state;&#xA;&#xA;    if (!wasmMalloc || !wasmFree) {&#xA;        throw new Error(&#34;WASM missing malloc/free exports&#34;);&#xA;    }&#xA;&#xA;    // Set wasmMemory BEFORE calling any exported functions.&#xA;    // The imports (print, strlen, etc.) call getMemory(), which requires&#xA;    // wasmMemory to be set. If init() or any startup code calls an import,&#xA;    // it will fail otherwise.&#xA;    wasmMemory = memory;&#xA;&#xA;    console.log(&#34;Initializing WEFX runtime...&#34;);&#xA;    const err = init();&#xA;    if (err) {&#xA;        throw new Error(&#34;WEFX init failed with error code: &#34; + err);&#xA;    }&#xA;    const width = wefx_xsize();&#xA;    const height = wefx_ysize();&#xA;    canvas.width = width;&#xA;    canvas.height = height;&#xA;&#xA;    // `screen` is exported as a WASM Global holding the *address* of the&#xA;    // C `unsigned int *screen` variable (a mutable global living in&#xA;    // linear memory), not its value — it must be dereferenced to get the&#xA;    // actual pixel buffer address that wefx_open() assigned into it.&#xA;    const offset = new Uint32Array(memory.buffer, screen.value, 1)[0];&#xA;    const imgArray = new Uint8ClampedArray(&#xA;        memory.buffer,&#xA;        offset,&#xA;        SIZE_OF_INT * width * height&#xA;    );&#xA;&#xA;    const toWefxEvent = (t, e, canvas) =&gt; {&#xA;        const xy = relativeXY(e, canvas);&#xA;        const k = e.key ? e.key.charCodeAt(0) : 0;&#xA;        wefx_add_queue_event(t, e.button, e.timeStamp, k, xy.x, xy.y);&#xA;    };&#xA;&#xA;    document.addEventListener(&#34;keypress&#34;, (e) =&gt;&#xA;        toWefxEvent(WEFX_KEYPRESS, e, canvas)&#xA;    );&#xA;    document.addEventListener(&#34;keydown&#34;, (e) =&gt;&#xA;        toWefxEvent(WEFX_KEYDOWN, e, canvas)&#xA;    );&#xA;    document.addEventListener(&#34;keyup&#34;, (e) =&gt;&#xA;        toWefxEvent(WEFX_KEYUP, e, canvas)&#xA;    );&#xA;    canvas.addEventListener(&#34;mousedown&#34;, (e) =&gt;&#xA;        toWefxEvent(WEFX_MOUSEDOWN, e, canvas)&#xA;    );&#xA;    canvas.addEventListener(&#34;mouseup&#34;, (e) =&gt;&#xA;        toWefxEvent(WEFX_MOUSEUP, e, canvas)&#xA;    );&#xA;    canvas.addEventListener(&#34;mousemove&#34;, (e) =&gt;&#xA;        toWefxEvent(WEFX_MOUSEMOVE, e, canvas)&#xA;    );&#xA;&#xA;    let start = Date.now();&#xA;    let lastFrame = start;&#xA;    let pixels = imgArray;&#xA;    let image = new ImageData(imgArray, width);&#xA;    const loop = (t) =&gt; {&#xA;        const current = Date.now();&#xA;        const delta = current - start;&#xA;        const dt = (current - lastFrame) / 1000; // seconds since last frame&#xA;        lastFrame = current;&#xA;&#xA;        const queue = wefx_get_queue();&#xA;        main_loop(delta * 0.05, dt, queue);&#xA;        wefx_draw(offset);&#xA;&#xA;        // A WebAssembly.Memory growing (malloc needing more pages, e.g.&#xA;        // from tensor allocations) replaces its backing ArrayBuffer —&#xA;        // every existing TypedArray view into the old buffer (including&#xA;        // `pixels` from bootstrap) goes dead (byteLength 0), which is&#xA;        // what throws &#34;Invalid width or height&#34; from putImageData once&#xA;        // that stale view no longer matches `image`&#39;s declared size.&#xA;        // Detect that and rebuild both views against the current buffer.&#xA;        if (pixels.buffer !== memory.buffer) {&#xA;        pixels = new Uint8ClampedArray(memory.buffer, offset, SIZE_OF_INT * width * height);&#xA;        image = new ImageData(pixels, width);&#xA;        }&#xA;        ctx.putImageData(image, 0, 0);&#xA;&#xA;        requestAnimationFrame(loop);&#xA;    };&#xA;    requestAnimationFrame(loop);&#xA;&#xA;    console.log(&#34;WASM bootstrap complete&#34;);&#xA;    wasmReady = true;&#xA;    } catch (err) {&#xA;    console.error(&#34;WASM bootstrap failed:&#34;, err);&#xA;    wasmReady = false;&#xA;    throw err;&#xA;    }&#xA;}&#xA;&#xA;// Start bootstrap and handle errors&#xA;bootstrap().catch(err =&gt; {&#xA;    console.error(&#34;Failed to start Lispix:&#34;, err);&#xA;    document.body.innerHTML = `&#xA;    &lt;div style=&#34;padding: 2rem; font-family: monospace;&#34;&gt;&#xA;        &lt;h1&gt;Failed to load Lispix&lt;/h1&gt;&#xA;        &lt;pre&gt;${err.message || err}&lt;/pre&gt;&#xA;    &lt;/div&gt;&#xA;    `;&#xA;});&#xA;&#xA;    function runLisp() {&#xA;    if (!wasmMemory || !malloc || !free) {&#xA;        console.warn(&#34;WASM not loaded yet; please wait and try again.&#34;);&#xA;        return;&#xA;    }&#xA;    const code = codeEl.value;&#xA;&#xA;    try {&#xA;        localStorage.setItem(CODE_STORAGE_KEY, code);&#xA;    } catch (err) {&#xA;        console.warn(&#34;Couldn&#39;t save code to localStorage:&#34;, err);&#xA;    }&#xA;&#xA;    // Allocate memory for the code string&#xA;    const len = new TextEncoder().encode(code).length;&#xA;    const ptr = malloc(len + 1);&#xA;&#xA;    // Copy code to WASM memory&#xA;    const memory = getMemory();&#xA;    const view = new Uint8Array(memory);&#xA;    const encoder = new TextEncoder();&#xA;    const encoded = encoder.encode(code);&#xA;    view.set(encoded, ptr);&#xA;    view[ptr + len] = 0; // Null terminator&#xA;&#xA;    // Clear output&#xA;    document.getElementById(&#39;output&#39;).value = &#34;&#34;;&#xA;&#xA;    // Evaluate&#xA;    lisp_eval_string(lisp_get_state(), ptr, len);&#xA;&#xA;    // Free allocated memory&#xA;    free(ptr);&#xA;    }&#xA;&#xA;    const outputPanel = document.getElementById(&#39;output-panel&#39;);&#xA;&#xA;    document.querySelectorAll(&#39;.tab-btn&#39;).forEach((btn) =&gt; {&#xA;    btn.addEventListener(&#39;click&#39;, (e) =&gt; {&#xA;        e.stopPropagation();&#xA;        document.querySelectorAll(&#39;.tab-btn&#39;).forEach((b) =&gt; b.classList.remove(&#39;active&#39;));&#xA;        document.querySelectorAll(&#39;.tab-panel&#39;).forEach((p) =&gt; p.classList.remove(&#39;active&#39;));&#xA;        btn.classList.add(&#39;active&#39;);&#xA;        document.getElementById(btn.dataset.tab + &#39;-tab&#39;).classList.add(&#39;active&#39;);&#xA;        outputPanel.classList.remove(&#39;collapsed&#39;);&#xA;    });&#xA;    });&#xA;&#xA;    document.getElementById(&#39;collapse-btn&#39;).addEventListener(&#39;click&#39;, (e) =&gt; {&#xA;    e.stopPropagation();&#xA;    outputPanel.classList.toggle(&#39;collapsed&#39;);&#xA;    });&#xA;&#xA;    document.getElementById(&#39;output-header&#39;).addEventListener(&#39;click&#39;, () =&gt; {&#xA;    outputPanel.classList.toggle(&#39;collapsed&#39;);&#xA;    });&#xA;&#xA;    document.getElementById(&#39;run-btn&#39;).addEventListener(&#39;click&#39;, runLisp);&#xA;    document.getElementById(&#39;code&#39;).addEventListener(&#39;keydown&#39;, (e) =&gt; {&#xA;    if (e.shiftKey &amp;&amp; e.key === &#39;Enter&#39;) {&#xA;        e.preventDefault();&#xA;        runLisp();&#xA;    } else if (e.key === &#39;Tab&#39;) {&#xA;        e.preventDefault();&#xA;        const el = e.target;&#xA;        const start = el.selectionStart;&#xA;        const end = el.selectionEnd;&#xA;        el.value = el.value.slice(0, start) + &#39;\t&#39; + el.value.slice(end);&#xA;        el.selectionStart = el.selectionEnd = start + 1;&#xA;    }&#xA;    });&#xA;&lt;/script&gt;</description>
			</item>
	</channel>
</rss>
