chiark / gitweb /
src/c-types-impl.lisp: Reorder `merge-keyword-lists' input lists.
[sod] / doc / clang.tex
index 348c5b634d827510edbba760982ad982b43e3fd0..18a8e1cfc1f41b8986f01021b840785b2c537eff 100644 (file)
@@ -38,18 +38,19 @@ The class hierarchy is shown in~\xref{fig:codegen.c-types.classes}.
 
 \begin{figure} \centering
   \parbox{10pt}{\begin{tabbing}
-    @|c-type| \\ \ind
-      @|qualifiable-c-type| \\ \ind
-        @|simple-c-type| \\ \ind
-          @|c-class-type| \- \\
-        @|tagged-c-type| \\ \ind
-          @|c-struct-type| \\
-          @|c-union-type| \\
-          @|c-enum-type| \- \\
-        @|c-atomic-type| \\
-        @|c-pointer-type| \- \\
-      @|c-array-type| \\
-      @|c-function-type|
+    @|c-type|                                                   \\ \ind
+      @|qualifiable-c-type|                                     \\ \ind
+        @|simple-c-type|                                        \\ \ind
+          @|c-class-type|                                     \-\\
+        @|tagged-c-type|                                        \\ \ind
+          @|c-struct-type|                                      \\
+          @|c-union-type|                                       \\
+          @|c-enum-type|                                      \-\\
+        @|c-atomic-type|                                        \\
+        @|c-pointer-type|                                     \-\\
+      @|c-array-type|                                           \\
+      @|c-function-type|                                        \\ \ind
+        @|c-keyword-function-type|                            \-
   \end{tabbing}}
   \caption{Classes representing C types}
 \label{fig:codegen.c-types.classes}
@@ -124,9 +125,9 @@ type specifier.  Type specifiers fit into two syntactic categories.
 \end{describe}
 
 \begin{describe}{mac}
-    {defctype \=@{ @<name> @! (@<name>^+) @} @<type-spec> \+ \\
-                @[[ @|:export| @<export-flag> @]]^* \-
-       \nlret @<names>}
+    {defctype \=@{ @<name> @! (@<name>^+) @} @<type-spec>     \+\\
+                @[[ @|:export| @<export-flag> @]]^*
+       \-\nlret @<names>}
   Defines a new symbolic type specifier @<name>; if a list of @<name>s is
   given, then all are defined in the same way.  The type constructed by using
   any of the @<name>s is as described by the type specifier @<type-spec>.
@@ -150,10 +151,10 @@ type specifier.  Type specifiers fit into two syntactic categories.
 \end{describe}
 
 \begin{describe}{mac}
-    {define-c-type-syntax @<name> @<lambda-list> \\ \ind
-      @[[ @<declaration>^* @! @<doc-string> @]] \\
-      @<form>^* \-
-     \nlret @<name>}
+    {define-c-type-syntax @<name> @<lambda-list>                \\ \ind
+      @[[ @<declaration>^* @! @<doc-string> @]]                 \\
+      @<form>^*
+     \-\nlret @<name>}
   Defines the symbol @<name> as a new type operator.  When a list of the form
   @|(@<name> @<argument>^*)| is used as a type specifier, the @<argument>s
   are bound to fresh variables according to @<lambda-list> (a destructuring
@@ -385,6 +386,96 @@ methods to \descref{c-qualifier-keyword}{gf}.
 \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}
 
 A \emph{leaf type} is a type which is not defined in terms of another type.
@@ -473,23 +564,35 @@ In Sod, the leaf types are
 \end{describe}
 
 \begin{describe}{mac}
-    {define-simple-c-type \=@{ @<name> @! (@<name>^+) @} @<string> \+ \\
-                            @[[ @|:export| @<export-flag> @]] \-
-      \nlret @<name>}
+    {define-simple-c-type
+       \=@{ @<name> @! (@<name>^+) @}
+         @{ @<string> @! (@<string>^*) @}                     \+\\
+         @[[ @|:export| @<export-flag> @]]
+      \-\nlret @<name>}
   Define type specifiers for a new simple C type.  Each symbol @<name> is
   defined as a symbolic type specifier for the (unique interned) simple C
-  type whose name is the value of @<string>.  Further, each @<name> is
-  defined to be a type operator: the type specifier @|(@<name>
+  type whose name is the value of (the first) @<string>.  Further, each
+  @<name> is defined to be a type operator: the type specifier @|(@<name>
   @<qualifier>^*)| evaluates to the (unique interned) simple C type whose
-  name is @<string> and which has the @<qualifiers> (which are evaluated).
+  name is (the first) @<string> and which has the @<qualifiers> (which are
+  evaluated).
 
-  Furthermore, a variable @|c-type-@<name>| is defined, for the first @<name>
-  only, and initialized with the newly constructed C type object.
+  Each of the @<string>s is associated with the resulting type for retrieval
+  by \descref{find-simple-c-type}{fun}.  Furthermore, a variable
+  @|c-type-@<name>| is defined, for the first @<name> only, and initialized
+  with the newly constructed C type object.
 
   If @<export-flag> is true, then the @|c-type-@<name>| variable name, and
   all of the @<name>s, are exported from the current package.
 \end{describe}
 
+\begin{describe}{fun}
+    {find-simple-c-type @<string> @> @{ @<simple-c-type> @! @|nil| @}}
+  If @<string> is the name of a simple C type, as established by the
+  \descref{define-simple-c-type}[macro]{mac}, then return the corresponding
+  @|simple-c-type| object; otherwise, return @|nil|.
+\end{describe}
+
 \begin{describe}{cls}{tagged-c-type (qualifiable-c-type)
     \&key :qualifiers :tag}
   Provides common behaviour for C tagged types.  A @<tag> is a string
@@ -704,7 +807,8 @@ function type is the type of the function's return value.
   not return nil.
 \end{describe}
 
-\begin{describe}{fun}{make-argument @<name> @<c-type> @> @<argument>}
+\begin{describe}{fun}
+    {make-argument @<name> @<c-type> \&optional @<default> @> @<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>.
 
@@ -713,14 +817,21 @@ function type is the type of the function's return value.
   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.
+
+  A @<default> may be supplied.  If the argument is used in a
+  keyword-argument list (e.g., in a \descref{c-keyword-function-type}
+  [object]{cls}), and the @<default> value is provided and non-nil, then its
+  (unescaped) printed representation is used to provide a default value if
+  the keyword argument is not supplied by the caller.
 \end{describe}
 
 \begin{describe*}
     {\dhead{fun}{argument-name @<argument> @> @<name>}
-     \dhead{fun}{argument-type @<argument> @> @<c-type>}}
-  Accessor functions for @|argument| objects.  They return the name (for
-  @|argument-name|) or type (for @|argument-type|) from the object, as passed
-  to @|make-argument|.
+     \dhead{fun}{argument-type @<argument> @> @<c-type>}
+     \dhead{fun}{argument-default @<argument> @> @<default>}}
+  Accessor functions for @|argument| objects.  They return the appropriate
+  component of the object, as set by to @|make-argument|.  The @<default> is
+  nil if no default was provided to @|make-argument|.
 \end{describe*}
 
 \begin{describe}{gf}
@@ -804,23 +915,85 @@ function type is the type of the function's return value.
 
   For example,
   \begin{prog}
-    (c-type (fun \=(lisp (c-type-subtype other-func)) \+ \\
+    (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
+    (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}{cls}
+    {c-keyword-function-type (c-function-type)
+      \&key :subtype :arguments :keywords}
+  Represents `functions' which accept keyword arguments.  Of course, actual C
+  functions can't accept keyword arguments directly, but this type is useful
+  for describing messages and methods which deal with keyword arguments.
+
+  An instance denotes the type of C function which accepts the position
+  argument list @<arguments>, and keyword arguments from the @<keywords>
+  list, and returns @<subtype>.  Either or both of the @<arguments> and
+  @<keywords> lists may be empty.  (It is important to note the distinction
+  between a function which doesn't accept keyword arguments, and one which
+  does but for which no keyword arguments are defined.  In particular, the
+  latter function can be changed later to accept a keyword argument without
+  breaking compatibility with old code.)  The @<arguments> and @<keywords>
+  lists must \emph{not} contain @|:ellipsis| markers: a function can accept
+  keywords, or a variable-length argument tail, but not both.
+
+  Keyword arguments may (but need not) have a \emph{default value} which is
+  supplied to the function body if the keyword is omitted.
+
+  Keyword functions are never considered to be the same as ordinary
+  functions.  Two keyword function types are considered to be the same if
+  their return types are the same, and their positional argument lists consist of
+  arguments with the same type, in the same order: the keyword arguments
+  accepted by the functions is not significant.
+
+  Keyword functions are constructed using an extended version of the @|fun|
+  specifier used for ordinary C function types.  The extended syntax is as
+  follows.
+  \begin{prog}
+    (fun \=@<return-type>
+           @{ (@<arg-name> @<arg-type>) @}^*                  \+\\
+           @{ \=:keys @{ (@<kw-name> @<kw-type> @[@<kw-default>@]) @}^*
+                   @[. @<form>@] @!                           \+\\
+                 . @<form> @}
+  \end{prog}
+  where either the symbol @|:keys| appears literally in the specifier, or the
+  @<form> evaluates to a list containing the symbol @|:keys|.  (If neither of
+  these circumstances obtains, then the specifier constructs an ordinary
+  function type.)
+
+  See the description of \descref{c-function-type}{cls} for how a trailing
+  @<form> is handled.
+
+  The list of @<arg-name>s and @<arg-type>s describes the positional
+  arguments.  The list of @<kw-name>s, @<kw-type>s and @<kw-defaults>s
+  describes the keyword arguments.
+\end{describe}
+
 \begin{describe}{fun}
     {make-function-type @<subtype> @<arguments> @> @<c-function-type>}
   Construct and return a new function type, returning @<subtype> and
   accepting the @<arguments>.
+
+  If the @<arguments> list contains a @|:keys| marker, then a
+  \descref{c-keyword-function-type}[object]{cls} is returned: those arguments
+  preceding the @|:keys| marker form the positional argument list, and those
+  following the marker form the list of keyword arguments.
+\end{describe}
+
+\begin{describe}{fun}
+    {make-keyword-function-type @<subtype> @<arguments> @<keywords>
+      \nlret @<c-keyword-function-type>}
+  Construct and return a new keyword-function type, returning @<subtype> and
+  accepting the @<arguments> and @<keywords>.
 \end{describe}
 
 \begin{describe}{gf}
@@ -837,6 +1010,62 @@ function type is the type of the function's return value.
   @|commentify-argument-names| to the argument list of the given type.
 \end{describe}
 
+\begin{describe}{fun}{reify-variable-argument-tail @<arguments> @> @<list>}
+  If the @<argument> list contains an @|:ellipsis| marker, then replace it
+  with a @|va_list|.  The name for the new argument, if any, is taken from
+  the \descref{*sod-ap*}[variable]{var}.  The new list is returned; the
+  original list is not modified, but may share structure with the new list.
+\end{describe}
+
+\begin{describe}{fun}{merge-keyword-lists @<lists> @> @<list>}
+  Merge a number of keyword-argument lists together and return the result.
+
+  The @<lists> parameter is a list consisting of a number of @|(@<origin>
+  . @<args>)| pairs: in each pair, @<origin> is either nil or an object whose
+  printed representation describes the origin of the corresponding @<args>
+  list suitable for inclusion in an error message, and @<args> is a list of
+  \descref{argument}{cls} objects.
+
+  The resulting list contains exactly one argument for each distinct argument
+  name appearing in the input @<lists>; this argument will contain the
+  default value from the earliest occurrence in the input @<lists> of an
+  argument with that name.
+
+  If the same name appears multiple times with different types, an error is
+  signalled quoting the name, conflicting types, and (if non-nil) the origins
+  of the offending argument objects.
+\end{describe}
+
+\begin{describe}{fun}
+    {pprint-c-function-type @<return-type> @<stream>
+                            @<print-args> @<print-kernel>}
+  Provides the top-level structure for printing C function types.
+
+  Output is written to @<stream> to describe a function type returning
+  @<return-type>, whose declarator kernel (containing the name, and any
+  further type operands) will be printed by @<print-kernel>, and whose
+  arguments, if any, will be printed by @<print-args>.
+
+  The @<print-kernel> function is a standard kernel-printing function
+  following the \descref{pprint-c-type}[protocol]{gf}.
+
+  The @<print-args> function is given a single argument, which is the
+  @<stream> to print on.  It should not print the surrounding parentheses.
+
+  The output written to @<stream> looks approximately like
+  \begin{prog}
+    @<return-type> @<kernel>(@<args>)
+  \end{prog}
+\end{describe}
+
+\begin{describe}{fun}{pprint-argument-list @<args> @<stream> @> @<flag>}
+  Print an argument list to @<stream>.
+
+  The @<args> is a list of \descref{argument}[objects]{cls}, optionally
+  containing an @|:ellipsis| marker.  The function returns true if any
+  arguments were actually printed.
+\end{describe}
+
 
 \subsection{Parsing C types} \label{sec:clang.c-types.parsing}
 
@@ -970,19 +1199,23 @@ Temporary names are represented by objects which implement a simple protocol.
 \end{describe}
 
 \begin{describe}{mac}
-    {definst @<code> (@<streamvar> \&key @<export>) (@<arg>^*) \\ \ind
-      @[[ @<declaration>^* @! @<doc-string> @]] \\
-      @<form>^* \-
-     \nlret @<code>}
+    {definst @<code> (@<streamvar> \&key @<export>) (@<arg>^*)  \\ \ind
+      @[[ @<declaration>^* @! @<doc-string> @]]                 \\
+      @<form>^*
+     \-\nlret @<code>}
 \end{describe}
 
 \begin{describe}{mac}
     {format-compound-statement
-        (@<stream> @<child> \&optional @<morep>) \\ \ind
-      @<declaration>^* \\
+        (@<stream> @<child> \&optional @<morep>)                \\ \ind
+      @<declaration>^*                                          \\
       @<form>^*}
 \end{describe}
 
+\begin{describe}{fun}
+    {format-banner-comment @<stream> @<control> \&rest @<args>}
+\end{describe}
+
 \begin{table}
   \begin{tabular}[C]{ll>{\codeface}l}                              \hlx*{hv}
     \thd{Class name} &
@@ -994,6 +1227,8 @@ Temporary names are represented by objects which implement a simple protocol.
     @|set|      & @<var> @<expr>           & @<var> = @<expr>;  \\ \hlx{v}
     @|update|   & @<var> @<op> @<expr>     & @<var> @<op>= @<expr>;
                                                                 \\ \hlx{v}
+    @|cond|     & @<cond> @<conseq> @<alt> & @<cond> ? @<conseq> : @<alt>
+                                                                \\ \hlx{v}
     @|return|   & @<expr>                  & return @[@<expr>@];
                                                                 \\ \hlx{v}
     @|break|    & ---                      & break;             \\ \hlx{v}
@@ -1002,18 +1237,26 @@ Temporary names are represented by objects which implement a simple protocol.
     @|call|     & @<func> @|\&rest| @<args>
                                            & @<func>(@<arg>_1,
                                                      $\ldots$,
-                                                     @<arg>_n)  \\ \hlx{vhv}
+                                                     @<arg>_n)  \\ \hlx{v}
+    @|banner|   & @<control> @|\&rest| @<args>
+                                           & /* @<banner> */    \\ \hlx{vhv}
     @|block|    & @<decls> @<body>         & \{ @[@<decls>@] @<body> \}
                                                                 \\ \hlx{v}
     @|if|       & @<cond> @<conseq> @|\&optional| @<alt>
                                            & if (@<cond>) @<conseq>
                                              @[else @<alt>@]    \\ \hlx{v}
