diff options
author | flywind <xzsflywind@gmail.com> | 2021-03-03 18:58:50 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-03 11:58:50 +0100 |
commit | 6391f6e861d4c1dc87a94861374973b809f0d09f (patch) | |
tree | 33e8cf8f03bdeea5126492efc8d9dd220ed34755 | |
parent | 4982d1c66212de2762eb4ebff183eaa09b00b1f8 (diff) | |
download | Nim-6391f6e861d4c1dc87a94861374973b809f0d09f.tar.gz |
fix #16384 and #17144 (#17126) [backport]
-rw-r--r-- | compiler/vm.nim | 3 | ||||
-rw-r--r-- | tests/stdlib/tlists.nim | 441 |
2 files changed, 225 insertions, 219 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim index ba14f2d51..429419cf8 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1019,7 +1019,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let nc = regs[rc].node if nb.kind != nc.kind: discard elif (nb == nc) or (nb.kind == nkNilLit): ret = true # intentional - elif sameConstant(nb, nc): ret = true + elif (nb.kind in {nkSym, nkTupleConstr, nkClosure} and nb.typ.kind == tyProc) and sameConstant(nb, nc): + ret = true # this also takes care of procvar's, represented as nkTupleConstr, e.g. (nil, nil) elif nb.kind == nkIntLit and nc.kind == nkIntLit and nb.intVal == nc.intVal: # TODO: nkPtrLit let tb = nb.getTyp diff --git a/tests/stdlib/tlists.nim b/tests/stdlib/tlists.nim index 2d3165c9c..54fa8b24f 100644 --- a/tests/stdlib/tlists.nim +++ b/tests/stdlib/tlists.nim @@ -2,232 +2,237 @@ discard """ targets: "c js" """ -import lists, sequtils +import std/[lists, sequtils] const data = [1, 2, 3, 4, 5, 6] -block SinglyLinkedListTest1: - var L: SinglyLinkedList[int] - for d in items(data): L.prepend(d) - for d in items(data): L.add(d) - doAssert($L == "[6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6]") - - doAssert(4 in L) - -block SinglyLinkedListTest2: - var L: SinglyLinkedList[string] - for d in items(data): L.prepend($d) - doAssert($L == """["6", "5", "4", "3", "2", "1"]""") - - doAssert("4" in L) - - -block DoublyLinkedListTest1: - var L: DoublyLinkedList[int] - for d in items(data): L.prepend(d) - for d in items(data): L.add(d) - L.remove(L.find(1)) - doAssert($L == "[6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6]") - - doAssert(4 in L) - -block SinglyLinkedRingTest1: - var L: SinglyLinkedRing[int] - L.prepend(4) - doAssert($L == "[4]") - L.prepend(4) - - doAssert($L == "[4, 4]") - doAssert(4 in L) - - -block DoublyLinkedRingTest1: - var L: DoublyLinkedRing[int] - L.prepend(4) - doAssert($L == "[4]") - L.prepend(4) - - doAssert($L == "[4, 4]") - doAssert(4 in L) - - L.add(3) - L.add(5) - doAssert($L == "[4, 4, 3, 5]") - - L.remove(L.find(3)) - L.remove(L.find(5)) - L.remove(L.find(4)) - L.remove(L.find(4)) - doAssert($L == "[]") - doAssert(4 notin L) - -block tlistsToString: - block: - var l = initDoublyLinkedList[int]() - l.add(1) - l.add(2) - l.add(3) - doAssert $l == "[1, 2, 3]" - block: - var l = initDoublyLinkedList[string]() - l.add("1") - l.add("2") - l.add("3") - doAssert $l == """["1", "2", "3"]""" - block: - var l = initDoublyLinkedList[char]() - l.add('1') - l.add('2') - l.add('3') - doAssert $l == """['1', '2', '3']""" - -# Copied here until it is merged into sequtils -template take(a: untyped, max: int): untyped = - type T = typeof(block: (for ai in a: ai)) - var ret: seq[T] - var i = 0 - if max > 0: - for ai in a: - ret.add ai - i.inc - if i >= max: break - ret - -template testCommon(initList, toList) = - - block: # toSinglyLinkedList, toDoublyLinkedList - let l = seq[int].default - doAssert l.toList.toSeq == [] - doAssert [1].toList.toSeq == [1] - doAssert [1, 2, 3].toList.toSeq == [1, 2, 3] - - block copy: - doAssert array[0, int].default.toList.copy.toSeq == [] - doAssert [1].toList.copy.toSeq == [1] - doAssert [1, 2].toList.copy.toSeq == [1, 2] - doAssert [1, 2, 3].toList.copy.toSeq == [1, 2, 3] - type Foo = ref object - x: int - var f0 = Foo(x: 0) - let f1 = Foo(x: 1) - var a = [f0].toList - var b = a.copy - b.add f1 - doAssert a.toSeq == [f0] - doAssert b.toSeq == [f0, f1] - f0.x = 42 - doAssert a.head.value.x == 42 - doAssert b.head.value.x == 42 - - block: # add, addMoved - block: - var - l0 = initList[int]() - l1 = [1].toList - l2 = [2, 3].toList - l3 = [4, 5, 6].toList - l0.add l3 - l1.add l3 - l2.addMoved l3 - doAssert l0.toSeq == [4, 5, 6] - doAssert l1.toSeq == [1, 4, 5, 6] - doAssert l2.toSeq == [2, 3, 4, 5, 6] - doAssert l3.toSeq == [] - l2.add l3 # re-adding l3 that was destroyed is now a no-op - doAssert l2.toSeq == [2, 3, 4, 5, 6] - doAssert l3.toSeq == [] - block: - var - l0 = initList[int]() - l1 = [1].toList - l2 = [2, 3].toList - l3 = [4, 5, 6].toList - l3.addMoved l0 - l2.addMoved l1 - doAssert l3.toSeq == [4, 5, 6] - doAssert l2.toSeq == [2, 3, 1] - l3.add l0 - doAssert l3.toSeq == [4, 5, 6] - block: - var c = [0, 1].toList - c.addMoved c - doAssert c.take(6) == [0, 1, 0, 1, 0, 1] - block: # prepend, prependMoved +template main = + block SinglyLinkedListTest1: + var L: SinglyLinkedList[int] + for d in items(data): L.prepend(d) + for d in items(data): L.add(d) + doAssert($L == "[6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6]") + + doAssert(4 in L) + + block SinglyLinkedListTest2: + var L: SinglyLinkedList[string] + for d in items(data): L.prepend($d) + doAssert($L == """["6", "5", "4", "3", "2", "1"]""") + + doAssert("4" in L) + + + block DoublyLinkedListTest1: + var L: DoublyLinkedList[int] + for d in items(data): L.prepend(d) + for d in items(data): L.add(d) + L.remove(L.find(1)) + doAssert($L == "[6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6]") + + doAssert(4 in L) + + block SinglyLinkedRingTest1: + var L: SinglyLinkedRing[int] + L.prepend(4) + doAssert($L == "[4]") + L.prepend(4) + + doAssert($L == "[4, 4]") + doAssert(4 in L) + + + block DoublyLinkedRingTest1: + var L: DoublyLinkedRing[int] + L.prepend(4) + doAssert($L == "[4]") + L.prepend(4) + + doAssert($L == "[4, 4]") + doAssert(4 in L) + + L.add(3) + L.add(5) + doAssert($L == "[4, 4, 3, 5]") + + L.remove(L.find(3)) + L.remove(L.find(5)) + L.remove(L.find(4)) + L.remove(L.find(4)) + doAssert($L == "[]") + doAssert(4 notin L) + + block tlistsToString: block: - var - l0 = initList[int]() - l1 = [1].toList - l2 = [2, 3].toList - l3 = [4, 5, 6].toList - l0.prepend l3 - l1.prepend l3 - doAssert l3.toSeq == [4, 5, 6] - l2.prependMoved l3 - doAssert l0.toSeq == [4, 5, 6] - doAssert l1.toSeq == [4, 5, 6, 1] - doAssert l2.toSeq == [4, 5, 6, 2, 3] - doAssert l3.toSeq == [] - l2.prepend l3 # re-prepending l3 that was destroyed is now a no-op - doAssert l2.toSeq == [4, 5, 6, 2, 3] - doAssert l3.toSeq == [] + var l = initDoublyLinkedList[int]() + l.add(1) + l.add(2) + l.add(3) + doAssert $l == "[1, 2, 3]" block: - var - l0 = initList[int]() - l1 = [1].toList - l2 = [2, 3].toList - l3 = [4, 5, 6].toList - l3.prependMoved l0 - l2.prependMoved l1 - doAssert l3.toSeq == [4, 5, 6] - doAssert l2.toSeq == [1, 2, 3] - l3.prepend l0 - doAssert l3.toSeq == [4, 5, 6] + var l = initDoublyLinkedList[string]() + l.add("1") + l.add("2") + l.add("3") + doAssert $l == """["1", "2", "3"]""" block: - var c = [0, 1].toList - c.prependMoved c - doAssert c.take(6) == [0, 1, 0, 1, 0, 1] - - block remove: - var l = [0, 1, 2, 3].toList - let - l0 = l.head - l1 = l0.next - l2 = l1.next - l3 = l2.next - l.remove l0 - doAssert l.toSeq == [1, 2, 3] - l.remove l2 + var l = initDoublyLinkedList[char]() + l.add('1') + l.add('2') + l.add('3') + doAssert $l == """['1', '2', '3']""" + + # Copied here until it is merged into sequtils + template take(a: untyped, max: int): untyped = + type T = typeof(block: (for ai in a: ai)) + var ret: seq[T] + var i = 0 + if max > 0: + for ai in a: + ret.add ai + i.inc + if i >= max: break + ret + + template testCommon(initList, toList) = + + block: # toSinglyLinkedList, toDoublyLinkedList + let l = seq[int].default + doAssert l.toList.toSeq == [] + doAssert [1].toList.toSeq == [1] + doAssert [1, 2, 3].toList.toSeq == [1, 2, 3] + + block copy: + doAssert array[0, int].default.toList.copy.toSeq == [] + doAssert [1].toList.copy.toSeq == [1] + doAssert [1, 2].toList.copy.toSeq == [1, 2] + doAssert [1, 2, 3].toList.copy.toSeq == [1, 2, 3] + type Foo = ref object + x: int + var f0 = Foo(x: 0) + let f1 = Foo(x: 1) + var a = [f0].toList + var b = a.copy + b.add f1 + doAssert a.toSeq == [f0] + doAssert b.toSeq == [f0, f1] + f0.x = 42 + doAssert a.head.value.x == 42 + doAssert b.head.value.x == 42 + + block: # add, addMoved + block: + var + l0 = initList[int]() + l1 = [1].toList + l2 = [2, 3].toList + l3 = [4, 5, 6].toList + l0.add l3 + l1.add l3 + l2.addMoved l3 + doAssert l0.toSeq == [4, 5, 6] + doAssert l1.toSeq == [1, 4, 5, 6] + doAssert l2.toSeq == [2, 3, 4, 5, 6] + doAssert l3.toSeq == [] + l2.add l3 # re-adding l3 that was destroyed is now a no-op + doAssert l2.toSeq == [2, 3, 4, 5, 6] + doAssert l3.toSeq == [] + block: + var + l0 = initList[int]() + l1 = [1].toList + l2 = [2, 3].toList + l3 = [4, 5, 6].toList + l3.addMoved l0 + l2.addMoved l1 + doAssert l3.toSeq == [4, 5, 6] + doAssert l2.toSeq == [2, 3, 1] + l3.add l0 + doAssert l3.toSeq == [4, 5, 6] + block: + var c = [0, 1].toList + c.addMoved c + doAssert c.take(6) == [0, 1, 0, 1, 0, 1] + + block: # prepend, prependMoved + block: + var + l0 = initList[int]() + l1 = [1].toList + l2 = [2, 3].toList + l3 = [4, 5, 6].toList + l0.prepend l3 + l1.prepend l3 + doAssert l3.toSeq == [4, 5, 6] + l2.prependMoved l3 + doAssert l0.toSeq == [4, 5, 6] + doAssert l1.toSeq == [4, 5, 6, 1] + doAssert l2.toSeq == [4, 5, 6, 2, 3] + doAssert l3.toSeq == [] + l2.prepend l3 # re-prepending l3 that was destroyed is now a no-op + doAssert l2.toSeq == [4, 5, 6, 2, 3] + doAssert l3.toSeq == [] + block: + var + l0 = initList[int]() + l1 = [1].toList + l2 = [2, 3].toList + l3 = [4, 5, 6].toList + l3.prependMoved l0 + l2.prependMoved l1 + doAssert l3.toSeq == [4, 5, 6] + doAssert l2.toSeq == [1, 2, 3] + l3.prepend l0 + doAssert l3.toSeq == [4, 5, 6] + block: + var c = [0, 1].toList + c.prependMoved c + doAssert c.take(6) == [0, 1, 0, 1, 0, 1] + + block remove: + var l = [0, 1, 2, 3].toList + let + l0 = l.head + l1 = l0.next + l2 = l1.next + l3 = l2.next + l.remove l0 + doAssert l.toSeq == [1, 2, 3] + l.remove l2 + doAssert l.toSeq == [1, 3] + l.remove l2 + doAssert l.toSeq == [1, 3] + l.remove l3 + doAssert l.toSeq == [1] + l.remove l1 + doAssert l.toSeq == [] + # Cycle preservation + var a = [10, 11, 12].toList + a.addMoved a + doAssert a.take(6) == @[10, 11, 12, 10, 11, 12] + a.remove a.head.next + doAssert a.take(6) == @[10, 12, 10, 12, 10, 12] + a.remove a.head + doAssert a.take(6) == @[12, 12, 12, 12, 12, 12] + + testCommon initSinglyLinkedList, toSinglyLinkedList + testCommon initDoublyLinkedList, toDoublyLinkedList + + block remove: # return value check + var l = [0, 1, 2, 3].toSinglyLinkedList + let n = l.head.next.next + doAssert l.remove(n) == true + doAssert l.toSeq == [0, 1, 3] + doAssert l.remove(n) == false + doAssert l.toSeq == [0, 1, 3] + doAssert l.remove(l.head) == true doAssert l.toSeq == [1, 3] - l.remove l2 - doAssert l.toSeq == [1, 3] - l.remove l3 + doAssert l.remove(l.head.next) == true doAssert l.toSeq == [1] - l.remove l1 + doAssert l.remove(l.head) == true doAssert l.toSeq == [] - # Cycle preservation - var a = [10, 11, 12].toList - a.addMoved a - doAssert a.take(6) == @[10, 11, 12, 10, 11, 12] - a.remove a.head.next - doAssert a.take(6) == @[10, 12, 10, 12, 10, 12] - a.remove a.head - doAssert a.take(6) == @[12, 12, 12, 12, 12, 12] - -testCommon initSinglyLinkedList, toSinglyLinkedList -testCommon initDoublyLinkedList, toDoublyLinkedList - -block remove: # return value check - var l = [0, 1, 2, 3].toSinglyLinkedList - let n = l.head.next.next - doAssert l.remove(n) == true - doAssert l.toSeq == [0, 1, 3] - doAssert l.remove(n) == false - doAssert l.toSeq == [0, 1, 3] - doAssert l.remove(l.head) == true - doAssert l.toSeq == [1, 3] - doAssert l.remove(l.head.next) == true - doAssert l.toSeq == [1] - doAssert l.remove(l.head) == true - doAssert l.toSeq == [] + +static: main() +main() |