Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33

Open
lilleman wants to merge 966 commits from worktree-todo-relative-dates-exact-counts into main
4 changed files with 30 additions and 35 deletions
Showing only changes of commit 010bcd15bc - Show all commits
+7 -17
View File
@@ -96,8 +96,8 @@ func checkOwnFamily(t *template) error {
}
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.familyRoot() == own.familyRoot() {
if e.readsRef() {
if head, isTable := n.(*template).head(e.read.key).(*table); isTable && head.familyRoot() == own.familyRoot() {
return e, head, true
}
}
@@ -161,7 +161,7 @@ func (c *drawCheck) hasRead(n node, stopAtGroup bool) bool {
}
r := false
for _, e := range renderEdges(n) {
if readsOnEdge(n, e.label) || (walksInto(e.to, stopAtGroup) && c.hasRead(e.to, stopAtGroup)) {
if readsOnEdge(n, e) || (walksInto(e.to, stopAtGroup) && c.hasRead(e.to, stopAtGroup)) {
r = true
break
}
@@ -173,9 +173,8 @@ func (c *drawCheck) hasRead(n node, stopAtGroup bool) bool {
return r
}
func readsOnEdge(n node, label string) bool {
a, isRef := refRead(n, label)
return isRef && (len(a.tail) > 0 || readsTable(n, a))
func readsOnEdge(n node, e renderEdge) bool {
return e.readsRef() && (len(e.read.tail) > 0 || readsTable(n, e.read))
}
func walksInto(to node, stopAtGroup bool) bool {
@@ -203,16 +202,6 @@ func readsTable(n node, a arm) bool {
return isTable
}
// refRead is the reference an edge of n reads; false when the edge reads none.
func refRead(n node, label string) (arm, bool) {
t, isTemplate := n.(*template)
if !isTemplate {
return arm{}, false
}
a := splitArm(label, t.link.refs)
return a, isRef(a.key)
}
// checkColumnDraws fences a record's columns as one render.
func checkColumnDraws(t *template, columns []string) error { return columnDraws(t, columns).check() }
@@ -342,7 +331,8 @@ func (w *drawWalk) walk(n node, at drawAt) {
// 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.
func (w *drawWalk) edge(from node, e renderEdge, at drawAt) {
if a, reads := refRead(from, e.label); reads {
if e.readsRef() {
a := e.read
tr := tableReadOf(from.(*template).head(a.key), a, e.to)
if k := (readKey{at.group, a.path, w.pinsID(&at.pins), w.pinsID(&at.wholePins)}); !w.read[k] {
w.read[k] = true
+9 -4
View File
@@ -96,15 +96,20 @@ func sortedNames(m map[string]node) []string {
}
// renderEdge is a child a node renders into, labelled by what reaches it (a field
// name, reference, or choice index) for a readable cycle report. operand names
// the builtin when the label is its operand rather than a token, so an error can
// name it the way the author wrote it.
// name, reference, or choice index) for a readable cycle report. read is the linked
// arm a template's edge reads, zero on any other. operand names the builtin when the
// label is its operand rather than a token, so an error can name it the way the
// author wrote it.
type renderEdge struct {
to node
label string
read arm
operand string
}
// readsRef reports whether the edge reads a reference.
func (e renderEdge) readsRef() bool { return isRef(e.read.key) }
// reached names an edge as the author spelled it, the vocabulary pathKeyReaders uses
// for the sibling fence.
func (e renderEdge) reached() string {
@@ -133,7 +138,7 @@ func renderEdges(n node) []renderEdge {
return
}
for _, leaf := range pathLeaves(c, a.tail) {
es = append(es, renderEdge{leaf, a.spelling, operand})
es = append(es, renderEdge{leaf, a.spelling, a, operand})
}
}
for _, o := range n.compiled.ops {
+14 -12
View File
@@ -56,8 +56,8 @@ func heldNodes(t *template, name string, readers []reader) map[node]bool {
return held
}
for _, r := range readers {
if a := splitArm(r.spelling, t.link.refs); a.key == name {
coverPath(t.head(name), a.tail, held)
if r.a.key == name {
coverPath(t.head(name), r.a.tail, held)
}
}
return held
@@ -74,7 +74,7 @@ func checkNameHeld(t *template, name string, readers []reader) error {
reader, isPath := t.compiled.pathKeys[name]
seen := map[node]bool{}
for _, e := range renderEdges(t) {
if splitArm(e.label, t.link.refs).key == name || !renders(e.to, held, seen) {
if e.read.key == name || !renders(e.to, held, seen) {
continue
}
if isPath {
@@ -134,7 +134,7 @@ func operandDraw(n node, into map[node]bool) {
}
into[n] = true
for _, e := range renderEdges(n) {
if isRef(e.label) {
if e.readsRef() {
continue
}
operandDraw(e.to, into)
@@ -181,20 +181,22 @@ func checkNoOverlap(ops []op, pathKeys map[string]string) error {
names := pathKeyReaders(ops, pathKeys)
// Stable over one format-order scan, so two readers of one name (a token and a
// calc operand both naming "p") are reported as the format writes them.
sort.SliceStable(names, func(i, j int) bool { return names[i].path < names[j].path })
sort.SliceStable(names, func(i, j int) bool { return names[i].a.path < names[j].a.path })
for i, level := range names {
for _, path := range names[i+1:] {
if strings.HasPrefix(path.path, level.path+".") {
return fmt.Errorf("%s renders a level that {%s} reads a path into; name the fields you want instead", level.label, path.spelling)
if strings.HasPrefix(path.a.path, level.a.path+".") {
return fmt.Errorf("%s renders a level that {%s} reads a path into; name the fields you want instead", level.label, path.a.spelling)
}
}
}
return nil
}
// reader is one way a format reaches a path key: as written, by its path,
// and how to name it.
type reader struct{ spelling, path, label string }
// reader is one way a format reaches a path key, and how to name it.
type reader struct {
a arm
label string
}
// pathKeyReaders lists every way a format reaches a sibling path key, in the order the
// format writes them. An operand renders its field, so it names a level exactly
@@ -204,12 +206,12 @@ func pathKeyReaders(ops []op, pathKeys map[string]string) []reader {
for _, o := range ops {
for _, a := range o.operands {
if _, isPathKey := pathKeys[a.key]; isPathKey && !isRef(a.key) {
names = append(names, reader{a.spelling, a.path, fmt.Sprintf("%s operand %q", o.fn, a.spelling)})
names = append(names, reader{a, fmt.Sprintf("%s operand %q", o.fn, a.spelling)})
}
}
for _, a := range o.arms {
if _, isPathKey := pathKeys[a.key]; isPathKey && !isRef(a.key) {
names = append(names, reader{a.spelling, a.path, "token {" + a.spelling + "}"})
names = append(names, reader{a, "token {" + a.spelling + "}"})
}
}
}
-2
View File
@@ -23,8 +23,6 @@ Shape 5.8, Self-sufficiency 5.7), every seat capped by Locality, all nine naming
This round, in order:
- Carry the arm on `renderEdge` so `graph.go`, `drawfence.go` and `holdfence.go` stop
re-parsing `label` through `splitArm`, whose key differs before and after link.
- Give `pathCover` a doc comment and say in each path walk's comment how it differs from
`pathCheck` at a choice and a table: every seat diffed the four loops by eye.
- Make `disagreement` a table keyed by the two datatypes and the proof, dropping the