split the inline and closure iterators into different symbol kinds for easier discrimination between them

This commit is contained in:
Zahary Karadjov 2014-03-06 21:57:35 +02:00
commit 862c0ef83d
26 changed files with 110 additions and 84 deletions

View file

@ -469,7 +469,8 @@ type
skResult, # special 'result' variable skResult, # special 'result' variable
skProc, # a proc skProc, # a proc
skMethod, # a method skMethod, # a method
skIterator, # an iterator skIterator, # an inline iterator
skClosureIterator, # a resumable closure iterator
skConverter, # a type converter skConverter, # a type converter
skMacro, # a macro skMacro, # a macro
skTemplate, # a template; currently also misused for user-defined skTemplate, # a template; currently also misused for user-defined
@ -485,8 +486,8 @@ type
TSymKinds* = set[TSymKind] TSymKinds* = set[TSymKind]
const const
routineKinds* = {skProc, skMethod, skIterator, skConverter, routineKinds* = {skProc, skMethod, skIterator, skClosureIterator,
skMacro, skTemplate} skConverter, skMacro, skTemplate}
tfIncompleteStruct* = tfVarargs tfIncompleteStruct* = tfVarargs
skError* = skUnknown skError* = skUnknown
@ -820,8 +821,8 @@ type
# the poor naming choices in the standard library. # the poor naming choices in the standard library.
const const
OverloadableSyms* = {skProc, skMethod, skIterator, skConverter, OverloadableSyms* = {skProc, skMethod, skIterator, skClosureIterator,
skModule, skTemplate, skMacro} skConverter, skModule, skTemplate, skMacro}
GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody, GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody,
tyGenericParam} tyGenericParam}
@ -843,7 +844,8 @@ const
tyTuple, tySequence} tyTuple, tySequence}
NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence, NilableTypes*: TTypeKinds = {tyPointer, tyCString, tyRef, tyPtr, tySequence,
tyProc, tyString, tyError} tyProc, tyString, tyError}
ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator, ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType,
skIterator, skClosureIterator,
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub} skMacro, skTemplate, skConverter, skEnumField, skLet, skStub}
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
nfDotSetter, nfDotField, nfDotSetter, nfDotField,
@ -869,7 +871,10 @@ const
nkStrKinds* = {nkStrLit..nkTripleStrLit} nkStrKinds* = {nkStrLit..nkTripleStrLit}
skLocalVars* = {skVar, skLet, skForVar, skParam, skResult} skLocalVars* = {skVar, skLet, skForVar, skParam, skResult}
skProcKinds* = {skProc, skTemplate, skMacro, skIterator, skMethod, skConverter} skProcKinds* = {skProc, skTemplate, skMacro, skIterator, skClosureIterator,
skMethod, skConverter}
skIterators* = {skIterator, skClosureIterator}
lfFullExternalName* = lfParamCopy # \ lfFullExternalName* = lfParamCopy # \
# only used when 'gCmd == cmdPretty': Indicates that the symbol has been # only used when 'gCmd == cmdPretty': Indicates that the symbol has been
@ -1479,8 +1484,7 @@ proc originatingModule*(s: PSym): PSym =
while result.kind != skModule: result = result.owner while result.kind != skModule: result = result.owner
proc isRoutine*(s: PSym): bool {.inline.} = proc isRoutine*(s: PSym): bool {.inline.} =
result = s.kind in {skProc, skTemplate, skMacro, skIterator, skMethod, result = s.kind in skProcKinds
skConverter}
proc hasPattern*(s: PSym): bool {.inline.} = proc hasPattern*(s: PSym): bool {.inline.} =
result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty result = isRoutine(s) and s.ast.sons[patternPos].kind != nkEmpty

View file

@ -1803,7 +1803,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
else: else:
genProc(p.module, sym) genProc(p.module, sym)
putLocIntoDest(p, d, sym.loc) putLocIntoDest(p, d, sym.loc)
of skProc, skConverter, skIterator: of skProc, skConverter, skIterators:
genProc(p.module, sym) genProc(p.module, sym)
if sym.loc.r == nil or sym.loc.t == nil: if sym.loc.r == nil or sym.loc.t == nil:
internalError(n.info, "expr: proc not init " & sym.name.s) internalError(n.info, "expr: proc not init " & sym.name.s)

