Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33
+7
-17
@@ -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
|
||||
|
||||
@@ -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
@@ -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 + "}"})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user