support for accessing types and consts defined in concepts with the dot operator
This commit is contained in:
parent
eab1d0cc02
commit
33f4e69759
3 changed files with 65 additions and 16 deletions
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue