diff --git a/builtins.go b/builtins.go index dd8e72d..31c3916 100644 --- a/builtins.go +++ b/builtins.go @@ -115,7 +115,7 @@ func formatFloat(v float64, dp int) string { func atoi(s string) int { n, err := strconv.Atoi(s) 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 } @@ -124,7 +124,7 @@ func atoi(s string) int { func atof(s string) float64 { f, err := strconv.ParseFloat(s, 64) 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 } diff --git a/calc.go b/calc.go index 60801fb..827fde1 100644 --- a/calc.go +++ b/calc.go @@ -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 // silently wrong number. 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) } @@ -191,7 +191,7 @@ func neverNumeric(n node) (text string, never bool) { func calcPrep(args []string) callFn { expr, err := parseCalc(args[0]) 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) for i, name := range calcVars(expr) { @@ -219,7 +219,7 @@ func indexVars(n calcNode, at map[string]int) calcNode { case calcVar: i, placed := at[string(n)] 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) case calcNeg: diff --git a/fejkdata.go b/fejkdata.go index 7999c23..25c0666 100644 --- a/fejkdata.go +++ b/fejkdata.go @@ -240,3 +240,7 @@ func newRand(seed uint64, seeded bool) (*session, error) { } return &session{Rand: r, counters: map[string]uint64{}}, nil } + +func internalError(format string, a ...any) string { + return "fejkdata: internal error: " + fmt.Sprintf(format, a...) +} diff --git a/graph.go b/graph.go index 10d7e65..7d30b9e 100644 --- a/graph.go +++ b/graph.go @@ -162,7 +162,7 @@ func renderEdges(n node) []renderEdge { case *folder, *nullItem: return nil default: - panic(fmt.Sprintf("fejkdata: renderEdges has no case for node %T", n)) + panic(internalError("renderEdges has no case for node %T", n)) } } diff --git a/hold.go b/hold.go index 0b30533..590ee5b 100644 --- a/hold.go +++ b/hold.go @@ -1,9 +1,6 @@ package fejkdata -import ( - "fmt" - "strings" -) +import "strings" // 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 @@ -39,7 +36,7 @@ func readField(s *session, t *template, held *hold, sc renderScope, a arm) readV } if !t.compiled.held[a.key] { 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)} } diff --git a/holdset.go b/holdset.go index 810b8d2..d0a2e0c 100644 --- a/holdset.go +++ b/holdset.go @@ -1,9 +1,6 @@ package fejkdata -import ( - "fmt" - "strings" -) +import "strings" // 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. @@ -61,7 +58,7 @@ func (sc renderScope) at(n node, pins *pinSet) renderScope { // rowOf is the row of t its columns render from. func (sc renderScope) rowOf(t *table) int { 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 } diff --git a/layout.go b/layout.go index 69f26c1..af98d7e 100644 --- a/layout.go +++ b/layout.go @@ -54,7 +54,7 @@ func layoutArg(a string) (string, error) { func layoutOf(a string) string { layout, err := layoutArg(a) 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 } @@ -128,11 +128,11 @@ func timeArg(_ map[string]node, a []string) error { func datePrep(a []string) callFn { from, err := time.Parse(dayLayout, a[0]) 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]) 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 return func(s *session, _ string, _ []string) string { diff --git a/path.go b/path.go index 3fd8b5b..771248c 100644 --- a/path.go +++ b/path.go @@ -353,7 +353,7 @@ type pathDraw struct { func drawPath(n node, tail []string, level string, w *pathDraw) node { leaf, err := w.walk(n, tail) 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 } diff --git a/pins.go b/pins.go index f16cee0..5866e3b 100644 --- a/pins.go +++ b/pins.go @@ -32,7 +32,7 @@ func (p *pinSet) pinned(t *table) (int, bool) { func (p *pinSet) mustRow(t *table) int { r, ok := p.pinned(t) 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 } diff --git a/render.go b/render.go index b6490d6..739ce15 100644 --- a/render.go +++ b/render.go @@ -85,7 +85,7 @@ func render(s *session, n node, sc renderScope) string { } return b.String() default: - panic(fmt.Sprintf("fejkdata: uncompiled node %T", n)) + panic(internalError("uncompiled node %T", n)) } } diff --git a/struct.go b/struct.go index 67f5643..a6f3df1 100644 --- a/struct.go +++ b/struct.go @@ -422,6 +422,6 @@ func setText(field reflect.Value, text string) { field.SetUint(n) } 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)) } } diff --git a/transform.go b/transform.go index d5a3ae6..e5f965e 100644 --- a/transform.go +++ b/transform.go @@ -17,7 +17,7 @@ var transforms = map[string]func(string) string{ func withTransforms(calls map[string]builtin) map[string]builtin { for name, fn := range transforms { 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} } @@ -68,7 +68,7 @@ func transformPrep(outer func(string) string) func([]string) callFn { return func(a []string) callFn { _, chain, err := unwrapTransform(a[0]) 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 { v := operands[0] diff --git a/value.go b/value.go index 3a764d8..0c73593 100644 --- a/value.go +++ b/value.go @@ -176,7 +176,7 @@ func (p *valueProof) proveTemplate(t *template) 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)) + panic(internalError("calc(%q) reached a proof unparsed: %v", args[0], err)) } v, doubt := p.proveExpr(expr, t.fields) 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) } - 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.