From df63d0f562ae1823e61b19950f9bed66b0b38435 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Sat, 3 Oct 2026 02:18:21 +0200 Subject: [PATCH] Draw a pick's references in the draw group of the read of the name, where the draw fences survey them --- README.md | 5 +++-- docs/decisions.md | 3 ++- draws.go | 17 ++++++----------- name.go | 7 +++---- name_test.go | 16 ---------------- 5 files changed, 14 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 96f071f..5a2ddc2 100644 --- a/README.md +++ b/README.md @@ -711,8 +711,9 @@ row: Renders e.g. `🇳🇴 Norway: capital Oslo, calling code +47`. Everything under a name is drawn once, so `{n}` and `{n.path}` agree, a [transform](#transforms) of `n.path` reads the same value, and a field `n` renders twice prints the same text twice. A name is a pick of its own: -`{t.name}` and `{/misc.territory.name}` beside it are two draws, as are two names bound to one -category. +`{t.name}` and `{/misc.territory.name}` beside it are two draws. A reference path read under a +name draws in the draw group of the read of the name, so give the reads of two names bound to +one category a [draw group](#draw-group) each to draw what it references apart. A name is drawn on its first read, and lives in the category binding it: any field of the category reads it, and a record's columns read one pick. Each render of the category picks diff --git a/docs/decisions.md b/docs/decisions.md index 40bd461..db0f4e0 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -904,4 +904,5 @@ whichever binds it. A read entering a category keeps the frame of each scope it own memo, and the category's root renders that frame when the read lands on the root, so `{n}` and `{n.path}` read one pick: per render and group for a reference path, per pick for a path through a name, and per render for `Fake("cat.field")`. A reference read under a pick -draws in the pick's own draw groups, so two names bound to one category are two picks of it. +draws in the draw group of the read of the name, the group the draw fences survey it in; a pick +with draw groups of its own would draw where no fence looks. diff --git a/draws.go b/draws.go index 38072b4..3695b45 100644 --- a/draws.go +++ b/draws.go @@ -51,10 +51,9 @@ type renderScope struct { entry *drawMemo base int // pick is the named pick what renders is part of, at pickKey, its path from the name; nil - // outside one. refs is the draw groups of the last pick entered, nil before one. + // outside one. pick *namedPick pickKey string - refs *renderDraws } type renderedRow struct { @@ -91,20 +90,16 @@ func (sc renderScope) rowOf(t *table) int { } func (sc renderScope) groupDraws() *groupDraws { - draws := sc.draws - if sc.refs != nil { - draws = sc.refs - } if sc.group == "" { - return &draws.unnamed + return &sc.draws.unnamed } - d, drew := draws.named[sc.group] + d, drew := sc.draws.named[sc.group] if !drew { - if draws.named == nil { - draws.named = map[string]*groupDraws{} + if sc.draws.named == nil { + sc.draws.named = map[string]*groupDraws{} } d = &groupDraws{} - draws.named[strings.Clone(sc.group)] = d + sc.draws.named[strings.Clone(sc.group)] = d } return d } diff --git a/name.go b/name.go index 5f40896..0a841ac 100644 --- a/name.go +++ b/name.go @@ -219,12 +219,12 @@ func linkName(t *template, a *arm) error { } // namedPick is one draw of a name: the variant drawn at each level under it, the value each -// path through it read, keyed by the path from the name, and the table rows they pinned; and the -// draw groups of the references read under it, so two names on one category are two picks of it. +// path through it read, keyed by the path from the name, and the table rows they pinned. A +// reference read under it draws in the draw group of the read of the name, which the draw +// fences survey it in. type namedPick struct { memo drawMemo pins pinSet - refs renderDraws } // pickFrame is one render of a name scope: a pick per binding, each drawn on its first read. @@ -316,7 +316,6 @@ func (sc renderScope) entryMemo() *drawMemo { func readName(s *generatorState, sc renderScope, a arm) readValue { p := sc.pickOf(a.bind) - sc.refs, sc.group = &p.refs, "" return readPicked(s, p, a.bind.head, a.steps, a.levels, a.path, sc.entering(&p.memo)) } diff --git a/name_test.go b/name_test.go index e3a07d7..d664e1f 100644 --- a/name_test.go +++ b/name_test.go @@ -337,19 +337,3 @@ func TestOneRenderReadsOneNameAcrossDrawGroups(t *testing.T) { } } } - -func TestTwoNamesOnOneCategoryAreTwoPicks(t *testing.T) { - dir := writeData(t, map[string]string{ - "given": `{"format":"{first}","first":["Ada","Bo","Cy","Di","Ed","Flo","Gus","Hal"]}`, - "person": `"{/given.first}"`, - "card": `"{/person as p}{/person as q}{p}|{q}"`, - }) - f := newGenerator(t, dir, WithSeed(53)) - for i := 0; i < 50; i++ { - got := strings.Split(fake(t, f, "card"), "|") - if got[0] != got[1] { - return - } - } - t.Fatal("card printed one person for p and q in 50 renders, want two picks") -}