support for accessing the inferred concept type params with the dot operator

This commit is contained in:
Zahary Karadjov 2016-07-29 18:12:05 +03:00
commit eab1d0cc02
6 changed files with 24 additions and 7 deletions

View file

@ -101,6 +101,8 @@ proc getUniqueType*(key: PType): PType =
gCanonicalTypes[k] = key gCanonicalTypes[k] = key
result = key result = key
of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor: of tyTypeDesc, tyTypeClasses, tyGenericParam, tyFromExpr, tyFieldAccessor:
if key.isResolvedUserTypeClass:
return getUniqueType(lastSon(key))
if key.sym != nil: if key.sym != nil:
internalError(key.sym.info, "metatype not eliminated") internalError(key.sym.info, "metatype not eliminated")
else: else:

View file

@ -909,12 +909,12 @@ proc makeDeref(n: PNode): PNode =
t = skipTypes(baseTyp, {tyGenericInst, tyAlias}) t = skipTypes(baseTyp, {tyGenericInst, tyAlias})
const const
tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass} tyTypeParamsHolders = {tyGenericInst, tyUserTypeClassInst, tyCompositeTypeClass}
tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias} tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias}
proc readTypeParameter(c: PContext, typ: PType, proc readTypeParameter(c: PContext, typ: PType,
paramName: PIdent, info: TLineInfo): PNode = paramName: PIdent, info: TLineInfo): PNode =
let ty = if typ.kind == tyGenericInst: typ.skipGenericAlias let ty = if typ.kind in {tyGenericInst, tyUserTypeClassInst}: typ.skipGenericAlias
else: (internalAssert(typ.kind == tyCompositeTypeClass); else: (internalAssert(typ.kind == tyCompositeTypeClass);
typ.sons[1].skipGenericAlias) typ.sons[1].skipGenericAlias)
let tbody = ty.sons[0] let tbody = ty.sons[0]

View file

@ -447,7 +447,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
of tyUserTypeClass: of tyUserTypeClass:
result = t result = t
of tyGenericInst: of tyGenericInst, tyUserTypeClassInst:
bailout() bailout()
result = instCopyType(cl, t) result = instCopyType(cl, t)
idTablePut(cl.localCache, t, result) idTablePut(cl.localCache, t, result)

View file

@ -642,7 +642,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
# We need to put them in the current sigmatch's binding table in order for them # 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 # to be resolvable while matching the rest of the parameters
for p in typeParams: for p in typeParams:
put(m.bindings, p[0].typ, p[1]) put(m.bindings, p[1], p[0].typ)
return isGeneric return isGeneric
@ -716,6 +716,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
tyGenericInst, tyGenericParam} + tyTypeClasses: tyGenericInst, tyGenericParam} + tyTypeClasses:
return typeRel(c, f, lastSon(a)) return typeRel(c, f, lastSon(a))
if a.isResolvedUserTypeClass:
return typeRel(c, f, a.lastSon)
template bindingRet(res) = template bindingRet(res) =
if doBind: if doBind:
let bound = aOrig.skipTypes({tyRange}).skipIntLit let bound = aOrig.skipTypes({tyRange}).skipIntLit
@ -1125,12 +1128,20 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
else: else:
return isNone return isNone
of tyUserTypeClass, tyUserTypeClassInst: of tyUserTypeClass:
considerPreviousT: considerPreviousT:
result = matchUserTypeClass(c.c, c, f, aOrig) result = matchUserTypeClass(c.c, c, f, aOrig)
if result == isGeneric: if result == isGeneric:
put(c, f, a) put(c, f, a)
of tyUserTypeClassInst:
considerPreviousT:
result = matchUserTypeClass(c.c, c, f, aOrig)
if result == isGeneric:
var fWithResolvedParams = generateTypeInstance(c.c, c.bindings, c.call.info, f)
fWithResolvedParams.sons.add a
put(c.bindings, f, fWithResolvedParams)
of tyCompositeTypeClass: of tyCompositeTypeClass:
considerPreviousT: considerPreviousT:
let roota = a.skipGenericAlias let roota = a.skipGenericAlias
@ -1397,7 +1408,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
arg = argSemantized arg = argSemantized
argType = argType argType = argType
c = m.c c = m.c
if inferTypeClassParam(c, f, argType): if inferTypeClassParam(c, f, argType):
return argSemantized return argSemantized

View file

@ -1485,6 +1485,9 @@ proc isEmptyContainer*(t: PType): bool =
of tyGenericInst, tyAlias: result = isEmptyContainer(t.lastSon) of tyGenericInst, tyAlias: result = isEmptyContainer(t.lastSon)
else: result = false else: result = false
proc isResolvedUserTypeClass*(t: PType): bool =
t.kind in {tyUserTypeClassInst} and t.base.sonsLen == t.sonsLen - 2
proc takeType*(formal, arg: PType): PType = proc takeType*(formal, arg: PType): PType =
# param: openArray[string] = [] # param: openArray[string] = []
# [] is an array constructor of length 0 of type string! # [] is an array constructor of length 0 of type string!

View file

@ -2,6 +2,7 @@ discard """
output: "20\n10" output: "20\n10"
msg: ''' msg: '''
INFERRED int INFERRED int
IMPLICIT INFERRED int int
''' '''
""" """
@ -32,7 +33,7 @@ proc genericAlgorithm[T](s: var Stack[T], y: T) =
echo s.pop echo s.pop
proc implicitGeneric(s: var Stack): auto = proc implicitGeneric(s: var Stack): auto =
# static: echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name static: echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
return s.pop() return s.pop()