Skip to content

Add a WebAssembly build and a browser playground - #61

Merged
alan23273850 merged 4 commits into
fmlab-iis:mainfrom
ondrik:wasm-playground
Oct 21, 2026
Merged

alan23273850 merged 4 commits into
fmlab-iis:mainfrom
ondrik:wasm-playground

Conversation

@ondrik

@ondrik ondrik commented Oct 20, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Builds AutoQ for WebAssembly and adds a browser playground at site/playground/, served at /playground/ next to the landing page. It runs the unchanged command-line main() entirely in the browser, with Z3 and the ANTLR runtime compiled in, so nothing is uploaded and results match the native tool.

Live preview: https://ondrik.github.io/AutoQ/playground/ is this branch deployed from my fork with the same workflow.

Depends on #58 (the landing page). This branch is built on #58's commit, so until #58 is merged this PR also shows that commit. After #58 is merged with a merge commit or a rebase, the diff here shrinks to the playground alone. If #58 is squash-merged, I'll rebase this branch.

What's in it

  • wasm/build.sh builds Z3 4.12.5 and the ANTLR 4.13.2 C++ runtime as static WebAssembly libraries (once, then cached), then builds AutoQ and writes autoq.js and autoq.wasm. It patches three lines of Z3: names left over from renames inside templates that are never instantiated, which the clang in current Emscripten rejects. Later Z3 releases contain the same fixes. Tested with Emscripten 6.0.12.
  • CMake: an Emscripten-only branch that uses the header-only parts of Boost, links the prebuilt Z3 and ANTLR libraries, skips the unit tests, and links autoq as an ES module exporting createAutoQ(). The native build is unchanged.
  • Source changes:
    • cli/autoq.cc: skip feenableexcept() under Emscripten, since WebAssembly has no floating-point traps.
    • src/util/memory.cpp: report the WebAssembly heap size under Emscripten. Emscripten's getrusage() doesn't set ru_maxrss, so the reported memory was garbage before.
  • site/playground/: editable file tabs, ver / ex / eq, --loopsum, Stop, Ctrl+Enter to run, and eleven examples. Six are taken from the repository: the README example, BV, symbolic Grover, Grover, if, and while with an invariant. Five are for eq: CX = H·CZ·H, SWAP as three CX gates, Toffoli against its Clifford+T decomposition, the same decomposition with one T flipped to T† ([unequal]), and XZ vs ZX (equal up to a global phase). eq has its own files (only a.qasm and b.qasm) and its own example list. ver and ex share one set of files, and each set keeps its edits when you switch commands. AutoQ runs in a Web Worker with a fresh instance per run. The landing page links to it from the hero, the nav and the start of Get started.
  • .github/workflows/pages.yml: installs Emscripten, restores the cached Z3/ANTLR build, runs wasm/build.sh and deploys site/. The generated autoq.js/autoq.wasm are gitignored. The first run builds Z3, which takes a while; later runs use the cache.
  • wasm/compare.mjs runs every playground example with the native CLI and with the WebAssembly build and checks that the output and exit code match. wasm/README.md documents the build and how the browser build differs from native.

Testing

  • node wasm/compare.mjs build/cli/autoq site/playground: all 11 examples print the same output and exit code as the native CLI. A malformed input gives the same error and exit code 1.
  • Headless Chrome, driven through the Run button: verdicts as expected, ex prints the README's result set, and switching ver → eq → ex → eq shows the right files and examples and keeps edits. No console errors. Light, dark and phone layouts checked.
  • autoq.wasm is 17 MB, or 5.2 MB gzipped. Download plus compile took under 0.1 s locally, and small examples run in 0.01–0.3 s.
  • Native Release build: compiles, and ctest passes (2/2).
  • Deployed on my fork by the updated pages.yml: the first run, which also builds Z3 and ANTLR, took 17m40s. The live page passes the same browser test.

Differences from the native build

  • No floating-point traps: an arithmetic error that stops the native tool with SIGFPE gives inf/NaN here.
  • Single-threaded, and limited to the memory a browser gives a page (at most 4 GB), so the largest benchmarks are better run natively.
  • Error messages show source paths relative to the repository root.

Try it locally

source ~/emsdk/emsdk_env.sh   # Emscripten 6.0.12
wasm/build.sh
python3 -m http.server -d site 8000   # open http://localhost:8000/playground/

🤖 Generated with Claude Code

https://claude.ai/code/session_013gtFQRPe1eSSpmA7EJ2KNY

ondrik and others added 4 commits October 20, 2026 20:42
A static landing page in site/ (no build step, self-hosted fonts) and a
workflow that deploys it to GitHub Pages on pushes to main that touch
site/** or the workflow.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gtFQRPe1eSSpmA7EJ2KNY
wasm/build.sh compiles the unchanged AutoQ CLI to WebAssembly with
Emscripten, together with Z3 4.12.5 and the ANTLR 4.13.2 C++ runtime
(built once and cached). site/playground runs it in a Web Worker: it
writes the input files into the in-memory file system and calls main()
with the CLI arguments, so results match the native tool.

- CMake: an Emscripten-only branch (header-only Boost, prebuilt Z3 and
  ANTLR, ES-module link options). The native build is unchanged.
- cli/autoq.cc: skip feenableexcept() under Emscripten (no FP traps).
- src/util/memory.cpp: report the WebAssembly heap size under
  Emscripten; its getrusage() does not set ru_maxrss.
- pages.yml: build the playground in CI with a cached dependency build.
- wasm/compare.mjs checks every playground example against the native
  CLI; wasm/README.md documents the build.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gtFQRPe1eSSpmA7EJ2KNY
The hero and the nav already link to it; this adds a sentence at the start of Get started for readers who want to try AutoQ before installing it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gtFQRPe1eSSpmA7EJ2KNY
In eq mode the editor now shows only a.qasm and b.qasm, and the example
list offers equivalence examples: CX = H·CZ·H, SWAP as three CX gates,
Toffoli against its Clifford+T decomposition, the same decomposition
with one T replaced by T† (unequal), and XZ vs ZX (equal up to global
phase). ver and ex keep sharing one workspace; each workspace keeps its
edits when switching commands. [equal]/[unequal] are highlighted like
[OK]/[failed].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013gtFQRPe1eSSpmA7EJ2KNY
@alan23273850
alan23273850 merged commit 6dda524 into fmlab-iis:main Oct 21, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants