Skip to content
jburgyPublic

About

Support materials for blog entries

Resources

Stars

3 stars

Watchers

1 watching

Forks

Latest commit

 

History

816 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Python package JavaScript Build and Deploy GitHub Pages

Tested with pytest codecov Ruff uv Checked with ty Checked with pyright

Python 3.13 | 3.14 License Last commit Binder

blog

Support materials for the posts on bur.gy — interpreters, compilers, solvers and assorted experiments, plus the machinery that turns some of them into demos you can type into from inside a blog post.

The prose lives in a different repository, jburgy/jburgy.github.io; this one holds the code the prose talks about.

How a demo reaches the page

The two repositories are deployed separately but land on the same origin.

jburgy.github.io  --Jekyll-->  https://bur.gy/            (the posts)
jburgy/blog       --Pages -->  https://bur.gy/blog/       (the demos)
  1. .github/workflows/deploy.yml runs on every push to main (and builds, without deploying, on pull requests). It checks out submodules, installs node, wasi-sdk and uv, then runs make --jobs=4 in assets/.
  2. actions/upload-pages-artifact takes the whole of assets/ as-is and actions/deploy-pages publishes it. Nothing outside assets/ is ever served.
  3. A post on bur.gy loads the result with an absolute path — /blog/wasi-repl.mjs, /blog/jonesforth.wasm, /blog/regexp/web/demo.mjs. Same origin, so no CORS, no CDN, and the demo version always matches whatever main last built.
  4. The WASI REPL demos need no COOP/COEP headers or service worker: wasi-command.mjs runs the guest on the main thread and suspends its blocking read() with JSPI (WebAssembly.Suspending/promising: Chrome 137+, Firefox 139+, not Safari).

The role of assets/

assets/ is not a source folder — it is the staging area that becomes the published site. Almost everything in it is generated and gitignored; what is checked in is the recipe:

file what it does
assets/Makefile the whole build. VPATH = ../forth, so it reaches back into sibling folders rather than duplicating their sources: wasi-sdk/uvx+python-zig for the C and Zig interpreters' .wasm builds, wat2wasm for the hand-written wasm, asc for the AssemblyScript ones, and plain cp for data files like jonesforth.f
assets/package.json wraps the asc invocations for the AssemblyScript builds, run through npx so nothing needs installing
assets/thug-life.js, assets/regexp-snapshot.svg one-off assets embedded by a single post each
assets/index.html the /blog/ landing page: every demo below, latest first, inlined inside a <details> per demo and lazily mounted the first time it's opened

What comes out, and where it comes from:

published as built from seen in
/blog/4th-wasi.wasm forth/4th.c (wasi-sdk target) forth/html/4th.html and What, Forth, Again?, as published
/blog/5th-wasi.wasm forth/5th.c (wasi-sdk target) forth/html/5th.html and What is Tail Call Elimination?, as published
/blog/6th-wasi.wasm forth/6th.zig (wasm32-wasi target) forth/html/6th.html and Why not try Zig next?, as published
/blog/jonesforth.wasm forth/wasm/jonesforth.wast How Many Roads Must a Man Walk Down?
/blog/regexp/web/ regexp/web/ + forth/wasm/tabulate.wast What Makes an Expression Regular?
/blog/fourt2py/web/ fourt2py/web/ shape a waveform's spectrum and hear FOURT.F transform it back, post forthcoming
/blog/lisp-wasi.wasm lisp/assembly/wasi.ts (real WASI ABI, same core.ts) What do you mean, homoiconic?; preamble is lisp/eliza.lisp, a pattern-matching ELIZA chatbot
/blog/lisp-wast.wasm lisp/assembly/core.wast (core.ts by hand in WAT, WASI command) the same post, as the core.wast tab, with the same lisp/eliza.lisp preamble
/blog/tabulate.wasm + /blog/lisp/eliza.f lisp/lisp.f on forth/wasm/tabulate.wast the same post, as the lisp.f tab; eliza.f is jonesforth.f, lisp.f, LISP and eliza.lisp concatenated, since a REPL takes one preamble
/blog/TinyBasic-wasi.wasm TinyBasic/assembly/wasi.ts (real WASI ABI, same core.ts) When did Basic become insulting?
/blog/jonesforth.f the jonesforth submodule every Forth terminal

