From 4adc31ee3d5d56e1566da746b464ec11a6865863 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Sat, 28 Apr 2018 18:23:54 +0200 Subject: stuff that is green --- compiler/semcall.nim | 33 ++++++++++++++++++--------------- compiler/semexprs.nim | 3 ++- compiler/sigmatch.nim | 24 +++++++++++++++++------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/compiler/semcall.nim b/compiler/semcall.nim index f443339f5..0df943531 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -59,7 +59,7 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, filter: TSymKinds, best, alt: var TCandidate, errors: var CandidateErrors, - diagnosticsFlag = false) = + diagnosticsFlag: bool) = var o: TOverloadIter var sym = initOverloadIter(o, c, headSymbol) 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))' let counterInitial = c.currentScope.symbols.counter var syms: seq[tuple[s: PSym, scope: int]] + var noSyms = true var nextSymIndex = 0 while sym != nil: if sym.kind in filter: @@ -102,18 +103,20 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode, 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 - elif errors != nil or z.diagnostics != nil: - errors.safeAdd(CandidateError( + elif errors.enabled or z.diagnostics.enabled: + errors.s.safeAdd(CandidateError( sym: sym, unmatchedVarParam: int z.mutabilityProblem, firstMismatch: z.firstMismatch, diagnostics: z.diagnostics)) + errors.enabled = true else: # Symbol table has been modified. Restart and pre-calculate all syms # before any further candidate init and compare. SLOW, but rare case. syms = initCandidateSymbols(c, headSymbol, initialBinding, filter, best, alt, o, diagnosticsFlag) - if syms == nil: + noSyms = false + if noSyms: sym = nextOverloadIter(o, c, headSymbol) scope = o.lastOverloadScope 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 # module information. let proto = describeArgs(c, n, 1, preferName) - for err in errors: + for err in errors.s: var errProto = "" let n = err.sym.typ.n for i in countup(1, n.len - 1): @@ -162,7 +165,7 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors): break var candidates = "" - for err in errors: + for err in errors.s: if err.sym.kind in routineKinds and err.sym.ast != nil: add(candidates, renderTree(err.sym.ast, {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 '" & renderNotLValue(n[err.unmatchedVarParam]) & "' is immutable\n") - for diag in err.diagnostics: + for diag in err.diagnostics.s: candidates.add(diag & "\n") result = (prefer, candidates) @@ -206,7 +209,7 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = if errorOutputs == {}: # fail fast: globalError(n.info, errTypeMismatch, "") - if errors.isNil or errors.len == 0: + if errors.s.len == 0: localError(n.info, errExprXCannotBeCalled, n[0].renderTree) return @@ -219,17 +222,18 @@ proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) = localError(n.info, errGenerated, result & "\nexpression: " & $n) proc bracketNotFoundError(c: PContext; n: PNode) = - var errors: CandidateErrors = @[] + var errors = CandidateErrors(enabled: true, s: @[]) var o: TOverloadIter let headSymbol = n[0] var symx = initOverloadIter(o, c, headSymbol) while symx != nil: if symx.kind in routineKinds: - errors.add(CandidateError(sym: symx, + errors.s.add(CandidateError(sym: symx, unmatchedVarParam: 0, firstMismatch: 0, - diagnostics: nil)) + diagnostics: OptionalStringSeq(enabled: false, s: @[]))) + errors.enabled = true symx = nextOverloadIter(o, c, headSymbol) - if errors.len == 0: + if errors.s.len == 0: localError(n.info, "could not resolve: " & $n) else: notFoundError(c, n, errors) @@ -423,12 +427,11 @@ proc tryDeref(n: PNode): PNode = proc semOverloadedCall(c: PContext, n, nOrig: PNode, filter: TSymKinds, flags: TExprFlags): PNode = - var errors: CandidateErrors = if efExplain in flags: @[] - else: nil + var errors = CandidateErrors(enabled: efExplain in flags, s: nil) var r = resolveOverloads(c, n, nOrig, filter, flags, errors) if r.state == csMatch: # 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) message(n.info, hintUserRaw, "Non-matching candidates for " & renderTree(n) & "\n" & diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 22dee81b7..66fe81ed3 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -305,7 +305,8 @@ proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode = maybeLiftType(t2, c, n.info) var m: TCandidate 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 result = newIntNode(nkIntLit, ord(match)) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 552d2cdca..0426a22f3 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -22,12 +22,18 @@ type TCandidateState* = enum csEmpty, csMatch, csNoMatch + OptionalStringSeq* = object + enabled*: bool + s*: seq[string] + CandidateError* = object sym*: PSym unmatchedVarParam*, firstMismatch*: int - diagnostics*: seq[string] + diagnostics*: OptionalStringSeq # seq[string] - CandidateErrors* = seq[CandidateError] + CandidateErrors* = object + enabled*: bool + s*: seq[CandidateError] TCandidate* = object c*: PContext @@ -60,7 +66,8 @@ type # matching. they will be reset if the matching # is not successful. may replace the bindings # 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 # displayed to the user. # triggered when overload resolution fails @@ -124,7 +131,8 @@ proc put(c: var TCandidate, key, val: PType) {.inline.} = idTablePut(c.bindings, key, val.skipIntLit) 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) c.calleeSym = callee if callee.kind in skProcKinds and calleeScope == -1: @@ -139,7 +147,7 @@ proc initCandidate*(ctx: PContext, c: var TCandidate, callee: PSym, c.calleeScope = 1 else: c.calleeScope = calleeScope - c.diagnostics = if diagnostics: @[] else: nil + c.diagnostics = OptionalStringSeq(enabled: diagnosticsEnabled, s: @[]) c.magic = c.calleeSym.magic initIdTable(c.bindings) if binding != nil and callee.kind in routineKinds: @@ -717,7 +725,7 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = diagnostics: seq[string] errorPrefix: string flags: TExprFlags = {} - collectDiagnostics = m.diagnostics != nil or + collectDiagnostics = m.diagnostics.enabled or sfExplain in typeClass.sym.flags if collectDiagnostics: @@ -736,7 +744,9 @@ proc matchUserTypeClass*(m: var TCandidate; ff, a: PType): PType = if collectDiagnostics: 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 -- cgit 1.4.1-2-gfad0