Answer prose round 1: pickKey names its two roots, readUnder says when it reads, levelKeys, draw and readField read on one pass, and the allocation case is named for what it reads
This commit is contained in:
@@ -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 {
|
||||
|
||||
+1
-1
@@ -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)},
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user