Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33
@@ -204,8 +204,7 @@ type arm struct {
|
|||||||
head string
|
head string
|
||||||
writtenHead string // head as written, sigil included
|
writtenHead string // head as written, sigil included
|
||||||
tail []string
|
tail []string
|
||||||
levels []string // the path at each level the tail passes through, the head first
|
levels []pickKey // the key of each level the steps pass, from the head they start at to the leaf
|
||||||
path string // head and tail, the one path every way of writing this read shares
|
|
||||||
steps []pathStep
|
steps []pathStep
|
||||||
leaves []node // every node the path may land on, one per variant it passes
|
leaves []node // every node the path may land on, one per variant it passes
|
||||||
kind armKind
|
kind armKind
|
||||||
@@ -230,7 +229,7 @@ func splitArm(name string, refs map[string]refBinding) arm {
|
|||||||
if linked {
|
if linked {
|
||||||
head = b.head
|
head = b.head
|
||||||
}
|
}
|
||||||
return arm{spelling: name, head: head, path: head}
|
return arm{spelling: name, head: head, levels: []pickKey{pickKey(head)}}
|
||||||
}
|
}
|
||||||
sigil, rest, _ := grammar.RefShape(name) // resolveLink proved it, and took b.tail as a suffix of its segments
|
sigil, rest, _ := grammar.RefShape(name) // resolveLink proved it, and took b.tail as a suffix of its segments
|
||||||
written, _ := grammar.SplitPath(rest)
|
written, _ := grammar.SplitPath(rest)
|
||||||
@@ -238,19 +237,27 @@ func splitArm(name string, refs map[string]refBinding) arm {
|
|||||||
}
|
}
|
||||||
segs, err := grammar.SplitPath(name)
|
segs, err := grammar.SplitPath(name)
|
||||||
if err != nil || len(segs) == 1 {
|
if err != nil || len(segs) == 1 {
|
||||||
return arm{spelling: name, head: name, path: name}
|
return arm{spelling: name, head: name, levels: []pickKey{pickKey(name)}}
|
||||||
}
|
}
|
||||||
return pathArm(name, segs[0], segs[0], segs[1:])
|
return pathArm(name, segs[0], segs[0], segs[1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func pathArm(name, head, writtenHead string, segs []string) arm {
|
func pathArm(name, head, writtenHead string, segs []string) arm {
|
||||||
levels := []string{head}
|
return arm{spelling: name, head: head, writtenHead: writtenHead, tail: segs, levels: levelKeys(append([]string{head}, segs...), 1)}
|
||||||
for i := 0; i < len(segs)-1; i++ {
|
|
||||||
levels = append(levels, head+"."+strings.Join(segs[:i+1], "."))
|
|
||||||
}
|
|
||||||
return arm{spelling: name, head: head, writtenHead: writtenHead, tail: segs, levels: levels, path: head + "." + strings.Join(segs, ".")}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// levelKeys is the key of each level path passes, the first after its first from segments.
|
||||||
|
func levelKeys(path []string, from int) []pickKey {
|
||||||
|
levels := make([]pickKey, len(path)-from+1)
|
||||||
|
for i := range levels {
|
||||||
|
levels[i] = pickKey(grammar.JoinSegments(path[:from+i]))
|
||||||
|
}
|
||||||
|
return levels
|
||||||
|
}
|
||||||
|
|
||||||
|
// key is the key of the leaf a lands on, the one key every way of writing this read shares.
|
||||||
|
func (a arm) key() pickKey { return a.levels[len(a.levels)-1] }
|
||||||
|
|
||||||
func checkSegments(a arm) error {
|
func checkSegments(a arm) error {
|
||||||
if len(a.tail) == 0 {
|
if len(a.tail) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -340,10 +347,6 @@ func (t *template) compileArm(name string, targets map[*nameBinding]nameTarget)
|
|||||||
}
|
}
|
||||||
w := compilePath(target.head, full)
|
w := compilePath(target.head, full)
|
||||||
a.kind, a.named, a.steps, a.leaves = namedRead, b, w.steps, w.leaves
|
a.kind, a.named, a.steps, a.leaves = namedRead, b, w.steps, w.leaves
|
||||||
a.levels = make([]string, len(full)+1)
|
a.levels = levelKeys(full, 0)
|
||||||
for i := range a.levels {
|
|
||||||
a.levels[i] = grammar.JoinSegments(full[:i])
|
|
||||||
}
|
|
||||||
a.path = grammar.JoinSegments(full)
|
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ type nameTarget struct {
|
|||||||
// target, the keys its reads address, and its reads.
|
// target, the keys its reads address, and its reads.
|
||||||
type linkedNames struct {
|
type linkedNames struct {
|
||||||
targets map[*nameBinding]nameTarget
|
targets map[*nameBinding]nameTarget
|
||||||
addressed map[*nameBinding]map[string]string
|
addressed map[*nameBinding]map[pickKey]string
|
||||||
uses map[*nameBinding][]nameUse
|
uses map[*nameBinding][]nameUse
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,15 +117,15 @@ func nameTargets(ts []linkSite) map[*nameBinding]nameTarget {
|
|||||||
|
|
||||||
// addressedKeys is every key the reads of each name in ts land on or pass, from the name, with the
|
// addressedKeys is every key the reads of each name in ts land on or pass, from the name, with the
|
||||||
// spelling of the first read reaching it.
|
// spelling of the first read reaching it.
|
||||||
func addressedKeys(ts []linkSite, targets map[*nameBinding]nameTarget) map[*nameBinding]map[string]string {
|
func addressedKeys(ts []linkSite, targets map[*nameBinding]nameTarget) map[*nameBinding]map[pickKey]string {
|
||||||
keys := map[*nameBinding]map[string]string{}
|
keys := map[*nameBinding]map[pickKey]string{}
|
||||||
for _, s := range ts {
|
for _, s := range ts {
|
||||||
for _, r := range namedReads(s.t) {
|
for _, r := range namedReads(s.t) {
|
||||||
b := r.a.named
|
b := r.a.named
|
||||||
if keys[b] == nil {
|
if keys[b] == nil {
|
||||||
keys[b] = map[string]string{}
|
keys[b] = map[pickKey]string{}
|
||||||
}
|
}
|
||||||
for _, key := range append(r.a.levels[len(targets[b].tail):], r.a.path) {
|
for _, key := range r.a.levels[len(targets[b].tail):] {
|
||||||
if _, seen := keys[b][key]; !seen {
|
if _, seen := keys[b][key]; !seen {
|
||||||
keys[b][key] = r.a.spelling
|
keys[b][key] = r.a.spelling
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ type nameBinding struct {
|
|||||||
nameTarget
|
nameTarget
|
||||||
// addressed is every key a read of the name lands on or passes, the spelling of the
|
// addressed is every key a read of the name lands on or passes, the spelling of the
|
||||||
// first read reaching it beside it; a pick keeps the draws at these keys, and only these.
|
// first read reaching it beside it; a pick keeps the draws at these keys, and only these.
|
||||||
addressed map[string]string
|
addressed map[pickKey]string
|
||||||
}
|
}
|
||||||
|
|
||||||
// nameUse is one read of a name: the path it reads into the name, "" for the name itself; the
|
// nameUse is one read of a name: the path it reads into the name, "" for the name itself; the
|
||||||
|
|||||||
+6
-6
@@ -28,7 +28,7 @@ func checkNameReads(label string, t *template, names linkedNames) error {
|
|||||||
return fmt.Errorf("%s: token {%s}: name %q is read inside %q, the field bound to it; read the name outside that field", label, r.o.Body, b.name, b.ref)
|
return fmt.Errorf("%s: token {%s}: name %q is read inside %q, the field bound to it; read the name outside that field", label, r.o.Body, b.name, b.ref)
|
||||||
}
|
}
|
||||||
for _, leaf := range r.a.leaves {
|
for _, leaf := range r.a.leaves {
|
||||||
if err := checkOnce(names.addressed[b], r.a.spelling, leaf, r.a.path); err != nil {
|
if err := checkOnce(names.addressed[b], r.a.spelling, leaf, r.a.key()); err != nil {
|
||||||
return fmt.Errorf("%s: token {%s}: %w", label, r.o.Body, err)
|
return fmt.Errorf("%s: token {%s}: %w", label, r.o.Body, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ func calcReads(spelling string) bool {
|
|||||||
|
|
||||||
// checkOnce walks n, rendering at key under a pick, into each level a read of the name addresses:
|
// checkOnce walks n, rendering at key under a pick, into each level a read of the name addresses:
|
||||||
// the keys of addressed.
|
// the keys of addressed.
|
||||||
func checkOnce(addressed map[string]string, read string, n node, key string) error {
|
func checkOnce(addressed map[pickKey]string, read string, n node, key pickKey) error {
|
||||||
switch n := n.(type) {
|
switch n := n.(type) {
|
||||||
case *choice:
|
case *choice:
|
||||||
for _, item := range n.items {
|
for _, item := range n.items {
|
||||||
@@ -136,7 +136,7 @@ func checkOnce(addressed map[string]string, read string, n node, key string) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkTemplateOnce(addressed map[string]string, read string, t *template, key string) error {
|
func checkTemplateOnce(addressed map[pickKey]string, read string, t *template, key pickKey) error {
|
||||||
reads := map[string]int{}
|
reads := map[string]int{}
|
||||||
var into []arm
|
var into []arm
|
||||||
for _, o := range t.compiled.ops {
|
for _, o := range t.compiled.ops {
|
||||||
@@ -144,20 +144,20 @@ func checkTemplateOnce(addressed map[string]string, read string, t *template, ke
|
|||||||
if grammar.IsRef(a.head) || a.kind == namedRead {
|
if grammar.IsRef(a.head) || a.kind == namedRead {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if _, kept := addressed[join(key, a.path)]; kept {
|
if _, kept := addressed[key.under(a.key())]; kept {
|
||||||
into = append(into, a)
|
into = append(into, a)
|
||||||
}
|
}
|
||||||
reads[a.head]++
|
reads[a.head]++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, head := range sortedNames(reads) {
|
for _, head := range sortedNames(reads) {
|
||||||
if by, kept := addressed[join(key, head)]; kept && reads[head] > 1 {
|
if by, kept := addressed[key.under(pickKey(head))]; kept && reads[head] > 1 {
|
||||||
return fmt.Errorf("{%s} renders field %q twice, so {%s} cannot say which draw it reads; drop {%s} or {%s}", read, head, by, read, by)
|
return fmt.Errorf("{%s} renders field %q twice, so {%s} cannot say which draw it reads; drop {%s} or {%s}", read, head, by, read, by)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, a := range into {
|
for _, a := range into {
|
||||||
for _, leaf := range a.leaves {
|
for _, leaf := range a.leaves {
|
||||||
if err := checkOnce(addressed, read, leaf, join(key, a.path)); err != nil {
|
if err := checkOnce(addressed, read, leaf, key.under(a.key())); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ func probePath(n node, tail []string, steps []pathStep) ([]pathStep, error) {
|
|||||||
// For a read through a name, memo keeps the variant drawn at each of levels, so paths sharing a
|
// For a read through a name, memo keeps the variant drawn at each of levels, so paths sharing a
|
||||||
// prefix share it. It returns the leaf and the pins its row is in: a step down after a step up draws
|
// prefix share it. It returns the leaf and the pins its row is in: a step down after a step up draws
|
||||||
// afresh, into pins of its own, which memo shares with every path stepping down there.
|
// afresh, into pins of its own, which memo shares with every path stepping down there.
|
||||||
func drawSteps(s *drawstate.State, n node, steps []pathStep, pins *pinSet, memo *drawMemo, levels []string) (node, *pinSet) {
|
func drawSteps(s *drawstate.State, n node, steps []pathStep, pins *pinSet, memo *drawMemo, levels []pickKey) (node, *pinSet) {
|
||||||
var climbed *rowsTable
|
var climbed *rowsTable
|
||||||
for _, st := range steps {
|
for _, st := range steps {
|
||||||
if c, ok := n.(*choice); ok {
|
if c, ok := n.(*choice); ok {
|
||||||
@@ -313,7 +313,7 @@ func (t *table) drawStep(s *drawstate.State, st pathStep, pins *pinSet) node {
|
|||||||
panic(invariant.Broken("drawStep has no case for step kind %d", st.kind))
|
panic(invariant.Broken("drawStep has no case for step kind %d", st.kind))
|
||||||
}
|
}
|
||||||
|
|
||||||
func drawVariant(s *drawstate.State, c *choice, memo *drawMemo, levels []string, at int) node {
|
func drawVariant(s *drawstate.State, c *choice, memo *drawMemo, levels []pickKey, at int) node {
|
||||||
if memo == nil {
|
if memo == nil {
|
||||||
return resolveChoice(s, c)
|
return resolveChoice(s, c)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,20 @@ 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
|
||||||
|
// at, which is "". A fresh read keys its levels from its own head until readUnder keys them under
|
||||||
|
// the pick.
|
||||||
|
type pickKey string
|
||||||
|
|
||||||
|
// under is the key of rel, a fresh read's key, in what renders at k. It never returns k itself: 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
|
||||||
|
}
|
||||||
|
return k + "." + rel
|
||||||
|
}
|
||||||
|
|
||||||
// namedPick is one draw of a name: the variant drawn at each level a read of it addresses, the
|
// namedPick is one draw of a name: the variant drawn at each level a read of it addresses, the
|
||||||
// value each read there produced, keyed by the path from the name, and the table rows they
|
// value each read there produced, keyed by the path from the name, and the table rows they
|
||||||
// pinned.
|
// pinned.
|
||||||
@@ -19,15 +33,15 @@ type namedPick struct {
|
|||||||
// twice reads one value; the frames a read opens for the name scopes around where it lands
|
// twice reads one value; the frames a read opens for the name scopes around where it lands
|
||||||
// (enter); and the rows drawn by each step down after a "..", by level.
|
// (enter); and the rows drawn by each step down after a "..", by level.
|
||||||
type drawMemo struct {
|
type drawMemo struct {
|
||||||
variant map[string]node
|
variant map[pickKey]node
|
||||||
value map[string]readValue
|
value map[pickKey]readValue
|
||||||
enteredFrames map[*nameScope]*pickFrame
|
enteredFrames map[*nameScope]*pickFrame
|
||||||
steppedDown map[string]*pinSet
|
steppedDown map[pickKey]*pinSet
|
||||||
}
|
}
|
||||||
|
|
||||||
// stepDownPins is the pins a path steps down into after stepping up to t: kept in m where there
|
// stepDownPins is the pins a path steps down into after stepping up to t: kept in m where there
|
||||||
// is one, so every path stepping down there reads one draw.
|
// is one, so every path stepping down there reads one draw.
|
||||||
func (m *drawMemo) stepDownPins(pins *pinSet, t *rowsTable, levels []string, at int) *pinSet {
|
func (m *drawMemo) stepDownPins(pins *pinSet, t *rowsTable, levels []pickKey, at int) *pinSet {
|
||||||
if m == nil {
|
if m == nil {
|
||||||
return pins.Above(t)
|
return pins.Above(t)
|
||||||
}
|
}
|
||||||
@@ -35,7 +49,7 @@ func (m *drawMemo) stepDownPins(pins *pinSet, t *rowsTable, levels []string, at
|
|||||||
if !ok {
|
if !ok {
|
||||||
p = pins.Above(t)
|
p = pins.Above(t)
|
||||||
if m.steppedDown == nil {
|
if m.steppedDown == nil {
|
||||||
m.steppedDown = map[string]*pinSet{}
|
m.steppedDown = map[pickKey]*pinSet{}
|
||||||
}
|
}
|
||||||
m.steppedDown[levels[at]] = p
|
m.steppedDown[levels[at]] = p
|
||||||
}
|
}
|
||||||
@@ -153,15 +167,15 @@ func readName(s *drawstate.State, sc renderScope, a arm) readValue {
|
|||||||
panic(invariant.Broken("name %q is read where no frame of its scope renders", a.named.name))
|
panic(invariant.Broken("name %q is read where no frame of its scope renders", a.named.name))
|
||||||
}
|
}
|
||||||
p := &f.picks[a.named.index]
|
p := &f.picks[a.named.index]
|
||||||
if r, done := p.memo.value[a.path]; done {
|
if r, done := p.memo.value[a.key()]; done {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
leaf, pins := p.draw(s, a.named.head, a.steps, a.levels, a.path)
|
leaf, pins := p.draw(s, a.named.head, a.steps, a.levels)
|
||||||
if a.named.bindsField() {
|
if a.named.bindsField() {
|
||||||
return p.renderAt(s, leaf, pins, a.path, sc)
|
return p.renderAt(s, leaf, pins, a.key(), sc)
|
||||||
}
|
}
|
||||||
sc, mark := sc.enter(leaf, &p.memo)
|
sc, mark := sc.enter(leaf, &p.memo)
|
||||||
r := p.renderAt(s, leaf, pins, a.path, sc)
|
r := p.renderAt(s, leaf, pins, a.key(), sc)
|
||||||
sc.frames.pop(mark)
|
sc.frames.pop(mark)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -176,63 +190,54 @@ func (sc renderScope) drawRowOf(s *drawstate.State, t *table) int {
|
|||||||
|
|
||||||
// keeps reports whether a read of sc's name addresses the level a starts at.
|
// keeps reports whether a read of sc's name addresses the level a starts at.
|
||||||
func (sc renderScope) keeps(a arm) bool {
|
func (sc renderScope) keeps(a arm) bool {
|
||||||
_, kept := sc.pick.named.addressed[underKey(sc.pickKey, a.head)]
|
_, kept := sc.pick.named.addressed[sc.pickAt.under(a.levels[0])]
|
||||||
return kept
|
return kept
|
||||||
}
|
}
|
||||||
|
|
||||||
// readUnder reads a of t, which renders as part of the pick sc.pick at sc.pickKey, where a read of
|
// 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 path from the name.
|
// the name addresses it: once per pick, by its key in the pick.
|
||||||
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, underKey(sc.pickKey, a.path)
|
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 {
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
levels := make([]string, len(a.levels))
|
levels := make([]pickKey, len(a.levels))
|
||||||
for i, l := range a.levels {
|
for i, l := range a.levels {
|
||||||
levels[i] = underKey(sc.pickKey, l)
|
levels[i] = sc.pickAt.under(l)
|
||||||
}
|
}
|
||||||
leaf, pins := p.draw(s, t.head(a.head), a.steps, levels, key)
|
leaf, pins := p.draw(s, t.head(a.head), a.steps, levels)
|
||||||
return p.renderAt(s, leaf, pins, key, sc)
|
return p.renderAt(s, leaf, pins, key, sc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// underKey is the key of path under the pick key prefix. It never returns prefix itself: prefix is
|
// draw draws the path from head under p, keeping the variant drawn at each of levels, the leaf's
|
||||||
// sc.pickKey, and a memo keeping it would move every render's scope to the heap.
|
// last, and returns the leaf and the pins its row is in.
|
||||||
func underKey(prefix, path string) string {
|
func (p *namedPick) draw(s *drawstate.State, head node, steps []pathStep, levels []pickKey) (node, *pinSet) {
|
||||||
if prefix == "" {
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
return prefix + "." + path
|
|
||||||
}
|
|
||||||
|
|
||||||
// draw draws the path key names under p, its variant at key kept too, returning the leaf and the
|
|
||||||
// pins its row is in.
|
|
||||||
func (p *namedPick) draw(s *drawstate.State, head node, steps []pathStep, levels []string, key string) (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 {
|
||||||
leaf = p.memo.variantOf(s, c, key)
|
leaf = p.memo.variantOf(s, c, levels[len(levels)-1])
|
||||||
}
|
}
|
||||||
return leaf, pins
|
return leaf, pins
|
||||||
}
|
}
|
||||||
|
|
||||||
// renderAt renders leaf, drawn at key into pins, as part of p, and keeps what it rendered.
|
// renderAt renders leaf, drawn at key into pins, as part of p, and keeps what it rendered.
|
||||||
func (p *namedPick) renderAt(s *drawstate.State, leaf node, pins *pinSet, key string, sc renderScope) readValue {
|
func (p *namedPick) renderAt(s *drawstate.State, leaf node, pins *pinSet, key pickKey, sc renderScope) readValue {
|
||||||
sc = sc.at(leaf, pins)
|
sc = sc.at(leaf, pins)
|
||||||
sc.pick, sc.pickKey = p, key
|
sc.pick, sc.pickAt = p, key
|
||||||
r := renderLeaf(s, leaf, sc)
|
r := renderLeaf(s, leaf, sc)
|
||||||
if p.memo.value == nil {
|
if p.memo.value == nil {
|
||||||
p.memo.value = map[string]readValue{}
|
p.memo.value = map[pickKey]readValue{}
|
||||||
}
|
}
|
||||||
p.memo.value[key] = r
|
p.memo.value[key] = r
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
// variantOf is the variant of c drawn at level, drawn now where none was.
|
// variantOf is the variant of c drawn at level, drawn now where none was.
|
||||||
func (m *drawMemo) variantOf(s *drawstate.State, c *choice, level string) node {
|
func (m *drawMemo) variantOf(s *drawstate.State, c *choice, level pickKey) node {
|
||||||
n, drew := m.variant[level]
|
n, drew := m.variant[level]
|
||||||
if !drew {
|
if !drew {
|
||||||
n = resolveChoice(s, c)
|
n = resolveChoice(s, c)
|
||||||
if m.variant == nil {
|
if m.variant == nil {
|
||||||
m.variant = map[string]node{}
|
m.variant = map[pickKey]node{}
|
||||||
}
|
}
|
||||||
m.variant[level] = n
|
m.variant[level] = n
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -300,4 +300,4 @@ func renderRecord(s *drawstate.State, t *template, sc renderScope) *Record {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// wholeLevels is the levels of a read of a whole name, as compileArm compiles {n}.
|
// wholeLevels is the levels of a read of a whole name, as compileArm compiles {n}.
|
||||||
var wholeLevels = []string{""}
|
var wholeLevels = []pickKey{""}
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ func expand(s *drawstate.State, t *template, sc renderScope) string {
|
|||||||
// 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. Kept, a read nested in the fresh one would key the pick's memo by
|
||||||
// sc.pickKey, the path from the name to what the pick renders, and share a value with a different
|
// sc.pickAt, where in the pick it renders, and share a value with a different
|
||||||
// node at that path.
|
// node at that path.
|
||||||
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 {
|
||||||
|
|||||||
@@ -18,10 +18,9 @@ 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; pickKey is the path from the name
|
// pick is the named pick being rendered, nil outside one; pickAt is where in it this renders.
|
||||||
// to what renders.
|
pick *namedPick
|
||||||
pick *namedPick
|
pickAt pickKey
|
||||||
pickKey string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type renderedRow struct {
|
type renderedRow struct {
|
||||||
|
|||||||
@@ -76,7 +76,6 @@
|
|||||||
| 91 | 0.1.0 | | **Accept a path through a name as a `calc` operand, so `{/misc.coordinate as c}{c}: {calc(c.lat * 60)}` computes from the coordinate `{c}` prints.** | 3 | 4 | 6 | 7 | 4.1, 5.3 | 19.9 |
|
| 91 | 0.1.0 | | **Accept a path through a name as a `calc` operand, so `{/misc.coordinate as c}{c}: {calc(c.lat * 60)}` computes from the coordinate `{c}` prints.** | 3 | 4 | 6 | 7 | 4.1, 5.3 | 19.9 |
|
||||||
| 89 | 0.1.0 | | **Fail `New` without `WithSeed`, naming the option, and seed the CLI from the system.** | 3 | 3 | 6 | 7 | 10.1 | 16.0 |
|
| 89 | 0.1.0 | | **Fail `New` without `WithSeed`, naming the option, and seed the CLI from the system.** | 3 | 3 | 6 | 7 | 10.1 | 16.0 |
|
||||||
| 127 | 0.1.0 | | **Give a Swedish street only postal codes whose delivery digit means street or rural delivery, dropping codes whose delivery digit is 9, or record why they stay.** | 3 | 3 | 4 | 6 | 4 | 14.4 |
|
| 127 | 0.1.0 | | **Give a Swedish street only postal codes whose delivery digit means street or rural delivery, dropping codes whose delivery digit is 9, or record why they stay.** | 3 | 3 | 4 | 6 | 4 | 14.4 |
|
||||||
| 118 | 0.1.0 | | **Give a pick key one type, so `pathArm`, `compileArm`, `addressedKeys`, `keeps`, `readUnder` and `checkTemplateOnce` spell it one way, and `arm.levels` start at the same level for a fresh read and a named read.** | 5 | 5 | 2 | 9 | 3.2, 3.3 | 13.9 |
|
|
||||||
| 110 | 0.1.0 | | **Refuse an empty segment in a path `Fake`, `FakeRecord` and the CLI take, as a reference does: `sv_SE.person.` reports `path has an empty segment`.** | 1 | 1 | 3 | 6 | 6 | 13.8 |
|
| 110 | 0.1.0 | | **Refuse an empty segment in a path `Fake`, `FakeRecord` and the CLI take, as a reference does: `sv_SE.person.` reports `path has an empty segment`.** | 1 | 1 | 3 | 6 | 6 | 13.8 |
|
||||||
| 120 | 0.1.0 | | **Rename the engine's overloaded nouns, so `scope`, `binding`, `link`, `pick` and `head` each name one thing.** | 2 | 4 | 1 | 8 | 3.3 | 13.4 |
|
| 120 | 0.1.0 | | **Rename the engine's overloaded nouns, so `scope`, `binding`, `link`, `pick` and `head` each name one thing.** | 2 | 4 | 1 | 8 | 3.3 | 13.4 |
|
||||||
| 123 | 0.1.0 | | **Name the name fences by what they refuse, and state each rule at `checkOnce`, `checkTemplateOnce` and `checkUses`, so they read without the README's Names list.** | 1 | 2 | 1 | 7 | 3.4, 3.3 | 13.1 |
|
| 123 | 0.1.0 | | **Name the name fences by what they refuse, and state each rule at `checkOnce`, `checkTemplateOnce` and `checkUses`, so they read without the README's Names list.** | 1 | 2 | 1 | 7 | 3.4, 3.3 | 13.1 |
|
||||||
@@ -264,10 +263,6 @@ Goal 10.1 has the caller supply the seed, and today `New` without `WithSeed` see
|
|||||||
|
|
||||||
`docs/research/research-geo-se.md` reads delivery digit 0 or 1 as boxes, 2–4 and 6–7 as street, 5 as rural, 8 as reply mail and 9 as competitions or temporary, with exceptions in big cities. `street_delivery` drops 0, 1 and 8 and keeps 9. The panel of 2026-10-05 found it; whether a shipped street carries a 9 code is unchecked.
|
`docs/research/research-geo-se.md` reads delivery digit 0 or 1 as boxes, 2–4 and 6–7 as street, 5 as rural, 8 as reply mail and 9 as competitions or temporary, with exceptions in big cities. `street_delivery` drops 0, 1 and 8 and keeps 9. The panel of 2026-10-05 found it; whether a shipped street carries a 9 code is unchecked.
|
||||||
|
|
||||||
### 118. Give a pick key one type, so `pathArm`, `compileArm`, `addressedKeys`, `keeps`, `readUnder` and `checkTemplateOnce` spell it one way, and `arm.levels` start at the same level for a fresh read and a named read.
|
|
||||||
|
|
||||||
Eight of the nine seats in the panel of 2026-10-05 named the key convention hardest after the named-pick read path itself. A fresh read's `levels` start at the head, `[head, head.a, …]`, while `compileArm` builds a named read's from the name, `["", a, a.b, …]`, so `arm.levels`' comment holds only for fresh reads. `addressedKeys` slices off the target's tail and `readUnder` re-prefixes with `underKey`; no type ties them. Keep the key a string, so the allocation gate holds.
|
|
||||||
|
|
||||||
### 110. Refuse an empty segment in a path `Fake`, `FakeRecord` and the CLI take, as a reference does: `sv_SE.person.` reports `path has an empty segment`.
|
### 110. Refuse an empty segment in a path `Fake`, `FakeRecord` and the CLI take, as a reference does: `sv_SE.person.` reports `path has an empty segment`.
|
||||||
|
|
||||||
Today `fejkdata 'sv_SE.person.'` reports `no field ""`, while `{/sv_SE.person.}` reports `path has an empty segment`. `grammar.CheckSegments` is the check a reference, a sibling path and a step up `..` run.
|
Today `fejkdata 'sv_SE.person.'` reports `no field ""`, while `{/sv_SE.person.}` reports `path has an empty segment`. `grammar.CheckSegments` is the check a reference, a sibling path and a step up `..` run.
|
||||||
|
|||||||
Reference in New Issue
Block a user