Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33
@@ -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)}
|
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 {
|
func levelKeys(path []string, from int) []pickKey {
|
||||||
levels := make([]pickKey, len(path)-from+1)
|
levels := make([]pickKey, len(path)-from+1)
|
||||||
for i := range levels {
|
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 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 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{
|
f, err := New(WithoutShippedData(), WithDataFS(fstest.MapFS{
|
||||||
"word.json": {Data: []byte(word)},
|
"word.json": {Data: []byte(word)},
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import (
|
|||||||
"github.com/larvit/fejkdata/internal/invariant"
|
"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
|
// pickKey is a level's path of segments from a root keyed "": for a named read, the node its
|
||||||
// at, which is "". A fresh read keys its levels from its own head until readUnder keys them under
|
// name's target starts at; for a fresh read, the template it sits in. under moves a fresh read's
|
||||||
// the pick.
|
// key into the pick it renders in.
|
||||||
type pickKey string
|
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
|
// under is rel, a key from a fresh read's levels, moved under k, the key of what renders. It never
|
||||||
// a render k is sc.pickAt, and a memo keeping it would move every render's scope to the heap.
|
// 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 {
|
func (k pickKey) under(rel pickKey) pickKey {
|
||||||
if k == "" {
|
if k == "" {
|
||||||
return rel
|
return rel
|
||||||
@@ -193,8 +193,8 @@ func (sc renderScope) keeps(a arm) bool {
|
|||||||
return kept
|
return kept
|
||||||
}
|
}
|
||||||
|
|
||||||
// readUnder reads a of t, which renders as part of the pick sc.pick at sc.pickAt, where a read of
|
// 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 it: once per pick, by its key in the pick.
|
// 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 {
|
func readUnder(s *drawstate.State, t *template, sc renderScope, a arm) readValue {
|
||||||
p, key := sc.pick, sc.pickAt.under(a.key())
|
p, key := sc.pick, sc.pickAt.under(a.key())
|
||||||
if r, done := p.memo.value[key]; done {
|
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)
|
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
|
// draw draws the path from head under p, keeping the variant drawn at each of levels, whose last
|
||||||
// last, and returns the leaf and the pins its row is in.
|
// 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) {
|
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)
|
leaf, pins := drawSteps(s, head, steps, &p.pins, &p.memo, levels)
|
||||||
if c, isChoice := leaf.(*choice); isChoice {
|
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
|
// 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
|
// 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.
|
// {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
|
// A fresh read clears sc.pick: were it kept, a read nested in the fresh one would key the pick's
|
||||||
// sc.pickAt, where in the pick it renders, and share a value with a different node at that key.
|
// 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 {
|
func readField(s *drawstate.State, t *template, sc renderScope, a arm) readValue {
|
||||||
switch {
|
switch {
|
||||||
case a.kind == namedRead:
|
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,
|
// base is the depth of the frame stack when the read rendering the category entered it,
|
||||||
// below which no frame is the category's.
|
// below which no frame is the category's.
|
||||||
base int
|
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
|
pick *namedPick
|
||||||
pickAt pickKey
|
pickAt pickKey
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user