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 ]