Update of /project/cells/cvsroot/cells In directory clnet:/tmp/cvs-serv28230
Modified Files: cell-types.lisp cells-manifesto.txt cells.lpr family.lisp md-slot-value.lisp model-object.lisp Log Message:
--- /project/cells/cvsroot/cells/cell-types.lisp 2006/06/23 01:04:55 1.14 +++ /project/cells/cvsroot/cells/cell-types.lisp 2006/06/29 09:54:06 1.15 @@ -141,7 +141,7 @@
(defmethod print-object ((c cell) stream) (c-print-value c stream) - (format stream "=[~d]~a/~a]" + (format stream "=~d/~a/~a]" (c-pulse c) (symbol-name (or (c-slot-name c) :anoncell)) (or (c-model c) :anonmd))) @@ -151,7 +151,7 @@ (defmethod c-print-value ((c c-ruled) stream) (format stream "~a" (cond ((c-validp c) "<vld>") ((c-unboundp c) "<unb>") - ((not (c-currentp c)) "<obs>") + ((not (c-currentp c)) "dirty") (t "<err>"))))
(defmethod c-print-value (c stream) --- /project/cells/cvsroot/cells/cells-manifesto.txt 2006/06/23 01:04:56 1.7 +++ /project/cells/cvsroot/cells/cells-manifesto.txt 2006/06/29 09:54:06 1.8 @@ -17,7 +17,7 @@ cascade across the paper.
VisiCalc let my father take the formula he had in mind and -put it in (declare it to) the electronic spreadsheet. Then VisiCalc +put it into (declare it to) the electronic spreadsheet. Then VisiCalc could do the tedious work: recalculating, knowing what to recalculate, and knowing in what order to recalculate.
@@ -75,11 +75,12 @@
:cell {nil | t | :ephemeral}
-:cell is optional. The default is ":cell t", meaning the Cells engine will manage the slot. -Specifying NIL signifies that this slot is entirely +:cell is optional. The default is ":cell t", meaning the Cells engine will manage the slot to give +it the spreadsheet-like characteristics. Specifying NIL signifies that this slot is entirely outside any handling by the Cells engine; it is just a plain CLOS slot.
-Specifying :ephemeral causes the Cells engine to reset the apparent slot +This next bit will not make sense until we have explained propagation of state change, but +specifying :ephemeral causes the Cells engine to reset the apparent slot value to NIL immediately and only after fully propagating any value assumed by the slot, either by assignment to an input Cell (the vastly more common case) or by a rule calculation.
@@ -92,7 +93,7 @@ both :cell nil and :unchanged-if.] If specified, the named function is a predicate of two arguments, the new and old value in that order. The predicate determines if a subsequent slot value (either computed or assigned to an input) is unchanged in the sense that no propagation -is necessary, either to dependent ruled cells or (getting ahead of ourselves) "on change" observers. +is necessary, either to dependent ruled cells or (getting ahead of ourselves again) "on change" observers. The default unchanged test is EQL.
Cell types @@ -111,9 +112,9 @@ yet grow based on text length and relevant font metrics to always leave room for one more character (if the GUI design calls for that).
-To summarize, the class specification supplied with DEFMODEL specifies whether a slot can ever -be managed by the Cells engine. For those that can, at and only at instance initialization time, -different instances can have different Cell types mediating the same slot. +To summarize, the class specification supplied with DEFMODEL specifies whether a slot can /ever/ +be managed by the Cells engine. For those that can, at and only at instance initialization time +different instances can have different Cell types and rules specified to mediate the same slot.
Input Cells ----------- @@ -121,7 +122,7 @@ get data from the world outside the model -- it cannot be rules all the way down. Typically, these input assignements are made by code polling OS events via some GetNextEvent API call, or by callbacks registered with an event system such as win32 WindowProc functions. Other code may poll sockets or -serial inputs from some external device. +serial inputs from an external device.
Ruled Cells ----------- @@ -161,7 +162,7 @@ we no longer know who else to update in light of such variation. The optimization, by the way, extends to eliminating ruled Cells which, after any computation, end up not depending on any other cell.
-Again, note that this is different than specifying ":cell nil" for some slot. Here, the Cells engine +Again, note that this is different from specifying ":cell nil" for some slot. Here, the Cells engine has been told to manage some slot, but for some instance the slot has been authored to bear some value for the lifetime of that instance.
@@ -248,6 +249,32 @@ the class designer when they decide to add a slot to a class. As instances are created and different rules specified for different slots to achieve custom behavior, the effort is the same as for the VisiCalc user.
+Model Building +-------------- +Everything above could describe one instance of one class defined by DEFMODEL. Of course, we want multiples +of both. In brief: + +-- cells can depend on other cells from any other instance. Since a rule gets passed only "self", Cell users +need something like the Family class included with the Cells package effectively to turn a collection of +instances into a network searchable by name or type. + +-- The overall model population must be maintainable by Cell slots such as the "kids" slot of the Family +class. The burden here is on the Cells engine to allow one cell of one child to ask for the value of a cell of +another child and vice versa (with different Cells), when both children are the product of the same rule, +or different rules when "cousins" are exchanging information. So we must gracefully traverse the parent/kids +tree dispatching kids rules just in time to produce the other instance sought. + +-- kid-slotting: used almost exclusively so far for orderly GUI layout, a parent must be able to specify +rules for specific slots of kids. Example: a "stack" class wants to provide rules for child geometry +specifying left, right, or centered alignment and vertical stacking (with optional spacing) one below +the other. The idea is that we want to other child instances without worrying about how they will +be arranged in some container. + +-- finalization: when an instance appears in the "old kids" but not in the "new kids", a Cells engine +may need to arrange for all Cells to "unsubscribe" from their dependents. Cells takes care of that if +one calls "not-to-be" on an instance. + + Suggested Applications ---------------------- Any application that must maintain an interesting, long-lived data model incorporating a stream of unpredictable @@ -508,3 +535,5 @@ 11. Weak Notification Automatically created inter-cell links must not inhibit garbage collection of either cell. (Technically optional, but very easy to do.) + + --- /project/cells/cvsroot/cells/cells.lpr 2006/06/25 21:30:34 1.16 +++ /project/cells/cvsroot/cells/cells.lpr 2006/06/29 09:54:06 1.17 @@ -1,4 +1,4 @@ -;; -*- lisp-version: "8.0 [Windows] (Jun 21, 2006 9:54)"; cg: "1.81"; -*- +;; -*- lisp-version: "8.0 [Windows] (Jun 28, 2006 10:53)"; cg: "1.81"; -*-
(in-package :cg-user)
--- /project/cells/cvsroot/cells/family.lisp 2006/06/13 05:05:12 1.8 +++ /project/cells/cvsroot/cells/family.lisp 2006/06/29 09:54:06 1.9 @@ -46,8 +46,10 @@ (unless (md-name self) (setf (md-name self) (gentemp (string (c-class-name (class-of self)))))))
- (when (fm-parent self) - (md-be-adopted self))) + (when (and (slot-boundp self '.fm-parent) + (fm-parent self) + (zerop (adopt-ct self))) + (md-be-adopted self)))
(defmodel perishable () ((expiration :initform nil :accessor expiration :initarg :expiration))) --- /project/cells/cvsroot/cells/md-slot-value.lisp 2006/06/25 21:30:34 1.23 +++ /project/cells/cvsroot/cells/md-slot-value.lisp 2006/06/29 09:54:06 1.24 @@ -81,8 +81,15 @@ (return-from calculate-and-set))
(when (find c *call-stack*) ;; circularity + (trc "cell appears in call stack:" c) + (loop with caller-reiterated + for caller in *call-stack* + until caller-reiterated + do (trc "caller:" caller) + (pprint (cr-code c)) + (setf caller-reiterated (eq caller c))) (c-break ;; break is problem when testing cells on some CLs - "cell ~a midst askers: ~a" c *call-stack*)) + "cell ~a midst askers (see above)" c))
(multiple-value-bind (raw-value propagation-code) (calculate-and-link c) --- /project/cells/cvsroot/cells/model-object.lisp 2006/06/23 01:04:56 1.8 +++ /project/cells/cvsroot/cells/model-object.lisp 2006/06/29 09:54:06 1.9 @@ -45,21 +45,22 @@ ; here we shuttle cells out of the slots and into a per-instance dictionary of cells, ; as well as tell the cells what slot and instance they are mediating. ; - (loop for esd in (class-slots (class-of self)) - for sn = (slot-definition-name esd) - for sv = (when (slot-boundp self sn) - (slot-value self sn)) - ;;do (print (list self sn sv (typep sv 'cell))) - when (typep sv 'cell) - do (if (md-slot-cell-type (type-of self) sn) - (md-install-cell self sn sv) - (when *c-debug* - (trc "warning: cell ~a offered for non-cellular model/slot ~a/~a" sv self sn)))) - ; - ; queue up for awakening - ; - (with-integrity (:awaken self) - (md-awaken self))) + (when (slot-boundp self '.md-state) + (loop for esd in (class-slots (class-of self)) + for sn = (slot-definition-name esd) + for sv = (when (slot-boundp self sn) + (slot-value self sn)) + ;;do (print (list self sn sv (typep sv 'cell))) + when (typep sv 'cell) + do (if (md-slot-cell-type (type-of self) sn) + (md-install-cell self sn sv) + (when *c-debug* + (trc "warning: cell ~a offered for non-cellular model/slot ~a/~a" sv self sn)))) + ; + ; queue up for awakening + ; + (with-integrity (:awaken self) + (md-awaken self))))
(defun md-install-cell (self sn c &aux (c-isa-cell (typep c 'cell))) ;