Created
September 4, 2025 20:19
-
-
Save MyNameIsTrez/1197d7731eea4343b933e737d339c233 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!doctype html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1" /> | |
| <title>Compile `print("hi")` to WASM at runtime</title> | |
| <style> | |
| body { font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, Arial, "Apple Color Emoji", "Segoe UI Emoji"; margin: 2rem; } | |
| .ok { color: #0a7f2e; } | |
| .err { color: #a40000; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>Runtime compilation of <code>print("hi")</code> → WebAssembly</h1> | |
| <p>Click the button and check the browser console:</p> | |
| <button id="run">Compile & Run</button> | |
| <div id="status"></div> | |
| <!-- Load the WABT module --> | |
| <script src="https://cdn.jsdelivr.net/npm/wabt/index.js"></script> | |
| <script> | |
| const status = document.getElementById('status'); | |
| const show = (html, cls = 'ok') => (status.innerHTML = `<p class="${cls}">${html}</p>`); | |
| function pythonToWat(pySource) { | |
| const m = pySource.match(/^\s*print\(\s*(['"])(.*?)\1\s*\)\s*$/); | |
| if (!m) throw new Error('Only simple print("...") supported in this demo.'); | |
| const text = m[2]; | |
| const enc = new TextEncoder(); | |
| const bytes = enc.encode(text); | |
| const watStringLiteral = Array.from(bytes).map(b => `\\${b.toString(16).padStart(2,'0')}`).join(''); | |
| const len = bytes.length; | |
| return `(module | |
| (import "env" "log" (func $log (param i32 i32))) | |
| (memory (export "memory") 1) | |
| (data (i32.const 1024) "${watStringLiteral}") | |
| (func (export "_start") | |
| i32.const 1024 | |
| i32.const ${len} | |
| call $log))`; | |
| } | |
| let memoryRef = null; | |
| const imports = { | |
| env: { | |
| log(ptr, len) { | |
| const view = new Uint8Array(memoryRef.buffer, ptr, len); | |
| const text = new TextDecoder().decode(view); | |
| console.log(text); | |
| } | |
| } | |
| }; | |
| document.getElementById('run').addEventListener('click', async () => { | |
| try { | |
| show('Compiling…'); | |
| const py = 'print("hi")'; | |
| const wat = pythonToWat(py); | |
| // Use WABT correctly | |
| const wabt = await WabtModule(); // returns the API object | |
| const mod = wabt.parseWat('module.wat', wat); | |
| mod.resolveNames(); | |
| mod.validate(); | |
| const { buffer } = mod.toBinary({ write_debug_names: true }); | |
| mod.destroy(); | |
| const { instance } = await WebAssembly.instantiate(buffer, imports); | |
| memoryRef = instance.exports.memory; | |
| instance.exports._start(); | |
| show('Success! Check your browser console for the output.'); | |
| } catch (err) { | |
| console.error(err); | |
| show('Error: ' + (err.message || err), 'err'); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment