Working test cases for the sophisticated matrix library example from the manual
Fixed the dot operator when used within return types (see tgenericdotrettype) Fixed the matching of generic concepts aliases used with the implicit generics style
This commit is contained in:
parent
52b241fd57
commit
cbf66e99a8
12 changed files with 211 additions and 53 deletions
|
|
@ -911,8 +911,7 @@ proc makeDeref(n: PNode): PNode =
|
||||||
t = skipTypes(baseTyp, {tyGenericInst, tyAlias})
|
t = skipTypes(baseTyp, {tyGenericInst, tyAlias})
|
||||||
|
|
||||||
const
|
const
|
||||||
tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass,
|
tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass}
|
||||||
tyUserTypeClass, tyUserTypeClassInst}
|
|
||||||
tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias}
|
tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias}
|
||||||
|
|
||||||
proc readTypeParameter(c: PContext, typ: PType,
|
proc readTypeParameter(c: PContext, typ: PType,
|
||||||
|
|
@ -1107,6 +1106,23 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
var ty = n.sons[0].typ
|
var ty = n.sons[0].typ
|
||||||
var f: PSym = nil
|
var f: PSym = nil
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
|
template tryReadingGenericParam(t: PType) =
|
||||||
|
case t.kind
|
||||||
|
of tyTypeParamsHolders:
|
||||||
|
return readTypeParameter(c, t, i, n.info)
|
||||||
|
of tyUserTypeClasses:
|
||||||
|
if t.isResolvedUserTypeClass:
|
||||||
|
return readTypeParameter(c, t, i, n.info)
|
||||||
|
else:
|
||||||
|
n.typ = makeTypeFromExpr(c, copyTree(n))
|
||||||
|
return n
|
||||||
|
of tyGenericParam:
|
||||||
|
n.typ = makeTypeFromExpr(c, copyTree(n))
|
||||||
|
return n
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
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
|
if ty.kind == tyTypeDesc: ty = ty.base
|
||||||
ty = ty.skipTypes(tyDotOpTransparent)
|
ty = ty.skipTypes(tyDotOpTransparent)
|
||||||
|
|
@ -1124,8 +1140,6 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
markUsed(n.info, f, c.graph.usageSym)
|
markUsed(n.info, f, c.graph.usageSym)
|
||||||
styleCheckUse(n.info, f)
|
styleCheckUse(n.info, f)
|
||||||
return
|
return
|
||||||
of tyTypeParamsHolders:
|
|
||||||
return readTypeParameter(c, ty, i, n.info)
|
|
||||||
of tyObject, tyTuple:
|
of tyObject, tyTuple:
|
||||||
if ty.n != nil and ty.n.kind == nkRecList:
|
if ty.n != nil and ty.n.kind == nkRecList:
|
||||||
let field = lookupInRecord(ty.n, i)
|
let field = lookupInRecord(ty.n, i)
|
||||||
|
|
@ -1134,8 +1148,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
n.typ.n = copyTree(n)
|
n.typ.n = copyTree(n)
|
||||||
return n
|
return n
|
||||||
else:
|
else:
|
||||||
# echo "TYPE FIELD ACCESS"
|
tryReadingGenericParam(ty)
|
||||||
# debug ty
|
|
||||||
return
|
return
|
||||||
# XXX: This is probably not relevant any more
|
# XXX: This is probably not relevant any more
|
||||||
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
|
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
|
||||||
|
|
@ -1178,8 +1191,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# we didn't find any field, let's look for a generic param
|
# we didn't find any field, let's look for a generic param
|
||||||
if result == nil:
|
if result == nil:
|
||||||
let t = n.sons[0].typ.skipTypes(tyDotOpTransparent)
|
let t = n.sons[0].typ.skipTypes(tyDotOpTransparent)
|
||||||
if t.kind in tyTypeParamsHolders:
|
tryReadingGenericParam(t)
|
||||||
result = readTypeParameter(c, t, i, n.info)
|
|
||||||
|
|
||||||
proc dotTransformation(c: PContext, n: PNode): PNode =
|
proc dotTransformation(c: PContext, n: PNode): PNode =
|
||||||
if isSymChoice(n.sons[1]):
|
if isSymChoice(n.sons[1]):
|
||||||
|
|
|
||||||
|
|
@ -845,9 +845,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
|
|
||||||
for i in 0 .. paramType.sonsLen - 2:
|
for i in 0 .. paramType.sonsLen - 2:
|
||||||
if paramType.sons[i].kind == tyStatic:
|
if paramType.sons[i].kind == tyStatic:
|
||||||
var x = copyNode(ast.emptyNode)
|
var staticCopy = paramType.sons[i].exactReplica
|
||||||
x.typ = paramType.sons[i]
|
staticCopy.flags.incl tfInferrableStatic
|
||||||
result.rawAddSon makeTypeFromExpr(c, x) # aka 'tyUnknown'
|
result.rawAddSon staticCopy
|
||||||
else:
|
else:
|
||||||
result.rawAddSon newTypeS(tyAnything, c)
|
result.rawAddSon newTypeS(tyAnything, c)
|
||||||
|
|
||||||
|
|
@ -891,7 +891,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
allowMetaTypes = true)
|
allowMetaTypes = true)
|
||||||
result = liftingWalk(expanded, true)
|
result = liftingWalk(expanded, true)
|
||||||
|
|
||||||
of tyUserTypeClass, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
|
of tyUserTypeClasses, tyBuiltInTypeClass, tyAnd, tyOr, tyNot:
|
||||||
result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), true))
|
result = addImplicitGeneric(copyType(paramType, getCurrOwner(c), true))
|
||||||
|
|
||||||
of tyGenericParam:
|
of tyGenericParam:
|
||||||
|
|
@ -1357,6 +1357,8 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
|
||||||
else: result = semGeneric(c, n, s, prev)
|
else: result = semGeneric(c, n, s, prev)
|
||||||
of nkDotExpr:
|
of nkDotExpr:
|
||||||
let typeExpr = semExpr(c, n)
|
let typeExpr = semExpr(c, n)
|
||||||
|
if typeExpr.typ.kind == tyFromExpr:
|
||||||
|
return typeExpr.typ
|
||||||
if typeExpr.typ.kind != tyTypeDesc:
|
if typeExpr.typ.kind != tyTypeDesc:
|
||||||
localError(n.info, errTypeExpected)
|
localError(n.info, errTypeExpected)
|
||||||
result = errorType(c)
|
result = errorType(c)
|
||||||
|
|
|
||||||
|
|
@ -404,6 +404,8 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericInvocation:
|
of tyGenericInvocation:
|
||||||
result = handleGenericInvocation(cl, t)
|
result = handleGenericInvocation(cl, t)
|
||||||
|
if result.lastSon.kind == tyUserTypeClass:
|
||||||
|
result.kind = tyUserTypeClassInst
|
||||||
|
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
localError(cl.info, errCannotInstantiateX, typeToString(t))
|
localError(cl.info, errCannotInstantiateX, typeToString(t))
|
||||||
|
|
|
||||||
|
|
@ -613,6 +613,13 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||||
template paramSym(kind): untyped =
|
template paramSym(kind): untyped =
|
||||||
newSym(kind, typeParamName, Concept.sym, Concept.sym.info)
|
newSym(kind, typeParamName, Concept.sym, Concept.sym.info)
|
||||||
|
|
||||||
|
block addTypeParam:
|
||||||
|
for prev in typeParams:
|
||||||
|
if prev[1].id == typ.id:
|
||||||
|
param = paramSym prev[0].kind
|
||||||
|
param.typ = prev[0].typ
|
||||||
|
break addTypeParam
|
||||||
|
|
||||||
case typ.kind
|
case typ.kind
|
||||||
of tyStatic:
|
of tyStatic:
|
||||||
param = paramSym skConst
|
param = paramSym skConst
|
||||||
|
|
@ -631,9 +638,10 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||||
else:
|
else:
|
||||||
makeTypeDesc(c, typ)
|
makeTypeDesc(c, typ)
|
||||||
|
|
||||||
addDecl(c, param)
|
|
||||||
typeParams.safeAdd((param, typ))
|
typeParams.safeAdd((param, typ))
|
||||||
|
|
||||||
|
addDecl(c, param)
|
||||||
|
|
||||||
for param in Concept.n[0]:
|
for param in Concept.n[0]:
|
||||||
var
|
var
|
||||||
dummyName: PNode
|
dummyName: PNode
|
||||||
|
|
@ -696,7 +704,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||||
put(m.bindings, p[1], p[0].typ)
|
put(m.bindings, p[1], p[0].typ)
|
||||||
|
|
||||||
if ff.kind == tyUserTypeClassInst:
|
if ff.kind == tyUserTypeClassInst:
|
||||||
result = generateTypeInstance(c, m.bindings, ff.sym.info, ff)
|
result = generateTypeInstance(c, m.bindings, Concept.sym.info, ff)
|
||||||
else:
|
else:
|
||||||
result = copyType(ff, ff.owner, true)
|
result = copyType(ff, ff.owner, true)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -183,7 +183,7 @@ proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
|
||||||
if result: return
|
if result: return
|
||||||
if not containsOrIncl(marker, t.id):
|
if not containsOrIncl(marker, t.id):
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyGenericInst, tyGenericBody, tyAlias:
|
of tyGenericInst, tyGenericBody, tyAlias, tyInferred:
|
||||||
result = iterOverTypeAux(marker, lastSon(t), iter, closure)
|
result = iterOverTypeAux(marker, lastSon(t), iter, closure)
|
||||||
else:
|
else:
|
||||||
for i in countup(0, sonsLen(t) - 1):
|
for i in countup(0, sonsLen(t) - 1):
|
||||||
|
|
@ -1320,6 +1320,9 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
|
||||||
if result < 0: return
|
if result < 0: return
|
||||||
if a < maxAlign: a = maxAlign
|
if a < maxAlign: a = maxAlign
|
||||||
result = align(result, a)
|
result = align(result, a)
|
||||||
|
of tyInferred:
|
||||||
|
if typ.len > 1:
|
||||||
|
result = computeSizeAux(typ.lastSon, a)
|
||||||
of tyGenericInst, tyDistinct, tyGenericBody, tyAlias:
|
of tyGenericInst, tyDistinct, tyGenericBody, tyAlias:
|
||||||
result = computeSizeAux(lastSon(typ), a)
|
result = computeSizeAux(lastSon(typ), a)
|
||||||
of tyTypeClasses:
|
of tyTypeClasses:
|
||||||
|
|
@ -1351,17 +1354,16 @@ proc getSize(typ: PType): BiggestInt =
|
||||||
if result < 0: internalError("getSize: " & $typ.kind)
|
if result < 0: internalError("getSize: " & $typ.kind)
|
||||||
|
|
||||||
proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
|
proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
|
||||||
if t.kind == tyStatic:
|
case t.kind
|
||||||
|
of tyStatic:
|
||||||
return t.n == nil
|
return t.n == nil
|
||||||
|
of tyTypeDesc:
|
||||||
if t.kind == tyTypeDesc:
|
|
||||||
if t.base.kind == tyNone: return true
|
if t.base.kind == tyNone: return true
|
||||||
if containsGenericTypeIter(t.base, closure): return true
|
if containsGenericTypeIter(t.base, closure): return true
|
||||||
return false
|
return false
|
||||||
|
of GenericTypes + tyTypeClasses + {tyFromExpr}:
|
||||||
if t.kind in GenericTypes + tyTypeClasses + {tyFromExpr}:
|
|
||||||
return true
|
return true
|
||||||
|
else:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc containsGenericType*(t: PType): bool =
|
proc containsGenericType*(t: PType): bool =
|
||||||
|
|
|
||||||
|
|
@ -1678,7 +1678,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
elif sfImportc in s.flags: c.importcSym(n.info, s)
|
elif sfImportc in s.flags: c.importcSym(n.info, s)
|
||||||
genLit(c, n, dest)
|
genLit(c, n, dest)
|
||||||
of skConst:
|
of skConst:
|
||||||
gen(c, s.ast, dest)
|
let constVal = if s.ast != nil: s.ast else: s.typ.n
|
||||||
|
gen(c, constVal, dest)
|
||||||
of skEnumField:
|
of skEnumField:
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
if s.position >= low(int16) and s.position <= high(int16):
|
if s.position >= low(int16) and s.position <= high(int16):
|
||||||
|
|
|
||||||
|
|
@ -305,6 +305,9 @@ The concept types can be parametric just like the regular generic types:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
### matrixalgo.nim
|
### matrixalgo.nim
|
||||||
|
|
||||||
|
import typetraits
|
||||||
|
|
||||||
type
|
type
|
||||||
AnyMatrix*[R, C: static[int]; T] = concept m, var mvar, type M
|
AnyMatrix*[R, C: static[int]; T] = concept m, var mvar, type M
|
||||||
M.ValueType is T
|
M.ValueType is T
|
||||||
|
|
@ -314,9 +317,13 @@ The concept types can be parametric just like the regular generic types:
|
||||||
m[int, int] is T
|
m[int, int] is T
|
||||||
mvar[int, int] = T
|
mvar[int, int] = T
|
||||||
|
|
||||||
|
type TransposedType = StripGenericParams(M)[C, R, T]
|
||||||
|
|
||||||
AnySquareMatrix*[N: static[int], T] = AnyMatrix[N, N, T]
|
AnySquareMatrix*[N: static[int], T] = AnyMatrix[N, N, T]
|
||||||
|
|
||||||
proc transpose*[R, C, T](m: AnyMatrix[R, C, T]): m.type.basis[C, R, T] =
|
AnyTransform3D* = AnyMatrix[4, 4, float]
|
||||||
|
|
||||||
|
proc transposed*(m: AnyMatrix): m.TransposedType =
|
||||||
for r in 0 .. <m.R:
|
for r in 0 .. <m.R:
|
||||||
for c in 0 .. <m.C:
|
for c in 0 .. <m.C:
|
||||||
result[r, c] = m[c, r]
|
result[r, c] = m[c, r]
|
||||||
|
|
@ -324,6 +331,9 @@ The concept types can be parametric just like the regular generic types:
|
||||||
proc determinant*(m: AnySquareMatrix): int =
|
proc determinant*(m: AnySquareMatrix): int =
|
||||||
...
|
...
|
||||||
|
|
||||||
|
proc setPerspectiveProjection*(m: AnyTransform3D) =
|
||||||
|
...
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
### matrix.nim
|
### matrix.nim
|
||||||
|
|
||||||
|
|
@ -331,11 +341,11 @@ The concept types can be parametric just like the regular generic types:
|
||||||
Matrix*[M, N: static[int]; T] = object
|
Matrix*[M, N: static[int]; T] = object
|
||||||
data: array[M*N, T]
|
data: array[M*N, T]
|
||||||
|
|
||||||
proc `[]`*(m: Matrix; m, n: int): m.T =
|
proc `[]`*(M: Matrix; m, n: int): M.T =
|
||||||
m.data[m * m.N + n]
|
M.data[m * M.N + n]
|
||||||
|
|
||||||
proc `[]=`*(m: var Matrix; m, n: int; v: m.T) =
|
proc `[]=`*(M: var Matrix; m, n: int; v: M.T) =
|
||||||
m.data[m * m.N + n] = v
|
M.data[m * M.N + n] = v
|
||||||
|
|
||||||
# Adapt the Matrix type to the concept's requirements
|
# Adapt the Matrix type to the concept's requirements
|
||||||
template Rows*(M: type Matrix): expr = M.M
|
template Rows*(M: type Matrix): expr = M.M
|
||||||
|
|
@ -347,8 +357,12 @@ The concept types can be parametric just like the regular generic types:
|
||||||
|
|
||||||
import matrix, matrixalgo
|
import matrix, matrixalgo
|
||||||
|
|
||||||
var v: Matrix[3, 3, int]
|
var
|
||||||
echo v.determinant
|
m: Matrix[3, 3, int]
|
||||||
|
projectionMatrix: Matrix[4, 4, float]
|
||||||
|
|
||||||
|
echo m.transposed.determinant
|
||||||
|
setPerspectiveProjection projectionMatrix
|
||||||
|
|
||||||
When the concept type is matched against a concrete type, the unbound type
|
When the concept type is matched against a concrete type, the unbound type
|
||||||
parameters are inferred from the body of the concept in a way that closely
|
parameters are inferred from the body of the concept in a way that closely
|
||||||
|
|
|
||||||
15
tests/concepts/matrix.nim
Normal file
15
tests/concepts/matrix.nim
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
type
|
||||||
|
Matrix*[M, N: static[int]; T] = object
|
||||||
|
data: array[M*N, T]
|
||||||
|
|
||||||
|
proc `[]`*(M: Matrix; m, n: int): M.T =
|
||||||
|
M.data[m * M.N + n]
|
||||||
|
|
||||||
|
proc `[]=`*(M: var Matrix; m, n: int; v: M.T) =
|
||||||
|
M.data[m * M.N + n] = v
|
||||||
|
|
||||||
|
# Adapt the Matrix type to the concept's requirements
|
||||||
|
template Rows*(M: type Matrix): expr = M.M
|
||||||
|
template Cols*(M: type Matrix): expr = M.N
|
||||||
|
template ValueType*(M: type Matrix): typedesc = M.T
|
||||||
|
|
||||||
28
tests/concepts/matrixalgo.nim
Normal file
28
tests/concepts/matrixalgo.nim
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
import typetraits
|
||||||
|
|
||||||
|
type
|
||||||
|
AnyMatrix*[R, C: static[int]; T] = concept m, var mvar, type M
|
||||||
|
M.ValueType is T
|
||||||
|
M.Rows == R
|
||||||
|
M.Cols == C
|
||||||
|
|
||||||
|
m[int, int] is T
|
||||||
|
mvar[int, int] = T
|
||||||
|
|
||||||
|
type TransposedType = StripGenericParams(M)[C, R, T]
|
||||||
|
|
||||||
|
AnySquareMatrix*[N: static[int], T] = AnyMatrix[N, N, T]
|
||||||
|
|
||||||
|
AnyTransform3D* = AnyMatrix[4, 4, float]
|
||||||
|
|
||||||
|
proc transposed*(m: AnyMatrix): m.TransposedType =
|
||||||
|
for r in 0 .. <m.R:
|
||||||
|
for c in 0 .. <m.C:
|
||||||
|
result[r, c] = m[c, r]
|
||||||
|
|
||||||
|
proc determinant*(m: AnySquareMatrix): int =
|
||||||
|
return 0
|
||||||
|
|
||||||
|
proc setPerspectiveProjection*(m: AnyTransform3D) =
|
||||||
|
discard
|
||||||
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
discard """
|
discard """
|
||||||
output: "0\n0"
|
output: "0\n0\n0"
|
||||||
msg: '''
|
msg: '''
|
||||||
R=3 C=3 TE=9 FF=14 FC=20 T=int
|
R=3 C=3 TE=9 FF=14 FC=20 T=int
|
||||||
|
R=3 C=3 T=int
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -41,13 +42,25 @@ proc `[]=`(m: var MyMatrix; r, c: int, v: m.T) =
|
||||||
|
|
||||||
proc foo(x: MyMatrix, arr: array[15, x.T]) = discard
|
proc foo(x: MyMatrix, arr: array[15, x.T]) = discard
|
||||||
|
|
||||||
proc matrixProc[R, C, TE, FF, FC, T](m: Matrix[R, C, TE, FF, FC, T]): T =
|
proc genericMatrixProc[R, C, TE, FF, FC, T](m: Matrix[R, C, TE, FF, FC, T]): T =
|
||||||
static:
|
static:
|
||||||
echo "R=", R, " C=", C, " TE=", TE, " FF=", FF, " FC=", FC, " T=", T.name
|
echo "R=", R, " C=", C, " TE=", TE, " FF=", FF, " FC=", FC, " T=", T.name
|
||||||
|
|
||||||
m[0, 0]
|
m[0, 0]
|
||||||
|
|
||||||
proc myMatrixProc(x: MyMatrix): MyMatrix.T = matrixProc(x)
|
proc implicitMatrixProc(m: Matrix): m.T =
|
||||||
|
static:
|
||||||
|
echo "R=", m.Rows,
|
||||||
|
" C=", m.Cols,
|
||||||
|
# XXX: fix these
|
||||||
|
#" TE=", m.TotalElements,
|
||||||
|
#" FF=", m.FromFoo,
|
||||||
|
#" FC=", m.FromConst,
|
||||||
|
" T=", m.T.name
|
||||||
|
|
||||||
|
m[0, 0]
|
||||||
|
|
||||||
|
proc myMatrixProc(x: MyMatrix): MyMatrix.T = genericMatrixProc(x)
|
||||||
|
|
||||||
var x: MyMatrix[3, 3, int]
|
var x: MyMatrix[3, 3, int]
|
||||||
|
|
||||||
|
|
@ -63,5 +76,6 @@ static:
|
||||||
no x is Matrix[3, 4, 9, 15, 20, int]
|
no x is Matrix[3, 4, 9, 15, 20, int]
|
||||||
|
|
||||||
echo x.myMatrixProc
|
echo x.myMatrixProc
|
||||||
echo x.matrixProc
|
echo x.genericMatrixProc
|
||||||
|
echo x.implicitMatrixProc
|
||||||
|
|
||||||
|
|
|
||||||
31
tests/concepts/tmatrixlib.nim
Normal file
31
tests/concepts/tmatrixlib.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
discard """
|
||||||
|
output: "0"
|
||||||
|
"""
|
||||||
|
|
||||||
|
import matrix, matrixalgo
|
||||||
|
|
||||||
|
import typetraits # XXX: this should be removed
|
||||||
|
|
||||||
|
var m: Matrix[3, 3, int]
|
||||||
|
var projectionMatrix: Matrix[4, 4, float]
|
||||||
|
|
||||||
|
echo m.transposed.determinant
|
||||||
|
setPerspectiveProjection projectionMatrix
|
||||||
|
|
||||||
|
template ok(x) = assert x
|
||||||
|
template no(x) = assert(not x)
|
||||||
|
|
||||||
|
static:
|
||||||
|
ok projectionMatrix is AnyTransform3D
|
||||||
|
no m is AnyTransform3D
|
||||||
|
|
||||||
|
type SquareStringMatrix = Matrix[5, 5, string]
|
||||||
|
|
||||||
|
ok SquareStringMatrix is AnyMatrix
|
||||||
|
ok SquareStringMatrix is AnySquareMatrix
|
||||||
|
no SquareStringMatrix is AnyTransform3D
|
||||||
|
|
||||||
|
ok Matrix[5, 10, int] is AnyMatrix
|
||||||
|
no Matrix[7, 15, float] is AnySquareMatrix
|
||||||
|
no Matrix[4, 4, int] is AnyTransform3D
|
||||||
|
|
||||||
29
tests/generics/tgenericdotrettype.nim
Normal file
29
tests/generics/tgenericdotrettype.nim
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
discard """
|
||||||
|
output: '''string
|
||||||
|
int
|
||||||
|
(int, string)
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import typetraits
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo[T, U] = object
|
||||||
|
x: T
|
||||||
|
y: U
|
||||||
|
|
||||||
|
proc bar[T](a: T): T.U =
|
||||||
|
echo result.type.name
|
||||||
|
|
||||||
|
proc bas(x: auto): x.T =
|
||||||
|
echo result.type.name
|
||||||
|
|
||||||
|
proc baz(x: Foo): (Foo.T, x.U) =
|
||||||
|
echo result.type.name
|
||||||
|
|
||||||
|
var
|
||||||
|
f: Foo[int, string]
|
||||||
|
x = bar f
|
||||||
|
z = bas f
|
||||||
|
y = baz f
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue