1 ! Copyright (C) 2007, 2008 Daniel Ehrenberg
2 ! Portions copyright (C) 2009, 2010 Slava Pestov, Joe Groff
3 ! See https://factorcode.org/license.txt for BSD license.
4 USING: accessors arrays assocs classes classes.tuple
5 compiler.units definitions effects fry generic generic.standard
6 hashtables kernel lexer make math namespaces parser sequences
7 sets slots words words.symbol ;
10 ERROR: broadcast-words-must-have-no-outputs group ;
14 : protocol-words ( protocol -- words )
15 "protocol-words" word-prop ;
17 : protocol-consult ( protocol -- consulters )
18 "protocol-consult" word-prop ;
20 GENERIC: group-words ( group -- words )
22 M: standard-generic group-words
23 dup "combination" word-prop #>> 2array 1array ;
25 : slot-words, ( slot-spec -- )
26 [ name>> reader-word 0 2array , ]
28 dup read-only>> [ drop ] [
29 name>> writer-word 0 2array ,
33 : slot-group-words ( slots -- words )
34 [ [ slot-words, ] each ] { } make ;
36 M: tuple-class group-words
37 all-slots slot-group-words ;
39 : check-broadcast-group ( group -- group )
40 dup group-words [ first stack-effect out>> empty? ] all?
41 [ broadcast-words-must-have-no-outputs ] unless ;
45 TUPLE: consultation group class quot loc ;
47 TUPLE: hook-consultation < consultation hook-var ;
49 TUPLE: broadcast < consultation ;
51 : <consultation> ( group class quot -- consultation )
54 : <broadcast> ( group class quot -- consultation )
55 [ check-broadcast-group ] 2dip f broadcast boa ;
57 :: <hook-consultation> ( group class var quot -- hook-consultation )
64 : create-consult-method ( word consultation -- method )
65 [ class>> swap first create-method dup fake-definition ] keep
66 [ drop ] [ "consultation" set-word-prop ] 2bi ;
68 PREDICATE: consult-method < method
69 "consultation" word-prop >boolean ;
71 M: consult-method reset-word
72 [ call-next-method ] [ "consultation" remove-word-prop ] bi ;
74 GENERIC#: (consult-method-quot) 2 ( consultation quot word -- object )
76 M: consultation (consult-method-quot)
77 '[ _ call _ execute ] nip ;
79 M: broadcast (consult-method-quot)
80 '[ _ call [ _ execute ] each ] nip ;
82 M:: hook-consultation (consult-method-quot) ( consultation quot word -- object )
83 [ quot call consultation hook-var>> [ word execute ] with-variable ] ;
85 : consult-method-quot ( consultation word -- object )
87 [ second [ [ dip ] curry ] times ] [ first ] bi
88 (consult-method-quot) ;
90 : define-consult-method ( word consultation -- )
91 [ create-consult-method ]
92 [ swap consult-method-quot ] 2bi
95 : each-generic ( consultation quot -- )
96 [ [ group>> group-words ] keep ] dip curry each ; inline
98 : register-consult ( consultation -- )
99 [ group>> "protocol-consult" ] [ ] [ class>> ] tri
100 '[ [ _ _ ] dip ?set-at ] change-word-prop ;
102 : consult-methods ( consultation -- )
103 [ define-consult-method ] each-generic ;
105 : unregister-consult ( consultation -- )
106 [ class>> ] [ group>> ] bi
107 "protocol-consult" word-prop delete-at ;
109 : unconsult-method ( word consultation -- )
110 [ class>> swap first ?lookup-method ] keep
112 over "consultation" word-prop eq?
113 [ forget ] [ drop ] if
116 : unconsult-methods ( consultation -- )
117 [ unconsult-method ] each-generic ;
121 : define-consult ( consultation -- )
122 [ register-consult ] [ consult-methods ] bi ;
125 scan-word scan-word parse-definition <consultation>
126 [ save-location ] [ define-consult ] bi ;
128 SYNTAX: HOOK-CONSULT:
129 scan-word scan-word scan-word parse-definition <hook-consultation>
130 [ save-location ] [ define-consult ] bi ;
133 scan-word scan-word parse-definition <broadcast>
134 [ save-location ] [ define-consult ] bi ;
136 M: consultation where loc>> ;
138 M: consultation set-where loc<< ;
140 M: consultation forget*
141 [ unconsult-methods ] [ unregister-consult ] bi ;
146 : forget-all-methods ( classes words -- )
147 [ first ?lookup-method forget ] cartesian-each ;
149 : protocol-users ( protocol -- users )
150 protocol-consult keys ;
152 : lost-words ( protocol wordlist -- lost-words )
153 [ protocol-words ] dip diff ;
155 : forget-old-definitions ( protocol new-wordlist -- )
156 [ drop protocol-users ] [ lost-words ] 2bi
159 : added-words ( protocol wordlist -- added-words )
160 swap protocol-words diff ;
162 : add-new-definitions ( protocol wordlist -- )
163 [ drop protocol-consult values ] [ added-words ] 2bi
164 [ swap define-consult-method ] cartesian-each ;
166 : initialize-protocol-props ( protocol wordlist -- )
168 drop "protocol-consult"
169 [ H{ } assoc-like ] change-word-prop
170 ] [ { } like "protocol-words" set-word-prop ] 2bi ;
172 : fill-in-depth ( wordlist -- wordlist' )
173 [ dup word? [ 0 2array ] when ] map ;
175 : show-words ( wordlist' -- wordlist )
176 [ dup second zero? [ first ] when ] map ;
178 : check-generic ( generic -- )
179 dup array? [ first ] when generic check-instance drop ;
183 : define-protocol ( protocol wordlist -- )
184 dup [ check-generic ] each
185 [ drop define-symbol ] [
187 [ forget-old-definitions ]
188 [ add-new-definitions ]
189 [ initialize-protocol-props ] 2tri
193 scan-new-word parse-definition define-protocol ;
195 PREDICATE: protocol < word protocol-words ; ! Subclass of symbol?
198 [ f forget-old-definitions ] [ call-next-method ] bi ;
200 M: protocol definition protocol-words show-words ;
202 M: protocol definer drop \ PROTOCOL: \ ; ;
204 M: protocol group-words protocol-words ;
206 SYNTAX: SLOT-PROTOCOL:
208 [ [ reader-word ] [ writer-word ] bi 2array ]
209 map-tokens concat define-protocol ;