1 ! Copyright (C) 2004, 2006 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
4 USING: arrays generic hashtables inference kernel
5 kernel-internals math namespaces sequences words parser ;
7 ! Infer possible classes of values in a dataflow IR.
8 : node-class# ( node n -- class )
9 over node-in-d <reversed> ?nth node-class ;
11 ! Variables used by the class inferencer
13 ! Current value --> class mapping
16 ! Current value --> literal mapping
17 SYMBOL: value-literals
22 GENERIC: apply-tie ( tie -- )
26 TUPLE: class-tie value class ;
28 : set-value-class* ( class value -- )
29 2dup swap <class-tie> ties get hash [ apply-tie ] when*
30 value-classes get set-hash ;
32 M: class-tie apply-tie
33 dup class-tie-class swap class-tie-value
36 TUPLE: literal-tie value literal ;
38 : set-value-literal* ( literal value -- )
39 over class over set-value-class*
40 2dup swap <literal-tie> ties get hash [ apply-tie ] when*
41 value-literals get set-hash ;
43 M: literal-tie apply-tie
44 dup literal-tie-literal swap literal-tie-value
47 GENERIC: infer-classes* ( node -- )
49 M: node infer-classes* drop ;
51 ! For conditionals, a map of child node # --> possibility
52 GENERIC: child-ties ( node -- seq )
55 node-children length f <array> ;
57 : value-class* ( value -- class )
58 value-classes get hash [ object ] unless* ;
60 : value-literal* ( value -- class )
61 value-literals get hash ;
63 : annotate-node ( node -- )
64 #! Annotate the node with the currently-inferred set of
67 [ dup value-class* ] map>hash swap set-node-classes ;
69 : intersect-classes ( classes values -- )
71 [ value-class* class-and ] keep set-value-class*
74 : set-tie ( tie tie -- ) ties get set-hash ;
76 : type/tag-ties ( node n -- )
77 over node-out-d first over [ <literal-tie> ] map-with
78 >r swap node-in-d first swap [ type>class <class-tie> ] map-with r>
81 \ type [ num-types type/tag-ties ] "create-ties" set-word-prop
83 \ tag [ num-tags type/tag-ties ] "create-ties" set-word-prop
86 dup node-in-d second value? [
87 dup node-in-d first2 value-literal* <literal-tie>
88 over node-out-d first general-t <class-tie>
91 ] "create-ties" set-word-prop
93 : create-ties ( #call -- )
94 #! If the node is calling a class test predicate, create a
96 dup node-param "create-ties" word-prop dup [
99 drop dup node-param "predicating" word-prop dup [
100 >r dup node-in-d first r> <class-tie>
101 swap node-out-d first general-t <class-tie>
109 node-in-d first value-literal 1array
110 ] "output-classes" set-word-prop
114 node-in-d [ value-class* ] map
115 ] "output-classes" set-word-prop
118 : output-classes ( node -- seq )
119 dup node-param "output-classes" word-prop [
122 node-param "inferred-effect" word-prop effect-out
123 dup [ word? ] all? [ drop f ] unless
126 M: #call infer-classes*
127 dup create-ties dup output-classes
128 [ swap node-out-d intersect-classes ] [ drop ] if* ;
130 M: #push infer-classes*
132 [ [ value-literal ] keep set-value-literal* ] each ;
135 node-in-d first dup general-t <class-tie>
136 swap f <literal-tie> 2array ;
138 M: #dispatch child-ties
140 swap node-children length [ <literal-tie> ] map-with ;
142 M: #declare infer-classes*
143 dup node-param swap node-in-d [ set-value-class* ] 2each ;
145 DEFER: (infer-classes)
147 : infer-children ( node -- )
148 dup node-children swap child-ties [
150 value-classes [ clone ] change
151 ties [ clone ] change
157 : merge-value-class ( # nodes -- class )
158 [ swap node-class# ] map-with
159 null [ class-or ] reduce ;
161 : annotate-merge ( nodes values -- )
163 [ pick merge-value-class swap set-value-class* ] 2each
166 : active-children ( node -- seq )
169 [ #terminate? not ] subset ;
171 : merge-children ( node -- )
172 dup node-successor dup #merge? [
173 swap active-children dup empty? [
176 swap node-out-d <reversed> annotate-merge
182 : (infer-classes) ( node -- )
188 node-successor (infer-classes)
191 : ?<hashtable> [ H{ } clone ] unless* ;
193 : infer-classes-with ( node classes literals -- )
195 ?<hashtable> value-literals set
196 ?<hashtable> value-classes set
201 : infer-classes ( node -- )
202 f f infer-classes-with ;
204 : infer-classes/node ( existing node -- )
205 #! Infer classes, using the existing node's class info as a
207 over node-classes rot node-literals infer-classes-with ;