overloading resolution finally takes inheritance depth into account
This commit is contained in:
parent
483f28d1cf
commit
e2f8d91290
3 changed files with 78 additions and 66 deletions
|
|
@ -32,6 +32,7 @@ type
|
||||||
bindings*: TIdTable # maps types to types
|
bindings*: TIdTable # maps types to types
|
||||||
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
baseTypeMatch: bool # needed for conversions from T to openarray[T]
|
||||||
# for example
|
# for example
|
||||||
|
inheritancePenalty: int # to prefer closest father object type
|
||||||
|
|
||||||
TTypeRelation* = enum # order is important!
|
TTypeRelation* = enum # order is important!
|
||||||
isNone, isConvertible,
|
isNone, isConvertible,
|
||||||
|
|
@ -53,6 +54,7 @@ proc initCandidateAux(c: var TCandidate, callee: PType) {.inline.} =
|
||||||
c.callee = callee
|
c.callee = callee
|
||||||
c.call = nil
|
c.call = nil
|
||||||
c.baseTypeMatch = false
|
c.baseTypeMatch = false
|
||||||
|
c.inheritancePenalty = 0
|
||||||
|
|
||||||
proc initCandidate*(c: var TCandidate, callee: PType) =
|
proc initCandidate*(c: var TCandidate, callee: PType) =
|
||||||
initCandidateAux(c, callee)
|
initCandidateAux(c, callee)
|
||||||
|
|
@ -100,6 +102,9 @@ proc cmpCandidates*(a, b: TCandidate): int =
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
if (a.calleeScope != -1) and (b.calleeScope != -1):
|
if (a.calleeScope != -1) and (b.calleeScope != -1):
|
||||||
result = a.calleeScope - b.calleeScope
|
result = a.calleeScope - b.calleeScope
|
||||||
|
if result != 0: return
|
||||||
|
# the other way round because of other semantics:
|
||||||
|
result = b.inheritancePenalty - a.inheritancePenalty
|
||||||
|
|
||||||
proc writeMatches*(c: TCandidate) =
|
proc writeMatches*(c: TCandidate) =
|
||||||
Writeln(stdout, "exact matches: " & $c.exactMatches)
|
Writeln(stdout, "exact matches: " & $c.exactMatches)
|
||||||
|
|
@ -133,8 +138,8 @@ proc getNotFoundError*(c: PContext, n: PNode): string =
|
||||||
if candidates != "":
|
if candidates != "":
|
||||||
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
|
add(result, "\n" & msgKindToString(errButExpected) & "\n" & candidates)
|
||||||
|
|
||||||
proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation
|
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation
|
||||||
proc concreteType(mapping: TIdTable, t: PType): PType =
|
proc concreteType(c: TCandidate, t: PType): PType =
|
||||||
case t.kind
|
case t.kind
|
||||||
of tyArrayConstr:
|
of tyArrayConstr:
|
||||||
# make it an array
|
# make it an array
|
||||||
|
|
@ -146,7 +151,7 @@ proc concreteType(mapping: TIdTable, t: PType): PType =
|
||||||
of tyGenericParam:
|
of tyGenericParam:
|
||||||
result = t
|
result = t
|
||||||
while true:
|
while true:
|
||||||
result = PType(idTableGet(mapping, t))
|
result = PType(idTableGet(c.bindings, t))
|
||||||
if result == nil:
|
if result == nil:
|
||||||
break # it's ok, no match
|
break # it's ok, no match
|
||||||
# example code that triggers it:
|
# example code that triggers it:
|
||||||
|
|
@ -204,28 +209,31 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
|
||||||
elif k >= tyFloat and k <= tyFloat128: result = isConvertible
|
elif k >= tyFloat and k <= tyFloat128: result = isConvertible
|
||||||
else: result = isNone
|
else: result = isNone
|
||||||
|
|
||||||
proc isObjectSubtype(a, f: PType): bool =
|
proc isObjectSubtype(a, f: PType): int =
|
||||||
var t = a
|
var t = a
|
||||||
assert t.kind == tyObject
|
assert t.kind == tyObject
|
||||||
|
var depth = 0
|
||||||
while t != nil and not sameObjectTypes(f, t):
|
while t != nil and not sameObjectTypes(f, t):
|
||||||
assert t.kind == tyObject
|
assert t.kind == tyObject
|
||||||
t = t.sons[0]
|
t = t.sons[0]
|
||||||
if t == nil: break
|
if t == nil: break
|
||||||
t = skipTypes(t, {tyGenericInst})
|
t = skipTypes(t, {tyGenericInst})
|
||||||
result = t != nil
|
inc depth
|
||||||
|
if t != nil:
|
||||||
|
result = depth
|
||||||
|
|
||||||
proc minRel(a, b: TTypeRelation): TTypeRelation =
|
proc minRel(a, b: TTypeRelation): TTypeRelation =
|
||||||
if a <= b: result = a
|
if a <= b: result = a
|
||||||
else: result = b
|
else: result = b
|
||||||
|
|
||||||
proc tupleRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
proc tupleRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
result = isNone
|
result = isNone
|
||||||
if sameType(f, a):
|
if sameType(f, a):
|
||||||
result = isEqual
|
result = isEqual
|
||||||
elif sonsLen(a) == sonsLen(f):
|
elif sonsLen(a) == sonsLen(f):
|
||||||
result = isEqual
|
result = isEqual
|
||||||
for i in countup(0, sonsLen(f) - 1):
|
for i in countup(0, sonsLen(f) - 1):
|
||||||
var m = typeRel(mapping, f.sons[i], a.sons[i])
|
var m = typeRel(c, f.sons[i], a.sons[i])
|
||||||
if m < isSubtype: return isNone
|
if m < isSubtype: return isNone
|
||||||
result = minRel(result, m)
|
result = minRel(result, m)
|
||||||
if f.n != nil and a.n != nil:
|
if f.n != nil and a.n != nil:
|
||||||
|
|
@ -237,7 +245,7 @@ proc tupleRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
var y = a.n.sons[i].sym
|
var y = a.n.sons[i].sym
|
||||||
if x.name.id != y.name.id: return isNone
|
if x.name.id != y.name.id: return isNone
|
||||||
|
|
||||||
proc matchTypeClass(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
proc matchTypeClass(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
for i in countup(0, f.sonsLen - 1):
|
for i in countup(0, f.sonsLen - 1):
|
||||||
let son = f.sons[i]
|
let son = f.sons[i]
|
||||||
var match = son.kind == skipTypes(a, {tyRange}).kind
|
var match = son.kind == skipTypes(a, {tyRange}).kind
|
||||||
|
|
@ -247,9 +255,9 @@ proc matchTypeClass(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
if a.kind == tyGenericInst and a.sons[0] == son:
|
if a.kind == tyGenericInst and a.sons[0] == son:
|
||||||
match = true
|
match = true
|
||||||
put(mapping, f, a)
|
put(c.bindings, f, a)
|
||||||
of tyTypeClass:
|
of tyTypeClass:
|
||||||
match = matchTypeClass(mapping, son, a) == isGeneric
|
match = matchTypeClass(c, son, a) == isGeneric
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
if tfAny in f.flags:
|
if tfAny in f.flags:
|
||||||
|
|
@ -263,7 +271,7 @@ proc matchTypeClass(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
# or none of them matched.
|
# or none of them matched.
|
||||||
result = if tfAny in f.flags: isNone else: isGeneric
|
result = if tfAny in f.flags: isNone else: isGeneric
|
||||||
|
|
||||||
proc procTypeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
|
proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
|
||||||
result = f.kind != a.kind and (f.kind == tyVar or a.kind == tyVar)
|
result = f.kind != a.kind and (f.kind == tyVar or a.kind == tyVar)
|
||||||
|
|
||||||
|
|
@ -276,13 +284,13 @@ proc procTypeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
result = isEqual # start with maximum; also correct for no
|
result = isEqual # start with maximum; also correct for no
|
||||||
# params at all
|
# params at all
|
||||||
for i in countup(1, sonsLen(f)-1):
|
for i in countup(1, sonsLen(f)-1):
|
||||||
var m = typeRel(mapping, f.sons[i], a.sons[i])
|
var m = typeRel(c, f.sons[i], a.sons[i])
|
||||||
if m <= isSubtype or inconsistentVarTypes(f.sons[i], a.sons[i]):
|
if m <= isSubtype or inconsistentVarTypes(f.sons[i], a.sons[i]):
|
||||||
return isNone
|
return isNone
|
||||||
else: result = minRel(m, result)
|
else: result = minRel(m, result)
|
||||||
if f.sons[0] != nil:
|
if f.sons[0] != nil:
|
||||||
if a.sons[0] != nil:
|
if a.sons[0] != nil:
|
||||||
var m = typeRel(mapping, f.sons[0], a.sons[0])
|
var m = typeRel(c, f.sons[0], a.sons[0])
|
||||||
# Subtype is sufficient for return types!
|
# Subtype is sufficient for return types!
|
||||||
if m < isSubtype or inconsistentVarTypes(f.sons[0], a.sons[0]):
|
if m < isSubtype or inconsistentVarTypes(f.sons[0], a.sons[0]):
|
||||||
result = isNone
|
result = isNone
|
||||||
|
|
@ -305,7 +313,7 @@ proc procTypeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
result = isNone
|
result = isNone
|
||||||
else: nil
|
else: nil
|
||||||
|
|
||||||
proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
# is a subtype of f?
|
# is a subtype of f?
|
||||||
result = isNone
|
result = isNone
|
||||||
assert(f != nil)
|
assert(f != nil)
|
||||||
|
|
@ -314,9 +322,9 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
skipTypes(f, {tyVar}).kind notin {
|
skipTypes(f, {tyVar}).kind notin {
|
||||||
tyGenericBody, tyGenericInvokation,
|
tyGenericBody, tyGenericInvokation,
|
||||||
tyGenericParam, tyTypeClass}:
|
tyGenericParam, tyTypeClass}:
|
||||||
return typeRel(mapping, f, lastSon(a))
|
return typeRel(c, f, lastSon(a))
|
||||||
if a.kind == tyVar and f.kind != tyVar:
|
if a.kind == tyVar and f.kind != tyVar:
|
||||||
return typeRel(mapping, f, a.sons[0])
|
return typeRel(c, f, a.sons[0])
|
||||||
case f.kind
|
case f.kind
|
||||||
of tyEnum:
|
of tyEnum:
|
||||||
if a.kind == f.kind and sameEnumTypes(f, a): result = isEqual
|
if a.kind == f.kind and sameEnumTypes(f, a): result = isEqual
|
||||||
|
|
@ -326,7 +334,7 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
|
elif skipTypes(a, {tyRange}).kind == f.kind: result = isSubtype
|
||||||
of tyRange:
|
of tyRange:
|
||||||
if a.kind == f.kind:
|
if a.kind == f.kind:
|
||||||
result = typeRel(mapping, base(f), base(a))
|
result = typeRel(c, base(f), base(a))
|
||||||
# bugfix: accept integer conversions here
|
# bugfix: accept integer conversions here
|
||||||
#if result < isGeneric: result = isNone
|
#if result < isGeneric: result = isNone
|
||||||
elif skipTypes(f, {tyRange}).kind == a.kind:
|
elif skipTypes(f, {tyRange}).kind == a.kind:
|
||||||
|
|
@ -348,45 +356,45 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
of tyFloat64: result = handleFloatRange(f, a)
|
of tyFloat64: result = handleFloatRange(f, a)
|
||||||
of tyFloat128: result = handleFloatRange(f, a)
|
of tyFloat128: result = handleFloatRange(f, a)
|
||||||
of tyVar:
|
of tyVar:
|
||||||
if a.kind == f.kind: result = typeRel(mapping, base(f), base(a))
|
if a.kind == f.kind: result = typeRel(c, base(f), base(a))
|
||||||
else: result = typeRel(mapping, base(f), a)
|
else: result = typeRel(c, base(f), a)
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
# tyArrayConstr cannot happen really, but
|
# tyArrayConstr cannot happen really, but
|
||||||
# we wanna be safe here
|
# we wanna be safe here
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyArray:
|
of tyArray:
|
||||||
result = minRel(typeRel(mapping, f.sons[0], a.sons[0]),
|
result = minRel(typeRel(c, f.sons[0], a.sons[0]),
|
||||||
typeRel(mapping, f.sons[1], a.sons[1]))
|
typeRel(c, f.sons[1], a.sons[1]))
|
||||||
if result < isGeneric: result = isNone
|
if result < isGeneric: result = isNone
|
||||||
of tyArrayConstr:
|
of tyArrayConstr:
|
||||||
result = typeRel(mapping, f.sons[1], a.sons[1])
|
result = typeRel(c, f.sons[1], a.sons[1])
|
||||||
if result < isGeneric:
|
if result < isGeneric:
|
||||||
result = isNone
|
result = isNone
|
||||||
else:
|
else:
|
||||||
if (result != isGeneric) and (lengthOrd(f) != lengthOrd(a)):
|
if (result != isGeneric) and (lengthOrd(f) != lengthOrd(a)):
|
||||||
result = isNone
|
result = isNone
|
||||||
elif f.sons[0].kind in GenericTypes:
|
elif f.sons[0].kind in GenericTypes:
|
||||||
result = minRel(result, typeRel(mapping, f.sons[0], a.sons[0]))
|
result = minRel(result, typeRel(c, f.sons[0], a.sons[0]))
|
||||||
else: nil
|
else: nil
|
||||||
of tyOpenArray:
|
of tyOpenArray:
|
||||||
case a.Kind
|
case a.Kind
|
||||||
of tyOpenArray:
|
of tyOpenArray:
|
||||||
result = typeRel(mapping, base(f), base(a))
|
result = typeRel(c, base(f), base(a))
|
||||||
if result < isGeneric: result = isNone
|
if result < isGeneric: result = isNone
|
||||||
of tyArrayConstr:
|
of tyArrayConstr:
|
||||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
|
if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
|
||||||
result = isSubtype # [] is allowed here
|
result = isSubtype # [] is allowed here
|
||||||
elif typeRel(mapping, base(f), a.sons[1]) >= isGeneric:
|
elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
|
||||||
result = isSubtype
|
result = isSubtype
|
||||||
of tyArray:
|
of tyArray:
|
||||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
|
if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
|
||||||
result = isSubtype
|
result = isSubtype
|
||||||
elif typeRel(mapping, base(f), a.sons[1]) >= isGeneric:
|
elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
|
||||||
result = isConvertible
|
result = isConvertible
|
||||||
of tySequence:
|
of tySequence:
|
||||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
||||||
result = isConvertible
|
result = isConvertible
|
||||||
elif typeRel(mapping, base(f), a.sons[0]) >= isGeneric:
|
elif typeRel(c, base(f), a.sons[0]) >= isGeneric:
|
||||||
result = isConvertible
|
result = isConvertible
|
||||||
else: nil
|
else: nil
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
|
@ -397,23 +405,27 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
||||||
result = isSubtype
|
result = isSubtype
|
||||||
else:
|
else:
|
||||||
result = typeRel(mapping, f.sons[0], a.sons[0])
|
result = typeRel(c, f.sons[0], a.sons[0])
|
||||||
if result < isGeneric: result = isNone
|
if result < isGeneric: result = isNone
|
||||||
else: nil
|
else: nil
|
||||||
of tyOrdinal:
|
of tyOrdinal:
|
||||||
if isOrdinalType(a):
|
if isOrdinalType(a):
|
||||||
var x = if a.kind == tyOrdinal: a.sons[0] else: a
|
var x = if a.kind == tyOrdinal: a.sons[0] else: a
|
||||||
result = typeRel(mapping, f.sons[0], x)
|
result = typeRel(c, f.sons[0], x)
|
||||||
if result < isGeneric: result = isNone
|
if result < isGeneric: result = isNone
|
||||||
of tyForward: InternalError("forward type in typeRel()")
|
of tyForward: InternalError("forward type in typeRel()")
|
||||||
of tyNil:
|
of tyNil:
|
||||||
if a.kind == f.kind: result = isEqual
|
if a.kind == f.kind: result = isEqual
|
||||||
of tyTuple:
|
of tyTuple:
|
||||||
if a.kind == tyTuple: result = tupleRel(mapping, f, a)
|
if a.kind == tyTuple: result = tupleRel(c, f, a)
|
||||||
of tyObject:
|
of tyObject:
|
||||||
if a.kind == tyObject:
|
if a.kind == tyObject:
|
||||||
if sameObjectTypes(f, a): result = isEqual
|
if sameObjectTypes(f, a): result = isEqual
|
||||||
elif isObjectSubtype(a, f): result = isSubtype
|
else:
|
||||||
|
var depth = isObjectSubtype(a, f)
|
||||||
|
if depth > 0:
|
||||||
|
inc(c.inheritancePenalty, depth)
|
||||||
|
result = isSubtype
|
||||||
of tyDistinct:
|
of tyDistinct:
|
||||||
if (a.kind == tyDistinct) and sameDistinctTypes(f, a): result = isEqual
|
if (a.kind == tyDistinct) and sameDistinctTypes(f, a): result = isEqual
|
||||||
of tySet:
|
of tySet:
|
||||||
|
|
@ -421,25 +433,25 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
|
||||||
result = isSubtype
|
result = isSubtype
|
||||||
else:
|
else:
|
||||||
result = typeRel(mapping, f.sons[0], a.sons[0])
|
result = typeRel(c, f.sons[0], a.sons[0])
|
||||||
if result <= isConvertible:
|
if result <= isConvertible:
|
||||||
result = isNone # BUGFIX!
|
result = isNone # BUGFIX!
|
||||||
of tyPtr:
|
of tyPtr:
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyPtr:
|
of tyPtr:
|
||||||
result = typeRel(mapping, base(f), base(a))
|
result = typeRel(c, base(f), base(a))
|
||||||
if result <= isConvertible: result = isNone
|
if result <= isConvertible: result = isNone
|
||||||
of tyNil: result = isSubtype
|
of tyNil: result = isSubtype
|
||||||
else: nil
|
else: nil
|
||||||
of tyRef:
|
of tyRef:
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyRef:
|
of tyRef:
|
||||||
result = typeRel(mapping, base(f), base(a))
|
result = typeRel(c, base(f), base(a))
|
||||||
if result <= isConvertible: result = isNone
|
if result <= isConvertible: result = isNone
|
||||||
of tyNil: result = isSubtype
|
of tyNil: result = isSubtype
|
||||||
else: nil
|
else: nil
|
||||||
of tyProc:
|
of tyProc:
|
||||||
result = procTypeRel(mapping, f, a)
|
result = procTypeRel(c, f, a)
|
||||||
of tyPointer:
|
of tyPointer:
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyPointer: result = isEqual
|
of tyPointer: result = isEqual
|
||||||
|
|
@ -468,10 +480,10 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
of tyEmpty:
|
of tyEmpty:
|
||||||
if a.kind == tyEmpty: result = isEqual
|
if a.kind == tyEmpty: result = isEqual
|
||||||
of tyGenericInst:
|
of tyGenericInst:
|
||||||
result = typeRel(mapping, lastSon(f), a)
|
result = typeRel(c, lastSon(f), a)
|
||||||
of tyGenericBody:
|
of tyGenericBody:
|
||||||
let ff = lastSon(f)
|
let ff = lastSon(f)
|
||||||
if ff != nil: result = typeRel(mapping, ff, a)
|
if ff != nil: result = typeRel(c, ff, a)
|
||||||
of tyGenericInvokation:
|
of tyGenericInvokation:
|
||||||
assert(f.sons[0].kind == tyGenericBody)
|
assert(f.sons[0].kind == tyGenericBody)
|
||||||
if a.kind == tyGenericInvokation:
|
if a.kind == tyGenericInvokation:
|
||||||
|
|
@ -485,40 +497,40 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
for i in countup(1, sonsLen(f) - 1):
|
for i in countup(1, sonsLen(f) - 1):
|
||||||
if a.sons[i].kind == tyGenericParam:
|
if a.sons[i].kind == tyGenericParam:
|
||||||
InternalError("wrong instantiated type!")
|
InternalError("wrong instantiated type!")
|
||||||
if typeRel(mapping, f.sons[i], a.sons[i]) <= isSubtype: return
|
if typeRel(c, f.sons[i], a.sons[i]) <= isSubtype: return
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = typeRel(mapping, f.sons[0], a)
|
result = typeRel(c, f.sons[0], a)
|
||||||
if result != isNone:
|
if result != isNone:
|
||||||
# we steal the generic parameters from the tyGenericBody:
|
# we steal the generic parameters from the tyGenericBody:
|
||||||
for i in countup(1, sonsLen(f) - 1):
|
for i in countup(1, sonsLen(f) - 1):
|
||||||
var x = PType(idTableGet(mapping, f.sons[0].sons[i - 1]))
|
var x = PType(idTableGet(c.bindings, f.sons[0].sons[i - 1]))
|
||||||
if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
|
if x == nil or x.kind in {tyGenericInvokation, tyGenericParam}:
|
||||||
InternalError("wrong instantiated type!")
|
InternalError("wrong instantiated type!")
|
||||||
put(mapping, f.sons[i], x)
|
put(c.bindings, f.sons[i], x)
|
||||||
of tyGenericParam, tyTypeClass:
|
of tyGenericParam, tyTypeClass:
|
||||||
var x = PType(idTableGet(mapping, f))
|
var x = PType(idTableGet(c.bindings, f))
|
||||||
if x == nil:
|
if x == nil:
|
||||||
result = matchTypeClass(mapping, f, a)
|
result = matchTypeClass(c, f, a)
|
||||||
if result == isGeneric:
|
if result == isGeneric:
|
||||||
var concrete = concreteType(mapping, a)
|
var concrete = concreteType(c, a)
|
||||||
if concrete == nil:
|
if concrete == nil:
|
||||||
result = isNone
|
result = isNone
|
||||||
else:
|
else:
|
||||||
put(mapping, f, concrete)
|
put(c.bindings, f, concrete)
|
||||||
elif a.kind == tyEmpty:
|
elif a.kind == tyEmpty:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
elif x.kind == tyGenericParam:
|
elif x.kind == tyGenericParam:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = typeRel(mapping, x, a) # check if it fits
|
result = typeRel(c, x, a) # check if it fits
|
||||||
of tyTypeDesc:
|
of tyTypeDesc:
|
||||||
if a.kind == tyTypeDesc:
|
if a.kind == tyTypeDesc:
|
||||||
if f.sonsLen == 0:
|
if f.sonsLen == 0:
|
||||||
result = isGeneric
|
result = isGeneric
|
||||||
else:
|
else:
|
||||||
result = matchTypeClass(mapping, f, a.sons[0])
|
result = matchTypeClass(c, f, a.sons[0])
|
||||||
if result == isGeneric: put(mapping, f, a)
|
if result == isGeneric: put(c.bindings, f, a)
|
||||||
else:
|
else:
|
||||||
result = isNone
|
result = isNone
|
||||||
of tyExpr, tyStmt:
|
of tyExpr, tyStmt:
|
||||||
|
|
@ -526,9 +538,9 @@ proc typeRel(mapping: var TIdTable, f, a: PType): TTypeRelation =
|
||||||
else: internalError("typeRel(" & $f.kind & ')')
|
else: internalError("typeRel(" & $f.kind & ')')
|
||||||
|
|
||||||
proc cmpTypes*(f, a: PType): TTypeRelation =
|
proc cmpTypes*(f, a: PType): TTypeRelation =
|
||||||
var mapping: TIdTable
|
var c: TCandidate
|
||||||
InitIdTable(mapping)
|
InitCandidate(c, f)
|
||||||
result = typeRel(mapping, f, a)
|
result = typeRel(c, f, a)
|
||||||
|
|
||||||
proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
|
proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
|
||||||
f: PType): PType =
|
f: PType): PType =
|
||||||
|
|
@ -552,8 +564,8 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
for i in countup(0, len(c.converters) - 1):
|
for i in countup(0, len(c.converters) - 1):
|
||||||
var src = c.converters[i].typ.sons[1]
|
var src = c.converters[i].typ.sons[1]
|
||||||
var dest = c.converters[i].typ.sons[0]
|
var dest = c.converters[i].typ.sons[0]
|
||||||
if (typeRel(m.bindings, f, dest) == isEqual) and
|
if (typeRel(m, f, dest) == isEqual) and
|
||||||
(typeRel(m.bindings, src, a) == isEqual):
|
(typeRel(m, src, a) == isEqual):
|
||||||
markUsed(arg, c.converters[i])
|
markUsed(arg, c.converters[i])
|
||||||
var s = newSymNode(c.converters[i])
|
var s = newSymNode(c.converters[i])
|
||||||
s.typ = c.converters[i].typ
|
s.typ = c.converters[i].typ
|
||||||
|
|
@ -572,7 +584,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
if f.sonsLen == 0:
|
if f.sonsLen == 0:
|
||||||
r = isGeneric
|
r = isGeneric
|
||||||
else:
|
else:
|
||||||
let match = matchTypeClass(m.bindings, f, a)
|
let match = matchTypeClass(m, f, a)
|
||||||
if match != isGeneric: r = isNone
|
if match != isGeneric: r = isNone
|
||||||
else:
|
else:
|
||||||
# XXX: Ideally, this should happen much earlier somewhere near
|
# XXX: Ideally, this should happen much earlier somewhere near
|
||||||
|
|
@ -590,7 +602,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
if r == isGeneric:
|
if r == isGeneric:
|
||||||
put(m.bindings, f, arg.typ)
|
put(m.bindings, f, arg.typ)
|
||||||
else:
|
else:
|
||||||
r = typeRel(m.bindings, f, a)
|
r = typeRel(m, f, a)
|
||||||
|
|
||||||
case r
|
case r
|
||||||
of isConvertible:
|
of isConvertible:
|
||||||
|
|
@ -633,7 +645,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
# check for a base type match, which supports openarray[T] without []
|
# check for a base type match, which supports openarray[T] without []
|
||||||
# constructor in a call:
|
# constructor in a call:
|
||||||
if result == nil and f.kind == tyOpenArray:
|
if result == nil and f.kind == tyOpenArray:
|
||||||
r = typeRel(m.bindings, base(f), a)
|
r = typeRel(m, base(f), a)
|
||||||
if r >= isGeneric:
|
if r >= isGeneric:
|
||||||
inc(m.convMatches)
|
inc(m.convMatches)
|
||||||
result = copyTree(arg)
|
result = copyTree(arg)
|
||||||
|
|
@ -663,7 +675,7 @@ proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
# iterators are not first class yet, so ignore them
|
# iterators are not first class yet, so ignore them
|
||||||
if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}:
|
if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}:
|
||||||
copyCandidate(z, m)
|
copyCandidate(z, m)
|
||||||
var r = typeRel(z.bindings, f, arg.sons[i].typ)
|
var r = typeRel(z, f, arg.sons[i].typ)
|
||||||
if r != isNone:
|
if r != isNone:
|
||||||
case x.state
|
case x.state
|
||||||
of csEmpty, csNoMatch:
|
of csEmpty, csNoMatch:
|
||||||
|
|
@ -687,7 +699,8 @@ proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType,
|
||||||
else:
|
else:
|
||||||
# only one valid interpretation found:
|
# only one valid interpretation found:
|
||||||
markUsed(arg, arg.sons[best].sym)
|
markUsed(arg, arg.sons[best].sym)
|
||||||
result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best], argOrig)
|
result = ParamTypesMatchAux(c, m, f, arg.sons[best].typ, arg.sons[best],
|
||||||
|
argOrig)
|
||||||
|
|
||||||
proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
|
proc IndexTypesMatch*(c: PContext, f, a: PType, arg: PNode): PNode =
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
discard """
|
discard """
|
||||||
disabled: true
|
output: "b"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -12,8 +12,8 @@ type
|
||||||
TC = object of TB
|
TC = object of TB
|
||||||
whatever: string
|
whatever: string
|
||||||
|
|
||||||
proc p(a: var TA) = nil
|
proc p(a: var TA) = echo "a"
|
||||||
proc p(b: var TB) = nil
|
proc p(b: var TB) = echo "b"
|
||||||
|
|
||||||
var c: TC
|
var c: TC
|
||||||
|
|
||||||
|
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -1,7 +1,6 @@
|
||||||
version 0.9.0
|
version 0.9.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
- change overloading resolution: toop.nim test
|
|
||||||
- implicit ref/ptr->var conversion
|
- implicit ref/ptr->var conversion
|
||||||
- deprecate ``var x, y = 0`` as it's confusing for tuple consistency
|
- deprecate ``var x, y = 0`` as it's confusing for tuple consistency
|
||||||
- finish support for unsigned ints:
|
- finish support for unsigned ints:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue