Hold only an expansion's names in formatOps.held, deleting keepsHold

This commit is contained in:
2026-09-29 16:18:13 +02:00
committed by Lillem4n
parent 14952d0c06
commit dee1e186e3
5 changed files with 13 additions and 19 deletions
+2 -1
View File
@@ -25,7 +25,8 @@ package fejkdata
// iteration of a `template.repeat`.
// - hold — keeping one draw of a name, so every route to it reads that value:
// an expansion holds a sibling path's head and an operand's field, its draw
// group a reference path's: `formatOps.held`, `formatOps.keepsHold`, `heldCheck`.
// group a reference path's: `formatOps.held` and `heldCheck` an expansion's,
// `readReference` a draw group's.
// - memo — what a hold or a draw group keeps its draws in, the variant drawn at
// each level and the value each path read: `drawMemo`, `readMemo`.
// - draw group — reference draws kept apart inside one render:
+5 -5
View File
@@ -381,12 +381,12 @@ type op struct {
}
// formatOps is a compiled format: its ops, the size of its literal text, and the
// names it holds: every head a path starts from, plus the fields an operand reads.
// names its expansion holds: every head a path that is not a reference starts from,
// plus the fields an operand reads.
type formatOps struct {
ops []op
grow int
held map[string]firstReach
keepsHold bool // some held name is not a reference path, so expand makes a hold
}
// firstReach is how a format first reaches a held name: the reader holding it, for
@@ -397,12 +397,12 @@ type firstReach struct {
}
func (c *formatOps) holdName(a arm, label string) {
if isRef(a.head) && len(a.tail) > 0 {
return
}
if c.held == nil {
c.held = map[string]firstReach{}
}
if !isRef(a.head) || len(a.tail) == 0 {
c.keepsHold = true
}
h, seen := c.held[a.head]
if !seen {
h.holder = label
+2 -5
View File
@@ -17,9 +17,6 @@ func heldCheck(path string, n node) error {
}
readers := pathHeadReaders(t.compiled)
for _, name := range heldNames(t) {
if t.compiled.held[name].path != "" && isRef(name) {
continue // held for the render: drawFence compares every read of it, by path, across the render and its groups
}
if err := checkNameHeld(t, name, readers); err != nil {
return fmt.Errorf("%s: %w", path, err)
}
@@ -201,12 +198,12 @@ func pathHeadReaders(c formatOps) []reader {
var names []reader
for _, o := range c.ops {
for _, a := range o.operands {
if c.held[a.head].path != "" && !isRef(a.head) {
if c.held[a.head].path != "" {
names = append(names, reader{a, fmt.Sprintf("%s operand %q", o.fn, a.spelling)})
}
}
for _, a := range o.arms {
if c.held[a.head].path != "" && !isRef(a.head) {
if c.held[a.head].path != "" {
names = append(names, reader{a, "token {" + a.spelling + "}"})
}
}
+1 -1
View File
@@ -121,7 +121,7 @@ func expand(s *generatorState, t *template, sc renderScope) string {
// repeat iteration get their own, since each is its own expansion. A reference
// path reads its draw group's memo in sc instead.
var hold *drawMemo
if t.compiled.keepsHold {
if len(t.compiled.held) > 0 {
hold = &drawMemo{
variant: make(map[string]node, len(t.compiled.held)),
value: make(map[string]readValue, len(t.compiled.held)),
-4
View File
@@ -37,10 +37,6 @@ on 2026-09-29 a fifth time (Navigation 6.9, Locality 5.2, Shape 6.1, Self-suffic
This round, in order:
- Split `formatOps.held` into the names an expansion holds and the reference paths a
render's draws hold, deleting `keepsHold` and `heldCheck`'s skip of a reference path:
one map carries both, told apart by `isRef` and `firstReach.path == ""`, and six seats
hunted for which fence owns which.
- Give `surveyAt`'s whole read one field, its table and pins together, rename
`alternatives` for what it answers, two reads that never render together, and say at
`check` why a level landing on a row may sit beside a path into it: five seats held