View file

@ -863,7 +863,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): PRope =
res.add(t.sons[i].strVal) res.add(t.sons[i].strVal)
of nkSym: of nkSym:
var sym = t.sons[i].sym var sym = t.sons[i].sym
if sym.kind in {skProc, skIterator, skMethod}: if sym.kind in {skProc, skIterator, skClosureIterator, skMethod}:
var a: TLoc var a: TLoc
initLocExpr(p, t.sons[i], a) initLocExpr(p, t.sons[i], a)
res.add(rdLoc(a).ropeToStr) res.add(rdLoc(a).ropeToStr)

View file

@ -69,7 +69,7 @@ proc mangleName(s: PSym): PRope =
if result == nil: if result == nil:
if gCmd == cmdCompileToLLVM: if gCmd == cmdCompileToLLVM:
case s.kind case s.kind
of skProc, skMethod, skConverter, skConst, skIterator: of skProc, skMethod, skConverter, skConst, skIterators:
result = ~"@" result = ~"@"
of skVar, skForVar, skResult, skLet: of skVar, skForVar, skResult, skLet:
if sfGlobal in s.flags: result = ~"@" if sfGlobal in s.flags: result = ~"@"

View file

@ -705,7 +705,7 @@ proc cgsym(m: BModule, name: string): PRope =
var sym = magicsys.getCompilerProc(name) var sym = magicsys.getCompilerProc(name)
if sym != nil: if sym != nil:
case sym.kind case sym.kind
of skProc, skMethod, skConverter, skIterator: genProc(m, sym) of skProc, skMethod, skConverter, skIterators: genProc(m, sym)
of skVar, skResult, skLet: genVarPrototype(m, sym) of skVar, skResult, skLet: genVarPrototype(m, sym)
of skType: discard getTypeDesc(m, sym.typ) of skType: discard getTypeDesc(m, sym.typ)
else: internalError("cgsym: " & name) else: internalError("cgsym: " & name)

View file

@ -366,7 +366,7 @@ proc generateJson(d: PDoc, n: PNode, jArray: PJsonNode = nil): PJsonNode =
proc genSection(d: PDoc, kind: TSymKind) = proc genSection(d: PDoc, kind: TSymKind) =
const sectionNames: array[skModule..skTemplate, string] = [ const sectionNames: array[skModule..skTemplate, string] = [
"Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Methods", "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Methods",
"Iterators", "Converters", "Macros", "Templates" "Iterators", "Iterators", "Converters", "Macros", "Templates"
] ]
if d.section[kind] == nil: return if d.section[kind] == nil: return
var title = sectionNames[kind].toRope var title = sectionNames[kind].toRope

View file

@ -103,7 +103,7 @@ proc importSymbol(c: PContext, n: PNode, fromMod: PSym) =
internalError(n.info, "importSymbol: 2") internalError(n.info, "importSymbol: 2")
# for an enumeration we have to add all identifiers # for an enumeration we have to add all identifiers
case s.kind case s.kind
of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter: of skProcKinds:
# for a overloadable syms add all overloaded routines # for a overloadable syms add all overloaded routines
var it: TIdentIter var it: TIdentIter
var e = initIdentIter(it, fromMod.tab, s.name) var e = initIdentIter(it, fromMod.tab, s.name)

View file

@ -1154,7 +1154,7 @@ proc createVar(p: PProc, typ: PType, indirect: bool): PRope =
proc isIndirect(v: PSym): bool = proc isIndirect(v: PSym): bool =
result = (sfAddrTaken in v.flags) and (mapType(v.typ) != etyObject) and result = (sfAddrTaken in v.flags) and (mapType(v.typ) != etyObject) and
v.kind notin {skProc, skConverter, skMethod, skIterator} v.kind notin {skProc, skConverter, skMethod, skIterator, skClosureIterator}
proc genVarInit(p: PProc, v: PSym, n: PNode) = proc genVarInit(p: PProc, v: PSym, n: PNode) =
var var

View file

