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

@ -23,11 +23,11 @@ proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
result = n
elif diff < 0:
result = newNodeIT(nkObjUpConv, n.info, d)
addSon(result, n)
result.add n
if downcast: internalError(conf, n.info, "cgmeth.genConv: no upcast allowed")
elif diff > 0:
result = newNodeIT(nkObjDownConv, n.info, d)
addSon(result, n)
result.add n
if not downcast:
internalError(conf, n.info, "cgmeth.genConv: no downcast allowed")
else:
@ -44,26 +44,26 @@ proc getDispatcher*(s: PSym): PSym =
proc methodCall*(n: PNode; conf: ConfigRef): PNode =
result = n
# replace ordinary method by dispatcher method:
let disp = getDispatcher(result.sons[0].sym)
let disp = getDispatcher(result[0].sym)
if disp != nil:
result.sons[0].sym = disp
result[0].sym = disp
# change the arguments to up/downcasts to fit the dispatcher's parameters:
for i in 1 ..< len(result):
result.sons[i] = genConv(result.sons[i], disp.typ.sons[i], true, conf)
for i in 1..<result.len:
result[i] = genConv(result[i], disp.typ[i], true, conf)
else:
localError(conf, n.info, "'" & $result.sons[0] & "' lacks a dispatcher")
localError(conf, n.info, "'" & $result[0] & "' lacks a dispatcher")
type
MethodResult = enum No, Invalid, Yes
proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
if a.name.id != b.name.id: return
if len(a.typ) != len(b.typ):
if a.typ.len != b.typ.len:
return
for i in 1 ..< len(a.typ):
var aa = a.typ.sons[i]
var bb = b.typ.sons[i]
for i in 1..<a.typ.len:
var aa = a.typ[i]
var bb = b.typ[i]
while true:
aa = skipTypes(aa, {tyGenericInst, tyAlias})
bb = skipTypes(bb, {tyGenericInst, tyAlias})
@ -72,7 +72,7 @@ proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
bb = bb.lastSon
else:
break
if sameType(a.typ.sons[i], b.typ.sons[i]):
if sameType(a.typ[i], b.typ[i]):
if aa.kind == tyObject and result != Invalid:
result = Yes
elif aa.kind == tyObject and bb.kind == tyObject and (i == 1 or multiMethods):
@ -90,22 +90,22 @@ proc sameMethodBucket(a, b: PSym; multiMethods: bool): MethodResult =
return No
if result == Yes:
# check for return type:
if not sameTypeOrNil(a.typ.sons[0], b.typ.sons[0]):
if b.typ.sons[0] != nil and b.typ.sons[0].kind == tyUntyped:
if not sameTypeOrNil(a.typ[0], b.typ[0]):
if b.typ[0] != nil and b.typ[0].kind == tyUntyped:
# infer 'auto' from the base to make it consistent:
b.typ.sons[0] = a.typ.sons[0]
b.typ[0] = a.typ[0]
else:
return No
proc attachDispatcher(s: PSym, dispatcher: PNode) =
if dispatcherPos < s.ast.len:
# we've added a dispatcher already, so overwrite it
s.ast.sons[dispatcherPos] = dispatcher
s.ast[dispatcherPos] = dispatcher
else:
setLen(s.ast.sons, dispatcherPos+1)
if s.ast[resultPos] == nil:
s.ast[resultPos] = newNodeI(nkEmpty, s.info)
s.ast.sons[dispatcherPos] = dispatcher
s.ast[dispatcherPos] = dispatcher
proc createDispatcher(s: PSym): PSym =
var disp = copySym(s)
@ -115,16 +115,16 @@ proc createDispatcher(s: PSym): PSym =
# we can't inline the dispatcher itself (for now):
if disp.typ.callConv == ccInline: disp.typ.callConv = ccDefault
disp.ast = copyTree(s.ast)
disp.ast.sons[bodyPos] = newNodeI(nkEmpty, s.info)
disp.ast[bodyPos] = newNodeI(nkEmpty, s.info)
disp.loc.r = nil
if s.typ.sons[0] != nil:
if s.typ[0] != nil:
if disp.ast.len > resultPos:
disp.ast.sons[resultPos].sym = copySym(s.ast.sons[resultPos].sym)
disp.ast[resultPos].sym = copySym(s.ast[resultPos].sym)
else:
# We've encountered a method prototype without a filled-in
# resultPos slot. We put a placeholder in there that will
# be updated in fixupDispatcher().
disp.ast.addSon(newNodeI(nkEmpty, s.info))
disp.ast.add newNodeI(nkEmpty, s.info)
attachDispatcher(s, newSymNode(disp))
# attach to itself to prevent bugs:
attachDispatcher(disp, newSymNode(disp))
@ -137,8 +137,8 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
# the lock level of the dispatcher needs to be updated/checked
# against that of the method.
if disp.ast.len > resultPos and meth.ast.len > resultPos and
disp.ast.sons[resultPos].kind == nkEmpty:
disp.ast.sons[resultPos] = copyTree(meth.ast.sons[resultPos])
disp.ast[resultPos].kind == nkEmpty:
disp.ast[resultPos] = copyTree(meth.ast[resultPos])
# The following code works only with lock levels, so we disable
# it when they're not available.
@ -158,13 +158,12 @@ proc fixupDispatcher(meth, disp: PSym; conf: ConfigRef) =
disp.typ.lockLevel = meth.typ.lockLevel
proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
let L = len(g.methods)
var witness: PSym
for i in 0 ..< L:
for i in 0..<g.methods.len:
let disp = g.methods[i].dispatcher
case sameMethodBucket(disp, s, multimethods = optMultiMethods in g.config.globalOptions)
of Yes:
add(g.methods[i].methods, s)
g.methods[i].methods.add(s)
attachDispatcher(s, disp.ast[dispatcherPos])
fixupDispatcher(s, disp, g.config)
#echo "fixup ", disp.name.s, " ", disp.id
@ -178,7 +177,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
of Invalid:
if witness.isNil: witness = g.methods[i].methods[0]
# create a new dispatcher:
add(g.methods, (methods: @[s], dispatcher: createDispatcher(s)))
g.methods.add((methods: @[s], dispatcher: createDispatcher(s)))
#echo "adding ", s.info
#if fromCache:
# internalError(s.info, "no method dispatcher found")
@ -190,32 +189,32 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
proc relevantCol(methods: seq[PSym], col: int): bool =
# returns true iff the position is relevant
var t = methods[0].typ.sons[col].skipTypes(skipPtrs)
var t = methods[0].typ[col].skipTypes(skipPtrs)
if t.kind == tyObject:
for i in 1 .. high(methods):
let t2 = skipTypes(methods[i].typ.sons[col], skipPtrs)
for i in 1..high(methods):
let t2 = skipTypes(methods[i].typ[col], skipPtrs)
if not sameType(t2, t):
return true
proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
for col in 1 ..< len(a.typ):
for col in 1..<a.typ.len:
if contains(relevantCols, col):
var aa = skipTypes(a.typ.sons[col], skipPtrs)
var bb = skipTypes(b.typ.sons[col], skipPtrs)
var aa = skipTypes(a.typ[col], skipPtrs)
var bb = skipTypes(b.typ[col], skipPtrs)
var d = inheritanceDiff(aa, bb)
if (d != high(int)) and d != 0:
return d
proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
# we use shellsort here; fast and simple
var n = len(a)
var n = a.len
var h = 1
while true:
h = 3 * h + 1
if h > n: break
while true:
h = h div 3
for i in h ..< n:
for i in h..<n:
var v = a[i]
var j = i
while cmpSignatures(a[j - h], v, relevantCols) >= 0:
@ -228,71 +227,70 @@ proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
var base = methods[0].ast[dispatcherPos].sym
result = base
var paramLen = len(base.typ)
var paramLen = base.typ.len
var nilchecks = newNodeI(nkStmtList, base.info)
var disp = newNodeI(nkIfStmt, base.info)
var ands = getSysMagic(g, unknownLineInfo(), "and", mAnd)
var iss = getSysMagic(g, unknownLineInfo(), "of", mOf)
let boolType = getSysType(g, unknownLineInfo(), tyBool)
for col in 1 ..< paramLen:
for col in 1..<paramLen:
if contains(relevantCols, col):
let param = base.typ.n.sons[col].sym
let param = base.typ.n[col].sym
if param.typ.skipTypes(abstractInst).kind in {tyRef, tyPtr}:
addSon(nilchecks, newTree(nkCall,
newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(param)))
for meth in 0 .. high(methods):
nilchecks.add newTree(nkCall,
newSymNode(getCompilerProc(g, "chckNilDisp")), newSymNode(param))
for meth in 0..high(methods):
var curr = methods[meth] # generate condition:
var cond: PNode = nil
for col in 1 ..< paramLen:
for col in 1..<paramLen:
if contains(relevantCols, col):
var isn = newNodeIT(nkCall, base.info, boolType)
addSon(isn, newSymNode(iss))
let param = base.typ.n.sons[col].sym
addSon(isn, newSymNode(param))
addSon(isn, newNodeIT(nkType, base.info, curr.typ.sons[col]))
isn.add newSymNode(iss)
let param = base.typ.n[col].sym
isn.add newSymNode(param)
isn.add newNodeIT(nkType, base.info, curr.typ[col])
if cond != nil:
var a = newNodeIT(nkCall, base.info, boolType)
addSon(a, newSymNode(ands))
addSon(a, cond)
addSon(a, isn)
a.add newSymNode(ands)
a.add cond
a.add isn
cond = a
else:
cond = isn
let retTyp = base.typ.sons[0]
let retTyp = base.typ[0]
let call = newNodeIT(nkCall, base.info, retTyp)
addSon(call, newSymNode(curr))
for col in 1 ..< paramLen:
addSon(call, genConv(newSymNode(base.typ.n.sons[col].sym),
curr.typ.sons[col], false, g.config))
call.add newSymNode(curr)
for col in 1..<paramLen:
call.add genConv(newSymNode(base.typ.n[col].sym),
curr.typ[col], false, g.config)
var ret: PNode
if retTyp != nil:
var a = newNodeI(nkFastAsgn, base.info)
addSon(a, newSymNode(base.ast.sons[resultPos].sym))
addSon(a, call)
a.add newSymNode(base.ast[resultPos].sym)
a.add call
ret = newNodeI(nkReturnStmt, base.info)
addSon(ret, a)
ret.add a
else:
ret = call
if cond != nil:
var a = newNodeI(nkElifBranch, base.info)
addSon(a, cond)
addSon(a, ret)
addSon(disp, a)
a.add cond
a.add ret
disp.add a
else:
disp = ret
nilchecks.add disp
nilchecks.flags.incl nfTransf # should not be further transformed
result.ast.sons[bodyPos] = nilchecks
result.ast[bodyPos] = nilchecks
proc generateMethodDispatchers*(g: ModuleGraph): PNode =
result = newNode(nkStmtList)
for bucket in 0 ..< len(g.methods):
for bucket in 0..<g.methods.len:
var relevantCols = initIntSet()
for col in 1 ..< len(g.methods[bucket].methods[0].typ):
for col in 1..<g.methods[bucket].methods[0].typ.len:
if relevantCol(g.methods[bucket].methods, col): incl(relevantCols, col)
if optMultiMethods notin g.config.globalOptions:
# if multi-methods are not enabled, we are interested only in the first field
break
sortBucket(g.methods[bucket].methods, relevantCols)
addSon(result,
newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols)))
result.add newSymNode(genDispatcher(g, g.methods[bucket].methods, relevantCols))