Set predicates: foldl/4, list_to_set/2, intersection/3, subtract/3, union/3
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Has been cancelled
Adds 5 new built-in predicates to the Prolog runtime with 15 tests. 390 → 405 tests across 20 suites (all passing). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,6 +35,7 @@ SUITES=(
|
|||||||
"meta_predicates:lib/prolog/tests/meta_predicates.sx:pl-meta-predicates-tests-run!"
|
"meta_predicates:lib/prolog/tests/meta_predicates.sx:pl-meta-predicates-tests-run!"
|
||||||
"list_predicates:lib/prolog/tests/list_predicates.sx:pl-list-predicates-tests-run!"
|
"list_predicates:lib/prolog/tests/list_predicates.sx:pl-list-predicates-tests-run!"
|
||||||
"meta_call:lib/prolog/tests/meta_call.sx:pl-meta-call-tests-run!"
|
"meta_call:lib/prolog/tests/meta_call.sx:pl-meta-call-tests-run!"
|
||||||
|
"set_predicates:lib/prolog/tests/set_predicates.sx:pl-set-predicates-tests-run!"
|
||||||
)
|
)
|
||||||
|
|
||||||
SCRIPT='(epoch 1)
|
SCRIPT='(epoch 1)
|
||||||
|
|||||||
@@ -1169,6 +1169,50 @@
|
|||||||
false))))))))
|
false))))))))
|
||||||
(else false)))))
|
(else false)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
pl-solve-foldl!
|
||||||
|
(fn
|
||||||
|
(db goal lst vin vout trail k)
|
||||||
|
(let
|
||||||
|
((l (pl-walk-deep lst)) (v0 (pl-walk vin)))
|
||||||
|
(cond
|
||||||
|
((and (pl-atom? l) (= (pl-atom-name l) "[]"))
|
||||||
|
(if (pl-unify! vout v0 trail) (k) false))
|
||||||
|
((and (pl-compound? l) (= (pl-fun l) "."))
|
||||||
|
(let
|
||||||
|
((head (first (pl-args l))) (tail (nth (pl-args l) 1)))
|
||||||
|
(let
|
||||||
|
((v1-var (pl-mk-rt-var "_FV")))
|
||||||
|
(let
|
||||||
|
((call-goal (pl-apply-goal goal (list head v0 v1-var))))
|
||||||
|
(if
|
||||||
|
(pl-solve-once! db call-goal trail)
|
||||||
|
(pl-solve-foldl! db goal tail v1-var vout trail k)
|
||||||
|
false)))))
|
||||||
|
(else false)))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
pl-list-to-set-sx
|
||||||
|
(fn
|
||||||
|
(lst seen)
|
||||||
|
(if
|
||||||
|
(empty? lst)
|
||||||
|
(list)
|
||||||
|
(let
|
||||||
|
((head (first lst)) (tail (rest lst)))
|
||||||
|
(if
|
||||||
|
(some (fn (s) (pl-struct-eq? head s)) seen)
|
||||||
|
(pl-list-to-set-sx tail seen)
|
||||||
|
(cons head (pl-list-to-set-sx tail (cons head seen))))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
pl-pl-list-contains?
|
||||||
|
(fn
|
||||||
|
(pl-lst elem)
|
||||||
|
(let
|
||||||
|
((sx-lst (pl-prolog-list-to-sx (pl-walk-deep pl-lst))))
|
||||||
|
(some (fn (x) (pl-struct-eq? elem x)) sx-lst))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
pl-solve!
|
pl-solve!
|
||||||
(fn
|
(fn
|
||||||
@@ -1758,6 +1802,84 @@
|
|||||||
((cond-g (pl-walk (first (pl-args g))))
|
((cond-g (pl-walk (first (pl-args g))))
|
||||||
(action-g (pl-walk (nth (pl-args g) 1))))
|
(action-g (pl-walk (nth (pl-args g) 1))))
|
||||||
(pl-solve-forall! db cond-g action-g trail cut-box k)))
|
(pl-solve-forall! db cond-g action-g trail cut-box k)))
|
||||||
|
((and (pl-compound? g) (= (pl-fun g) "foldl") (= (len (pl-args g)) 4))
|
||||||
|
(pl-solve-foldl!
|
||||||
|
db
|
||||||
|
(pl-walk (first (pl-args g)))
|
||||||
|
(pl-walk (nth (pl-args g) 1))
|
||||||
|
(pl-walk (nth (pl-args g) 2))
|
||||||
|
(pl-walk (nth (pl-args g) 3))
|
||||||
|
trail
|
||||||
|
k))
|
||||||
|
((and (pl-compound? g) (= (pl-fun g) "list_to_set") (= (len (pl-args g)) 2))
|
||||||
|
(let
|
||||||
|
((lst-rt (pl-walk (first (pl-args g))))
|
||||||
|
(res-rt (pl-walk (nth (pl-args g) 1))))
|
||||||
|
(if
|
||||||
|
(pl-proper-list? lst-rt)
|
||||||
|
(let
|
||||||
|
((sx-lst (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx lst-rt))))
|
||||||
|
(let
|
||||||
|
((unique-lst (pl-list-to-set-sx sx-lst (list))))
|
||||||
|
(pl-solve-eq! res-rt (pl-list-to-prolog unique-lst) trail k)))
|
||||||
|
false)))
|
||||||
|
((and (pl-compound? g) (= (pl-fun g) "intersection") (= (len (pl-args g)) 3))
|
||||||
|
(let
|
||||||
|
((s1-rt (pl-walk (first (pl-args g))))
|
||||||
|
(s2-rt (pl-walk (nth (pl-args g) 1)))
|
||||||
|
(res-rt (pl-walk (nth (pl-args g) 2))))
|
||||||
|
(if
|
||||||
|
(and (pl-proper-list? s1-rt) (pl-proper-list? s2-rt))
|
||||||
|
(let
|
||||||
|
((s1-sx (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx s1-rt)))
|
||||||
|
(s2-sx
|
||||||
|
(map
|
||||||
|
(fn (x) (pl-walk-deep x))
|
||||||
|
(pl-prolog-list-to-sx s2-rt))))
|
||||||
|
(let
|
||||||
|
((inter (filter (fn (x) (some (fn (y) (pl-struct-eq? x y)) s2-sx)) s1-sx)))
|
||||||
|
(pl-solve-eq! res-rt (pl-list-to-prolog inter) trail k)))
|
||||||
|
false)))
|
||||||
|
((and (pl-compound? g) (= (pl-fun g) "subtract") (= (len (pl-args g)) 3))
|
||||||
|
(let
|
||||||
|
((s1-rt (pl-walk (first (pl-args g))))
|
||||||
|
(s2-rt (pl-walk (nth (pl-args g) 1)))
|
||||||
|
(res-rt (pl-walk (nth (pl-args g) 2))))
|
||||||
|
(if
|
||||||
|
(and (pl-proper-list? s1-rt) (pl-proper-list? s2-rt))
|
||||||
|
(let
|
||||||
|
((s1-sx (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx s1-rt)))
|
||||||
|
(s2-sx
|
||||||
|
(map
|
||||||
|
(fn (x) (pl-walk-deep x))
|
||||||
|
(pl-prolog-list-to-sx s2-rt))))
|
||||||
|
(let
|
||||||
|
((diff (filter (fn (x) (not (some (fn (y) (pl-struct-eq? x y)) s2-sx))) s1-sx)))
|
||||||
|
(pl-solve-eq! res-rt (pl-list-to-prolog diff) trail k)))
|
||||||
|
false)))
|
||||||
|
((and (pl-compound? g) (= (pl-fun g) "union") (= (len (pl-args g)) 3))
|
||||||
|
(let
|
||||||
|
((s1-rt (pl-walk (first (pl-args g))))
|
||||||
|
(s2-rt (pl-walk (nth (pl-args g) 1)))
|
||||||
|
(res-rt (pl-walk (nth (pl-args g) 2))))
|
||||||
|
(if
|
||||||
|
(and (pl-proper-list? s1-rt) (pl-proper-list? s2-rt))
|
||||||
|
(let
|
||||||
|
((s1-sx (map (fn (x) (pl-walk-deep x)) (pl-prolog-list-to-sx s1-rt)))
|
||||||
|
(s2-sx
|
||||||
|
(map
|
||||||
|
(fn (x) (pl-walk-deep x))
|
||||||
|
(pl-prolog-list-to-sx s2-rt))))
|
||||||
|
(let
|
||||||
|
((s2-only (filter (fn (x) (not (some (fn (y) (pl-struct-eq? x y)) s1-sx))) s2-sx)))
|
||||||
|
(let
|
||||||
|
((union-lst (append s1-sx s2-only)))
|
||||||
|
(pl-solve-eq!
|
||||||
|
res-rt
|
||||||
|
(pl-list-to-prolog union-lst)
|
||||||
|
trail
|
||||||
|
k))))
|
||||||
|
false)))
|
||||||
(true (pl-solve-user! db g trail cut-box k))))))
|
(true (pl-solve-user! db g trail cut-box k))))))
|
||||||
|
|
||||||
(define
|
(define
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"total_passed": 390,
|
"total_passed": 405,
|
||||||
"total_failed": 0,
|
"total_failed": 0,
|
||||||
"total": 390,
|
"total": 405,
|
||||||
"suites": {"parse":{"passed":25,"total":25,"failed":0},"unify":{"passed":47,"total":47,"failed":0},"clausedb":{"passed":14,"total":14,"failed":0},"solve":{"passed":62,"total":62,"failed":0},"operators":{"passed":19,"total":19,"failed":0},"dynamic":{"passed":11,"total":11,"failed":0},"findall":{"passed":11,"total":11,"failed":0},"term_inspect":{"passed":14,"total":14,"failed":0},"append":{"passed":6,"total":6,"failed":0},"reverse":{"passed":6,"total":6,"failed":0},"member":{"passed":7,"total":7,"failed":0},"nqueens":{"passed":6,"total":6,"failed":0},"family":{"passed":10,"total":10,"failed":0},"atoms":{"passed":34,"total":34,"failed":0},"query_api":{"passed":16,"total":16,"failed":0},"iso_predicates":{"passed":29,"total":29,"failed":0},"meta_predicates":{"passed":25,"total":25,"failed":0},"list_predicates":{"passed":33,"total":33,"failed":0},"meta_call":{"passed":15,"total":15,"failed":0}},
|
"suites": {"parse":{"passed":25,"total":25,"failed":0},"unify":{"passed":47,"total":47,"failed":0},"clausedb":{"passed":14,"total":14,"failed":0},"solve":{"passed":62,"total":62,"failed":0},"operators":{"passed":19,"total":19,"failed":0},"dynamic":{"passed":11,"total":11,"failed":0},"findall":{"passed":11,"total":11,"failed":0},"term_inspect":{"passed":14,"total":14,"failed":0},"append":{"passed":6,"total":6,"failed":0},"reverse":{"passed":6,"total":6,"failed":0},"member":{"passed":7,"total":7,"failed":0},"nqueens":{"passed":6,"total":6,"failed":0},"family":{"passed":10,"total":10,"failed":0},"atoms":{"passed":34,"total":34,"failed":0},"query_api":{"passed":16,"total":16,"failed":0},"iso_predicates":{"passed":29,"total":29,"failed":0},"meta_predicates":{"passed":25,"total":25,"failed":0},"list_predicates":{"passed":33,"total":33,"failed":0},"meta_call":{"passed":15,"total":15,"failed":0},"set_predicates":{"passed":15,"total":15,"failed":0}},
|
||||||
"generated": "2026-04-25T11:59:16+00:00"
|
"generated": "2026-04-25T12:21:38+00:00"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# Prolog scoreboard
|
# Prolog scoreboard
|
||||||
|
|
||||||
**390 / 390 passing** (0 failure(s)).
|
**405 / 405 passing** (0 failure(s)).
|
||||||
Generated 2026-04-25T11:59:16+00:00.
|
Generated 2026-04-25T12:21:38+00:00.
|
||||||
|
|
||||||
| Suite | Passed | Total | Status |
|
| Suite | Passed | Total | Status |
|
||||||
|-------|--------|-------|--------|
|
|-------|--------|-------|--------|
|
||||||
@@ -24,6 +24,7 @@ Generated 2026-04-25T11:59:16+00:00.
|
|||||||
| meta_predicates | 25 | 25 | ok |
|
| meta_predicates | 25 | 25 | ok |
|
||||||
| list_predicates | 33 | 33 | ok |
|
| list_predicates | 33 | 33 | ok |
|
||||||
| meta_call | 15 | 15 | ok |
|
| meta_call | 15 | 15 | ok |
|
||||||
|
| set_predicates | 15 | 15 | ok |
|
||||||
|
|
||||||
Run `bash lib/prolog/conformance.sh` to refresh. Override the binary
|
Run `bash lib/prolog/conformance.sh` to refresh. Override the binary
|
||||||
with `SX_SERVER=path/to/sx_server.exe bash …`.
|
with `SX_SERVER=path/to/sx_server.exe bash …`.
|
||||||
|
|||||||
195
lib/prolog/tests/set_predicates.sx
Normal file
195
lib/prolog/tests/set_predicates.sx
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
;; lib/prolog/tests/set_predicates.sx — foldl/4, list_to_set/2, intersection/3, subtract/3, union/3
|
||||||
|
|
||||||
|
(define pl-sp-test-count 0)
|
||||||
|
(define pl-sp-test-pass 0)
|
||||||
|
(define pl-sp-test-fail 0)
|
||||||
|
(define pl-sp-test-failures (list))
|
||||||
|
|
||||||
|
(define
|
||||||
|
pl-sp-test!
|
||||||
|
(fn
|
||||||
|
(name got expected)
|
||||||
|
(begin
|
||||||
|
(set! pl-sp-test-count (+ pl-sp-test-count 1))
|
||||||
|
(if
|
||||||
|
(= got expected)
|
||||||
|
(set! pl-sp-test-pass (+ pl-sp-test-pass 1))
|
||||||
|
(begin
|
||||||
|
(set! pl-sp-test-fail (+ pl-sp-test-fail 1))
|
||||||
|
(append!
|
||||||
|
pl-sp-test-failures
|
||||||
|
(str name "\n expected: " expected "\n got: " got)))))))
|
||||||
|
|
||||||
|
(define
|
||||||
|
pl-sp-goal
|
||||||
|
(fn
|
||||||
|
(src env)
|
||||||
|
(pl-instantiate (nth (first (pl-parse (str "g :- " src "."))) 2) env)))
|
||||||
|
|
||||||
|
;; DB with add/3 for foldl tests
|
||||||
|
(define pl-sp-db (pl-mk-db))
|
||||||
|
(pl-db-load! pl-sp-db (pl-parse "add(X, Acc, NAcc) :- NAcc is Acc + X."))
|
||||||
|
|
||||||
|
;; ── foldl/4 ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define pl-sp-env-fl1 {:S (pl-mk-rt-var "S")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "foldl(add, [1,2,3,4], 0, S)" pl-sp-env-fl1)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"foldl(add,[1,2,3,4],0,S) -> S=10"
|
||||||
|
(pl-num-val (pl-walk-deep (dict-get pl-sp-env-fl1 "S")))
|
||||||
|
10)
|
||||||
|
|
||||||
|
(define pl-sp-env-fl2 {:S (pl-mk-rt-var "S")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "foldl(add, [], 5, S)" pl-sp-env-fl2)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"foldl(add,[],5,S) -> S=5"
|
||||||
|
(pl-num-val (pl-walk-deep (dict-get pl-sp-env-fl2 "S")))
|
||||||
|
5)
|
||||||
|
|
||||||
|
(define pl-sp-env-fl3 {:S (pl-mk-rt-var "S")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "foldl(add, [1,2,3], 0, S)" pl-sp-env-fl3)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"foldl(add,[1,2,3],0,S) -> S=6"
|
||||||
|
(pl-num-val (pl-walk-deep (dict-get pl-sp-env-fl3 "S")))
|
||||||
|
6)
|
||||||
|
|
||||||
|
;; ── list_to_set/2 ──────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define pl-sp-env-lts1 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "list_to_set([1,2,3,2,1], R)" pl-sp-env-lts1)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"list_to_set([1,2,3,2,1],R) -> [1,2,3]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-lts1 "R")))
|
||||||
|
".(1, .(2, .(3, [])))")
|
||||||
|
|
||||||
|
(define pl-sp-env-lts2 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "list_to_set([], R)" pl-sp-env-lts2)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"list_to_set([],R) -> []"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-lts2 "R")))
|
||||||
|
"[]")
|
||||||
|
|
||||||
|
(define pl-sp-env-lts3 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "list_to_set([a,b,a,c], R)" pl-sp-env-lts3)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"list_to_set([a,b,a,c],R) -> [a,b,c]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-lts3 "R")))
|
||||||
|
".(a, .(b, .(c, [])))")
|
||||||
|
|
||||||
|
;; ── intersection/3 ─────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define pl-sp-env-int1 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "intersection([1,2,3,4], [2,4,6], R)" pl-sp-env-int1)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"intersection([1,2,3,4],[2,4,6],R) -> [2,4]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-int1 "R")))
|
||||||
|
".(2, .(4, []))")
|
||||||
|
|
||||||
|
(define pl-sp-env-int2 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "intersection([1,2,3], [4,5,6], R)" pl-sp-env-int2)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"intersection([1,2,3],[4,5,6],R) -> []"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-int2 "R")))
|
||||||
|
"[]")
|
||||||
|
|
||||||
|
(define pl-sp-env-int3 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "intersection([], [1,2,3], R)" pl-sp-env-int3)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"intersection([],[1,2,3],R) -> []"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-int3 "R")))
|
||||||
|
"[]")
|
||||||
|
|
||||||
|
;; ── subtract/3 ─────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define pl-sp-env-sub1 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "subtract([1,2,3,4], [2,4], R)" pl-sp-env-sub1)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"subtract([1,2,3,4],[2,4],R) -> [1,3]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-sub1 "R")))
|
||||||
|
".(1, .(3, []))")
|
||||||
|
|
||||||
|
(define pl-sp-env-sub2 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "subtract([1,2,3], [], R)" pl-sp-env-sub2)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"subtract([1,2,3],[],R) -> [1,2,3]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-sub2 "R")))
|
||||||
|
".(1, .(2, .(3, [])))")
|
||||||
|
|
||||||
|
(define pl-sp-env-sub3 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "subtract([], [1,2], R)" pl-sp-env-sub3)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"subtract([],[1,2],R) -> []"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-sub3 "R")))
|
||||||
|
"[]")
|
||||||
|
|
||||||
|
;; ── union/3 ────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define pl-sp-env-uni1 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "union([1,2,3], [2,3,4], R)" pl-sp-env-uni1)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"union([1,2,3],[2,3,4],R) -> [1,2,3,4]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-uni1 "R")))
|
||||||
|
".(1, .(2, .(3, .(4, []))))")
|
||||||
|
|
||||||
|
(define pl-sp-env-uni2 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "union([], [1,2], R)" pl-sp-env-uni2)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"union([],[1,2],R) -> [1,2]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-uni2 "R")))
|
||||||
|
".(1, .(2, []))")
|
||||||
|
|
||||||
|
(define pl-sp-env-uni3 {:R (pl-mk-rt-var "R")})
|
||||||
|
(pl-solve-once!
|
||||||
|
pl-sp-db
|
||||||
|
(pl-sp-goal "union([1,2], [], R)" pl-sp-env-uni3)
|
||||||
|
(pl-mk-trail))
|
||||||
|
(pl-sp-test!
|
||||||
|
"union([1,2],[],R) -> [1,2]"
|
||||||
|
(pl-format-term (pl-walk-deep (dict-get pl-sp-env-uni3 "R")))
|
||||||
|
".(1, .(2, []))")
|
||||||
|
|
||||||
|
;; ── Runner ─────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
(define pl-set-predicates-tests-run! (fn () {:failed pl-sp-test-fail :passed pl-sp-test-pass :total pl-sp-test-count :failures pl-sp-test-failures}))
|
||||||
Reference in New Issue
Block a user