diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ccgexprs.nim | 21 | ||||
-rw-r--r-- | compiler/ccgstmts.nim | 2 | ||||
-rw-r--r-- | compiler/jstypes.nim | 2 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 40 | ||||
-rw-r--r-- | compiler/parser.nim | 9 | ||||
-rw-r--r-- | compiler/plugins.nim | 13 | ||||
-rw-r--r-- | compiler/plugins/active.nim | 2 | ||||
-rw-r--r-- | compiler/plugins/itersgen.nim | 49 | ||||
-rw-r--r-- | compiler/semexprs.nim | 41 | ||||
-rw-r--r-- | compiler/sempass2.nim | 16 | ||||
-rw-r--r-- | compiler/semstmts.nim | 8 | ||||
-rw-r--r-- | compiler/semtypes.nim | 51 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 4 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 11 | ||||
-rw-r--r-- | compiler/transf.nim | 6 |
15 files changed, 179 insertions, 96 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index c9ff9d4f0..df3b655e3 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -959,6 +959,7 @@ proc genEcho(p: BProc, n: PNode) = addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)]) linefmt(p, cpsStmts, "printf($1$2);$n", makeCString(repeat("%s", n.len) & tnl), args) + linefmt(p, cpsStmts, "fflush(stdout);$n") proc gcUsage(n: PNode) = if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree) @@ -1415,11 +1416,11 @@ proc binaryExprIn(p: BProc, e: PNode, a, b, d: var TLoc, frmt: string) = proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc) = case int(getSize(skipTypes(e.sons[1].typ, abstractVar))) - of 1: binaryExprIn(p, e, a, b, d, "(($1 &(1<<(($2)&7)))!=0)") - of 2: binaryExprIn(p, e, a, b, d, "(($1 &(1<<(($2)&15)))!=0)") - of 4: binaryExprIn(p, e, a, b, d, "(($1 &(1<<(($2)&31)))!=0)") - of 8: binaryExprIn(p, e, a, b, d, "(($1 &(IL64(1)<<(($2)&IL64(63))))!=0)") - else: binaryExprIn(p, e, a, b, d, "(($1[$2/8] &(1<<($2%8)))!=0)") + of 1: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&7U)))!=0)") + of 2: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&15U)))!=0)") + of 4: binaryExprIn(p, e, a, b, d, "(($1 &(1U<<((NU)($2)&31U)))!=0)") + of 8: binaryExprIn(p, e, a, b, d, "(($1 &((NU64)1<<((NU)($2)&63U)))!=0)") + else: binaryExprIn(p, e, a, b, d, "(($1[(NU)($2)>>3] &(1U<<((NU)($2)&7U)))!=0)") proc binaryStmtInExcl(p: BProc, e: PNode, d: var TLoc, frmt: string) = var a, b: TLoc @@ -1500,8 +1501,8 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) = else: internalError(e.info, "genSetOp()") else: case op - of mIncl: binaryStmtInExcl(p, e, d, "$1[$2/8] |=(1<<($2%8));$n") - of mExcl: binaryStmtInExcl(p, e, d, "$1[$2/8] &= ~(1<<($2%8));$n") + of mIncl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3] |=(1U<<($2&7U));$n") + of mExcl: binaryStmtInExcl(p, e, d, "$1[(NU)($2)>>3]] &= ~(1U<<($2&7U));$n") of mCard: unaryExprChar(p, e, d, "#cardSet($1, " & $size & ')') of mLtSet, mLeSet: getTemp(p, getSysType(tyInt), i) # our counter @@ -1733,8 +1734,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mEcho: genEcho(p, e[1].skipConv) of mArrToSeq: genArrToSeq(p, e, d) of mNLen..mNError, mSlurp..mQuoteAst: - echo "from here ", p.prc.name.s, " ", p.prc.info - writestacktrace() localError(e.info, errXMustBeCompileTime, e.sons[0].sym.name.s) of mSpawn: let n = lowerings.wrapProcForSpawn(p.module.module, e, e.typ, nil, nil) @@ -1788,11 +1787,11 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = initLocExpr(p, e.sons[i].sons[0], a) initLocExpr(p, e.sons[i].sons[1], b) lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" & - "$2[$1/8] |=(1<<($1%8));$n", [rdLoc(idx), rdLoc(d), + "$2[(NU)($1)>>3] |=(1U<<((NU)($1)&7U));$n", [rdLoc(idx), rdLoc(d), rdSetElemLoc(a, e.typ), rdSetElemLoc(b, e.typ)]) else: initLocExpr(p, e.sons[i], a) - lineF(p, cpsStmts, "$1[$2/8] |=(1<<($2%8));$n", + lineF(p, cpsStmts, "$1[(NU)($2)>>3] |=(1U<<((NU)($2)&7U));$n", [rdLoc(d), rdSetElemLoc(a, e.typ)]) else: # small set diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index f4a7c4400..73497bded 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -16,7 +16,7 @@ const # above X strings a hash-switch for strings is generated proc registerGcRoot(p: BProc, v: PSym) = - if gSelectedGC in {gcMarkAndSweep, gcGenerational} and + if gSelectedGC in {gcMarkAndSweep, gcGenerational, gcV2} and containsGarbageCollectedRef(v.loc.t): # we register a specialized marked proc here; this has the advantage # that it works out of the box for thread local storage then :-) diff --git a/compiler/jstypes.nim b/compiler/jstypes.nim index 367c173ea..611f50eaf 100644 --- a/compiler/jstypes.nim +++ b/compiler/jstypes.nim @@ -116,7 +116,7 @@ proc genEnumInfo(p: PProc, typ: PType, name: Rope) = [name, genTypeInfo(p, typ.sons[0])]) proc genTypeInfo(p: PProc, typ: PType): Rope = - let t = typ.skipTypes({tyGenericInst}) + let t = typ.skipTypes({tyGenericInst, tyDistinct}) result = "NTI$1" % [rope(t.id)] if containsOrIncl(p.g.typeInfoGenerated, t.id): return case t.kind diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index cccc94756..be1631af0 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -126,6 +126,7 @@ type fn, closureParam, state, resultSym: PSym # most are only valid if # fn.kind == skClosureIterator obj: PType + isIterator: bool PEnv = ref TEnv TEnv {.final.} = object of RootObj @@ -197,24 +198,29 @@ proc getHiddenParam(routine: PSym): PSym = result = hidden.sym assert sfFromGeneric in result.flags -proc getEnvParam(routine: PSym): PSym = +proc getEnvParam*(routine: PSym): PSym = let params = routine.ast.sons[paramsPos] let hidden = lastSon(params) if hidden.kind == nkSym and hidden.sym.name.s == paramName: result = hidden.sym assert sfFromGeneric in result.flags -proc initIter(iter: PSym): TIter = +proc initIter(iter: PSym; ptrType: PType = nil): TIter = result.fn = iter - if iter.kind == skClosureIterator: + result.isIterator = ptrType != nil or iter.kind == skClosureIterator + #echo "fuck you ", ptrType != nil + if result.isIterator: var cp = getEnvParam(iter) if cp == nil: - result.obj = createEnvObj(iter) + result.obj = if ptrType != nil: ptrType.lastSon else: createEnvObj(iter) cp = newSym(skParam, getIdent(paramName), iter, iter.info) incl(cp.flags, sfFromGeneric) - cp.typ = newType(tyRef, iter) - rawAddSon(cp.typ, result.obj) + if ptrType != nil: + cp.typ = ptrType + else: + cp.typ = newType(tyRef, iter) + rawAddSon(cp.typ, result.obj) addHiddenParam(iter, cp) else: result.obj = cp.typ.sons[0] @@ -534,6 +540,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode, env: PEnv) = let fn = n.sym if isInnerProc(fn, o.fn) and not containsOrIncl(o.processed, fn.id): let body = fn.getBody + if nfLL in body.flags: return # handle deeply nested captures: let ex = closureCreationPoint(body) @@ -794,7 +801,7 @@ proc finishEnvironments(o: POuterContext) = proc transformOuterProcBody(o: POuterContext, n: PNode; it: TIter): PNode = if nfLL in n.flags: result = nil - elif it.fn.kind == skClosureIterator: + elif it.isIterator: # unfortunately control flow is still convoluted and we can end up # multiple times here for the very same iterator. We shield against this # with some rather primitive check for now: @@ -843,7 +850,7 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = if newBody != nil: local.ast.sons[bodyPos] = newBody - if it.fn.kind == skClosureIterator and interestingIterVar(local) and + if it.isIterator and interestingIterVar(local) and it.fn == local.owner: # every local goes through the closure: #if not containsOrIncl(o.capturedVars, local.id): @@ -931,7 +938,7 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = when false: if n.sons[1].kind == nkSym: var local = n.sons[1].sym - if it.fn.kind == skClosureIterator and interestingIterVar(local) and + if it.isIterator and interestingIterVar(local) and it.fn == local.owner: # every local goes through the closure: addUniqueField(it.obj, local) @@ -941,14 +948,25 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode = if x != nil: n.sons[1] = x result = transformOuterConv(n) of nkYieldStmt: - if it.fn.kind == skClosureIterator: result = transformYield(o, n, it) + if it.isIterator: result = transformYield(o, n, it) else: outerProcSons(o, n, it) of nkReturnStmt: - if it.fn.kind == skClosureIterator: result = transformReturn(o, n, it) + if it.isIterator: result = transformReturn(o, n, it) else: outerProcSons(o, n, it) else: outerProcSons(o, n, it) +proc liftIterToProc*(fn: PSym; body: PNode; ptrType: PType): PNode = + var o = newOuterContext(fn) + let ex = closureCreationPoint(body) + let env = newEnv(o, nil, ex, fn) + addParamsToEnv(fn, env) + searchForInnerProcs(o, body, env) + createEnvironments(o) + let it = initIter(fn, ptrType) + result = transformOuterProcBody(o, body, it) + finishEnvironments(o) + proc liftLambdas*(fn: PSym, body: PNode): PNode = # XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs # the transformation even when compiling to JS ... diff --git a/compiler/parser.nim b/compiler/parser.nim index dbf9706ea..11dd6788a 100644 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -991,7 +991,7 @@ proc isExprStart(p: TParser): bool = of tkSymbol, tkAccent, tkOpr, tkNot, tkNil, tkCast, tkIf, tkProc, tkIterator, tkBind, tkAddr, tkParLe, tkBracketLe, tkCurlyLe, tkIntLit..tkCharLit, tkVar, tkRef, tkPtr, - tkTuple, tkObject, tkType, tkWhen, tkCase: + tkTuple, tkObject, tkType, tkWhen, tkCase, tkOut: result = true else: result = false @@ -1038,7 +1038,7 @@ proc parseObject(p: var TParser): PNode proc parseTypeClass(p: var TParser): PNode proc primary(p: var TParser, mode: TPrimaryMode): PNode = - #| typeKeyw = 'var' | 'ref' | 'ptr' | 'shared' | 'tuple' + #| typeKeyw = 'var' | 'out' | 'ref' | 'ptr' | 'shared' | 'tuple' #| | 'proc' | 'iterator' | 'distinct' | 'object' | 'enum' #| primary = typeKeyw typeDescK #| / prefixOperator* identOrLiteral primarySuffix* @@ -1112,6 +1112,7 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode = optInd(p, result) addSon(result, primary(p, pmNormal)) of tkVar: result = parseTypeDescKAux(p, nkVarTy, mode) + of tkOut: result = parseTypeDescKAux(p, nkVarTy, mode) of tkRef: result = parseTypeDescKAux(p, nkRefTy, mode) of tkPtr: result = parseTypeDescKAux(p, nkPtrTy, mode) of tkDistinct: result = parseTypeDescKAux(p, nkDistinctTy, mode) @@ -1763,7 +1764,7 @@ proc parseObject(p: var TParser): PNode = addSon(result, parseObjectPart(p)) proc parseTypeClassParam(p: var TParser): PNode = - if p.tok.tokType == tkVar: + if p.tok.tokType in {tkOut, tkVar}: result = newNodeP(nkVarTy, p) getTok(p) result.addSon(p.parseSymbol) @@ -1771,7 +1772,7 @@ proc parseTypeClassParam(p: var TParser): PNode = result = p.parseSymbol proc parseTypeClass(p: var TParser): PNode = - #| typeClassParam = ('var')? symbol + #| typeClassParam = ('var' | 'out')? symbol #| typeClass = typeClassParam ^* ',' (pragma)? ('of' typeDesc ^* ',')? #| &IND{>} stmt result = newNodeP(nkTypeClassTy, p) diff --git a/compiler/plugins.nim b/compiler/plugins.nim index 1c9b7b77b..19a0bc84d 100644 --- a/compiler/plugins.nim +++ b/compiler/plugins.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## Plugin support for the Nim compiler. Right now there are no plugins and they +## Plugin support for the Nim compiler. Right now they ## need to be build with the compiler, no DLL support. import ast, semdata, idents @@ -20,13 +20,16 @@ type next: Plugin proc pluginMatches(p: Plugin; s: PSym): bool = - if s.name.id != p.fn.id: return false - let module = s.owner + if s.name.id != p.fn.id: + return false + let module = s.skipGenericOwner if module == nil or module.kind != skModule or - module.name.id != p.module.id: return false + module.name.id != p.module.id: + return false let package = module.owner if package == nil or package.kind != skPackage or - package.name.id != p.package.id: return false + package.name.id != p.package.id: + return false return true var head: Plugin diff --git a/compiler/plugins/active.nim b/compiler/plugins/active.nim index e9c11c2ea..7b6411178 100644 --- a/compiler/plugins/active.nim +++ b/compiler/plugins/active.nim @@ -10,4 +10,4 @@ ## Include file that imports all plugins that are active. import - locals.locals + locals.locals, itersgen diff --git a/compiler/plugins/itersgen.nim b/compiler/plugins/itersgen.nim new file mode 100644 index 000000000..91e1d2783 --- /dev/null +++ b/compiler/plugins/itersgen.nim @@ -0,0 +1,49 @@ +# +# +# The Nim Compiler +# (c) Copyright 2015 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Plugin to transform an inline iterator into a data structure. + +import plugins, ast, astalgo, magicsys, lookups, semdata, + lambdalifting, msgs, rodread + +proc iterToProcImpl(c: PContext, n: PNode): PNode = + result = newNodeI(nkStmtList, n.info) + let iter = n[1] + if iter.kind != nkSym or iter.sym.kind != skIterator: + localError(iter.info, "first argument needs to be an iterator") + return + if n[2].typ.isNil: + localError(n[2].info, "second argument needs to be a type") + return + if n[3].kind != nkIdent: + localError(n[3].info, "third argument needs to be an identifier") + return + + let t = n[2].typ.skipTypes({tyTypeDesc, tyGenericInst}) + if t.kind notin {tyRef, tyPtr} or t.lastSon.kind != tyObject: + localError(n[2].info, + "type must be a non-generic ref|ptr to object with state field") + return + let body = liftIterToProc(iter.sym, iter.sym.getBody, t) + + let prc = newSym(skProc, n[3].ident, iter.sym.owner, iter.sym.info) + prc.typ = copyType(iter.sym.typ, prc, false) + excl prc.typ.flags, tfCapturesEnv + prc.typ.n.add newSymNode(getEnvParam(iter.sym)) + prc.typ.rawAddSon t + let orig = iter.sym.ast + prc.ast = newProcNode(nkProcDef, n.info, + name = newSymNode(prc), + params = orig[paramsPos], + pragmas = orig[pragmasPos], + body = body) + prc.ast.add iter.sym.ast.sons[resultPos] + addInterfaceDecl(c, prc) + +registerPlugin("stdlib", "system", "iterToProc", iterToProcImpl) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 58c42d410..95a90463c 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -385,7 +385,8 @@ proc isOpImpl(c: PContext, n: PNode): PNode = result = newIntNode(nkIntLit, ord(t.kind == tyProc and t.callConv == ccClosure and tfIterator notin t.flags)) - else: discard + else: + result = newIntNode(nkIntLit, 0) else: var t2 = n[2].typ.skipTypes({tyTypeDesc}) maybeLiftType(t2, c, n.info) @@ -1434,20 +1435,15 @@ proc semYield(c: PContext, n: PNode): PNode = var iterType = c.p.owner.typ let restype = iterType.sons[0] if restype != nil: - let adjustedRes = if restype.kind == tyIter: restype.base - else: restype - if adjustedRes.kind != tyExpr: - n.sons[0] = fitNode(c, adjustedRes, n.sons[0]) + if restype.kind != tyExpr: + n.sons[0] = fitNode(c, restype, n.sons[0]) if n.sons[0].typ == nil: internalError(n.info, "semYield") - if resultTypeIsInferrable(adjustedRes): + if resultTypeIsInferrable(restype): let inferred = n.sons[0].typ - if restype.kind == tyIter: - restype.sons[0] = inferred - else: - iterType.sons[0] = inferred + iterType.sons[0] = inferred - semYieldVarResult(c, n, adjustedRes) + semYieldVarResult(c, n, restype) else: localError(n.info, errCannotReturnExpr) elif c.p.owner.typ.sons[0] != nil: @@ -1780,7 +1776,24 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = result = setMs(n, s) result.sons[1] = semExpr(c, n.sons[1]) result.typ = n[1].typ - else: result = semDirectOp(c, n, flags) + of mPlugin: + # semDirectOp with conditional 'afterCallActions': + let nOrig = n.copyTree + #semLazyOpAux(c, n) + result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) + if result == nil: + result = errorNode(c, n) + else: + let callee = result.sons[0].sym + if callee.magic == mNone: + semFinishOperands(c, result) + activate(c, result) + fixAbstractType(c, result) + analyseIfAddressTakenInCall(c, result) + if callee.magic != mNone: + result = magicsAfterOverloadResolution(c, result, flags) + else: + result = semDirectOp(c, n, flags) proc semWhen(c: PContext, n: PNode, semCheck = true): PNode = # If semCheck is set to false, ``when`` will return the verbatim AST of @@ -2167,7 +2180,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = message(n.info, warnDeprecated, "bind") result = semExpr(c, n.sons[0], flags) of nkTypeOfExpr, nkTupleTy, nkTupleClassTy, nkRefTy..nkEnumTy, nkStaticTy: - var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter}) + var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc}) result.typ = makeTypeDesc(c, typ) #result = symNodeFromType(c, typ, n.info) of nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit: @@ -2240,7 +2253,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = var tupexp = semTuplePositionsConstr(c, n, flags) if isTupleType(tupexp): # reinterpret as type - var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc, tyIter}) + var typ = semTypeNode(c, n, nil).skipTypes({tyTypeDesc}) result.typ = makeTypeDesc(c, typ) else: result = tupexp diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim index 29cce9247..c3a9e01a0 100644 --- a/compiler/sempass2.nim +++ b/compiler/sempass2.nim @@ -504,7 +504,8 @@ proc notNilCheck(tracked: PEffects, n: PNode, paramType: PType) = if n.kind == nkAddr: # addr(x[]) can't be proven, but addr(x) can: if not containsNode(n, {nkDerefExpr, nkHiddenDeref}): return - elif (n.kind == nkSym and n.sym.kind in routineKinds) or n.kind in procDefs: + elif (n.kind == nkSym and n.sym.kind in routineKinds) or + n.kind in procDefs+{nkObjConstr}: # 'p' is not nil obviously: return case impliesNotNil(tracked.guards, n) @@ -704,7 +705,15 @@ proc track(tracked: PEffects, n: PNode) = for i in 1 .. <len(n): trackOperand(tracked, n.sons[i], paramType(op, i)) if a.kind == nkSym and a.sym.magic in {mNew, mNewFinalize, mNewSeq}: # may not look like an assignment, but it is: - initVarViaNew(tracked, n.sons[1]) + let arg = n.sons[1] + initVarViaNew(tracked, arg) + if {tfNeedsInit} * arg.typ.lastSon.flags != {}: + if a.sym.magic == mNewSeq and n[2].kind in {nkCharLit..nkUInt64Lit} and + n[2].intVal == 0: + # var s: seq[notnil]; newSeq(s, 0) is a special case! + discard + else: + message(arg.info, warnProveInit, $arg) for i in 0 .. <safeLen(n): track(tracked, n.sons[i]) of nkDotExpr: @@ -875,7 +884,8 @@ proc trackProc*(s: PSym, body: PNode) = var t: TEffects initEffects(effects, s, t) track(t, body) - if not isEmptyType(s.typ.sons[0]) and tfNeedsInit in s.typ.sons[0].flags and + if not isEmptyType(s.typ.sons[0]) and + {tfNeedsInit, tfNotNil} * s.typ.sons[0].flags != {} and s.kind in {skProc, skConverter, skMethod}: var res = s.ast.sons[resultPos].sym # get result symbol if res.id notin t.init: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index adb1c81c1..e80f1cfda 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -330,7 +330,8 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym = styleCheckDef(result) proc checkNilable(v: PSym) = - if sfGlobal in v.flags and {tfNotNil, tfNeedsInit} * v.typ.flags != {}: + if {sfGlobal, sfImportC} * v.flags == {sfGlobal} and + {tfNotNil, tfNeedsInit} * v.typ.flags != {}: if v.ast.isNil: message(v.info, warnProveInit, v.name.s) elif tfNotNil in v.typ.flags and tfNotNil notin v.ast.typ.flags: @@ -539,7 +540,7 @@ proc symForVar(c: PContext, n: PNode): PSym = proc semForVars(c: PContext, n: PNode): PNode = result = n var length = sonsLen(n) - let iterBase = n.sons[length-2].typ.skipTypes({tyIter}) + let iterBase = n.sons[length-2].typ var iter = skipTypes(iterBase, {tyGenericInst}) # length == 3 means that there is one for loop variable # and thus no tuple unpacking: @@ -593,8 +594,7 @@ proc semFor(c: PContext, n: PNode): PNode = result.kind = nkParForStmt else: result = semForFields(c, n, call.sons[0].sym.magic) - elif (isCallExpr and call.sons[0].typ.callConv == ccClosure) or - call.typ.kind == tyIter: + elif isCallExpr and call.sons[0].typ.callConv == ccClosure: # first class iterator: result = semForVars(c, n) elif not isCallExpr or call.sons[0].kind != nkSym or diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 65cb9421b..65edb756f 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -135,13 +135,19 @@ proc semAnyRef(c: PContext; n: PNode; kind: TTypeKind; prev: PType): PType = checkMinSonsLen(n, 1) var base = semTypeNode(c, n.lastSon, nil) result = newOrPrevType(kind, prev, c) + var isNilable = false # check every except the last is an object: for i in isCall .. n.len-2: - let region = semTypeNode(c, n[i], nil) - if region.skipTypes({tyGenericInst}).kind notin {tyError, tyObject}: - message n[i].info, errGenerated, "region needs to be an object type" - addSonSkipIntLit(result, region) + let ni = n[i] + if ni.kind == nkNilLit: + isNilable = true + else: + let region = semTypeNode(c, ni, nil) + if region.skipTypes({tyGenericInst}).kind notin {tyError, tyObject}: + message n[i].info, errGenerated, "region needs to be an object type" + addSonSkipIntLit(result, region) addSonSkipIntLit(result, base) + #if not isNilable: result.flags.incl tfNotNil proc semVarType(c: PContext, n: PNode, prev: PType): PType = if sonsLen(n) == 1: @@ -826,15 +832,6 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, result = newTypeWithSons(c, tyCompositeTypeClass, @[paramType, result]) result = addImplicitGeneric(result) - of tyIter: - if paramType.callConv == ccInline: - if procKind notin {skTemplate, skMacro, skIterator}: - localError(info, errInlineIteratorsAsProcParams) - if paramType.len == 1: - let lifted = liftingWalk(paramType.base) - if lifted != nil: paramType.sons[0] = lifted - result = addImplicitGeneric(paramType) - of tyGenericInst: if paramType.lastSon.kind == tyUserTypeClass: var cp = copyType(paramType, getCurrOwner(), false) @@ -865,11 +862,6 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot: result = addImplicitGeneric(copyType(paramType, getCurrOwner(), true)) - of tyExpr: - if procKind notin {skMacro, skTemplate}: - result = addImplicitGeneric(newTypeS(tyAnything, c)) - #result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil) - of tyGenericParam: markUsed(info, paramType.sym) styleCheckUse(info, paramType.sym) @@ -996,7 +988,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, # see tchainediterators # in cases like iterator foo(it: iterator): type(it) # we don't need to change the return type to iter[T] - if not r.isInlineIterator: r = newTypeWithSons(c, tyIter, @[r]) + result.flags.incl tfIterator + # XXX Would be nice if we could get rid of this result.sons[0] = r result.n.typ = r @@ -1151,7 +1144,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = # for ``type(countup(1,3))``, see ``tests/ttoseq``. checkSonsLen(n, 1) let typExpr = semExprWithType(c, n.sons[0], {efInTypeof}) - result = typExpr.typ.skipTypes({tyIter}) + result = typExpr.typ of nkPar: if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) else: @@ -1169,6 +1162,14 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = semTypeNode(c, b, prev) elif ident != nil and ident.id == ord(wDotDot): result = semRangeAux(c, n, prev) + elif n[0].kind == nkNilLit and n.len == 2: + result = semTypeNode(c, n.sons[1], prev) + if result.skipTypes({tyGenericInst}).kind in NilableTypes+GenericTypes: + if tfNotNil in result.flags: + result = freshType(result, prev) + result.flags.excl(tfNotNil) + else: + localError(n.info, errGenerated, "invalid type") elif n[0].kind notin nkIdentKinds: result = semTypeExpr(c, n) else: @@ -1209,7 +1210,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = elif op.id == ord(wType): checkSonsLen(n, 2) let typExpr = semExprWithType(c, n.sons[1], {efInTypeof}) - result = typExpr.typ.skipTypes({tyIter}) + result = typExpr.typ else: result = semTypeExpr(c, n) of nkWhenStmt: @@ -1290,14 +1291,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result.flags.incl tfHasStatic of nkIteratorTy: if n.sonsLen == 0: - result = newConstraint(c, tyIter) + result = newTypeS(tyBuiltInTypeClass, c) + let child = newTypeS(tyProc, c) + child.flags.incl tfIterator + result.addSonSkipIntLit(child) else: result = semProcTypeWithScope(c, n, prev, skClosureIterator) + result.flags.incl(tfIterator) if n.lastSon.kind == nkPragma and hasPragma(n.lastSon, wInline): - result.kind = tyIter result.callConv = ccInline else: - result.flags.incl(tfIterator) result.callConv = ccClosure of nkProcTy: if n.sonsLen == 0: diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 7957ac50a..20b60a88d 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -77,7 +77,7 @@ proc cacheTypeInst*(inst: PType) = # update the refcount let gt = inst.sons[0] let t = if gt.kind == tyGenericBody: gt.lastSon else: gt - if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses: + if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses: return gt.sym.typeInstCache.safeAdd(inst) @@ -390,7 +390,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = t if t == nil: return - if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses: + if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses: let lookup = PType(idTableGet(cl.typeMap, t)) if lookup != nil: return lookup diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 9fda8c860..aee42e021 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1256,10 +1256,6 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType, result.typ = getInstantiatedType(c, arg, m, base(f)) m.baseTypeMatch = true -proc isInlineIterator*(t: PType): bool = - result = t.kind == tyIter or - (t.kind == tyBuiltInTypeClass and t.base.kind == tyIter) - proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) = case r of isConvertible, isIntConv: inc(m.convMatches, convMatch) @@ -1323,13 +1319,6 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, else: return argSemantized # argOrig - if r != isNone and f.isInlineIterator: - var inlined = newTypeS(tyStatic, c) - inlined.sons = @[argType] - inlined.n = argSemantized - put(m.bindings, f, inlined) - return argSemantized - # If r == isBothMetaConvertible then we rerun typeRel. # bothMetaCounter is for safety to avoid any infinite loop, # I don't have any example when it is needed. diff --git a/compiler/transf.nim b/compiler/transf.nim index 3d78a6b92..3a5ff982e 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -478,9 +478,8 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = result[1] = newNode(nkEmpty).PTransNode return result c.breakSyms.add(labl) - if call.typ.kind != tyIter and - (call.kind notin nkCallKinds or call.sons[0].kind != nkSym or - call.sons[0].sym.kind != skIterator): + if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or + call.sons[0].sym.kind != skIterator: n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode result[1] = lambdalifting.liftForLoop(n).PTransNode discard c.breakSyms.pop @@ -512,7 +511,6 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = for i in countup(1, sonsLen(call) - 1): var arg = transform(c, call.sons[i]).PNode var formal = skipTypes(iter.typ, abstractInst).n.sons[i].sym - if arg.typ.kind == tyIter: continue case putArgInto(arg, formal.typ) of paDirectMapping: idNodeTablePut(newC.mapping, formal, arg) |