forked from kennytilton/cells
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cell-types.lisp
executable file
·181 lines (142 loc) · 5.69 KB
/
cell-types.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
;; -*- mode: Lisp; Syntax: Common-Lisp; Package: cells; -*-
#|
Cells -- Automatic Dataflow Managememnt
(See defpackage.lisp for license and copyright notigification)
|#
(in-package :cells)
(defstruct (cell (:conc-name c-))
model
slot-name
value
inputp ;; t for old c-variable class
synaptic
(caller-store (make-fifo-queue) :type cons) ;; (C3) probably better to notify callers FIFO
(state :nascent :type symbol) ;; :nascent, :awake, :optimized-away
(value-state :unbound :type symbol) ;; {:unbound | :unevaluated | :uncurrent | :valid}
; uncurrent (aka dirty) new for 06-10-15. we need this so
; c-quiesce can force a caller to update when asked
; in case the owner of the quiesced cell goes out of existence
; in a way the caller will not see via any kids dependency. Saw
; this one coming a long time ago: depending on cell X implies
; a dependency on the existence of instance owning X
(pulse 0 :type fixnum)
(pulse-last-changed 0 :type fixnum) ;; lazys can miss changes by missing change of X followed by unchange of X in subsequent DP
(pulse-observed 0 :type fixnum)
lazy
(optimize t)
debug
md-info)
;_____________________ print __________________________________
#+sigh
(defmethod print-object :before ((c cell) stream)
(declare (ignorable stream))
#+shhh (unless (or *stop* *print-readably*)
(format stream "[~a~a:" (if (c-inputp c) "i" "?")
(cond
((null (c-model c)) #\0)
((eq :eternal-rest (md-state (c-model c))) #\_)
((not (c-currentp c)) #\#)
(t #\space)))))
(defmethod print-object ((c cell) stream)
(declare (ignorable stream))
(if *stop*
(format stream "<~d:~a ~a/~a = ~a>"
(c-pulse c)
(subseq (string (c-state c)) 0 1)
(symbol-name (or (c-slot-name c) :anoncell))
(md-name (c-model c))
(type-of (c-value c)))
(let ((*print-circle* t))
#+failsafe (format stream "~a/~a" (c-model c)(c-slot-name c))
(if *print-readably*
(call-next-method)
(progn
(c-print-value c stream)
(format stream "<~d:~a ~a/~a = ~a>"
(c-pulse c)
(subseq (string (c-state c)) 0 1)
(symbol-name (or (c-slot-name c) :anoncell))
(print-cell-model (c-model c))
(if (consp (c-value c))
"LST" (c-value c))))))))
(export! print-cell-model)
(defgeneric print-cell-model (md)
(:method (other) (print-object other nil)))
(defmethod trcp :around ((c cell))
(and ;*c-debug*
(or (c-debug c)
(call-next-method))))
(defun c-callers (c)
"Make it easier to change implementation"
(fifo-data (c-caller-store c)))
(defun caller-ensure (used new-caller)
(unless (find new-caller (c-callers used))
(trc nil "caller-ensure fifo-adding new-caller" new-caller :used used)
(fifo-add (c-caller-store used) new-caller)))
(defun caller-drop (used caller)
(fifo-delete (c-caller-store used) caller))
; --- ephemerality --------------------------------------------------
;
; Not a type, but an option to the :cell parameter of defmodel
;
(defun ephemeral-p (c)
(eql :ephemeral (md-slot-cell-type (type-of (c-model c)) (c-slot-name c))))
(defun ephemeral-reset (c)
(when (ephemeral-p c) ;; so caller does not need to worry about this
;
; as of Cells3 we defer resetting ephemerals because everything
; else gets deferred and we cannot /really/ reset it until
; within finish_business we are sure all callers have been recalculated
; and all outputs completed.
;
; ;; good q: what does (setf <ephem> 'x) return? historically nil, but...?
;
;;(trcx bingo-ephem c)
(with-integrity (:ephemeral-reset c)
(trc nil "!!!!!!!!!!!!!! ephemeral-reset resetting:" c)
(md-slot-value-store (c-model c) (c-slot-name c) nil)
(setf (c-value c) nil))))
; -----------------------------------------------------
(defun c-validate (self c)
(when (not (and (c-slot-name c) (c-model c)))
(format t "~&unadopted cell: ~s md:~s" c self)
(c-break "unadopted cell ~a ~a" self c)
(error 'c-unadopted :cell c)))
(defstruct (c-ruled
(:include cell)
(:conc-name cr-))
(code nil :type list) ;; /// feature this out on production build
rule)
(defun c-optimized-away-p (c)
(eq :optimized-away (c-state c)))
;----------------------------
(defmethod trcp-slot (self slot-name)
(declare (ignore self slot-name)))
(defstruct (c-dependent
(:include c-ruled)
(:conc-name cd-))
;; chop (synapses nil :type list)
(useds nil :type list)
(usage (blank-usage-mask)))
(defun blank-usage-mask ()
(make-array 16 :element-type 'bit
:initial-element 0))
(defstruct (c-drifter
(:include c-dependent)))
(defstruct (c-drifter-absolute
(:include c-drifter)))
;_____________________ accessors __________________________________
(defmethod c-useds (other) (declare (ignore other)))
(defmethod c-useds ((c c-dependent)) (cd-useds c))
(defun c-validp (c)
(eql (c-value-state c) :valid))
(defun c-unboundp (c)
(eql :unbound (c-value-state c)))
;__________________
(defmethod c-print-value ((c c-ruled) stream)
(format stream "~a" (cond ((c-validp c) (cons (c-value c) "<vld>"))
((c-unboundp c) "<unb>")
((not (c-currentp c)) "dirty")
(t "<err>"))))
(defmethod c-print-value (c stream)
(declare (ignore c stream)))