+    @|for|      & @<init> @<cond> @<update> @<body> &
+      for (@<init>; @<cond>; @<update>) @<body>                 \\ \hlx{v}
     @|while|    & @<cond> @<body>          & while (@<cond>) @<body>
                                                                 \\ \hlx{v}
     @|do-while| & @<body> @<cond>          & do @<body> while (@<cond>);
                                                                 \\ \hlx{v}
-    @|function| & @<name> @<type> @<body>  &
-      \vtop{\hbox{\strut @<type>_0 @<name>(@<type>_1 @<arg>_1, $\ldots$,
+    @|function| &
+      \vtop{\hbox{\strut @<name> @<type> @<body>}
+            \hbox{\strut \quad @|\&optional @<banner>|}
+            \hbox{\strut \quad @|\&rest| @<banner-args>}} &
+      \vtop{\hbox{\strut @[/* @<banner> */@]}
+            \hbox{\strut @<type>_0 @<name>(@<type>_1 @<arg>_1, $\ldots$,
                                            @<type>_n @<arg>_n @[, \dots@])}
             \hbox{\strut \quad @<body>}}                        \\ \hlx*{vh}
   \end{tabular}
@@ -1043,6 +1286,9 @@ Temporary names are represented by objects which implement a simple protocol.
 \begin{describe}{gf}{emit-decls @<codegen> @<decls>}
 \end{describe}
 
+\begin{describe}{fun}{emit-banner @<codegen> @<control> \&rest @<args>}
+\end{describe}
+
 \begin{describe}{gf}{codegen-push @<codegen>}
 \end{describe}
 
@@ -1068,10 +1314,10 @@ Temporary names are represented by objects which implement a simple protocol.
 \end{describe}
 
 \begin{describe}{mac}
-    {with-temporary-var (@<codegen> @<var> @<type>) \\ \ind
-      @<declaration>^* \\
-      @<form>^* \-
-     \nlret @<value>^*}
+    {with-temporary-var (@<codegen> @<var> @<type>)             \\ \ind
+      @<declaration>^*                                          \\
+      @<form>^*
+     \-\nlret @<value>^*}
 \end{describe}
 
 \begin{describe}{fun}{deliver-expr @<codegen> @<target> @<expr>}