datalog: magic-sets building blocks (199/199)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 22s

Adds the primitives a future magic-sets rewriter will compose:

  dl-magic-rel-name rel adornment    → "magic_<rel>^<adornment>"
  dl-magic-lit rel adn bound-args    → magic literal as SX list
  dl-bound-args lit adornment        → bound-position arg values

Rewriter algorithm (worklist over (rel, adornment) pairs,
generating seed, propagation, and adorned-rule outputs) is still
TODO — these helpers are inspection-only for now.

4 new magic tests cover naming, lit construction, and bound-args
extraction (mixed/free).
This commit is contained in:
2026-05-08 09:53:38 +00:00
parent 71b73bd87e
commit 2a01d8ac91
5 changed files with 80 additions and 7 deletions

View File

@@ -158,3 +158,45 @@
(dl-vars-bound-by-lit lit bound)))))))
(get rule :body))
out))))
;; ── Magic predicate naming + bound-args extraction ─────────────
;; These are building blocks for the magic-sets *transformation*
;; itself. The transformation (which generates rewritten rules
;; with magic_<rel>^<adornment> filters) is future work — for now
;; these helpers can be used to inspect what such a transformation
;; would produce.
;; "magic_p^bf" given relation "p" and adornment "bf".
(define
dl-magic-rel-name
(fn (rel adornment) (str "magic_" rel "^" adornment)))
;; A magic predicate literal:
;; (magic_<rel>^<adornment> arg1 arg2 ...)
(define
dl-magic-lit
(fn
(rel adornment bound-args)
(cons (string->symbol (dl-magic-rel-name rel adornment)) bound-args)))
;; Extract bound args (those at "b" positions in `adornment`) from a
;; literal `(rel arg1 arg2 ... argN)`. Returns the list of arg values.
(define
dl-bound-args
(fn
(lit adornment)
(let ((args (rest lit)) (out (list)))
(do
(define
dl-ba-loop
(fn
(i)
(when
(< i (len args))
(do
(when
(= (slice adornment i (+ i 1)) "b")
(append! out (nth args i)))
(dl-ba-loop (+ i 1))))))
(dl-ba-loop 0)
out))))

View File

@@ -1,8 +1,8 @@
{
"lang": "datalog",
"total_passed": 194,
"total_passed": 199,
"total_failed": 0,
"total": 194,
"total": 199,
"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":18,"failed":0,"total":18},
{"name":"api","passed":14,"failed":0,"total":14},
{"name":"magic","passed":10,"failed":0,"total":10},
{"name":"magic","passed":15,"failed":0,"total":15},
{"name":"demo","passed":18,"failed":0,"total":18}
],
"generated": "2026-05-08T09:50:50+00:00"
"generated": "2026-05-08T09:53:23+00:00"
}

View File

@@ -1,6 +1,6 @@
# datalog scoreboard
**194 / 194 passing** (0 failure(s)).
**199 / 199 passing** (0 failure(s)).
| Suite | Passed | Total | Status |
|-------|--------|-------|--------|
@@ -13,5 +13,5 @@
| negation | 10 | 10 | ok |
| aggregates | 18 | 18 | ok |
| api | 14 | 14 | ok |
| magic | 10 | 10 | ok |
| magic | 15 | 15 | ok |
| demo | 18 | 18 | ok |

View File

@@ -124,7 +124,30 @@
{:lit (list (quote p) (quote X)) :adornment "f"}
{:lit (list (quote is) (quote Y)
(list (string->symbol "+") (quote X) 1))
:adornment "fb"})))))
:adornment "fb"}))
;; Magic predicate naming.
(dl-mt-test! "magic-rel-name"
(dl-magic-rel-name "ancestor" "bf")
"magic_ancestor^bf")
;; Bound-args extraction.
(dl-mt-test! "bound-args bf"
(dl-bound-args (list (quote ancestor) (quote tom) (quote X)) "bf")
(list (quote tom)))
(dl-mt-test! "bound-args mixed"
(dl-bound-args (list (quote p) 1 (quote Y) 3) "bfb")
(list 1 3))
(dl-mt-test! "bound-args all-free"
(dl-bound-args (list (quote p) (quote X) (quote Y)) "ff")
(list))
;; Magic literal construction.
(dl-mt-test! "magic-lit"
(dl-magic-lit "ancestor" "bf" (list (quote tom)))
(list (string->symbol "magic_ancestor^bf") (quote tom))))))
(define
dl-magic-tests-run!

View File

@@ -156,6 +156,8 @@ large graphs.
is a constant or a variable already in the bound set.
- [ ] Magic transformation: for each adorned predicate, generate a
`magic_<pred>` relation and rewrite rule bodies to filter through it.
*Building blocks present in `magic.sx`: `dl-magic-rel-name`,
`dl-magic-lit`, `dl-bound-args`. Full rewriter still TODO.*
- [x] Sideways information passing strategy (SIPS): left-to-right
`dl-rule-sips rule head-adornment` walks body literals tracking
the bound set, returning `({:lit :adornment} ...)`. Recognises
@@ -289,6 +291,12 @@ large graphs.
_Newest first._
- 2026-05-08 — Phase 6 building blocks for the magic-sets
transformation: `dl-magic-rel-name`, `dl-magic-lit`,
`dl-bound-args`. The rewriter that generates magic seed and
propagation rules is still future work; with these primitives
in place it's a straightforward worklist algorithm. 4 new tests.
- 2026-05-08 — Phase 6 adornments + SIPS in
`lib/datalog/magic.sx`. Inspection helpers — `dl-adorn-goal` and
`dl-adorn-lit` compute per-arg `b`/`f` patterns under a bound