diff --git a/docs/decisions.md b/docs/decisions.md index edbb4bf..f7d0996 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -412,9 +412,9 @@ another never meet, and each may select its own row of another table; the cells row, and whatever they reach, do meet, and so does the format beside them. The rule the fence applies is that two reads meet unless they sit in rows that never render together: rows falling under different rows of a table a path pinned, two rows of that table -itself included. A table read whole draws its row apart from every pin, so its rows -are alternatives only to each other, and a cell of one meets a read pinning a region -the row is not in. A choice's items get no such treatment yet: two items selecting +itself included. A table read whole draws its row apart from every pin, so the rows of +one whole read are alternatives only to each other, and a cell of one meets a read +pinning an ancestor row the row is not under. A choice's items get no such treatment yet: two items selecting different rows are still refused. ## A table never reaches its own family, by any route diff --git a/drawfence.go b/drawfence.go index 435ff69..ec40eda 100644 --- a/drawfence.go +++ b/drawfence.go @@ -179,14 +179,14 @@ type drawWalk struct { } // drawAt is where a walk stands: the draw group it draws in, how the render's root reached it, the -// table rows it pinned, the table a whole read draws a row of, and the row of it whose cells the -// walk is in. +// table rows it pinned, the table a whole read draws a row of, and the rows of whole draws whose +// cells the walk is in. type drawAt struct { group string route drawRoute alt pinSet drawn *table // left out of the visit keys: only this table's own cells compare against it, which the own-family fence keeps true - whole tablePin + whole pinSet } // drawRoute is how a render reaches a draw: as its author spells it, and the root edge's label. @@ -239,7 +239,8 @@ func (w *drawWalk) walk(n node, at drawAt) { w.edge(n, e, at) case cell.cellOf == at.drawn: in := at - in.whole = tablePin{cell.cellOf, cell.cellRow} + in.whole = at.whole.clone() + in.whole.add(cell.cellOf, cell.cellRow) w.edge(n, e, in) case at.alt.clash(cell.cellOf, cell.cellRow) == nil: in := at @@ -250,12 +251,7 @@ 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 { - if at.whole.t == nil { - return at.alt.key() - } - return fmt.Sprintf("%s%p{%d}", at.alt.key(), at.whole.t, at.whole.row) -} +func (at drawAt) rowsKey() string { return at.alt.key() + "|" + at.whole.key() } // 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. diff --git a/family.go b/family.go index 1123871..55646fb 100644 --- a/family.go +++ b/family.go @@ -219,15 +219,4 @@ func checkOwnFamily(t *template) error { // alternatives reports whether two reads sit in different rows of one table: rows the walks pinned, // or rows of one whole draw. // docs/decisions.md#the-rows-of-a-table-are-alternatives -func alternatives(a, b drawAt) bool { - if a.whole.t != nil && a.whole.t == b.whole.t && a.whole.row != b.whole.row { - return true - } - found := false - a.alt.each(func(t *table, r int) { - if br, in := b.alt.pinned(t); in && br != r { - found = true - } - }) - return found -} +func alternatives(a, b drawAt) bool { return a.alt.differs(&b.alt) || a.whole.differs(&b.whole) } diff --git a/pins.go b/pins.go index f6acc46..4b5e668 100644 --- a/pins.go +++ b/pins.go @@ -153,6 +153,17 @@ func (p pinSet) entered(t *table, r int) pinSet { return p } +// differs reports whether p and q hold different rows of one table. +func (p *pinSet) differs(q *pinSet) bool { + found := false + p.each(func(t *table, r int) { + if qr, in := q.pinned(t); in && qr != r { + found = true + } + }) + return found +} + // key spells the set for a map, by the tables' identities in path order. func (p *pinSet) key() string { var pins []tablePin