101 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Factor
		
	
	
		
		
			
		
	
	
			101 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Factor
		
	
	
|  | ! Copyright (C) 2005 Mackenzie Straight. | ||
|  | ! See http://factorcode.org/license.txt for BSD license. | ||
|  | IN: dlists | ||
|  | USING: kernel math  ;
 | ||
|  | 
 | ||
|  | ! Double-linked lists. | ||
|  | 
 | ||
|  | TUPLE: dlist first last ;
 | ||
|  | 
 | ||
|  | : <dlist> dlist construct-empty ;
 | ||
|  | 
 | ||
|  | TUPLE: dlist-node data prev next ;
 | ||
|  | 
 | ||
|  | C: <dlist-node> dlist-node | ||
|  | 
 | ||
|  | : dlist-push-end ( data dlist -- )
 | ||
|  |     [ dlist-last f <dlist-node> ] keep
 | ||
|  |     [ dlist-last [ dupd set-dlist-node-next ] when* ] keep
 | ||
|  |     2dup set-dlist-last | ||
|  |     dup dlist-first [ 2drop ] [ set-dlist-first ] if ;
 | ||
|  | 
 | ||
|  | : dlist-empty? ( dlist -- ? )
 | ||
|  |     dlist-first f = ;
 | ||
|  |      | ||
|  | : (unlink-prev) ( dlist dnode -- )
 | ||
|  |     dup dlist-node-prev [ | ||
|  |         dupd swap dlist-node-next swap set-dlist-node-next | ||
|  |     ] when*
 | ||
|  |     2dup swap dlist-first eq? [  | ||
|  |         dlist-node-next swap set-dlist-first  | ||
|  |     ] [ 2drop ] if ;
 | ||
|  | 
 | ||
|  | : (unlink-next) ( dlist dnode -- )
 | ||
|  |     dup dlist-node-next [ | ||
|  |         dupd swap dlist-node-prev swap set-dlist-node-prev | ||
|  |     ] when*
 | ||
|  |     2dup swap dlist-last eq? [ | ||
|  |         dlist-node-prev swap set-dlist-last | ||
|  |     ] [ 2drop ] if ;
 | ||
|  | 
 | ||
|  | : (dlist-unlink) ( dlist dnode -- )
 | ||
|  |     [ (unlink-prev) ] 2keep (unlink-next) ;
 | ||
|  | 
 | ||
|  | : (dlist-pop-front) ( dlist -- data )
 | ||
|  |     [ dlist-first dlist-node-data ] keep dup dlist-first (dlist-unlink) ;
 | ||
|  | 
 | ||
|  | : dlist-pop-front ( dlist -- data )
 | ||
|  |     dup dlist-empty? [ drop f ] [ (dlist-pop-front) ] if ;
 | ||
|  | 
 | ||
|  | : (dlist-remove) ( dlist quot dnode -- obj/f )
 | ||
|  |     [ | ||
|  |         [ dlist-node-data swap call ] 2keep rot [ | ||
|  |             swapd [ (dlist-unlink) ] keep dlist-node-data nip
 | ||
|  |         ] [ | ||
|  |             dlist-node-next (dlist-remove) | ||
|  |         ] if
 | ||
|  |     ] [ | ||
|  |         2drop f
 | ||
|  |     ] if* ; inline
 | ||
|  | 
 | ||
|  | : dlist-remove ( quot dlist -- obj/f )
 | ||
|  |     #! Return first item in the dlist that when passed to the | ||
|  |     #! predicate quotation, true is left on the stack. The | ||
|  |     #! item is removed from the dlist. The quotation | ||
|  |     #! must have stack effect ( obj -- bool ). | ||
|  |     #! TODO: needs a better name. | ||
|  |     dup dlist-first swapd (dlist-remove) ; inline
 | ||
|  | 
 | ||
|  | : (dlist-contains?) ( pred dnode -- bool )
 | ||
|  |     [ | ||
|  |         [ dlist-node-data swap call ] 2keep rot [ | ||
|  |             2drop t
 | ||
|  |         ] [ | ||
|  |             dlist-node-next (dlist-contains?) | ||
|  |         ] if
 | ||
|  |     ] [ | ||
|  |         drop f
 | ||
|  |     ] if* ; inline
 | ||
|  | 
 | ||
|  | : dlist-contains? ( quot dlist -- obj/f )
 | ||
|  |     #! Return true if any item in the dlist that when passed to the | ||
|  |     #! predicate quotation, true is left on the stack. | ||
|  |     #! The 'pred' quotation must have stack effect ( obj -- bool ). | ||
|  |     #! TODO: needs a better name. | ||
|  |     dlist-first (dlist-contains?) ; inline
 | ||
|  | 
 | ||
|  | : (dlist-each) ( quot dnode -- )
 | ||
|  |     [ | ||
|  |         [ dlist-node-data swap call ] 2keep  | ||
|  |         dlist-node-next (dlist-each) | ||
|  |     ] [ | ||
|  |         drop
 | ||
|  |     ] if* ; inline
 | ||
|  | 
 | ||
|  | : dlist-each ( dlist quot -- )
 | ||
|  |     swap dlist-first (dlist-each) ; inline
 | ||
|  | 
 | ||
|  | : dlist-length ( dlist -- length )
 | ||
|  |     0 swap [ drop 1+ ] dlist-each ;
 | ||
|  | 
 |