datalog: comparison ops require same-type operands
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 28s
Type-mixed comparisons were silently inconsistent:
<("hello", 5) => no result, no error (silent false)
<(a, 5) => raises "Expected number, got symbol"
Both should fail loudly with a comprehensible message. Added
dl-compare-typeok?: <, <=, >, >= now require both operands to share
a primitive type (both numbers or both strings) and raise a clear
"comparison <op> requires same-type operands" error otherwise.
`!=` is exempted because it's the polymorphic inequality test
built on dl-tuple-equal? — cross-type pairs are legitimately unequal
and the existing semantics for that case match user intuition.
2 new regression tests; conformance 267/267.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -82,6 +82,20 @@
|
||||
(else (error (str "datalog arith: unknown op " rel)))))))))
|
||||
(else (error (str "datalog arith: not a number — " w)))))))
|
||||
|
||||
;; Comparable types — both operands must be the same primitive type
|
||||
;; (both numbers, both strings). `!=` is the exception: it's defined
|
||||
;; for any pair (returns true iff not equal) since dl-tuple-equal?
|
||||
;; handles type-mixed comparisons.
|
||||
(define
|
||||
dl-compare-typeok?
|
||||
(fn
|
||||
(rel a b)
|
||||
(cond
|
||||
((= rel "!=") true)
|
||||
((and (number? a) (number? b)) true)
|
||||
((and (string? a) (string? b)) true)
|
||||
(else false))))
|
||||
|
||||
(define
|
||||
dl-eval-compare
|
||||
(fn
|
||||
@@ -98,6 +112,11 @@
|
||||
rel
|
||||
" has unbound argument; "
|
||||
"ensure prior body literal binds the variable")))
|
||||
((not (dl-compare-typeok? rel a b))
|
||||
(error
|
||||
(str "datalog: comparison " rel " requires same-type "
|
||||
"operands (both numbers or both strings), got "
|
||||
a " and " b)))
|
||||
(else
|
||||
(let
|
||||
((ok (cond ((= rel "<") (< a b)) ((= rel "<=") (<= a b)) ((= rel ">") (> a b)) ((= rel ">=") (>= a b)) ((= rel "!=") (not (dl-tuple-equal? a b))) (else (error (str "datalog: unknown compare " rel))))))
|
||||
|
||||
Reference in New Issue
Block a user