playground: showcase the features it has not heard of, and say which compiler it is - #67
Merged
Conversation
…compiler it is
The playground has not been touched since it shipped, so it advertises the
language as of 0.1.0. Everything from 0.2.0 through 0.5.0 landed after it, and
the docs were updated for it while the playground was not. The gap that matters
most: computation expressions are one of the two F# showcase features this
project leads with, and they had no playground presence at all.
Two examples, both verified by running them through the real compiler:
- **Computation expressions** covers `option { }` (the 0.5.0 built-in), the
`result { }` it mirrors, and `seq { }`, so the picker shows the feature the
front page advertises.
- **Opaque types** covers the zero-cost newtype and, in passing, the
destructuring `let` bindings 0.5.0 added, including the record form.
The page also never said which compiler it had loaded, so a stale deploy was
invisible and a visitor could not tell what they were trying. `pyfun::VERSION`
is now exported from the library, the WASM shim re-exports it, and the footer
shows it. The footer also links back to the course, which every page of the
course links into but which nothing linked back from.
Two real bugs on the way through:
- Diagnostics drifted on any source containing a non-ASCII character. Spans
from Rust are byte offsets and the line/column walk indexed UTF-16 code
units, so one accented character earlier in the buffer moved every later
diagnostic. It now walks the encoded bytes.
- Two internals-tour code blocks always failed their Run button, because they
were fragments quoted mid-prose with no type or measure declaration. Both are
now complete programs, which also fixes the exhaustiveness chapter quoting a
diagnostic at line 4 of a three-line block.
Plus the docs highlighter, which claimed to mirror the VS Code grammar and had
drifted from both it and the lexer: no `option`, no `opaque`, no `as`, and `in`,
which is not a Pyfun keyword.
CI: the Pages build installed whatever wasm-pack was newest that day, the only
unpinned tool in the pipeline, and recompiled the whole compiler for wasm32 on
every deploy. Pinned to 0.15.0 and cached. Pyodide moves to 314.0.3.
Sharing the playground URL produced a bare link with no summary text. The description and the two Open Graph tags are the half of that gap that does not need an image.
The wasm-pack pin and the cargo cache are the only part of this touching a workflow file, and merging a workflow change needs a token scope the CLI does not carry here. Splitting them out lets the playground work land now.
simontreanor
added a commit
that referenced
this pull request
Aug 2, 2026
The Pages workflow installed wasm-pack through the upstream installer script, which takes whatever version is newest that day. It was the one unpinned tool in a pipeline that pins its Rust toolchain and its mdBook, so a wasm-pack release could change a deploy without anything in the repo changing. Pinned to 0.15.0, the version the local builds use. The job also had no cargo cache, so every deploy recompiled the whole compiler for wasm32 from scratch. Split out of #67 because merging a workflow change needs a token scope the CLI here does not carry.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The playground has not been touched since it shipped in #2. Everything from 0.2.0 through 0.5.0 landed after that, and the docs were updated for it while the playground was not, so the picker advertises the language as of 0.1.0.
The gap that matters most: computation expressions are one of the two F# showcase features this project leads with, and they had no playground presence at all. Opaque types (0.2.0) and destructuring
let(0.5.0) were likewise absent.Two new examples
Both were extracted from
app.jsand run through the real compiler, along with the five existing ones (all seven still compile and run):option { }, theresult { }it mirrors, andseq { }Some('Ada is 36')/None_/Ok(7)/Error('not a number')/[1, 2, 3]letincluding the record formu-1001/credits between 7 and 17Which compiler is this?
The page never said, so a stale deploy was invisible and a visitor could not tell what they were trying.
pyfun::VERSIONis now exported from the library (the binary and the LSP each had their ownenv!call), the WASM shim re-exports it asversion(), and the footer shows it. The footer also links back to the course, which every page of the course links into and nothing linked back from.Two real bugs
lineColwalked UTF-16 code units, so a single accented character earlier in the buffer moved the reported line:col of every later diagnostic. It now walks the encoded bytes, counting characters for the column.docs-run.jsattaches Run to everycode.language-pyfunblock, and these two were fragments quoted mid-prose with notype Shape/measure min scope, so clicking Run always producedunknown constructor/unknown measure. Both are now complete programs. That also fixes the exhaustiveness chapter, which quotes a diagnostic at--> 4:3above a three-line block: with the type declaration restored, line 4 is where thematchactually is.Also
The docs highlighter (
docs/theme/highlight.js) says in its own header that it mirrorseditors/vscode/pyfun.tmLanguage.json. It had drifted from both that and the lexer: nooption, noopaque, noas, and it highlightedin, which is not inTok::keywordat all. Lesson 13'soption { }and lesson 22'sopaque typewere rendering unhighlighted on the live site.CI: the Pages build installed whatever wasm-pack was newest that day (the one unpinned tool in a pipeline that otherwise reproduces exactly) and recompiled the whole compiler for wasm32 from scratch on every deploy. Now pinned to 0.15.0, matching the local toolchain, and cached. Pyodide goes to 314.0.3.
Verification
wasm-pack buildsucceeds and exportsversion;node --checkpasses on all three playground modules; every bundled example runs;cargo test,cargo clippy --all-targets -- -D warningsandcargo fmt --checkare clean. I could not click through the rendered page (no browser extension connected here), so the footer version string and picker label are verified by construction rather than by eye.