chiark / gitweb /
src/c-types-parse.lisp: Introduce a pluggable parser for declspecs.
[sod] / src / classes.lisp
index 3d01f57c6aa5c5c5a7dc453b8afa01f798f52154..d403d109e60fdbe131a4428b983ecb15b804c237 100644 (file)
@@ -7,7 +7,7 @@
 
 ;;;----- 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
 
 (cl:in-package #:sod)
 
+;;; Note!  You'll notice that none of the classes defined here store property
+;;; sets persistently, even though there's a `:pset' keyword argument
+;;; accepted by many of the classes' initialization methods.  That's because
+;;; part of the pset protocol involves checking that there are no unused
+;;; properties, and this typically happens shortly after the appropriate
+;;; objects are constructed.  It would be tempting to stash the pset at
+;;; initialization time, and then pick some property from it out later -- but
+;;; that won't work in general because an error might have been signalled
+;;; about that property.  It wouldn't surprise me greatly to discover that
+;;; `most' code paths resulted in the property being looked up in time to
+;;; avoid the unused-property error, but a subtle change in circumstances
+;;; then causes a thing done on demand to be done later, leading to
+;;; irritating and misleading errors being reported to the user.  So please
+;;; don't do that.
+
 ;;;--------------------------------------------------------------------------
 ;;; Classes.
 
@@ -61,20 +76,20 @@ (defclass sod-class ()
    (methods :initarg :methods :initform nil
            :type list :accessor sod-class-methods)
 
-   (class-precedence-list :type list :accessor sod-class-precedence-list)
+   (class-precedence-list :type list :reader sod-class-precedence-list)
 
-   (type :type c-class-type :accessor sod-class-type)
+   (%type :type c-class-type :reader sod-class-type)
 
-   (chain-head :type sod-class :accessor sod-class-chain-head)
-   (chain :type list :accessor sod-class-chain)
-   (chains :type list :accessor sod-class-chains)
+   (chain-head :type sod-class :reader sod-class-chain-head)
+   (chain :type list :reader sod-class-chain)
+   (chains :type list :reader sod-class-chains)
 
-   (ilayout :type ilayout :accessor sod-class-ilayout)
-   (effective-methods :type list :accessor sod-class-effective-methods)
-   (vtables :type list :accessor sod-class-vtables)
+   (%ilayout :type ilayout :reader sod-class-ilayout)
+   (effective-methods :type list :reader sod-class-effective-methods)
+   (vtables :type list :reader sod-class-vtables)
 
-   (state :initform nil :type (member nil :finalized broken)
-         :accessor sod-class-state))
+   (state :initform nil :type (member nil :finalized :broken)
+         :reader sod-class-state))
   (:documentation
    "Classes describe the layout and behaviour of objects.
 
@@ -179,19 +194,19 @@ (defclass sod-class ()
        specific) for the class and all of its superclasses.
 
    Finally, slots concerning the instance and vtable layout of the class are
-   computed on demand via methods on `slot-unbound'.
+   computed on demand (see `define-on-demand-slot').
 
      * The ILAYOUT describes the layout for an instance of the class.  It's
-       quite complicated; see the documentation of the ILAYOUT class for
+       quite complicated; see the documentation of the `ilayout' class for
        detais.
 
      * The EFFECTIVE-METHODS are a list of effective methods, specialized for
        the class.
 
      * The VTABLES are a list of descriptions of vtables for the class.  The
-       individual elements are VTABLE objects, which are even more
-       complicated than ILAYOUT structures.  See the class documentation for
-       details."))
+       individual elements are `vtable' objects, which are even more
+       complicated than `ilayout' structures.  See the class documentation
+       for details."))
 
 (defmethod print-object ((class sod-class) stream)
   (maybe-print-unreadable-object (class stream :type t)
@@ -205,8 +220,8 @@ (defclass sod-slot ()
   ((name :initarg :name :type string :reader sod-slot-name)
    (location :initarg :location :initform (file-location nil)
             :type file-location :reader file-location)
-   (class :initarg :class :type sod-class :reader sod-slot-class)
-   (type :initarg :type :type c-type :reader sod-slot-type))
+   (%class :initarg :class :type sod-class :reader sod-slot-class)
+   (%type :initarg :type :type c-type :reader sod-slot-type))
   (:documentation
    "Slots are units of information storage in instances.
 
@@ -244,7 +259,7 @@ (defclass sod-initializer ()
   ((slot :initarg :slot :type sod-slot :reader sod-initializer-slot)
    (location :initarg :location :initform (file-location nil)
             :type file-location :reader file-location)
-   (class :initarg :class :type sod-class :reader sod-initializer-class)
+   (%class :initarg :class :type sod-class :reader sod-initializer-class)
    (value-kind :initarg :value-kind :type keyword
               :reader sod-initializer-value-kind)
    (value-form :initarg :value-form :type c-fragment
@@ -279,14 +294,11 @@ (defclass sod-initializer ()
    and `sod-instance-initializer'."))
 
 (defmethod print-object ((initializer sod-initializer) stream)
-  (if *print-escape*
-      (print-unreadable-object (initializer stream :type t)
-       (format stream "~A = ~A"
-               (sod-initializer-slot initializer)
-               initializer))
-      (format stream "~:[{~A}~;~A~]"
-             (eq (sod-initializer-value-kind initializer) :single)
-             (sod-initializer-value-form initializer))))
+  (with-slots (slot value-kind value-form) initializer
+    (if *print-escape*
+       (print-unreadable-object (initializer stream :type t)
+         (format stream "~A = ~A" slot value-form))
+       (format stream "~:[{~A}~;~A~]" (eq value-kind :single) value-form))))
 
 (export 'sod-class-initializer)
 (defclass sod-class-initializer (sod-initializer)
@@ -323,10 +335,10 @@ (defclass sod-message ()
   ((name :initarg :name :type string :reader sod-message-name)
    (location :initarg :location :initform (file-location nil)
             :type file-location :reader file-location)
-   (class :initarg :class :type sod-class :reader sod-message-class)
-   (type :initarg :type :type c-function-type :reader sod-message-type))
+   (%class :initarg :class :type sod-class :reader sod-message-class)
+   (%type :initarg :type :type c-function-type :reader sod-message-type))
   (:documentation
-   "Messages the means for stimulating an object to behave.
+   "Messages are the means for stimulating an object to behave.
 
    SOD is a single-dispatch object system, like Smalltalk, C++, Python and so
    on, but unlike CLOS and Dylan.  Behaviour is invoked by `sending messages'
@@ -375,8 +387,8 @@ (defclass sod-method ()
   ((message :initarg :message :type sod-message :reader sod-method-message)
    (location :initarg :location :initform (file-location nil)
             :type file-location :reader file-location)
-   (class :initarg :class :type sod-class :reader sod-method-class)
-   (type :initarg :type :type c-function-type :reader sod-method-type)
+   (%class :initarg :class :type sod-class :reader sod-method-class)
+   (%type :initarg :type :type c-function-type :reader sod-method-type)
    (body :initarg :body :type (or c-fragment null) :reader sod-method-body))
   (:documentation
    "(Direct) methods are units of behaviour.
@@ -409,27 +421,27 @@ (defclass sod-method ()
        will, in general, differ from the type of the message for several
        reasons.
 
-        -- Firstly, the method type must include names for all of the
-            method's parameters.  The message definition can omit the
-            parameter names (in the same way as a function declaration can).
-            Formally, the message definition can contain abstract
-            declarators, whereas method definitions must not.
+        -- The method type must include names for all of the method's
+           parameters.  The message definition can omit the parameter
+           names (in the same way as a function declaration can).  Formally,
+           the message definition can contain abstract declarators, whereas
+           method definitions must not.
 
         -- Method combinations may require different parameter or return
-            types.  For example, `before' and `after' methods don't
-            contribute to the message's return value, so they must be defined
-            as returning `void'.
+           types.  For example, `before' and `after' methods don't
+           contribute to the message's return value, so they must be defined
+           as returning `void'.
 
         -- Method combinations may permit methods whose parameter and/or
-            return types don't exactly match the corresponding types of the
-            message.  For example, one might have methods with covariant
-            return types and contravariant parameter types.  (This sounds
-            nice, but it doesn't actually seem like such a clever idea when
-            you consider that the co-/contravariance must hold among all the
-            applicable methods ordered according to the class precedence
-            list.  As a result, a user might have to work hard to build
-            subclasses whose CPLs match the restrictions implied by the
-            method types.)
+           return types don't exactly match the corresponding types of the
+           message.  For example, one might have methods with covariant
+           return types and contravariant parameter types.  (This sounds
+           nice, but it doesn't actually seem like such a clever idea when
+           you consider that the co-/contravariance must hold among all the
+           applicable methods ordered according to the class precedence
+           list.  As a result, a user might have to work hard to build
+           subclasses whose CPLs match the restrictions implied by the
+           method types.)
 
    Method objects are fairly passive in the SOD translator.  However,
    subclasses of `sod-message' may (and probably will) construct instances of