X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/1f7d590d9c7b87442c8d8b6424ed4f769d377692..a47b5b286ee7c98c16b4023e5d6954cfdd9faa88:/doc/output.tex?ds=sidebyside

diff --git a/doc/output.tex b/doc/output.tex
index 29a8b4d..4571b6a 100644
--- a/doc/output.tex
+++ b/doc/output.tex
@@ -7,7 +7,7 @@
 
 %%%----- Licensing notice ---------------------------------------------------
 %%%
-%%% This file is part of the Sensble Object Design, an object system for C.
+%%% This file is part of the Sensible Object Design, an object system for C.
 %%%
 %%% SOD is free software; you can redistribute it and/or modify
 %%% it under the terms of the GNU General Public License as published by
@@ -25,7 +25,177 @@
 
 \chapter{The output system} \label{ch:output}
 
+This chapter deals with actually generating output files.  It will be of
+interest to programmers introducing new layout object classes, or new kinds
+of output files.  An understanding of the material in
+\xref{sec:structures.layout} will prove valuable.
+
 %%%--------------------------------------------------------------------------
+\section{Output sequencing} \label{sec:output.sequencer}
+
+C compilers are picky about the order in which things are presented to them
+in their input; but information about the structure of our classes is
+scattered among a variety of different layout objects.  It's not the case
+that a layout object only contributes to a single localized portion of the
+output: for example, a @|vtmsgs| layout object is responsible for declaring
+both the appropriate @|struct $C$__vtmsgs_$a$| structure in the header file,
+populated with method entry pointers, but also declaring its member in the
+enclosing @|struct $C$__vt_$i$| structure.
+
+One approach would be to have the various layout objects just know how to
+call each other in the right order so as to have everything come out
+properly.  That would make extending the translator, e.g., to add new kinds
+of layout objects, rather difficult.  And it doesn't let users insert custom
+C fragments in flexible ways.
+
+Instead, there's a clear separation between which things need to be output,
+and the order in which they're produced.
+
+Ordering is handled by a \emph{sequencer} object.  A sequencer doesn't know
+anything particular about output: its job is simply to do things in a
+particular order.  It's described here because Sod only uses it for output
+scheduling.
+
+A sequencer maintains a collection of named \emph{items}, each of which has a
+name and a list of functions associated with it.  A name can be any Lisp
+object.  Names are compared using @|equal|, so lists can be used to construct
+a hierarchical namespace.
+
+The sequencer also maintains a collection of \emph{constraints}, which take
+the form of lists of item names.  A constraint of the form @|($N_1$, $N_2$,
+$\ldots$, $N_k$)| requires that the item named $N_1$ must be scheduled before
+the item named $N_2$, and so on, all of which must be scheduled before the
+item named $N_k$.  Items with these names do not need to exist or be known to
+the sequencer.  An item name may appear in any number of constraints, all of
+which apply.
+
+It might be that a collection of constraints is impossible to satisfy: for
+example, the set
+\begin{center} \codeface
+  (alice bob) \qquad (bob carol) \qquad (carol alice)
+\end{center}
+can't be satisfied, since the first constraint requires that @|alice|
+precedes @|bob|, but the third says that @|alice| must come after @|carol|,
+and the second that @|carol| comes after @|bob|: it's not possible that
+@|alice| comes before @|bob| and after @|bob|.  In this case, the sequencer
+fails and signals an error of type @|inconsistent-merge-error|.
+
+It is possible, but tedious, to explicitly order an entire collection of
+items by adding constraints.  In the absence of explicit constraints to order
+them, items are ordered according to the order in which constraints naming
+them were first added to the sequencer.  Items not named in any constraint
+are not processed at all.
+
+For example, suppose we have the following constraints.
+\begin{center} \codeface
+  (perl java) \qquad
+  (lisp java) \qquad
+  (python icon) \qquad
+  (icon perl)
+\end{center}
+The constraints give us that $@|python| < @|icon| < @|perl| < @|java|$, and
+also $@|lisp| < @|java|$.  In this case, @|lisp| precedes @|python| because
+@|lisp| is mentioned in the second constraint while @|python| isn't mentioned
+until the third.  So the final processing order is
+\begin{center}
+  @|lisp|, \quad
+  @|python|, \quad
+  @|icon|, \quad
+  @|perl|, \quad
+  @|java|
+\end{center}
+
+
+\begin{describe}{cls}{sequencer-item}
+  An object of class @|sequencer-item| represents a sequencer item.
+  Sequencer items maintain a \emph{name} and a list of \emph{functions}.
+  Names are compared using @|equal|.
+
+  The functions are maintained in \emph{reverse order}, because it's
+  convenient to be able to add new functions using @|push|.
+\end{describe}
+
+\begin{describe}{fun}{sequencer-item-p @<object> @> @<generalized-boolean>}
+  Return non-nil if and only if @<object> is a @|sequencer-item|.
+\end{describe}
+
+\begin{describe}{fun}
+    {make-sequencer-item @<name> \&optional @<functions> @> @<item>}
+  Create and return a new sequencer item with the given @<name> and list of
+  @<functions>; the list of functions defaults to nil if omitted.
+\end{describe}
+
+\begin{describe*}
+    {\dhead{fun}{sequencer-item-name @<item> @> @<name>}
+     \dhead{fun}{sequencer-item-functions @<item> @> @<list>}
+     \dhead{fun}{setf (sequencer-item-functions @<item>) @<list>}}
+   These functions read or modify the state of a sequencer @<item>, as
+   originally established by @|make-sequencer-item|.
+
+   It is an error to modify an item's list of functions during a call to
+   @|invoke-sequencer-items| on the item's owning sequencer.
+\end{describe*}
+
+\begin{describe}{cls}{sequencer () \&key :constraints}
+\end{describe}
+
+\begin{describe}{fun}{ensure-sequencer-item @<sequencer> @<name> @> @<item>}
+\end{describe}
+
+\begin{describe}{fun}{add-sequencer-constraint @<sequencer> @<constraint>}
+\end{describe}
+
+\begin{describe}{fun}
+    {invoke-sequencer-items @<sequencer> \&rest @<arguments>}
+\end{describe}
+
+\begin{describe}{gf}{hook-output progn @<object> @<reason> @<sequencer>}
+  \begin{describe}{meth}
+    {hook-output progn (@<object> t) (@<reason> t) @<sequencer>}
+  \end{describe}
+\end{describe}
+
+\begin{describe}{mac}
+    {sequence-output (@<stream-var> @<sequencer>)               \\ \ind
+      @{ :constraint (@<item-name>^*) @}                        \\
+      @{ (@<item-name> @<form>^*) @}^*}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Module output} \label{output.module}
+
+\subsection{Producing output}
+
+\begin{describe}{fun}{output-module @<module> @<reason> @<stream>}
+\end{describe}
+
+
+\subsection{Managing output types} \label{output.module.manage}
+
+\begin{describe}{fun}{declare-output-type @<reason> @<pathname>}
+\end{describe}
+
+\begin{describe}{fun}{output-type-pathname @<reason> @> @<pathname>}
+\end{describe}
+
+
+\subsection{Utilities} \label{output.module.utilities}
+
+\begin{describe}{fun}{banner @<title> @<output> \&key :blank-line-p}
+\end{describe}
+
+\begin{describe}{fun}{guard-name @<filename> @> @<string>}
+\end{describe}
+
+\begin{describe}{fun}
+    {one-off-output @<token> @<sequencer> @<item-name> @<function>}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Class output} \label{output.class}
+
+\begin{describe}{var}{*instance-class*}
+\end{describe}
 
 %% output for `h' files
 %%
@@ -38,6 +208,9 @@
 %% includes
 %% includes end
 %% classes start
+%% early-user start
+%% early-user
+%% early-user end
 %% CLASS banner
 %% CLASS islots start
 %% CLASS islots slots
@@ -68,6 +241,9 @@
 %% CLASS conversions
 %% CLASS object
 %% classes end
+%% user start
+%% user
+%% user end
 %% guard end
 %% epilogue
 
@@ -77,6 +253,9 @@
 %% includes start
 %% includes
 %% includes end
+%% early-user start
+%% early-user
+%% early-user end
 %% classes start
 %% CLASS banner
 %% CLASS direct-methods start
@@ -105,6 +284,9 @@
 %% CLASS object CHAIN-HEAD ichain end
 %% CLASS object end
 %% classes end
+%% user start
+%% user
+%% user end
 %% epilogue
 
 %%%----- That's all, folks --------------------------------------------------
