predsort/3, term_variables/2, arith: floor/ceiling/truncate/round/sign/sqrt/pow
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
- pl-eval-arith: add floor, ceiling, truncate, round, sqrt, sign, pow, integer, float, float_integer_part, float_fractional_part, **, ^ operators - pl-collect-vars: helper that extracts unbound variables from a term (left-to-right, deduplicated by var id) - term_variables/2: dispatches via pl-collect-vars, unifies second arg with var list - pl-predsort-insert!: inserts one element into a sorted list using a 3-arg comparator predicate; deduplicates elements where comparator returns '=' - pl-predsort-build!: builds sorted list via fold over pl-predsort-insert! - predsort/3: full ISO predsort — sorts and deduplicates a list using a caller-supplied predicate - lib/prolog/tests/advanced.sx: 21 tests (12 arith, 5 term_variables, 4 predsort) - conformance.sh: add advanced suite - scoreboard: 517/517 (was 496/496) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ SUITES=(
|
||||
"io_predicates:lib/prolog/tests/io_predicates.sx:pl-io-predicates-tests-run!"
|
||||
"assert_rules:lib/prolog/tests/assert_rules.sx:pl-assert-rules-tests-run!"
|
||||
"string_agg:lib/prolog/tests/string_agg.sx:pl-string-agg-tests-run!"
|
||||
"advanced:lib/prolog/tests/advanced.sx:pl-advanced-tests-run!"
|
||||
)
|
||||
|
||||
SCRIPT='(epoch 1)
|
||||
|
||||
@@ -410,6 +410,72 @@
|
||||
((sorted-keys (sort (keys kv))))
|
||||
(map (fn (k) (dict-get kv k)) sorted-keys))))))
|
||||
|
||||
(define
|
||||
pl-collect-vars
|
||||
(fn
|
||||
(term seen-ids)
|
||||
(let
|
||||
((walked (pl-walk term)))
|
||||
(cond
|
||||
((pl-var? walked)
|
||||
(let
|
||||
((id (pl-var-id walked)))
|
||||
(if
|
||||
(some (fn (s) (= s id)) seen-ids)
|
||||
(list seen-ids (list))
|
||||
(list (cons id seen-ids) (list walked)))))
|
||||
((pl-compound? walked)
|
||||
(reduce
|
||||
(fn
|
||||
(acc arg)
|
||||
(let
|
||||
((result (pl-collect-vars arg (first acc))))
|
||||
(list (first result) (append (nth acc 1) (nth result 1)))))
|
||||
(list seen-ids (list))
|
||||
(pl-args walked)))
|
||||
(true (list seen-ids (list)))))))
|
||||
|
||||
(define
|
||||
pl-predsort-insert!
|
||||
(fn
|
||||
(db pred elem sorted trail)
|
||||
(if
|
||||
(empty? sorted)
|
||||
(list elem)
|
||||
(let
|
||||
((head (first sorted)) (order-var (pl-mk-rt-var "_PO")))
|
||||
(let
|
||||
((call-goal (pl-apply-goal pred (list order-var elem head)))
|
||||
(mark (pl-trail-mark trail)))
|
||||
(let
|
||||
((ok (pl-solve-once! db call-goal trail)))
|
||||
(if
|
||||
ok
|
||||
(let
|
||||
((order (pl-atom-name (pl-walk-deep order-var))))
|
||||
(do
|
||||
(pl-trail-undo-to! trail mark)
|
||||
(cond
|
||||
((= order "<") (cons elem sorted))
|
||||
((= order "=") sorted)
|
||||
((= order ">")
|
||||
(let
|
||||
((rest-sorted (pl-predsort-insert! db pred elem (rest sorted) trail)))
|
||||
(if rest-sorted (cons head rest-sorted) false)))
|
||||
(true false))))
|
||||
(begin (pl-trail-undo-to! trail mark) false))))))))
|
||||
|
||||
(define
|
||||
pl-predsort-build!
|
||||
(fn
|
||||
(db pred items trail)
|
||||
(reduce
|
||||
(fn
|
||||
(sorted elem)
|
||||
(if sorted (pl-predsort-insert! db pred elem sorted trail) false))
|
||||
(list)
|
||||
items)))
|
||||
|
||||
(define
|
||||
pl-collect-solutions
|
||||
(fn
|
||||
@@ -782,6 +848,7 @@
|
||||
false)))
|
||||
(true false)))))
|
||||
|
||||
;; ── Structural equality helper (for ==/2, \==/2, delete/3) ────────
|
||||
(define
|
||||
pl-solve-atom-chars!
|
||||
(fn
|
||||
@@ -820,6 +887,7 @@
|
||||
false))
|
||||
(true false)))))
|
||||
|
||||
;; ── Flatten helper: collect all non-list leaves into SX list ───────
|
||||
(define
|
||||
pl-solve-atom-codes!
|
||||
(fn
|
||||
@@ -864,6 +932,7 @@
|
||||
false))
|
||||
(true false)))))
|
||||
|
||||
;; ── numlist helper: build SX list of ("num" i) for i in [lo..hi] ──
|
||||
(define
|
||||
pl-solve-char-code!
|
||||
(fn
|
||||
@@ -886,7 +955,7 @@
|
||||
k))
|
||||
(true false)))))
|
||||
|
||||
;; ── Structural equality helper (for ==/2, \==/2, delete/3) ────────
|
||||
;; ── atomic_list_concat helper: collect atom names / num vals ───────
|
||||
(define
|
||||
pl-struct-eq?
|
||||
(fn
|
||||
@@ -896,19 +965,18 @@
|
||||
(= (dict-get a :id) (dict-get b :id)))
|
||||
((and (pl-atom? a) (pl-atom? b))
|
||||
(= (pl-atom-name a) (pl-atom-name b)))
|
||||
((and (pl-num? a) (pl-num? b))
|
||||
(= (pl-num-val a) (pl-num-val b)))
|
||||
((and (pl-num? a) (pl-num? b)) (= (pl-num-val a) (pl-num-val b)))
|
||||
((and (pl-compound? a) (pl-compound? b))
|
||||
(if
|
||||
(and
|
||||
(= (pl-fun a) (pl-fun b))
|
||||
(= (len (pl-args a)) (len (pl-args b))))
|
||||
(let
|
||||
((all-eq true)
|
||||
(i 0))
|
||||
((all-eq true) (i 0))
|
||||
(begin
|
||||
(for-each
|
||||
(fn (ai)
|
||||
(fn
|
||||
(ai)
|
||||
(begin
|
||||
(if
|
||||
(not (pl-struct-eq? ai (nth (pl-args b) i)))
|
||||
@@ -920,7 +988,7 @@
|
||||
false))
|
||||
(true false))))
|
||||
|
||||
;; ── Flatten helper: collect all non-list leaves into SX list ───────
|
||||
;; ── sum_list helper ────────────────────────────────────────────────
|
||||
(define
|
||||
pl-flatten-prolog
|
||||
(fn
|
||||
@@ -941,7 +1009,7 @@
|
||||
(cons h (pl-flatten-prolog tl)))))
|
||||
(true (list w))))))
|
||||
|
||||
;; ── numlist helper: build SX list of ("num" i) for i in [lo..hi] ──
|
||||
;; ── max_list / min_list helpers ────────────────────────────────────
|
||||
(define
|
||||
pl-numlist-build
|
||||
(fn
|
||||
@@ -951,7 +1019,6 @@
|
||||
(list)
|
||||
(cons (list "num" lo) (pl-numlist-build (+ lo 1) hi)))))
|
||||
|
||||
;; ── atomic_list_concat helper: collect atom names / num vals ───────
|
||||
(define
|
||||
pl-atomic-list-collect
|
||||
(fn
|
||||
@@ -959,7 +1026,8 @@
|
||||
(let
|
||||
((items (pl-prolog-list-to-sx prolog-list)))
|
||||
(map
|
||||
(fn (item)
|
||||
(fn
|
||||
(item)
|
||||
(let
|
||||
((w (pl-walk-deep item)))
|
||||
(cond
|
||||
@@ -968,7 +1036,7 @@
|
||||
(true ""))))
|
||||
items))))
|
||||
|
||||
;; ── sum_list helper ────────────────────────────────────────────────
|
||||
;; ── delete/3 helper: remove elements struct-equal to elem ──────────
|
||||
(define
|
||||
pl-sum-list-sx
|
||||
(fn
|
||||
@@ -976,12 +1044,11 @@
|
||||
(let
|
||||
((items (pl-prolog-list-to-sx prolog-list)))
|
||||
(reduce
|
||||
(fn (acc item)
|
||||
(+ acc (pl-num-val (pl-walk-deep item))))
|
||||
(fn (acc item) (+ acc (pl-num-val (pl-walk-deep item))))
|
||||
0
|
||||
items))))
|
||||
|
||||
;; ── max_list / min_list helpers ────────────────────────────────────
|
||||
;; ── join string list with separator ────────────────────────────────
|
||||
(define
|
||||
pl-max-list-sx
|
||||
(fn
|
||||
@@ -989,8 +1056,10 @@
|
||||
(let
|
||||
((items (pl-prolog-list-to-sx prolog-list)))
|
||||
(reduce
|
||||
(fn (acc item)
|
||||
(let ((v (pl-num-val (pl-walk-deep item))))
|
||||
(fn
|
||||
(acc item)
|
||||
(let
|
||||
((v (pl-num-val (pl-walk-deep item))))
|
||||
(if (> v acc) v acc)))
|
||||
(pl-num-val (pl-walk-deep (first items)))
|
||||
(rest items)))))
|
||||
@@ -1002,26 +1071,24 @@
|
||||
(let
|
||||
((items (pl-prolog-list-to-sx prolog-list)))
|
||||
(reduce
|
||||
(fn (acc item)
|
||||
(let ((v (pl-num-val (pl-walk-deep item))))
|
||||
(fn
|
||||
(acc item)
|
||||
(let
|
||||
((v (pl-num-val (pl-walk-deep item))))
|
||||
(if (< v acc) v acc)))
|
||||
(pl-num-val (pl-walk-deep (first items)))
|
||||
(rest items)))))
|
||||
|
||||
;; ── delete/3 helper: remove elements struct-equal to elem ──────────
|
||||
(define
|
||||
pl-delete-sx
|
||||
(fn
|
||||
(prolog-list elem)
|
||||
(let
|
||||
((items (pl-prolog-list-to-sx prolog-list))
|
||||
(ew (pl-walk-deep elem)))
|
||||
((items (pl-prolog-list-to-sx prolog-list)) (ew (pl-walk-deep elem)))
|
||||
(filter
|
||||
(fn (item)
|
||||
(not (pl-struct-eq? (pl-walk-deep item) ew)))
|
||||
(fn (item) (not (pl-struct-eq? (pl-walk-deep item) ew)))
|
||||
items))))
|
||||
|
||||
;; ── join string list with separator ────────────────────────────────
|
||||
(define
|
||||
pl-join-strings
|
||||
(fn
|
||||
@@ -1029,10 +1096,7 @@
|
||||
(if
|
||||
(empty? strs)
|
||||
""
|
||||
(reduce
|
||||
(fn (acc s) (str acc sep s))
|
||||
(first strs)
|
||||
(rest strs)))))
|
||||
(reduce (fn (acc s) (str acc sep s)) (first strs) (rest strs)))))
|
||||
|
||||
(define
|
||||
pl-apply-goal
|
||||
@@ -1433,14 +1497,7 @@
|
||||
(let
|
||||
((clause (first parsed)))
|
||||
(let
|
||||
((actual-term
|
||||
(if
|
||||
(and
|
||||
(list? clause)
|
||||
(= (len clause) 3)
|
||||
(= (nth clause 0) "clause"))
|
||||
(nth clause 1)
|
||||
clause)))
|
||||
((actual-term (if (and (list? clause) (= (len clause) 3) (= (nth clause 0) "clause")) (nth clause 1) clause)))
|
||||
(let
|
||||
((fresh (pl-instantiate actual-term {})))
|
||||
(if (pl-unify! term-arg fresh trail) (k) false))))
|
||||
@@ -1473,10 +1530,14 @@
|
||||
(set! pl-output-buffer saved-buffer)
|
||||
(if
|
||||
result
|
||||
(if (pl-unify! var (list "atom" captured) trail) (k) false)
|
||||
(if
|
||||
(pl-unify! var (list "atom" captured) trail)
|
||||
(k)
|
||||
false)
|
||||
false))))))
|
||||
false))))
|
||||
|
||||
|
||||
(define
|
||||
pl-solve-writeln!
|
||||
(fn
|
||||
@@ -1495,7 +1556,8 @@
|
||||
(if
|
||||
(pl-atom? fmt-walked)
|
||||
(do
|
||||
(pl-output-write! (pl-format-process (pl-atom-name fmt-walked) (list)))
|
||||
(pl-output-write!
|
||||
(pl-format-process (pl-atom-name fmt-walked) (list)))
|
||||
(k))
|
||||
false))))
|
||||
|
||||
@@ -1516,7 +1578,6 @@
|
||||
(k)))
|
||||
false))))
|
||||
|
||||
|
||||
(define
|
||||
pl-substring
|
||||
(fn (s start sublen) (substring s start (+ start sublen))))
|
||||
@@ -2407,6 +2468,32 @@
|
||||
(pl-walk (nth (pl-args g) 2))
|
||||
trail
|
||||
k))
|
||||
((and (pl-compound? g) (= (pl-fun g) "term_variables") (= (len (pl-args g)) 2))
|
||||
(let
|
||||
((term (pl-walk (nth (pl-args g) 0)))
|
||||
(vars-arg (pl-walk (nth (pl-args g) 1))))
|
||||
(let
|
||||
((result (pl-collect-vars term (list))))
|
||||
(let
|
||||
((var-list (nth result 1)))
|
||||
(let
|
||||
((prolog-vars (pl-list-to-prolog var-list)))
|
||||
(if (pl-unify! vars-arg prolog-vars trail) (k) false))))))
|
||||
((and (pl-compound? g) (= (pl-fun g) "predsort") (= (len (pl-args g)) 3))
|
||||
(let
|
||||
((pred (pl-walk (nth (pl-args g) 0)))
|
||||
(list-arg (pl-walk (nth (pl-args g) 1)))
|
||||
(result-arg (pl-walk (nth (pl-args g) 2))))
|
||||
(let
|
||||
((items (pl-prolog-list-to-sx (pl-walk-deep list-arg))))
|
||||
(let
|
||||
((sorted (pl-predsort-build! db pred items trail)))
|
||||
(if
|
||||
sorted
|
||||
(let
|
||||
((prolog-sorted (pl-list-to-prolog sorted)))
|
||||
(if (pl-unify! result-arg prolog-sorted trail) (k) false))
|
||||
false)))))
|
||||
(true (pl-solve-user! db g trail cut-box k))))))
|
||||
|
||||
(define
|
||||
@@ -2543,6 +2630,42 @@
|
||||
((va (pl-eval-arith (first args)))
|
||||
(vb (pl-eval-arith (nth args 1))))
|
||||
(cond ((< va vb) va) (true vb))))
|
||||
((and (= f "floor") (= (len args) 1))
|
||||
(floor (pl-eval-arith (first args))))
|
||||
((and (= f "ceiling") (= (len args) 1))
|
||||
(ceil (pl-eval-arith (first args))))
|
||||
((and (= f "truncate") (= (len args) 1))
|
||||
(truncate (pl-eval-arith (first args))))
|
||||
((and (= f "round") (= (len args) 1))
|
||||
(round (pl-eval-arith (first args))))
|
||||
((and (= f "sqrt") (= (len args) 1))
|
||||
(sqrt (pl-eval-arith (first args))))
|
||||
((and (= f "sign") (= (len args) 1))
|
||||
(let
|
||||
((v (pl-eval-arith (first args))))
|
||||
(cond ((< v 0) -1) ((> v 0) 1) (true 0))))
|
||||
((and (= f "integer") (= (len args) 1))
|
||||
(truncate (pl-eval-arith (first args))))
|
||||
((and (= f "float") (= (len args) 1))
|
||||
(pl-eval-arith (first args)))
|
||||
((and (= f "float_integer_part") (= (len args) 1))
|
||||
(truncate (pl-eval-arith (first args))))
|
||||
((and (= f "float_fractional_part") (= (len args) 1))
|
||||
(let
|
||||
((v (pl-eval-arith (first args))))
|
||||
(- v (truncate v))))
|
||||
((and (= f "**") (= (len args) 2))
|
||||
(pow
|
||||
(pl-eval-arith (first args))
|
||||
(pl-eval-arith (nth args 1))))
|
||||
((and (= f "^") (= (len args) 2))
|
||||
(pow
|
||||
(pl-eval-arith (first args))
|
||||
(pl-eval-arith (nth args 1))))
|
||||
((and (= f "pow") (= (len args) 2))
|
||||
(pow
|
||||
(pl-eval-arith (first args))
|
||||
(pl-eval-arith (nth args 1))))
|
||||
(true 0))))
|
||||
(true 0)))))
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"total_passed": 496,
|
||||
"total_passed": 517,
|
||||
"total_failed": 0,
|
||||
"total": 496,
|
||||
"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},"char_predicates":{"passed":27,"total":27,"failed":0},"io_predicates":{"passed":24,"total":24,"failed":0},"assert_rules":{"passed":15,"total":15,"failed":0},"string_agg":{"passed":25,"total":25,"failed":0}},
|
||||
"generated": "2026-04-25T13:49:43+00:00"
|
||||
"total": 517,
|
||||
"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},"char_predicates":{"passed":27,"total":27,"failed":0},"io_predicates":{"passed":24,"total":24,"failed":0},"assert_rules":{"passed":15,"total":15,"failed":0},"string_agg":{"passed":25,"total":25,"failed":0},"advanced":{"passed":21,"total":21,"failed":0}},
|
||||
"generated": "2026-04-25T14:12:52+00:00"
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Prolog scoreboard
|
||||
|
||||
**496 / 496 passing** (0 failure(s)).
|
||||
Generated 2026-04-25T13:49:43+00:00.
|
||||
**517 / 517 passing** (0 failure(s)).
|
||||
Generated 2026-04-25T14:12:52+00:00.
|
||||
|
||||
| Suite | Passed | Total | Status |
|
||||
|-------|--------|-------|--------|
|
||||
@@ -29,6 +29,7 @@ Generated 2026-04-25T13:49:43+00:00.
|
||||
| io_predicates | 24 | 24 | ok |
|
||||
| assert_rules | 15 | 15 | ok |
|
||||
| string_agg | 25 | 25 | ok |
|
||||
| advanced | 21 | 21 | ok |
|
||||
|
||||
Run `bash lib/prolog/conformance.sh` to refresh. Override the binary
|
||||
with `SX_SERVER=path/to/sx_server.exe bash …`.
|
||||
|
||||
254
lib/prolog/tests/advanced.sx
Normal file
254
lib/prolog/tests/advanced.sx
Normal file
@@ -0,0 +1,254 @@
|
||||
;; lib/prolog/tests/advanced.sx — predsort/3, term_variables/2, arith extensions
|
||||
|
||||
(define pl-adv-test-count 0)
|
||||
(define pl-adv-test-pass 0)
|
||||
(define pl-adv-test-fail 0)
|
||||
(define pl-adv-test-failures (list))
|
||||
|
||||
(define
|
||||
pl-adv-test!
|
||||
(fn
|
||||
(name got expected)
|
||||
(begin
|
||||
(set! pl-adv-test-count (+ pl-adv-test-count 1))
|
||||
(if
|
||||
(= got expected)
|
||||
(set! pl-adv-test-pass (+ pl-adv-test-pass 1))
|
||||
(begin
|
||||
(set! pl-adv-test-fail (+ pl-adv-test-fail 1))
|
||||
(append!
|
||||
pl-adv-test-failures
|
||||
(str name "\n expected: " expected "\n got: " got)))))))
|
||||
|
||||
(define
|
||||
pl-adv-goal
|
||||
(fn
|
||||
(src env)
|
||||
(pl-instantiate (nth (first (pl-parse (str "g :- " src "."))) 2) env)))
|
||||
|
||||
(define pl-adv-db (pl-mk-db))
|
||||
;; Load a numeric comparator for predsort tests
|
||||
(pl-db-load!
|
||||
pl-adv-db
|
||||
(pl-parse
|
||||
"cmp_num(Order, X, Y) :- (X < Y -> Order = '<' ; (X > Y -> Order = '>' ; Order = '='))."))
|
||||
|
||||
;; ── Arithmetic extensions ──────────────────────────────────────────
|
||||
|
||||
(define pl-adv-arith-env-1 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is floor(3.7)" pl-adv-arith-env-1)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"floor(3.7) = 3"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-1 "X")))
|
||||
3)
|
||||
|
||||
(define pl-adv-arith-env-2 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is ceiling(3.2)" pl-adv-arith-env-2)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"ceiling(3.2) = 4"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-2 "X")))
|
||||
4)
|
||||
|
||||
(define pl-adv-arith-env-3 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is truncate(3.9)" pl-adv-arith-env-3)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"truncate(3.9) = 3"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-3 "X")))
|
||||
3)
|
||||
|
||||
(define pl-adv-arith-env-4 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is truncate(0 - 3.9)" pl-adv-arith-env-4)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"truncate(0-3.9) = -3"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-4 "X")))
|
||||
-3)
|
||||
|
||||
(define pl-adv-arith-env-5 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is round(3.5)" pl-adv-arith-env-5)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"round(3.5) = 4"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-5 "X")))
|
||||
4)
|
||||
|
||||
(define pl-adv-arith-env-6 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is sqrt(4.0)" pl-adv-arith-env-6)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"sqrt(4.0) = 2"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-6 "X")))
|
||||
2)
|
||||
|
||||
(define pl-adv-arith-env-7 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is sign(0 - 5)" pl-adv-arith-env-7)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"sign(0-5) = -1"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-7 "X")))
|
||||
-1)
|
||||
|
||||
(define pl-adv-arith-env-8 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is sign(0)" pl-adv-arith-env-8)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"sign(0) = 0"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-8 "X")))
|
||||
0)
|
||||
|
||||
(define pl-adv-arith-env-9 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is sign(3)" pl-adv-arith-env-9)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"sign(3) = 1"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-9 "X")))
|
||||
1)
|
||||
|
||||
(define pl-adv-arith-env-10 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is pow(2, 3)" pl-adv-arith-env-10)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"pow(2,3) = 8"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-10 "X")))
|
||||
8)
|
||||
|
||||
(define pl-adv-arith-env-11 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is floor(0 - 3.7)" pl-adv-arith-env-11)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"floor(0-3.7) = -4"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-11 "X")))
|
||||
-4)
|
||||
|
||||
(define pl-adv-arith-env-12 {:X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "X is ceiling(0 - 3.2)" pl-adv-arith-env-12)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"ceiling(0-3.2) = -3"
|
||||
(pl-num-val (pl-walk-deep (dict-get pl-adv-arith-env-12 "X")))
|
||||
-3)
|
||||
|
||||
;; ── term_variables/2 ──────────────────────────────────────────────
|
||||
|
||||
(define pl-adv-tv-env-1 {:Vs (pl-mk-rt-var "Vs")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "term_variables(hello, Vs)" pl-adv-tv-env-1)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"term_variables(hello,Vs) -> []"
|
||||
(pl-format-term (pl-walk-deep (dict-get pl-adv-tv-env-1 "Vs")))
|
||||
"[]")
|
||||
|
||||
(define pl-adv-tv-env-2 {:Vs (pl-mk-rt-var "Vs")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "term_variables(f(a, g(b)), Vs)" pl-adv-tv-env-2)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"term_variables(f(a,g(b)),Vs) -> []"
|
||||
(pl-format-term (pl-walk-deep (dict-get pl-adv-tv-env-2 "Vs")))
|
||||
"[]")
|
||||
|
||||
(define pl-adv-tv-env-3 {:Y (pl-mk-rt-var "Y") :Vs (pl-mk-rt-var "Vs") :X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "term_variables(f(X, Y), Vs)" pl-adv-tv-env-3)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"term_variables(f(X,Y),Vs) has 2 vars"
|
||||
(pl-list-length (pl-walk-deep (dict-get pl-adv-tv-env-3 "Vs")))
|
||||
2)
|
||||
|
||||
(define pl-adv-tv-env-4 {:Vs (pl-mk-rt-var "Vs") :X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "term_variables(X, Vs)" pl-adv-tv-env-4)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"term_variables(X,Vs) has 1 var"
|
||||
(pl-list-length (pl-walk-deep (dict-get pl-adv-tv-env-4 "Vs")))
|
||||
1)
|
||||
|
||||
(define pl-adv-tv-env-5 {:Y (pl-mk-rt-var "Y") :Vs (pl-mk-rt-var "Vs") :X (pl-mk-rt-var "X")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "term_variables(foo(X, Y, X), Vs)" pl-adv-tv-env-5)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"term_variables(foo(X,Y,X),Vs) deduplicates X -> 2 vars"
|
||||
(pl-list-length (pl-walk-deep (dict-get pl-adv-tv-env-5 "Vs")))
|
||||
2)
|
||||
|
||||
;; ── predsort/3 ────────────────────────────────────────────────────
|
||||
|
||||
(define pl-adv-ps-env-1 {:R (pl-mk-rt-var "R")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "predsort(cmp_num, [], R)" pl-adv-ps-env-1)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"predsort([]) -> []"
|
||||
(pl-format-term (pl-walk-deep (dict-get pl-adv-ps-env-1 "R")))
|
||||
"[]")
|
||||
|
||||
(define pl-adv-ps-env-2 {:R (pl-mk-rt-var "R")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "predsort(cmp_num, [1], R)" pl-adv-ps-env-2)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"predsort([1]) -> [1]"
|
||||
(pl-format-term (pl-walk-deep (dict-get pl-adv-ps-env-2 "R")))
|
||||
".(1, [])")
|
||||
|
||||
(define pl-adv-ps-env-3 {:R (pl-mk-rt-var "R")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "predsort(cmp_num, [3,1,2], R)" pl-adv-ps-env-3)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"predsort([3,1,2]) -> [1,2,3]"
|
||||
(pl-format-term (pl-walk-deep (dict-get pl-adv-ps-env-3 "R")))
|
||||
".(1, .(2, .(3, [])))")
|
||||
|
||||
(define pl-adv-ps-env-4 {:R (pl-mk-rt-var "R")})
|
||||
(pl-solve-once!
|
||||
pl-adv-db
|
||||
(pl-adv-goal "predsort(cmp_num, [3,1,2,1,3], R)" pl-adv-ps-env-4)
|
||||
(pl-mk-trail))
|
||||
(pl-adv-test!
|
||||
"predsort([3,1,2,1,3]) dedup -> [1,2,3]"
|
||||
(pl-format-term (pl-walk-deep (dict-get pl-adv-ps-env-4 "R")))
|
||||
".(1, .(2, .(3, [])))")
|
||||
|
||||
;; ── Runner ─────────────────────────────────────────────────────────
|
||||
|
||||
(define pl-advanced-tests-run! (fn () {:failed pl-adv-test-fail :passed pl-adv-test-pass :total pl-adv-test-count :failures pl-adv-test-failures}))
|
||||
Reference in New Issue
Block a user