diff --git a/lib/datalog/scoreboard.json b/lib/datalog/scoreboard.json index c89da138..9d8fb6d2 100644 --- a/lib/datalog/scoreboard.json +++ b/lib/datalog/scoreboard.json @@ -1,8 +1,8 @@ { "lang": "datalog", - "total_passed": 226, + "total_passed": 227, "total_failed": 0, - "total": 226, + "total": 227, "suites": [ {"name":"tokenize","passed":26,"failed":0,"total":26}, {"name":"parse","passed":18,"failed":0,"total":18}, @@ -13,8 +13,8 @@ {"name":"negation","passed":10,"failed":0,"total":10}, {"name":"aggregates","passed":19,"failed":0,"total":19}, {"name":"api","passed":20,"failed":0,"total":20}, - {"name":"magic","passed":26,"failed":0,"total":26}, + {"name":"magic","passed":27,"failed":0,"total":27}, {"name":"demo","passed":21,"failed":0,"total":21} ], - "generated": "2026-05-08T12:28:42+00:00" + "generated": "2026-05-08T12:31:39+00:00" } diff --git a/lib/datalog/scoreboard.md b/lib/datalog/scoreboard.md index b0593332..98e6ecc0 100644 --- a/lib/datalog/scoreboard.md +++ b/lib/datalog/scoreboard.md @@ -1,6 +1,6 @@ # datalog scoreboard -**226 / 226 passing** (0 failure(s)). +**227 / 227 passing** (0 failure(s)). | Suite | Passed | Total | Status | |-------|--------|-------|--------| @@ -13,5 +13,5 @@ | negation | 10 | 10 | ok | | aggregates | 19 | 19 | ok | | api | 20 | 20 | ok | -| magic | 26 | 26 | ok | +| magic | 27 | 27 | ok | | demo | 21 | 21 | ok | diff --git a/lib/datalog/tests/magic.sx b/lib/datalog/tests/magic.sx index 96b9f81e..90b6f75b 100644 --- a/lib/datalog/tests/magic.sx +++ b/lib/datalog/tests/magic.sx @@ -197,6 +197,20 @@ 6) ;; dl-magic-query: end-to-end driver, doesn't mutate caller's db. + ;; Magic over a rule with negated body literal — propagation + ;; rules generated only for positive lits; negated lits pass + ;; through unchanged. + (dl-mt-test! "magic over rule with negation" + (let + ((db (dl-program + "u(a). u(b). u(c). banned(b). + active(X) :- u(X), not(banned(X))."))) + (let + ((semi (dl-query db (list (quote active) (quote X)))) + (magic (dl-magic-query db (list (quote active) (quote X))))) + (= (len semi) (len magic)))) + true) + ;; Magic over a rule whose body contains an aggregate. ;; The rewriter passes aggregate body lits through unchanged ;; (no propagation generated for them), so semi-naive's count