// wasm/python/lumbda-py.js // Python tier loader — Pyodide (CPython-in-WASM) hosting lumbda.py. // // ES module form so it works in both window and Web Worker contexts. // Exports createPythonTier() -> Promise<{ evalLisp(src) -> Promise }>. const PYODIDE_VERSION = "0.27.2"; const PYODIDE_INDEX_URL = `https://cdn.jsdelivr.net/pyodide/v${PYODIDE_VERSION}/full/`; async function _bootstrap() { // Dynamic ES-module import works in both window and Worker (module type) // contexts. The CDN ships pyodide.mjs alongside pyodide.js. const { loadPyodide } = await import(PYODIDE_INDEX_URL + "pyodide.mjs"); const pyodide = await loadPyodide({ indexURL: PYODIDE_INDEX_URL }); // Pull lumbda.py + stdlib.lsp into Pyodide's virtual FS. Paths resolve // relative to THIS loader (under python/) for both window and Worker. const pyURL = new URL("./lumbda.py", import.meta.url).href; const stdlibURL = new URL("./stdlib.lsp", import.meta.url).href; const lumbdaSrc = await (await fetch(pyURL)).text(); const stdlibSrc = await (await fetch(stdlibURL)).text(); pyodide.FS.writeFile("/home/pyodide/lumbda.py", lumbdaSrc); pyodide.FS.writeFile("/home/pyodide/stdlib.lsp", stdlibSrc); await pyodide.runPythonAsync(` import sys, io sys.path.insert(0, "/home/pyodide") import lumbda _env = lumbda.make_global_env() for _e in lumbda.read_all(lumbda.PRELUDE): lumbda.leval(_e, _env) def _lumbda_eval(src): buf = io.StringIO() old = sys.stdout sys.stdout = buf last = None try: for e in lumbda.read_all(src): last = lumbda.leval(e, _env) except Exception as ex: sys.stdout = old return f"{buf.getvalue()}error: {ex}" sys.stdout = old out = buf.getvalue() if last is not None and not isinstance(last, lumbda._Void): rep = lumbda.show(last) if out and not out.endswith("\\n"): out += "\\n" out += rep return out `); return { async evalLisp(src) { pyodide.globals.set("_src_in", src); return await pyodide.runPythonAsync("_lumbda_eval(_src_in)"); }, }; } // Closure-encapsulated singleton (see lumbda-c.loader.js for rationale). export const createPythonTier = (() => { let tier = null; return async () => { if (!tier) tier = await _bootstrap(); return tier; }; })();