1 ! Copyright (C) 2004, 2006 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: arrays definitions errors hashtables kernel
5 kernel-internals namespaces sequences strings words
8 PREDICATE: word class ( obj -- ? ) "class" word-prop ;
14 PREDICATE: word builtin ( obj -- ? ) builtins get memq? ;
16 : classes ( -- seq ) class<map get hash-keys ;
18 : type>class ( n -- class ) builtins get nth ;
20 : predicate-word ( word -- predicate )
21 word-name "?" append create-in ;
23 : predicate-effect 1 1 <effect> ;
25 : define-predicate ( class predicate quot -- )
27 over predicate-effect "declared-effect" set-word-prop
29 2dup unit "predicate" set-word-prop
30 swap "predicating" set-word-prop
35 : superclass ( class -- super ) "superclass" word-prop ;
37 : members ( class -- seq ) "members" word-prop ;
39 : (flatten-class) ( class -- )
40 dup members [ [ (flatten-class) ] each ] [ dup set ] ?if ;
42 : flatten-class ( class -- seq )
43 [ (flatten-class) ] make-hash ;
45 : (types) ( class -- )
48 [ (types) ] [ "type" word-prop dup set ] ?if
51 : types ( class -- seq )
52 [ (types) ] make-hash hash-keys natural-sort ;
56 : superclass< ( cls1 cls2 -- ? )
57 >r superclass r> 2dup and [ (class<) ] [ 2drop f ] if ;
59 : union-class< ( cls1 cls2 -- ? )
60 [ flatten-class ] 2apply hash-keys swap
61 [ drop swap [ (class<) ] contains-with? ] hash-all-with? ;
63 : class-empty? ( class -- ? )
64 members dup [ empty? ] when ;
66 : (class<) ( class1 class2 -- ? )
68 { [ 2dup eq? ] [ 2drop t ] }
69 { [ over class-empty? ] [ 2drop t ] }
70 { [ 2dup superclass< ] [ 2drop t ] }
71 { [ 2dup [ members ] 2apply or not ] [ 2drop f ] }
72 { [ t ] [ union-class< ] }
75 : class< ( class1 class2 -- ? )
76 class<map get hash hash-member? ;
78 : class-compare ( class1 class2 -- n )
79 2dup eq? [ 2drop 0 ] [ class< 1 -1 ? ] if ;
81 : lookup-union ( classes -- class )
82 typemap get hash [ object ] unless* ;
84 : types* ( class -- classes )
85 types [ type>class dup ] map>hash ;
87 : (class-or) ( class class -- class )
88 [ types* ] 2apply hash-union lookup-union ;
90 : class-or ( class1 class2 -- class )
92 { [ 2dup class< ] [ nip ] }
93 { [ 2dup swap class< ] [ drop ] }
94 { [ t ] [ (class-or) ] }
97 : (class-and) ( class class -- class )
98 [ types* ] 2apply hash-intersect lookup-union ;
100 : class-and ( class1 class2 -- class )
102 { [ 2dup class< ] [ drop ] }
103 { [ 2dup swap class< ] [ nip ] }
104 { [ t ] [ (class-and) ] }
107 : classes-intersect? ( class1 class2 -- ? )
108 class-and class-empty? not ;
110 : min-class ( class seq -- class/f )
111 [ dupd classes-intersect? ] subset dup empty? [
114 tuck [ class< ] all-with? [ peek ] [ drop f ] if
117 : smaller-classes ( class -- seq )
118 classes [ swap (class<) ] subset-with ;
120 : smaller-classes+ ( class -- )
121 [ smaller-classes [ dup ] map>hash ] keep
122 class<map get set-hash ;
124 : bigger-classes ( class -- seq )
125 classes [ (class<) ] subset-with ;
127 : bigger-classes+ ( class -- )
129 [ dupd class<map get hash set-hash ] each-with ;
131 : define-class ( class -- )
132 dup t "class" set-word-prop
133 dup dup flatten-class typemap get set-hash
134 dup smaller-classes+ bigger-classes+ ;
136 ! Predicate classes for generalized predicate dispatch.
137 : define-predicate-class ( class predicate definition -- )
139 3dup nip "definition" set-word-prop
140 pick superclass "predicate" word-prop
141 [ \ dup , % , [ drop f ] , \ if , ] [ ] make
144 PREDICATE: class predicate "definition" word-prop ;
146 ! Union classes for dispatch on multiple classes.
147 : union-predicate ( seq -- quot )
148 [ dup ] swap [ "predicate" word-prop append ] map-with
149 [ [ drop t ] 2array ] map [ drop f ] swap alist>quot ;
151 : set-members ( class members -- )
152 [ bootstrap-word ] map "members" set-word-prop ;
154 : define-union ( class predicate members -- )
155 3dup nip set-members pick define-class
156 union-predicate define-predicate ;
158 PREDICATE: class union members ;
160 ! Definition protocol
161 : smaller-classes- ( class -- )
162 class<map get remove-hash ;
164 : bigger-classes- ( class -- )
165 classes [ class<map get hash remove-hash ] each-with ;
167 : forget-class ( class -- )
168 dup subdefs [ forget ] each
169 dup "predicate" word-prop [ forget ] each
170 dup dup flatten-class typemap get remove-hash forget-word
171 dup smaller-classes- bigger-classes- ;
173 M: class forget forget-class ;