Add the table node: rows TSV, key and name selection, linked tables drawn consistently, and the choice-of-rows fence

This commit is contained in:
2026-09-17 12:28:46 +02:00
parent d4060e041a
commit f6b54c8ae6
20 changed files with 1517 additions and 151 deletions
+18 -8
View File
@@ -109,7 +109,7 @@ func operandReader(t *template, head string) string {
// coverPath collects what holding one path pins: every choice level the path
// passes through, whole, and the leaf it renders.
func coverPath(n node, tail []string, into map[node]bool) {
_ = walkPath(n, tail, pathWalk{
_, _ = walkPath(n, tail, pathWalk{
choice: func(c *choice, _ []string) ([]node, error) { cover(c, into, false); return nil, nil },
leaf: func(n node) error { cover(n, into, false); return nil },
})
@@ -262,6 +262,16 @@ func checkNoRepeatedRead(format string, c formatOps, refs map[string]refBinding)
type draws struct {
variant map[string]node
value map[string]draw
pins [4]tablePin // the rows pinned, inline so a render pinning a few tables stays off the heap
npins int
more map[*table]int // the rows pinned past the inline four
s *session // what draws a row; nil where a walk only proves selectors
}
// tablePin is one table's pinned row.
type tablePin struct {
t *table
row int
}
// draw is what one read drew: its text, and whether it landed on a null.
@@ -284,12 +294,11 @@ func readField(s *session, t *template, held *draws, sc drawScope, a arm) draw {
}
return draw{text: render(s, t.fields[a.key], sc)}
}
d := readScope(held, sc, a)
d := readScope(s, held, sc, a)
if r, done := d.value[a.path]; done {
return r
}
var r draw
_ = walkPath(t.fields[a.key], a.tail, pathWalk{
leaf, _ := walkPath(t.fields[a.key], a.tail, pathWalk{
// Hold the draw at every level passed through, so two paths sharing a
// prefix share it.
choice: func(c *choice, rest []string) ([]node, error) {
@@ -307,8 +316,9 @@ func readField(s *session, t *template, held *draws, sc drawScope, a arm) draw {
}
return []node{n}, nil
},
leaf: func(n node) error { r = renderLeaf(s, n, sc); return nil },
pins: d,
})
r := renderLeaf(s, leaf, sc)
if d.value == nil {
d.value = map[string]draw{}
}
@@ -319,9 +329,9 @@ func readField(s *session, t *template, held *draws, sc drawScope, a arm) draw {
// readScope is the draws a held read keeps its draw in: for a reference that reads a path,
// the render's draws for its group, so its draw spans the render; for a sibling, or a
// reference read whole, held.
func readScope(held *draws, sc drawScope, a arm) *draws {
func readScope(s *session, held *draws, sc drawScope, a arm) *draws {
if isRef(a.key) && len(a.tail) > 0 {
return sc.draws()
return sc.draws(s)
}
return held
}
@@ -335,7 +345,7 @@ func renderLeaf(s *session, n node, sc drawScope) draw {
}
r := draw{text: render(s, n, sc)}
if t, _ := n.(*template); t != nil && t.readsColumn != nil {
r.null = sc.in(t).draws().value[t.readsColumn.a.path].null
r.null = sc.in(t).draws(s).value[t.readsColumn.a.path].null
}
return r
}