@ -232,9 +232,9 @@ proc newOuterContext(fn: PSym, up: POuterContext = nil): POuterContext =
initIdNodeTable(result.localsToAccess) initIdNodeTable(result.localsToAccess)
initIdTable(result.localsToEnv) initIdTable(result.localsToEnv)
initIdTable(result.lambdasToEnv) initIdTable(result.lambdasToEnv)
result.isIter = fn.kind == skIterator and fn.typ.callConv == ccClosure result.isIter = fn.kind == skClosureIterator
if result.isIter: initIterContext(result, fn) if result.isIter: initIterContext(result, fn)
proc newInnerContext(fn: PSym): PInnerContext = proc newInnerContext(fn: PSym): PInnerContext =
new(result) new(result)
result.fn = fn result.fn = fn
@ -292,8 +292,7 @@ proc newCall(a, b: PSym): PNode =
result.add newSymNode(b) result.add newSymNode(b)
proc isInnerProc(s, outerProc: PSym): bool {.inline.} = proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
result = (s.kind in {skProc, skMethod, skConverter} or result = s.kind in {skProc, skMethod, skConverter, skClosureIterator} and
s.kind == skIterator and s.typ.callConv == ccClosure) and
s.skipGenericOwner == outerProc s.skipGenericOwner == outerProc
#s.typ.callConv == ccClosure #s.typ.callConv == ccClosure
@ -653,7 +652,7 @@ proc outerProcSons(o: POuterContext, n: PNode) =
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))
let iter = n.sym let iter = n.sym
assert iter.kind == skIterator assert iter.kind == skClosureIterator
result = newNodeIT(nkStmtListExpr, n.info, n.typ) result = newNodeIT(nkStmtListExpr, n.info, n.typ)
@ -679,7 +678,7 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
var closure = PEnv(idTableGet(o.lambdasToEnv, local)) var closure = PEnv(idTableGet(o.lambdasToEnv, local))
if local.kind == skIterator and local.typ.callConv == ccClosure: if local.kind == skClosureIterator:
# consider: [i1, i2, i1] Since we merged the iterator's closure # consider: [i1, i2, i1] Since we merged the iterator's closure
# with the captured owning variables, we need to generate the # with the captured owning variables, we need to generate the
# closure generation code again: # closure generation code again:
@ -843,10 +842,10 @@ proc liftForLoop*(body: PNode): PNode =
# static binding? # static binding?
var env: PSym var env: PSym
if call[0].kind == nkSym and call[0].sym.kind == skIterator: if call[0].kind == nkSym and call[0].sym.kind == skClosureIterator:
# createClosure() # createClosure()
let iter = call[0].sym let iter = call[0].sym
assert iter.kind == skIterator assert iter.kind == skClosureIterator
env = copySym(getHiddenParam(iter)) env = copySym(getHiddenParam(iter))
var v = newNodeI(nkVarSection, body.info) var v = newNodeI(nkVarSection, body.info)

View file

@ -109,7 +109,7 @@ type
proc getSymRepr*(s: PSym): string = proc getSymRepr*(s: PSym): string =
case s.kind case s.kind
of skProc, skMethod, skConverter, skIterator: result = getProcHeader(s) of skProc, skMethod, skConverter, skIterators: result = getProcHeader(s)
else: result = s.name.s else: result = s.name.s
proc ensureNoMissingOrUnusedSymbols(scope: PScope) = proc ensureNoMissingOrUnusedSymbols(scope: PScope) =

View file

@ -772,6 +772,17 @@ proc implictPragmas*(c: PContext, sym: PSym, n: PNode,
addToLib(lib, sym) addToLib(lib, sym)
if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s) if sym.loc.r == nil: sym.loc.r = toRope(sym.name.s)
proc hasPragma*(n: PNode, pragma: TSpecialWord): bool =
if n == nil or n.sons == nil:
return false
for p in n.sons:
var key = if p.kind == nkExprColonExpr: p[0] else: p
if key.kind == nkIdent and whichKeyword(key.ident) == pragma:
return true
return false
proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) = proc pragma(c: PContext, sym: PSym, n: PNode, validPragmas: TSpecialWords) =
if n == nil: return if n == nil: return
for i in countup(0, sonsLen(n) - 1): for i in countup(0, sonsLen(n) - 1):

View file

