The spike counted nodes it could do. This counts nodes a real input
actually contains, after Reach prunes, which is the question that decides
whether whole-program coverage is reachable.
The answer is worse than the spike's four buckets suggested: enum-compare
needs Str, Make, Field and Call before it prints anything, because the
prelude builds a slice to print one. And loops.flan carries Handled,
RestartCase and Signal one each -- conditions are not an advanced feature
to defer, they are in the reachable set of a program that only loops.
The prelude's own (vec-new Form) was refused with "nothing here says what
(vec-new) is a Vec of" -- a message about a missing annotation, to a program
that had written one. The build went red the moment the Form declaration was
checked against anything, which is why the front half landed unmeasured.
The test a leading bare symbol has to pass was spelled out twice, once in
vec_new_elem and once in map_new_types, and both lists were written before
unions existed: primitives, structs, enums, aliases. resolve_name has known
about unions since they landed, so the two halves disagreed about what a type
name is. Now there is one list, read by both, so the next kind of type cannot
be added to one of them.
The case is in unions.flan rather than in a file of its own, because what it
asserts is that a union is an element type like any other -- (vec-new Shape),
(map-new string Shape) -- and that is a sentence about unions.
Also drops forms.so, a build artefact the last lane committed.
They were committed by a git add -A taken after running the program by
hand from the source tree. The suite runs it out of _build and cleans up
after itself; this is only for a run done directly.
No emscripten port provides raylib — emcc --show-ports offers contrib.glfw3
and nothing else nearby — so build-web.sh clones raylib at the 5.5 tag and
compiles its seven modules with -DPLATFORM_WEB -DGRAPHICS_API_OPENGL_ES2 into
one archive under vendor/raylib/web, which is gitignored along with the
checkout it came from.
5.5 because that is the tag whose .so.550 the host links. raylib.flan carries
raylib's struct layouts and enum values, and two targets built from different
raylibs would disagree about them without saying so.
rglfw.c is not among the modules: the web platform uses emscripten's own GLFW
port, which is why link carries @web -sUSE_GLFW=3. No headers are installed,
for the same reason the host build needs none — the generated shim declares
the prototypes it uses.
link now names the host library under @native and the archive under @web,
through ${FLAN_RAYLIB_WEB}, so a web build with the variable unset is refused
with the name of the variable rather than a page of undefined GLFW symbols.
The one thing this costs: a wasi build that reaches raylib now fails on
undefined symbols instead of on the missing -l:libraylib.so.550.
Audio, render textures, fonts, gamepads, touch and gestures were all
absent, and a game cannot ship without the first of them. Fonts were
refused by name last time because a Font drags in two more aggregates
and two owned arrays with nothing headless to check them against; the
generator takes all of it unchanged now, and the check turned out to
exist — raylib measures text with pure CPU arithmetic over every field.
SetGamepadVibration stays unbound for two reasons at once: its arity
differs between the 5.1 and 6.1 headers with no 5.5 header to settle
it, and the symbol in libraylib.so.550 disassembles to a TraceLog stub
that touches no motor.
The extern-boundary refusal and a restart-case one each had a run of spaces
mid-sentence where an OCaml line continuation had been lost. The textures lane
found the first while reading the FFI rules; the second was mine, from the same
editing mistake in the same week.
The restart-case one turned out to be unreachable as well. Each clause is
checked with the type the form has already settled on, so a clause that
disagrees is refused by expect where it is written - the dedicated message
could only have fired if that check did not, and it does. Removed rather than
reworded; a message nothing can produce is worse than no message, because the
next person tries to work out what reaches it.
conditions.org is how to drive what is built, as against spec-conditions.md
which is what it should mean and NEXT.md which is why it is shaped that way.
Every refusal message in it is verbatim rather than paraphrased, because the
reason is the thing worth knowing and a remembered approximation of it is how a
cheatsheet starts lying.
conditions-play.flan is the program to poke at. It loops rather than exiting so
flan dev can attach to it, and it is deliberately two frames deep with a defer
in the middle, so that redefining probe or fetch from Emacs and watching the
next pass through run-once shows the transfer crossing something.
It also carries the two gotchas that are not in any spec or message: a handler
closes over nothing, and invoking a restart re-runs whatever sits between it
and the target - which is what "restarts go at the resync point" is actually
about.