Optimise pickBestCandidate: reduce heap allocations.
This commit is contained in:
parent
b0d9c11e53
commit
b0c12a7dc4
1 changed files with 43 additions and 61 deletions
|
|
@ -40,67 +40,49 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
filter: TSymKinds,
|
filter: TSymKinds,
|
||||||
best, alt: var TCandidate,
|
best, alt: var TCandidate,
|
||||||
errors: var CandidateErrors) =
|
errors: var CandidateErrors) =
|
||||||
var o: TOverloadIter
|
while true:
|
||||||
# thanks to the lazy semchecking for operands, we need to iterate over the
|
block pickAttempt:
|
||||||
# symbol table *before* any call to 'initCandidate' which might invoke
|
var o: TOverloadIter
|
||||||
# semExpr which might modify the symbol table in cases like
|
var sym = initOverloadIter(o, c, headSymbol)
|
||||||
# 'init(a, 1, (var b = new(Type2); b))'.
|
# Thanks to the lazy semchecking for operands, we need to check whether
|
||||||
var symx = initOverloadIter(o, c, headSymbol)
|
# 'initCandidate' modifies the symbol table (via semExpr).
|
||||||
let symScope = o.lastOverloadScope
|
# This can occur in cases like 'init(a, 1, (var b = new(Type2); b))'
|
||||||
|
let counterInitial = c.currentScope.symbols.counter
|
||||||
var syms: seq[tuple[a: PSym, b: int]] = @[]
|
# Initialise 'best' and 'alt' with the first available symbol
|
||||||
while symx != nil:
|
while sym != nil:
|
||||||
if symx.kind in filter:
|
if sym.kind in filter:
|
||||||
syms.add((symx, o.lastOverloadScope))
|
initCandidate(c, best, sym, initialBinding, o.lastOverloadScope)
|
||||||
symx = nextOverloadIter(o, c, headSymbol)
|
initCandidate(c, alt, sym, initialBinding, o.lastOverloadScope)
|
||||||
if syms.len == 0:
|
best.state = csNoMatch
|
||||||
when false:
|
break
|
||||||
if skIterator notin filter:
|
else:
|
||||||
# also try iterators, but these are 2nd class:
|
sym = nextOverloadIter(o, c, headSymbol)
|
||||||
symx = initOverloadIter(o, c, headSymbol)
|
var z: TCandidate
|
||||||
while symx != nil:
|
while sym != nil:
|
||||||
if symx.kind == skIterator:
|
if sym.kind notin filter:
|
||||||
syms.add((symx, 100))
|
sym = nextOverloadIter(o, c, headSymbol)
|
||||||
symx = nextOverloadIter(o, c, headSymbol)
|
continue
|
||||||
if syms.len == 0: return
|
determineType(c, sym)
|
||||||
else:
|
initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
|
||||||
return
|
if c.currentScope.symbols.counter != counterInitial: break pickAttempt
|
||||||
|
matches(c, n, orig, z)
|
||||||
var z: TCandidate
|
if errors != nil:
|
||||||
initCandidate(c, best, syms[0][0], initialBinding, symScope)
|
errors.safeAdd((sym, int z.mutabilityProblem))
|
||||||
initCandidate(c, alt, syms[0][0], initialBinding, symScope)
|
if z.errors != nil:
|
||||||
best.state = csNoMatch
|
for err in z.errors:
|
||||||
|
errors.add(err)
|
||||||
for i in 0 .. <syms.len:
|
if z.state == csMatch:
|
||||||
let sym = syms[i][0]
|
# little hack so that iterators are preferred over everything else:
|
||||||
determineType(c, sym)
|
if sym.kind == skIterator: inc(z.exactMatches, 200)
|
||||||
initCandidate(c, z, sym, initialBinding, syms[i][1])
|
case best.state
|
||||||
|
of csEmpty, csNoMatch: best = z
|
||||||
#if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
|
of csMatch:
|
||||||
# gDebug = true
|
var cmp = cmpCandidates(best, z)
|
||||||
matches(c, n, orig, z)
|
if cmp < 0: best = z # x is better than the best so far
|
||||||
if errors != nil:
|
elif cmp == 0: alt = z # x is as good as the best so far
|
||||||
errors.safeAdd((sym, int z.mutabilityProblem))
|
else: discard
|
||||||
if z.errors != nil:
|
sym = nextOverloadIter(o, c, headSymbol)
|
||||||
for err in z.errors:
|
break # pick attempt was successful
|
||||||
errors.add(err)
|
|
||||||
if z.state == csMatch:
|
|
||||||
# little hack so that iterators are preferred over everything else:
|
|
||||||
if sym.kind == skIterator: inc(z.exactMatches, 200)
|
|
||||||
case best.state
|
|
||||||
of csEmpty, csNoMatch: best = z
|
|
||||||
of csMatch:
|
|
||||||
var cmp = cmpCandidates(best, z)
|
|
||||||
if cmp < 0: best = z # x is better than the best so far
|
|
||||||
elif cmp == 0: alt = z # x is as good as the best so far
|
|
||||||
else: discard
|
|
||||||
#if sym.name.s == "cmp" and (n.info ?? "rstgen.nim") and n.info.line == 516:
|
|
||||||
# echo "Matches ", n.info, " ", typeToString(sym.typ)
|
|
||||||
# debug sym
|
|
||||||
# writeMatches(z)
|
|
||||||
# for i in 1 .. <len(z.call):
|
|
||||||
# z.call[i].typ.debug
|
|
||||||
# quit 1
|
|
||||||
|
|
||||||
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
# Gives a detailed error message; this is separated from semOverloadedCall,
|
# Gives a detailed error message; this is separated from semOverloadedCall,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue