1 ! Copyright (C) 2006, 2010 Slava Pestov, Daniel Ehrenberg.
2 ! See https://factorcode.org/license.txt for BSD license.
3 USING: accessors arrays assocs kernel kernel.private math
4 math.order math.private quotations sequences sequences.private
8 ! Most of these combinators have compile-time expansions in
9 ! the optimizing compiler. See stack-checker.transforms and
10 ! compiler.tree.propagation.call-effect
14 : call-effect-unsafe ( quot effect -- ) drop call ;
16 : execute-effect-unsafe ( word effect -- ) drop execute ;
19 ERROR-HANDLER-QUOT special-object [ die ] or
20 ( error -- * ) call-effect-unsafe ;
24 ERROR: wrong-values quot call-site ;
26 ! We can't USE: effects here so we forward reference slots instead
31 : call-effect ( quot effect -- )
32 ! Don't use fancy combinators here, since this word always
35 [ [ get-datastack ] dip dip ] dip
36 dup terminated?>> [ 2drop f ] [
37 dup in>> length swap out>> length
41 [ 2drop ] [ wrong-values ] if ;
43 : execute-effect ( word effect -- )
44 [ [ execute ] curry ] dip call-effect ;
50 : cleave>quot ( seq -- quot )
51 [ [ keep ] curry ] map concat [ drop ] append [ ] like ;
54 : 2cleave ( x y seq -- )
55 [ 2keep ] each 2drop ;
57 : 2cleave>quot ( seq -- quot )
58 [ [ 2keep ] curry ] map concat [ 2drop ] append [ ] like ;
61 : 3cleave ( x y z seq -- )
62 [ 3keep ] each 3drop ;
64 : 3cleave>quot ( seq -- quot )
65 [ [ 3keep ] curry ] map concat [ 3drop ] append [ ] like ;
68 : 4cleave ( w x y z seq -- )
69 [ 4keep ] each 4drop ;
71 : 4cleave>quot ( seq -- quot )
72 [ [ 4keep ] curry ] map concat [ 4drop ] append [ ] like ;
75 : shallow-spread>quot ( seq -- quot )
76 [ ] [ [ dup empty? [ [ dip ] curry ] unless ] dip append ] reduce ;
78 : deep-spread>quot ( seq -- quot )
79 [ ] [ [ [ dip ] curry ] dip append ] reduce ;
81 : spread ( objs... seq -- )
82 deep-spread>quot call ;
88 [ dup callable? [ drop t ] [ first call ] if ] find nip
89 [ dup callable? [ call ] [ second call ] if ]
92 : alist>quot ( default assoc -- quot )
93 [ rot \ if 3array append [ ] like ] assoc-each ;
95 : cond>quot ( assoc -- quot )
96 [ dup pair? [ [ t ] swap 2array ] unless ] map
97 reverse! [ no-cond ] swap alist>quot ;
100 ERROR: no-case object ;
102 : case-find ( obj assoc -- obj' )
105 dupd first dup word? [
108 dup wrapper? [ wrapped>> ] when
113 \ case-find t "no-compile" set-word-prop
115 : case ( obj assoc -- )
117 { [ dup array? ] [ nip second call ] }
118 { [ dup callable? ] [ call ] }
119 { [ dup not ] [ drop no-case ] }
122 : linear-case-quot ( default assoc -- quot )
124 [ 1quotation \ dup prefix \ = suffix ]
125 [ \ drop prefix ] bi*
126 ] assoc-map reverse! alist>quot ;
130 : (distribute-buckets) ( buckets pair keys -- )
132 drop [ swap adjoin ] curry each
135 [ 2dup ] dip hashcode pick length rem rot nth adjoin
139 : <buckets> ( initial length -- array )
140 next-power-of-2 <iota> swap [ nip clone ] curry map ;
142 : distribute-buckets ( alist initial quot -- buckets )
143 swapd [ [ dup first ] dip call 2array ] curry map
144 [ length <buckets> dup ] keep
145 [ first2 (distribute-buckets) ] with each ; inline
147 : hash-case-table ( default assoc -- array )
148 V{ } [ 1array ] distribute-buckets [
149 [ [ literalize ] dip ] assoc-map linear-case-quot
152 : hash-dispatch-quot ( table -- quot )
153 [ length 1 - [ fixnum-bitand ] curry ] keep
154 [ dispatch ] curry append ;
156 : hash-case-quot ( default assoc -- quot )
157 hash-case-table hash-dispatch-quot
158 [ dup hashcode >fixnum ] prepend ;
160 : contiguous-range? ( keys -- ? )
161 dup [ fixnum? ] all? [
163 [ length ] [ supremum ] [ infimum ] tri - - 1 =
167 : dispatch-case-quot ( default assoc -- quot )
169 [ keys [ infimum ] [ supremum ] bi over ]
170 [ sort-keys values [ >quotation ] map ] bi
173 integer>fixnum-strict dup _ _ between? [
181 : case>quot ( default assoc -- quot )
183 { [ dup empty? ] [ 2drop ] }
184 { [ dup [ length 4 <= ] [ [ word? ] any? ] bi or ] [ drop linear-case-quot ] }
185 { [ dup contiguous-range? ] [ drop dispatch-case-quot ] }
186 { [ dup [ wrapper? ] none? ] [ drop hash-case-quot ] }
187 { [ dup [ wrapper? ] all? ] [ drop [ [ wrapped>> ] dip ] assoc-map hash-case-quot ] }
188 [ drop linear-case-quot ]
191 : to-fixed-point ( ... object quot: ( ... object(n) -- ... object(n+1) ) -- ... object(n) )
192 [ keep over = ] keep [ to-fixed-point ] curry unless ; inline recursive