1 ! Copyright (C) 2007, 2009 Mackenzie Straight, Doug Coleman,
3 ! See http://factorcode.org/license.txt for BSD license.
4 USING: combinators kernel math sequences accessors deques
5 search-deques summary hashtables fry ;
12 INSTANCE: f ?dlist-node
14 TUPLE: dlist-node obj { prev ?dlist-node } { next ?dlist-node } ;
16 INSTANCE: dlist-node ?dlist-node
18 C: <dlist-node> dlist-node
24 { back ?dlist-node } ;
29 : <hashed-dlist> ( -- search-deque )
30 20 <hashtable> <dlist> <search-deque> ;
32 M: dlist deque-empty? front>> not ;
34 M: dlist-node node-value obj>> ;
36 : set-prev-when ( dlist-node dlist-node/f -- )
37 [ (>>prev) ] [ drop ] if* ; inline
39 : set-next-when ( dlist-node dlist-node/f -- )
40 [ (>>next) ] [ drop ] if* ; inline
42 : set-next-prev ( dlist-node -- )
43 dup next>> set-prev-when ; inline
45 : normalize-front ( dlist -- )
46 dup back>> [ f >>front ] unless drop ; inline
48 : normalize-back ( dlist -- )
49 dup front>> [ f >>back ] unless drop ; inline
51 : set-back-to-front ( dlist -- )
52 dup back>> [ dup front>> >>back ] unless drop ; inline
54 : set-front-to-back ( dlist -- )
55 dup front>> [ dup back>> >>front ] unless drop ; inline
57 : (dlist-find-node) ( dlist-node quot: ( node -- ? ) -- node/f ? )
60 [ drop t ] [ [ next>> ] dip (dlist-find-node) ] if
61 ] [ 2drop f f ] if ; inline recursive
63 : dlist-find-node ( dlist quot -- node/f ? )
64 [ front>> ] dip (dlist-find-node) ; inline
66 : dlist-each-node ( dlist quot -- )
67 '[ @ f ] dlist-find-node 2drop ; inline
69 : unlink-node ( dlist-node -- )
70 dup prev>> over next>> set-prev-when
71 dup next>> swap prev>> set-next-when ; inline
75 M: dlist push-front* ( obj dlist -- dlist-node )
76 [ front>> f swap <dlist-node> dup dup set-next-prev ] keep
80 M: dlist push-back* ( obj dlist -- dlist-node )
81 [ back>> f <dlist-node> ] keep
82 [ back>> set-next-when ] 2keep
88 M: empty-dlist summary ( dlist -- )
91 M: dlist peek-front ( dlist -- obj )
92 front>> [ obj>> ] [ empty-dlist ] if* ;
94 M: dlist pop-front* ( dlist -- )
97 [ empty-dlist ] unless*
98 [ f ] change-next drop
104 M: dlist peek-back ( dlist -- obj )
105 back>> [ obj>> ] [ empty-dlist ] if* ;
107 M: dlist pop-back* ( dlist -- )
110 [ empty-dlist ] unless*
111 [ f ] change-prev drop
117 : dlist-find ( dlist quot -- obj/f ? )
118 '[ obj>> @ ] dlist-find-node [ obj>> t ] [ drop f f ] if ; inline
120 : dlist-contains? ( dlist quot -- ? )
121 dlist-find nip ; inline
123 M: dlist deque-member? ( value dlist -- ? )
124 [ = ] with dlist-contains? ;
126 M: dlist delete-node ( dlist-node dlist -- )
128 { [ 2dup front>> eq? ] [ nip pop-front* ] }
129 { [ 2dup back>> eq? ] [ nip pop-back* ] }
133 : delete-node-if* ( dlist quot -- obj/f ? )
134 dupd dlist-find-node [
136 [ swap delete-node ] keep obj>> t
144 : delete-node-if ( dlist quot -- obj/f )
145 '[ obj>> @ ] delete-node-if* drop ; inline
147 M: dlist clear-deque ( dlist -- )
152 : dlist-each ( dlist quot -- )
153 '[ obj>> @ ] dlist-each-node ; inline
155 : dlist>seq ( dlist -- seq )
156 [ ] accumulator [ dlist-each ] dip ;
158 : 1dlist ( obj -- dlist ) <dlist> [ push-front ] keep ;
161 <dlist> [ '[ _ push-back ] dlist-each ] keep ;
163 INSTANCE: dlist deque