1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays kernel kernel.private math namespaces
4 sequences strings words effects generic generic.standard
5 classes slots.private combinators accessors words ;
8 TUPLE: slot-spec name offset class initial read-only reader writer ;
10 : <slot-spec> ( -- slot-spec )
12 object bootstrap-word >>class ;
14 : define-typecheck ( class generic quot -- )
16 dup define-simple-generic
20 : define-slot-word ( class offset word quot -- )
21 rot >fixnum prefix define-typecheck ;
23 : create-accessor ( name effect -- word )
24 >r "accessors" create dup r>
25 "declared-effect" set-word-prop ;
27 : reader-quot ( decl -- quot )
30 dup object bootstrap-word eq?
31 [ drop ] [ 1array , \ declare , ] if
34 : reader-word ( name -- word )
35 ">>" append (( object -- value )) create-accessor ;
37 : define-reader ( class slot-spec -- )
39 [ name>> reader-word ]
40 [ class>> reader-quot ]
41 tri define-slot-word ;
43 : writer-word ( name -- word )
44 "(>>" swap ")" 3append (( value object -- )) create-accessor ;
46 ERROR: bad-slot-value value object index ;
48 : writer-quot ( decl -- quot )
50 dup object bootstrap-word eq?
51 [ drop \ set-slot , ] [
53 "predicate" word-prop %
54 [ [ set-slot ] [ bad-slot-value ] if ] %
58 : define-writer ( class slot-spec -- )
60 [ name>> writer-word ]
61 [ class>> writer-quot ]
62 tri define-slot-word ;
64 : setter-word ( name -- word )
65 ">>" prepend (( object value -- object )) create-accessor ;
67 : define-setter ( slot-spec -- )
68 name>> dup setter-word dup deferred? [
69 [ \ over , swap writer-word , ] [ ] make define-inline
72 : changer-word ( name -- word )
73 "change-" prepend (( object quot -- object )) create-accessor ;
75 : define-changer ( slot-spec -- )
76 name>> dup changer-word dup deferred? [
82 ] [ ] make define-inline
85 : define-slot-methods ( class slot-spec -- )
88 dup read-only>> [ 2drop ] [
89 [ define-setter drop ]
90 [ define-changer drop ]
96 : define-accessors ( class specs -- )
97 [ define-slot-methods ] with each ;
99 : define-protocol-slot ( name -- )
104 [ changer-word drop ]
107 GENERIC: make-slot ( desc -- slot-spec )
113 : peel-off-name ( slot-spec array -- slot-spec array )
114 [ first >>name ] [ rest ] bi ; inline
116 : peel-off-class ( slot-spec array -- slot-spec array )
118 ! We'd use class? here, but during bootstrap, we sometimes
119 ! create slots whose class hasn't been defined yet.
120 dup first name>> ":" tail? not [
121 [ first >>class ] [ rest ] bi
125 : peel-off-attributes ( slot-spec array -- slot-spec array )
128 { initial: [ [ first >>initial ] [ rest ] bi ] }
129 { read-only: [ [ first >>read-only ] [ rest ] bi ] }
138 [ dup empty? not ] [ peel-off-attributes ] [ ] while drop ;
140 : make-slots ( slots base -- specs )
141 over length [ + ] with map
142 [ [ make-slot ] dip >>offset ] 2map ;
144 : slot-named ( name specs -- spec/f )
145 [ slot-spec-name = ] with find nip ;