%%% -*-latex-*-
%%%
%%% Output machinery
%%%
%%% (c) 2015 Straylight/Edgeware
%%%

%%%----- Licensing notice ---------------------------------------------------
%%%
%%% 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
%%% the Free Software Foundation; either version 2 of the License, or
%%% (at your option) any later version.
%%%
%%% SOD is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%%% GNU General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with SOD; if not, write to the Free Software Foundation,
%%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

\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*}
    {\dhead{fun}{sequencer-constraints @<sequencer> @> @<list>}
     \dhead{fun}{setf (sequencer-constraints @<sequencer>) @<list>}
     \dhead{fun}{sequencer-table @<sequencer> @> @<hash-table>}}
\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}
    {add-sequencer-item-function @<sequencer> @<name> @<function>}
\end{describe}

\begin{describe}{fun}
    {invoke-sequencer-items @<sequencer> \&rest @<arguments>}
\end{describe}

\begin{describe}{gf}{hook-output @<object> @<reason> @<sequencer>}
  \begin{describe}{meth}{t,t}
    {hook-output (@<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}{gf}
    {module-output-file @<module> @<output-type> @<output-dir>
      @> @<pathname>}
  \begin{describe*}
      {\dhead{meth}{module,symbol}
          {module-output-file \=(@<module> module)              \\
                              \>(@<output-type> symbol)         \\
                              \>@<output-dir>
           \nlret @<pathname>}
       \dhead{meth}{module,pathname}
          {module-output-file \=(@<module> module)              \\
                              \>(@<output-type> pathname)       \\
                              \>@<output-dir>
           \nlret @<pathname>}}
  \end{describe*}
\end{describe}

\begin{describe}{gf}{write-dependency-file @<module> @<reason> @<output-dir>}
\end{describe}

\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}

\begin{describe}{gf}{emit-class-typedef @<class> @<stream>}
\end{describe}

\begin{describe}{gf}{emit-class-object-decl @<class> @<stream>}
\end{describe}

\begin{describe}{gf}{emit-class-conversion-macro @<class> @<super> @<stream>}
\end{describe}

\begin{describe*}
    {\dhead{gf}{emit-message-macro @<class> @<entry> @<stream>}
     \dhead{gf}{emit-message-macro-defn
                  \=@<class> @<entry> @<varargsp> @<me> \\
                  \>@<in-names> @<out-names> @<stream>}}
\end{describe*}

%% output for `h' files
%%
%% prologue
%% guard start
%% typedefs start
%% typedefs
%% typedefs end
%% includes start
%% includes
%% includes end
%% classes start
%% early-user start
%% early-user
%% early-user end
%% CLASS banner
%% CLASS islots start
%% CLASS islots slots
%% CLASS islots end
%% CLASS vtmsgs start
%% CLASS vtmsgs CLASS start
%% CLASS vtmsgs CLASS slots
%% CLASS vtmsgs CLASS end
%% CLASS vtmsgs end
%% CLASS vtables start
%% CLASS vtables CHAIN-HEAD start
%% CLASS vtables CHAIN-HEAD slots
%% CLASS vtables CHAIN-HEAD end
%% CLASS vtables end
%% CLASS vtable-externs
%% CLASS vtable-externs-after
%% CLASS methods start
%% CLASS methods
%% CLASS methods end
%% CLASS ichains start
%% CLASS ichains CHAIN-HEAD start
%% CLASS ichains CHAIN-HEAD slots
%% CLASS ichains CHAIN-HEAD end
%% CLASS ichains end
%% CLASS ilayout start
%% CLASS ilayout slots
%% CLASS ilayout end
%% CLASS conversions
%% CLASS object
%% classes end
%% user start
%% user
%% user end
%% guard end
%% epilogue

%% output for `c' files
%%
%% prologue
%% includes start
%% includes
%% includes end
%% early-user start
%% early-user
%% early-user end
%% classes start
%% CLASS banner
%% CLASS direct-methods start
%% CLASS direct-methods METHOD start
%% CLASS direct-methods METHOD body
%% CLASS direct-methods METHOD end
%% CLASS direct-methods end
%% CLASS effective-methods
%% CLASS vtables start
%% CLASS vtables CHAIN-HEAD start
%% CLASS vtables CHAIN-HEAD class-pointer METACLASS
%% CLASS vtables CHAIN-HEAD base-offset
%% CLASS vtables CHAIN-HEAD chain-offset TARGET-HEAD
%% CLASS vtables CHAIN-HEAD vtmsgs CLASS start
%% CLASS vtables CHAIN-HEAD vtmsgs CLASS slots
%% CLASS vtables CHAIN-HEAD vtmsgs CLASS end
%% CLASS vtables CHAIN-HEAD end
%% CLASS vtables end
%% CLASS object prepare
%% CLASS object start
%% CLASS object CHAIN-HEAD ichain start
%% CLASS object SUPER slots start
%% CLASS object SUPER slots
%% CLASS object SUPER vtable
%% CLASS object SUPER slots end
%% CLASS object CHAIN-HEAD ichain end
%% CLASS object end
%% classes end
%% user start
%% user
%% user end
%% epilogue

%%%----- That's all, folks --------------------------------------------------

%%% Local variables:
%%% mode: LaTeX
%%% TeX-master: "sod.tex"
%%% TeX-PDF-mode: t
%%% End:
