added system.finished for first class iterators
This commit is contained in:
parent
7a2c11d3cf
commit
7f6633a06f
8 changed files with 55 additions and 12 deletions
|
|
@ -344,7 +344,7 @@ type
|
||||||
nfSem # node has been checked for semantics
|
nfSem # node has been checked for semantics
|
||||||
|
|
||||||
TNodeFlags* = set[TNodeFlag]
|
TNodeFlags* = set[TNodeFlag]
|
||||||
TTypeFlag* = enum # keep below 15 for efficiency reasons (now: 14)
|
TTypeFlag* = enum # keep below 17 for efficiency reasons (now: 16)
|
||||||
tfVarargs, # procedure has C styled varargs
|
tfVarargs, # procedure has C styled varargs
|
||||||
tfNoSideEffect, # procedure type does not allow side effects
|
tfNoSideEffect, # procedure type does not allow side effects
|
||||||
tfFinal, # is the object final?
|
tfFinal, # is the object final?
|
||||||
|
|
|
||||||
|
|
@ -692,13 +692,6 @@ proc liftIterator*(iter: PSym, body: PNode): PNode =
|
||||||
stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
|
stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt)))
|
||||||
result.add(stateAsgnStmt)
|
result.add(stateAsgnStmt)
|
||||||
|
|
||||||
# TODO:
|
|
||||||
# - nested iterators
|
|
||||||
# - arglist as a type
|
|
||||||
# - tyIterator everywhere
|
|
||||||
# - 'finished' builtin
|
|
||||||
# - 'start' builtin (XXX copy Lua's terminology?)
|
|
||||||
|
|
||||||
proc liftIterSym*(n: PNode): PNode =
|
proc liftIterSym*(n: PNode): PNode =
|
||||||
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
|
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
|
||||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||||
|
|
|
||||||
|
|
@ -1473,7 +1473,7 @@ proc simpleStmt(p: var TParser): PNode =
|
||||||
case p.tok.tokType
|
case p.tok.tokType
|
||||||
of tkReturn: result = parseReturnOrRaise(p, nkReturnStmt)
|
of tkReturn: result = parseReturnOrRaise(p, nkReturnStmt)
|
||||||
of tkRaise: result = parseReturnOrRaise(p, nkRaiseStmt)
|
of tkRaise: result = parseReturnOrRaise(p, nkRaiseStmt)
|
||||||
of tkYield: result = parseYieldOrDiscard(p, nkYieldStmt)
|
of tkYield: result = parseReturnOrRaise(p, nkYieldStmt)
|
||||||
of tkDiscard: result = parseReturnOrRaise(p, nkDiscardStmt)
|
of tkDiscard: result = parseReturnOrRaise(p, nkDiscardStmt)
|
||||||
of tkBreak: result = parseBreakOrContinue(p, nkBreakStmt)
|
of tkBreak: result = parseBreakOrContinue(p, nkBreakStmt)
|
||||||
of tkContinue: result = parseBreakOrContinue(p, nkContinueStmt)
|
of tkContinue: result = parseBreakOrContinue(p, nkContinueStmt)
|
||||||
|
|
|
||||||
|
|
@ -1173,6 +1173,8 @@ proc SemYield(c: PContext, n: PNode): PNode =
|
||||||
SemYieldVarResult(c, n, restype)
|
SemYieldVarResult(c, n, restype)
|
||||||
else:
|
else:
|
||||||
localError(n.info, errCannotReturnExpr)
|
localError(n.info, errCannotReturnExpr)
|
||||||
|
elif c.p.owner.typ.sons[0] != nil:
|
||||||
|
localError(n.info, errGenerated, "yield statement must yield a value")
|
||||||
|
|
||||||
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
|
proc lookUpForDefined(c: PContext, i: PIdent, onlyCurrentScope: bool): PSym =
|
||||||
if onlyCurrentScope:
|
if onlyCurrentScope:
|
||||||
|
|
|
||||||
|
|
@ -818,7 +818,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
|
||||||
result = semProcAux(c, n, skIterator, iteratorPragmas)
|
result = semProcAux(c, n, skIterator, iteratorPragmas)
|
||||||
var s = result.sons[namePos].sym
|
var s = result.sons[namePos].sym
|
||||||
var t = s.typ
|
var t = s.typ
|
||||||
if t.sons[0] == nil:
|
if t.sons[0] == nil and s.typ.callConv != ccClosure:
|
||||||
LocalError(n.info, errXNeedsReturnType, "iterator")
|
LocalError(n.info, errXNeedsReturnType, "iterator")
|
||||||
# iterators are either 'inline' or 'closure'; for backwards compatibility,
|
# iterators are either 'inline' or 'closure'; for backwards compatibility,
|
||||||
# we require first class iterators to be marked with 'closure' explicitly
|
# we require first class iterators to be marked with 'closure' explicitly
|
||||||
|
|
|
||||||
|
|
@ -2096,6 +2096,12 @@ when not defined(EcmaScript) and not defined(NimrodVM):
|
||||||
`result` = `x`.ClEnv;
|
`result` = `x`.ClEnv;
|
||||||
""".}
|
""".}
|
||||||
|
|
||||||
|
proc finished*[T: proc](x: T): bool {.noSideEffect, inline.} =
|
||||||
|
## can be used to determine if a first class iterator has finished.
|
||||||
|
{.emit: """
|
||||||
|
`result` = *((NI*) `x`.ClEnv) < 0;
|
||||||
|
""".}
|
||||||
|
|
||||||
elif defined(ecmaScript) or defined(NimrodVM):
|
elif defined(ecmaScript) or defined(NimrodVM):
|
||||||
# Stubs:
|
# Stubs:
|
||||||
proc GC_disable() = nil
|
proc GC_disable() = nil
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,14 @@ ta da1 1
|
||||||
3 3
|
3 3
|
||||||
0
|
0
|
||||||
1
|
1
|
||||||
2'''
|
2
|
||||||
|
a1: A
|
||||||
|
a2: A
|
||||||
|
a1: B
|
||||||
|
a2: B
|
||||||
|
a1: C
|
||||||
|
a2: C
|
||||||
|
a1: D'''
|
||||||
"""
|
"""
|
||||||
# Test first class iterator:
|
# Test first class iterator:
|
||||||
|
|
||||||
|
|
@ -77,3 +84,34 @@ proc invoke(iter: proc(): int {.closure.}) =
|
||||||
|
|
||||||
invoke(count0)
|
invoke(count0)
|
||||||
invoke(count2)
|
invoke(count2)
|
||||||
|
|
||||||
|
|
||||||
|
# simple tasking:
|
||||||
|
type
|
||||||
|
TTask = proc (ticker: int) {.closure.}
|
||||||
|
|
||||||
|
iterator a1(ticker: int) {.closure.} =
|
||||||
|
echo "a1: A"
|
||||||
|
yield
|
||||||
|
echo "a1: B"
|
||||||
|
yield
|
||||||
|
echo "a1: C"
|
||||||
|
yield
|
||||||
|
echo "a1: D"
|
||||||
|
|
||||||
|
iterator a2(ticker: int) {.closure.} =
|
||||||
|
echo "a2: A"
|
||||||
|
yield
|
||||||
|
echo "a2: B"
|
||||||
|
yield
|
||||||
|
echo "a2: C"
|
||||||
|
|
||||||
|
proc runTasks(t: varargs[TTask]) =
|
||||||
|
var ticker = 0
|
||||||
|
while true:
|
||||||
|
let x = t[ticker mod t.len]
|
||||||
|
if finished(x): break
|
||||||
|
x(ticker)
|
||||||
|
inc ticker
|
||||||
|
|
||||||
|
runTasks(a1, a2)
|
||||||
|
|
|
||||||
6
todo.txt
6
todo.txt
|
|
@ -1,7 +1,11 @@
|
||||||
version 0.9.2
|
version 0.9.2
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- test&finish first class iterators
|
- test&finish first class iterators:
|
||||||
|
* nested iterators
|
||||||
|
* arglist as a type?
|
||||||
|
* tyIterator?
|
||||||
|
|
||||||
- fix closure bug finally
|
- fix closure bug finally
|
||||||
- overloading based on ASTs: 'constraint' should not be in PType but for the
|
- overloading based on ASTs: 'constraint' should not be in PType but for the
|
||||||
parameter *symbol*
|
parameter *symbol*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue