From d279408ba523093729f1ba5e27a7813591db92d1 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Wed, 30 Sep 2026 19:57:29 +0200 Subject: [PATCH] Step a table's routes past its selector, and panic on an arm with no bound head --- docs/decisions.md | 5 ++--- path.go | 1 + reference.go | 8 +++++--- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/decisions.md b/docs/decisions.md index 2ab0cd1..2aef6aa 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -846,9 +846,8 @@ the direct chain is the one a reader can predict from the tables' parents. 2026-09-28, larv-review on systems-architect's finding; approved 2026-09-28 by lilleman. Re-tested 2026-09-29 by collapsing them into one loop switching on a mode field. -Goals 2 and 11: `pathCheck`, `pathProbe` and `pathDraw` stay separate loops; `pathCover` -became the cover `pathCheck` compiles, on 2026-09-30. -One loop fails `perf_test.go`: the check's leaves, the probe's selectors and the errors +Goals 2 and 11: `pathCheck`, `pathProbe` and `pathDraw` stay separate loops. +One loop fails `perf_test.go`: the check's leaves and the errors naming a level leak the walker's contents, and Go tracks a struct's fields as one, so the draw's pins, arm and memo leak with them. Held by pointer, a repeat of a reference path rose from 66 to 106 allocations; copied into the walker by value, diff --git a/path.go b/path.go index 9659ce8..a7c10a6 100644 --- a/path.go +++ b/path.go @@ -278,6 +278,7 @@ func (w *pathCheck) tableSteps(t *table, r tableRoute, tail []string) error { } row, _ := w.pins.pinned(t) w.emit(pathStep{kind: stepSelect, name: r.sel, row: row}, tail) + tail = tail[1:] } if r.draw { w.emit(pathStep{kind: stepDraw}, tail) diff --git a/reference.go b/reference.go index 833b0f7..f2ac8cb 100644 --- a/reference.go +++ b/reference.go @@ -113,10 +113,12 @@ func compileArms(t *template) { } func compileArm(t *template, a *arm) { - if head := t.head(a.head); head != nil { - w := compilePath(head, a.tail) - a.steps, a.leaves, a.cover = w.steps, w.leaves, w.cover + head := t.head(a.head) + if head == nil { + panic(internalError("{%s} reads a head nothing bound", a.spelling)) } + w := compilePath(head, a.tail) + a.steps, a.leaves, a.cover = w.steps, w.leaves, w.cover } // resolveLink binds every reference t reads, refusing one to t's own category, and keys