parameter passing works the same for macros and templates; use callsite magic to access the invokation AST
This commit is contained in:
parent
6bcdb9c8f4
commit
b4844a189d
16 changed files with 270 additions and 180 deletions
|
|
@ -3102,7 +3102,7 @@ a template. ``inject`` and ``gensym`` have no effect in ``dirty`` templates.
|
|||
Macros
|
||||
------
|
||||
|
||||
A `macro`:idx: is a special kind of low level template. They can be used
|
||||
A `macro`:idx: is a special kind of low level template. Macros can be used
|
||||
to implement `domain specific languages`:idx:. Like templates, macros come in
|
||||
the 2 flavors *immediate* and *ordinary*.
|
||||
|
||||
|
|
@ -3129,12 +3129,12 @@ variable number of arguments:
|
|||
# ``macros`` module:
|
||||
import macros
|
||||
|
||||
macro debug(n: expr): stmt =
|
||||
macro debug(n: varargs[expr]): stmt =
|
||||
# `n` is a Nimrod AST that contains the whole macro invocation
|
||||
# this macro returns a list of statements:
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
# iterate over any argument that is passed to this macro:
|
||||
for i in 1..n.len-1:
|
||||
for i in 0..n.len-1:
|
||||
# add a call to the statement list that writes the expression;
|
||||
# `toStrLit` converts an AST to its string representation:
|
||||
add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
|
||||
|
|
@ -3167,6 +3167,11 @@ The macro call expands to:
|
|||
writeln(stdout, x)
|
||||
|
||||
|
||||
Arguments that are passed to a ``varargs`` parameter are wrapped in an array
|
||||
constructor expression. This is why ``debug`` iterates over all of ``n``'s
|
||||
children.
|
||||
|
||||
|
||||
BindSym
|
||||
~~~~~~~
|
||||
|
||||
|
|
@ -3179,9 +3184,9 @@ builtin can be used for that:
|
|||
.. code-block:: nimrod
|
||||
import macros
|
||||
|
||||
macro debug(n: expr): stmt =
|
||||
macro debug(n: varargs[expr]): stmt =
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
for i in 1..n.len-1:
|
||||
for i in 0..n.len-1:
|
||||
# we can bind symbols in scope via 'bindSym':
|
||||
add(result, newCall(bindSym"write", bindSym"stdout", toStrLit(n[i])))
|
||||
add(result, newCall(bindSym"write", bindSym"stdout", newStrLitNode(": ")))
|
||||
|
|
|
|||
12
doc/tut2.txt
12
doc/tut2.txt
|
|
@ -67,7 +67,7 @@ Objects have access to their type at runtime. There is an
|
|||
person: TPerson
|
||||
assert(student of TStudent) # is true
|
||||
|
||||
Object fields that should be visible from outside the defining module, have to
|
||||
Object fields that should be visible from outside the defining module have to
|
||||
be marked by ``*``. In contrast to tuples, different object types are
|
||||
never *equivalent*. New object types can only be defined within a type
|
||||
section.
|
||||
|
|
@ -631,19 +631,19 @@ Expression Macros
|
|||
-----------------
|
||||
|
||||
The following example implements a powerful ``debug`` command that accepts a
|
||||
variable number of arguments (this cannot be done with templates):
|
||||
variable number of arguments:
|
||||
|
||||
.. code-block:: nimrod
|
||||
# to work with Nimrod syntax trees, we need an API that is defined in the
|
||||
# ``macros`` module:
|
||||
import macros
|
||||
|
||||
macro debug(n: expr): stmt =
|
||||
# `n` is a Nimrod AST that contains the whole macro expression
|
||||
macro debug(n: varargs[expr]): stmt =
|
||||
# `n` is a Nimrod AST that contains a list of expressions;
|
||||
# this macro returns a list of statements:
|
||||
result = newNimNode(nnkStmtList, n)
|
||||
# iterate over any argument that is passed to this macro:
|
||||
for i in 1..n.len-1:
|
||||
for i in 0..n.len-1:
|
||||
# add a call to the statement list that writes the expression;
|
||||
# `toStrLit` converts an AST to its string representation:
|
||||
result.add(newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
|
||||
|
|
@ -702,5 +702,3 @@ regular expressions:
|
|||
return tkOperator
|
||||
else:
|
||||
return tkUnknown
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue