Key drawWalk's visits by interned pin sets and the whole table
This commit is contained in:
+43
-16
@@ -226,9 +226,10 @@ func columnDraws(t *template, columns []string) *drawWalk {
|
|||||||
|
|
||||||
// drawWalk gathers the references one render reads, by draw group, for check to compare.
|
// drawWalk gathers the references one render reads, by draw group, for check to compare.
|
||||||
type drawWalk struct {
|
type drawWalk struct {
|
||||||
reads []pathRead
|
reads []pathRead
|
||||||
read map[readKey]bool
|
read map[readKey]bool
|
||||||
seen map[nodeVisit]bool
|
seen map[nodeVisit]bool
|
||||||
|
pinIDs map[pinsLink]pinsID
|
||||||
}
|
}
|
||||||
|
|
||||||
// drawAt is where a walk stands: the draw group it draws in, how the render's root reached it, the
|
// drawAt is where a walk stands: the draw group it draws in, how the render's root reached it, the
|
||||||
@@ -238,7 +239,7 @@ type drawAt struct {
|
|||||||
group string
|
group string
|
||||||
route drawRoute
|
route drawRoute
|
||||||
pins pinSet
|
pins pinSet
|
||||||
wholeTable *table // left out of the visit keys: only this table's own cells compare against it, which the own-family fence keeps true
|
wholeTable *table
|
||||||
wholePins pinSet
|
wholePins pinSet
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,19 +254,48 @@ type pathRead struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type nodeVisit struct {
|
type nodeVisit struct {
|
||||||
n node
|
n node
|
||||||
group string
|
group string
|
||||||
rowsKey string
|
wholeTable *table
|
||||||
|
pins pinsID
|
||||||
|
wholePins pinsID
|
||||||
}
|
}
|
||||||
|
|
||||||
type readKey struct {
|
type readKey struct {
|
||||||
group string
|
group string
|
||||||
path string
|
path string
|
||||||
rowsKey string
|
pins pinsID
|
||||||
|
wholePins pinsID
|
||||||
|
}
|
||||||
|
|
||||||
|
// pinsID names a pin set within one walk: two sets pinning the same rows share one.
|
||||||
|
type pinsID int
|
||||||
|
|
||||||
|
// pinsLink is a set's last pin, in path order, and the id of the set before it.
|
||||||
|
type pinsLink struct {
|
||||||
|
prev pinsID
|
||||||
|
pin tablePin
|
||||||
}
|
}
|
||||||
|
|
||||||
func newDrawWalk() *drawWalk {
|
func newDrawWalk() *drawWalk {
|
||||||
return &drawWalk{read: map[readKey]bool{}, seen: map[nodeVisit]bool{}}
|
return &drawWalk{read: map[readKey]bool{}, seen: map[nodeVisit]bool{}, pinIDs: map[pinsLink]pinsID{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *drawWalk) pinsID(p *pinSet) pinsID {
|
||||||
|
var pins []tablePin
|
||||||
|
p.each(func(t *table, r int) { pins = append(pins, tablePin{t, r}) })
|
||||||
|
sort.Slice(pins, func(i, j int) bool { return pins[i].t.path < pins[j].t.path })
|
||||||
|
id := pinsID(0)
|
||||||
|
for _, q := range pins {
|
||||||
|
l := pinsLink{id, q}
|
||||||
|
next, ok := w.pinIDs[l]
|
||||||
|
if !ok {
|
||||||
|
next = pinsID(len(w.pinIDs) + 1)
|
||||||
|
w.pinIDs[l] = next
|
||||||
|
}
|
||||||
|
id = next
|
||||||
|
}
|
||||||
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk follows what rendering n renders. A repeat renders over draws of its own, so the walk stops
|
// walk follows what rendering n renders. A repeat renders over draws of its own, so the walk stops
|
||||||
@@ -273,7 +303,7 @@ func newDrawWalk() *drawWalk {
|
|||||||
// alone and an unpinned one draws a row inside its nearest pinned ancestor's, so that cell never
|
// alone and an unpinned one draws a row inside its nearest pinned ancestor's, so that cell never
|
||||||
// renders on this route.
|
// renders on this route.
|
||||||
func (w *drawWalk) walk(n node, at drawAt) {
|
func (w *drawWalk) walk(n node, at drawAt) {
|
||||||
v := nodeVisit{n, at.group, at.rowsKey()}
|
v := nodeVisit{n, at.group, at.wholeTable, w.pinsID(&at.pins), w.pinsID(&at.wholePins)}
|
||||||
if w.seen[v] {
|
if w.seen[v] {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -305,15 +335,12 @@ func (w *drawWalk) walk(n node, at drawAt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rowsKey spells the rows the walk stands in, pinned and whole, for a map.
|
|
||||||
func (at drawAt) rowsKey() string { return at.pins.mapKey() + "|" + at.wholePins.mapKey() }
|
|
||||||
|
|
||||||
// edge records the reference an edge reads, then walks on with every row the read
|
// edge records the reference an edge reads, then walks on with every row the read
|
||||||
// pins entered, so a selected row renders only its own cells.
|
// pins entered, so a selected row renders only its own cells.
|
||||||
func (w *drawWalk) edge(from node, e renderEdge, at drawAt) {
|
func (w *drawWalk) edge(from node, e renderEdge, at drawAt) {
|
||||||
if a, reads := refRead(from, e.label); reads {
|
if a, reads := refRead(from, e.label); reads {
|
||||||
tr := tableReadOf(from.(*template).head(a.key), a, e.to)
|
tr := tableReadOf(from.(*template).head(a.key), a, e.to)
|
||||||
if k := (readKey{at.group, a.path, at.rowsKey()}); !w.read[k] {
|
if k := (readKey{at.group, a.path, w.pinsID(&at.pins), w.pinsID(&at.wholePins)}); !w.read[k] {
|
||||||
w.read[k] = true
|
w.read[k] = true
|
||||||
w.reads = append(w.reads, pathRead{at, a, tr})
|
w.reads = append(w.reads, pathRead{at, a, tr})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"maps"
|
"maps"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type tablePin struct {
|
type tablePin struct {
|
||||||
@@ -163,15 +162,3 @@ func (p *pinSet) differs(q *pinSet) bool {
|
|||||||
})
|
})
|
||||||
return found
|
return found
|
||||||
}
|
}
|
||||||
|
|
||||||
// mapKey spells the set for a map, by the tables' identities in path order.
|
|
||||||
func (p *pinSet) mapKey() string {
|
|
||||||
var pins []tablePin
|
|
||||||
p.each(func(t *table, r int) { pins = append(pins, tablePin{t, r}) })
|
|
||||||
sort.Slice(pins, func(i, j int) bool { return pins[i].t.path < pins[j].t.path })
|
|
||||||
var b strings.Builder
|
|
||||||
for _, q := range pins {
|
|
||||||
fmt.Fprintf(&b, "%p[%d]", q.t, q.row)
|
|
||||||
}
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ Shape 5.8, Self-sufficiency 5.7), every seat capped by Locality, all nine naming
|
|||||||
|
|
||||||
This round, in order:
|
This round, in order:
|
||||||
|
|
||||||
- Key `drawWalk`'s visits by the pins, not `rowsKey`'s `%p` strings, and make leaving
|
|
||||||
`wholeTable` out of the key fail loudly where `checkOwnFamily` has not run: the walk is
|
|
||||||
sound only because another fence ran first, and nothing at the walk enforces it.
|
|
||||||
- Split `hold`'s two lifetimes, the expansion's sibling hold and the render's group
|
- Split `hold`'s two lifetimes, the expansion's sibling hold and the render's group
|
||||||
hold, into two types, and stop `readField` rewriting `sc.pins`: which pins a column
|
hold, into two types, and stop `readField` rewriting `sc.pins`: which pins a column
|
||||||
reads depends on which distant caller last overrode them, the cost seven seats named.
|
reads depends on which distant caller last overrode them, the cost seven seats named.
|
||||||
|
|||||||
Reference in New Issue
Block a user