Record the repeat cap's reach, 64-bit only, the constant-divisor rule and the rejected default spellings; correct the repeat cap comment
Tests / vet + fmt + tests (pull_request) Successful in 58s

This commit is contained in:
2026-09-02 19:09:50 +02:00
parent 08c7ef9b7f
commit c5304bb6e7
2 changed files with 17 additions and 1 deletions
+16
View File
@@ -382,6 +382,22 @@ tokens add cost in proportion to the output.
when that file lacks a field those references read. Accepted: overriding is the when that file lacks a field those references read. Accepted: overriding is the
point of layering, the error names the reference and the field, and the fix is point of layering, the error names the reference and the field, and the fix is
the consumer's file carrying the fields the shipped tree reads. the consumer's file carrying the fields the shipped tree reads.
- **The repeat cap bounds renders, not bytes.** A repeat, alone or nested, may
ask for at most 1 048 576 renders; how large each render is stays what the data
asked for, so `{hex(1048576)}` repeated to the cap is a terabyte, loaded without
complaint. A byte estimate would need every builtin to declare a width to fence
a shape no data comes near, and the harm lands on the author who wrote it.
- **64-bit targets only.** The gate builds amd64, and the buffer sizing a render
pre-computes (renders × bytes) assumes a 64-bit int; on a 32-bit target it could
overflow and panic.
- **A constant zero divisor is a load error; a sometimes-zero one prints `Inf`.**
`1/0` and a fixed `"0"` field are decidable, so they join the never-numeric
operand as a load error; a divisor that is only sometimes zero is data, and
`Inf` printing visibly is the never-fail rule.
- **A default written out, and a constant spelled as a sample, are load errors.**
`weight: 1`, `repeat: 1`, `separator: ""`, `int(5,5)`, `float(1,1,2)`, `+5`
and `05` each spell what a shorter form already spells, so each is rejected
naming that form.
- **Samples say what they emit, transforms what they do.** `{upper(2)}` is two - **Samples say what they emit, transforms what they do.** `{upper(2)}` is two
letters, `{uppercase(x)}` is `x` upper-cased; one name for both would turn on letters, `{uppercase(x)}` is `x` upper-cased; one name for both would turn on
whether the argument looks like a number. whether the argument looks like a number.
+1 -1
View File
@@ -288,7 +288,7 @@ func repeatOf(m map[string]any) (int, error) {
if r == 1 { if r == 1 {
return 0, fmt.Errorf("repeat 1 is the default, so it has no effect; drop it") return 0, fmt.Errorf("repeat 1 is the default, so it has no effect; drop it")
} }
if r > maxLen { // cap so a fat-fingered repeat can't build a multi-GB string if r > maxLen { // caps the renders one repeat asks for; checkRepeatReach bounds what nested ones multiply to
return 0, fmt.Errorf("repeat %v exceeds the maximum %d", rv, maxLen) return 0, fmt.Errorf("repeat %v exceeds the maximum %d", rv, maxLen)
} }
return int(r), nil return int(r), nil