[cells-devel] Re: [cello-devel] Constructor syntax

Thomas F. Burdick tfb at OCF.Berkeley.EDU
Tue May 11 22:52:51 UTC 2004

Kenny Tilton writes:
 >  if you want to send me something with these two amendments I will 
 > manually merge with the Cells I have here, currently a subdirectory of 
 > Cello, and then future Cello/Cells releases will have that. I guess I am 
 > still leaning towards that structure, in which Cells can be accessed 
 > indepenendently but from within the larger Cello context.

Coolio, let's get it in CVS, over in Cello-land, then.

I tried to add unbound-cells support to Cells itself, and I think it
works, but I wasn't expecting it to.  In short:

  (defmodel adder ()
    ((x :accessor adder-x :initform (cv))
     (y :accessor adder-y :initform (cv))
     (sum :accessor adder-sum :initform (c? (+ (^adder-x) (^adder-y))))))

  (defparameter >>adder (to-be (make-instance 'adder)))

  (setf (adder-x >>adder) 0)

The above happily works.  It doesn't trigger the rule until I do:

  (adder-sum >>adder)
    => <unbound-cell error>

Am I crazy, or shouldn't it have given me that when I set adder-x to
0?  Even if I am crazy, and that should work fine, one change does
need to be made: cells doesn't currently catch the unbound-cell
errors, because I wasn't sure where in the propagation code to put it.

Here are my changes:

========== in cells.lisp
(defconstant +unbound+ '+unbound+)

(define-condition unbound-cell (unbound-slot) ())

========== in cell-types.lisp
(defmacro c-formula ((&rest keys &key lazy cyclic-p cyclic-value) &body forms)
  (declare (ignore lazy cyclic-p cyclic-value))
  `(make-c-dependent :code ',forms :rule (c-lambda , at forms)
		          , at keys))

(defmacro c-variable ((&rest keys &key cyclic-p) &optional (value +unbound+))
  (declare (ignore cyclic-p))
  `(make-c-variable :value ,value , at keys))

(defmacro cv (&optional (defn +unbound+))
    :value ,defn)) ;; use c-independent if need deferred execution

========== in defmodel.lisp
=============== this isn't particularly related, it just quiets down
=============== SBCL a little.
     ; -------  defclass ---------------  (^slot-value ,model ',',slotname)
       (defclass ,class ,(or directsupers '(model-object));; now we can def the class
               ,(mapcar (lambda (s)
                          (list* (car s)
                            (let ((ias (cdr s)))
                              ;; We handle accessor below
                              (when (getf ias :cell t)
                                (remf ias :reader)
                                (remf ias :writer)
                                (remf ias :accessor))
                              (remf ias :cell)
                              (remf ias :cwhen)
                              (remf ias :unchanged-if)
                              ias))) (mapcar #'copy-list slotspecs))
                ,@(or (cdr (find :documentation options :key #'car))
               (:default-initargs ;; nil ok and needed: acl oddity in re not clearing d-i's sans this
                   ,@(cdr (find :default-initargs options :key #'car)))
               (:metaclass ,(or (find :metaclass options :key #'car)

========== in md-slot-value.lisp
=============== in defun md-slot-value 
  ; this next bit is not written (c-relay-value <link> (etypecase slot-c...))
  ; because that would link before accessing possibly an invalid ruled slot
  ; (during md-awaken), and after calculating it would propagate to users and
  ; re-enter this calculation. Switching the order of the parameters would
  ; also work, but we need to document this very specific order of operations
  ; anyway, can't just leave that to the left-right thing.
  (let ((slot-value (etypecase slot-c
                      (null (bd-slot-value self slot-spec))
                      (c-variable (c-value slot-c))
                      (c-ruled (c-ruled-slot-value slot-c)))))
    (format *debug-io* "slot ~S of ~S is ~S" self slot-spec slot-value)
    (when (eql slot-value +unbound+)
      (error 'unbound-cell :instance self :name slot-spec))
     (when (car *c-calculators*)
       (c-link-ex slot-c))

========== in model-object.lisp
(defun c-install (self sn c)
  (assert (typep c 'cell))
  (trc nil "installing cell" sn c)
   (c-model c) self
   (c-slot-spec c) sn
   (md-slot-cell self sn) c
   (slot-value self sn) (when (typep c 'c-variable)
		      (c-value c)))
  (when (eql (slot-value self sn) +unbound+)
    (slot-makunbound self sn)))

Phew!  Okay, I'm making sure I only edit verion-controlled source from
now on, so I can make Emacs do the differencing work for me.

More information about the cello-devel mailing list