@ -64,7 +64,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
errors[errors.len - 1].add("\n " & err) errors[errors.len - 1].add("\n " & err)
if z.state == csMatch: if z.state == csMatch:
# little hack so that iterators are preferred over everything else: # little hack so that iterators are preferred over everything else:
if sym.kind == skIterator: inc(z.exactMatches, 200) if sym.kind in skIterators: inc(z.exactMatches, 200)
case best.state case best.state
of csEmpty, csNoMatch: best = z of csEmpty, csNoMatch: best = z
of csMatch: of csMatch:
@ -289,8 +289,9 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
result = newNodeI(a.kind, n.info) result = newNodeI(a.kind, n.info)
for i in countup(0, len(a)-1): for i in countup(0, len(a)-1):
var candidate = a.sons[i].sym var candidate = a.sons[i].sym
if candidate.kind in {skProc, skMethod, skConverter, skIterator}: if candidate.kind in {skProc, skMethod, skConverter,
# if suffices that the candidate has the proper number of generic skIterator, skClosureIterator}:
# it suffices that the candidate has the proper number of generic
# type parameters: # type parameters:
if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1: if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
result.add(explicitGenericSym(c, n, candidate)) result.add(explicitGenericSym(c, n, candidate))

View file

@ -274,7 +274,7 @@ proc makeRangeType*(c: PContext; first, last: BiggestInt;
addSonSkipIntLit(result, intType) # basetype of range addSonSkipIntLit(result, intType) # basetype of range
proc markIndirect*(c: PContext, s: PSym) {.inline.} = proc markIndirect*(c: PContext, s: PSym) {.inline.} =
if s.kind in {skProc, skConverter, skMethod, skIterator}: if s.kind in {skProc, skConverter, skMethod, skIterator, skClosureIterator}:
incl(s.flags, sfAddrTaken) incl(s.flags, sfAddrTaken)
# XXX add to 'c' for global analysis # XXX add to 'c' for global analysis

View file

@ -662,11 +662,11 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
flags: TExprFlags): PNode = flags: TExprFlags): PNode =
if flags*{efInTypeof, efWantIterator} != {}: if flags*{efInTypeof, efWantIterator} != {}:
# consider: 'for x in pReturningArray()' --> we don't want the restriction # consider: 'for x in pReturningArray()' --> we don't want the restriction
# to 'skIterator' anymore; skIterator is preferred in sigmatch already for # to 'skIterators' anymore; skIterators are preferred in sigmatch already
# typeof support. # for typeof support.
# for ``type(countup(1,3))``, see ``tests/ttoseq``. # for ``type(countup(1,3))``, see ``tests/ttoseq``.
result = semOverloadedCall(c, n, nOrig, result = semOverloadedCall(c, n, nOrig,
{skProc, skMethod, skConverter, skMacro, skTemplate, skIterator}) {skProc, skMethod, skConverter, skMacro, skTemplate}+skIterators)
else: else:
result = semOverloadedCall(c, n, nOrig, result = semOverloadedCall(c, n, nOrig,
{skProc, skMethod, skConverter, skMacro, skTemplate}) {skProc, skMethod, skConverter, skMacro, skTemplate})
@ -679,7 +679,7 @@ 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 in skIterators) and (callee.id == c.p.owner.id):
localError(n.info, errRecursiveDependencyX, callee.name.s) localError(n.info, errRecursiveDependencyX, callee.name.s)
if sfNoSideEffect notin callee.flags: if sfNoSideEffect notin callee.flags:
if {sfImportc, sfSideEffect} * callee.flags != {}: if {sfImportc, sfSideEffect} * callee.flags != {}:
@ -1193,7 +1193,7 @@ proc semReturn(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1)
if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro} or if c.p.owner.kind in {skConverter, skMethod, skProc, skMacro} or
(c.p.owner.kind == skIterator and c.p.owner.typ.callConv == ccClosure): c.p.owner.kind == skClosureIterator:
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
# transform ``return expr`` to ``result = expr; return`` # transform ``return expr`` to ``result = expr; return``
if c.p.resultSym != nil: if c.p.resultSym != nil:
@ -1258,7 +1258,7 @@ proc semYieldVarResult(c: PContext, n: PNode, restype: PType) =
proc semYield(c: PContext, n: PNode): PNode = proc semYield(c: PContext, n: PNode): PNode =
result = n result = n
checkSonsLen(n, 1) checkSonsLen(n, 1)
if c.p.owner == nil or c.p.owner.kind != skIterator: if c.p.owner == nil or c.p.owner.kind notin skIterators:
localError(n.info, errYieldNotAllowedHere) localError(n.info, errYieldNotAllowedHere)
elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline: elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
localError(n.info, errYieldNotAllowedInTryStmt) localError(n.info, errYieldNotAllowedInTryStmt)
@ -1266,9 +1266,11 @@ proc semYield(c: PContext, n: PNode): PNode =
n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility: n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility:
var restype = c.p.owner.typ.sons[0] var restype = c.p.owner.typ.sons[0]
if restype != nil: if restype != nil:
n.sons[0] = fitNode(c, restype.base, n.sons[0]) let adjustedRes = if c.p.owner.kind == skIterator: restype.base
else: restype
n.sons[0] = fitNode(c, adjustedRes, n.sons[0])
if n.sons[0].typ == nil: internalError(n.info, "semYield") if n.sons[0].typ == nil: internalError(n.info, "semYield")
semYieldVarResult(c, n, restype) semYieldVarResult(c, n, adjustedRes)
else: else:
localError(n.info, errCannotReturnExpr) localError(n.info, errCannotReturnExpr)
elif c.p.owner.typ.sons[0] != nil: elif c.p.owner.typ.sons[0] != nil:
@ -1828,7 +1830,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
var s = lookUp(c, n) var s = lookUp(c, n)
semCaptureSym(s, c.p.owner) semCaptureSym(s, c.p.owner)
result = semSym(c, n, s, flags) result = semSym(c, n, s, flags)
if s.kind in {skProc, skMethod, skIterator, skConverter}: if s.kind in {skProc, skMethod, skConverter}+skIterators:
#performProcvarCheck(c, n, s) #performProcvarCheck(c, n, s)
result = symChoice(c, n, s, scClosed) result = symChoice(c, n, s, scClosed)
if result.kind == nkSym: if result.kind == nkSym:
@ -1918,7 +1920,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
localError(n.info, errUseQualifier, s.name.s) localError(n.info, errUseQualifier, s.name.s)
elif s.magic == mNone: result = semDirectOp(c, n, flags) elif s.magic == mNone: result = semDirectOp(c, n, flags)
else: result = semMagic(c, n, s, flags) else: result = semMagic(c, n, s, flags)
of skProc, skMethod, skConverter, skIterator: of skProc, skMethod, skConverter, skIterators:
if s.magic == mNone: result = semDirectOp(c, n, flags) if s.magic == mNone: result = semDirectOp(c, n, flags)
else: result = semMagic(c, n, s, flags) else: result = semMagic(c, n, s, flags)
else: else:
@ -1942,7 +1944,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
of nkBracketExpr: of nkBracketExpr:
checkMinSonsLen(n, 1) checkMinSonsLen(n, 1)
var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared}) var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
if s != nil and s.kind in {skProc, skMethod, skConverter, skIterator}: if s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators:
# type parameters: partial generic specialization # type parameters: partial generic specialization
n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s) n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
result = explicitGenericInstantiation(c, n, s) result = explicitGenericInstantiation(c, n, s)

