X-Git-Url: https://git.distorted.org.uk/~mdw/sod/blobdiff_plain/e07fb83cca55921ef64b73880276277fee9107a8..f458e64e36509fa8c204f1dbcafff1d3dc059619:/doc/clang.tex diff --git a/doc/clang.tex b/doc/clang.tex index b94ef95..b273a2c 100644 --- a/doc/clang.tex +++ b/doc/clang.tex @@ -38,17 +38,19 @@ The class hierarchy is shown in~\xref{fig:codegen.c-types.classes}. \begin{figure} \centering \parbox{10pt}{\begin{tabbing} - @|c-type| \\ \ind - @|qualifiable-c-type| \\ \ind - @|simple-c-type| \\ \ind - @|c-class-type| \- \\ - @|tagged-c-type| \\ \ind - @|c-struct-type| \\ - @|c-union-type| \\ - @|c-enum-type| \- \\ - @|c-pointer-type| \- \\ - @|c-array-type| \\ - @|c-function-type| + @|c-type| \\ \ind + @|qualifiable-c-type| \\ \ind + @|simple-c-type| \\ \ind + @|c-class-type| \-\\ + @|tagged-c-type| \\ \ind + @|c-struct-type| \\ + @|c-union-type| \\ + @|c-enum-type| \-\\ + @|c-atomic-type| \\ + @|c-pointer-type| \-\\ + @|c-array-type| \\ + @|c-function-type| \\ \ind + @|c-keyword-function-type| \- \end{tabbing}} \caption{Classes representing C types} \label{fig:codegen.c-types.classes} @@ -123,9 +125,9 @@ type specifier. Type specifiers fit into two syntactic categories. \end{describe} \begin{describe}{mac} - {defctype \=@{ @ @! (@^+) @} @ \+ \\ - @[[ @|:export| @ @]]^* \- - \nlret @} + {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 @. @@ -149,10 +151,10 @@ type specifier. Type specifiers fit into two syntactic categories. \end{describe} \begin{describe}{mac} - {define-c-type-syntax @ @ \\ \ind - @[[ @^* @! @ @]] \\ - @
^* \- - \nlret @} + {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 @@ -167,12 +169,12 @@ type specifier. Type specifiers fit into two syntactic categories. \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 + If @ is a list, then \descref{expand-c-type-form}{gf} is invoked. \end{describe} \begin{describe}{gf}{expand-c-type-form @ @ @> @} - Returns the Lisp form that @|(c-type (@ . @)| would expand + Returns the Lisp form that @|(c-type (@ . @))| would expand into. \end{describe} @@ -306,6 +308,29 @@ argument lists for methods. This is done by @|c-type-equal-p|. \subsection{Type qualifiers and qualifiable types} \label{sec:clang.ctypes.qual} +Qualifiers -- @|const|, @|volatile|, and so on -- are represented as lists of +keywords attached to types. Not all C types can carry qualifiers: notably, +function and array types cannot be qualified. + +For the most part, the C qualifier keywords correspond to like-named Lisp +keywords, only the Lisp keyword names are in uppercase. The correspondence +is shown in \xref{tab:clang.ctypes.qual}. + +\begin{table} + \begin{tabular}[C]{*2{>{\codeface}l}l} \hlx*{hv} + \thd{\textbf{C name}} & \thd{\textbf{Lisp name}} \\ \hlx{vhv} + _Atomic & :atomic \\ + const & :const \\ + restrict & :restrict \\ + volatile & :volatile \\ \hlx*{vh} + \end{tabular} + \caption{C and Lisp qualifier names} \label{tab:clang.ctypes.qual} +\end{table} + +The default behaviour, on output, is to convert keywords to lowercase and +hope for the best: special cases can be dealt with by adding appropriate +methods to \descref{c-qualifier-keyword}{gf}. + \begin{describe}{cls}{qualifiable-c-type (c-type) \&key :qualifiers} The class @|qualifiable-c-type| describes C types which can bear `qualifiers' (\Cplusplus\ calls them `cv-qualifiers'): @|const|, @@ -343,6 +368,113 @@ argument lists for methods. This is done by @|c-type-equal-p|. non-null then the final character of the returned string will be a space. \end{describe} +\begin{describe}{gf}{c-qualifier-keyword @ @> @} + 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} + +\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} @@ -432,23 +564,35 @@ In Sod, the leaf types are \end{describe} \begin{describe}{mac} - {define-simple-c-type \=@{ @ @! (@^+) @} @ \+ \\ - @[[ @|:export| @ @]] \- - \nlret @} + {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). - Furthermore, a variable @|c-type-@| is defined, for the first @ - only, and initialized with the newly constructed C type object. + Each of the @s is associated with the resulting type for retrieval + by \descref{find-simple-c-type}{fun}. 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{define-simple-c-type}[macro]{mac}, then return the corresponding + @|simple-c-type| object; otherwise, return @|nil|. +\end{describe} + \begin{describe}{cls}{tagged-c-type (qualifiable-c-type) \&key :qualifiers :tag} Provides common behaviour for C tagged types. A @ is a string @@ -542,6 +686,38 @@ protocol. \end{describe} +\subsection{Atomic types} \label{sec:clang.c-types.atomic} + +Atomic types are compound types. The subtype of an atomic type is simply the +underlying type of the object. Note that, as far as Sod is concerned, atomic +types are not the same as atomic-qualified types: you must be consistent +about which you use. + +\begin{describe}{cls} + {c-atomic-type (qualifiable-c-type) \&key :qualifiers :subtype} + Represents an atomic type. An instance denotes the C type + @|_Atomic(@)|. + + 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 are compound types. The subtype of a pointer type is the type it @@ -631,7 +807,8 @@ function type is the type of the function's return value. 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 @. @@ -640,14 +817,21 @@ function type is the type of the function's return value. 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{c-keyword-function-type} + [object]{cls}), 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*} {\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|. + \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}{gf} @@ -731,23 +915,85 @@ function type is the type of the function's return value. For example, \begin{prog} - (c-type (fun \=(lisp (c-type-subtype other-func)) \+ \\ + (c-type (fun \=(lisp (c-type-subtype other-func)) \+\\ ("first" int) . (c-function-arguments other-func)) \end{prog} evaluates to a function type like @|other-func|, only with an additional argument of type @|int| added to the front of its argument list. This could also have been written \begin{prog} - (let (\=(args (c-function-arguments other-func)) \+ \\ - (ret (c-type-subtype other-func))) \- \\ \ind + (let (\=(args (c-function-arguments other-func)) \+\\ + (ret (c-type-subtype other-func))) \-\\ \ind (c-type (fun \=(lisp ret) ("first" int) . args) \end{prog} \end{describe} +\begin{describe}{cls} + {c-keyword-function-type (c-function-type) + \&key :subtype :arguments :keywords} + Represents `functions' which accept keyword arguments. Of course, actual C + functions can't accept keyword arguments directly, but this type is useful + for describing messages and methods which deal with keyword arguments. + + An instance denotes the type of C function which accepts the position + argument list @, 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{c-function-type}{cls} 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{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 @ @ @ + \nlret @} + Construct and return a new keyword-function type, returning @ and + accepting the @ and @. \end{describe} \begin{describe}{gf} @@ -764,6 +1010,84 @@ function type is the type of the function's return value. @|commentify-argument-names| to the argument list of the given type. \end{describe} +\begin{describe}{fun}{reify-variable-argument-tail @ @> @} + 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{*sod-ap*}[variable]{var}. The new list is returned; the + original list is not modified, but may share structure with the new list. +\end{describe} + +\begin{describe}{fun} + {merge-keyword-lists @ @ @> @} + 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{argument}{cls} 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{file-location}{gf}, 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{info}{fun}) 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} + {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{pprint-c-type}[protocol]{gf}. + + 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{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} @@ -897,19 +1221,23 @@ Temporary names are represented by objects which implement a simple protocol. \end{describe} \begin{describe}{mac} - {definst @ (@ \&key @) (@^*) \\ \ind - @[[ @^* @! @ @]] \\ - @^* \- - \nlret @} + {definst @ (@ \&key @) (@^*) \\ \ind + @[[ @^* @! @ @]] \\ + @^* + \-\nlret @} \end{describe} \begin{describe}{mac} {format-compound-statement - (@ @ \&optional @) \\ \ind - @^* \\ + (@ @ \&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} & @@ -921,6 +1249,8 @@ Temporary names are represented by objects which implement a simple protocol. @|set| & @ @ & @ = @; \\ \hlx{v} @|update| & @ @ @ & @ @= @; \\ \hlx{v} + @|cond| & @ @ @ & @ ? @ : @ + \\ \hlx{v} @|return| & @ & return @[@@]; \\ \hlx{v} @|break| & --- & break; \\ \hlx{v} @@ -929,18 +1259,26 @@ Temporary names are represented by objects which implement a simple protocol. @|call| & @ @|\&rest| @ & @(@_1, $\ldots$, - @_n) \\ \hlx{vhv} + @_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 @_0 @(@_1 @_1, $\ldots$, + @|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} @@ -970,6 +1308,9 @@ Temporary names are represented by objects which implement a simple protocol. \begin{describe}{gf}{emit-decls @ @} \end{describe} +\begin{describe}{fun}{emit-banner @ @ \&rest @} +\end{describe} + \begin{describe}{gf}{codegen-push @} \end{describe} @@ -995,10 +1336,10 @@ Temporary names are represented by objects which implement a simple protocol. \end{describe} \begin{describe}{mac} - {with-temporary-var (@ @ @) \\ \ind - @^* \\ - @^* \- - \nlret @^*} + {with-temporary-var (@ @ @) \\ \ind + @^* \\ + @^* + \-\nlret @^*} \end{describe} \begin{describe}{fun}{deliver-expr @ @ @}