Как я могу получить название процедуры в Nim?

Я пытаюсь написать макрос для отладочной печати на языке Nim. В настоящее время этот макрос добавляет filename а такжеline на выход instantiationInfo(),

import macros  
macro debugPrint(msg: untyped): typed =
  result = quote do:
    let pos = instantiationInfo()
    echo pos.filename, ":", pos.line, ": ", `msg`

proc hello() =
  debugPrint "foo bar"
hello()

в настоящее время вывод:

debug_print.nim:9: foo bar

Я хотел бы добавить имя процедуры (или итератора) места, где был вызван макрос.

желаемый результат:

debug_print.nim:9(proc hello): foo bar

Как я могу получить имя процедуры (или итератор) в Nim, как __func__ в С?

2 ответа

Решение

Во время выполнения вы можете сделать getFrame().procname, но он работает только с включенной функцией трассировки стека (не в выпусках сборки).

На удивление во время компиляции я не могу найти способ сделать это. Есть callsite() в модуле макросов, но это не достаточно далеко. Это звучит как то, что может вписаться в macros.LineInfo объект.

Хакерское решение было бы также использовать __func__ и разобрать это обратно в имя процесса Nim:

template procName: string =
  var name: cstring
  {.emit: "`name` = __func__;".}
  ($name).rsplit('_', 1)[0]

Опираясь на ответ из @def-, но делая его более устойчивым для обработки крайних случаев функций, содержащих подчеркивания, и хэшей, содержащих конечные _N, или не используя также более уникальные имена, так как в противном случае макрос потерпит неудачу, если proc определит переменную name

import strutils

proc procNameAux*(name:cstring): string =
  let temp=($name).rsplit('_', 2)
    #CHECKME: IMPROVE; the magic '4' chosen to be enough for most cases
    # EG: bar_baz_9c8JPzPvtM9azO6OB23bjc3Q_3
  if temp.len>=3 and temp[2].len < 4:
    ($name).rsplit('_', 2)[0]
  else:
    # EG: foo_9c8JPzPvtM9azO6OB23bjc3Q
    ($name).rsplit('_', 1)[0]

template procName*: string =
  var name2: cstring
  {.emit: "`name2` = __func__;".}
  procNameAux(name2)

proc foo_bar()=
  echo procName # prints foo_bar

foo_bar()

ПРИМЕЧАНИЕ: это все еще имеет некоторые проблемы, которые запускаются в сложных крайних случаях, см. https://github.com/nim-lang/Nim/issues/8212

Другие вопросы по тегам