;;;----- 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
;;;--------------------------------------------------------------------------
;;; Classes.
-(defmethod guess-metaclass ((class sod-class))
- "Default metaclass-guessing function for classes.
-
- Return the most specific metaclass of any of the CLASS's direct
- superclasses."
- (do ((supers (sod-class-direct-superclasses class) (cdr supers))
- (meta nil (let ((candidate (sod-class-metaclass (car supers))))
- (cond ((null meta) candidate)
- ((sod-subclass-p meta candidate) meta)
- ((sod-subclass-p candidate meta) candidate)
- (t (error "Unable to choose metaclass for `~A'"
- class))))))
- ((endp supers) meta)))
-
(defmethod shared-initialize :after ((class sod-class) slot-names &key pset)
"Specific behaviour for SOD class initialization.
(pset :nick :id)
(string-downcase (slot-value class 'name)))
- ;; If no metaclass, guess one in a (Lisp) class-specific way.
+ ;; Set the metaclass if the appropriate property has been provided;
+ ;; otherwise leave it unbound for now, and we'll sort out the mess during
+ ;; finalization.
(default-slot-from-property (class 'metaclass slot-names)
- (pset :metaclass :id meta (find-sod-class meta))
- (guess-metaclass class))
+ (pset :metaclass :id meta (find-sod-class meta)))
;; If no chain-link, then start a new chain here.
(default-slot-from-property (class 'chain-link slot-names)
:location (file-location location)
:pset pset)))
(with-slots (slots) class
- (setf slots (append slots (list slot)))))))
+ (setf slots (append slots (list slot))))
+ slot)))
(defmethod shared-initialize :after ((slot sod-slot) slot-names &key pset)
"This method does nothing.
(file-location location))))
(with-slots (instance-initializers) class
(setf instance-initializers
- (append instance-initializers (list initializer)))))))
+ (append instance-initializers (list initializer))))
+ initializer)))
(defmethod make-sod-class-initializer
((class sod-class) nick name value-kind value-form pset
(file-location location))))
(with-slots (class-initializers) class
(setf class-initializers
- (append class-initializers (list initializer)))))))
+ (append class-initializers (list initializer))))
+ initializer)))
(defmethod make-sod-initializer-using-slot
((class sod-class) (slot sod-slot)
:slot slot
:value-kind value-kind
:value-form value-form
- :location location
+ :location (file-location location)
:pset pset))
(defmethod shared-initialize :after
:location (file-location location)
:pset pset)))
(with-slots (messages) class
- (setf messages (append messages (list message)))))))
+ (setf messages (append messages (list message))))
+ message)))
(defmethod shared-initialize :after
((message sod-message) slot-names &key pset)
(declare (ignore slot-names pset))
- (with-slots (type) message
+ (with-slots ((type %type)) message
(check-message-type message type)))
(defmethod check-message-type ((message sod-message) (type c-function-type))
type body pset
(file-location location))))
(with-slots (methods) class
- (setf methods (append methods (list method)))))))
+ (setf methods (append methods (list method))))
+ method)))
(defmethod make-sod-method-using-message
((message sod-message) (class sod-class) type body pset location)
:class class
:type type
:body body
- :location location
+ :location (file-location location)
:pset pset))
(defmethod sod-message-method-class
(declare (ignore slot-names pset))
;; Check that the arguments are named if we have a method body.
- (with-slots (body type) method
+ (with-slots (body (type %type)) method
(unless (or (not body)
(every (lambda (arg)
(or (eq arg :ellipsis)
(argument-name arg)
- (eq (argument-type arg) (c-type void))))
+ (c-type-equal-p (argument-type arg)
+ c-type-void)))
(c-function-arguments type)))
(error "Abstract declarators not permitted in method definitions")))
;; Check the method type.
- (with-slots (message type) method
+ (with-slots (message (type %type)) method
(check-method-type method message type)))
(defmethod check-method-type
((method sod-method) (message sod-message) (type c-type))
(error "Methods must have function type, not ~A" type))
+(export 'check-method-return-type)
+(defun check-method-return-type (method-type wanted-type)
+ "Signal an error unless METHOD-TYPE does not return the WANTED-TYPE."
+ (let ((method-returns (c-type-subtype method-type)))
+ (unless (c-type-equal-p method-returns wanted-type)
+ (error "Method return type ~A should be ~A"
+ method-returns wanted-type))))
+
+(export 'check-method-return-type-against-message)
+(defun check-method-return-type-against-message (method-type message-type)
+ "Signal an error unless METHOD-TYPE and MESSAGE-TYPE return the same type."
+ (let ((message-returns (c-type-subtype message-type))
+ (method-returns (c-type-subtype method-type)))
+ (unless (c-type-equal-p message-returns method-returns)
+ (error "Method return type ~A doesn't match message ~A"
+ method-returns message-returns))))
+
+(export 'check-method-argument-lists)
+(defun check-method-argument-lists (method-type message-type)
+ "Signal an error unless METHOD-TYPE and MESSAGE-TYPE have matching argument
+ lists.
+
+ This checks that the two types have matching lists of arguments."
+ (unless (argument-lists-compatible-p (c-function-arguments message-type)
+ (c-function-arguments method-type))
+ (error "Method arguments ~A don't match message ~A"
+ method-type message-type)))
+
(defmethod check-method-type
((method sod-method) (message sod-message) (type c-function-type))
- (with-slots ((msgtype type)) message
- (unless (c-type-equal-p (c-type-subtype msgtype)
- (c-type-subtype type))
- (error "Method return type ~A doesn't match message ~A"
- (c-type-subtype msgtype) (c-type-subtype type)))
- (unless (argument-lists-compatible-p (c-function-arguments msgtype)
- (c-function-arguments type))
- (error "Method arguments ~A don't match message ~A" type msgtype))))
+ (with-slots ((msgtype %type)) message
+ (check-method-return-type-against-message type msgtype)
+ (check-method-argument-lists type msgtype)))
;;;----- That's all, folks --------------------------------------------------