factor/basis/dlists/dlists.factor

194 lines
4.8 KiB
Factor
Raw Normal View History

! Copyright (C) 2007, 2009 Mackenzie Straight, Doug Coleman,
2008-03-20 21:14:07 -04:00
! Slava Pestov.
2007-11-05 02:41:23 -05:00
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays combinators combinators.short-circuit
deques fry hashtables kernel parser search-deques sequences
summary vocabs.loader ;
2007-11-05 02:41:23 -05:00
IN: dlists
<PRIVATE
MIXIN: ?dlist-node
2007-11-05 02:41:23 -05:00
INSTANCE: f ?dlist-node
2007-11-05 02:43:29 -05:00
TUPLE: dlist-node obj { prev ?dlist-node } { next ?dlist-node } ;
2008-03-20 21:14:07 -04:00
INSTANCE: dlist-node ?dlist-node
2008-03-20 21:14:07 -04:00
2007-11-05 02:41:23 -05:00
C: <dlist-node> dlist-node
PRIVATE>
TUPLE: dlist
{ front ?dlist-node }
{ back ?dlist-node } ;
2007-11-05 02:41:23 -05:00
2008-11-16 08:04:51 -05:00
: <dlist> ( -- list )
dlist new ; inline
: <hashed-dlist> ( -- search-deque )
20 <hashtable> <dlist> <search-deque> ;
2010-04-01 20:05:32 -04:00
M: dlist deque-empty? front>> not ; inline
M: dlist-node node-value obj>> ;
2007-11-05 02:41:23 -05:00
<PRIVATE
: dlist-nodes= ( dlist-node/f dlist-node/f -- ? )
{
[ [ dlist-node? ] both? ]
[ [ obj>> ] bi@ = ]
} 2&& ; inline
PRIVATE>
M: dlist equal?
over dlist? [
[ front>> ] bi@
[ 2dup dlist-nodes= ]
[ [ next>> ] bi@ ] while
2011-11-03 00:56:06 -04:00
or not
] [
2drop f
] if ;
2007-11-05 02:41:23 -05:00
: set-prev-when ( dlist-node dlist-node/f -- )
[ prev<< ] [ drop ] if* ; inline
2007-11-05 02:41:23 -05:00
: set-next-when ( dlist-node dlist-node/f -- )
[ next<< ] [ drop ] if* ; inline
2007-11-05 02:41:23 -05:00
: set-next-prev ( dlist-node -- )
dup next>> set-prev-when ; inline
2007-11-05 02:41:23 -05:00
: normalize-front ( dlist -- )
dup back>> [ f >>front ] unless drop ; inline
2007-11-05 02:41:23 -05:00
: normalize-back ( dlist -- )
dup front>> [ f >>back ] unless drop ; inline
2007-11-05 02:41:23 -05:00
: set-back-to-front ( dlist -- )
dup back>> [ dup front>> >>back ] unless drop ; inline
2007-11-05 02:41:23 -05:00
: set-front-to-back ( dlist -- )
dup front>> [ dup back>> >>front ] unless drop ; inline
2007-11-05 02:43:29 -05:00
: (dlist-find-node) ( ... dlist-node quot: ( ... node -- ... ? ) -- ... node/f )
2008-03-20 21:14:07 -04:00
over [
[ call ] 2keep rot
[ drop ] [ [ next>> ] dip (dlist-find-node) ] if
] [ 2drop f ] if ; inline recursive
2007-11-05 02:43:29 -05:00
: dlist-find-node ( ... dlist quot: ( ... node -- ... ? ) -- ... node/f )
2008-11-29 14:29:19 -05:00
[ front>> ] dip (dlist-find-node) ; inline
2007-11-05 02:43:29 -05:00
: dlist-find-node-prev ( ... dlist quot: ( ... value -- ... ? ) -- ... obj/f ? )
dlist-find-node [ prev>> ] [ f ] if* ; inline
: dlist-each-node ( ... dlist quot: ( ... node -- ... ) -- ... )
'[ @ f ] dlist-find-node drop ; inline
2007-11-05 02:43:29 -05:00
: unlink-node ( dlist-node -- )
dup prev>> over next>> set-prev-when
dup next>> swap prev>> set-next-when ; inline
2007-11-05 02:41:23 -05:00
PRIVATE>
M: dlist push-front* ( obj dlist -- dlist-node )
2008-03-20 21:14:07 -04:00
[ front>> f swap <dlist-node> dup dup set-next-prev ] keep
[ front<< ] keep
set-back-to-front ;
2007-11-05 02:41:23 -05:00
M: dlist push-back* ( obj dlist -- dlist-node )
2008-03-20 21:14:07 -04:00
[ back>> f <dlist-node> ] keep
[ back>> set-next-when ] 2keep
[ back<< ] 2keep
set-front-to-back ;
M: dlist peek-front* ( dlist -- obj/f ? )
front>> [ obj>> t ] [ f f ] if* ;
M: dlist peek-back* ( dlist -- obj/f ? )
back>> [ obj>> t ] [ f f ] if* ;
M: dlist pop-front* ( dlist -- )
[
[
[ empty-deque ] unless*
next>>
f over set-prev-when
] change-front drop
] keep
normalize-back ;
2007-11-05 02:41:23 -05:00
M: dlist pop-back* ( dlist -- )
[
[
[ empty-deque ] unless*
prev>>
f over set-next-when
] change-back drop
] keep
normalize-front ;
2007-11-05 02:41:23 -05:00
: dlist-find ( ... dlist quot: ( ... value -- ... ? ) -- ... obj/f ? )
'[ obj>> @ ] dlist-find-node [ obj>> t ] [ f f ] if* ; inline
2007-11-05 02:41:23 -05:00
: dlist-any? ( ... dlist quot: ( ... value -- ... ? ) -- ... ? )
2007-11-15 17:21:45 -05:00
dlist-find nip ; inline
2007-11-05 02:41:23 -05:00
2008-08-19 15:06:20 -04:00
M: dlist deque-member? ( value dlist -- ? )
[ = ] with dlist-any? ;
2007-11-16 00:17:34 -05:00
M: dlist delete-node ( dlist-node dlist -- )
2007-11-05 02:41:23 -05:00
{
{ [ 2dup front>> eq? ] [ nip pop-front* ] }
{ [ 2dup back>> eq? ] [ nip pop-back* ] }
[ drop unlink-node ]
2007-11-05 02:41:23 -05:00
} cond ;
: delete-node-if* ( ... dlist quot: ( ... value -- ... ? ) -- ... obj/f ? )
2008-03-20 21:14:07 -04:00
dupd dlist-find-node [
dup [
[ swap delete-node ] keep obj>> t
2008-03-20 21:14:07 -04:00
] [
2drop f f
] if
2007-11-05 02:41:23 -05:00
] [
drop f f
] if* ; inline
2007-11-05 02:41:23 -05:00
: delete-node-if ( ... dlist quot: ( ... value -- ... ? ) -- ... obj/f )
'[ obj>> @ ] delete-node-if* drop ; inline
2007-11-15 21:44:10 -05:00
2008-08-19 15:06:20 -04:00
M: dlist clear-deque ( dlist -- )
2008-03-20 21:14:07 -04:00
f >>front
f >>back
drop ;
2008-02-06 20:23:39 -05:00
: dlist-each ( ... dlist quot: ( ... value -- ... ) -- ... )
'[ obj>> @ ] dlist-each-node ; inline
: dlist>seq ( dlist -- seq )
[ ] collector [ dlist-each ] dip ;
: seq>dlist ( seq -- dlist )
<dlist> [ '[ _ push-back ] each ] keep ;
: 1dlist ( obj -- dlist ) <dlist> [ push-front ] keep ;
: dlist-filter ( ... dlist quot: ( ... value -- ... ? ) -- ... dlist' )
over [ '[ dup obj>> @ [ drop ] [ _ delete-node ] if ] dlist-each-node ] keep ; inline
M: dlist clone
<dlist> [ '[ _ push-back ] dlist-each ] keep ;
2008-08-19 15:06:20 -04:00
INSTANCE: dlist deque
SYNTAX: DL{ \ } [ seq>dlist ] parse-literal ;
{ "dlists" "prettyprint" } "dlists.prettyprint" require-when