IO predicates: term_to_atom/2, term_string/2, with_output_to/2, format/1,2, writeln/1
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 6 new built-in predicates to the Prolog runtime and 24 tests covering term<->atom conversion (bidirectional), output capture, format directives (~w/~a/~d/~n/~~). 456/456 tests passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1359,6 +1359,164 @@
|
||||
k)
|
||||
false))))
|
||||
|
||||
(define
|
||||
pl-format-process
|
||||
(fn
|
||||
(fmt-str args-list)
|
||||
(let
|
||||
((chars (split fmt-str "")) (result "") (remaining args-list))
|
||||
(define
|
||||
do-char
|
||||
(fn
|
||||
(cs r rem)
|
||||
(cond
|
||||
((empty? cs) r)
|
||||
((= (first cs) "~")
|
||||
(if
|
||||
(empty? (rest cs))
|
||||
(str r "~")
|
||||
(let
|
||||
((directive (first (rest cs))) (tail (rest (rest cs))))
|
||||
(cond
|
||||
((= directive "n") (do-char tail (str r "\n") rem))
|
||||
((= directive "N") (do-char tail (str r "\n") rem))
|
||||
((= directive "t") (do-char tail (str r "\t") rem))
|
||||
((= directive "~") (do-char tail (str r "~") rem))
|
||||
((= directive "w")
|
||||
(if
|
||||
(empty? rem)
|
||||
(do-char tail (str r "?") rem)
|
||||
(do-char
|
||||
tail
|
||||
(str r (pl-format-term (first rem)))
|
||||
(rest rem))))
|
||||
((= directive "a")
|
||||
(if
|
||||
(empty? rem)
|
||||
(do-char tail (str r "?") rem)
|
||||
(do-char
|
||||
tail
|
||||
(str r (pl-format-term (first rem)))
|
||||
(rest rem))))
|
||||
((= directive "d")
|
||||
(if
|
||||
(empty? rem)
|
||||
(do-char tail (str r "?") rem)
|
||||
(do-char
|
||||
tail
|
||||
(str r (pl-format-term (first rem)))
|
||||
(rest rem))))
|
||||
(true (do-char tail (str r "~" directive) rem))))))
|
||||
(true (do-char (rest cs) (str r (first cs)) rem)))))
|
||||
(do-char chars "" args-list))))
|
||||
|
||||
(define
|
||||
pl-solve-term-to-atom!
|
||||
(fn
|
||||
(term-arg atom-arg trail k)
|
||||
(let
|
||||
((t-walked (pl-walk term-arg)) (a-walked (pl-walk atom-arg)))
|
||||
(cond
|
||||
((not (pl-var? t-walked))
|
||||
(let
|
||||
((formatted (pl-format-term t-walked)))
|
||||
(let
|
||||
((result-atom (list "atom" formatted)))
|
||||
(if (pl-unify! atom-arg result-atom trail) (k) false))))
|
||||
((and (pl-var? t-walked) (pl-atom? a-walked))
|
||||
(let
|
||||
((atom-str (pl-atom-name a-walked)))
|
||||
(let
|
||||
((parsed (pl-parse (str atom-str "."))))
|
||||
(if
|
||||
(and (list? parsed) (> (len parsed) 0))
|
||||
(let
|
||||
((clause (first parsed)))
|
||||
(let
|
||||
((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))))
|
||||
false))))
|
||||
(true false)))))
|
||||
|
||||
(define
|
||||
pl-solve-with-output-to!
|
||||
(fn
|
||||
(db sink goal trail cut-box k)
|
||||
(let
|
||||
((sink-walked (pl-walk-deep sink)))
|
||||
(if
|
||||
(and
|
||||
(pl-compound? sink-walked)
|
||||
(or
|
||||
(= (pl-fun sink-walked) "atom")
|
||||
(= (pl-fun sink-walked) "string"))
|
||||
(= (len (pl-args sink-walked)) 1))
|
||||
(let
|
||||
((var (first (pl-args sink-walked)))
|
||||
(saved-buffer pl-output-buffer))
|
||||
(do
|
||||
(set! pl-output-buffer "")
|
||||
(let
|
||||
((result (pl-solve-once! db goal trail)))
|
||||
(let
|
||||
((captured pl-output-buffer))
|
||||
(do
|
||||
(set! pl-output-buffer saved-buffer)
|
||||
(if
|
||||
result
|
||||
(if (pl-unify! var (list "atom" captured) trail) (k) false)
|
||||
false))))))
|
||||
false))))
|
||||
|
||||
(define
|
||||
pl-solve-writeln!
|
||||
(fn
|
||||
(term-arg k)
|
||||
(do
|
||||
(pl-output-write! (pl-format-term term-arg))
|
||||
(pl-output-write! "\n")
|
||||
(k))))
|
||||
|
||||
(define
|
||||
pl-solve-format-1!
|
||||
(fn
|
||||
(fmt-arg k)
|
||||
(let
|
||||
((fmt-walked (pl-walk-deep fmt-arg)))
|
||||
(if
|
||||
(pl-atom? fmt-walked)
|
||||
(do
|
||||
(pl-output-write! (pl-format-process (pl-atom-name fmt-walked) (list)))
|
||||
(k))
|
||||
false))))
|
||||
|
||||
(define
|
||||
pl-solve-format-2!
|
||||
(fn
|
||||
(db fmt-arg args-arg trail k)
|
||||
(let
|
||||
((fmt-walked (pl-walk-deep fmt-arg))
|
||||
(args-walked (pl-walk-deep args-arg)))
|
||||
(if
|
||||
(pl-atom? fmt-walked)
|
||||
(let
|
||||
((args-sx (pl-prolog-list-to-sx args-walked)))
|
||||
(do
|
||||
(pl-output-write!
|
||||
(pl-format-process (pl-atom-name fmt-walked) args-sx))
|
||||
(k)))
|
||||
false))))
|
||||
|
||||
|
||||
(define
|
||||
pl-solve!
|
||||
(fn
|
||||
@@ -2057,6 +2215,32 @@
|
||||
(nth (pl-args g) 1)
|
||||
trail
|
||||
k))
|
||||
((and (pl-compound? g) (= (pl-fun g) "term_to_atom") (= (len (pl-args g)) 2))
|
||||
(pl-solve-term-to-atom!
|
||||
(nth (pl-args g) 0)
|
||||
(nth (pl-args g) 1)
|
||||
trail
|
||||
k))
|
||||
((and (pl-compound? g) (= (pl-fun g) "term_string") (= (len (pl-args g)) 2))
|
||||
(pl-solve-term-to-atom!
|
||||
(nth (pl-args g) 0)
|
||||
(nth (pl-args g) 1)
|
||||
trail
|
||||
k))
|
||||
((and (pl-compound? g) (= (pl-fun g) "with_output_to") (= (len (pl-args g)) 2))
|
||||
(pl-solve-with-output-to!
|
||||
db
|
||||
(nth (pl-args g) 0)
|
||||
(nth (pl-args g) 1)
|
||||
trail
|
||||
cut-box
|
||||
k))
|
||||
((and (pl-compound? g) (= (pl-fun g) "writeln") (= (len (pl-args g)) 1))
|
||||
(pl-solve-writeln! (nth (pl-args g) 0) k))
|
||||
((and (pl-compound? g) (= (pl-fun g) "format") (= (len (pl-args g)) 1))
|
||||
(pl-solve-format-1! (nth (pl-args g) 0) k))
|
||||
((and (pl-compound? g) (= (pl-fun g) "format") (= (len (pl-args g)) 2))
|
||||
(pl-solve-format-2! db (nth (pl-args g) 0) (nth (pl-args g) 1) trail k))
|
||||
(true (pl-solve-user! db g trail cut-box k))))))
|
||||
|
||||
(define
|
||||
|
||||
Reference in New Issue
Block a user