doc/syntax.tex: Replace `listing' environments with `prog'.
[sod] / doc / clang.tex
index 6f7e218..0c6c4bb 100644 (file)
@@ -46,6 +46,7 @@ The class hierarchy is shown in~\xref{fig:codegen.c-types.classes}.
           @|c-struct-type| \\
           @|c-union-type| \\
           @|c-enum-type| \- \\
+        @|c-atomic-type| \\
         @|c-pointer-type| \- \\
       @|c-array-type| \\
       @|c-function-type| \\ \ind
@@ -165,8 +166,16 @@ type specifier.  Type specifiers fit into two syntactic categories.
   type specifiers among its arguments.
 \end{describe}
 
-\begin{describe}{fun}{expand-c-type-spec @<type-spec> @> @<form>}
+\begin{describe}{gf}{expand-c-type-spec @<type-spec> @> @<form>}
   Returns the Lisp form that @|(c-type @<type-spec>)| would expand into.
+
+  If @<type-spec> is a list, then \descref{expand-c-type-form}{fun} is
+  invoked.
+\end{describe}
+
+\begin{describe}{gf}{expand-c-type-form @<head> @<tail> @> @<form>}
+  Returns the Lisp form that @|(c-type (@<head> . @<tail>)| would expand
+  into.
 \end{describe}
 
 \begin{describe}{gf}
@@ -299,6 +308,29 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
 \subsection{Type qualifiers and qualifiable types}
 \label{sec:clang.ctypes.qual}
 
+Qualifiers -- @|const|, @|volatile|, and so on -- are represented as lists of
+keywords attached to types.  Not all C types can carry qualifiers: notably,
+function and array types cannot be qualified.
+
+For the most part, the C qualifier keywords correspond to like-named Lisp
+keywords, only the Lisp keyword names are in uppercase.  The correspondence
+is shown in \xref{tab:clang.ctypes.qual}.
+
+\begin{table}
+  \begin{tabular}[C]{*2{>{\codeface}l}l}                           \hlx*{hv}
+    \thd{\textbf{C name}}       & \thd{\textbf{Lisp name}}      \\ \hlx{vhv}
+    _Atomic                     & :atomic                       \\
+    const                       & :const                        \\
+    restrict                    & :restrict                     \\
+    volatile                    & :volatile                     \\ \hlx*{vh}
+  \end{tabular}
+  \caption{C and Lisp qualifier names} \label{tab:clang.ctypes.qual}
+\end{table}
+
+The default behaviour, on output, is to convert keywords to lowercase and
+hope for the best: special cases can be dealt with by adding appropriate
+methods to \descref{c-qualifier-keyword}{gf}.
+
 \begin{describe}{cls}{qualifiable-c-type (c-type) \&key :qualifiers}
   The class @|qualifiable-c-type| describes C types which can bear
   `qualifiers' (\Cplusplus\ calls them `cv-qualifiers'): @|const|,
@@ -336,6 +368,113 @@ argument lists for methods.  This is done by @|c-type-equal-p|.
   non-null then the final character of the returned string will be a space.
 \end{describe}
 
+\begin{describe}{gf}{c-qualifier-keyword @<qualifier> @> @<string>}
+  Return, as a string, the C keyword corresponding to the Lisp @<qualifier>.
+
+  There is a standard method, which deals with many qualifiers.  Additional
+  methods exist for qualifier keywords which need special handling, such as
+  @|:atomic|; they are not listed here explicitly.
+
+  \begin{describe}{meth}{c-qualifier-keyword @<keyword> @> @<string>}
+    Returns the @<keyword>'s print-name, in lower case.  This is sufficient
+    for the standard qualifiers @|:const|, @|:restrict|, and @|:volatile|.
+  \end{describe}
+\end{describe}
+
+\begin{describe}{fun}{c-type-qualifier-keywords @<c-type> @> @<list>}
+  Return the @<c-type>'s qualifiers, as a list of C keyword names.
+\end{describe}
+
+
+\subsection{Storage specifiers} \label{sec:clang.ctypes.specs}
+
+Some declaration specifiers, mostly to do with how to store the specific
+object in question, are determinedly `top level', and, unlike qualifiers,
+don't stay attached to the base type when acted on by declarator operators.
+Sod calls these `storage specifiers', though no such category exists in the C
+standard.  They have their own protocol, which is similar in many ways to
+that of C types.
+
+Every Lisp keyword is potentially a storage specifier, which simply maps to
+its lower-case print name in C; but other storage specifiers may be more
+complicated objects.
+
+\begin{describe}{cls}
+    {c-storage-specifiers-type (c-type) \&key :subtype :specifiers}
+  A type which carries storage specifiers.  The @<subtype> is the actual
+  type, and may be any C type; the @<specifiers> are a list of
+  storage-specifier objects.
+
+  The type specifier @|(specs @<subtype> @<specifier>^*)| wraps the
+  @<subtype> in a @|c-storage-specifiers-type|, carrying the @<specifier>s,
+  which are a list of storage specifiers in S-expression notation.
+\end{describe}
+
+\begin{describe}{fun}{c-type-specifiers @<type> @> @<list>}
+  Returns the list of type specifiers attached to the @<type> object, which
+  must be a @|c-storage-specifiers-type|.
+\end{describe}
+
+\begin{describe}{mac}
+    {define-c-storage-specifier-syntax @<name> @<lambda-list> \\ \ind
+      @[[ @<declaration>^* @! @<doc-string> @]] \\
+      @<form>^* \-
+     \nlret @<name>}
+
+  Defines the symbol @<name> as a new storage-specifier operator.  When a
+  list of the form @|(@<name> @<argument>^*)| is used as a storage specifier,
+  the @<argument>s are bound to fresh variables according to the
+  @<lambda-list> (a destructuring lambda-list) and the @<form>s evaluated in
+  order in the resulting lexical environment as an implicit @<progn>.  The
+  value should be a Lisp form which will evaluate to the storage-specifier
+  object described by the arguments.
+
+  The @<form>s may call @|expand-c-storage-specifier| in order to recursively
+  expand storage specifiers among its arguments.
+\end{describe}
+
+\begin{describe}{gf}{expand-c-storage-specifier @<spec> @> @<form>}
+  Returns the Lisp form that @<spec> expands to within @|(c-type (specs
+  @<subtype> @<spec>))|.
+
+  If @<spec> is a list, then \descref{expand-c-storage-specifier-form} is
+  invoked.
+\end{describe}
+
+\begin{describe}{gf}{expand-c-storage-specifier-form @<spec> @> @<form>}
+  Returns the Lisp form that @|(@<head> . @<tail>)| expands to within
+  @|(c-type (specs @<subtype> (@<head> . @<tail>)))|.
+\end{describe}
+
+\begin{describe}{gf}{pprint-c-storage-specifier @<spec> @<stream>}
+\end{describe}
+
+\begin{describe}{gf}
+    {print-c-storage-specifier @<stream> @<spec>
+                               \&optional @<colon> @<atsign>}
+\end{describe}
+
+\begin{describe}{fun}{wrap-c-type @<func> @<base-type> @> @<c-type>}
+  Apply @<func> to the underlying C type of @<base-type> to create a new
+  `wrapped' type, and attach the storage specifiers of @<base-type> to the
+  wrapped type.
+
+  If @<base-type> is \emph{not} a @|c-storage-specifiers-type|, then return
+  @|(funcall @<func> @<base-type>)|.  Otherwise, return a new
+  @|c-storage-specifiers-type|, with the same specifiers, but whose subtype
+  is the result of applying @<func> to the subtype of the original
+  @<base-type>.
+\end{describe}
+
+\begin{describe}{cls}{alignas-storage-specifier () \&key :alignment}
+  The class of @|_Alignas| storage specifiers; an instance denotes the
+  specifier @|_Alignas(@<alignment>)|.  The @<alignment> parameter may be any
+  printable object, but is usually a string or C fragment.
+
+  The storage specifier form @|(alignas @<alignment>)| returns a storage
+  specifier @|_Alignas(@<alignment>)|, where @<alignment> is evaluated.
+\end{describe}
+
 
 \subsection{Leaf types} \label{sec:clang.c-types.leaf}
 
@@ -535,6 +674,38 @@ protocol.
 \end{describe}
 
 
+\subsection{Atomic types} \label{sec:clang.c-types.atomic}
+
+Atomic types are compound types.  The subtype of an atomic type is simply the
+underlying type of the object.  Note that, as far as Sod is concerned, atomic
+types are not the same as atomic-qualified types: you must be consistent
+about which you use.
+
+\begin{describe}{cls}
+    {c-atomic-type (qualifiable-c-type) \&key :qualifiers :subtype}
+  Represents an atomic type.  An instance denotes the C type
+  @|_Atomic(@<subtype>)|.
+
+  The @<subtype> may be any C type.\footnote{%
+    C does not permit atomic function or array types.} %
+  Two atomic types are equal if and only if their subtypes are equal and they
+  have matching qualifiers.  It is possible, though probably not useful, to
+  have an atomic-qualified atomic type.
+
+  The type specifier @|(atomic @<type-spec> @<qualifier>^*)| returns a type
+  qualified atomic @<subtype>, where @<subtype> is the type specified by
+  @<type-spec> and the @<qualifier>s are qualifier keywords (which are
+  evaluated).
+\end{describe}
+
+\begin{describe}{fun}
+    {make-atomic-type @<c-type> \&optional @<qualifiers> @> @<c-atomic-type>}
+  Return an object describing the type qualified atomic @<subtype>.  If
+  @<subtype> is interned, then the returned atomic type object is interned
+  also.
+\end{describe}
+
+
 \subsection{Pointer types} \label{sec:clang.c-types.pointer}
 
 Pointers are compound types.  The subtype of a pointer type is the type it