From: Raymond Toy
Subject: writing a custom pretty-printer
Date: 
Message-ID: <4nit8qlmvq.fsf@rtp.ericsson.se>
I'm trying to write a pretty-printer for some macros in f2cl, and I'm
stuck on getting the following pretty-printed the way I want.

An example, pretty printed the way I want is:

(F2CL-LIB:FDO (I 3 (+ I 1))
              ((> I N4) NIL)
   (TAGBODY
     (SETF T1 (- (AINT (+ (* (FREF D (I) ((1 1024))) RDX) R1)) 2.0d0))
     (FSET (FREF D (I) ((1 1024))) (- (FREF D (I) ((1 1024))) (* T1 BDX)))
     (FSET (FREF D ((- I 1)) ((1 1024))) (+ (FREF D ((- I 1)) ((1 1024))) T1))

The general format looks something like:

(fdo (var init step)
     ((end-test) return-val)
  body)

The body always starts with tagbody if that makes it easier.  I can
get the pprinter to have the var-init-step and end-test on one line,
but I want them on separate lines.

This is what I have so far, but it's not quite right (and quite a
gross hack):

(defun pprint-fdo (fdo-sexp)
  (pprint-logical-block (nil fdo-sexp :prefix "(" :suffix ")")
    ;; The fdo
    (write (first fdo-sexp))
    (write-char #\space)
    ;; The var step stuff
    (pprint-logical-block (nil nil)
      (write (second fdo-sexp))
      (write-char #\space)
      (pprint-newline :mandatory)
      (write (third fdo-sexp))
      (write-char #\space))
    ;; The body
    (setf fdo-sexp (cdddr fdo-sexp))
    (loop
	(when (null fdo-sexp)
	  (return-from pprint-fdo))
	(write-char #\space)
      (pprint-newline :linear)
      (write (first fdo-sexp))
      (pop fdo-sexp))))

Any suggestions would be most welcome.

Ray

From: Pekka P. Pirinen
Subject: Re: writing a custom pretty-printer
Date: 
Message-ID: <usn7mj39n.fsf@globalgraphics.com>
Raymond Toy <···@rtp.ericsson.se> writes:

> I'm trying to write a pretty-printer for some macros in f2cl, and I'm
> stuck on getting the following pretty-printed the way I want.
> [...] The general format looks something like:
> 
> (fdo (var init step)
>      ((end-test) return-val)
>   body)
> 
> [...] This is what I have so far, but it's not quite right (and
> quite a gross hack):
> 
> (defun pprint-fdo (fdo-sexp)
>   (pprint-logical-block (nil fdo-sexp :prefix "(" :suffix ")")
>     ;; The fdo
>     (write (first fdo-sexp))
>     (write-char #\space)
>     ;; The var step stuff
>     (pprint-logical-block (nil nil)
>     [...]

PPRINT-LOGICAL-BLOCK is not for doing indents, PPRINT-INDENT is your
friend there.

(defun pprint-fdo (fdo-sexp)
  (pprint-logical-block (nil fdo-sexp :prefix "(" :suffix ")")
    (write (pprint-pop))
    (write-char #\space)
    ; (pprint-newline :miser)
    (pprint-indent :current 0)
    (write (pprint-pop))
    (pprint-newline :mandatory)
    (write (pprint-pop))
    (pprint-indent :block 1)
    (pprint-newline :mandatory)
    (loop
     (write (pprint-pop))
     (pprint-exit-if-list-exhausted)
     (write-char #\space)
     (pprint-newline :linear))))

Using PPRINT-POP saves a lot of trouble, especially if the expression
is ever malformed.
-- 
Pekka P. Pirinen
You're only young once, but you can be immature forever.
From: Raymond Toy
Subject: Re: writing a custom pretty-printer
Date: 
Message-ID: <4nk7syg0me.fsf@rtp.ericsson.se>
>>>>> "Pekka" == Pekka P Pirinen <···············@globalgraphics.com> writes:

    Pekka> PPRINT-LOGICAL-BLOCK is not for doing indents, PPRINT-INDENT is your
    Pekka> friend there.

    Pekka> (defun pprint-fdo (fdo-sexp)
    Pekka>   (pprint-logical-block (nil fdo-sexp :prefix "(" :suffix ")")
    Pekka>     (write (pprint-pop))
    Pekka>     (write-char #\space)
    Pekka>     ; (pprint-newline :miser)
    Pekka>     (pprint-indent :current 0)
    Pekka>     (write (pprint-pop))
    Pekka>     (pprint-newline :mandatory)
    Pekka>     (write (pprint-pop))
    Pekka>     (pprint-indent :block 1)
    Pekka>     (pprint-newline :mandatory)
    Pekka>     (loop
    Pekka>      (write (pprint-pop))
    Pekka>      (pprint-exit-if-list-exhausted)
    Pekka>      (write-char #\space)
    Pekka>      (pprint-newline :linear))))

Hmm, I'm pretty sure I tried something like that.  I guess I was
running into a bug in CMUCL and/or clisp.  For

(pprint-fdo '(F2CL-LIB::FDO ((I N4 (+ I (- 1))))
                ((> I 3) NIL)
    (TAGBODY
      (F2CL-LIB::FSET (F2CL-LIB::FREF A-%DATA% (I) ((1 (+ NW 4))) A-%OFFSET%)
                     (COERCE (F2CL-LIB::FREF D ((- I 1)) ((1 1024)))
                             'SINGLE-FLOAT))
     LABEL150)))

CMUCL gives:

(F2CL-LIB:FDO ((I N4 (+ I (- 1))))
                ((> I 3) NIL)
    (TAGBODY
      (F2CL-LIB:FSET (F2CL-LIB:FREF A-%DATA% (I) ((1 (+ NW 4))) A-%OFFSET%)
                     (COERCE (F2CL-LIB:FREF D ((- I 1)) ((1 1024)))
                             'SINGLE-FLOAT))
     LABEL150))

which isn't what I want, and Clisp gives

(F2CL-LIB::FDO ((I N4 (+ I (- 1))))
               ((> I 3) NIL)
                (TAGBODY
                 (F2CL-LIB::FSET (F2CL-LIB::FREF A-%DATA% (I) ((1 (+ NW 4))) A-%OFFSET%)
                  (COERCE (F2CL-LIB::FREF D ((- I 1)) ((1 1024))) 'SINGLE-FLOAT))
                 LABEL150))

I guess I'll have to file bug reports with them. :-(

Thanks for your help!

Ray