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:
@@ -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)))))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user