1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays assocs kernel kernel.private slots.private math
4 namespaces make sequences vectors words quotations definitions
5 hashtables layouts combinators sequences.private generic
6 classes classes.algebra classes.private generic.standard.engines
7 generic.standard.engines.tag generic.standard.engines.predicate
8 generic.standard.engines.tuple accessors ;
11 GENERIC: dispatch# ( word -- n )
14 "combination" word-prop dispatch# ;
16 GENERIC: method-declaration ( class generic -- quot )
18 M: generic method-declaration
19 "combination" word-prop method-declaration ;
21 M: quotation engine>quot
22 assumed get generic get method-declaration prepend ;
24 ERROR: no-method object generic ;
26 : error-method ( word -- quot )
27 picker swap [ no-method ] curry append ;
29 : push-method ( method specializer atomic assoc -- )
31 [ H{ } clone <predicate-dispatch-engine> ] unless*
32 [ methods>> set-at ] keep
35 : flatten-method ( class method assoc -- )
36 [ dup flatten-class keys swap ] 2dip [
37 [ spin ] dip push-method
40 : flatten-methods ( assoc -- assoc' )
47 : <big-dispatch-engine> ( assoc -- engine )
50 convert-hi-tag-methods
51 <lo-tag-dispatch-engine> ;
53 : find-default ( methods -- quot )
54 #! Side-effects methods.
55 object bootstrap-word swap delete-at* [
56 drop generic get "default-method" word-prop 1quotation
59 : mangle-method ( method generic -- quot )
60 [ 1quotation ] [ extra-values \ drop <repetition> ] bi*
63 : <standard-engine> ( word -- engine )
64 object bootstrap-word assumed set {
66 [ "engines" word-prop forget-all ]
67 [ V{ } clone "engines" set-word-prop ]
70 [ generic get mangle-method ] assoc-map
71 [ find-default default set ]
72 [ <big-dispatch-engine> ]
77 : single-combination ( word -- quot )
78 [ <standard-engine> engine>quot ] with-scope ;
80 ERROR: inconsistent-next-method class generic ;
82 ERROR: no-next-method class generic ;
84 : single-next-method-quot ( class generic -- quot )
86 [ drop "predicate" word-prop % ]
90 [ [ no-next-method ] 2curry [ ] like ] if* ,
92 [ [ inconsistent-next-method ] 2curry , ]
97 : single-effective-method ( obj word -- method )
98 [ [ order [ instance? ] with find-last nip ] keep method ]
99 [ "default-method" word-prop ]
102 TUPLE: standard-combination # ;
104 C: <standard-combination> standard-combination
106 PREDICATE: standard-generic < generic
107 "combination" word-prop standard-combination? ;
109 PREDICATE: simple-generic < standard-generic
110 "combination" word-prop #>> zero? ;
112 : define-simple-generic ( word -- )
113 T{ standard-combination f 0 } define-generic ;
115 : with-standard ( combination quot -- quot' )
116 [ #>> (dispatch#) ] dip with-variable ; inline
118 M: standard-generic extra-values drop 0 ;
120 M: standard-combination make-default-method
121 [ error-method ] with-standard ;
123 M: standard-combination perform-combination
124 [ drop ] [ [ single-combination ] with-standard ] 2bi define ;
126 M: standard-combination dispatch# #>> ;
128 M: standard-combination method-declaration
129 dispatch# object <array> swap prefix [ declare ] curry [ ] like ;
131 M: standard-combination next-method-quot*
133 single-next-method-quot picker prepend
136 M: standard-generic effective-method
137 [ dispatch# (picker) call ] keep single-effective-method ;
139 TUPLE: hook-combination var ;
141 C: <hook-combination> hook-combination
143 PREDICATE: hook-generic < generic
144 "combination" word-prop hook-combination? ;
146 : with-hook ( combination quot -- quot' )
148 dip var>> [ get ] curry prepend
149 ] with-variable ; inline
151 M: hook-combination dispatch# drop 0 ;
153 M: hook-combination method-declaration 2drop [ ] ;
155 M: hook-generic extra-values drop 1 ;
157 M: hook-generic effective-method
158 [ "combination" word-prop var>> get ] keep
159 single-effective-method ;
161 M: hook-combination make-default-method
162 [ error-method ] with-hook ;
164 M: hook-combination perform-combination
165 [ drop ] [ [ single-combination ] with-hook ] 2bi define ;
167 M: hook-combination next-method-quot*
168 [ single-next-method-quot ] with-hook ;
170 M: simple-generic definer drop \ GENERIC: f ;
172 M: standard-generic definer drop \ GENERIC# f ;
174 M: hook-generic definer drop \ HOOK: f ;