Two comments the sweep could not reach, and a handoff note that was wrong

check.ml's prose carried struct literals in the old spelling in two
comments the form-level scan does not see, OCaml comments not being forms.

The Emacs handoff said MANUAL.md and flan-mode.el's font-lock still show
the colon. MANUAL.md does not mention a struct literal at all. font-lock
does have something, but it is the opposite of what was written: it colours
:name as a constant and has no rule for .name, so a field label is now
unfontified rather than wrongly coloured. Said accurately, with the line.

runtime/flan_rt.c:256 also shows {:name ...} and is left alone on purpose --
it describes the *printed* form, which still uses colons and is correct.
This commit is contained in:
Joseph Ferano 2026-09-12 15:03:35 +07:00
parent e992491799
commit 73fb16bfa3
3 changed files with 11 additions and 9 deletions

View File

@ -2073,7 +2073,7 @@ rule here is that what is not supported is rejected explicitly with the reason.
reason, on the construction side and on the destructuring side, which is what stops the colon drifting back.
**The sweep is a tool, not a one-off.** `tools/colon-to-dot.py` converted 681 labels across 45 `.flan` files,
`vendor/`, and the Flan embedded in `lib/prelude.ml` and the tests. It works on *forms*, not on text: a keyword
`vendor/` included, and 94 more in the Flan embedded in `lib/prelude.ml` and the tests. It works on *forms*, not on text: a keyword
becomes a dot only where it sits in a field-label position inside a brace, so an enum member in value position
(`{.k :hi}`), a genuine EDN map inside a string (`test/programs/edn.flan`), and a type-position `{K V}` are all left
alone. It was kept in the tree because several lanes branched before it and their Flan needs the same pass at merge.

14
NEXT.md
View File

@ -280,13 +280,15 @@ length is not known until the file is read and therefore cannot exist before an
~~**6. A field label is written with a dot, not a colon, and the colon is reserved for keys.**~~ **Done.**
`{.x 1.0 .y 2.0}` is struct construction and `{inner .field}` is destructuring; the old spelling is refused, and the
refusal names the new one. `:keys` kept its colon — it names no field, so leaving it alone is what lets the dot mean
exactly one thing. 681 labels across 45 `.flan` files, `vendor/` and the Flan embedded in `lib/prelude.ml` and the
tests. `Map` is now free to take `{:key value}` without colliding with struct literals. See BUILT.md, "The colon
belongs to keys".
exactly one thing. 681 labels across 45 `.flan` files including `vendor/`, plus 94 more in the Flan embedded in
`lib/prelude.ml` and the tests. `Map` is now free to take `{:key value}` without colliding with struct literals. See
BUILT.md, "The colon belongs to keys".
**Two things it left behind.** `render.ml` still *prints* a struct with colons, deliberately:
`emacs/flan-inspect.el:165` parses that output and hard-codes the colon, so the printer has to move with its reader
and that belongs to the Emacs lane. `emacs/MANUAL.md` and `flan-mode.el`'s font-lock also still show the colon.
**What it left for the Emacs lane, both verified.** `render.ml` still *prints* a struct with colons, deliberately:
`emacs/flan-inspect.el:165` parses that output and hard-codes the colon when it reads a field out, so the printer
has to move in the same commit as its reader. And `flan-mode.el:61` font-locks `:name` as a constant with nothing
matching `.name`, so a field label is now unfontified where it used to be coloured. Neither is urgent; both belong
with whoever next opens `emacs/`.
**7. `Map` follows Odin's implementation.** Read `base/runtime/dynamic_map_internal.odin` before writing any of it;
the checkout is at `~/Repositories/Odin`. Three properties are the ones worth copying, and they are stated in its own

View File

@ -1384,7 +1384,7 @@ and fold_left_prim ctx ~want loc name p ok what args =
No allocating operation returns an error and none can fail silently. When
the allocator cannot satisfy a request the operation signals
(StorageExhausted {:bytes n :align a :allocator id})
(StorageExhausted {.bytes n .align a .allocator id})
with [error] whose type is Never inside a [restart-case] offering
[retry]. That is one rule over every allocating operation, which is what
@ -2309,7 +2309,7 @@ and named_call ctx ~want loc name args =
1. It does NOT check UTF-8, because `string` does not claim UTF-8. The
prelude settles this: valid-utf8? is an ordinary function you call when
you care, decode-rune/rune-at/rune-count all take [u8] rather than
string, and decode-rune answers {:ok false :width 1} on a malformed
string, and decode-rune answers {.ok false .width 1} on a malformed
byte rather than assuming its input is well-formed. The one place the
runtime treats a string differently from a byte slice is
flan_escape_bytes, for a string nested in a printed structure, and that