Every row above is also embedded live in assets/index.html itself (/blog/'s own landing page), one <details> per demo, alongside ising/'s and fourt2py/web/'s demos -- not just linked to its post.

Folders

Folders that feed a demo are marked ▶.

folder what is in it
forth/ — README ▶ Eleven jonesforth interpreters in C, Zig, Rust and hand-written wasm, catalogued by dispatch strategy. 4th.c, 5th.c, 6th.zig and wasm/jonesforth.wast are the ones that ship
regexp/ ▶ Thompson's 1968 construction, ported over and over: the original Algol 60, C (bytecode, threaded, switched, and a 32-bit JIT), Julia, Zig, Python and Forth. regexp/web/ is the browser demo, regexp/tracing/ — README — draws the animated snapshot
lisp/ ▶ sectorlisp rewritten in AssemblyScript, unmodified. assembly/core.ts holds the interpreter; wasiHost.ts gives it real WASI fd_read/fd_write (see asc's --use flags in package.json). eliza.lisp is a small ELIZA chatbot fed as the demo's preamble, written as a single self-recursive expression (the same sibling-LAMBDA/self-application trick lisp.lisp's own metacircular-evaluator bootstrap already uses); its keyword/reflection rules follow z88dk's clisp Tiny ELIZA example, reimplemented from scratch against sectorlisp's nine primitives (no numbers, no mutation). lisp.f is the same language again in FORTH, with a mark-and-sweep GC whose roots are the FORTH data and return stacks; it runs eliza.lisp unmodified on forth/wasm/jonesforth.wast and forth/wasm/tabulate.wast (see tests/lisp-forth.test.mjs). assembly/core.wast is core.ts once more, hand-written in WAT for the fewest instructions (raw-address cells, nil = 0, shallow binding), as a WASI command checked by tests/wast.test.mjs
TinyBasic/ ▶ Tiny BASIC's original IL virtual machine, plus a Python assembler for it and an AssemblyScript interpreter, split into core.ts/wasiHost.ts the same way as lisp/
assets/ ▶ The build and publish staging area described above
simplex/ — README The NSWC SMPLX revised simplex solver: the Fortran, a NumPy transcription, an f2py wrapper and benchmarks
linprog/ Linear-programming odds and ends around the same posts
sudoku/ Sudoku as an exact-cover / satisfiability problem
fourt2py/ ▶ Calling 1960s Fortran (FOURT) from Python — the "what ever happened to Fortran?" experiment. fourt2py/web/ is a browser demo: drag knots on a frequency-domain chart and fourt.pow2.mjs — a plain-JS specialization of FOURT.F to one dimension and power-of-two lengths — turns it into an oscilloscope trace and a tone. fourt2py/wasm/fourt.c (a general C transliteration compiled to WebAssembly) and fourt2py/web/fourt.pure.mjs (its general, non-power-of-two pure-JS counterpart) aren't part of the deployed demo but remain for comparison — see fourt2py/web/benchmark.mjs
progress/ Foreign-function and progress-reporting experiments
talks/ Slide decks, including the Zig-from-Python and data-visualisation talks
fun/ The scratch drawer: n-body, bytecode assemblers, Prechelt's benchmark, Zig toys
aoc2024/, aoc2025/, foo/ Advent of Code and puzzle solutions; excluded from pytest collection (see CODE_REVIEW.md)
notebooks/ Jupyter notebooks, reachable through the Binder badge above
jonesforth/ ▶ Submodule, not ours. deploy.yml needs submodules: true

The other workflows

workflow what it does
pythonpackage.yml uv + ruff + ty + pytest on 3.13 and 3.14. Needs gfortran and 32-bit gcc for the Fortran and jonesforth fixtures
javascript.yml node 24, wasi-sdk and nightly Rust; builds forth/5th.wasm and forth/web/4th.wasm, then runs the vitest and mocha suites with coverage
deploy.yml the Pages build described above

pythonpackage.yml and javascript.yml both upload coverage to Codecov (the badge above links there), the latter tagged with forth/regexp-web/fourt2py flags so each job's numbers stay distinguishable. Both workflows run unconditionally on every push (javascript.yml has no path filter) so every commit produces the same 5 uploads (2 Python matrix jobs + 3 JS jobs); codecov.yml's after_n_builds: 5 tells Codecov to wait for all of them before finalizing the report — without it, Codecov finalizes as soon as the first couple of uploads land, silently dropping whichever jobs are still running. This requires activating the repo at codecov.io once and adding its upload token as the CODECOV_TOKEN repo secret; after that, opening a pull request's Files changed tab shows uncovered lines flagged inline, right next to the diff — install the Codecov browser extension to get the same green/red coverage gutters on any file on github.com, not just the ones in a diff.

About

Support materials for blog entries

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages