\end{describe}
\begin{table}
- \begin{tabular}[C]{|l|l|} \hlx{hv}
- \textbf{C type} & \textbf{Specifiers} \\ \hlx{vhv}
- @|void| & @|void| \\ \hlx{vhv}
+ \begin{tabular}[C]{ll} \hlx*{hv}
+ \thd{C type} & \thd{Specifiers} \\ \hlx{vhv}
+ @|void| & @|void| \\ \hlx{v}
@|char| & @|char| \\ \hlx{v}
- @|unsigned char| & @|unsigned-char|, @|uchar| \\ \hlx{v}
- @|signed char| & @|signed-char|, @|schar| \\ \hlx{vhv}
+ @|unsigned char| & @|unsigned-char|, @|uchar| \\ \hlx{}
+ @|signed char| & @|signed-char|, @|schar| \\ \hlx{v}
@|short| & @|short|, @|signed-short|, @|short-int|,
- @|signed-short-int| @|sshort| \\ \hlx{v}
+ @|signed-short-int| @|sshort| \\ \hlx{}
@|unsigned short| & @|unsigned-short|, @|unsigned-short-int|,
- @|ushort| \\ \hlx{vhv}
+ @|ushort| \\ \hlx{v}
@|int| & @|int|, @|signed|, @|signed-int|,
- @|sint| \\ \hlx{v}
- @|unsigned int| & @|unsigned|, @|unsigned-int|, @|uint| \\ \hlx{vhv}
+ @|sint| \\ \hlx{}
+ @|unsigned int| & @|unsigned|, @|unsigned-int|, @|uint| \\ \hlx{v}
@|long| & @|long|, @|signed-long|, @|long-int|,
- @|signed-long-int|, @|slong| \\ \hlx{v}
+ @|signed-long-int|, @|slong| \\ \hlx{}
@|unsigned long| & @|unsigned-long|, @|unsigned-long-int|,
- @|ulong| \\ \hlx{vhv}
+ @|ulong| \\ \hlx{v}
@|long long| & @|long-long|, @|signed-long-long|,
@|long-long-int|, \\
& \qquad @|signed-long-long-int|,
@|llong|, @|sllong| \\ \hlx{v}
@|unsigned long long|
& @|unsigned-long-long|, @|unsigned-long-long-int|,
- @|ullong| \\ \hlx{vhv}
- @|float| & @|float| \\ \hlx{v}
- @|double| & @|double| \\ \hlx{vhv}
+ @|ullong| \\ \hlx{v}
+ @|float| & @|float| \\ \hlx{}
+ @|double| & @|double| \\ \hlx{v}
@|va_list| & @|va-list| \\ \hlx{v}
@|size_t| & @|size-t| \\ \hlx{v}
- @|ptrdiff_t| & @|ptrdiff-t| \\ \hlx{vh}
+ @|ptrdiff_t| & @|ptrdiff-t| \\ \hlx*{vh}
\end{tabular}
\caption{Builtin symbolic type specifiers for simple C types}
\label{tab:codegen.c-types.simple}
evaluated). The synonyms @|ptr| and @|pointer| may be used in place of the
star @`*'.
- The symbol @|string| is a type specifier for the type of pointer to
+ The symbol @|string| is a type specifier for the type pointer to
characters; the symbol @|const-string| is a type specifier for the type
pointer to constant characters.
\end{describe}
\begin{describe}{fun}
{make-pointer-type @<c-type> \&optional @<qualifiers>
@> @<c-pointer-type>}
- Return an object describing the type of qualified pointers to @<subtype>.
+ Return an object describing the type qualified pointer to @<subtype>.
If @<subtype> is interned, then the returned pointer type object is
interned also.
\end{describe}
\subsection{Array types} \label{sec:clang.c-types.array}
-Arrays implement the compound-type protocol. The subtype of an array is the
-array element type.
+Arrays implement the compound-type protocol. The subtype of an array type is
+the array element type.
\begin{describe}{cls}{c-array-type (c-type) \&key :subtype :dimensions}
Represents a multidimensional C array type. The @<dimensions> are a list
\subsection{Function types} \label{sec:clang.c-types.fun}
+Function types implement the compound-type protocol. The subtype of a
+function type is the type of the function's return value.
+
\begin{describe}{cls}{argument}
+ Represents an ordinary function argument.
\end{describe}
\begin{describe}{fun}{argumentp @<value> @> @<generalized-boolean>}
+ Decide whether @<value> is an @<argument> object: if so, return non-nil; if
+ not return nil.
\end{describe}
\begin{describe}{fun}{make-argument @<name> @<c-type> @> @<argument>}
+ Construct and a return a new @<argument> object. The argument has type
+ @<c-type>, which must be a @|c-type| object, and is named @<name>.
+
+ The @<name> may be nil to indicate that the argument has no name: in this
+ case the argument will be formatted as an abstract declarator, which is not
+ suitable for function definitions. If @<name> is not nil, then the
+ @<name>'s print representation, with @|*print-escape*| nil, is used as the
+ argument name.
\end{describe}
-\begin{describe}{fun}{argument-name @<argument> @> @<string>}
+\begin{describe}{fun}{argument-name @<argument> @> @<name>}
+ Return the name of the @<argument>, as it was supplied to @|make-argument|.
\end{describe}
\begin{describe}{fun}{argument-type @<argument> @> @<c-type>}
+ Return the type of the @<argument>, as it was supplied to @|make-argument|.
\end{describe}
-\begin{describe}{fun}
+\begin{describe}{gf}
{commentify-argument-name @<name> @> @<commentified-name>}
-\end{describe}
+ Convert the argument name @<name> so that it's suitable to declare the
+ function in a header file.
-\begin{describe}{cls}{c-function-type (c-type) \&key :subtype :arguments}
- Represents C function types. An instance denotes the C type of a C
- function which FIXME
+ Robust header files shouldn't include literal argument names in
+ declarations of functions or function types, since this restricts the
+ including file from defining such names as macros. This generic function
+ is used to convert names into a safe form.
+
+ \begin{describe}{meth}{commentify-argument-name (@<name> null) @> nil}
+ Returns nil: if the argument name is already omitted, it's safe for use
+ in a header file.
+ \end{describe}
+ \begin{describe}{meth}{commentify-argument-name (@<name> t) @> @<string>}
+ Returns the print form of @<name> wrapped in a C comment, as
+ @`/*@<name>*/'.
+ \end{describe}
\end{describe}
\begin{describe}{fun}
- {c-function-arguments @<c-function-type> @> @<arguments>}
+ {commentify-argument-names @<arguments> @> @<commentified-arguments>}
+ Convert the @<arguments> list so that it's suitable for use in a header
+ file.
+
+ The @<arguments> list should be a list whose items are @|argument| objects
+ or the keyword @|:ellipsis|. The return value is a list constructed as
+ follows. For each @|argument| object in the input list, there is a
+ corresponding @|argument| object in the returned list, with the same type,
+ and whose name is the result of @|commentify-argument-name| applied to the
+ input argument name; an @|:ellipsis| in the input list is passed through
+ unchanged.
\end{describe}
-\begin{describe}{fun}
- {make-c-type @<c-type> @<arguments> @> @<c-function-type>}
+\begin{describe}{cls}{c-function-type (c-type) \&key :subtype :arguments}
+ Represents C function types. An instance denotes the type of a C
+ function which accepts the @<arguments> and returns @<subtype>.
+
+ The @<arguments> are a possibly empty list. All but the last element of
+ the list must be @|argument| objects; the final element may instead be the
+ keyword @|:ellipsis|, which denotes a variable argument list.
+
+ An @<arguments> list consisting of a single argument with type @|void| is
+ converted into an empty list. On output as C code, an empty argument list
+ is written as @|void|. It is not possible to represent a pre-ANSI C
+ function without prototypes.
+
+ Two function types are considered to be the same if their return types are
+ the same, and their argument lists consist of arguments with the same type,
+ in the same order, and either both or neither argument list ends with
+ @|:ellipsis|; argument names are not compared.
+
+ The type specifier @|(fun @<return-type> @{ (@<arg-name> @<arg-type>) @}^*
+ @[:ellipsis @! . @<form> @])| constructs a function type. The function has
+ the subtype @<return-type>. The remaining items in the type-specifier list
+ are used to construct the argument list. The argument items are a possibly
+ improper list, beginning with zero or more \emph{explicit arguments}:
+ two-item @<arg-name>/@<arg-type> lists. For each such list, an @|argument|
+ object is constructed with the given name (evaluated) and type. Following
+ the explicit arguments, there may be
+ \begin{itemize}
+ \item nothing, in which case the function's argument list consists only of
+ the explicit arguments;
+ \item the keyword @|:ellipsis|, as the final item in the type-specifier
+ list, indicating a variable argument list may follow the explicit
+ arguments; or
+ \item a possibly-improper list tail, beginning with an atom either as a
+ list item or as the final list cdr, indicating that the entire list tail
+ is Lisp expression which is to be evaluated to compute the remaining
+ arguments.
+ \end{itemize}
+ A tail expression may return a list of @|argument| objects, optionally
+ followed by an @|:ellipsis|.
+
+ For example,
+ \begin{prog}
+ (c-type (fun \=(lisp (c-type-subtype other-func)) \+ \\
+ ("first" int) . (c-function-arguments other-func))
+ \end{prog}
+ evaluates to a function type like @|other-func|, only with an additional
+ argument of type @|int| added to the front of its argument list. This
+ could also have been written
+ \begin{prog}
+ (let (\=(args (c-function-arguments other-func)) \+ \\
+ (ret (c-type-subtype other-func))) \- \\ \ind
+ (c-type (fun \=(lisp ret) ("first" int) . args)
+ \end{prog}
\end{describe}
\begin{describe}{fun}
- {commentify-argument-names @<arguments> @> @<commentified-arguments>}
+ {make-function-type @<subtype> @<arguments> @> @<c-function-type>}
+ Construct and return a new function type, returning @<subtype> and
+ accepting the @<arguments>.
+\end{describe}
+
+\begin{describe}{gf}
+ {c-function-arguments @<c-function-type> @> @<arguments>}
+ Return the arguments list of the @<c-function-type>.
\end{describe}
\begin{describe}{fun}
- {commentify-function-type @<c-type> @> @<commentified-c-type>}
+ {commentify-function-type @<c-function-type> @> @<commentified-c-type>}
+ Return a commentified version of the @<c-function-type>.
+
+ The returned type has the same subtype as the given type, and the argument
+ list of the returned type is the result of applying
+ @|commentify-argument-names| to the argument list of the given type.
\end{describe}
\subsection{Parsing C types} \label{sec:clang.c-types.parsing}
%%%--------------------------------------------------------------------------
\section{Generating C code} \label{sec:clang.codegen}
+This section deals with Sod's facilities for constructing and manipulating C
+expressions, declarations, instructions and definitions.
+
+\subsection{Temporary names} \label{sec:clang.codegen.temporaries}
+
+Many C-level objects, especially ones with external linkage or inclusion in a
+header file, are assigned names which are simple strings, perhaps fixed ones,
+perhaps constructed. Other objects don't need meaningful names, and
+suitably unique constructed names would be tedious and most likely rather
+opaque. Therefore Sod has an ability to construct \emph{temporary names}.
+
+These aren't temporary in the sense that they name C objects which have
+limited lifetimes at runtime. Rather, the idea is that the names be
+significant only to small pieces of Lisp code, which will soon forget about
+them.
+
+\subsubsection{The temporary name protocol}
+Temporary names are represented by objects which implement a simple protocol.
+
+\begin{describe}{gf}{format-temporary-name @<var> @<stream>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{gf}{var-in-use-p @<var> @> @<generalized-boolean>}
+ \dhead[setf var-in-use-p]
+ {gf}{setf (var-in-use-p @<var>) @<generalized-boolean>}}
+\end{describe*}
+
+\subsubsection{Temporary name objects}
+
+\begin{describe}{cls}{temporary-name () \&key :tag}
+ A temporary name object. This is the root of a small collection of
+ subclasses, but is also usable on its own.
+\end{describe}
+
+\begin{describe}{meth}
+ {commentify-argument-name (@<name> temporary-name) @> nil}
+\end{describe}
+
+\begin{table}
+ \begin{tabular}[C]{*2{>{\codeface}l}} \hlx*{hv}
+ \thd{\textbf{Class}} & \thd{\textbf{Name format}} \\ \hlx{vhv}
+ temporary-name & @<tag> \\
+ temporary-argument & sod__a@<tag> \\
+ temporary-function & sod__f@<tag> \\
+ temporary-variable & sod__v@<tag> \\ \hlx*{vh}
+ \end{tabular}
+ \caption{Temporary name formats}
+ \label{tab:codegen.codegen.temps-format}
+\end{table}
+
+\begin{describe}{cls}{temporary-argument (temporary-name) \&key :tag}
+\end{describe}
+
+\begin{describe}{cls}{temporary-function (temporary-name) \&key :tag}
+\end{describe}
+
+\begin{describe}{fun}{temporary-function @> @<name>}
+\end{describe}
+
+\begin{describe}{cls}
+ {temporary-variable (temporary-name) \&key :tag :in-use-p}
+\end{describe}
+
+\subsubsection{Well-known `temporary' names}
+
+\begin{table}
+ \begin{tabular}[C]{*2{>{\codeface}l}} \hlx*{hv}
+ \thd{\textbf{Variable}} & \thd{\textbf{Name format}} \\ \hlx{vhv}
+ {}*sod-ap* & sod__ap \\
+ {}*sod-master-ap* & sod__master_ap \\
+ {}*sod-tmp-ap* & sod__tmp_ap \\ \hlx*{vh}
+ \end{tabular}
+ \caption{Well-known temporary names}
+ \label{tab:codegen.codegen.well-known-temps}
+\end{table}
+
+\subsection{Instructions} \label{sec:clang.codegen.insts}
+
+\begin{describe}{cls}{inst () \&key}
+\end{describe}
+
+\begin{describe}{gf}{inst-metric @<inst>}
+\end{describe}
+
+\begin{describe}{mac}
+ {definst @<code> (@<streamvar> \&key @<export>) (@<arg>^*)
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {format-compound-statement (@<stream> @<child> \&optional @<morep>)
+ @<body-form>^*}
+\end{describe}
+
+\begin{table}
+ \begin{tabular}[C]{ll>{\codeface}l} \hlx*{hv}
+ \thd{Class name} &
+ \thd{Arguments} &
+ \thd{Output format} \\ \hlx{vhv}
+ @|var| & @<name> @<type> @<init> & @<type> @<name> @[= @<init>@];
+ \\ \hlx{v}
+ @|set| & @<var> @<expr> & @<var> = @<expr>; \\ \hlx{v}
+ @|update| & @<var> @<op> @<expr> & @<var> @<op>= @<expr>;
+ \\ \hlx{v}
+ @|return| & @<expr> & return @[@<expr>@];
+ \\ \hlx{v}
+ @|break| & --- & break; \\ \hlx{v}
+ @|continue| & --- & continue; \\ \hlx{v}
+ @|expr| & @<expr> & @<expr>; \\ \hlx{v}
+ @|call| & @<func> @<args> & @<func>(@<arg>_1,
+ $\ldots$,
+ @<arg>_n) \\ \hlx{v}
+ @|va-start| & @<ap> @<arg> & va_start(@<ap>, @<arg>);
+ \\ \hlx{v}
+ @|va-copy| & @<to> @<from> & va_copy(@<to>, @<from>);
+ \\ \hlx{v}
+ @|va-end| & @<ap> & va_end(@<ap>); \\ \hlx{vhv}
+ @|block| & @<decls> @<body> & \{ @[@<decls>@] @<body> \}
+ \\ \hlx{v}
+ @|if| & @<cond> @<conseq> @<alt> & if (@<cond>) @<conseq>
+ @[else @<alt>@] \\ \hlx{v}
+ @|while| & @<cond> @<body> & while (@<cond>) @<body>
+ \\ \hlx{v}
+ @|do-while| & @<body> @<cond> & do @<body> while (@<cond>);
+ \\ \hlx{v}
+ @|function| & @<name> @<type> @<body> &
+ @<type>_0 @<name>(@<type>_1 @<arg>_1, $\ldots$,
+ @<type>_n @<arg>_n @[, \dots@])
+ @<body> \\ \hlx*{vh}
+ \end{tabular}
+ \caption{Instruction classes}
+ \label{tab:codegen.codegen.insts}
+\end{table}
+
+\subsection{Code generation} \label{sec:clang.codegen.codegen}
+
+\begin{describe}{gf}{codegen-functions @<codegen> @> @<list>}
+\end{describe}
+
+\begin{describe}{gf}
+ {ensure-var @<codegen> @<name> @<type> \&optional @<init>}
+\end{describe}
+
+\begin{describe}{gf}{emit-inst @<codegen> @<inst>}
+\end{describe}
+
+\begin{describe}{gf}{emit-insts @<codegen> @<insts>}
+\end{describe}
+
+\begin{describe}{gf}{emit-decl @<codegen> @<decl>}
+\end{describe}
+
+\begin{describe}{gf}{emit-declss @<codegen> @<decls>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-push @<codegen>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-pop @<codegen> @> @<decls> @<insts>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-pop-block @<codegen> @> @<block-inst>}
+\end{describe}
+
+\begin{describe}{gf}
+ {codegen-pop-function @<codegen> @<name> @<type> @> @<name>}
+\end{describe}
+
+\begin{describe}{gf}{codegen-add-function @<codegen> @<function>}
+\end{describe}
+
+\begin{describe}{fun}
+ {codegen-build-function @<codegen> @<name> @<type> @<vars> @<insts>
+ @> @<name>}
+\end{describe}
+
+\begin{describe}{gf}{temporary-var @<codegen> @<type> @> @<name>}
+\end{describe}
+
+\begin{describe}{mac}
+ {with-temporary-var (@<codegen> @<var> @<type>) @<body-form>^*
+ @> @<value>^*}
+\end{describe}
+
+\begin{describe}{fun}{deliver-expr @<codegen> @<target> @<expr>}
+\end{describe}
+
+\begin{describe}{fun}{convert-stmts @<codegen> @<target> @<type> @<func>}
+\end{describe}
+
+\begin{describe}{cls}{codegen () \&key :vars :insts (:temp-index 0)}
+\end{describe}
+
%%%----- That's all, folks --------------------------------------------------
%%% Local variables:
--- /dev/null
+%%% -*-latex-*-
+%%%
+%%% Miscellaneous functionality
+%%%
+%%% (c) 2015 Straylight/Edgeware
+%%%
+
+%%%----- Licensing notice ---------------------------------------------------
+%%%
+%%% This file is part of the Sensble 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{Miscellaneous functionality} \label{ch:misc}
+
+%%%--------------------------------------------------------------------------
+\section{Utilities} \label{sec:misc.utilities}
+
+These symbols are defined in the @|sod-utilities| package.
+
+\begin{describe}{mac}
+ {with-gensyms (@{ @<var> @! (@<var> @[@<name>@]) @}^*) \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {once-only (@[[ :environment @<env> @]]
+ @{ @<var> @! (@<var> @[@<value-form>@]) @}^*) \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {parse-body @<body> @> @<doc-string> @<declarations> @<body-forms>}
+\end{describe}
+
+\begin{describe}{sym}{it}
+\end{describe}
+
+\begin{describe}{mac}{aif @<condition> @<consequent> @[@<alt>@]}
+\end{describe}
+
+\begin{describe}{mac}{awhen @<condition> @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}{acond @{ (@<condition> @<form>^*) @}^*}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{mac}
+ {acase @<scrutinee> @{ (@{ @<case> @! (@<case>^*) @} @<form>^*) @}^*}
+ \dhead{mac}
+ {aecase @<scrutinee> @{ (@{ @<case> @! (@<case>^*) @} @<form>^*) @}^*}
+ \dhead{mac}{atypecase @<scrutinee> @{ (@<type> @<form>^*) @}^*}
+ \dhead{mac}{aetypecase @<scrutinee> @{ (@<type> @<form>^*) @}^*}}
+\end{describe*}
+
+\begin{describe}{mac}{asetf @{ @<place> @<value> @}^*}
+\end{describe}
+
+\begin{describe}{gf}{instance-initargs @<instance>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{fun}{copy-instance @<instance> \&rest @<initargs>}
+ \dhead{gf}{copy-instance-using-class @<class> @<instance>
+ \&rest @<initargs>}}
+\end{describe*}
+
+\begin{describe*}
+ {\dhead{gf}{generic-function-methods @<generic-function> @> @<list>}
+ \dhead{gf}{method-specializers @<method> @> @<list>}
+ \dhead{cls}{eql-specializer}
+ \dhead{gf}{eql-specializer-object @<specializer> @> @<value>}}
+\end{describe*}
+
+\begin{describe}{fun}{make-list-builder \&optional @<initial> @> @<builder>}
+\end{describe}
+
+\begin{describe}{fun}{lbuild-add @<builder> @<item> @> @<builder>}
+\end{describe}
+
+\begin{describe}{fun}{lbuild-add-list @<builder> @<list> @> @<builder>}
+\end{describe}
+
+\begin{describe}{fun}{lbuild-list @<builder> @> @<list>}
+\end{describe}
+
+\begin{describe}{fun}
+ {mappend @<function> @<list> \&rest @<more-lists> @> @<result-list>}
+\end{describe}
+
+\begin{describe}{cls}{inconsistent-merge-error (error) \&key :candidates}
+\end{describe}
+
+\begin{describe}{gf}{merge-error-candidates @<error> @> @<list>}
+\end{describe}
+
+\begin{describe}{fun}
+ {merge-lists @<lists> \&key :pick (:test \#'eql) @> @<list>}
+\end{describe}
+
+\begin{describe}{mac}
+ {categorize (\=@<item-var> @<items>
+ @[[ :bind (@{ @<var> @! (@<var> @[@<value>@]) @}^*) @]])
+ \\ \ind\ind
+ (@{ @<cat-var> @<cat-predicate> @}^*) \- \\
+ @<body-form>^* \-
+ \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{fun}
+ {frob-identifier @<string> \&key :swap-case :swap-hyphen
+ @> @<frobbed-string>}
+\end{describe}
+
+\begin{describe}{fun}{whitespace-char-p @<character> @> @<generic-function>}
+\end{describe}
+
+\begin{describe}{fun}
+ {update-position @<character> @<line> @<column>
+ @> @<new-line> @<new-column>}
+\end{describe}
+
+\begin{describe}{fun}
+ {backtrack-position @<character> @<line> @<column>
+ @> @<old-line> @<old-column>}
+\end{describe}
+
+\begin{describe}{fun}
+ {compose @<function> \&rest @<more-functions> @> @<function>}
+\end{describe}
+
+\begin{describe}{fun}{symbolicate \&rest @<symbols> @> @<symbol>}
+\end{describe}
+
+\begin{describe}{mac}
+ {maybe-print-unreadable-object (@<object> @<stream>
+ @[[ :type @<type> @!
+ :identity @<identity> @]]) \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {dosequence (@<var> @<sequence>
+ @[[ :start @<start> @! :end @<end> @!
+ :indexvar @<var> @]]) \\ \ind
+ @{ @<tag> @! @<body-form> @}^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {define-access-wrapper @<from> @<to>
+ @[[ :read-only @<read-only-flag> @]]}
+\end{describe}
+
+\begin{describe}{mac}
+ {default-slot (@<instance> @<slot> @[@<slot-names>@]) \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {define-on-demand-slot @<class> @<slot> (@<instance>) \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Condition utilities} \label{sec:misc.condition}
+
+These symbols are defined in the @|sod-parser| package.
+
+\begin{describe}{cls}{enclosing-condition (condition) \&key :condition}
+\end{describe}
+
+\begin{describe}{gf}
+ {enclosed-condition @<enclosing-condition> @> @<condition>}
+\end{describe}
+
+\begin{describe}{fun}{cerror* @<datum> \&rest @<arguments>}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Option parser} \label{sec:misc.optparse}
+
+These symbols are defined in the @!optparse| package.
+
+\begin{describe}{fun}{exit \&optional (@<code> 0) \&key :abrupt}
+\end{describe}
+
+\begin{describe}{var}{*program-name*}
+\end{describe}
+
+\begin{describe}{var}{*command-line*}
+\end{describe}
+
+\begin{describe}{fun}{set-command-line-arguments}
+\end{describe}
+
+\begin{describe}{cls}{loc}
+\end{describe}
+
+\begin{describe}{fun}{locp @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{macro}{locf @<place> @> @<locative>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{fun}{ref @<locative> @> @<value>}
+ \dhead{fun}{setf (ref @<locative>) @<value>}}
+\end{describe*}
+
+\begin{describe}{mac}
+ {with-locatives
+ @{ @<var> @! (@{ @<var> @!
+ (@<var> @[@<locative>@]) @}^*) @} \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{fun}{moan @<format-string> \&rest @<format-args>}
+\end{describe}
+
+\begin{describe}{fun}{die @<format-string> \&rest @<format-args>}
+\end{describe}
+
+\begin{describe}{var}{*options*}
+\end{describe}
+
+\begin{describe}{cls}{option}
+\end{describe}
+
+\begin{describe}{fun}{optionp @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+ {make-option \=@<long-name> @<short-name> \+ \\
+ \&optional @<arg-name> \\
+ \&key :tag :negated-tag :arg-optional-p :documentation \-
+ \nlret @<option>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{fun}{opt-short-name @<option> @> @<character-or-null>}
+ \dhead{fun}{setf (opt-short-name @<option>) @<character-or-null>}
+ \dhead{fun}{opt-long-name @<option> @> @<string-or-null>}
+ \dhead{fun}{setf (opt-long-name @<option>) @<string-or-null>}
+ \dhead{fun}{opt-tag @<option> @> @<tag>}
+ \dhead{fun}{setf (opt-tag @<option>) @<tag>}
+ \dhead{fun}{opt-negated-tag @<option> @> @<tag>}
+ \dhead{fun}{setf (opt-negated-tag @<option>) @<tag>}
+ \dhead{fun}{opt-arg-name @<option> @> @<string-or-null>}
+ \dhead{fun}{setf (opt-arg-name @<option>) @<string-or-null>}
+ \dhead{fun}{opt-optional-p @<option> @> @<generalized-boolean>}
+ \dhead{fun}{setf (opt-optional-p @<option>) @<generalized-boolean>}
+ \dhead{fun}{opt-documentation @<option> @> @<string-or-null>}
+ \dhead{fun}{setf (opt-documentation @<option>) @<string-or-null>}}
+\end{describe*}
+
+\begin{describe}{cls}{option-parser}
+\end{describe}
+
+\begin{describe}{fun}{option-parser-p @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+ {make-option-parser \&key \=:args :options :non-option :numericp \+ \\
+ :negated-numeric-p long-only-p \-
+ \nlret @<option-parser>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{fun}{op-options @<option-parser> @> @<list>}
+ \dhead{fun}{setf (op-options @<option-parser>) @<list>}
+ \dhead{fun}{op-non-option @<option-parser> @> @<action>}
+ \dhead{fun}{setf (op-non-option @<option-parser>) @<action>}
+ \dhead{fun}{op-long-only-p @<option-parser> @> @<generalized-boolean>}
+ \dhead{fun}{setf (op-long-only-p @<option-parser>) @<generalized-boolean>}
+ \dhead{fun}{op-numeric-p @<option-parser> @> @<generalized-boolean>}
+ \dhead{fun}{setf (op-numeric-p @<option-parser>) @<generalized-boolean>}
+ \dhead{fun}{op-negated-numeric-p @<option-parser> @<generalized-boolean>}
+ \dhead{fun}{setf (op-negated-numeric-p @<option-parser>) @<generalized-boolean>}
+ \dhead{fun}{op-negated-p @<option-parser> @> @<generalized-boolean>}
+ \dhead{fun}{setf (op-negated-p @<option-parser>) @<generalized-boolean>}}
+\end{describe*}
+
+\begin{describe}{cls}
+ {option-parse-error (error simple-condition)
+ \&key :format-control :format-arguments}
+\end{describe}
+
+\begin{describe}{fun}{option-parse-remainder @<option-parser>}
+\end{describe}
+
+\begin{describe}{fun}{option-parse-return @<tag> \&optional @<argument>}
+\end{describe}
+
+\begin{describe}{fun}{option-parse-next @<option-parser>}
+\end{describe}
+
+\begin{describe}{mac}{option-parse-try @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}{with-unix-error-reporting () @<body-form>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {defopthandler @<name> (@<var> @[@<arg>@]) @<lambda-list> \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{fun}
+ {invoke-option-handler @<handler> @<locative> @<arg> @<arguments>}
+\end{describe}
+
+\begin{describe}{opt}{set \&optional @<value>}
+\end{describe}
+
+\begin{describe}{opt}{clear \&optional @<value>}
+\end{describe}
+
+\begin{describe}{opt}{inc \&optional @<maximum> @<step>}
+\end{describe}
+
+\begin{describe}{opt}{dec \&optional <minimum> <step>}
+\end{describe}
+
+\begin{describe}{opt}{read}
+\end{describe}
+
+\begin{describe}{opt}{int \&key :radix :min :max}
+\end{describe}
+
+\begin{describe}{opt}{string}
+\end{describe}
+
+\begin{describe}{opt}{keyword \&optional @<valid>}
+\end{describe}
+
+\begin{describe}{opt}{list \&optional @<handler> \&rest @<handler-args>}
+\end{describe}
+
+\begin{describe}{mac}{defoptmacro @<name> @<lambda-list> @<body-form>^*}
+\end{describe}
+
+\begin{describe}{fun}{parse-option-form @<form>}
+\end{describe}
+
+\begin{describe}{mac}
+ {options @{ \=@<string> @! \+ \\
+ @<option-macro> @! (@<option-macro> @<macro-arg>^*) @! \\
+ (@[[ \=@<character> @! (:short-name @<character>) @! \+ \\
+ @<string>^* @! @<symbol> @! @<rational> @!
+ (:long-name @<string>) @! \\
+ (@<string> @<format-arg>^+) @!
+ (:doc @<string> @<format-arg>^*) @! \\
+ (:opt-arg @<arg-name>) @! \\
+ @<keyword> @! (:tag @<tag>) @!
+ (:negated-tag @<tag>) @! \\
+ @{ (@<handler> @<var> @<handler-arg>^*) @}^* @]]) @}^*}
+\end{describe}
+
+\begin{describe}{fun}
+ {simple-usage @<option-list> \&optional @<mandatory-args> @> @<list>}
+\end{describe}
+
+\begin{describe}{fun}{show-usage @<prog> @<usage> \&optional @<stream>}
+\end{describe}
+
+\begin{describe}{fun}
+ {show-help @<prog> @<usage> @<option-list> \&optional @<stream>}
+\end{describe}
+
+\begin{describe}{fun}{sanity-check-option-list @<option-list>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{var}{*help*}
+ \dhead{var}{*version*}
+ \dhead{var}{*usage*}}
+\end{describe*}
+
+\begin{describe}{fun}{do-usage \&optional @<stream>}
+\end{describe}
+
+\begin{describe}{fun}{die-usage}
+\end{describe}
+
+\begin{describe}{optmac}
+ {help-options \&key :short-help :short-version :short-usage}
+\end{describe}
+
+\begin{describe}{fun}
+ {define-program \&key \=:program-name \+ \\
+ :help :version :usage :full-usage \\
+ :options}
+\end{describe}
+
+\begin{describe}{mac}
+ {do-options (@[[ :parser @<option-parser> @]]) \\ \ind
+ @{ (@{ @<case> @! (@<case>^*)@} (@[@[@<opt-var>@] @<arg-var>@])
+ @<form>^*) @}^*}
+\end{describe}
+
+%%%--------------------------------------------------------------------------
+\section{Property sets} \label{sec:misc.pset}
+
+%%%--------------------------------------------------------------------------
+\section{Miscellaneous translator features} \label{sec:misc.pset}
+
+\begin{describe}{var}{*sod-version*}
+\end{describe}
+
+\begin{describe}{var}{*debugout-pathname*}
+\end{describe}
+
+\begin{describe}{fun}{test-module @<path> @<reason>}
+\end{describe}
+
+\begin{describe}{fun}{exercise}
+\end{describe}
+
+%%%----- That's all, folks --------------------------------------------------
+
+%%% Local variables:
+%%% mode: LaTeX
+%%% TeX-master: "sod.tex"
+%%% TeX-PDF-mode: t
+%%% End:
\emph{indicators}. Finally, the consumed flag is non-nil if the parser
consumed any input items.
+\begin{describe}{fun}{combine-parser-failures @<failures> @> @<list>}
+\end{describe}
+
%%%--------------------------------------------------------------------------
-\section{File locations}
+\section{File locations} \label{sec:parsing.floc}
+
+\begin{describe}{cls}{file-location}
+\end{describe}
+
+\begin{describe}{fun}{file-location-p @<object> @> @<generalized-boolean>}
+\end{describe}
+
+\begin{describe}{fun}
+ {make-file-location @<filename> \&optional @<line> @<column>
+ @> @<file-location>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{fun}{file-location-filename @<floc> @> @<string-or-nil>}
+ \dhead{fun}{file-location-line @<floc> @> @<fixnum-or-nil>}
+ \dhead{fun}{file-location-column @<floc> @> @<fixnum-or-nil>}}
+\end{describe*}
+
+\begin{describe}{gf}{file-location @<object> @> @<floc>}
+ \begin{describe}{meth}{file-location (@<floc> file-location) @> @<floc>}
+ \end{describe}
+ \begin{describe}{meth}{file-location (@<stream> stream) @> @<floc>}
+ \end{describe}
+ \begin{describe}{meth}{file-location (@<any> t) @> @<floc>}
+ \end{describe}
+\end{describe}
+
+\begin{describe}{cls}{condition-with-location (condition) \&key :location}
+\end{describe}
+
+\begin{describe}{meth}
+ {file-location (@<condition> condition-with-location) @> @<floc>}
+\end{describe}
+
+\begin{describe*}
+ {\quad\=\quad\=\kill
+ \dhead{cls}
+ {error-with-location (condition-with-location error) \\ \>
+ \&key :location}
+ \dhead{cls}
+ {warning-with-location (condition-with-location warning) \\ \>
+ \&key :location}
+ \dhead{cls}
+ {enclosing-error-with-location
+ (enclosing-error-with-location error) \\ \>
+ \&key :condition :location}
+ \dhead{cls}
+ {enclosing-warning-with-location
+ (enclosing-condition-with-location warning) \\ \>
+ \&key :condition :location}
+ \dhead{cls}
+ {simple-condition-with-location
+ (condition-with-location simple-condition) \\ \>
+ \&key :format-control :format-arguments :location}
+ \dhead{cls}
+ {simple-error-with-location
+ (error-with-location simple-error) \\ \>
+ \&key :format-control :format-arguments :location}
+ \dhead{cls}
+ {simple-warning-with-location
+ (warning-with-location simple-warning) \\ \>
+ \&key :format-control :format-arguments :location}}
+\end{describe*}
+
+\begin{describe}{fun}
+ {make-condition-with-location @<default-type> @<floc>
+ @<datum> \&rest @<arguments>
+ \nlret @<condition-with-location>}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{fun}{error-with-location @<floc> @<datum> \&rest @<arguments>}
+ \dhead{fun}{cerror-with-location @<floc> @<continue-string>
+ @<datum> \&rest @<arguments>}
+ \dhead{fun}{cerror*-with-location @<floc> @<datum> \&rest @<arguments>}
+ \dhead{fun}{warn-with-location @<floc> @<datum> \&rest @<arguments>}}
+\end{describe*}
+
+\begin{describe}{mac}
+ {with-default-error-location (@<floc>) @<body-form>^* @> @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {count-and-report-errors () @<body-form>^*
+ @> @<value> @<n-errors> @<n-warnings>}
+\end{describe}
%%%--------------------------------------------------------------------------
\section{Scanners} \label{sec:parsing.scanner}
\subsection{Scanner file-location protocol} \label{sec:parsing.scanner.floc}
-Some scanners participate in the file-location protocol (\xref{sec:floc}).
-They implement a method on @|file-location| which collects the necessary
-information using scanner-specific functions described here.
+Some scanners participate in the file-location protocol
+(\xref{sec:parsing.floc}). They implement a method on @|file-location| which
+collects the necessary information using scanner-specific functions described
+here.
\begin{describe}{fun}{scanner-file-location @<scanner> @> @<file-location>}
Return a @|file-location| object describing the current position of the
specialized methods on @|file-location|.
\end{describe}
-\begin{describe}{gf}{scanner-filename @<scanner> @> @<string>}
- Return the name of the file the scanner is currently processing, as a
- string, or nil if the filename is not known.
-\end{describe}
-
-\begin{describe}{meth}{scanner-filename (@<scanner> t) @> @<string>}
- Returns nil.
-\end{describe}
-
-\begin{describe}{gf}{scanner-line @<scanner> @> @<integer>}
- Return the line number of the @<scanner>'s current position, as an integer,
- or nil if the line number is not known.
-\end{describe}
-
-\begin{describe}{meth}{scanner-line (@<scanner> t) @> @<integer>}
- Returns nil.
-\end{describe}
+\begin{describe*}
+ {\dhead{gf}{scanner-filename @<scanner> @> @<string>}
+ \dhead{gf}{scanner-line @<scanner> @> @<integer>}
+ \dhead{gf}{scanner-column @<scanner> @> @<integer>}}
+ Return the filename, line and column components of the @<scanner>'s current
+ position, for use in assembling a @<file-location>: see the
+ @|scanner-file-location| function.
-\begin{describe}{gf}{scanner-column @<scanner> @> @<integer>}
- Return the column number of the @<scanner>'s current position, as an
- integer, or nil if the column number is not known.
-\end{describe}
-
-\begin{describe}{meth}{scanner-column (@<scanner> t) @> @<integer>}
- Returns nil.
-\end{describe}
+ There are default methods on all three generic functions which simply
+ return nil.
+\end{describe*}
\subsection{Character scanners} \label{sec:parsing.scanner.char}
\end{describe}
%%%--------------------------------------------------------------------------
-\section{Parsing macros}
+\section{Parsing syntax}
-%%%--------------------------------------------------------------------------
+\begin{describe}{gf}{expand-parser-spec @<context> @<spec> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}
+ {expand-parser-form @<context> @<head> @<tail> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{wrap-parser @<context> @<form> @> @<wrapped-form>}
+\end{describe}
+
+\begin{describe}{mac}
+ {defparse @<name> (@[[ :context (@<var> @<context-class>) @]]
+ @<destructuring-lambda-list-item>^*) \\ \ind
+ @<body-form>^* \-
+ \nlret @<name>}
+\end{describe}
+
+\begin{describe}{mac}
+ {with-parser-context
+ (@<context-class> @{ @<init-keyword> @<value> @}^*) \\ \ind
+ @<body-form>^* \-
+ \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{lmac}
+ {parse @<parser> @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+\begin{describe}{gf}{parser-at-eof-p @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-step @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{sym}{it}
+\end{describe}
+
+\begin{describe}{mac}
+ {if-parse (@[[ \=:result @<result-var> @!
+ :expected @<expected-var> @! \+ \\
+ :consumedp @<consumed-var> @]]) \- \\ \ind\ind
+ @<parser> \- \\
+ @<consequent> \\
+ @[@<alternatve>@] \-
+ \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {when-parse (@[@<result-var>@]) @<parser> \\ \ind
+ @<body-form>^* \-
+ \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{mac}
+ {cond-parse (@[[ \=:result @<result-var> @!
+ :expected @<expected-var> @! \+ \\
+ :consumedp @<consumed-var> @]]) \- \\ \ind
+ @{ (@<parser> @<form>^*) @}^* \-
+ \nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{parse}{:eof}
+\end{describe}
+
+\begin{describe}{parseform}{lisp @<form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{label @<parser>}
+\end{describe}
+
+\begin{describe}{parse}{t}
+\end{describe}
+
+\begin{describe}{parseform}{t @<value>}
+\end{describe}
+
+\begin{describe}{parse}{nil}
+\end{describe}
+
+\begin{describe}{parseform}{nil @<indicator>}
+\end{describe}
+
+\begin{describe}{parseform}{when @<cond> @<parser>}
+\end{describe}
+
+\begin{describe}{parseform}
+ {seq (@{ @<atomic-parser-spec> @! (@[@<var>@] @<parser>) @}^*) \\ \ind
+ @<body-form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{and @<parser>^*}
+\end{describe}
+
+\begin{describe}{parseform}{or @<parser>^*}
+\end{describe}
+
+\begin{describe}{parseform}{? @<parser> @[@<default>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+ {many (\=@<accumulator-var> @<init-form> @<update-form> \+ \\
+ @[[ \=:new @<new-var> @! :final @<final-form> @! \+ \\
+ :min @<minimum> @! :max @<maximum> @! \\
+ :commitp @<commitp> @]]) \-\- \\ \ind
+ @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+ {list (@[[ :min @<minimum> @! :max @<maximum> @!
+ :commitp @<commitp> @]])\\ \ind
+ @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{parseform}
+ {skip-many (@[[ :min @<minimum> @! :max @<maximum> @!
+ :commitp @<commitp> @]])\\ \ind
+ @<item-parser> @[@<sep-parser>@]}
+\end{describe}
+
+\begin{describe}{fun}{call-pluggable-parser @<symbol> \&rest @<args>}
+\end{describe}
+
+\begin{describe}{parseform}{plug @<symbol> @<arg>^*}
+\end{describe}
+
+\begin{describe}{fun}
+ {pluggable-parser-add @<symbol> @<tag> @<parser-function>}
+\end{describe}
+
+\begin{describe}{mac}
+ {define-pluggable-parser @<symbol> @<tag> @<lambda-list> @<body-form>^*}
+\end{describe}
+
+\begin{describe}{gf}{parser-capture-place @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-restore-place @<context> @<place> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-release-place @<context> @<place> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}
+ {parser-places-must-be-released-p @<context> @> @<generalized-boolean>>}
+\end{describe}
+
+\begin{describe}{mac}
+ {with-parser-place (@<place-var> @<context>) @<body-form>^*}
+\end{describe}
+
+\begin{describe}{parseform}{peek @<parser>}
+\end{describe}
+
+\begin{describe}{cls}{character-parser-context () \&key}
+\end{describe}
+
+\begin{describe}{gf}{parser-current-char @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{parseform}
+ {if-char (@[@<result-var>@]) @<condition> @<consequent> @<alternative>}
+\end{describe}
+
+\begin{describe}{parseform}{char @<character>}
+\end{describe}
+
+\begin{describe}[char]{parse}{@<character>}
+\end{describe}
+
+\begin{describe}[string]{parse}{@<string>}
+\end{describe}
+
+\begin{describe}{parse}{:any}
+\end{describe}
+
+\begin{describe}{parseform}{satisfies @<predicate>}
+\end{describe}
+
+\begin{describe}{parseform}{not @<character>}
+\end{describe}
+
+\begin{describe}{parseform}{filter @<predicate>}
+\end{describe}
+
+\begin{describe}{parse}{:whitespace}
+\end{describe}
+
+\begin{describe}{cls}{token-parser-context () \&key}
+\end{describe}
+
+\begin{describe}{gf}{parser-token-type @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{gf}{parser-token-value @<context> @> @<form>}
+\end{describe}
+
+\begin{describe}{parseform}{token @<type> @[@<value>@] @[:peekp @<peek>@]}
+\end{describe}
+
+\begin{describe}[atom]{parse}{@<atom>}
+\end{describe}
+
+\begin{describe}[string]{parse}{@<string>}
+\end{describe}
+
+\begin{describe}{cls}{scanner-context () \&key :scanner}
+\end{describe}
+
+\begin{describe}{gf}{parse-scanner @<context> @> @<symbol>}
+\end{describe}
+
+\begin{describe}{cls}
+ {character-scanner-context (scanner-context character-parser-context)
+ \&key :scanner}
+\end{describe}
+
+\begin{describe}{cls}
+ {token-scanner-context (scanner-context token-parser-context)
+ \&key :scanner}
+\end{describe}
+
+%% FIXME parser-expr
+
+%%%-------------------------------------------------------------------------
\section{Lexical analyser}
%%%----- That's all, folks --------------------------------------------------