;;;----- 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
;; accessor functions later.
((label :type keyword :initarg :label :reader ds-label)
(name :type string :initarg :name :reader ds-name)
- (kind :type (member type sign size qualifier)
+ (kind :type (member type complexity sign size qualifier)
:initarg :kind :reader ds-kind)
(taggedp :type boolean :initarg :taggedp
:initform nil :reader ds-taggedp))
(defparameter *declspec-map*
(let ((map (make-hash-table :test #'equal)))
- (dolist (item '((type :void :char :int :float :double)
+ (dolist (item '((type :void :char :int :float :double
+ (:bool :name "_Bool"))
+ (complexity (:complex :name "_Complex")
+ (:imaginary :name "_Imaginary"))
((type :taggedp t) :enum :struct :union)
(size :short :long (:long-long :name "long long"))
(sign :signed :unsigned)
:taggedp taggedp)))
(setf (gethash name map) ds
(gethash label map) ds))))))
+ (dolist (label '(:complex :imaginary :bool))
+ (setf (gethash (string-downcase label) map) (gethash label map)))
map)
"Maps symbolic labels and textual names to `declspec' instances.")
;; This could have been done with `defstruct' just as well, but a
;; `defclass' can be tweaked interactively, which is a win at the moment.
((type :initform nil :initarg :type :reader ds-type)
+ (complexity :initform nil :initarg :complexity :reader ds-complexity)
(sign :initform nil :initarg :sign :reader ds-sign)
(size :initform nil :initarg :size :reader ds-size)
(qualifier :initform nil :initarg :qualifiers :reader ds-qualifiers))
(defmethod ds-kind ((ty c-type)) 'type)
(defparameter *good-declspecs*
- '(((:int) (:signed :unsigned) (:short :long :long-long))
- ((:char) (:signed :unsigned) ())
- ((:double) () (:long))
- (t () ()))
+ '(((:int) (:signed :unsigned) (:short :long :long-long) ())
+ ((:char) (:signed :unsigned) () ())
+ ((:double) () (:long) (:complex :imaginary))
+ (t () () ()))
"List of good collections of declaration specifiers.
- Each item is a list of the form (TYPES SIGNS SIZES). Each of TYPES, SIGNS
- and SIZES is either a list of acceptable specifiers of the appropriate
- kind, or T, which matches any specifier.")
+ Each item is a list of the form (TYPES SIGNS SIZES COMPLEXITIES). Each of
+ TYPES, SIGNS, SIZES, and COMPLEXITIES, is either a list of acceptable
+ specifiers of the appropriate kind, or T, which matches any specifier.")
(defun good-declspecs-p (specs)
"Are SPECS a good collection of declaration specifiers?"
- (let ((speclist (list (ds-type specs) (ds-sign specs) (ds-size specs))))
+ (let ((speclist (list (ds-type specs)
+ (ds-sign specs)
+ (ds-size specs)
+ (ds-complexity specs))))
(some (lambda (it)
(every (lambda (spec pat)
(or (eq pat t) (null spec)
(let ((type (ds-type specs))
(size (ds-size specs))
(sign (ds-sign specs))
+ (cplx (ds-complexity specs))
(quals (mapcar #'ds-label (ds-qualifiers specs))))
(cond ((typep type 'c-type)
(qualify-c-type type quals))
- ((or type size sign)
+ ((or type size sign cplx)
(when (and sign (eq (ds-label sign) :signed)
(eq (ds-label type) :int))
(setf sign nil))
(make-simple-type (format nil "~{~@[~A~^ ~]~}"
(mapcar #'ds-name
(remove nil
- (list sign size type))))
+ (list sign cplx
+ size type))))
quals))
(t
nil))))
;; Turns out to be easier to do this by hand.
(let ((ds (and (eq (token-type scanner) :id)
(let ((kw (token-value scanner)))
- (or (gethash kw *module-type-map*)
+ (or (and (boundp '*module-type-map*)
+ (gethash kw *module-type-map*))
(gethash kw *declspec-map*))))))
(cond ((or (not ds) (and predicate (not (funcall predicate ds))))
(values (list indicator) nil nil))
permitted. In this case, you must ensure that ABSTRACTP is true so that
the appropriate heuristic can be applied. As a convenience, if ABSTRACTP
is true then `(? :id)' is used as the default KERNEL."
+
+ ;; This is a bit confusing. This is a strangely-shaped operator grammer,
+ ;; which wouldn't be so bad, but the `values' being operated on are pairs
+ ;; of the form (FUNC . NAME). The NAME is whatever the KERNEL parser
+ ;; produces as its result, and will be passed out unchanged. The FUNC is a
+ ;; type-constructor function which will be eventually be applied to the
+ ;; input BASE-TYPE, but we can't calculate the actual result as we go along
+ ;; because of the rather annoying inside-out nature of the declarator
+ ;; syntax.
+
(with-parser-context (token-scanner-context :scanner scanner)
(let ((kernel-parser (cond (kernel kernel)
(abstractp (parser () (? :id)))