Report every invariant break through internalError

This commit is contained in:
2026-09-29 01:38:45 +02:00
committed by Lillem4n
parent 3aa747de02
commit 514d738b08
13 changed files with 25 additions and 27 deletions
+2 -2
View File
@@ -115,7 +115,7 @@ func formatFloat(v float64, dp int) string {
func atoi(s string) int { func atoi(s string) int {
n, err := strconv.Atoi(s) n, err := strconv.Atoi(s)
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: builtin arg %q reached prep unvalidated: %v", s, err)) panic(internalError("builtin arg %q reached prep unvalidated: %v", s, err))
} }
return n return n
} }
@@ -124,7 +124,7 @@ func atoi(s string) int {
func atof(s string) float64 { func atof(s string) float64 {
f, err := strconv.ParseFloat(s, 64) f, err := strconv.ParseFloat(s, 64)
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: builtin arg %q reached prep unvalidated: %v", s, err)) panic(internalError("builtin arg %q reached prep unvalidated: %v", s, err))
} }
return f return f
} }
+3 -3
View File
@@ -38,7 +38,7 @@ func (n calcIdx) eval(operands []string) float64 {
// than returning NaN, so a node kind indexVars forgets is a stack trace and not a // than returning NaN, so a node kind indexVars forgets is a stack trace and not a
// silently wrong number. // silently wrong number.
func (n calcVar) eval([]string) float64 { func (n calcVar) eval([]string) float64 {
panic(fmt.Sprintf("fejkdata: calc operand %q was never placed", string(n))) panic(internalError("calc operand %q was never placed", string(n)))
} }
func (n calcNeg) eval(operands []string) float64 { return -n.x.eval(operands) } func (n calcNeg) eval(operands []string) float64 { return -n.x.eval(operands) }
@@ -191,7 +191,7 @@ func neverNumeric(n node) (text string, never bool) {
func calcPrep(args []string) callFn { func calcPrep(args []string) callFn {
expr, err := parseCalc(args[0]) expr, err := parseCalc(args[0])
if err != nil { // a nil AST would be a nil dereference per render, with no message if err != nil { // a nil AST would be a nil dereference per render, with no message
panic(fmt.Sprintf("fejkdata: calc(%q) reached prep unparsed: %v", args[0], err)) panic(internalError("calc(%q) reached prep unparsed: %v", args[0], err))
} }
at := make(map[string]int) at := make(map[string]int)
for i, name := range calcVars(expr) { for i, name := range calcVars(expr) {
@@ -219,7 +219,7 @@ func indexVars(n calcNode, at map[string]int) calcNode {
case calcVar: case calcVar:
i, placed := at[string(n)] i, placed := at[string(n)]
if !placed { // calcVars named every operand, so a miss means the two disagree if !placed { // calcVars named every operand, so a miss means the two disagree
panic(fmt.Sprintf("fejkdata: calc operand %q is not among the names read for it", string(n))) panic(internalError("calc operand %q is not among the names read for it", string(n)))
} }
return calcIdx(i) return calcIdx(i)
case calcNeg: case calcNeg:
+4
View File
@@ -240,3 +240,7 @@ func newRand(seed uint64, seeded bool) (*session, error) {
} }
return &session{Rand: r, counters: map[string]uint64{}}, nil return &session{Rand: r, counters: map[string]uint64{}}, nil
} }
func internalError(format string, a ...any) string {
return "fejkdata: internal error: " + fmt.Sprintf(format, a...)
}
+1 -1
View File
@@ -162,7 +162,7 @@ func renderEdges(n node) []renderEdge {
case *folder, *nullItem: case *folder, *nullItem:
return nil return nil
default: default:
panic(fmt.Sprintf("fejkdata: renderEdges has no case for node %T", n)) panic(internalError("renderEdges has no case for node %T", n))
} }
} }
+2 -5
View File
@@ -1,9 +1,6 @@
package fejkdata package fejkdata
import ( import "strings"
"fmt"
"strings"
)
// hold is what one expansion has drawn for the names it holds: the variant each was drawn as, so // hold is what one expansion has drawn for the names it holds: the variant each was drawn as, so
// every path under it reads one variant; and the value each read produced, by its path, so the // every path under it reads one variant; and the value each read produced, by its path, so the
@@ -39,7 +36,7 @@ func readField(s *session, t *template, held *hold, sc renderScope, a arm) readV
} }
if !t.compiled.held[a.key] { if !t.compiled.held[a.key] {
if len(a.tail) > 0 { if len(a.tail) > 0 {
panic(fmt.Sprintf("fejkdata: %q reads a path into %q, which the expansion does not hold", a.spelling, a.key)) panic(internalError("%q reads a path into %q, which the expansion does not hold", a.spelling, a.key))
} }
return readValue{text: render(s, t.head(a.key), sc)} return readValue{text: render(s, t.head(a.key), sc)}
} }
+2 -5
View File
@@ -1,9 +1,6 @@
package fejkdata package fejkdata
import ( import "strings"
"fmt"
"strings"
)
// holdSet is one render's reference draws: the unnamed draw group's, and each named one's; and a // holdSet is one render's reference draws: the unnamed draw group's, and each named one's; and a
// test's trace of its reads. // test's trace of its reads.
@@ -61,7 +58,7 @@ func (sc renderScope) at(n node, pins *pinSet) renderScope {
// rowOf is the row of t its columns render from. // rowOf is the row of t its columns render from.
func (sc renderScope) rowOf(t *table) int { func (sc renderScope) rowOf(t *table) int {
if sc.row.t != t { if sc.row.t != t {
panic(fmt.Sprintf("fejkdata: a column of %s is rendered with no row pinned", t.category)) panic(internalError("a column of %s is rendered with no row pinned", t.category))
} }
return sc.row.row return sc.row.row
} }
+3 -3
View File
@@ -54,7 +54,7 @@ func layoutArg(a string) (string, error) {
func layoutOf(a string) string { func layoutOf(a string) string {
layout, err := layoutArg(a) layout, err := layoutArg(a)
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: builtin arg %q reached prep unvalidated: %v", a, err)) panic(internalError("builtin arg %q reached prep unvalidated: %v", a, err))
} }
return layout return layout
} }
@@ -128,11 +128,11 @@ func timeArg(_ map[string]node, a []string) error {
func datePrep(a []string) callFn { func datePrep(a []string) callFn {
from, err := time.Parse(dayLayout, a[0]) from, err := time.Parse(dayLayout, a[0])
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: builtin arg %q reached prep unvalidated: %v", a[0], err)) panic(internalError("builtin arg %q reached prep unvalidated: %v", a[0], err))
} }
to, err := time.Parse(dayLayout, a[1]) to, err := time.Parse(dayLayout, a[1])
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: builtin arg %q reached prep unvalidated: %v", a[1], err)) panic(internalError("builtin arg %q reached prep unvalidated: %v", a[1], err))
} }
layout, start, span := layoutOf(a[2]), from.Unix(), int(to.Unix()-from.Unix())+86400 layout, start, span := layoutOf(a[2]), from.Unix(), int(to.Unix()-from.Unix())+86400
return func(s *session, _ string, _ []string) string { return func(s *session, _ string, _ []string) string {
+1 -1
View File
@@ -353,7 +353,7 @@ type pathDraw struct {
func drawPath(n node, tail []string, level string, w *pathDraw) node { func drawPath(n node, tail []string, level string, w *pathDraw) node {
leaf, err := w.walk(n, tail) leaf, err := w.walk(n, tail)
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: %s: %v; the path should have been proved before it was drawn", join(level, joinSegments(tail)), err)) panic(internalError("%s: %v; the path should have been proved before it was drawn", join(level, joinSegments(tail)), err))
} }
return leaf return leaf
} }
+1 -1
View File
@@ -32,7 +32,7 @@ func (p *pinSet) pinned(t *table) (int, bool) {
func (p *pinSet) mustRow(t *table) int { func (p *pinSet) mustRow(t *table) int {
r, ok := p.pinned(t) r, ok := p.pinned(t)
if !ok { if !ok {
panic(fmt.Sprintf("fejkdata: a column of %s is rendered with no row pinned", t.category)) panic(internalError("a column of %s is rendered with no row pinned", t.category))
} }
return r return r
} }
+1 -1
View File
@@ -85,7 +85,7 @@ func render(s *session, n node, sc renderScope) string {
} }
return b.String() return b.String()
default: default:
panic(fmt.Sprintf("fejkdata: uncompiled node %T", n)) panic(internalError("uncompiled node %T", n))
} }
} }
+1 -1
View File
@@ -422,6 +422,6 @@ func setText(field reflect.Value, text string) {
field.SetUint(n) field.SetUint(n)
} }
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: %q reached a %s field unproven: %v", text, field.Type(), err)) panic(internalError("%q reached a %s field unproven: %v", text, field.Type(), err))
} }
} }
+2 -2
View File
@@ -17,7 +17,7 @@ var transforms = map[string]func(string) string{
func withTransforms(calls map[string]builtin) map[string]builtin { func withTransforms(calls map[string]builtin) map[string]builtin {
for name, fn := range transforms { for name, fn := range transforms {
if _, clash := calls[name]; clash { if _, clash := calls[name]; clash {
panic("fejkdata: " + name + " is registered as a builtin and a transform") panic(internalError("%s is registered as a builtin and a transform", name))
} }
calls[name] = builtin{arity: 1, checkArgs: transformArg, prep: transformPrep(fn), operands: transformOperand} calls[name] = builtin{arity: 1, checkArgs: transformArg, prep: transformPrep(fn), operands: transformOperand}
} }
@@ -68,7 +68,7 @@ func transformPrep(outer func(string) string) func([]string) callFn {
return func(a []string) callFn { return func(a []string) callFn {
_, chain, err := unwrapTransform(a[0]) _, chain, err := unwrapTransform(a[0])
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: transform arg %q reached prep unvalidated: %v", a[0], err)) panic(internalError("transform arg %q reached prep unvalidated: %v", a[0], err))
} }
return func(_ *session, _ string, operands []string) string { return func(_ *session, _ string, operands []string) string {
v := operands[0] v := operands[0]
+2 -2
View File
@@ -176,7 +176,7 @@ func (p *valueProof) proveTemplate(t *template) proven {
func (p *valueProof) proveCalc(t *template, body string, args []string) proven { func (p *valueProof) proveCalc(t *template, body string, args []string) proven {
expr, err := parseCalc(args[0]) expr, err := parseCalc(args[0])
if err != nil { if err != nil {
panic(fmt.Sprintf("fejkdata: calc(%q) reached a proof unparsed: %v", args[0], err)) panic(internalError("calc(%q) reached a proof unparsed: %v", args[0], err))
} }
v, doubt := p.proveExpr(expr, t.fields) v, doubt := p.proveExpr(expr, t.fields)
if doubt == "" && !(magnitude(v) <= calcLimit) { if doubt == "" && !(magnitude(v) <= calcLimit) {
@@ -219,7 +219,7 @@ func (p *valueProof) proveExpr(n calcNode, fields map[string]node) (proven, stri
} }
return combine(n, l, r) return combine(n, l, r)
} }
panic(fmt.Sprintf("fejkdata: calc node %T has no bound", n)) panic(internalError("calc node %T has no bound", n))
} }
// combine bounds one operation from the bounds of its sides. // combine bounds one operation from the bounds of its sides.