X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/1f7d590d9c7b87442c8d8b6424ed4f769d377692..944bf9362ff51217b1617f85126d26e821b8aa91:/doc/clang.tex diff --git a/doc/clang.tex b/doc/clang.tex index c26ece5..aebc94d 100644 --- a/doc/clang.tex +++ b/doc/clang.tex @@ -7,7 +7,7 @@ %%%----- 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 @@ -34,24 +34,26 @@ The Sod translator represents C types in a fairly simple and direct way. 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. @@ -65,11 +67,12 @@ specified to return interned objects: programs may rely on receiving the same (@|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{mac}{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 \descref{mac}{defctype}, +\descref{mac}{c-type-alias} and \descref{mac}{define-c-type-syntax}. The descriptions of each of the various classes include descriptions of the initargs which may be passed to @|make-instance| when constructing a new @@ -80,14 +83,18 @@ syntax are strongly recommended over direct use of @|make-instance|. 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{gf}{print-c-type}[function] prints a C type value using + the S-expression notation. It is mainly useful for diagnostic purposes. +\item The \descref{gf}{pprint-c-type}[function] 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. +\begin{describe}{fun}{c-name-case @ @> @} +\end{describe} + + \subsection{The C type root class} \label{sec:clang.c-types.root} \begin{describe}{cls}{c-type ()} @@ -100,6 +107,7 @@ Neither generic function defines a default primary method; subclasses of 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 @@ -120,8 +128,9 @@ type specifier. Type specifiers fit into two syntactic categories. \end{describe} \begin{describe}{mac} - {defctype @{ @ @! (@ @^*) @} @ - @> @} + {defctype \=@{ @ @! (@^+) @} @ \+\\ + @[[ @|:export| @ @]]^* + \-\nlret @} Defines a new symbolic type specifier @; if a list of @s is given, then all are defined in the same way. The type constructed by using any of the @s is as described by the type specifier @. @@ -129,6 +138,13 @@ type specifier. Type specifiers fit into two syntactic categories. 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 @ is used in a type specifier. + + A variable named @|c-type-@|, for the first @ only, is defined + and initialized to contain the C type object so constructed. Altering or + binding this name is discouraged. + + If @ is true, then the variable name, and all of the @s, + are exported from the current package. \end{describe} \begin{describe}{mac}{c-type-alias @ @^* @> @} @@ -138,7 +154,10 @@ type specifier. Type specifiers fit into two syntactic categories. \end{describe} \begin{describe}{mac} - {define-c-type-syntax @ @ @
^* @> @} + {define-c-type-syntax @ @ \\ \ind + @[[ @^* @! @ @]] \\ + @^* + \-\nlret @} Defines the symbol @ as a new type operator. When a list of the form @|(@ @^*)| is used as a type specifier, the @s are bound to fresh variables according to @ (a destructuring @@ -150,8 +169,16 @@ type specifier. Type specifiers fit into two syntactic categories. type specifiers among its arguments. \end{describe} -\begin{describe}{fun}{expand-c-type-spec @ @> @} +\begin{describe}{gf}{expand-c-type-spec @ @> @} Returns the Lisp form that @|(c-type @)| would expand into. + + If @ is a list, then \descref{gf}{expand-c-type-form} is + invoked. +\end{describe} + +\begin{describe}{gf}{expand-c-type-form @ @ @> @} + Returns the Lisp form that @|(c-type (@ . @))| would expand + into. \end{describe} \begin{describe}{gf} @@ -166,6 +193,7 @@ type specifier. Type specifiers fit into two syntactic categories. 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 @@ -183,12 +211,12 @@ argument lists for methods. This is done by @|c-type-equal-p|. The generic function @|c-type-equal-p| uses the @|and| method combination. - \begin{describe}{meth}{c-type-equal-p @_1 @_2} + \begin{describe}{meth}{t,t}{c-type-equal-p @_1 @_2} A default primary method for @|c-type-equal-p| is defined. It simply returns @|nil|. This way, methods can specialize on both arguments without fear that a call will fail because no methods are applicable. \end{describe} - \begin{describe}{ar-meth}{c-type-equal-p @_1 @_2} + \begin{describe}{ar-meth}{}{c-type-equal-p @_1 @_2} A default around-method for @|c-type-equal-p| is defined. It returns true if @_1 and @_2 are @|eql|; otherwise it delegates to the primary methods. Since several common kinds of C types are interned, @@ -196,6 +224,7 @@ argument lists for methods. This is done by @|c-type-equal-p|. \end{describe} \end{describe} + \subsection{Outputting C types} \label{sec:clang.c-types.output} \begin{describe}{gf}{pprint-c-type @ @ @} @@ -232,20 +261,19 @@ argument lists for methods. This is done by @|c-type-equal-p|. directly attached. If the @ function intends to provide its own additional declarator operators, it should check the @ in order to determine whether parentheses are necessary. See also the - @|maybe-in-parens| macro (page~\pageref{mac:maybe-in-parens}). + \descref{mac}{maybe-in-parens}[macro]. The @ 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 @ 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{fun}{c-type-space}[function]. Every concrete subclass of @|c-type| is expected to provide a primary method on this function. There is no default primary method. - \begin{describe}{ar-meth}{pprint-c-type @ @ @} + \begin{describe}{ar-meth}{}{pprint-c-type @ @ @} A default around method is defined on @|pprint-c-type| which `canonifies' non-function @ arguments. In particular: \begin{itemize} @@ -265,7 +293,9 @@ argument lists for methods. This is done by @|c-type-equal-p|. \end{describe} \begin{describe}{mac} - {maybe-in-parens (@ @) @^*} + {maybe-in-parens (@ @) + @^* + @^*} The @ is evaluated, and then the @s are evaluated in sequence within a pretty-printer logical block writing to the stream named by the symbol @. If the @ evaluates to nil, then @@ -277,9 +307,33 @@ argument lists for methods. This is done by @|c-type-equal-p|. within the @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{C name} & \thd{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{gf}{c-qualifier-keyword}. + \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|, @@ -290,18 +344,22 @@ argument lists for methods. This is done by @|c-type-equal-p|. 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} +\begin{describe}{fun} + {canonify-qualifiers @ @> @} +\end{describe} + \begin{describe}{gf}{c-type-qualifiers @ @> @} Returns the qualifiers of the @|qualifiable-c-type| instance @ as an immutable list. \end{describe} -\begin{describe}{fun}{qualify-type @ @ @> @} +\begin{describe}{fun}{qualify-c-type @ @ @> @} The argument @ must be an instance of @|qualifiable-c-type|, currently bearing no qualifiers, and @ a list of qualifier keywords. The result is a C type object like @ except that it @@ -311,12 +369,121 @@ argument lists for methods. This is done by @|c-type-equal-p|. type will be interned. \end{describe} -\begin{describe}{fun}{format-qualifiers @} +\begin{describe}{fun}{format-qualifiers @ @> @} Returns a string containing the qualifiers listed in @ in C syntax, with a space after each. In particular, if @ is non-null then the final character of the returned string will be a space. \end{describe} +\begin{describe}{gf}{c-qualifier-keyword @ @> @} + Return, as a string, the C keyword corresponding to the Lisp @. + + 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}{keyword} + {c-qualifier-keyword @ @> @} + Returns the @'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 @ @> @} + Return the @'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 @ is the actual + type, and may be any C type; the @ are a list of + storage-specifier objects. + + The type specifier @|(specs @ @^*)| wraps the + @ in a @|c-storage-specifiers-type|, carrying the @s, + which are a list of storage specifiers in S-expression notation. +\end{describe} + +\begin{describe}{fun}{c-type-specifiers @ @> @} + Returns the list of type specifiers attached to the @ object, which + must be a @|c-storage-specifiers-type|. +\end{describe} + +\begin{describe}{mac} + {define-c-storage-specifier-syntax @ @ \\ \ind + @[[ @^* @! @ @]] \\ + @^* \- + \nlret @} + + Defines the symbol @ as a new storage-specifier operator. When a + list of the form @|(@ @^*)| is used as a storage specifier, + the @s are bound to fresh variables according to the + @ (a destructuring lambda-list) and the @s evaluated in + order in the resulting lexical environment as an implicit @. The + value should be a Lisp form which will evaluate to the storage-specifier + object described by the arguments. + + The @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 @ @> @} + Returns the Lisp form that @ expands to within @|(c-type (specs + @ @))|. + + If @ is a list, then \descref{gf}{expand-c-storage-specifier-form} is + invoked. +\end{describe} + +\begin{describe}{gf}{expand-c-storage-specifier-form @ @> @} + Returns the Lisp form that @|(@ . @)| expands to within + @|(c-type (specs @ (@ . @)))|. +\end{describe} + +\begin{describe}{gf}{pprint-c-storage-specifier @ @} +\end{describe} + +\begin{describe}{gf} + {print-c-storage-specifier @ @ + \&optional @ @} +\end{describe} + +\begin{describe}{fun}{wrap-c-type @ @ @> @} + Apply @ to the underlying C type of @ to create a new + `wrapped' type, and attach the storage specifiers of @ to the + wrapped type. + + If @ is \emph{not} a @|c-storage-specifiers-type|, then return + @|(funcall @ @)|. Otherwise, return a new + @|c-storage-specifiers-type|, with the same specifiers, but whose subtype + is the result of applying @ to the subtype of the original + @. +\end{describe} + +\begin{describe}{cls}{alignas-storage-specifier () \&key :alignment} + The class of @|_Alignas| storage specifiers; an instance denotes the + specifier @|_Alignas(@)|. The @ parameter may be any + printable object, but is usually a string or C fragment. + + The storage specifier form @|(alignas @)| returns a storage + specifier @|_Alignas(@)|, where @ 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. @@ -341,44 +508,77 @@ In Sod, the leaf types are Two simple type objects are equal if and only if they have @|string=| names and matching qualifiers. + \def\x#1{\desclabel{const}{c-type-#1}} + \x{bool} \x{char} \x{wchar-t} \x{signed-char} \x{unsigned-char} \x{short} + \x{unsigned-short} \x{int} \x{unsigned} \x{long} \x{unsigned-long} + \x{long-long} \x{unsigned-long-long} \x{size-t} \x{ptrdiff-t} \x{float} + \x{double} \x{long-double} \x{float-imaginary} \x{double-imaginary} + \x{long-double-imaginary} \x{float-complex} \x{double-complex} + \x{long-double-complex} \x{va-list} \x{void} + \crossproduct\x{{{int}{uint}}{{}{-least}{-fast}}{{8}{16}{32}{64}}{{-t}}} + \crossproduct\x{{{int}{uint}}{{ptr}{max}}{{-t}}} + 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} + @|int$n$_t| & @|int$n$-t| + (for $n \in \{ @|8|, @|16|, @|32|, @|64| \}$) + \\ \hlx{} + @|uint$n$_t| & @|uint$n$-t| \\ \hlx{} + @|int_least$n$_t| & @|int_least$n$-t| \\ \hlx{} + @|uint_least$n$_t| & @|uint_least$n$-t| \\ \hlx{} + @|int_fast$n$_t| & @|int_fast$n$-t| \\ \hlx{} + @|uint_fast$n$_t| & @|uint_fast$n$-t| \\ \hlx{v} + @|intptr_t| & @|intptr-t| \\ \hlx{} + @|uintptr_t| & @|uintptr-t| \\ \hlx{} + @|intmax_t| & @|intmax-t| \\ \hlx{} + @|uintmax_t| & @|uintmax-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} @@ -394,13 +594,33 @@ In Sod, the leaf types are \end{describe} \begin{describe}{mac} - {define-simple-c-type @{ @ @! (@^*) @} @ @> @} + {define-simple-c-type + \=@{ @ @! (@^+) @} + @{ @ @! (@^*) @} \+\\ + @[[ @|:export| @ @]] + \-\nlret @} Define type specifiers for a new simple C type. Each symbol @ is defined as a symbolic type specifier for the (unique interned) simple C - type whose name is the value of @. Further, each @ is - defined to be a type operator: the type specifier @|(@ + type whose name is the value of (the first) @. Further, each + @ is defined to be a type operator: the type specifier @|(@ @^*)| evaluates to the (unique interned) simple C type whose - name is @ and which has the @ (which are evaluated). + name is (the first) @ and which has the @ (which are + evaluated). + + Each of the @s is associated with the resulting type for retrieval + by \descref{fun}{find-simple-c-type}. Furthermore, a variable + @|c-type-@| is defined, for the first @ only, and initialized + with the newly constructed C type object. + + If @ is true, then the @|c-type-@| variable name, and + all of the @s, are exported from the current package. +\end{describe} + +\begin{describe}{fun} + {find-simple-c-type @ @> @{ @ @! @|nil| @}} + If @ is the name of a simple C type, as established by the + \descref{mac}{define-simple-c-type}[macro], then return the corresponding + @|simple-c-type| object; otherwise, return @|nil|. \end{describe} \begin{describe}{cls}{tagged-c-type (qualifiable-c-type) @@ -419,6 +639,14 @@ In Sod, the leaf types are structs and unions. \end{boxy} +\begin{describe}{gf}{c-type-tag @ @> @} +\end{describe} + +\begin{describe}{fun} + {make-c-tagged-type @ @ \&optional @ + @> @} +\end{describe} + \begin{describe}{gf}{c-tagged-type-kind @ @> @} Returns a keyword classifying the tagged @: one of @|:enum|, @|:struct| or @|:union|. User-defined subclasses of @|tagged-c-type| @@ -445,6 +673,7 @@ In Sod, the leaf types are interned) enumerated type with the given @ and @s (all evaluated). \end{describe} + \begin{describe}{fun} {make-enum-type @ \&optional @ @> @} Return the (unique interned) C type object for the enumerated C type whose @@ -460,6 +689,7 @@ In Sod, the leaf types are interned) structured type with the given @ and @s (all evaluated). \end{describe} + \begin{describe}{fun} {make-struct-type @ \&optional @ @> @} Return the (unique interned) C type object for the structured C type whose @@ -483,6 +713,7 @@ In Sod, the leaf types are 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 @@ -494,10 +725,43 @@ protocol. this means depends on the class of @. \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(@)|. + + The @ 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 @ @^*)| returns a type + qualified atomic @, where @ is the type specified by + @ and the @s are qualifier keywords (which are + evaluated). +\end{describe} + +\begin{describe}{fun} + {make-atomic-type @ \&optional @ @> @} + Return an object describing the type qualified atomic @. If + @ 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} @@ -513,7 +777,7 @@ to. 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} @@ -521,15 +785,16 @@ to. \begin{describe}{fun} {make-pointer-type @ \&optional @ @> @} - Return an object describing the type of qualified pointers to @. + Return an object describing the type qualified pointer to @. If @ 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 @ are a list @@ -567,53 +832,625 @@ array element type. Returns the dimensions of @, 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 @ @> @} + Decide whether @ is an @ object: if so, return non-nil; if + not return nil. \end{describe} -\begin{describe}{fun}{make-argument @ @ @> @} +\begin{describe}{fun} + {make-argument @ @ \&optional @ @> @} + Construct and a return a new @ object. The argument has type + @, which must be a @|c-type| object, and is named @. + + The @ 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 @ is not nil, then the + @'s print representation, with @|*print-escape*| nil, is used as the + argument name. + + A @ may be supplied. If the argument is used in a + keyword-argument list (e.g., in a \descref{cls}{c-keyword-function-type} + [object]), and the @ 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 @ @> @} -\end{describe} +\begin{describe*} + {\dhead{fun}{argument-name @ @> @} + \dhead{fun}{argument-type @ @> @} + \dhead{fun}{argument-default @ @> @}} + Accessor functions for @|argument| objects. They return the appropriate + component of the object, as set by to @|make-argument|. The @ is + nil if no default was provided to @|make-argument|. +\end{describe*} -\begin{describe}{fun}{argument-type @ @> @} +\begin{describe}{gf} + {commentify-argument-name @ @> @} + Convert the argument 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}{meth}{null} + {commentify-argument-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}{t} + {commentify-argument-name (@ t) @> @} + Returns the print form of @ wrapped in a C comment, as + @`/*@*/'. + \end{describe} \end{describe} \begin{describe}{fun} - {commentify-argument-name @ @> @} + {commentify-argument-names @ @> @} + Convert the @ list so that it's suitable for use in a header + file. + + The @ 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 @ and returns @. + + The @ 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 @ 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 @ + @{ (@ @) @}^* + @[:ellipsis @! . @@]) + \end{prog} + constructs a function type. The function has the subtype @. + 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 + @/@ 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 a 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 @, and keyword arguments from the @ + list, and returns @. Either or both of the @ and + @ 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 @ and @ + 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 \=@ + @{ (@ @) @}^* \+\\ + @{ \=:keys @{ (@ @ @[@@]) @}^* + @[. @@] @! \+\\ + . @ @} + \end{prog} + where either the symbol @|:keys| appears literally in the specifier, or the + @ 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{cls}{c-function-type} for how a trailing + @ is handled. + + The list of @s and @s describes the positional + arguments. The list of @s, @s and @s + describes the keyword arguments. +\end{describe} + +\begin{describe}{fun} + {make-function-type @ @ @> @} + Construct and return a new function type, returning @ and + accepting the @. + + If the @ list contains a @|:keys| marker, then a + \descref{cls}{c-keyword-function-type}[object] 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 @ @ @ + \nlret @} + Construct and return a new keyword-function type, returning @ and + accepting the @ and @. +\end{describe} + +\begin{describe}{gf} {c-function-arguments @ @> @} + Return the (non-keyword) argument list of the @. +\end{describe} + +\begin{describe}{gf} + {c-function-keywords @ @> @} + Return the keyword-argument list of the @. \end{describe} \begin{describe}{fun} - {make-c-type @ @ @> @} + {commentify-function-type @ @> @} + Return a commentified version of the @. + + 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 @ @> @} + If the @ 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{var}{*sod-ap*}[variable]. 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 @ @> @} + {merge-keyword-lists @ @ @> @} + Merge a number of keyword-argument lists together and return the result. + + The @ is either nil or a function designator; see below. + + The @ parameter is a list consisting of a number of + @|(@ . @)| pairs: in each pair, @ + is either nil or a function designator, and @ is a list of + \descref{cls}{argument} objects. + + The resulting list contains exactly one argument for each distinct argument + name appearing in the input @; this argument will contain the + default value from the earliest occurrence in the input @ 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 @ 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 @ or other object acceptable to + \descref{gf}{file-location}, to be used as the location of the main + error; and + \item an object @, 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 @'. Either, + or both, of @ and @ may be nil, though this is considered poor + practice; if @ is nil, this is equivalent to a function + which returns two nil values. Following the error, the @s + for the @ 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{fun}{info}) to give more detail for diagnosing the + conflict. If a @ is nil, then nothing happens; this is + considered poor practice. \end{describe} \begin{describe}{fun} - {commentify-function-type @ @> @} + {pprint-c-function-type @ @ + @ @} + Provides the top-level structure for printing C function types. + + Output is written to @ to describe a function type returning + @, whose declarator kernel (containing the name, and any + further type operands) will be printed by @, and whose + arguments, if any, will be printed by @. + + The @ function is a standard kernel-printing function + following the \descref{gf}{pprint-c-type}[protocol]. + + The @ function is given a single argument, which is the + @ to print on. It should not print the surrounding parentheses. + + The output written to @ looks approximately like + \begin{prog} + @ @(@) + \end{prog} \end{describe} +\begin{describe}{fun}{pprint-argument-list @ @ @> @} + Print an argument list to @. + + The @ is a list of \descref{cls}{argument}[objects], 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 @ + @> @ @ @} +\end{describe} + +\begin{describe}{fun} + {parse-declarator @ @ \&key :kernel :abstractp + \nlret @ @ @} +\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 @ @> @} + \dhead{gf}{setf (c-type-class @) @}} +\end{describe*} + +\begin{describe}{fun}{find-class-type @ @> @} +\end{describe} + +\begin{describe}{fun} + {make-class-type @ \&optional @ @> @} +\end{describe} + +\begin{describe}{fun}{find-sod-class @ @> @} +\end{describe} + +\begin{describe}{fun}{record-sod-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 @ @} +\end{describe} + +\begin{describe*} + {\dhead{gf}{var-in-use-p @ @> @} + \dhead{gf}{setf (var-in-use-p @) @}} +\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}{gf}{temp-tag @ @> @} +\end{describe} + +\begin{describe}{meth}{temporary-name} + {commentify-argument-name (@ temporary-name) @> nil} +\end{describe} + +\begin{table} + \begin{tabular}[C]{*2{>{\codeface}l}} \hlx*{hv} + \thd{Class} & \thd{Name format} \\ \hlx{vhv} + temporary-name & @ \\ + temporary-argument & sod__a@ \\ + temporary-function & sod__f@ \\ + temporary-variable & sod__v@ \\ \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 @> @} +\end{describe} + +\begin{describe}{cls} + {temporary-variable (temporary-name) \&key :tag :in-use-p} +\end{describe} + +\subsubsection{Well-known `temporary' names} + +\begin{table} + \def\x#1{\desclabel{var}{#1}} + \x{*sod-ap*} \x{*sod-master-ap*} \x{*null-pointer*} + \begin{tabular}[C]{*2{>{\codeface}l}} \hlx*{hv} + \thd{Variable} & \thd{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 @} +\end{describe} + +\begin{describe}{mac} + {definst @ (@ \&key @) (@^*) \\ \ind + @[[ @^* @! @ @]] \\ + @^* + \-\nlret @} +\end{describe} + +\begin{describe}{mac} + {format-compound-statement + (@ @ \&optional @) \\ \ind + @^* \\ + @^*} +\end{describe} + +\begin{describe}{fun} + {format-banner-comment @ @ \&rest @} +\end{describe} + +\begin{table} + \begin{tabular}[C]{ll>{\codeface}l} \hlx*{hv} + \thd{Class name} & + \thd{Arguments} & + \thd{Output format}\\ \hlx{vhv} + @|var| & @ @ @|\&optional| @ + & @ @ @[= @@]; + \\ \hlx{v} + @|set| & @ @ & @ = @; \\ \hlx{v} + @|update| & @ @ @ & @ @= @; + \\ \hlx{v} + @|cond| & @ @ @ & @ ? @ : @ + \\ \hlx{v} + @|return| & @ & return @[@@]; + \\ \hlx{v} + @|break| & --- & break; \\ \hlx{v} + @|continue| & --- & continue; \\ \hlx{v} + @|expr| & @ & @; \\ \hlx{v} + @|call| & @ @|\&rest| @ + & @(@_1, + $\ldots$, + @_n) \\ \hlx{v} + @|banner| & @ @|\&rest| @ + & /* @ */ \\ \hlx{vhv} + @|block| & @ @ & \{ @[@@] @ \} + \\ \hlx{v} + @|if| & @ @ @|\&optional| @ + & if (@) @ + @[else @@] \\ \hlx{v} + @|for| & @ @ @ @ & + for (@; @; @) @ \\ \hlx{v} + @|while| & @ @ & while (@) @ + \\ \hlx{v} + @|do-while| & @ @ & do @ while (@); + \\ \hlx{v} + @|function| & + \vtop{\hbox{\strut @ @ @} + \hbox{\strut \quad @|\&optional @|} + \hbox{\strut \quad @|\&rest| @}} & + \vtop{\hbox{\strut @[/* @ */@]} + \hbox{\strut @_0 @(@_1 @_1, $\ldots$, + @_n @_n @[, \dots@])} + \hbox{\strut \quad @}} \\ \hlx*{vh} + \end{tabular} + \caption{Instruction classes} + \label{tab:codegen.codegen.insts} +\end{table} + +\begin{describe*} + {\dhead*{cls}{@-inst (inst) \&key \dots} + \dhead*{fn}{make-@-inst \dots} + \dhead*{gf}{inst-@ @ @> @}} + \def\instclass#1#2#3{% + #1{cls}{#3-inst}[#2]% + #1{fun}{make-#3-inst}[#2]% + } + \def\instslot#1#2#3{#1{gf}{inst-#3}[#2]} + \def\makelabels#1#2{% + \def\x{\instclass{#1}{#2}} + \x{var} \x{set} \x{update} \x{cond} \x{return} \x{break} \x{continue} + \x{expr} \x{call} \x{banner} \x{block} \x{if} \x{for} \x{while} + \x{do-while} \x{function} + \def\x{\instslot{#1}{#2}} + \x{name} \x{type} \x{init} \x{var} \x{expr} \x{op} \x{cond} \x{conseq} + \x{alt} \x{func} \x{args} \x{control} \x{decls} \x{body} \x{update} + \x{banner} \x{banner-args} + } + \makelabels{\desclabel}{|(} + + Sod provides a number of built-in instruction types generated by + \descref{mac}{definst}: see \xref{tab:codegen.codegen.insts}. + + \makelabels{\descindex}{|)} +\end{describe*} + + +\subsection{Code generation} \label{sec:clang.codegen.codegen} + +\begin{describe}{gf}{codegen-functions @ @> @} +\end{describe} + +\begin{describe}{gf} + {ensure-var @ @ @ \&optional @} +\end{describe} + +\begin{describe}{gf}{emit-inst @ @} +\end{describe} + +\begin{describe}{gf}{emit-insts @ @} +\end{describe} + +\begin{describe}{gf}{emit-decl @ @} +\end{describe} + +\begin{describe}{gf}{emit-decls @ @} +\end{describe} + +\begin{describe}{fun}{emit-banner @ @ \&rest @} +\end{describe} + +\begin{describe}{gf}{codegen-push @} +\end{describe} + +\begin{describe}{gf}{codegen-pop @ @> @ @} +\end{describe} + +\begin{describe}{gf}{codegen-pop-block @ @> @} +\end{describe} + +\begin{describe}{gf} + {codegen-pop-function @ @ @ @> @} +\end{describe} + +\begin{describe}{gf}{codegen-add-function @ @} +\end{describe} + +\begin{describe}{fun} + {codegen-build-function @ @ @ @ @ + @> @} +\end{describe} + +\begin{describe}{gf}{temporary-var @ @ @> @} +\end{describe} + +\begin{describe}{mac} + {with-temporary-var (@ @ @) \\ \ind + @^* \\ + @^* + \-\nlret @^*} +\end{describe} + +\begin{describe}{fun}{deliver-expr @ @ @} +\end{describe} + +\begin{describe}{fun} + {deliver-call @ @ @ \&rest @} +\end{describe} + +\begin{describe}{fun}{convert-stmts @ @ @ @} +\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*} + {\dhead{gf}{c-fragment-text @ @> @} + \dhead{meth}{c-fragment} + {file-location (@ c-fragment) @> @}} +\end{describe*} + +\begin{describe}{fun} + {scan-c-fragment @ @ + @> @ @ @} +\end{describe} + +\begin{describe}{fun} + {parse-delimited-fragment @ @ @ \&key :keep-end + \nlret @ @ @} +\end{describe} + %%%----- That's all, folks -------------------------------------------------- %%% Local variables: