concept type params inference working in basic examples

This commit is contained in:
Zahary Karadjov
2016-07-29 04:56:14 +03:00
parent 0d8a503e45
commit 66e0f0e19c
5 changed files with 93 additions and 2 deletions

View File

@@ -482,6 +482,7 @@ type
tfHasStatic
tfGenericTypeParam
tfImplicitTypeParam
tfInferrableTypeClassTypeParam
tfWildcard # consider a proc like foo[T, I](x: Type[T, I])
# T and I here can bind to both typedesc and static types
# before this is determined, we'll consider them to be a

View File

@@ -318,7 +318,9 @@ proc isOpImpl(c: PContext, n: PNode): PNode =
else:
result = newIntNode(nkIntLit, 0)
else:
var t2 = n[2].typ.skipTypes({tyTypeDesc})
var rhsOrigType = n[2].typ
discard inferTypeClassParam(c, t1, rhsOrigType)
var t2 = rhsOrigType.skipTypes({tyTypeDesc})
maybeLiftType(t2, c, n.info)
var m: TCandidate
initCandidate(c, m, t2)

View File

@@ -883,7 +883,8 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
for i in 1 .. <paramType.len:
let lifted = liftingWalk(paramType.sons[i])
if lifted != nil: paramType.sons[i] = lifted
when false:
if paramType.base.lastSon.kind == tyUserTypeClass:
let expanded = instGenericContainer(c, info, paramType,
allowMetaTypes = true)
result = liftingWalk(expanded, true)

View File

@@ -585,6 +585,8 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
dec c.inTypeClass
closeScope(c)
var typeParams: seq[(PSym, PType)]
if ff.kind == tyUserTypeClassInst:
for i in 1 .. <(ff.len - 1):
var
@@ -607,7 +609,12 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
param = paramSym skType
param.typ = makeTypeDesc(c, typ)
if typ.isMetaType:
param.typ.flags.incl tfInferrableTypeClassTypeParam
addDecl(c, param)
typeParams.safeAdd((param, typ))
#echo "A ", param.name.s, " ", typeToString(param.typ), " ", param.kind
for param in body.n[0]:
@@ -630,6 +637,13 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
var checkedBody = c.semTryExpr(c, body.n[3].copyTree)
if checkedBody == nil: return isNone
# The inferrable type params have been identified during the semTryExpr above.
# We need to put them in the current sigmatch's binding table in order for them
# to be resolvable while matching the rest of the parameters
for p in typeParams:
put(m.bindings, p[0].typ, p[1])
return isGeneric
proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool =
@@ -1355,6 +1369,27 @@ proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) =
of isEqual: inc(m.exactMatches)
of isNone: discard
proc skipToInferrableParam(tt: PType): PType =
var t = tt
while t != nil:
if tfInferrableTypeClassTypeParam in t.flags:
return t
if t.sonsLen > 0 and t.kind == tyTypeDesc:
t = t.base
else:
return nil
return nil
proc inferTypeClassParam*(c: PContext, f, a: PType): bool =
if c.inTypeClass == 0: return false
var inferrableType = a.skipToInferrableParam
if inferrableType == nil: return false
inferrableType.assignType f
return true
proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
argSemantized, argOrig: PNode): PNode =
var
@@ -1363,6 +1398,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
argType = argType
c = m.c
if inferTypeClassParam(c, f, argType):
return argSemantized
if tfHasStatic in fMaybeStatic.flags:
# XXX: When implicit statics are the default
# this will be done earlier - we just have to

View File

@@ -0,0 +1,49 @@
discard """
output: "20\n10"
msg: '''
INFERRED int
'''
"""
import typetraits
template reject(e: expr) =
static: assert(not compiles(e))
type
ArrayStack = object
data: seq[int]
proc push(s: var ArrayStack, item: int) =
s.data.add item
proc pop(s: var ArrayStack): int =
return s.data.pop()
type
Stack[T] = concept var s
s.push(T)
s.pop() is T
proc genericAlgorithm[T](s: var Stack[T], y: T) =
static: echo "INFERRED ", T.name
s.push(y)
echo s.pop
proc implicitGeneric(s: var Stack): auto =
# static: echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
return s.pop()
var s = ArrayStack(data: @[])
s.push 10
s.genericAlgorithm 20
echo s.implicitGeneric
reject s.genericAlgorithm "x"
reject s.genericAlgorithm 1.0
reject "str".implicitGeneric
reject implicitGeneric(10)