preparations for 0.8.12

This commit is contained in:
Araq
2011-07-10 15:48:13 +02:00
parent 2565ff8dde
commit 5b96eaa953
81 changed files with 2355 additions and 826 deletions

View File

@@ -33,7 +33,11 @@ Core
* `threads <threads.html>`_
Nimrod thread support. **Note**: This is part of the system module. Do not
import it directly.
import it explicitely.
* `inboxes <inboxes.html>`_
Nimrod message passing support for threads. **Note**: This is part of the
system module. Do not import it explicitely.
* `macros <macros.html>`_
Contains the AST API and documentation of Nimrod for writing macros.

View File

@@ -473,10 +473,9 @@ Pre-defined integer types
These integer types are pre-defined:
``int``
the generic signed integer type; its size is platform dependent
(the compiler chooses the processor's fastest integer type).
This type should be used in general. An integer literal that has no type
suffix is of this type.
the generic signed integer type; its size is platform dependent and has the
same size as a pointer. This type should be used in general. An integer
literal that has no type suffix is of this type.
intXX
additional signed integer types of XX bits use this naming scheme
@@ -581,7 +580,7 @@ the ``+``, ``-``, ``*``, ``/`` operators for floating point types.
Boolean type
~~~~~~~~~~~~
The `boolean`:idx: type is named ``bool`` in Nimrod and can be one of the two
The `boolean`:idx: type is named `bool`:idx: in Nimrod and can be one of the two
pre-defined values ``true`` and ``false``. Conditions in while,
if, elif, when statements need to be of type bool.
@@ -670,7 +669,7 @@ use explicitely:
valueD = (3, "abc")
As can be seen from the example, it is possible to both specify a field's
ordinal value and its string value by using a tuple construction. It is also
ordinal value and its string value by using a tuple. It is also
possible to only specify one of them.
@@ -930,7 +929,7 @@ Reference and pointer types
~~~~~~~~~~~~~~~~~~~~~~~~~~~
References (similar to `pointers`:idx: in other programming languages) are a
way to introduce many-to-one relationships. This means different references can
point to and modify the same location in memory.
point to and modify the same location in memory (also called `aliasing`:idx:).
Nimrod distinguishes between `traced`:idx: and `untraced`:idx: references.
Untraced references are also called *pointers*. Traced references point to
@@ -1002,7 +1001,7 @@ pointer) as if it would have the type ``ptr TData``. Casting should only be
done if it is unavoidable: it breaks type safety and bugs can lead to
mysterious crashes.
**Note**: The example only works because the memory is initialized with zero
**Note**: The example only works because the memory is initialized to zero
(``alloc0`` instead of ``alloc`` does this): ``d.s`` is thus initialized to
``nil`` which the string assignment can handle. You need to know low level
details like this when mixing garbage collected data with unmanaged memory.
@@ -1055,7 +1054,7 @@ each other:
`inline`:idx:
The inline convention means the the caller should not call the procedure,
but inline its code directly. Note that Nimrod does not inline, but leaves
this to the C compiler. Thus it generates ``__inline`` procedures. This is
this to the C compiler; it generates ``__inline`` procedures. This is
only a hint for the compiler: it may completely ignore it and
it may inline procedures that are not marked as ``inline``.
@@ -1069,8 +1068,7 @@ each other:
`closure`:idx:
indicates that the procedure expects a context, a closure that needs
to be passed to the procedure. The calling convention ``nimcall`` is
compatible to ``closure``.
to be passed to the procedure.
`syscall`:idx:
The syscall convention is the same as ``__syscall`` in C. It is used for
@@ -1311,7 +1309,8 @@ algorithm returns true:
if b.kind == distinct and typeEquals(b.baseType, a): return true
return false
You can, however, define your own implicit converters:
The convertible relation can be relaxed by a user-defined type
`converter`:idx:.
.. code-block:: nimrod
converter toInt(x: char): int = result = ord(x)
@@ -1527,27 +1526,27 @@ given, control passes after the ``case`` statement.
To suppress the static error in the ordinal case an ``else`` part with a ``nil``
statement can be used.
As a special semantic extension, an expression in an ``of`` branch of a case
statement may evaluate to a set constructor; the set is then expanded into
a list of its elements:
.. code-block:: nimrod
const
SymChars: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
proc classify(s: string) =
case s[0]
of SymChars, '_': echo "an identifier"
of '0'..'9': echo "a number"
else: echo "other"
# is equivalent to:
proc classify(s: string) =
case s[0]
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': echo "an identifier"
of '0'..'9': echo "a number"
else: echo "other"
As a special semantic extension, an expression in an ``of`` branch of a case
statement may evaluate to a set constructor; the set is then expanded into
a list of its elements:
.. code-block:: nimrod
const
SymChars: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
proc classify(s: string) =
case s[0]
of SymChars, '_': echo "an identifier"
of '0'..'9': echo "a number"
else: echo "other"
# is equivalent to:
proc classify(s: string) =
case s[0]
of 'a'..'z', 'A'..'Z', '\x80'..'\xFF', '_': echo "an identifier"
of '0'..'9': echo "a number"
else: echo "other"
When statement
~~~~~~~~~~~~~~
@@ -2036,7 +2035,7 @@ Overloading of the subscript operator
The ``[]`` subscript operator for arrays/openarrays/sequences can be overloaded.
Overloading support is only possible if the first parameter has no type that
already supports the built-in ``[]`` notation. Currently the compiler
does not check this. XXX Multiple indexes
does not check this restriction.
Multi-methods
@@ -2612,8 +2611,8 @@ iterator in which case the overloading resolution takes place:
write(stdout, x) # not ambiguous: uses the module C's x
Messages
========
Compiler Messages
=================
The Nimrod compiler emits different kinds of messages: `hint`:idx:,
`warning`:idx:, and `error`:idx: messages. An *error* message is emitted if
@@ -3045,3 +3044,116 @@ This is only useful if the program is compiled as a dynamic library via the
``--app:lib`` command line option.
Threads
=======
Even though Nimrod's `thread`:idx: support and semantics are preliminary,
they should be quite usable already. 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 `inboxes <inboxes.html>`_ modules
for the thread API.
Nimrod'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,
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 will become the norm in the future.
Thread pragma
-------------
A proc that is executed as a new thread of execution should be marked by the
`thread pragma`:idx:. The compiler checks procedures marked as ``thread`` 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
allocated from different (thread local) heaps.
Since the semantic checking of threads requires a whole program analysis,
it is quite expensive and can be turned off with ``--threadanalysis:off`` to
improve compile times.
A thread proc is passed to ``createThread`` and invoked indirectly; so the
``thread`` pragma implies ``procvar``.
Actor model
-----------
Nimrod supports the `actor model`:idx: of concurrency natively:
.. code-block:: nimrod
type
TMsgKind = enum
mLine, mEof
TMsg = object {.pure, final.}
case k: TMsgKind
of mEof: nil
of mLine: data: string
var
thr: TThread[TMsg]
printedLines = 0
m: TMsg
proc print() {.thread.} =
while true:
var x = recv[TMsg]()
if x.k == mEof: break
echo x.data
discard atomicInc(printedLines)
createThread(thr, print)
var input = open("readme.txt")
while not endOfFile(input):
m.data = input.readLine()
thr.send(m)
close(input)
m.k = mEof
thr.send(m)
joinThread(thr)
echo printedLines
In the actor model threads communicate only over sending messages (`send`:idx:
and `recv`:idx: built-ins), not by sharing memory. Every thread has
an `inbox`:idx: that keeps incoming messages until the thread requests a new
message via the ``recv`` operation. The inbox is an unlimited FIFO queue.
In the above example the ``print`` thread also communicates with its
parent thread over the ``printedLines`` global variable. In general, it is
highly advisable to only read from globals, but not to write to them. In fact
a write to a global that contains GC'ed memory is always wrong, because it
violates the *no heap sharing restriction*:
.. code-block:: nimrod
var
global: string
t: TThread[string]
proc horrible() {.thread.} =
global = "string in thread local heap!"
createThread(t, horrible)
joinThread(t)
For the above code the compiler procudes "Warning: write to foreign heap". This
warning might become an error message in future versions of the compiler.
Creating a thread is an expensive operation, because a new stack and heap needs
to be created for the thread. It is therefore highly advisable that a thread
handles a large amount of work. Nimrod prefers *coarse grained*
over *fine grained* concurrency.
Threads and exceptions
----------------------
The interaction between threads and exception is simple: A *handled* exception
in one thread cannot affect any other thread. However, an *unhandled*
exception in one thread terminates the whole *process*!

