1 ! Copyright (C) 2004, 2008 Slava Pestov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: arrays generic assocs kernel math namespaces parser
4 sequences words vectors math.intervals effects classes
5 inference.state accessors combinators ;
9 : <computed> ( -- value ) \ <computed> counter ;
12 TUPLE: value < identity-tuple literal uid recursion ;
14 : <value> ( obj -- value )
15 <computed> recursive-state get value boa ;
17 M: value hashcode* nip value-uid ;
20 TUPLE: curried obj quot ;
25 TUPLE: composed quot1 quot2 ;
27 C: <composed> composed
29 UNION: special curried composed ;
31 TUPLE: node < identity-tuple
34 classes literals intervals
35 history successor children ;
37 M: node hashcode* drop node hashcode* ;
39 GENERIC: flatten-curry ( value -- )
41 M: curried flatten-curry
42 [ obj>> flatten-curry ]
43 [ quot>> flatten-curry ] bi ;
45 M: composed flatten-curry
46 [ quot1>> flatten-curry ]
47 [ quot2>> flatten-curry ] bi ;
49 M: object flatten-curry , ;
51 : flatten-curries ( seq -- newseq )
52 dup [ special? ] contains? [
53 [ [ flatten-curry ] each ] { } make
56 : flatten-meta-d ( -- seq )
57 meta-d get clone flatten-curries ;
59 : modify-values ( node quot -- )
65 } cleave drop ; inline
67 : node-shuffle ( node -- shuffle )
68 [ in-d>> ] [ out-d>> ] bi <effect> ;
70 : param-node ( param class -- node )
71 new swap >>param ; inline
73 : in-node ( seq class -- node )
74 new swap >>in-d ; inline
76 : all-in-node ( class -- node )
77 flatten-meta-d swap in-node ; inline
79 : out-node ( seq class -- node )
80 new swap >>out-d ; inline
82 : all-out-node ( class -- node )
83 flatten-meta-d swap out-node ; inline
86 dup zero? [ drop f ] [ meta-d get swap tail* ] if ;
89 dup zero? [ drop f ] [ meta-r get swap tail* ] if ;
91 : node-child ( node -- child ) node-children first ;
93 TUPLE: #label < node word loop? returns calls ;
95 : #label ( word label -- node )
96 \ #label param-node swap >>word ;
98 PREDICATE: #loop < #label #label-loop? ;
100 TUPLE: #entry < node ;
102 : #entry ( -- node ) \ #entry all-out-node ;
104 TUPLE: #call < node ;
106 : #call ( word -- node ) \ #call param-node ;
108 TUPLE: #call-label < node ;
110 : #call-label ( label -- node ) \ #call-label param-node ;
112 TUPLE: #push < node ;
114 : #push ( -- node ) \ #push new ;
116 TUPLE: #shuffle < node ;
118 : #shuffle ( -- node ) \ #shuffle new ;
122 : #>r ( -- node ) \ #>r new ;
126 : #r> ( -- node ) \ #r> new ;
128 TUPLE: #values < node ;
130 : #values ( -- node ) \ #values all-in-node ;
132 TUPLE: #return < node ;
134 : #return ( label -- node )
135 \ #return all-in-node swap >>param ;
137 TUPLE: #branch < node ;
139 TUPLE: #if < #branch ;
141 : #if ( -- node ) peek-d 1array \ #if in-node ;
143 TUPLE: #dispatch < #branch ;
145 : #dispatch ( -- node ) peek-d 1array \ #dispatch in-node ;
147 TUPLE: #merge < node ;
149 : #merge ( -- node ) \ #merge all-out-node ;
151 TUPLE: #terminate < node ;
153 : #terminate ( -- node ) \ #terminate new ;
155 TUPLE: #declare < node ;
157 : #declare ( classes -- node ) \ #declare param-node ;
159 : node-inputs ( d-count r-count node -- )
161 [ swap d-tail flatten-curries >>in-d drop ]
162 [ swap r-tail flatten-curries >>in-r drop ] 2bi* ;
164 : node-outputs ( d-count r-count node -- )
166 [ swap d-tail flatten-curries >>out-d drop ]
167 [ swap r-tail flatten-curries >>out-r drop ] 2bi* ;
171 dup current-node [ set-node-successor ] change
173 dup dataflow-graph set current-node set
176 : node-values ( node -- values )
177 { [ in-d>> ] [ out-d>> ] [ in-r>> ] [ out-r>> ] } cleave
180 : last-node ( node -- last )
181 dup successor>> [ last-node ] [ ] ?if ;
183 : penultimate-node ( node -- penultimate )
184 dup successor>> dup [
186 [ nip penultimate-node ] [ drop ] if
191 : #drop ( n -- #shuffle )
192 d-tail flatten-curries \ #shuffle in-node ;
194 : node-exists? ( node quot -- ? )
199 >r [ children>> ] [ successor>> ] bi suffix r>
200 [ node-exists? ] curry contains?
206 GENERIC: calls-label* ( label node -- ? )
208 M: node calls-label* 2drop f ;
210 M: #call-label calls-label* param>> eq? ;
212 : calls-label? ( label node -- ? )
213 [ calls-label* ] with node-exists? ;
215 : recursive-label? ( node -- ? )
216 [ param>> ] keep calls-label? ;
220 : >node ( node -- ) node-stack get push ;
221 : node> ( -- node ) node-stack get pop ;
222 : node@ ( -- node ) node-stack get peek ;
224 : iterate-next ( -- node ) node@ successor>> ;
226 : iterate-nodes ( node quot -- )
228 [ swap >node call node> drop ] keep iterate-nodes
233 : (each-node) ( quot -- next )
234 node@ [ swap call ] 2keep
237 [ (each-node) ] keep swap
240 iterate-next ; inline
242 : with-node-iterator ( quot -- )
243 >r V{ } clone node-stack r> with-variable ; inline
245 : each-node ( node quot -- )
248 [ (each-node) ] keep swap
250 ] with-node-iterator ; inline
252 : map-children ( node quot -- )
255 [ map ] curry change-children drop
263 : (transform-nodes) ( prev node quot -- )
266 successor>> dup successor>>
269 r> 2drop f >>successor drop
272 : transform-nodes ( node quot -- new-node )
274 [ call dup dup successor>> ] keep (transform-nodes)
275 ] [ drop ] if ; inline
277 : node-literal? ( node value -- ? )
278 dup value? >r swap literals>> key? r> or ;
280 : node-literal ( node value -- obj )
282 [ nip value-literal ] [ swap literals>> at ] if ;
284 : node-interval ( node value -- interval )
285 swap intervals>> at ;
287 : node-class ( node value -- class )
288 swap classes>> at object or ;
290 : node-input-classes ( node -- seq )
291 dup in-d>> [ node-class ] with map ;
293 : node-output-classes ( node -- seq )
294 dup out-d>> [ node-class ] with map ;
296 : node-input-intervals ( node -- seq )
297 dup in-d>> [ node-interval ] with map ;
299 : node-class-first ( node -- class )
300 dup in-d>> first node-class ;
302 : active-children ( node -- seq )
303 children>> [ last-node ] map [ #terminate? not ] filter ;
307 PREDICATE: #tail-merge < #merge node-successor #tail? ;
309 PREDICATE: #tail-values < #values node-successor #tail? ;
312 POSTPONE: f #return #tail-values #tail-merge #terminate ;
314 : tail-call? ( -- ? )
315 #! We don't consider calls which do non-local exits to be
316 #! tail calls, because this gives better error traces.
318 successor>> [ #tail? ] [ #terminate? not ] bi and