diff options
author | Mike Montague <mikemon@gmail.com> | 2022-07-12 20:21:41 -0700 |
---|---|---|
committer | Mike Montague <mikemon@gmail.com> | 2022-07-12 20:21:41 -0700 |
commit | 3fdf5beda024872a05a0babc26c8726a4b393e1d (patch) | |
tree | 833b3f4ea0800837eaa097f9721d3c86d1b71181 | |
parent | ded2fb779e8b9d07aa8a62321f651936e126dc75 (diff) |
srfi 166: add written, written-shared, and written-simply
-rw-r--r-- | src/srfi-166.scm | 89 | ||||
-rw-r--r-- | test/srfi.scm | 86 |
2 files changed, 106 insertions, 69 deletions
diff --git a/src/srfi-166.scm b/src/srfi-166.scm index e6ce064..a7cd274 100644 --- a/src/srfi-166.scm +++ b/src/srfi-166.scm @@ -4,7 +4,8 @@ show displayed written - + written-shared + written-simply escaped maybe-escaped numeric @@ -34,7 +35,10 @@ fitted fitted/right fitted/both - + ;pretty + ;pretty-shared + ;pretty-simply + ;pretty-with-color columnar tabular wrapped @@ -98,6 +102,7 @@ comma-sep word-separator? + ;; exported for testing make-runner string-split make-infinite-runner @@ -127,7 +132,6 @@ (parameterize ((var tmp) ...) ((displayed fmt))) ...) nothing)) ((%with ((var val) . rest) (vars ...) fmt ...) (%with rest ((var val tmp) vars ...) fmt ...)))) - (define (show dest . fmts) (let ((show-port (if (port? dest) @@ -147,18 +151,39 @@ ((char? obj) (%formatter () ((output) (string obj)))) (else (written obj)))) (define (written obj) - (fn () ((writer) obj))) + (fn (writer) (writer obj))) (define (written-default obj) - (%write obj)) - (define (%write obj) + (%write obj (find-shared-objects obj #f))) + (define (written-shared obj) + (%write obj (find-shared-objects obj #t))) + (define (written-simply obj) + (%write obj #f)) + (define (find-shared-objects obj all) + (define (find-shared obj all shared) + (if (or (pair? obj) (vector? obj)) + (let ((cnt (%hash-table-ref shared obj 0))) + (%hash-table-set! shared obj (+ cnt 1)) + (if (= cnt 0) + (if (pair? obj) + (begin + (find-shared (car obj) all shared) + (find-shared (cdr obj) all shared)) + (vector-for-each + (lambda (elem) (find-shared elem all shared)) obj))) + (if (and (not all) (= (%hash-table-ref shared obj 0) 1)) + (%hash-table-delete! shared obj))))) + (let ((shared (make-eq-hash-table))) + (find-shared obj all shared) + shared)) + (define (%write obj shared) (let ((write-radix (case (radix) ((2 8 10 16) (radix)) (else 10)))) (with ((radix write-radix) (precision (if (= write-radix 10) (precision) #f)) (sign-rule #f) (comma-rule #f) (decimal-sep #\.)) - (%write-object obj)))) - (define (%write-object obj) + (%write-object obj shared (box 0))))) + (define (%write-object obj shared count) (define (%write-number num) (each (if (exact? num) @@ -169,30 +194,44 @@ (else "")) "") (numeric num))) - (define (%write-list lst) + (define (shared-object? obj shared) + (let ((val (if shared (%hash-table-ref shared obj 0) 0))) + (or (box? val) (> val 1)))) + (define (%write-list lst shared count) (cond ((null? lst) ")") - ((pair? lst) - (each " " (%write-object (car lst)) (fn () (%write-list (cdr lst))))) - (else (each " . " (%write-object lst) ")")))) - (define (%write-vector vec idx) + ((and (pair? lst) (not (shared-object? lst shared))) + (each " " (%write-object (car lst) shared count) + (fn () (%write-list (cdr lst) shared count)))) + (else (each " . " (%write-object lst shared count) ")")))) + (define (%write-vector vec idx shared count) (cond ((= idx (vector-length vec)) ")") (else (each (if (> idx 0) " " nothing) - (%write-object (vector-ref obj idx)) - (fn () (%write-vector vec (+ idx 1))))))) - (cond - ((number? obj) (%write-number obj)) - ((pair? obj) - (each "(" (%write-object (car obj)) (fn () (%write-list (cdr obj))))) - ((vector? obj) (each "#(" (%write-vector obj 0))) - (else - (let ((port (open-output-string))) - (write obj port) - (get-output-string port))))) - + (%write-object (vector-ref obj idx) shared count) + (fn () (%write-vector vec (+ idx 1) shared count)))))) + (let ((val (if shared (%hash-table-ref shared obj 0) 0))) + (if (box? val) + (each "#" (number->string (unbox val)) "#") + (each + (if (> val 1) + (let ((cnt (unbox count))) + (%hash-table-set! shared obj (box cnt)) + (set-box! count (+ cnt 1)) + (each "#" (number->string cnt) "=")) + nothing) + (cond + ((number? obj) (%write-number obj)) + ((pair? obj) + (each "(" (%write-object (car obj) shared count) + (fn () (%write-list (cdr obj) shared count)))) + ((vector? obj) (each "#(" (%write-vector obj 0 shared count))) + (else + (let ((port (open-output-string))) + (write obj port) + (get-output-string port)))))))) (define escaped (case-lambda ((fmt) (%escaped fmt #\" #\\ #f)) diff --git a/test/srfi.scm b/test/srfi.scm index 64702fe..4930e3c 100644 --- a/test/srfi.scm +++ b/test/srfi.scm @@ -3579,6 +3579,48 @@ (check-equal " 1 first line\n 2 second line\n 3 third line\n" (show #f (columnar 4 'right 'infinite (line-numbers) " " (from-file "output-166.txt")))) +;; shared structures +(check-equal "#0=(1 . #0#)" + (show #f (written (let ((ones (list 1))) (set-cdr! ones ones) ones)))) +(check-equal "(0 . #0=(1 . #0#))" + (show #f (written (let ((ones (list 1))) + (set-cdr! ones ones) + (cons 0 ones))))) +(check-equal "(sym . #0=(sym . #0#))" + (show #f (written (let ((syms (list 'sym))) + (set-cdr! syms syms) + (cons 'sym syms))))) +(check-equal "(#0=(1 . #0#) #1=(2 . #1#))" + (show #f (written (let ((ones (list 1)) + (twos (list 2))) + (set-cdr! ones ones) + (set-cdr! twos twos) + (list ones twos))))) +(check-equal "(#0=(1 . #0#) #0#)" + (show #f (written (let ((ones (list 1))) + (set-cdr! ones ones) + (list ones ones))))) +(check-equal "((1) (1))" + (show #f (written (let ((ones (list 1))) + (list ones ones))))) + +(check-equal "(#0=(1) #0#)" + (show #f (written-shared (let ((ones (list 1))) + (list ones ones))))) + +;; cycles without shared detection +(check-equal "(1 1 1 1 1" + (show #f (trimmed/lazy + 10 + (written-simply + (let ((ones (list 1))) (set-cdr! ones ones) ones))))) + +(check-equal "(1 1 1 1 1 " + (show #f (trimmed/lazy + 11 + (written-simply + (let ((ones (list 1))) (set-cdr! ones ones) ones))))) + #| ;; color (check-equal "\x1B;[31mred\x1B;[39m" (show #f (as-red "red"))) @@ -3608,50 +3650,6 @@ (define (run-tests) (test-begin "show") - ;; shared structures - - (test "#0=(1 . #0#)" - (show #f (written (let ((ones (list 1))) (set-cdr! ones ones) ones)))) - (test "(0 . #0=(1 . #0#))" - (show #f (written (let ((ones (list 1))) - (set-cdr! ones ones) - (cons 0 ones))))) - (test "(sym . #0=(sym . #0#))" - (show #f (written (let ((syms (list 'sym))) - (set-cdr! syms syms) - (cons 'sym syms))))) - (test "(#0=(1 . #0#) #1=(2 . #1#))" - (show #f (written (let ((ones (list 1)) - (twos (list 2))) - (set-cdr! ones ones) - (set-cdr! twos twos) - (list ones twos))))) - (test "(#0=(1 . #0#) #0#)" - (show #f (written (let ((ones (list 1))) - (set-cdr! ones ones) - (list ones ones))))) - (test "((1) (1))" - (show #f (written (let ((ones (list 1))) - (list ones ones))))) - - (test "(#0=(1) #0#)" - (show #f (written-shared (let ((ones (list 1))) - (list ones ones))))) - - ;; cycles without shared detection - - (test "(1 1 1 1 1" - (show #f (trimmed/lazy - 10 - (written-simply - (let ((ones (list 1))) (set-cdr! ones ones) ones))))) - - (test "(1 1 1 1 1 " - (show #f (trimmed/lazy - 11 - (written-simply - (let ((ones (list 1))) (set-cdr! ones ones) ones))))) - ;; pretty printing (test-pretty "(foo bar)\n") |