diff --git a/README.md b/README.md index 53197b7..6c2f345 100644 --- a/README.md +++ b/README.md @@ -1334,7 +1334,7 @@ draw.go one reference draw per render and group: the draw set a render r drawfence.go the load fences over reference draws: the drawGroup option, and the walk over a render's reads family.go a family of linked tables: what a reference path reads of one, and the fence over paths into it reference.go reference sigils, and binding references across the tree -graph.go the render graph: edges, cycles, the repeat bound, tree walks +graph.go the graph the fences walk: containment and render edges, and the cycle and repeat fences builtins.go the {name()} function registry and its implementations layout.go date and time layouts: the instants one is proved against, and the two samples checksum.go the check characters a derivation appends, and the IBAN they sit inside @@ -1342,7 +1342,7 @@ transform.go the builtins that rewrite an operand's value, and the ASCII fold calc.go the {calc()} arithmetic evaluator: parser, eval, validation datatype.go column datatypes: DataType, where datatype and null may sit, a column's datatype value.go the value proof: what a typed column or calc operand holds, checked at load -data.go data loading: fs.FS folders/files -> namespace tree, multi-source merge +data.go the load path: fs.FS folders/files -> namespace tree, multi-source merge, then the fences in order cmd/fejkdata/ the fejkdata CLI data/ shipped data (JSON, and a TSV per table), embedded at build: locale folders, geo, misc data-import/ the scripts that rebuild each sourced table (see DATA-LICENSES.md) diff --git a/data.go b/data.go index b6549b1..3ad356f 100644 --- a/data.go +++ b/data.go @@ -193,3 +193,55 @@ func mergeChildren(dst, src map[string]node) { dst[k] = v } } + +// nodeScope is the set of nodes one validation pass covers: a whole loaded tree, +// or a single inline node. +type nodeScope func(fn func(path string, n node) error) error + +func treeScope(root map[string]node) nodeScope { + return func(fn func(path string, n node) error) error { return walkNodes(root, fn) } +} + +func inlineScope(n node, label string) nodeScope { + return func(fn func(path string, m node) error) error { return eachNode(n, label, fn) } +} + +func checkScope(s nodeScope) error { + if err := checkColumns(s); err != nil { + return err + } + return checkRenders(s) +} + +// checkRenders runs the per-node fences over a scope, each over the whole scope +// before the next, so which of several broken nodes is reported does not depend on +// the walk. It runs after checkNoCycles, whose guarantee is what lets the walks +// terminate. +func checkRenders(s nodeScope) error { + mem := reachMemo{} + if err := s(func(path string, n node) error { return repeatCheck(path, n, mem) }); err != nil { + return err + } + if err := s(heldCheck); err != nil { + return err + } + fence := &drawCheck{} + refs := false + if err := s(func(path string, n node) error { + if t, ok := n.(*template); ok && len(t.refs) > 0 { + refs = true + } + return fence.checkDrawGroup(path, n) + }); err != nil { + return err + } + if refs { + if err := s(fence.checkDraws); err != nil { + return err + } + if err := s(fence.checkRecordDraws); err != nil { + return err + } + } + return s((&valueProof{}).checkDatatype) +} diff --git a/graph.go b/graph.go index 681cc9d..d0fcf79 100644 --- a/graph.go +++ b/graph.go @@ -185,58 +185,6 @@ func pathLeaves(n node, tail []string) []node { return out } -// nodeScope is the set of nodes one validation pass covers: a whole loaded tree, -// or a single inline node. -type nodeScope func(fn func(path string, n node) error) error - -func treeScope(root map[string]node) nodeScope { - return func(fn func(path string, n node) error) error { return walkNodes(root, fn) } -} - -func inlineScope(n node, label string) nodeScope { - return func(fn func(path string, m node) error) error { return eachNode(n, label, fn) } -} - -func checkScope(s nodeScope) error { - if err := checkColumns(s); err != nil { - return err - } - return checkRenders(s) -} - -// checkRenders runs the per-node fences over a scope, each over the whole scope -// before the next, so which of several broken nodes is reported does not depend on -// the walk. It runs after checkNoCycles, whose guarantee is what lets the walks -// terminate. -func checkRenders(s nodeScope) error { - mem := reachMemo{} - if err := s(func(path string, n node) error { return repeatCheck(path, n, mem) }); err != nil { - return err - } - if err := s(heldCheck); err != nil { - return err - } - fence := &drawCheck{} - refs := false - if err := s(func(path string, n node) error { - if t, ok := n.(*template); ok && len(t.refs) > 0 { - refs = true - } - return fence.checkDrawGroup(path, n) - }); err != nil { - return err - } - if refs { - if err := s(fence.checkDraws); err != nil { - return err - } - if err := s(fence.checkRecordDraws); err != nil { - return err - } - } - return s((&valueProof{}).checkDatatype) -} - type reachMemo map[node]int func (m reachMemo) of(n node) int { diff --git a/todo.md b/todo.md index 0c4cfa7..19215bf 100644 --- a/todo.md +++ b/todo.md @@ -21,9 +21,6 @@ name says whether a unit runs at `New` or at `Fake`. This round, in order: -- Move `nodeScope`, `checkScope` and `checkRenders` out of `graph.go` and refresh the - README Layout lines for `graph.go` and `data.go`: the order every load fence runs in - is the load path's spine, and no file name carries it. - Name the `draw` stem apart: the free `pinned` in `holdfence.go` is not `(*draws).pinned` in `hold.go`, `compileFormat` is a method on both `*template` and `*table`, and `draws`, `drawSet`, `drawScope`, `drawWalk`, `drawAt`, `drawKey`,