Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
191 lines (183 loc) · 6.33 KB
/
Copy pathindex.html
File metadata and controls
191 lines (183 loc) · 6.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>rontolisp WASM in the browser</title>
<style>
:root {
color-scheme: light dark;
--fg: #1a1a1a;
--bg: #fafafa;
--accent: #2d6cdf;
--term-bg: #1e1e2e;
--term-fg: #cdd6f4;
}
body {
font-family: system-ui, -apple-system, sans-serif;
max-width: 760px;
margin: 2rem auto;
padding: 0 1rem;
color: var(--fg);
background: var(--bg);
line-height: 1.5;
}
h1 {
font-size: 1.5rem;
}
h2 {
font-size: 1.15rem;
margin-top: 2rem;
border-bottom: 1px solid #ccc;
padding-bottom: 0.25rem;
}
p.lead {
color: #555;
}
button {
background: var(--accent);
color: #fff;
border: 0;
border-radius: 6px;
padding: 0.5rem 1rem;
font-size: 0.95rem;
cursor: pointer;
}
button:disabled {
opacity: 0.5;
cursor: default;
}
textarea {
width: 100%;
box-sizing: border-box;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.9rem;
padding: 0.5rem;
border: 1px solid #bbb;
border-radius: 6px;
resize: vertical;
}
pre.term {
background: var(--term-bg);
color: var(--term-fg);
padding: 1rem;
border-radius: 8px;
overflow-x: auto;
white-space: pre-wrap;
min-height: 2rem;
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
font-size: 0.9rem;
}
.row {
display: flex;
gap: 0.5rem;
align-items: center;
flex-wrap: wrap;
}
code {
background: #00000010;
padding: 0.1rem 0.3rem;
border-radius: 4px;
}
</style>
</head>
<body>
<h1>Running rontolisp WASM in plain HTML + JavaScript</h1>
<p class="lead">
The two programs below were written in Lisp and compiled <em>ahead of
time</em> to WebAssembly (WASI Preview 1) with rontolisp. This page
provides a tiny WASI shim in JavaScript, instantiates each
<code>.wasm</code> module, runs its <code>_start</code>, and shows whatever
it printed to stdout. No server, no framework. All the Lisp sources and the
shim live in
<a href="https://github.com/making/rontolisp/tree/develop/examples/browser/wasm-browser"
>examples/browser/wasm-browser</a
>.
</p>
<p class="lead">
Want to write Lisp and compile it to WASM <em>in the browser</em>, then run
the result here? See the
<a href="../">playground</a> and its
<a href="../compile-run.html">compile & run</a> page (these
links work on the published site).
</p>
<h2>1. Run a self-contained program</h2>
<p>
<code>hello.wasm</code> computes Fibonacci numbers and some exact rational
arithmetic, printing the result. Click to run it in your browser.
Source:
<a href="https://github.com/making/rontolisp/blob/develop/examples/browser/wasm-browser/hello.lisp"
>hello.lisp</a
>.
</p>
<div class="row">
<button id="run-hello">Run hello.wasm</button>
</div>
<pre class="term" id="out-hello">(output appears here)</pre>
<h2>2. Pass input from the page into the program</h2>
<p>
<code>greet.wasm</code> reads one line from <em>stdin</em>. The shim feeds
the text below as stdin, so this shows how to send data from the browser
into a WASM program. Source:
<a href="https://github.com/making/rontolisp/blob/develop/examples/browser/wasm-browser/greet.lisp"
>greet.lisp</a
>.
</p>
<div class="row" style="flex-direction: column; align-items: stretch">
<textarea id="stdin" rows="1" placeholder="type a name..."></textarea>
<div class="row">
<button id="run-greet">Run greet.wasm</button>
</div>
</div>
<pre class="term" id="out-greet">(output appears here)</pre>
<h2>3. Real randomness from the host</h2>
<p>
<code>dice.wasm</code> rolls five dice with <code>random</code>. On WASI
Preview 1 <code>random</code> draws real entropy from the host's
<code>random_get</code> (the shim backs it with
<code>crypto.getRandomValues</code>), so click <em>Roll again</em> and the
result changes every time -- it is not a fixed pseudo-random sequence.
Source:
<a href="https://github.com/making/rontolisp/blob/develop/examples/browser/wasm-browser/dice.lisp"
>dice.lisp</a
>.
</p>
<div class="row">
<button id="run-dice">Roll dice.wasm</button>
</div>
<pre class="term" id="out-dice">(output appears here)</pre>
<script type="module">
import { runWasm } from "./wasi-shim.js";
async function run(buttonId, outId, wasmUrl, opts) {
const btn = document.getElementById(buttonId);
const out = document.getElementById(outId);
btn.disabled = true;
out.textContent = "running...";
try {
const { stdout, stderr } = await runWasm(wasmUrl, opts);
out.textContent = stdout + (stderr ? "\n[stderr]\n" + stderr : "");
} catch (e) {
out.textContent = "Error: " + e.message + "\n\n" +
"If you see a WebAssembly compile/link error, your browser may " +
"lack WebAssembly GC support (needs Chrome 119+, Firefox 120+, " +
"or Safari 18.2+). Also make sure you are serving this page over " +
"http:// (not opening the file directly).";
} finally {
btn.disabled = false;
}
}
document.getElementById("run-hello").addEventListener("click", () =>
run("run-hello", "out-hello", "./hello.wasm"),
);
document.getElementById("run-greet").addEventListener("click", () => {
const stdin = document.getElementById("stdin").value + "\n";
run("run-greet", "out-greet", "./greet.wasm", { stdin });
});
const diceBtn = document.getElementById("run-dice");
diceBtn.addEventListener("click", async () => {
await run("run-dice", "out-dice", "./dice.wasm");
diceBtn.textContent = "Roll again";
});
</script>
</body>
</html>