diff options
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 4 | ||||
-rw-r--r-- | compiler/astalgo.nim | 8 | ||||
-rw-r--r-- | compiler/guards.nim | 4 | ||||
-rw-r--r-- | compiler/msgs.nim | 6 | ||||
-rw-r--r-- | compiler/sem.nim | 7 | ||||
-rw-r--r-- | compiler/semcall.nim | 12 | ||||
-rw-r--r-- | compiler/semexprs.nim | 62 | ||||
-rw-r--r-- | compiler/seminst.nim | 2 | ||||
-rw-r--r-- | compiler/semstmts.nim | 18 | ||||
-rw-r--r-- | compiler/semtempl.nim | 4 | ||||
-rw-r--r-- | compiler/semtypes.nim | 99 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 16 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 19 | ||||
-rw-r--r-- | compiler/transf.nim | 12 | ||||
-rw-r--r-- | compiler/vm.nim | 4 |
15 files changed, 194 insertions, 83 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 9c9dfce9a..f9cab0d88 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -818,6 +818,9 @@ type counter*: int data*: TObjectSeq + TImplication* = enum + impUnknown, impNo, impYes + # BUGFIX: a module is overloadable so that a proc can have the # same name as an imported module. This is necessary because of # the poor naming choices in the standard library. @@ -865,6 +868,7 @@ const nkCallKinds* = {nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkCallStrLit, nkHiddenCallConv} + nkLiterals* = {nkCharLit..nkTripleStrLit} nkLambdaKinds* = {nkLambda, nkDo} declarativeDefs* = {nkProcDef, nkMethodDef, nkIteratorDef, nkConverterDef} procDefs* = nkLambdaKinds + declarativeDefs diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index cce2cc215..36dd7f562 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -50,7 +50,7 @@ proc strTableGet*(t: TStrTable, name: PIdent): PSym type TTabIter*{.final.} = object # consider all fields here private h*: THash # current hash - + proc initTabIter*(ti: var TTabIter, tab: TStrTable): PSym proc nextIter*(ti: var TTabIter, tab: TStrTable): PSym # usage: @@ -157,6 +157,12 @@ proc leValue*(a, b: PNode): bool = #InternalError(a.info, "leValue") discard +proc weakLeValue*(a, b: PNode): TImplication = + if a.kind notin nkLiterals or b.kind notin nkLiterals: + result = impUnknown + else: + result = if leValue(a, b): impYes else: impNo + proc lookupInRecord(n: PNode, field: PIdent): PSym = result = nil case n.kind diff --git a/compiler/guards.nim b/compiler/guards.nim index fe868054f..f475f5068 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -274,10 +274,6 @@ proc pred(n: PNode): PNode = else: result = n -type - TImplication* = enum - impUnknown, impNo, impYes - proc impliesEq(fact, eq: PNode): TImplication = let (loc, val) = if isLocation(eq.sons[1]): (1, 2) else: (2, 1) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 66763e7f5..5bc490d14 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -96,8 +96,8 @@ type errOnlyACallOpCanBeDelegator, errUsingNoSymbol, errMacroBodyDependsOnGenericTypes, errDestructorNotGenericEnough, - - errXExpectsTwoArguments, + errInlineIteratorsAsProcParams, + errXExpectsTwoArguments, errXExpectsObjectTypes, errXcanNeverBeOfThisSubtype, errTooManyIterations, errCannotInterpretNodeX, errFieldXNotFound, errInvalidConversionFromTypeX, errAssertionFailed, errCannotGenerateCodeForX, errXRequiresOneArgument, @@ -331,6 +331,8 @@ const "because the parameter '$1' has a generic type", errDestructorNotGenericEnough: "Destructor signarue is too specific. " & "A destructor must be associated will all instantiations of a generic type", + errInlineIteratorsAsProcParams: "inline iterators can be used as parameters only for " & + "templates, macros and other inline iterators", errXExpectsTwoArguments: "\'$1\' expects two arguments", errXExpectsObjectTypes: "\'$1\' expects object types", errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype", diff --git a/compiler/sem.nim b/compiler/sem.nim index 5ee46654e..c8228618b 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -139,6 +139,10 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym = result = n.sym internalAssert sfGenSym in result.flags internalAssert result.kind == kind + # when there is a nested proc inside a template, semtmpl + # will assign a wrong owner during the first pass over the + # template; we must fix it here: see #909 + result.owner = getCurrOwner() else: result = newSym(kind, considerAcc(n), getCurrOwner(), n.info) @@ -194,7 +198,8 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode = result = semExprWithType(c, evaluated) else: result = evaluated - semmacrosanity.annotateType(result, eOrig.typ) + let expectedType = eOrig.typ.skipTypes({tyStatic}) + semmacrosanity.annotateType(result, expectedType) else: result = semExprWithType(c, evaluated) #result = fitNode(c, e.typ, result) inlined with special case: diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 2e5def75a..5d480bc98 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -82,7 +82,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: seq[string]) = # fail fast: globalError(n.info, errTypeMismatch, "") var result = msgKindToString(errTypeMismatch) - add(result, describeArgs(c, n, 1 + ord(nfDotField in n.flags))) + add(result, describeArgs(c, n, 1)) add(result, ')') var candidates = "" @@ -114,7 +114,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode, var errors: seq[string] var usedSyms: seq[PNode] - + template pickBest(headSymbol: expr) = pickBestCandidate(c, headSymbol, n, orig, initialBinding, filter, result, alt, errors) @@ -166,7 +166,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode, n.sons[0..1] = [callOp, n[1], calleeName] orig.sons[0..1] = [callOp, orig[1], calleeName] pickBest(callOp) - + if overloadsState == csEmpty and result.state == csEmpty: localError(n.info, errUndeclaredIdentifier, considerAcc(f).s) return @@ -175,9 +175,15 @@ proc resolveOverloads(c: PContext, n, orig: PNode, localError(n.info, errExprXCannotBeCalled, renderTree(n, {renderNoComments})) else: + if {nfDotField, nfDotSetter} * n.flags != {}: + # clean up the inserted ops + n.sons.delete(2) + n.sons[0] = f + errors = @[] pickBest(f) notFoundError(c, n, errors) + return if alt.state == csMatch and cmpCandidates(result, alt) == 0 and diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 203a51816..62a816a50 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -885,7 +885,7 @@ proc lookupInRecordAndBuildCheck(c: PContext, n, r: PNode, field: PIdent, of nkSym: if r.sym.name.id == field.id: result = r.sym else: illFormedAst(n) - + proc makeDeref(n: PNode): PNode = var t = skipTypes(n.typ, {tyGenericInst}) result = n @@ -899,6 +899,21 @@ proc makeDeref(n: PNode): PNode = addSon(result, a) t = skipTypes(t.sons[0], {tyGenericInst}) +proc readTypeParameter(c: PContext, ty: PType, + paramName: PIdent, info: TLineInfo): PNode = + internalAssert ty.kind == tyGenericInst + let ty = ty.skipGenericAlias + let tbody = ty.sons[0] + for s in countup(0, tbody.len-2): + let tParam = tbody.sons[s] + if tParam.sym.name == paramName: + let rawTyp = ty.sons[s + 1] + if rawTyp.kind == tyStatic: + return rawTyp.n + else: + let foundTyp = makeTypeDesc(c, rawTyp) + return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) + proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = ## returns nil if it's not a built-in field access checkSonsLen(n, 2) @@ -916,7 +931,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = var ty = n.sons[0].typ var f: PSym = nil result = nil - if isTypeExpr(n.sons[0]) or ty.kind == tyTypeDesc and ty.base.kind != tyNone: + if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone): if ty.kind == tyTypeDesc: ty = ty.base case ty.kind of tyEnum: @@ -925,28 +940,17 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = f = getSymFromList(ty.n, i) if f != nil: break ty = ty.sons[0] # enum inheritance - if f != nil: + if f != nil: result = newSymNode(f) result.info = n.info result.typ = ty markUsed(n, f) return of tyGenericInst: - assert ty.sons[0].kind == tyGenericBody - let tbody = ty.sons[0] - for s in countup(0, tbody.len-2): - let tParam = tbody.sons[s] - if tParam.sym.name == i: - let rawTyp = ty.sons[s + 1] - if rawTyp.kind == tyStatic: - return rawTyp.n - else: - let foundTyp = makeTypeDesc(c, rawTyp) - return newSymNode(copySym(tParam.sym).linkTo(foundTyp), n.info) - return + return readTypeParameter(c, ty, i, n.info) of tyObject, tyTuple: if ty.n.kind == nkRecList: - for field in ty.n.sons: + for field in ty.n: if field.sym.name == i: n.typ = newTypeWithSons(c, tyFieldAccessor, @[ty, field.sym.typ]) n.typ.n = copyTree(n) @@ -958,6 +962,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = # XXX: This is probably not relevant any more # reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim": ty = n.sons[0].typ + return nil ty = skipTypes(ty, {tyGenericInst, tyVar, tyPtr, tyRef}) var check: PNode = nil @@ -990,6 +995,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode = n.typ = f.typ result = n + # we didn't find any field, let's look for a generic param + if result == nil and n.sons[0].typ.kind == tyGenericInst: + result = readTypeParameter(c, n.sons[0].typ, i, n.info) + proc dotTransformation(c: PContext, n: PNode): PNode = if isSymChoice(n.sons[1]): result = newNodeI(nkDotCall, n.info) @@ -1119,6 +1128,9 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} = n.sons[0] = x # 'result[]' --> 'result' n.sons[1] = takeImplicitAddr(c, ri) +template resultTypeIsInferrable(typ: PType): expr = + typ.isMetaType and typ.kind != tyTypeDesc + proc semAsgn(c: PContext, n: PNode): PNode = checkSonsLen(n, 2) var a = n.sons[0] @@ -1170,7 +1182,7 @@ proc semAsgn(c: PContext, n: PNode): PNode = if lhsIsResult: {efAllowDestructor} else: {}) if lhsIsResult: n.typ = enforceVoidContext - if lhs.sym.typ.isMetaType and lhs.sym.typ.kind != tyTypeDesc: + if resultTypeIsInferrable(lhs.sym.typ): if cmpTypes(c, lhs.typ, rhs.typ) == isGeneric: internalAssert c.p.resultSym != nil lhs.typ = rhs.typ @@ -1259,12 +1271,21 @@ proc semYield(c: PContext, n: PNode): PNode = localError(n.info, errYieldNotAllowedInTryStmt) elif n.sons[0].kind != nkEmpty: n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility: - var restype = c.p.owner.typ.sons[0] + var iterType = c.p.owner.typ + var restype = iterType.sons[0] if restype != nil: 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 resultTypeIsInferrable(adjustedRes): + let inferred = n.sons[0].typ + if c.p.owner.kind == skIterator: + iterType.sons[0].sons[0] = inferred + else: + iterType.sons[0] = inferred + semYieldVarResult(c, n, adjustedRes) else: localError(n.info, errCannotReturnExpr) @@ -1346,7 +1367,7 @@ proc expectString(c: PContext, n: PNode): string = localError(n.info, errStringLiteralExpected) proc getMagicSym(magic: TMagic): PSym = - result = newSym(skProc, getIdent($magic), getCurrOwner(), gCodegenLineInfo) + result = newSym(skProc, getIdent($magic), systemModule, gCodegenLineInfo) result.magic = magic proc newAnonSym(kind: TSymKind, info: TLineInfo, @@ -1939,7 +1960,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = of nkBracketExpr: checkMinSonsLen(n, 1) var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared}) - if s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators: + if (s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators) or + n[0].kind in nkSymChoices: # type parameters: partial generic specialization n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s) result = explicitGenericInstantiation(c, n, s) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 8faf1d21a..4bcfa7f15 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -20,7 +20,7 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable, if a.kind != nkSym: internalError(a.info, "instantiateGenericParamList; no symbol") var q = a.sym - if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic}+tyTypeClasses: + if q.typ.kind notin {tyTypeDesc, tyGenericParam, tyStatic, tyIter}+tyTypeClasses: continue var s = newSym(skType, q.name, getCurrOwner(), q.info) s.flags = s.flags + {sfUsed, sfFromGeneric} diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index a11386966..edce7c9bd 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -661,10 +661,18 @@ proc semFor(c: PContext, n: PNode): PNode = openScope(c) n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator}) var call = n.sons[length-2] - if call.kind in nkCallKinds and call.sons[0].typ.callConv == ccClosure: + let isCallExpr = call.kind in nkCallKinds + if isCallExpr and call.sons[0].sym.magic != mNone: + if call.sons[0].sym.magic == mOmpParFor: + result = semForVars(c, n) + 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: # first class iterator: result = semForVars(c, n) - elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or + elif not isCallExpr or call.sons[0].kind != nkSym or call.sons[0].sym.kind notin skIterators: if length == 3: n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2]) @@ -673,12 +681,6 @@ proc semFor(c: PContext, n: PNode): PNode = else: localError(n.sons[length-2].info, errIteratorExpected) result = semForVars(c, n) - elif call.sons[0].sym.magic != mNone: - if call.sons[0].sym.magic == mOmpParFor: - result = semForVars(c, n) - result.kind = nkParForStmt - else: - result = semForFields(c, n, call.sons[0].sym.magic) else: result = semForVars(c, n) # propagate any enforced VoidContext: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 31624a97f..42268d44f 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -348,7 +348,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = of nkMethodDef: result = semRoutineInTemplBody(c, n, skMethod) of nkIteratorDef: - result = semRoutineInTemplBody(c, n, n[namePos].sym.kind) + let kind = if hasPragma(n[pragmasPos], wClosure): skClosureIterator + else: skIterator + result = semRoutineInTemplBody(c, n, kind) of nkTemplateDef: result = semRoutineInTemplBody(c, n, skTemplate) of nkMacroDef: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index a619de7ff..f91222477 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -147,26 +147,38 @@ proc semDistinct(c: PContext, n: PNode, prev: PType): PType = else: result = newConstraint(c, tyDistinct) -proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = +proc semRangeAux(c: PContext, n: PNode, prev: PType): PType = assert isRange(n) checkSonsLen(n, 3) result = newOrPrevType(tyRange, prev, c) result.n = newNodeI(nkRange, n.info) - if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): + if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): localError(n.info, errRangeIsEmpty) - var a = semConstExpr(c, n[1]) - var b = semConstExpr(c, n[2]) - if not sameType(a.typ, b.typ): + + var range: array[2, PNode] + range[0] = semExprWithType(c, n[1], {efDetermineType}) + range[1] = semExprWithType(c, n[2], {efDetermineType}) + + var rangeT: array[2, PType] + for i in 0..1: rangeT[i] = range[i].typ.skipTypes({tyStatic}).skipIntLit + + if not sameType(rangeT[0], rangeT[1]): localError(n.info, errPureTypeMismatch) - elif a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar, - tyFloat..tyFloat128,tyUInt8..tyUInt32}: + elif not rangeT[0].isOrdinalType: localError(n.info, errOrdinalTypeExpected) - elif enumHasHoles(a.typ): - localError(n.info, errEnumXHasHoles, a.typ.sym.name.s) - elif not leValue(a, b): localError(n.info, errRangeIsEmpty) - addSon(result.n, a) - addSon(result.n, b) - addSonSkipIntLit(result, b.typ) + elif enumHasHoles(rangeT[0]): + localError(n.info, errEnumXHasHoles, rangeT[0].sym.name.s) + + for i in 0..1: + if hasGenericArguments(range[i]): + result.n.addSon makeStaticExpr(c, range[i]) + else: + result.n.addSon semConstExpr(c, range[i]) + + if weakLeValue(result.n[0], result.n[1]) == impNo: + localError(n.info, errRangeIsEmpty) + + addSonSkipIntLit(result, rangeT[0]) proc semRange(c: PContext, n: PNode, prev: PType): PType = result = nil @@ -602,15 +614,24 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = incl(result.flags, tfFinal) proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) = - if kind == skMacro and param.typ.kind notin {tyTypeDesc, tyStatic}: - # within a macro, every param has the type PNimrodNode! - # and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}: - let nn = getSysSym"PNimrodNode" - var a = copySym(param) - a.typ = nn.typ - if sfGenSym notin a.flags: addDecl(c, a) + template addDecl(x) = + if sfGenSym notin x.flags: addDecl(c, x) + + if kind == skMacro: + if param.typ.kind == tyTypeDesc: + addDecl(param) + elif param.typ.kind == tyStatic: + var a = copySym(param) + a.typ = param.typ.base + addDecl(a) + else: + # within a macro, every param has the type PNimrodNode! + let nn = getSysSym"PNimrodNode" + var a = copySym(param) + a.typ = nn.typ + addDecl(a) else: - if sfGenSym notin param.flags: addDecl(c, param) + addDecl(param) let typedescId = getIdent"typedesc" @@ -721,7 +742,16 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, allowMetaTypes = true) 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) @@ -840,9 +870,13 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, addParamOrResult(c, arg, kind) if gCmd == cmdPretty: checkDef(a.sons[j], arg) - + var r: PType if n.sons[0].kind != nkEmpty: - var r = semTypeNode(c, n.sons[0], nil) + r = semTypeNode(c, n.sons[0], nil) + elif kind == skIterator: + r = newTypeS(tyAnything, c) + + if r != nil: # turn explicit 'void' return type into 'nil' because the rest of the # compiler only checks for 'nil': if skipTypes(r, {tyGenericInst}).kind != tyEmpty: @@ -852,7 +886,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode, if lifted != nil: r = lifted r.flags.incl tfRetType r = skipIntLit(r) - if kind == skIterator: r = newTypeWithSons(c, tyIter, @[r]) + if kind == skIterator: + # 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.sons[0] = r res.typ = r @@ -984,7 +1022,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = of nkTypeOfExpr: # for ``type(countup(1,3))``, see ``tests/ttoseq``. checkSonsLen(n, 1) - result = semExprWithType(c, n.sons[0], {efInTypeof}).typ.skipTypes({tyIter}) + let typExpr = semExprWithType(c, n.sons[0], {efInTypeof}) + result = typExpr.typ.skipTypes({tyIter}) of nkPar: if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev) else: @@ -1103,8 +1142,12 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = result = newConstraint(c, tyIter) else: result = semProcTypeWithScope(c, n, prev, skClosureIterator) - result.flags.incl(tfIterator) - result.callConv = ccClosure + 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: result = newConstraint(c, tyProc) diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 22edc6e32..80e2aa284 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -181,7 +181,8 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = of nkStaticExpr: var n = prepareNode(cl, n) n = reResolveCallsWithTypedescParams(cl, n) - result = cl.c.semExpr(cl.c, n) + result = if cl.allowMetaTypes: n + else: cl.c.semExpr(cl.c, n) else: var length = sonsLen(n) if length > 0: @@ -305,6 +306,11 @@ proc skipIntLiteralParams(t: PType) = if skipped != p: t.sons[i] = skipped if i > 0: t.n.sons[i].sym.typ = skipped + + # when the typeof operator is used on a static input + # param, the results gets infected with static as well: + if t.sons[0] != nil and t.sons[0].kind == tyStatic: + t.sons[0] = t.sons[0].base proc propagateFieldFlags(t: PType, n: PNode) = # This is meant for objects and tuples @@ -314,16 +320,15 @@ proc propagateFieldFlags(t: PType, n: PNode) = of nkSym: propagateToOwner(t, n.sym.typ) of nkRecList, nkRecCase, nkOfBranch, nkElse: - if n.sons != nil: - for son in n.sons: - propagateFieldFlags(t, son) + for son in n: + propagateFieldFlags(t, son) else: discard proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = t if t == nil: return - if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses: + if t.kind in {tyStatic, tyGenericParam, tyIter} + tyTypeClasses: let lookup = PType(idTableGet(cl.typeMap, t)) if lookup != nil: return lookup @@ -336,6 +341,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = replaceTypeVarsT(cl, lastSon(t)) of tyFromExpr: + if cl.allowMetaTypes: return var n = prepareNode(cl, t.n) n = cl.c.semConstExpr(cl.c, n) if n.typ.kind == tyTypeDesc: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index c0898ef26..19f10def8 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -1014,6 +1014,10 @@ 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 paramTypesMatchAux(m: var TCandidate, f, argType: PType, argSemantized, argOrig: PNode): PNode = var @@ -1021,7 +1025,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, arg = argSemantized argType = argType c = m.c - + if tfHasStatic in fMaybeStatic.flags: # XXX: When implicit statics are the default # this will be done earlier - we just have to @@ -1060,7 +1064,14 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, return arg.typ.n else: return 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 + case r of isConvertible: inc(m.convMatches) @@ -1188,7 +1199,9 @@ proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode = # a.typ == nil is valid result = a elif a.typ.isNil: - result = c.semOperand(c, a, {efDetermineType}) + let flags = if formal.kind == tyIter: {efDetermineType, efWantIterator} + else: {efDetermineType} + result = c.semOperand(c, a, flags) else: result = a diff --git a/compiler/transf.nim b/compiler/transf.nim index f4b716c5b..9586398c9 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -425,7 +425,7 @@ proc findWrongOwners(c: PTransf, n: PNode) = x.sym.owner.name.s & " " & getCurrOwner(c).name.s) else: for i in 0 .. <safeLen(n): findWrongOwners(c, n.sons[i]) - + proc transformFor(c: PTransf, n: PNode): PTransNode = # generate access statements for the parameters (unless they are constant) # put mapping from formal parameters to actual parameters @@ -433,12 +433,13 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = var length = sonsLen(n) var call = n.sons[length - 2] - if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or - call.sons[0].sym.kind != skIterator: + if call.typ.kind != tyIter and + (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 return lambdalifting.liftForLoop(n).PTransNode #InternalError(call.info, "transformFor") - + #echo "transforming: ", renderTree(n) result = newTransNode(nkStmtList, n.info, 0) var loopBody = transformLoopBody(c, n.sons[length-1]) @@ -459,6 +460,7 @@ 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) @@ -480,7 +482,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode = dec(c.inlining) popInfoContext() popTransCon(c) - #echo "transformed: ", renderTree(n) + # echo "transformed: ", result.PNode.renderTree proc getMagicOp(call: PNode): TMagic = if call.sons[0].kind == nkSym and diff --git a/compiler/vm.nim b/compiler/vm.nim index f9b143bce..2a80106a5 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -425,7 +425,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = decodeBC(rkNode) let src = regs[rb].node if src.kind notin {nkEmpty..nkNilLit}: - regs[ra].node = src.sons[rc] + let n = src.sons[rc] + regs[ra].node = if n.kind == nkExprColonExpr: n[1] + else: n else: stackTrace(c, tos, pc, errIndexOutOfBounds) of opcWrObj: |