diff options
author | Araq <rumpf_a@web.de> | 2012-08-22 22:46:02 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-08-22 22:46:02 +0200 |
commit | f8931798899647b65ebb7d7dcf28d6976da599ce (patch) | |
tree | 0fdbd7f0b5516279458d21bf99a698cb2cb89e37 /doc | |
parent | a95e958046447d0ef88d93337171d4b8339348a4 (diff) | |
download | Nim-f8931798899647b65ebb7d7dcf28d6976da599ce.tar.gz |
documented hygienic templates; made tests green; fixed system.clamp
Diffstat (limited to 'doc')
-rwxr-xr-x | doc/manual.txt | 61 | ||||
-rwxr-xr-x | doc/nimrodc.txt | 2 |
2 files changed, 59 insertions, 4 deletions
diff --git a/doc/manual.txt b/doc/manual.txt index 813f1a5b4..07be0c492 100755 --- a/doc/manual.txt +++ b/doc/manual.txt @@ -2967,8 +2967,8 @@ In templates identifiers can be constructed with the backticks notation: template typedef(name: expr, typ: typeDesc) {.immediate.} = type - `T name`* = typ - `P name`* = ref `T name` + `T name`* {.inject.} = typ + `P name`* {.inject.} = ref `T name` typedef(myint, int) var x: PMyInt @@ -2982,7 +2982,7 @@ Lookup rules for template parameters A parameter ``p`` in a template is even substituted in the expression ``x.p``. Thus template arguments can be used as field names and a global symbol can be -covered by the same argument name even when fully qualified: +shadowed by the same argument name even when fully qualified: .. code-block:: nimrod # module 'm' @@ -3017,6 +3017,61 @@ But the global symbol can properly be captured by a ``bind`` statement: tstLev(levA) # produces: 'levA levB' + +Hygiene in templates +~~~~~~~~~~~~~~~~~~~~ + +Per default templates are `hygienic`:idx:\: Local identifiers declared in a +template cannot be accessed in the instantiation context: + +.. code-block:: nimrod + + template newException*(exceptn: typeDesc, message: string): expr = + var + e: ref exceptn # e is implicitely gensym'ed here + new(e) + e.msg = message + e + + # so this works: + let e = "message" + raise newException(EIO, e) + + +Whether a symbol that is declared in a template is exposed to the instantiation +scope is controlled by the `inject`:idx: and `gensym`:idx: pragmas: gensym'ed +symbols are not exposed but inject'ed are. + +The default for symbols of entity ``type``, ``var``, ``let`` and ``const`` +is ``gensym`` and for ``proc``, ``iterator``, ``converter``, ``template``, +``macro`` is ``inject``. However, if the name of the entity is passed as a +template parameter, it is an inject'ed symbol: + +.. code-block:: nimrod + template withFile(f, fn, mode: expr, actions: stmt): stmt {.immediate.} = + block: + var f: TFile # since 'f' is a template param, it's injected implicitely + ... + + withFile(txt, "ttempl3.txt", fmWrite): + txt.writeln("line 1") + txt.writeln("line 2") + + +The ``inject`` and ``gensym`` pragmas are second class annotations; they have +no semantics outside of a template definition and cannot be abstracted over: + +.. code-block:: nimrod + {.pragma myInject: inject.} + + template t() = + var x {.myInject.}: int # does NOT work + + +To get rid of hygiene in templates, one can use the `dirty`:idx: pragma for +a template. ``inject`` and ``gensym`` have no effect in ``dirty`` templates. + + Macros ------ diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt index 98e1b96d8..7b969c3bb 100755 --- a/doc/nimrodc.txt +++ b/doc/nimrodc.txt @@ -487,7 +487,7 @@ objects as `shallow`:idx:\: .. code-block:: Nimrod var s = "abc" shallow(s) # mark 's' as shallow string - var x = s # now might does not copy the string! + var x = s # now might not copy the string! Usage of ``shallow`` is always safe once you know the string won't be modified anymore, similar to Ruby's `freeze`:idx:. |