;;;----- 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))
(:documentation
"Represents the important components of a declaration specifier.
- The only interesting instances of this class are in the table
- `*declspec-map*'."))
+ The only interesting instances of this class are in the table
+ `*declspec-map*'."))
(defmethod shared-initialize :after ((ds declspec) slot-names &key)
"If no name is provided then derive one from the label.
(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 :compat "_Bool"))
+ (complexity (:complex :compat "_Complex")
+ (:imaginary :compat "_Imaginary"))
((type :taggedp t) :enum :struct :union)
(size :short :long (:long-long :name "long long"))
(sign :signed :unsigned)
(destructuring-bind (label
&key
(name (string-downcase label))
+ compat
(taggedp taggedp))
(if (consp spec) spec (list spec))
(let ((ds (make-instance 'declspec
:label label
- :name name
+ :name (or compat name)
:kind kind
:taggedp taggedp)))
(setf (gethash name map) ds
- (gethash label map) ds))))))
+ (gethash label map) ds)
+ (when compat
+ (setf (gethash compat map) ds)))))))
map)
"Maps symbolic labels and textual names to `declspec' instances.")
+(defmethod ds-label ((ty c-type)) :c-type)
+(defmethod ds-name ((ty c-type)) (princ-to-string ty))
+(defmethod ds-kind ((ty c-type)) 'type)
+
;; A collection of declaration specifiers, and how to merge them together.
(defclass declspecs ()
;; 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))
- (:documentation
- "Represents a collection of declaration specifiers.
+ (:documentation "Represents a collection of declaration specifiers.
- This is used during type parsing to represent the type under
- construction. Instances are immutable: we build new ones rather than
- modifying existing ones. This leads to a certain amount of churn, but
- we'll just have to live with that.
+ This is used during type parsing to represent the type under construction.
+ Instances are immutable: we build new ones rather than modifying existing
+ ones. This leads to a certain amount of churn, but we'll just have to
+ live with that.
- (Why are instances immutable? Because it's much easier to merge a new
- specifier into an existing collection and then check that the resulting
- thing is valid, rather than having to deal with all of the possible
- special cases of what the new thing might be. And if the merged
- collection isn't good, I must roll back to the previous version. So I
- don't get to take advantage of a mutable structure.)"))
-
-(defmethod ds-label ((ty c-type)) :c-type)
-(defmethod ds-name ((ty c-type)) (princ-to-string ty))
-(defmethod ds-kind ((ty c-type)) 'type)
+ (Why are instances immutable? Because it's much easier to merge a new
+ specifier into an existing collection and then check that the resulting
+ thing is valid, rather than having to deal with all of the possible
+ special cases of what the new thing might be. And if the merged
+ collection isn't good, I must roll back to the previous version. So I
+ don't get to take advantage of a mutable structure.)"))
(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))
(cons #'identity name))))
(argument-list ()
- ;; [ argument [ `,' argument ]* [ `,' `...' ] ] | `...'
+ ;; [argument [`,' argument]* [`,' `...']] | `...'
;;
;; The possibility of a trailing `,' `...' means that we
;; can't use the standard `list' parser. Note that, unlike