X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/0f2c2a9d564769dc571ea5636aee67a3cd679d6a..b7fcf94152e4c1938fbca55d13b1e6a64b694bd6:/doc/clang.tex diff --git a/doc/clang.tex b/doc/clang.tex index 22222e2..5a22984 100644 --- a/doc/clang.tex +++ b/doc/clang.tex @@ -46,6 +46,7 @@ The class hierarchy is shown in~\xref{fig:codegen.c-types.classes}. @|c-struct-type| \\ @|c-union-type| \\ @|c-enum-type| \- \\ + @|c-atomic-type| \\ @|c-pointer-type| \- \\ @|c-array-type| \\ @|c-function-type| @@ -65,11 +66,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{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 @@ -80,14 +82,15 @@ 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{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 ()} @@ -100,6 +103,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 +124,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 +134,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 @ @^* @> @} @@ -153,8 +165,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{expand-c-type-form}{fun} 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} @@ -169,6 +189,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 @@ -199,6 +220,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 @ @ @} @@ -235,15 +257,14 @@ 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{maybe-in-parens}[macro]{mac}. 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{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. @@ -282,9 +303,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{\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|, @@ -295,8 +340,8 @@ 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} @@ -316,12 +361,111 @@ 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}{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{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} + + \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. @@ -410,13 +554,21 @@ 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 @|(@ @^*)| evaluates to the (unique interned) simple C type whose name is @ and which has the @ (which are evaluated). + + 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}{cls}{tagged-c-type (qualifiable-c-type) @@ -499,6 +651,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 @@ -510,10 +663,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} @@ -542,6 +728,7 @@ to. interned also. \end{describe} + \subsection{Array types} \label{sec:clang.c-types.array} Arrays implement the compound-type protocol. The subtype of an array type is @@ -583,6 +770,7 @@ the 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 @@ -609,8 +797,8 @@ function type is the type of the function's return value. \end{describe} \begin{describe*} - {\dhead{fun}{argument-name @ @> @} - \dhead{fun}{argument-type @ @> @}} + {\dhead{fun}{argument-name @ @> @} + \dhead{fun}{argument-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|. @@ -668,14 +856,19 @@ function type is the type of the function's return value. in the same order, and either both or neither argument list ends with @|:ellipsis|; argument names are not compared. - The type specifier @|(fun @ @{ (@ @) @}^* - @[:ellipsis @! . @ @])| 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 + 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; @@ -725,6 +918,7 @@ function type is the type of the function's return value. @|commentify-argument-names| to the argument list of the given type. \end{describe} + \subsection{Parsing C types} \label{sec:clang.c-types.parsing} \begin{describe}{fun} @@ -737,6 +931,7 @@ function type is the type of the function's return value. \nlret @ @ @} \end{describe} + \subsection{Class types} \label{sec:clang.c-types.class} \begin{describe}{cls} @@ -771,6 +966,7 @@ function type is the type of the function's return value. 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 @@ -838,12 +1034,14 @@ Temporary names are represented by objects which implement a simple protocol. \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 \\ \hlx*{vh} + {}*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} @@ -871,7 +1069,8 @@ Temporary names are represented by objects which implement a simple protocol. \thd{Class name} & \thd{Arguments} & \thd{Output format} \\ \hlx{vhv} - @|var| & @ @ @ & @ @ @[= @@]; + @|var| & @ @ @|\&optional| @ + & @ @ @[= @@]; \\ \hlx{v} @|set| & @ @ & @ = @; \\ \hlx{v} @|update| & @ @ @ & @ @= @; @@ -881,31 +1080,29 @@ Temporary names are represented by objects which implement a simple protocol. @|break| & --- & break; \\ \hlx{v} @|continue| & --- & continue; \\ \hlx{v} @|expr| & @ & @; \\ \hlx{v} - @|call| & @ @ & @(@_1, + @|call| & @ @|\&rest| @ + & @(@_1, $\ldots$, - @_n) \\ \hlx{v} - @|va-start| & @ @ & va_start(@, @); - \\ \hlx{v} - @|va-copy| & @ @ & va_copy(@, @); - \\ \hlx{v} - @|va-end| & @ & va_end(@); \\ \hlx{vhv} + @_n) \\ \hlx{vhv} @|block| & @ @ & \{ @[@@] @ \} \\ \hlx{v} - @|if| & @ @ @ & if (@) @ + @|if| & @ @ @|\&optional| @ + & if (@) @ @[else @@] \\ \hlx{v} @|while| & @ @ & while (@) @ \\ \hlx{v} @|do-while| & @ @ & do @ while (@); \\ \hlx{v} @|function| & @ @ @ & - @_0 @(@_1 @_1, $\ldots$, - @_n @_n @[, \dots@]) - @ \\ \hlx*{vh} + \vtop{\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} + \subsection{Code generation} \label{sec:clang.codegen.codegen} \begin{describe}{gf}{codegen-functions @ @> @} @@ -924,7 +1121,7 @@ Temporary names are represented by objects which implement a simple protocol. \begin{describe}{gf}{emit-decl @ @} \end{describe} -\begin{describe}{gf}{emit-declss @ @} +\begin{describe}{gf}{emit-decls @ @} \end{describe} \begin{describe}{gf}{codegen-push @} @@ -961,6 +1158,10 @@ Temporary names are represented by objects which implement a simple protocol. \begin{describe}{fun}{deliver-expr @ @ @} \end{describe} +\begin{describe}{fun} + {deliver-call @ @ @ \&rest @} +\end{describe} + \begin{describe}{fun}{convert-stmts @ @ @ @} \end{describe}