Cosmetic compiler cleanup (#12718)

* Cleanup compiler code base

* Unify add calls

* Unify len invocations

* Unify range operators

* Fix oversight

* Remove {.procvar.} pragma

* initCandidate -> newCandidate where reasonable

* Unify safeLen calls
This commit is contained in:
Clyybber 2019-11-28 17:13:04 +01:00 • committed by Andreas Rumpf
commit 7e747d11c6
109 changed files with 6115 additions and 6254 deletions

View file

@ -167,8 +167,8 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
initIdTable(c.bindings)
if binding != nil and callee.kind in routineKinds:
var typeParams = callee.ast[genericParamsPos]
for i in 1..min(len(typeParams), len(binding)-1):
var formalTypeParam = typeParams.sons[i-1].typ
for i in 1..min(typeParams.len, binding.len-1):
var formalTypeParam = typeParams[i-1].typ
var bound = binding[i].typ
if bound != nil:
if formalTypeParam.kind == tyTypeDesc:
@ -220,7 +220,7 @@ proc sumGeneric(t: PType): int =
inc result, maxBranch
break
of tyVar:
t = t.sons[0]
t = t[0]
inc result
inc isvar
of tyTypeDesc:
@ -229,12 +229,12 @@ proc sumGeneric(t: PType): int =
inc result
of tyGenericInvocation, tyTuple, tyProc, tyAnd:
result += ord(t.kind in {tyGenericInvocation, tyAnd})
for i in 0 ..< t.len:
if t.sons[i] != nil:
result += sumGeneric(t.sons[i])
for i in 0..<t.len:
if t[i] != nil:
result += sumGeneric(t[i])
break
of tyStatic:
return sumGeneric(t.sons[0]) + 1
return sumGeneric(t[0]) + 1
of tyGenericParam, tyUntyped, tyTyped: break
of tyAlias, tySink: t = t.lastSon
of tyBool, tyChar, tyEnum, tyObject, tyPointer,
@ -249,12 +249,12 @@ proc sumGeneric(t: PType): int =
proc complexDisambiguation(a, b: PType): int =
# 'a' matches better if *every* argument matches better or equal than 'b'.
var winner = 0
for i in 1 ..< min(a.len, b.len):
let x = a.sons[i].sumGeneric
let y = b.sons[i].sumGeneric
for i in 1..<min(a.len, b.len):
let x = a[i].sumGeneric
let y = b[i].sumGeneric
#if ggDebug:
#echo "came herA ", typeToString(a.sons[i]), " ", x
#echo "came herB ", typeToString(b.sons[i]), " ", y
#echo "came herA ", typeToString(a[i]), " ", x
#echo "came herB ", typeToString(b[i]), " ", y
if x != y:
if winner == 0:
if x > y: winner = 1
@ -269,8 +269,8 @@ proc complexDisambiguation(a, b: PType): int =
result = winner
when false:
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
for i in 1..<a.len: x += a[i].sumGeneric
for i in 1..<b.len: y += b[i].sumGeneric
result = x - y
proc writeMatches*(c: TCandidate) =
@ -305,7 +305,7 @@ proc cmpCandidates*(a, b: TCandidate): int =
proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string =
if arg.kind in nkSymChoices:
result = typeToString(arg[0].typ, prefer)
for i in 1 ..< arg.len:
for i in 1..<arg.len:
result.add(" | ")
result.add typeToString(arg[i].typ, prefer)
elif arg.typ == nil:
@ -316,25 +316,25 @@ proc argTypeToString(arg: PNode; prefer: TPreferedDesc): string =
proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
prefer: TPreferedDesc = preferName): string =
result = ""
for i in startIdx ..< n.len:
var arg = n.sons[i]
if n.sons[i].kind == nkExprEqExpr:
add(result, renderTree(n.sons[i].sons[0]))
add(result, ": ")
for i in startIdx..<n.len:
var arg = n[i]
if n[i].kind == nkExprEqExpr:
result.add(renderTree(n[i][0]))
result.add(": ")
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo}:
# XXX we really need to 'tryExpr' here!
arg = c.semOperand(c, n.sons[i].sons[1])
n.sons[i].typ = arg.typ
n.sons[i].sons[1] = arg
arg = c.semOperand(c, n[i][1])
n[i].typ = arg.typ
n[i][1] = arg
else:
if arg.typ.isNil and arg.kind notin {nkStmtList, nkDo, nkElse,
nkOfBranch, nkElifBranch,
nkExceptBranch}:
arg = c.semOperand(c, n.sons[i])
n.sons[i] = arg
arg = c.semOperand(c, n[i])
n[i] = arg
if arg.typ != nil and arg.typ.kind == tyError: return
add(result, argTypeToString(arg, prefer))
if i != len(n) - 1: add(result, ", ")
result.add(argTypeToString(arg, prefer))
if i != n.len - 1: result.add(", ")
proc typeRel*(c: var TCandidate, f, aOrig: PType,
flags: TTypeRelFlags = {}): TTypeRelation
@ -345,7 +345,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
if c.isNoCall: result = t
else: result = nil
of tySequence, tySet:
if t.sons[0].kind == tyEmpty: result = nil
if t[0].kind == tyEmpty: result = nil
else: result = t
of tyGenericParam, tyAnything:
result = t
@ -362,7 +362,7 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType =
of tyOwned:
# bug #11257: the comparison system.`==`[T: proc](x, y: T) works
# better without the 'owned' type:
if f != nil and f.len > 0 and f.sons[0].skipTypes({tyBuiltInTypeClass}).kind == tyProc:
if f != nil and f.len > 0 and f[0].skipTypes({tyBuiltInTypeClass}).kind == tyProc:
result = t.lastSon
else:
result = t
@ -440,10 +440,10 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
proc genericParamPut(c: var TCandidate; last, fGenericOrigin: PType) =
if fGenericOrigin != nil and last.kind == tyGenericInst and
last.len-1 == fGenericOrigin.len:
for i in 1 ..< len(fGenericOrigin):
let x = PType(idTableGet(c.bindings, fGenericOrigin.sons[i]))
for i in 1..<fGenericOrigin.len:
let x = PType(idTableGet(c.bindings, fGenericOrigin[i]))
if x == nil:
put(c, fGenericOrigin.sons[i], last.sons[i])
put(c, fGenericOrigin[i], last[i])
proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
var t = a
@ -452,7 +452,7 @@ proc isObjectSubtype(c: var TCandidate; a, f, fGenericOrigin: PType): int =
var last = a
while t != nil and not sameObjectTypes(f, t):
assert t.kind == tyObject
t = t.sons[0]
t = t[0]
if t == nil: break
last = t
t = skipTypes(t, skipPtrs)
@ -473,7 +473,7 @@ proc skipToObject(t: PType; skipped: var SkippedPtr): PType =
while r != nil:
case r.kind
of tyGenericInvocation:
r = r.sons[0]
r = r[0]
of tyRef:
inc ptrs
skipped = skippedRef
@ -500,7 +500,7 @@ proc isGenericSubtype(c: var TCandidate; a, f: PType, d: var int, fGenericOrigin
# XXX sameObjectType can return false here. Need to investigate
# why that is but sameObjectType does way too much work here anyway.
while t != nil and r.sym != t.sym and askip == fskip:
t = t.sons[0]
t = t[0]
if t == nil: break
last = t
t = t.skipToObject(askip)
@ -518,22 +518,22 @@ proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
result = isNone
if sameType(f, a):
result = isEqual
elif len(a) == len(f):
elif a.len == f.len:
result = isEqual
let firstField = if f.kind == tyTuple: 0
else: 1
for i in firstField ..< len(f):
var m = typeRel(c, f.sons[i], a.sons[i])
for i in firstField..<f.len:
var m = typeRel(c, f[i], a[i])
if m < isSubtype: return isNone
result = minRel(result, m)
if f.n != nil and a.n != nil:
for i in 0 ..< len(f.n):
for i in 0..<f.n.len:
# check field names:
if f.n.sons[i].kind != nkSym: return isNone
elif a.n.sons[i].kind != nkSym: return isNone
if f.n[i].kind != nkSym: return isNone
elif a.n[i].kind != nkSym: return isNone
else:
var x = f.n.sons[i].sym
var y = a.n.sons[i].sym
var x = f.n[i].sym
var y = a.n[i].sym
if f.kind == tyObject and typeRel(c, x.typ, y.typ) < isSubtype:
return isNone
if x.name.id != y.name.id: return isNone
@ -552,7 +552,7 @@ proc inconsistentVarTypes(f, a: PType): bool {.inline.} =
proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
## For example we have:
## .. code-block:: nim
##..code-block:: nim
## proc myMap[T,S](sIn: seq[T], f: proc(x: T): S): seq[S] = ...
## proc innerProc[Q,W](q: Q): W = ...
## And we want to match: myMap(@[1,2,3], innerProc)
@ -607,7 +607,7 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
case a.kind
of tyProc:
if len(f) != len(a): return
if f.len != a.len: return
result = isEqual # start with maximum; also correct for no
# params at all
@ -617,15 +617,15 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
# Note: We have to do unification for the parameters before the
# return type!
for i in 1 ..< f.len:
checkParam(f.sons[i], a.sons[i])
for i in 1..<f.len:
checkParam(f[i], a[i])
if f.sons[0] != nil:
if a.sons[0] != nil:
checkParam(f.sons[0], a.sons[0])
if f[0] != nil:
if a[0] != nil:
checkParam(f[0], a[0])
else:
return isNone
elif a.sons[0] != nil:
elif a[0] != nil:
return isNone
if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
@ -687,20 +687,20 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
openScope(c)
matchedConceptContext.candidateType = a
typeClass[0].sons[0] = a
typeClass[0][0] = a
c.matchedConcept = addr(matchedConceptContext)
defer:
c.matchedConcept = prevMatchedConcept
typeClass[0].sons[0] = prevCandidateType
typeClass[0][0] = prevCandidateType
closeScope(c)
var typeParams: seq[(PSym, PType)]
if ff.kind == tyUserTypeClassInst:
for i in 1 ..< (ff.len - 1):
for i in 1..<(ff.len - 1):
var
typeParamName = ff.base.sons[i-1].sym.name
typ = ff.sons[i]
typeParamName = ff.base[i-1].sym.name
typ = ff[i]
param: PSym
alreadyBound = PType(idTableGet(m.bindings, typ))
@ -944,8 +944,8 @@ proc isCovariantPtr(c: var TCandidate, f, a: PType): bool =
let body = f.base
return body == a.base and
a.len == 3 and
tfWeakCovariant notin body.sons[0].flags and
baseTypesCheck(f.sons[1], a.sons[1])
tfWeakCovariant notin body[0].flags and
baseTypesCheck(f[1], a[1])
else:
return false
@ -1038,7 +1038,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
result = typeRel(c, aOrig.base, candidate)
if result != isNone:
c.inferredTypes.add aOrig
aOrig.sons.add candidate
aOrig.add candidate
result = isEqual
return
@ -1146,7 +1146,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
# that may appear in the range:
for i in 0..1:
if f.n[i].kind == nkStaticExpr:
f.n.sons[i] = tryResolvingStaticExpr(c, f.n[i])
f.n[i] = tryResolvingStaticExpr(c, f.n[i])
result = typeRangeRel(f, a)
else:
if skipTypes(f, {tyRange}).kind == a.kind:
@ -1174,20 +1174,20 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyArray:
case a.kind
of tyArray:
var fRange = f.sons[0]
var aRange = a.sons[0]
var fRange = f[0]
var aRange = a[0]
if fRange.kind == tyGenericParam:
var prev = PType(idTableGet(c.bindings, fRange))
if prev == nil:
put(c, fRange, a.sons[0])
put(c, fRange, a[0])
fRange = a
else:
fRange = prev
let ff = f.sons[1].skipTypes({tyTypeDesc})
let ff = f[1].skipTypes({tyTypeDesc})
# This typeDesc rule is wrong, see bug #7331
let aa = a.sons[1] #.skipTypes({tyTypeDesc})
let aa = a[1] #.skipTypes({tyTypeDesc})
if f.sons[0].kind != tyGenericParam and aa.kind == tyEmpty:
if f[0].kind != tyGenericParam and aa.kind == tyEmpty:
result = isGeneric
else:
result = typeRel(c, ff, aa)
@ -1220,7 +1220,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
if f.kind == tyVarargs:
if tfVarargs in a.flags:
return typeRel(c, f.base, a.lastSon)
if f.sons[0].kind == tyTyped: return
if f[0].kind == tyTyped: return
template matchArrayOrSeq(aBase: PType) =
let ff = f.base
@ -1239,29 +1239,29 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
result = typeRel(c, base(f), base(a))
if result < isGeneric: result = isNone
of tyArray:
if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
if (f[0].kind != tyGenericParam) and (a[1].kind == tyEmpty):
return isSubtype
matchArrayOrSeq(a.sons[1])
matchArrayOrSeq(a[1])
of tySequence:
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
if (f[0].kind != tyGenericParam) and (a[0].kind == tyEmpty):
return isConvertible
matchArrayOrSeq(a.sons[0])
matchArrayOrSeq(a[0])
of tyString:
if f.kind == tyOpenArray:
if f.sons[0].kind == tyChar:
if f[0].kind == tyChar:
result = isConvertible
elif f.sons[0].kind == tyGenericParam and a.len > 0 and
elif f[0].kind == tyGenericParam and a.len > 0 and
typeRel(c, base(f), base(a)) >= isGeneric:
result = isConvertible
else: discard
of tySequence:
case a.kind
of tySequence:
if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
if (f[0].kind != tyGenericParam) and (a[0].kind == tyEmpty):
result = isSubtype
else:
let ff = f.sons[0]
let aa = a.sons[0]
let ff = f[0]
let aa = a[0]
result = typeRel(c, ff, aa)
if result < isGeneric:
if nimEnableCovariance and
@ -1277,11 +1277,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
else: discard
of tyOrdinal:
if isOrdinalType(a):
var x = if a.kind == tyOrdinal: a.sons[0] else: a
if f.sons[0].kind == tyNone:
var x = if a.kind == tyOrdinal: a[0] else: a
if f[0].kind == tyNone:
result = isGeneric
else:
result = typeRel(c, f.sons[0], x)
result = typeRel(c, f[0], x)
if result < isGeneric: result = isNone
elif a.kind == tyGenericParam:
result = isGeneric
@ -1314,10 +1314,10 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
elif c.coerceDistincts: result = typeRel(c, f.base, a)
of tySet:
if a.kind == tySet:
if f.sons[0].kind != tyGenericParam and a.sons[0].kind == tyEmpty:
if f[0].kind != tyGenericParam and a[0].kind == tyEmpty:
result = isSubtype
else:
result = typeRel(c, f.sons[0], a.sons[0])
result = typeRel(c, f[0], a[0])
if result <= isConvertible:
result = isNone # BUGFIX!
of tyPtr, tyRef:
@ -1325,8 +1325,8 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
if a.kind == f.kind:
# ptr[R, T] can be passed to ptr[T], but not the other way round:
if a.len < f.len: return isNone
for i in 0..f.len-2:
if typeRel(c, f.sons[i], a.sons[i]) == isNone: return isNone
for i in 0..<f.len-1:
if typeRel(c, f[i], a[i]) == isNone: return isNone
result = typeRel(c, f.lastSon, a.lastSon, flags + {trNoCovariance})
subtypeCheck()
if result <= isIntConv: result = isNone
@ -1384,13 +1384,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyPtr:
# ptr[Tag, char] is not convertible to 'cstring' for now:
if a.len == 1:
let pointsTo = a.sons[0].skipTypes(abstractInst)
let pointsTo = a[0].skipTypes(abstractInst)
if pointsTo.kind == tyChar: result = isConvertible
elif pointsTo.kind == tyUncheckedArray and pointsTo.sons[0].kind == tyChar:
elif pointsTo.kind == tyUncheckedArray and pointsTo[0].kind == tyChar:
result = isConvertible
elif pointsTo.kind == tyArray and firstOrd(nil, pointsTo.sons[0]) == 0 and
skipTypes(pointsTo.sons[0], {tyRange}).kind in {tyInt..tyInt64} and
pointsTo.sons[1].kind == tyChar:
elif pointsTo.kind == tyArray and firstOrd(nil, pointsTo[0]) == 0 and
skipTypes(pointsTo[0], {tyRange}).kind in {tyInt..tyInt64} and
pointsTo[1].kind == tyChar:
result = isConvertible
else: discard
@ -1416,14 +1416,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
# YYYY
result = isEqual
for i in 1 .. rootf.len-2:
let ff = rootf.sons[i]
let aa = roota.sons[i]
for i in 1..<rootf.len-1:
let ff = rootf[i]
let aa = roota[i]
let res = typeRel(c, ff, aa, nextFlags)
if res != isEqual: result = isGeneric
if res notin {isEqual, isGeneric}:
if trNoCovariance notin flags and ff.kind == aa.kind:
let paramFlags = rootf.base.sons[i-1].flags
let paramFlags = rootf.base[i-1].flags
hasCovariance =
if tfCovariant in paramFlags:
if tfWeakCovariant in paramFlags:
@ -1471,7 +1471,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyGenericBody:
considerPreviousT:
if a == f or a.kind == tyGenericInst and a.sons[0] == f:
if a == f or a.kind == tyGenericInst and a[0] == f:
bindingRet isGeneric
let ff = lastSon(f)
if ff != nil:
@ -1480,7 +1480,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyGenericInvocation:
var x = a.skipGenericAlias
var preventHack = false
if x.kind == tyOwned and f.sons[0].kind != tyOwned:
if x.kind == tyOwned and f[0].kind != tyOwned:
preventHack = true
x = x.lastSon
# XXX: This is very hacky. It should be moved back into liftTypeParam
@ -1492,21 +1492,21 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
return typeRel(c, inst, a)
var depth = 0
if x.kind == tyGenericInvocation or f.sons[0].kind != tyGenericBody:
if x.kind == tyGenericInvocation or f[0].kind != tyGenericBody:
#InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
# simply no match for now:
discard
elif x.kind == tyGenericInst and f.sons[0] == x.sons[0] and
len(x) - 1 == len(f):
for i in 1 ..< len(f):
if x.sons[i].kind == tyGenericParam:
elif x.kind == tyGenericInst and f[0] == x[0] and
x.len - 1 == f.len:
for i in 1..<f.len:
if x[i].kind == tyGenericParam:
internalError(c.c.graph.config, "wrong instantiated type!")
elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype:
elif typeRel(c, f[i], x[i]) <= isSubtype:
# Workaround for regression #4589
if f.sons[i].kind != tyTypeDesc: return
if f[i].kind != tyTypeDesc: return
result = isGeneric
elif x.kind == tyGenericInst and isGenericSubtype(c, x, f, depth, f) and
(len(x) - 1 == len(f)):
(x.len - 1 == f.len):
# do not recurse here in order to not K bind twice for this code:
#
# type
@ -1518,7 +1518,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
c.inheritancePenalty += depth
result = isGeneric
else:
let genericBody = f.sons[0]
let genericBody = f[0]
var askip = skippedNone
var fskip = skippedNone
let aobj = x.skipToObject(askip)
@ -1538,14 +1538,14 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
# var it1 = internalFind(root, 312) # cannot instantiate: 'D'
#
# we steal the generic parameters from the tyGenericBody:
for i in 1 ..< len(f):
let x = PType(idTableGet(c.bindings, genericBody.sons[i-1]))
for i in 1..<f.len:
let x = PType(idTableGet(c.bindings, genericBody[i-1]))
if x == nil:
discard "maybe fine (for eg. a==tyNil)"
elif x.kind in {tyGenericInvocation, tyGenericParam}:
internalError(c.c.graph.config, "wrong instantiated type!")
else:
let key = f.sons[i]
let key = f[i]
let old = PType(idTableGet(c.bindings, key))
if old == nil:
put(c, key, x)
@ -1612,7 +1612,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
of tyBuiltInTypeClass:
considerPreviousT:
let targetKind = f.sons[0].kind
let targetKind = f[0].kind
let effectiveArgType = a.skipTypes({tyRange, tyGenericInst,
tyBuiltInTypeClass, tyAlias, tySink, tyOwned})
let typeClassMatches = targetKind == effectiveArgType.kind and
@ -1643,9 +1643,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
let roota = a.skipGenericAlias
let rootf = f.lastSon.skipGenericAlias
if a.kind == tyGenericInst and roota.base == rootf.base:
for i in 1 .. rootf.len-2:
let ff = rootf.sons[i]
let aa = roota.sons[i]
for i in 1..<rootf.len-1:
let ff = rootf[i]
let aa = roota[i]
result = typeRel(c, ff, aa)
if result == isNone: return
if ff.kind == tyRange and result != isEqual: return isNone
@ -1689,9 +1689,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
result = isNone
else:
# check if 'T' has a constraint as in 'proc p[T: Constraint](x: T)'
if f.len > 0 and f.sons[0].kind != tyNone:
if f.len > 0 and f[0].kind != tyNone:
let oldInheritancePenalty = c.inheritancePenalty
result = typeRel(c, f.sons[0], a, flags + {trDontBind})
result = typeRel(c, f[0], a, flags + {trDontBind})
if doBind and result notin {isNone, isGeneric}:
let concrete = concreteType(c, a, f)
if concrete == nil: return isNone
@ -1772,7 +1772,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
result = typeRel(c, f.base, a)
if result != isNone:
c.inferredTypes.add f
f.sons.add a
f.add a
of tyTypeDesc:
var prev = PType(idTableGet(c.bindings, f))
@ -1846,8 +1846,7 @@ when false:
echo f, " <- ", aOrig, " res ", result
proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
var m: TCandidate
initCandidate(c, m, f)
var m = newCandidate(c, f)
result = typeRel(m, f, a)
proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
@ -1870,15 +1869,15 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
else:
result.typ = f
if result.typ == nil: internalError(c.graph.config, arg.info, "implicitConv")
addSon(result, c.graph.emptyNode)
addSon(result, arg)
result.add c.graph.emptyNode
result.add arg
proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
arg: PNode): PNode =
result = nil
for i in 0 ..< len(c.converters):
var src = c.converters[i].typ.sons[1]
var dest = c.converters[i].typ.sons[0]
for i in 0..<c.converters.len:
var src = c.converters[i].typ[1]
var dest = c.converters[i].typ[0]
# for generic type converters we need to check 'src <- a' before
# 'f <- dest' in order to not break the unification:
# see tests/tgenericconverter:
@ -1902,7 +1901,7 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
s.typ = c.converters[i].typ
s.info = arg.info
result = newNodeIT(nkHiddenCallConv, arg.info, dest)
addSon(result, s)
result.add s
# We build the call expression by ourselves in order to avoid passing this
# expression trough the semantic check phase once again so let's make sure
# it is correct
@ -1912,10 +1911,10 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
elif src.kind == tyVar:
# Analyse the converter return type
param = newNodeIT(nkHiddenAddr, arg.info, s.typ[1])
param.addSon(copyTree(arg))
param.add copyTree(arg)
else:
param = copyTree(arg)
addSon(result, param)
result.add param
if dest.kind in {tyVar, tyLent}:
dest.flags.incl tfVarIsPtr
@ -1942,7 +1941,7 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
if result != nil:
if result.typ == nil: return nil
# resulting type must be consistent with the other arguments:
var r = typeRel(m, f.sons[0], result.typ)
var r = typeRel(m, f[0], result.typ)
if r < isGeneric: return nil
if result.kind == nkCall: result.kind = nkHiddenCallConv
inc(m.convMatches)
@ -1962,8 +1961,8 @@ proc incMatches(m: var TCandidate; r: TTypeRelation; convMatch = 1) =
of isNone: discard
template matchesVoidProc(t: PType): bool =
(t.kind == tyProc and t.len == 1 and t.sons[0] == nil) or
(t.kind == tyBuiltInTypeClass and t.sons[0].kind == tyProc)
(t.kind == tyProc and t.len == 1 and t[0] == nil) or
(t.kind == tyBuiltInTypeClass and t[0].kind == tyProc)
proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
argSemantized, argOrig: PNode): PNode =
@ -2174,31 +2173,31 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
# this correctly is inefficient. We have to copy `m` here to be able to
# roll back the side effects of the unification algorithm.
let c = m.c
var x, y, z: TCandidate
initCandidate(c, x, m.callee)
initCandidate(c, y, m.callee)
initCandidate(c, z, m.callee)
var
x = newCandidate(c, m.callee)
y = newCandidate(c, m.callee)
z = newCandidate(c, m.callee)
x.calleeSym = m.calleeSym
y.calleeSym = m.calleeSym
z.calleeSym = m.calleeSym
var best = -1
for i in 0 ..< arg.len:
if arg.sons[i].sym.kind in {skProc, skFunc, skMethod, skConverter,
for i in 0..<arg.len:
if arg[i].sym.kind in {skProc, skFunc, skMethod, skConverter,
skIterator, skMacro, skTemplate}:
copyCandidate(z, m)
z.callee = arg.sons[i].typ
z.callee = arg[i].typ
if tfUnresolved in z.callee.flags: continue
z.calleeSym = arg.sons[i].sym
#if arg.sons[i].sym.name.s == "cmp":
z.calleeSym = arg[i].sym
#if arg[i].sym.name.s == "cmp":
# ggDebug = true
# echo "CALLLEEEEEEEE A ", typeToString(z.callee)
# XXX this is still all wrong: (T, T) should be 2 generic matches
# and (int, int) 2 exact matches, etc. Essentially you cannot call
# typeRel here and expect things to work!
let r = typeRel(z, f, arg.sons[i].typ)
let r = typeRel(z, f, arg[i].typ)
incMatches(z, r, 2)
#if arg.sons[i].sym.name.s == "cmp": # and arg.info.line == 606:
# echo "M ", r, " ", arg.info, " ", typeToString(arg.sons[i].sym.typ)
#if arg[i].sym.name.s == "cmp": # and arg.info.line == 606:
# echo "M ", r, " ", arg.info, " ", typeToString(arg[i].sym.typ)
# writeMatches(z)
if r != isNone:
z.state = csMatch
@ -2226,10 +2225,9 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
else: result = nil
else:
# only one valid interpretation found:
markUsed(m.c, arg.info, arg.sons[best].sym)
onUse(arg.info, arg.sons[best].sym)
result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
argOrig)
markUsed(m.c, arg.info, arg[best].sym)
onUse(arg.info, arg[best].sym)
result = paramTypesMatchAux(m, f, arg[best].typ, arg[best], argOrig)
when false:
if m.calleeSym != nil and m.calleeSym.name.s == "[]":
echo m.c.config $ arg.info, " for ", m.calleeSym.name.s, " ", m.c.config $ m.calleeSym.info
@ -2239,10 +2237,10 @@ proc setSon(father: PNode, at: int, son: PNode) =
let oldLen = father.len
if oldLen <= at:
setLen(father.sons, at + 1)
father.sons[at] = son
father[at] = son
# insert potential 'void' parameters:
#for i in oldLen ..< at:
# father.sons[i] = newNodeIT(nkEmpty, son.info, getSysType(tyVoid))
#for i in oldLen..<at:
# father[i] = newNodeIT(nkEmpty, son.info, getSysType(tyVoid))
# we are allowed to modify the calling node in the 'prepare*' procs:
proc prepareOperand(c: PContext; formal: PType; a: PNode): PNode =
@ -2271,9 +2269,9 @@ proc prepareOperand(c: PContext; a: PNode): PNode =
considerGenSyms(c, result)
proc prepareNamedParam(a: PNode; c: PContext) =
if a.sons[0].kind != nkIdent:
var info = a.sons[0].info
a.sons[0] = newIdentNode(considerQuotedIdent(c, a.sons[0]), info)
if a[0].kind != nkIdent:
var info = a[0].info
a[0] = newIdentNode(considerQuotedIdent(c, a[0]), info)
proc arrayConstr(c: PContext, n: PNode): PType =
result = newTypeS(tyArray, c)
@ -2288,10 +2286,10 @@ proc arrayConstr(c: PContext, info: TLineInfo): PType =
proc incrIndexType(t: PType) =
assert t.kind == tyArray
inc t.sons[0].n.sons[1].intVal
inc t[0].n[1].intVal
template isVarargsUntyped(x): untyped =
x.kind == tyVarargs and x.sons[0].kind == tyUntyped
x.kind == tyVarargs and x[0].kind == tyUntyped
proc matchesAux(c: PContext, n, nOrig: PNode,
m: var TCandidate, marker: var IntSet) =
@ -2333,37 +2331,37 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
m.call = newNodeI(n.kind, n.info)
m.call.typ = base(m.callee) # may be nil
var formalLen = m.callee.n.len
addSon(m.call, n.sons[0])
m.call.add n[0]
var container: PNode = nil # constructed container
formal = if formalLen > 1: m.callee.n.sons[1].sym else: nil
formal = if formalLen > 1: m.callee.n[1].sym else: nil
while a < n.len:
if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
formal = m.callee.n.sons[f].sym
formal = m.callee.n[f].sym
incl(marker, formal.position)
if n.sons[a].kind == nkHiddenStdConv:
doAssert n.sons[a].sons[0].kind == nkEmpty and
n.sons[a].sons[1].kind in {nkBracket, nkArgList}
if n[a].kind == nkHiddenStdConv:
doAssert n[a][0].kind == nkEmpty and
n[a][1].kind in {nkBracket, nkArgList}
# Steal the container and pass it along
setSon(m.call, formal.position + 1, n.sons[a].sons[1])
setSon(m.call, formal.position + 1, n[a][1])
else:
if container.isNil:
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
container = newNodeIT(nkArgList, n[a].info, arrayConstr(c, n.info))
setSon(m.call, formal.position + 1, container)
else:
incrIndexType(container.typ)
addSon(container, n.sons[a])
elif n.sons[a].kind == nkExprEqExpr:
container.add n[a]
elif n[a].kind == nkExprEqExpr:
# named param
m.firstMismatch.kind = kUnknownNamedParam
# check if m.callee has such a param:
prepareNamedParam(n.sons[a], c)
if n.sons[a].sons[0].kind != nkIdent:
localError(c.config, n.sons[a].info, "named parameter has to be an identifier")
prepareNamedParam(n[a], c)
if n[a][0].kind != nkIdent:
localError(c.config, n[a].info, "named parameter has to be an identifier")
noMatch()
return
formal = getNamedParamFromList(m.callee.n, n.sons[a].sons[0].ident)
formal = getNamedParamFromList(m.callee.n, n[a][0].ident)
if formal == nil:
# no error message!
noMatch()
@ -2374,24 +2372,24 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
# we used to produce 'errCannotBindXTwice' here but see
# bug #3836 of why that is not sound (other overload with
# different parameter names could match later on):
when false: localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
when false: localError(n[a].info, errCannotBindXTwice, formal.name.s)
noMatch()
return
m.baseTypeMatch = false
m.typedescMatched = false
n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1])
n.sons[a].typ = n.sons[a].sons[1].typ
arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
n.sons[a].sons[1], n.sons[a].sons[1])
n[a][1] = prepareOperand(c, formal.typ, n[a][1])
n[a].typ = n[a][1].typ
arg = paramTypesMatch(m, formal.typ, n[a].typ,
n[a][1], n[a][1])
m.firstMismatch.kind = kTypeMismatch
if arg == nil:
noMatch()
return
checkConstraint(n.sons[a].sons[1])
checkConstraint(n[a][1])
if m.baseTypeMatch:
#assert(container == nil)
container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
addSon(container, arg)
container = newNodeIT(nkBracket, n[a].info, arrayConstr(c, arg))
container.add arg
setSon(m.call, formal.position + 1, container)
if f != formalLen - 1: container = nil
else:
@ -2404,13 +2402,13 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
if tfVarargs in m.callee.flags:
# is ok... but don't increment any counters...
# we have no formal here to snoop at:
n.sons[a] = prepareOperand(c, n.sons[a])
if skipTypes(n.sons[a].typ, abstractVar-{tyTypeDesc}).kind==tyString:
addSon(m.call, implicitConv(nkHiddenStdConv,
getSysType(c.graph, n.sons[a].info, tyCString),
copyTree(n.sons[a]), m, c))
n[a] = prepareOperand(c, n[a])
if skipTypes(n[a].typ, abstractVar-{tyTypeDesc}).kind==tyString:
m.call.add implicitConv(nkHiddenStdConv,
getSysType(c.graph, n[a].info, tyCString),
copyTree(n[a]), m, c)
else:
addSon(m.call, copyTree(n.sons[a]))
m.call.add copyTree(n[a])
elif formal != nil and formal.typ.kind == tyVarargs:
m.firstMismatch.kind = kTypeMismatch
# beware of the side-effects in 'prepareOperand'! So only do it for
@ -2418,13 +2416,13 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
m.baseTypeMatch = false
m.typedescMatched = false
incl(marker, formal.position)
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
n.sons[a], nOrig.sons[a])
n[a] = prepareOperand(c, formal.typ, n[a])
arg = paramTypesMatch(m, formal.typ, n[a].typ,
n[a], nOrig[a])
if arg != nil and m.baseTypeMatch and container != nil:
addSon(container, arg)
container.add arg
incrIndexType(container.typ)
checkConstraint(n.sons[a])
checkConstraint(n[a])
else:
noMatch()
return
@ -2433,32 +2431,32 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
noMatch()
return
else:
if m.callee.n.sons[f].kind != nkSym:
internalError(c.config, n.sons[a].info, "matches")
if m.callee.n[f].kind != nkSym:
internalError(c.config, n[a].info, "matches")
noMatch()
return
formal = m.callee.n.sons[f].sym
formal = m.callee.n[f].sym
m.firstMismatch.kind = kTypeMismatch
if containsOrIncl(marker, formal.position) and container.isNil:
m.firstMismatch.kind = kPositionalAlreadyGiven
# positional param already in namedParams: (see above remark)
when false: localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
when false: localError(n[a].info, errCannotBindXTwice, formal.name.s)
noMatch()
return
if formal.typ.isVarargsUntyped:
if container.isNil:
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
container = newNodeIT(nkArgList, n[a].info, arrayConstr(c, n.info))
setSon(m.call, formal.position + 1, container)
else:
incrIndexType(container.typ)
addSon(container, n.sons[a])
container.add n[a]
else:
m.baseTypeMatch = false
m.typedescMatched = false
n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
n.sons[a], nOrig.sons[a])
n[a] = prepareOperand(c, formal.typ, n[a])
arg = paramTypesMatch(m, formal.typ, n[a].typ,
n[a], nOrig[a])
if arg == nil:
noMatch()
return
@ -2466,11 +2464,11 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
assert formal.typ.kind == tyVarargs
#assert(container == nil)
if container.isNil:
container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
container = newNodeIT(nkBracket, n[a].info, arrayConstr(c, arg))
container.typ.flags.incl tfVarargs
else:
incrIndexType(container.typ)
addSon(container, arg)
container.add arg
setSon(m.call, formal.position + 1,
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
#if f != formalLen - 1: container = nil
@ -2487,11 +2485,11 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
# a container
#assert arg.kind == nkHiddenStdConv # for 'nim check'
# this assertion can be off
localError(c.config, n.sons[a].info, "cannot convert $1 to $2" % [
typeToString(n.sons[a].typ), typeToString(formal.typ) ])
localError(c.config, n[a].info, "cannot convert $1 to $2" % [
typeToString(n[a].typ), typeToString(formal.typ) ])
noMatch()
return
checkConstraint(n.sons[a])
checkConstraint(n[a])
inc(a)
# for some edge cases (see tdont_return_unowned_from_owned test case)
m.firstMismatch.arg = a
@ -2500,8 +2498,8 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
proc semFinishOperands*(c: PContext, n: PNode) =
# this needs to be called to ensure that after overloading resolution every
# argument has been sem'checked:
for i in 1 ..< n.len:
n.sons[i] = prepareOperand(c, n.sons[i])
for i in 1..<n.len:
n[i] = prepareOperand(c, n[i])
proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
# for 'suggest' support:
@ -2522,9 +2520,8 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
matchesAux(c, n, nOrig, m, marker)
if m.state == csNoMatch: return
# check that every formal parameter got a value:
var f = 1
while f < len(m.callee.n):
var formal = m.callee.n.sons[f].sym
for f in 1..<m.callee.n.len:
var formal = m.callee.n[f].sym
if not containsOrIncl(marker, formal.position):
if formal.ast == nil:
if formal.typ.kind == tyVarargs:
@ -2563,15 +2560,13 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
put(m, formal.typ, defaultValue.typ)
defaultValue.flags.incl nfDefaultParam
setSon(m.call, formal.position + 1, defaultValue)
inc(f)
# forget all inferred types if the overload matching failed
if m.state == csNoMatch:
for t in m.inferredTypes:
if t.len > 1: t.sons.setLen 1
proc argtypeMatches*(c: PContext, f, a: PType, fromHlo = false): bool =
var m: TCandidate
initCandidate(c, m, f)
var m = newCandidate(c, f)
let res = paramTypesMatch(m, f, a, c.graph.emptyNode, nil)
#instantiateGenericConverters(c, res, m)
# XXX this is used by patterns.nim too; I think it's better to not
@ -2583,13 +2578,12 @@ proc argtypeMatches*(c: PContext, f, a: PType, fromHlo = false): bool =
res != nil and m.convMatches == 0 and m.intConvMatches in [0, 256]
proc instTypeBoundOp*(c: PContext; dc: PSym; t: PType; info: TLineInfo;
op: TTypeAttachedOp; col: int): PSym {.procvar.} =
var m: TCandidate
initCandidate(c, m, dc.typ)
op: TTypeAttachedOp; col: int): PSym =
var m = newCandidate(c, dc.typ)
if col >= dc.typ.len:
localError(c.config, info, "cannot instantiate: '" & dc.name.s & "'")
return nil
var f = dc.typ.sons[col]
var f = dc.typ[col]
if op == attachedDeepCopy:
if f.kind in {tyRef, tyPtr}: f = f.lastSon
@ -2632,8 +2626,8 @@ tests:
result = newType(tyArray, dummyOwner)
var n = newNodeI(nkRange, UnknownLineInfo())
addSon(n, newIntNode(nkIntLit, 0))
addSon(n, newIntNode(nkIntLit, x))
n.add newIntNode(nkIntLit, 0)
n.add newIntNode(nkIntLit, x)
let range = newType(tyRange, dummyOwner)
result.rawAddSon(range)
@ -2660,8 +2654,7 @@ tests:
T2.sym.position = 1
setup:
var c: TCandidate
initCandidate(nil, c, nil)
var c = newCandidate(nil, nil)
template yes(x, y) =
test astToStr(x) & " is " & astToStr(y):