Compare commits

...

2 Commits

Author SHA1 Message Date
lilleman 72a6ef9071 Name the typed spelling for a column read whose values hold the datatype beside it, and say holding for a datatype taken from a column read
Tests / vet + fmt + tests (pull_request) Successful in 1m2s
Tests / vet + fmt + tests (push) Successful in 7s
2026-09-15 21:44:36 +02:00
lilleman 1e60d52e48 Tests: a typed column read whose values hold the datatype declared beside it names the typed spelling 2026-09-15 21:43:09 +02:00
2 changed files with 19 additions and 6 deletions
+18 -6
View File
@@ -171,22 +171,34 @@ func disagreement(a *template, da DataType, b *template, db DataType) error {
case bare.fromString: // an object may carry a weight, which this spelling would drop case bare.fromString: // an object may carry a weight, which this spelling would drop
return fmt.Errorf(`item %q declares no datatype, and a column holds one; write it as {"format":%q,"datatype":%q}`, bare.format, bare.format, want) return fmt.Errorf(`item %q declares no datatype, and a column holds one; write it as {"format":%q,"datatype":%q}`, bare.format, bare.format, want)
} }
return fmt.Errorf(`item %q declares no datatype beside one declaring %s; a column holds one, so give it "datatype": %q`, bare.format, want, want) return fmt.Errorf(`item %q declares no datatype beside one holding %s; a column holds one, so give it "datatype": %q`, bare.format, want, want)
} }
// bothTyped names the fix for two items holding different datatypes: reading one that takes its // bothTyped names the fix for two items holding different datatypes: the one taking its datatype
// datatype from the column it reads as text, since only a declared datatype can be edited away. // from the column it reads is typed as the other where its values prove it, else read as text.
func bothTyped(a *template, da DataType, b *template, db DataType) error { func bothTyped(a *template, da DataType, b *template, db DataType) error {
read := a read, other := a, db
if a.datatype != DataTypeString { if a.datatype != DataTypeString {
read = b read, other = b, da
} }
if read.datatype != DataTypeString { switch {
case read.datatype != DataTypeString:
return fmt.Errorf("its items hold %s and %s; a column holds one datatype", da, db) return fmt.Errorf("its items hold %s and %s; a column holds one datatype", da, db)
case (&valueProof{}).columnItem(read).not[other] == "":
return fmt.Errorf("its items hold %s and %s; a column holds one datatype, so %s", da, db, typedAs(read, other))
} }
return fmt.Errorf("its items hold %s and %s; a column holds one datatype, so to read %q as text, %s", da, db, read.format, asText(read)) return fmt.Errorf("its items hold %s and %s; a column holds one datatype, so to read %q as text, %s", da, db, read.format, asText(read))
} }
// typedAs names the spelling giving a column-read item datatype d, keeping the other keys an object
// item carries.
func typedAs(t *template, d DataType) string {
if t.fromString {
return fmt.Sprintf(`write %q as {"format":%q,"datatype":%q}`, t.format, t.format, d)
}
return fmt.Sprintf(`give %q "datatype": %q`, t.format, d)
}
// asText names the spelling that reads the column a column-read item reads as text, keeping the // asText names the spelling that reads the column a column-read item reads as text, keeping the
// other keys an object item carries. // other keys an object item carries.
func asText(t *template) string { func asText(t *template) string {
+1
View File
@@ -53,6 +53,7 @@ func TestDatatypeRejectsAValueItsTypeRejects(t *testing.T) {
{"a datatype over a typed column", `{"format":"{/src.score}","datatype":"integer"}`, `{/src.score} takes datatype integer from the column it reads; drop "datatype"`}, {"a datatype over a typed column", `{"format":"{/src.score}","datatype":"integer"}`, `{/src.score} takes datatype integer from the column it reads; drop "datatype"`},
{"a datatype a typed column's values reject", `{"format":"{/src.score}","datatype":"boolean"}`, "{int(1,9)} prints an integer, not a boolean"}, {"a datatype a typed column's values reject", `{"format":"{/src.score}","datatype":"boolean"}`, "{int(1,9)} prints an integer, not a boolean"},
{"two typed columns it reads", `["{/src.score}","{/src.flag}"]`, `so to read "{/src.score}" as text, write {"format":"{text}","text":"{/src.score}"}`}, {"two typed columns it reads", `["{/src.score}","{/src.flag}"]`, `so to read "{/src.score}" as text, write {"format":"{text}","text":"{/src.score}"}`},
{"a typed column read that holds the datatype declared beside it", `[{"format":"1.5","datatype":"number"},"{/src.score}"]`, `so write "{/src.score}" as {"format":"{/src.score}","datatype":"number"}`},
{"text beside a weighted typed column read", `[{"format":"{/src.score}","weight":3},"n/a"]`, `to read that column as text, set its "format" to "{text}" and add "text": "{/src.score}"`}, {"text beside a weighted typed column read", `[{"format":"{/src.score}","weight":3},"n/a"]`, `to read that column as text, set its "format" to "{text}" and add "text": "{/src.score}"`},
{"a value of the column it reads", `{"format":"{/src.code}","datatype":"integer"}`, `"2x" is not an integer`}, {"a value of the column it reads", `{"format":"{/src.code}","datatype":"integer"}`, `"2x" is not an integer`},
{"a null read into text", `{"format":"{x}","x":"{/src.score}","datatype":"integer"}`, "reads a null"}, {"a null read into text", `{"format":"{x}","x":"{/src.score}","datatype":"integer"}`, "reads a null"},