1 ! Copyright (C) 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: kernel effects accessors math math.private
4 math.integers.private math.partial-dispatch math.intervals
5 math.parser math.order layouts words sequences sequences.private
6 arrays assocs classes classes.algebra combinators generic.math
7 splitting fry locals classes.tuple alien.accessors
8 classes.tuple.private slots.private definitions strings.private
9 vectors hashtables generic quotations
11 compiler.tree.comparisons
12 compiler.tree.propagation.info
13 compiler.tree.propagation.nodes
14 compiler.tree.propagation.slots
15 compiler.tree.propagation.simple
16 compiler.tree.propagation.constraints
17 compiler.tree.propagation.call-effect
18 compiler.tree.propagation.transforms ;
19 IN: compiler.tree.propagation.known-words
22 [ { number number } "input-classes" set-word-prop ] each
25 [ { real real } "input-classes" set-word-prop ] each
28 [ { rational rational } "input-classes" set-word-prop ] each
30 { bitand bitor bitxor bitnot shift }
31 [ { integer integer } "input-classes" set-word-prop ] each
33 \ bitnot { integer } "input-classes" set-word-prop
35 : ?change-interval ( info quot -- quot' )
36 over interval>> [ [ clone ] dip change-interval ] [ 2drop ] if ; inline
38 { bitnot fixnum-bitnot bignum-bitnot } [
39 [ [ interval-bitnot ] ?change-interval ] "outputs" set-word-prop
42 \ abs [ [ interval-abs ] ?change-interval ] "outputs" set-word-prop
44 : math-closure ( class -- newclass )
45 { fixnum bignum integer rational float real number object }
46 [ class<= ] with find nip ;
48 : fits-in-fixnum? ( interval -- ? )
49 fixnum-interval interval-subset? ;
51 : binary-op-class ( info1 info2 -- newclass )
53 2dup [ null-class? ] either? [ 2drop null ] [
54 [ math-closure ] bi@ math-class-max
57 : binary-op-interval ( info1 info2 quot -- newinterval )
58 [ [ interval>> ] bi@ ] dip call ; inline
60 : won't-overflow? ( class interval -- ? )
61 [ fixnum class<= ] [ fits-in-fixnum? ] bi* and ;
63 : may-overflow ( class interval -- class' interval' )
66 [ [ integer math-class-max ] dip ] unless
69 : may-be-rational ( class interval -- class' interval' )
71 [ rational math-class-max ] dip
74 : ensure-math-class ( class must-be -- class' )
77 : number-valued ( class interval -- class' interval' )
78 [ number ensure-math-class ] dip ;
80 : integer-valued ( class interval -- class' interval' )
81 [ integer ensure-math-class ] dip ;
83 : real-valued ( class interval -- class' interval' )
84 [ real ensure-math-class ] dip ;
86 : float-valued ( class interval -- class' interval' )
91 : binary-op ( word interval-quot post-proc-quot -- )
93 [ binary-op-class ] [ _ binary-op-interval ] 2bi
96 ] "outputs" set-word-prop ;
98 \ + [ [ interval+ ] [ may-overflow number-valued ] binary-op ] each-derived-op
99 \ + [ [ interval+ ] [ number-valued ] binary-op ] each-fast-derived-op
101 \ - [ [ interval- ] [ may-overflow number-valued ] binary-op ] each-derived-op
102 \ - [ [ interval- ] [ number-valued ] binary-op ] each-fast-derived-op
104 \ * [ [ interval* ] [ may-overflow number-valued ] binary-op ] each-derived-op
105 \ * [ [ interval* ] [ number-valued ] binary-op ] each-fast-derived-op
107 \ / [ [ interval/-safe ] [ may-be-rational number-valued ] binary-op ] each-derived-op
108 \ /i [ [ interval/i ] [ may-overflow integer-valued ] binary-op ] each-derived-op
109 \ /f [ [ interval/f ] [ float-valued ] binary-op ] each-derived-op
111 \ mod [ [ interval-mod ] [ real-valued ] binary-op ] each-derived-op
112 \ rem [ [ interval-rem ] [ may-overflow real-valued ] binary-op ] each-derived-op
114 { /mod fixnum/mod } [
116 [ "outputs" word-prop ] bi@
117 '[ _ _ 2bi ] "outputs" set-word-prop
120 \ shift [ [ interval-shift-safe ] [ may-overflow integer-valued ] binary-op ] each-derived-op
121 \ shift [ [ interval-shift-safe ] [ integer-valued ] binary-op ] each-fast-derived-op
123 \ bitand [ [ interval-bitand ] [ integer-valued ] binary-op ] each-derived-op
124 \ bitor [ [ interval-bitor ] [ integer-valued ] binary-op ] each-derived-op
125 \ bitxor [ [ interval-bitxor ] [ integer-valued ] binary-op ] each-derived-op
127 :: (comparison-constraints) ( in1 in2 op -- constraint )
128 [let | i1 [ in1 value-info interval>> ]
129 i2 [ in2 value-info interval>> ] |
130 in1 i1 i2 op assumption is-in-interval
131 in2 i2 i1 op swap-comparison assumption is-in-interval
135 :: comparison-constraints ( in1 in2 out op -- constraint )
136 in1 in2 op (comparison-constraints) out t-->
137 in1 in2 op negate-comparison (comparison-constraints) out f--> /\ ;
139 : define-comparison-constraints ( word op -- )
140 '[ _ comparison-constraints ] "constraints" set-word-prop ;
143 [ dup '[ _ define-comparison-constraints ] each-derived-op ] each
145 ! Remove redundant comparisons
146 : fold-comparison ( info1 info2 word -- info )
147 [ [ interval>> ] bi@ ] dip interval-comparison {
148 { incomparable [ object-info ] }
149 { t [ t <literal-info> ] }
150 { f [ f <literal-info> ] }
155 [ _ fold-comparison ] "outputs" set-word-prop
159 generic-comparison-ops [
160 dup specific-comparison
161 '[ _ fold-comparison ] "outputs" set-word-prop
164 : maybe-or-never ( ? -- info )
165 [ object-info ] [ f <literal-info> ] if ;
167 : info-intervals-intersect? ( info1 info2 -- ? )
168 2dup [ class>> real class<= ] both?
169 [ [ interval>> ] bi@ intervals-intersect? ] [ 2drop t ] if ;
171 { number= bignum= float= } [
173 info-intervals-intersect? maybe-or-never
174 ] "outputs" set-word-prop
177 : info-classes-intersect? ( info1 info2 -- ? )
178 [ class>> ] bi@ classes-intersect? ;
181 over value-info literal>> fixnum? [
182 [ value-info literal>> is-equal-to ] dip t-->
184 ] "constraints" set-word-prop
187 [ info-intervals-intersect? ]
188 [ info-classes-intersect? ]
189 2bi and maybe-or-never
190 ] "outputs" set-word-prop
194 { [ 2dup [ fixnum classes-intersect? not ] either? ] [ f <literal-info> ] }
195 { [ 2dup [ fixnum class<= ] both? ] [ t <literal-info> ] }
198 ] "outputs" set-word-prop
202 { bignum>fixnum fixnum }
205 { fixnum>bignum bignum }
206 { float>bignum bignum }
209 { fixnum>float float }
210 { bignum>float float }
214 '[ _ swap interval>> <class/interval-info> ] "outputs" set-word-prop
217 { numerator denominator }
218 [ [ drop integer <class-info> ] "outputs" set-word-prop ] each
220 { (log2) fixnum-log2 bignum-log2 } [
222 [ class>> ] [ interval>> interval-log2 ] bi <class/interval-info>
223 ] "outputs" set-word-prop
227 2drop fixnum 0 23 2^ [a,b] <class/interval-info>
228 ] "outputs" set-word-prop
242 [ "alien-signed-" ?head ]
243 [ string>number 8 * 1 - 2^ dup neg swap 1 - [a,b] ]
246 [ "alien-unsigned-" ?head ]
247 [ string>number 8 * 2^ 1 - 0 swap [a,b] ]
250 [ fits-in-fixnum? fixnum integer ? ] keep <class/interval-info>
251 '[ 2drop _ ] "outputs" set-word-prop
254 { <tuple> <tuple-boa> } [
256 literal>> dup array? [ first ] [ drop tuple ] if <class-info>
258 ] "outputs" set-word-prop
262 literal>> dup tuple-class? [ drop tuple ] unless <class-info>
263 ] "outputs" set-word-prop
265 ! the output of clone has the same type as the input
267 [ clone f >>literal f >>literal? ]
268 "outputs" set-word-prop
273 [ literal>> swap value-info-slot ] [ 2drop object-info ] if
274 ] "outputs" set-word-prop
277 [ value-info ] dip over literal>> class? [
278 [ literal>> ] dip predicate-constraints
280 ] "constraints" set-word-prop
283 ! We need to force the caller word to recompile when the class
284 ! is redefined, since now we're making assumptions but the
285 ! class definition itself.
289 [ inlined-dependency depends-on ]
290 [ predicate-output-infos ]
292 ] [ 2drop object-info ] if
293 ] "outputs" set-word-prop