allow generic typedesc field access (#12220)
Co-authored-by: Clyybber <darkmine956@gmail.com>
This commit is contained in:
parent
4476d8a2e0
commit
ba0af0f827
2 changed files with 61 additions and 56 deletions
|
|
@ -1271,6 +1271,54 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
|
||||||
onUse(info, s)
|
onUse(info, s)
|
||||||
result = newSymNode(s, info)
|
result = newSymNode(s, info)
|
||||||
|
|
||||||
|
proc tryReadingGenericParam(c: PContext, n: PNode, i: PIdent, t: PType): PNode =
|
||||||
|
case t.kind
|
||||||
|
of tyTypeParamsHolders:
|
||||||
|
result = readTypeParameter(c, t, i, n.info)
|
||||||
|
if result == c.graph.emptyNode:
|
||||||
|
result = n
|
||||||
|
n.typ = makeTypeFromExpr(c, n.copyTree)
|
||||||
|
of tyUserTypeClasses:
|
||||||
|
if t.isResolvedUserTypeClass:
|
||||||
|
result = readTypeParameter(c, t, i, n.info)
|
||||||
|
else:
|
||||||
|
n.typ = makeTypeFromExpr(c, copyTree(n))
|
||||||
|
result = n
|
||||||
|
of tyGenericParam, tyAnything:
|
||||||
|
n.typ = makeTypeFromExpr(c, copyTree(n))
|
||||||
|
result = n
|
||||||
|
else:
|
||||||
|
discard
|
||||||
|
|
||||||
|
proc tryReadingTypeField(c: PContext, n: PNode, i: PIdent, ty: PType): PNode =
|
||||||
|
var ty = ty.skipTypes(tyDotOpTransparent)
|
||||||
|
case ty.kind
|
||||||
|
of tyEnum:
|
||||||
|
# look up if the identifier belongs to the enum:
|
||||||
|
var f = PSym(nil)
|
||||||
|
while ty != nil:
|
||||||
|
f = getSymFromList(ty.n, i)
|
||||||
|
if f != nil: break
|
||||||
|
ty = ty.sons[0] # enum inheritance
|
||||||
|
if f != nil:
|
||||||
|
result = newSymNode(f)
|
||||||
|
result.info = n.info
|
||||||
|
result.typ = ty
|
||||||
|
markUsed(c, n.info, f)
|
||||||
|
onUse(n.info, f)
|
||||||
|
of tyObject, tyTuple:
|
||||||
|
if ty.n != nil and ty.n.kind == nkRecList:
|
||||||
|
let field = lookupInRecord(ty.n, i)
|
||||||
|
if field != nil:
|
||||||
|
n.typ = makeTypeDesc(c, field.typ)
|
||||||
|
result = n
|
||||||
|
of tyGenericInst:
|
||||||
|
result = tryReadingTypeField(c, n, i, ty.lastSon)
|
||||||
|
if result == nil:
|
||||||
|
result = tryReadingGenericParam(c, n, i, ty)
|
||||||
|
else:
|
||||||
|
result = tryReadingGenericParam(c, n, i, ty)
|
||||||
|
|
||||||
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
## returns nil if it's not a built-in field access
|
## returns nil if it's not a built-in field access
|
||||||
checkSonsLen(n, 2, c.config)
|
checkSonsLen(n, 2, c.config)
|
||||||
|
|
@ -1301,28 +1349,6 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
var f: PSym = nil
|
var f: PSym = nil
|
||||||
result = nil
|
result = nil
|
||||||
|
|
||||||
template tryReadingGenericParam(t: PType) =
|
|
||||||
case t.kind
|
|
||||||
of tyTypeParamsHolders:
|
|
||||||
result = readTypeParameter(c, t, i, n.info)
|
|
||||||
if result == c.graph.emptyNode:
|
|
||||||
result = n
|
|
||||||
n.typ = makeTypeFromExpr(c, n.copyTree)
|
|
||||||
return
|
|
||||||
of tyUserTypeClasses:
|
|
||||||
if t.isResolvedUserTypeClass:
|
|
||||||
return readTypeParameter(c, t, i, n.info)
|
|
||||||
else:
|
|
||||||
n.typ = makeTypeFromExpr(c, copyTree(n))
|
|
||||||
return n
|
|
||||||
of tyGenericParam, tyAnything:
|
|
||||||
n.typ = makeTypeFromExpr(c, copyTree(n))
|
|
||||||
return n
|
|
||||||
else:
|
|
||||||
discard
|
|
||||||
|
|
||||||
var argIsType = false
|
|
||||||
|
|
||||||
if ty.kind == tyTypeDesc:
|
if ty.kind == tyTypeDesc:
|
||||||
if ty.base.kind == tyNone:
|
if ty.base.kind == tyNone:
|
||||||
# This is a still unresolved typedesc parameter.
|
# This is a still unresolved typedesc parameter.
|
||||||
|
|
@ -1335,40 +1361,10 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
else:
|
else:
|
||||||
return nil
|
return nil
|
||||||
else:
|
else:
|
||||||
ty = ty.base
|
return tryReadingTypeField(c, n, i, ty.base)
|
||||||
argIsType = true
|
elif isTypeExpr(n.sons[0]):
|
||||||
else:
|
return tryReadingTypeField(c, n, i, ty)
|
||||||
argIsType = isTypeExpr(n[0])
|
|
||||||
|
|
||||||
if argIsType:
|
|
||||||
ty = ty.skipTypes(tyDotOpTransparent)
|
|
||||||
case ty.kind
|
|
||||||
of tyEnum:
|
|
||||||
# look up if the identifier belongs to the enum:
|
|
||||||
while ty != nil:
|
|
||||||
f = getSymFromList(ty.n, i)
|
|
||||||
if f != nil: break
|
|
||||||
ty = ty[0] # enum inheritance
|
|
||||||
if f != nil:
|
|
||||||
result = newSymNode(f)
|
|
||||||
result.info = n.info
|
|
||||||
result.typ = ty
|
|
||||||
markUsed(c, n.info, f)
|
|
||||||
onUse(n.info, f)
|
|
||||||
return
|
|
||||||
of tyObject, tyTuple:
|
|
||||||
if ty.n != nil and ty.n.kind == nkRecList:
|
|
||||||
let field = lookupInRecord(ty.n, i)
|
|
||||||
if field != nil:
|
|
||||||
n.typ = makeTypeDesc(c, field.typ)
|
|
||||||
return n
|
|
||||||
else:
|
|
||||||
tryReadingGenericParam(ty)
|
|
||||||
return
|
|
||||||
# XXX: This is probably not relevant any more
|
|
||||||
# reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
|
|
||||||
ty = n[0].typ
|
|
||||||
return nil
|
|
||||||
if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass:
|
if ty.kind in tyUserTypeClasses and ty.isResolvedUserTypeClass:
|
||||||
ty = ty.lastSon
|
ty = ty.lastSon
|
||||||
ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink})
|
ty = skipTypes(ty, {tyGenericInst, tyVar, tyLent, tyPtr, tyRef, tyOwned, tyAlias, tySink})
|
||||||
|
|
@ -1412,7 +1408,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# we didn't find any field, let's look for a generic param
|
# we didn't find any field, let's look for a generic param
|
||||||
if result == nil:
|
if result == nil:
|
||||||
let t = n[0].typ.skipTypes(tyDotOpTransparent)
|
let t = n[0].typ.skipTypes(tyDotOpTransparent)
|
||||||
tryReadingGenericParam(t)
|
result = tryReadingGenericParam(c, n, i, t)
|
||||||
|
|
||||||
proc dotTransformation(c: PContext, n: PNode): PNode =
|
proc dotTransformation(c: PContext, n: PNode): PNode =
|
||||||
if isSymChoice(n[1]):
|
if isSymChoice(n[1]):
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ method Base
|
||||||
yield Base
|
yield Base
|
||||||
yield Child
|
yield Child
|
||||||
12
|
12
|
||||||
|
1
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -41,3 +42,11 @@ type
|
||||||
MyRefType = ref MyType
|
MyRefType = ref MyType
|
||||||
|
|
||||||
echo sizeof(default(MyRefType)[])
|
echo sizeof(default(MyRefType)[])
|
||||||
|
|
||||||
|
type
|
||||||
|
Foo[T] = object
|
||||||
|
val: T
|
||||||
|
|
||||||
|
var x: Foo[int].val
|
||||||
|
inc(x)
|
||||||
|
echo x
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue