diff options
Diffstat (limited to 'doc')
-rw-r--r-- | doc/tut1.rst | 13 | ||||
-rw-r--r-- | doc/tut2.rst | 87 |
2 files changed, 85 insertions, 15 deletions
diff --git a/doc/tut1.rst b/doc/tut1.rst index 32faf6168..1f8b60fe0 100644 --- a/doc/tut1.rst +++ b/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 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: diff --git a/doc/tut2.rst b/doc/tut2.rst index 845feb6d1..985a7257f 100644 --- a/doc/tut2.rst +++ b/doc/tut2.rst @@ -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 ========================= |