| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | ! Copyright (C) 2008 Slava Pestov. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							|  |  |  | USING: sequences kernel sets namespaces accessors assocs | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | arrays combinators continuations columns math vectors | 
					
						
							| 
									
										
										
										
											2009-01-16 16:14:30 -05:00
										 |  |  | grouping stack-checker.branches | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | compiler.tree | 
					
						
							|  |  |  | compiler.tree.def-use | 
					
						
							| 
									
										
										
										
											2009-08-04 20:18:40 -04:00
										 |  |  | compiler.tree.recursive | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | compiler.tree.combinators ;
 | 
					
						
							| 
									
										
										
										
											2010-02-26 16:01:01 -05:00
										 |  |  | FROM: namespaces => set ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | IN: compiler.tree.checker | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | ! Check some invariants; this can help catch compiler bugs. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | ERROR: check-use-error value message ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-use ( value uses -- )
 | 
					
						
							|  |  |  |     [ empty? [ "No use" check-use-error ] [ drop ] if ] | 
					
						
							|  |  |  |     [ all-unique? [ drop ] [ "Uses not all unique" check-use-error ] if ] 2bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-def-use ( -- )
 | 
					
						
							|  |  |  |     def-use get [ uses>> check-use ] assoc-each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | GENERIC: check-node* ( node -- )
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | M: #shuffle check-node* | 
					
						
							| 
									
										
										
										
											2008-11-11 19:46:31 -05:00
										 |  |  |     [ [ mapping>> values ] [ [ in-d>> ] [ in-r>> ] bi append ] bi subset? [ "Bad mapping inputs" throw ] unless ] | 
					
						
							|  |  |  |     [ [ mapping>> keys ] [ [ out-d>> ] [ out-r>> ] bi append ] bi set= [ "Bad mapping outputs" throw ] unless ] | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  |     bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-lengths ( seq -- )
 | 
					
						
							|  |  |  |     [ length ] map all-equal? [ "Bad lengths" throw ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | M: #copy check-node* inputs/outputs 2array check-lengths ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | M: #return-recursive check-node* inputs/outputs 2array check-lengths ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | M: #phi check-node* | 
					
						
							| 
									
										
										
										
											2008-08-18 21:49:03 -04:00
										 |  |  |     [ [ phi-in-d>> <flipped> ] [ out-d>> ] bi 2array check-lengths ] | 
					
						
							|  |  |  |     [ phi-in-d>> check-lengths ] | 
					
						
							|  |  |  |     bi ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | M: #enter-recursive check-node* | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |     [ [ label>> enter-out>> ] [ out-d>> ] bi assert= ] | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  |     [ [ in-d>> ] [ out-d>> ] bi 2array check-lengths ] | 
					
						
							| 
									
										
										
										
											2008-08-13 15:17:04 -04:00
										 |  |  |     [ recursive-phi-in check-lengths ] | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |     tri ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | M: #push check-node* | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  |     out-d>> length 1 = [ "Bad #push" throw ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | M: node check-node* drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-values ( seq -- )
 | 
					
						
							|  |  |  |     [ integer? ] all? [ "Bad values" throw ] unless ;
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | ERROR: check-node-error node error ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-14 00:52:49 -04:00
										 |  |  | : check-node ( node -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         [ node-uses-values check-values ] | 
					
						
							|  |  |  |         [ node-defs-values check-values ] | 
					
						
							|  |  |  |         [ check-node* ] | 
					
						
							|  |  |  |         tri
 | 
					
						
							|  |  |  |     ] [ check-node-error ] recover ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | SYMBOL: datastack | 
					
						
							|  |  |  | SYMBOL: retainstack | 
					
						
							| 
									
										
										
										
											2008-08-19 22:48:08 -04:00
										 |  |  | SYMBOL: terminated? | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | GENERIC: check-stack-flow* ( node -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : (check-stack-flow) ( nodes -- )
 | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |     [ check-stack-flow* terminated? get not ] all? drop ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : init-stack-flow ( -- )
 | 
					
						
							|  |  |  |     V{ } clone datastack set
 | 
					
						
							|  |  |  |     V{ } clone retainstack set ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-stack-flow ( nodes -- )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         init-stack-flow | 
					
						
							|  |  |  |         (check-stack-flow) | 
					
						
							|  |  |  |     ] with-scope ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-inputs ( seq var -- )
 | 
					
						
							|  |  |  |     [ dup length ] dip [ swap cut* swap ] change
 | 
					
						
							|  |  |  |     sequence= [ "Bad stack flow" throw ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-in-d ( node -- )
 | 
					
						
							|  |  |  |     in-d>> datastack check-inputs ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-in-r ( node -- )
 | 
					
						
							|  |  |  |     in-r>> retainstack check-inputs ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-outputs ( node var -- )
 | 
					
						
							|  |  |  |     get push-all ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-out-d ( node -- )
 | 
					
						
							|  |  |  |     out-d>> datastack check-outputs ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-out-r ( node -- )
 | 
					
						
							|  |  |  |     out-r>> retainstack check-outputs ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #introduce check-stack-flow* check-out-d ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #push check-stack-flow* check-out-d ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #call check-stack-flow* [ check-in-d ] [ check-out-d ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-11 19:46:31 -05:00
										 |  |  | M: #shuffle check-stack-flow* | 
					
						
							|  |  |  |     { [ check-in-d ] [ check-in-r ] [ check-out-d ] [ check-out-r ] } cleave ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : assert-datastack-empty ( -- )
 | 
					
						
							|  |  |  |     datastack get empty? [ "Data stack not empty" throw ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : assert-retainstack-empty ( -- )
 | 
					
						
							|  |  |  |     retainstack get empty? [ "Retain stack not empty" throw ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #return check-stack-flow* | 
					
						
							| 
									
										
										
										
											2008-08-24 02:21:23 -04:00
										 |  |  |     check-in-d | 
					
						
							|  |  |  |     assert-datastack-empty | 
					
						
							|  |  |  |     terminated? get [ assert-retainstack-empty ] unless ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #enter-recursive check-stack-flow* | 
					
						
							|  |  |  |     check-out-d ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #return-recursive check-stack-flow* | 
					
						
							|  |  |  |     [ check-in-d ] [ check-out-d ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #call-recursive check-stack-flow* | 
					
						
							|  |  |  |     [ check-in-d ] [ check-out-d ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-terminate-in-d ( #terminate -- )
 | 
					
						
							|  |  |  |     in-d>> datastack get over length tail* sequence=
 | 
					
						
							|  |  |  |     [ "Bad terminate data stack" throw ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-terminate-in-r ( #terminate -- )
 | 
					
						
							|  |  |  |     in-r>> retainstack get over length tail* sequence=
 | 
					
						
							|  |  |  |     [ "Bad terminate retain stack" throw ] unless ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #terminate check-stack-flow* | 
					
						
							| 
									
										
										
										
											2008-08-19 22:48:08 -04:00
										 |  |  |     terminated? on
 | 
					
						
							|  |  |  |     [ check-terminate-in-d ] | 
					
						
							|  |  |  |     [ check-terminate-in-r ] bi ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | SYMBOL: branch-out | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-22 22:03:53 -04:00
										 |  |  | : check-branch ( nodes -- stack )
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  |     [ | 
					
						
							|  |  |  |         datastack [ clone ] change
 | 
					
						
							| 
									
										
										
										
											2009-04-22 22:03:53 -04:00
										 |  |  |         V{ } clone retainstack set
 | 
					
						
							|  |  |  |         (check-stack-flow) | 
					
						
							|  |  |  |         terminated? get [ assert-retainstack-empty ] unless
 | 
					
						
							|  |  |  |         terminated? get f datastack get ?
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  |     ] with-scope ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: #branch check-stack-flow* | 
					
						
							|  |  |  |     [ check-in-d ] | 
					
						
							|  |  |  |     [ children>> [ check-branch ] map branch-out set ] | 
					
						
							|  |  |  |     bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : check-phi-in ( #phi -- )
 | 
					
						
							|  |  |  |     phi-in-d>> branch-out get [ | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |         dup [ | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  |             over length tail* sequence= [ | 
					
						
							|  |  |  |                 "Branch outputs don't match phi inputs" | 
					
						
							|  |  |  |                 throw
 | 
					
						
							|  |  |  |             ] unless
 | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |         ] [ | 
					
						
							|  |  |  |             2drop
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  |         ] if
 | 
					
						
							|  |  |  |     ] 2each ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : set-phi-datastack ( #phi -- )
 | 
					
						
							|  |  |  |     phi-in-d>> first length
 | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |     branch-out get [ ] find nip swap head* >vector datastack set ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #phi check-stack-flow* | 
					
						
							| 
									
										
										
										
											2009-01-29 23:19:07 -05:00
										 |  |  |     branch-out get [ ] any? [ | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |         [ check-phi-in ] [ set-phi-datastack ] [ check-out-d ] tri
 | 
					
						
							|  |  |  |     ] [ drop terminated? on ] if ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #recursive check-stack-flow* | 
					
						
							| 
									
										
										
										
											2008-08-22 04:12:15 -04:00
										 |  |  |     [ check-in-d ] [ child>> (check-stack-flow) ] bi ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #copy check-stack-flow* [ check-in-d ] [ check-out-d ] bi ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-06 22:06:07 -05:00
										 |  |  | M: #alien-node check-stack-flow* [ check-in-d ] [ check-out-d ] bi ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-28 00:49:26 -04:00
										 |  |  | M: #alien-callback check-stack-flow* child>> check-stack-flow ;
 | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: #declare check-stack-flow* drop ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-08-10 00:00:27 -04:00
										 |  |  | : check-nodes ( nodes -- )
 | 
					
						
							|  |  |  |     compute-def-use | 
					
						
							|  |  |  |     check-def-use | 
					
						
							| 
									
										
										
										
											2008-08-19 18:11:33 -04:00
										 |  |  |     [ [ check-node ] each-node ] | 
					
						
							|  |  |  |     [ check-stack-flow ] | 
					
						
							|  |  |  |     bi ;
 |