View File

@@ -28,7 +28,7 @@ Compiler Usage
Command line switches
---------------------
Basis command line switches are:
Basic command line switches are:
.. include:: basicopt.txt
@@ -57,11 +57,11 @@ configuration file that is read automatically. This specific file has to
be in the same directory as the project and be of the same name, except
that its extension should be ``.cfg``.
Command line settings have priority over configuration file settings.
The default build of a project is a `debug build`:idx:. To compile a
`release build`:idx: define the ``release`` symbol::
Command line settings have priority over configuration file settings.
The default build of a project is a `debug build`:idx:. To compile a
`release build`:idx: define the ``release`` symbol::
nimrod c -d:release myproject.nim
@@ -75,17 +75,17 @@ However, the generated C code is not platform independent. C code generated for
Linux does not compile on Windows, for instance. The comment on top of the
C file lists the OS, CPU and CC the file has been compiled for.
Cross compilation
=================
To `cross compile`:idx:, use for example::
nimrod c --cpu:i386 --os:linux --compile_only --gen_script myproject.nim
Then move the C code and the compile script ``compile_myproject.sh`` to your
Linux i386 machine and run the script.
Cross compilation
=================
To `cross compile`:idx:, use for example::
nimrod c --cpu:i386 --os:linux --compile_only --gen_script myproject.nim
Then move the C code and the compile script ``compile_myproject.sh`` to your
Linux i386 machine and run the script.
DLL generation
==============
@@ -101,6 +101,8 @@ To link against ``nimrtl.dll`` use the command::
nimrod c -d:useNimRtl myprog.nim
**Note**: Currently the creation of ``nimrtl.dll`` with thread support has
never been tested and is unlikely to work!
Additional Features
@@ -146,49 +148,49 @@ encloses the header file in ``""`` in the generated C code.
**Note**: This will not work for the LLVM backend.
Compile pragma
--------------
The `compile`:idx: pragma can be used to compile and link a C/C++ source file
with the project:
Compile pragma
--------------
The `compile`:idx: pragma can be used to compile and link a C/C++ source file
with the project:
.. code-block:: Nimrod
{.compile: "myfile.cpp".}
**Note**: Nimrod computes a CRC checksum and only recompiles the file if it
has changed. You can use the ``-f`` command line option to force recompilation
of the file.
Link pragma
-----------
The `link`:idx: pragma can be used to link an additional file with the project:
{.compile: "myfile.cpp".}
**Note**: Nimrod computes a CRC checksum and only recompiles the file if it
has changed. You can use the ``-f`` command line option to force recompilation
of the file.
Link pragma
-----------
The `link`:idx: pragma can be used to link an additional file with the project:
.. code-block:: Nimrod
{.link: "myfile.o".}
Emit pragma
-----------
The `emit`:idx: pragma can be used to directly affect the output of the
compiler's code generator. So it makes your code unportable to other code
generators/backends. Its usage is highly discouraged! However, it can be
extremely useful for interfacing with C++ or Objective C code.
Example:
{.link: "myfile.o".}
Emit pragma
-----------
The `emit`:idx: pragma can be used to directly affect the output of the
compiler's code generator. So it makes your code unportable to other code
generators/backends. Its usage is highly discouraged! However, it can be
extremely useful for interfacing with C++ or Objective C code.
Example:
.. code-block:: Nimrod
{.emit: """
static int cvariable = 420;
""".}
proc embedsC() {.pure.} =
var nimrodVar = 89
# use backticks to access Nimrod symbols within an emit section:
{.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimrodVar`);""".}
embedsC()
{.emit: """
static int cvariable = 420;
""".}
proc embedsC() {.pure.} =
var nimrodVar = 89
# use backticks to access Nimrod symbols within an emit section:
{.emit: """fprintf(stdout, "%d\n", cvariable + (int)`nimrodVar`);""".}
embedsC()
LineDir option
--------------
@@ -229,22 +231,22 @@ The `volatile`:idx: pragma is for variables only. It declares the variable as
``volatile``, whatever that means in C/C++.
**Note**: This pragma will not exist for the LLVM backend.
Nimrod interactive mode
=======================
The Nimrod compiler supports an `interactive mode`:idx:. This is also known as
a `REPL`:idx: (*read eval print loop*). If Nimrod has been built with the
``-d:useGnuReadline`` switch, it uses the GNU readline library for terminal
input management. To start Nimrod in interactive mode use the command
``nimrod i``. To quit use the ``quit()`` command. To determine whether an input
line is an incomplete statement to be continued these rules are used:
1. The line ends with ``[-+*/\\<>!\?\|%&$@~,;:=#^]\s*$``.
2. The line starts with a space (indentation).
3. The line is within a triple quoted string literal. However, the detection
does not work if the line contains more than one ``"""``.
Nimrod interactive mode
=======================
The Nimrod compiler supports an `interactive mode`:idx:. This is also known as
a `REPL`:idx: (*read eval print loop*). If Nimrod has been built with the
``-d:useGnuReadline`` switch, it uses the GNU readline library for terminal
input management. To start Nimrod in interactive mode use the command
``nimrod i``. To quit use the ``quit()`` command. To determine whether an input
line is an incomplete statement to be continued these rules are used:
1. The line ends with ``[-+*/\\<>!\?\|%&$@~,;:=#^]\s*$``.
2. The line starts with a space (indentation).
3. The line is within a triple quoted string literal. However, the detection
does not work if the line contains more than one ``"""``.
Debugging with Nimrod
@@ -294,24 +296,24 @@ However it is not efficient to do:
var s = varA # assignment has to copy the whole string into a new buffer!
The compiler optimizes string case statements: A hashing scheme is used for them
if several different string constants are used. So code like this is reasonably
efficient:
.. code-block:: Nimrod
case normalize(k.key)
of "name": c.name = v
of "displayname": c.displayName = v
of "version": c.version = v
of "os": c.oses = split(v, {';'})
of "cpu": c.cpus = split(v, {';'})
of "authors": c.authors = split(v, {';'})
of "description": c.description = v
of "app":
case normalize(v)
of "console": c.app = appConsole
of "gui": c.app = appGUI
else: quit(errorStr(p, "expected: console or gui"))
of "license": c.license = UnixToNativePath(k.value)
if several different string constants are used. So code like this is reasonably
efficient:
.. code-block:: Nimrod
case normalize(k.key)
of "name": c.name = v
of "displayname": c.displayName = v
of "version": c.version = v
of "os": c.oses = split(v, {';'})
of "cpu": c.cpus = split(v, {';'})
of "authors": c.authors = split(v, {';'})
of "description": c.description = v
of "app":
case normalize(v)
of "console": c.app = appConsole
of "gui": c.app = appGUI
else: quit(errorStr(p, "expected: console or gui"))
of "license": c.license = UnixToNativePath(k.value)
else: quit(errorStr(p, "unknown variable: " & k.key))

File diff suppressed because it is too large Load Diff