diff options
author | Araq <rumpf_a@web.de> | 2015-11-10 22:51:03 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2015-11-10 22:51:03 +0100 |
commit | f9ad735e55d45d6a3ed7e9e7da7abd31065f99ac (patch) | |
tree | c046a9ba8e20e6b5239373bae1c6f588761d4349 /doc/manual | |
parent | b6374f1f68d899e7eed65c553f3e8b71e688c61c (diff) | |
download | Nim-f9ad735e55d45d6a3ed7e9e7da7abd31065f99ac.tar.gz |
documented untyped/typed meta-types
Diffstat (limited to 'doc/manual')
-rw-r--r-- | doc/manual/modules.txt | 2 | ||||
-rw-r--r-- | doc/manual/templates.txt | 108 |
2 files changed, 88 insertions, 22 deletions
diff --git a/doc/manual/modules.txt b/doc/manual/modules.txt index e6a08b5ce..ac47d89dd 100644 --- a/doc/manual/modules.txt +++ b/doc/manual/modules.txt @@ -152,9 +152,11 @@ In module related statements, if any part of the module name / path begins with a number, you may have to quote it in double quotes. In the following example, it would be seen as a literal number '3.0' of type 'float64' if not quoted, if uncertain - quote it: + .. code-block:: nim import "gfx/3d/somemodule" + Scope rules ----------- Identifiers are valid from the point of their declaration until the end of diff --git a/doc/manual/templates.txt b/doc/manual/templates.txt index 092d65ea2..b60fe632e 100644 --- a/doc/manual/templates.txt +++ b/doc/manual/templates.txt @@ -10,7 +10,7 @@ The syntax to *invoke* a template is the same as calling 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) @@ -23,50 +23,56 @@ templates: | ``a in b`` is transformed into ``contains(b, a)``. | ``notin`` and ``isnot`` have the obvious meanings. -The "types" of templates can be the symbols ``expr`` (stands for *expression*), -``stmt`` (stands for *statement*) or ``typedesc`` (stands for *type +The "types" of templates can be the symbols ``untyped``, +``typed`` or ``typedesc`` (stands for *type description*). These are "meta types", they can only be used in certain -contexts. Real types can be used too; this implies that expressions are -expected. +contexts. Real types can be used too; this implies that ``typed`` expressions +are expected. -Ordinary vs immediate templates -------------------------------- +Typed vs untyped parameters +--------------------------- -There are two different kinds of templates: immediate templates and -ordinary templates. Ordinary templates take part in overloading resolution. As -such their arguments need to be type checked before the template is invoked. -So ordinary templates cannot receive undeclared identifiers: +An ``untyped`` parameter means that symbol lookups and type resolution is not +performed before the expression is passed to the template. This means that for +example *undeclared* identifiers can be passed to the template: .. code-block:: nim - template declareInt(x: expr) = + template declareInt(x: untyped) = var x: int - declareInt(x) # error: unknown identifier: 'x' + declareInt(x) # valid + x = 3 -An ``immediate`` template does not participate in overload resolution and so -its arguments are not checked for semantics before invocation. So they can -receive undeclared identifiers: .. code-block:: nim - template declareInt(x: expr) {.immediate.} = + template declareInt(x: typed) = var x: int - declareInt(x) # valid + declareInt(x) # invalid, because x has not been declared and so has no type + +A template where every parameter is ``untyped`` is called an `immediate`:idx: +template. For historical reasons templates can be explicitly annotated with +an ``immediate`` pragma and then these templates do not take part in +overloading resolution and the parameters' types are *ignored* by the +compiler. Explicit immediate templates are about to be deprecated in later +versions of the compiler. + +**Note**: For historical reasons ``stmt`` is an alias for ``typed`` and +``expr`` an alias for ``untyped``, but new code should use the newer, +clearer names. Passing a code block to a template ---------------------------------- -If there is a ``stmt`` parameter it should be the last in the template -declaration, because statements are passed to a template via a +You can pass a block of statements as a last parameter to a template via a special ``:`` syntax: .. code-block:: nim - - template withFile(f, fn, mode: expr, actions: stmt): stmt {.immediate.} = + template withFile(f, fn, mode, actions: untyped): untyped = var f: File if open(f, fn, mode): try: @@ -84,6 +90,64 @@ In the example the two ``writeLine`` statements are bound to the ``actions`` parameter. +Usually to pass a block of code to a template the parameter that accepts +the block needs to be of type ``untyped``. Because symbol lookups are then +delayed until template instantiation time: + +.. code-block:: nim + template t(body: typed) = + block: + body + + t: + var i = 1 + echo i + + t: + var i = 2 # fails with 'attempt to redeclare i' + echo i + +The above code fails with the mysterious error message that ``i`` has already +been declared. The reason for this is that the ``var i = ...`` bodies need to +be type-checked before they are passed to the ``body`` parameter and type +checking in Nim implies symbol lookups. For the symbol lookups to succeed +``i`` needs to be added to the current (i.e. outer) scope. After type checking +these additions to the symbol table are not rolled back (for better or worse). +The same code works with ``untyped`` as the passed body is not required to be +type-checked: + +.. code-block:: nim + template t(body: untyped) = + block: + body + + t: + var i = 1 + echo i + + t: + var i = 2 # compiles + echo i + + +Varargs of untyped +------------------ + +In addition to the ``untyped`` meta-type that prevents type checking there is +also ``varargs[untyped]`` so that not even the number of parameters is fixed: + +.. code-block:: nim + template hideIdentifiers(x: varargs[untyped]) = discard + + hideIdentifiers(undeclared1, undeclared2) + +However, since a template cannot iterate over varargs, this feature is +generally much more useful for macros. + +**Note**: For historical reasons ``varargs[expr]`` is not equivalent +to ``varargs[untyped]``. + + Symbol binding in templates --------------------------- |