The queue records item 7's review pass: the or fix, and two things left alone

FIX.org's item 7 gets the full account of the review that followed
landing: or's fix (ad0f1fb), named there rather than left as "review
pass"; the keyword-condition diagnostic given up on purpose, the
author's call; and the exponential retry on a chain of nested not that
does not type-check, looked at and left alone since a cheaper retry
would cost message fidelity on a compound condition wrapping a literal,
not just speed.
This commit is contained in:
Joseph Ferano 2026-09-20 09:56:53 +07:00
parent ad0f1fbd6a
commit b5f17826fe

46
FIX.org
View File

@ -436,18 +436,46 @@ rename. typed-flan branch freezes the static language pre-dyn.
6. defclass = named dyn map + shape tag; CLOS class dispatch AND
Clojure-style arbitrary dispatch functions. After 1.
7. dyn if: truthiness (nil/false are false, all else true). Typed stays
strict bool. — LANDED, a94efcc
strict bool. — LANDED, 264765a
Reaches when, cond, if's own condition, and's condition, or's
condition, not and while for free or by hand, all through one funnel
in check.ml (check_truthy). One thing fell out of it that nobody had
decided: and's answer position already carries a non-bool dyn value
through, Clojure-style, because its short-circuit sentinel is the else
arm and the real value's type wins; or's sentinel is the then arm
instead, so it is what decides the whole expression's type, and or's
answer stays a strict bool. Reordering or to match and is a real fix
and nobody's called it yet — left alone, noted in parse.ml at
shortcircuit.
in check.ml (check_truthy). Two things fell out of it that nobody had
decided going in, one fixed on review and one left as the author's
call:
- or's answer used to stay a strict bool where and's already carried a
non-bool dyn value through, Clojure-style — and's short-circuit
sentinel sits in the else arm, so the real value's type wins there,
but or's sat in the then arm, the one check_if types first, so it
decided the whole expression's type and a later non-bool dyn answer
hit the strict bool boundary and trapped. (or nil "x"), the
canonical (or x default) idiom, crashed rather than answering "x".
FIXED, ad0f1fb: or now binds its test to a temp and answers the
temp, Clojure's own expansion, evaluating the test once and handing
back whichever operand actually decided it.
- A bare keyword condition used to be checked with want:Bool from the
start and refused by the keyword arm's enum-or-refuse case: ":kw is
an enum member where an enum is expected and a dyn keyword
elsewhere, but bool is expected here", there being no enum in play.
Checked with no expectation first, as every scrutinee now is, it
resolves as the dyn keyword instead, and a dyn keyword is
unconditionally truthy — a typed if with a bare keyword condition
now compiles and always takes the then branch. The author's call:
lispy truthiness wins here, the lost diagnostic is not brought back.
Pinned in test_flan.ml so it does not regress by accident.
Also noted at check_truthy (check.ml) and not acted on: check_truthy's
own retry-on-failure, needed to keep a refused literal's or None's
message unchanged, re-runs the whole failing subtree rather than only
the leaf that needs it, which is exponential in how deep a chain of
nested not gets on a program that does not type-check. Moot for
anything that compiles; visible only around twenty levels deep, and
only the dev daemon's half-typed-form recompiles could ever feel it.
A cheaper retry was tried and shelved — it would need to thread want
exactly as far as the full retry already does, or it changes which
literal further inside a compound condition gets the nicer message,
not just the speed.
8. Return slot stays mandatory (dyn or ()) — the parse ambiguity it closes
is real; revisit only if it grates. SETTLED 2026-09-19, reconfirmed with
the author: both spellings stay legal, () is not collapsing into dyn.