doc: Trim .txt files trailing whitespace

via OSX: find . -name '*.txt' -exec sed -i '' -E 's/[[:space:]]+$//' {} +
This commit is contained in:
Adam Strzelecki 2015-09-04 23:10:48 +02:00
commit 0b44d812f1
33 changed files with 566 additions and 566 deletions

View file

@ -14,20 +14,20 @@ optional *a*. Parentheses may be used to group elements.
``&`` is the lookahead operator; ``&a`` means that an ``a`` is expected but
not consumed. It will be consumed in the following rule.
The ``|``, ``/`` symbols are used to mark alternatives and have the lowest
precedence. ``/`` is the ordered choice that requires the parser to try the
The ``|``, ``/`` symbols are used to mark alternatives and have the lowest
precedence. ``/`` is the ordered choice that requires the parser to try the
alternatives in the given order. ``/`` is often used to ensure the grammar
is not ambiguous.
is not ambiguous.
Non-terminals start with a lowercase letter, abstract terminal symbols are in
UPPERCASE. Verbatim terminal symbols (including keywords) are quoted
with ``'``. An example::
ifStmt = 'if' expr ':' stmts ('elif' expr ':' stmts)* ('else' stmts)?
The binary ``^*`` operator is used as a shorthand for 0 or more occurrences
separated by its second argument; likewise ``^+`` means 1 or more
occurrences: ``a ^+ b`` is short for ``a (b a)*``
separated by its second argument; likewise ``^+`` means 1 or more
occurrences: ``a ^+ b`` is short for ``a (b a)*``
and ``a ^* b`` is short for ``(a (b a)*)?``. Example::
arrayConstructor = '[' expr ^* ',' ']'

View file

@ -26,9 +26,9 @@ program execution. Unless explicitly classified, an error is a static error.
A `checked runtime error`:idx: is an error that the implementation detects
and reports at runtime. The method for reporting such errors is via *raising
exceptions* or *dying with a fatal error*. However, the implementation
exceptions* or *dying with a fatal error*. However, the implementation
provides a means to disable these runtime checks. See the section pragmas_
for details.
for details.
Whether a checked runtime error results in an exception or in a fatal error at
runtime is implementation specific. Thus the following program is always

View file

@ -5,7 +5,7 @@ Exception tracking
------------------
Nim supports exception tracking. The `raises`:idx: pragma can be used
to explicitly define which exceptions a proc/iterator/method/converter is
to explicitly define which exceptions a proc/iterator/method/converter is
allowed to raise. The compiler verifies this:
.. code-block:: nim
@ -24,7 +24,7 @@ An empty ``raises`` list (``raises: []``) means that no exception may be raised:
result = false
A ``raises`` list can also be attached to a proc type. This affects type
A ``raises`` list can also be attached to a proc type. This affects type
compatibility:
.. code-block:: nim
@ -35,7 +35,7 @@ compatibility:
proc p(x: string) =
raise newException(OSError, "OS")
c = p # type error
@ -46,30 +46,30 @@ possibly raised exceptions; the algorithm operates on ``p``'s call graph:
raise ``system.Exception`` (the base type of the exception hierarchy) and
thus any exception unless ``T`` has an explicit ``raises`` list.
However if the call is of the form ``f(...)`` where ``f`` is a parameter
of the currently analysed routine it is ignored. The call is optimistically
of the currently analysed routine it is ignored. The call is optimistically
assumed to have no effect. Rule 2 compensates for this case.
2. Every expression of some proc type within a call that is not a call
itself (and not nil) is assumed to be called indirectly somehow and thus
2. Every expression of some proc type within a call that is not a call
itself (and not nil) is assumed to be called indirectly somehow and thus
its raises list is added to ``p``'s raises list.
3. Every call to a proc ``q`` which has an unknown body (due to a forward
declaration or an ``importc`` pragma) is assumed to
3. Every call to a proc ``q`` which has an unknown body (due to a forward
declaration or an ``importc`` pragma) is assumed to
raise ``system.Exception`` unless ``q`` has an explicit ``raises`` list.
4. Every call to a method ``m`` is assumed to
4. Every call to a method ``m`` is assumed to
raise ``system.Exception`` unless ``m`` has an explicit ``raises`` list.
5. For every other call the analysis can determine an exact ``raises`` list.
6. For determining a ``raises`` list, the ``raise`` and ``try`` statements
6. For determining a ``raises`` list, the ``raise`` and ``try`` statements
of ``p`` are taken into consideration.
Rules 1-2 ensure the following works:
Rules 1-2 ensure the following works:
.. code-block:: nim
proc noRaise(x: proc()) {.raises: [].} =
# unknown call that might raise anything, but valid:
x()
proc doRaise() {.raises: [IOError].} =
raise newException(IOError, "IO")
proc use() {.raises: [].} =
# doesn't compile! Can raise IOError!
noRaise(doRaise)
@ -82,21 +82,21 @@ Tag tracking
------------
The exception tracking is part of Nim's `effect system`:idx:. Raising an
exception is an *effect*. Other effects can also be defined. A user defined
exception is an *effect*. Other effects can also be defined. A user defined
effect is a means to *tag* a routine and to perform checks against this tag:
.. code-block:: nim
type IO = object ## input/output effect
proc readLine(): string {.tags: [IO].}
proc no_IO_please() {.tags: [].} =
# the compiler prevents this:
let x = readLine()
A tag has to be a type name. A ``tags`` list - like a ``raises`` list - can
A tag has to be a type name. A ``tags`` list - like a ``raises`` list - can
also be attached to a proc type. This affects type compatibility.
The inference for tag tracking is analogous to the inference for
The inference for tag tracking is analogous to the inference for
exception tracking.
@ -105,7 +105,7 @@ Read/Write tracking
**Note**: Read/write tracking is not yet implemented!
The inference for read/write tracking is analogous to the inference for
The inference for read/write tracking is analogous to the inference for
exception tracking.

