Skip to content

playground: showcase the features it has not heard of, and say which compiler it is - #67

Merged
simontreanor merged 3 commits into
mainfrom
docs/playground-0.5.0
Aug 2, 2026
Merged

playground: showcase the features it has not heard of, and say which compiler it is#67
simontreanor merged 3 commits into
mainfrom
docs/playground-0.5.0

Conversation

@simontreanor

Copy link
Copy Markdown
Owner

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.js and run through the real compiler, along with the five existing ones (all seven still compile and run):

# Example Output
1 Computation expressionsoption { }, the result { } it mirrors, and seq { } Some('Ada is 36') / None_ / Ok(7) / Error('not a number') / [1, 2, 3]
2 Opaque types — the zero-cost newtype, plus destructuring let including the record form u-1001 / credits between 7 and 17

Which compiler is this?

The page never said, 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 binary and the LSP each had their own env! call), the WASM shim re-exports it as version(), 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

  • Diagnostics drifted on non-ASCII source. Spans from Rust are byte offsets; lineCol walked 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.
  • Two internals-tour blocks always failed their Run button. docs-run.js attaches Run to every code.language-pyfun block, and these two were fragments quoted mid-prose with no type Shape / measure m in scope, so clicking Run always produced unknown constructor / unknown measure. Both are now complete programs. That also fixes the exhaustiveness chapter, which quotes a diagnostic at --> 4:3 above a three-line block: with the type declaration restored, line 4 is where the match actually is.

Also

The docs highlighter (docs/theme/highlight.js) says in its own header that it mirrors editors/vscode/pyfun.tmLanguage.json. It had drifted from both that and the lexer: no option, no opaque, no as, and it highlighted in, which is not in Tok::keyword at all. Lesson 13's option { } and lesson 22's opaque type were 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 build succeeds and exports version; node --check passes on all three playground modules; every bundled example runs; cargo test, cargo clippy --all-targets -- -D warnings and cargo fmt --check are 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.

…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
simontreanor merged commit 8852bd5 into main Aug 2, 2026
15 checks passed
@simontreanor
simontreanor deleted the docs/playground-0.5.0 branch August 2, 2026 22:09
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.
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.

1 participant