View file

@ -42,7 +42,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
of skUnknown: of skUnknown:
# Introduced in this pass! Leave it as an identifier. # Introduced in this pass! Leave it as an identifier.
result = n result = n
of skProc, skMethod, skIterator, skConverter: of skProc, skMethod, skIterators, skConverter:
result = symChoice(c, n, s, scOpen) result = symChoice(c, n, s, scOpen)
of skTemplate: of skTemplate:
if macroToExpand(s): if macroToExpand(s):
@ -141,7 +141,7 @@ proc semGenericStmt(c: PContext, n: PNode,
# symbol lookup ... # symbol lookup ...
of skUnknown, skParam: of skUnknown, skParam:
# Leave it as an identifier. # Leave it as an identifier.
of skProc, skMethod, skIterator, skConverter: of skProc, skMethod, skIterators, skConverter:
result.sons[0] = symChoice(c, n.sons[0], s, scOption) result.sons[0] = symChoice(c, n.sons[0], s, scOption)
first = 1 first = 1
of skGenericParam: of skGenericParam:

View file

@ -76,8 +76,8 @@ proc performProcvarCheck(c: PContext, n: PNode, s: PSym) =
proc semProcvarCheck(c: PContext, n: PNode) = proc semProcvarCheck(c: PContext, n: PNode) =
let n = n.skipConv let n = n.skipConv
if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skIterator, if n.kind == nkSym and n.sym.kind in {skProc, skMethod, skConverter,
skConverter}: skIterator, skClosureIterator}:
performProcvarCheck(c, n, n.sym) performProcvarCheck(c, n, n.sym)
proc semProc(c: PContext, n: PNode): PNode proc semProc(c: PContext, n: PNode): PNode
@ -665,7 +665,7 @@ proc semFor(c: PContext, n: PNode): PNode =
# first class iterator: # first class iterator:
result = semForVars(c, n) result = semForVars(c, n)
elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
call.sons[0].sym.kind != skIterator: call.sons[0].sym.kind notin skIterators:
if length == 3: if length == 3:
n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2]) n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
elif length == 4: elif length == 4:
@ -998,8 +998,7 @@ proc activate(c: PContext, n: PNode) =
discard discard
proc maybeAddResult(c: PContext, s: PSym, n: PNode) = proc maybeAddResult(c: PContext, s: PSym, n: PNode) =
if s.typ.sons[0] != nil and if s.typ.sons[0] != nil and s.kind != skIterator:
(s.kind != skIterator or s.typ.callConv == ccClosure):
addResult(c, s.typ.sons[0], n.info, s.kind) addResult(c, s.typ.sons[0], n.info, s.kind)
addResultNode(c, n) addResultNode(c, n)
@ -1074,12 +1073,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: if s.kind in skIterators:
s.typ.flags.incl(tfIterator) s.typ.flags.incl(tfIterator)
var proto = searchForProc(c, s.scope, s) var proto = searchForProc(c, s.scope, s)
if proto == nil: if proto == nil:
if s.kind == skIterator and isAnon: s.typ.callConv = ccClosure if s.kind == skClosureIterator: s.typ.callConv = ccClosure
else: s.typ.callConv = lastOptionEntry(c).defaultCC else: s.typ.callConv = lastOptionEntry(c).defaultCC
# add it here, so that recursive procs are possible: # add it here, so that recursive procs are possible:
if sfGenSym in s.flags: discard if sfGenSym in s.flags: discard
@ -1139,7 +1138,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
n.sons[bodyPos] = transformBody(c.module, semBody, s) n.sons[bodyPos] = transformBody(c.module, semBody, s)
popProcCon(c) popProcCon(c)
else: else:
if s.typ.sons[0] != nil and kind != skIterator: if s.typ.sons[0] != nil and kind notin skIterators:
addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info)) addDecl(c, newSym(skUnknown, getIdent"result", nil, n.info))
var toBind = initIntSet() var toBind = initIntSet()
n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind) n.sons[bodyPos] = semGenericStmtScope(c, n.sons[bodyPos], {}, toBind)
@ -1166,7 +1165,10 @@ proc determineType(c: PContext, s: PSym) =
discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType) discard semProcAux(c, s.ast, s.kind, {}, stepDetermineType)
proc semIterator(c: PContext, n: PNode): PNode = proc semIterator(c: PContext, n: PNode): PNode =
result = semProcAux(c, n, skIterator, iteratorPragmas) let kind = if hasPragma(n[pragmasPos], wClosure) or
n[namePos].kind == nkEmpty: skClosureIterator
else: skIterator
result = semProcAux(c, n, kind, 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 and s.typ.callConv != ccClosure: if t.sons[0] == nil and s.typ.callConv != ccClosure:

View file

@ -171,7 +171,7 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
of skUnknown: of skUnknown:
# Introduced in this pass! Leave it as an identifier. # Introduced in this pass! Leave it as an identifier.
result = n result = n
of skProc, skMethod, skIterator, skConverter, skTemplate, skMacro: of OverloadableSyms:
result = symChoice(c, n, s, scOpen) result = symChoice(c, n, s, scOpen)
of skGenericParam: of skGenericParam:
result = newSymNodeTypeDesc(s, n.info) result = newSymNodeTypeDesc(s, n.info)
@ -348,7 +348,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
of nkMethodDef: of nkMethodDef:
result = semRoutineInTemplBody(c, n, skMethod) result = semRoutineInTemplBody(c, n, skMethod)
of nkIteratorDef: of nkIteratorDef:
result = semRoutineInTemplBody(c, n, skIterator) result = semRoutineInTemplBody(c, n, n[namePos].sym.kind)
of nkTemplateDef: of nkTemplateDef:
result = semRoutineInTemplBody(c, n, skTemplate) result = semRoutineInTemplBody(c, n, skTemplate)
of nkMacroDef: of nkMacroDef:

View file

@ -953,6 +953,23 @@ proc semTypeClass(c: PContext, n: PNode, prev: PType): PType =
let typ = semTypeNode(c, n, nil) let typ = semTypeNode(c, n, nil)
result.sons.safeAdd(typ) result.sons.safeAdd(typ)
proc semProcTypeWithScope(c: PContext, n: PNode,
prev: PType, kind: TSymKind): PType =
checkSonsLen(n, 2)
openScope(c)
result = semProcTypeNode(c, n.sons[0], nil, prev, kind)
# dummy symbol for `pragma`:
var s = newSymS(kind, newIdentNode(getIdent("dummy"), n.info), c)
s.typ = result
if n.sons[1].kind == nkEmpty or n.sons[1].len == 0:
if result.callConv == ccDefault:
result.callConv = ccClosure
#Message(n.info, warnImplicitClosure, renderTree(n))
else:
pragma(c, s, n.sons[1], procTypePragmas)
when useEffectSystem: setEffectsForProcType(result, n.sons[1])
closeScope(c)
proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
result = nil result = nil
if gCmd == cmdIdeTools: suggestExpr(c, n) if gCmd == cmdIdeTools: suggestExpr(c, n)
@ -1075,27 +1092,18 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
var base = semTypeNode(c, n.sons[0], nil) var base = semTypeNode(c, n.sons[0], nil)
result.rawAddSon(base) result.rawAddSon(base)
result.flags.incl tfHasStatic result.flags.incl tfHasStatic
of nkProcTy, nkIteratorTy: of nkIteratorTy:
if n.sonsLen == 0:
result = newConstraint(c, tyIter)
else:
result = semProcTypeWithScope(c, n, prev, skClosureIterator)
result.flags.incl(tfIterator)
result.callConv = ccClosure
of nkProcTy:
if n.sonsLen == 0: if n.sonsLen == 0:
result = newConstraint(c, tyProc) result = newConstraint(c, tyProc)
else: else:
checkSonsLen(n, 2) result = semProcTypeWithScope(c, n, prev, skProc)
openScope(c)
result = semProcTypeNode(c, n.sons[0], nil, prev, skProc)
# dummy symbol for `pragma`:
var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
s.typ = result
if n.sons[1].kind == nkEmpty or n.sons[1].len == 0:
if result.callConv == ccDefault:
result.callConv = ccClosure
#Message(n.info, warnImplicitClosure, renderTree(n))
else:
pragma(c, s, n.sons[1], procTypePragmas)
when useEffectSystem: setEffectsForProcType(result, n.sons[1])
closeScope(c)
if n.kind == nkIteratorTy:
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

@ -1142,7 +1142,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
z.calleeSym = m.calleeSym z.calleeSym = m.calleeSym
var best = -1 var best = -1
for i in countup(0, sonsLen(arg) - 1): for i in countup(0, sonsLen(arg) - 1):
if arg.sons[i].sym.kind in {skProc, skIterator, skMethod, skConverter}: if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}+skIterators:
copyCandidate(z, m) copyCandidate(z, m)
var r = typeRel(z, f, arg.sons[i].typ) var r = typeRel(z, f, arg.sons[i].typ)
if r != isNone: if r != isNone:

