1 ! Copyright (C) 2005, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 IN: optimizer.known-words
4 USING: accessors alien arrays generic hashtables definitions
5 inference.dataflow inference.state inference.class kernel assocs
6 math math.order math.private kernel.private sequences words
7 parser vectors strings sbufs io namespaces assocs quotations
8 sequences.private io.binary io.streams.string layouts splitting
9 math.intervals math.floats.private classes.tuple classes.predicate
10 classes.tuple.private classes classes.algebra optimizer.def-use
11 optimizer.backend optimizer.pattern-match optimizer.inlining
12 float-arrays sequences.private combinators byte-arrays
15 { <tuple> <tuple-boa> (tuple) } [
17 dup node-in-d peek node-literal
18 dup tuple-layout? [ class>> ] [ drop tuple ] if
20 ] "output-classes" set-word-prop
24 dup node-in-d peek node-literal
25 dup class? [ drop tuple ] unless 1array f
26 ] "output-classes" set-word-prop
28 ! if the input to new is a literal tuple class, we can expand it
29 : literal-new? ( #call -- ? )
30 dup in-d>> first node-literal tuple-class? ;
32 : new-quot ( class -- quot )
33 dup all-slots 1 tail ! delegate slot
34 [ [ initial>> literalize , ] each literalize , \ boa , ] [ ] make ;
36 : expand-new ( #call -- node )
37 dup dup in-d>> first node-literal
38 [ +inlined+ depends-on ] [ new-quot ] bi
42 { [ dup literal-new? ] [ expand-new ] }
45 ! the output of clone has the same type as the input
48 node-in-d [ value-class* ] map f
49 ] "output-classes" set-word-prop
52 ! not [ A ] [ B ] if ==> [ B ] [ A ] if
53 : flip-branches? ( #call -- ? ) sole-consumer #if? ;
55 : (flip-branches) ( #if -- )
56 dup node-children reverse swap set-node-children ;
58 : flip-branches ( #call -- #if )
59 #! If a not is followed by an #if, flip branches and
61 dup sole-consumer (flip-branches) [ ] f splice-quot ;
64 { [ dup flip-branches? ] [ flip-branches ] }
67 ! eq? on objects of disjoint types is always f
68 : disjoint-eq? ( node -- ? )
69 node-input-classes first2 2dup and
70 [ classes-intersect? not ] [ 2drop f ] if ;
73 { [ dup disjoint-eq? ] [ [ f ] inline-literals ] }
76 : literal-member? ( #call -- ? )
77 node-in-d peek dup value?
78 [ value-literal sequence? ] [ drop f ] if ;
80 : expand-member ( #call quot -- )
81 >r dup node-in-d peek value-literal r> call f splice-quot ;
83 : bit-member-n 256 ; inline
85 : bit-member? ( seq -- ? )
86 #! Can we use a fast byte array test here?
88 { [ dup length 8 < ] [ f ] }
89 { [ dup [ integer? not ] contains? ] [ f ] }
90 { [ dup [ 0 < ] contains? ] [ f ] }
91 { [ dup [ bit-member-n >= ] contains? ] [ f ] }
95 : bit-member-seq ( seq -- flags )
96 bit-member-n swap [ member? 1 0 ? ] curry B{ } map-as ;
98 : exact-float? ( f -- ? )
99 dup float? [ dup >integer >float = ] [ drop f ] if ; inline
101 : bit-member-quot ( seq -- newquot )
103 [ drop ] % ! drop the sequence itself; we don't use it at run time
107 { [ over fixnum? ] [ ?nth 1 eq? ] }
108 { [ over bignum? ] [ ?nth 1 eq? ] }
109 { [ over exact-float? ] [ ?nth 1 eq? ] }
115 : member-quot ( seq -- newquot )
119 [ literalize [ t ] ] { } map>assoc
120 [ drop f ] suffix [ nip case ] curry
124 { [ dup literal-member? ] [ [ member-quot ] expand-member ] }
127 : memq-quot ( seq -- newquot )
128 [ [ dupd eq? ] curry [ drop t ] ] { } map>assoc
129 [ drop f ] suffix [ nip cond ] curry ;
132 { [ dup literal-member? ] [ [ memq-quot ] expand-member ] }
135 ! if the result of eq? is t and the second input is a literal,
136 ! the first input is equal to the second
138 dup node-in-d second dup value? [
140 value-literal 0 `input literal,
141 \ f class-not 0 `output class,
146 ] "constraints" set-word-prop
148 ! open-code instance? checks on predicate classes
149 : literal-predicate-class? ( #call -- ? )
150 dup in-d>> second node-literal predicate-class? ;
152 : expand-predicate-instance ( #call -- node )
153 dup dup in-d>> second node-literal
154 [ +inlined+ depends-on ]
155 [ "predicate-definition" word-prop [ drop ] prepose ] bi
158 \ predicate-instance? {
159 { [ dup literal-predicate-class? ] [ expand-predicate-instance ] }
162 ! eq? on the same object is always t
164 { { @ @ } [ 2drop t ] }
168 { first first2 first3 first4 }
169 [ { array } "specializer" set-word-prop ] each
171 { peek pop* pop push } [
172 { vector } "specializer" set-word-prop
176 { { string sbuf } { array vector } { byte-array byte-vector } }
177 "specializer" set-word-prop
180 { { string string } { array array } }
181 "specializer" set-word-prop
184 { { fixnum fixnum string } { fixnum fixnum array } }
185 "specializer" set-word-prop
188 { { string } { array } }
189 "specializer" set-word-prop
193 "specializer" set-word-prop
195 \ find-last-sep { string sbuf } "specializer" set-word-prop
197 \ >string { sbuf } "specializer" set-word-prop
199 \ >array { { string } { vector } } "specializer" set-word-prop
201 \ >vector { { array } { vector } } "specializer" set-word-prop
203 \ >sbuf { string } "specializer" set-word-prop
205 \ split, { string string } "specializer" set-word-prop
207 \ memq? { array } "specializer" set-word-prop
209 \ member? { fixnum string } "specializer" set-word-prop
211 \ assoc-stack { vector } "specializer" set-word-prop
213 \ >le { { fixnum fixnum } { bignum fixnum } } "specializer" set-word-prop
215 \ >be { { bignum fixnum } { fixnum fixnum } } "specializer" set-word-prop