fix #16384 and #17144 (#17126) [backport]

This commit is contained in:
flywind 2021-03-03 18:58:50 +08:00 • committed by GitHub
commit 6391f6e861
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 209 additions and 203 deletions

View file

@ -1019,7 +1019,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
let nc = regs[rc].node let nc = regs[rc].node
if nb.kind != nc.kind: discard if nb.kind != nc.kind: discard
elif (nb == nc) or (nb.kind == nkNilLit): ret = true # intentional 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) # 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 elif nb.kind == nkIntLit and nc.kind == nkIntLit and nb.intVal == nc.intVal: # TODO: nkPtrLit
let tb = nb.getTyp let tb = nb.getTyp

View file

@ -2,232 +2,237 @@ discard """
targets: "c js" targets: "c js"
""" """
import lists, sequtils import std/[lists, sequtils]
const const
data = [1, 2, 3, 4, 5, 6] 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) 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]")
block SinglyLinkedListTest2: doAssert(4 in L)
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 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: block DoublyLinkedListTest1:
var L: DoublyLinkedList[int] var L: DoublyLinkedList[int]
for d in items(data): L.prepend(d) for d in items(data): L.prepend(d)
for d in items(data): L.add(d) for d in items(data): L.add(d)
L.remove(L.find(1)) L.remove(L.find(1))
doAssert($L == "[6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6]") doAssert($L == "[6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6]")
doAssert(4 in L) doAssert(4 in L)
block SinglyLinkedRingTest1: block SinglyLinkedRingTest1:
var L: SinglyLinkedRing[int] var L: SinglyLinkedRing[int]
L.prepend(4) L.prepend(4)
doAssert($L == "[4]") doAssert($L == "[4]")
L.prepend(4) L.prepend(4)
doAssert($L == "[4, 4]") doAssert($L == "[4, 4]")
doAssert(4 in L) doAssert(4 in L)
block DoublyLinkedRingTest1: block DoublyLinkedRingTest1:
var L: DoublyLinkedRing[int] var L: DoublyLinkedRing[int]
L.prepend(4) L.prepend(4)
doAssert($L == "[4]") doAssert($L == "[4]")
L.prepend(4) L.prepend(4)
doAssert($L == "[4, 4]") doAssert($L == "[4, 4]")
doAssert(4 in L) doAssert(4 in L)
L.add(3) L.add(3)
L.add(5) L.add(5)
doAssert($L == "[4, 4, 3, 5]") doAssert($L == "[4, 4, 3, 5]")
L.remove(L.find(3)) L.remove(L.find(3))
L.remove(L.find(5)) L.remove(L.find(5))
L.remove(L.find(4)) L.remove(L.find(4))
L.remove(L.find(4)) L.remove(L.find(4))
doAssert($L == "[]") doAssert($L == "[]")
doAssert(4 notin L) doAssert(4 notin L)
block tlistsToString: 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: block:
var var l = initDoublyLinkedList[int]()
l0 = initList[int]() l.add(1)
l1 = [1].toList l.add(2)
l2 = [2, 3].toList l.add(3)
l3 = [4, 5, 6].toList doAssert $l == "[1, 2, 3]"
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: block:
var var l = initDoublyLinkedList[string]()
l0 = initList[int]() l.add("1")
l1 = [1].toList l.add("2")
l2 = [2, 3].toList l.add("3")
l3 = [4, 5, 6].toList doAssert $l == """["1", "2", "3"]"""
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: block:
var c = [0, 1].toList var l = initDoublyLinkedList[char]()
c.addMoved c l.add('1')
doAssert c.take(6) == [0, 1, 0, 1, 0, 1] l.add('2')
l.add('3')
doAssert $l == """['1', '2', '3']"""
block: # prepend, prependMoved # Copied here until it is merged into sequtils
block: template take(a: untyped, max: int): untyped =
var type T = typeof(block: (for ai in a: ai))
l0 = initList[int]() var ret: seq[T]
l1 = [1].toList var i = 0
l2 = [2, 3].toList if max > 0:
l3 = [4, 5, 6].toList for ai in a:
l0.prepend l3 ret.add ai
l1.prepend l3 i.inc
doAssert l3.toSeq == [4, 5, 6] if i >= max: break
l2.prependMoved l3 ret
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: template testCommon(initList, toList) =
var l = [0, 1, 2, 3].toList
let block: # toSinglyLinkedList, toDoublyLinkedList
l0 = l.head let l = seq[int].default
l1 = l0.next doAssert l.toList.toSeq == []
l2 = l1.next doAssert [1].toList.toSeq == [1]
l3 = l2.next doAssert [1, 2, 3].toList.toSeq == [1, 2, 3]
l.remove l0
doAssert l.toSeq == [1, 2, 3] block copy:
l.remove l2 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] doAssert l.toSeq == [1, 3]
l.remove l2 doAssert l.remove(l.head.next) == true
doAssert l.toSeq == [1, 3]
l.remove l3
doAssert l.toSeq == [1] doAssert l.toSeq == [1]
l.remove l1 doAssert l.remove(l.head) == true
doAssert l.toSeq == [] 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 static: main()
testCommon initDoublyLinkedList, toDoublyLinkedList main()
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 == []