diff options
Diffstat (limited to 'tests/iter')
-rw-r--r-- | tests/iter/t1550.nim | 4 | ||||
-rw-r--r-- | tests/iter/t20891.nim | 28 | ||||
-rw-r--r-- | tests/iter/t21306.nim | 118 | ||||
-rw-r--r-- | tests/iter/t21737.nim | 22 | ||||
-rw-r--r-- | tests/iter/t22148.nim | 15 | ||||
-rw-r--r-- | tests/iter/t22548.nim | 21 | ||||
-rw-r--r-- | tests/iter/t22619.nim | 83 | ||||
-rw-r--r-- | tests/iter/t2771.nim | 4 | ||||
-rw-r--r-- | tests/iter/tanoniter1.nim | 1 | ||||
-rw-r--r-- | tests/iter/tclosureiters.nim | 22 | ||||
-rw-r--r-- | tests/iter/tgeniteratorinblock.nim | 54 | ||||
-rw-r--r-- | tests/iter/titer.nim | 33 | ||||
-rw-r--r-- | tests/iter/titer11.nim | 1 | ||||
-rw-r--r-- | tests/iter/titer12.nim | 1 | ||||
-rw-r--r-- | tests/iter/titer_issues.nim | 17 | ||||
-rw-r--r-- | tests/iter/titervaropenarray.nim | 2 | ||||
-rw-r--r-- | tests/iter/tyieldintry.nim | 24 |
17 files changed, 440 insertions, 10 deletions
diff --git a/tests/iter/t1550.nim b/tests/iter/t1550.nim index 8ad96f0da..c971943ee 100644 --- a/tests/iter/t1550.nim +++ b/tests/iter/t1550.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + type A[T] = iterator(x: T): T {.gcsafe, closure.} diff --git a/tests/iter/t20891.nim b/tests/iter/t20891.nim new file mode 100644 index 000000000..34deec41b --- /dev/null +++ b/tests/iter/t20891.nim @@ -0,0 +1,28 @@ +import macros, tables + +var mapping {.compileTime.}: Table[string, NimNode] + +macro register(a: static[string], b: typed): untyped = + mapping[a] = b + +macro getPtr(a: static[string]): untyped = + result = mapping[a] + +proc foo() = + iterator it() {.closure.} = + discard + proc getIterPtr(): pointer {.nimcall.} = + rawProc(it) + register("foo", getIterPtr()) + discard getIterPtr() # Comment either this to make it work +foo() # or this + +proc bar() = + iterator it() {.closure.} = + discard getPtr("foo") # Or this + discard + proc getIterPtr(): pointer {.nimcall.} = + rawProc(it) + register("bar", getIterPtr()) + discard getIterPtr() +bar() diff --git a/tests/iter/t21306.nim b/tests/iter/t21306.nim new file mode 100644 index 000000000..4d0396294 --- /dev/null +++ b/tests/iter/t21306.nim @@ -0,0 +1,118 @@ +discard """ + targets: "c js" +""" + +# bug #21306 +type + FutureState {.pure.} = enum + Pending, Finished, Cancelled, Failed + + FutureBase = ref object of RootObj + state: FutureState + error: ref CatchableError + id: uint + + Future[T] = ref object of FutureBase + closure: iterator(f: Future[T]): FutureBase {.raises: [Defect, CatchableError, Exception], gcsafe.} + value: T + +template setupFutureBase() = + new(result) + result.state = FutureState.Pending + +proc newFutureImpl[T](): Future[T] = + setupFutureBase() + +template newFuture[T](fromProc: static[string] = ""): Future[T] = + newFutureImpl[T]() + +proc internalRead[T](fut: Future[T]): T = + when T isnot void: + return fut.value + +template await[T](f: Future[T]): untyped = + when declared(chronosInternalRetFuture): + when not declaredInScope(chronosInternalTmpFuture): + var chronosInternalTmpFuture {.inject.}: FutureBase = f + else: + chronosInternalTmpFuture = f + + yield chronosInternalTmpFuture + + when T isnot void: + cast[type(f)](chronosInternalTmpFuture).internalRead() + +type + VerifierError {.pure.} = enum + Invalid + MissingParent + UnviableFork + Duplicate + ProcessingCallback = proc() {.gcsafe, raises: [Defect].} + BlockVerifier = + proc(signedBlock: int): + Future[VerifierError] {.gcsafe, raises: [Defect].} + + SyncQueueKind {.pure.} = enum + Forward, Backward + + SyncRequest[T] = object + kind: SyncQueueKind + index: uint64 + slot: uint64 + count: uint64 + item: T + + SyncResult[T] = object + request: SyncRequest[T] + data: seq[ref int] + + SyncQueue[T] = ref object + kind: SyncQueueKind + readyQueue: seq[SyncResult[T]] + blockVerifier: BlockVerifier + +iterator blocks[T](sq: SyncQueue[T], + sr: SyncResult[T]): ref int = + case sq.kind + of SyncQueueKind.Forward: + for i in countup(0, len(sr.data) - 1): + yield sr.data[i] + of SyncQueueKind.Backward: + for i in countdown(len(sr.data) - 1, 0): + yield sr.data[i] + +proc push[T](sq: SyncQueue[T]; sr: SyncRequest[T]; data: seq[ref int]; + processingCb: ProcessingCallback = nil): Future[void] {. + stackTrace: off, gcsafe.} = + iterator push_436208182(chronosInternalRetFuture: Future[void]): FutureBase {. + closure, gcsafe, raises: [Defect, CatchableError, Exception].} = + block: + template result(): auto {.used.} = + {.fatal: "You should not reference the `result` variable inside" & + " a void async proc".} + + let item = default(SyncResult[T]) + for blk in sq.blocks(item): + let res = await sq.blockVerifier(blk[]) + + var resultFuture = newFuture[void]("push") + resultFuture.closure = push_436208182 + return resultFuture + +type + SomeTPeer = ref object + score: int + +proc getSlice(): seq[ref int] = + discard + +template smokeTest(kkind: SyncQueueKind, start, finish: uint64, + chunkSize: uint64) = + var queue: SyncQueue[SomeTPeer] + var request: SyncRequest[SomeTPeer] + discard queue.push(request, getSlice()) + +for k in {SyncQueueKind.Forward}: + for item in [(uint64(1181), uint64(1399), 41'u64)]: + smokeTest(k, item[0], item[1], item[2]) \ No newline at end of file diff --git a/tests/iter/t21737.nim b/tests/iter/t21737.nim new file mode 100644 index 000000000..da06faea7 --- /dev/null +++ b/tests/iter/t21737.nim @@ -0,0 +1,22 @@ +discard """ + action: compile +""" + +template mytoSeq*(iter: untyped): untyped = + var result: seq[typeof(iter)]# = @[] + for x in iter: + result.add(x) + result + +iterator test(dir:int): int = + yield 1234 + +iterator walkGlobKinds (): int = + let dir2 = 123 + let it = mytoSeq(test(dir2)) + +proc main()= + let it = iterator(): int= + for path in walkGlobKinds(): + yield path +main() diff --git a/tests/iter/t22148.nim b/tests/iter/t22148.nim new file mode 100644 index 000000000..9954eed87 --- /dev/null +++ b/tests/iter/t22148.nim @@ -0,0 +1,15 @@ +discard """ + action: compile +""" + +import std/memfiles + +# bug #22148 +proc make*(input: string) = + var inp = memfiles.open(input) + for line in memSlices(inp): + let lineF = MemFile(mem: line.data, size: line.size) + for word in memSlices(lineF, ','): + discard + +make("") # Must call to trigger diff --git a/tests/iter/t22548.nim b/tests/iter/t22548.nim new file mode 100644 index 000000000..b9abb75d0 --- /dev/null +++ b/tests/iter/t22548.nim @@ -0,0 +1,21 @@ +discard """ + action: compile +""" + +type Xxx[T] = object + +iterator x(v: string): char = + var v2: Xxx[int] + + var y: v2.T + + echo y + +proc bbb(vv: string): proc () = + proc xxx() = + for c in x(vv): + echo c + + return xxx + +bbb("test")() diff --git a/tests/iter/t22619.nim b/tests/iter/t22619.nim new file mode 100644 index 000000000..6a98391f3 --- /dev/null +++ b/tests/iter/t22619.nim @@ -0,0 +1,83 @@ +# bug #22619 + +when false: # todo fixme + block: + type + Resource = object + value: int + + Object = object + r {.cursor.}: Resource + s {.cursor.}: seq[Resource] + + var numDestroy = 0 + + proc `=copy`(x: var Resource, y: Resource) {.error.} # disallow full copies + proc `=destroy`(x: Resource) = + inc numDestroy + + proc test() = + # perform the test in procedure so that globals aren't used (their different + # semantics with regards to destruction would interfere) + var + r = Resource(value: 1) # initialize a resource + s = @[Resource(value: 2)] + + # make sure no copy is required in the initializer expression: + var o = Object(r: r, s: s) + + # copying the object doesn't perform a full copy of the cursor fields: + var o2 = o + discard addr(o2) # prevent `o2` from being turned into a cursor + + # check that the fields were shallow-copied: + doAssert o2.r.value == 1 + doAssert o2.s[0].value == 2 + + # make sure no copy is required with normal field assignments: + o.r = r + o.s = s + + + # when `o` and `o2` are destroyed, their destructor must not be called on + # their fields + + test() + + # one call for the `r` local and one for the object in `s` + doAssert numDestroy == 2 + +block: + type Value = distinct int + + var numDestroy = 0 + + when defined(gcRefc): + proc `=destroy`(x: var Value) = + inc numDestroy + else: + proc `=destroy`(x: Value) = + inc numDestroy + + iterator iter(s: seq[Value]): int {.closure.} = + # because it is used across yields, `s2` is lifted into the iterator's + # environment. Since non-ref cursors in object didn't have their hooks + # disabled inside the environments lifted hooks, this led to double + # frees + var s2 {.cursor.} = s + var i = 0 + let L = s2.len + while i < L: + yield s2[i].int + inc i + + proc test() = + var s = @[Value(1), Value(2)] + let cl = iter + # make sure resuming the iterator works: + doAssert cl(s) == 1 + doAssert cl(s) == 2 + doAssert cl(s) == 0 + + test() + doAssert numDestroy == 2 diff --git a/tests/iter/t2771.nim b/tests/iter/t2771.nim index 49befb0a9..71a8a9dcd 100644 --- a/tests/iter/t2771.nim +++ b/tests/iter/t2771.nim @@ -1,3 +1,7 @@ +discard """ + targets: "c js" +""" + template t1(i: int): int= i+1 template t2(i: int): int= diff --git a/tests/iter/tanoniter1.nim b/tests/iter/tanoniter1.nim index 9f0d0a74b..fee16497f 100644 --- a/tests/iter/tanoniter1.nim +++ b/tests/iter/tanoniter1.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js" output: '''1 2 3 diff --git a/tests/iter/tclosureiters.nim b/tests/iter/tclosureiters.nim index 85611373c..4a2639852 100644 --- a/tests/iter/tclosureiters.nim +++ b/tests/iter/tclosureiters.nim @@ -1,4 +1,5 @@ discard """ + targets: "c js" output: '''0 1 2 @@ -152,15 +153,18 @@ iterator filesIt(path: string): auto {.closure.} = yield prefix / f # bug #13815 -var love = iterator: int {.closure.} = - yield cast[type( - block: - var a = 0 - yield a - a)](0) - -for i in love(): - echo i +when not defined(js): + var love = iterator: int {.closure.} = + yield cast[type( + block: + var a = 0 + yield a + a)](0) + + for i in love(): + echo i +else: + echo 0 # bug #18474 iterator pairs(): (int, int) {.closure.} = diff --git a/tests/iter/tgeniteratorinblock.nim b/tests/iter/tgeniteratorinblock.nim new file mode 100644 index 000000000..2ab903996 --- /dev/null +++ b/tests/iter/tgeniteratorinblock.nim @@ -0,0 +1,54 @@ +discard """ + output: '''30 +60 +90 +150 +180 +210 +240 +60 +180 +240 +[60, 180, 240] +[60, 180]''' +""" +import std/enumerate + +template map[T; Y](i: iterable[T], fn: proc(x: T): Y): untyped = + iterator internal(): Y {.gensym.} = + for it in i: + yield fn(it) + internal() + +template filter[T](i: iterable[T], fn: proc(x: T): bool): untyped = + iterator internal(): T {.gensym.} = + for it in i: + if fn(it): + yield it + internal() + +template group[T](i: iterable[T], amount: static int): untyped = + iterator internal(): array[amount, T] {.gensym.} = + var val: array[amount, T] + for ind, it in enumerate i: + val[ind mod amount] = it + if ind mod amount == amount - 1: + yield val + internal() + +var a = [10, 20, 30, 50, 60, 70, 80] + +proc mapFn(x: int): int = x * 3 +proc filterFn(x: int): bool = x mod 20 == 0 + +for x in a.items.map(mapFn): + echo x + +for y in a.items.map(mapFn).filter(filterFn): + echo y + +for y in a.items.map(mapFn).filter(filterFn).group(3): + echo y + +for y in a.items.map(mapFn).filter(filterFn).group(2): + echo y diff --git a/tests/iter/titer.nim b/tests/iter/titer.nim index 3a2450ae3..b03d43f36 100644 --- a/tests/iter/titer.nim +++ b/tests/iter/titer.nim @@ -112,3 +112,36 @@ let res = collect: fn2(v2) doAssert res == @[42, 43, 43, 44] + +block: # bug #21110 + iterator p(): int = + when nimvm: + yield 0 + else: + yield 0 + + template foo = + for k in p(): + let m = "" + proc e() = discard m & "" + e() + static: foo() + foo() + + +# bug #15924 +iterator walk(): (int, int) {.closure.} = + yield (10,11) + +for (i,j) in walk(): + doAssert i == 10 + +proc main123() = + let x = false + iterator it(): (bool, bool) {.closure.} = # normally {.closure.} here makes #21476 work + discard x + + for (_, _) in it(): + discard + +main123() diff --git a/tests/iter/titer11.nim b/tests/iter/titer11.nim index 2b39c74f7..153b3c29a 100644 --- a/tests/iter/titer11.nim +++ b/tests/iter/titer11.nim @@ -1,4 +1,5 @@ discard """ +targets: "c js" output: ''' [ 1 diff --git a/tests/iter/titer12.nim b/tests/iter/titer12.nim index f7fc64da4..f264a0e82 100644 --- a/tests/iter/titer12.nim +++ b/tests/iter/titer12.nim @@ -1,4 +1,5 @@ discard """ +targets: "c js" output: ''' Selecting 2 1.0 diff --git a/tests/iter/titer_issues.nim b/tests/iter/titer_issues.nim index adba8a8e3..c82b3902d 100644 --- a/tests/iter/titer_issues.nim +++ b/tests/iter/titer_issues.nim @@ -1,4 +1,5 @@ discard """ + target: "c js" output: ''' 0 1 @@ -392,3 +393,19 @@ iterator tryFinally() {.closure.} = var x = tryFinally x() + +block: # bug #24033 + type Query = ref object + + iterator pairs(query: Query): (int, (string, float32)) = + var output: (int, (string, float32)) = (0, ("foo", 3.14)) + for id in @[0, 1, 2]: + output[0] = id + yield output + + var collections: seq[(int, string, string)] + + for id, (str, num) in Query(): + collections.add (id, str, $num) + + doAssert collections[1] == (1, "foo", "3.14") diff --git a/tests/iter/titervaropenarray.nim b/tests/iter/titervaropenarray.nim index ad1192bd8..b2fe71ceb 100644 --- a/tests/iter/titervaropenarray.nim +++ b/tests/iter/titervaropenarray.nim @@ -1,6 +1,6 @@ discard """ output: "123" - targets: "c" + targets: "c cpp" """ # Try to break the transformation pass: iterator iterAndZero(a: var openArray[int]): int = diff --git a/tests/iter/tyieldintry.nim b/tests/iter/tyieldintry.nim index 9df201dd4..e51ab7f0d 100644 --- a/tests/iter/tyieldintry.nim +++ b/tests/iter/tyieldintry.nim @@ -1,4 +1,5 @@ discard """ + matrix: "; --experimental:strictdefs; -d:nimOptIters" targets: "c cpp" """ @@ -503,3 +504,26 @@ block: # void iterator except: discard var a = it + +if defined(nimOptIters): # Locals present in only 1 state should be on the stack + proc checkOnStack(a: pointer, shouldBeOnStack: bool) = + # Quick and dirty way to check if a points to stack + var dummy = 0 + let dummyAddr = addr dummy + let distance = abs(cast[int](dummyAddr) - cast[int](a)) + const requiredDistance = 300 + if shouldBeOnStack: + doAssert(distance <= requiredDistance, "a is not on stack, but should") + else: + doAssert(distance > requiredDistance, "a is on stack, but should not") + + iterator it(): int {.closure.} = + var a = 1 + var b = 2 + var c {.liftLocals.} = 3 + checkOnStack(addr a, true) + checkOnStack(addr b, false) + checkOnStack(addr c, false) + yield a + yield b + test(it, 1, 2) |