макросы
Этот модуль содержит интерфейс к абстрактного синтаксического дерева (AST) компилятора. Макросы работают с этим деревом.
См. также:
AST в Nim
Этот раздел описывает, как AST моделируется с помощью системы типов Nim. AST состоит из узлов (NimNode) с переменным количеством дочерних узлов. Каждый узел имеет поле, названное kind, которое описывает содержимое узла:
type
NimNodeKind = enum ## kind of a node; only explanatory
nnkNone, ## invalid node kind
nnkEmpty, ## empty node
nnkIdent, ## node contains an identifier
nnkIntLit, ## node contains an int literal (example: 10)
nnkStrLit, ## node contains a string literal (example: "abc")
nnkNilLit, ## node contains a nil literal (example: nil)
nnkCaseStmt, ## node represents a case statement
... ## many more
NimNode = ref NimNodeObj
NimNodeObj = object
case kind: NimNodeKind ## the node's kind
of nnkNone, nnkEmpty, nnkNilLit:
discard ## node contains no additional fields
of nnkCharLit..nnkUInt64Lit:
intVal: BiggestInt ## the int literal
of nnkFloatLit..nnkFloat64Lit:
floatVal: BiggestFloat ## the float literal
of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym:
strVal: string ## the string literal
else:
sons: seq[NimNode] ## the node's sons (or children)
Для типа NimNode, оператор [] был перегружен: n[i] — это n-й дочерний узел.
Для указания AST для различных конструкций Nim используется обозначение nodekind(son1, son2, ...) или nodekind(value) или nodekind(field=value).
Некоторые дочерние узлы могут отсутствовать. Отсутствующий дочерний узел имеет тип nnkEmpty; дочерний узел никогда не может быть nil.
Листовые узлы/Атомы
Лист AST часто соответствует терминальному символу в конкретном синтаксисе. Обратите внимание, что по умолчанию float в Nim отображается как float64, так что по умолчанию AST для числа с плавающей запятой — это nnkFloat64Lit, как показано ниже.
| Выражение Nim | Соответствующий AST |
|---|---|
42 |
nnkIntLit(intVal = 42) |
42'i8 |
nnkInt8Lit(intVal = 42) |
42'i16 |
nnkInt16Lit(intVal = 42) |
42'i32 |
nnkInt32Lit(intVal = 42) |
42'i64 |
nnkInt64Lit(intVal = 42) |
42'u8 |
nnkUInt8Lit(intVal = 42) |
42'u16 |
nnkUInt16Lit(intVal = 42) |
42'u32 |
nnkUInt32Lit(intVal = 42) |
42'u64 |
nnkUInt64Lit(intVal = 42) |
42.0 |
nnkFloat64Lit(floatVal = 42.0) |
42.0'f32 |
nnkFloat32Lit(floatVal = 42.0) |
42.0'f64 |
nnkFloat64Lit(floatVal = 42.0) |
"abc" |
nnkStrLit(strVal = "abc") |
r"abc" |
nnkRStrLit(strVal = "abc") |
"""abc""" |
nnkTripleStrLit(strVal = "abc") |
' ' |
nnkCharLit(intVal = 32) |
nil |
nnkNilLit() |
myIdentifier |
nnkIdent(strVal = "myIdentifier") |
myIdentifier |
после прохода поиска: nnkSym(strVal = "myIdentifier", ...)
|
Идентификаторы — это узлы nnkIdent. После прохода поиска имён эти узлы преобразуются в узлы nnkSym.
Вызовы/выражения
Вызов команды
Конкретный синтаксис:
echo "abc", "xyz"
AST:
nnkCommand(
nnkIdent("echo"),
nnkStrLit("abc"),
nnkStrLit("xyz")
) Вызов с ()
Конкретный синтаксис:
echo("abc", "xyz")
AST:
nnkCall(
nnkIdent("echo"),
nnkStrLit("abc"),
nnkStrLit("xyz")
) Вызов инфиксного оператора
Конкретный синтаксис:
"abc" & "xyz"
AST:
nnkInfix(
nnkIdent("&"),
nnkStrLit("abc"),
nnkStrLit("xyz")
)
Обратите внимание, что при использовании нескольких инфиксных операторов команда анализируется с учётом приоритета операторов.
Конкретный синтаксис:
5 + 3 * 4
AST:
nnkInfix(
nnkIdent("+"),
nnkIntLit(5),
nnkInfix(
nnkIdent("*"),
nnkIntLit(3),
nnkIntLit(4)
)
)
Если вы решите использовать инфиксные операторы в префиксной форме, AST будет вести себя как вызов родительской функции с nnkAccQuoted, как показано ниже:
Конкретный синтаксис:
`+`(3, 4)
AST:
nnkCall(
nnkAccQuoted(
nnkIdent("+")
),
nnkIntLit(3),
nnkIntLit(4)
) Вызов префиксного оператора
Конкретный синтаксис:
? "xyz"
AST:
nnkPrefix(
nnkIdent("?"),
nnkStrLit("abc")
) Вызов постфиксного оператора
Примечание: В Nim нет постфиксных операторов. Однако узел nnkPostfix используется для маркера экспорта звёздочкой *.
Конкретный синтаксис:
identifier*
AST:
nnkPostfix(
nnkIdent("*"),
nnkIdent("identifier")
) Вызов с именованными аргументами
Конкретный синтаксис:
writeLine(file=stdout, "hallo")
AST:
nnkCall(
nnkIdent("writeLine"),
nnkExprEqExpr(
nnkIdent("file"),
nnkIdent("stdout")
),
nnkStrLit("hallo")
) Вызов с литералом необработанной строки
Это используется, например, в примерах bindSym здесь и с re"some regexp" в модуле регулярных выражений.
Конкретный синтаксис:
echo"abc"
AST:
nnkCallStrLit(
nnkIdent("echo"),
nnkRStrLit("hello")
) Оператор разыменования []
Конкретный синтаксис:
x[]
AST:
nnkDerefExpr(nnkIdent("x")) Оператор addr
Конкретный синтаксис:
addr(x)
AST:
nnkAddr(nnkIdent("x")) Оператор приведения типа
Конкретный синтаксис:
cast[T](x)
AST:
nnkCast(nnkIdent("T"), nnkIdent("x")) Оператор доступа к объекту .
Конкретный синтаксис:
x.y
AST:
nnkDotExpr(nnkIdent("x"), nnkIdent("y"))
Если вы используете гибкий синтаксис вызова Nim (как в x.len()), результат будет таким же, но обернут в nnkCall.
Оператор доступа к массиву []
Конкретный синтаксис:
x[y]
AST:
nnkBracketExpr(nnkIdent("x"), nnkIdent("y")) Скобки
Скобки для влияния на приоритет операторов или построения кортежей создаются с помощью узла nnkPar.
Конкретный синтаксис:
(1, 2, (3))
AST:
nnkPar(nnkIntLit(1), nnkIntLit(2), nnkPar(nnkIntLit(3)))
Фигурные скобки
Фигурные скобки используются как конструктор множества.
Конкретный синтаксис:
{1, 2, 3}
AST:
nnkCurly(nnkIntLit(1), nnkIntLit(2), nnkIntLit(3))
При использовании как конструктора таблицы синтаксис отличается.
Конкретный синтаксис:
{a: 3, b: 5}
AST:
nnkTableConstr(
nnkExprColonExpr(nnkIdent("a"), nnkIntLit(3)),
nnkExprColonExpr(nnkIdent("b"), nnkIntLit(5))
) Квадратные скобки
Квадратные скобки используются как конструктор массива.
Конкретный синтаксис:
[1, 2, 3]
AST:
nnkBracket(nnkIntLit(1), nnkIntLit(2), nnkIntLit(3))
Диапазоны
Диапазоны встречаются в конструкторах множеств, ветвях оператора case или срезах массивов. Внутренне используется тип узла nnkRange, но при построении AST вместо этого следует использовать построение с .. как инфиксным оператором.
Конкретный синтаксис:
1..3
AST:
nnkInfix(
nnkIdent(".."),
nnkIntLit(1),
nnkIntLit(3)
)
Пример кода:
macro genRepeatEcho(): stmt =
result = newNimNode(nnkStmtList)
var forStmt = newNimNode(nnkForStmt) # generate a for statement
forStmt.add(ident("i")) # use the variable `i` for iteration
var rangeDef = newNimNode(nnkInfix).add(
ident("..")).add(
newIntLitNode(3),newIntLitNode(5)) # iterate over the range 3..5
forStmt.add(rangeDef)
forStmt.add(newCall(ident("echo"), newIntLitNode(3))) # meat of the loop
result.add(forStmt)
genRepeatEcho() # gives:
# 3
# 3
# 3 Выражение if
Представление выражения if тонкое, но легко просматривается.
Конкретный синтаксис:
if cond1: expr1 elif cond2: expr2 else: expr3
AST:
nnkIfExpr( nnkElifExpr(cond1, expr1), nnkElifExpr(cond2, expr2), nnkElseExpr(expr3) )
Комментарии документации
Комментарии с двойным диез (##) в коде фактически имеют собственный формат, используя strVal для получения и установки текста комментария. Комментарии с одиночным диез (#) игнорируются.
Конкретный синтаксис:
## This is a comment ## This is part of the first comment stmt1 ## Yet another
AST:
nnkCommentStmt() # only appears once for the first two lines!
stmt1
nnkCommentStmt() # another nnkCommentStmt because there is another comment
# (separate from the first) Директивы
Одной из интересных особенностей Nim являются директивы, позволяющие тонко настраивать различные аспекты языка. Они бывают разных типов, например, украшают процедуры и объекты, но отдельная директива emit демонстрирует основы с AST.
Конкретный синтаксис:
{.emit: "#include <stdio.h>".}
AST:
nnkPragma(
nnkExprColonExpr(
nnkIdent("emit"),
nnkStrLit("#include <stdio.h>") # the "argument"
)
)
Появляется столько nnkIdent , сколько директив находится между {..}. Обратите внимание, что объявление новых директив по сути то же самое:
Конкретный синтаксис:
{.pragma: cdeclRename, cdecl.}
AST:
nnkPragma(
nnkExprColonExpr(
nnkIdent("pragma"), # this is always first when declaring a new pragma
nnkIdent("cdeclRename") # the name of the pragma
),
nnkIdent("cdecl")
) Операторы
Оператор if
Представление оператора if тонкое, но легко просматривается. Если нет ветви else, дочерний узел nnkElse отсутствует.
Конкретный синтаксис:
if cond1: stmt1 elif cond2: stmt2 elif cond3: stmt3 else: stmt4
AST:
nnkIfStmt( nnkElifBranch(cond1, stmt1), nnkElifBranch(cond2, stmt2), nnkElifBranch(cond3, stmt3), nnkElse(stmt4) )
Оператор when
Как оператор if, но корень имеет тип nnkWhenStmt.
Присваивание
Конкретный синтаксис:
x = 42
AST:
nnkAsgn(nnkIdent("x"), nnkIntLit(42))
Это не синтаксис присваивания, когда он комбинируется с var, let, или const.
Список операторов
Конкретный синтаксис:
stmt1 stmt2 stmt3
AST:
nnkStmtList(stmt1, stmt2, stmt3)
Оператор case
Конкретный синтаксис:
case expr1 of expr2, expr3..expr4: stmt1 of expr5: stmt2 elif cond1: stmt3 else: stmt4
AST:
nnkCaseStmt( expr1, nnkOfBranch(expr2, nnkRange(expr3, expr4), stmt1), nnkOfBranch(expr5, stmt2), nnkElifBranch(cond1, stmt3), nnkElse(stmt4) )
Части nnkElifBranch и nnkElse могут отсутствовать.
Оператор while
Конкретный синтаксис:
while expr1: stmt1
AST:
nnkWhileStmt(expr1, stmt1)
Оператор for
Конкретный синтаксис:
for ident1, ident2 in expr1: stmt1
AST:
nnkForStmt(ident1, ident2, expr1, stmt1)
Оператор try
Конкретный синтаксис:
try: stmt1 except e1, e2: stmt2 except e3: stmt3 except: stmt4 finally: stmt5
AST:
nnkTryStmt( stmt1, nnkExceptBranch(e1, e2, stmt2), nnkExceptBranch(e3, stmt3), nnkExceptBranch(stmt4), nnkFinally(stmt5) )
Оператор return
Конкретный синтаксис:
return expr1
AST:
nnkReturnStmt(expr1)
Оператор yield
Как return, но с типом узла nnkYieldStmt.
nnkYieldStmt(expr1)
Оператор discard
Как return, но с типом узла nnkDiscardStmt.
nnkDiscardStmt(expr1)
Оператор continue
Конкретный синтаксис:
continue
AST:
nnkContinueStmt()
Оператор break
Конкретный синтаксис:
break otherLocation
AST:
nnkBreakStmt(nnkIdent("otherLocation"))
Если break используется без места перехода, nnkEmpty заменяет nnkIdent.
Оператор блока
Конкретный синтаксис:
block name:
AST:
nnkBlockStmt(nnkIdent("name"), nnkStmtList(...))
Блок block не нуждается в имени, в этом случае используется nnkEmpty.
Оператор asm
Конкретный синтаксис:
asm """ some asm """
AST:
nnkAsmStmt(
nnkEmpty(), # for pragmas
nnkTripleStrLit("some asm"),
) Раздел импорта
Заявление Nim's import фактически принимает различные варианты в зависимости от присутствующих ключевых слов. Начнем с самого простого варианта.
Конкретная синтаксическая запись:
import math
AST:
nnkImportStmt(nnkIdent("math"))
С except, мы получаем nnkImportExceptStmt.
Конкретная синтаксическая запись:
import math except pow
AST:
nnkImportExceptStmt(nnkIdent("math"),nnkIdent("pow"))
Обратите внимание, что import math as m не использует другой узел; вместо этого мы используем nnkImportStmt с as в качестве инфиксного оператора.
Конкретная синтаксическая запись:
import strutils as su
AST:
nnkImportStmt(
nnkInfix(
nnkIdent("as"),
nnkIdent("strutils"),
nnkIdent("su")
)
) Из заявления
Если мы используем from ... import, результат также отличается.
Конкретная синтаксическая запись:
from math import pow
AST:
nnkFromStmt(nnkIdent("math"), nnkIdent("pow"))
Использование from math as m import pow идентично модификатору as со import заявлением, но заключено в nnkFromStmt.
Заявление о выводе
Когда вы делаете импортированный модуль доступным для модулей, которые импортируют ваш модуль, синтаксис export довольно простой.
Конкретная синтаксическая запись:
export unsigned
AST:
nnkExportStmt(nnkIdent("unsigned"))
Подобно заявлению import, AST отличается для export ... except.
Конкретная синтаксическая запись:
export math except pow # we're going to implement our own exponentiation
AST:
nnkExportExceptStmt(nnkIdent("math"),nnkIdent("pow")) Заявление об включении
Как и простое import заявление, но с nnkIncludeStmt.
Конкретная синтаксическая запись:
include blocks
AST:
nnkIncludeStmt(nnkIdent("blocks")) Раздел Var
Конкретная синтаксическая запись:
var a = 3
AST:
nnkVarSection(
nnkIdentDefs(
nnkIdent("a"),
nnkEmpty(), # or nnkIdent(...) if the variable declares the type
nnkIntLit(3),
)
)
Обратите внимание, что второй или третий (или оба) параметра выше должны существовать, так как компилятор должен каким-то образом узнать тип (который он может вывести из заданного присваивания).
Это не тот же AST для всех случаев использования var. Подробности см. в разделе Объявление процедуры.
Раздел Let
Это эквивалентно var, но с nnkLetSection вместо nnkVarSection.
Конкретная синтаксическая запись:
let a = 3
AST:
nnkLetSection(
nnkIdentDefs(
nnkIdent("a"),
nnkEmpty(), # or nnkIdent(...) for the type
nnkIntLit(3),
)
) Раздел Const
Конкретная синтаксическая запись:
const a = 3
AST:
nnkConstSection(
nnkConstDef( # not nnkConstDefs!
nnkIdent("a"),
nnkEmpty(), # or nnkIdent(...) if the variable declares the type
nnkIntLit(3), # required in a const declaration!
)
) Раздел Type
Начиная с простого случая, раздел type выглядит так же, как var и const.
Конкретная синтаксическая запись:
type A = int
AST:
nnkTypeSection(
nnkTypeDef(
nnkIdent("A"),
nnkEmpty(),
nnkIdent("int")
)
)
Объявление типов distinct аналогично, при этом последнее nnkIdent заключено в nnkDistinctTy.
Конкретная синтаксическая запись:
type MyInt = distinct int
AST:
# ...
nnkTypeDef(
nnkIdent("MyInt"),
nnkEmpty(),
nnkDistinctTy(
nnkIdent("int")
)
)
Если раздел type использует параметры обобщения, они обрабатываются здесь:
Конкретная синтаксическая запись:
type A[T] = expr1
AST:
nnkTypeSection(
nnkTypeDef(
nnkIdent("A"),
nnkGenericParams(
nnkIdentDefs(
nnkIdent("T"),
nnkEmpty(), # if the type is declared with options, like
# ``[T: SomeInteger]``, they are given here
nnkEmpty(),
)
)
expr1,
)
)
Обратите внимание, что не все nnkTypeDef используют nnkIdent в качестве параметра. Одно из наиболее распространенных применений объявлений типов — работа с объектами.
Конкретная синтаксическая запись:
type IO = object of RootObj
AST:
# ...
nnkTypeDef(
nnkIdent("IO"),
nnkEmpty(),
nnkObjectTy(
nnkEmpty(), # no pragmas here
nnkOfInherit(
nnkIdent("RootObj") # inherits from RootObj
)
nnkEmpty()
)
)
Синтаксис объектов Nim богат. Давайте рассмотрим сложный пример целиком, чтобы увидеть некоторые из сложностей.
Конкретная синтаксическая запись:
type Obj[T] = object {.inheritable.}
name: string
case isFat: bool
of true:
m: array[100_000, T]
of false:
m: array[10, T]
AST:
# ...
nnkObjectTy(
nnkPragma(
nnkIdent("inheritable")
),
nnkEmpty(),
nnkRecList( # list of object parameters
nnkIdentDefs(
nnkIdent("name"),
nnkIdent("string"),
nnkEmpty()
),
nnkRecCase( # case statement within object (not nnkCaseStmt)
nnkIdentDefs(
nnkIdent("isFat"),
nnkIdent("bool"),
nnkEmpty()
),
nnkOfBranch(
nnkIdent("true"),
nnkRecList( # again, a list of object parameters
nnkIdentDefs(
nnkIdent("m"),
nnkBracketExpr(
nnkIdent("array"),
nnkIntLit(100000),
nnkIdent("T")
),
nnkEmpty()
)
),
nnkOfBranch(
nnkIdent("false"),
nnkRecList(
nnkIdentDefs(
nnkIdent("m"),
nnkBracketExpr(
nnkIdent("array"),
nnkIntLit(10),
nnkIdent("T")
),
nnkEmpty()
)
)
)
)
)
)
Использование enum аналогично использованию object.
Конкретная синтаксическая запись:
type X = enum First
AST:
# ...
nnkEnumTy(
nnkEmpty(),
nnkIdent("First") # you need at least one nnkIdent or the compiler complains
)
Использование concept (экспериментальная) аналогично объектам.
Конкретная синтаксическая запись:
type Con = concept x,y,z (x & y & z) is string
AST:
# ...
nnkTypeClassTy( # note this isn't nnkConceptTy!
nnkArglist(
# ... idents for x, y, z
)
# ...
)
Статические типы, такие как static[int], используют nnkIdent в nnkStaticTy.
Конкретная синтаксическая запись:
type A[T: static[int]] = object
AST:
# ... within nnkGenericParams
nnkIdentDefs(
nnkIdent("T"),
nnkStaticTy(
nnkIdent("int")
),
nnkEmpty()
)
# ...
В общем случае объявление типов отражает этот синтаксис (например, nnkStaticTy для static, и т. д.). Далее следуют примеры (исключения помечены как *):
| Тип Nim | Соответствующий AST |
|---|---|
static |
nnkStaticTy |
tuple |
nnkTupleTy |
var |
nnkVarTy |
ptr |
nnkPtrTy |
ref |
nnkRefTy |
distinct |
nnkDistinctTy |
enum |
nnkEnumTy |
concept |
nnkTypeClassTy* |
array |
nnkBracketExpr(nnkIdent("array"),...* |
proc |
nnkProcTy |
iterator |
nnkIteratorTy |
object |
nnkObjectTy |
Обращайте особое внимание при объявлении типов как proc. Поведение аналогично Procedure declaration, ниже, но nnkGenericParams не обрабатывается. Параметры обобщения обрабатываются в типе, а не в самом proc.
Конкретная синтаксическая запись:
type MyProc[T] = proc(x: T)
AST:
# ...
nnkTypeDef(
nnkIdent("MyProc"),
nnkGenericParams( # here, not with the proc
# ...
)
nnkProcTy( # behaves like a procedure declaration from here on
nnkFormalParams(
# ...
)
)
)
Тот же синтаксис применяется к iterator (с nnkIteratorTy), но не применяется к converter или template.
Заявление Mixin
Конкретная синтаксическая запись:
mixin x
AST:
nnkMixinStmt(nnkIdent("x")) Заявление Bind
Конкретная синтаксическая запись:
bind x
AST:
nnkBindStmt(nnkIdent("x")) Объявление процедуры
Давайте рассмотрим процедуру со многими интересными аспектами, чтобы понять, как разбиваются вызовы процедур.
Конкретная синтаксическая запись:
proc hello*[T: SomeInteger](x: int = 3, y: float32): int {.inline.} = discard
AST:
nnkProcDef(
nnkPostfix(nnkIdent("*"), nnkIdent("hello")), # the exported proc name
nnkEmpty(), # patterns for term rewriting in templates and macros (not procs)
nnkGenericParams( # generic type parameters, like with type declaration
nnkIdentDefs(
nnkIdent("T"),
nnkIdent("SomeInteger"),
nnkEmpty()
)
),
nnkFormalParams(
nnkIdent("int"), # the first FormalParam is the return type. nnkEmpty() if there is none
nnkIdentDefs(
nnkIdent("x"),
nnkIdent("int"), # type type (required for procs, not for templates)
nnkIntLit(3) # a default value
),
nnkIdentDefs(
nnkIdent("y"),
nnkIdent("float32"),
nnkEmpty()
)
),
nnkPragma(nnkIdent("inline")),
nnkEmpty(), # reserved slot for future use
nnkStmtList(nnkDiscardStmt(nnkEmpty())) # the meat of the proc
)
Есть еще один момент. Nim имеет гибкую идентификацию типов для своих процедур. Несмотря на то, что proc(a: int, b: int) и proc(a, b: int) эквивалентны в коде, AST немного отличается для последнего.
Конкретная синтаксическая запись:
proc(a, b: int)
AST:
# ...AST as above...
nnkFormalParams(
nnkEmpty(), # no return here
nnkIdentDefs(
nnkIdent("a"), # the first parameter
nnkIdent("b"), # directly to the second parameter
nnkIdent("int"), # their shared type identifier
nnkEmpty(), # default value would go here
)
),
# ...
Когда процедура использует специальную переменную типа возврата var, результат отличается от результата раздела var.
Конкретная синтаксическая запись:
proc hello(): var int
AST:
# ...
nnkFormalParams(
nnkVarTy(
nnkIdent("int")
)
) Объявление итератора
Синтаксис итераторов похож на процедуры, но nnkIteratorDef заменяет nnkProcDef.
Конкретная синтаксическая запись:
iterator nonsense[T](x: seq[T]): float {.closure.} = ...
AST:
nnkIteratorDef(
nnkIdent("nonsense"),
nnkEmpty(),
...
) Объявление преобразователя
Преобразователь похож на процедуру.
Конкретная синтаксическая запись:
converter toBool(x: float): bool
AST:
nnkConverterDef(
nnkIdent("toBool"),
# ...
) Объявление шаблона
Шаблоны (а также макросы, как мы увидим) имеют немного расширенный AST по сравнению с процедурами и итераторами. Причина в этом [макросы переписывания терминов](manual.html#term-rewriting-macros). Вы видите nnkEmpty() в качестве второго аргумента к nnkProcDef и nnkIteratorDef выше? Именно туда попадают макросы переписывания терминов.
Конкретная синтаксическая запись:
template optOpt{expr1}(a: int): int
AST:
nnkTemplateDef(
nnkIdent("optOpt"),
nnkStmtList( # instead of nnkEmpty()
expr1
),
# follows like a proc or iterator
)
Если шаблон не имеет типов для своих параметров, идентификаторы типов внутри nnkFormalParams просто становятся nnkEmpty.
Объявление макроса
Макросы ведут себя как шаблоны, но nnkTemplateDef заменяется на nnkMacroDef.
Особые виды узлов
Существует несколько видов узлов, используемых для семантической проверки или генерации кода. Они доступны из этого модуля, но не должны использоваться. Другие виды узлов специально разработаны для упрощения манипулирования AST. Они описаны здесь.
Будет написано позже.
Импорты
- since
Типы
NimNodeKind = enum nnkNone, nnkEmpty, nnkIdent, nnkSym, nnkType, nnkCharLit, nnkIntLit, nnkInt8Lit, nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkUIntLit, nnkUInt8Lit, nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit, nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit, nnkTripleStrLit, nnkNilLit, nnkComesFrom, nnkDotCall, nnkCommand, nnkCall, nnkCallStrLit, nnkInfix, nnkPrefix, nnkPostfix, nnkHiddenCallConv, nnkExprEqExpr, nnkExprColonExpr, nnkIdentDefs, nnkVarTuple, nnkPar, nnkObjConstr, nnkCurly, nnkCurlyExpr, nnkBracket, nnkBracketExpr, nnkPragmaExpr, nnkRange, nnkDotExpr, nnkCheckedFieldExpr, nnkDerefExpr, nnkIfExpr, nnkElifExpr, nnkElseExpr, nnkLambda, nnkDo, nnkAccQuoted, nnkTableConstr, nnkBind, nnkClosedSymChoice, nnkOpenSymChoice, nnkHiddenStdConv, nnkHiddenSubConv, nnkConv, nnkCast, nnkStaticExpr, nnkAddr, nnkHiddenAddr, nnkHiddenDeref, nnkObjDownConv, nnkObjUpConv, nnkChckRangeF, nnkChckRange64, nnkChckRange, nnkStringToCString, nnkCStringToString, nnkAsgn, nnkFastAsgn, nnkGenericParams, nnkFormalParams, nnkOfInherit, nnkImportAs, nnkProcDef, nnkMethodDef, nnkConverterDef, nnkMacroDef, nnkTemplateDef, nnkIteratorDef, nnkOfBranch, nnkElifBranch, nnkExceptBranch, nnkElse, nnkAsmStmt, nnkPragma, nnkPragmaBlock, nnkIfStmt, nnkWhenStmt, nnkForStmt, nnkParForStmt, nnkWhileStmt, nnkCaseStmt, nnkTypeSection, nnkVarSection, nnkLetSection, nnkConstSection, nnkConstDef, nnkTypeDef, nnkYieldStmt, nnkDefer, nnkTryStmt, nnkFinally, nnkRaiseStmt, nnkReturnStmt, nnkBreakStmt, nnkContinueStmt, nnkBlockStmt, nnkStaticStmt, nnkDiscardStmt, nnkStmtList, nnkImportStmt, nnkImportExceptStmt, nnkExportStmt, nnkExportExceptStmt, nnkFromStmt, nnkIncludeStmt, nnkBindStmt, nnkMixinStmt, nnkUsingStmt, nnkCommentStmt, nnkStmtListExpr, nnkBlockExpr, nnkStmtListType, nnkBlockType, nnkWith, nnkWithout, nnkTypeOfExpr, nnkObjectTy, nnkTupleTy, nnkTupleClassTy, nnkTypeClassTy, nnkStaticTy, nnkRecList, nnkRecCase, nnkRecWhen, nnkRefTy, nnkPtrTy, nnkVarTy, nnkConstTy, nnkMutableTy, nnkDistinctTy, nnkProcTy, nnkIteratorTy, nnkSharedTy, nnkEnumTy, nnkEnumFieldDef, nnkArglist, nnkPattern, nnkHiddenTryStmt, nnkClosure, nnkGotoState, nnkState, nnkBreakState, nnkFuncDef, nnkTupleConstr
- Исходный код Редактировать
NimNodeKinds = set[NimNodeKind]
- Исходный код Редактировать
NimTypeKind = enum ntyNone, ntyBool, ntyChar, ntyEmpty, ntyAlias, ntyNil, ntyExpr, ntyStmt, ntyTypeDesc, ntyGenericInvocation, ntyGenericBody, ntyGenericInst, ntyGenericParam, ntyDistinct, ntyEnum, ntyOrdinal, ntyArray, ntyObject, ntyTuple, ntySet, ntyRange, ntyPtr, ntyRef, ntyVar, ntySequence, ntyProc, ntyPointer, ntyOpenArray, ntyString, ntyCString, ntyForward, ntyInt, ntyInt8, ntyInt16, ntyInt32, ntyInt64, ntyFloat, ntyFloat32, ntyFloat64, ntyFloat128, ntyUInt, ntyUInt8, ntyUInt16, ntyUInt32, ntyUInt64, ntyUnused0, ntyUnused1, ntyUnused2, ntyVarargs, ntyUncheckedArray, ntyError, ntyBuiltinTypeClass, ntyUserTypeClass, ntyUserTypeClassInst, ntyCompositeTypeClass, ntyInferred, ntyAnd, ntyOr, ntyNot, ntyAnything, ntyStatic, ntyFromExpr, ntyOptDeprecated, ntyVoid
- Исходный код Редактировать
TNimTypeKinds {...}{.deprecated.} = set[NimTypeKind]- Исходный код Редактировать
NimSymKind = enum nskUnknown, nskConditional, nskDynLib, nskParam, nskGenericParam, nskTemp, nskModule, nskType, nskVar, nskLet, nskConst, nskResult, nskProc, nskFunc, nskMethod, nskIterator, nskConverter, nskMacro, nskTemplate, nskField, nskEnumField, nskForVar, nskLabel, nskStub
- Исходный код Редактировать
TNimSymKinds {...}{.deprecated.} = set[NimSymKind]- Исходный код Редактировать
NimIdent {...}{.deprecated.} = object of RootObj- Представляет идентификатор Nim в AST. Примечание: Это редко используется, для создания идентификатора из строки используйте
ident"abc". Исходный код Редактировать NimSym {...}{.deprecated.} = ref NimSymObj- Представляет символ Nim в компиляторе; символ — это идентификатор, по которому производится поиск. Исходный код Редактировать
BindSymRule = enum brClosed, ## only the symbols in current scope are bound brOpen, ## open wrt overloaded symbols, but may be a single ## symbol if not ambiguous (the rules match that of ## binding in generics) brForceOpen ## same as brOpen, but it will always be open even ## if not ambiguous (this cannot be achieved with ## any other means in the language currently)- определяет, как ведет себя
bindSymИсходный код Редактировать LineInfo = object filename*: string line*, column*: int
- Исходный код Редактировать
Константы
nnkLiterals = {nnkCharLit..nnkNilLit}- Исходный код Редактировать
nnkCallKinds = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallStrLit}- Исходный код Редактировать
RoutineNodes = {nnkProcDef, nnkFuncDef, nnkMethodDef, nnkDo, nnkLambda, nnkIteratorDef, nnkTemplateDef, nnkConverterDef, nnkMacroDef}- Исходный код Редактировать
AtomicNodes = {nnkNone..nnkNilLit}- Исходный код Редактировать
CallNodes = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand, nnkCallStrLit, nnkHiddenCallConv}- Исходный код Редактировать
Процедуры
proc toNimIdent(s: string): NimIdent {...}{.magic: "StrToIdent", noSideEffect, deprecated: "Deprecated since version 0.18.0: Use \'ident\' or \'newIdentNode\' instead.".}- Создаёт идентификатор из строки
s. Исходный код Редактировать proc `==`(a, b: NimIdent): bool {...}{.magic: "EqIdent", noSideEffect, deprecated: "Deprecated since version 0.18.1; Use \'==\' on \'NimNode\' instead.".}- Сравнивает два идентификатора Nim. Исходный код Редактировать
proc `==`(a, b: NimNode): bool {...}{.magic: "EqNimrodNode", noSideEffect.}- Сравнивает два узла Nim. Возвращает true, если узлы структурно эквивалентны. Это означает, что два независимо созданных узла могут быть равны. Исходный код Редактировать
proc `==`(a, b: NimSym): bool {...}{.magic: "EqNimrodNode", noSideEffect, deprecated: "Deprecated since version 0.18.1; Use \'==(NimNode, NimNode)\' instead.".}- Сравнивает два символа Nim. Исходный код Редактировать
proc sameType(a, b: NimNode): bool {...}{.magic: "SameNodeType", noSideEffect, raises: [], tags: [].}- Сравнивает типы двух узлов Nim. Возвращает true, если типы одинаковы, например, при сравнении алиаса с исходным типом. Исходный код Редактировать
proc len(n: NimNode): int {...}{.magic: "NLen", noSideEffect.}- Возвращает количество дочерних элементов
n. Исходный код Редактировать proc `[]`(n: NimNode; i: int): NimNode {...}{.magic: "NChild", noSideEffect.}- Получить
n'si-й дочерний элемент. Исходный код Редактировать proc `[]`(n: NimNode; i: BackwardsIndex): NimNode {...}{.raises: [], tags: [].}- Получить
n'si-й дочерний элемент. Исходный код Редактировать proc `[]`[T, U](n: NimNode; x: HSlice[T, U]): seq[NimNode]
- Операция среза для NimNode. Возвращает последовательность дочерних элементов
nв пределах диапазона [n[x.a], n[x.b]]. Исходный код Редактировать proc `[]=`(n: NimNode; i: int; child: NimNode) {...}{.magic: "NSetChild", noSideEffect.}- Установить
n'si-й дочерний элемент вchild. Исходный код Редактировать proc `[]=`(n: NimNode; i: BackwardsIndex; child: NimNode) {...}{.raises: [], tags: [].}- Установить
n'si-й дочерний элемент вchild. Исходный код Редактировать proc add(father, child: NimNode): NimNode {...}{.magic: "NAdd", discardable, noSideEffect, locks: 0.}- Добавляет
childк узлуfather. Возвращает родительский узел для вложенных вызовов. Исходный код Редактировать proc add(father: NimNode; children: varargs[NimNode]): NimNode {...}{. magic: "NAddMultiple", discardable, noSideEffect, locks: 0.}- Добавляет каждый дочерний элемент
childrenк узлуfather. Возвращает узелfatherдля вложенных вызовов. Исходный код Редактировать proc del(father: NimNode; idx = 0; n = 1) {...}{.magic: "NDel", noSideEffect.}- Удаляет
nдочерних элементовfather, начиная с индексаidx. Исходный код Редактировать proc kind(n: NimNode): NimNodeKind {...}{.magic: "NKind", noSideEffect.}- Возвращает
kindузлаn. Исходный код Редактировать proc intVal(n: NimNode): BiggestInt {...}{.magic: "NIntVal", noSideEffect.}- Возвращает целое значение из любого целочисленного литерала или символа поля перечисления. Исходный код Редактировать
proc floatVal(n: NimNode): BiggestFloat {...}{.magic: "NFloatVal", noSideEffect.}- Возвращает число с плавающей точкой из любого литерала с плавающей точкой. Исходный код Редактировать
proc ident(n: NimNode): NimIdent {...}{.magic: "NIdent", noSideEffect, deprecated: "Deprecated since version 0.18.1; All functionality is defined on \'NimNode\'.".}- Исходный код Редактировать
proc symbol(n: NimNode): NimSym {...}{.magic: "NSymbol", noSideEffect, deprecated: "Deprecated since version 0.18.1; All functionality is defined on \'NimNode\'.".}- Исходный код Редактировать
proc getImpl(s: NimSym): NimNode {...}{.magic: "GetImpl", noSideEffect, deprecated: "use `getImpl: NimNode -> NimNode` instead".}- Исходный код Редактировать
proc symKind(symbol: NimNode): NimSymKind {...}{.magic: "NSymKind", noSideEffect.}- Исходный код Редактировать
proc getImpl(symbol: NimNode): NimNode {...}{.magic: "GetImpl", noSideEffect.}- Возвращает копию объявления символа или
nil. Исходный код Редактировать proc strVal(n: NimNode): string {...}{.magic: "NStrVal", noSideEffect.}-
Возвращает строковое значение идентификатора, символа, комментария или строкового литерала.
См. также:
- strVal= proc для установки строкового значения.
proc `$`(i: NimIdent): string {...}{.magic: "NStrVal", noSideEffect, deprecated: "Deprecated since version 0.18.1; Use \'strVal\' instead.".}- Преобразует идентификатор Nim в строку. Исходный код Редактировать
proc `$`(s: NimSym): string {...}{.magic: "NStrVal", noSideEffect, deprecated: "Deprecated since version 0.18.1; Use \'strVal\' instead.".}- Преобразует символ Nim в строку. Исходный код Редактировать
proc getImplTransformed(symbol: NimNode): NimNode {...}{.magic: "GetImplTransf", noSideEffect.}- Для типизированных proc возвращает AST после прохода трансформации; это полезно для отладки того, как компилятор преобразует код (например:
defer,for), но обратите внимание, что преобразования кода зависят от реализации и могут быть изменены. См. пример вtests/macros/tmacros_various.nim. Исходный код Редактировать proc owner(sym: NimNode): NimNode {...}{.magic: "SymOwner", noSideEffect.}-
Принимает узел типа
nnkSymи возвращает символ владельца. Значение 'владелец' зависит отsym'sNimSymKindи контекста объявления. Для объявления верхнего уровня это символnskModule, для локальных переменных proc -nskProcсимвол, для полей enum/object -nskTypeсимвол и т.д. Для символов без владельца возвращаетсяnil.См. также:
- symKind proc для получения типа символа
- getImpl proc для получения объявления символа
proc isInstantiationOf(instanceProcSym, genProcSym: NimNode): bool {...}{. magic: "SymIsInstantiationOf", noSideEffect.}- Проверяет, является ли символ proc экземпляром символа универсального proc. Полезно для проверки символов proc по отношению к универсальным символам, возвращаемым
bindSym. Исходный код Редактировать proc getType(n: NimNode): NimNode {...}{.magic: "NGetType", noSideEffect.}
- С помощью 'getType' вы можете получить тип узла. Тип Nim отображается в Nim AST, поэтому это немного запутанно, но это означает, что один и тот же API можно использовать для обхода типов. Рекурсивные типы сглаживаются для вас, поэтому нет опасности бесконечной рекурсии во время обхода. Чтобы разрешить рекурсивные типы, нужно снова вызвать 'getType'. Чтобы узнать, какой тип это, вызовите
typeKindна результате getType. Исходный код Изменить proc getType(n: typedesc): NimNode {...}{.magic: "NGetType", noSideEffect.}- Версия
getType, которая принимаетtypedesc. Исходный код Изменить proc typeKind(n: NimNode): NimTypeKind {...}{.magic: "NGetType", noSideEffect.}- Возвращает тип узла 'n', который должен представлять тип, то есть узел должен быть получен с помощью
getType. Исходный код Изменить proc getTypeInst(n: NimNode): NimNode {...}{.magic: "NGetType", noSideEffect, raises: [], tags: [].}- Возвращает тип узла в форме, соответствующей тому, как экземпляр типа был объявлен в коде.
Пример:
type Vec[N: static[int], T] = object arr: array[N, T] Vec4[T] = Vec[4, T] Vec4f = Vec4[float32] var a: Vec4f var b: Vec4[float32] var c: Vec[4, float32] macro dumpTypeInst(x: typed): untyped = newLit(x.getTypeInst.repr) doAssert(dumpTypeInst(a) == "Vec4f") doAssert(dumpTypeInst(b) == "Vec4[float32]") doAssert(dumpTypeInst(c) == "Vec[4, float32]")Исходный код Изменить proc getTypeInst(n: typedesc): NimNode {...}{.magic: "NGetType", noSideEffect.}- Версия
getTypeInst, которая принимаетtypedesc. Исходный код Изменить proc getTypeImpl(n: NimNode): NimNode {...}{.magic: "NGetType", noSideEffect, raises: [], tags: [].}- Возвращает тип узла в форме, соответствующей реализации типа. Любые промежуточные псевдонимы расширяются, чтобы получить окончательную реализацию типа. Вместо этого вы можете использовать
getImplдля символа, если хотите найти промежуточные псевдонимы.Пример:
type Vec[N: static[int], T] = object arr: array[N, T] Vec4[T] = Vec[4, T] Vec4f = Vec4[float32] var a: Vec4f var b: Vec4[float32] var c: Vec[4, float32] macro dumpTypeImpl(x: typed): untyped = newLit(x.getTypeImpl.repr) let t = """ object arr: array[0 .. 3, float32] """ doAssert(dumpTypeImpl(a) == t) doAssert(dumpTypeImpl(b) == t) doAssert(dumpTypeImpl(c) == t)Исходный код Изменить proc signatureHash(n: NimNode): string {...}{.magic: "NSigHash", noSideEffect.}- Возвращает стабильный идентификатор, полученный из сигнатуры символа. Сигнатура объединяет множество факторов, таких как тип символа, модуль владения символом и другие. Тот же идентификатор используется в бэкенде для создания искажённого имени символа. Исходный код Изменить
proc symBodyHash(s: NimNode): string {...}{.noSideEffect, raises: [], tags: [].}- Возвращает стабильный дайджест для символов, полученный не только из сигнатуры типа и владеющего модуля, но также и из тела реализации. Все процедуры/переменные, используемые в реализации этого символа, также хешируются рекурсивно, включая магические значения из модуля системы. Исходный код Изменить
proc getTypeImpl(n: typedesc): NimNode {...}{.magic: "NGetType", noSideEffect.}- Версия
getTypeImpl, которая принимаетtypedesc. Исходный код Изменить proc intVal=(n: NimNode; val: BiggestInt) {...}{.magic: "NSetIntVal", noSideEffect.}- Исходный код Изменить
proc floatVal=(n: NimNode; val: BiggestFloat) {...}{.magic: "NSetFloatVal", noSideEffect.}- Исходный код Изменить
proc symbol=(n: NimNode; val: NimSym) {...}{.magic: "NSetSymbol", noSideEffect, deprecated: "Deprecated since version 0.18.1; Generate a new \'NimNode\' with \'genSym\' instead.".}- Исходный код Изменить
proc ident=(n: NimNode; val: NimIdent) {...}{.magic: "NSetIdent", noSideEffect, deprecated: "Deprecated since version 0.18.1; Generate a new \'NimNode\' with \'ident(string)\' instead.".}- Исходный код Изменить
proc strVal=(n: NimNode; val: string) {...}{.magic: "NSetStrVal", noSideEffect.}-
Устанавливает строковое значение строковой литерали или комментария. Установка
strValзапрещена для узловnnkIdentиnnkSym; необходимо создать новый узел с помощьюidentилиbindSym.См. также:
- процедуру strVal для получения строкового значения.
- процедуру ident для создания идентификатора.
- процедуру bindSym для связывания символа.
proc newNimNode(kind: NimNodeKind; lineInfoFrom: NimNode = nil): NimNode {...}{. magic: "NNewNimNode", noSideEffect.}-
Создаёт новый узел AST указанного типа.
Параметр
Исходный код ИзменитьlineInfoFromиспользуется для информации о строках, когда сгенерированный код вызывает ошибку. Вы должны убедиться, что он установлен на узел, который вы преобразуете. proc copyNimNode(n: NimNode): NimNode {...}{.magic: "NCopyNimNode", noSideEffect.}- Исходный код Изменить
proc copyNimTree(n: NimNode): NimNode {...}{.magic: "NCopyNimTree", noSideEffect.}- Исходный код Изменить
proc error(msg: string; n: NimNode = nil) {...}{.magic: "NError", gcsafe, locks: 0.}- Выводит сообщение об ошибке во время компиляции. Необязательный параметр
n: NimNodeиспользуется в качестве источника для информации о файле и строке в сообщении об ошибке компиляции. Исходный код Изменить proc warning(msg: string; n: NimNode = nil) {...}{.magic: "NWarning", gcsafe, locks: 0.}- Выводит сообщение об ошибке во время компиляции. Исходный код Изменить
proc hint(msg: string; n: NimNode = nil) {...}{.magic: "NHint", gcsafe, locks: 0.}- Выводит сообщение с подсказкой во время компиляции. Исходный код Изменить
proc newStrLitNode(s: string): NimNode {...}{.compileTime, noSideEffect, raises: [], tags: [].}- Создаёт узел строковой литерали из
s. Исходный код Изменить proc newCommentStmtNode(s: string): NimNode {...}{.compileTime, noSideEffect, raises: [], tags: [].}- Создаёт узел комментария. Исходный код Изменить
proc newIntLitNode(i: BiggestInt): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт узел целочисленной литерали из
i. Исходный код Изменить proc newFloatLitNode(f: BiggestFloat): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт узел с плавающей точкой из
f. Исходный код Изменить proc newIdentNode(i: NimIdent): NimNode {...}{.compileTime, deprecated, raises: [], tags: [].}- Создаёт узел идентификатора из
i. Исходный код Изменить proc newIdentNode(i: string): NimNode {...}{.magic: "StrToIdent", noSideEffect.}- Создаёт узел идентификатора из
i. Это просто псевдоним дляident(string). Используйте его, он короче. Исходный код Изменить proc ident(name: string): NimNode {...}{.magic: "StrToIdent", noSideEffect.}- Создаёт новый узел ident из строки. Исходный код Изменить
proc bindSym(ident: string | NimNode; rule: BindSymRule = brClosed): NimNode {...}{. magic: "NBindSym", noSideEffect.}
-
Создаёт узел, который связывает
identс узлом символа. Связанный символ может быть перегруженным символом. Еслиidentявляется узлом NimNode, у него должен быть видnnkIdent. Еслиrule == brClosedявляется либо деревомnnkClosedSymChoice, либо возвращаетсяnnkSym, если символ не является неоднозначным. Еслиrule == brOpenявляется либо деревомnnkOpenSymChoice, либо возвращаетсяnnkSym, если символ не является неоднозначным. Еслиrule == brForceOpenвсегда возвращается деревоnnkOpenSymChoice, даже если символ не является неоднозначным.Экспериментальная функция: для активации используйте {.experimental: "dynamicBindSym"}. Если вызов происходит из шаблона/обычного кода, то
Исходный код Редактироватьidentиruleдолжны быть константным выражением/литеральным значением. Если вызов происходит из макросов/времени компиляции/статических блоков, тоidentиruleмогут быть вычисляемыми значениями ВМ. proc genSym(kind: NimSymKind = nskLet; ident = ""): NimNode {...}{.magic: "NGenSym", noSideEffect.}- Генерирует свежий символ, гарантированно уникальный. Символ должен встречаться в контексте объявления. Исходный код Редактировать
proc callsite(): NimNode {...}{.magic: "NCallSite", gcsafe, locks: 0, deprecated: "Deprecated since v0.18.1; use varargs[untyped] in the macro prototype instead".}- Возвращает АСТ узла вызова выражения, вызвавшего этот макрос. Исходный код Редактировать
proc toStrLit(n: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Преобразует АСТ
nв конкретный код Nim и оборачивает его в узел строки. Исходный код Редактировать proc `$`(arg: LineInfo): string {...}{.raises: [], tags: [].}- Возвращает строковое представление в формате
filepath(line, column). Исходный код Редактировать proc copyLineInfo(arg: NimNode; info: NimNode) {...}{.magic: "NLineInfo", noSideEffect.}- Копирует lineinfo из
info. Исходный код Редактировать proc lineInfoObj(n: NimNode): LineInfo {...}{.compileTime, raises: [], tags: [].}- Возвращает
LineInfoобъектаn, используя абсолютный путь дляfilename. Исходный код Редактировать proc lineInfo(arg: NimNode): string {...}{.compileTime, raises: [], tags: [].}- Возвращает информацию о строке в формате
filepath(line, column). Исходный код Редактировать proc internalErrorFlag(): string {...}{.magic: "NError", noSideEffect.}- Некоторые встроенные функции устанавливают флаг ошибки. Затем это преобразуется в соответствующее исключение. Примечание: Обычный код приложения не должен вызывать это. Исходный код Редактировать
proc parseExpr(s: string): NimNode {...}{.noSideEffect, compileTime, raises: [ValueError], tags: [].}- Компилирует переданную строку в её представление АСТ. Ожидается одно выражение. Выбрасывает
ValueErrorдля ошибок разбора. Исходный код Редактировать proc parseStmt(s: string): NimNode {...}{.noSideEffect, compileTime, raises: [ValueError], tags: [].}- Компилирует переданную строку в её представление АСТ. Ожидается одна или несколько инструкций. Выбрасывает
ValueErrorдля ошибок разбора. Исходный код Редактировать proc getAst(macroOrTemplate: untyped): NimNode {...}{.magic: "ExpandToAst", noSideEffect.}- Получает узлы АСТ, возвращённые из вызова макроса или шаблона. Пример:
macro FooMacro() = var ast = getAst(BarTemplate())
Исходный код Редактировать proc quote(bl: typed; op = "``"): NimNode {...}{.magic: "QuoteAst", noSideEffect.}-
Оператор квази-цитирования. Принимает выражение или блок и возвращает АСТ, который его представляет. Внутри процитированной АСТ вы можете интерполировать выражения NimNode из окружающего контекста. Если оператор не указан, цитирование выполняется с помощью обратных кавычек. В противном случае, указанный оператор должен использоваться как префиксный оператор для любого интерполируемого выражения.
Пример:
macro check(ex: untyped) = # this is a simplified version of the check macro from the # unittest module. # If there is a failed check, we want to make it easy for # the user to jump to the faulty line in the code, so we # get the line info here: var info = ex.lineinfo # We will also display the code string of the failed check: var expString = ex.toStrLit # Finally we compose the code to implement the check: result = quote do: if not `ex`: echo `info` & ": Check failed: " & `expString`Исходный код Редактировать proc expectKind(n: NimNode; k: NimNodeKind) {...}{.compileTime, raises: [], tags: [].}- Проверяет, что
nимеет видk. Если это не так, компиляция прерывается с сообщением об ошибке. Это полезно для написания макросов, которые проверяют АСТ, передаваемый им. Исходный код Редактировать proc expectMinLen(n: NimNode; min: int) {...}{.compileTime, raises: [], tags: [].}- Проверяет, что
nимеет как минимумminдочерних узлов. Если это не так, компиляция прерывается с сообщением об ошибке. Это полезно для написания макросов, которые проверяют количество аргументов. Исходный код Редактировать proc expectLen(n: NimNode; len: int) {...}{.compileTime, raises: [], tags: [].}- Проверяет, что
nимеет ровноlenдочерних узлов. Если это не так, компиляция прерывается с сообщением об ошибке. Это полезно для написания макросов, которые проверяют количество аргументов. Исходный код Редактировать proc expectLen(n: NimNode; min, max: int) {...}{.compileTime, raises: [], tags: [].}- Проверяет, что
nимеет количество дочерних узлов в диапазонеmin..max. Если это не так, компиляция прерывается с сообщением об ошибке. Это полезно для написания макросов, которые проверяют количество аргументов. Исходный код Редактировать proc newTree(kind: NimNodeKind; children: varargs[NimNode]): NimNode {...}{. compileTime, raises: [], tags: [].}- Создаёт новый узел с дочерними узлами. Исходный код Редактировать
proc newCall(theProc: NimNode; args: varargs[NimNode]): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел вызова.
theProc— это процедура, которая вызывается с аргументамиargs[0..]. Исходный код Редактировать proc newCall(theProc: NimIdent; args: varargs[NimNode]): NimNode {...}{.compileTime, deprecated: "Deprecated since v0.18.1; use \'newCall(string, ...)\' or \'newCall(NimNode, ...)\' instead", raises: [], tags: [].}- Создаёт новый узел вызова.
theProc— это процедура, которая вызывается с аргументамиargs[0..]. Исходный код Редактировать proc newCall(theProc: string; args: varargs[NimNode]): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел вызова.
theProc— это процедура, которая вызывается с аргументамиargs[0..]. Исходный код Редактировать proc newLit(c: char): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел символа-литерала. Исходный код Редактировать
proc newLit(i: int): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы. Исходный код Редактировать
proc newLit(i: int8): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы. Исходный код Редактировать
proc newLit(i: int16): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы. Исходный код Редактировать
proc newLit(i: int32): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы. Исходный код Редактировать
proc newLit(i: int64): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы. Исходный код Редактировать
proc newLit(i: uint): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целой беззнаковой литералы. Исходный код Редактировать
proc newLit(i: uint8): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целой беззнаковой литералы. Исходный код Редактировать
proc newLit(i: uint16): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы без знака. Исходный код Редактировать
proc newLit(i: uint32): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы без знака. Исходный код Редактировать
proc newLit(i: uint64): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел целочисленной литералы без знака. Исходный код Редактировать
proc newLit(b: bool): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел булевой литералы. Исходный код Редактировать
proc newLit(s: string): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел строковой литералы. Исходный код Редактировать
proc newLit(f: float32): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел вещественной литералы. Исходный код Редактировать
proc newLit(f: float64): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый узел вещественной литералы. Исходный код Редактировать
proc newLit(arg: enum): NimNode {...}{.compileTime.}- Исходный код Редактировать
proc newLit(arg: object): NimNode {...}{.compileTime.}- Исходный код Редактировать
proc newLit(arg: ref object): NimNode {...}{.compileTime.}- Создаёт новый узел литералы типа ref. Исходный код Редактировать
proc newLit[N, T](arg: array[N, T]): NimNode {...}{.compileTime.}- Исходный код Редактировать
proc newLit[T](arg: seq[T]): NimNode {...}{.compileTime.}- Исходный код Редактировать
proc newLit[T](s: set[T]): NimNode {...}{.compileTime.}- Исходный код Редактировать
proc newLit[T: tuple](arg: T): NimNode {...}{.compileTime.}- Используйте -d:nimHasWorkaround14720, чтобы восстановить поведение до внесения исправления, принудительно создавая именованную кортеж, даже когда
argявляется безымянным. Исходный код Редактировать proc nestList(op: NimNode; pack: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Вложенный список
packв дерево выражений вызова:[a, b, c]преобразуется вop(a, op(c, d)). Это также известно как выражение свертки. Исходный код Редактировать proc nestList(op: NimNode; pack: NimNode; init: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Вложенный список
packв дерево выражений вызова:[a, b, c]преобразуется вop(a, op(c, d)). Это также известно как выражение свертки. Исходный код Редактировать proc treeRepr(n: NimNode): string {...}{.compileTime, gcsafe, locks: 0, raises: [], tags: [].}-
Преобразует AST
nв удобочитаемую строку в виде дерева.См. также
Исходный код Редактироватьrepr,lispRepr, иastGenRepr. proc lispRepr(n: NimNode; indented = false): string {...}{.compileTime, gcsafe, locks: 0, raises: [], tags: [].}-
Преобразует AST
nв удобочитаемую строку в стиле Lisp.См. также
Исходный код Редактироватьrepr,treeRepr, иastGenRepr. proc astGenRepr(n: NimNode): string {...}{.compileTime, gcsafe, locks: 0, raises: [], tags: [].}-
Преобразует AST
nв код, необходимый для генерации этого AST.См. также
Исходный код Редактироватьrepr,treeRepr, иlispRepr. proc newEmptyNode(): NimNode {...}{.compileTime, noSideEffect, raises: [], tags: [].}- Создаёт новый пустой узел. Исходный код Редактировать
proc newStmtList(stmts: varargs[NimNode]): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый список операторов. Исходный код Редактировать
proc newPar(exprs: varargs[NimNode]): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новое выражение в скобках. Исходный код Редактировать
proc newBlockStmt(label, body: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый оператор блока с меткой. Исходный код Редактировать
proc newBlockStmt(body: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый блок: stmt. Исходный код Редактировать
proc newVarStmt(name, value: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый оператор var. Исходный код Редактировать
proc newLetStmt(name, value: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый оператор let. Исходный код Редактировать
proc newConstStmt(name, value: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новый оператор const. Исходный код Редактировать
proc newAssignment(lhs, rhs: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc newDotExpr(a, b: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новое выражение с точкой. a.dot(b) ->
a.bИсходный код Редактировать proc newColonExpr(a, b: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Создаёт новое выражение с двоеточием. newColonExpr(a, b) ->
a: bИсходный код Редактировать proc newIdentDefs(name, kind: NimNode; default = newEmptyNode()): NimNode {...}{. compileTime, raises: [], tags: [].}-
Создаёт новый узел
nnkIdentDefsопределённого типа и значения.nnkIdentDefsдолжны иметь как минимум три дочерних узла, но могут иметь больше: сначала идёт список идентификаторов, затем тип и узел значения. Эта вспомогательная процедура создаёт поддерево из трёх узлов, первым из которых является имя единственного идентификатора. Узлыkindиdefault(значение) могут быть пустыми в зависимости от того, где появляетсяnnkIdentDefs: определения кортежей или объектов будут иметь пустой узелdefault, блокиletилиvarмогут иметь пустой узелkindв случае, если идентификатору присваивается значение. Пример:var varSection = newNimNode(nnkVarSection).add( newIdentDefs(ident("a"), ident("string")), newIdentDefs(ident("b"), newEmptyNode(), newLit(3))) # --> var # a: string # b = 3Если вам нужно создать несколько идентификаторов, вам необходимо использовать более низкоуровневую функцию
newNimNode:result = newNimNode(nnkIdentDefs).add( ident("a"), ident("b"), ident("c"), ident("string"), newStrLitNode("Hello"))Исходный код Редактировать proc newNilLit(): NimNode {...}{.compileTime, raises: [], tags: [].}- Новая сокращенная литерала nil. Исходный код Редактировать
proc last(node: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Возвращает последний элемент в дочерних элементах узла. То же самое, что и
node[^1]. Исходный код Редактировать proc expectKind(n: NimNode; k: set[NimNodeKind]) {...}{.compileTime, raises: [], tags: [].}- Проверяет, что
nимеет типk. В противном случае компиляция прерывается с сообщением об ошибке. Это полезно для написания макросов, которые проверяют AST, переданный им. Исходный код Редактировать proc newProc(name = newEmptyNode(); params: openArray[NimNode] = [newEmptyNode()]; body: NimNode = newStmtList(); procType = nnkProcDef; pragmas: NimNode = newEmptyNode()): NimNode {...}{.compileTime, raises: [], tags: [].}
-
Сокращение для создания новой процедуры.
Массив
Исходный код Редактироватьparamsдолжен начинаться с возвращаемого типа процедуры, за которым следует список IdentDefs, определяющих параметры. proc newIfStmt(branches: varargs[tuple[cond, body: NimNode]]): NimNode {...}{. compileTime, raises: [], tags: [].}- Конструктор для
ifоператоров.newIfStmt( (Ident, StmtList), ... )
Исходный код Редактировать proc newEnum(name: NimNode; fields: openArray[NimNode]; public, pure: bool): NimNode {...}{. compileTime, raises: [], tags: [].}- Создаёт новый перечисление.
nameдолжен быть идентификатором. Поля могут быть либо идентификаторами, либо EnumFieldDefnewEnum( name = ident("Colors"), fields = [ident("Blue"), ident("Red")], public = true, pure = false) # type Colors* = Blue RedИсходный код Редактировать proc copyChildrenTo(src, dest: NimNode) {...}{.compileTime, raises: [], tags: [].}- Копирует все дочерние элементы из
srcвdest. Исходный код Редактировать proc name(someProc: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc name=(someProc: NimNode; val: NimNode) {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc params(someProc: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc params=(someProc: NimNode; params: NimNode) {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc pragma(someProc: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Получить пragma типа процедуры. Они будут расширены. Исходный код Редактировать
proc pragma=(someProc: NimNode; val: NimNode) {...}{.compileTime, raises: [], tags: [].}- Установить пragma типа процедуры. Исходный код Редактировать
proc addPragma(someProc, pragma: NimNode) {...}{.compileTime, raises: [], tags: [].}- Добавляет пragma к определению процедуры. Исходный код Редактировать
proc body(someProc: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc body=(someProc: NimNode; val: NimNode) {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc basename(a: NimNode): NimNode {...}{.raises: [], tags: [].}- Извлечь идентификатор из префиксных/постфиксных выражений. Исходный код Редактировать
proc `$`(node: NimNode): string {...}{.compileTime, raises: [], tags: [].}- Получить строку узла идентификатора. Исходный код Редактировать
proc insert(a: NimNode; pos: int; b: NimNode) {...}{.compileTime, raises: [], tags: [].}- Вставить узел
bв узелaвpos. Исходный код Редактировать proc basename=(a: NimNode; val: string) {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc postfix(node: NimNode; op: string): NimNode {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc prefix(node: NimNode; op: string): NimNode {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc infix(a: NimNode; op: string; b: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc unpackPostfix(node: NimNode): tuple[node: NimNode, op: string] {...}{. compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc unpackPrefix(node: NimNode): tuple[node: NimNode, op: string] {...}{. compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc unpackInfix(node: NimNode): tuple[left: NimNode, op: string, right: NimNode] {...}{. compileTime, raises: [], tags: [].}- Исходный код Редактировать
proc copy(node: NimNode): NimNode {...}{.compileTime, raises: [], tags: [].}- Псевдоним для copyNimTree. Исходный код Редактировать
proc eqIdent(a: string; b: string): bool {...}{.magic: "EqIdent", noSideEffect.}- Сравнение, нечувствительное к стилю. Исходный код Редактировать
proc eqIdent(a: NimNode; b: string): bool {...}{.magic: "EqIdent", noSideEffect.}- Сравнение, нечувствительное к стилю.
aможет быть идентификатором или символом.aможет быть заключено в маркер экспорта (nnkPostfix) или заключено в обратные кавычки (nnkAccQuoted), эти узлы будут распакованы. Исходный код Редактировать proc eqIdent(a: string; b: NimNode): bool {...}{.magic: "EqIdent", noSideEffect.}- Сравнение, нечувствительное к стилю.
bможет быть идентификатором или символом.bможет быть заключено в маркер экспорта (nnkPostfix) или заключено в обратные кавычки (nnkAccQuoted), эти узлы будут распакованы. Исходный код Редактировать proc eqIdent(a: NimNode; b: NimNode): bool {...}{.magic: "EqIdent", noSideEffect.}- Сравнение, нечувствительное к стилю.
aиbмогут быть идентификатором или символом. Оба могут быть заключены в маркер экспорта (nnkPostfix) или заключены в обратные кавычки (nnkAccQuoted), эти узлы будут распакованы. Исходный код Редактировать proc expectIdent(n: NimNode; name: string) {...}{.compileTime, raises: [], tags: [].}- Проверить, что
eqIdent(n,name)верно. В противном случае компиляция прерывается с сообщением об ошибке. Это полезно для написания макросов, которые проверяют AST, передаваемый им. Исходный код Редактировать proc hasArgOfName(params: NimNode; name: string): bool {...}{.compileTime, raises: [], tags: [].}- Поиск в
nnkFormalParamsпо аргументу. Исходный код Редактировать proc addIdentIfAbsent(dest: NimNode; ident: string) {...}{.compileTime, raises: [], tags: [].}- Добавить
identкdest, если его нет. Это предназначено для использования с pragmas. Исходный код Редактировать proc boolVal(n: NimNode): bool {...}{.compileTime, noSideEffect, raises: [], tags: [].}- Исходный код Редактировать
proc nodeID(n: NimNode): int {...}{.magic: "NodeId".}- Возвращает id
n, если компилятор был скомпилирован со флагом-d:useNodeids, в противном случае возвращает-1. Эта процедура предназначена только для отладки компилятора. Исходный код Редактировать proc getProjectPath(): string {...}{.raises: [], tags: [].}
-
Возвращает путь к текущему компилируемому проекту.
Не следует путать с system.currentSourcePath, который возвращает путь к исходному файлу, содержащему вызов шаблона.
Например, предположим
dir1/foo.nim, что импортируетdir2/bar.nim, имейтеbar.nimвывести какgetProjectPath, так иcurrentSourcePathвыходы.Теперь, когда
foo.nimкомпилируется,getProjectPathизbar.nimвернёт путь кdir1/, в то время какcurrentSourcePathвернёт путь к файлу исходного кодаbar.nim.Теперь, когда
bar.nimкомпилируется напрямую,getProjectPathтеперь вернёт путь кdir2/, аcurrentSourcePathпо-прежнему вернёт тот же путь, путь к исходному файлуbar.nim.Путь, возвращённый этой процедурой, устанавливается во время компиляции.
См. также:
Исходный код Редактировать proc getSize(arg: NimNode): int {...}{.magic: "NSizeOf", noSideEffect, raises: [], tags: [].}- Возвращает тот же результат, что и
system.sizeof, если размер известен компилятору Nim. Возвращает отрицательное значение, если компилятор Nim не знает размер. Исходный код Редактировать proc getAlign(arg: NimNode): int {...}{.magic: "NSizeOf", noSideEffect, raises: [], tags: [].}- Возвращает тот же результат, что и
system.alignof, если выравнивание известно компилятору Nim. Работает сNimNodeдля использования в контексте макроса. Возвращает отрицательное значение, если компилятор Nim не знает выравнивание. Исходный код Редактировать proc getOffset(arg: NimNode): int {...}{.magic: "NSizeOf", noSideEffect, raises: [], tags: [].}- Возвращает, экспортируется ли символ или нет. Исходный код Редактировать
proc extractDocCommentsAndRunnables(n: NimNode): NimNode {...}{.raises: [], tags: [].}- возвращает
nnkStmtList, содержащий комментарии документации верхнего уровня и runnableExamples вa, останавливаясь на первом дочернем элементе, который не является ни тем, ни другим. Пример:import macros macro transf(a): untyped = result = quote do: proc fun2*() = discard let header = extractDocCommentsAndRunnables(a.body) # correct usage: rest is appended result.body = header result.body.add quote do: discard # just an example # incorrect usage: nesting inside a nnkStmtList: # result.body = quote do: (`header`; discard) proc fun*() {.transf.} = ## first comment runnableExamples: discard runnableExamples: discard ## last comment discard # first statement after doc comments + runnableExamples ## not docgen'dИсходный код Редактировать
Итераторы
iterator items(n: NimNode): NimNode {...}{.inline, raises: [], tags: [].}- Перебирает дочерние элементы узла NimNode
n. Исходный код Редактировать iterator pairs(n: NimNode): (int, NimNode) {...}{.inline, raises: [], tags: [].}- Перебирает дочерние элементы узла NimNode
nи их индексы. Исходный код Редактировать iterator children(n: NimNode): NimNode {...}{.inline, raises: [], tags: [].}- Перебирает дочерние элементы узла NimNode
n. Исходный код Редактировать
Макросы
macro dumpTree(s: untyped): untyped
-
Принимает блок кода Nim и выводит разбор дерева абстрактного синтаксиса с использованием процедуры
treeRepr. Вывод происходит во время компиляции.Вы можете использовать это как инструмент для изучения дерева абстрактного синтаксиса Nim и для выявления типов узлов, которые должны быть созданы для представления определённого выражения/высказывания.
Например:
dumpTree: echo "Hello, World!"
Выводит:
StmtList Command Ident "echo" StrLit "Hello, World!"Также см.
Исходный код РедактироватьdumpAstGenиdumpLisp. macro dumpLisp(s: untyped): untyped
-
Принимает блок кода Nim и выводит разбор дерева абстрактного синтаксиса с использованием процедуры
lispRepr. Вывод происходит во время компиляции.Вы можете использовать это как инструмент для изучения дерева абстрактного синтаксиса Nim и для выявления типов узлов, которые должны быть созданы для представления определённого выражения/высказывания.
Например:
dumpLisp: echo "Hello, World!"
Выводит:
(StmtList (Command (Ident "echo") (StrLit "Hello, World!")))
Также см.
Исходный код РедактироватьdumpAstGenиdumpTree. macro dumpAstGen(s: untyped): untyped
-
Принимает блок кода Nim и выводит разбор дерева абстрактного синтаксиса с использованием процедуры
astGenRepr. Вывод происходит во время компиляции.Вы можете использовать это как инструмент для написания макросов быстрее, написав примеры вывода, а затем скопировав фрагменты в макрос для модификации.
Например:
dumpAstGen: echo "Hello, World!"
Выводит:
nnkStmtList.newTree( nnkCommand.newTree( newIdentNode("echo"), newLit("Hello, World!") ) )Также см.
Исходный код РедактироватьdumpTreeиdumpLisp. macro expandMacros(body: typed): untyped
-
Расширяет один уровень макроса — полезно для отладки. Может использоваться для проверки того, что происходит при расширении вызова макроса, не изменяя его результат.
Например,
import sugar, macros let x = 10 y = 20 expandMacros: dump(x + y)
фактически отобразит
Исходный код Редактироватьx + y, но в то же время выведет во время компиляции расширение макросаdump, которое в данном случае равноdebugEcho ["x + y", " = ", x + y]. macro hasCustomPragma(n: typed; cp: typed{nkSym}): untyped-
Расширяется до
true, если выражениеn, которое ожидается какnnkDotExpr(при проверке поля), процедура или тип имеют пользовательский псевдонимcp.См. также
getCustomPragmaVal.template myAttr() {.pragma.} type MyObj = object myField {.myAttr.}: int proc myProc() {.myAttr.} = discard var o: MyObj assert(o.myField.hasCustomPragma(myAttr)) assert(myProc.hasCustomPragma(myAttr))Исходный код Редактировать macro getCustomPragmaVal(n: typed; cp: typed{nkSym}): untyped-
Расширяется до значения пользовательского псевдонима
cpвыраженияn, которое ожидается какnnkDotExpr, процедура или тип.См. также
hasCustomPragmatemplate serializationKey(key: string) {.pragma.} type MyObj {.serializationKey: "mo".} = object myField {.serializationKey: "mf".}: int var o: MyObj assert(o.myField.getCustomPragmaVal(serializationKey) == "mf") assert(o.getCustomPragmaVal(serializationKey) == "mo") assert(MyObj.getCustomPragmaVal(serializationKey) == "mo")Исходный код Редактировать macro unpackVarargs(callee: untyped; args: varargs[untyped]): untyped
- Исходный код Редактировать
Шаблоны
template `or`(x, y: NimNode): NimNode
- Оцените
xи, если это не пустой узел, верните его. В противном случае оцените доy. Может использоваться для цепочки нескольких выражений, чтобы получить первое непустое выражение.let node = mightBeEmpty() or mightAlsoBeEmpty() or fallbackNode
Исходный код Редактировать template findChild(n: NimNode; cond: untyped): NimNode {...}{.dirty.}- Найдите первый дочерний узел, соответствующий условию (или nil).
var res = findChild(n, it.kind == nnkPostfix and it.basename.ident == toNimIdent"foo")Исходный код Редактировать
© 2006–2021 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/macros.html