Answer architecture round 3 and principles audits round 2: a weight drawn against nothing names the drop, null alone on stdin names jq, the CLI-copy decision names hasEmptySegment, the padding and layout decisions quote what they catch, and the padded binding is filed
This commit is contained in:
@@ -459,6 +459,9 @@ func parseInput(raw string) (input, error) {
|
||||
if trimmed == "" {
|
||||
return input{}, fmt.Errorf("stdin holds no template: %s", pipeHint)
|
||||
}
|
||||
if trimmed == "null" {
|
||||
return input{}, fmt.Errorf("stdin holds only null, as jq prints for a missing key: %s", pipeHint)
|
||||
}
|
||||
text := raw
|
||||
if json.Valid([]byte(trimmed)) {
|
||||
text = trimmed
|
||||
@@ -511,7 +514,7 @@ func hasEmptySegment(path string) bool {
|
||||
switch {
|
||||
case seg != "":
|
||||
stepUp = false
|
||||
case stepUp && !last, !stepUp && last:
|
||||
case stepUp != last:
|
||||
return true
|
||||
default:
|
||||
stepUp = !stepUp
|
||||
|
||||
+5
-5
@@ -102,7 +102,7 @@ template per run.
|
||||
2026-10-07, Lilleman auf Larv. Serves goal 9.6: a CLI carrying your own modules is a few
|
||||
lines of Go and works just like `fejkdata`, so `fejkdata`'s own CLI is such a CLI and
|
||||
imports nothing under `internal/`. It copies one reading the API does not export yet,
|
||||
the lone reference: `isPath` and `withoutSelectors` in `cmd/fejkdata`, pinned to the
|
||||
the lone reference: `isPath`, `hasEmptySegment` and `withoutSelectors` in `cmd/fejkdata`, pinned to the
|
||||
grammar by a test, until `todo.md` item 129 moves that reading into the library.
|
||||
|
||||
## A template that does not compile is misuse (exit 2), including a reference that resolves to nothing, save a lone reference under the CLI's `--format` until item 129
|
||||
@@ -119,8 +119,8 @@ until item 129: it reads a path, and only the data is absent.
|
||||
|
||||
Padding is where the two readings disagree: a format string renders it, JSON drops it. A
|
||||
template that parses as JSON is its JSON, so its padding is dropped, as `encoding/json`
|
||||
drops it. Goal 5.7 refuses only a spelling that suggests a mistake, and padding around
|
||||
JSON suggests none.
|
||||
drops it. Goal 5.7: only an obvious mistake fails to load, and padding around JSON is
|
||||
none.
|
||||
|
||||
## A JSON string stays a template even where its bare text renders alike
|
||||
|
||||
@@ -640,8 +640,8 @@ Table section teaches it.
|
||||
2026-09-18, Lilleman auf Larv. Serves goal 5.6.
|
||||
|
||||
A layout may carry the comma that separates arguments,
|
||||
`'January 2, 2006'`, and a bare `2006-01-02` reads like a third date, so a bare layout is
|
||||
refused naming the quoted one. The layout is Go's reference time because the
|
||||
`'January 2, 2006'`, a bare `2006-01-02` reads like a third date, and a double-quoted one
|
||||
could be quotes printed in the output, so each is refused naming the single-quoted one. The layout is Go's reference time because the
|
||||
library renders with it and a Go caller already knows it; its names are English, and a
|
||||
locale's own month and weekday names are data.
|
||||
|
||||
|
||||
@@ -118,13 +118,14 @@ const (
|
||||
// compileAt compiles a node drawn against no other: no choice's item, or a one-item choice's.
|
||||
// A weight there does nothing, bar the default 1 written out.
|
||||
func compileAt(v any, pos position) (node, error) {
|
||||
w, err := weightOf(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if w != 1 {
|
||||
if o, isObject := v.(map[string]any); isObject {
|
||||
if w, isNumber := o["weight"].(float64); isNumber && w != 1 {
|
||||
return nil, fmt.Errorf(`weight %v skews a draw between items, and nothing here is drawn against this one; drop "weight"`, w)
|
||||
}
|
||||
}
|
||||
if _, err := weightOf(v); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return compileItem(v, pos)
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
`Bar = 9`
|
||||
|
||||
`Next ID = 161`
|
||||
`Next ID = 162`
|
||||
|
||||
| Goal | W |
|
||||
|---|---|
|
||||
@@ -123,6 +123,7 @@
|
||||
| 79 | 0.2.0 | decision | **Beside a `--data-path`, load in `New` the user's categories, the shipped ones they override or read, and the shipped ones whose reads reach an overridden one; load the rest on first reach.** | 6 | 6 | 7 | 8 | 13 | 12.9 |
|
||||
| 27 | 0.2.0 | | **Merge `en_US.ip` and `sv_SE.ip`, today byte-identical, into one `misc.ip`.** | 3 | 2 | 4 | 6 | 8 | 12.3 |
|
||||
| 107 | 0.2.0 | decision | **Move the template engine into `internal/`, leaving the root the public API and its options.** | 6 | 9 | 3 | 8 | 3.2, 3.4 | 12.2 |
|
||||
| 161 | 0.2.0 | | **Refuse an identifier that starts or ends with whitespace, so `{ x as p}` loads as `{x as p}` or every field can be bound to a name.** | 2 | 2 | 2 | 6 | 5.6, 4.1 | 11.7 |
|
||||
| 112 | 0.2.0 | | **Check a calc's field operands where its template resolves, beside its name operands, once item 36 reports every mistake at once.** | 2 | 2 | 1 | 6 | 3.2 | 10.3 |
|
||||
| 108 | 0.2.0 | defect | **Name item 26 in the decision "No builtin reads the clock, so a date is bounded by days, never by an age", as the item that ends its conflict with goal 4.** | 1 | 1 | 1 | 4 | 3.4 | 8.0 |
|
||||
| 38 | 0.3.0 | defect | **Compare `calcParser.binary`'s operator as a rune.** | 1 | 1 | 3 | 6 | 6 | 13.8 |
|
||||
@@ -465,6 +466,10 @@ The decision "With only the shipped set, a category loads on the first call reac
|
||||
|
||||
The engine returns column values and the root builds `Record`. Revises the decision "The template engine stays the root package until item 107; what reads no engine type, a table's rows included, sits in `internal/`", and, if the vocabulary moves, "The vocabulary sits below `doc.go`'s package clause, not in the package doc".
|
||||
|
||||
### 161. Refuse an identifier that starts or ends with whitespace, so `{ x as p}` loads as `{x as p}` or every field can be bound to a name.
|
||||
|
||||
`grammar/identifier.go` allows a field named ` x`, and `{ x}` reads it, but `checkBind` in `format.go` refuses every padded binding, so no spelling binds that field to a name (goal 4.1), and the refusal names one meaning only (goal 5.6). The goals audit of the narrowed goal 5.7 found it.
|
||||
|
||||
### 112. Check a calc's field operands where its template resolves, beside its name operands, once item 36 reports every mistake at once.
|
||||
|
||||
Needs item 36. `checkCalcFields` runs at compile and `checkCalcNames` in `resolveTemplates`, two passes over one rule. Moving the field check there before item 36 would change which of two mistakes in two category files a load reports, since every category compiles before any resolves.
|
||||
|
||||
Reference in New Issue
Block a user