.c	Friday  June 10,1983  19:04  NM+7H.24M.55S.  -*- Bolio -*-

.chapter "Summary"
.setq summary-section-page section-page

This chapter discusses how one might actually go about using the
pretty-printer components to do things.  There is one 2extremely
important* point:  the components of the pretty-printer 2do not*
work by default in the default lan{nil} environment;  see
(actually-using-things-section-page).

.section "Defining Pretty-Print Methods"

The most common expected use of this document is to provide the means
for definition of pretty-print methods on 3defstruct* or
3defflavor*-defined objects.  Note that for objects defined with
3defstruct*, it is only possible to define printing and
pretty-printing methods for those defined with the 3:extend*
option (or, the 3:named* option with no other type specified;  in
some future release, 3defstruct* will provide this as the default).
The method is defined with 3defmethod*.  For instance, one might do
the following:
.lisp
(defstruct (foo :named :conc-name)
  a b c)
.end_lisp
.lisp
(defmethod (foo :pp-dispatch) (format-description)
  (declare (ignore format-description))
  (pp-fixed-series-with-brackets
     "#<" ">" 'foo (foo-a self)
     (foo-b self) (foo-c self)))
.end_lisp
In this case, the default 3:pp-anaphor-dispatch* method supplied
for 3defstruct*-defined structures is adequate, because it
recursively dispatches over all of the structure components.  In the
above example, 3pp-fixed-series-with-brackets* may not be exactly
what is desired, because it only writes the components as a series;
what is really wanted in this specialized case is a head-body followed
by the components as a series:
.lisp
(defmethod (foo :pp-dispatch) (format-description)
  (declare (ignore format-description))
  (write-with-brackets "#<" ">"
    (write-head-then-body
      (pp-dispatch 'foo)
      (body-coming 1)
      (pp-fixed-series (foo-a self) (foo-b self) (foo-c self)))))
.end_lisp
This particular special case should be supplied as a function like
3pp-fixed-series-with-brackets* in a future release.

If one is defining a 3:pp-dispatch* on a 3defflavor*-defined
object, then it might be necessary to define a
3:pp-anaphor-dispatch* method to handle circularity checking in
the components which will be printed.  That is, the
3:pp-anaphor-dispatch* method which the object inherits must
"match" the 3:pp-dispatch* method, so that it recurses through the
same components which will be written by the 3:pp-dispatch* method.
.lisp
(defflavor triple (ilk tie cue plist) ()
  :initable-instance-variables)
.end_lisp
.lisp
(defmethod (triple :pp-dispatch) (format-description)
  (declare (ignore format-description))
  (write-with-brackets "[" "]"
    (write-head-then-body
      (write-head-then-body
        (pp-dispatch ilk)
        (body-coming 2 t)
        (write-with-prefix "*" (pp-dispatch tie)))
      (body-coming 2)
      (pp-dispatch cue))))
.end_lisp
.lisp
(defmethod (triple :pp-anaphor-dispatch) ()
  (pp-anaphor-dispatch ilk)
  (pp-anaphor-dispatch tie)
  (pp-anaphor-dispatch cue))
.end_lisp

There is yet another potential "inheritance" problem which will almost
undoubtedly be encountered.  That is, if the 3:print-self* method
is defined, it may not be used by the pretty-printer for some objects,
and (conversely) if the 3:pp-dispatch* method is defined, the
3:print-self* method will not be affected.

The specific problems are these.  The default 3:print-self* method
for 3defstruct*-defined objects is to print them like (for the
3foo* example)
.lisp
#S(foo a 2a-contents* b 2b-contents* c 2c-contents*)
.end_lisp
The default 3:pp-dispatch* method does effectively the same thing,
only using the lan{write} formalism and 3pp-dispatch*.  If one
defines a 3:print-self* method for such an object, the
3:pp-dispatch* method remains unchanged, so will 2still*
pretty-print that object using the #S notation.

For 3defflavor*-defined objects, the behaviour is reversed
somewhat.  That is, the default 3:print-self* method prints
.lisp
#<2flavor-name* 2instance-address*>
.end_lisp
which can be treated as an atomic object, so the default
3:pp-dispatch* method treats the object as being atomic (for the
purposes of pretty-printing).  In this case, if one defines a more
complicated 3:print-self* method for the object, that method will
still be invoked to print the object as if it were atomic, by the
default 3:pp-dispatch* method.  This case is less serious, because
the pretty-printer still could not know how to deal with the object
unless a 3:pp-dispatch* method were defined.

The solution to this is actually rather simple, and has been employed
in the past in a specialized lan{maclisp} environment.  After all,
the pretty-printer is capable of 2not* pretty-printing, but the
printer is not capable of pretty-printing.  Therefore, the "fix" is
for the 3:pp-dispatch* method to be the canonical way for print
methods to be defined, and all printing goes through the
pretty-printer by default!  This is what will be done when the printer
is brought completely up to lan{common lisp} standards.

.defun print-via-pretty-printer object stream level slashify-p
This function is designed for use in the 3:print-self* method of
something which is defining its printing entirely in terms of the
lan{write} formalism and the 3:pp-dispatch* method.  For
instance,
.lisp
(defmethod (foo :print-self) (stream level slashify-p)
  (print-via-pretty-printer object stream level slashify-p))
.end_lisp
One must ensure that there is in fact a 3:pp-dispatch* method
defined so that this will not infinitely recurse!  And, of course, a
3:pp-anaphor-dispatch* may still be needed to dispatch over the
interesting components.
.end_defun


.section "Defining Format Descriptions"

Some other time perhaps.  I believe this is mostly derivable from the
previous chapters.


.section "Actually Using Things"
.setq actually-using-things-section-page section-page

The default lan{nil} environment really only contains enough of the
pretty-printer to run already compiled code.  It is not capable of
either running any of the macros defined by it, nor of compiling calls
to them.  This is because all of the declarative information was
extracted out by the lan{lsb} compilation, and is not loaded into
the normal lan{nil} environment.

What this means is that to compile things, one must either use
lan{lsb} and declare the system to be 3built-on* the
3pretty-print* and 3pretty-print-definition* systems (a system
built on 3pretty-print-definition* is transitively built on
3write*), or one
must explicitly load the lan{lsb}-produced declarations into the
lan{nil} environment.

Anyway, the way this is done is to first make sure lan{lsb} is
loaded.  If it is not, then
.lisp
(load "nil$disk:[lsb]load")
.end_lisp
which loads it all up.  (In principle, there could be a mini-load
which would enable the loading and use of the declaration files,
without doing everything else.)  Then, one can load the public
declarations files which lan{lsb} produces.  These are the files
with the extension 7PDC*, for 3pubdcl*:
.lisp
(load "nil$disk:[format]write.pdc")
(load "nil$disk:[format]ppdef.pdc")
(load "nil$disk:[format]ppdesc.pdc")
(load "nil$disk:[format]ppcode.pdc")
.end_lisp
That is, in the current scheme of things, sufficient to allow both
interpretation and compilation of any code which uses the public
facilities described here.

