-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlist.fs
162 lines (134 loc) · 3.54 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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
[undefined] list.fs [if]
vocabulary list.fs also list.fs definitions
0
dup constant list:node:next cell +
dup constant list:node:data cell +
constant list:node:struct
: list:node:nend? list:node:next + @ 0<> ;
0
dup constant list:tail cell +
dup constant list:head cell +
constant list:struct
( list:node:struct )
( +-----------+ +-----------+ +-----------+ )
( | next |------->| next |------->| next |--> 0 )
( +-----------+ +-----------+ +-----------+ )
( | data | | data | | data | )
( +-----------+ +-----------+ +-----------+ )
( ^---------+ ^ )
( | | )
( list:struct | | )
( +-----------+ | | )
( | tail |<--+ | )
( +-----------+ | )
( | head |<----------------------------------+ )
( +-----------+ )
: list:.node ( node -- )
hex
." node: { "
dup list:node:next + @ .
list:node:data + @ .
." } "
decimal
;
\ allot new list object
: list:create ( -- list )
here
dup list:struct allot
list:struct erase
;
\ allot new node and set data to u
: list:node:create ( data -- node )
here dup >r
list:node:struct allot
dup list:node:struct erase
list:node:data + !
r>
;
\ allot new node with data and append to list return list
: list:append ( list data -- list )
dup list:node:create dup >r
list:node:data + !
dup list:tail + @ 0= if
r@ over list:tail + !
then
dup list:head + @ 0<> if
r@ over list:head + @ list:node:next + !
then
r> over list:head + !
;
\ execute xt on every element of list
: list:for-each ( xt list -- )
list:tail + @ >r
begin
r@ list:node:data + @ over execute
r@ list:node:nend?
while
r> list:node:next + @ >r
repeat
rdrop drop
;
\ execute xt on every element of list1 and create a new list2 and return
: list:map ( list1 xt -- list2 )
swap list:tail + @ >r
list:create ( xt list2 )
begin
over r@ list:node:data + @ swap execute ( xt list2 result )
2dup list:append 2drop
r@ list:node:nend?
while
r> list:node:next + @ >r
repeat
rdrop nip
;
\ return list length
: list:length ( list -- n )
0
swap list:tail + @ >r
begin
1+
r@ list:node:nend?
while
r> list:node:next + @ >r
repeat
rdrop
;
\ return the nth data from list
: list:nth ( list n -- data )
0
rot list:tail + @ >r
begin
2dup <>
while
r> list:node:next + @ >r
1+
repeat
2drop
r> list:node:data + @
;
\ apply func xt on every element accumulating result in acc. xt is called with ( acc element -- acc )
: list:reduce ( list acc xt -- acc )
rot list:tail + @ >r ( acc xt ) ( R: iter )
r@ 0= if rdrop drop exit then
begin
r@ list:node:data + @ swap dup >r execute r> ( acc xt )
r@ list:node:nend?
while
r> list:node:next + @ >r
repeat
rdrop drop
;
\ execute xt on every node and return true if at least one returns true. xt is called with ( element -- t )
: list:some ( list xt -- t )
swap list:tail + @ >r ( xt ) ( R: iter )
begin
r@ list:node:nend?
while
r@ list:node:data + @ over execute ( xt t )
0<> if rdrop drop true exit then
r> list:node:next + @ >r
repeat
rdrop false
;
previous definitions
[endif]