further improvements to the error messages produced by concepts
This commit is contained in:
parent
9e9b289fc5
commit
fe48dd1cbe
8 changed files with 85 additions and 54 deletions
|
|
@ -133,7 +133,7 @@ type
|
||||||
hintConditionAlwaysTrue, hintName, hintPattern,
|
hintConditionAlwaysTrue, hintName, hintPattern,
|
||||||
hintExecuting, hintLinking, hintDependency,
|
hintExecuting, hintLinking, hintDependency,
|
||||||
hintSource, hintStackTrace, hintGCStats,
|
hintSource, hintStackTrace, hintGCStats,
|
||||||
hintUser
|
hintUser, hintUserRaw
|
||||||
|
|
||||||
const
|
const
|
||||||
MsgKindToStr*: array[TMsgKind, string] = [
|
MsgKindToStr*: array[TMsgKind, string] = [
|
||||||
|
|
@ -434,10 +434,11 @@ const
|
||||||
hintSource: "$1",
|
hintSource: "$1",
|
||||||
hintStackTrace: "$1",
|
hintStackTrace: "$1",
|
||||||
hintGCStats: "$1",
|
hintGCStats: "$1",
|
||||||
hintUser: "$1"]
|
hintUser: "$1",
|
||||||
|
hintUserRaw: "$1"]
|
||||||
|
|
||||||
const
|
const
|
||||||
WarningsToStr*: array[0..30, string] = ["CannotOpenFile", "OctalEscape",
|
WarningsToStr* = ["CannotOpenFile", "OctalEscape",
|
||||||
"XIsNeverRead", "XmightNotBeenInit",
|
"XIsNeverRead", "XmightNotBeenInit",
|
||||||
"Deprecated", "ConfigDeprecated",
|
"Deprecated", "ConfigDeprecated",
|
||||||
"SmallLshouldNotBeUsed", "UnknownMagic",
|
"SmallLshouldNotBeUsed", "UnknownMagic",
|
||||||
|
|
@ -449,12 +450,12 @@ const
|
||||||
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
|
"ProveInit", "ProveField", "ProveIndex", "GcUnsafe", "GcUnsafe2", "Uninit",
|
||||||
"GcMem", "Destructor", "LockLevel", "ResultShadowed", "User"]
|
"GcMem", "Destructor", "LockLevel", "ResultShadowed", "User"]
|
||||||
|
|
||||||
HintsToStr*: array[0..22, string] = ["Success", "SuccessX", "LineTooLong",
|
HintsToStr* = ["Success", "SuccessX", "LineTooLong",
|
||||||
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
"XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
|
||||||
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
"ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
|
||||||
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",
|
"Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",
|
||||||
"Source", "StackTrace", "GCStats",
|
"Source", "StackTrace", "GCStats",
|
||||||
"User"]
|
"User", "UserRaw"]
|
||||||
|
|
||||||
const
|
const
|
||||||
fatalMin* = errUnknown
|
fatalMin* = errUnknown
|
||||||
|
|
@ -658,9 +659,6 @@ proc concat(strings: openarray[string]): string =
|
||||||
result = newStringOfCap totalLen
|
result = newStringOfCap totalLen
|
||||||
for s in strings: result.add s
|
for s in strings: result.add s
|
||||||
|
|
||||||
template writeBufferedMsg(args: varargs[string, `$`]) =
|
|
||||||
bufferedMsgs.safeAdd concat(args)
|
|
||||||
|
|
||||||
proc suggestWriteln*(s: string) =
|
proc suggestWriteln*(s: string) =
|
||||||
if eStdOut in errorOutputs:
|
if eStdOut in errorOutputs:
|
||||||
if isNil(writelnHook):
|
if isNil(writelnHook):
|
||||||
|
|
@ -929,7 +927,7 @@ proc rawMessage*(msg: TMsgKind, args: openArray[string]) =
|
||||||
if msg notin gNotes: return
|
if msg notin gNotes: return
|
||||||
title = HintTitle
|
title = HintTitle
|
||||||
color = HintColor
|
color = HintColor
|
||||||
kind = HintsToStr[ord(msg) - ord(hintMin)]
|
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||||
inc(gHintCounter)
|
inc(gHintCounter)
|
||||||
let s = msgKindToString(msg) % args
|
let s = msgKindToString(msg) % args
|
||||||
|
|
||||||
|
|
@ -997,7 +995,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
|
||||||
ignoreMsg = optHints notin gOptions or msg notin gNotes
|
ignoreMsg = optHints notin gOptions or msg notin gNotes
|
||||||
title = HintTitle
|
title = HintTitle
|
||||||
color = HintColor
|
color = HintColor
|
||||||
kind = HintsToStr[ord(msg) - ord(hintMin)]
|
if msg != hintUserRaw: kind = HintsToStr[ord(msg) - ord(hintMin)]
|
||||||
inc(gHintCounter)
|
inc(gHintCounter)
|
||||||
# NOTE: currently line info line numbers start with 1,
|
# NOTE: currently line info line numbers start with 1,
|
||||||
# but column numbers start with 0, however most editors expect
|
# but column numbers start with 0, however most editors expect
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,6 @@ proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
|
||||||
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
||||||
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
|
||||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||||
proc isOpImpl(c: PContext, n: PNode): PNode
|
|
||||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
|
||||||
flags: TExprFlags = {}): PNode
|
flags: TExprFlags = {}): PNode
|
||||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ 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,
|
||||||
# as semOverlodedCall is already pretty slow (and we need this information
|
# as semOverlodedCall is already pretty slow (and we need this information
|
||||||
# only in case of an error).
|
# only in case of an error).
|
||||||
if c.compilesContextId > 0:
|
if errorOutputs == {}:
|
||||||
# fail fast:
|
# fail fast:
|
||||||
globalError(n.info, errTypeMismatch, "")
|
globalError(n.info, errTypeMismatch, "")
|
||||||
if errors.isNil or errors.len == 0:
|
if errors.isNil or errors.len == 0:
|
||||||
|
|
@ -263,7 +263,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
|
||||||
internalAssert result.state == csMatch
|
internalAssert result.state == csMatch
|
||||||
#writeMatches(result)
|
#writeMatches(result)
|
||||||
#writeMatches(alt)
|
#writeMatches(alt)
|
||||||
if c.compilesContextId > 0:
|
if errorOutputs == {}:
|
||||||
# quick error message for performance of 'compiles' built-in:
|
# quick error message for performance of 'compiles' built-in:
|
||||||
globalError(n.info, errGenerated, "ambiguous call")
|
globalError(n.info, errGenerated, "ambiguous call")
|
||||||
elif gErrorCounter == 0:
|
elif gErrorCounter == 0:
|
||||||
|
|
@ -374,7 +374,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
|
||||||
# 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.len > 0:
|
||||||
let (_, candidates) = presentFailedCandidates(c, n, errors)
|
let (_, candidates) = presentFailedCandidates(c, n, errors)
|
||||||
message(n.info, hintUser,
|
message(n.info, hintUserRaw,
|
||||||
"Non-matching candidates for " & renderTree(n) & "\n" &
|
"Non-matching candidates for " & renderTree(n) & "\n" &
|
||||||
candidates)
|
candidates)
|
||||||
result = semResolvedCall(c, n, r)
|
result = semResolvedCall(c, n, r)
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,7 @@ proc semOf(c: PContext, n: PNode): PNode =
|
||||||
n.typ = getSysType(tyBool)
|
n.typ = getSysType(tyBool)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
proc isOpImpl(c: PContext, n: PNode): PNode =
|
proc isOpImpl(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
internalAssert n.sonsLen == 3 and
|
internalAssert n.sonsLen == 3 and
|
||||||
n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
|
n[1].typ != nil and n[1].typ.kind == tyTypeDesc and
|
||||||
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
n[2].kind in {nkStrLit..nkTripleStrLit, nkType}
|
||||||
|
|
@ -324,12 +324,13 @@ proc isOpImpl(c: PContext, n: PNode): 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 = @[]
|
||||||
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))
|
||||||
|
|
||||||
result.typ = n.typ
|
result.typ = n.typ
|
||||||
|
|
||||||
proc semIs(c: PContext, n: PNode): PNode =
|
proc semIs(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
if sonsLen(n) != 3:
|
if sonsLen(n) != 3:
|
||||||
localError(n.info, errXExpectsTwoArguments, "is")
|
localError(n.info, errXExpectsTwoArguments, "is")
|
||||||
|
|
||||||
|
|
@ -349,7 +350,7 @@ proc semIs(c: PContext, n: PNode): PNode =
|
||||||
return
|
return
|
||||||
|
|
||||||
# BUGFIX: don't evaluate this too early: ``T is void``
|
# BUGFIX: don't evaluate this too early: ``T is void``
|
||||||
if not n[1].typ.base.containsGenericType: result = isOpImpl(c, n)
|
if not n[1].typ.base.containsGenericType: result = isOpImpl(c, n, flags)
|
||||||
|
|
||||||
proc semOpAux(c: PContext, n: PNode) =
|
proc semOpAux(c: PContext, n: PNode) =
|
||||||
const flags = {efDetermineType}
|
const flags = {efDetermineType}
|
||||||
|
|
@ -754,7 +755,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
# This is a proc variable, apply normal overload resolution
|
# This is a proc variable, apply normal overload resolution
|
||||||
let m = resolveIndirectCall(c, n, nOrig, t)
|
let m = resolveIndirectCall(c, n, nOrig, t)
|
||||||
if m.state != csMatch:
|
if m.state != csMatch:
|
||||||
if c.compilesContextId > 0:
|
if errorOutputs == {}:
|
||||||
# speed up error generation:
|
# speed up error generation:
|
||||||
globalError(n.info, errTypeMismatch, "")
|
globalError(n.info, errTypeMismatch, "")
|
||||||
return emptyNode
|
return emptyNode
|
||||||
|
|
@ -1837,7 +1838,7 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
||||||
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
of mLow: result = semLowHigh(c, setMs(n, s), mLow)
|
||||||
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
of mHigh: result = semLowHigh(c, setMs(n, s), mHigh)
|
||||||
of mSizeOf: result = semSizeof(c, setMs(n, s))
|
of mSizeOf: result = semSizeof(c, setMs(n, s))
|
||||||
of mIs: result = semIs(c, setMs(n, s))
|
of mIs: result = semIs(c, setMs(n, s), flags)
|
||||||
of mOf: result = semOf(c, setMs(n, s))
|
of mOf: result = semOf(c, setMs(n, s))
|
||||||
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
of mShallowCopy: result = semShallowCopy(c, n, flags)
|
||||||
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
of mExpandToAst: result = semExpandToAst(c, n, s, flags)
|
||||||
|
|
|
||||||
|
|
@ -1609,7 +1609,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
n.typ = n.sons[i].typ
|
n.typ = n.sons[i].typ
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
var expr = semExpr(c, n.sons[i])
|
var expr = semExpr(c, n.sons[i], flags)
|
||||||
n.sons[i] = expr
|
n.sons[i] = expr
|
||||||
if c.inTypeClass > 0 and expr.typ != nil:
|
if c.inTypeClass > 0 and expr.typ != nil:
|
||||||
case expr.typ.kind
|
case expr.typ.kind
|
||||||
|
|
|
||||||
|
|
@ -664,6 +664,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||||
var
|
var
|
||||||
oldWriteHook: type(writelnHook)
|
oldWriteHook: type(writelnHook)
|
||||||
diagnostics: seq[string]
|
diagnostics: seq[string]
|
||||||
|
errorPrefix: string
|
||||||
flags: TExprFlags = {}
|
flags: TExprFlags = {}
|
||||||
collectDiagnostics = m.diagnostics != nil or
|
collectDiagnostics = m.diagnostics != nil or
|
||||||
sfExplain in Concept.sym.flags
|
sfExplain in Concept.sym.flags
|
||||||
|
|
@ -673,8 +674,12 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
|
||||||
# XXX: we can't write to m.diagnostics directly, because
|
# XXX: we can't write to m.diagnostics directly, because
|
||||||
# Nim doesn't support capturing var params in closures
|
# Nim doesn't support capturing var params in closures
|
||||||
diagnostics = @[]
|
diagnostics = @[]
|
||||||
writelnHook = proc (s: string) = diagnostics.add(s)
|
|
||||||
flags = {efExplain}
|
flags = {efExplain}
|
||||||
|
writelnHook = proc (s: string) =
|
||||||
|
if errorPrefix == nil: errorPrefix = Concept.sym.name.s & ":"
|
||||||
|
let msg = s.replace("Error:", errorPrefix)
|
||||||
|
if oldWriteHook != nil: oldWriteHook msg
|
||||||
|
diagnostics.add msg
|
||||||
|
|
||||||
var checkedBody = c.semTryExpr(c, body.copyTree, flags)
|
var checkedBody = c.semTryExpr(c, body.copyTree, flags)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,63 @@
|
||||||
discard """
|
discard """
|
||||||
cmd: "nim c --verbosity:0 --colors:off $file"
|
cmd: "nim c --verbosity:0 --colors:off $file"
|
||||||
nimout: '''
|
nimout: '''
|
||||||
tests/concepts/texplain.nim(71, 10) Hint: Non-matching candidates for e(y)
|
tests/concepts/texplain.nim(99, 10) Hint: Non-matching candidates for e(y)
|
||||||
proc e(i: int): int
|
proc e(i: int): int
|
||||||
[User]
|
|
||||||
tests/concepts/texplain.nim(74, 7) Hint: Non-matching candidates for e(10)
|
tests/concepts/texplain.nim(102, 7) Hint: Non-matching candidates for e(10)
|
||||||
proc e[ExplainedConcept](o: ExplainedConcept): int
|
proc e(o: ExplainedConcept): int
|
||||||
tests/concepts/texplain.nim(38, 6) Error: undeclared field: 'foo'
|
tests/concepts/texplain.nim(65, 6) ExplainedConcept: undeclared field: 'foo'
|
||||||
tests/concepts/texplain.nim(38, 6) Error: undeclared field: '.'
|
tests/concepts/texplain.nim(65, 6) ExplainedConcept: undeclared field: '.'
|
||||||
tests/concepts/texplain.nim(38, 6) Error: type mismatch: got (
|
tests/concepts/texplain.nim(65, 6) ExplainedConcept: expression '.' cannot be called
|
||||||
[User]
|
tests/concepts/texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||||
tests/concepts/texplain.nim(77, 10) Hint: Non-matching candidates for e(10)
|
tests/concepts/texplain.nim(66, 6) ExplainedConcept: undeclared field: 'bar'
|
||||||
proc e[ExplainedConcept](o: ExplainedConcept): int
|
tests/concepts/texplain.nim(66, 6) ExplainedConcept: undeclared field: '.'
|
||||||
tests/concepts/texplain.nim(38, 6) Error: undeclared field: 'foo'
|
tests/concepts/texplain.nim(66, 6) ExplainedConcept: expression '.' cannot be called
|
||||||
tests/concepts/texplain.nim(38, 6) Error: undeclared field: '.'
|
tests/concepts/texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||||
tests/concepts/texplain.nim(38, 6) Error: type mismatch: got (
|
|
||||||
[User]
|
tests/concepts/texplain.nim(105, 10) Hint: Non-matching candidates for e(10)
|
||||||
tests/concepts/texplain.nim(81, 20) Error: type mismatch: got (
|
proc e(o: ExplainedConcept): int
|
||||||
tests/concepts/texplain.nim(82, 20) Error: type mismatch: got (
|
tests/concepts/texplain.nim(65, 6) ExplainedConcept: undeclared field: 'foo'
|
||||||
tests/concepts/texplain.nim(83, 20) Hint: Non-matching candidates for r(y)
|
tests/concepts/texplain.nim(65, 6) ExplainedConcept: undeclared field: '.'
|
||||||
proc r(i: string): int
|
tests/concepts/texplain.nim(65, 6) ExplainedConcept: expression '.' cannot be called
|
||||||
[User]
|
tests/concepts/texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||||
tests/concepts/texplain.nim(91, 2) Error: type mismatch: got (MatchingType)
|
tests/concepts/texplain.nim(66, 6) ExplainedConcept: undeclared field: 'bar'
|
||||||
|
tests/concepts/texplain.nim(66, 6) ExplainedConcept: undeclared field: '.'
|
||||||
|
tests/concepts/texplain.nim(66, 6) ExplainedConcept: expression '.' cannot be called
|
||||||
|
tests/concepts/texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||||
|
|
||||||
|
tests/concepts/texplain.nim(109, 20) Error: type mismatch: got (NonMatchingType)
|
||||||
but expected one of:
|
but expected one of:
|
||||||
proc f[NestedConcept](o: NestedConcept)
|
proc e(o: ExplainedConcept): int
|
||||||
tests/concepts/texplain.nim(42, 6) Error: undeclared field: 'foo'
|
tests/concepts/texplain.nim(65, 5) ExplainedConcept: type class predicate failed
|
||||||
tests/concepts/texplain.nim(42, 6) Error: undeclared field: '.'
|
proc e(i: int): int
|
||||||
tests/concepts/texplain.nim(42, 6) Error: type mismatch: got (
|
|
||||||
tests/concepts/texplain.nim(46, 5) Error: type class predicate failed
|
tests/concepts/texplain.nim(110, 20) Error: type mismatch: got (NonMatchingType)
|
||||||
|
but expected one of:
|
||||||
|
proc r(o: RegularConcept): int
|
||||||
|
tests/concepts/texplain.nim(69, 5) RegularConcept: type class predicate failed
|
||||||
|
proc r[T](a: SomeNumber; b: T; c: auto)
|
||||||
|
proc r(i: string): int
|
||||||
|
|
||||||
|
tests/concepts/texplain.nim(111, 20) Hint: Non-matching candidates for r(y)
|
||||||
|
proc r[T](a: SomeNumber; b: T; c: auto)
|
||||||
|
proc r(i: string): int
|
||||||
|
|
||||||
|
tests/concepts/texplain.nim(119, 2) Error: type mismatch: got (MatchingType)
|
||||||
|
but expected one of:
|
||||||
|
proc f(o: NestedConcept)
|
||||||
|
tests/concepts/texplain.nim(69, 6) RegularConcept: undeclared field: 'foo'
|
||||||
|
tests/concepts/texplain.nim(69, 6) RegularConcept: undeclared field: '.'
|
||||||
|
tests/concepts/texplain.nim(69, 6) RegularConcept: expression '.' cannot be called
|
||||||
|
tests/concepts/texplain.nim(69, 5) RegularConcept: type class predicate failed
|
||||||
|
tests/concepts/texplain.nim(70, 6) RegularConcept: undeclared field: 'bar'
|
||||||
|
tests/concepts/texplain.nim(70, 6) RegularConcept: undeclared field: '.'
|
||||||
|
tests/concepts/texplain.nim(70, 6) RegularConcept: expression '.' cannot be called
|
||||||
|
tests/concepts/texplain.nim(69, 5) RegularConcept: type class predicate failed
|
||||||
|
tests/concepts/texplain.nim(73, 5) NestedConcept: type class predicate failed
|
||||||
'''
|
'''
|
||||||
line: 46
|
line: 119
|
||||||
errormsg: "type class predicate failed"
|
errormsg: "type mismatch: got (MatchingType)"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -56,6 +83,7 @@ type
|
||||||
proc e(o: ExplainedConcept): int = 1
|
proc e(o: ExplainedConcept): int = 1
|
||||||
proc e(i: int): int = i
|
proc e(i: int): int = i
|
||||||
|
|
||||||
|
proc r[T](a: SomeNumber, b: T, c: auto) = discard
|
||||||
proc r(o: RegularConcept): int = 1
|
proc r(o: RegularConcept): int = 1
|
||||||
proc r(i: string): int = 1
|
proc r(i: string): int = 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,8 @@ let
|
||||||
|
|
||||||
var targets = {low(TTarget)..high(TTarget)}
|
var targets = {low(TTarget)..high(TTarget)}
|
||||||
|
|
||||||
|
proc normalizeMsg(s: string): string = s.strip.replace("\C\L", "\L")
|
||||||
|
|
||||||
proc callCompiler(cmdTemplate, filename, options: string,
|
proc callCompiler(cmdTemplate, filename, options: string,
|
||||||
target: TTarget): TSpec =
|
target: TTarget): TSpec =
|
||||||
let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target],
|
let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target],
|
||||||
|
|
@ -184,7 +186,7 @@ proc addResult(r: var TResults, test: TTest,
|
||||||
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
|
proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest) =
|
||||||
if strip(expected.msg) notin strip(given.msg):
|
if strip(expected.msg) notin strip(given.msg):
|
||||||
r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
|
r.addResult(test, expected.msg, given.msg, reMsgsDiffer)
|
||||||
elif expected.nimout.len > 0 and expected.nimout.normalize notin given.nimout.normalize:
|
elif expected.nimout.len > 0 and expected.nimout.normalizeMsg notin given.nimout.normalizeMsg:
|
||||||
r.addResult(test, expected.nimout, given.nimout, reMsgsDiffer)
|
r.addResult(test, expected.nimout, given.nimout, reMsgsDiffer)
|
||||||
elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and
|
elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and
|
||||||
"internal error:" notin expected.msg:
|
"internal error:" notin expected.msg:
|
||||||
|
|
@ -235,8 +237,6 @@ proc nimoutCheck(test: TTest; expectedNimout: string; given: var TSpec) =
|
||||||
if exp notin giv:
|
if exp notin giv:
|
||||||
given.err = reMsgsDiffer
|
given.err = reMsgsDiffer
|
||||||
|
|
||||||
proc normalize(s: string): string = s.strip.replace("\C\L", "\L")
|
|
||||||
|
|
||||||
proc makeDeterministic(s: string): string =
|
proc makeDeterministic(s: string): string =
|
||||||
var x = splitLines(s)
|
var x = splitLines(s)
|
||||||
sort(x, system.cmp)
|
sort(x, system.cmp)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue