Record each selector's table and spelling in pathProbe.readRow

This commit is contained in:
2026-09-29 09:20:20 +02:00
committed by Lillem4n
parent 2499e71809
commit 2e553d29f7
4 changed files with 24 additions and 28 deletions
+20 -10
View File
@@ -289,10 +289,13 @@ func (w *pathCover) walk(n node, tail []string) (node, error) {
// pathProbe proves a path resolves without drawing. Where pathCheck walks every // pathProbe proves a path resolves without drawing. Where pathCheck walks every
// variant of a choice, it walks the first, which carriedByAll lets stand for all; at a // variant of a choice, it walks the first, which carriedByAll lets stand for all; at a
// table it selects as pathCheck does and marks in drawn the tables a draw would pin. // table it selects as pathCheck does. Probing an arm, it records what the read takes:
// in drawn the tables a draw would pin, and in sels each selector's table and spelling.
type pathProbe struct { type pathProbe struct {
pins pinSet pins pinSet
a *arm
drawn map[*table]bool drawn map[*table]bool
sels []tableSel
} }
func (w *pathProbe) walk(n node, tail []string) (node, error) { func (w *pathProbe) walk(n node, tail []string) (node, error) {
@@ -310,7 +313,7 @@ func (w *pathProbe) walk(n node, tail []string) (node, error) {
if r, err = x.route(tail, descended); err != nil { if r, err = x.route(tail, descended); err != nil {
return nil, err return nil, err
} }
if err := w.readRow(x, r); err != nil { if err := w.readRow(x, tail, r); err != nil {
return nil, err return nil, err
} }
n, tail, descended = r.next, r.rest, r.descends n, tail, descended = r.next, r.rest, r.descends
@@ -324,15 +327,22 @@ func (w *pathProbe) walk(n node, tail []string) (node, error) {
return n, nil return n, nil
} }
func (w *pathProbe) readRow(t *table, r tableRoute) error { func (w *pathProbe) readRow(t *table, tail []string, r tableRoute) error {
if r.sel != "" { switch {
case r.sel != "":
if w.a != nil {
walked := len(w.a.tail) - len(tail) + 1
written := w.a.spelling[:len(w.a.spelling)-len(joinSegments(w.a.tail))]
w.sels = append(w.sels, tableSel{t, written + joinSegments(w.a.tail[:walked])})
}
return w.pins.selectRow(t, r.sel) return w.pins.selectRow(t, r.sel)
} case r.draw && w.a != nil:
if !r.draw { if w.drawn == nil {
return nil w.drawn = map[*table]bool{}
} }
for stop := w.pins.nearestPinned(t); t != stop; t = t.parentT { for stop := w.pins.nearestPinned(t); t != stop; t = t.parentT {
w.drawn[t] = true w.drawn[t] = true
}
} }
return nil return nil
} }
+3 -14
View File
@@ -191,21 +191,10 @@ func tableReadOf(head node, a arm, leaf node) *tableRead {
if !isTable { if !isTable {
return nil return nil
} }
probe := &pathProbe{drawn: map[*table]bool{}} probe := &pathProbe{a: &a}
_, _ = probe.walk(t, a.tail) _, _ = probe.walk(t, a.tail)
tr := &tableRead{headTable: t, pins: probe.pins, drawn: probe.drawn} _, landsRow := leaf.(*tableRow)
written := a.spelling[:len(a.spelling)-len(joinSegments(a.tail))] return &tableRead{headTable: t, pins: probe.pins, drawn: probe.drawn, sels: probe.sels, landsRow: landsRow}
cur := t
for i, seg := range a.tail {
switch d := cur.descendant(seg); {
case isSelector(seg):
tr.sels = append(tr.sels, tableSel{cur, written + joinSegments(a.tail[:i+1])})
case d != nil:
cur = d
}
}
_, tr.landsRow = leaf.(*tableRow)
return tr
} }
// selected is the selector in r on t, or on the nearest ancestor of t it selects. // selected is the selector in r on t, or on the nearest ancestor of t it selects.
+1 -1
View File
@@ -39,7 +39,7 @@ func (f *Generator) Fake(path string) (string, error) {
// selects or draws. // selects or draws.
func descend(s *session, root node, segments []string, sc renderScope) (node, error) { func descend(s *session, root node, segments []string, sc renderScope) (node, error) {
// docs/decisions.md#a-path-is-walked-once-without-drawing-before-it-is-walked-for-real // docs/decisions.md#a-path-is-walked-once-without-drawing-before-it-is-walked-for-real
if _, err := (&pathProbe{drawn: map[*table]bool{}}).walk(root, segments); err != nil { if _, err := (&pathProbe{}).walk(root, segments); err != nil {
return nil, err return nil, err
} }
return drawPath(root, segments, "", &pathDraw{s: s, pins: &sc.groupHold().pins}), nil return drawPath(root, segments, "", &pathDraw{s: s, pins: &sc.groupHold().pins}), nil
-3
View File
@@ -28,9 +28,6 @@ ranking `readSurvey.walk` hardest and all seven the unit they would least modify
This round, in order: This round, in order:
- Record each selector's table and spelling in `pathProbe.readRow`, and delete
`tableReadOf`'s second walk over the tail: it steps by `descendant` apart from
`route`, so a route that steps up to a parent row credits a selector to the wrong table.
- Move the render's read path — `readField`, `readReference`, `readHeld`, `traceRead`, - Move the render's read path — `readField`, `readReference`, `readHeld`, `traceRead`,
`renderLeaf`, `resolveChoice`, `renderOnce` and `expandAnew` — into `render.go`, and `renderLeaf`, `resolveChoice`, `renderOnce` and `expandAnew` — into `render.go`, and
merge what `hold.go` and `holdset.go` keep into one file: both architects followed one read merge what `hold.go` and `holdset.go` keep into one file: both architects followed one read