aboutsummaryrefslogtreecommitdiff
path: root/src/web/zc.js
blob: 4f14d3c856fe622de59b971d2d74e2a55016df56 (plain) (blame)
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
// 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);