support for static params in the user defined type classes
This commit is contained in:
parent
2f90be13e2
commit
05cbbac4e5
6 changed files with 73 additions and 25 deletions
|
|
@ -399,6 +399,7 @@ const
|
||||||
tyPureObject* = tyTuple
|
tyPureObject* = tyTuple
|
||||||
GcTypeKinds* = {tyRef, tySequence, tyString}
|
GcTypeKinds* = {tyRef, tySequence, tyString}
|
||||||
tyError* = tyProxy # as an errornous node should match everything
|
tyError* = tyProxy # as an errornous node should match everything
|
||||||
|
tyUnknown* = tyFromExpr
|
||||||
|
|
||||||
tyUnknownTypes* = {tyError, tyFromExpr}
|
tyUnknownTypes* = {tyError, tyFromExpr}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -277,16 +277,14 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
|
||||||
styleCheckUse(n.sons[0].info, finalCallee)
|
styleCheckUse(n.sons[0].info, finalCallee)
|
||||||
if finalCallee.ast == nil:
|
if finalCallee.ast == nil:
|
||||||
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
|
internalError(n.info, "calleeSym.ast is nil") # XXX: remove this check!
|
||||||
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
|
if x.hasFauxMatch:
|
||||||
# a generic proc!
|
|
||||||
if not x.proxyMatch:
|
|
||||||
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
|
||||||
else:
|
|
||||||
result = x.call
|
result = x.call
|
||||||
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
||||||
result.typ = finalCallee.typ.sons[0]
|
if containsGenericType(result.typ) or x.fauxMatch == tyUnknown:
|
||||||
if containsGenericType(result.typ): result.typ = errorType(c)
|
result.typ = newTypeS(x.fauxMatch, c)
|
||||||
return
|
return
|
||||||
|
if finalCallee.ast.sons[genericParamsPos].kind != nkEmpty:
|
||||||
|
finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
|
||||||
result = x.call
|
result = x.call
|
||||||
instGenericConvertersSons(c, result, x)
|
instGenericConvertersSons(c, result, x)
|
||||||
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
result.sons[0] = newSymNode(finalCallee, result.sons[0].info)
|
||||||
|
|
|
||||||
|
|
@ -1262,10 +1262,14 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
n.sons[i] = semExpr(c, n.sons[i])
|
n.sons[i] = semExpr(c, n.sons[i])
|
||||||
if c.inTypeClass > 0 and n[i].typ != nil and n[i].typ.kind == tyBool:
|
if c.inTypeClass > 0 and n[i].typ != nil:
|
||||||
|
case n[i].typ.kind
|
||||||
|
of tyBool:
|
||||||
let verdict = semConstExpr(c, n[i])
|
let verdict = semConstExpr(c, n[i])
|
||||||
if verdict.intVal == 0:
|
if verdict.intVal == 0:
|
||||||
localError(result.info, "type class predicate failed")
|
localError(result.info, "type class predicate failed")
|
||||||
|
of tyUnknown: continue
|
||||||
|
else: discard
|
||||||
if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
|
if n.sons[i].typ == enforceVoidContext or usesResult(n.sons[i]):
|
||||||
voidContext = true
|
voidContext = true
|
||||||
n.typ = enforceVoidContext
|
n.typ = enforceVoidContext
|
||||||
|
|
|
||||||
|
|
@ -781,9 +781,11 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
result = newTypeS(tyGenericInvokation, c)
|
result = newTypeS(tyGenericInvokation, c)
|
||||||
result.rawAddSon(paramType)
|
result.rawAddSon(paramType)
|
||||||
|
|
||||||
for i in 0 .. paramType.sonsLen - 2:
|
for i in 0 .. paramType.sonsLen - 2:
|
||||||
result.rawAddSon newTypeS(tyAnything, c)
|
let dummyType = if paramType.sons[i].kind == tyStatic: tyUnknown
|
||||||
# result.rawAddSon(copyType(paramType.sons[i], getCurrOwner(), true))
|
else: tyAnything
|
||||||
|
result.rawAddSon newTypeS(dummyType, c)
|
||||||
|
|
||||||
if paramType.lastSon.kind == tyUserTypeClass:
|
if paramType.lastSon.kind == tyUserTypeClass:
|
||||||
result.kind = tyUserTypeClassInst
|
result.kind = tyUserTypeClassInst
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,9 @@ type
|
||||||
bindings*: TIdTable # maps types to types
|
bindings*: TIdTable # maps types to types
|
||||||
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
||||||
# for example
|
# 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
|
genericConverter*: bool # true if a generic converter needs to
|
||||||
# be instantiated
|
# be instantiated
|
||||||
coerceDistincts*: bool # this is an explicit coercion that can strip away
|
coerceDistincts*: bool # this is an explicit coercion that can strip away
|
||||||
|
|
@ -66,6 +68,8 @@ const
|
||||||
|
|
||||||
proc markUsed*(info: TLineInfo, s: PSym)
|
proc markUsed*(info: TLineInfo, s: PSym)
|
||||||
|
|
||||||
|
template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
|
||||||
|
|
||||||
proc initCandidateAux(ctx: PContext,
|
proc initCandidateAux(ctx: PContext,
|
||||||
c: var TCandidate, callee: PType) {.inline.} =
|
c: var TCandidate, callee: PType) {.inline.} =
|
||||||
c.c = ctx
|
c.c = ctx
|
||||||
|
|
@ -465,9 +469,23 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||||
var
|
var
|
||||||
typeParamName = ff.base.sons[i-1].sym.name
|
typeParamName = ff.base.sons[i-1].sym.name
|
||||||
typ = ff.sons[i]
|
typ = ff.sons[i]
|
||||||
param = newSym(skType, typeParamName, body.sym, body.sym.info)
|
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)
|
param.typ = makeTypeDesc(c, typ)
|
||||||
|
|
||||||
addDecl(c, param)
|
addDecl(c, param)
|
||||||
|
|
||||||
for param in body.n[0]:
|
for param in body.n[0]:
|
||||||
|
|
@ -1067,7 +1085,7 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
|
||||||
c: PContext): PNode =
|
c: PContext): PNode =
|
||||||
result = newNodeI(kind, arg.info)
|
result = newNodeI(kind, arg.info)
|
||||||
if containsGenericType(f):
|
if containsGenericType(f):
|
||||||
if not m.proxyMatch:
|
if not m.hasFauxMatch:
|
||||||
result.typ = getInstantiatedType(c, arg, m, f)
|
result.typ = getInstantiatedType(c, arg, m, f)
|
||||||
else:
|
else:
|
||||||
result.typ = errorType(c)
|
result.typ = errorType(c)
|
||||||
|
|
@ -1246,9 +1264,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
|
||||||
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
|
||||||
of isNone:
|
of isNone:
|
||||||
# do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
|
# 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)
|
inc(m.genericMatches)
|
||||||
m.proxyMatch = true
|
m.fauxMatch = a.kind
|
||||||
return copyTree(arg)
|
return copyTree(arg)
|
||||||
result = userConvMatch(c, m, f, a, arg)
|
result = userConvMatch(c, m, f, a, arg)
|
||||||
# check for a base type match, which supports varargs[T] without []
|
# check for a base type match, which supports varargs[T] without []
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
discard """
|
discard """
|
||||||
output: "Sortable\nSortable\nContainer"
|
output: '''Sortable
|
||||||
|
Sortable
|
||||||
|
Container
|
||||||
|
true
|
||||||
|
true
|
||||||
|
false
|
||||||
|
false
|
||||||
|
false
|
||||||
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import typetraits
|
import typetraits
|
||||||
|
|
@ -41,3 +49,20 @@ proc y(x: TObj): int = 10
|
||||||
proc testFoo(x: TFoo) = discard
|
proc testFoo(x: TFoo) = discard
|
||||||
testFoo(TObj(x: 10))
|
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]
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue