Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33

Open
lilleman wants to merge 966 commits from worktree-todo-relative-dates-exact-counts into main
5 changed files with 29 additions and 25 deletions
Showing only changes of commit 317486df0a - Show all commits
+3 -3
View File
@@ -188,12 +188,12 @@ func ibanValid(s string) bool {
return rem == 1
}
// TestRegistryShapes pins the builtin contract compileOps relies on: every entry
// TestRegistryShapes pins the builtin contract compileFormat relies on: every entry
// supplies prep, and args parsed at compile only behind a check.
func TestRegistryShapes(t *testing.T) {
for name, b := range builtins {
if b.prep == nil {
t.Errorf("builtin %q has no prep: compileOps would call a nil func", name)
t.Errorf("builtin %q has no prep: compileFormat would call a nil func", name)
}
if b.arity != 0 && b.checkArgs == nil {
t.Errorf("builtin %q parses args in prep with no check", name)
@@ -203,7 +203,7 @@ func TestRegistryShapes(t *testing.T) {
// TestArgGuardsPanic pins the guards that report a builtin arg its check should
// have rejected. No data reaches them — checkFunc runs a builtin's check before
// compileOps ever calls prep — so they are exercised directly.
// compileFormat ever calls prep — so they are exercised directly.
func TestArgGuardsPanic(t *testing.T) {
for name, call := range map[string]func(){
"atoi on an unvalidated arg": func() { atoi("nope") },
+2 -12
View File
@@ -441,19 +441,9 @@ func (c *formatOps) field(tok formatToken, refs map[string]refBinding) {
c.ops = append(c.ops, op{formatToken: tok, arms: arms})
}
// compileFormat compiles a format into ops, and applies the fences that need the
// compiled reads.
func compileFormat(toks []formatToken, refs map[string]refBinding) (formatOps, error) {
c := compileOps(toks, refs)
if err := checkNoOverlap(c); err != nil {
return c, err
}
return c, checkNoRepeatedRead(c)
}
// compileOps compiles a parsed format. Call checkTokens first: it is what proves
// compileFormat compiles a parsed format. Call checkTokens first: it is what proves
// every token valid.
func compileOps(toks []formatToken, refs map[string]refBinding) formatOps {
func compileFormat(toks []formatToken, refs map[string]refBinding) formatOps {
var c formatOps
for _, tok := range toks {
switch tok.kind {
+14 -1
View File
@@ -15,10 +15,23 @@ func heldCheck(path string, n node) error {
if !ok || len(t.compiled.held) == 0 {
return nil
}
if err := checkHeld(t); err != nil {
return fmt.Errorf("%s: %w", t.site.label(path), err)
}
return nil
}
func checkHeld(t *template) error {
if err := checkNoOverlap(t.compiled); err != nil {
return err
}
if err := checkNoRepeatedRead(t.compiled); err != nil {
return err
}
readers := pathHeadReaders(t.compiled)
for _, name := range heldNames(t) {
if err := checkNameHeld(t, name, readers); err != nil {
return fmt.Errorf("%s: %w", path, err)
return err
}
}
return nil
+8
View File
@@ -73,6 +73,14 @@ func (s tableSite) isCell() bool {
return s.table != nil && s.row != formatRow
}
// label names the template at path in an error, a cell by its line in the rows file.
func (s tableSite) label(path string) string {
if s.isCell() {
return fmt.Sprintf("%s, line %d", path, s.row+2)
}
return path
}
// templateLink is what a template resolves to in the assembled tree.
type templateLink struct {
refs map[string]refBinding // each reference the format reads -> what it resolves to
+2 -9
View File
@@ -81,18 +81,11 @@ func linkRefs(root map[string]node) error {
// linkTemplate resolves t's references in category, "" for an inline template, and
// compiles its format against them.
func linkTemplate(folder []string, path, category string, t *template, root map[string]node) error {
if t.site.isCell() {
path = fmt.Sprintf("%s, line %d", path, t.site.row+2)
}
link, err := t.resolveLink(folder, path, category, root)
link, err := t.resolveLink(folder, t.site.label(path), category, root)
if err != nil {
return err
}
compiled, err := compileFormat(t.tokens, link.refs)
if err != nil {
return fmt.Errorf("%s: %w", path, err)
}
t.link, t.compiled = link, compiled
t.link, t.compiled = link, compileFormat(t.tokens, link.refs)
compileArms(t)
return nil
}