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:
jlp765
2017-01-07 18:18:45 +10:00
committed by Andreas Rumpf
parent 92ecbc9958
commit 86c73cdfc2
2 changed files with 85 additions and 15 deletions

View File

@@ -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
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
literals* to create block comments:

View File

@@ -557,7 +557,7 @@ To *invoke* a template, call it like a procedure.
Example:
.. code-block:: nim
template `!=` (a, b: expr): expr =
template `!=` (a, b: untyped): untyped =
# this definition exists in the System module
not (a == b)
@@ -603,19 +603,20 @@ Turning the ``log`` proc into a template solves this problem:
x = 4
log("x has the value: " & $x)
The parameters' types can be ordinary types or the meta types ``expr``
(stands for *expression*), ``stmt`` (stands for *statement*) or ``typedesc``
(stands for *type description*). If the template has no explicit return type,
``stmt`` is used for consistency with procs and methods.
The parameters' types can be ordinary types or the meta types ``untyped``,
``typed``, or ``typedesc``.
``typedesc`` stands for *type description*, and ``untyped`` means symbol lookups and
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
declaration. The reason is that statements can be passed to a template
via a special ``:`` syntax:
If the template has no explicit return type,
``void`` is used for consistency with procs and methods.
To pass a block of statements to a template, use 'untyped' for the last parameter:
.. code-block:: nim
template withFile(f: expr, filename: string, mode: FileMode,
body: stmt): stmt {.immediate.} =
template withFile(f: untyped, filename: string, mode: FileMode,
body: untyped): typed =
let fn = filename
var f: File
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
once.
Macros
======
@@ -672,7 +672,7 @@ variable number of arguments:
# ``macros`` module:
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;
# this macro returns a list of statements (n is passed for proper line
# information):
@@ -723,7 +723,7 @@ regular expressions:
.. code-block:: nim
macro case_token(n: stmt): stmt =
macro case_token(n: typed): typed =
# creates a lexical analyzer from regular expressions
# ... (implementation is an exercise for the reader :-)
discard
@@ -815,7 +815,7 @@ modified source code implementing the macro:
import macros, strutils
macro readCfgAndBuildSource(cfgFilename: string): stmt =
macro readCfgAndBuildSource(cfgFilename: string): typed =
let
inputString = slurp(cfgFilename.strVal)
var
@@ -941,7 +941,7 @@ macro:
import macros, strutils
macro readCfgAndBuildAST(cfgFilename: string): stmt =
macro readCfgAndBuildAST(cfgFilename: string): typed =
let
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
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
=========================