Fix a render's fallback frame to its unnamed group, and draw a pick's references in draw groups of its own
This commit is contained in:
+2
-2
@@ -12,8 +12,8 @@ replacement, and each removed path, column or flag.
|
|||||||
and prints nothing, and `{t}`, `{t.capital}` and `{t.calling-code}` read that one row.
|
and prints nothing, and `{t}`, `{t.capital}` and `{t.calling-code}` read that one row.
|
||||||
A name lives in the category binding it, so every field and record column of the
|
A name lives in the category binding it, so every field and record column of the
|
||||||
category reads one pick, a transform reads it as `{lowercase(t.name)}`, and a name a
|
category reads one pick, a transform reads it as `{lowercase(t.name)}`, and a name a
|
||||||
`repeat` binds picks again on every iteration. Refused at `New`: a name bound twice in
|
`repeat` binds picks again on every iteration. Refused at `New`: a name bound twice
|
||||||
one category, or inside a `repeat` and outside it; a name that is a field or an option;
|
outside any `repeat`, twice in one `repeat`, or both inside a `repeat` and outside it; a name that is a field or an option;
|
||||||
a binding of anything but a reference; a binding in a choice's item; a binding nothing
|
a binding of anything but a reference; a binding in a choice's item; a binding nothing
|
||||||
reads; a path through a name that selects a row; and a binding in a table. A field,
|
reads; a path through a name that selects a row; and a binding in a table. A field,
|
||||||
column, category or folder name may not contain ` as `.
|
column, category or folder name may not contain ` as `.
|
||||||
|
|||||||
@@ -711,15 +711,16 @@ row:
|
|||||||
Renders e.g. `🇳🇴 Norway: capital Oslo, calling code +47`. Everything under a name is drawn
|
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
|
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:
|
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.
|
`{t.name}` and `{/misc.territory.name}` beside it are two draws, as are two names bound to one
|
||||||
|
category.
|
||||||
|
|
||||||
A name is drawn on its first read, and lives in the category binding it: any field of the
|
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
|
category reads it, and a record's columns read one pick. Each render of the category picks
|
||||||
anew, and so does each bare reference to it. A name a `repeat` binds picks again on every
|
anew, and so does each bare reference to it. A name a `repeat` binds picks again on every
|
||||||
iteration, and one bound outside the repeat keeps its pick on every line.
|
iteration, and one bound outside the repeat keeps its pick on every line.
|
||||||
|
|
||||||
Rejected at load: a name bound twice in one category, or both inside a `repeat` and outside
|
Rejected at load: a name bound twice outside any `repeat`, twice in one `repeat`, or both
|
||||||
it; a name that is a field or an option; a binding of anything but a reference; a binding in
|
inside a `repeat` and outside it; a name that is a field or an option; a binding of anything but a reference; a binding in
|
||||||
a choice's item, which every other item would leave unbound; a binding nothing reads; a path
|
a choice's item, which every other item would leave unbound; a binding nothing reads; a path
|
||||||
through a name that selects a row, which the reference selects instead; and a binding in a
|
through a name that selects a row, which the reference selects instead; and a binding in a
|
||||||
table's format or cell. A field, column, category or folder name may not contain ` as `.
|
table's format or cell. A field, column, category or folder name may not contain ` as `.
|
||||||
|
|||||||
+2
-1
@@ -903,4 +903,5 @@ pick is drawn on its first read, so a record's columns, rendered in name order,
|
|||||||
whichever binds it. A read entering a category keeps the frame of each scope it enters in its
|
whichever binds it. A read entering a category keeps the frame of each scope it enters in its
|
||||||
own memo, and the category's root renders that frame when the read lands on the root, so
|
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
|
`{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")`.
|
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.
|
||||||
|
|||||||
@@ -51,9 +51,10 @@ type renderScope struct {
|
|||||||
entry *drawMemo
|
entry *drawMemo
|
||||||
base int
|
base int
|
||||||
// pick is the named pick what renders is part of, at pickKey, its path from the name; nil
|
// pick is the named pick what renders is part of, at pickKey, its path from the name; nil
|
||||||
// outside one.
|
// outside one. refs is the draw groups of the last pick entered, nil before one.
|
||||||
pick *namedPick
|
pick *namedPick
|
||||||
pickKey string
|
pickKey string
|
||||||
|
refs *renderDraws
|
||||||
}
|
}
|
||||||
|
|
||||||
type renderedRow struct {
|
type renderedRow struct {
|
||||||
@@ -90,16 +91,20 @@ func (sc renderScope) rowOf(t *table) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (sc renderScope) groupDraws() *groupDraws {
|
func (sc renderScope) groupDraws() *groupDraws {
|
||||||
if sc.group == "" {
|
draws := sc.draws
|
||||||
return &sc.draws.unnamed
|
if sc.refs != nil {
|
||||||
|
draws = sc.refs
|
||||||
}
|
}
|
||||||
d, drew := sc.draws.named[sc.group]
|
if sc.group == "" {
|
||||||
|
return &draws.unnamed
|
||||||
|
}
|
||||||
|
d, drew := draws.named[sc.group]
|
||||||
if !drew {
|
if !drew {
|
||||||
if sc.draws.named == nil {
|
if draws.named == nil {
|
||||||
sc.draws.named = map[string]*groupDraws{}
|
draws.named = map[string]*groupDraws{}
|
||||||
}
|
}
|
||||||
d = &groupDraws{}
|
d = &groupDraws{}
|
||||||
sc.draws.named[strings.Clone(sc.group)] = d
|
draws.named[strings.Clone(sc.group)] = d
|
||||||
}
|
}
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -219,10 +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
|
// 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.
|
// 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.
|
||||||
type namedPick struct {
|
type namedPick struct {
|
||||||
memo drawMemo
|
memo drawMemo
|
||||||
pins pinSet
|
pins pinSet
|
||||||
|
refs renderDraws
|
||||||
}
|
}
|
||||||
|
|
||||||
// pickFrame is one render of a name scope: a pick per binding, each drawn on its first read.
|
// pickFrame is one render of a name scope: a pick per binding, each drawn on its first read.
|
||||||
@@ -299,15 +301,22 @@ func (sc renderScope) pickOf(b *nameBinding) *namedPick {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
memo := sc.entry
|
return &sc.entryMemo().frameOf(b.scope).picks[b.index]
|
||||||
if memo == nil {
|
}
|
||||||
memo = &sc.groupDraws().memo
|
|
||||||
|
// entryMemo is the memo of the read that entered the category rendering, else the unnamed draw
|
||||||
|
// group's of the render: one memo for a render begun below a category's root, whatever draw group
|
||||||
|
// its templates name.
|
||||||
|
func (sc renderScope) entryMemo() *drawMemo {
|
||||||
|
if sc.entry != nil {
|
||||||
|
return sc.entry
|
||||||
}
|
}
|
||||||
return &memo.frameOf(b.scope).picks[b.index]
|
return &sc.draws.unnamed.memo
|
||||||
}
|
}
|
||||||
|
|
||||||
func readName(s *generatorState, sc renderScope, a arm) readValue {
|
func readName(s *generatorState, sc renderScope, a arm) readValue {
|
||||||
p := sc.pickOf(a.bind)
|
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))
|
return readPicked(s, p, a.bind.head, a.steps, a.levels, a.path, sc.entering(&p.memo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,13 +93,9 @@ func render(s *generatorState, n node, sc renderScope) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// renderRepeat renders each iteration of t as a render of its own, inside the name scopes
|
// renderRepeat renders each iteration of t as a render of its own, inside the name scopes
|
||||||
// rendering t, where a name bound outside t keeps its pick: a scope sc's category was entered
|
// rendering t, where a name bound outside t keeps its pick in the frame sc.entryMemo keeps.
|
||||||
// past keeps its frame in that read's memo, else in sc's render's.
|
|
||||||
func renderRepeat(s *generatorState, t *template, sc renderScope) string {
|
func renderRepeat(s *generatorState, t *template, sc renderScope) string {
|
||||||
entry := sc.entry
|
entry := sc.entryMemo()
|
||||||
if entry == nil {
|
|
||||||
entry = &sc.groupDraws().memo
|
|
||||||
}
|
|
||||||
var b strings.Builder
|
var b strings.Builder
|
||||||
b.Grow(t.repeat * (t.compiled.grow + len(t.separator)))
|
b.Grow(t.repeat * (t.compiled.grow + len(t.separator)))
|
||||||
for i := 0; i < t.repeat; i++ {
|
for i := 0; i < t.repeat; i++ {
|
||||||
|
|||||||
Reference in New Issue
Block a user