Skip to content

Commit

Permalink
Fix pprint column rounding issue
Browse files Browse the repository at this point in the history
  • Loading branch information
shirok committed Dec 25, 2024
1 parent baf10fa commit c9d753f
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 11 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2024-12-24 Shiro Kawai <shiro@acm.org>

* lib/gauche/pputil.scm (do-layout-elements): Fix column rounding
issue https://github.com/shirok/Gauche/issues/941

2024-12-20 Shiro Kawai <shiro@acm.org>

* lib/gauche/numioutil.scm: Move print-exact-decimal-point-number
Expand Down
24 changes: 15 additions & 9 deletions lib/gauche/pputil.scm
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@
(define-inline (>=* a b) (and a b (>= a b)))
(define-inline (-* a b . args)
(and a b (if (null? args) (- a b) (apply -* (- a b) args))))
(define-inline (+* a b . args)
(and a b (if (null? args) (+ a b) (apply +* (+ a b) args))))
(define-inline (min* a b) (if a (if b (min a b) a) b))

;; Render OBJ into a string. The resulting string is then used with
Expand Down Expand Up @@ -297,31 +299,35 @@
;; find out best fit. Each layouter may be invoked more than once,
;; when retry happens.
(define (do-layout-elements room memo elts)
(define (do-oneline r es strs)
(define (do-oneline r es strs first?)
(match es
[() (cons strs (-* room r))]
[(e . es) (match-let1 (s . w) (e room memo)
[(e . es) (match-let1 (s . w) (e r memo)
(cond [(not w) (do-linear room elts)] ;giveup
[(>* w room) ;too big
(do-fill room es (list* 'b s 'b strs))]
[(>* w r)
[(and first? (>* r w))
(do-oneline (-* r w) es (list* s 's strs) #f)]
[(>* w (-* r 1))
(do-fill (-* room w) es (list* s 'b strs))]
[else
(do-oneline (-* r w 1) es (list* s 's strs))]))]))
(do-oneline (-* r w 1) es (list* s 's strs) #f)]))]))
(define (do-fill r es strs)
(match es
[() (cons strs #f)]
[(e . es) (match-let1 (s . w) (e room memo)
[(e . es) (match-let1 (s . w) (e r memo)
(cond [(not w) (do-linear room elts)]
[(>* w (-* r 1))
(do-fill (-* room w 1) es (list* s 'b strs))]
[else (do-fill (-* r w 1) es (list* s 's strs))]))]))
(do-fill (-* room w) es (list* s 'b strs))]
[else
(do-fill (-* r w 1) es (list* s 's strs))]))]))
(define (do-linear r es)
(cons (fold (^[e strs] (match-let1 (s . w) (e room memo) (list* s 'b strs)))
'() es)
#f))
(match-let1 (s . w) (do-oneline room elts '())
(cons (cons ")" s) w)))

(match-let1 (s . w) (do-oneline room elts '() #t)
(cons (cons ")" s) (+* w 1))))

;; Render the nested list of strings. Some trick: S's and b's right
;; after open paren are ignored. S's right after b's are also ignored.
Expand Down
37 changes: 35 additions & 2 deletions test/io2.scm
Original file line number Diff line number Diff line change
Expand Up @@ -707,8 +707,8 @@
[data2 '(Lorem (ipsum #(dolor (sit (amet . consectetur)))))]
)
(define (t name expect data . args)
(test* #"~|name| ~|args|" expect
(with-output-to-string (^[] (apply pprint data args)))))
(test*/diff #"~|name| ~|args|" expect
(with-output-to-string (^[] (apply pprint data args)))))
(define elli (with-module gauche.internal (string-ellipsis)))
(let-syntax
([t* (syntax-rules ()
Expand Down Expand Up @@ -763,6 +763,39 @@
\n (ipsum #(dolor (sit #))))\n")
))

;; Rounding error
;; https://github.com/shirok/Gauche/issues/941
(test*/diff "rounding"
"(abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc
abc abc abc abc abc abc abc abc abc abc)
"
(with-output-to-string (cut pprint (make-list 100 'abc)
:indent 20 :width 60)))

;; some more rounding tests
(let ((expected '("(abc)\n"
"(abc abc)\n"
"(abc abc\n abc)\n"
"(abc abc\n abc abc)\n"
"(abc abc\n abc abc\n abc)\n"
"(abc abc\n abc abc\n abc abc)\n"
"(abc abc\n abc abc\n abc abc\n abc)\n"
"(abc abc\n abc abc\n abc abc\n abc abc)\n")))
(dotimes [i (length expected)]
(test*/diff #"rounding ~i"
(~ expected i)
(with-output-to-string
(cut pprint (make-list (+ i 1) 'abc) :width 8))))
)

(test* "no newline" "(a\n a)"
(call-with-output-string
(cut pprint '(a a) :width 3 :newline #f :port <>)))
Expand Down

0 comments on commit c9d753f

Please sign in to comment.