diff --git a/format.go b/format.go index ab0e60f..3f724fc 100644 --- a/format.go +++ b/format.go @@ -246,7 +246,7 @@ func pathArm(name, head, writtenHead string, segs []string) arm { return arm{spelling: name, head: head, writtenHead: writtenHead, tail: segs, levels: levelKeys(append([]string{head}, segs...), 1)} } -// levelKeys keys each prefix of path, from its first from segments to the whole of it. +// levelKeys is the key of each prefix of path holding at least from segments, shortest first. func levelKeys(path []string, from int) []pickKey { levels := make([]pickKey, len(path)-from+1) for i := range levels { diff --git a/perf_test.go b/perf_test.go index a88314e..ea7a144 100644 --- a/perf_test.go +++ b/perf_test.go @@ -64,7 +64,7 @@ func TestNoReferenceAllocRegression(t *testing.T) { }{ {"a repeat of a reference path", `{"format":"{r}","r":{"format":"{/word.w}","repeat":20,"separator":", "}}`, 25}, {"a repeat of a name", `{"format":"{r}","r":{"format":"{/word as n}{n.w}{n.w}","repeat":20,"separator":", "}}`, 162}, - {"a read under a nested pick", `{"format":"{place.geo as g}{g} {g.town.zip}","place":{"format":"{geo}","geo":{"format":"{town.zip}","town":{"format":"{zip}","zip":"1"}}}}`, 10}, + {"a read two levels under a pick", `{"format":"{place.geo as g}{g} {g.town.zip}","place":{"format":"{geo}","geo":{"format":"{town.zip}","town":{"format":"{zip}","zip":"1"}}}}`, 10}, } { f, err := New(WithoutShippedData(), WithDataFS(fstest.MapFS{ "word.json": {Data: []byte(word)}, diff --git a/pick.go b/pick.go index eb537be..2aa8a3c 100644 --- a/pick.go +++ b/pick.go @@ -5,13 +5,13 @@ import ( "github.com/larvit/fejkdata/internal/invariant" ) -// pickKey is where a level sits in a named pick: its path from the head the name's target starts -// at, which is "". A fresh read keys its levels from its own head until readUnder keys them under -// the pick. +// pickKey is a level's path of segments from a root keyed "": for a named read, the node its +// name's target starts at; for a fresh read, the template it sits in. under moves a fresh read's +// key into the pick it renders in. type pickKey string -// under is the key of rel, a fresh read's key, in what renders at k. It never returns k itself: on -// a render k is sc.pickAt, and a memo keeping it would move every render's scope to the heap. +// under is rel, a key from a fresh read's levels, moved under k, the key of what renders. It never +// returns k itself: on a render k is sc.pickAt, and a memo keeping it would move every render's scope to the heap. func (k pickKey) under(rel pickKey) pickKey { if k == "" { return rel @@ -193,8 +193,8 @@ func (sc renderScope) keeps(a arm) bool { return kept } -// readUnder reads a of t, which renders as part of the pick sc.pick at sc.pickAt, where a read of -// the name addresses it: once per pick, by its key in the pick. +// readUnder reads a, an arm of t, once per pick: t renders in sc.pick at sc.pickAt, and a read of +// the name addresses the level a starts at. It keys the value by a's key under sc.pickAt. func readUnder(s *drawstate.State, t *template, sc renderScope, a arm) readValue { p, key := sc.pick, sc.pickAt.under(a.key()) if r, done := p.memo.value[key]; done { @@ -209,8 +209,8 @@ func readUnder(s *drawstate.State, t *template, sc renderScope, a arm) readValue return p.renderAt(s, leaf, pins, key, sc) } -// draw draws the path from head under p, keeping the variant drawn at each of levels, the leaf's -// last, and returns the leaf and the pins its row is in. +// draw draws the path from head under p, keeping the variant drawn at each of levels, whose last +// is the leaf's key, and returns the leaf and the pins its row is in. func (p *namedPick) draw(s *drawstate.State, head node, steps []pathStep, levels []pickKey) (node, *pinSet) { leaf, pins := drawSteps(s, head, steps, &p.pins, &p.memo, levels) if c, isChoice := leaf.(*choice); isChoice { diff --git a/render.go b/render.go index 6b58fb9..507b416 100644 --- a/render.go +++ b/render.go @@ -145,8 +145,8 @@ func expand(s *drawstate.State, t *template, sc renderScope) string { // readField renders one arm of a token. A read is kept in a name's pick when it reads the name, or // a level that a read of the name being rendered addresses; every other read draws afresh, so // {word} {word} draws twice and {p.a} {p.b} reads two draws of p. -// A fresh read clears sc.pick. Kept, a read nested in the fresh one would key the pick's memo by -// sc.pickAt, where in the pick it renders, and share a value with a different node at that key. +// A fresh read clears sc.pick: were it kept, a read nested in the fresh one would key the pick's +// memo under sc.pickAt and share a value with another node at that key. func readField(s *drawstate.State, t *template, sc renderScope, a arm) readValue { switch { case a.kind == namedRead: diff --git a/scope.go b/scope.go index d38afe1..421109a 100644 --- a/scope.go +++ b/scope.go @@ -18,7 +18,7 @@ type renderScope struct { // base is the depth of the frame stack when the read rendering the category entered it, // below which no frame is the category's. base int - // pick is the named pick being rendered, nil outside one; pickAt is where in it this renders. + // pick is the named pick being rendered, nil outside one; pickAt is the key in it of what renders. pick *namedPick pickAt pickKey }