Answer architecture round 2: guard Noun's range, name calc once as builtinfunc.Calc, and place readTableOptions in item 46

This commit is contained in:
2026-10-05 15:48:34 +02:00
committed by Lillem4n
parent a229ae90a2
commit 679bd43c7c
7 changed files with 15 additions and 6 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ func checkCalcFields(args []string, fields map[string]node) error {
// checkCalcNames holds each calc of t reading a name to the checks checkCalcFields makes of a field.
func checkCalcNames(path string, t *template) error {
for _, o := range t.compiled.ops {
if o.Fn != "calc" || !slices.ContainsFunc(o.operands, func(a arm) bool { return a.kind == namedRead }) {
if o.Fn != builtinfunc.Calc || !slices.ContainsFunc(o.operands, func(a arm) bool { return a.kind == namedRead }) {
continue
}
if err := checkOperands(o.Args[0], builtinfunc.ParsedCalc(o.Args[0]), operandNodes(o)); err != nil {
+1 -1
View File
@@ -12,7 +12,7 @@ import (
// operands fields holds.
func checkFunc(tok grammar.Token, fields map[string]node) error {
err := builtinfunc.Check(tok.Fn, tok.Args)
if err == nil && tok.Fn == "calc" {
if err == nil && tok.Fn == builtinfunc.Calc {
err = checkCalcFields(tok.Args, fields)
}
if err != nil {
+4
View File
@@ -43,6 +43,10 @@ type builtin struct {
prints datatype.DataType
}
// Calc is the name of the builtin whose operands the caller checks and proves, as nodes only
// it holds.
const Calc = "calc"
// rng is the randomness a builtin sample draws from, which *drawstate.State satisfies.
type rng interface {
IntN(n int) int
+1 -1
View File
@@ -66,7 +66,7 @@ var builtins = withTransforms(map[string]builtin{
}},
"date": {arity: -1, checkArgs: dateArgs, prep: datePrep},
"time": {arity: -1, checkArgs: timeArg, prep: timePrep},
"calc": {arity: -1, checkArgs: checkCalc, prep: calcPrep, operands: calcOperands, noRefOperands: true},
Calc: {arity: -1, checkArgs: checkCalc, prep: calcPrep, operands: calcOperands, noRefOperands: true},
// seq is the one stateful builtin: a per-generator counter from 1, advancing on
// each call. An optional name selects an independent counter; no name uses the
// default one. Deterministic by construction, so seeded output stays stable.
+6 -1
View File
@@ -31,4 +31,9 @@ func (d DataType) String() string {
}
// Noun is the datatype as an error names what a value is.
func Noun(d DataType) string { return nouns[d] }
func Noun(d DataType) string {
if d < 0 || d >= Count {
return d.String()
}
return nouns[d]
}
+1 -1
View File
@@ -380,7 +380,7 @@ Require the path step to reach a sibling category.
### 46. Report the same error every load for a table with two bad options, and for a folder with two unnamed rows files.
`readTableOptions` and `walkDir` in `internal/datafiles` return on the first in Go's map order.
`readTableOptions` in `table.go` and `walkDir` in `internal/datafiles` return on the first in Go's map order.
### 107. Move the template engine into `internal/`, leaving the root the public API and its options.
+1 -1
View File
@@ -173,7 +173,7 @@ func (p *valueProof) proveTemplate(t *template) proven.Value {
leaves = append(leaves, a.leaves...)
}
return p.proveUnion(leaves)
case name == "calc":
case name == builtinfunc.Calc:
return p.proveCalc(o)
case builtinfunc.IsTransform(name):
return proven.Unproven(fmt.Sprintf("{%s} rewrites text rather than printing a value; write the values it would print", body))