From a8bdd49e082ee69a63a8f63c2780787df2dfad2c Mon Sep 17 00:00:00 2001 From: haxscramper Date: Tue, 25 Jan 2022 17:16:13 +0300 Subject: [PATCH] debug: add debug(), debugAst() etc. to astrepr Closes https://github.com/nim-works/nimskull/issues/203 - adds missing debug procedures to the `astrepr` module, returning the old API for debugging. --- compiler/front/cli_reporter.nim | 30 +------------ compiler/front/msgs.nim | 32 ++++++++++++++ compiler/utils/astrepr.nim | 76 ++++++++++++++++++++++++++++----- lib/experimental/colortext.nim | 3 +- 4 files changed, 102 insertions(+), 39 deletions(-) diff --git a/compiler/front/cli_reporter.nim b/compiler/front/cli_reporter.nim index 5d38b4f55a6..14fc0b2c79a 100644 --- a/compiler/front/cli_reporter.nim +++ b/compiler/front/cli_reporter.nim @@ -20,7 +20,8 @@ import tables, intsets, json, - strtabs + strtabs, + os ], experimental/[ colortext @@ -96,33 +97,6 @@ func wrap(conf: ConfigRef, text: ColText): string = toString(text, conf.useColor()) -import std/[os] - -proc formatPath(conf: ConfigRef, path: string): string = - ## Format absolute path for reporting - if path in conf.m.filenameToIndexTbl: - # Check if path is registered in filename table index - in that case - # formatting is done using `FileInfo` data from the config. - let id = conf.m.filenameToIndexTbl[path] - result = toFilenameOption(conf, id, conf.filenameOption) - - else: - # Path not registered in the filename table - most likely an - # instantiation info report location - when compileOption"excessiveStackTrace": - # instLoc(), when `--excessiveStackTrace` is used, generates full - # paths that /might/ need to be filtered if `--filenames:canonical`. - const compilerRoot = currentSourcePath().parentDir().parentDir() - if conf.filenameOption == foCanonical and - path.startsWith(compilerRoot): - result = path[(compilerRoot.len + 1) .. ^1] - - else: - result = path - - else: - result = path - proc formatTrace*(conf: ConfigRef, trace: seq[StackTraceEntry]): string = ## Format stack trace entries for reporting var paths: seq[string] diff --git a/compiler/front/msgs.nim b/compiler/front/msgs.nim index f3d1b3d34f7..f97d11d0721 100644 --- a/compiler/front/msgs.nim +++ b/compiler/front/msgs.nim @@ -284,6 +284,38 @@ proc toFilenameOption*(conf: ConfigRef, fileIdx: FileIndex, opt: FilenameOption) else: result = toFilenameOption(conf, fileIdx, foName) +proc formatPath*(conf: ConfigRef, path: string): string = + ## Format absolute file path for error message reporting. If path is not + ## registered in the `filenameToIndexTbl` and is not a path to the + ## compiler source, return it unchanged. If configuration is nil also + ## return path unchanged. + if isNil(conf): + return path + + if path in conf.m.filenameToIndexTbl: + # Check if path is registered in filename table index - in that case + # formatting is done using `FileInfo` data from the config. + let id = conf.m.filenameToIndexTbl[path] + result = toFilenameOption(conf, id, conf.filenameOption) + + else: + # Path not registered in the filename table - most likely an + # instantiation info report location + when compileOption"excessiveStackTrace": + # instLoc(), when `--excessiveStackTrace` is used, generates full + # paths that /might/ need to be filtered if `--filenames:canonical`. + const compilerRoot = currentSourcePath().parentDir().parentDir() + if conf.filenameOption == foCanonical and + path.startsWith(compilerRoot): + result = path[(compilerRoot.len + 1) .. ^1] + + else: + result = path + + else: + result = path + + proc toMsgFilename*(conf: ConfigRef; fileIdx: FileIndex): string = toFilenameOption(conf, fileIdx, conf.filenameOption) diff --git a/compiler/utils/astrepr.nim b/compiler/utils/astrepr.nim index c4aa2cf102c..5adfa8f8817 100644 --- a/compiler/utils/astrepr.nim +++ b/compiler/utils/astrepr.nim @@ -5,7 +5,8 @@ import ast, reports, renderer, - lineinfos + lineinfos, + errorhandling ], front/[ options, @@ -152,12 +153,10 @@ proc symFields( if trfShowSymTypes in flags and not sym.typ.isNil(): field("typ", conf.textRepr(sym.typ)) - if trfShowSymLineInfo in flags and sym.info != unknownLineInfo: + if not isNil(conf) and trfShowSymLineInfo in flags and sym.info != unknownLineInfo: field("info", conf.toMsgFilename(sym.info.fileIndex) + fgBlue) - add "(" - add $sym.info.line + fgCyan - add "." - add $sym.info.col + fgCyan + add "(", $sym.info.line + fgCyan + add ".", $sym.info.col + fgCyan add ")" if trfShowSymOwner in flags and not sym.owner.isNil(): @@ -349,7 +348,8 @@ proc treeRepr*( else: field("typ", conf.textRepr(n.typ)) - if trfShowNodeLineInfo in flags and n.info != unknownLineInfo: + if not conf.isNil() and trfShowNodeLineInfo in flags and + n.info != unknownLineInfo: field("info", conf.toMsgFilename(n.info.fileIndex) + fgBlue) add "(" add $n.info.line + fgCyan @@ -400,9 +400,19 @@ proc treeRepr*( addComment() of nkError: - let report = conf.getReport(n).semReport - field("err", substr($report.kind, 4) + termFg(5, 2, 0)) - hfield("errid", $n.reportId.int + fgRed) + if isNil(conf): + field("err", substr($n.errorKind(), 4) + termFg(5, 2, 0)) + + else: + let report = conf.getReport(n).semReport + field("err", substr($report.kind, 4) + termFg(5, 2, 0)) + hfield("errid", $n.reportId.int + fgRed) + + let (file, line, col) = n.compilerInstInfo() + field("info", formatPath(conf, file) + fgBlue) + add "(", $line + fgCyan + add ".", $col + fgCyan + add ")" else: discard @@ -432,3 +442,49 @@ proc treeRepr*( add "\n" aux(pnode, @[]) + +proc debugAst*(it: PNode) {.exportc.} = + ## Print out tree representation of the AST node. + ## + ## .. note:: there is no `ConfigRef` argument, and because of that some + ## information cannot be fully retrieved from the AST (such as full + ## paths of the FileIndex entries). + ## + ## .. tip:: This proc is annotated with `{.exportc.}` which means it's + ## mangled name exactly the same - `debugAst` and you can call it + ## from the `gdb` debugging session. + echo treeRepr(nil, it) + +proc debugType*(it: PType) {.exportc.} = + ## Print out tree represntation of the type. Can also be used in gdb + ## debugging session due to `.exportc.` annotation + echo treeRepr(nil, it) + +proc debugSym*(it: PSym) {.exportc.} = + ## Print out tree represntation of the symbol. Can also be used in gdb + ## debugging session due to `.exportc.` annotation + echo treeRepr(nil, it) + +proc debug*(it: PNode) = + ## Convenience overload of `debugAst` + debugAst(it) + +proc debug*(it: PType) = + ## Convenience overload of `debugType` + debugType(it) + +proc debug*(it: PSym) = + ## Convenience overload of `debugSym` + debugSym(it) + +proc debug*(conf: ConfigRef, it: PNode) = + ## Print tree representation of the AST + echo treeRepr(conf, it) + +proc debug*(conf: ConfigRef, it: PType) = + ## Print tree representation of the type + echo treeRepr(conf, it) + +proc debug*(conf: ConfigRef, it: PSym) = + ## Print tree reprsentation of the symbol + echo treeRepr(conf, it) diff --git a/lib/experimental/colortext.nim b/lib/experimental/colortext.nim index 5665f3f83fd..dfcac0b7fdb 100644 --- a/lib/experimental/colortext.nim +++ b/lib/experimental/colortext.nim @@ -714,7 +714,8 @@ template coloredResult*(indentationStep: int = 2): untyped = template add(arg: untyped): untyped {.used.} = outPtr[].add arg template add(arg1, arg2: untyped): untyped {.used.} = - outPtr[].add(arg1, arg2) + outPtr[].add(arg1) + outPtr[].add(arg2) template addIndent(level: int, sep: int = indentationStep): untyped {.used.} = outPtr[].addIndent(level, sep)