mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 05:50:30 +00:00
support derived values in non-generic user type classes
This commit is contained in:
@@ -428,6 +428,7 @@ const
|
||||
tyAnd, tyOr, tyNot, tyAnything}
|
||||
|
||||
tyMetaTypes* = {tyGenericParam, tyTypeDesc, tyExpr} + tyTypeClasses
|
||||
tyUserTypeClasses* = {tyUserTypeClass, tyUserTypeClassInst}
|
||||
|
||||
type
|
||||
TTypeKinds* = set[TTypeKind]
|
||||
@@ -471,6 +472,8 @@ type
|
||||
# can be attached to generic procs with free standing
|
||||
# type parameters: e.g. proc foo[T]()
|
||||
# depends on unresolved static params.
|
||||
tfResolved # marks a user type class, after it has been bound to a
|
||||
# concrete type (lastSon becomes the concrete type)
|
||||
tfRetType, # marks return types in proc (used to detect type classes
|
||||
# used as return types for return type inference)
|
||||
tfCapturesEnv, # whether proc really captures some environment
|
||||
|
||||
@@ -890,7 +890,7 @@ proc genSeqElem(p: BProc, x, y: PNode, d: var TLoc) =
|
||||
rfmt(nil, "$1->data[$2]", rdLoc(a), rdCharLoc(b)), a.s)
|
||||
|
||||
proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
|
||||
var ty = skipTypes(n.sons[0].typ, abstractVarRange)
|
||||
var ty = skipTypes(n.sons[0].typ, abstractVarRange + tyUserTypeClasses)
|
||||
if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.lastSon, abstractVarRange)
|
||||
case ty.kind
|
||||
of tyArray: genArrayElem(p, n.sons[0], n.sons[1], d)
|
||||
@@ -1359,7 +1359,7 @@ proc genDollar(p: BProc, n: PNode, d: var TLoc, frmt: string) =
|
||||
proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
var a = e.sons[1]
|
||||
if a.kind == nkHiddenAddr: a = a.sons[0]
|
||||
let typ = skipTypes(a.typ, abstractVar)
|
||||
var typ = skipTypes(a.typ, abstractVar + tyUserTypeClasses)
|
||||
case typ.kind
|
||||
of tyOpenArray, tyVarargs:
|
||||
if op == mHigh: unaryExpr(p, e, d, "($1Len_0-1)")
|
||||
|
||||
@@ -136,6 +136,7 @@ proc isCastable(dst, src: PType): bool =
|
||||
# castableTypeKinds = {tyInt, tyPtr, tyRef, tyCstring, tyString,
|
||||
# tySequence, tyPointer, tyNil, tyOpenArray,
|
||||
# tyProc, tySet, tyEnum, tyBool, tyChar}
|
||||
let src = src.skipTypes(tyUserTypeClasses)
|
||||
if skipTypes(dst, abstractInst-{tyOpenArray}).kind == tyOpenArray:
|
||||
return false
|
||||
if skipTypes(src, abstractInst-{tyTypeDesc}).kind == tyTypeDesc:
|
||||
@@ -908,28 +909,14 @@ proc makeDeref(n: PNode): PNode =
|
||||
t = skipTypes(baseTyp, {tyGenericInst, tyAlias})
|
||||
|
||||
const
|
||||
tyTypeParamsHolders = {tyGenericInst, tyUserTypeClassInst, tyCompositeTypeClass}
|
||||
tyTypeParamsHolders = {tyGenericInst, tyCompositeTypeClass,
|
||||
tyUserTypeClass, tyUserTypeClassInst}
|
||||
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]
|
||||
if tParam.sym.name.id == paramName.id:
|
||||
let rawTyp = ty.sons[s + 1]
|
||||
if rawTyp.kind == tyStatic:
|
||||
return rawTyp.n
|
||||
else:
|
||||
let foundTyp = makeTypeDesc(c, rawTyp)
|
||||
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
|
||||
|
||||
if ty.n != nil:
|
||||
for statement in ty.n:
|
||||
if typ.kind in {tyUserTypeClass, tyUserTypeClassInst}:
|
||||
for statement in typ.n:
|
||||
case statement.kind
|
||||
of nkTypeSection:
|
||||
for def in statement:
|
||||
@@ -939,7 +926,7 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||
# 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)
|
||||
return newSymNode(copySym(def[0].sym).linkTo(foundType), info)
|
||||
|
||||
of nkConstSection:
|
||||
for def in statement:
|
||||
@@ -948,6 +935,20 @@ proc readTypeParameter(c: PContext, typ: PType,
|
||||
|
||||
else:
|
||||
discard
|
||||
|
||||
if typ.kind != tyUserTypeClass:
|
||||
let ty = if typ.kind == tyCompositeTypeClass: typ.sons[1].skipGenericAlias
|
||||
else: typ.skipGenericAlias
|
||||
let tbody = ty.sons[0]
|
||||
for s in countup(0, tbody.len-2):
|
||||
let tParam = tbody.sons[s]
|
||||
if tParam.sym.name.id == paramName.id:
|
||||
let rawTyp = ty.sons[s + 1]
|
||||
if rawTyp.kind == tyStatic:
|
||||
return rawTyp.n
|
||||
else:
|
||||
let foundTyp = makeTypeDesc(c, rawTyp)
|
||||
return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
|
||||
|
||||
return nil
|
||||
|
||||
|
||||
@@ -1197,22 +1197,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
|
||||
else:
|
||||
return isNone
|
||||
|
||||
of tyUserTypeClass:
|
||||
considerPreviousT:
|
||||
of tyUserTypeClassInst, tyUserTypeClass:
|
||||
if f.isResolvedUserTypeClass:
|
||||
result = typeRel(c, f.lastSon, a)
|
||||
else:
|
||||
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:
|
||||
var matched = matchUserTypeClass(c.c, c, f, aOrig)
|
||||
if matched != nil:
|
||||
matched.sons.add a
|
||||
put(c.bindings, f, matched)
|
||||
bindConcreteTypeToUserTypeClass(matched, a)
|
||||
put(c, f, matched)
|
||||
result = isGeneric
|
||||
else:
|
||||
result = isNone
|
||||
|
||||
@@ -63,7 +63,7 @@ const
|
||||
abstractVarRange* = {tyGenericInst, tyRange, tyVar, tyDistinct, tyOrdinal,
|
||||
tyTypeDesc, tyAlias, tyInferred}
|
||||
abstractInst* = {tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc, tyAlias,
|
||||
tyInferred}
|
||||
tyInferred} + tyTypeClasses
|
||||
skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias,
|
||||
tyInferred}
|
||||
# typedescX is used if we're sure tyTypeDesc should be included (or skipped)
|
||||
@@ -417,6 +417,13 @@ const
|
||||
|
||||
const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
|
||||
|
||||
template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
|
||||
tc.sons.safeAdd concrete
|
||||
tc.flags.incl tfResolved
|
||||
|
||||
template isResolvedUserTypeClass*(t: PType): bool =
|
||||
tfResolved in t.flags
|
||||
|
||||
proc addTypeFlags(name: var string, typ: PType) {.inline.} =
|
||||
if tfNotNil in typ.flags: name.add(" not nil")
|
||||
|
||||
@@ -461,6 +468,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
|
||||
if t.n != nil: result.add "(" & renderTree(t.n) & ")"
|
||||
of tyUserTypeClass:
|
||||
internalAssert t.sym != nil and t.sym.owner != nil
|
||||
if t.isResolvedUserTypeClass: return typeToString(t.lastSon)
|
||||
return t.sym.owner.name.s
|
||||
of tyBuiltInTypeClass:
|
||||
result = case t.base.kind:
|
||||
@@ -1314,12 +1322,15 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
|
||||
result = align(result, a)
|
||||
of tyGenericInst, tyDistinct, tyGenericBody, tyAlias:
|
||||
result = computeSizeAux(lastSon(typ), a)
|
||||
of tyTypeClasses:
|
||||
result = if typ.isResolvedUserTypeClass: computeSizeAux(typ.lastSon, a)
|
||||
else: szUnknownSize
|
||||
of tyTypeDesc:
|
||||
result = computeSizeAux(typ.base, a)
|
||||
of tyForward: return szIllegalRecursion
|
||||
of tyStatic:
|
||||
if typ.n != nil: result = computeSizeAux(lastSon(typ), a)
|
||||
else: result = szUnknownSize
|
||||
result = if typ.n != nil: computeSizeAux(typ.lastSon, a)
|
||||
else: szUnknownSize
|
||||
else:
|
||||
#internalError("computeSizeAux()")
|
||||
result = szUnknownSize
|
||||
@@ -1492,9 +1503,6 @@ proc isEmptyContainer*(t: PType): bool =
|
||||
of tyGenericInst, tyAlias: result = isEmptyContainer(t.lastSon)
|
||||
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 =
|
||||
# param: openArray[string] = []
|
||||
# [] is an array constructor of length 0 of type string!
|
||||
|
||||
@@ -175,7 +175,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
|
||||
result.add mapTypeToAst(t.sons[i], info)
|
||||
else:
|
||||
result = mapTypeToAstX(t.lastSon, info, inst, allowRecursion)
|
||||
of tyGenericBody, tyOrdinal, tyUserTypeClassInst:
|
||||
of tyGenericBody, tyOrdinal:
|
||||
result = mapTypeToAst(t.lastSon, info)
|
||||
of tyDistinct:
|
||||
if inst:
|
||||
@@ -285,9 +285,12 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
|
||||
of tyProxy: result = atomicType("error", mNone)
|
||||
of tyBuiltInTypeClass:
|
||||
result = mapTypeToBracket("builtinTypeClass", mNone, t, info)
|
||||
of tyUserTypeClass:
|
||||
result = mapTypeToBracket("concept", mNone, t, info)
|
||||
result.add t.n.copyTree
|
||||
of tyUserTypeClass, tyUserTypeClassInst:
|
||||
if t.isResolvedUserTypeClass:
|
||||
result = mapTypeToAst(t.lastSon, info)
|
||||
else:
|
||||
result = mapTypeToBracket("concept", mNone, t, info)
|
||||
result.add t.n.copyTree
|
||||
of tyCompositeTypeClass:
|
||||
result = mapTypeToBracket("compositeTypeClass", mNone, t, info)
|
||||
of tyAnd: result = mapTypeToBracket("and", mAnd, t, info)
|
||||
|
||||
@@ -2,6 +2,8 @@ discard """
|
||||
output: '''Sortable
|
||||
Sortable
|
||||
Container
|
||||
TObj
|
||||
int
|
||||
'''
|
||||
"""
|
||||
|
||||
@@ -20,7 +22,7 @@ type
|
||||
C.len is Ordinal
|
||||
for v in items(C):
|
||||
v.type is tuple|object
|
||||
|
||||
|
||||
proc foo(c: ObjectContainer) =
|
||||
echo "Container"
|
||||
|
||||
@@ -79,6 +81,9 @@ proc ptrproc(x: ptr TObj, y: string) = discard
|
||||
proc staticproc(x: static[TObj]) = discard
|
||||
proc typeproc(t: type TObj) = discard
|
||||
|
||||
proc testFoo(x: TFoo) = discard
|
||||
proc testFoo(x: TFoo) =
|
||||
echo x.TypeName
|
||||
echo x.MappedType.name
|
||||
|
||||
testFoo(TObj(x: 10))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user