1 ! Copyright (C) 2005, 2006 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: arrays errors generic hashtables inference kernel
5 math math-internals sequences words parser ;
7 ! A system for associating dataflow optimizers with words.
9 : optimizer-hooks ( node -- conditions )
10 node-param "optimizer-hooks" word-prop ;
12 : optimize-hooks ( node -- node/t )
13 dup optimizer-hooks cond ;
15 : define-optimizers ( word optimizers -- )
16 { [ t ] [ drop t ] } add "optimizer-hooks" set-word-prop ;
18 : partial-eval? ( #call -- ? )
19 dup node-param "foldable" word-prop [
20 dup node-in-d [ node-literal? ] all-with?
25 : literal-in-d ( #call -- inputs )
26 dup node-in-d [ node-literal ] map-with ;
28 : partial-eval ( #call -- node )
29 dup literal-in-d over node-param
30 [ with-datastack ] catch
31 [ 3drop t ] [ inline-literals ] if ;
33 : call>no-op ( not -- node/f )
34 #! Note: cloning the vectors, since subst-values will modify
36 [ node-in-d clone ] keep
37 [ node-out-d clone ] keep
38 [ subst-values ] keep node-successor ;
40 : flip-branches ( not -- #if )
41 #! If a not is followed by an #if, flip branches and
44 dup node-children reverse swap set-node-children ;
46 ! An if following a not flips the two branches
48 { [ dup node-successor #if? ] [ flip-branches ] }
51 ! eq? on objects of disjoint types is always f
52 : disjoint-eq? ( node -- ? )
53 dup node-classes swap node-in-d
54 [ swap ?hash ] map-with
55 first2 2dup and [ classes-intersect? not ] [ 2drop f ] if ;
58 { [ dup disjoint-eq? ] [ [ f ] inline-literals ] }
61 ! type applied to an object of a known type can be folded
62 : known-type? ( node -- ? )
63 0 node-class# types length 1 number= ;
65 : fold-known-type ( node -- node )
66 dup 0 node-class# types first 1array inline-literals ;
69 { [ dup known-type? ] [ fold-known-type ] }
72 ! Arithmetic identities
75 : define-identities ( words identities -- )
76 swap [ swap "identities" set-word-prop ] each-with ;
78 : literals-match? ( values template -- ? )
80 over value? [ >r value-literal r> ] [ nip @ ] if =
83 : values-match? ( values template -- ? )
84 [ @ = [ drop f ] unless ] 2map [ ] subset all-eq? ;
86 : apply-identity? ( values identity -- ? )
87 first 2dup literals-match? >r values-match? r> and ;
89 : find-identity ( node -- values identity )
90 dup node-in-d swap node-param "identities" word-prop
91 [ dupd apply-identity? ] find nip ;
93 : apply-identities ( node -- node/f )
94 dup find-identity dup [
95 second swap dataflow-with [ subst-node ] keep
100 [ + fixnum+ bignum+ float+ ] {
105 [ - fixnum- bignum- float- ] {
107 { { @ @ } [ 2drop 0 ] }
110 [ * fixnum* bignum* float* ] {
115 { { @ -1 } [ drop 0 swap - ] }
116 { { -1 @ } [ nip 0 swap - ] }
119 [ / fixnum/i bignum/i float/f ] {
121 { { @ -1 } [ drop 0 swap - ] }
124 [ fixnum-mod bignum-mod ] {
125 { { @ 1 } [ 2drop 0 ] }
128 [ bitand fixnum-bitand bignum-bitand ] {
129 { { @ -1 } [ drop ] }
136 [ bitor fixnum-bitor bignum-bitor ] {
141 { { -1 @ } [ drop ] }
144 [ bitxor fixnum-bitxor bignum-bitxor ] {
147 { { @ -1 } [ drop bitnot ] }
148 { { -1 @ } [ nip bitnot ] }
149 { { @ @ } [ 2drop 0 ] }
152 [ shift fixnum-shift bignum-shift ] {
157 [ < fixnum< bignum< float< ] {
158 { { @ @ } [ 2drop f ] }
161 [ <= fixnum<= bignum<= float<= ] {
162 { { @ @ } [ 2drop t ] }
165 [ > fixnum> bignum> float>= ] {
166 { { @ @ } [ 2drop f ] }
169 [ >= fixnum>= bignum>= float>= ] {
170 { { @ @ } [ 2drop t ] }
173 [ eq? bignum= float= number= = ] {
174 { { @ @ } [ 2drop t ] }
177 M: #call optimize-node*
179 { [ dup partial-eval? ] [ partial-eval ] }
180 { [ dup find-identity nip ] [ apply-identities ] }
181 { [ dup optimizer-hooks ] [ optimize-hooks ] }
182 { [ dup optimize-predicate? ] [ optimize-predicate ] }
183 { [ t ] [ inline-method ] }