optimized friendly stack traces
This commit is contained in:
parent
383c80971c
commit
6cf2fcaaf1
2 changed files with 21 additions and 29 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import os, tables, strutils, times, heapqueue, options, deques
|
import os, tables, strutils, times, heapqueue, options, deques, cstrutils
|
||||||
|
|
||||||
# TODO: This shouldn't need to be included, but should ideally be exported.
|
# TODO: This shouldn't need to be included, but should ideally be exported.
|
||||||
type
|
type
|
||||||
|
|
@ -217,19 +217,15 @@ proc `callback=`*[T](future: Future[T],
|
||||||
## If future has already completed then ``cb`` will be called immediately.
|
## If future has already completed then ``cb`` will be called immediately.
|
||||||
future.callback = proc () = cb(future)
|
future.callback = proc () = cb(future)
|
||||||
|
|
||||||
proc diff[T](a, b: seq[T]): (int, seq[T]) =
|
proc diff[T](a, b: seq[T]; firstB, lastB: int): int =
|
||||||
## Iterates through both sequences until the items do not match,
|
## Iterates through both sequences until the items do not match,
|
||||||
## returns the remainder of `b` after the last item that does not match
|
## returns the remainder of `b[firstB..lastB]` after the last item that does not match
|
||||||
## together with the index of the last match.
|
## together with the index of the last match.
|
||||||
##
|
result = firstB
|
||||||
## .. code-block::nim
|
for i in 0..<min(a.len, lastB - firstB + 1):
|
||||||
## doAssert(diff(@[1,2,42,123], @[1,2,123,678,21]) == (1, @[123,678,21]))
|
result = i+firstB
|
||||||
var lastIndex = 0
|
if a[i] != b[i+firstB]:
|
||||||
for i in 0..<min(a.len, b.len):
|
|
||||||
lastIndex = i
|
|
||||||
if a[i] != b[i]:
|
|
||||||
break
|
break
|
||||||
return (lastIndex, b[lastIndex .. ^1])
|
|
||||||
|
|
||||||
proc mergeEntries(entries: seq[StackTraceEntry]): seq[StackTraceEntry] =
|
proc mergeEntries(entries: seq[StackTraceEntry]): seq[StackTraceEntry] =
|
||||||
## Merges stack trace entries containing re-raise entries into one
|
## Merges stack trace entries containing re-raise entries into one
|
||||||
|
|
@ -248,12 +244,11 @@ proc mergeEntries(entries: seq[StackTraceEntry]): seq[StackTraceEntry] =
|
||||||
reRaiseEnd.inc()
|
reRaiseEnd.inc()
|
||||||
assert entries[reRaiseEnd].procName.isNil
|
assert entries[reRaiseEnd].procName.isNil
|
||||||
assert entries[reRaiseEnd].line == -100 # Signifies end of re-raise block.
|
assert entries[reRaiseEnd].line == -100 # Signifies end of re-raise block.
|
||||||
let reRaisedEntries = entries[i+1 .. reRaiseEnd-1]
|
|
||||||
|
|
||||||
let (lastIndex, remainder) = diff(result, reRaisedEntries)
|
let lastIndex = diff(result, entries, i+1, reRaiseEnd-1)
|
||||||
# Insert all the entries after lastIndex.
|
# Insert all the entries after lastIndex.
|
||||||
for i in 0..<remainder.len:
|
for j in lastIndex..<reRaiseEnd - i - 1:
|
||||||
result.insert(remainder[i], lastIndex+i)
|
result.insert(entries[j+i+1], j)
|
||||||
i = reRaiseEnd+1
|
i = reRaiseEnd+1
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|
@ -264,17 +259,15 @@ proc getHint(entry: StackTraceEntry): string =
|
||||||
## We try to provide some hints about stack trace entries that the user
|
## We try to provide some hints about stack trace entries that the user
|
||||||
## may not be familiar with, in particular calls inside the stdlib.
|
## may not be familiar with, in particular calls inside the stdlib.
|
||||||
result = ""
|
result = ""
|
||||||
let name = ($entry.procName).normalize()
|
if entry.procname == "processPendingCallbacks":
|
||||||
case name
|
if cmpIgnoreStyle(entry.filename, "asyncdispatch.nim") == 0:
|
||||||
of "processpendingcallbacks":
|
|
||||||
if cmpIgnoreStyle($entry.filename, "asyncdispatch.nim") == 0:
|
|
||||||
return "Executes pending callbacks"
|
return "Executes pending callbacks"
|
||||||
of "poll":
|
elif entry.procname == "poll":
|
||||||
if cmpIgnoreStyle($entry.filename, "asyncdispatch.nim") == 0:
|
if cmpIgnoreStyle(entry.filename, "asyncdispatch.nim") == 0:
|
||||||
return "Processes asynchronous completion events"
|
return "Processes asynchronous completion events"
|
||||||
|
|
||||||
if name.endsWith("continue"):
|
if entry.procname.endsWith("_continue"):
|
||||||
if cmpIgnoreStyle($entry.filename, "asyncmacro.nim") == 0:
|
if cmpIgnoreStyle(entry.filename, "asyncmacro.nim") == 0:
|
||||||
return "Resumes an async procedure"
|
return "Resumes an async procedure"
|
||||||
|
|
||||||
proc `$`*(entries: seq[StackTraceEntry]): string =
|
proc `$`*(entries: seq[StackTraceEntry]): string =
|
||||||
|
|
@ -286,21 +279,18 @@ proc `$`*(entries: seq[StackTraceEntry]): string =
|
||||||
if left.len > longestLeft:
|
if left.len > longestLeft:
|
||||||
longestLeft = left.len
|
longestLeft = left.len
|
||||||
|
|
||||||
const indent = 2
|
const indent = spaces(2)
|
||||||
# Format the entries.
|
# Format the entries.
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
let indentStr = spaces(indent)
|
|
||||||
|
|
||||||
let left = "$#($#)" % [$entry.filename, $entry.line]
|
let left = "$#($#)" % [$entry.filename, $entry.line]
|
||||||
result.add("$#$#$# $#\n" % [
|
result.add((indent & "$#$# $#\n") % [
|
||||||
indentStr,
|
|
||||||
left,
|
left,
|
||||||
spaces(longestLeft - left.len + 2),
|
spaces(longestLeft - left.len + 2),
|
||||||
$entry.procName
|
$entry.procName
|
||||||
])
|
])
|
||||||
let hint = getHint(entry)
|
let hint = getHint(entry)
|
||||||
if hint.len > 0:
|
if hint.len > 0:
|
||||||
result.add(indentStr & "└─" & hint & "\n")
|
result.add(indent & "└─" & hint & "\n")
|
||||||
|
|
||||||
proc injectStacktrace[T](future: Future[T]) =
|
proc injectStacktrace[T](future: Future[T]) =
|
||||||
when not defined(release):
|
when not defined(release):
|
||||||
|
|
|
||||||
|
|
@ -389,6 +389,8 @@ proc asyncSingleProc(prc: NimNode): NimNode {.compileTime.} =
|
||||||
outerProcBody.add(closureIterator)
|
outerProcBody.add(closureIterator)
|
||||||
|
|
||||||
# -> createCb(retFuture)
|
# -> createCb(retFuture)
|
||||||
|
# NOTE: The "_continue" suffix is checked for in asyncfutures.nim to produce
|
||||||
|
# friendlier stack traces:
|
||||||
var cbName = genSym(nskProc, prcName & "_continue")
|
var cbName = genSym(nskProc, prcName & "_continue")
|
||||||
var procCb = getAst createCb(retFutureSym, iteratorNameSym,
|
var procCb = getAst createCb(retFutureSym, iteratorNameSym,
|
||||||
newStrLitNode(prcName),
|
newStrLitNode(prcName),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue