Further tutorial updates (#5176)
* tut1: added multiline comments * tut2: replaced expr/stmt with untyped/typed * added some more template/macro example * remove immediate pragma from example
This commit is contained in:
parent
92ecbc9958
commit
86c73cdfc2
2 changed files with 85 additions and 15 deletions
13
doc/tut1.rst
13
doc/tut1.rst
|
|
@ -125,6 +125,19 @@ Documentation comments are tokens; they are only allowed at certain places in
|
||||||
the input file as they belong to the syntax tree! This feature enables simpler
|
the input file as they belong to the syntax tree! This feature enables simpler
|
||||||
documentation generators.
|
documentation generators.
|
||||||
|
|
||||||
|
Multiline comments are started with ``#[`` and terminated with ``]#``. Multiline
|
||||||
|
comments can also be nested.
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
#[
|
||||||
|
You can have any Nim code text commented
|
||||||
|
out inside this with no indentation restrictions.
|
||||||
|
yes("May I ask a pointless question?")
|
||||||
|
#[
|
||||||
|
Note: these can be nested!!
|
||||||
|
]#
|
||||||
|
]#
|
||||||
|
|
||||||
You can also use the `discard statement`_ together with *long string
|
You can also use the `discard statement`_ together with *long string
|
||||||
literals* to create block comments:
|
literals* to create block comments:
|
||||||
|
|
||||||
|
|
|
||||||
87
doc/tut2.rst
87
doc/tut2.rst
|
|
@ -557,7 +557,7 @@ To *invoke* a template, call it like a procedure.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template `!=` (a, b: expr): expr =
|
template `!=` (a, b: untyped): untyped =
|
||||||
# this definition exists in the System module
|
# this definition exists in the System module
|
||||||
not (a == b)
|
not (a == b)
|
||||||
|
|
||||||
|
|
@ -603,19 +603,20 @@ Turning the ``log`` proc into a template solves this problem:
|
||||||
x = 4
|
x = 4
|
||||||
log("x has the value: " & $x)
|
log("x has the value: " & $x)
|
||||||
|
|
||||||
The parameters' types can be ordinary types or the meta types ``expr``
|
The parameters' types can be ordinary types or the meta types ``untyped``,
|
||||||
(stands for *expression*), ``stmt`` (stands for *statement*) or ``typedesc``
|
``typed``, or ``typedesc``.
|
||||||
(stands for *type description*). If the template has no explicit return type,
|
``typedesc`` stands for *type description*, and ``untyped`` means symbol lookups and
|
||||||
``stmt`` is used for consistency with procs and methods.
|
type resolution is not performed before the expression is passed to the template.
|
||||||
|
|
||||||
If there is a ``stmt`` parameter it should be the last in the template
|
If the template has no explicit return type,
|
||||||
declaration. The reason is that statements can be passed to a template
|
``void`` is used for consistency with procs and methods.
|
||||||
via a special ``:`` syntax:
|
|
||||||
|
To pass a block of statements to a template, use 'untyped' for the last parameter:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
template withFile(f: expr, filename: string, mode: FileMode,
|
template withFile(f: untyped, filename: string, mode: FileMode,
|
||||||
body: stmt): stmt {.immediate.} =
|
body: untyped): typed =
|
||||||
let fn = filename
|
let fn = filename
|
||||||
var f: File
|
var f: File
|
||||||
if open(f, fn, mode):
|
if open(f, fn, mode):
|
||||||
|
|
@ -636,7 +637,6 @@ avoid a common bug: to forget to close the file. Note how the
|
||||||
``let fn = filename`` statement ensures that ``filename`` is evaluated only
|
``let fn = filename`` statement ensures that ``filename`` is evaluated only
|
||||||
once.
|
once.
|
||||||
|
|
||||||
|
|
||||||
Macros
|
Macros
|
||||||
======
|
======
|
||||||
|
|
||||||
|
|
@ -672,7 +672,7 @@ variable number of arguments:
|
||||||
# ``macros`` module:
|
# ``macros`` module:
|
||||||
import macros
|
import macros
|
||||||
|
|
||||||
macro debug(n: varargs[expr]): stmt =
|
macro debug(n: varargs[untyped]): typed =
|
||||||
# `n` is a Nim AST that contains a list of expressions;
|
# `n` is a Nim AST that contains a list of expressions;
|
||||||
# this macro returns a list of statements (n is passed for proper line
|
# this macro returns a list of statements (n is passed for proper line
|
||||||
# information):
|
# information):
|
||||||
|
|
@ -723,7 +723,7 @@ regular expressions:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
|
|
||||||
macro case_token(n: stmt): stmt =
|
macro case_token(n: typed): typed =
|
||||||
# creates a lexical analyzer from regular expressions
|
# creates a lexical analyzer from regular expressions
|
||||||
# ... (implementation is an exercise for the reader :-)
|
# ... (implementation is an exercise for the reader :-)
|
||||||
discard
|
discard
|
||||||
|
|
@ -815,7 +815,7 @@ modified source code implementing the macro:
|
||||||
|
|
||||||
import macros, strutils
|
import macros, strutils
|
||||||
|
|
||||||
macro readCfgAndBuildSource(cfgFilename: string): stmt =
|
macro readCfgAndBuildSource(cfgFilename: string): typed =
|
||||||
let
|
let
|
||||||
inputString = slurp(cfgFilename.strVal)
|
inputString = slurp(cfgFilename.strVal)
|
||||||
var
|
var
|
||||||
|
|
@ -941,7 +941,7 @@ macro:
|
||||||
|
|
||||||
import macros, strutils
|
import macros, strutils
|
||||||
|
|
||||||
macro readCfgAndBuildAST(cfgFilename: string): stmt =
|
macro readCfgAndBuildAST(cfgFilename: string): typed =
|
||||||
let
|
let
|
||||||
inputString = slurp(cfgFilename.strVal)
|
inputString = slurp(cfgFilename.strVal)
|
||||||
|
|
||||||
|
|
@ -992,6 +992,63 @@ example you add ``echo treeRepr(result)`` you should get the same output as
|
||||||
using the ``dumpTree`` macro, but of course you can call that at any point of
|
using the ``dumpTree`` macro, but of course you can call that at any point of
|
||||||
the macro where you might be having troubles.
|
the macro where you might be having troubles.
|
||||||
|
|
||||||
|
Example Templates and Macros
|
||||||
|
============================
|
||||||
|
|
||||||
|
Lifting Procs
|
||||||
|
+++++++++++++
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
import math
|
||||||
|
|
||||||
|
template liftScalarProc(fname) =
|
||||||
|
## Lift a proc taking one scalar parameter and returning a
|
||||||
|
## scalar value (eg ``proc sssss[T](x: T): float``),
|
||||||
|
## to provide templated procs that can handle a single
|
||||||
|
## parameter of seq[T] or nested seq[seq[]] or the same type
|
||||||
|
##
|
||||||
|
## .. code-block:: Nim
|
||||||
|
## liftScalarProc(abs)
|
||||||
|
## # now abs(@[@[1,-2], @[-2,-3]]) == @[@[1,2], @[2,3]]
|
||||||
|
proc fname[T](x: openarray[T]): auto =
|
||||||
|
var temp: T
|
||||||
|
type outType = type(fname(temp))
|
||||||
|
result = newSeq[outType](x.len)
|
||||||
|
for i in 0..<x.len:
|
||||||
|
result[i] = fname(x[i])
|
||||||
|
|
||||||
|
liftScalarProc(sqrt) # make sqrt() work for sequences
|
||||||
|
echo sqrt(@[4.0, 16.0, 25.0, 36.0]) # => @[2.0, 4.0, 5.0, 6.0]
|
||||||
|
|
||||||
|
Identifier Mangling
|
||||||
|
+++++++++++++++++++
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
proc echoHW() =
|
||||||
|
echo "Hello world"
|
||||||
|
proc echoHW0() =
|
||||||
|
echo "Hello world 0"
|
||||||
|
proc echoHW1() =
|
||||||
|
echo "Hello world 1"
|
||||||
|
|
||||||
|
template joinSymbols(a, b: untyped): untyped =
|
||||||
|
`a b`()
|
||||||
|
|
||||||
|
joinSymbols(echo, HW)
|
||||||
|
|
||||||
|
macro str2Call(s1, s2): typed =
|
||||||
|
result = newNimNode(nnkStmtList)
|
||||||
|
for i in 0..1:
|
||||||
|
# combines s1, s2 and an integer into an proc identifier
|
||||||
|
# that is called in a statement list
|
||||||
|
result.add(newCall(!($s1 & $s2 & $i)))
|
||||||
|
|
||||||
|
str2Call("echo", "HW")
|
||||||
|
|
||||||
|
# Output:
|
||||||
|
# Hello world
|
||||||
|
# Hello world 0
|
||||||
|
# Hello world 1
|
||||||
|
|
||||||
Compilation to JavaScript
|
Compilation to JavaScript
|
||||||
=========================
|
=========================
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue