diff options
Diffstat (limited to 'lib/core/macros.nim')
-rw-r--r-- | lib/core/macros.nim | 167 |
1 files changed, 82 insertions, 85 deletions
diff --git a/lib/core/macros.nim b/lib/core/macros.nim index ecf85935f..57764410e 100644 --- a/lib/core/macros.nim +++ b/lib/core/macros.nim @@ -201,10 +201,9 @@ template `or`*(x, y: NimNode): NimNode = ## Evaluate `x` and when it is not an empty node, return ## it. Otherwise evaluate to `y`. Can be used to chain several ## expressions to get the first expression that is not empty. - ## - ## .. code-block:: nim - ## + ## ``` ## let node = mightBeEmpty() or mightAlsoBeEmpty() or fallbackNode + ## ``` let arg = x if arg != nil and arg.kind != nnkEmpty: @@ -545,11 +544,10 @@ proc getAst*(macroOrTemplate: untyped): NimNode {.magic: "ExpandToAst", noSideEf ## Obtains the AST nodes returned from a macro or template invocation. ## See also `genasts.genAst`. ## Example: - ## - ## .. code-block:: nim - ## + ## ``` ## macro FooMacro() = ## var ast = getAst(BarTemplate()) + ## ``` proc quote*(bl: typed, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.} = ## Quasi-quoting operator. @@ -1003,18 +1001,18 @@ macro dumpTree*(s: untyped): untyped = echo s.treeRepr ## a certain expression/statement. ## ## For example: - ## - ## .. code-block:: nim - ## dumpTree: - ## echo "Hello, World!" + ## ``` + ## dumpTree: + ## echo "Hello, World!" + ## ``` ## ## Outputs: - ## - ## .. code-block:: - ## StmtList - ## Command - ## Ident "echo" - ## StrLit "Hello, World!" + ## ``` + ## StmtList + ## Command + ## Ident "echo" + ## StrLit "Hello, World!" + ## ``` ## ## Also see `dumpAstGen` and `dumpLisp`. @@ -1027,18 +1025,18 @@ macro dumpLisp*(s: untyped): untyped = echo s.lispRepr(indented = true) ## a certain expression/statement. ## ## For example: - ## - ## .. code-block:: nim - ## dumpLisp: - ## echo "Hello, World!" + ## ``` + ## dumpLisp: + ## echo "Hello, World!" + ## ``` ## ## Outputs: - ## - ## .. code-block:: - ## (StmtList - ## (Command - ## (Ident "echo") - ## (StrLit "Hello, World!"))) + ## ``` + ## (StmtList + ## (Command + ## (Ident "echo") + ## (StrLit "Hello, World!"))) + ## ``` ## ## Also see `dumpAstGen` and `dumpTree`. @@ -1050,20 +1048,20 @@ macro dumpAstGen*(s: untyped): untyped = echo s.astGenRepr ## outputs and then copying the snippets into the macro for modification. ## ## For example: - ## - ## .. code-block:: nim - ## dumpAstGen: - ## echo "Hello, World!" + ## ``` + ## dumpAstGen: + ## echo "Hello, World!" + ## ``` ## ## Outputs: - ## - ## .. code-block:: nim - ## nnkStmtList.newTree( - ## nnkCommand.newTree( - ## newIdentNode("echo"), - ## newLit("Hello, World!") - ## ) - ## ) + ## ``` + ## nnkStmtList.newTree( + ## nnkCommand.newTree( + ## newIdentNode("echo"), + ## newLit("Hello, World!") + ## ) + ## ) + ## ``` ## ## Also see `dumpTree` and `dumpLisp`. @@ -1128,23 +1126,22 @@ proc newIdentDefs*(name, kind: NimNode; ## `let` or `var` blocks may have an empty `kind` node if the ## identifier is being assigned a value. Example: ## - ## .. code-block:: nim - ## + ## ``` ## var varSection = newNimNode(nnkVarSection).add( ## newIdentDefs(ident("a"), ident("string")), ## newIdentDefs(ident("b"), newEmptyNode(), newLit(3))) ## # --> var ## # a: string ## # b = 3 + ## ``` ## ## If you need to create multiple identifiers you need to use the lower level ## `newNimNode`: - ## - ## .. code-block:: nim - ## + ## ``` ## result = newNimNode(nnkIdentDefs).add( ## ident("a"), ident("b"), ident("c"), ident("string"), ## newStrLitNode("Hello")) + ## ``` newNimNode(nnkIdentDefs).add(name, kind, default) proc newNilLit*(): NimNode = @@ -1191,14 +1188,12 @@ proc newProc*(name = newEmptyNode(); proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]): NimNode = ## Constructor for `if` statements. - ## - ## .. code-block:: nim - ## - ## newIfStmt( - ## (Ident, StmtList), - ## ... - ## ) - ## + ## ``` + ## newIfStmt( + ## (Ident, StmtList), + ## ... + ## ) + ## ``` result = newNimNode(nnkIfStmt) if len(branches) < 1: error("If statement must have at least one branch") @@ -1209,17 +1204,15 @@ proc newEnum*(name: NimNode, fields: openArray[NimNode], public, pure: bool): NimNode = ## Creates a new enum. `name` must be an ident. Fields are allowed to be - ## either idents or EnumFieldDef - ## - ## .. code-block:: nim - ## - ## newEnum( - ## name = ident("Colors"), - ## fields = [ident("Blue"), ident("Red")], - ## public = true, pure = false) - ## - ## # type Colors* = Blue Red + ## either idents or EnumFieldDef: + ## ``` + ## newEnum( + ## name = ident("Colors"), + ## fields = [ident("Blue"), ident("Red")], + ## public = true, pure = false) ## + ## # type Colors* = Blue Red + ## ``` expectKind name, nnkIdent if len(fields) < 1: @@ -1383,10 +1376,10 @@ iterator children*(n: NimNode): NimNode {.inline.} = template findChild*(n: NimNode; cond: untyped): NimNode {.dirty.} = ## Find the first child node matching condition (or nil). - ## - ## .. code-block:: nim + ## ``` ## var res = findChild(n, it.kind == nnkPostfix and ## it.basename.ident == ident"foo") + ## ``` block: var res: NimNode for it in n.children: @@ -1491,7 +1484,7 @@ macro expandMacros*(body: typed): untyped = ## ## For instance, ## - ## .. code-block:: nim + ## ``` ## import std/[sugar, macros] ## ## let @@ -1499,6 +1492,7 @@ macro expandMacros*(body: typed): untyped = ## y = 20 ## expandMacros: ## dump(x + y) + ## ``` ## ## will actually dump `x + y`, but at the same time will print at ## compile time the expansion of the `dump` macro, which in this @@ -1608,7 +1602,7 @@ macro hasCustomPragma*(n: typed, cp: typed{nkSym}): untyped = ## ## See also `getCustomPragmaVal`_. ## - ## .. code-block:: nim + ## ``` ## template myAttr() {.pragma.} ## type ## MyObj = object @@ -1619,6 +1613,7 @@ macro hasCustomPragma*(n: typed, cp: typed{nkSym}): untyped = ## var o: MyObj ## assert(o.myField.hasCustomPragma(myAttr)) ## assert(myProc.hasCustomPragma(myAttr)) + ## ``` let pragmaNode = customPragmaNode(n) for p in pragmaNode: if (p.kind == nnkSym and p == cp) or @@ -1632,7 +1627,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped = ## ## See also `hasCustomPragma`_. ## - ## .. code-block:: nim + ## ``` ## template serializationKey(key: string) {.pragma.} ## type ## MyObj {.serializationKey: "mo".} = object @@ -1641,6 +1636,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped = ## assert(o.myField.getCustomPragmaVal(serializationKey) == "mf") ## assert(o.getCustomPragmaVal(serializationKey) == "mo") ## assert(MyObj.getCustomPragmaVal(serializationKey) == "mo") + ## ``` result = nil let pragmaNode = customPragmaNode(n) for p in pragmaNode: @@ -1727,25 +1723,26 @@ proc extractDocCommentsAndRunnables*(n: NimNode): NimNode = ## runnableExamples in `a`, stopping at the first child that is neither. ## Example: ## - ## .. code-block:: nim - ## import std/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 + ## ``` + ## import std/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 + ## ``` result = newStmtList() for ni in n: |