// wasm/asm/lumbda-asm.loader.js
// Asm tier loader — instantiates lumbda-asm.wasm and exposes evalLisp.
//
// Memory layout (mirrors lumbda.wat):
//   0x10000  output buffer (read after each call)
//   0x20000  source buffer (write before each call)

async function _bootstrap() {
    const wasmURL = new URL("./lumbda-asm.wasm", import.meta.url).href;
    const resp = await fetch(wasmURL);
    const bytes = await resp.arrayBuffer();
    const { instance } = await WebAssembly.instantiate(bytes);
    const exp = instance.exports;

    exp.lumbda_init();

    const enc = new TextEncoder();
    const dec = new TextDecoder();

    return {
        async evalLisp(src) {
            const srcBytes = enc.encode(src);
            const srcPtr = exp.lumbda_source_ptr();
            const mem = new Uint8Array(exp.memory.buffer);
            mem.set(srcBytes, srcPtr);
            try {
                exp.lumbda_eval(srcBytes.length);
            } catch (e) {
                return `error: ${e.message}`;
            }
            const outPtr = exp.lumbda_output_ptr();
            const outLen = exp.lumbda_output_len();
            return dec.decode(new Uint8Array(exp.memory.buffer, outPtr, outLen));
        },
    };
}

// Closure-encapsulated singleton (see lumbda-c.loader.js for rationale).
export const createAsmTier = (() => {
    let tier = null;
    return async () => {
        if (!tier) tier = await _bootstrap();
        return tier;
    };
})();
