aboutsummaryrefslogtreecommitdiff
path: root/src/web/zc.js
diff options
context:
space:
mode:
authorGravatar Moon Flower <moonflower@elhenney.local> 2026-10-12 08:46:23 +0330
committerGravatar Moon Flower <moonflower@elhenney.local> 2026-10-12 08:46:23 +0330
commitecc350ca5c2eb50be8309c5f14f8bf0d87db9a02 (patch)
tree70e0af76a1b13affff7c6cc8aac7b3e6ef960478 /src/web/zc.js
a
Diffstat (limited to 'src/web/zc.js')
-rw-r--r--src/web/zc.js28
1 files changed, 28 insertions, 0 deletions
diff --git a/src/web/zc.js b/src/web/zc.js
new file mode 100644
index 0000000..4f14d3c
--- /dev/null
+++ b/src/web/zc.js
@@ -0,0 +1,28 @@
+// runs zc in a browser or in node: the microcore compiled to webassembly,
+// with the compiler genome inside. ZC.load(bytes) gives a machine, and
+// machine.run(source) compiles and runs a program the way `zy < file.zc` does,
+// returning what it printed. every run starts from a fresh instance.
+(function (root) {
+ async function load(wasm) {
+ if (typeof wasm === 'string') wasm = await (await fetch(wasm)).arrayBuffer();
+ const mod = await WebAssembly.compile(wasm);
+ return {
+ async run(source) {
+ let out = [], msg = [], mem;
+ const inst = await WebAssembly.instantiate(mod, {
+ env: { js_putc: c => { out.push(c); }, js_msg: c => { msg.push(c); } }
+ });
+ const x = inst.exports;
+ const bytes = new TextEncoder().encode(source);
+ if (bytes.length > x.wasm_input_cap()) throw new Error('program too long for the input buffer');
+ new Uint8Array(x.memory.buffer).set(bytes, x.wasm_input());
+ x.wasm_set_input(bytes.length);
+ const status = x.wasm_run();
+ const dec = new TextDecoder();
+ return { output: dec.decode(new Uint8Array(out)), messages: dec.decode(new Uint8Array(msg)), status };
+ }
+ };
+ }
+ const ZC = { load };
+ if (typeof module !== 'undefined' && module.exports) module.exports = ZC; else root.ZC = ZC;
+})(typeof self !== 'undefined' ? self : this);