Answer architecture round 3: the generated header names go generate, one sorted-keys helper everywhere, one site constructor, and an inline folder reference refused before anything loads

This commit is contained in:
2026-10-03 17:46:28 +02:00
committed by Lillem4n
parent 3bb8628e39
commit cc8797744b
10 changed files with 32 additions and 42 deletions
+5 -1
View File
@@ -203,13 +203,17 @@ func categorySites(root *folder) []categorySite {
walk(append(dir[:len(dir):len(dir)], name), sub)
continue
}
out = append(out, categorySite{dir: dir, path: join(strings.Join(dir, "."), name), in: g, n: g.children[name]})
out = append(out, siteIn(dir, g, name))
}
}
walk(nil, root)
return out
}
func siteIn(dir []string, in *folder, name string) categorySite {
return categorySite{dir: dir, path: join(strings.Join(dir, "."), name), in: in, n: in.children[name]}
}
func sitesScope(sites []categorySite) nodeScope {
return func(fn func(path string, n node) error) error {
for _, s := range sites {
+1 -6
View File
@@ -180,12 +180,7 @@ func paths(n node) []string {
func tablePaths(t *table) []string {
out := append([]string{""}, t.header...)
sort.Strings(out[1:])
children := make([]string, 0, len(t.children))
for name := range t.children {
children = append(children, name)
}
sort.Strings(children)
for _, name := range children {
for _, name := range sortedNames(t.children) {
for _, p := range paths(t.children[name]) {
out = append(out, join(name, p))
}
+18 -5
View File
@@ -152,6 +152,9 @@ func inputValue(input string) (any, error) {
// binding's.
func bindInline(root *folder, n node, label string, typedByGo bool) error {
scope := inlineScope(n, label)
if err := refuseFolderRefs(scope); err != nil {
return err
}
loadShipped(root, unloadedReads(root, nil, scope))
return binding{
scope: scope,
@@ -166,10 +169,9 @@ func bindInline(root *folder, n node, label string, typedByGo bool) error {
}.bind()
}
// linkNodeRefs binds the references in an inline node's templates against the
// loaded tree.
func linkNodeRefs(scope nodeScope, root map[string]node) error {
if err := scope(func(path string, m node) error {
// refuseFolderRefs refuses a reference an inline node writes from a folder, which it has none of.
func refuseFolderRefs(scope nodeScope) error {
return scope(func(path string, m node) error {
t, ok := m.(*template)
if !ok {
return nil
@@ -183,7 +185,18 @@ func linkNodeRefs(scope nodeScope, root map[string]node) error {
return fmt.Errorf("%s: reference {%s}: an inline template has no folder; write {/%s}", path, name, rest)
}
}
return linkTemplate(nil, path, "", t, root)
return nil
})
}
// linkNodeRefs binds the references in an inline node's templates against the
// loaded tree.
func linkNodeRefs(scope nodeScope, root map[string]node) error {
if err := scope(func(path string, m node) error {
if t, ok := m.(*template); ok {
return linkTemplate(nil, path, "", t, root)
}
return nil
}); err != nil {
return err
}
+1 -7
View File
@@ -3,7 +3,6 @@ package fejkdata
import (
"fmt"
"slices"
"sort"
)
// checkNameReads refuses each binding of t that checkUses refuses, and a read such as {n} whose
@@ -117,12 +116,7 @@ func (b *nameBinding) checkTemplateOnce(read string, t *template, key string) er
}
}
}
heads := make([]string, 0, len(fresh))
for head := range fresh {
heads = append(heads, head)
}
sort.Strings(heads)
for _, head := range heads {
for _, head := range sortedNames(fresh) {
if by, kept := b.addressed[join(key, head)]; kept && fresh[head] > 1 {
return fmt.Errorf("{%s} renders field %q twice, so {%s} cannot say which draw it reads; drop {%s} or {%s}", read, head, by, read, by)
}
+1 -6
View File
@@ -11,12 +11,7 @@ import (
// docs/decisions.md#one-name-one-meaning
func TestNoFunctionSpellsAMethod(t *testing.T) {
funcs, methods := declaredCalls(namespaceFiles(t))
names := make([]string, 0, len(funcs))
for name := range funcs {
names = append(names, name)
}
sort.Strings(names)
for _, name := range names {
for _, name := range sortedNames(funcs) {
if recv := methods[name]; len(recv) > 0 {
sort.Strings(recv)
t.Errorf("func %s is spelled by %s too; name them apart", name, strings.Join(recv, " and "))
+1 -6
View File
@@ -2,7 +2,6 @@ package fejkdata
import (
"fmt"
"sort"
"strings"
)
@@ -470,11 +469,7 @@ func unreachableInChoice(c *choice, want string) error {
if len(c.shared) == 0 {
return fmt.Errorf("no variant of this %d-way choice carries %q", len(c.items), want)
}
offered := make([]string, 0, len(c.shared))
for p := range c.shared {
offered = append(offered, p)
}
sort.Strings(offered)
offered := sortedNames(c.shared)
return fmt.Errorf("not every variant of this %d-way choice carries %q; all carry %v", len(c.items), want, offered)
}
+1 -7
View File
@@ -2,7 +2,6 @@ package fejkdata
import (
"os"
"sort"
"strconv"
"strings"
"testing"
@@ -109,12 +108,7 @@ func readsFact(n node) string {
if len(set) == 0 {
return ""
}
keys := make([]string, 0, len(set))
for k := range set {
keys = append(keys, k)
}
sort.Strings(keys)
return "\treads " + strings.Join(keys, " ")
return "\treads " + strings.Join(sortedNames(set), " ")
}
func TestShippedShapeNamesReads(t *testing.T) {
+1 -1
View File
@@ -139,7 +139,7 @@ func (u unloadedCategory) load() (categorySite, error) {
return categorySite{}, err
}
delete(u.in.unloaded, u.name)
return categorySite{dir: u.dir, path: join(strings.Join(u.dir, "."), u.name), in: u.in, n: u.in.children[u.name]}, nil
return siteIn(u.dir, u.in, u.name), nil
}
// linkedTables is the tables beside u that link to it or that it links to: its parent, and
+2 -2
View File
@@ -66,7 +66,7 @@ func TestShippedIndexIsCurrent(t *testing.T) {
func shippedIndexSource(whole *Generator) ([]byte, error) {
var b bytes.Buffer
b.WriteString("// Code generated by TestShippedIndexIsCurrent with REPIN=1. DO NOT EDIT.\n\npackage fejkdata\n\nvar shippedIndex = map[string]shippedEntry{\n")
b.WriteString("// Code generated by go generate. DO NOT EDIT.\n\npackage fejkdata\n\nvar shippedIndex = map[string]shippedEntry{\n")
for _, s := range categorySites(&whole.root) {
fmt.Fprintf(&b, "%q: {", s.path)
if t, isTable := s.n.(*table); isTable && t.parentIndex >= 0 {
@@ -183,7 +183,7 @@ func TestOnDemandRendersAsTheWholeLoad(t *testing.T) {
}
func TestEveryShippedCategoryLoadsAlone(t *testing.T) {
for p := range shippedIndex {
for _, p := range sortedNames(shippedIndex) {
f, err := New()
if err != nil {
t.Fatalf("New() = %v", err)
+1 -1
View File
@@ -1,4 +1,4 @@
// Code generated by TestShippedIndexIsCurrent with REPIN=1. DO NOT EDIT.
// Code generated by go generate. DO NOT EDIT.
package fejkdata