1
2
3 container duplex-list:_elem [
4 value:_elem
5 next:&:duplex-list:_elem
6 prev:&:duplex-list:_elem
7 ]
8
9
10 def push x:_elem, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
11 local-scope
12 load-ingredients
13 result:&:duplex-list:_elem <- new {(duplex-list _elem): type}
14 *result <- merge x, in, 0
15 {
16 break-unless in
17 *in <- put *in, prev:offset, result
18 }
19 return result
20 ]
21
22 def first in:&:duplex-list:_elem -> result:_elem [
23 local-scope
24 load-ingredients
25 return-unless in, 0
26 result <- get *in, value:offset
27 ]
28
29 def next in:&:duplex-list:_elem -> result:&:duplex-list:_elem/contained-in:in [
30 local-scope
31 load-ingredients
32 return-unless in, 0
33 result <- get *in, next:offset
34 ]
35
36 def prev in:&:duplex-list:_elem -> result:&:duplex-list:_elem/contained-in:in [
37 local-scope
38 load-ingredients
39 return-unless in, 0
40 result <- get *in, prev:offset
41 return result
42 ]
43
44 scenario duplex-list-handling [
45 run [
46 local-scope
47
48 10:num/raw <- copy 34
49 11:num/raw <- copy 35
50 list:&:duplex-list:char <- push 3, 0
51 list <- push 4, list
52 list <- push 5, list
53 list2:&:duplex-list:char <- copy list
54 20:char/raw <- first list2
55 list2 <- next list2
56 21:char/raw <- first list2
57 list2 <- next list2
58 22:char/raw <- first list2
59 30:&:duplex-list:char/raw <- next list2
60 31:char/raw <- first 30:&:duplex-list:char/raw
61 32:&:duplex-list:char/raw <- next 30:&:duplex-list:char/raw
62 33:&:duplex-list:char/raw <- prev 30:&:duplex-list:char/raw
63 list2 <- prev list2
64 40:char/raw <- first list2
65 list2 <- prev list2
66 41:char/raw <- first list2
67 50:bool/raw <- equal list, list2
68 ]
69 memory-should-contain [
70 0 <- 0
71 10 <- 34
72 11 <- 35
73 20 <- 5
74 21 <- 4
75 22 <- 3
76 30 <- 0
77 31 <- 0
78 32 <- 0
79 33 <- 0
80 40 <- 4
81 41 <- 5
82 50 <- 1
83 ]
84 ]
85
86
87 def insert x:_elem, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
88 local-scope
89 load-ingredients
90 new-node:&:duplex-list:_elem <- new {(duplex-list _elem): type}
91 *new-node <- put *new-node, value:offset, x
92
93 next-node:&:duplex-list:_elem <- get *in, next:offset
94 *in <- put *in, next:offset, new-node
95 *new-node <- put *new-node, prev:offset, in
96 *new-node <- put *new-node, next:offset, next-node
97 return-unless next-node
98 *next-node <- put *next-node, prev:offset, new-node
99 ]
100
101 scenario inserting-into-duplex-list [
102 local-scope
103 list:&:duplex-list:char <- push 3, 0
104 list <- push 4, list
105 list <- push 5, list
106 run [
107 list2:&:duplex-list:char <- next list
108 list2 <- insert 6, list2
109
110 list2 <- copy list
111 10:char/raw <- first list2
112 list2 <- next list2
113 11:char/raw <- first list2
114 list2 <- next list2
115 12:char/raw <- first list2
116 list2 <- next list2
117 13:char/raw <- first list2
118 list2 <- prev list2
119 20:char/raw <- first list2
120 list2 <- prev list2
121 21:char/raw <- first list2
122 list2 <- prev list2
123 22:char/raw <- first list2
124 30:bool/raw <- equal list, list2
125 ]
126 memory-should-contain [
127 10 <- 5
128 11 <- 4
129 12 <- 6
130 13 <- 3
131 20 <- 6
132 21 <- 4
133 22 <- 5
134 30 <- 1
135 ]
136 ]
137
138 scenario inserting-at-end-of-duplex-list [
139 local-scope
140 list:&:duplex-list:char <- push 3, 0
141 list <- push 4, list
142 list <- push 5, list
143 run [
144 list2:&:duplex-list:char <- next list
145 list2 <- next list2
146 list2 <- insert 6, list2
147
148 list2 <- copy list
149 10:char/raw <- first list2
150 list2 <- next list2
151 11:char/raw <- first list2
152 list2 <- next list2
153 12:char/raw <- first list2
154 list2 <- next list2
155 13:char/raw <- first list2
156 list2 <- prev list2
157 20:char/raw <- first list2
158 list2 <- prev list2
159 21:char/raw <- first list2
160 list2 <- prev list2
161 22:char/raw <- first list2
162 30:bool/raw <- equal list, list2
163 ]
164 memory-should-contain [
165 10 <- 5
166 11 <- 4
167 12 <- 3
168 13 <- 6
169 20 <- 3
170 21 <- 4
171 22 <- 5
172 30 <- 1
173 ]
174 ]
175
176 scenario inserting-after-start-of-duplex-list [
177 local-scope
178 list:&:duplex-list:char <- push 3, 0
179 list <- push 4, list
180 list <- push 5, list
181 run [
182 list <- insert 6, list
183
184 list2:&:duplex-list:char <- copy list
185 10:char/raw <- first list2
186 list2 <- next list2
187 11:char/raw <- first list2
188 list2 <- next list2
189 12:char/raw <- first list2
190 list2 <- next list2
191 13:char/raw <- first list2
192 list2 <- prev list2
193 20:char/raw <- first list2
194 list2 <- prev list2
195 21:char/raw <- first list2
196 list2 <- prev list2
197 22:char/raw <- first list2
198 30:bool/raw <- equal list, list2
199 ]
200 memory-should-contain [
201 10 <- 5
202 11 <- 6
203 12 <- 4
204 13 <- 3
205 20 <- 4
206 21 <- 6
207 22 <- 5
208 30 <- 1
209 ]
210 ]
211
212
213
214
215
216 def remove x:&:duplex-list:_elem/contained-in:in, in:&:duplex-list:_elem -> in:&:duplex-list:_elem [
217 local-scope
218 load-ingredients
219
220 return-unless x
221 next-node:&:duplex-list:_elem <- get *x, next:offset
222 prev-node:&:duplex-list:_elem <- get *x, prev:offset
223
224 *x <- put *x, next:offset, 0
225 *x <- put *x, prev:offset, 0
226
227 {
228 break-unless next-node
229 *next-node <- put *next-node, prev:offset, prev-node
230 }
231
232 {
233 break-unless prev-node
234 *prev-node <- put *prev-node, next:offset, next-node
235 return
236 }
237
238
239 return next-node
240 ]
241
242 scenario removing-from-duplex-list [
243 local-scope
244 list:&:duplex-list:char <- push 3, 0
245 list <- push 4, list
246 list <- push 5, list
247 run [
248 list2:&:duplex-list:char <- next list
249 list <- remove list2, list
250 10:bool/raw <- equal list2, 0
251
252 list2 <- copy list
253 11:char/raw <- first list2
254 list2 <- next list2
255 12:char/raw <- first list2
256 20:&:duplex-list:char/raw <- next list2
257 list2 <- prev list2
258 30:char/raw <- first list2
259 40:bool/raw <- equal list, list2
260 ]
261 memory-should-contain [
262 10 <- 0
263 11 <- 5
264 12 <- 3
265 20 <- 0
266 30 <- 5
267 40 <- 1
268 ]
269 ]
270
271 scenario removing-from-start-of-duplex-list [
272 local-scope
273 list:&:duplex-list:char <- push 3, 0
274 list <- push 4, list
275 list <- push 5, list
276 run [
277 list <- remove list, list
278
279 list2:&:duplex-list:char <- copy list
280 10:char/raw <- first list2
281 list2 <- next list2
282 11:char/raw <- first list2
283 20:&:duplex-list:char/raw <- next list2
284 list2 <- prev list2
285 30:char/raw <- first list2
286 40:bool/raw <- equal list, list2
287 ]
288 memory-should-contain [
289 10 <- 4
290 11 <- 3
291 20 <- 0
292 30 <- 4
293 40 <- 1
294 ]
295 ]
296
297 scenario removing-from-end-of-duplex-list [
298 local-scope
299 list:&:duplex-list:char <- push 3, 0
300 list <- push 4, list
301 list <- push 5, list
302 run [
303
304 list2:&:duplex-list:char <- next list
305 list2 <- next list2
306 list <- remove list2, list
307 10:bool/raw <- equal list2, 0
308
309 list2 <- copy list
310 11:char/raw <- first list2
311 list2 <- next list2
312 12:char/raw <- first list2
313 20:&:duplex-list:char/raw <- next list2
314 list2 <- prev list2
315 30:char/raw <- first list2
316 40:bool/raw <- equal list, list2
317 ]
318 memory-should-contain [
319 10 <- 0
320 11 <- 5
321 12 <- 4
322 20 <- 0
323 30 <- 5
324 40 <- 1
325 ]
326 ]
327
328 scenario removing-from-singleton-duplex-list [
329 local-scope
330 list:&:duplex-list:char <- push 3, 0
331 run [
332 list <- remove list, list
333 1:num/raw <- copy list
334 ]
335 memory-should-contain [
336 1 <- 0
337 ]
338 ]
339
340
341
342
343
344
345 def remove-between start:&:duplex-list:_elem, end:&:duplex-list:_elem/contained-in:start -> start:&:duplex-list:_elem [
346 local-scope
347 load-ingredients
348 next:&:duplex-list:_elem <- get *start, next:offset
349 nothing-to-delete?:bool <- equal next, end
350 return-if nothing-to-delete?
351 assert next, [malformed duplex list]
352
353
354 *next <- put *next, prev:offset, 0
355 *start <- put *start, next:offset, end
356 return-unless end
357
358
359 prev:&:duplex-list:_elem <- get *end, prev:offset
360 assert prev, [malformed duplex list - 2]
361 *prev <- put *prev, next:offset, 0
362 *end <- put *end, prev:offset, start
363 ]
364
365 scenario remove-range [
366
367 local-scope
368 list:&:duplex-list:char <- push 18, 0
369 list <- push 17, list
370 list <- push 16, list
371 list <- push 15, list
372 list <- push 14, list
373 list <- push 13, list
374 run [
375
376
377 list2:&:duplex-list:char <- next list
378 list2 <- next list2
379 list2 <- remove-between list2, 0
380
381 10:char/raw <- get *list, value:offset
382 list <- next list
383 11:char/raw <- get *list, value:offset
384 list <- next list
385 12:char/raw <- get *list, value:offset
386 20:&:duplex-list:char/raw <- next list
387 ]
388 memory-should-contain [
389 10 <- 13
390 11 <- 14
391 12 <- 15
392 20 <- 0
393 ]
394 ]
395
396 scenario remove-range-to-final [
397 local-scope
398
399 list:&:duplex-list:char <- push 18, 0
400 list <- push 17, list
401 list <- push 16, list
402 list <- push 15, list
403 list <- push 14, list
404 list <- push 13, list
405 run [
406
407
408 list2:&:duplex-list:char <- next list
409
410 end:&:duplex-list:char <- next list2
411 end <- next end
412 end <- next end
413 end <- next end
414 remove-between list2, end
415
416 10:char/raw <- get *list, value:offset
417 list <- next list
418 11:char/raw <- get *list, value:offset
419 list <- next list
420 12:char/raw <- get *list, value:offset
421 20:&:duplex-list:char/raw <- next list
422 ]
423 memory-should-contain [
424 10 <- 13
425 11 <- 14
426 12 <- 18
427 20 <- 0
428 ]
429 ]
430
431 scenario remove-range-empty [
432 local-scope
433
434 list:&:duplex-list:char <- push 15, 0
435 list <- push 14, list
436 list <- push 13, list
437 run [
438
439 list2:&:duplex-list:char <- next list
440 remove-between list, list2
441
442 10:char/raw <- get *list, value:offset
443 list <- next list
444 11:char/raw <- get *list, value:offset
445 list <- next list
446 12:char/raw <- get *list, value:offset
447 20:&:duplex-list:char/raw <- next list
448 ]
449
450 memory-should-contain [
451 10 <- 13
452 11 <- 14
453 12 <- 15
454 20 <- 0
455 ]
456 ]
457
458 scenario remove-range-to-end [
459 local-scope
460
461 list:&:duplex-list:char <- push 18, 0
462 list <- push 17, list
463 list <- push 16, list
464 list <- push 15, list
465 list <- push 14, list
466 list <- push 13, list
467 run [
468
469 list2:&:duplex-list:char <- next list
470 remove-between list2, 0
471
472 10:char/raw <- get *list, value:offset
473 list <- next list
474 11:char/raw <- get *list, value:offset
475 20:&:duplex-list:char/raw <- next list
476 ]
477 memory-should-contain [
478 10 <- 13
479 11 <- 14
480 20 <- 0
481 ]
482 ]
483
484
485 def insert-range in:&:duplex-list:_elem, start:&:duplex-list:_elem/contained-in:in -> in:&:duplex-list:_elem [
486 local-scope
487 load-ingredients
488 return-unless in
489 return-unless start
490 end:&:duplex-list:_elem <- copy start
491 {
492 next:&:duplex-list:_elem <- next end/insert-range
493 break-unless next
494 end <- copy next
495 loop
496 }
497 next:&:duplex-list:_elem <- next in
498 *end <- put *end, next:offset, next
499 {
500 break-unless next
501 *next <- put *next, prev:offset, end
502 }
503 *in <- put *in, next:offset, start
504 *start <- put *start, prev:offset, in
505 ]
506
507 def append in:&:duplex-list:_elem, new:&:duplex-list:_elem/contained-in:in -> in:&:duplex-list:_elem [
508 local-scope
509 load-ingredients
510 last:&:duplex-list:_elem <- last in
511 *last <- put *last, next:offset, new
512 return-unless new
513 *new <- put *new, prev:offset, last
514 ]
515
516 def last in:&:duplex-list:_elem -> result:&:duplex-list:_elem [
517 local-scope
518 load-ingredients
519 result <- copy in
520 {
521 next:&:duplex-list:_elem <- next result
522 break-unless next
523 result <- copy next
524 loop
525 }
526 ]
527
528
529 def dump-from x:&:duplex-list:_elem [
530 local-scope
531 load-ingredients
532 $print x, [: ]
533 {
534 break-unless x
535 c:_elem <- get *x, value:offset
536 $print c, [ ]
537 x <- next x
538 {
539 is-newline?:bool <- equal c, 10/newline
540 break-unless is-newline?
541 $print 10/newline
542 $print x, [: ]
543 }
544 loop
545 }
546 $print 10/newline, [---], 10/newline
547 ]