From 63223c6d6343658472e5245557184701161478a3 Mon Sep 17 00:00:00 2001 From: Lilleman auf Larv Date: Wed, 7 Oct 2026 00:56:45 +0200 Subject: [PATCH] Answer stability round 1, prose round 1 and product-owner round 1: startOf's doc names the head, the old senses leave names, comments, messages and tests, and the vocabulary defines scope, link and head --- README.md | 4 ++-- builtins_test.go | 12 ++++++------ calc_test.go | 8 ++++---- data.go | 9 ++++----- datatype_test.go | 4 ++-- doc.go | 15 +++++++++------ docs/decisions.md | 2 +- env.go | 2 +- fejkdata_test.go | 8 ++++---- format.go | 19 +++++++++---------- format_test.go | 6 +++--- graph.go | 8 ++++---- name.go | 22 +++++++++++----------- name_test.go | 2 +- node.go | 4 ++-- node_test.go | 4 ++-- one_spelling_test.go | 8 ++++---- path_test.go | 2 +- perf_test.go | 4 ++-- pick_test.go | 6 +++--- reference_test.go | 2 +- render.go | 2 +- shipped_test.go | 2 +- table_test.go | 4 ++-- valueproof.go | 2 +- 25 files changed, 81 insertions(+), 80 deletions(-) diff --git a/README.md b/README.md index d2d5e61..55c31aa 100644 --- a/README.md +++ b/README.md @@ -961,14 +961,14 @@ table.go tables: their options, format and cells, and the link to the par name.go names: {x as n} bindings, the scopes they live in, and the reads they answer namefence.go the load fences over names pick.go a render's named picks: the frames of the name scopes rendering, the memo a pick keeps, and the reads kept under it -env.go the env a render reads names and rows through +env.go renderEnv: what a render reads names and rows through path.go the dotted-path walks, and proving a path resolves render.go Fake, the recursive renderer (choices, format strings, expansions) and the reads its tokens make record.go records: Record, the JSON/CSV/SQL serializers, and their entry points struct.go structs: FakeStruct, fake tags as one record's columns, and a field's Go type as its column's datatype inline.go inline templates: Template, NewTemplate, FakeTemplate, IsTemplate, and their compile and resolve format.go a format's tokens checked against their fields, and compiled -reference.go resolving references across the tree +reference.go one reference's resolution: its sigil, its category, its tail resolve.go resolving templates against the assembled tree in steps, each over every template before the next graph.go the node graph: tree walks, containment and render edges, and the cycle and repeat fences calc.go the {calc()} operand checks: never a number, and a constant zero divisor diff --git a/builtins_test.go b/builtins_test.go index 9be496e..1162ae7 100644 --- a/builtins_test.go +++ b/builtins_test.go @@ -145,7 +145,7 @@ func TestBuiltinArgLimits(t *testing.T) { `{"format":"{x}","x":"1","repeat":2000000000}`, // repeat -> multi-GB join } for _, tmpl := range bad { - if _, err := linked(t, tmpl); err == nil { + if _, err := resolved(t, tmpl); err == nil { t.Errorf("compile(%s) = nil error, want a limit rejection", tmpl) } } @@ -204,12 +204,12 @@ func mustPanic(t *testing.T, name string, call func()) { func TestClassBuiltinArgs(t *testing.T) { for _, bad := range []string{`"{digits(0)}"`, `"{digits(2000000000)}"`, `"{upper(-1)}"`, `"{lower(x)}"`, `"{digits()}"`, `"{upper(1,2)}"`} { - if _, err := linked(t, bad); err == nil { + if _, err := resolved(t, bad); err == nil { t.Errorf("compile(%s) = nil error, want the arg rejected", bad) } } for _, ok := range []string{`"{digits(1048576)}"`, `"{upper(1)}"`, `"{lower(26)}"`} { - if _, err := linked(t, ok); err != nil { + if _, err := resolved(t, ok); err != nil { t.Errorf("compile(%s) = %v", ok, err) } } @@ -291,7 +291,7 @@ func TestBuiltinDateArgs(t *testing.T) { `"{time('x')}"`: "text", `"{date(1990-01-01,1990-12-31,'15:04')}"`: "time('15:04')", } { - _, err := linked(t, tmpl) + _, err := resolved(t, tmpl) if err == nil || !strings.Contains(err.Error(), want) { t.Errorf("compile(%s) = %v, want an error mentioning %q", tmpl, err, want) } @@ -405,7 +405,7 @@ func TestBuiltinCompileErrors(t *testing.T) { `"{iban(US)}"`, // unsupported country `"{seq(a,b)}"`, // seq takes at most one name } { - if _, err := linked(t, bad); err == nil { + if _, err := resolved(t, bad); err == nil { t.Errorf("compile(%s) = nil error, want error", bad) } } @@ -419,7 +419,7 @@ func TestArgErrorsNameTheSpelling(t *testing.T) { `"{hex(99999999999999999999)}"`: "exceeds the maximum", `"{int(007,9)}"`: "write 7", } { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), want) { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("compile(%s) = %v, want an error saying %q", src, err, want) } } diff --git a/calc_test.go b/calc_test.go index c50be75..82961a1 100644 --- a/calc_test.go +++ b/calc_test.go @@ -204,7 +204,7 @@ func TestCalcOverANeverNumericOperandIsRejected(t *testing.T) { `{"format":"{calc(x * 2)}","x":["a","b"]}`: `"x"`, `{"format":"{calc(x + y)}","x":"1","y":"{{2}}"}`: `"{2}"`, } { - _, err := linked(t, src) + _, err := resolved(t, src) if err == nil || !strings.Contains(err.Error(), want) || !strings.Contains(err.Error(), "never a number") { t.Errorf("compile(%s) = %v, want the operand rejected naming %s", src, err, want) } @@ -215,7 +215,7 @@ func TestCalcOverANeverNumericOperandIsRejected(t *testing.T) { `{"format":"{calc(x * 2)}","x":["1","abc"]}`, `{"format":"{calc(x * 2)}","x":"{digits(2)}"}`, } { - if _, err := linked(t, ok); err != nil { + if _, err := resolved(t, ok); err != nil { t.Errorf("compile(%s) = %v, want it accepted", ok, err) } } @@ -230,7 +230,7 @@ func TestCalcConstantZeroDivisorIsRejected(t *testing.T) { `{"format":"{calc((a/0)+b)}","a":"1","b":"2"}`: "divides by 0", `{"format":"{calc(a/-0)}","a":"1"}`: "divides by -0", } { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), want) { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("compile(%s) = %v, want the constant zero divisor rejected naming %q", src, err, want) } } @@ -259,7 +259,7 @@ func TestCalcCompileErrors(t *testing.T) { `"{calc(1, x)}"`, // decimals arg not an integer `"{calc(1, -1)}"`, // decimals negative } { - if _, err := linked(t, bad); err == nil { + if _, err := resolved(t, bad); err == nil { t.Errorf("compile(%s) = nil error, want error", bad) } } diff --git a/data.go b/data.go index cbdf28a..ba62626 100644 --- a/data.go +++ b/data.go @@ -67,7 +67,7 @@ func mergeChildren(dst, src map[string]node) { } // nodeSet is the set of nodes one validation pass covers: the categories one load -// binds, or a single inline node. +// reads, or a single inline node. type nodeSet func(fn func(label string, n node) error) error // categorySite is a loaded category and where it sits: the folder holding it, that @@ -157,10 +157,9 @@ func (p pipeline) run() error { return checkNodeFences(p.nodes) } -// checkNodeFences runs the per-node fences every pipeline runs over its nodes, each -// over all of them before the next, so which of several broken nodes is reported -// does not depend on the walk. Its walks recurse unguarded, so run refuses their cycles -// first. +// checkNodeFences runs the per-node fences over s, each over every node before the next, +// so which of several broken nodes is reported does not depend on the walk. Its walks +// recurse unguarded, so pipeline.run refuses cycles first. func checkNodeFences(s nodeSet) error { mem := renderCounts{} if err := s(func(label string, n node) error { return repeatCheck(label, n, mem) }); err != nil { diff --git a/datatype_test.go b/datatype_test.go index 416f6bf..07fc3f4 100644 --- a/datatype_test.go +++ b/datatype_test.go @@ -18,7 +18,7 @@ func TestDatatypeAndNullSitOnlyInAColumn(t *testing.T) { `{"format":"","age":[null,{"format":"{int(18,99)}","datatype":"integer","weight":9}]}`, `{"format":"","pick":[[null,"a"],"b"]}`, } { - if _, err := linked(t, src); err != nil { + if _, err := resolved(t, src); err != nil { t.Errorf("compile(%s) = %v, want a column to take a datatype and null", src, err) } } @@ -32,7 +32,7 @@ func TestDatatypeAndNullSitOnlyInAColumn(t *testing.T) { `null`: `so write ""`, `{"format":"{p}","p":{"format":"{x}","x":[null,"a"]}}`: `so write ""`, } { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), want) { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("compile(%s) = %v, want an error containing %q", src, err, want) } } diff --git a/doc.go b/doc.go index b421c8f..474c1de 100644 --- a/doc.go +++ b/doc.go @@ -24,18 +24,21 @@ package fejkdata // start one each, and `FakeStruct` one per record. // - env — what a render reads names and rows through: `renderEnv`. // - named pick — the draw a token such as {/person as p} binds to a name, drawn -// on its first read and kept while its scope renders: a category, or one -// repeat iteration: `nameBinding`, `nameScope`, `namedPick`, `pickFrame`. -// A scope is only ever a name's. +// on its first read and kept while its scope renders: `nameBinding`, +// `namedPick`, `pickFrame`. +// - scope — where a name is bound: a category, or one repeat iteration: `nameScope`. // - memo — what a named pick keeps its draws in, the variant drawn at each level // and the value each path read: `drawMemo`. // - pin — fixing which row of a table one path, or one named pick, uses: // `pinSet`, `namedPick.pins`, `table.drawStep`. // - family — a table and every table reaching it through a chain of parent -// links (`table.linkParent`). Only a table links. -// - resolve — tying each template's references and names to the merged tree: +// links. +// - link — a table's tie to its parent table, each row to its parent row: +// `table.linkParent`. +// - resolve — tying each template's references and names to the assembled tree: // `resolveTemplates`. -// - head — a read's first segment, a string: `arm.head`. The node it names is +// - head — the string a read starts from: a field's name, or a reference's +// category path with its sigil, /sv_SE.address: `arm.head`. The node it names is // the read's start: `template.startOf`, `nameTarget.start`. // - fence — a load-time check, run over each category, template or struct as it // loads or compiles, so rendering a compiled tree cannot fail. diff --git a/docs/decisions.md b/docs/decisions.md index 258db29..4ff6812 100644 --- a/docs/decisions.md +++ b/docs/decisions.md @@ -795,7 +795,7 @@ the direct chain is the one a reader can predict from the tables' parents. 2026-09-30, larv-review on the comprehension round the maintainer approved on 2026-09-29; replaces "The path walks are separate loops". -Goals 3 and 13: `drawSteps` draws every path from its steps, compiled at resolve by +Goals 3 and 13: `drawSteps` draws every path from its steps, compiled when templates resolve, by `pathCheck` or, for a caller's path, by `probePath` into a stack buffer. Both take each step through `takeStep`, and differ only at a choice: the check walks every variant, the probe the first. On 2026-09-29 one loop over all three walks, switching on a mode field, diff --git a/env.go b/env.go index 61c1301..067bfc3 100644 --- a/env.go +++ b/env.go @@ -43,7 +43,7 @@ func (env renderEnv) at(n node, pins *pinSet) renderEnv { // rowOf is the row of t its columns render from. func (env renderEnv) rowOf(t *table) int { if env.row.t != t { - panic(invariant.Broken("a column of %s renders in a scope holding no row of it", t.rows.Segment())) + panic(invariant.Broken("a column of %s renders in an env holding no row of it", t.rows.Segment())) } return env.row.index } diff --git a/fejkdata_test.go b/fejkdata_test.go index cde259e..b97391d 100644 --- a/fejkdata_test.go +++ b/fejkdata_test.go @@ -111,8 +111,8 @@ func parse(t *testing.T, s string) any { return v } -// linked compiles a JSON fragment and links it against no data. -func linked(t *testing.T, s string) (node, error) { +// resolved compiles a JSON fragment and resolves it against no data. +func resolved(t *testing.T, s string) (node, error) { t.Helper() n, err := compile(parse(t, s)) if err != nil { @@ -121,10 +121,10 @@ func linked(t *testing.T, s string) (node, error) { return n, resolveInlineTemplates(inlineNodes(n, "template"), nil) } -// compiled parses, compiles and links a JSON fragment into a node. +// compiled parses, compiles and resolves a JSON fragment into a node. func compiled(t *testing.T, s string) node { t.Helper() - n, err := linked(t, s) + n, err := resolved(t, s) if err != nil { t.Fatalf("compile %q: %v", s, err) } diff --git a/format.go b/format.go index 95c1de7..832cc8b 100644 --- a/format.go +++ b/format.go @@ -120,8 +120,7 @@ func checkBind(t grammar.Token, fields map[string]node) error { return nil } -// checkBound proves what a binding names is a reference or a path into a field of the binding -// template. +// checkBound proves what a binding binds is a reference or a path into a field of its binder. func checkBound(ref string, fields map[string]node) error { if grammar.IsRef(ref) { _, _, err := grammar.RefShape(ref) @@ -190,7 +189,7 @@ func checkNoRepeatedArm(body string, names []string) error { seen := make(map[string]bool, len(names)) for _, name := range names { if seen[name] { - return fmt.Errorf("token {%s}: arm %q is repeated; an alternation picks its arms evenly, so skew the odds with a choice's weights instead", body, name) + return fmt.Errorf("token {%s}: arm %q is repeated; an alternation draws its arms evenly, so skew the odds with a choice's weights instead", body, name) } seen[name] = true } @@ -223,17 +222,17 @@ const ( // resolveRefs resolved it to; before that, a reference is whole. func splitArm(name string, refs map[string]resolvedRef) arm { if grammar.IsRef(name) { - b, linked := refs[name] - if !linked || len(b.tail) == 0 { + r, resolved := refs[name] + if !resolved || len(r.tail) == 0 { head := name - if linked { - head = b.head + if resolved { + head = r.head } return arm{spelling: name, head: head, levels: []pickKey{pickKey(head)}} } - sigil, rest, _ := grammar.RefShape(name) // resolveRefs proved it, and took b.tail as a suffix of its segments + sigil, rest, _ := grammar.RefShape(name) // resolveRefs proved it, and took r.tail as a suffix of its segments written, _ := grammar.SplitPath(rest) - return pathArm(name, b.head, sigil+grammar.JoinSegments(written[:len(written)-len(b.tail)]), b.tail) + return pathArm(name, r.head, sigil+grammar.JoinSegments(written[:len(written)-len(r.tail)]), r.tail) } segs, err := grammar.SplitPath(name) if err != nil || len(segs) == 1 { @@ -330,7 +329,7 @@ func (t *template) compileArm(name string, targets map[*nameBinding]nameTarget) if !t.isName(a.head) { start := t.startOf(a.head) if start == nil { - panic(invariant.Broken("{%s} reads a head nothing bound", a.spelling)) + panic(invariant.Broken("{%s} reads a head nothing resolved", a.spelling)) } w := compilePath(start, a.tail) a.steps, a.leaves = w.steps, w.leaves diff --git a/format_test.go b/format_test.go index ecd66c4..95b96e2 100644 --- a/format_test.go +++ b/format_test.go @@ -20,7 +20,7 @@ func TestStringIsAFormat(t *testing.T) { if got := mustRender(t, f, `"{digits(3)}"`); !regexp.MustCompile(`^[0-9]{3}$`).MatchString(got) { t.Errorf(`render("{digits(3)}") = %q, want three digits`, got) } - if _, err := linked(t, `"{x}"`); err == nil || !strings.Contains(err.Error(), `no field "x"`) { + if _, err := resolved(t, `"{x}"`); err == nil || !strings.Contains(err.Error(), `no field "x"`) { t.Errorf(`compile("{x}") = %v, want a no-field error`, err) } } @@ -50,7 +50,7 @@ func TestBraceEscapes(t *testing.T) { `{"format":"{a{b}","a":"Q"}`: "'{'", `"{x"`: "unterminated", } { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), want) { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("compile(%s) = %v, want an error mentioning %s", src, err, want) } } @@ -125,7 +125,7 @@ func TestFormatCompileErrors(t *testing.T) { `"{int(1)}"`, // wrong arity `"{float(1,2)}"`, // wrong arity } { - if _, err := linked(t, bad); err == nil { + if _, err := resolved(t, bad); err == nil { t.Errorf("compile(%s) = nil error, want error", bad) } } diff --git a/graph.go b/graph.go index cb707b8..c0afe30 100644 --- a/graph.go +++ b/graph.go @@ -183,18 +183,18 @@ func checkNoCycles(s nodeSet) error { grey = 1 black = 2 ) - inScope := map[node]bool{} + inSet := map[node]bool{} _ = s(func(_ string, n node) error { - inScope[n] = true + inSet[n] = true if t, isTable := n.(*table); isTable { - inScope[t.rowNode] = true // a selector lands on it, and contained lists it nowhere + inSet[t.rowNode] = true // a selector lands on it, and contained lists it nowhere } return nil }) color := map[node]int{} var visit func(n node, label string) error visit = func(n node, label string) error { - if !inScope[n] { + if !inSet[n] { return nil // loaded before these nodes and proven then, so it never reaches back into it } switch color[n] { diff --git a/name.go b/name.go index d5278cf..e0e06f2 100644 --- a/name.go +++ b/name.go @@ -92,7 +92,7 @@ func bindNames(root node) error { } } } - read, err := resolveReads(root, scopes) + read, err := answerReads(root, scopes) if err != nil { return err } @@ -165,16 +165,16 @@ func eachContained(n node, where string, fn func(c node, where string) error) er return nil } -// resolveReads answers each unbound read under root with a name its template sees, and returns -// the set of bindings some read answers to. It resolves a template's fields before its format, the +// answerReads answers each unbound read under root with a name its template sees, and returns +// the set of bindings some read answers to. It answers a template's fields before its format, the // order compile reports in, and refuses a field spelling a name. A refusal searches scopes, every // scope of the category, for a name bound where the read cannot see it. -func resolveReads(root node, scopes []*nameScope) (map[*nameBinding]bool, error) { +func answerReads(root node, scopes []*nameScope) (map[*nameBinding]bool, error) { read := map[*nameBinding]bool{} - var resolve func(n node, where string) error - resolve = func(n node, where string) error { + var answer func(n node, where string) error + answer = func(n node, where string) error { t, isTemplate := n.(*template) - if err := eachContained(n, where, resolve); err != nil { + if err := eachContained(n, where, answer); err != nil { return err } if !isTemplate { @@ -192,18 +192,18 @@ func resolveReads(root node, scopes []*nameScope) (map[*nameBinding]bool, error) for _, u := range t.unbound { b := t.nameScope.lookup(u.head) if b == nil { - return unresolved(where, u, t.nameScope, scopes) + return unanswered(where, u, t.nameScope, scopes) } read[b] = true } return nil } - return read, resolve(root, "") + return read, answer(root, "") } -// unresolved is the refusal of u, a read no field or name answers: naming the repeat binding the +// unanswered is the refusal of u, a read no field or name answers: naming the repeat binding the // name where the read cannot see it, else the names the read sees. -func unresolved(where string, u unboundRead, seen *nameScope, scopes []*nameScope) error { +func unanswered(where string, u unboundRead, seen *nameScope, scopes []*nameScope) error { for _, sc := range scopes { if b, ok := sc.bindings[u.head]; ok { at := strings.TrimSuffix(b.where, ": ") diff --git a/name_test.go b/name_test.go index 37558d9..801fdaf 100644 --- a/name_test.go +++ b/name_test.go @@ -61,7 +61,7 @@ func TestANameKeepsWhatItsPathsAddress(t *testing.T) { differ = differ || got[0][0] != got[0][2] } if !differ { - t.Fatal("{w}-{w} under a name drew w once in 100 renders, want each {w} a pick of its own") + t.Fatal("{w}-{w} under a name drew w once in 100 renders, want each {w} a draw of its own") } } diff --git a/node.go b/node.go index 874aa35..5749cb2 100644 --- a/node.go +++ b/node.go @@ -47,7 +47,7 @@ func (*nullItem) isNode() {} // template renders a format string, substituting {tokens} from fields. A bare // JSON string is a template with no fields. repeat (default 1) renders that format // that many times and joins the results with separator (default ""), each render -// an independent pick. Every format compiles in `resolveTemplates`. +// an independent draw. Every format compiles in `resolveTemplates`. type template struct { // Filled by `compileString`, `compileTemplate` and `table.compileRowFormat`: format string @@ -80,7 +80,7 @@ type templateRefs struct { func (*template) isNode() {} -// startOf is the node an arm's startOf names: a sibling field, or a reference's category. +// startOf is the node an arm's head names: a sibling field, or a reference's category. func (t *template) startOf(name string) node { if grammar.IsRef(name) { return t.refs.categories[name] diff --git a/node_test.go b/node_test.go index 9b3e017..74f8de9 100644 --- a/node_test.go +++ b/node_test.go @@ -7,7 +7,7 @@ import ( ) func TestWeightZeroIsRejected(t *testing.T) { - _, err := linked(t, `[{"format":"X","weight":0},"Y"]`) + _, err := resolved(t, `[{"format":"X","weight":0},"Y"]`) if err == nil || !strings.Contains(err.Error(), "weight 0") || !strings.Contains(err.Error(), "remove") { t.Fatalf("compile(weight 0) = %v, want it rejected naming the fix", err) } @@ -75,7 +75,7 @@ func TestNodeCompileErrors(t *testing.T) { `{"format":"x","repeat":2,"separator":5}`, // non-string separator `{"format":"{x}","x":"v","repeat":2,"separator":""}`, // separator "" is the default } { - if _, err := linked(t, bad); err == nil { + if _, err := resolved(t, bad); err == nil { t.Errorf("compile(%s) = nil error, want error", bad) } } diff --git a/one_spelling_test.go b/one_spelling_test.go index abbf9e9..2c9d11e 100644 --- a/one_spelling_test.go +++ b/one_spelling_test.go @@ -7,7 +7,7 @@ import ( func TestOneItemChoiceIsRejected(t *testing.T) { for _, src := range []string{`["x"]`, `[{"format":"{d}","d":"x"}]`, `{"format":"{w}","w":["only"]}`} { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), "one-item choice") { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), "one-item choice") { t.Errorf("compile(%s) = %v, want the one-item choice rejected", src, err) } } @@ -20,11 +20,11 @@ func TestRepeatedChoiceItemIsRejected(t *testing.T) { `{"format":"{w}","w":["", "", "x"]}`: `{ "format": "", "weight": 2 }`, `{"format":"","w":[null,null,"a"]}`: "a null takes no weight", } { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), want) { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("compile(%s) = %v, want an error naming %s", src, err, want) } } - if _, err := linked(t, `[{"format":"a","weight":2}, "b"]`); err != nil { + if _, err := resolved(t, `[{"format":"a","weight":2}, "b"]`); err != nil { t.Errorf("compile(weighted a, b) = %v", err) } } @@ -39,7 +39,7 @@ func TestInertObjectIsRejected(t *testing.T) { `{"format":"{x}","x":"v","repeat":2,"separator":""}`: "default", `{"format":"","n":{"format":"1","datatype":"string"}}`: `datatype "string" is the default`, } { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), want) { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("compile(%s) = %v, want an error mentioning %s", src, err, want) } } diff --git a/path_test.go b/path_test.go index 0120f0a..8c02d84 100644 --- a/path_test.go +++ b/path_test.go @@ -142,7 +142,7 @@ func TestPathKeyIsUnambiguous(t *testing.T) { } // TestMissingFieldNamesItself keeps the precise diagnosis for the ordinary typo: a -// single-variant choice always picks the same item, so it needs no every-variant +// single-variant choice always draws the same item, so it needs no every-variant // guard and the error can name the field that is missing. func TestMissingFieldNamesItself(t *testing.T) { f := newGenerator(t, "data", WithSeed(1)) diff --git a/perf_test.go b/perf_test.go index 8944922..065bb49 100644 --- a/perf_test.go +++ b/perf_test.go @@ -55,7 +55,7 @@ func TestNoRenderAllocRegression(t *testing.T) { } } -// The repeat shape prices what keeps a render's scope off the heap: a copy dropped costs an alloc an iteration. +// The repeat shape prices what keeps a render's env off the heap: a copy dropped costs an alloc an iteration. func TestNoReferenceAllocRegression(t *testing.T) { word := `{"format":"{w}","w":["alpha","beta","gamma","delta"]}` for _, s := range []struct { @@ -74,7 +74,7 @@ func TestNoReferenceAllocRegression(t *testing.T) { t.Fatalf("New(%s): %v", s.name, err) } if allocs := testing.AllocsPerRun(10000, func() { f.Fake("x") }); allocs > s.base*s.slack { - t.Errorf("%s: %.1f allocs/op regressed past %.1f (baseline %.1f × %.2f); a render's scope reaching the heap is the usual cause", s.name, allocs, s.base*s.slack, s.base, s.slack) + t.Errorf("%s: %.1f allocs/op regressed past %.1f (baseline %.1f × %.2f); a render's env reaching the heap is the usual cause", s.name, allocs, s.base*s.slack, s.base, s.slack) } } } diff --git a/pick_test.go b/pick_test.go index 1619bd4..dd12dbb 100644 --- a/pick_test.go +++ b/pick_test.go @@ -26,7 +26,7 @@ func varies(t *testing.T, f *Generator, src string, differ func(got string) bool return } } - t.Fatalf("400 renders of %s never drew apart, want each {…} a pick of its own", src) + t.Fatalf("400 renders of %s never drew apart, want each {…} a draw of its own", src) } func TestEveryTokenDrawsAfresh(t *testing.T) { @@ -57,7 +57,7 @@ func TestEveryReferenceDrawsAfresh(t *testing.T) { differ = p[0] != p[1] } if !differ { - t.Errorf("400 renders of %s never drew apart, want each reference a pick of its own", src) + t.Errorf("400 renders of %s never drew apart, want each reference a draw of its own", src) } } } @@ -124,7 +124,7 @@ func TestAFieldBindingIsRefusedWhereNoFieldIs(t *testing.T) { `{"format":"{place as p}{calc(p * 2)}","place":["1","2"]}`: `write place where it is read`, `{"format":"{place as place}{place}{place}","place":["x","y"]}`: `name "place" is a field of the root template too`, } { - if _, err := linked(t, src); err == nil || !strings.Contains(err.Error(), want) { + if _, err := resolved(t, src); err == nil || !strings.Contains(err.Error(), want) { t.Errorf("%s = %v, want it refused naming %s", src, err, want) } } diff --git a/reference_test.go b/reference_test.go index 6f860b9..8643a79 100644 --- a/reference_test.go +++ b/reference_test.go @@ -59,7 +59,7 @@ func TestReferenceCombinesLoadedPaths(t *testing.T) { } // TestReferenceChain follows a reference to a node that is itself a reference, so -// linking order cannot matter. +// resolve order cannot matter. func TestReferenceChain(t *testing.T) { dir := writeData(t, map[string]string{ "a": `"{/b}"`, diff --git a/render.go b/render.go index 8595d48..4fdd141 100644 --- a/render.go +++ b/render.go @@ -89,7 +89,7 @@ func render(s *drawstate.State, n node, env renderEnv) string { } // renderRepeat renders each iteration of t inside the name scopes rendering t, where a name bound -// outside t keeps its pick, and a name t binds picks again. +// outside t keeps its pick, and a name t binds takes a fresh pick. func renderRepeat(s *drawstate.State, t *template, env renderEnv) string { var b strings.Builder b.Grow(t.repeat * (t.compiled.grow + len(t.separator))) diff --git a/shipped_test.go b/shipped_test.go index ed7daf8..23c6ca3 100644 --- a/shipped_test.go +++ b/shipped_test.go @@ -30,7 +30,7 @@ func newShippedWhole(t testing.TB, opts ...Option) *Generator { return f } -// loadedCategories is the dot path of every category f has parsed and linked. +// loadedCategories is the dot path of every category f has parsed and resolved. func loadedCategories(f *Generator) []string { var out []string for _, s := range categorySites(&f.root) { diff --git a/table_test.go b/table_test.go index c25f2f7..389e7a3 100644 --- a/table_test.go +++ b/table_test.go @@ -1105,8 +1105,8 @@ func TestAStepSitsAtTheSegmentItConsumes(t *testing.T) { "region[12].name", } { a := splitArm(path, nil) - head := f.root.children[a.head].(*table) - a.steps = compilePath(head, a.tail).steps + start := f.root.children[a.head].(*table) + a.steps = compilePath(start, a.tail).steps for _, st := range a.steps { seg := "" switch st.kind { diff --git a/valueproof.go b/valueproof.go index f55c4d1..0d41e52 100644 --- a/valueproof.go +++ b/valueproof.go @@ -10,7 +10,7 @@ import ( "github.com/larvit/fejkdata/internal/proven" ) -// valueProof proves what typed columns and their calc operands hold, each node once per nodeSet. +// valueProof proves what typed columns and their calc operands hold, each node once per proof. type valueProof struct { memo map[node]proven.Facts columnMemo map[node]proven.Facts