View file

@ -113,7 +113,7 @@ proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode =
result[1] = ri result[1] = ri
proc transformSymAux(c: PTransf, n: PNode): PNode = proc transformSymAux(c: PTransf, n: PNode): PNode =
#if n.sym.kind == skIterator and n.sym.typ.callConv == ccClosure: #if n.sym.kind == skClosureIterator:
# return liftIterSym(n) # return liftIterSym(n)
var b: PNode var b: PNode
var tc = c.transCon var tc = c.transCon
@ -434,7 +434,6 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
var length = sonsLen(n) var length = sonsLen(n)
var call = n.sons[length - 2] var call = n.sons[length - 2]
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
call.sons[0].typ.callConv == ccClosure or
call.sons[0].sym.kind != skIterator: call.sons[0].sym.kind != skIterator:
n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
return lambdalifting.liftForLoop(n).PTransNode return lambdalifting.liftForLoop(n).PTransNode
@ -454,7 +453,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
var newC = newTransCon(getCurrOwner(c)) var newC = newTransCon(getCurrOwner(c))
newC.forStmt = n newC.forStmt = n
newC.forLoopBody = loopBody newC.forLoopBody = loopBody
if iter.kind != skIterator: internalError(call.info, "transformFor") internalAssert iter.kind == skIterator
# generate access statements for the parameters (unless they are constant) # generate access statements for the parameters (unless they are constant)
pushTransCon(c, newC) pushTransCon(c, newC)
for i in countup(1, sonsLen(call) - 1): for i in countup(1, sonsLen(call) - 1):
@ -741,7 +740,7 @@ proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
var c = openTransf(module, "") var c = openTransf(module, "")
result = processTransf(c, n, prc) result = processTransf(c, n, prc)
result = liftLambdas(prc, result) result = liftLambdas(prc, result)
#if prc.kind == skIterator and prc.typ.callConv == ccClosure: #if prc.kind == skClosureIterator:
# result = lambdalifting.liftIterator(prc, result) # result = lambdalifting.liftIterator(prc, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
when useEffectSystem: trackProc(prc, result) when useEffectSystem: trackProc(prc, result)

