Commit Graph

178 Commits

Author SHA1 Message Date
M 4f87a4dd9e Tests for a calc operand reading the expansion's draw
A field the format renders and a calc reads is drawn twice today, so
"{net} x {qty} = {calc(net * qty, 2)}" can print a net that is not the net
it multiplied. The dotted-path rule already holds one draw for a level;
these pin the same hold for a plain sibling a calc reads.

Also pinned: the hold reaches a bare token of the same name, belongs to one
expansion (each repeat iteration and each nested template draws its own),
and leaves a name no calc reads drawing every time.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 13:33:05 +02:00
M b09bc56e87 Reject a repeated alternation arm
An alternation picks its arms evenly, so {a|a|b} was a covert 3:1 skew — a
third spelling of what a choice's weight is for, reachable only by
experiment. The check runs over the arms as written, before a reference arm
is let through, so {..a|..a} is caught too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 13:33:05 +02:00
M cc76d300e7 Tests for a repeated alternation arm
{a|a|b} skews an alternation three to one, an undocumented third way to
weight beside a choice's weight and a repeated choice entry. These pin its
rejection, and one accepted case fixes the boundary: {x}{x} is two tokens,
so it stays two independent draws.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 13:33:05 +02:00
M b7c854f2d4 Reject a name the token grammar reserves
The dot rule was spelled twice — once for a category or folder, once for a
field — and covered only the dot. Both now go through checkName, which
rejects the four characters no format can name: . | ( and }.

