mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
The first commit reverts the revert of #23787. The second fixes lambdalifting in convolutedly nested closures/closureiters. This is considered to be the reason of #24094, though I can't tell for sure, as I was not able to reproduce #24094 for complicated but irrelevant reasons. Therefore I ask @jmgomez, @metagn or anyone who could reproduce it to try it again with this PR. I would suggest this PR to not be squashed if possible, as the history is already messy enough. Some theory behind the lambdalifting fix: - A closureiter that captures anything outside its body will always have `:up` in its env. This property is now used as a trigger to lift any proc that captures such a closureiter. - Instantiating a closureiter involves filling out its `:up`, which was previously done incorrectly. The fixed algorithm is to use "current" env if it is the owner of the iter declaration, or traverse through `:up`s of env param until the common ancestor is found. --------- Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
140 lines
2.0 KiB
Nim
140 lines
2.0 KiB
Nim
discard """
|
|
targets: "c"
|
|
output: '''
|
|
Test 1:
|
|
12
|
|
Test 2:
|
|
23
|
|
23
|
|
Test 3:
|
|
34
|
|
34
|
|
Test 4:
|
|
45
|
|
45
|
|
50
|
|
50
|
|
Test 5:
|
|
45
|
|
123
|
|
47
|
|
50
|
|
Test 6:
|
|
<hi>
|
|
Test 7:
|
|
0
|
|
1
|
|
2
|
|
'''
|
|
"""
|
|
|
|
block: #24094
|
|
echo "Test 1:"
|
|
proc foo() =
|
|
let x = 12
|
|
iterator bar2(): int {.closure.} =
|
|
yield x
|
|
proc bar() =
|
|
let z = bar2
|
|
for y in z(): # just doing bar2() gives param not in env: x
|
|
echo y
|
|
bar()
|
|
|
|
foo()
|
|
|
|
block: #24094
|
|
echo "Test 2:"
|
|
iterator foo(): int {.closure.} =
|
|
let x = 23
|
|
iterator bar2(): int {.closure.} =
|
|
yield x
|
|
proc bar() =
|
|
let z = bar2
|
|
for y in z():
|
|
echo y
|
|
bar()
|
|
yield x
|
|
|
|
for x in foo(): echo x
|
|
|
|
block: #24094
|
|
echo "Test 3:"
|
|
iterator foo(): int {.closure.} =
|
|
let x = 34
|
|
proc bar() =
|
|
echo x
|
|
iterator bar2(): int {.closure.} =
|
|
bar()
|
|
yield x
|
|
for y in bar2():
|
|
yield y
|
|
|
|
for x in foo(): echo x
|
|
|
|
block:
|
|
echo "Test 4:"
|
|
proc foo() =
|
|
var x = 45
|
|
iterator bar2(): int {.closure.} =
|
|
yield x
|
|
yield x + 3
|
|
|
|
let b1 = bar2
|
|
let b2 = bar2
|
|
echo b1()
|
|
echo b2()
|
|
x = 47
|
|
echo b1()
|
|
echo b2()
|
|
foo()
|
|
|
|
block:
|
|
echo "Test 5:"
|
|
proc foo() =
|
|
var x = 45
|
|
iterator bar2(): int {.closure.} =
|
|
yield x
|
|
yield x + 3
|
|
|
|
proc bar() =
|
|
var y = 123
|
|
iterator bar3(): int {.closure.} =
|
|
yield x
|
|
yield y
|
|
let b3 = bar3
|
|
for z in b3():
|
|
echo z
|
|
x = 47
|
|
let b2 = bar2
|
|
for z in b2():
|
|
echo z
|
|
bar()
|
|
foo()
|
|
|
|
block: #19154
|
|
echo "Test 6:"
|
|
proc test(s: string): proc(): iterator(): string =
|
|
iterator it(): string = yield s
|
|
proc f(): iterator(): string = it
|
|
return f
|
|
|
|
let it = test("hi")()
|
|
for s in it():
|
|
echo "<", s, ">"
|
|
|
|
block: #3824
|
|
echo "Test 7:"
|
|
proc main =
|
|
iterator factory(): int {.closure.} =
|
|
iterator bar(): int {.closure.} =
|
|
yield 0
|
|
yield 1
|
|
yield 2
|
|
|
|
for x in bar(): yield x
|
|
|
|
for x in factory():
|
|
echo x
|
|
|
|
main()
|