%%%----- 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
However, because it spends a fair amount of its time dealing with C types, it
provides a number of useful operations and macros.
-The class hierarchy is shown in~\xref{fig:proto.c-types}.
+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-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:proto.c-types}
+\label{fig:codegen.c-types.classes}
\end{figure}
C type objects are immutable unless otherwise specified.
(@|eq|) type object for similar (possibly merely @|equal|) arguments. Where
not specified, clients may still not rely on receiving fresh objects.
-A convenient S-expression notation is provided by the @|c-type| macro. Use
-of this macro is merely an abbreviation for corresponding use of the various
-constructor functions, and therefore interns type objects in the same manner.
-The syntax accepted by the macro can be extended in order to support new
-classes: see @|defctype|, @|c-type-alias| and @|define-c-type-syntax|.
+A convenient S-expression notation is provided by the
+\descref{c-type}[macro]{mac}. Use of this macro is merely an abbreviation
+for corresponding use of the various constructor functions, and therefore
+interns type objects in the same manner. The syntax accepted by the macro
+can be extended in order to support new classes: see \descref{defctype}{mac},
+\descref{c-type-alias}{mac} and \descref{define-c-type-syntax}{mac}.
The descriptions of each of the various classes include descriptions of the
initargs which may be passed to @|make-instance| when constructing a new
There are two protocols for printing C types. Unfortunately they have
similar names.
\begin{itemize}
-\item The @|print-c-type| function prints a C type value using the
- S-expression notation. It is mainly useful for diagnostic purposes.
-\item The @|pprint-c-type| function prints a C type as a C-syntax
- declaration.
+\item The \descref{print-c-type}[function]{gf} prints a C type value using
+ the S-expression notation. It is mainly useful for diagnostic purposes.
+\item The \descref{pprint-c-type}[function]{gf} prints a C type as a
+ C-syntax declaration.
\end{itemize}
Neither generic function defines a default primary method; subclasses of
@|c-type| must define their own methods in order to print correctly.
+
\subsection{The C type root class} \label{sec:clang.c-types.root}
\begin{describe}{cls}{c-type ()}
The class @|c-type| is abstract.
\end{describe}
+
\subsection{C type S-expression notation} \label{sec:clang.c-types.sexp}
The S-expression representation of a type is described syntactically as a
\end{describe}
\begin{describe}{mac}
- {defctype @{ @<name> @! (@<name> @<nickname>^*) @} @<type-spec>
- @> @<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>.
The resulting type object is constructed once, at the time that the macro
expansion is evaluated; the same (@|eq|) value is used each time any
@<name> is used in a type specifier.
+
+ A variable named @|c-type-@<name>|, for the first @<name> only, is defined
+ and initialized to contain the C type object so constructed. Altering or
+ binding this name is discouraged.
+
+ If @<export-flag> is true, then the variable name, and all of the @<name>s,
+ are exported from the current package.
\end{describe}
\begin{describe}{mac}{c-type-alias @<original> @<alias>^* @> @<aliases>}
\end{describe}
\begin{describe}{mac}
- {define-c-type-syntax @<name> @<lambda-list> @<form>^* @> @<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
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}
default method.
\end{describe}
+
\subsection{Comparing C types} \label{sec:clang.c-types.cmp}
It is necessary to compare C types for equality, for example when checking
\end{describe}
\end{describe}
+
\subsection{Outputting C types} \label{sec:clang.c-types.output}
\begin{describe}{gf}{pprint-c-type @<c-type> @<stream> @<kernel>}
directly attached. If the @<kernel> function intends to provide its own
additional declarator operators, it should check the @<priority> in order
to determine whether parentheses are necessary. See also the
- @|maybe-in-parens| macro (page~\pageref{mac:maybe-in-parens}).
+ \descref{maybe-in-parens}[macro]{mac}.
The @<spacep> argument indicates whether a space needs to be printed in
order to separate the declarator from the declaration specifiers. A kernel
which contains an identifier should insert a space before the identifier
when @<spacep> is non-nil. An `empty' kernel, as found in an abstract
declarator (one that specifies no name), looks more pleasing without a
- trailing space. See also the @|c-type-space| function
- (page~\pageref{fun:c-type-space}).
+ trailing space. See also the \descref{c-type-space}[function]{fun}.
Every concrete subclass of @|c-type| is expected to provide a primary
method on this function. There is no default primary method.
\end{describe}
\begin{describe}{mac}
- {maybe-in-parens (@<stream-var> @<guard-form>) @<form>^*}
+ {maybe-in-parens (@<stream-var> @<guard-form>)
+ @<declaration>^*
+ @<form>^*}
The @<guard-form> is evaluated, and then the @<form>s are evaluated in
sequence within a pretty-printer logical block writing to the stream named
by the symbol @<stream-var>. If the @<guard-form> evaluates to nil, then
within the @<form>s.
\end{describe}
+
\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|,
qualifiers; others keywords may be used, though this isn't recommended.
Two qualifiable types are equal only if they have \emph{matching
- qualifiers}: i.e., every qualifier attached to one is also attached to
- the other: order is not significant, and neither is multiplicity.
+ qualifiers}: i.e., every qualifier attached to one is also attached to the
+ other: order is not significant, and neither is multiplicity.
The class @|qualifiable-c-type| is abstract.
\end{describe}
type will be interned.
\end{describe}
-\begin{describe}{fun}{format-qualifiers @<qualifiers>}
+\begin{describe}{fun}{format-qualifiers @<qualifiers> @> @<string>}
Returns a string containing the qualifiers listed in @<qualifiers> in C
syntax, with a space after each. In particular, if @<qualifiers> is
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}
A \emph{leaf type} is a type which is not defined in terms of another type.
and matching qualifiers.
A number of symbolic type specifiers for builtin types are predefined as
- shown in \xref{tab:proto.c-types.simple}. These are all defined as if by
+ shown in \xref{tab:codegen.c-types.simple}. These are all defined as if by
@|define-simple-c-type|, so can be used to construct qualified types.
\end{describe}
\begin{table}
- \begin{tabular}[C]{|l|l|} \hlx{hv}
- \textbf{C type} & \textbf{Specifiers} \\ \hlx{vhv}
- @|void| & @|void| \\ \hlx{vhv}
- @|char| & @|char| \\ \hlx{v}
+ \begin{tabular}[C]{ll} \hlx*{hv}
+ \thd{C type} & \thd{Specifiers} \\ \hlx{vhv}
+ @|void| & @|void| \\ \hlx{v}
+ @|_Bool| & @|bool| \\ \hlx{v}
+ @|char| & @|char| \\ \hlx{}
+ @|wchar_t| & @|wchar-t| \\ \hlx{v}
+ @|signed char| & @|signed-char|, @|schar| \\ \hlx{}
@|unsigned char| & @|unsigned-char|, @|uchar| \\ \hlx{v}
- @|signed char| & @|signed-char|, @|schar| \\ \hlx{vhv}
@|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|, \\
+ @|long-long-int|, \\ \hlx{}
& \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}
- @|va_list| & @|va-list| \\ \hlx{v}
- @|size_t| & @|size-t| \\ \hlx{v}
- @|ptrdiff_t| & @|ptrdiff-t| \\ \hlx{vh}
+ @|ullong| \\ \hlx{v}
+ @|size_t| & @|size-t| \\ \hlx{}
+ @|ptrdiff_t| & @|ptrdiff-t| \\ \hlx{v}
+ @|float| & @|float| \\ \hlx{}
+ @|double| & @|double| \\ \hlx{}
+ @|long double| & @|long-double| \\ \hlx{v}
+ @|float _Imaginary| & @|float-imaginary| \\ \hlx{}
+ @|double _Imaginary|& @|double-imaginary| \\ \hlx{}
+ @|long double _Imaginary|
+ & @|long-double-imaginary| \\ \hlx{v}
+ @|float _Complex| & @|float-complex| \\ \hlx{}
+ @|double _Complex| & @|double-complex| \\ \hlx{}
+ @|long double _Complex|
+ & @|long-double-complex| \\ \hlx{v}
+ @|va_list| & @|va-list| \\ \hlx*{vh}
\end{tabular}
\caption{Builtin symbolic type specifiers for simple C types}
- \label{tab:proto.c-types.simple}
+ \label{tab:codegen.c-types.simple}
\end{table}
\begin{describe}{fun}
\end{describe}
\begin{describe}{mac}
- {define-simple-c-type @{ @<name> @! (@<name>^*) @} @<string> @> @<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).
+
+ 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)
keywords).
\end{describe}
+
\subsection{Compound C types} \label{sec:code.c-types.compound}
Some C types are \emph{compound types}: they're defined in terms of existing
this means depends on the class of @<c-type>.
\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 compound types. The subtype of a pointer type is the type it points
-to.
+Pointers are compound types. The subtype of a pointer type is the type it
+points to.
\begin{describe}{cls}
{c-pointer-type (qualifiable-c-type) \&key :qualifiers :subtype}
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
Returns the dimensions of @<c-type>, an array type, as an immutable list.
\end{describe}
+
\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>}
+\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>.
+
+ 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.
+
+ 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}{fun}{argument-name @<argument> @> @<string>}
-\end{describe}
+\begin{describe*}
+ {\dhead{fun}{argument-name @<argument> @> @<name>}
+ \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}
+ {commentify-argument-name @<name> @> @<commentified-name>}
+ Convert the argument name @<name> so that it's suitable to declare the
+ function in a header file.
+
+ 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}{fun}{argument-type @<argument> @> @<c-type>}
+ \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}
- {commentify-argument-name @<name> @> @<commentified-name>}
+ {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}{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
+ 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
+ \begin{prog}
+ (fun @<return-type>
+ @{ (@<arg-name> @<arg-type>) @}^*
+ @[:ellipsis @! . @<form>@])
+ \end{prog}
+ 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}{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}
{c-function-arguments @<c-function-type> @> @<arguments>}
+ Return the arguments list of the @<c-function-type>.
\end{describe}
\begin{describe}{fun}
- {make-c-type @<c-type> @<arguments> @> @<c-function-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}
+
+\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}
- {commentify-argument-names @<arguments> @> @<commentified-arguments>}
+ {merge-keyword-lists @<what-function> @<lists> @> @<list>}
+ Merge a number of keyword-argument lists together and return the result.
+
+ The @<what-function> is either nil or a function designator; see below.
+
+ The @<lists> parameter is a list consisting of a number of
+ @|(@<report-function> . @<args>)| pairs: in each pair, @<report-function>
+ is either nil or a function designator, 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, a continuable
+ error will be signalled, and one of the conflicting argument types will be
+ chosen arbitrarily. The @<what-function> will be called to establish
+ information which will be reported to the user. It will be called with no
+ arguments and is expected to return two values:
+ \begin{itemize}
+ \item a file location @<floc> or other object acceptable to
+ \descref{file-location}{gf}, to be used as the location of the main
+ error; and
+ \item an object @<what>, whose printed representation should be a noun
+ phrase describing the object for which the argument lists are being
+ combined.
+ \end{itemize}
+ The phrasing of the error message is `type mismatch in @<what>'. Either,
+ or both, of @<floc> and @<what> may be nil, though this is considered poor
+ practice; if @<what-function> is nil, this is equivalent to a function
+ which returns two nil values. Following the error, the @<report-function>s
+ for the @<args> lists containing the conflicting argument objects are
+ called, in an arbitrary order, with a single argument which is the
+ offending @|argument| object; the function is expected to issue information
+ messages (see \descref{info}{fun}) to give more detail for diagnosing the
+ conflict. If a @<report-function> is nil, then nothing happens; this is
+ considered poor practice.
\end{describe}
\begin{describe}{fun}
- {commentify-function-type @<c-type> @> @<commentified-c-type>}
+ {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}
+\begin{describe}{fun}
+ {parse-c-type @<scanner>
+ @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+\begin{describe}{fun}
+ {parse-declarator @<scanner> @<base-type> \&key :kernel :abstractp
+ \nlret @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+
+\subsection{Class types} \label{sec:clang.c-types.class}
+
+\begin{describe}{cls}
+ {c-class-type (simple-c-type) \&key :class :tag :qualifiers :name}
+\end{describe}
+
+\begin{describe*}
+ {\dhead{gf}{c-type-class @<class-type> @> @<class>}
+ \dhead{gf}{setf (c-type-class @<class-type>) @<class>}}
+\end{describe*}
+
+\begin{describe}{fun}{find-class-type @<name> @> @<class-type-or-nil>}
+\end{describe}
+
+\begin{describe}{fun}
+ {make-class-type @<name> \&optional @<qualifiers> @> @<class-type>}
+\end{describe}
+
+\begin{describe}{fun}
+ {make-class-type @<name> \&optional @<qualifiers> @> @<class-type>}
+\end{describe}
+
+\begin{describe}{fun}{find-sod-class @<name> @> @<class>}
+\end{describe}
+
+\begin{describe}{fun}{record-sod-class @<class>}
+\end{describe}
+
%%%--------------------------------------------------------------------------
\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 \\
+ {}*null-pointer* & NULL \\ \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>^*) \\ \ind
+ @[[ @<declaration>^* @! @<doc-string> @]] \\
+ @<form>^*
+ \-\nlret @<code>}
+\end{describe}
+
+\begin{describe}{mac}
+ {format-compound-statement
+ (@<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} &
+ \thd{Arguments} &
+ \thd{Output format} \\ \hlx{vhv}
+ @|var| & @<name> @<type> @|\&optional| @<init>
+ & @<type> @<name> @[= @<init>@];
+ \\ \hlx{v}
+ @|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}
+ @|continue| & --- & continue; \\ \hlx{v}
+ @|expr| & @<expr> & @<expr>; \\ \hlx{v}
+ @|call| & @<func> @|\&rest| @<args>
+ & @<func>(@<arg>_1,
+ $\ldots$,
+ @<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| &
+ \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}
+ \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-decls @<codegen> @<decls>}
+\end{describe}
+
+\begin{describe}{fun}{emit-banner @<codegen> @<control> \&rest @<args>}
+\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>) \\ \ind
+ @<declaration>^* \\
+ @<form>^*
+ \-\nlret @<value>^*}
+\end{describe}
+
+\begin{describe}{fun}{deliver-expr @<codegen> @<target> @<expr>}
+\end{describe}
+
+\begin{describe}{fun}
+ {deliver-call @<codegen> @<target> @<func> \&rest @<args>}
+\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}
+
+%%%--------------------------------------------------------------------------
+\section{Literal C code fragments} \label{sec:clang.fragment}
+
+\begin{describe}{cls}{c-fragment () \&key :location :text}
+\end{describe}
+
+\begin{describe}{gf}{c-fragment-text @<fragment> @> @<string>}
+\end{describe}
+
+\begin{describe}{fun}
+ {scan-c-fragment @<scanner> @<end-chars>
+ @> @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
+\begin{describe}{fun}
+ {parse-delimited-fragment @<scanner> @<begin> @<end> \&key :keep-end
+ \nlret @<result> @<success-flag> @<consumed-flag>}
+\end{describe}
+
%%%----- That's all, folks --------------------------------------------------
%%% Local variables: