-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdlist.fs
85 lines (63 loc) · 2.2 KB
/
dlist.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
\ **********************************
\ Doubly Linked Circular Lists
\ handle points to head on list
\ handle = 0 if empty list
\ tail of list points to head
\ head of list points to tail
\ **********************************
0
cell field >next \ pointer to next node
cell field >prev \ pointer to previous node
struct dlist
{
: empty ( head -- h 1 ) \ helper leaves word if empty list
dup @ dup 0= if 2drop pull drop exit then ;
public
\ This adds a node to the head of the list
: l_add ( node head -- ) \ add node to list
dup @ if ( n h )
2dup @ 2dup >prev @
2dup ! swap >prev !
2dup >prev ! swap !
! exit
then
over dup dup !+ ! !
;
: l_rm ( head -- ) \ remove node at head
empty \ exit if empty
dup dup >next @ = if drop 0 else \ skip if only one node
dup >prev @ swap >next @ \ get next and prev
2dup >prev ! \ set next.prev = prev
tuck swap >next ! \ set prev.next = next
then swap ! \ set head = next
;
: l_next ( head -- ) \ move head to next item
empty @ swap ! ;
\ This adds a node to the tail of the list
: l_queue ( node handle -- )
tuck l_add l_next ;
\ Remove and return next node from list
: l_dequeue ( handle -- node )
dup @ swap l_rm ;
: l_prev ( head -- ) \ move head to previous item
empty >prev @ swap ! ;
: l_head ( "name" -- ) \ create a list head
create 0 , ;
\ l_dountil is a word that iterates over a list.
\ it takes an xt and a list head. xt is executed for every
\ list node until xt returns true. When an xt returns a true flag
\ l_dountil returns a true flag and rotates the list head to point
\ to the affirmed node, else it returns false and leaves the head
\ unmodified.
\ The passed xt's is prototyped like follows: ( a -- f )
\ where a is the address to the list's data
\ where f is true to stop iterating, or false to continue
: l_dountil ( xt h -- a | 0 ) \ does xt for head node in h
@ dup 0= if nip exit then dup push
begin
( xt 1 -- xt 1 f )
2dup push push swap exec pull pull rot
if nip pull drop exit then
@ dup r@ = until 2drop pull drop false
;
}