| 
									
										
										
										
											2008-07-30 04:38:10 -04:00
										 |  |  | ! Copyright (C) 2008 Slava Pestov. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2008-10-02 02:17:45 -04:00
										 |  |  | USING: kernel assocs arrays namespaces accessors sequences deques | 
					
						
							| 
									
										
										
										
											2008-11-16 06:53:25 -05:00
										 |  |  | search-deques dlists compiler.tree compiler.tree.combinators ;
 | 
					
						
							| 
									
										
										
										
											2008-09-12 06:17:27 -04:00
										 |  |  | IN: compiler.tree.recursive | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Collect label info | 
					
						
							|  |  |  | GENERIC: collect-label-info ( node -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #return-recursive collect-label-info | 
					
						
							|  |  |  |     dup label>> (>>return) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #call-recursive collect-label-info | 
					
						
							|  |  |  |     dup label>> calls>> push ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #recursive collect-label-info | 
					
						
							|  |  |  |     label>> V{ } clone >>calls drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: node collect-label-info drop ;
 | 
					
						
							| 
									
										
										
										
											2008-07-30 04:38:10 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  | ! A loop is a #recursive which only tail calls itself, and those | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  | ! calls are nested inside other loops only. We optimistically | 
					
						
							|  |  |  | ! assume all #recursive nodes are loops, disqualifying them as | 
					
						
							|  |  |  | ! we see evidence to the contrary. | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  | : (tail-calls) ( tail? seq -- seq' )
 | 
					
						
							|  |  |  |     reverse [ swap [ and ] keep ] map nip reverse ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : tail-calls ( tail? node -- seq )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ #phi? ] | 
					
						
							|  |  |  |         [ #return? ] | 
					
						
							|  |  |  |         [ #return-recursive? ] | 
					
						
							|  |  |  |         tri or or
 | 
					
						
							|  |  |  |     ] map (tail-calls) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  | SYMBOL: loop-heights | 
					
						
							|  |  |  | SYMBOL: loop-calls | 
					
						
							| 
									
										
										
										
											2008-08-10 23:22:26 -04:00
										 |  |  | SYMBOL: loop-stack | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  | SYMBOL: work-list | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  | GENERIC: collect-loop-info* ( tail? node -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : non-tail-label-info ( nodes -- )
 | 
					
						
							|  |  |  |     [ f swap collect-loop-info* ] each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (collect-loop-info) ( tail? nodes -- )
 | 
					
						
							|  |  |  |     [ tail-calls ] keep [ collect-loop-info* ] 2each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  | : remember-loop-info ( label -- )
 | 
					
						
							| 
									
										
										
										
											2008-08-10 23:22:26 -04:00
										 |  |  |     loop-stack get length swap loop-heights get set-at ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #recursive collect-loop-info* | 
					
						
							|  |  |  |     [ | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  |         [ | 
					
						
							|  |  |  |             label>> | 
					
						
							| 
									
										
										
										
											2008-10-02 02:17:45 -04:00
										 |  |  |             [ swap 2array loop-stack [ swap suffix ] change ] | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  |             [ remember-loop-info ] | 
					
						
							|  |  |  |             [ t >>loop? drop ] | 
					
						
							|  |  |  |             tri
 | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         [ t swap child>> (collect-loop-info) ] bi
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  |     ] with-scope ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-02 02:17:45 -04:00
										 |  |  | : current-loop-nesting ( label -- alist )
 | 
					
						
							| 
									
										
										
										
											2008-08-10 23:22:26 -04:00
										 |  |  |     loop-stack get swap loop-heights get at tail ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : disqualify-loop ( label -- )
 | 
					
						
							|  |  |  |     work-list get push-front ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  | M: #call-recursive collect-loop-info* | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  |     label>> | 
					
						
							|  |  |  |     swap [ dup disqualify-loop ] unless
 | 
					
						
							| 
									
										
										
										
											2008-10-02 02:17:45 -04:00
										 |  |  |     dup current-loop-nesting | 
					
						
							|  |  |  |     [ keys [ loop-calls get push-at ] with each ] | 
					
						
							|  |  |  |     [ [ nip not ] assoc-filter keys [ disqualify-loop ] each ] | 
					
						
							|  |  |  |     bi ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #if collect-loop-info* | 
					
						
							|  |  |  |     children>> [ (collect-loop-info) ] with each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #dispatch collect-loop-info* | 
					
						
							|  |  |  |     children>> [ (collect-loop-info) ] with each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: node collect-loop-info* 2drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : collect-loop-info ( node -- )
 | 
					
						
							| 
									
										
										
										
											2008-08-10 23:22:26 -04:00
										 |  |  |     { } loop-stack set
 | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  |     H{ } clone loop-calls set
 | 
					
						
							|  |  |  |     H{ } clone loop-heights set
 | 
					
						
							|  |  |  |     <hashed-dlist> work-list set
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  |     t swap (collect-loop-info) ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  | : disqualify-loops ( -- )
 | 
					
						
							|  |  |  |     work-list get [ | 
					
						
							|  |  |  |         dup loop?>> [ | 
					
						
							|  |  |  |             [ f >>loop? drop ] | 
					
						
							|  |  |  |             [ loop-calls get at [ disqualify-loop ] each ] | 
					
						
							|  |  |  |             bi
 | 
					
						
							|  |  |  |         ] [ drop ] if
 | 
					
						
							| 
									
										
										
										
											2008-08-27 06:54:01 -04:00
										 |  |  |     ] slurp-deque ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 02:58:39 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-12 06:17:27 -04:00
										 |  |  | : analyze-recursive ( nodes -- nodes )
 | 
					
						
							|  |  |  |     dup [ collect-label-info ] each-node | 
					
						
							| 
									
										
										
										
											2008-08-10 20:22:13 -04:00
										 |  |  |     dup collect-loop-info disqualify-loops ;
 |