-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlist.fs
86 lines (64 loc) · 2.08 KB
/
list.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
\ **********************************
\ List Node Structure
\ offset size what
\ 0 2 next node
\ 2 2 previous node
\ 4 ??? node data
{
: empty? ( head -- h 1 f ) \ returns true if list is empty
dup @ dup @= ;
: empty ( head -- h 1 ) \ helper leaves word if empty list
empty? if 2drop pull drop exit then ;
public
: l_add ( node handle -- ) \ add node to list
empty? if ( n h 1 )
drop over dup 2dup ! \ new.next = new
cell+ ! \ new.prev = new
! exit \ head = new
then
dup @ rot push push
2dup ! \ 1.next = new
over cell+ ! \ new.prev = 1
pull 2dup cell+ ! \ 2.prev = new
over ! \ new.next = 2
pull ! \ head = new
;
: l_next ( head -- ) \ move head to next item
empty @ swap ! ;
: l_prev ( head -- ) \ move head to previous item
empty cell+ @ swap ! ;
: l_new ( -- node ) \ allocates space for a node
here dup dup , , ;
: l_head ( "name" -- ) \ create a list head
create 0 , ;
: l_data ( h -- a ) \ returns data field address of first node
@ 2 cells + ;
\ does xt for each node in list until xt returns true
\ xt is this: ( x a -- f ) where a is address of node data
\ h is set to the node that xt returns true or 0 if no xt return true
\ or list is empty
: l_doeachuntil ( x xt h -- )
\ test for empty list
empty? if 3drop drop exit then push
\ execute xt
begin 3dup l_data swap exec
\ return if xt returns true
if -rot pull 3drop drop exit then
\ move h to next node
dup l_next
\ stop loop if we've reached the first node
dup @ r@ = until
\ clean up
pull 3drop drop ;
}
\ prints list of node names
: list ( lh -- )
[[ >name type cr false ]] swap l_doeachuntil drop ;
\ find node on a list by name, returns data pointer
: lfind ( ca lh -- a )