summary refs log tree commit diff stats
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/tut1.rst13
-rw-r--r--doc/tut2.rst87
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
 =========================