Commit Graph

32 Commits

Author SHA1 Message Date
lilleman c5c06375d8 Reject a repeated bare token of a held name, naming the single-token spelling
Tests / vet + fmt + tests (pull_request) Successful in 53s
2026-09-02 18:21:03 +02:00
lilleman 31c2f12098 Hold a reference path like a sibling path; add the lowercase, uppercase and ascii transforms 2026-09-02 12:52:19 +02:00
lilleman ff4b243148 Format text is literal; class runs are {digits(n)} {upper(n)} {lower(n)}; a string is a format 2026-09-02 12:37:21 +02:00
lilleman 05dc042e49 Rename the project to fejkdata and record the fork source
Tests / vet + fmt + tests (pull_request) Failing after 6s
2026-09-01 20:24:03 +02:00
M 64a0d29496 Say why an empty name is rejected, and finish what that removed
Tests / vet + fmt + tests (push) Failing after 42s
The reason given was wrong. A dot path did reach an empty-named field:
Fake("a.") returned it, Fake("a.b.") returned a nested one, and {..a.} bound
it. What was true is narrower — List never offered it, because an empty name
is no path segment — so the engine accepted spellings it would not advertise.
The message, the test comment and the README say that instead.

Two things the rejection finished off:

A {} token still reported "no field \"\"", pointing at a fix the loader now
rejects — two errors for one rule. It is told the name can never exist, like
an option token already is.

addressable is dead: both halves of "not empty and no dot" are now rejected
where a name is authored. Mutating it to panic leaves the suite green here
and panics on main, so it was live and is not. Keeping it would preserve the
silent-hiding this change removes — List quietly omitting a name rather than
New refusing it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-01 07:31:18 +02:00
M 909596ec2d Trim comments that restate or argue
The operand order was written out in three places; it now lives at calcVars,
which fixes it, and the other two point there. Dropped the note explaining
why ')' is not reserved, which said what the set is not rather than what it
is, and shortened reservedList's doc to less than its body. The note on held
now states where it reaches instead of arguing against a design this repo no
longer contains.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 258bce3b98 Let a clearer token error win over the repeated-arm check
The dedup now runs after the per-arm loop, so a missing reference path or a
missing field is reported as itself. A repeated reference arm is still
caught: the loop lets a well-formed reference through without erroring, and
the dedup reads the arms as written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 9ed0d3bf55 Hold a calc operand's draw for the expansion
A field the format rendered and a calc read was drawn twice, so the operand
shown could differ from the operand computed — the same disagreement the
dotted-path rule already fences, in its plainest spelling. The README
carried it as a caveat, which is what a rule like this exists to remove.

A calc operand now joins the names an expansion holds, so it is drawn once
and every later read of it — the calc, and any bare token spelling it —
sees that draw. The hold stays per expansion: each repeat iteration and each
nested template draws its own.

expand reads a calc's operands before the call and hands over their values,
so a builtin takes (emitted, operands) rather than the sibling fields, and
the evaluator indexes that slice instead of walking the node tree. That is
what keeps the draws a local. Handing them to a builtin instead lets them
escape through an indirect call, which put two maps on the heap for every
held format, calc or not: BenchmarkBound went 56 B/5 allocs -> 744 B/10.

Measured against main: Bound 359 -> 349 ns at 56 B/5 allocs, unchanged;
Calc 416 -> 577 ns and one more alloc, which is what the correlation costs.

Validation is unchanged: t.bound still carries only the levels a dotted
token reads, so the overlap fences fence exactly what they did.

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 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 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 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 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 f7165274c7 Accept one spelling per draw, and reject 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 f512c1663d Hold a path's draw at every level it passes through 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 16f91503b0 Reject a standalone weight on key presence, whatever its value 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
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 5b6480a094 Updates from reviewers 2026-06-09 10:03:53 +02:00
lilleman cee2f35a2c Add {calc()}: arithmetic over number literals and sibling fields 2026-06-09 07:59:29 +02:00
lilleman cde56b7924 Add session-scoped seq() builtin; move uuid v4 from locales to misc only 2026-06-09 01:52:39 +02:00
lilleman ae41e6bb97 Add ID/checksum/numeric builtins and a misc data folder (uuid v4, mac, creditcard) 2026-06-09 01:25:41 +02:00
lilleman 18de1b7004 Add {..path} references: render a node from elsewhere in the merged data root 2026-06-09 00:11:17 +02:00
lilleman 8db65ac598 Replace locale dirs with a data-folder namespace model: New([]paths), folder dot-paths, last-wins merge 2026-06-08 23:52:37 +02:00
lilleman acf7571334 Stuff 2026-06-08 23:35:51 +02:00
lilleman 3e1cd3ee2a Add repeat/separator templates; validate at compile time; support Go 1.22+ via GO_VERSION 2026-06-08 21:11:58 +02:00
lilleman 943a1d9f1b Add fakes library: recursive JSON template engine, i18n locales, Docker workflow 2026-06-05 19:51:18 +02:00