lumen-wasm 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # lumen-wasm
2
+
3
+ WebAssembly bindings for the Lumen compiler and VM.
4
+
5
+ This crate provides a WASM-compatible interface for compiling and executing Lumen programs in browser and WASI environments.
6
+
7
+ ## Prerequisites
8
+
9
+ Install wasm-pack:
10
+
11
+ ```bash
12
+ cargo install wasm-pack
13
+ ```
14
+
15
+ ## Building
16
+
17
+ ### Browser Target
18
+
19
+ ```bash
20
+ wasm-pack build --target web
21
+ ```
22
+
23
+ Or use the CLI:
24
+
25
+ ```bash
26
+ lumen build wasm --target web
27
+ ```
28
+
29
+ Output in `pkg/`:
30
+ - `lumen_wasm.js` - JavaScript glue code
31
+ - `lumen_wasm_bg.wasm` - WASM binary
32
+ - `lumen_wasm.d.ts` - TypeScript definitions
33
+
34
+ ### Node.js Target
35
+
36
+ ```bash
37
+ wasm-pack build --target nodejs
38
+ ```
39
+
40
+ Or:
41
+
42
+ ```bash
43
+ lumen build wasm --target nodejs
44
+ ```
45
+
46
+ ### WASI Target
47
+
48
+ ```bash
49
+ cargo build --target wasm32-wasi
50
+ ```
51
+
52
+ (Requires `wasm32-wasi` target installed: `rustup target add wasm32-wasi`)
53
+
54
+ ## Usage
55
+
56
+ ### Browser
57
+
58
+ ```html
59
+ <script type="module">
60
+ import init, { run, compile, check, version } from './pkg/lumen_wasm.js';
61
+
62
+ await init();
63
+
64
+ const source = `
65
+ cell main() -> Int
66
+ 42
67
+ end
68
+ `;
69
+
70
+ // Type-check
71
+ const checkResult = check(source);
72
+ console.log(checkResult.to_json());
73
+
74
+ // Compile to LIR
75
+ const lirResult = compile(source);
76
+ console.log(lirResult.to_json());
77
+
78
+ // Execute
79
+ const runResult = run(source, "main");
80
+ console.log(runResult.to_json());
81
+
82
+ // Get version
83
+ console.log("Lumen version:", version());
84
+ </script>
85
+ ```
86
+
87
+ ### Node.js
88
+
89
+ ```javascript
90
+ const { run, check, compile, version } = require('./pkg/lumen_wasm.js');
91
+
92
+ const source = `
93
+ cell factorial(n: Int) -> Int
94
+ if n <= 1
95
+ 1
96
+ else
97
+ n * factorial(n - 1)
98
+ end
99
+ end
100
+
101
+ cell main() -> Int
102
+ factorial(5)
103
+ end
104
+ `;
105
+
106
+ const result = run(source, "main");
107
+ const parsed = JSON.parse(result.to_json());
108
+
109
+ if (parsed.ok) {
110
+ console.log("Result:", parsed.ok);
111
+ } else {
112
+ console.error("Error:", parsed.error);
113
+ }
114
+ ```
115
+
116
+ ### Wasmtime (WASI)
117
+
118
+ ```bash
119
+ cargo build --target wasm32-wasi --release
120
+ wasmtime target/wasm32-wasi/release/lumen_wasm.wasm
121
+ ```
122
+
123
+ ## API
124
+
125
+ ### `check(source: &str) -> LumenResult`
126
+
127
+ Type-check Lumen source code.
128
+
129
+ Returns:
130
+ - Success: `{"ok": "Type-checked successfully"}`
131
+ - Error: `{"error": "error message with diagnostics"}`
132
+
133
+ ### `compile(source: &str) -> LumenResult`
134
+
135
+ Compile Lumen source to LIR JSON.
136
+
137
+ Returns:
138
+ - Success: `{"ok": "<LIR JSON>"}`
139
+ - Error: `{"error": "error message with diagnostics"}`
140
+
141
+ ### `run(source: &str, cell_name: Option<String>) -> LumenResult`
142
+
143
+ Compile and execute Lumen source.
144
+
145
+ Parameters:
146
+ - `source` - Lumen source code
147
+ - `cell_name` - Cell to execute (default: "main")
148
+
149
+ Returns:
150
+ - Success: `{"ok": "<output>"}`
151
+ - Error: `{"error": "error message"}`
152
+
153
+ ### `version() -> String`
154
+
155
+ Get the Lumen compiler version.
156
+
157
+ ### `LumenResult`
158
+
159
+ Result wrapper with helper methods:
160
+
161
+ - `is_ok() -> bool` - Returns true if successful
162
+ - `is_err() -> bool` - Returns true if failed
163
+ - `to_json() -> String` - Get result as JSON string
164
+
165
+ ## Examples
166
+
167
+ See `examples/wasm_hello.lm.md` for Lumen code examples.
168
+
169
+ See `examples/wasm_browser.html` for a complete browser demo.
170
+
171
+ ## Current Limitations
172
+
173
+ - No filesystem access in browser (WASI supports filesystem)
174
+ - No tool providers yet (coming in Phase 3)
175
+ - No trace recording (requires file I/O)
176
+ - No multi-file imports yet
177
+
178
+ ## Size Optimization
179
+
180
+ The release profile is optimized for small binary size:
181
+
182
+ ```toml
183
+ [profile.release]
184
+ opt-level = "z" # Optimize for size
185
+ lto = true # Link-time optimization
186
+ codegen-units = 1 # Single codegen unit
187
+ panic = "abort" # Smaller panic handler
188
+ ```
189
+
190
+ Further optimize with `wasm-opt`:
191
+
192
+ ```bash
193
+ wasm-opt -Oz -o optimized.wasm pkg/lumen_wasm_bg.wasm
194
+ ```
195
+
196
+ ## Development
197
+
198
+ Run tests:
199
+
200
+ ```bash
201
+ cargo test
202
+ ```
203
+
204
+ Run WASM tests:
205
+
206
+ ```bash
207
+ wasm-pack test --headless --firefox
208
+ ```
209
+
210
+ ## See Also
211
+
212
+ - `docs/WASM_STRATEGY.md` - Overall WASM compilation strategy
213
+ - `examples/wasm_hello.lm.md` - Example Lumen programs for WASM
214
+ - `examples/wasm_browser.html` - Interactive browser demo
@@ -0,0 +1,61 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /**
5
+ * Result of a compilation or execution operation.
6
+ *
7
+ * JSON format:
8
+ * - Success: `{"ok": "result_value"}`
9
+ * - Error: `{"error": "error_message"}`
10
+ */
11
+ export class LumenResult {
12
+ private constructor();
13
+ free(): void;
14
+ [Symbol.dispose](): void;
15
+ /**
16
+ * Returns true if the operation failed.
17
+ */
18
+ is_err(): boolean;
19
+ /**
20
+ * Returns true if the operation succeeded.
21
+ */
22
+ is_ok(): boolean;
23
+ /**
24
+ * Returns the result as a JSON string.
25
+ */
26
+ to_json(): string;
27
+ }
28
+
29
+ /**
30
+ * Type-check a Lumen source file.
31
+ *
32
+ * Returns a LumenResult:
33
+ * - On success: `{"ok": "Type-checked successfully"}`
34
+ * - On error: `{"error": "error message with diagnostics"}`
35
+ */
36
+ export function check(source: string): LumenResult;
37
+
38
+ /**
39
+ * Compile Lumen source to LIR JSON.
40
+ *
41
+ * Returns a LumenResult:
42
+ * - On success: `{"ok": "<LIR JSON>"}`
43
+ * - On error: `{"error": "error message with diagnostics"}`
44
+ */
45
+ export function compile(source: string): LumenResult;
46
+
47
+ /**
48
+ * Compile and execute Lumen source.
49
+ *
50
+ * Returns a LumenResult:
51
+ * - On success: `{"ok": "<output>"}`
52
+ * - On error: `{"error": "error message"}`
53
+ *
54
+ * The `cell_name` parameter specifies which cell to execute (default: "main").
55
+ */
56
+ export function run(source: string, cell_name?: string | null): LumenResult;
57
+
58
+ /**
59
+ * Get the version of the Lumen compiler.
60
+ */
61
+ export function version(): string;
package/lumen_wasm.js ADDED
@@ -0,0 +1,9 @@
1
+ /* @ts-self-types="./lumen_wasm.d.ts" */
2
+
3
+ import * as wasm from "./lumen_wasm_bg.wasm";
4
+ import { __wbg_set_wasm } from "./lumen_wasm_bg.js";
5
+ __wbg_set_wasm(wasm);
6
+ wasm.__wbindgen_start();
7
+ export {
8
+ LumenResult, check, compile, run, version
9
+ } from "./lumen_wasm_bg.js";
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Result of a compilation or execution operation.
3
+ *
4
+ * JSON format:
5
+ * - Success: `{"ok": "result_value"}`
6
+ * - Error: `{"error": "error_message"}`
7
+ */
8
+ export class LumenResult {
9
+ static __wrap(ptr) {
10
+ ptr = ptr >>> 0;
11
+ const obj = Object.create(LumenResult.prototype);
12
+ obj.__wbg_ptr = ptr;
13
+ LumenResultFinalization.register(obj, obj.__wbg_ptr, obj);
14
+ return obj;
15
+ }
16
+ __destroy_into_raw() {
17
+ const ptr = this.__wbg_ptr;
18
+ this.__wbg_ptr = 0;
19
+ LumenResultFinalization.unregister(this);
20
+ return ptr;
21
+ }
22
+ free() {
23
+ const ptr = this.__destroy_into_raw();
24
+ wasm.__wbg_lumenresult_free(ptr, 0);
25
+ }
26
+ /**
27
+ * Returns true if the operation failed.
28
+ * @returns {boolean}
29
+ */
30
+ is_err() {
31
+ const ret = wasm.lumenresult_is_err(this.__wbg_ptr);
32
+ return ret !== 0;
33
+ }
34
+ /**
35
+ * Returns true if the operation succeeded.
36
+ * @returns {boolean}
37
+ */
38
+ is_ok() {
39
+ const ret = wasm.lumenresult_is_ok(this.__wbg_ptr);
40
+ return ret !== 0;
41
+ }
42
+ /**
43
+ * Returns the result as a JSON string.
44
+ * @returns {string}
45
+ */
46
+ to_json() {
47
+ let deferred1_0;
48
+ let deferred1_1;
49
+ try {
50
+ const ret = wasm.lumenresult_to_json(this.__wbg_ptr);
51
+ deferred1_0 = ret[0];
52
+ deferred1_1 = ret[1];
53
+ return getStringFromWasm0(ret[0], ret[1]);
54
+ } finally {
55
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
56
+ }
57
+ }
58
+ }
59
+ if (Symbol.dispose) LumenResult.prototype[Symbol.dispose] = LumenResult.prototype.free;
60
+
61
+ /**
62
+ * Type-check a Lumen source file.
63
+ *
64
+ * Returns a LumenResult:
65
+ * - On success: `{"ok": "Type-checked successfully"}`
66
+ * - On error: `{"error": "error message with diagnostics"}`
67
+ * @param {string} source
68
+ * @returns {LumenResult}
69
+ */
70
+ export function check(source) {
71
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
72
+ const len0 = WASM_VECTOR_LEN;
73
+ const ret = wasm.check(ptr0, len0);
74
+ return LumenResult.__wrap(ret);
75
+ }
76
+
77
+ /**
78
+ * Compile Lumen source to LIR JSON.
79
+ *
80
+ * Returns a LumenResult:
81
+ * - On success: `{"ok": "<LIR JSON>"}`
82
+ * - On error: `{"error": "error message with diagnostics"}`
83
+ * @param {string} source
84
+ * @returns {LumenResult}
85
+ */
86
+ export function compile(source) {
87
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
88
+ const len0 = WASM_VECTOR_LEN;
89
+ const ret = wasm.compile(ptr0, len0);
90
+ return LumenResult.__wrap(ret);
91
+ }
92
+
93
+ /**
94
+ * Compile and execute Lumen source.
95
+ *
96
+ * Returns a LumenResult:
97
+ * - On success: `{"ok": "<output>"}`
98
+ * - On error: `{"error": "error message"}`
99
+ *
100
+ * The `cell_name` parameter specifies which cell to execute (default: "main").
101
+ * @param {string} source
102
+ * @param {string | null} [cell_name]
103
+ * @returns {LumenResult}
104
+ */
105
+ export function run(source, cell_name) {
106
+ const ptr0 = passStringToWasm0(source, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
107
+ const len0 = WASM_VECTOR_LEN;
108
+ var ptr1 = isLikeNone(cell_name) ? 0 : passStringToWasm0(cell_name, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
109
+ var len1 = WASM_VECTOR_LEN;
110
+ const ret = wasm.run(ptr0, len0, ptr1, len1);
111
+ return LumenResult.__wrap(ret);
112
+ }
113
+
114
+ /**
115
+ * Get the version of the Lumen compiler.
116
+ * @returns {string}
117
+ */
118
+ export function version() {
119
+ let deferred1_0;
120
+ let deferred1_1;
121
+ try {
122
+ const ret = wasm.version();
123
+ deferred1_0 = ret[0];
124
+ deferred1_1 = ret[1];
125
+ return getStringFromWasm0(ret[0], ret[1]);
126
+ } finally {
127
+ wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
128
+ }
129
+ }
130
+ export function __wbg___wbindgen_throw_be289d5034ed271b(arg0, arg1) {
131
+ throw new Error(getStringFromWasm0(arg0, arg1));
132
+ }
133
+ export function __wbg_getRandomValues_71d446877d8b0ad4() { return handleError(function (arg0, arg1) {
134
+ globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
135
+ }, arguments); }
136
+ export function __wbg_getTime_1e3cd1391c5c3995(arg0) {
137
+ const ret = arg0.getTime();
138
+ return ret;
139
+ }
140
+ export function __wbg_new_0_73afc35eb544e539() {
141
+ const ret = new Date();
142
+ return ret;
143
+ }
144
+ export function __wbindgen_init_externref_table() {
145
+ const table = wasm.__wbindgen_externrefs;
146
+ const offset = table.grow(4);
147
+ table.set(0, undefined);
148
+ table.set(offset + 0, undefined);
149
+ table.set(offset + 1, null);
150
+ table.set(offset + 2, true);
151
+ table.set(offset + 3, false);
152
+ }
153
+ const LumenResultFinalization = (typeof FinalizationRegistry === 'undefined')
154
+ ? { register: () => {}, unregister: () => {} }
155
+ : new FinalizationRegistry(ptr => wasm.__wbg_lumenresult_free(ptr >>> 0, 1));
156
+
157
+ function addToExternrefTable0(obj) {
158
+ const idx = wasm.__externref_table_alloc();
159
+ wasm.__wbindgen_externrefs.set(idx, obj);
160
+ return idx;
161
+ }
162
+
163
+ function getArrayU8FromWasm0(ptr, len) {
164
+ ptr = ptr >>> 0;
165
+ return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
166
+ }
167
+
168
+ function getStringFromWasm0(ptr, len) {
169
+ ptr = ptr >>> 0;
170
+ return decodeText(ptr, len);
171
+ }
172
+
173
+ let cachedUint8ArrayMemory0 = null;
174
+ function getUint8ArrayMemory0() {
175
+ if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
176
+ cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
177
+ }
178
+ return cachedUint8ArrayMemory0;
179
+ }
180
+
181
+ function handleError(f, args) {
182
+ try {
183
+ return f.apply(this, args);
184
+ } catch (e) {
185
+ const idx = addToExternrefTable0(e);
186
+ wasm.__wbindgen_exn_store(idx);
187
+ }
188
+ }
189
+
190
+ function isLikeNone(x) {
191
+ return x === undefined || x === null;
192
+ }
193
+
194
+ function passStringToWasm0(arg, malloc, realloc) {
195
+ if (realloc === undefined) {
196
+ const buf = cachedTextEncoder.encode(arg);
197
+ const ptr = malloc(buf.length, 1) >>> 0;
198
+ getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
199
+ WASM_VECTOR_LEN = buf.length;
200
+ return ptr;
201
+ }
202
+
203
+ let len = arg.length;
204
+ let ptr = malloc(len, 1) >>> 0;
205
+
206
+ const mem = getUint8ArrayMemory0();
207
+
208
+ let offset = 0;
209
+
210
+ for (; offset < len; offset++) {
211
+ const code = arg.charCodeAt(offset);
212
+ if (code > 0x7F) break;
213
+ mem[ptr + offset] = code;
214
+ }
215
+ if (offset !== len) {
216
+ if (offset !== 0) {
217
+ arg = arg.slice(offset);
218
+ }
219
+ ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
220
+ const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
221
+ const ret = cachedTextEncoder.encodeInto(arg, view);
222
+
223
+ offset += ret.written;
224
+ ptr = realloc(ptr, len, offset, 1) >>> 0;
225
+ }
226
+
227
+ WASM_VECTOR_LEN = offset;
228
+ return ptr;
229
+ }
230
+
231
+ let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
232
+ cachedTextDecoder.decode();
233
+ const MAX_SAFARI_DECODE_BYTES = 2146435072;
234
+ let numBytesDecoded = 0;
235
+ function decodeText(ptr, len) {
236
+ numBytesDecoded += len;
237
+ if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
238
+ cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
239
+ cachedTextDecoder.decode();
240
+ numBytesDecoded = len;
241
+ }
242
+ return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
243
+ }
244
+
245
+ const cachedTextEncoder = new TextEncoder();
246
+
247
+ if (!('encodeInto' in cachedTextEncoder)) {
248
+ cachedTextEncoder.encodeInto = function (arg, view) {
249
+ const buf = cachedTextEncoder.encode(arg);
250
+ view.set(buf);
251
+ return {
252
+ read: arg.length,
253
+ written: buf.length
254
+ };
255
+ };
256
+ }
257
+
258
+ let WASM_VECTOR_LEN = 0;
259
+
260
+
261
+ let wasm;
262
+ export function __wbg_set_wasm(val) {
263
+ wasm = val;
264
+ }
Binary file
package/package.json ADDED
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "lumen-wasm",
3
+ "type": "module",
4
+ "collaborators": [
5
+ "Lumen Contributors"
6
+ ],
7
+ "description": "WebAssembly bindings for the Lumen compiler and VM",
8
+ "version": "0.1.1",
9
+ "license": "MIT OR Apache-2.0",
10
+ "files": [
11
+ "lumen_wasm_bg.wasm",
12
+ "lumen_wasm.js",
13
+ "lumen_wasm_bg.js",
14
+ "lumen_wasm.d.ts"
15
+ ],
16
+ "main": "lumen_wasm.js",
17
+ "types": "lumen_wasm.d.ts",
18
+ "sideEffects": [
19
+ "./lumen_wasm.js",
20
+ "./snippets/*"
21
+ ]
22
+ }