stuff that is green
This commit is contained in:
parent
f64f9e50cc
commit
4adc31ee3d
3 changed files with 37 additions and 23 deletions
|
|
@ -59,7 +59,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
filter: TSymKinds,
|
filter: TSymKinds,
|
||||||
best, alt: var TCandidate,
|
best, alt: var TCandidate,
|
||||||
errors: var CandidateErrors,
|
errors: var CandidateErrors,
|
||||||
diagnosticsFlag = false) =
|
diagnosticsFlag: bool) =
|
||||||
var o: TOverloadIter
|
var o: TOverloadIter
|
||||||
var sym = initOverloadIter(o, c, headSymbol)
|
var sym = initOverloadIter(o, c, headSymbol)
|
||||||
var scope = o.lastOverloadScope
|
var scope = o.lastOverloadScope
|
||||||
|
|
@ -68,6 +68,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
# This can occur in cases like 'init(a, 1, (var b = new(Type2); b))'
|
# This can occur in cases like 'init(a, 1, (var b = new(Type2); b))'
|
||||||
let counterInitial = c.currentScope.symbols.counter
|
let counterInitial = c.currentScope.symbols.counter
|
||||||
var syms: seq[tuple[s: PSym, scope: int]]
|
var syms: seq[tuple[s: PSym, scope: int]]
|
||||||
|
var noSyms = true
|
||||||
var nextSymIndex = 0
|
var nextSymIndex = 0
|
||||||
while sym != nil:
|
while sym != nil:
|
||||||
if sym.kind in filter:
|
if sym.kind in filter:
|
||||||
|
|
@ -102,18 +103,20 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
|
||||||
var cmp = cmpCandidates(best, z)
|
var cmp = cmpCandidates(best, z)
|
||||||
if cmp < 0: best = z # x is better than the best so far
|
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
|
elif cmp == 0: alt = z # x is as good as the best so far
|
||||||
elif errors != nil or z.diagnostics != nil:
|
elif errors.enabled or z.diagnostics.enabled:
|
||||||
errors.safeAdd(CandidateError(
|
errors.s.safeAdd(CandidateError(
|
||||||
sym: sym,
|
sym: sym,
|
||||||
unmatchedVarParam: int z.mutabilityProblem,
|
unmatchedVarParam: int z.mutabilityProblem,
|
||||||
firstMismatch: z.firstMismatch,
|
firstMismatch: z.firstMismatch,
|
||||||
diagnostics: z.diagnostics))
|
diagnostics: z.diagnostics))
|
||||||
|
errors.enabled = true
|
||||||
else:
|
else:
|
||||||
# Symbol table has been modified. Restart and pre-calculate all syms
|
# Symbol table has been modified. Restart and pre-calculate all syms
|
||||||
# before any further candidate init and compare. SLOW, but rare case.
|
# before any further candidate init and compare. SLOW, but rare case.
|
||||||
syms = initCandidateSymbols(c, headSymbol, initialBinding, filter,
|
syms = initCandidateSymbols(c, headSymbol, initialBinding, filter,
|
||||||
best, alt, o, diagnosticsFlag)
|
best, alt, o, diagnosticsFlag)
|
||||||
if syms == nil:
|
noSyms = false
|
||||||
|
if noSyms:
|
||||||
sym = nextOverloadIter(o, c, headSymbol)
|
sym = nextOverloadIter(o, c, headSymbol)
|
||||||
scope = o.lastOverloadScope
|
scope = o.lastOverloadScope
|
||||||
elif nextSymIndex < syms.len:
|
elif nextSymIndex < syms.len:
|
||||||
|
|
@ -148,7 +151,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||||
# we do a pre-analysis. If all types produce the same string, we will add
|
# we do a pre-analysis. If all types produce the same string, we will add
|
||||||
# module information.
|
# module information.
|
||||||
let proto = describeArgs(c, n, 1, preferName)
|
let proto = describeArgs(c, n, 1, preferName)
|
||||||
for err in errors:
|
for err in errors.s:
|
||||||
var errProto = ""
|
var errProto = ""
|
||||||
let n = err.sym.typ.n
|
let n = err.sym.typ.n
|
||||||
for i in countup(1, n.len - 1):
|
for i in countup(1, n.len - 1):
|
||||||
|
|
@ -162,7 +165,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||||
break
|
break
|
||||||
|
|
||||||
var candidates = ""
|
var candidates = ""
|
||||||
for err in errors:
|
for err in errors.s:
|
||||||
if err.sym.kind in routineKinds and err.sym.ast != nil:
|
if err.sym.kind in routineKinds and err.sym.ast != nil:
|
||||||
add(candidates, renderTree(err.sym.ast,
|
add(candidates, renderTree(err.sym.ast,
|
||||||
{renderNoBody, renderNoComments, renderNoPragmas}))
|
{renderNoBody, renderNoComments, renderNoPragmas}))
|
||||||
|
|
@ -194,7 +197,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
|
||||||
candidates.add(" for a 'var' type a variable needs to be passed, but '" &
|
candidates.add(" for a 'var' type a variable needs to be passed, but '" &
|
||||||
renderNotLValue(n[err.unmatchedVarParam]) &
|
renderNotLValue(n[err.unmatchedVarParam]) &
|
||||||
"' is immutable\n")
|
"' is immutable\n")
|
||||||
for diag in err.diagnostics:
|
for diag in err.diagnostics.s:
|
||||||
candidates.add(diag & "\n")
|
candidates.add(diag & "\n")
|
||||||
|
|
||||||
result = (prefer, candidates)
|
result = (prefer, candidates)
|
||||||
|
|
@ -206,7 +209,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
if errorOutputs == {}:
|
if errorOutputs == {}:
|
||||||
# fail fast:
|
# fail fast:
|
||||||
globalError(n.info, errTypeMismatch, "")
|
globalError(n.info, errTypeMismatch, "")
|
||||||
if errors.isNil or errors.len == 0:
|
if errors.s.len == 0:
|
||||||
localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
|
localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -219,17 +222,18 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
|
||||||
localError(n.info, errGenerated, result & "\nexpression: " & $n)
|
localError(n.info, errGenerated, result & "\nexpression: " & $n)
|
||||||
|
|
||||||
proc bracketNotFoundError(c: PContext; n: PNode) =
|
proc bracketNotFoundError(c: PContext; n: PNode) =
|
||||||
var errors: CandidateErrors = @[]
|
var errors = CandidateErrors(enabled: true, s: @[])
|
||||||
var o: TOverloadIter
|
var o: TOverloadIter
|
||||||
let headSymbol = n[0]
|
let headSymbol = n[0]
|
||||||
var symx = initOverloadIter(o, c, headSymbol)
|
var symx = initOverloadIter(o, c, headSymbol)
|
||||||
while symx != nil:
|
while symx != nil:
|
||||||
if symx.kind in routineKinds:
|
if symx.kind in routineKinds:
|
||||||
errors.add(CandidateError(sym: symx,
|
errors.s.add(CandidateError(sym: symx,
|
||||||
unmatchedVarParam: 0, firstMismatch: 0,
|
unmatchedVarParam: 0, firstMismatch: 0,
|
||||||
diagnostics: nil))
|
diagnostics: OptionalStringSeq(enabled: false, s: @[])))
|
||||||
|
errors.enabled = true
|
||||||
symx = nextOverloadIter(o, c, headSymbol)
|
symx = nextOverloadIter(o, c, headSymbol)
|
||||||
if errors.len == 0:
|
if errors.s.len == 0:
|
||||||
localError(n.info, "could not resolve: " & $n)
|
localError(n.info, "could not resolve: " & $n)
|
||||||
else:
|
else:
|
||||||
notFoundError(c, n, errors)
|
notFoundError(c, n, errors)
|
||||||
|
|
@ -423,12 +427,11 @@ proc tryDeref(n: PNode): PNode =
|
||||||
|
|
||||||
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
filter: TSymKinds, flags: TExprFlags): PNode =
|
filter: TSymKinds, flags: TExprFlags): PNode =
|
||||||
var errors: CandidateErrors = if efExplain in flags: @[]
|
var errors = CandidateErrors(enabled: efExplain in flags, s: nil)
|
||||||
else: nil
|
|
||||||
var r = resolveOverloads(c, n, nOrig, filter, flags, errors)
|
var r = resolveOverloads(c, n, nOrig, filter, flags, errors)
|
||||||
if r.state == csMatch:
|
if r.state == csMatch:
|
||||||
# this may be triggered, when the explain pragma is used
|
# this may be triggered, when the explain pragma is used
|
||||||
if errors.len > 0:
|
if errors.s.len > 0:
|
||||||
let (_, candidates) = presentFailedCandidates(c, n, errors)
|
let (_, candidates) = presentFailedCandidates(c, n, errors)
|
||||||
message(n.info, hintUserRaw,
|
message(n.info, hintUserRaw,
|
||||||
"Non-matching candidates for " & renderTree(n) & "\n" &
|
"Non-matching candidates for " & renderTree(n) & "\n" &
|
||||||
|
|
|
||||||
|
|
@ -305,7 +305,8 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
maybeLiftType(t2, c, n.info)
|
maybeLiftType(t2, c, n.info)
|
||||||
var m: TCandidate
|
var m: TCandidate
|
||||||
initCandidate(c, m, t2)
|
initCandidate(c, m, t2)
|
||||||
if efExplain in flags: m.diagnostics = @[]
|
if efExplain in flags:
|
||||||
|
m.diagnostics = OptionalStringSeq(enabled: true, s: @[])
|
||||||
let match = typeRel(m, t2, t1) >= isSubtype # isNone
|
let match = typeRel(m, t2, t1) >= isSubtype # isNone
|
||||||
result = newIntNode(nkIntLit, ord(match))
|
result = newIntNode(nkIntLit, ord(match))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,18 @@ type
|
||||||
TCandidateState* = enum
|
TCandidateState* = enum
|
||||||
csEmpty, csMatch, csNoMatch
|
csEmpty, csMatch, csNoMatch
|
||||||
|
|
||||||
|
OptionalStringSeq* = object
|
||||||
|
enabled*: bool
|
||||||
|
s*: seq[string]
|
||||||
|
|
||||||
CandidateError* = object
|
CandidateError* = object
|
||||||
sym*: PSym
|
sym*: PSym
|
||||||
unmatchedVarParam*, firstMismatch*: int
|
unmatchedVarParam*, firstMismatch*: int
|
||||||
diagnostics*: seq[string]
|
diagnostics*: OptionalStringSeq # seq[string]
|
||||||
|
|
||||||
CandidateErrors* = seq[CandidateError]
|
CandidateErrors* = object
|
||||||
|
enabled*: bool
|
||||||
|
s*: seq[CandidateError]
|
||||||
|
|
||||||
TCandidate* = object
|
TCandidate* = object
|
||||||
c*: PContext
|
c*: PContext
|
||||||
|
|
@ -60,7 +66,8 @@ type
|
||||||
# matching. they will be reset if the matching
|
# matching. they will be reset if the matching
|
||||||
# is not successful. may replace the bindings
|
# is not successful. may replace the bindings
|
||||||
# table in the future.
|
# table in the future.
|
||||||
diagnostics*: seq[string] # when this is not nil, the matching process
|
diagnostics*: OptionalStringSeq # \
|
||||||
|
# when diagnosticsEnabled, the matching process
|
||||||
# will collect extra diagnostics that will be
|
# will collect extra diagnostics that will be
|
||||||
# displayed to the user.
|
# displayed to the user.
|
||||||
# triggered when overload resolution fails
|
# triggered when overload resolution fails
|
||||||
|
|
@ -124,7 +131,8 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} =
|
||||||
idTablePut(c.bindings, key, val.skipIntLit)
|
idTablePut(c.bindings, key, val.skipIntLit)
|
||||||
|
|
||||||
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
||||||
binding: PNode, calleeScope = -1, diagnostics = false) =
|
binding: PNode, calleeScope = -1,
|
||||||
|
diagnosticsEnabled = false) =
|
||||||
initCandidateAux(ctx, c, callee.typ)
|
initCandidateAux(ctx, c, callee.typ)
|
||||||
c.calleeSym = callee
|
c.calleeSym = callee
|
||||||
if callee.kind in skProcKinds and calleeScope == -1:
|
if callee.kind in skProcKinds and calleeScope == -1:
|
||||||
|
|
@ -139,7 +147,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym,
|
||||||
c.calleeScope = 1
|
c.calleeScope = 1
|
||||||
else:
|
else:
|
||||||
c.calleeScope = calleeScope
|
c.calleeScope = calleeScope
|
||||||
c.diagnostics = if diagnostics: @[] else: nil
|
c.diagnostics = OptionalStringSeq(enabled: diagnosticsEnabled, s: @[])
|
||||||
c.magic = c.calleeSym.magic
|
c.magic = c.calleeSym.magic
|
||||||
initIdTable(c.bindings)
|
initIdTable(c.bindings)
|
||||||
if binding != nil and callee.kind in routineKinds:
|
if binding != nil and callee.kind in routineKinds:
|
||||||
|
|
@ -717,7 +725,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||||
diagnostics: seq[string]
|
diagnostics: seq[string]
|
||||||
errorPrefix: string
|
errorPrefix: string
|
||||||
flags: TExprFlags = {}
|
flags: TExprFlags = {}
|
||||||
collectDiagnostics = m.diagnostics != nil or
|
collectDiagnostics = m.diagnostics.enabled or
|
||||||
sfExplain in typeClass.sym.flags
|
sfExplain in typeClass.sym.flags
|
||||||
|
|
||||||
if collectDiagnostics:
|
if collectDiagnostics:
|
||||||
|
|
@ -736,7 +744,9 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType =
|
||||||
|
|
||||||
if collectDiagnostics:
|
if collectDiagnostics:
|
||||||
writelnHook = oldWriteHook
|
writelnHook = oldWriteHook
|
||||||
for msg in diagnostics: m.diagnostics.safeAdd msg
|
for msg in diagnostics:
|
||||||
|
m.diagnostics.s.safeAdd msg
|
||||||
|
m.diagnostics.enabled = true
|
||||||
|
|
||||||
if checkedBody == nil: return nil
|
if checkedBody == nil: return nil
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue