Skip to content

Instantly share code, notes, and snippets.

@MyNameIsTrez
Created September 4, 2025 20:19
Show Gist options
  • Select an option

  • Save MyNameIsTrez/1197d7731eea4343b933e737d339c233 to your computer and use it in GitHub Desktop.

Select an option

Save MyNameIsTrez/1197d7731eea4343b933e737d339c233 to your computer and use it in GitHub Desktop.
<!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 &amp; 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