]> Cypherpunks.ru repositories - gostls13.git/blob - test/typeparam/list2.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / typeparam / list2.go
1 // run
2
3 // Copyright 2021 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
6
7 // Package list provides a doubly linked list of some element type
8 // (generic form of the "container/list" package).
9
10 package main
11
12 import (
13         "fmt"
14         "strconv"
15 )
16
17 // Element is an element of a linked list.
18 type _Element[T any] struct {
19         // Next and previous pointers in the doubly-linked list of elements.
20         // To simplify the implementation, internally a list l is implemented
21         // as a ring, such that &l.root is both the next element of the last
22         // list element (l.Back()) and the previous element of the first list
23         // element (l.Front()).
24         next, prev *_Element[T]
25
26         // The list to which this element belongs.
27         list *_List[T]
28
29         // The value stored with this element.
30         Value T
31 }
32
33 // Next returns the next list element or nil.
34 func (e *_Element[T]) Next() *_Element[T] {
35         if p := e.next; e.list != nil && p != &e.list.root {
36                 return p
37         }
38         return nil
39 }
40
41 // Prev returns the previous list element or nil.
42 func (e *_Element[T]) Prev() *_Element[T] {
43         if p := e.prev; e.list != nil && p != &e.list.root {
44                 return p
45         }
46         return nil
47 }
48
49 // _List represents a doubly linked list.
50 // The zero value for _List is an empty list ready to use.
51 type _List[T any] struct {
52         root _Element[T] // sentinel list element, only &root, root.prev, and root.next are used
53         len  int         // current list length excluding (this) sentinel element
54 }
55
56 // Init initializes or clears list l.
57 func (l *_List[T]) Init() *_List[T] {
58         l.root.next = &l.root
59         l.root.prev = &l.root
60         l.len = 0
61         return l
62 }
63
64 // New returns an initialized list.
65 func _New[T any]() *_List[T] { return new(_List[T]).Init() }
66
67 // Len returns the number of elements of list l.
68 // The complexity is O(1).
69 func (l *_List[_]) Len() int { return l.len }
70
71 // Front returns the first element of list l or nil if the list is empty.
72 func (l *_List[T]) Front() *_Element[T] {
73         if l.len == 0 {
74                 return nil
75         }
76         return l.root.next
77 }
78
79 // Back returns the last element of list l or nil if the list is empty.
80 func (l *_List[T]) Back() *_Element[T] {
81         if l.len == 0 {
82                 return nil
83         }
84         return l.root.prev
85 }
86
87 // lazyInit lazily initializes a zero _List value.
88 func (l *_List[_]) lazyInit() {
89         if l.root.next == nil {
90                 l.Init()
91         }
92 }
93
94 // insert inserts e after at, increments l.len, and returns e.
95 func (l *_List[T]) insert(e, at *_Element[T]) *_Element[T] {
96         e.prev = at
97         e.next = at.next
98         e.prev.next = e
99         e.next.prev = e
100         e.list = l
101         l.len++
102         return e
103 }
104
105 // insertValue is a convenience wrapper for insert(&_Element[T]{Value: v}, at).
106 func (l *_List[T]) insertValue(v T, at *_Element[T]) *_Element[T] {
107         return l.insert(&_Element[T]{Value: v}, at)
108 }
109
110 // remove removes e from its list, decrements l.len, and returns e.
111 func (l *_List[T]) remove(e *_Element[T]) *_Element[T] {
112         e.prev.next = e.next
113         e.next.prev = e.prev
114         e.next = nil // avoid memory leaks
115         e.prev = nil // avoid memory leaks
116         e.list = nil
117         l.len--
118         return e
119 }
120
121 // move moves e to next to at and returns e.
122 func (l *_List[T]) move(e, at *_Element[T]) *_Element[T] {
123         if e == at {
124                 return e
125         }
126         e.prev.next = e.next
127         e.next.prev = e.prev
128
129         e.prev = at
130         e.next = at.next
131         e.prev.next = e
132         e.next.prev = e
133
134         return e
135 }
136
137 // Remove removes e from l if e is an element of list l.
138 // It returns the element value e.Value.
139 // The element must not be nil.
140 func (l *_List[T]) Remove(e *_Element[T]) T {
141         if e.list == l {
142                 // if e.list == l, l must have been initialized when e was inserted
143                 // in l or l == nil (e is a zero _Element) and l.remove will crash
144                 l.remove(e)
145         }
146         return e.Value
147 }
148
149 // PushFront inserts a new element e with value v at the front of list l and returns e.
150 func (l *_List[T]) PushFront(v T) *_Element[T] {
151         l.lazyInit()
152         return l.insertValue(v, &l.root)
153 }
154
155 // PushBack inserts a new element e with value v at the back of list l and returns e.
156 func (l *_List[T]) PushBack(v T) *_Element[T] {
157         l.lazyInit()
158         return l.insertValue(v, l.root.prev)
159 }
160
161 // InsertBefore inserts a new element e with value v immediately before mark and returns e.
162 // If mark is not an element of l, the list is not modified.
163 // The mark must not be nil.
164 func (l *_List[T]) InsertBefore(v T, mark *_Element[T]) *_Element[T] {
165         if mark.list != l {
166                 return nil
167         }
168         // see comment in _List.Remove about initialization of l
169         return l.insertValue(v, mark.prev)
170 }
171
172 // InsertAfter inserts a new element e with value v immediately after mark and returns e.
173 // If mark is not an element of l, the list is not modified.
174 // The mark must not be nil.
175 func (l *_List[T]) InsertAfter(v T, mark *_Element[T]) *_Element[T] {
176         if mark.list != l {
177                 return nil
178         }
179         // see comment in _List.Remove about initialization of l
180         return l.insertValue(v, mark)
181 }
182
183 // MoveToFront moves element e to the front of list l.
184 // If e is not an element of l, the list is not modified.
185 // The element must not be nil.
186 func (l *_List[T]) MoveToFront(e *_Element[T]) {
187         if e.list != l || l.root.next == e {
188                 return
189         }
190         // see comment in _List.Remove about initialization of l
191         l.move(e, &l.root)
192 }
193
194 // MoveToBack moves element e to the back of list l.
195 // If e is not an element of l, the list is not modified.
196 // The element must not be nil.
197 func (l *_List[T]) MoveToBack(e *_Element[T]) {
198         if e.list != l || l.root.prev == e {
199                 return
200         }
201         // see comment in _List.Remove about initialization of l
202         l.move(e, l.root.prev)
203 }
204
205 // MoveBefore moves element e to its new position before mark.
206 // If e or mark is not an element of l, or e == mark, the list is not modified.
207 // The element and mark must not be nil.
208 func (l *_List[T]) MoveBefore(e, mark *_Element[T]) {
209         if e.list != l || e == mark || mark.list != l {
210                 return
211         }
212         l.move(e, mark.prev)
213 }
214
215 // MoveAfter moves element e to its new position after mark.
216 // If e or mark is not an element of l, or e == mark, the list is not modified.
217 // The element and mark must not be nil.
218 func (l *_List[T]) MoveAfter(e, mark *_Element[T]) {
219         if e.list != l || e == mark || mark.list != l {
220                 return
221         }
222         l.move(e, mark)
223 }
224
225 // PushBackList inserts a copy of an other list at the back of list l.
226 // The lists l and other may be the same. They must not be nil.
227 func (l *_List[T]) PushBackList(other *_List[T]) {
228         l.lazyInit()
229         for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
230                 l.insertValue(e.Value, l.root.prev)
231         }
232 }
233
234 // PushFrontList inserts a copy of an other list at the front of list l.
235 // The lists l and other may be the same. They must not be nil.
236 func (l *_List[T]) PushFrontList(other *_List[T]) {
237         l.lazyInit()
238         for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
239                 l.insertValue(e.Value, &l.root)
240         }
241 }
242
243 // Transform runs a transform function on a list returning a new list.
244 func _Transform[TElem1, TElem2 any](lst *_List[TElem1], f func(TElem1) TElem2) *_List[TElem2] {
245         ret := _New[TElem2]()
246         for p := lst.Front(); p != nil; p = p.Next() {
247                 ret.PushBack(f(p.Value))
248         }
249         return ret
250 }
251
252 func checkListLen[T any](l *_List[T], len int) bool {
253         if n := l.Len(); n != len {
254                 panic(fmt.Sprintf("l.Len() = %d, want %d", n, len))
255                 return false
256         }
257         return true
258 }
259
260 func checkListPointers[T any](l *_List[T], es []*_Element[T]) {
261         root := &l.root
262
263         if !checkListLen(l, len(es)) {
264                 return
265         }
266
267         // zero length lists must be the zero value or properly initialized (sentinel circle)
268         if len(es) == 0 {
269                 if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root {
270                         panic(fmt.Sprintf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root))
271                 }
272                 return
273         }
274         // len(es) > 0
275
276         // check internal and external prev/next connections
277         for i, e := range es {
278                 prev := root
279                 Prev := (*_Element[T])(nil)
280                 if i > 0 {
281                         prev = es[i-1]
282                         Prev = prev
283                 }
284                 if p := e.prev; p != prev {
285                         panic(fmt.Sprintf("elt[%d](%p).prev = %p, want %p", i, e, p, prev))
286                 }
287                 if p := e.Prev(); p != Prev {
288                         panic(fmt.Sprintf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev))
289                 }
290
291                 next := root
292                 Next := (*_Element[T])(nil)
293                 if i < len(es)-1 {
294                         next = es[i+1]
295                         Next = next
296                 }
297                 if n := e.next; n != next {
298                         panic(fmt.Sprintf("elt[%d](%p).next = %p, want %p", i, e, n, next))
299                 }
300                 if n := e.Next(); n != Next {
301                         panic(fmt.Sprintf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next))
302                 }
303         }
304 }
305
306 func TestList() {
307         l := _New[string]()
308         checkListPointers(l, []*(_Element[string]){})
309
310         // Single element list
311         e := l.PushFront("a")
312         checkListPointers(l, []*(_Element[string]){e})
313         l.MoveToFront(e)
314         checkListPointers(l, []*(_Element[string]){e})
315         l.MoveToBack(e)
316         checkListPointers(l, []*(_Element[string]){e})
317         l.Remove(e)
318         checkListPointers(l, []*(_Element[string]){})
319
320         // Bigger list
321         l2 := _New[int]()
322         e2 := l2.PushFront(2)
323         e1 := l2.PushFront(1)
324         e3 := l2.PushBack(3)
325         e4 := l2.PushBack(600)
326         checkListPointers(l2, []*(_Element[int]){e1, e2, e3, e4})
327
328         l2.Remove(e2)
329         checkListPointers(l2, []*(_Element[int]){e1, e3, e4})
330
331         l2.MoveToFront(e3) // move from middle
332         checkListPointers(l2, []*(_Element[int]){e3, e1, e4})
333
334         l2.MoveToFront(e1)
335         l2.MoveToBack(e3) // move from middle
336         checkListPointers(l2, []*(_Element[int]){e1, e4, e3})
337
338         l2.MoveToFront(e3) // move from back
339         checkListPointers(l2, []*(_Element[int]){e3, e1, e4})
340         l2.MoveToFront(e3) // should be no-op
341         checkListPointers(l2, []*(_Element[int]){e3, e1, e4})
342
343         l2.MoveToBack(e3) // move from front
344         checkListPointers(l2, []*(_Element[int]){e1, e4, e3})
345         l2.MoveToBack(e3) // should be no-op
346         checkListPointers(l2, []*(_Element[int]){e1, e4, e3})
347
348         e2 = l2.InsertBefore(2, e1) // insert before front
349         checkListPointers(l2, []*(_Element[int]){e2, e1, e4, e3})
350         l2.Remove(e2)
351         e2 = l2.InsertBefore(2, e4) // insert before middle
352         checkListPointers(l2, []*(_Element[int]){e1, e2, e4, e3})
353         l2.Remove(e2)
354         e2 = l2.InsertBefore(2, e3) // insert before back
355         checkListPointers(l2, []*(_Element[int]){e1, e4, e2, e3})
356         l2.Remove(e2)
357
358         e2 = l2.InsertAfter(2, e1) // insert after front
359         checkListPointers(l2, []*(_Element[int]){e1, e2, e4, e3})
360         l2.Remove(e2)
361         e2 = l2.InsertAfter(2, e4) // insert after middle
362         checkListPointers(l2, []*(_Element[int]){e1, e4, e2, e3})
363         l2.Remove(e2)
364         e2 = l2.InsertAfter(2, e3) // insert after back
365         checkListPointers(l2, []*(_Element[int]){e1, e4, e3, e2})
366         l2.Remove(e2)
367
368         // Check standard iteration.
369         sum := 0
370         for e := l2.Front(); e != nil; e = e.Next() {
371                 sum += e.Value
372         }
373         if sum != 604 {
374                 panic(fmt.Sprintf("sum over l = %d, want 604", sum))
375         }
376
377         // Clear all elements by iterating
378         var next *_Element[int]
379         for e := l2.Front(); e != nil; e = next {
380                 next = e.Next()
381                 l2.Remove(e)
382         }
383         checkListPointers(l2, []*(_Element[int]){})
384 }
385
386 func checkList[T comparable](l *_List[T], es []interface{}) {
387         if !checkListLen(l, len(es)) {
388                 return
389         }
390
391         i := 0
392         for e := l.Front(); e != nil; e = e.Next() {
393                 le := e.Value
394                 // Comparison between a generically-typed variable le and an interface.
395                 if le != es[i] {
396                         panic(fmt.Sprintf("elt[%d].Value = %v, want %v", i, le, es[i]))
397                 }
398                 i++
399         }
400 }
401
402 func TestExtending() {
403         l1 := _New[int]()
404         l2 := _New[int]()
405
406         l1.PushBack(1)
407         l1.PushBack(2)
408         l1.PushBack(3)
409
410         l2.PushBack(4)
411         l2.PushBack(5)
412
413         l3 := _New[int]()
414         l3.PushBackList(l1)
415         checkList(l3, []interface{}{1, 2, 3})
416         l3.PushBackList(l2)
417         checkList(l3, []interface{}{1, 2, 3, 4, 5})
418
419         l3 = _New[int]()
420         l3.PushFrontList(l2)
421         checkList(l3, []interface{}{4, 5})
422         l3.PushFrontList(l1)
423         checkList(l3, []interface{}{1, 2, 3, 4, 5})
424
425         checkList(l1, []interface{}{1, 2, 3})
426         checkList(l2, []interface{}{4, 5})
427
428         l3 = _New[int]()
429         l3.PushBackList(l1)
430         checkList(l3, []interface{}{1, 2, 3})
431         l3.PushBackList(l3)
432         checkList(l3, []interface{}{1, 2, 3, 1, 2, 3})
433
434         l3 = _New[int]()
435         l3.PushFrontList(l1)
436         checkList(l3, []interface{}{1, 2, 3})
437         l3.PushFrontList(l3)
438         checkList(l3, []interface{}{1, 2, 3, 1, 2, 3})
439
440         l3 = _New[int]()
441         l1.PushBackList(l3)
442         checkList(l1, []interface{}{1, 2, 3})
443         l1.PushFrontList(l3)
444         checkList(l1, []interface{}{1, 2, 3})
445 }
446
447 func TestRemove() {
448         l := _New[int]()
449         e1 := l.PushBack(1)
450         e2 := l.PushBack(2)
451         checkListPointers(l, []*(_Element[int]){e1, e2})
452         e := l.Front()
453         l.Remove(e)
454         checkListPointers(l, []*(_Element[int]){e2})
455         l.Remove(e)
456         checkListPointers(l, []*(_Element[int]){e2})
457 }
458
459 func TestIssue4103() {
460         l1 := _New[int]()
461         l1.PushBack(1)
462         l1.PushBack(2)
463
464         l2 := _New[int]()
465         l2.PushBack(3)
466         l2.PushBack(4)
467
468         e := l1.Front()
469         l2.Remove(e) // l2 should not change because e is not an element of l2
470         if n := l2.Len(); n != 2 {
471                 panic(fmt.Sprintf("l2.Len() = %d, want 2", n))
472         }
473
474         l1.InsertBefore(8, e)
475         if n := l1.Len(); n != 3 {
476                 panic(fmt.Sprintf("l1.Len() = %d, want 3", n))
477         }
478 }
479
480 func TestIssue6349() {
481         l := _New[int]()
482         l.PushBack(1)
483         l.PushBack(2)
484
485         e := l.Front()
486         l.Remove(e)
487         if e.Value != 1 {
488                 panic(fmt.Sprintf("e.value = %d, want 1", e.Value))
489         }
490         if e.Next() != nil {
491                 panic(fmt.Sprintf("e.Next() != nil"))
492         }
493         if e.Prev() != nil {
494                 panic(fmt.Sprintf("e.Prev() != nil"))
495         }
496 }
497
498 func TestMove() {
499         l := _New[int]()
500         e1 := l.PushBack(1)
501         e2 := l.PushBack(2)
502         e3 := l.PushBack(3)
503         e4 := l.PushBack(4)
504
505         l.MoveAfter(e3, e3)
506         checkListPointers(l, []*(_Element[int]){e1, e2, e3, e4})
507         l.MoveBefore(e2, e2)
508         checkListPointers(l, []*(_Element[int]){e1, e2, e3, e4})
509
510         l.MoveAfter(e3, e2)
511         checkListPointers(l, []*(_Element[int]){e1, e2, e3, e4})
512         l.MoveBefore(e2, e3)
513         checkListPointers(l, []*(_Element[int]){e1, e2, e3, e4})
514
515         l.MoveBefore(e2, e4)
516         checkListPointers(l, []*(_Element[int]){e1, e3, e2, e4})
517         e2, e3 = e3, e2
518
519         l.MoveBefore(e4, e1)
520         checkListPointers(l, []*(_Element[int]){e4, e1, e2, e3})
521         e1, e2, e3, e4 = e4, e1, e2, e3
522
523         l.MoveAfter(e4, e1)
524         checkListPointers(l, []*(_Element[int]){e1, e4, e2, e3})
525         e2, e3, e4 = e4, e2, e3
526
527         l.MoveAfter(e2, e3)
528         checkListPointers(l, []*(_Element[int]){e1, e3, e2, e4})
529         e2, e3 = e3, e2
530 }
531
532 // Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized _List
533 func TestZeroList() {
534         var l1 = new(_List[int])
535         l1.PushFront(1)
536         checkList(l1, []interface{}{1})
537
538         var l2 = new(_List[int])
539         l2.PushBack(1)
540         checkList(l2, []interface{}{1})
541
542         var l3 = new(_List[int])
543         l3.PushFrontList(l1)
544         checkList(l3, []interface{}{1})
545
546         var l4 = new(_List[int])
547         l4.PushBackList(l2)
548         checkList(l4, []interface{}{1})
549 }
550
551 // Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l.
552 func TestInsertBeforeUnknownMark() {
553         var l _List[int]
554         l.PushBack(1)
555         l.PushBack(2)
556         l.PushBack(3)
557         l.InsertBefore(1, new(_Element[int]))
558         checkList(&l, []interface{}{1, 2, 3})
559 }
560
561 // Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l.
562 func TestInsertAfterUnknownMark() {
563         var l _List[int]
564         l.PushBack(1)
565         l.PushBack(2)
566         l.PushBack(3)
567         l.InsertAfter(1, new(_Element[int]))
568         checkList(&l, []interface{}{1, 2, 3})
569 }
570
571 // Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l.
572 func TestMoveUnknownMark() {
573         var l1 _List[int]
574         e1 := l1.PushBack(1)
575
576         var l2 _List[int]
577         e2 := l2.PushBack(2)
578
579         l1.MoveAfter(e1, e2)
580         checkList(&l1, []interface{}{1})
581         checkList(&l2, []interface{}{2})
582
583         l1.MoveBefore(e1, e2)
584         checkList(&l1, []interface{}{1})
585         checkList(&l2, []interface{}{2})
586 }
587
588 // Test the Transform function.
589 func TestTransform() {
590         l1 := _New[int]()
591         l1.PushBack(1)
592         l1.PushBack(2)
593         l2 := _Transform(l1, strconv.Itoa)
594         checkList(l2, []interface{}{"1", "2"})
595 }
596
597 func main() {
598         TestList()
599         TestExtending()
600         TestRemove()
601         TestIssue4103()
602         TestIssue6349()
603         TestMove()
604         TestZeroList()
605         TestInsertBeforeUnknownMark()
606         TestInsertAfterUnknownMark()
607         TestTransform()
608 }