Allow recursive closure iterators (#19939)
This commit is contained in:
parent
2c0aaac304
commit
ce4078acd4
3 changed files with 16 additions and 5 deletions
|
|
@ -886,7 +886,8 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||||
case callee.kind
|
case callee.kind
|
||||||
of skMacro, skTemplate: discard
|
of skMacro, skTemplate: discard
|
||||||
else:
|
else:
|
||||||
if callee.kind == skIterator and callee.id == c.p.owner.id:
|
if callee.kind == skIterator and callee.id == c.p.owner.id and
|
||||||
|
not isClosureIterator(c.p.owner.typ):
|
||||||
localError(c.config, n.info, errRecursiveDependencyIteratorX % callee.name.s)
|
localError(c.config, n.info, errRecursiveDependencyIteratorX % callee.name.s)
|
||||||
# error correction, prevents endless for loop elimination in transf.
|
# error correction, prevents endless for loop elimination in transf.
|
||||||
# See bug #2051:
|
# See bug #2051:
|
||||||
|
|
|
||||||
|
|
@ -4326,13 +4326,10 @@ Closure iterators and inline iterators have some restrictions:
|
||||||
1. For now, a closure iterator cannot be executed at compile time.
|
1. For now, a closure iterator cannot be executed at compile time.
|
||||||
2. `return` is allowed in a closure iterator but not in an inline iterator
|
2. `return` is allowed in a closure iterator but not in an inline iterator
|
||||||
(but rarely useful) and ends the iteration.
|
(but rarely useful) and ends the iteration.
|
||||||
3. Neither inline nor closure iterators can be (directly)* recursive.
|
3. Inline iterators cannot be recursive.
|
||||||
4. Neither inline nor closure iterators have the special `result` variable.
|
4. Neither inline nor closure iterators have the special `result` variable.
|
||||||
5. Closure iterators are not supported by the JS backend.
|
5. Closure iterators are not supported by the JS backend.
|
||||||
|
|
||||||
(*) Closure iterators can be co-recursive with a factory proc which results
|
|
||||||
in similar syntax to a recursive iterator. More details follow.
|
|
||||||
|
|
||||||
Iterators that are neither marked `{.closure.}` nor `{.inline.}` explicitly
|
Iterators that are neither marked `{.closure.}` nor `{.inline.}` explicitly
|
||||||
default to being inline, but this may change in future versions of the
|
default to being inline, but this may change in future versions of the
|
||||||
implementation.
|
implementation.
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ end
|
||||||
9018
|
9018
|
||||||
@[1, 2]
|
@[1, 2]
|
||||||
@[1, 2, 3]
|
@[1, 2, 3]
|
||||||
|
1
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -274,3 +275,15 @@ iterator cc() {.closure.} =
|
||||||
break
|
break
|
||||||
|
|
||||||
var a2 = cc
|
var a2 = cc
|
||||||
|
|
||||||
|
# bug #16876
|
||||||
|
block:
|
||||||
|
iterator a(num: int): int {.closure.} =
|
||||||
|
if num == 1:
|
||||||
|
yield num
|
||||||
|
else:
|
||||||
|
for i in a(num - 1):
|
||||||
|
yield i
|
||||||
|
|
||||||
|
for i in a(5):
|
||||||
|
echo i
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue