More depth debug proc (#10782)

* improved output on debugType
* cycle detection in debug print
* debug info finally really helpful
* finally usable debug info
* quote enum values
This commit is contained in:
Arne Döring 2019-03-04 09:17:47 +01:00 • committed by Andreas Rumpf
commit ebe0473511

View file

@ -351,105 +351,225 @@ proc symToYaml(conf: ConfigRef; n: PSym, indent: int = 0, maxRecDepth: int = - 1
var marker = initIntSet() var marker = initIntSet()
result = symToYamlAux(conf, n, marker, indent, maxRecDepth) result = symToYamlAux(conf, n, marker, indent, maxRecDepth)
proc debugTree*(conf: ConfigRef; n: PNode, indent: int, maxRecDepth: int; renderType=false): Rope import tables
proc debugType(conf: ConfigRef; n: PType, maxRecDepth=100): Rope =
if n == nil:
result = rope("null")
else:
result = rope($n.kind)
if n.sym != nil:
add(result, " ")
add(result, n.sym.name.s)
if n.kind in IntegralTypes and n.n != nil:
add(result, ", n: ")
add(result, debugTree(conf, n.n, 2, maxRecDepth-1, renderType=false))
if (n.kind != tyString) and (sonsLen(n) > 0) and maxRecDepth != 0:
add(result, "(")
for i in countup(0, sonsLen(n) - 1):
if i > 0: add(result, ", ")
if n.sons[i] == nil:
add(result, "null")
else:
add(result, debugType(conf, n.sons[i], maxRecDepth-1))
if n.kind == tyObject and n.n != nil:
add(result, ", n: ")
add(result, debugTree(conf, n.n, 2, maxRecDepth-1, renderType=true))
add(result, ")")
proc debugTree(conf: ConfigRef; n: PNode, indent: int, maxRecDepth: int; type
renderType=false): Rope = DebugPrinter = object
if n == nil: conf: ConfigRef
result = rope("null") visited: Table[pointer, int]
else: renderSymType: bool
var istr = rspaces(indent + 2) indent: int
result = "{$N$1\"kind\": $2" % currentLine: int
[istr, makeYamlString($n.kind)] firstItem: bool
when defined(useNodeIds): res: string
addf(result, ",$N$1\"id\": $2", [istr, rope(n.id)])
if conf != nil:
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(conf, n.info)])
if maxRecDepth != 0:
if card(n.flags) > 0:
addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)])
case n.kind
of nkCharLit..nkUInt64Lit:
addf(result, ",$N$1\"intVal\": $2", [istr, rope(n.intVal)])
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
addf(result, ",$N$1\"floatVal\": $2",
[istr, rope(n.floatVal.toStrMaxPrecision)])
of nkStrLit..nkTripleStrLit:
addf(result, ",$N$1\"strVal\": $2", [istr, makeYamlString(n.strVal)])
of nkSym:
let s = n.sym
var symStr = ""
symStr.add "\"kind\": \""
symStr.add $s.kind
symStr.add "\", \"name\": \""
symStr.add s.name.s
symStr.add "\", \"id\": "
symStr.add s.id
if s.kind in {skField, skEnumField, skParam}:
symStr.add ", \"position\": "
symStr.add s.position
addf(result, ",$N$1\"sym\": {$2}", [
istr, rope(symStr)])
if renderType and n.sym.typ != nil: proc indentMore(this: var DebugPrinter) =
addf(result, ",$N$1\"typ\": $2", [istr, debugType(conf, n.sym.typ, 2)]) this.indent += 2
of nkIdent:
if n.ident != nil: proc indentLess(this: var DebugPrinter) =
addf(result, ",$N$1\"ident\": $2", [istr, makeYamlString(n.ident.s)]) this.indent -= 2
else:
addf(result, ",$N$1\"ident\": null", [istr]) proc newlineAndIndent(this: var DebugPrinter) =
else: this.res.add "\n"
if renderType and n.typ != nil: this.currentLine += 1
addf(result, ",$N$1\"typ\": $2", [istr, debugType(conf, n.typ, 2)]) for i in 0 ..< this.indent:
if sonsLen(n) > 0: this.res.add ' '
addf(result, ",$N$1\"sons\": [", [istr])
for i in countup(0, sonsLen(n) - 1): proc openCurly(this: var DebugPrinter) =
if i > 0: add(result, ",") this.res.add "{"
addf(result, "$N$1$2", [rspaces(indent + 4), debugTree(conf, n.sons[i], this.indentMore
indent + 4, maxRecDepth - 1, renderType)]) this.firstItem = true
addf(result, "$N$1]", [istr])
addf(result, "$N$1}", [rspaces(indent)]) proc closeCurly(this: var DebugPrinter) =
this.indentLess
this.newlineAndIndent
this.res.add "}"
proc comma(this: var DebugPrinter) =
this.res.add ", "
proc openBracket(this: var DebugPrinter) =
this.res.add "["
#this.indentMore
proc closeBracket(this: var DebugPrinter) =
#this.indentLess
this.res.add "]"
proc key(this: var DebugPrinter; key: string) =
if not this.firstItem:
this.res.add ","
this.firstItem = false
this.newlineAndIndent
this.res.add "\""
this.res.add key
this.res.add "\": "
proc value(this: var DebugPrinter; value: string) =
this.res.add "\""
this.res.add value
this.res.add "\""
proc value(this: var DebugPrinter; value: BiggestInt) =
this.res.add value
proc value[T: enum](this: var DebugPrinter; value: T) =
this.value $value
proc value[T: enum](this: var DebugPrinter; value: set[T]) =
this.openBracket
let high = card(value)-1
var i = 0
for v in value:
this.value v
if i != high:
this.comma
inc i
this.closeBracket
template earlyExit(this: var DebugPrinter; n: PType | PNode | PSym) =
if n == nil:
this.res.add "null"
return
let index = this.visited.getOrDefault(cast[pointer](n), -1)
if index < 0:
this.visited[cast[pointer](n)] = this.currentLine
else:
this.res.add "<defined "
this.res.add(this.currentLine - index)
this.res.add " lines upwards>"
return
proc value(this: var DebugPrinter; value: PType): void
proc value(this: var DebugPrinter; value: PNode): void
proc value(this: var DebugPrinter; value: PSym): void =
earlyExit(this, value)
this.openCurly
this.key("kind")
this.value($value.kind)
this.key("name")
this.value(value.name.s)
this.key("id")
this.value(value.id)
if value.kind in {skField, skEnumField, skParam}:
this.key("position")
this.value(value.position)
if card(value.flags) > 0:
this.key("flags")
this.value(value.flags)
if this.renderSymType and value.typ != nil:
this.key "typ"
this.value(value.typ)
this.closeCurly
proc value(this: var DebugPrinter; value: PType): void =
earlyExit(this, value)
this.openCurly
this.key "kind"
this.value value.kind
if value.sym != nil:
this.key "sym"
this.value value.sym
if card(value.flags) > 0:
this.key "flags"
this.value value.flags
if value.kind in IntegralTypes and value.n != nil:
this.key "n"
this.value value.n
if sonsLen(value) > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
this.comma
this.closeBracket
if value.n != nil:
this.key "n"
this.value value.n
this.closeCurly
proc value(this: var DebugPrinter; value: PNode): void =
earlyExit(this, value)
this.openCurly
this.key "kind"
this.value value.kind
when defined(useNodeIds):
this.key "id"
this.value value.id
if this.conf != nil:
this.key "info"
this.value $lineInfoToStr(this.conf, value.info)
if card(value.flags) > 0:
this.key "flags"
this.value value.flags
case value.kind
of nkCharLit..nkUInt64Lit:
this.key "intVal"
this.value value.intVal
of nkFloatLit, nkFloat32Lit, nkFloat64Lit:
this.key "floatVal"
this.value value.floatVal.toStrMaxPrecision
of nkStrLit..nkTripleStrLit:
this.key "strVal"
this.value value.strVal
of nkSym:
this.key "sym"
this.value(value.sym)
of nkIdent:
if value.ident != nil:
this.key "ident"
this.value value.ident.s
else:
if this.renderSymType and value.typ != nil:
this.key "typ"
this.value value.typ
if sonsLen(value) > 0:
this.key "sons"
this.openBracket
for i in 0 ..< sonsLen(value):
this.value value.sons[i]
if i != sonsLen(value) - 1:
this.comma
this.closeBracket
this.closeCurly
when declared(echo): when declared(echo):
proc debug(n: PSym; conf: ConfigRef) = proc debug(n: PSym; conf: ConfigRef) =
if n == nil: var this: DebugPrinter
echo("null") this.visited = initTable[pointer, int]()
elif n.kind == skUnknown: this.renderSymType = true
echo("skUnknown") this.value(n)
else: echo($this.res)
#writeLine(stdout, $symToYaml(n, 0, 1))
echo("$1_$2: $3, $4, $5, $6" % [
n.name.s, $n.id, $flagsToStr(n.flags), $flagsToStr(n.loc.flags),
$lineInfoToStr(conf, n.info), $n.kind])
proc debug(n: PType; conf: ConfigRef) = proc debug(n: PType; conf: ConfigRef) =
echo($debugType(conf, n)) var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.value(n)
echo($this.res)
proc debug(n: PNode; conf: ConfigRef) = proc debug(n: PNode; conf: ConfigRef) =
echo($debugTree(conf, n, 0, 100)) var this: DebugPrinter
this.visited = initTable[pointer, int]()
this.renderSymType = true
this.value(n)
echo($this.res)
proc nextTry(h, maxHash: Hash): Hash = proc nextTry(h, maxHash: Hash): Hash =
result = ((5 * h) + 1) and maxHash result = ((5 * h) + 1) and maxHash