diff --git a/datatype.go b/datatype.go index d9e3424..7fad539 100644 --- a/datatype.go +++ b/datatype.go @@ -138,6 +138,9 @@ func columnItems(n node) (items []*template, nullable bool) { items = append(items, n) case *nullItem: nullable = true + case *tableColumn: + default: + panic(internalError("columnItems has no case for node %T", n)) } } collect(n) diff --git a/node.go b/node.go index 56bd89a..77ab03d 100644 --- a/node.go +++ b/node.go @@ -11,8 +11,9 @@ import ( // node is a compiled element of the namespace tree: a folder, choice, null, // template, table, column or row. Compiling JSON into these once (see compile) -// means rendering never re-inspects the raw JSON. A new kind needs a -// case in contained, paths, render and renderEdges; each panics on a kind it does not list. +// means rendering never re-inspects the raw JSON. A new kind needs a case in +// columnItems, contained, paths, prove, render, renderEdges and stepInto; each +// panics on a kind it does not list. type node interface{ isNode() } // folder is a namespace of named children, built from a directory of JSON files diff --git a/path.go b/path.go index cf62df0..206ec95 100644 --- a/path.go +++ b/path.go @@ -142,6 +142,9 @@ func stepInto(n node, seg string) (node, error) { } case *tableColumn: return nil, fmt.Errorf("no field %q: %q is a column, and a cell holds no fields", seg, n.t.header[n.i]) + case *nullItem: + default: + panic(internalError("stepInto has no case for node %T", n)) } return nil, fmt.Errorf("no field %q", seg) } diff --git a/todo.md b/todo.md index 3ecf6de..40b1f4f 100644 --- a/todo.md +++ b/todo.md @@ -28,10 +28,6 @@ ranking `readSurvey.walk` hardest and all seven the unit they would least modify This round, in order: -- Give `prove`, `stepInto` and `columnItems` a case per node kind and panic through - `internalError` on the rest, and list every such switch in `node`'s doc: `prove`'s - default tells a typed column reading a bare table that it reads a null, and six seats - found `node` naming four of them. - Replace `disagreements`' ten keys with the rule they encode: a declared fix holds one datatype, a read one is `readTyped` where proven and `readAsText` otherwise, a text one is `otherAsText` beside an unproven read and `declare` otherwise. Six seats could not @@ -222,8 +218,6 @@ by a `data-import/` script, as README goal 12 asks. first in Go's map order. - Report a CRLF rows file holding only its header as having no rows: `parseRows` answers "line 2 is empty". -- Refuse a bare table read in a typed column with a reason naming the table, once - `prove` has a case per node kind. - Keep one copy of the selector characters in `data-import/`: `httpmethod.py` and `protocol.py` each copy `inSelector`, and `tsv.py`'s `write` enforces neither. - Refuse two whole reads of one table family in one render, which goal 5 promises is a diff --git a/value.go b/value.go index 243d0bd..ef82019 100644 --- a/value.go +++ b/value.go @@ -89,10 +89,14 @@ func (p *valueProof) prove(n node) proven { v = p.proveTemplate(n) case *tableColumn: v = p.proveCells(n) + case *table: + v = p.prove(n.rowNode) case *tableRow: v = unproven(fmt.Sprintf("%q renders a row of %s, which is composed text", n.t.formatTemplate.format, n.t.segment)) - default: + case *nullItem: v = unproven(`it reads a null, which renders "" outside its own column`) + default: + panic(internalError("prove has no case for node %T", n)) } p.memo[n] = v return v