support for accessing types and consts defined in concepts with the dot operator

This commit is contained in:
Zahary Karadjov 2016-07-30 13:21:14 +03:00
commit 33f4e69759
3 changed files with 65 additions and 16 deletions

View file

@ -912,11 +912,14 @@ const
tyTypeParamsHolders = {tyGenericInst, tyUserTypeClassInst, 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 in {tyGenericInst, tyUserTypeClassInst}: 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]
for s in countup(0, tbody.len-2): for s in countup(0, tbody.len-2):
let tParam = tbody.sons[s] let tParam = tbody.sons[s]
@ -927,7 +930,29 @@ proc readTypeParameter(c: PContext, typ: PType,
else: else:
let foundTyp = makeTypeDesc(c, rawTyp) let foundTyp = makeTypeDesc(c, rawTyp)
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info) return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
#echo "came here: returned nil"
if ty.n != nil:
for statement in ty.n:
case statement.kind
of nkTypeSection:
for def in statement:
if def[0].sym.name.id == paramName.id:
# XXX: Instead of lifting the section type to a typedesc
# here, we could try doing it earlier in semTypeSection.
# This seems semantically correct and then we'll be able
# to return the section symbol directly here
let foundType = makeTypeDesc(c, def[2].typ)
return newSymNode(copySym(def[2].sym).linkTo(foundType), info)
of nkConstSection:
for def in statement:
if def[0].sym.name.id == paramName.id:
return def[2]
else:
discard
return nil
proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
let s = getGenSym(c, sym) let s = getGenSym(c, sym)

View file

@ -572,11 +572,11 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
result = isNone result = isNone
proc matchUserTypeClass*(c: PContext, m: var TCandidate, proc matchUserTypeClass*(c: PContext, m: var TCandidate,
ff, a: PType): TTypeRelation = ff, a: PType): PType =
var body = ff.skipTypes({tyUserTypeClassInst}) var body = ff.skipTypes({tyUserTypeClassInst})
if c.inTypeClass > 4: if c.inTypeClass > 4:
localError(body.n[3].info, $body.n[3] & " too nested for type matching") localError(body.n[3].info, $body.n[3] & " too nested for type matching")
return isNone return nil
openScope(c) openScope(c)
inc c.inTypeClass inc c.inTypeClass
@ -636,7 +636,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
#echo "B ", dummyName.ident.s, " ", typeToString(dummyType), " ", dummyparam.kind #echo "B ", dummyName.ident.s, " ", typeToString(dummyType), " ", dummyparam.kind
var checkedBody = c.semTryExpr(c, body.n[3].copyTree) var checkedBody = c.semTryExpr(c, body.n[3].copyTree)
if checkedBody == nil: return isNone if checkedBody == nil: return nil
# The inferrable type params have been identified during the semTryExpr above. # 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 # We need to put them in the current sigmatch's binding table in order for them
@ -644,7 +644,12 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
for p in typeParams: for p in typeParams:
put(m.bindings, p[1], p[0].typ) put(m.bindings, p[1], p[0].typ)
return isGeneric if ff.kind == tyUserTypeClassInst:
result = generateTypeInstance(c, m.bindings, m.call.info, ff)
else:
result = copyType(ff, ff.owner, true)
result.n = checkedBody
proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool = proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool =
if rules.kind == nkWith: if rules.kind == nkWith:
@ -1130,17 +1135,23 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyUserTypeClass: of tyUserTypeClass:
considerPreviousT: considerPreviousT:
result = matchUserTypeClass(c.c, c, f, aOrig) var matched = matchUserTypeClass(c.c, c, f, aOrig)
if result == isGeneric: if matched != nil:
# TODO, make user type classes skipable too
put(c, f, a) put(c, f, a)
result = isGeneric
else:
result = isNone
of tyUserTypeClassInst: of tyUserTypeClassInst:
considerPreviousT: considerPreviousT:
result = matchUserTypeClass(c.c, c, f, aOrig) var matched = matchUserTypeClass(c.c, c, f, aOrig)
if result == isGeneric: if matched != nil:
var fWithResolvedParams = generateTypeInstance(c.c, c.bindings, c.call.info, f) matched.sons.add a
fWithResolvedParams.sons.add a put(c.bindings, f, matched)
put(c.bindings, f, fWithResolvedParams) result = isGeneric
else:
result = isNone
of tyCompositeTypeClass: of tyCompositeTypeClass:
considerPreviousT: considerPreviousT:

View file

@ -2,11 +2,15 @@ discard """
output: "20\n10" output: "20\n10"
msg: ''' msg: '''
INFERRED int INFERRED int
VALUE TYPE int
VALUE TYPE NAME INT
IMPLICIT INFERRED int int IMPLICIT INFERRED int int
IMPLICIT VALUE TYPE int int
IMPLICIT VALUE TYPE NAME INT INT
''' '''
""" """
import typetraits import typetraits, strutils
template reject(e: expr) = template reject(e: expr) =
static: assert(not compiles(e)) static: assert(not compiles(e))
@ -26,14 +30,23 @@ type
s.push(T) s.push(T)
s.pop() is T s.pop() is T
type ValueType = T
const ValueTypeName = T.name.toUpper
proc genericAlgorithm[T](s: var Stack[T], y: T) = proc genericAlgorithm[T](s: var Stack[T], y: T) =
static: echo "INFERRED ", T.name static:
echo "INFERRED ", T.name
echo "VALUE TYPE ", s.ValueType.name
echo "VALUE TYPE NAME ", s.ValueTypeName
s.push(y) s.push(y)
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
echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name
echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", s.ValueTypeName
return s.pop() return s.pop()