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
parent eab1d0cc02
commit 33f4e69759
3 changed files with 65 additions and 16 deletions

View File

@@ -912,11 +912,14 @@ const
tyTypeParamsHolders = {tyGenericInst, tyUserTypeClassInst, tyCompositeTypeClass}
tyDotOpTransparent = {tyVar, tyPtr, tyRef, tyAlias}
proc readTypeParameter(c: PContext, typ: PType,
paramName: PIdent, info: TLineInfo): PNode =
let ty = if typ.kind in {tyGenericInst, tyUserTypeClassInst}: typ.skipGenericAlias
else: (internalAssert(typ.kind == tyCompositeTypeClass);
typ.sons[1].skipGenericAlias)
let tbody = ty.sons[0]
for s in countup(0, tbody.len-2):
let tParam = tbody.sons[s]
@@ -927,7 +930,29 @@ proc readTypeParameter(c: PContext, typ: PType,
else:
let foundTyp = makeTypeDesc(c, rawTyp)
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 =
let s = getGenSym(c, sym)

View File

@@ -572,11 +572,11 @@ proc typeRangeRel(f, a: PType): TTypeRelation {.noinline.} =
result = isNone
proc matchUserTypeClass*(c: PContext, m: var TCandidate,
ff, a: PType): TTypeRelation =
ff, a: PType): PType =
var body = ff.skipTypes({tyUserTypeClassInst})
if c.inTypeClass > 4:
localError(body.n[3].info, $body.n[3] & " too nested for type matching")
return isNone
return nil
openScope(c)
inc c.inTypeClass
@@ -636,7 +636,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
#echo "B ", dummyName.ident.s, " ", typeToString(dummyType), " ", dummyparam.kind
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.
# 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:
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 =
if rules.kind == nkWith:
@@ -1130,17 +1135,23 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
of tyUserTypeClass:
considerPreviousT:
result = matchUserTypeClass(c.c, c, f, aOrig)
if result == isGeneric:
var matched = matchUserTypeClass(c.c, c, f, aOrig)
if matched != nil:
# TODO, make user type classes skipable too
put(c, f, a)
result = isGeneric
else:
result = isNone
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)
var matched = matchUserTypeClass(c.c, c, f, aOrig)
if matched != nil:
matched.sons.add a
put(c.bindings, f, matched)
result = isGeneric
else:
result = isNone
of tyCompositeTypeClass:
considerPreviousT:
@@ -1408,7 +1419,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
arg = argSemantized
argType = argType
c = m.c
if inferTypeClassParam(c, f, argType):
return argSemantized

View File

@@ -2,11 +2,15 @@ discard """
output: "20\n10"
msg: '''
INFERRED int
VALUE TYPE int
VALUE TYPE NAME 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) =
static: assert(not compiles(e))
@@ -26,14 +30,23 @@ type
s.push(T)
s.pop() is T
type ValueType = T
const ValueTypeName = T.name.toUpper
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)
echo s.pop
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()