View file

@ -1247,7 +1247,7 @@ proc computeSize(typ: PType): BiggestInt =
proc getReturnType*(s: PSym): PType = proc getReturnType*(s: PSym): PType =
# Obtains the return type of a iterator/proc/macro/template # Obtains the return type of a iterator/proc/macro/template
assert s.kind in {skProc, skTemplate, skMacro, skIterator} assert s.kind in skProcKinds
result = s.typ.sons[0] result = s.typ.sons[0]
proc getSize(typ: PType): BiggestInt = proc getSize(typ: PType): BiggestInt =

View file

@ -1311,7 +1311,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
case s.kind case s.kind
of skVar, skForVar, skTemp, skLet, skParam, skResult: of skVar, skForVar, skTemp, skLet, skParam, skResult:
genRdVar(c, n, dest, flags) genRdVar(c, n, dest, flags)
of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator: of skProc, skConverter, skMacro, skTemplate, skMethod, skIterators:
# 'skTemplate' is only allowed for 'getAst' support: # 'skTemplate' is only allowed for 'getAst' support:
if sfImportc in s.flags: c.importcSym(n.info, s) if sfImportc in s.flags: c.importcSym(n.info, s)
genLit(c, n, dest) genLit(c, n, dest)

View file

@ -279,8 +279,8 @@ skForVar
col 7: "" col 7: ""
skIterator skIterator, skClosureIterator
---------- -----------------------------
The fourth column will be the empty string if the iterator is being The fourth column will be the empty string if the iterator is being
defined, since at that point in the file the parser hasn't processed defined, since at that point in the file the parser hasn't processed

View file

@ -88,7 +88,7 @@ type
nskUnknown, nskConditional, nskDynLib, nskParam, nskUnknown, nskConditional, nskDynLib, nskParam,
nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet, nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet,
nskConst, nskResult, nskConst, nskResult,
nskProc, nskMethod, nskIterator, nskProc, nskMethod, nskIterator, nskClosureIterator,
nskConverter, nskMacro, nskTemplate, nskField, nskConverter, nskMacro, nskTemplate, nskField,
nskEnumField, nskForVar, nskLabel, nskEnumField, nskForVar, nskLabel,
nskStub nskStub

View file

@ -1,6 +1,6 @@
discard """ discard """
line: 10 line: 10
errormsg: "value returned by statement has to be discarded" errormsg: "value of type 'string' has to be discarded"
""" """
# bug #578 # bug #578

View file

@ -8,7 +8,7 @@ discard """
""" """
proc factory(a, b: int): iterator (): int = proc factory(a, b: int): iterator (): int =
iterator foo(): int = iterator foo(): int {.closure.} =
var x = a var x = a
while x <= b: while x <= b:
yield x yield x