better overloading resolution for generics
This commit is contained in:
parent
8090b6c027
commit
d13bcf6575
4 changed files with 65 additions and 19 deletions
|
|
@ -97,6 +97,45 @@ proc copyCandidate(a: var TCandidate, b: TCandidate) =
|
||||||
a.baseTypeMatch = b.baseTypeMatch
|
a.baseTypeMatch = b.baseTypeMatch
|
||||||
copyIdTable(a.bindings, b.bindings)
|
copyIdTable(a.bindings, b.bindings)
|
||||||
|
|
||||||
|
proc sumGeneric(t: PType): int =
|
||||||
|
var t = t
|
||||||
|
while true:
|
||||||
|
case t.kind
|
||||||
|
of tyGenericInst, tyArray, tyRef, tyPtr, tyDistinct, tyArrayConstr,
|
||||||
|
tyOpenArray, tyVarargs, tySet, tyRange, tySequence, tyGenericBody:
|
||||||
|
t = t.lastSon
|
||||||
|
inc result
|
||||||
|
of tyVar:
|
||||||
|
# but do not make 'var T' more specific than 'T'!
|
||||||
|
t = t.sons[0]
|
||||||
|
of tyGenericInvokation, tyTuple:
|
||||||
|
result = ord(t.kind == tyGenericInvokation)
|
||||||
|
for i in 0 .. <t.len: result += t.sons[i].sumGeneric
|
||||||
|
break
|
||||||
|
of tyGenericParam, tyExpr, tyStmt, tyTypeDesc, tyTypeClass: break
|
||||||
|
else: return 0
|
||||||
|
|
||||||
|
proc complexDisambiguation(a, b: PType): int =
|
||||||
|
var x, y: int
|
||||||
|
for i in 1 .. <a.len: x += a.sons[i].sumGeneric
|
||||||
|
for i in 1 .. <b.len: y += b.sons[i].sumGeneric
|
||||||
|
result = x - y
|
||||||
|
when false:
|
||||||
|
proc betterThan(a, b: PType): bool {.inline.} = a.sumGeneric > b.sumGeneric
|
||||||
|
|
||||||
|
if a.len > 1 and b.len > 1:
|
||||||
|
let aa = a.sons[1].sumGeneric
|
||||||
|
let bb = b.sons[1].sumGeneric
|
||||||
|
var a = a
|
||||||
|
var b = b
|
||||||
|
|
||||||
|
if aa < bb: swap(a, b)
|
||||||
|
# all must be better
|
||||||
|
for i in 2 .. <min(a.len, b.len):
|
||||||
|
if not a.sons[i].betterThan(b.sons[i]): return 0
|
||||||
|
# a must be longer or of the same length as b:
|
||||||
|
result = a.len - b.len
|
||||||
|
|
||||||
proc cmpCandidates*(a, b: TCandidate): int =
|
proc cmpCandidates*(a, b: TCandidate): int =
|
||||||
result = a.exactMatches - b.exactMatches
|
result = a.exactMatches - b.exactMatches
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
|
|
@ -113,6 +152,9 @@ proc cmpCandidates*(a, b: TCandidate): int =
|
||||||
if result != 0: return
|
if result != 0: return
|
||||||
# the other way round because of other semantics:
|
# the other way round because of other semantics:
|
||||||
result = b.inheritancePenalty - a.inheritancePenalty
|
result = b.inheritancePenalty - a.inheritancePenalty
|
||||||
|
if result != 0: return
|
||||||
|
# prefer more specialized generic over more general generic:
|
||||||
|
result = complexDisambiguation(a.callee, b.callee)
|
||||||
|
|
||||||
proc writeMatches*(c: TCandidate) =
|
proc writeMatches*(c: TCandidate) =
|
||||||
Writeln(stdout, "exact matches: " & $c.exactMatches)
|
Writeln(stdout, "exact matches: " & $c.exactMatches)
|
||||||
|
|
|
||||||
|
|
@ -1532,7 +1532,7 @@ iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[
|
||||||
## The current implementation also has a bug that affects symbol binding
|
## The current implementation also has a bug that affects symbol binding
|
||||||
## in the loop body.
|
## in the loop body.
|
||||||
|
|
||||||
proc `==`*[T: tuple](x, y: T): bool =
|
proc `==`*[T: tuple|object](x, y: T): bool =
|
||||||
## generic ``==`` operator for tuples that is lifted from the components
|
## generic ``==`` operator for tuples that is lifted from the components
|
||||||
## of `x` and `y`.
|
## of `x` and `y`.
|
||||||
for a, b in fields(x, y):
|
for a, b in fields(x, y):
|
||||||
|
|
@ -1557,7 +1557,7 @@ proc `<`*[T: tuple](x, y: T): bool =
|
||||||
if c > 0: return false
|
if c > 0: return false
|
||||||
return false
|
return false
|
||||||
|
|
||||||
proc `$`*[T: tuple](x: T): string =
|
proc `$`*[T: tuple|object](x: T): string =
|
||||||
## generic ``$`` operator for tuples that is lifted from the components
|
## generic ``$`` operator for tuples that is lifted from the components
|
||||||
## of `x`. Example:
|
## of `x`. Example:
|
||||||
##
|
##
|
||||||
|
|
|
||||||
20
tests/run/toverl3.nim
Executable file
20
tests/run/toverl3.nim
Executable file
|
|
@ -0,0 +1,20 @@
|
||||||
|
discard """
|
||||||
|
file: "toverl3.nim"
|
||||||
|
output: '''m1
|
||||||
|
tup1'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Tests more specific generic match:
|
||||||
|
|
||||||
|
proc m[T](x: T) = echo "m2"
|
||||||
|
proc m[T](x: var ref T) = echo "m1"
|
||||||
|
|
||||||
|
proc tup[S, T](x: tuple[a: S, b: ref T]) = echo "tup1"
|
||||||
|
proc tup[S, T](x: tuple[a: S, b: T]) = echo "tup2"
|
||||||
|
|
||||||
|
var
|
||||||
|
obj: ref int
|
||||||
|
tu: tuple[a: int, b: ref bool]
|
||||||
|
|
||||||
|
m(obj)
|
||||||
|
tup(tu)
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
discard """
|
|
||||||
file: "toverlop.nim"
|
|
||||||
output: "3"
|
|
||||||
"""
|
|
||||||
# Test operator overloading
|
|
||||||
|
|
||||||
proc `%` (a, b: int): int =
|
|
||||||
return a mod b
|
|
||||||
|
|
||||||
var x, y: int
|
|
||||||
x = 15
|
|
||||||
y = 6
|
|
||||||
write(stdout, x % y)
|
|
||||||
#OUT 3
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue