diff --git a/README.md b/README.md index 5ae2e24..ce80187 100644 --- a/README.md +++ b/README.md @@ -902,7 +902,7 @@ checksum.go the check characters a derivation appends, and the IBAN they sit transform.go the builtins that rewrite an operand's value, and the ASCII folding calc.go the {calc()} arithmetic evaluator: parser, eval, validation datatype.go column datatypes: DataType, where datatype and null may sit, a column's datatype -valueproof.go the value proof: what a typed column or calc operand holds, checked at load +valueproof.go the value proof: what a typed column, calc operand or struct field holds, checked at load data.go the load path: fs.FS folders/files -> merged namespace tree, and the bind pipeline every entry point runs cmd/fejkdata/ the fejkdata CLI data/ shipped data (JSON, and a TSV per table), embedded at build: locale folders, geo, misc diff --git a/format.go b/format.go index c9f44d6..db76043 100644 --- a/format.go +++ b/format.go @@ -262,7 +262,7 @@ func checkArm(name string, fields map[string]node, wholeToken bool) error { } return fmt.Errorf("no field %q", a.head) } - if err := checkPath(field, a.tail, a.head); err != nil { + if err := checkResolves(field, a.tail, a.head); err != nil { return fmt.Errorf("field %q: %w", a.head, err) } return nil diff --git a/path.go b/path.go index b2ae912..5891486 100644 --- a/path.go +++ b/path.go @@ -472,12 +472,12 @@ func unreachableInChoice(c *choice, want string) error { return fmt.Errorf("not every variant of this %d-way choice carries %q; all carry %v", len(c.items), want, offered) } -func checkPath(n node, tail []string, level string) error { +func checkResolves(n node, tail []string, level string) error { _, err := (&pathCheck{level: level, tail: tail}).run(n) return err } -// compilePath compiles a path checkPath proved. +// compilePath compiles a path checkResolves proved. func compilePath(n node, tail []string) pathCheck { w := pathCheck{tail: tail} if _, err := w.run(n); err != nil { diff --git a/reference.go b/reference.go index 8eae402..92e65f3 100644 --- a/reference.go +++ b/reference.go @@ -147,7 +147,7 @@ func (t *template) resolveLink(folder []string, path, category string, root map[ if category != "" && head == "/"+category { return link, fmt.Errorf("%s: reference {%s}: names the category it sits in; read a sibling field as a path, or move the shared value into its own category and reference that", path, name) } - if err := checkPath(target, tail, head); err != nil { + if err := checkResolves(target, tail, head); err != nil { return link, fmt.Errorf("%s: reference {%s}: %w", path, name, err) } link.refHeads[head] = target diff --git a/struct.go b/struct.go index eb38a56..3016a68 100644 --- a/struct.go +++ b/struct.go @@ -317,37 +317,6 @@ func (k columnKind) holds(v proven) bool { return v.lo >= k.lo && v.hi <= k.hi } -// checkField rejects a column a field of Go type ft cannot fill: a datatype, which the Go type -// sets, a null outside a pointer, or a value its kind's datatype or range refuses. -func (p *valueProof) checkField(label string, ft reflect.Type, column node) error { - items, _ := columnItems(column) - for _, it := range items { - if it.datatype != DataTypeString { - return fmt.Errorf("%s: its Go type %s sets the datatype; drop \"datatype\"", label, ft) - } - } - elem := ft - if ft.Kind() == reflect.Pointer { - elem = ft.Elem() - } else if p.proveColumn(column).nullable { - return fmt.Errorf("%s: its tag can draw null, which %s cannot hold; make it *%s", label, ft, ft) - } - kind := columnKinds[elem.Kind()] - if kind.datatype == DataTypeString { - return nil - } - for _, it := range items { - v := p.proveColumnItem(it) - if reason := v.not[kind.datatype]; reason != "" { - return fmt.Errorf("%s (%s): %s", label, ft, reason) - } - if !kind.holds(v) { - return fmt.Errorf("%s (%s): %q is not proven within %s; narrow it to that range, or make the field %s", label, ft, it.format, elem.Kind(), kind.wider) - } - } - return nil -} - // fill draws the record into v's tagged fields, then each nested struct as a record of its own. func (s *structShape) fill(state *generatorState, v reflect.Value) { if s.record != nil { diff --git a/todo.md b/todo.md index 3db5960..22e5dec 100644 --- a/todo.md +++ b/todo.md @@ -40,9 +40,6 @@ maintainer chose on 2026-09-30 to go on with the path steps regardless. This round, in order: -- Move `valueProof.checkField` to `valueproof.go`, and rename `checkPath`, which differs - from the `pathCheck` type it wraps by word order alone: both architects placed them - wrong. - Correct the claims readers followed wrong: `IsTemplate`'s doc says an argument holding a bracket that is not valid JSON errors, where `misc.territory[SE]` is a path; the README says rows are indexed on the first draw, where `New` builds the key map; and diff --git a/valueproof.go b/valueproof.go index 0ac6217..6a8bf3e 100644 --- a/valueproof.go +++ b/valueproof.go @@ -3,6 +3,7 @@ package fejkdata import ( "fmt" "math" + "reflect" "regexp" "slices" "strconv" @@ -43,6 +44,37 @@ func (p *valueProof) checkDatatype(path string, n node) error { return nil } +// checkField rejects a column a field of Go type ft cannot fill: a datatype, which the Go type +// sets, a null outside a pointer, or a value its kind's datatype or range refuses. +func (p *valueProof) checkField(label string, ft reflect.Type, column node) error { + items, _ := columnItems(column) + for _, it := range items { + if it.datatype != DataTypeString { + return fmt.Errorf("%s: its Go type %s sets the datatype; drop \"datatype\"", label, ft) + } + } + elem := ft + if ft.Kind() == reflect.Pointer { + elem = ft.Elem() + } else if p.proveColumn(column).nullable { + return fmt.Errorf("%s: its tag can draw null, which %s cannot hold; make it *%s", label, ft, ft) + } + kind := columnKinds[elem.Kind()] + if kind.datatype == DataTypeString { + return nil + } + for _, it := range items { + v := p.proveColumnItem(it) + if reason := v.not[kind.datatype]; reason != "" { + return fmt.Errorf("%s (%s): %s", label, ft, reason) + } + if !kind.holds(v) { + return fmt.Errorf("%s (%s): %q is not proven within %s; narrow it to that range, or make the field %s", label, ft, it.format, elem.Kind(), kind.wider) + } + } + return nil +} + // proveColumnItem proves a column item: what it renders, or, when it is a column it reads, that column. func (p *valueProof) proveColumnItem(t *template) proven { if t.link.readsColumn == nil {