ArrayBox
ESC to close
ctrl+k keyboard • ctrl+h help
box mode
space or type select arraybox
enter evaluate code
shift + enter evaluate selection
shift + enter insert newline
ctrl + p show language picker
ctrl + ↑ ↓ switch language
ctrl + k toggle keyboard overlay
ctrl + b show fonts
ctrl + space open primitive search
ctrl + l create permalink (copy URL)
ctrl + f format code (no evaluation)
ctrl + / toggle comment
ctrl + shift + ↑ ↓ cycle through input history
f1 show docs for glyph at cursor
ctrl + shift + c compare primitives across languages
keyboard mode
s or type search primitives
↑ ↓ navigate keys
shift cycle through docs
f1 open full docs link
fonts
APL APL387
BQN BQN386
Uiua Uiua386
J JetBrains Mono
Kap APL387
TinyAPL APL387

'); iframeDoc.close(); return new Promise((resolve, reject) => { // Setup Module config in the iframe BEFORE loading the script // (same pattern as J loader) iframe.contentWindow.Module = { locateFile: function(path, prefix) { return wasmBaseUrl + path; }, onRuntimeInitialized: function() { try { console.log('[BQN] WASM runtime initialized'); const Module = iframe.contentWindow.Module; // Wrap C functions cbqn_runLine = Module.cwrap('cbqn_runLine', null, ['string', 'number']); bqnModule = Module; bqnReady = true; bqnLoading = false; console.log('[BQN] CBQN WASM loaded successfully!'); resolve(true); } catch (error) { console.error('[BQN] Error wrapping functions:', error); bqnLoadError = error; bqnLoading = false; reject(error); } }, onAbort: function(what) { console.error('[BQN] WASM initialization aborted:', what); bqnLoadError = new Error(what || 'CBQN WASM initialization aborted'); bqnLoading = false; reject(bqnLoadError); }, // Capture stdout - cbqn_runLine sends formatted results here print: function(text) { stdoutBuf += text + '\n'; }, // Capture stderr - cbqn_runLine sends error messages here printErr: function(text) { stderrBuf += text + '\n'; } }; // Load the script with absolute URL const script = iframeDoc.createElement('script'); script.src = wasmBaseUrl + 'BQN.js'; script.onerror = function(e) { console.error('[BQN] Failed to load BQN.js:', e); bqnLoadError = new Error('Failed to load CBQN WASM script'); bqnLoading = false; reject(bqnLoadError); }; iframeDoc.head.appendChild(script); }); } catch (error) { console.error('[BQN] WASM loading failed:', error); bqnLoadError = error; bqnLoading = false; return false; } })(); return bqnLoadPromise; } async function evalBQN(code) { if (!bqnReady) { if (!bqnLoading && !bqnLoadError) { loadBQN().catch(() => {}); } if (bqnLoadError) { return { success: false, output: `CBQN failed to load: ${bqnLoadError.message}\n\nCheck browser console (F12) for details.` }; } // Wait for loading to complete const startWait = Date.now(); const maxWait = 15000; // 15 second timeout while (!bqnReady && !bqnLoadError && (Date.now() - startWait) < maxWait) { await new Promise(r => setTimeout(r, 100)); } if (!bqnReady) { if (bqnLoadError) { return { success: false, output: `CBQN failed to load: ${bqnLoadError.message}` }; } return { success: false, output: 'CBQN WASM loading...' }; } } // Clear output buffers stdoutBuf = ''; stderrBuf = ''; try { // Use cbqn_runLine which has built-in error catching via CATCH/setjmp. // It prints formatted results to stdout and errors to stderr. // cbqn_runLine expects the code string and its byte length. const encoder = new TextEncoder(); const encoded = encoder.encode(code); cbqn_runLine(code, encoded.length); const stdout = stdoutBuf.replace(/\n$/, ''); const stderr = stderrBuf.replace(/\n$/, ''); if (stderr) { // Error output present - extract the error message // CBQN stderr format: "Error: \n" let errMsg = stderr; // Remove the "Error: " prefix if present if (errMsg.startsWith('Error: ')) { errMsg = errMsg.slice(7); } return { success: false, output: errMsg }; } return { success: true, output: stdout }; } catch (error) { // Shouldn't normally happen since cbqn_runLine catches errors internally let errMsg = error.message || String(error); return { success: false, output: errMsg }; } } // Expose to global scope for use in main script window.cbqnWasm = { load: loadBQN, isReady: () => bqnReady, getError: () => bqnLoadError, eval: evalBQN }; // Pre-load CBQN when page loads loadBQN().catch(() => {}); })();