next steps for first class iterators

This commit is contained in:
Araq 2012-11-26 02:43:32 +01:00
commit dd9ad9e497
7 changed files with 16 additions and 7 deletions

View file

@ -888,7 +888,13 @@ proc evalIsOp*(n: PNode): PNode =
of "closure": of "closure":
let t = skipTypes(t1, abstractRange) let t = skipTypes(t1, abstractRange)
result = newIntNode(nkIntLit, ord(t.kind == tyProc and result = newIntNode(nkIntLit, ord(t.kind == tyProc and
t.callConv == ccClosure)) t.callConv == ccClosure and
tfIterator notin t.flags))
of "iterator":
let t = skipTypes(t1, abstractRange)
result = newIntNode(nkIntLit, ord(t.kind == tyProc and
t.callConv == ccClosure and
tfIterator in t.flags))
else: else:
let t2 = n[2].typ let t2 = n[2].typ
var match = if t2.kind == tyTypeClass: matchTypeClass(t2, t1) var match = if t2.kind == tyTypeClass: matchTypeClass(t2, t1)

View file

@ -738,7 +738,7 @@ proc isExprStart(p: TParser): bool =
of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf,
tkProc, tkIterator, tkBind, tkProc, tkIterator, tkBind,
tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr,
tkTuple, tkType, tkWhen, tkCase: tkTuple, tkType, tkWhen, tkCase, tkShared:
result = true result = true
else: result = false else: result = false
@ -788,6 +788,7 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
of tkVar: result = parseTypeDescKAux(p, nkVarTy, mode) of tkVar: result = parseTypeDescKAux(p, nkVarTy, mode)
of tkRef: result = parseTypeDescKAux(p, nkRefTy, mode) of tkRef: result = parseTypeDescKAux(p, nkRefTy, mode)
of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, mode) of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, mode)
of tkShared: result = parseTypeDescKAux(p, nkSharedTy, mode)
of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr, mode) of tkType: result = parseTypeDescKAux(p, nkTypeOfExpr, mode)
of tkTuple: result = parseTuple(p) of tkTuple: result = parseTuple(p)
of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}) of tkProc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef})

View file

@ -744,11 +744,12 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
rawAddSon(s.typ, nil) rawAddSon(s.typ, nil)
if n.sons[patternPos].kind != nkEmpty: if n.sons[patternPos].kind != nkEmpty:
n.sons[patternPos] = semPattern(c, n.sons[patternPos]) n.sons[patternPos] = semPattern(c, n.sons[patternPos])
if s.kind == skIterator: s.typ.flags.incl(tfIterator)
var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope
# open for parameters # open for parameters
if proto == nil: if proto == nil:
s.typ.callConv = lastOptionEntry(c).defaultCC s.typ.callConv = lastOptionEntry(c).defaultCC
# add it here, so that recursive procs are possible: # add it here, so that recursive procs are possible:
# -2 because we have a scope open for parameters # -2 because we have a scope open for parameters
if sfGenSym in s.flags: nil if sfGenSym in s.flags: nil

View file

@ -911,6 +911,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
closeScope(c.tab) closeScope(c.tab)
if n.kind == nkIteratorTy: if n.kind == nkIteratorTy:
result.flags.incl(tfIterator) result.flags.incl(tfIterator)
result.callConv = ccClosure
of nkEnumTy: result = semEnum(c, n, prev) of nkEnumTy: result = semEnum(c, n, prev)
of nkType: result = n.typ of nkType: result = n.typ
of nkStmtListType: result = semStmtListType(c, n, prev) of nkStmtListType: result = semStmtListType(c, n, prev)

View file

@ -293,6 +293,8 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}: elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
# noSideEffect implies ``tfThread``! XXX really? # noSideEffect implies ``tfThread``! XXX really?
return isNone return isNone
elif f.flags * {tfIterator} != a.flags * {tfIterator}:
return isNone
elif f.callconv != a.callconv: elif f.callconv != a.callconv:
# valid to pass a 'nimcall' thingie to 'closure': # valid to pass a 'nimcall' thingie to 'closure':
if f.callconv == ccClosure and a.callconv == ccDefault: if f.callconv == ccClosure and a.callconv == ccDefault:

View file

@ -79,7 +79,7 @@ iterator count2(): int {.closure.} =
# a first class iterator has the type 'proc {.closure.}', but maybe # a first class iterator has the type 'proc {.closure.}', but maybe
# it shouldn't: # it shouldn't:
proc invoke(iter: proc(): int {.closure.}) = proc invoke(iter: iterator(): int {.closure.}) =
for x in iter(): echo x for x in iter(): echo x
invoke(count0) invoke(count0)
@ -88,7 +88,7 @@ invoke(count2)
# simple tasking: # simple tasking:
type type
TTask = proc (ticker: int) {.closure.} TTask = iterator (ticker: int)
iterator a1(ticker: int) {.closure.} = iterator a1(ticker: int) {.closure.} =
echo "a1: A" echo "a1: A"

View file

@ -2,7 +2,6 @@ version 0.9.2
============= =============
- test&finish first class iterators: - test&finish first class iterators:
* tyIterator: implement nkIteratorTy, nkSharedTy
* allow return in first class iterators * allow return in first class iterators
* nested iterators * nested iterators
* arglist as a type? * arglist as a type?
@ -34,7 +33,6 @@ Bugs
- bug: the parser is not strict enough with newlines: 'echo "a" echo "b"' - bug: the parser is not strict enough with newlines: 'echo "a" echo "b"'
compiles compiles
- bug: blocks can "export" an identifier but the CCG generates {} for them ... - bug: blocks can "export" an identifier but the CCG generates {} for them ...
- bug: what if we pass an iterator to a proc var? iterators use tyProc too ...
version 0.9.XX version 0.9.XX