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 [ [ flatten-class keys ] keep ] 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 : single-next-method-quot ( class generic -- quot/f )
83 2dup next-method dup [
85 pick "predicate" word-prop %
87 [ inconsistent-next-method ] 2curry ,
92 : single-effective-method ( obj word -- method )
93 [ [ order [ instance? ] with find-last nip ] keep method ]
94 [ "default-method" word-prop ]
97 TUPLE: standard-combination # ;
99 C: <standard-combination> standard-combination
101 PREDICATE: standard-generic < generic
102 "combination" word-prop standard-combination? ;
104 PREDICATE: simple-generic < standard-generic
105 "combination" word-prop #>> zero? ;
107 : define-simple-generic ( word -- )
108 T{ standard-combination f 0 } define-generic ;
110 : with-standard ( combination quot -- quot' )
111 [ #>> (dispatch#) ] dip with-variable ; inline
113 M: standard-generic extra-values drop 0 ;
115 M: standard-combination make-default-method
116 [ error-method ] with-standard ;
118 M: standard-combination perform-combination
119 [ drop ] [ [ single-combination ] with-standard ] 2bi define ;
121 M: standard-combination dispatch# #>> ;
123 M: standard-combination method-declaration
124 dispatch# object <array> swap prefix [ declare ] curry [ ] like ;
126 M: standard-combination next-method-quot*
128 single-next-method-quot
129 dup [ picker prepend ] when
132 M: standard-generic effective-method
133 [ dispatch# (picker) call ] keep single-effective-method ;
135 TUPLE: hook-combination var ;
137 C: <hook-combination> hook-combination
139 PREDICATE: hook-generic < generic
140 "combination" word-prop hook-combination? ;
142 : with-hook ( combination quot -- quot' )
144 [ hook-combination ] dip with-variable
145 ] with-variable ; inline
147 : prepend-hook-var ( quot -- quot' )
148 hook-combination get var>> [ get ] curry prepend ;
150 M: hook-combination dispatch# drop 0 ;
152 M: hook-combination method-declaration 2drop [ ] ;
154 M: hook-generic extra-values drop 1 ;
156 M: hook-generic effective-method
157 [ "combination" word-prop var>> get ] keep
158 single-effective-method ;
160 M: hook-combination make-default-method
161 [ error-method prepend-hook-var ] with-hook ;
163 M: hook-combination perform-combination
165 [ single-combination prepend-hook-var ] with-hook
168 M: hook-combination next-method-quot*
170 single-next-method-quot
171 dup [ prepend-hook-var ] when
174 M: simple-generic definer drop \ GENERIC: f ;
176 M: standard-generic definer drop \ GENERIC# f ;
178 M: hook-generic definer drop \ HOOK: f ;