tyieldintry.nim 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. discard """
  2. targets: "c"
  3. output: "ok"
  4. """
  5. var closureIterResult = newSeq[int]()
  6. # XXX Investigate why this fails now for 'nim cpp'
  7. proc checkpoint(arg: int) =
  8. closureIterResult.add(arg)
  9. type
  10. TestException = object of Exception
  11. AnotherException = object of Exception
  12. proc testClosureIterAux(it: iterator(): int, exceptionExpected: bool, expectedResults: varargs[int]) =
  13. closureIterResult.setLen(0)
  14. var exceptionCaught = false
  15. try:
  16. for i in it():
  17. closureIterResult.add(i)
  18. except TestException:
  19. exceptionCaught = true
  20. if closureIterResult != @expectedResults or exceptionCaught != exceptionExpected:
  21. if closureIterResult != @expectedResults:
  22. echo "Expected: ", @expectedResults
  23. echo "Actual: ", closureIterResult
  24. if exceptionCaught != exceptionExpected:
  25. echo "Expected exception: ", exceptionExpected
  26. echo "Got exception: ", exceptionCaught
  27. doAssert(false)
  28. proc test(it: iterator(): int, expectedResults: varargs[int]) =
  29. testClosureIterAux(it, false, expectedResults)
  30. proc testExc(it: iterator(): int, expectedResults: varargs[int]) =
  31. testClosureIterAux(it, true, expectedResults)
  32. proc raiseException() =
  33. raise newException(TestException, "Test exception!")
  34. block:
  35. iterator it(): int {.closure.} =
  36. var i = 5
  37. while i != 0:
  38. yield i
  39. if i == 3:
  40. yield 123
  41. dec i
  42. test(it, 5, 4, 3, 123, 2, 1)
  43. block:
  44. iterator it(): int {.closure.} =
  45. yield 0
  46. try:
  47. checkpoint(1)
  48. raiseException()
  49. except TestException:
  50. checkpoint(2)
  51. yield 3
  52. checkpoint(4)
  53. finally:
  54. checkpoint(5)
  55. checkpoint(6)
  56. test(it, 0, 1, 2, 3, 4, 5, 6)
  57. block:
  58. iterator it(): int {.closure.} =
  59. yield 0
  60. try:
  61. yield 1
  62. checkpoint(2)
  63. finally:
  64. checkpoint(3)
  65. yield 4
  66. checkpoint(5)
  67. yield 6
  68. test(it, 0, 1, 2, 3, 4, 5, 6)
  69. block:
  70. iterator it(): int {.closure.} =
  71. yield 0
  72. try:
  73. yield 1
  74. raiseException()
  75. yield 2
  76. finally:
  77. checkpoint(3)
  78. yield 4
  79. checkpoint(5)
  80. yield 6
  81. testExc(it, 0, 1, 3, 4, 5, 6)
  82. block:
  83. iterator it(): int {.closure.} =
  84. try:
  85. try:
  86. raiseException()
  87. except AnotherException:
  88. yield 123
  89. finally:
  90. checkpoint(3)
  91. finally:
  92. checkpoint(4)
  93. testExc(it, 3, 4)
  94. block:
  95. iterator it(): int {.closure.} =
  96. try:
  97. yield 1
  98. raiseException()
  99. except AnotherException:
  100. checkpoint(123)
  101. finally:
  102. checkpoint(2)
  103. checkpoint(3)
  104. testExc(it, 1, 2)
  105. block:
  106. iterator it(): int {.closure.} =
  107. try:
  108. yield 0
  109. try:
  110. yield 1
  111. try:
  112. yield 2
  113. raiseException()
  114. except AnotherException:
  115. yield 123
  116. finally:
  117. yield 3
  118. except AnotherException:
  119. yield 124
  120. finally:
  121. yield 4
  122. checkpoint(1234)
  123. except:
  124. yield 5
  125. checkpoint(6)
  126. finally:
  127. checkpoint(7)
  128. yield 8
  129. checkpoint(9)
  130. test(it, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  131. block:
  132. iterator it(): int {.closure.} =
  133. try:
  134. yield 0
  135. return 2
  136. finally:
  137. checkpoint(1)
  138. checkpoint(123)
  139. test(it, 0, 1)
  140. block:
  141. iterator it(): int {.closure.} =
  142. try:
  143. try:
  144. yield 0
  145. raiseException()
  146. finally:
  147. checkpoint(1)
  148. except TestException:
  149. yield 2
  150. return
  151. finally:
  152. yield 3
  153. checkpoint(123)
  154. test(it, 0, 1, 2, 3)
  155. block:
  156. iterator it(): int {.closure.} =
  157. try:
  158. try:
  159. yield 0
  160. raiseException()
  161. finally:
  162. return # Return in finally should stop exception propagation
  163. except AnotherException:
  164. yield 2
  165. return
  166. finally:
  167. yield 3
  168. checkpoint(123)
  169. test(it, 0, 3)
  170. block: # Yield in yield
  171. iterator it(): int {.closure.} =
  172. template foo(): int =
  173. yield 1
  174. 2
  175. for i in 0 .. 2:
  176. checkpoint(0)
  177. yield foo()
  178. test(it, 0, 1, 2, 0, 1, 2, 0, 1, 2)
  179. block:
  180. iterator it(): int {.closure.} =
  181. let i = if true:
  182. yield 0
  183. 1
  184. else:
  185. 2
  186. yield i
  187. test(it, 0, 1)
  188. block:
  189. iterator it(): int {.closure.} =
  190. var foo = 123
  191. let i = try:
  192. yield 0
  193. raiseException()
  194. 1
  195. except TestException as e:
  196. assert(e.msg == "Test exception!")
  197. case foo
  198. of 1:
  199. yield 123
  200. 2
  201. of 123:
  202. yield 5
  203. 6
  204. else:
  205. 7
  206. yield i
  207. test(it, 0, 5, 6)
  208. block:
  209. iterator it(): int {.closure.} =
  210. proc voidFoo(i1, i2, i3: int) =
  211. checkpoint(i1)
  212. checkpoint(i2)
  213. checkpoint(i3)
  214. proc foo(i1, i2, i3: int): int =
  215. voidFoo(i1, i2, i3)
  216. i3
  217. proc bar(i1: int): int =
  218. checkpoint(i1)
  219. template tryexcept: int =
  220. try:
  221. yield 1
  222. raiseException()
  223. 123
  224. except TestException:
  225. yield 2
  226. checkpoint(3)
  227. 4
  228. let e1 = true
  229. template ifelse1: int =
  230. if e1:
  231. yield 10
  232. 11
  233. else:
  234. 12
  235. template ifelse2: int =
  236. if ifelse1() == 12:
  237. yield 20
  238. 21
  239. else:
  240. yield 22
  241. 23
  242. let i = foo(bar(0), tryexcept, ifelse2)
  243. discard foo(bar(0), tryexcept, ifelse2)
  244. voidFoo(bar(0), tryexcept, ifelse2)
  245. yield i
  246. test(it,
  247. # let i = foo(bar(0), tryexcept, ifelse2)
  248. 0, # bar(0)
  249. 1, 2, 3, # tryexcept
  250. 10, # ifelse1
  251. 22, # ifelse22
  252. 0, 4, 23, # foo
  253. # discard foo(bar(0), tryexcept, ifelse2)
  254. 0, # bar(0)
  255. 1, 2, 3, # tryexcept
  256. 10, # ifelse1
  257. 22, # ifelse22
  258. 0, 4, 23, # foo
  259. # voidFoo(bar(0), tryexcept, ifelse2)
  260. 0, # bar(0)
  261. 1, 2, 3, # tryexcept
  262. 10, # ifelse1
  263. 22, # ifelse22
  264. 0, 4, 23, # foo
  265. 23 # i
  266. )
  267. block:
  268. iterator it(): int {.closure.} =
  269. checkpoint(0)
  270. for i in 0 .. 1:
  271. try:
  272. yield 1
  273. raiseException()
  274. except TestException as e:
  275. doAssert(e.msg == "Test exception!")
  276. yield 2
  277. except AnotherException:
  278. yield 123
  279. except:
  280. yield 1234
  281. finally:
  282. yield 3
  283. checkpoint(4)
  284. yield 5
  285. test(it, 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
  286. block:
  287. iterator it(): int {.closure.} =
  288. var i = 5
  289. template foo(): bool =
  290. yield i
  291. true
  292. while foo():
  293. dec i
  294. if i == 0:
  295. break
  296. test(it, 5, 4, 3, 2, 1)
  297. block: # Short cirquits
  298. iterator it(): int {.closure.} =
  299. template trueYield: bool =
  300. yield 1
  301. true
  302. template falseYield: bool =
  303. yield 0
  304. false
  305. if trueYield or falseYield:
  306. discard falseYield and trueYield
  307. if falseYield and trueYield:
  308. checkpoint(123)
  309. test(it, 1, 0, 0)
  310. block: #7969
  311. type
  312. SomeObj = object
  313. id: int
  314. iterator it(): int {.closure.} =
  315. template yieldAndSomeObj: SomeObj =
  316. var s: SomeObj
  317. s.id = 2
  318. yield 1
  319. s
  320. checkpoint(yieldAndSomeObj().id)
  321. var i = 5
  322. case i
  323. of 0:
  324. checkpoint(123)
  325. of 1, 2, 5:
  326. checkpoint(3)
  327. else:
  328. checkpoint(123)
  329. test(it, 1, 2, 3)
  330. block: # yield in blockexpr
  331. iterator it(): int {.closure.} =
  332. yield(block:
  333. checkpoint(1)
  334. yield 2
  335. 3
  336. )
  337. test(it, 1, 2, 3)
  338. block: #8851
  339. type
  340. Foo = ref object of RootObj
  341. template someFoo(): Foo =
  342. var f: Foo
  343. yield 1
  344. f
  345. iterator it(): int {.closure.} =
  346. var o: RootRef
  347. o = someFoo()
  348. test(it, 1)
  349. block: # 8243
  350. iterator it(): int {.closure.} =
  351. template yieldAndSeq: seq[int] =
  352. yield 1
  353. @[123, 5, 123]
  354. checkpoint(yieldAndSeq[1])
  355. test(it, 1, 5)
  356. block:
  357. iterator it(): int {.closure.} =
  358. template yieldAndSeq: seq[int] =
  359. yield 1
  360. @[123, 5, 123]
  361. template yieldAndNum: int =
  362. yield 2
  363. 1
  364. checkpoint(yieldAndSeq[yieldAndNum])
  365. test(it, 1, 2, 5)
  366. block: #9694 - yield in ObjConstr
  367. type Foo = object
  368. a, b: int
  369. template yieldAndNum: int =
  370. yield 1
  371. 2
  372. iterator it(): int {.closure.} =
  373. let a = Foo(a: 5, b: yieldAndNum())
  374. checkpoint(a.b)
  375. test(it, 1, 2)
  376. block: #9716
  377. iterator it(): int {.closure.} =
  378. var a = 0
  379. for i in 1 .. 3:
  380. var a: int # Make sure the "local" var is reset
  381. var b: string # ditto
  382. yield 1
  383. a += 5
  384. b &= "hello"
  385. doAssert(a == 5)
  386. doAssert(b == "hello")
  387. test(it, 1, 1, 1)
  388. block: # nnkChckRange
  389. type Foo = distinct uint64
  390. template yieldDistinct: Foo =
  391. yield 2
  392. Foo(0)
  393. iterator it(): int {.closure.} =
  394. yield 1
  395. var a: int
  396. a = int(yieldDistinct())
  397. yield 3
  398. test(it, 1, 2, 3)
  399. echo "ok"