Skip to content

Commit

Permalink
add more APIs to compiler/debugutils; re-export it (#18243)
Browse files Browse the repository at this point in the history
  • Loading branch information
timotheecour committed Jun 18, 2021
1 parent a250481 commit 87cd9b2
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 0 deletions.
37 changes: 37 additions & 0 deletions compiler/debugutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,26 @@ Utilities to help with debugging nim compiler.
Experimental API, subject to change.
]##

#[
## example
useful debugging flags:
--stacktrace -d:debug -d:nimDebugUtils
nim c -o:bin/nim_temp --stacktrace -d:debug -d:nimDebugUtils compiler/nim
## future work
* expose and improve astalgo.debug, replacing it by std/prettyprints,
refs https://github.com/nim-lang/RFCs/issues/385
]#

import options
import std/wrapnils
export wrapnils
# allows using things like: `?.n.sym.typ.len`

import std/stackframes
export stackframes
# allows using things like: `setFrameMsg c.config$n.info & " " & $n.kind`
# which doesn't log, but augments stacktrace with side channel information

var conf0: ConfigRef

Expand All @@ -17,3 +36,21 @@ proc onNewConfigRef*(conf: ConfigRef) {.inline.} =
proc getConfigRef*(): ConfigRef =
## nil, if -d:nimDebugUtils wasn't specified
result = conf0

proc isCompilerDebug*(): bool =
##[
Provides a simple way for user code to enable/disable logging in the compiler
in a granular way. This can then be used in the compiler as follows:
```nim
if isCompilerDebug():
echo ?.n.sym.typ.len
```
]##
runnableExamples:
proc main =
echo 2
{.define(nimCompilerDebug).}
echo 3.5 # code section in which `isCompilerDebug` will be true
{.undef(nimCompilerDebug).}
echo 'x'
conf0.isDefined("nimCompilerDebug")
3 changes: 3 additions & 0 deletions compiler/options.nim
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,10 @@ const foreignPackageNotesDefault* = {
proc isDefined*(conf: ConfigRef; symbol: string): bool

when defined(nimDebugUtils):
# this allows inserting debugging utilties in all modules that import `options`
# with a single switch, which is useful when debugging compiler.
import debugutils
export debugutils

proc initConfigRefCommon(conf: ConfigRef) =
conf.selectedGC = gcRefc
Expand Down
7 changes: 7 additions & 0 deletions compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2716,6 +2716,13 @@ proc getNilType(c: PContext): PType =
proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
when defined(nimCompilerStacktraceHints):
setFrameMsg c.config$n.info & " " & $n.kind
when false: # see `tdebugutils`
if isCompilerDebug():
echo (">", c.config$n.info, n, flags, n.kind)
defer:
if isCompilerDebug():
echo ("<", c.config$n.info, n, ?.result.typ)

result = n
if c.config.cmd == cmdIdeTools: suggestExpr(c, n)
if nfSem in n.flags: return
Expand Down
38 changes: 38 additions & 0 deletions tests/compiler/tdebugutils.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
discard """
joinable: false
disabled: true
"""

#[
This test illustrates some features of `debugutils` to debug the compiler.
## example
this shows how to enable compiler logging just for a section of user code,
without generating tons of unrelated log messages for code you're not interested
in debugging.
```sh
# enable some debugging code, e.g. the `when false:` block in `semExpr`
nim c -o:bin/nim_temp --stacktrace -d:debug -d:nimDebugUtils compiler/nim
bin/nim_temp c tests/compiler/tdebugutils.nim
```
(use --filenames:abs for abs files)
## result
("<", "tdebugutils.nim(16, 3)", {.define(nimCompilerDebug).}, nil)
(">", "tdebugutils.nim(17, 3)", let a = 2.5 * 3, {}, nkLetSection)
(">", "tdebugutils.nim(17, 15)", 2.5 * 3, {efAllowDestructor, efWantValue}, nkInfix)
(">", "tdebugutils.nim(17, 11)", 2.5, {efAllowStmt, efDetermineType, efOperand}, nkFloatLit)
("<", "tdebugutils.nim(17, 11)", 2.5, float64)
(">", "tdebugutils.nim(17, 17)", 3, {efAllowStmt, efDetermineType, efOperand}, nkIntLit)
("<", "tdebugutils.nim(17, 17)", 3, int literal(3))
("<", "tdebugutils.nim(17, 15)", 2.5 * 3, float)
("<", "tdebugutils.nim(17, 3)", let a = 2.5 * 3, nil)
(">", "tdebugutils.nim(18, 3)", {.undef(nimCompilerDebug).}, {}, nkPragma)
]#

proc main =
{.define(nimCompilerDebug).}
let a = 2.5 * 3
{.undef(nimCompilerDebug).}

0 comments on commit 87cd9b2

Please sign in to comment.