View file

@ -164,7 +164,7 @@ Alternatively, the ``distinct`` type modifier can be applied to the type class
to allow each param matching the type class to bind to a different type.
If a proc param doesn't have a type specified, Nim will use the
``distinct auto`` type class (also known as ``any``). Note this behavior is
``distinct auto`` type class (also known as ``any``). Note this behavior is
deprecated for procs; templates, however, support them:
.. code-block:: nim

View file

@ -36,7 +36,7 @@ With this notation we can now easily define the core of the grammar: A block of
statements (simplified example)::
ifStmt = 'if' expr ':' stmt
(IND{=} 'elif' expr ':' stmt)*
(IND{=} 'elif' expr ':' stmt)*
(IND{=} 'else' ':' stmt)?
simpleStmt = ifStmt / ...
@ -156,7 +156,7 @@ contain the following `escape sequences`:idx:\ :
================== ===================================================
Strings in Nim may contain any 8-bit value, even embedded zeros. However
Strings in Nim may contain any 8-bit value, even embedded zeros. However
some operations may interpret the first binary zero as a terminator.
@ -174,7 +174,7 @@ be whitespace between the opening ``"""`` and the newline),
the newline (and the preceding whitespace) is not included in the string. The
ending of the string literal is defined by the pattern ``"""[^"]``, so this:
.. code-block:: nim
.. code-block:: nim
""""long string within quotes""""
Produces::
@ -187,9 +187,9 @@ Raw string literals
Terminal symbol in the grammar: ``RSTR_LIT``.
There are also raw string literals that are preceded with the
letter ``r`` (or ``R``) and are delimited by matching double quotes (just
like ordinary string literals) and do not interpret the escape sequences.
There are also raw string literals that are preceded with the
letter ``r`` (or ``R``) and are delimited by matching double quotes (just
like ordinary string literals) and do not interpret the escape sequences.
This is especially convenient for regular expressions or Windows paths:
.. code-block:: nim
@ -201,21 +201,21 @@ To produce a single ``"`` within a raw string literal, it has to be doubled:
.. code-block:: nim
r"a""b"
Produces::
a"b
``r""""`` is not possible with this notation, because the three leading
quotes introduce a triple quoted string literal. ``r"""`` is the same
as ``"""`` since triple quoted string literals do not interpret escape
``r""""`` is not possible with this notation, because the three leading
quotes introduce a triple quoted string literal. ``r"""`` is the same
as ``"""`` since triple quoted string literals do not interpret escape
sequences either.
Generalized raw string literals
-------------------------------
Terminal symbols in the grammar: ``GENERALIZED_STR_LIT``,
Terminal symbols in the grammar: ``GENERALIZED_STR_LIT``,
``GENERALIZED_TRIPLESTR_LIT``.
The construct ``identifier"string literal"`` (without whitespace between the
@ -281,7 +281,7 @@ Numerical constants are of a single type and have the form::
DEC_LIT = digit ( ['_'] digit )*
OCT_LIT = '0' ('o' | 'c' | 'C') octdigit ( ['_'] octdigit )*
BIN_LIT = '0' ('b' | 'B' ) bindigit ( ['_'] bindigit )*
INT_LIT = HEX_LIT
| DEC_LIT
| OCT_LIT
@ -383,7 +383,7 @@ The following strings denote other tokens::
` ( ) { } [ ] , ; [. .] {. .} (. .)
The `slice`:idx: operator `..`:tok: takes precedence over other tokens that
contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok:
The `slice`:idx: operator `..`:tok: takes precedence over other tokens that
contain a dot: `{..}`:tok: are the three tokens `{`:tok:, `..`:tok:, `}`:tok:
and not the two tokens `{.`:tok:, `.}`:tok:.

View file

@ -63,7 +63,7 @@ model low level lockfree mechanisms:
.. code-block:: nim
var dummyLock {.compileTime.}: int
var atomicCounter {.guard: dummyLock.}: int
template atomicRead(x): expr =
{.locks: [dummyLock].}:
memoryReadBarrier()
@ -135,30 +135,30 @@ Lock levels are used to enforce a global locking order in order to prevent
deadlocks at compile-time. A lock level is an constant integer in the range
0..1_000. Lock level 0 means that no lock is acquired at all.
If a section of code holds a lock of level ``M`` than it can also acquire any
If a section of code holds a lock of level ``M`` than it can also acquire any
lock of level ``N < M``. Another lock of level ``M`` cannot be acquired. Locks
of the same level can only be acquired *at the same time* within a
of the same level can only be acquired *at the same time* within a
single ``locks`` section:
.. code-block:: nim
var a, b: TLock[2]
var x: TLock[1]
# invalid locking order: TLock[1] cannot be acquired before TLock[2]:
{.locks: [x].}:
{.locks: [x].}:
{.locks: [a].}:
...
# valid locking order: TLock[2] acquired before TLock[1]:
{.locks: [a].}:
{.locks: [a].}:
{.locks: [x].}:
...
# invalid locking order: TLock[2] acquired before TLock[2]:
{.locks: [a].}:
{.locks: [a].}:
{.locks: [b].}:
...
# valid locking order, locks of the same level acquired at the same time:
{.locks: [a, b].}:
{.locks: [a, b].}:
...
@ -187,7 +187,7 @@ level. This then means that the routine may acquire locks of up to this level.
This is essential so that procs can be called within a ``locks`` section:
.. code-block:: nim
proc p() {.locks: 3.} = discard
proc p() {.locks: 3.} = discard
var a: TLock[4]
{.locks: [a].}:
@ -195,6 +195,6 @@ This is essential so that procs can be called within a ``locks`` section:
p()
As usual ``locks`` is an inferred effect and there is a subtype
As usual ``locks`` is an inferred effect and there is a subtype
relation: ``proc () {.locks: N.}`` is a subtype of ``proc () {.locks: M.}``
iff (M <= N).

View file

@ -81,8 +81,8 @@ A module alias can be introduced via the ``as`` keyword:
echo su.format("$1", "lalelu")
The original module name is then not accessible. The
notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"``
The original module name is then not accessible. The
notations ``path/to/module`` or ``path.to.module`` or ``"path/to/module"``
can be used to refer to a module in subdirectories:
.. code-block:: nim
@ -104,7 +104,7 @@ Likewise the following does not make sense as the name is ``strutils`` already:
From import statement
~~~~~~~~~~~~~~~~~~~~~
After the ``from`` statement a module name follows followed by
After the ``from`` statement a module name follows followed by
an ``import`` to list the symbols one likes to use without explict
full qualification:
@ -115,8 +115,8 @@ full qualification:
# always possible: full qualification:
echo strutils.replace("abc", "a", "z")
It's also possible to use ``from module import nil`` if one wants to import
the module but wants to enforce fully qualified access to every symbol
It's also possible to use ``from module import nil`` if one wants to import
the module but wants to enforce fully qualified access to every symbol
in ``module``.
@ -134,15 +134,15 @@ modules don't need to import a module's dependencies:
# module A
import B
export B.MyObject
proc `$`*(x: MyObject): string = "my object"
.. code-block:: nim
# module C
import A
# B.MyObject has been imported implicitly here:
# B.MyObject has been imported implicitly here:
var x: MyObject
echo($x)
@ -185,7 +185,7 @@ following places:
Module scope
~~~~~~~~~~~~
All identifiers of a module are valid from the point of declaration until
the end of the module. Identifiers from indirectly dependent modules are *not*
the end of the module. Identifiers from indirectly dependent modules are *not*
available. The `system`:idx: module is automatically imported in every module.
If a module imports an identifier by two different modules, each occurrence of

View file

@ -120,7 +120,7 @@ current module:
Method call syntax
------------------
For object oriented programming, the syntax ``obj.method(args)`` can be used
For object oriented programming, the syntax ``obj.method(args)`` can be used
instead of ``method(obj, args)``. The parentheses can be omitted if there are no
remaining arguments: ``obj.len`` (instead of ``len(obj)``).
@ -128,7 +128,7 @@ This method call syntax is not restricted to objects, it can be used
to supply any type of first argument for procedures:
.. code-block:: nim
echo("abc".len) # is the same as echo(len("abc"))
echo("abc".toUpper())
echo({'a', 'b', 'c'}.card)
@ -143,11 +143,11 @@ See also: `Limitations of the method call syntax`_.
Properties
----------
Nim has no need for *get-properties*: Ordinary get-procedures that are called
with the *method call syntax* achieve the same. But setting a value is
with the *method call syntax* achieve the same. But setting a value is
different; for this a special setter syntax is needed:
.. code-block:: nim
type
Socket* = ref object of RootObj
FHost: int # cannot be accessed from the outside of the module
@ -157,7 +157,7 @@ different; for this a special setter syntax is needed:
proc `host=`*(s: var Socket, value: int) {.inline.} =
## setter of hostAddr
s.FHost = value
proc host*(s: Socket): int {.inline.} =
## getter of hostAddr
s.FHost
@ -180,18 +180,18 @@ more argument in this case:
.. code-block:: nim
proc optarg(x: int, y: int = 0): int = x + y
proc singlearg(x: int): int = 20*x
echo optarg 1, " ", singlearg 2 # prints "1 40"
let fail = optarg 1, optarg 8 # Wrong. Too many arguments for a command call
let x = optarg(1, optarg 8) # traditional procedure call with 2 arguments
let y = 1.optarg optarg 8 # same thing as above, w/o the parenthesis
assert x == y
The command invocation syntax also can't have complex expressions as arguments.
For example: (`anonymous procs`_), ``if``, ``case`` or ``try``. The (`do
notation`_) is limited, but usable for a single proc (see the example in the
corresponding section). Function calls with no arguments still needs () to
The command invocation syntax also can't have complex expressions as arguments.
For example: (`anonymous procs`_), ``if``, ``case`` or ``try``. The (`do
notation`_) is limited, but usable for a single proc (see the example in the
corresponding section). Function calls with no arguments still needs () to
distinguish between a call and the function itself as a first class value.
@ -221,7 +221,7 @@ the proc's name.
cmp(x.len, y.len))
Procs as expressions can appear both as nested procs and inside top level
Procs as expressions can appear both as nested procs and inside top level
executable code.
@ -237,10 +237,10 @@ calls can use the ``do`` keyword:
sort(cities) do (x,y: string) -> int:
cmp(x.len, y.len)
# Less parenthesis using the method plus command syntax:
cities = cities.map do (x:string) -> string:
cities = cities.map do (x:string) -> string:
"City of " & x
``do`` is written after the parentheses enclosing the regular proc params.
``do`` is written after the parentheses enclosing the regular proc params.
The proc expression represented by the do block is appended to them.
More than one ``do`` block can appear in a single call:
@ -261,11 +261,11 @@ Nonoverloadable builtins
The following builtin procs cannot be overloaded for reasons of implementation
simplicity (they require specialized semantic checking)::
declared, defined, definedInScope, compiles, low, high, sizeOf,
declared, defined, definedInScope, compiles, low, high, sizeOf,
is, of, shallowCopy, getAst, astToStr, spawn, procCall
Thus they act more like keywords than like ordinary identifiers; unlike a
keyword however, a redefinition may `shadow`:idx: the definition in
Thus they act more like keywords than like ordinary identifiers; unlike a
keyword however, a redefinition may `shadow`:idx: the definition in
the ``system`` module. From this list the following should not be written in dot
notation ``x.f`` since ``x`` cannot be type checked before it gets passed
to ``f``::
@ -342,11 +342,11 @@ returned value is an l-value and can be modified by the caller:
proc WriteAccessToG(): var int =
result = g
WriteAccessToG() = 6
assert g == 6
It is a compile time error if the implicitly introduced pointer could be
It is a compile time error if the implicitly introduced pointer could be
used to access a location beyond its lifetime:
.. code-block:: nim
@ -354,7 +354,7 @@ used to access a location beyond its lifetime:
var g = 0
result = g # Error!
For iterators, a component of a tuple return type can have a ``var`` type too:
For iterators, a component of a tuple return type can have a ``var`` type too:
.. code-block:: nim
iterator mpairs(a: var seq[string]): tuple[key: int, val: var string] =
@ -384,28 +384,28 @@ dispatch.
x: int
PlusExpr = ref object of Expression
a, b: Expression
method eval(e: Expression): int =
# override this base method
quit "to override!"
method eval(e: Literal): int = return e.x
method eval(e: PlusExpr): int =
# watch out: relies on dynamic binding
result = eval(e.a) + eval(e.b)
proc newLit(x: int): Literal =
new(result)
result.x = x
proc newPlus(a, b: Expression): PlusExpr =
new(result)
result.a = a
result.b = b
echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
In the example the constructors ``newLit`` and ``newPlus`` are procs
because they should use static binding, but ``eval`` is a method because it
requires dynamic binding.
@ -418,24 +418,24 @@ dispatching:
Thing = ref object of RootObj
Unit = ref object of Thing
x: int
method collide(a, b: Thing) {.inline.} =
quit "to override!"
method collide(a: Thing, b: Unit) {.inline.} =
echo "1"
method collide(a: Unit, b: Thing) {.inline.} =
echo "2"
var a, b: Unit
new a
new b
collide(a, b) # output: 2
Invocation of a multi-method cannot be ambiguous: collide 2 is preferred over
collide 1 because the resolution works from left to right.
Invocation of a multi-method cannot be ambiguous: collide 2 is preferred over
collide 1 because the resolution works from left to right.
In the example ``Unit, Thing`` is preferred over ``Thing, Unit``.
**Performance note**: Nim does not produce a virtual method table, but
@ -450,7 +450,7 @@ Iterators and the for statement
The `for`:idx: statement is an abstract mechanism to iterate over the elements
of a container. It relies on an `iterator`:idx: to do so. Like ``while``
statements, ``for`` statements open an `implicit block`:idx:, so that they
can be left with a ``break`` statement.
can be left with a ``break`` statement.
The ``for`` loop declares iteration variables - their scope reaches until the
end of the loop body. The iteration variables' types are inferred by the
@ -486,7 +486,7 @@ The compiler generates code as if the programmer would have written this:
If the iterator yields a tuple, there can be as many iteration variables
as there are components in the tuple. The i'th iteration variable's type is
the type of the i'th component. In other words, implicit tuple unpacking in a
the type of the i'th component. In other words, implicit tuple unpacking in a
for loop context is supported.
Implict items/pairs invocations
@ -498,11 +498,11 @@ ie. an ``items`` iterator is implicitly invoked:
.. code-block:: nim
for x in [1,2,3]: echo x
If the for loop has exactly 2 variables, a ``pairs`` iterator is implicitly
invoked.
Symbol lookup of the identifiers ``items``/``pairs`` is performed after
Symbol lookup of the identifiers ``items``/``pairs`` is performed after
the rewriting step, so that all overloads of ``items``/``pairs`` are taken
into account.
@ -511,7 +511,7 @@ First class iterators
---------------------
There are 2 kinds of iterators in Nim: *inline* and *closure* iterators.
An `inline iterator`:idx: is an iterator that's always inlined by the compiler
An `inline iterator`:idx: is an iterator that's always inlined by the compiler
leading to zero overhead for the abstraction, but may result in a heavy
increase in code size. Inline iterators are second class citizens;
They can be passed as parameters only to other inlining code facilities like
@ -522,7 +522,7 @@ In contrast to that, a `closure iterator`:idx: can be passed around more freely:
.. code-block:: nim
iterator count0(): int {.closure.} =
yield 0
iterator count2(): int {.closure.} =
var x = 1
yield x
@ -539,7 +539,7 @@ Closure iterators have other restrictions than inline iterators:
1. ``yield`` in a closure iterator can not occur in a ``try`` statement.
2. For now, a closure iterator cannot be evaluated at compile time.
3. ``return`` is allowed in a closure iterator (but rarely useful) and ends
3. ``return`` is allowed in a closure iterator (but rarely useful) and ends
iteration.
4. Neither inline nor closure iterators can be recursive.
@ -547,7 +547,7 @@ Iterators that are neither marked ``{.closure.}`` nor ``{.inline.}`` explicitly
default to being inline, but this may change in future versions of the
implementation.
The ``iterator`` type is always of the calling convention ``closure``
The ``iterator`` type is always of the calling convention ``closure``
implicitly; the following example shows how to use iterators to implement
a `collaborative tasking`:idx: system:
@ -650,7 +650,7 @@ parameters of an outer factory proc:
Converters
==========
A converter is like an ordinary proc except that it enhances
A converter is like an ordinary proc except that it enhances
the "implicitly convertible" type relation (see `Convertible relation`_):
.. code-block:: nim

View file

@ -34,7 +34,7 @@ templates and macros), depending on the desired effect:
The following dot operators are available:
operator `.`
------------
------------
This operator will be matched against both field accesses and method calls.
operator `.()`

View file

@ -176,8 +176,8 @@ The rules for compile-time computability are:
1. Literals are compile-time computable.
2. Type conversions are compile-time computable.
3. Procedure calls of the form ``p(X)`` are compile-time computable if
``p`` is a proc without side-effects (see the `noSideEffect pragma
<#pragmas-nosideeffect-pragma>`_ for details) and if ``X`` is a
``p`` is a proc without side-effects (see the `noSideEffect pragma
<#pragmas-nosideeffect-pragma>`_ for details) and if ``X`` is a
(possibly empty) list of compile-time computable arguments.

View file

@ -1,11 +1,11 @@
Taint mode
==========
The Nim compiler and most parts of the standard library support
a taint mode. Input strings are declared with the `TaintedString`:idx:
The Nim compiler and most parts of the standard library support
a taint mode. Input strings are declared with the `TaintedString`:idx:
string type declared in the ``system`` module.
If the taint mode is turned on (via the ``--taintMode:on`` command line
If the taint mode is turned on (via the ``--taintMode:on`` command line
option) it is a distinct string type which helps to detect input
validation errors:
@ -13,7 +13,7 @@ validation errors:
echo "your name: "
var name: TaintedString = stdin.readline
# it is safe here to output the name without any input validation, so
# we simply convert `name` to string to make the compiler happy:
# we simply convert `name` to string to make the compiler happy:
echo "hi, ", name.string
If the taint mode is turned off, ``TaintedString`` is simply an alias for

View file

@ -16,17 +16,17 @@ Example:
assert(5 != 6) # the compiler rewrites that to: assert(not (5 == 6))
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
The ``!=``, ``>``, ``>=``, ``in``, ``notin``, ``isnot`` operators are in fact
templates:
| ``a > b`` is transformed into ``b < a``.
| ``a in b`` is transformed into ``contains(b, a)``.
| ``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
description*). These are "meta types", they can only be used in certain
contexts. Real types can be used too; this implies that expressions are
The "types" of templates can be the symbols ``expr`` (stands for *expression*),
``stmt`` (stands for *statement*) 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.
@ -40,7 +40,7 @@ So ordinary templates cannot receive undeclared identifiers:
.. code-block:: nim
template declareInt(x: expr) =
template declareInt(x: expr) =
var x: int
declareInt(x) # error: unknown identifier: 'x'
@ -51,7 +51,7 @@ receive undeclared identifiers:
.. code-block:: nim
template declareInt(x: expr) {.immediate.} =
template declareInt(x: expr) {.immediate.} =
var x: int
declareInt(x) # valid
@ -75,11 +75,11 @@ special ``:`` syntax:
close(f)
else:
quit("cannot open: " & fn)
withFile(txt, "ttempl3.txt", fmWrite):
txt.writeLine("line 1")
txt.writeLine("line 2")
In the example the two ``writeLine`` statements are bound to the ``actions``
parameter.
@ -92,9 +92,9 @@ bound from the definition scope of the template:
.. code-block:: nim
# Module A
var
var
lastId = 0
template genId*: expr =
inc(lastId)
lastId
@ -102,10 +102,10 @@ bound from the definition scope of the template:
.. code-block:: nim
# Module B
import A
echo genId() # Works as 'lastId' has been bound in 'genId's defining scope
As in generics symbol binding can be influenced via ``mixin`` or ``bind``
As in generics symbol binding can be influenced via ``mixin`` or ``bind``
statements.
@ -117,11 +117,11 @@ In templates identifiers can be constructed with the backticks notation:
.. code-block:: nim
template typedef(name: expr, typ: typedesc) {.immediate.} =
template typedef(name: expr, typ: typedesc) {.immediate.} =
type
`T name`* {.inject.} = typ
`P name`* {.inject.} = ref `T name`
typedef(myint, int)
var x: PMyInt
@ -150,7 +150,7 @@ shadowed by the same argument name even when fully qualified:
tstLev(levA)
# produces: 'levA levA'
But the global symbol can properly be captured by a ``bind`` statement:
.. code-block:: nim
@ -177,14 +177,14 @@ Per default templates are `hygienic`:idx:\: Local identifiers declared in a
template cannot be accessed in the instantiation context:
.. code-block:: nim
template newException*(exceptn: typedesc, message: string): expr =
var
e: ref exceptn # e is implicitly gensym'ed here
new(e)
e.msg = message
e
# so this works:
let e = "message"
raise newException(EIO, e)
@ -196,7 +196,7 @@ 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
``macro`` is ``inject``. However, if the name of the entity is passed as a
template parameter, it is an inject'ed symbol:
.. code-block:: nim
@ -204,7 +204,7 @@ template parameter, it is an inject'ed symbol:
block:
var f: File # since 'f' is a template param, it's injected implicitly
...
withFile(txt, "ttempl3.txt", fmWrite):
txt.writeLine("line 1")
txt.writeLine("line 2")
@ -215,7 +215,7 @@ no semantics outside of a template definition and cannot be abstracted over:
.. code-block:: nim
{.pragma myInject: inject.}
template t() =
var x {.myInject.}: int # does NOT work
@ -334,9 +334,9 @@ BindSym
-------
The above ``debug`` macro relies on the fact that ``write``, ``writeLine`` and
``stdout`` are declared in the system module and thus visible in the
``stdout`` are declared in the system module and thus visible in the
instantiating context. There is a way to use bound identifiers
(aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym``
(aka `symbols`:idx:) instead of using unbound identifiers. The ``bindSym``
builtin can be used for that:
.. code-block:: nim
@ -418,8 +418,8 @@ powerful programming construct that still suffices. So the "check list" is:
Macros as pragmas
-----------------
Whole routines (procs, iterators etc.) can also be passed to a template or
a macro via the pragma notation:
Whole routines (procs, iterators etc.) can also be passed to a template or
a macro via the pragma notation:
.. code-block:: nim
template m(s: stmt) = discard

View file

@ -3,32 +3,32 @@ Term rewriting macros
Term rewriting macros are macros or templates that have not only
a *name* but also a *pattern* that is searched for after the semantic checking
phase of the compiler: This means they provide an easy way to enhance the
phase of the compiler: This means they provide an easy way to enhance the
compilation pipeline with user defined optimizations:
.. code-block:: nim
template optMul{`*`(a, 2)}(a: int): int = a+a
let x = 3
echo x * 2
The compiler now rewrites ``x * 2`` as ``x + x``. The code inside the
curlies is the pattern to match against. The operators ``*``, ``**``,
``|``, ``~`` have a special meaning in patterns if they are written in infix
``|``, ``~`` have a special meaning in patterns if they are written in infix
notation, so to match verbatim against ``*`` the ordinary function call syntax
needs to be used.
Unfortunately optimizations are hard to get right and even the tiny example
is **wrong**:
is **wrong**:
.. code-block:: nim
template optMul{`*`(a, 2)}(a: int): int = a+a
proc f(): int =
echo "side effect!"
result = 55
echo f() * 2
We cannot duplicate 'a' if it denotes an expression that has a side effect!
@ -36,11 +36,11 @@ Fortunately Nim supports side effect analysis:
.. code-block:: nim
template optMul{`*`(a, 2)}(a: int{noSideEffect}): int = a+a
proc f(): int =
echo "side effect!"
result = 55
echo f() * 2 # not optimized ;-)
You can make one overload matching with a constraint and one without, and the
@ -53,13 +53,13 @@ blindly:
.. code-block:: nim
template mulIsCommutative{`*`(a, b)}(a, b: int): int = b*a
What optimizers really need to do is a *canonicalization*:
.. code-block:: nim
template canonMul{`*`(a, b)}(a: int{lit}, b: int): int = b*a
The ``int{lit}`` parameter pattern matches against an expression of
The ``int{lit}`` parameter pattern matches against an expression of
type ``int``, but only if it's a literal.
@ -67,7 +67,7 @@ type ``int``, but only if it's a literal.
Parameter constraints
---------------------
The `parameter constraint`:idx: expression can use the operators ``|`` (or),
The `parameter constraint`:idx: expression can use the operators ``|`` (or),
``&`` (and) and ``~`` (not) and the following predicates:
=================== =====================================================
@ -75,7 +75,7 @@ Predicate Meaning
=================== =====================================================
``atom`` The matching node has no children.
``lit`` The matching node is a literal like "abc", 12.
``sym`` The matching node must be a symbol (a bound
``sym`` The matching node must be a symbol (a bound
identifier).
``ident`` The matching node must be an identifier (an unbound
identifier).
@ -101,15 +101,15 @@ Predicate Meaning
``enumfield`` A symbol which is a field in an enumeration.
``forvar`` A for loop variable.
``label`` A label (used in ``block`` statements).
``nk*`` The matching AST must have the specified kind.
``nk*`` The matching AST must have the specified kind.
(Example: ``nkIfStmt`` denotes an ``if`` statement.)
``alias`` States that the marked parameter needs to alias
``alias`` States that the marked parameter needs to alias
with *some* other parameter.
``noalias`` States that *every* other parameter must not alias
with the marked parameter.
=================== =====================================================
Predicates that share their name with a keyword have to be escaped with
Predicates that share their name with a keyword have to be escaped with
backticks: `` `const` ``.
The ``alias`` and ``noalias`` predicates refer not only to the matching AST,
but also to every other bound parameter; syntactically they need to occur after
@ -151,14 +151,14 @@ constant folding, so the following does not work:
The reason is that the compiler already transformed the 1 into "1" for
the ``echo`` statement. However, a term rewriting macro should not change the
semantics anyway. In fact they can be deactivated with the ``--patterns:off``
command line option or temporarily with the ``patterns`` pragma.
command line option or temporarily with the ``patterns`` pragma.
The ``{}`` operator
~~~~~~~~~~~~~~~~~~~
A pattern expression can be bound to a pattern parameter via the ``expr{param}``
notation:
notation:
.. code-block:: nim
template t{(0|1|2){x}}(x: expr): expr = x+1
@ -176,7 +176,7 @@ The ``~`` operator is the **not** operator in patterns:
template t{x = (~x){y} and (~x){z}}(x, y, z: bool): stmt =
x = y
if x: x = z
var
a = false
b = true
@ -189,12 +189,12 @@ The ``*`` operator
~~~~~~~~~~~~~~~~~~
The ``*`` operator can *flatten* a nested binary expression like ``a & b & c``
to ``&(a, b, c)``:
to ``&(a, b, c)``:
.. code-block:: nim
var
calls = 0
proc `&&`(s: varargs[string]): string =
result = s[0]
for i in 1..len(s)-1: result.add s[i]
@ -211,8 +211,8 @@ to ``&(a, b, c)``:
The second operator of `*` must be a parameter; it is used to gather all the
arguments. The expression ``"my" && (space & "awe" && "some " ) && "concat"``
is passed to ``optConc`` in ``a`` as a special list (of kind ``nkArgList``)
which is flattened into a call expression; thus the invocation of ``optConc``
is passed to ``optConc`` in ``a`` as a special list (of kind ``nkArgList``)
which is flattened into a call expression; thus the invocation of ``optConc``
produces:
.. code-block:: nim
@ -245,7 +245,7 @@ all the arguments, but also the matched operators in reverse polish notation:
var x, y, z: Matrix
echo x + y * z - x
echo x + y * z - x
This passes the expression ``x + y * z - x`` to the ``optM`` macro as
an ``nnkArgList`` node containing::
@ -265,7 +265,7 @@ an ``nnkArgList`` node containing::
Parameters
----------
Parameters in a pattern are type checked in the matching process. If a
Parameters in a pattern are type checked in the matching process. If a
parameter is of the type ``varargs`` it is treated specially and it can match
0 or more arguments in the AST to be matched against:
@ -275,7 +275,7 @@ parameter is of the type ``varargs`` it is treated specially and it can match
((write|writeLine){w})(f, y)
}(x, y: varargs[expr], f: File, w: expr) =
w(f, x, y)
Example: Partial evaluation
@ -310,7 +310,7 @@ The following example shows how some form of hoisting can be implemented:
The ``optPeg`` template optimizes the case of a peg constructor with a string
literal, so that the pattern will only be parsed once at program startup and
stored in a global ``gl`` which is then re-used. This optimization is called
stored in a global ``gl`` which is then re-used. This optimization is called
hoisting because it is comparable to classical loop hoisting.
@ -343,7 +343,7 @@ ordinary routines.
Move optimization
-----------------
The ``call`` constraint is particularly useful to implement a move
The ``call`` constraint is particularly useful to implement a move
optimization for types that have copying semantics:
.. code-block:: nim

View file

@ -301,7 +301,7 @@ matches better than just ``T`` then.
proc sayHi(x: var int): string =
# matches a var int
result = $(x + 10)
proc sayHello(x: int) =
var m = x # a mutable version of x
echo sayHi(x) # matches the non-var version of sayHi

View file

@ -18,6 +18,6 @@ Example:
A type section begins with the ``type`` keyword. It contains multiple
type definitions. A type definition binds a type to a name. Type definitions
can be recursive or even mutually recursive. Mutually recursive types are only
possible within a single ``type`` section. Nominal types like ``objects``
possible within a single ``type`` section. Nominal types like ``objects``
or ``enums`` can only be defined in a ``type`` section.