%%%----- 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-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.
\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
\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
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}
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
\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>}
-\end{describe}
+ 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>.
-\begin{describe}{fun}{argument-name @<argument> @> @<string>}
+ 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.
\end{describe}
-\begin{describe}{fun}{argument-type @<argument> @> @<c-type>}
+\begin{describe*}
+ {\dhead{fun}{argument-name @<argument> @> @<name>}
+ \dhead{fun}{argument-type @<argument> @> @<c-type>}}
+ Accessor functions for @|argument| objects. They return the name (for
+ @|argument-name|) or type (for @|argument-type|) from the object, as passed
+ to @|make-argument|.
+\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}{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}{fun}
+ {make-function-type @<subtype> @<arguments> @> @<c-function-type>}
+ Construct and return a new function type, returning @<subtype> and
+ accepting the @<arguments>.
+\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}
+ {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}
+\subsection{Parsing C types} \label{sec:clang.c-types.parsing}
+
\begin{describe}{fun}
- {make-c-type @<c-type> @<arguments> @> @<c-function-type>}
+ {parse-c-type @<scanner>
+ @> @<result> @<success-flag> @<consumed-flag>}
\end{describe}
\begin{describe}{fun}
- {commentify-argument-names @<arguments> @> @<commentified-arguments>}
+ {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}
- {commentify-function-type @<c-type> @> @<commentified-c-type>}
+ {make-class-type @<name> \&optional @<qualifiers> @> @<class-type>}
\end{describe}
-\subsection{Parsing C types} \label{sec:clang.c-types.parsing}
+\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 \\ \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{table}
+ \begin{tabular}[C]{ll>{\codeface}l} \hlx*{hv}
+ \thd{Class name} &
+ \thd{Arguments} &
+ \thd{Output format} \\ \hlx{vhv}
+ @|var| & @<name> @<type> @<init> & @<type> @<name> @[= @<init>@];
+ \\ \hlx{v}
+ @|set| & @<var> @<expr> & @<var> = @<expr>; \\ \hlx{v}
+ @|update| & @<var> @<op> @<expr> & @<var> @<op>= @<expr>;
+ \\ \hlx{v}
+ @|return| & @<expr> & return @[@<expr>@];
+ \\ \hlx{v}
+ @|break| & --- & break; \\ \hlx{v}
+ @|continue| & --- & continue; \\ \hlx{v}
+ @|expr| & @<expr> & @<expr>; \\ \hlx{v}
+ @|call| & @<func> @<args> & @<func>(@<arg>_1,
+ $\ldots$,
+ @<arg>_n) \\ \hlx{v}
+ @|va-start| & @<ap> @<arg> & va_start(@<ap>, @<arg>);
+ \\ \hlx{v}
+ @|va-copy| & @<to> @<from> & va_copy(@<to>, @<from>);
+ \\ \hlx{v}
+ @|va-end| & @<ap> & va_end(@<ap>); \\ \hlx{vhv}
+ @|block| & @<decls> @<body> & \{ @[@<decls>@] @<body> \}
+ \\ \hlx{v}
+ @|if| & @<cond> @<conseq> @<alt> & if (@<cond>) @<conseq>
+ @[else @<alt>@] \\ \hlx{v}
+ @|while| & @<cond> @<body> & while (@<cond>) @<body>
+ \\ \hlx{v}
+ @|do-while| & @<body> @<cond> & do @<body> while (@<cond>);
+ \\ \hlx{v}
+ @|function| & @<name> @<type> @<body> &
+ @<type>_0 @<name>(@<type>_1 @<arg>_1, $\ldots$,
+ @<type>_n @<arg>_n @[, \dots@])
+ @<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}{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}{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: