1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays definitions hashtables kernel kernel.private math
4 namespaces sequences sequences.private strings vectors words
5 quotations memory combinators generic classes classes.algebra
6 classes.private slots.deprecated slots.private slots
7 compiler.units math.private accessors assocs effects ;
10 M: tuple class 1 slot 2 slot { word } declare ;
12 ERROR: not-a-tuple object ;
14 : check-tuple ( object -- tuple )
15 dup tuple? [ not-a-tuple ] unless ; inline
19 : (tuple) ( layout -- tuple )
20 #! In non-optimized code, this word simply calls the
21 #! <tuple> primitive. In optimized code, an intrinsic
22 #! is generated which allocates a tuple but does not set
23 #! any of its slots. This means that any code that uses
24 #! (tuple) must fill in the slots before the next
27 #! This word is only used in the expansion of <tuple-boa>,
28 #! where this invariant is guaranteed to hold.
31 : tuple-layout ( class -- layout )
34 : layout-of ( tuple -- layout )
35 1 slot { tuple-layout } declare ; inline
37 : tuple-size ( tuple -- size )
38 layout-of size>> ; inline
40 : prepare-tuple>array ( tuple -- n tuple layout )
41 check-tuple [ tuple-size ] [ ] [ layout-of ] tri ;
43 : copy-tuple-slots ( n tuple -- array )
44 [ array-nth ] curry map ;
48 : tuple>array ( tuple -- array )
50 >r copy-tuple-slots r>
53 : tuple-slots ( tuple -- seq )
54 prepare-tuple>array drop copy-tuple-slots ;
56 : all-slots ( class -- slots )
57 superclasses [ "slots" word-prop ] map concat ;
59 : check-slots ( seq class -- seq class )
62 class>> 2dup instance?
63 [ 2drop ] [ bad-slot-value ] if
65 ] if-bootstrapping ; inline
67 GENERIC: slots>tuple ( seq class -- tuple )
69 M: tuple-class slots>tuple
71 tuple-layout <tuple> [
73 [ [ set-array-nth ] curry ]
77 : >tuple ( seq -- tuple )
80 : slot-names ( class -- seq )
81 "slot-names" word-prop ;
83 ERROR: bad-superclass class ;
87 : tuple= ( tuple1 tuple2 -- ? )
88 2dup [ layout-of ] bi@ eq? [
90 [ [ [ drop array-nth ] [ nip array-nth ] 3bi = ] 2curry ]
96 : tuple-instance? ( object class echelon -- ? )
97 #! 4 slot == superclasses>>
100 2dup array-capacity fixnum<
101 [ array-nth eq? ] [ 3drop f ] if
102 ] [ 3drop f ] if ; inline
104 : define-tuple-predicate ( class -- )
105 dup dup tuple-layout echelon>>
106 [ tuple-instance? ] 2curry define-predicate ;
108 : superclass-size ( class -- n )
109 superclasses but-last-slice
110 [ slot-names length ] map sum ;
112 : (instance-check-quot) ( class -- quot )
115 [ "predicate" word-prop % ]
116 [ [ bad-slot-value ] curry , ] bi
120 : (fixnum-check-quot) ( class -- quot )
121 (instance-check-quot) fixnum "coercer" word-prop prepend ;
123 : instance-check-quot ( class -- quot )
125 { [ dup object bootstrap-word eq? ] [ drop [ ] ] }
126 { [ dup "coercer" word-prop ] [ "coercer" word-prop ] }
127 { [ dup \ fixnum class<= ] [ (fixnum-check-quot) ] }
128 [ (instance-check-quot) ]
131 : boa-check-quot ( class -- quot )
132 all-slots 1 tail [ class>> instance-check-quot ] map spread>quot ;
134 : define-boa-check ( class -- )
135 dup boa-check-quot "boa-check" set-word-prop ;
137 : tuple-prototype ( class -- prototype )
138 [ all-slots [ initial>> ] map ] keep slots>tuple ;
140 : define-tuple-prototype ( class -- )
141 dup tuple-prototype "prototype" set-word-prop ;
143 : generate-tuple-slots ( class slots -- slot-specs )
144 over superclass-size 2 + make-slots deprecated-slots ;
146 : define-tuple-slots ( class -- )
147 dup dup "slot-names" word-prop generate-tuple-slots
148 [ "slots" set-word-prop ]
149 [ define-accessors ] ! new
150 [ define-slots ] ! old
153 : make-tuple-layout ( class -- layout )
155 [ [ superclass-size ] [ slot-names length ] bi + ]
156 [ superclasses dup length 1- ] tri
159 : define-tuple-layout ( class -- )
160 dup make-tuple-layout "layout" set-word-prop ;
162 : compute-slot-permutation ( new-slots old-slots -- triples )
163 [ [ [ name>> ] map ] bi@ [ index ] curry map ]
164 [ drop [ class>> ] map ]
165 [ drop [ initial>> ] map ]
168 : update-slot ( old-values n class initial -- value )
170 >r >r swap nth dup r> instance?
171 [ r> drop ] [ drop r> ] if
172 ] [ >r 3drop r> ] if ;
174 : apply-slot-permutation ( old-values triples -- new-values )
175 [ first3 update-slot ] with map ;
177 : permute-slots ( old-values layout -- new-values )
178 [ class>> all-slots ] [ outdated-tuples get at ] bi
179 compute-slot-permutation
180 apply-slot-permutation ;
182 : update-tuple ( tuple -- newtuple )
183 [ tuple-slots ] [ layout-of ] bi
184 [ permute-slots ] [ class>> ] bi
187 : update-tuples ( -- )
189 dup assoc-empty? [ drop ] [
192 [ >r layout-of r> key? ] [ 2drop f ] if
194 dup [ update-tuple ] map become
197 [ update-tuples ] update-tuples-hook set-global
199 : update-tuples-after ( class -- )
200 [ all-slots ] [ tuple-layout ] bi outdated-tuples get set-at ;
202 M: tuple-class update-class
204 [ define-tuple-layout ]
205 [ define-tuple-slots ]
206 [ define-tuple-predicate ]
207 [ define-tuple-prototype ]
211 : define-new-tuple-class ( class superclass slots -- )
212 [ drop f f tuple-class define-class ]
213 [ nip "slot-names" set-word-prop ]
214 [ 2drop update-classes ]
217 : subclasses ( class -- classes )
218 class-usages [ tuple-class? ] filter ;
220 : each-subclass ( class quot -- )
221 >r subclasses r> each ; inline
223 : redefine-tuple-class ( class superclass slots -- )
227 [ update-tuples-after ]
228 [ +inlined+ changed-definition ]
233 [ define-new-tuple-class ]
236 : tuple-class-unchanged? ( class superclass slots -- ? )
237 rot tuck [ superclass = ] [ slot-names = ] 2bi* and ;
239 : valid-superclass? ( class -- ? )
240 [ tuple-class? ] [ tuple eq? ] bi or ;
242 : check-superclass ( superclass -- )
243 dup valid-superclass? [ bad-superclass ] unless drop ;
247 GENERIC# define-tuple-class 2 ( class superclass slots -- )
249 M: word define-tuple-class
250 over check-superclass
251 define-new-tuple-class ;
253 M: tuple-class define-tuple-class
254 over check-superclass
255 3dup tuple-class-unchanged?
256 [ 3drop ] [ redefine-tuple-class ] if ;
258 : thrower-effect ( slots -- effect )
259 [ dup array? [ first ] when ] map f <effect> t >>terminated? ;
261 : define-error-class ( class superclass slots -- )
262 [ define-tuple-class ]
263 [ [ dup [ boa throw ] curry ] [ drop ] [ thrower-effect ] tri* ] 3bi
266 M: tuple-class reset-class
268 dup "slots" word-prop [
270 [ reader-word method forget ]
271 [ writer-word method forget ] 2bi
277 "layout" "slots" "slot-names" "boa-check" "prototype"
282 M: tuple-class rank-class drop 0 ;
284 M: tuple-class instance?
285 dup tuple-layout echelon>> tuple-instance? ;
288 (clone) dup delegate clone over set-delegate ;
291 over tuple? [ tuple= ] [ 2drop f ] if ;
295 [ class hashcode ] [ tuple-size ] [ ] tri
297 swapd array-nth hashcode* sequence-hashcode-step
299 ] recursive-hashcode ;
302 "prototype" word-prop (clone) ;
305 [ "boa-check" word-prop call ]
310 M: object get-slots ( obj slots -- ... )
311 [ execute ] with each ;
313 M: object set-slots ( ... obj slots -- )
314 <reversed> get-slots ;
316 : delegates ( obj -- seq ) [ delegate ] follow ;
318 : is? ( obj quot -- ? ) >r delegates r> contains? ; inline