77 lines
2.5 KiB
Go
77 lines
2.5 KiB
Go
package fejkdata
|
|
|
|
// drawMemo is what a named pick has drawn: the variant each level was drawn as, so every path
|
|
// under it reads one variant; the value each read produced, by its path, so the same read written
|
|
// 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.
|
|
type drawMemo struct {
|
|
variant map[string]node
|
|
value map[string]readValue
|
|
enteredFrames map[*nameScope]*pickFrame
|
|
steppedDown map[string]*pinSet
|
|
}
|
|
|
|
// 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.
|
|
func (m *drawMemo) stepDownPins(pins *pinSet, t *table, levels []string, at int) *pinSet {
|
|
if m == nil {
|
|
return pins.above(t)
|
|
}
|
|
p, ok := m.steppedDown[levels[at]]
|
|
if !ok {
|
|
p = pins.above(t)
|
|
if m.steppedDown == nil {
|
|
m.steppedDown = map[string]*pinSet{}
|
|
}
|
|
m.steppedDown[levels[at]] = p
|
|
}
|
|
return p
|
|
}
|
|
|
|
// readValue is what one read drew: its text, and whether it landed on a null.
|
|
type readValue struct {
|
|
text string
|
|
null bool
|
|
}
|
|
|
|
// renderScope is where a render reads: the frames of the name scopes rendering; and row, the row
|
|
// of the table rendering, which its columns read. It passes by value, and what is read from it
|
|
// reaches a map key, an interface or a func value only as a copy; else sc, and with it every
|
|
// render's frames, moves to the heap.
|
|
type renderScope struct {
|
|
frames *frameStack
|
|
row renderedRow
|
|
// 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; pickKey is the path from the name
|
|
// to what renders.
|
|
pick *namedPick
|
|
pickKey string
|
|
}
|
|
|
|
type renderedRow struct {
|
|
t *table
|
|
index int
|
|
}
|
|
|
|
// at is the scope n, the leaf of a path that pinned its rows in pins, renders in: where n is a
|
|
// table's row or column, at the row pins holds for that table.
|
|
func (sc renderScope) at(n node, pins *pinSet) renderScope {
|
|
switch n := n.(type) {
|
|
case *tableRow:
|
|
sc.row = renderedRow{n.t, pins.mustRow(n.t)}
|
|
case *tableColumn:
|
|
sc.row = renderedRow{n.t, pins.mustRow(n.t)}
|
|
}
|
|
return sc
|
|
}
|
|
|
|
// rowOf is the row of t its columns render from.
|
|
func (sc renderScope) rowOf(t *table) int {
|
|
if sc.row.t != t {
|
|
panic(internalError("a column of %s renders in a scope holding no row of it", t.segment))
|
|
}
|
|
return sc.row.index
|
|
}
|