diff options
author | Zahary Karadjov <zahary@gmail.com> | 2014-01-06 00:15:55 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2014-01-06 00:15:55 +0200 |
commit | 1ffae7cbafd63ed5d8546dcda1a0e5ec883fd00b (patch) | |
tree | c553bf1a94197b95a0fdf54b8cc2885c3b16a128 /compiler | |
parent | 789ba107cf3bcc1a87d896fc7cbfa11e151898c2 (diff) | |
download | Nim-1ffae7cbafd63ed5d8546dcda1a0e5ec883fd00b.tar.gz |
progress towards fixing tgenericshardcases
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/semdata.nim | 15 | ||||
-rw-r--r-- | compiler/semexprs.nim | 10 | ||||
-rw-r--r-- | compiler/seminst.nim | 3 | ||||
-rw-r--r-- | compiler/semtypes.nim | 28 | ||||
-rw-r--r-- | compiler/semtypinst.nim | 104 | ||||
-rw-r--r-- | compiler/types.nim | 2 |
7 files changed, 130 insertions, 33 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 2f6b6fc9f..1d356b6d8 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -418,6 +418,7 @@ type tfHasGCedMem, # type contains GC'ed memory tfHasStatic tfGenericTypeParam + tfImplicitTypeParam TTypeFlags* = set[TTypeFlag] diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 2e920d9cf..980abb865 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -218,6 +218,16 @@ proc makeTypeFromExpr*(c: PContext, n: PNode): PType = result = newTypeS(tyFromExpr, c) result.n = n +proc newTypeWithSons*(c: PContext, kind: TTypeKind, + sons: seq[PType]): PType = + result = newType(kind, getCurrOwner()) + result.sons = sons + +proc makeStaticExpr*(c: PContext, n: PNode): PNode = + result = newNodeI(nkStaticExpr, n.info) + result.sons = @[n] + result.typ = newTypeWithSons(c, tyStatic, @[n.typ]) + proc makeAndType*(c: PContext, t1, t2: PType): PType = result = newTypeS(tyAnd, c) result.sons = @[t1, t2] @@ -238,11 +248,6 @@ proc makeNotType*(c: PContext, t1: PType): PType = proc newTypeS(kind: TTypeKind, c: PContext): PType = result = newType(kind, getCurrOwner()) -proc newTypeWithSons*(c: PContext, kind: TTypeKind, - sons: seq[PType]): PType = - result = newType(kind, getCurrOwner()) - result.sons = sons - proc errorType*(c: PContext): PType = ## creates a type representing an error state result = newTypeS(tyError, c) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 00c0e0f78..1f7803c95 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -231,7 +231,7 @@ proc semCast(c: PContext, n: PNode): PNode = if not isCastable(result.typ, result.sons[1].typ): localError(result.info, errExprCannotBeCastedToX, typeToString(result.typ)) - + proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = const opToStr: array[mLow..mHigh, string] = ["low", "high"] @@ -239,7 +239,7 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = localError(n.info, errXExpectsTypeOrValue, opToStr[m]) else: n.sons[1] = semExprWithType(c, n.sons[1], {efDetermineType}) - var typ = skipTypes(n.sons[1].typ, abstractVarRange) + var typ = skipTypes(n.sons[1].typ, abstractVarRange+{tyTypeDesc}) case typ.kind of tySequence, tyString, tyOpenArray, tyVarargs: n.typ = getSysType(tyInt) @@ -249,8 +249,10 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = # do not skip the range! n.typ = n.sons[1].typ.skipTypes(abstractVar) of tyGenericParam: - # leave it for now, it will be resolved in semtypinst - n.typ = getSysType(tyInt) + # prepare this for resolving in semtypinst: + # we must use copyTree here in order to avoid creating a cycle + # that could easily turn into an infinite recursion in semtypinst + n.typ = makeTypeFromExpr(c, n.copyTree) else: localError(n.info, errInvalidArgForX, opToStr[m]) result = n diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 370d59b10..8faf1d21a 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -167,8 +167,7 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable, result.ast = n pushOwner(result) openScope(c) - if n.sons[genericParamsPos].kind == nkEmpty: - internalError(n.info, "generateInstance") + internalAssert n.sons[genericParamsPos].kind != nkEmpty n.sons[namePos] = newSymNode(result) pushInfoContext(info) var entry = TInstantiation.new diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index 79147ab82..64c8f81e2 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -186,6 +186,11 @@ proc semRange(c: PContext, n: PNode, prev: PType): PType = localError(n.info, errXExpectsOneTypeParam, "range") result = newOrPrevType(tyError, prev, c) +proc nMinusOne(n: PNode): PNode = + result = newNode(nkCall, n.info, @[ + newSymNode(getSysMagic("<", mUnaryLt)), + n]) + proc semArray(c: PContext, n: PNode, prev: PType): PType = var indx, base: PType result = newOrPrevType(tyArray, prev, c) @@ -194,7 +199,9 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = if isRange(n[1]): indx = semRangeAux(c, n[1], nil) else: let e = semExprWithType(c, n.sons[1], {efDetermineType}) - if e.kind in {nkIntLit..nkUInt64Lit}: + if e.typ.kind == tyFromExpr: + indx = e.typ + elif e.kind in {nkIntLit..nkUInt64Lit}: indx = makeRangeType(c, 0, e.intVal-1, n.info, e.typ) elif e.kind == nkSym and e.typ.kind == tyStatic: if e.sym.ast != nil: return semArray(c, e.sym.ast, nil) @@ -202,11 +209,25 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType = if not isOrdinalType(e.typ.lastSon): localError(n[1].info, errOrdinalTypeExpected) indx = e.typ + elif e.kind in nkCallKinds and hasGenericArguments(e): + if not isOrdinalType(e.typ): + localError(n[1].info, errOrdinalTypeExpected) + # This is an int returning call, depending on an + # yet unknown generic param (see tgenericshardcases). + # We are going to construct a range type that will be + # properly filled-out in semtypinst (see how tyStaticExpr + # is handled there). + let intType = getSysType(tyInt) + indx = newTypeS(tyRange, c) + indx.sons = @[intType] + indx.n = newNode(nkRange, n.info, @[ + newIntTypeNode(nkIntLit, 0, intType), + makeStaticExpr(c, e.nMinusOne)]) else: indx = e.typ.skipTypes({tyTypeDesc}) addSonSkipIntLit(result, indx) if indx.kind == tyGenericInst: indx = lastSon(indx) - if indx.kind notin {tyGenericParam, tyStatic}: + if indx.kind notin {tyGenericParam, tyStatic, tyFromExpr}: if not isOrdinalType(indx): localError(n.sons[1].info, errOrdinalTypeExpected) elif enumHasHoles(indx): @@ -619,6 +640,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, var s = newSym(skType, finalTypId, owner, info) if typId == nil: s.flags.incl(sfAnon) s.linkTo(typeClass) + typeClass.flags.incl tfImplicitTypeParam s.position = genericParams.len genericParams.addSon(newSymNode(s)) result = typeClass @@ -844,7 +866,7 @@ proc semGenericParamInInvokation(c: PContext, n: PNode): PType = proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = result = newOrPrevType(tyGenericInvokation, prev, c) addSonSkipIntLit(result, s.typ) - + template addToResult(typ) = if typ.isNil: internalAssert false diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 75d266679..b08119d4a 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -98,11 +98,50 @@ proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode = result = copyNode(n) result.typ = replaceTypeVarsT(cl, n.typ) if result.kind == nkSym: result.sym = replaceTypeVarsS(cl, n.sym) - for i in 0 .. safeLen(n)-1: - # XXX HACK: ``f(a, b)``, avoid to instantiate `f` - if i == 0: result.add(n[i]) + let isCall = result.kind in nkCallKinds + for i in 0 .. <n.safeLen: + # XXX HACK: ``f(a, b)``, avoid to instantiate `f` + if isCall and i == 0: result.add(n[i]) else: result.add(prepareNode(cl, n[i])) +proc isTypeParam(n: PNode): bool = + # XXX: generic params should use skGenericParam instead of skType + return n.kind == nkSym and + (n.sym.kind == skGenericParam or + (n.sym.kind == skType and sfFromGeneric in n.sym.flags)) + +proc hasGenericArguments*(n: PNode): bool = + if n.kind == nkSym: + return n.sym.kind == skGenericParam or + (n.sym.kind == skType and + n.sym.typ.flags * {tfGenericTypeParam, tfImplicitTypeParam} != {}) + else: + for s in n.sons: + if hasGenericArguments(s): return true + return false + +proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode = + # This is needed fo tgenericshardcases + # It's possible that a generic param will be used in a proc call to a + # typedesc accepting proc. After generic param substitution, such procs + # should be optionally instantiated with the correct type. In order to + # perform this instantiation, we need to re-run the generateInstance path + # in the compiler, but it's quite complicated to do so at the moment so we + # resort to a mild hack; the head symbol of the call is temporary reset and + # overload resolution is executed again (which may trigger generateInstance). + if n.kind in nkCallKinds and sfFromGeneric in n[0].sym.flags: + var needsFixing = false + for i in 1 .. <n.safeLen: + if isTypeParam(n[i]): needsFixing = true + if needsFixing: + n.sons[0] = newSymNode(n.sons[0].sym.owner) + return cl.c.semOverloadedCall(cl.c, n, n, {skProc}) + + for i in 0 .. <n.safeLen: + n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i]) + + return n + proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = if n == nil: return result = copyNode(n) @@ -135,6 +174,10 @@ proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = result = replaceTypeVarsN(cl, branch) else: result = newNodeI(nkRecList, n.info) + of nkStaticExpr: + var n = prepareNode(cl, n) + n = reResolveCallsWithTypedescParams(cl, n) + result = cl.c.semExpr(cl.c, n) else: var length = sonsLen(n) if length > 0: @@ -273,45 +316,58 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = result = t if t == nil: return - #if t.kind == tyStatic and t.sym != nil and t.sym.kind == skGenericParam: - # let s = lookupTypeVar(cl, t) - # return if s != nil: s else: t - if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses: let lookup = PType(idTableGet(cl.typeMap, t)) if lookup != nil: return lookup - + case t.kind of tyGenericInvokation: result = handleGenericInvokation(cl, t) + of tyGenericBody: internalError(cl.info, "ReplaceTypeVarsT: tyGenericBody" ) result = replaceTypeVarsT(cl, lastSon(t)) + of tyFromExpr: var n = prepareNode(cl, t.n) - n = cl.c.semExpr(cl.c, n, {}) - result = n.typ.skipTypes({tyTypeDesc}) + n = cl.c.semConstExpr(cl.c, n) + if n.typ.kind == tyTypeDesc: + # XXX: sometimes, chained typedescs enter here. + # It may be worth investigating why this is happening, + # because it may cause other bugs elsewhere. + result = n.typ.skipTypes({tyTypeDesc}) + # result = n.typ.base + else: + if n.typ.kind != tyStatic: + # XXX: In the future, semConstExpr should + # return tyStatic values to let anyone make + # use of this knowledge. The patching here + # won't be necessary then. + result = newTypeS(tyStatic, cl.c) + result.sons = @[n.typ] + result.n = n + else: + result = n.typ + of tyInt: result = skipIntLit(t) # XXX now there are also float literals + of tyTypeDesc: let lookup = PType(idTableGet(cl.typeMap, t)) # lookupTypeVar(cl, t) if lookup != nil: result = lookup if tfUnresolved in t.flags: result = result.base + elif t.sonsLen > 0: + result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0])) + of tyGenericInst: result = instCopyType(cl, t) for i in 1 .. <result.sonsLen: result.sons[i] = ReplaceTypeVarsT(cl, result.sons[i]) propagateToOwner(result, result.lastSon) + else: - if t.kind == tyArray: - let idxt = t.sons[0] - if idxt.kind == tyStatic and - idxt.sym != nil and idxt.sym.kind == skGenericParam: - let value = lookupTypeVar(cl, idxt).n - t.sons[0] = makeRangeType(cl.c, 0, value.intVal - 1, value.info) - if containsGenericType(t): result = instCopyType(cl, t) result.size = -1 # needs to be recomputed @@ -326,13 +382,25 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType = # XXX: This is not really needed? # if result.kind in GenericTypes: # localError(cl.info, errCannotInstantiateX, typeToString(t, preferName)) - + case result.kind + of tyArray: + let idx = result.sons[0] + if idx.kind == tyStatic: + if idx.n == nil: + let lookup = lookupTypeVar(cl, idx) + internalAssert lookup != nil + idx.n = lookup.n + + result.sons[0] = makeRangeType(cl.c, 0, idx.n.intVal - 1, idx.n.info) + of tyObject, tyTuple: propagateFieldFlags(result, result.n) + of tyProc: eraseVoidParams(result) skipIntLiteralParams(result) + else: discard proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo, diff --git a/compiler/types.nim b/compiler/types.nim index dd808915e..36c9f1934 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -1231,7 +1231,7 @@ proc getSize(typ: PType): BiggestInt = if result < 0: internalError("getSize: " & $typ.kind) proc containsGenericTypeIter(t: PType, closure: PObject): bool = - result = t.kind in GenericTypes + tyTypeClasses + {tyTypeDesc} or + result = t.kind in GenericTypes + tyTypeClasses + {tyTypeDesc,tyFromExpr} or t.kind == tyStatic and t.n == nil proc containsGenericType*(t: PType): bool = |