mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
macros.quote: document hard to use op; add more useful examples (#16489)
* macros.quote: document hard to use `op`; add more useful examples
* add back doc comment removed in a60305fbf3
* address comment
* fixup
* clarify quoting rules
* Update lib/core/macros.nim
Co-authored-by: Clyybber <darkmine956@gmail.com>
Co-authored-by: Clyybber <darkmine956@gmail.com>
This commit is contained in:
@@ -566,34 +566,82 @@ proc getAst*(macroOrTemplate: untyped): NimNode {.magic: "ExpandToAst", noSideEf
|
||||
## macro FooMacro() =
|
||||
## var ast = getAst(BarTemplate())
|
||||
|
||||
proc quote*(bl: typed, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.}
|
||||
proc quote*(bl: typed, op = "``"): NimNode {.magic: "QuoteAst", noSideEffect.} =
|
||||
## Quasi-quoting operator.
|
||||
## Accepts an expression or a block and returns the AST that represents it.
|
||||
## Within the quoted AST, you are able to interpolate NimNode expressions
|
||||
## from the surrounding scope. If no operator is given, quoting is done using
|
||||
## backticks. Otherwise, the given operator must be used as a prefix operator
|
||||
## for any interpolated expression.
|
||||
##
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nim
|
||||
##
|
||||
## 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`
|
||||
## for any interpolated expression. The original meaning of the interpolation
|
||||
## operator may be obtained by escaping it (by prefixing it with itself) when used
|
||||
## as a unary operator:
|
||||
## e.g. `@` is escaped as `@@`, `&%` is escaped as `&%&%` and so on; see examples.
|
||||
runnableExamples:
|
||||
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`
|
||||
check 1 + 1 == 2
|
||||
|
||||
runnableExamples:
|
||||
# example showing how to define a symbol that requires backtick without
|
||||
# quoting it.
|
||||
var destroyCalled = false
|
||||
macro bar() =
|
||||
let s = newTree(nnkAccQuoted, ident"=destroy")
|
||||
# let s = ident"`=destroy`" # this would not work
|
||||
result = quote do:
|
||||
type Foo = object
|
||||
# proc `=destroy`(a: var Foo) = destroyCalled = true # this would not work
|
||||
proc `s`(a: var Foo) = destroyCalled = true
|
||||
block:
|
||||
let a = Foo()
|
||||
bar()
|
||||
doAssert destroyCalled
|
||||
|
||||
runnableExamples:
|
||||
# custom `op`
|
||||
var destroyCalled = false
|
||||
macro bar() =
|
||||
var x = 1.5
|
||||
result = quote("@") do:
|
||||
type Foo = object
|
||||
proc `=destroy`(a: var Foo) =
|
||||
doAssert @x == 1.5
|
||||
doAssert compiles(@x == 1.5)
|
||||
let b1 = @[1,2]
|
||||
let b2 = @@[1,2]
|
||||
doAssert $b1 == "[1, 2]"
|
||||
doAssert $b2 == "@[1, 2]"
|
||||
destroyCalled = true
|
||||
block:
|
||||
let a = Foo()
|
||||
bar()
|
||||
doAssert destroyCalled
|
||||
|
||||
proc `&%`(x: int): int = 1
|
||||
proc `&%`(x, y: int): int = 2
|
||||
|
||||
macro bar2() =
|
||||
var x = 3
|
||||
result = quote("&%") do:
|
||||
var y = &%x # quoting operator
|
||||
doAssert &%&%y == 1 # unary operator => need to escape
|
||||
doAssert y &% y == 2 # binary operator => no need to escape
|
||||
doAssert y == 3
|
||||
bar2()
|
||||
|
||||
proc expectKind*(n: NimNode, k: NimNodeKind) {.compileTime.} =
|
||||
## Checks that `n` is of kind `k`. If this is not the case,
|
||||
|
||||
Reference in New Issue
Block a user