anchor.diff:             (equal readers1 readers2)
              (equal writers1 writers2)))))
   
  +(defmethod print-object ((property-spec property-spec) stream)
  +  (print-unreadable-object (property-spec stream :identity t)
  +    (format stream "Property-Spec ~A" (property-spec-name property-spec))))
  +;;;
  +;;; API
  +;;;
  +;;; - Generic functions that define the basic interface for interacting with sheep properties.
  +
  +;;; Existential functions
   (defgeneric add-property (sheep property-name value &key)
     (:documentation "Adds a property named PROPERTY-NAME to SHEEP, initalized with VALUE."))
  +
  +(defgeneric remove-property (sheep property)
  +  (:documentation "If PROPERTY-NAME is a direct property of SHEEP, this function removes it. If
  +PROPERTY-NAME is inherited from one of SHEEP's parents, or if PROPERTY-NAME does not exist in SHEEP's
  +hierarchy list, an error is signaled. This function returns SHEEP after property removal."))
  +
  +(defgeneric remove-all-direct-properties (sheep)
  +  (:documentation "Wipes out all direct properties and their values from SHEEP."))
  +
  +(defgeneric has-direct-property-p (sheep property)
  +  (:documentation "Returns T if SHEEP has PROPERTY as a direct property. NIL otherwise."))
  +
  +(defgeneric has-property-p (sheep property-name)
  +  (:documentation "Returns T if calling PROPERTY-VALUE on SHEEP using the same property-name
  +would yield a value (i.e. not signal an unbound-property condition)."))
  +
  +;;; Value
  +(defgeneric direct-property-value (sheep property)
  +  (:documentation "Returns the property-value set locally in SHEEP for PROPERTY. 
  +If the value is non-local (is delegated or does not exist in the hierarchy list), an
  +UNBOUND-PROPERTY condition is signaled."))
  +
  +(defgeneric property-value (sheep property-name)
  +  (:documentation "Returns a property-value that is not necessarily local to SHEEP."))
  +
  +(defgeneric (setf property-value) (new-value sheep property-name)
  +  (:documentation "Sets NEW-VALUE as the value of a direct-property belonging to SHEEP, named
  +PROPERTY-NAME. If the property does not already exist anywhere in the hierarchy list, an error
  +is signaled."))
  +
  +;;; Reflection API
  +(defgeneric property-owner (sheep property-name &optional errorp)
  +  (:documentation "Returns the sheep object with a direct-property called PROPERTY-NAME from which
  +SHEEP inherits its value. If ERRORP is T, an error is signaled if the property is unbound. Otherwise,
  +NIL is returned."))
  +
  +(defgeneric available-properties (sheep)
  +  (:documentation "Returns a list of property-spec objects describing all properties available to
  +SHEEP, including inherited ones."))
  +
  +(defgeneric property-summary (sheep &optional stream)
  +  (:documentation "Provides a pretty-printed representation of SHEEP's available properties."))
  +
  +(defgeneric direct-property-summary (sheep &optional stream)
  +  (:documentation "Provides a pretty-printed representation of SHEEP's direct properties."))
  +
  +;;;
  +;;; Methods
  +;;;
  +
  +;;; Existential
  +(defmethod add-property ((sheep standard-sheep) property-name value 
  +                         &key (allocation :sheep))
  +  "Allocates VALUE as one of SHEEP's direct-properties. :allocation determines where the value
  +is actually allocated. For the standard method, anything other than :sheep signals an error."
  +  (if (eq allocation :sheep)
  +      (let ((property-table (sheep-property-value-table sheep)))
  +        (when (has-direct-property-p sheep property-name)
  +          (warn "~A already has a direct property named ~A. Overwriting." sheep property-name))
  +        (setf (gethash property-name property-table) value)
  +        sheep)
  +      (error "Standard sheep can only have :sheep allocation.")))
  +
   (defmethod add-property :after ((sheep standard-sheep) property-name value
                                   &key readers writers (make-accessors-p t))
     "Once the property is allocated, this method takes care of creating the property-spec object
  
positive.code:                :format-control "Property ~A is unbound for sheep ~S"
                 :format-args (list property-name sheep)))))
  
  (defgeneric has-property-p (sheep property-name))
  (defmethod has-property-p ((sheep standard-sheep) property-name)
    "Returns T if a property with PROPERTY-NAME is available to SHEEP."
    (handler-case
        (when (property-owner sheep property-name)
          t)
      (unbound-property () nil)))
  
  (defgeneric (setf property-value) (new-value sheep property-name)
    (:documentation "Sets NEW-VALUE as the value of a direct-property belonging to SHEEP, named
  PROPERTY-NAME. If the property does not already exist anywhere in the hierarchy list, an error
  is signaled."))
  (defmethod (setf property-value) (new-value (sheep standard-sheep) property-name)
    (unless (symbolp property-name)
      (error "Property-name must be a symbol"))
    (if (has-property-p sheep property-name)
        (let ((property-table (sheep-property-value-table sheep)))
          (setf (gethash property-name property-table) new-value))
        (error "Property ~A does not exist for sheep ~A." property-name sheep)))
  
  ;; Reflection
  (defmethod print-object ((property-spec property-spec) stream)
    (print-unreadable-object (property-spec stream :identity t)
      (format stream "Property-Spec ~A" (property-spec-name property-spec))))
  (defun sheep-direct-properties (sheep)
    "Returns a set of direct property-spec definition metaobjects."
    (loop for pname being the hash-keys of (sheep-property-value-table sheep)
  
negative.code:     (setf (gethash property-name (sheep-property-spec-table sheep))
            property-spec)))
  
  (defmethod remove-property ((sheep standard-sheep) (property-name symbol))
    (if property-name
        (remove-property sheep (gethash property-name (sheep-property-spec-table sheep)))
        (error "Cannot remove property: ~A is not a direct property of ~A" property-name sheep)))
  (defmethod remove-property ((sheep standard-sheep) (property property-spec))
    (let ((name (property-spec-name property)))
      (if (has-direct-property-p sheep name)
          (progn (remhash name (sheep-property-value-table sheep))
                 (remhash name (sheep-property-spec-table sheep))
                 sheep)
          (error "Cannot remove property: ~A is not a direct property of ~A" name sheep))))
  
  (defmethod remove-all-direct-properties ((sheep standard-sheep))
    (clrhash (sheep-property-value-table sheep))
    (clrhash (sheep-property-spec-table sheep))
    sheep)
  
  (defmethod has-direct-property-p ((sheep standard-sheep) property-name)
    (nth-value 1 (gethash property-name (sheep-property-value-table sheep))))
  
  (defmethod has-property-p ((sheep standard-sheep) property-name)
    "Returns T if a property with PROPERTY-NAME is available to SHEEP."
    (handler-case
        (when (property-owner sheep property-name)
          t)
      (unbound-property () nil)))
  
  ;;; values
  (defmethod direct-property-value ((sheep standard-sheep) (property-name symbol))
    (let ((property (gethash property-name (sheep-property-spec-table sheep))))
      (if property
          (direct-property-value sheep property)
          (error 'unbound-property
                 :format-control "~A has no direct property with name ~A"
                 :format-args (list sheep property-name)))))
  (defmethod direct-property-value ((sheep standard-sheep) (property property-spec))
    (multiple-value-bind (value hasp)
        (gethash (property-spec-name property) (sheep-property-value-table sheep))
      (if hasp
          value
          (error 'unbound-property
                 :format-control "~A has no direct property with name ~A"
                 :format-args (list sheep (property-spec-name property))))))
  
  (defmethod property-value ((sheep standard-sheep) property-name)
    (property-value-with-hierarchy-list sheep property-name))
  (defun property-value-with-hierarchy-list (sheep property-name)
    (let ((hl (sheep-hierarchy-list sheep)))
      (or (loop for sheep in hl
  