]> gitweb.factorcode.org Git - factor.git/blob - basis/delegate/delegate.factor
16e1967aa6bd8af7fda1119838ffdb879f4105f9
[factor.git] / basis / delegate / delegate.factor
1 ! Copyright (C) 2007, 2008 Daniel Ehrenberg
2 ! Portions copyright (C) 2009, 2010 Slava Pestov, Joe Groff
3 ! See http://factorcode.org/license.txt for BSD license.
4 USING: accessors arrays assocs classes.tuple definitions effects generic
5 generic.standard hashtables kernel lexer math parser
6 generic.parser sequences sets slots words words.symbol fry
7 compiler.units make ;
8 IN: delegate
9
10 ERROR: broadcast-words-must-have-no-outputs group ;
11
12 <PRIVATE
13
14 : protocol-words ( protocol -- words )
15     \ protocol-words word-prop ;
16
17 : protocol-consult ( protocol -- consulters )
18     \ protocol-consult word-prop ;
19
20 GENERIC: group-words ( group -- words )
21
22 M: standard-generic group-words
23     dup "combination" word-prop #>> 2array 1array ;
24
25 : slot-words, ( slot-spec -- )
26     [ name>> reader-word 0 2array , ]
27     [
28         dup read-only>> [ drop ] [
29             name>> writer-word 0 2array ,
30         ] if
31     ] bi ;
32
33 : slot-group-words ( slots -- words )
34     [ [ slot-words, ] each ] { } make ;
35
36 M: tuple-class group-words
37     all-slots slot-group-words ;
38
39 : check-broadcast-group ( group -- group )
40     dup group-words [ first stack-effect out>> empty? ] all?
41     [ broadcast-words-must-have-no-outputs ] unless ;
42
43 ! Consultation
44
45 TUPLE: consultation group class quot loc ;
46 TUPLE: broadcast < consultation ;
47
48 : <consultation> ( group class quot -- consultation )
49     f consultation boa ; 
50 : <broadcast> ( group class quot -- consultation )
51     [ check-broadcast-group ] 2dip f broadcast boa ; 
52
53 : create-consult-method ( word consultation -- method )
54     [ class>> swap first create-method dup fake-definition ] keep
55     [ drop ] [ "consultation" set-word-prop ] 2bi ;
56
57 PREDICATE: consult-method < method "consultation" word-prop ;
58
59 M: consult-method reset-word
60     [ call-next-method ] [ f "consultation" set-word-prop ] bi ;
61
62 GENERIC# (consult-method-quot) 2 ( consultation quot word -- object )
63
64 M: consultation (consult-method-quot)
65     '[ _ call _ execute ] nip ;
66 M: broadcast (consult-method-quot)
67     '[ _ call [ _ execute ] each ] nip ;
68
69 : consult-method-quot ( consultation word -- object )
70     [ dup quot>> ] dip
71     [ second [ [ dip ] curry ] times ] [ first ] bi
72     (consult-method-quot) ;
73
74 : consult-method ( word consultation -- )
75     [ create-consult-method ]
76     [ swap consult-method-quot ] 2bi
77     define ;
78
79 : each-generic ( consultation quot -- )
80     [ [ group>> group-words ] keep ] dip curry each ; inline
81
82 : register-consult ( consultation -- )
83     [ group>> \ protocol-consult ] [ ] [ class>> ] tri
84     '[ [ _ _ ] dip ?set-at ] change-word-prop ;
85
86 : consult-methods ( consultation -- )
87     [ consult-method ] each-generic ;
88
89 : unregister-consult ( consultation -- )
90     [ class>> ] [ group>> ] bi
91     \ protocol-consult word-prop delete-at ;
92
93 : unconsult-method ( word consultation -- )
94     [ class>> swap first ?lookup-method ] keep
95     over [
96         over "consultation" word-prop eq?
97         [ forget ] [ drop ] if
98     ] [ 2drop ] if ;
99
100 : unconsult-methods ( consultation -- )
101     [ unconsult-method ] each-generic ;
102
103 PRIVATE>
104
105 : define-consult ( consultation -- )
106     [ register-consult ] [ consult-methods ] bi ;
107
108 SYNTAX: CONSULT:
109     scan-word scan-word parse-definition <consultation>
110     [ save-location ] [ define-consult ] bi ;
111
112 SYNTAX: BROADCAST:
113     scan-word scan-word parse-definition <broadcast>
114     [ save-location ] [ define-consult ] bi ;
115
116 M: consultation where loc>> ;
117
118 M: consultation set-where loc<< ;
119
120 M: consultation forget*
121     [ unconsult-methods ] [ unregister-consult ] bi ;
122
123 ! Protocols
124 <PRIVATE
125
126 : forget-all-methods ( classes words -- )
127     [ first ?lookup-method forget ] cartesian-each ;
128
129 : protocol-users ( protocol -- users )
130     protocol-consult keys ;
131
132 : lost-words ( protocol wordlist -- lost-words )
133     [ protocol-words ] dip diff ;
134
135 : forget-old-definitions ( protocol new-wordlist -- )
136     [ drop protocol-users ] [ lost-words ] 2bi
137     forget-all-methods ;
138
139 : added-words ( protocol wordlist -- added-words )
140     swap protocol-words diff ;
141
142 : add-new-definitions ( protocol wordlist -- )
143     [ drop protocol-consult values ] [ added-words ] 2bi
144     [ swap consult-method ] cartesian-each ;
145
146 : initialize-protocol-props ( protocol wordlist -- )
147     [
148         drop \ protocol-consult
149         [ H{ } assoc-like ] change-word-prop
150     ] [ { } like \ protocol-words set-word-prop ] 2bi ;
151
152 : fill-in-depth ( wordlist -- wordlist' )
153     [ dup word? [ 0 2array ] when ] map ;
154
155 : show-words ( wordlist' -- wordlist )
156     [ dup second zero? [ first ] when ] map ;
157
158 ERROR: not-a-generic word ;
159
160 : check-generic ( generic -- )
161     dup array? [ first ] when
162     dup generic? [ drop ] [ not-a-generic ] if ;
163
164 PRIVATE>
165
166 : define-protocol ( protocol wordlist -- )
167     dup [ check-generic ] each
168     [ drop define-symbol ] [
169         fill-in-depth
170         [ forget-old-definitions ]
171         [ add-new-definitions ]
172         [ initialize-protocol-props ] 2tri
173     ] 2bi ;
174
175 SYNTAX: PROTOCOL:
176     scan-new-word parse-definition define-protocol ;
177
178 PREDICATE: protocol < word protocol-words ; ! Subclass of symbol?
179
180 M: protocol forget*
181     [ f forget-old-definitions ] [ call-next-method ] bi ;
182
183
184 M: protocol definition protocol-words show-words ;
185
186 M: protocol definer drop \ PROTOCOL: \ ; ;
187
188 M: protocol group-words protocol-words ;
189
190 SYNTAX: SLOT-PROTOCOL:
191     scan-new-word ";"
192     [ [ reader-word ] [ writer-word ] bi 2array ]
193     map-tokens concat define-protocol ;