Commit Graph

17 Commits

Author SHA1 Message Date
M 39d59aec23 Pin the prep-time guards, and say why an operand's set is the narrow one
The guards report an invariant break instead of computing around it, and no
data reaches them, so they are called directly: coverage 97.4% -> 97.7%,
which also covers the empty-cover skip through a literal operand.

operandDraw's doc keeps why neither wider set works, since both were tried
here — containment reaches a sibling the operand never renders, the render
closure reaches a source two operands share — and drops the rest.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 027d5c33fc Name a calc operand as one when the fence reports it
A renderEdge label can be an operand name, and both messages printed it as
{name} — so an author was told a token renders the level when no such token
existed in the format. An edge now carries whether its label is an operand and
names itself the way boundReaders does, so both fences speak one language.

The narrowed operand cover fixed the other half: the render closure pulled the
other operand into the cover, which could report the two sides the wrong way
round ({n} renders "m" where it is m that reaches n).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 7e073462c8 Document the fence a calc operand gets, and trim two comments
The one-spelling section described a calc operand only as a route that
renders a level, so a reader could not predict that {..cat.net} beside
{calc(net * 2, 2)} is now a load error with no path token in sight. It says
so, and says what an operand's draw covers and what it leaves free.

Dropped the paragraph in checkBoundLevelsHeld that restated its own first
line and the loop below it, and the escape-analysis note in expand.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 2e187117f8 Cover a calc operand by what it renders
The fence now asks the right question for each kind of hold. A path head keeps
containment, since a path may read into anything the level carries. An operand
head takes the render closure, because a calc renders its field and that draw
fixes only the value the render produces.

That stops rejecting a reference to a sibling the operand never renders, which
had loaded fine before the fence widened, and starts rejecting a reference
that reaches what the operand renders through. A head whose cover is empty —
a fixed string — skips the walk.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 2dbc9b1f9f Drop the unreachable reference-prefix checks
A name starting with ".." also starts with ".", so loadDir's hidden-entry
skip reaches it first and neither isRef branch could ever fire. Removed, and
the comment in named now names the skip that actually holds the invariant it
depends on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +02:00
M 465eb05704 Fence a calc operand against every route that renders it
checkBoundLevelsHeld already performed the right walk; it iterated the wrong
set. Walking t.held covers both kinds of hold — the level a dotted token
reads and the sibling a calc reads — so the guarantee the README states now
holds for every spelling of the operand, not just the bare one.

The path message is unchanged. A calc-only head gets its own, naming the
sibling spelling that reads the held draw.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-31 21:58:37 +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 32b9aa5c81 Aim a path token's render edge at what it renders 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 b8da6fdbc0 See a path token's head when walking for cycles 2026-08-30 22:31:54 +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
Mikael Göransson 2d8fcae4f4 Reject a folder using the reference prefix, and filter bindings only where they exist 2026-08-28 12:59:28 +02:00
Mikael Göransson e14f3a4145 Reserve the reference prefix in authored names, and report one compile error 2026-08-28 12:59:28 +02:00
lilleman f03825671e Report the canonical node path in load errors 2026-08-28 12:59:28 +02:00
lilleman f526441e30 Reject reference cycles in unrendered fields, and make New errors deterministic 2026-08-28 12:59:28 +02:00
lilleman 5b6480a094 Updates from reviewers 2026-06-09 10:03:53 +02:00