datalog: anonymous-renamer avoids user _anon<N> collision
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 25s
The renamer for anonymous `_` variables started at counter 0 and
produced `_anon1, _anon2, ...` unconditionally. A user writing the
same naming convention would see their variables shadowed:
(dl-eval "p(a, b). p(c, d). q(_anon1) :- p(_anon1, _)."
"?- q(X).")
=> () ; should be ({:X a} {:X c})
The `_` got renamed to `_anon1` too, collapsing the two positions
of `p` to a single var (forcing args to be equal — which neither
tuple satisfies).
Fix: scan each rule (and query goal) for the highest `_anon<N>`
already present and start the renamer past it. New helpers
`dl-max-anon-num` / `dl-max-anon-num-list` / `dl-try-parse-int`
walk the rule tree; `dl-make-anon-renamer` now takes a `start`
argument; `dl-rename-anon-rule` and the query-time renamer in
`dl-query` both compute the start from the input.
1 regression test; conformance 275/275.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,7 +15,7 @@ for rose-ash data (e.g. federation graph, content relationships).
|
||||
|
||||
## Status (rolling)
|
||||
|
||||
`bash lib/datalog/conformance.sh` → **274/274 across 11 suites**
|
||||
`bash lib/datalog/conformance.sh` → **275/275 across 11 suites**
|
||||
(tokenize, parse, unify, eval, builtins, semi_naive, negation, aggregates,
|
||||
api, magic, demo). Source is ~3100 LOC, tests ~2900 LOC, public API
|
||||
documented in `lib/datalog/datalog.sx`.
|
||||
@@ -320,6 +320,17 @@ large graphs.
|
||||
|
||||
_Newest first._
|
||||
|
||||
- 2026-05-11 — Anonymous-variable renamer collided with user-written
|
||||
`_anon<N>` symbols. The renamer started counter at 0 and produced
|
||||
`_anon1, _anon2, ...` unconditionally; if the user wrote
|
||||
`q(_anon1) :- p(_anon1, _).` the `_` got renamed to `_anon1` too,
|
||||
collapsing the two positions of `p` to a single var and returning
|
||||
the empty result instead of `{a, c}`. Fix: scan each rule (and
|
||||
query) for the max `_anon<N>` and start the renamer past it. The
|
||||
renamer constructor now takes a `start` arg; new helpers
|
||||
`dl-max-anon-num` / `dl-max-anon-num-list` walk the rule tree.
|
||||
1 regression test; 275/275.
|
||||
|
||||
- 2026-05-11 — `dl-magic-query` could silently diverge from
|
||||
`dl-query` when an aggregate's inner-goal relation was IDB. The
|
||||
rewriter passes aggregate body lits through unchanged (no magic
|
||||
|
||||
Reference in New Issue
Block a user