Give whole one meaning, the bare table read, and name the pinned row pinnedRow, landsRow and compileRowFormat

This commit is contained in:
2026-09-26 15:22:30 +02:00
committed by Lillem4n
parent 203b235fdd
commit c1b928a3f5
11 changed files with 23 additions and 25 deletions
+3 -2
View File
@@ -32,8 +32,9 @@ package fejkdata
// `pinSet`, `pinSet.pin`, `table.drawIn`. // `pinSet`, `pinSet.pin`, `table.drawIn`.
// - family — a table and every table reaching it through a chain of // - family — a table and every table reaching it through a chain of
// `table.parentT`, named by the root that chain ends at: `table.family`. // `table.parentT`, named by the root that chain ends at: `table.family`.
// - whole — a read that lands on a `tableRow`, so the row renders through its table's // - whole — a read of a table with no selector and no descent, {/city}, landing on
// format: `tableRead.landsWhole` says a read did, `table.wholeRow` is the node. // the `table` itself: it draws a row apart from every pin, so the fences keep the rows
// its cells stand in as `drawAt.wholePins`, beside `drawAt.wholeTable`.
// - fence — a load-time check, so rendering a compiled tree cannot fail: `New` // - fence — a load-time check, so rendering a compiled tree cannot fail: `New`
// runs them over the data set, `NewTemplate` and `FakeStruct` over what those // runs them over the data set, `NewTemplate` and `FakeStruct` over what those
// compile. The draw fences are `heldCheck`, `drawCheck` and `checkFamilies`. // compile. The draw fences are `heldCheck`, `drawCheck` and `checkFamilies`.
+1 -1
View File
@@ -95,7 +95,7 @@ func vocabulary(t *testing.T, files []*ast.File) string {
} }
// declaredSymbols is every name the package declares at the top level, a method and // declaredSymbols is every name the package declares at the top level, a method and
// a struct field keyed under its type: pinSet.pin, tableRead.landsWhole. // a struct field keyed under its type: pinSet.pin, tableRead.landsRow.
func declaredSymbols(files []*ast.File) map[string]bool { func declaredSymbols(files []*ast.File) map[string]bool {
names := declaredFuncs(files) names := declaredFuncs(files)
for _, f := range files { for _, f := range files {
+1 -1
View File
@@ -301,7 +301,7 @@ func (w *drawWalk) check() error {
if into.at.group != level.at.group || alternatives(level.at, into.at) { if into.at.group != level.at.group || alternatives(level.at, into.at) {
continue continue
} }
if strings.HasPrefix(into.a.path, level.a.path+".") && !(level.tr != nil && level.tr.landsWhole) { if strings.HasPrefix(into.a.path, level.a.path+".") && !(level.tr != nil && level.tr.landsRow) {
return overlapError(level.at.route, level.a.spelling, into) return overlapError(level.at.route, level.a.spelling, into)
} }
} }
+1 -1
View File
@@ -129,7 +129,7 @@ func renderRoot(s *session, t *template) {
var set holdSet var set holdSet
sc := renderScope{set: &set} sc := renderScope{set: &set}
sc.hold().pins.pin(t.table, r) sc.hold().pins.pin(t.table, r)
render(s, t.table.wholeRow, sc) render(s, t.table.pinnedRow, sc)
} }
case t.cellOf != nil: case t.cellOf != nil:
sc.t, sc.row = t.cellOf, t.cellRow sc.t, sc.row = t.cellOf, t.cellRow
+6 -6
View File
@@ -10,11 +10,11 @@ import (
// row pinned, and their unpinned ancestors — each selector's spelling, and whether // row pinned, and their unpinned ancestors — each selector's spelling, and whether
// it lands on a row rendered whole. // it lands on a row rendered whole.
type tableRead struct { type tableRead struct {
headTable *table headTable *table
pins pinSet pins pinSet
drawn map[*table]bool drawn map[*table]bool
sels []tableSel sels []tableSel
landsWhole bool landsRow bool
} }
// tableSel is one selector on the way: the table it selects a row of, and the path // tableSel is one selector on the way: the table it selects a row of, and the path
@@ -44,7 +44,7 @@ func tableReadOf(head node, a arm, leaf node) *tableRead {
cur = d cur = d
} }
} }
_, tr.landsWhole = leaf.(*tableRow) _, tr.landsRow = leaf.(*tableRow)
return tr return tr
} }
+1 -1
View File
@@ -61,7 +61,7 @@ type renderTrace struct {
// readHold is the hold a held read keeps its draw in: for a reference that reads a path, // readHold is the hold a held read keeps its draw in: for a reference that reads a path,
// the render's hold for its group, so its draw spans the render; for a sibling, or a // the render's hold for its group, so its draw spans the render; for a sibling, or a
// reference read whole, held. // bare reference, held.
func readHold(held *hold, sc renderScope, a arm) *hold { func readHold(held *hold, sc renderScope, a arm) *hold {
if isRef(a.key) && len(a.tail) > 0 { if isRef(a.key) && len(a.tail) > 0 {
return sc.hold() return sc.hold()
+1 -1
View File
@@ -43,7 +43,7 @@ func (*nullItem) isNode() {}
// that many times and joins the results with separator (default ""), each render // that many times and joins the results with separator (default ""), each render
// an independent pick. A format holding a reference compiles in `linkTemplateRefs`. // an independent pick. A format holding a reference compiles in `linkTemplateRefs`.
type template struct { type template struct {
// Filled by `compileString`, `compileTemplate` and `table.compileWhole`: // Filled by `compileString`, `compileTemplate` and `table.compileRowFormat`:
format string format string
tokens []formatToken tokens []formatToken
fields map[string]node fields map[string]node
+1 -1
View File
@@ -268,7 +268,7 @@ func walkTable(t *table, tail []string, w pathWalk, descended bool) (node, error
case len(tail) == 0 && sel == "" && !descended: case len(tail) == 0 && sel == "" && !descended:
return walkPath(t, nil, w) return walkPath(t, nil, w)
case len(tail) == 0: case len(tail) == 0:
return walkPath(t.wholeRow, nil, w) return walkPath(t.pinnedRow, nil, w)
case child != nil: case child != nil:
return walkTable(child, tail[1:], w, true) return walkTable(child, tail[1:], w, true)
} }
+7 -7
View File
@@ -20,8 +20,8 @@ type table struct {
header []string header []string
col map[string]int col map[string]int
fields map[string]node // column nodes, the format's fields fields map[string]node // column nodes, the format's fields
wholeRow *tableRow // the pinned row rendered by the format pinnedRow *tableRow
cells []string // rows × columns, flat cells []string // rows × columns, flat
cellTemplates map[int]*template cellTemplates map[int]*template
keyIndex int // keyIndex through parentIndex are column indexes, -1 where the option is absent keyIndex int // keyIndex through parentIndex are column indexes, -1 where the option is absent
nameIndex int nameIndex int
@@ -103,7 +103,7 @@ func compileTable(m map[string]any, category string, files *categoryFiles) (*tab
if err := t.checkCells(); err != nil { if err := t.checkCells(); err != nil {
return nil, fmt.Errorf("%s: %w", o.rows, err) return nil, fmt.Errorf("%s: %w", o.rows, err)
} }
if err := t.compileWhole(o.format); err != nil { if err := t.compileRowFormat(o.format); err != nil {
return nil, err return nil, err
} }
return t, nil return t, nil
@@ -321,9 +321,9 @@ func (t *table) checkCells() error {
return nil return nil
} }
// compileWhole compiles the format a row renders whole through, over the columns // compileRowFormat compiles the format a row renders through, over the columns as its
// as its fields. // fields.
func (t *table) compileWhole(format string) error { func (t *table) compileRowFormat(format string) error {
toks, err := parseFormat(format) toks, err := parseFormat(format)
if err != nil { if err != nil {
return err return err
@@ -343,7 +343,7 @@ func (t *table) compileWhole(format string) error {
return err return err
} }
t.formatTemplate = &template{format: format, tokens: toks, fields: t.fields, repeat: 1, isRecord: true, table: t} t.formatTemplate = &template{format: format, tokens: toks, fields: t.fields, repeat: 1, isRecord: true, table: t}
t.wholeRow = &tableRow{t} t.pinnedRow = &tableRow{t}
return t.formatTemplate.compileRefFree() return t.formatTemplate.compileRefFree()
} }
+1 -1
View File
@@ -599,7 +599,7 @@ func TestTableRowsAreAlternatives(t *testing.T) {
"a cell reaching a table whose rows are alternatives": {"country.tsv": "alpha2\tname\tmoney\nFI\tFinland\t{/y.sym}\nSE\tSweden\t{/cur[SEK].sym}\n"}, "a cell reaching a table whose rows are alternatives": {"country.tsv": "alpha2\tname\tmoney\nFI\tFinland\t{/y.sym}\nSE\tSweden\t{/cur[SEK].sym}\n"},
"a cell agreeing with the row it selects": {"country.tsv": "alpha2\tname\tmoney\nFI\tFinland\t{/y[1].sym} {/cur[SEK].sym}\nSE\tSweden\t{/cur[SEK].sym}\n"}, "a cell agreeing with the row it selects": {"country.tsv": "alpha2\tname\tmoney\nFI\tFinland\t{/y[1].sym} {/cur[SEK].sym}\nSE\tSweden\t{/cur[SEK].sym}\n"},
"a selected row's cell beside the row it agrees with": {"z.json": `"{/country[SE].money} {/cur[SEK].sym}"`}, "a selected row's cell beside the row it agrees with": {"z.json": `"{/country[SE].money} {/cur[SEK].sym}"`},
"a selected row whole beside the row it agrees with": {"z.json": `"{/country[SE]} {/cur[SEK].sym}"`}, "a selected row beside the row it agrees with": {"z.json": `"{/country[SE]} {/cur[SEK].sym}"`},
"a column under a selected ancestor": { "a column under a selected ancestor": {
"city.json": `{"format":"{name} {money}","rows":"city.tsv","key":"name","parent":"country"}`, "city.json": `{"format":"{name} {money}","rows":"city.tsv","key":"name","parent":"country"}`,
"city.tsv": "name\tcountry\tmoney\nHelsinki\tFI\t{/cur[EUR].sym}\nMalmö\tSE\t{/cur[SEK].sym}\nLund\tSE\t{/cur[SEK].sym}\n", "city.tsv": "name\tcountry\tmoney\nHelsinki\tFI\t{/cur[EUR].sym}\nMalmö\tSE\t{/cur[SEK].sym}\nLund\tSE\t{/cur[SEK].sym}\n",
-3
View File
@@ -21,9 +21,6 @@ Self-sufficiency 5.6), every seat capped by Locality, and all nine naming
This round, in order: This round, in order:
- Give "whole" one meaning: `doc.go` defines it as a read landing on a `tableRow`,
while `drawAt.wholeTable`, `checkFamilyPair` and `checkOwnFamily`'s comment use it for
a bare read landing on a `*table`, the one that draws without pinning.
- Give a table's current row one owner: `renderScope.t` and `row` hold it beside the - Give a table's current row one owner: `renderScope.t` and `row` hold it beside the
`pinSet`, and `renderLeaf` reads a column's null back from a hold `readField` wrote. `pinSet`, and `renderLeaf` reads a column's null back from a hold `readField` wrote.
- Split `walkPath`'s four modes, so a caller does not select a behaviour by which of - Split `walkPath`'s four modes, so a caller does not select a behaviour by which of