diff --git a/drawfence.go b/drawfence.go index f54da29..01adc1e 100644 --- a/drawfence.go +++ b/drawfence.go @@ -75,6 +75,44 @@ func (c *drawCheck) checkDraws(path string, n node) error { return nil } +// checkOwnFamily refuses a table's format or cell that reads, however many templates +// away and through a repeat or a draw group too, a table of its own family: a whole +// read draws its row without pinning it, so the family would draw apart from the row +// it renders, whichever draws the reaching template holds. +// docs/decisions.md#a-table-never-reaches-its-own-family-by-any-route +func checkOwnFamily(t *template) error { + own := t.table + if own == nil { + own = t.cellOf + } + if own == nil { + return nil + } + seen := map[node]bool{} + var find func(n node) (renderEdge, *table, bool) + find = func(n node) (renderEdge, *table, bool) { + if seen[n] { + return renderEdge{}, nil, false + } + seen[n] = true + for _, e := range renderEdges(n) { + if a, isRef := refRead(n, e.label); isRef { + if head, isTable := n.(*template).head(a.key).(*table); isTable && head.family() == own.family() { + return e, head, true + } + } + if e, head, found := find(e.to); found { + return e, head, true + } + } + return renderEdge{}, nil, false + } + if e, head, found := find(t); found { + return fmt.Errorf("%s reads %s, a table of its own family, which a bare read of %s would draw apart from the row it renders; read the family from a template beside it, or add the value as a column", e.reached(), head.category, own.category) + } + return nil +} + func renderDraws(t *template) *drawWalk { w := newDrawWalk() for _, e := range renderEdges(t) { @@ -483,41 +521,3 @@ func (r *tableRead) replay(d *pinSet) error { }) return err } - -// checkOwnFamily refuses a table's format or cell that reads, however many templates -// away and through a repeat or a draw group too, a table of its own family: a whole -// read draws its row without pinning it, so the family would draw apart from the row -// it renders, whichever draws the reaching template holds. -// docs/decisions.md#a-table-never-reaches-its-own-family-by-any-route -func checkOwnFamily(t *template) error { - own := t.table - if own == nil { - own = t.cellOf - } - if own == nil { - return nil - } - seen := map[node]bool{} - var find func(n node) (renderEdge, *table, bool) - find = func(n node) (renderEdge, *table, bool) { - if seen[n] { - return renderEdge{}, nil, false - } - seen[n] = true - for _, e := range renderEdges(n) { - if a, isRef := refRead(n, e.label); isRef { - if head, isTable := n.(*template).head(a.key).(*table); isTable && head.family() == own.family() { - return e, head, true - } - } - if e, head, found := find(e.to); found { - return e, head, true - } - } - return renderEdge{}, nil, false - } - if e, head, found := find(t); found { - return fmt.Errorf("%s reads %s, a table of its own family, which a bare read of %s would draw apart from the row it renders; read the family from a template beside it, or add the value as a column", e.reached(), head.category, own.category) - } - return nil -}