fix argument_parser
This commit is contained in:
parent
f701ee086a
commit
74f4901430
1 changed files with 29 additions and 24 deletions
|
|
@ -343,53 +343,57 @@ proc allowsNil(f: PType): TTypeRelation {.inline.} =
|
||||||
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)
|
||||||
|
|
||||||
proc procParamTypeRel(c: var TCandidate, f, a: PType,
|
proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
result: var TTypeRelation) =
|
var f = f
|
||||||
var
|
|
||||||
m: TTypeRelation
|
|
||||||
f = f
|
|
||||||
|
|
||||||
if a.isMetaType:
|
if a.isMetaType:
|
||||||
if f.isMetaType:
|
if f.isMetaType:
|
||||||
# we are matching a generic proc (as proc param)
|
# We are matching a generic proc (as proc param)
|
||||||
# to another generic type appearing in the proc
|
# to another generic type appearing in the proc
|
||||||
# sigunature. there is a change that the target
|
# signature. There is a change that the target
|
||||||
# type is already fully-determined, so we are
|
# type is already fully-determined, so we are
|
||||||
# going to try resolve it
|
# going to try resolve it
|
||||||
f = generateTypeInstance(c.c, c.bindings, c.call.info, f)
|
f = generateTypeInstance(c.c, c.bindings, c.call.info, f)
|
||||||
if f == nil or f.isMetaType:
|
if f == nil or f.isMetaType:
|
||||||
# no luck resolving the type, so the inference fails
|
# no luck resolving the type, so the inference fails
|
||||||
result = isNone
|
return isNone
|
||||||
return
|
|
||||||
let reverseRel = typeRel(c, a, f)
|
let reverseRel = typeRel(c, a, f)
|
||||||
if reverseRel == isGeneric:
|
if reverseRel == isGeneric:
|
||||||
m = isInferred
|
result = isInferred
|
||||||
|
inc c.genericMatches
|
||||||
else:
|
else:
|
||||||
m = typeRel(c, f, a)
|
result = typeRel(c, f, a)
|
||||||
|
|
||||||
if m <= isSubtype or inconsistentVarTypes(f, a):
|
if result <= isSubtype or inconsistentVarTypes(f, a):
|
||||||
result = isNone
|
result = isNone
|
||||||
return
|
|
||||||
else:
|
if result == isEqual:
|
||||||
result = minRel(m, result)
|
inc c.exactMatches
|
||||||
|
|
||||||
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
|
||||||
case a.kind
|
case a.kind
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if sonsLen(f) != sonsLen(a): return
|
if sonsLen(f) != sonsLen(a): return
|
||||||
# Note: We have to do unification for the parameters before the
|
|
||||||
# return type!
|
|
||||||
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):
|
|
||||||
procParamTypeRel(c, f.sons[i], a.sons[i], result)
|
template checkParam(f, a) =
|
||||||
|
result = minRel(result, procParamTypeRel(c, f, a))
|
||||||
|
if result == isNone: return
|
||||||
|
|
||||||
|
# Note: We have to do unification for the parameters before the
|
||||||
|
# return type!
|
||||||
|
for i in 1 .. <f.sonsLen:
|
||||||
|
checkParam(f.sons[i], a.sons[i])
|
||||||
|
|
||||||
if f.sons[0] != nil:
|
if f.sons[0] != nil:
|
||||||
if a.sons[0] != nil:
|
if a.sons[0] != nil:
|
||||||
procParamTypeRel(c, f.sons[0], a.sons[0], result)
|
checkParam(f.sons[0], a.sons[0])
|
||||||
else:
|
else:
|
||||||
return isNone
|
return isNone
|
||||||
elif a.sons[0] != nil:
|
elif a.sons[0] != nil:
|
||||||
return isNone
|
return isNone
|
||||||
|
|
||||||
if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
|
if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
|
||||||
return isNone
|
return isNone
|
||||||
elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
|
elif tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {}:
|
||||||
|
|
@ -1101,6 +1105,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||||
# incorrect to simply use the first fitting match. However, to implement
|
# incorrect to simply use the first fitting match. However, to implement
|
||||||
# this correctly is inefficient. We have to copy `m` here to be able to
|
# this correctly is inefficient. We have to copy `m` here to be able to
|
||||||
# roll back the side effects of the unification algorithm.
|
# roll back the side effects of the unification algorithm.
|
||||||
|
|
||||||
let c = m.c
|
let c = m.c
|
||||||
var x, y, z: TCandidate
|
var x, y, z: TCandidate
|
||||||
initCandidate(c, x, m.callee)
|
initCandidate(c, x, m.callee)
|
||||||
|
|
@ -1122,10 +1127,10 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||||
x.state = csMatch
|
x.state = csMatch
|
||||||
of csMatch:
|
of csMatch:
|
||||||
var cmp = cmpCandidates(x, z)
|
var cmp = cmpCandidates(x, z)
|
||||||
if cmp < 0:
|
if cmp < 0:
|
||||||
best = i
|
best = i
|
||||||
x = z
|
x = z
|
||||||
elif cmp == 0:
|
elif cmp == 0:
|
||||||
y = z # z is as good as x
|
y = z # z is as good as x
|
||||||
if x.state == csEmpty:
|
if x.state == csEmpty:
|
||||||
result = nil
|
result = nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue