diff options
author | Joseph Poirier <jdpoirier@gmail.com> | 2015-01-02 21:47:09 -0600 |
---|---|---|
committer | Joseph Poirier <jdpoirier@gmail.com> | 2015-01-02 21:47:09 -0600 |
commit | efe183861cc8416872e6c1a44f642e6b03049616 (patch) | |
tree | 84fb6bbc5a4f81c1055db9d98492c133886fc846 | |
parent | d15d9f41110a245b2b5a13bd8a882eeb79311acd (diff) | |
parent | 8f82205d12c7546b7369505b54d0157b4909fe6d (diff) | |
download | Nim-efe183861cc8416872e6c1a44f642e6b03049616.tar.gz |
Merge remote-tracking branch 'upstream/devel' into devel
-rw-r--r-- | compiler/ast.nim | 1 | ||||
-rw-r--r-- | compiler/semcall.nim | 16 | ||||
-rw-r--r-- | compiler/semdata.nim | 2 | ||||
-rw-r--r-- | compiler/semexprs.nim | 4 | ||||
-rw-r--r-- | compiler/semstmts.nim | 12 | ||||
-rw-r--r-- | compiler/semtypes.nim | 11 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 91 | ||||
-rw-r--r-- | doc/tut1.txt | 4 | ||||
-rw-r--r-- | tests/generics/t1050.nim | 16 | ||||
-rw-r--r-- | tests/metatype/tsemistatic.nim | 8 | ||||
-rw-r--r-- | tests/metatype/tstaticparams.nim | 65 | ||||
-rw-r--r-- | tests/metatype/tusertypeclasses.nim | 27 | ||||
-rw-r--r-- | tests/misc/tvarious.nim | 108 |
13 files changed, 252 insertions, 113 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index d85dbf42c..883b68d71 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -399,6 +399,7 @@ const tyPureObject* = tyTuple GcTypeKinds* = {tyRef, tySequence, tyString} tyError* = tyProxy # as an errornous node should match everything + tyUnknown* = tyFromExpr tyUnknownTypes* = {tyError, tyFromExpr} diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 3971b8ff5..a712cc195 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -277,16 +277,14 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode = styleCheckUse(n.sons[0].info, finalCallee) if finalCallee.ast == nil: internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check! + if x.hasFauxMatch: + result = x.call + result.sons[0] = newSymNode(finalCallee, result.sons[0].info) + if containsGenericType(result.typ) or x.fauxMatch == tyUnknown: + result.typ = newTypeS(x.fauxMatch, c) + return if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty: - # a generic proc! - if not x.proxyMatch: - finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info) - else: - result = x.call - result.sons[0] = newSymNode(finalCallee, result.sons[0].info) - result.typ = finalCallee.typ.sons[0] - if containsGenericType(result.typ): result.typ = errorType(c) - return + finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info) result = x.call instGenericConvertersSons(c, result, x) result.sons[0] = newSymNode(finalCallee, result.sons[0].info) diff --git a/compiler/semdata.nim b/compiler/semdata.nim index f876770c0..623f9b633 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -268,7 +268,7 @@ proc makeRangeWithStaticExpr*(c: PContext, n: PNode): PType = template rangeHasStaticIf*(t: PType): bool = # this accepts the ranges's node - t.n[1].kind == nkStaticExpr + t.n != nil and t.n.len > 1 and t.n[1].kind == nkStaticExpr template getStaticTypeFromRange*(t: PType): PType = t.n[1][0][1].typ diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 89110a479..68921a15a 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -229,7 +229,7 @@ proc semConv(c: PContext, n: PNode): PNode = return n result = newNodeI(nkConv, n.info) - var targetType = semTypeNode(c, n.sons[0], nil) + var targetType = semTypeNode(c, n.sons[0], nil).skipTypes({tyTypeDesc}) maybeLiftType(targetType, c, n[0].info) result.addSon copyTree(n.sons[0]) var op = semExprWithType(c, n.sons[1]) @@ -780,7 +780,6 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect) elif t != nil and t.kind == tyTypeDesc: if n.len == 1: return semObjConstr(c, n, flags) - let destType = t.skipTypes({tyTypeDesc, tyGenericInst}) return semConv(c, n) else: result = overloadedCallOpr(c, n) @@ -928,7 +927,6 @@ proc readTypeParameter(c: PContext, typ: PType, let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias else: (internalAssert(typ.kind == tyCompositeTypeClass); typ.sons[1].skipGenericAlias) - #debug ty let tbody = ty.sons[0] for s in countup(0, tbody.len-2): let tParam = tbody.sons[s] diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 3b0332939..1396ef374 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -1262,10 +1262,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode = return else: n.sons[i] = semExpr(c, n.sons[i]) - if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool: - let verdict = semConstExpr(c, n[i]) - if verdict.intVal == 0: - localError(result.info, "type class predicate failed") + if c.inTypeClass > 0 and n[i].typ != nil: + case n[i].typ.kind + of tyBool: + let verdict = semConstExpr(c, n[i]) + if verdict.intVal == 0: + localError(result.info, "type class predicate failed") + of tyUnknown: continue + else: discard if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]): voidContext = true n.typ = enforceVoidContext diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index eb15c3809..deb4b1288 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -225,11 +225,10 @@ proc semArrayIndex(c: PContext, n: PNode): PType = elif e.kind == nkSym and e.typ.kind == tyStatic: if e.sym.ast != nil: return semArrayIndex(c, e.sym.ast) - internalAssert c.inGenericContext > 0 if not isOrdinalType(e.typ.lastSon): localError(n[1].info, errOrdinalTypeExpected) result = makeRangeWithStaticExpr(c, e) - result.flags.incl tfUnresolved + if c.inGenericContext >0: result.flags.incl tfUnresolved elif e.kind in nkCallKinds and hasGenericArguments(e): if not isOrdinalType(e.typ): localError(n[1].info, errOrdinalTypeExpected) @@ -782,10 +781,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, of tyGenericBody: result = newTypeS(tyGenericInvokation, c) result.rawAddSon(paramType) + for i in 0 .. paramType.sonsLen - 2: - result.rawAddSon newTypeS(tyAnything, c) - # result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true)) - + let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown + else: tyAnything + result.rawAddSon newTypeS(dummyType, c) + if paramType.lastSon.kind == tyUserTypeClass: result.kind = tyUserTypeClassInst result.rawAddSon paramType.lastSon diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index b58818a29..0182cb555 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -39,7 +39,9 @@ type bindings*: TIdTable # maps types to types baseTypeMatch: bool # needed for conversions from T to openarray[T] # for example - proxyMatch*: bool # to prevent instantiations + fauxMatch*: TTypeKind # the match was successful only due to the use + # of error or wildcard (unknown) types. + # this is used to prevent instantiations. genericConverter*: bool # true if a generic converter needs to # be instantiated coerceDistincts*: bool # this is an explicit coercion that can strip away @@ -66,6 +68,8 @@ const proc markUsed*(info: TLineInfo, s: PSym) +template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone + proc initCandidateAux(ctx: PContext, c: var TCandidate, callee: PType) {.inline.} = c.c = ctx @@ -109,9 +113,12 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym, for i in 1..min(sonsLen(typeParams), sonsLen(binding)-1): var formalTypeParam = typeParams.sons[i-1].typ var bound = binding[i].typ - if bound != nil and formalTypeParam.kind != tyTypeDesc: + internalAssert bound != nil + if formalTypeParam.kind == tyTypeDesc: + if bound.kind != tyTypeDesc: + bound = makeTypeDesc(ctx, bound) + else: bound = bound.skipTypes({tyTypeDesc}) - assert bound != nil put(c.bindings, formalTypeParam, bound) proc newCandidate*(ctx: PContext, callee: PSym, @@ -462,9 +469,23 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate, var typeParamName = ff.base.sons[i-1].sym.name typ = ff.sons[i] - param = newSym(skType, typeParamName, body.sym, body.sym.info) - - param.typ = makeTypeDesc(c, typ) + param: PSym + + template paramSym(kind): expr = + newSym(kind, typeParamName, body.sym, body.sym.info) + + case typ.kind + of tyStatic: + param = paramSym skConst + param.typ = typ.base + param.ast = typ.n + of tyUnknown: + param = paramSym skVar + param.typ = typ + else: + param = paramSym skType + param.typ = makeTypeDesc(c, typ) + addDecl(c, param) for param in body.n[0]: @@ -626,6 +647,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype of tyRange: if a.kind == f.kind: + if f.base.kind == tyNone: return isGeneric result = typeRel(c, base(f), base(a)) # bugfix: accept integer conversions here #if result < isGeneric: result = isNone @@ -672,22 +694,27 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = else: fRange = prev result = typeRel(c, f.sons[1], a.sons[1]) - if result < isGeneric: - result = isNone - elif tfUnresolved in fRange.flags and - rangeHasStaticIf(fRange): - # This is a range from an array instantiated with a generic - # static param. We must extract the static param here and bind - # it to the size of the currently supplied array. - var - rangeStaticT = fRange.getStaticTypeFromRange - replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType]) - inputUpperBound = a.sons[0].n[1].intVal - # we must correct for the off-by-one discrepancy between - # ranges and static params: - replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1) - put(c.bindings, rangeStaticT, replacementT) - result = isGeneric + if result < isGeneric: return isNone + if rangeHasStaticIf(fRange): + if tfUnresolved in fRange.flags: + # This is a range from an array instantiated with a generic + # static param. We must extract the static param here and bind + # it to the size of the currently supplied array. + var + rangeStaticT = fRange.getStaticTypeFromRange + replacementT = newTypeWithSons(c.c, tyStatic, @[tyInt.getSysType]) + inputUpperBound = a.sons[0].n[1].intVal + # we must correct for the off-by-one discrepancy between + # ranges and static params: + replacementT.n = newIntNode(nkIntLit, inputUpperBound + 1) + put(c.bindings, rangeStaticT, replacementT) + return isGeneric + + let len = tryResolvingStaticExpr(c, fRange.n[1]) + if len.kind == nkIntLit and len.intVal+1 == lengthOrd(a): + return # if we get this far, the result is already good + else: + return isNone elif lengthOrd(fRange) != lengthOrd(a): result = isNone else: discard @@ -945,7 +972,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = else: internalAssert a.sons != nil and a.sons.len > 0 c.typedescMatched = true - result = typeRel(c, f.base, a.base) + result = typeRel(c, f.base, a.skipTypes({tyGenericParam, tyTypeDesc})) else: result = isNone else: @@ -980,7 +1007,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation = if aOrig.kind == tyStatic: result = typeRel(c, f.lastSon, a) if result != isNone and f.n != nil: - if not exprStructuralEquivalent(f.n, a.n): + if not exprStructuralEquivalent(f.n, aOrig.n): result = isNone if result != isNone: put(c.bindings, f, aOrig) else: @@ -1045,10 +1072,10 @@ proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation = initCandidate(c, m, f) result = typeRel(m, f, a) -proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, - f: PType): PType = +proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate, + f: PType): PType = result = PType(idTableGet(m.bindings, f)) - if result == nil: + if result == nil: result = generateTypeInstance(c, m.bindings, arg, f) if result == nil: internalError(arg.info, "getInstantiatedType") @@ -1058,7 +1085,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, c: PContext): PNode = result = newNodeI(kind, arg.info) if containsGenericType(f): - if not m.proxyMatch: + if not m.hasFauxMatch: result.typ = getInstantiatedType(c, arg, m, f) else: result.typ = errorType(c) @@ -1130,7 +1157,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 @@ -1144,7 +1171,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, return argSemantized if argType.kind == tyStatic: - if m.callee.kind == tyGenericBody: + if m.callee.kind == tyGenericBody and tfGenericTypeParam notin argType.flags: result = newNodeI(nkType, argOrig.info) result.typ = makeTypeFromExpr(c, arg) return @@ -1237,9 +1264,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType, result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c) of isNone: # do not do this in ``typeRel`` as it then can't infere T in ``ref T``: - if a.kind == tyProxy: + if a.kind in {tyProxy, tyUnknown}: inc(m.genericMatches) - m.proxyMatch = true + m.fauxMatch = a.kind return copyTree(arg) result = userConvMatch(c, m, f, a, arg) # check for a base type match, which supports varargs[T] without [] diff --git a/doc/tut1.txt b/doc/tut1.txt index 4c32fa0ae..5901dd02a 100644 --- a/doc/tut1.txt +++ b/doc/tut1.txt @@ -1070,7 +1070,7 @@ Operation Comment ``dec(x, n)`` decrements `x` by `n`; `n` is an integer ``succ(x)`` returns the successor of `x` ``succ(x, n)`` returns the `n`'th successor of `x` -``prec(x)`` returns the predecessor of `x` +``pred(x)`` returns the predecessor of `x` ``pred(x, n)`` returns the `n`'th predecessor of `x` ----------------- -------------------------------------------------------- @@ -1323,7 +1323,7 @@ define operators which accept TSlice objects to define ranges. a = "Nim is a progamming language" b = "Slices are useless." - echo a[10..15] # --> 'a prog' + echo a[7..12] # --> 'a prog' b[11.. -2] = "useful" echo b # --> 'Slices are useful.' diff --git a/tests/generics/t1050.nim b/tests/generics/t1050.nim new file mode 100644 index 000000000..a6f9a2482 --- /dev/null +++ b/tests/generics/t1050.nim @@ -0,0 +1,16 @@ +discard """ + msg: "int" + output: "4" +""" + +import typetraits + +type ArrayType[T] = distinct T + +proc arrayItem(a: ArrayType): auto = + static: echo(name(type(a).T)) + result = (type(a).T)(4) + +var arr: ArrayType[int] +echo arrayItem(arr) + diff --git a/tests/metatype/tsemistatic.nim b/tests/metatype/tsemistatic.nim index 0a003be03..a13175ba8 100644 --- a/tests/metatype/tsemistatic.nim +++ b/tests/metatype/tsemistatic.nim @@ -1,9 +1,15 @@ discard """ msg: "static 10\ndynamic\nstatic 20\n" output: "s\nd\nd\ns" - disabled: "true" """ +type + semistatic[T] = + static[T] or T + +template isStatic*(x): expr = + compiles(static(x)) + proc foo(x: semistatic[int]) = when isStatic(x): static: echo "static ", x diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim index 6d7c569e0..e98a2871f 100644 --- a/tests/metatype/tstaticparams.nim +++ b/tests/metatype/tstaticparams.nim @@ -1,6 +1,6 @@ discard """ file: "tstaticparams.nim" - output: "abracadabra\ntest\n3\n15\n4\n2" + output: "abracadabra\ntest\n3\n15\n4\n2\nfloat\n3\nfloat\nyin\nyang" """ type @@ -56,3 +56,66 @@ type TTestSub[N: static[int]] = TTest[1, N] var z: TTestSub[2] echo z.high + +# issue 1049 +proc matrix_1*[M, N, T](mat: Matrix[M,N,T], a: array[N, int]) = discard +proc matrix_2*[M, N, T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard + +proc matrix_3*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N, int]) = discard +proc matrix_4*[M, N: static[int]; T](mat: Matrix[M,N,T], a: array[N+1, int]) = discard + +var + tmat: Matrix[4,4,int] + ar1: array[4, int] + ar2: array[5, int] + +matrix_1(tmat, ar1) +matrix_2(tmat, ar2) +matrix_3(tmat, ar1) +matrix_4(tmat, ar2) + +template reject(x): stmt = + static: assert(not compiles(x)) + +# test with arrays of wrong size +reject matrix_1(tmat, ar2) +reject matrix_2(tmat, ar1) +reject matrix_3(tmat, ar2) +reject matrix_4(tmat, ar1) + +# bug 1820 + +type + T1820_1[T; Y: static[int]] = object + bar: T + +proc intOrFloat*[Y](f: T1820_1[int, Y]) = echo "int" +proc intOrFloat*[Y](f: T1820_1[float, Y]) = echo "float" +proc threeOrFour*[T](f: T1820_1[T, 3]) = echo "3" +proc threeOrFour*[T](f: T1820_1[T, 4]) = echo "4" + +var foo_1: T1820_1[float, 3] + +foo_1.intOrFloat +foo_1.threeOrFour + +type + YinAndYang = enum + Yin, + Yang + + T1820_2[T; Y: static[YinAndYang]] = object + bar: T + +proc intOrFloat*[Y](f: T1820_2[int, Y]) = echo "int" +proc intOrFloat*[Y](f: T1820_2[float, Y]) = echo "float" +proc yinOrYang*[T](f: T1820_2[T, YinAndYang.Yin]) = echo "yin" +proc yinOrYang*[T](f: T1820_2[T, Yang]) = echo "yang" + +var foo_2: T1820_2[float, Yin] +var foo_3: T1820_2[float, YinAndYang.Yang] + +foo_2.intOrFloat +foo_2.yinOrYang +foo_3.yinOrYang + diff --git a/tests/metatype/tusertypeclasses.nim b/tests/metatype/tusertypeclasses.nim index 6e9e4934b..4e5e6221c 100644 --- a/tests/metatype/tusertypeclasses.nim +++ b/tests/metatype/tusertypeclasses.nim @@ -1,5 +1,13 @@ discard """ - output: "Sortable\nSortable\nContainer" + output: '''Sortable +Sortable +Container +true +true +false +false +false +''' """ import typetraits @@ -41,3 +49,20 @@ proc y(x: TObj): int = 10 proc testFoo(x: TFoo) = discard testFoo(TObj(x: 10)) +type + Matrix[Rows, Cols: static[int]; T] = generic M + M.M == Rows + M.N == Cols + M.T is T + + MyMatrix[M, N: static[int]; T] = object + data: array[M*N, T] + +var x: MyMatrix[3, 3, int] + +echo x is Matrix +echo x is Matrix[3, 3, int] +echo x is Matrix[3, 3, float] +echo x is Matrix[4, 3, int] +echo x is Matrix[3, 4, int] + diff --git a/tests/misc/tvarious.nim b/tests/misc/tvarious.nim index 434d25e48..8124b3fc7 100644 --- a/tests/misc/tvarious.nim +++ b/tests/misc/tvarious.nim @@ -1,67 +1,67 @@ -# Test various aspects +# Test various aspects # bug #572 var a=12345678901'u64 - + var x = (x: 42, y: (a: 8, z: 10)) echo x.y - -import - mvarious - -type - PA = ref TA - PB = ref TB - - TB = object - a: PA - - TA = object - b: TB - x: int - -proc getPA(): PA = - var - b: bool - b = not false - return nil + +import + mvarious + +type + PA = ref TA + PB = ref TB + + TB = object + a: PA + + TA = object + b: TB + x: int + +proc getPA(): PA = + var + b: bool + b = not false + return nil # bug #501 proc f(): int = 54 - -var - global: int - -var - s: string - i: int - r: TA - -r.b.a.x = 0 -global = global + 1 -exportme() -write(stdout, "Hallo wie heißt du? ") -write(stdout, getPA().x) -s = readLine(stdin) -i = 0 -while i < s.len: - if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n") - i = i + 1 - -write(stdout, "Du heißt " & s) + +var + global: int + +var + s: string + i: int + r: TA + +r.b.a.x = 0 +global = global + 1 +exportme() +write(stdout, "Hallo wie heißt du? ") +write(stdout, getPA().x) +s = readLine(stdin) +i = 0 +while i < s.len: + if s[i] == 'c': write(stdout, "'c' in deinem Namen gefunden\n") + i = i + 1 + +write(stdout, "Du heißt " & s) # bug #544 -when false: - # yay, fails again - type Bar [T; I:range] = array[I, T] - proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] = - when len(a) != 3: - # Error: constant expression expected - {.fatal:"Dimensions have to be 3".} - #... - block: - var a, b: Bar[int, 0..2] - discard foo(a, b) + +# yay, fails again +type Bar [T; I:range] = array[I, T] +proc foo*[T; I:range](a, b: Bar[T, I]): Bar[T, I] = + when len(a) != 3: + # Error: constant expression expected + {.fatal:"Dimensions have to be 3".} + #... +block: + var a, b: Bar[int, range[0..2]] + discard foo(a, b) # bug #1788 |