doc updates; fixes 'inc' for 'char'
This commit is contained in:
parent
165619552a
commit
edc4940c26
8 changed files with 97 additions and 191 deletions
|
|
@ -14,7 +14,7 @@ deprecated pragma
|
|||
|
||||
The deprecated pragma is used to mark a symbol as deprecated:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
proc p() {.deprecated.}
|
||||
var x {.deprecated.}: char
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ It can also be used as a statement. Then it takes a list of *renamings*. The
|
|||
upcoming ``nimfix`` tool can automatically update the code and perform these
|
||||
renamings:
|
||||
|
||||
.. code-block:: nimrod
|
||||
.. code-block:: nim
|
||||
type
|
||||
File = object
|
||||
Stream = ref object
|
||||
|
|
@ -78,7 +78,7 @@ as helpers for macros.
|
|||
|
||||
noReturn pragma
|
||||
---------------
|
||||
The ``noreturn`` pragma is used to mark a proc that never returns.
|
||||
The ``noreturn`` pragma is used to mark a proc that never returns.
|
||||
|
||||
|
||||
acyclic pragma
|
||||
|
|
@ -122,25 +122,25 @@ shallow pragma
|
|||
--------------
|
||||
The ``shallow`` pragma affects the semantics of a type: The compiler is
|
||||
allowed to make a shallow copy. This can cause serious semantic issues and
|
||||
break memory safety! However, it can speed up assignments considerably,
|
||||
because the semantics of Nim require deep copying of sequences and strings.
|
||||
break memory safety! However, it can speed up assignments considerably,
|
||||
because the semantics of Nim require deep copying of sequences and strings.
|
||||
This can be expensive, especially if sequences are used to build a tree
|
||||
structure:
|
||||
structure:
|
||||
|
||||
.. code-block:: nim
|
||||
type
|
||||
NodeKind = enum nkLeaf, nkInner
|
||||
Node {.final, shallow.} = object
|
||||
case kind: NodeKind
|
||||
of nkLeaf:
|
||||
of nkLeaf:
|
||||
strVal: string
|
||||
of nkInner:
|
||||
of nkInner:
|
||||
children: seq[Node]
|
||||
|
||||
|
||||
pure pragma
|
||||
-----------
|
||||
An object type can be marked with the ``pure`` pragma so that its type
|
||||
An object type can be marked with the ``pure`` pragma so that its type
|
||||
field which is used for runtime type identification is omitted. This used to be
|
||||
necessary for binary compatibility with other compiled languages.
|
||||
|
||||
|
|
@ -163,12 +163,12 @@ error pragma
|
|||
------------
|
||||
The ``error`` pragma is used to make the compiler output an error message
|
||||
with the given content. Compilation does not necessarily abort after an error
|
||||
though.
|
||||
though.
|
||||
|
||||
The ``error`` pragma can also be used to
|
||||
annotate a symbol (like an iterator or proc). The *usage* of the symbol then
|
||||
triggers a compile-time error. This is especially useful to rule out that some
|
||||
operation is valid due to overloading and type conversions:
|
||||
operation is valid due to overloading and type conversions:
|
||||
|
||||
.. code-block:: nim
|
||||
## check that underlying int values are compared and not the pointers:
|
||||
|
|
@ -201,7 +201,7 @@ The ``line`` pragma can be used to affect line information of the annotated
|
|||
statement as seen in stack backtraces:
|
||||
|
||||
.. code-block:: nim
|
||||
|
||||
|
||||
template myassert*(cond: expr, msg = "") =
|
||||
if not cond:
|
||||
# change run-time line information of the 'raise' statement:
|
||||
|
|
@ -215,26 +215,26 @@ If the ``line`` pragma is used with a parameter, the parameter needs be a
|
|||
|
||||
linearScanEnd pragma
|
||||
--------------------
|
||||
The ``linearScanEnd`` pragma can be used to tell the compiler how to
|
||||
The ``linearScanEnd`` pragma can be used to tell the compiler how to
|
||||
compile a Nim `case`:idx: statement. Syntactically it has to be used as a
|
||||
statement:
|
||||
|
||||
.. code-block:: nim
|
||||
case myInt
|
||||
of 0:
|
||||
of 0:
|
||||
echo "most common case"
|
||||
of 1:
|
||||
of 1:
|
||||
{.linearScanEnd.}
|
||||
echo "second most common case"
|
||||
of 2: echo "unlikely: use branch table"
|
||||
else: echo "unlikely too: use branch table for ", myInt
|
||||
|
||||
In the example, the case branches ``0`` and ``1`` are much more common than
|
||||
the other cases. Therefore the generated assembler code should test for these
|
||||
values first, so that the CPU's branch predictor has a good chance to succeed
|
||||
In the example, the case branches ``0`` and ``1`` are much more common than
|
||||
the other cases. Therefore the generated assembler code should test for these
|
||||
values first, so that the CPU's branch predictor has a good chance to succeed
|
||||
(avoiding an expensive CPU pipeline stall). The other cases might be put into a
|
||||
jump table for O(1) overhead, but at the cost of a (very likely) pipeline
|
||||
stall.
|
||||
stall.
|
||||
|
||||
The ``linearScanEnd`` pragma should be put into the last branch that should be
|
||||
tested against via linear scanning. If put into the last branch of the
|
||||
|
|
@ -243,8 +243,8 @@ whole ``case`` statement, the whole ``case`` statement uses linear scanning.
|
|||
|
||||
computedGoto pragma
|
||||
-------------------
|
||||
The ``computedGoto`` pragma can be used to tell the compiler how to
|
||||
compile a Nim `case`:idx: in a ``while true`` statement.
|
||||
The ``computedGoto`` pragma can be used to tell the compiler how to
|
||||
compile a Nim `case`:idx: in a ``while true`` statement.
|
||||
Syntactically it has to be used as a statement inside the loop:
|
||||
|
||||
.. code-block:: nim
|
||||
|
|
@ -278,21 +278,21 @@ Syntactically it has to be used as a statement inside the loop:
|
|||
of enumE:
|
||||
break
|
||||
inc(pc)
|
||||
|
||||
|
||||
vm()
|
||||
|
||||
As the example shows ``computedGoto`` is mostly useful for interpreters. If
|
||||
the underlying backend (C compiler) does not support the computed goto
|
||||
the underlying backend (C compiler) does not support the computed goto
|
||||
extension the pragma is simply ignored.
|
||||
|
||||
|
||||
unroll pragma
|
||||
-------------
|
||||
The ``unroll`` pragma can be used to tell the compiler that it should unroll
|
||||
a `for`:idx: or `while`:idx: loop for runtime efficiency:
|
||||
a `for`:idx: or `while`:idx: loop for runtime efficiency:
|
||||
|
||||
.. code-block:: nim
|
||||
proc searchChar(s: string, c: char): int =
|
||||
proc searchChar(s: string, c: char): int =
|
||||
for i in 0 .. s.high:
|
||||
{.unroll: 4.}
|
||||
if s[i] == c: return i
|
||||
|
|
@ -440,7 +440,7 @@ Example:
|
|||
|
||||
Please note that if a callable symbol is never used in this scenario, its body
|
||||
will never be compiled. This is the default behavior leading to best compilation
|
||||
times, but if exhaustive compilation of all definitions is required, using
|
||||
times, but if exhaustive compilation of all definitions is required, using
|
||||
``nim check`` provides this option as well.
|
||||
|
||||
Example:
|
||||
|
|
@ -461,9 +461,9 @@ Example:
|
|||
pragma pragma
|
||||
-------------
|
||||
|
||||
The ``pragma`` pragma can be used to declare user defined pragmas. This is
|
||||
useful because Nim's templates and macros do not affect pragmas. User
|
||||
defined pragmas are in a different module-wide scope than all other symbols.
|
||||
The ``pragma`` pragma can be used to declare user defined pragmas. This is
|
||||
useful because Nim's templates and macros do not affect pragmas. User
|
||||
defined pragmas are in a different module-wide scope than all other symbols.
|
||||
They cannot be imported from a module.
|
||||
|
||||
Example:
|
||||
|
|
@ -473,8 +473,8 @@ Example:
|
|||
{.pragma: rtl, exportc, dynlib, cdecl.}
|
||||
else:
|
||||
{.pragma: rtl, importc, dynlib: "client.dll", cdecl.}
|
||||
|
||||
proc p*(a, b: int): int {.rtl.} =
|
||||
|
||||
proc p*(a, b: int): int {.rtl.} =
|
||||
result = a+b
|
||||
|
||||
In the example a new pragma named ``rtl`` is introduced that either imports
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
Threads
|
||||
=======
|
||||
|
||||
To enable thread support the ``--threads:on`` command line switch needs to
|
||||
be used. The ``system`` module then contains several threading primitives.
|
||||
See the `threads <threads.html>`_ and `channels <channels.html>`_ modules
|
||||
To enable thread support the ``--threads:on`` command line switch needs to
|
||||
be used. The ``system`` module then contains several threading primitives.
|
||||
See the `threads <threads.html>`_ and `channels <channels.html>`_ modules
|
||||
for the low level thread API. There are also high level parallelism constructs
|
||||
available. See `spawn`_ for further details.
|
||||
|
||||
Nim's memory model for threads is quite different than that of other common
|
||||
programming languages (C, Pascal, Java): Each thread has its own (garbage
|
||||
collected) heap and sharing of memory is restricted to global variables. This
|
||||
helps to prevent race conditions. GC efficiency is improved quite a lot,
|
||||
programming languages (C, Pascal, Java): Each thread has its own (garbage
|
||||
collected) heap and sharing of memory is restricted to global variables. This
|
||||
helps to prevent race conditions. GC efficiency is improved quite a lot,
|
||||
because the GC never has to stop other threads and see what they reference.
|
||||
Memory allocation requires no lock at all! This design easily scales to massive
|
||||
multicore processors that are becoming the norm.
|
||||
|
|
@ -22,10 +22,10 @@ Thread pragma
|
|||
A proc that is executed as a new thread of execution should be marked by the
|
||||
``thread`` pragma for reasons of readability. The compiler checks for
|
||||
violations of the `no heap sharing restriction`:idx:\: This restriction implies
|
||||
that it is invalid to construct a data structure that consists of memory
|
||||
that it is invalid to construct a data structure that consists of memory
|
||||
allocated from different (thread local) heaps.
|
||||
|
||||
A thread proc is passed to ``createThread`` or ``spawn`` and invoked
|
||||
A thread proc is passed to ``createThread`` or ``spawn`` and invoked
|
||||
indirectly; so the ``thread`` pragma implies ``procvar``.
|
||||
|
||||
|
||||
|
|
@ -34,7 +34,7 @@ GC safety
|
|||
|
||||
We call a proc ``p`` `GC safe`:idx: when it doesn't access any global variable
|
||||
that contains GC'ed memory (``string``, ``seq``, ``ref`` or a closure) either
|
||||
directly or indirectly through a call to a GC unsafe proc.
|
||||
directly or indirectly through a call to a GC unsafe proc.
|
||||
|
||||
The `gcsafe`:idx: annotation can be used to mark a proc to be gcsafe,
|
||||
otherwise this property is inferred by the compiler. Note that ``noSideEfect``
|
||||
|
|
@ -45,10 +45,9 @@ contain a ``ref`` or ``closure`` type. This enforces
|
|||
the *no heap sharing restriction*.
|
||||
|
||||
Routines that are imported from C are always assumed to be ``gcsafe``.
|
||||
To enable the GC-safety checking the ``--threadAnalysis:on`` command line
|
||||
switch must be used. This is a temporary workaround to ease the porting effort
|
||||
from old code to the new threading model. In the future the thread analysis
|
||||
will always be performed.
|
||||
To disable the GC-safety checking the ``--threadAnalysis:off`` command line
|
||||
switch can be used. This is a temporary workaround to ease the porting effort
|
||||
from old code to the new threading model.
|
||||
|
||||
|
||||
Future directions:
|
||||
|
|
@ -59,13 +58,13 @@ Future directions:
|
|||
Threadvar pragma
|
||||
----------------
|
||||
|
||||
A global variable can be marked with the ``threadvar`` pragma; it is
|
||||
A global variable can be marked with the ``threadvar`` pragma; it is
|
||||
a `thread-local`:idx: variable then:
|
||||
|
||||
.. code-block:: nim
|
||||
var checkpoints* {.threadvar.}: seq[string]
|
||||
|
||||
Due to implementation restrictions thread local variables cannot be
|
||||
Due to implementation restrictions thread local variables cannot be
|
||||
initialized within the ``var`` section. (Every thread local variable needs to
|
||||
be replicated at thread creation.)
|
||||
|
||||
|
|
@ -73,7 +72,7 @@ be replicated at thread creation.)
|
|||
Threads and exceptions
|
||||
----------------------
|
||||
|
||||
The interaction between threads and exceptions is simple: A *handled* exception
|
||||
The interaction between threads and exceptions is simple: A *handled* exception
|
||||
in one thread cannot affect any other thread. However, an *unhandled* exception
|
||||
in one thread terminates the whole *process*!
|
||||
|
||||
|
|
@ -82,7 +81,7 @@ in one thread terminates the whole *process*!
|
|||
Parallel & Spawn
|
||||
================
|
||||
|
||||
Nim has two flavors of parallelism:
|
||||
Nim has two flavors of parallelism:
|
||||
1) `Structured`:idx: parallelism via the ``parallel`` statement.
|
||||
2) `Unstructured`:idx: parallelism via the standalone ``spawn`` statement.
|
||||
|
||||
|
|
@ -115,7 +114,7 @@ Spawn statement
|
|||
|
||||
proc processLine(line: string) =
|
||||
discard "do some heavy lifting here"
|
||||
|
||||
|
||||
for x in lines("myinput.txt"):
|
||||
spawn processLine(x)
|
||||
sync()
|
||||
|
|
@ -144,7 +143,7 @@ wait on multiple flow variables at the same time:
|
|||
|
||||
.. code-block:: nim
|
||||
import threadpool, ...
|
||||
|
||||
|
||||
# wait until 2 out of 3 servers received the update:
|
||||
proc main =
|
||||
var responses = newSeq[RawFlowVar](3)
|
||||
|
|
@ -203,8 +202,7 @@ restrictions / changes:
|
|||
the ``parallel`` section. This is called the *immutability check*. Currently
|
||||
it is not specified what exactly "complex location" means. We need to make
|
||||
this an optimization!
|
||||
* Every array access has to be provably within bounds. This is called
|
||||
* Every array access has to be provably within bounds. This is called
|
||||
the *bounds check*.
|
||||
* Slices are optimized so that no copy is performed. This optimization is not
|
||||
yet performed for ordinary slices outside of a ``parallel`` section. Slices
|
||||
are also special in that they currently do not support negative indexes!
|
||||
yet performed for ordinary slices outside of a ``parallel`` section.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue