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


.chapter "The WRITE Module"
.setq write-section-page section-page

The lan{write} module defines the basic formatting control
formalism.

All term_i{writing} is performed with respect to the
term_i{current write environment}.  Write operations are valid
within the (unshadowed) dynamic scope of this environment.  This
environment provides the context within which parameters such as the
output stream, line length, pretty-printing or not, and
character-width information may be specified.

The writing of complex expressions is performed by breaking down the
input expression recursively into a small number of possible formats
(for instance, a series), and the terminal nodes.  For each
non-terminal node format, there is a macro wrapper provided, and
functions which must be called to delimit the components of that
format, and also to parameterize it.  The macros provided supply the
variable bindings and function calls necessary to actually perform the
formatting;  all of the formatting choices are made by lan{write}
itself.  The code performing the writing need only parse the input
expression in terms of these formats, calling the appropriate
lan{write} primitives;  the control structure defines the format.
For instance, the list 3(foo bar)* might be written by
.lisp
(write-with-brackets "(" ")"
  (write-series
    (next-element-coming)
    (write-atom-in-prin1-style 'foo)
    (last-element-coming)
    (write-atom-in-prin1-style 'bar)))
.end_lisp
The above expression must of course occur within an appropriately
initialized lan{write} environment. 

.section "Writing Environments"

.defmac write-afresh {form}*
Evaluates each of the 2form*s in a fresh writing environment.  Generally,
the first things which must be done are operations which initialize the
environment.  This involves the use of 3set-up-for-printing* or
3set-up-for-flatsizing* to specify how output is to be performed
and whether pretty-printing is enabled, and initialization of
special variable parameters which control other things (these are not
included in this document).

This wrapper sets up the environment necessary for the lan{write}
code.  Typically, pretty-printers or other formatters built on
lan{write} will need to augment this environment, and will provide a
wrapper macro which subsumes 3write-afresh*;  for instance, the
lan{ppdef} module, which establishes conventions for pretty-printing
lan{lisp} expressions, defines 3pp-environment*
((pp-environment-fun)) to be used instead.
.end_defmac

.defun set-up-for-printing print-stream? pretty-print?
This initializes a fresh writing environment to do output to
2print-stream?*.  Various attributes of the stream such as its
line width and the current character position are obtained.  If
2pretty-print?* is not 3nil*, then pretty-printing is
enabled;  otherwise, the output will be performed without line breaks
and extra spacing.
.end_defun

.defun set-up-for-flatsizing maximum-width-to-compute?
This may be used instead of 3set-up-for-printing* if the operation
being performed is a 3flatsize* operation rather than actual
printing.  This enables the pretty-printer to compute 3flatsize*
(or 3flatc*) directly, rather than forcing it to go through a
dummy stream.  (This is not normally used in lan{nil} right now,
although it would help.)
.end_defun


.section "Writing Non-Terminal Nodes"

.subsection "Prefix, Suffix, and Bracketing Operations"

.defmac write-with-prefix prefix {form}*
The write operations which the 2form*s perform are prefixed by
2prefix*.  2prefix* should be a string or symbol.  For
instance, the pretty-printing which causes 3(quote
2expression*)* to come out as 3'2expression** is done
by
.lisp
(write-with-prefix "'"
  2forms-to-write-the-expression*)
.end_lisp
.end_defmac

.defmac write-with-suffix suffix {form}*
Similar to 3write-with-prefix*.  I do not believe this is used in
the pretty-printer code.  It could be used to suffix an expression
with a comma, for instance.
.end_defmac

.defmac write-with-brackets left-bracket right-bracket {form}*
The write operations performed by the 2form*s will be output
within the brackets 2left-bracket* and 2right-bracket*, which
may be strings or symbols, as for 3write-with-prefix*.
3write-with-brackets* additionally maintains an internal
term_i{bracket nesting count}, which is used to terminate printing
early:  if the value of var_i{prinlevel} is not 3nil*, then if
the bracket nesting depth reaches it, the 2form*s will not be
executed, and the single character 3#* will be written instead.

This is probably the wrong modularity here, but...
.end_defmac

.subsection "Writing Series"

A term_i{series} is a sequence of elements in which (other than
by order) no element is "more distinguished" than any other.  A
lan{lisp} list written as a series might come out as
.lisp
(foo bar baz mumbledyfrotz
 quux qwerty bubbles)
.end_lisp
Note how the 3quux* lines up under the 3foo*.  Optionally, all
of the elements of the series but the last may be followed by a
term_i{suffix symbol}.  It is possible to specify that the elements
of the series be delimited by whitespace, or not.  Finally, the format
may be forced into a term_i{linear arrangement};  this means that
either all of the elements of the series start on the same line, or
they are all aligned vertically (if they do not fit on the same
line).  The above list would then come out as either
.lisp
(foo bar baz mumbledyfrotz quux qwerty bubbles)
.end_lisp
or, if that was too long to fit on one line,
.lisp
(foo
 bar
 baz
 2etc*)
.end_lisp

.defmac write-series {form}*
Evaluation of the 2form*s should write the elements of the series,
and possibly also parameterize the writing of the series by use of
3series-separation*.

The elements of the series are separated by use of
3next-element-coming* and/or 3last-element-coming*.
3last-element-coming* must be called before the final element of
the series;  it may be called either after, or in place of, a
call to 3next-element-coming*, which should precede the writing of
each element of the series.
.end_defmac

.defun series-separation &optional separation-suffix-symbol? no-space-needed-between-elements? linear-arrangement-only?
This controls how the series is output.  If
2separation-suffix-symbol?* is specified and not 3nil*, then
it is a symbol or string which is used as a suffix for each element
but the last.  If 2no-space-needed-between-elements?* is
specified and not 3nil*, then when elements are placed on the same
line, they will not be delimited by whitespace;  only by
2separation-suffix-symbol?* (if any).  If
2linear-arrangement-only?* is specified and not 3nil*, then
the elements of the series will either all be written on the same
line, or each on a new line.
.end_defun

.defun next-element-coming
.defun1 last-element-coming
3next-element-coming* should be called before the writing of each
element of a series within 3write-series*.  The final element
should be preceded by a call to 3last-element-coming*;
3last-element-coming* may be called either in place of or in
addition to the call to 3next-element-coming*.
.end_defun

The writing of a lan{nil} complex number, whose syntax is
3#C(2realpart* 2imagpart*)* might look like this:
.lisp
(write-with-brackets "#C(" ")"
  (write-series
    (next-element-coming)
    2write the real part of the number*
    (last-element-coming)
    2write the imaginary part of the number*))
.end_lisp

.subsection "Writing Head-Body"

The other major format for non-terminal nodes is the
term_i{head-body} format.  This is used for constructs in which some
part (the head) is somehow distinguished from the rest (the body).
Consider the lan{lisp} code fragment
.lisp
(let ((var1 (compute-first-variable))
      (var2 (compute-second-variable)))
  (mung-around-on-var1)
  (mung-around-on-var2))
.end_lisp
Ignoring all bracketing, this is first a head-body relationship.  The
head of the first form is the sequence of subexpressions 3let* and
the 3let* binding list;  the body is the the sequence of
expressions 3(mung-around-on-var1)* and
3(mung-around-on-var2)*.  The indentation by which the body
exceeds the indentation of the head (where the 3let* is output) is
known as the term_i{hanging indentation};  in this case, 31*.
Presumably, the two
expression sequences which comprise the head and body are handled in a
similar fashion;  the lan{lisp} code pretty-printer will write the
head as a recursive head-body (with 3let* the head and the letlist
the body), and the body (the forms in the 3let*) as a series.

.defmac write-head-then-body {form}*
The evaluation of 2form*s should write the head, then the body.
The two are delimited by a call to 3body-coming*, which 2must*
occur.
.end_defmac

.defun body-coming &optional (unsqueezed-hanging-indentation 2) no-space-needed-here? hanging-indentation-only?
This is used to delimit the head from the body within a
3write-head-then-body* form.  2unsqueezed-hanging-indentation*
is the indentation by which the body will be indented more than the
head;  it must be non-negative.  That amount may be decreased
("squeezed") if the body requires it.  If
2no-space-needed-here?* not 3nil*, then the head and body
will not be separated by a space (if they fall on the same line);
normally they will.  If 2hanging-indentation-only?* is not
3nil*, then the body will 2always* be placed on the following
line.
.end_defun


.section "Writing Terminal Nodes"

In the following, certain arguments are called term_i{pnamed
object}s.  This is something from which a print name can be trivially
derived:  a symbol, string, or (in lan{nil}) a character object.

.defun write-spelling pnamed-object
Writes the characters of 2pnamed-object*, a string or symbol.
.end_defun

.defun write-character single-character-pnamed-object
Writes the single character.
.end_defun

.defun write-atom-in-prin1-style atomic-object
Writes 2atomic-object*;  it will be output with 3prin1*.
.end_defun

.defun write-symbol-in-prin1-style symbol
This is a special case of 3write-atom-in-prin1-style*.
.end_defun

.defun write-non-symbol-atom non-symbol-atomic-object
Writes the non-symbol 2non-symbol-atomic-object*;  it will be
output as by 3princ*.
.end_defun

.defun write-keyword-in-prin1-style symbol
2symbol* is output in 3prin1* style, 2except* that (in
lan{lisp} implementations which support packages) it will not have
its package prefix output.  This is used for the output of lan{lisp}
tokens which need to be invertible with 3read* (hence are in
3prin1* style), but for which the package is irrelevant;  for
instance, keywords to the 3loop* macro.
.end_defun

.defun write-integer-in-decimal integer
.end_defun


.section "Low-Level Buffering Operations and Conventions"

This is the stuff which would be used were one to define new formats
like 3write-series* or 3write-head-then-body*.  Discussion of
this is deferred to some later date and document.

