diff --git a/data.go b/data.go index 5299de3..08dab0a 100644 --- a/data.go +++ b/data.go @@ -124,8 +124,8 @@ type categoryFiles struct { tsv map[string]bool } -// rows reads the rows file a category names beside it. -func (c *categoryFiles) rows(name string) (string, error) { +// readRows reads the rows file a category names beside it. +func (c *categoryFiles) readRows(name string) (string, error) { if _, present := c.tsv[name]; !present { return "", fmt.Errorf("rows names %s, which is not beside it in %s", name, c.src.name(c.dir)) } diff --git a/datatype.go b/datatype.go index fae8097..31e1a0a 100644 --- a/datatype.go +++ b/datatype.go @@ -166,7 +166,7 @@ func disagreement(a *template, da DataType, b *template, db DataType) error { switch { case da != DataTypeString && db != DataTypeString: return bothTyped(a, da, b, db) - case typed.datatype == DataTypeString && (&valueProof{}).columnItem(bare).not[want] != "": + case typed.datatype == DataTypeString && (&valueProof{}).proveColumnItem(bare).not[want] != "": return fmt.Errorf(`item %q is not %s, the datatype item %q takes from the column it reads; to read that column as text, %s`, bare.format, dataTypeNouns[want], typed.format, asText(typed)) case bare.fromString: // an object may carry a weight, which this spelling would drop return fmt.Errorf(`item %q declares no datatype, and a column holds one; write it as {"format":%q,"datatype":%q}`, bare.format, bare.format, want) @@ -184,7 +184,7 @@ func bothTyped(a *template, da DataType, b *template, db DataType) error { switch { case read.datatype != DataTypeString: return fmt.Errorf("its items hold %s and %s; a column holds one datatype", da, db) - case (&valueProof{}).columnItem(read).not[other] == "": + case (&valueProof{}).proveColumnItem(read).not[other] == "": return fmt.Errorf("its items hold %s and %s; a column holds one datatype, so %s", da, db, typedAs(read, other)) } return fmt.Errorf("its items hold %s and %s; a column holds one datatype, so to read %q as text, %s", da, db, read.format, asText(read)) diff --git a/graph.go b/graph.go index 09fcc11..0ff962f 100644 --- a/graph.go +++ b/graph.go @@ -67,7 +67,7 @@ func contained(n node) []namedNode { return nil } var out []namedNode - for r := 0; r < n.t.rows(); r++ { + for r := 0; r < n.t.rowCount(); r++ { if cell := n.t.cellTemplate(r, n.i); cell != nil { out = append(out, namedNode{node: cell}) } @@ -171,13 +171,13 @@ func pathLeaves(n node, tail []string) []node { type reachMemo map[node]int -func (m reachMemo) of(n node) int { +func (m reachMemo) renderCount(n node) int { if r, done := m[n]; done { return r } r := 1 for _, e := range renderEdges(n) { - if c := m.of(e.to); c > r { + if c := m.renderCount(e.to); c > r { r = c } } @@ -192,8 +192,8 @@ func (m reachMemo) of(n node) int { // path, so nested repeats cannot build what one repeat may not. // docs/decisions.md#the-repeat-cap-bounds-renders-not-bytes func repeatCheck(path string, n node, mem reachMemo) error { - if t, ok := n.(*template); ok && t.repeat > 1 && mem.of(n) > MaxRepeat { - return fmt.Errorf("%s: repeat %d multiplies to %d renders along one path, above the maximum %d", path, t.repeat, mem.of(n), MaxRepeat) + if t, ok := n.(*template); ok && t.repeat > 1 && mem.renderCount(n) > MaxRepeat { + return fmt.Errorf("%s: repeat %d multiplies to %d renders along one path, above the maximum %d", path, t.repeat, mem.renderCount(n), MaxRepeat) } return nil } diff --git a/struct.go b/struct.go index aeb5e2c..193255a 100644 --- a/struct.go +++ b/struct.go @@ -105,7 +105,7 @@ func (sc *structCompile) record(t reflect.Type, label string) (*structShape, err sc.visiting[t] = true defer delete(sc.visiting, t) c := &structFields{structCompile: sc, t: t, label: label, tags: map[string]any{}, shape: &structShape{}} - if err := c.walk(t, nil); err != nil { + if err := c.gatherFields(t, nil); err != nil { return nil, err } if len(c.tags) > 0 { @@ -123,19 +123,19 @@ func (sc *structCompile) spend(label string) error { return fmt.Errorf(`%s: the struct fields reach more than %d structs; leave a struct field unfilled with fake:"-"`, label, maxStructs) } -// walk gathers the fields of struct type t, which sits at index within c.t. -func (c *structFields) walk(t reflect.Type, index []int) error { +// gatherFields gathers the fields of struct type t, which sits at index within c.t. +func (c *structFields) gatherFields(t reflect.Type, index []int) error { for i := 0; i < t.NumField(); i++ { sf := t.Field(i) sf.Index = append(index[:len(index):len(index)], i) - if err := c.field(sf); err != nil { + if err := c.addField(sf); err != nil { return err } } return nil } -func (c *structFields) field(sf reflect.StructField) error { +func (c *structFields) addField(sf reflect.StructField) error { tag, tagged := sf.Tag.Lookup("fake") elem := structOf(sf.Type) switch { @@ -145,7 +145,7 @@ func (c *structFields) field(sf reflect.StructField) error { } return nil case tagged: - return c.column(sf, tag) + return c.addTag(sf, tag) case elem == nil || c.visiting[elem]: return nil case sf.Anonymous: @@ -167,8 +167,8 @@ func structOf(t reflect.Type) reflect.Type { return t } -// column adds a tagged field's tag to the record, refusing one another field hides. -func (c *structFields) column(sf reflect.StructField, tag string) error { +// addTag adds a tagged field's tag to the record, refusing one another field hides. +func (c *structFields) addTag(sf reflect.StructField, tag string) error { if visible, ok := c.t.FieldByName(sf.Name); !ok || !slices.Equal(visible.Index, sf.Index) { return fmt.Errorf("%s.%s: hidden by another field named %s, so its fake tag cannot fill it; rename one", c.label, fieldPath(c.t, sf.Index), sf.Name) } @@ -196,7 +196,7 @@ func (c *structFields) embed(sf reflect.StructField, elem reflect.Type) error { c.visiting[elem] = true defer delete(c.visiting, elem) tags, nested := len(c.tags), len(c.shape.nested) - if err := c.walk(elem, sf.Index); err != nil { + if err := c.gatherFields(elem, sf.Index); err != nil { return err } if sf.Type.Kind() == reflect.Pointer && !sf.IsExported() && (len(c.tags) > tags || len(c.shape.nested) > nested) { @@ -327,7 +327,7 @@ func (p *valueProof) checkField(label string, ft reflect.Type, column node) erro elem := ft if ft.Kind() == reflect.Pointer { elem = ft.Elem() - } else if p.column(column).null { + } else if p.proveColumn(column).null { return fmt.Errorf("%s: its tag can draw null, which %s cannot hold; make it *%s", label, ft, ft) } kind := columnKinds[elem.Kind()] @@ -335,7 +335,7 @@ func (p *valueProof) checkField(label string, ft reflect.Type, column node) erro return nil } for _, it := range items { - v := p.columnItem(it) + v := p.proveColumnItem(it) if reason := v.not[kind.datatype]; reason != "" { return fmt.Errorf("%s (%s): %s", label, ft, reason) } diff --git a/table.go b/table.go index 45471fb..43ee53c 100644 --- a/table.go +++ b/table.go @@ -58,7 +58,7 @@ type row struct{ t *table } func (*row) isNode() {} -func (t *table) rows() int { return len(t.cells) / len(t.columns) } +func (t *table) rowCount() int { return len(t.cells) / len(t.columns) } func (t *table) cell(row, col int) string { return t.cells[row*len(t.columns)+col] } @@ -89,7 +89,7 @@ func compileTable(m map[string]any, category string, files *categoryFiles) (*tab if err != nil { return nil, err } - data, err := files.rows(o.rows) + data, err := files.readRows(o.rows) if err != nil { return nil, err } @@ -184,7 +184,7 @@ func (t *table) parseRows(data string) error { } rest = more } - if t.rows() < 2 { + if t.rowCount() < 2 { return fmt.Errorf("has one row, which is a template; write it as one") } return nil @@ -240,8 +240,8 @@ func (t *table) proveNamesInsideParent() error { if t.key >= 0 || t.name < 0 { return nil } - inside := make(map[string]int, t.rows()) - for r := 0; r < t.rows(); r++ { + inside := make(map[string]int, t.rowCount()) + for r := 0; r < t.rowCount(); r++ { k := t.cell(r, t.parent) + "\t" + t.cell(r, t.name) if first, dup := inside[k]; dup { return fmt.Errorf("%s line %d: name %q repeats line %d inside %s %q; a name selects one row inside its parent; drop one, or add a key column", t.file, r+2, t.cell(r, t.name), first+2, t.columns[t.parent], t.cell(r, t.parent)) @@ -256,8 +256,8 @@ func (t *table) indexKeys() error { if t.key < 0 { return nil } - t.byKey = make(map[string]int, t.rows()) - for r := 0; r < t.rows(); r++ { + t.byKey = make(map[string]int, t.rowCount()) + for r := 0; r < t.rowCount(); r++ { k := t.cell(r, t.key) if k == "" { return fmt.Errorf("%s line %d: the key is empty", t.file, r+2) @@ -267,7 +267,7 @@ func (t *table) indexKeys() error { } t.byKey[k] = r } - for r := 0; r < t.rows() && t.name >= 0; r++ { + for r := 0; r < t.rowCount() && t.name >= 0; r++ { if n := t.cell(r, t.name); t.byKey[n] != r { if other, isKey := t.byKey[n]; isKey { return fmt.Errorf("%s line %d: name %q is the key of line %d, which a selector reads first, so the name could never select this row", t.file, r+2, n, other+2) @@ -282,7 +282,7 @@ func (t *table) sumWeights() error { if t.weight < 0 { return nil } - t.cum = make([]float64, t.rows()) + t.cum = make([]float64, t.rowCount()) total := 0.0 for r := range t.cum { w, err := strconv.ParseFloat(t.cell(r, t.weight), 64) @@ -419,15 +419,15 @@ func (t *table) linkParent(path string, siblings map[string]node) error { return fmt.Errorf("%q is named like a column of %q, its ancestor, so %s.%s could read either; rename one", t.category, q.category, q.category, t.category) } } - linked := make(map[string]bool, p.rows()) - for r := 0; r < t.rows(); r++ { + linked := make(map[string]bool, p.rowCount()) + for r := 0; r < t.rowCount(); r++ { k := t.cell(r, t.parent) if _, ok := p.byKey[k]; !ok { return fmt.Errorf("%s line %d: %s %q is no key of %s", t.file, r+2, name, k, p.file) } linked[k] = true } - for r := 0; r < p.rows(); r++ { + for r := 0; r < p.rowCount(); r++ { if k := p.cell(r, p.key); !linked[k] { return fmt.Errorf("%s links no row to %s %q; every %s row needs one, or drop line %d of %s", t.file, name, k, name, r+2, p.file) } @@ -443,15 +443,15 @@ func (t *table) linkParent(path string, siblings map[string]node) error { func (t *table) indexed() *tableIndex { t.once.Do(func() { if t.name >= 0 { - t.index.byName = make(map[string][]int, t.rows()) - for r := 0; r < t.rows(); r++ { + t.index.byName = make(map[string][]int, t.rowCount()) + for r := 0; r < t.rowCount(); r++ { n := t.cell(r, t.name) t.index.byName[n] = append(t.index.byName[n], r) } } if t.parent >= 0 { t.index.children = map[string][]int{} - for r := 0; r < t.rows(); r++ { + for r := 0; r < t.rowCount(); r++ { k := t.cell(r, t.parent) t.index.children[k] = append(t.index.children[k], r) } @@ -476,7 +476,7 @@ func (t *table) indexed() *tableIndex { // interface so that the walk that draws through it keeps its hold set off the heap. func (t *table) draw(s *session) int { if t.cum == nil { - return s.IntN(t.rows()) + return s.IntN(t.rowCount()) } return pickCum(s, t.cum) } diff --git a/table_test.go b/table_test.go index 99838c8..1875906 100644 --- a/table_test.go +++ b/table_test.go @@ -982,7 +982,7 @@ func TestEnteredRowsAgreeWithPinning(t *testing.T) { } var none pinSet for _, entered := range tables { - for row := 0; row < entered.rows(); row++ { + for row := 0; row < entered.rowCount(); row++ { whole := drawAt{drawn: entered} whole.whole.add(entered, row) s := none.entered(entered, row) @@ -993,7 +993,7 @@ func TestEnteredRowsAgreeWithPinning(t *testing.T) { t.Errorf("a render draws %s beside %s, which pinning it there refuses", cand.selectorSpelling(r), entered.selectorSpelling(row)) } } - for cr := 0; cr < cand.rows(); cr++ { + for cr := 0; cr < cand.rowCount(); cr++ { beside := s.clone() refused := beside.pinRow(cand, cr) != nil candAt := drawAt{pins: none.entered(cand, cr)} diff --git a/todo.md b/todo.md index 3e71e27..78b582a 100644 --- a/todo.md +++ b/todo.md @@ -19,11 +19,9 @@ Self-sufficiency 5.6), every seat capped by Locality or Self-sufficiency. This round, in order: -- Give `rows` and `field` one meaning each, per the decision "One name, one meaning": - `categoryFiles.rows` returns a TSV file name where `table.rows` counts rows, and - `formatOps.field` compiles a `{field}` token where `structFields.field` reads a Go - struct field. Rename every other shared name that names two things — `walk`, - `column`, `expr` and `of` included. +- Rename the shared names left that name two things, per the decision "One name, one + meaning": judge each of `check`, `draw`, `drawn`, `head`, `key`, `name`, `named`, + `names`, `null`, `number`, `record` and `variant`. - Run the nine-seat panel again and file what it names here. ### Data diff --git a/value.go b/value.go index 250bb25..2d94b83 100644 --- a/value.go +++ b/value.go @@ -37,23 +37,23 @@ func (p *valueProof) checkDatatype(path string, n node) error { if d := readDatatype(t); d == t.datatype { return fmt.Errorf(`%s: %s takes datatype %s from the column it reads; drop "datatype"`, path, t.format, d) } - if reason := p.columnItem(t).not[t.datatype]; reason != "" { + if reason := p.proveColumnItem(t).not[t.datatype]; reason != "" { return fmt.Errorf("%s: datatype %s: %s", path, t.datatype, reason) } return nil } -// columnItem proves a column item: what it renders, or, when it is a column it reads, that column. -func (p *valueProof) columnItem(t *template) proven { +// 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.readsColumn == nil { - return p.of(t) + return p.prove(t) } - return p.column(t.readsColumn.column) + return p.proveColumn(t.readsColumn.column) } -// column proves a column over what its items draw, a null item marking it null rather than +// proveColumn proves a column over what its items draw, a null item marking it null rather than // rendering "". -func (p *valueProof) column(n node) proven { +func (p *valueProof) proveColumn(n node) proven { if v, done := p.columns[n]; done { return v } @@ -63,7 +63,7 @@ func (p *valueProof) column(n node) proven { items, nullable := columnItems(n) var v proven for i, it := range items { - if w := p.columnItem(it); i == 0 { + if w := p.proveColumnItem(it); i == 0 { v = w } else { v = v.or(w) @@ -74,7 +74,7 @@ func (p *valueProof) column(n node) proven { return v } -func (p *valueProof) of(n node) proven { +func (p *valueProof) prove(n node) proven { if v, done := p.memo[n]; done { return v } @@ -84,11 +84,11 @@ func (p *valueProof) of(n node) proven { var v proven switch n := n.(type) { case *choice: - v = p.unite(n.items) + v = p.proveUnion(n.items) case *template: - v = p.template(n) + v = p.proveTemplate(n) case *column: - v = p.cells(n) + v = p.proveCells(n) case *row: v = unproven(fmt.Sprintf("%q renders a row of %s, which is composed text", n.t.format.format, n.t.category)) default: @@ -98,13 +98,13 @@ func (p *valueProof) of(n node) proven { return v } -// cells proves a table column over every cell it may render. -func (p *valueProof) cells(c *column) proven { +// proveCells proves a table column over every cell it may render. +func (p *valueProof) proveCells(c *column) proven { var v proven - for r := 0; r < c.t.rows(); r++ { + for r := 0; r < c.t.rowCount(); r++ { var w proven if cell := c.t.cellTemplate(r, c.i); cell != nil { - w = p.of(cell) + w = p.prove(cell) } else { w = literalValue(c.t.cell(r, c.i)) } @@ -117,10 +117,10 @@ func (p *valueProof) cells(c *column) proven { return v } -func (p *valueProof) unite(nodes []node) proven { - v := p.of(nodes[0]) +func (p *valueProof) proveUnion(nodes []node) proven { + v := p.prove(nodes[0]) for _, n := range nodes[1:] { - v = v.or(p.of(n)) + v = v.or(p.prove(n)) } return v } @@ -140,9 +140,9 @@ func (v proven) or(w proven) proven { return v } -// template proves a template that renders one value: fixed text, or a format that is +// proveTemplate proves a template that renders one value: fixed text, or a format that is // one token alone. -func (p *valueProof) template(t *template) proven { +func (p *valueProof) proveTemplate(t *template) proven { switch { case t.repeat != 1: return unproven(fmt.Sprintf("%q carries a repeat, which composes text rather than one value", t.format)) @@ -161,9 +161,9 @@ func (p *valueProof) template(t *template) proven { for _, a := range o.arms { leaves = append(leaves, pathLeaves(t.head(a.key), a.tail)...) } - return p.unite(leaves) + return p.proveUnion(leaves) case name == "calc": - return p.calc(t, body, args) + return p.proveCalc(t, body, args) case builtins[name].number != nil: return builtins[name].number(body, builtins[name].prints, args) case isTransform: @@ -172,12 +172,12 @@ func (p *valueProof) template(t *template) proven { return printing(body, DataTypeString, proven{notOperand: fmt.Sprintf("{%s} prints text, not a number", body)}) } -func (p *valueProof) calc(t *template, body string, args []string) proven { +func (p *valueProof) proveCalc(t *template, body string, args []string) proven { expr, err := parseCalc(args[0]) if err != nil { panic(fmt.Sprintf("fejkdata: calc(%q) reached a proof unparsed: %v", args[0], err)) } - v, doubt := p.expr(expr, t.fields) + v, doubt := p.proveExpr(expr, t.fields) if doubt == "" && !(magnitude(v) <= calcLimit) { doubt = calcText(expr) + " is not proven within 1e300" } @@ -191,28 +191,28 @@ func (p *valueProof) calc(t *template, body string, args []string) proven { // math.MaxFloat64 that rounding in the bounds cannot hide an overflow. const calcLimit = 1e300 -// expr bounds a calc expression from its operands, or says why it cannot. -func (p *valueProof) expr(n calcNode, fields map[string]node) (proven, string) { +// proveExpr bounds a calc expression from its operands, or says why it cannot. +func (p *valueProof) proveExpr(n calcNode, fields map[string]node) (proven, string) { switch n := n.(type) { case calcNum: v := float64(n) return bounded(v, v, v == math.Trunc(v)), "" case calcVar: - v := p.of(fields[string(n)]) + v := p.prove(fields[string(n)]) if v.notOperand != "" { return proven{}, fmt.Sprintf("operand %q: %s", string(n), v.notOperand) } return proven{lo: v.lo, hi: v.hi, nonZero: v.nonZero, integral: v.integral}, "" case calcNeg: - v, doubt := p.expr(n.x, fields) + v, doubt := p.proveExpr(n.x, fields) v.lo, v.hi = -v.hi, -v.lo return v, doubt case calcBin: - l, doubt := p.expr(n.l, fields) + l, doubt := p.proveExpr(n.l, fields) if doubt != "" { return l, doubt } - r, doubt := p.expr(n.r, fields) + r, doubt := p.proveExpr(n.r, fields) if doubt != "" { return r, doubt }