1 ! Copyright (C) 2006, 2009 Slava Pestov, Daniel Ehrenberg.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays sequences sequences.private math.private
4 kernel kernel.private math assocs quotations vectors
5 hashtables sorting words sets math.order make ;
10 : call-effect-unsafe ( quot effect -- ) drop call ;
12 : execute-effect-unsafe ( word effect -- ) drop execute ;
14 M: object throw 5 getenv [ die ] or (( error -- * )) call-effect-unsafe ;
18 ERROR: wrong-values effect ;
20 ! We can't USE: effects here so we forward reference slots instead
24 : call-effect ( quot effect -- )
25 [ [ datastack ] dip dip ] dip
26 [ in>> length ] [ out>> length ] [ ] tri [ check-datastack ] dip
27 [ wrong-values ] curry unless ;
29 : execute-effect ( word effect -- )
30 [ [ execute ] curry ] dip call-effect ;
36 : cleave>quot ( seq -- quot )
37 [ [ keep ] curry ] map concat [ drop ] append [ ] like ;
40 : 2cleave ( x y seq -- )
41 [ 2keep ] each 2drop ;
43 : 2cleave>quot ( seq -- quot )
44 [ [ 2keep ] curry ] map concat [ 2drop ] append [ ] like ;
47 : 3cleave ( x y z seq -- )
48 [ 3keep ] each 3drop ;
50 : 3cleave>quot ( seq -- quot )
51 [ [ 3keep ] curry ] map concat [ 3drop ] append [ ] like ;
54 : spread>quot ( seq -- quot )
55 [ ] [ [ dup empty? [ [ dip ] curry ] unless ] dip append ] reduce ;
57 : spread ( objs... seq -- )
64 [ dup callable? [ drop t ] [ first call ] if ] find nip
65 [ dup callable? [ call ] [ second call ] if ]
68 : alist>quot ( default assoc -- quot )
69 [ rot \ if 3array append [ ] like ] assoc-each ;
71 : cond>quot ( assoc -- quot )
72 [ dup pair? [ [ t ] swap 2array ] unless ] map
73 reverse [ no-cond ] swap alist>quot ;
76 ERROR: no-case object ;
78 : case-find ( obj assoc -- obj' )
81 dupd first dup word? [
84 dup wrapper? [ wrapped>> ] when
89 \ case-find t "no-compile" set-word-prop
91 : case ( obj assoc -- )
93 { [ dup array? ] [ nip second call ] }
94 { [ dup callable? ] [ call ] }
95 { [ dup not ] [ drop no-case ] }
98 : linear-case-quot ( default assoc -- quot )
100 [ 1quotation \ dup prefix \ = suffix ]
101 [ \ drop prefix ] bi*
102 ] assoc-map alist>quot ;
106 : (distribute-buckets) ( buckets pair keys -- )
108 drop [ swap adjoin ] curry each
111 [ 2dup ] dip hashcode pick length rem rot nth adjoin
115 : <buckets> ( initial length -- array )
116 next-power-of-2 iota swap [ nip clone ] curry map ;
118 : distribute-buckets ( alist initial quot -- buckets )
119 swapd [ [ dup first ] dip call 2array ] curry map
120 [ length <buckets> dup ] keep
121 [ first2 (distribute-buckets) ] with each ; inline
123 : hash-case-table ( default assoc -- array )
124 V{ } [ 1array ] distribute-buckets
125 [ [ [ literalize ] dip ] assoc-map linear-case-quot ] with map ;
127 : hash-dispatch-quot ( table -- quot )
128 [ length 1 - [ fixnum-bitand ] curry ] keep
129 [ dispatch ] curry append ;
131 : hash-case-quot ( default assoc -- quot )
132 hash-case-table hash-dispatch-quot
133 [ dup hashcode >fixnum ] prepend ;
135 : contiguous-range? ( keys -- ? )
136 dup [ fixnum? ] all? [
139 [ [ supremum ] [ infimum ] bi - ]
144 : dispatch-case-quot ( default assoc -- quot )
147 dup keys [ infimum , ] [ supremum , ] bi \ between? ,
149 dup keys infimum , [ - >fixnum ] %
150 sort-keys values [ >quotation ] map ,
152 ] [ ] make , , \ if ,
157 : case>quot ( default assoc -- quot )
159 { [ dup empty? ] [ 2drop ] }
160 { [ dup [ length 4 <= ] [ [ word? ] any? ] bi or ] [ drop linear-case-quot ] }
161 { [ dup contiguous-range? ] [ drop dispatch-case-quot ] }
162 { [ dup [ wrapper? ] any? not ] [ drop hash-case-quot ] }
163 { [ dup [ wrapper? ] all? ] [ drop [ [ wrapped>> ] dip ] assoc-map hash-case-quot ] }
164 [ drop linear-case-quot ]
167 : recursive-hashcode ( n obj quot -- code )
168 pick 0 <= [ 3drop 0 ] [ [ 1 - ] 2dip call ] if ; inline
170 ! These go here, not in sequences and hashtables, since those
171 ! two cannot depend on us
172 M: sequence hashcode* [ sequence-hashcode ] recursive-hashcode ;
174 M: reversed hashcode* [ sequence-hashcode ] recursive-hashcode ;
176 M: slice hashcode* [ sequence-hashcode ] recursive-hashcode ;
178 M: hashtable hashcode*
181 [ assoc-hashcode ] [ nip assoc-size ] if
182 ] recursive-hashcode ;
184 : to-fixed-point ( object quot: ( object(n) -- object(n+1) ) -- object(n) )
185 [ keep over = ] keep [ to-fixed-point ] curry unless ; inline recursive