')' stays legal: on its own it is spellable, and rejecting it would refuse a
name that works.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 13:33:05 +02:00
M cc8f8db83f Tests for a name no token can spell
A dot is already rejected in a category, folder or field name. The token
grammar reserves three more characters: '|' separates a token's arms, '('
opens a function call, and '}' ends the token. A name carrying one resolves
by dot path and is advertised by List, yet no format can name it.

These pin the rejection, and one accepted case fixes the boundary: ')' on
its own is spellable, so it stays legal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 13:33:05 +02:00
M 403d68de27 Write every builtin one way
A builtin could be spelled as prep (args parsed once, at compile) or call
(args parsed per render), reaching the same closure by two routes. Nothing
enforced the "exactly one of" invariant: supplying both silently dropped
call, supplying neither compiled and then panicked inside a render, and a
test existed only to police it.

prep does everything call did, so it is now the one spelling. The zero-arg
shapes the README already names — a derivation reads the output emitted so
far, a generator reads only the rng — lift through derive and generate, so
the registry reads as that taxonomy. iban stops looking its country up per
render.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 13:33:05 +02:00
M 24084fc0cf List every node's children one way
authored and named differed only in whether a "..path" binding was skipped,
which made two spellings of one question: what does this node contain? They
could never disagree — loadDir rejects a category or folder carrying the
prefix, so a group's children are never bindings, and TestReferenceErrors
pins both rejections.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 13:33:05 +02:00
M 5a69b02ee0 Find a format's bound readers in one ordered scan 2026-08-30 22:31:54 +02:00
M c1222eaf72 Label the error fences, and settle a tie by where the format writes it 2026-08-30 22:31:54 +02:00
M 4a1073f018 Test that a path reaches every variant it might draw 2026-08-30 22:31:54 +02:00
M 32b9aa5c81 Aim a path token's render edge at what it renders 2026-08-30 22:31:54 +02:00
M 1987deb14c Tests for a path token rendering its leaf, not the level it starts from 2026-08-30 22:31:54 +02:00
M 447cfae50a Hold a bound level against every route that renders it, and let a matching string be 2026-08-30 22:31:54 +02:00
M c755d085a9 Tests for a reference reaching a bound level from anywhere, and a literal that merely matches 2026-08-30 22:31:54 +02:00
M 3ebaa5958d Close the calc and reference spellings of an overlap, and reach the repeat rule behind a choice 2026-08-30 22:31:54 +02:00
M 9b5e34332b Tests for overlap via calc and references, repeat behind a choice, and nested choice draws 2026-08-30 22:31:54 +02:00
M f7165274c7 Accept one spelling per draw, and reject a path into a repeating level 2026-08-30 22:31:54 +02:00
M 97ecbe208f Tests for one spelling per draw, and a path into a repeating level 2026-08-30 22:31:54 +02:00
M e05fed1190 Hold a path's last level too, and reject an unfinished path 2026-08-30 22:31:54 +02:00
M 8accca54b1 Tests for a path sharing its prefix's draw and rejecting an empty segment 2026-08-30 22:31:54 +02:00
M e4b37091e4 Say that a path is held at every level 2026-08-30 22:31:54 +02:00
M f512c1663d Hold a path's draw at every level it passes through 2026-08-30 22:31:54 +02:00
M eb0c5dc066 Tests for a path holding its draw at every level 2026-08-30 22:31:54 +02:00
M 644f3ed9d9 Benchmark what a bound draw costs 2026-08-30 22:31:54 +02:00
M b8da6fdbc0 See a path token's head when walking for cycles 2026-08-30 22:31:54 +02:00
M d7c4f43135 Document the path token and the one-draw rule 2026-08-30 22:31:54 +02:00
M a25b42ace2 Read one value when a bound path is read twice 2026-08-30 22:31:54 +02:00
M 12100239f5 Draw a dotted token's head once per expansion 2026-08-30 22:31:54 +02:00
M 5263c866c4 Tests for a dotted sibling token drawing its head once per expansion 2026-08-30 22:31:54 +02:00
Mikael Göransson e371d217f4 Say what the objectid category actually is, and re-flow the registry comment 2026-08-28 13:35:12 +02:00
lilleman 43d3a752b3 Retire the objectid builtin; ship it as data instead 2026-08-28 13:35:12 +02:00
lilleman c11ae5f04f Expect objectid as a data category rather than a builtin 2026-08-28 13:35:12 +02:00
M 16f91503b0 Reject a standalone weight on key presence, whatever its value 2026-08-28 13:27:32 +02:00
M 48cadd6c4d Tests that a standalone weight of any type is rejected 2026-08-28 13:27:32 +02:00
M b14caae3a8 Reject options that cannot take effect, and skip entries that are not data 2026-08-28 13:27:32 +02:00
M 8d0393713c Tests for options that cannot take effect, and entries that are not data 2026-08-28 13:27:32 +02:00
lilleman af09a86e71 Express hex-shaped data with the hex() builtin instead of a hand-rolled choice 2026-08-28 13:25:41 +02:00
M aec0497ce5 Say what the triple-letter test and the escape rule actually cover 2026-08-28 13:24:07 +02:00
M 630f75f556 Remove the duplicated Vasa street prefix 2026-08-28 13:24:07 +02:00
Mikael Göransson e73cb398ac Keep every legal compound surname reachable, and tighten the README wording 2026-08-28 13:24:07 +02:00
lilleman cd25aea6f1 Correct the format-string example, and stop Swedish name data composing a triple letter 2026-08-28 13:24:07 +02:00
lilleman 404650ecc2 Test that shipped Swedish name data never composes a triple letter 2026-08-28 13:24:07 +02:00
Mikael Göransson 37759f773f Pin the builtin registry shape and grow as a lower bound, and correct stale comments 2026-08-28 13:20:07 +02:00
lilleman ab9846c2ff Compile format strings at New instead of re-scanning them on every render 2026-08-28 13:20:07 +02:00
lilleman 5282f37a59 Golden test pinning the seeded output of each part of the token grammar 2026-08-28 13:20:07 +02:00
Mikael Göransson 362c484825 Advertise only spellable paths, and name what a choice's variants share 2026-08-28 13:15:14 +02:00
Mikael Göransson 595809bf38 Tests for an ambiguous dot-path key and for naming a missing field 2026-08-28 13:15:14 +02:00
Mikael Göransson 1665b37cad Precompute each choice's shared paths so a dotted path stays O(1) 2026-08-28 13:15:14 +02:00
lilleman af5b8c9abd Require every choice variant to carry a path, and list only what Fake accepts 2026-08-28 13:15:14 +02:00
lilleman 7d5d03e393 Tests for the every-arm rule on paths through a choice, and the List/Fake contract 2026-08-28 13:15:14 +02:00