c-types-impl.lisp
cl:* variable function c-type
cl:array class c-type
+ atomic c-type
bool c-type
c-array-dimensions generic
c-array-type class
+ c-atomic-type class
c-enum-type class
c-function-arguments generic
c-function-type class
long-long c-type
long-long-int c-type
make-array-type function
+ make-atomic-type function
make-c-tagged-type function
make-enum-type function
make-function-type function
c-array-type
c-function-type
qualifiable-c-type
+ c-atomic-type
c-pointer-type
simple-c-type
c-class-type
c-function-arguments
c-function-type
c-qualifier-keyword
+ (eql :atomic)
cl:symbol
c-tagged-type-kind
c-enum-type
c-type-equal-p
t t
c-array-type c-array-type
+ c-atomic-type c-atomic-type
c-class-type c-class-type
c-function-type c-function-type
c-pointer-type c-pointer-type
qualifiable-c-type
c-type-subtype
c-array-type
+ c-atomic-type
c-function-type
c-pointer-type
c-type-tag
(eql cl:function) t
(eql cl:nil) t
(eql cl:union) t
+ (eql atomic) t
(eql bool) t
(eql double) t
(eql double-complex) t
pprint-c-type
t t t
c-array-type t t
+ c-atomic-type t t
c-function-type t t
c-pointer-type t t
simple-c-type t t
standard-message
print-c-type
t c-array-type
+ t c-atomic-type
t c-class-type
t c-function-type
t c-pointer-type
@|c-struct-type| \\
@|c-union-type| \\
@|c-enum-type| \- \\
+ @|c-atomic-type| \\
@|c-pointer-type| \- \\
@|c-array-type| \\
@|c-function-type|
\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|,
\end{describe}
+\subsection{Atomic types} \label{sec:clang.c-types.atomic}
+
+Atomic types are compound types. The subtype of an atomic type is simply the
+underlying type of the object. Note that, as far as Sod is concerned, atomic
+types are not the same as atomic-qualified types: you must be consistent
+about which you use.
+
+\begin{describe}{cls}
+ {c-atomic-type (qualifiable-c-type) \&key :qualifiers :subtype}
+ Represents an atomic type. An instance denotes the C type
+ @|_Atomic(@<subtype>)|.
+
+ The @<subtype> may be any C type.\footnote{%
+ C does not permit atomic function or array types.} %
+ Two atomic types are equal if and only if their subtypes are equal and they
+ have matching qualifiers. It is possible, though probably not useful, to
+ have an atomic-qualified atomic type.
+
+ The type specifier @|(atomic @<type-spec> @<qualifier>^*)| returns a type
+ qualified atomic @<subtype>, where @<subtype> is the type specified by
+ @<type-spec> and the @<qualifier>s are qualifier keywords (which are
+ evaluated).
+\end{describe}
+
+\begin{describe}{fun}
+ {make-atomic-type @<c-type> \&optional @<qualifiers> @> @<c-atomic-type>}
+ Return an object describing the type qualified atomic @<subtype>. If
+ @<subtype> is interned, then the returned atomic type object is interned
+ also.
+\end{describe}
+
+
\subsection{Pointer types} \label{sec:clang.c-types.pointer}
Pointers are compound types. The subtype of a pointer type is the type it
\alt "bool" | "_Bool"
\alt "imaginary" | "_Imaginary" | "complex" | "_Complex"
\alt <qualifier>
+\alt <atomic-type>
-<qualifier> ::= "const" | "volatile" | "restrict"
+<qualifier> ::= <atomic> | "const" | "volatile" | "restrict"
+
+<atomic-type> ::=
+ <atomic> "(" @<declaration-specifier>^+ <abstract-declarator> ")"
+
+<atomic> ::= "atomic" | "_Atomic"
<type-name> ::= <identifier>
\end{grammar}
more @<qualifier>s, and one of the following, up to reordering.
\begin{itemize}
\item @<type-name>
+\item @<atomic-type>
\item @"struct" @<identifier>, @"union" @<identifier>, @"enum" @<identifier>
\item @"void"
\item @"_Bool", @"bool"
<argument> ::= @<declaration-specifier>^+ <argument-declarator>
+<abstract-declarator> ::= <declarator>$[\epsilon]$
+
<argument-declarator> ::= <declarator>$[\mbox{@<identifier> @! $\epsilon$}]$
<simple-declarator> ::= <declarator>$[\mbox{@<identifier>}]$
(c-type-tag type)
(c-type-qualifiers type)))
+;;;--------------------------------------------------------------------------
+;;; Atomic types.
+
+;; Class definition.
+
+(export 'c-atomic-type)
+(defclass c-atomic-type (qualifiable-c-type)
+ ((subtype :initarg :subtype :type c-type :reader c-type-subtype))
+ (:documentation "C atomic types."))
+
+;; Constructor function.
+
+(export 'make-atomic-type)
+(defun make-atomic-type (subtype &optional qualifiers)
+ "Return a (maybe distinguished) atomic type."
+ (make-or-intern-c-type 'c-atomic-type subtype
+ :subtype subtype
+ :qualifiers (canonify-qualifiers qualifiers)))
+
+;; Comparison protocol.
+
+(defmethod c-type-equal-p and ((type-a c-atomic-type) (type-b c-atomic-type))
+ (c-type-equal-p (c-type-subtype type-a) (c-type-subtype type-b)))
+
+;; C-syntax output protocol.
+
+(defmethod pprint-c-type ((type c-atomic-type) stream kernel)
+ (pprint-logical-block (stream nil)
+ (format stream "~{~A ~@_~}" (c-type-qualifier-keywords type))
+ (write-string "_Atomic(" stream)
+ (pprint-indent :current 0 stream)
+ (pprint-c-type (c-type-subtype type) stream
+ (lambda (stream prio spacep)
+ (declare (ignore stream prio spacep))))
+ (write-char #\) stream)))
+
+;; S-expression notation protocol.
+
+(defmethod print-c-type (stream (type c-atomic-type) &optional colon atsign)
+ (declare (ignore colon atsign))
+ (format stream "~:@<ATOMIC ~@_~/sod:print-c-type/~{ ~_~S~}~:>"
+ (c-type-subtype type)
+ (c-type-qualifiers type)))
+
+(export 'atomic)
+(define-c-type-syntax atomic (sub &rest quals)
+ "Return the type of atomic SUB."
+ `(make-atomic-type ,(expand-c-type-spec sub) (list ,@quals)))
+
;;;--------------------------------------------------------------------------
;;; Pointer types.
(scanner-step scanner)
(values ds t t)))))
+(define-pluggable-parser complex-declspec atomic-typepsec (scanner)
+ ;; `atomic' `(' type-name `)'
+ ;; `_Atomic' `(' type-name `)'
+ (with-parser-context (token-scanner-context :scanner scanner)
+ (parse (peek (seq ((nil (or "atomic" "_Atomic"))
+ #\(
+ (decls (parse-c-type scanner))
+ (subtype (parse-declarator scanner decls
+ :kernel (parse-empty)
+ :abstractp t))
+ #\))
+ (make-atomic-type (car subtype)))))))
+
(defun scan-and-merge-declspec (scanner specs)
"Scan a declaration specifier and merge it with SPECS.
.B _Complex
.|
.I qualifier
+.|
+.I atomic-type
.br
.I qualifier
::=
+.I atomic
+|
.B const
|
.B volatile
|
.B restrict
.br
+.I atomic-type
+::=
+.I
+atomic
+.B (
+.IR declaration-specifier \*+
+.I abstract-declarator
+.B )
+.br
+.I atomic
+::=
+.B atomic
+|
+.B _Atomic
+.br
.I type-name
::=
.I identifier
.IR declaration-specifier \*+
.I argument-declarator
.br
+.I abstract-declarator
+::=
+.IR declarator [\*e]
+.br
.I argument-declarator
::=
.IR declarator [ identifier " | \*e]"