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

0
compiler/ccgthreadvars.nim Normal file → Executable file
View File

View File

@@ -52,12 +52,12 @@ proc CloseScope*(tab: var TSymTab) =
if (tab.tos > len(tab.stack)): InternalError("CloseScope")
var it: TTabIter
var s = InitTabIter(it, tab.stack[tab.tos-1])
while s != nil:
while s != nil:
if sfForward in s.flags:
LocalError(s.info, errImplOfXexpected, getSymRepr(s))
elif ({sfUsed, sfInInterface} * s.flags == {}) and
(optHints in s.options): # BUGFIX: check options in s!
if not (s.kind in {skForVar, skParam, skMethod, skUnknown}):
elif {sfUsed, sfInInterface} * s.flags == {} and optHints in s.options:
# BUGFIX: check options in s!
if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
Message(s.info, hintXDeclaredButNotUsed, getSymRepr(s))
s = NextIter(it, tab.stack[tab.tos-1])
astalgo.rawCloseScope(tab)

View File

@@ -522,6 +522,7 @@ proc rawMessage*(msg: TMsgKind, args: openarray[string]) =
of warnMin..warnMax:
if not (optWarns in gOptions): return
if not (msg in gNotes): return
writeContext(unknownLineInfo())
frmt = rawWarningFormat
inc(gWarnCounter)
of hintMin..hintMax:
@@ -552,6 +553,7 @@ proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
lastError = info
of warnMin..warnMax:
ignoreMsg = optWarns notin gOptions or msg notin gNotes
if not ignoreMsg: writeContext(info)
frmt = posWarningFormat
inc(gWarnCounter)
of hintMin..hintMax:

View File

@@ -1,7 +1,7 @@
#
#
# The Nimrod Compiler
# (c) Copyright 2010 Andreas Rumpf
# (c) Copyright 2011 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
@@ -15,6 +15,6 @@ const
defaultAsmMarkerSymbol* = '!'
VersionMajor* = 0
VersionMinor* = 8
VersionPatch* = 11
VersionPatch* = 12
VersionAsString* = $VersionMajor & "." & $VersionMinor & "." & $VersionPatch

View File

@@ -19,6 +19,8 @@ proc instantiateGenericParamList(c: PContext, n: PNode, pt: TIdTable) =
var q = a.sym
if not (q.typ.kind in {tyTypeDesc, tyGenericParam}): continue
var s = newSym(skType, q.name, getCurrOwner())
s.info = q.info
incl(s.flags, sfUsed)
var t = PType(IdTableGet(pt, q.typ))
if t == nil:
LocalError(a.info, errCannotInstantiateX, s.name.s)

View File

@@ -205,7 +205,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
incl(result.flags, sfGlobal)
else:
result = semIdentWithPragma(c, kind, n, {})
proc semVar(c: PContext, n: PNode): PNode =
var b: PNode
result = copyNode(n)

36
compiler/semthreads.nim Normal file → Executable file
View File

@@ -112,7 +112,7 @@ proc analyseSym(c: PProcCtx, n: PNode): TThreadOwner =
if sfGlobal in v.flags:
if sfThreadVar in v.flags:
result = toMine
elif containsTyRef(v.typ):
elif containsGarbageCollectedRef(v.typ):
result = toTheirs
of skTemp, skForVar: result = toNil
of skConst: result = toMine
@@ -126,7 +126,8 @@ proc analyseSym(c: PProcCtx, n: PNode): TThreadOwner =
proc lvalueSym(n: PNode): PNode =
result = n
while result.kind in {nkDotExpr, nkBracketExpr, nkDerefExpr, nkHiddenDeref}:
while result.kind in {nkDotExpr, nkCheckedFieldExpr,
nkBracketExpr, nkDerefExpr, nkHiddenDeref}:
result = result.sons[0]
proc writeAccess(c: PProcCtx, n: PNode, owner: TThreadOwner) =
@@ -138,7 +139,18 @@ proc writeAccess(c: PProcCtx, n: PNode, owner: TThreadOwner) =
var lastOwner = analyseSym(c, a)
case lastOwner
of toNil:
c.mapping[v.id] = owner # fine, toNil can be overwritten
# fine, toNil can be overwritten
var newOwner: TThreadOwner
if sfGlobal in v.flags:
newOwner = owner
elif containsTyRef(v.typ):
# ``var local = gNode`` --> ok, but ``local`` is theirs!
newOwner = owner
else:
# ``var local = gString`` --> string copy: ``local`` is mine!
newOwner = toMine
# XXX BUG what if the tuple contains both ``tyRef`` and ``tyString``?
c.mapping[v.id] = newOwner
of toVoid, toUndefined: InternalError(n.info, "writeAccess")
of toTheirs: Message(n.info, warnWriteToForeignHeap)
of toMine:
@@ -146,7 +158,7 @@ proc writeAccess(c: PProcCtx, n: PNode, owner: TThreadOwner) =
Message(n.info, warnDifferentHeaps)
else:
# we could not backtrack to a concrete symbol, but that's fine:
var lastOwner = analyseSym(c, n)
var lastOwner = analyse(c, n)
case lastOwner
of toNil: nil # fine, toNil can be overwritten
of toVoid, toUndefined: InternalError(n.info, "writeAccess")
@@ -178,7 +190,7 @@ proc analyseCall(c: PProcCtx, n: PNode): TThreadOwner =
pushInfoContext(n.info)
result = analyse(newCtx, prc.ast.sons[codePos])
if prc.ast.sons[codePos].kind == nkEmpty and
{sfNoSideEffect, sfThread} * prc.flags == {}:
{sfNoSideEffect, sfThread, sfImportc} * prc.flags == {}:
Message(n.info, warnAnalysisLoophole, renderTree(n))
if prc.typ.sons[0] != nil:
if prc.ast.len > resultPos:
@@ -228,7 +240,7 @@ template aggregateOwner(result, ana: expr) =
var a = ana # eval once
if result != a:
if result == toNil: result = a
else: Message(n.info, warnDifferentHeaps)
elif a != toNil: Message(n.info, warnDifferentHeaps)
proc analyseArgs(c: PProcCtx, n: PNode, start = 1) =
for i in start..n.len-1: discard analyse(c, n[i])
@@ -241,7 +253,14 @@ proc analyseOp(c: PProcCtx, n: PNode): TThreadOwner =
else:
var prc = n[0].sym
case prc.magic
of mNone: result = analyseCall(c, n)
of mNone:
if sfSystemModule in prc.owner.flags:
# System module proc does no harm :-)
analyseArgs(c, n)
if prc.typ.sons[0] == nil: result = toVoid
else: result = toNil
else:
result = analyseCall(c, n)
of mNew, mNewFinalize, mNewSeq, mSetLengthStr, mSetLengthSeq,
mAppendSeqElem, mReset, mAppendStrCh, mAppendStrStr:
writeAccess(c, n[1], toMine)
@@ -260,8 +279,7 @@ proc analyseOp(c: PProcCtx, n: PNode): TThreadOwner =
analyseArgs(c, n)
result = toMine
else:
# don't recurse, but check args; NOTE: This is essential that
# ``mCreateThread`` is handled here to avoid the recursion
# don't recurse, but check args:
analyseArgs(c, n)
if prc.typ.sons[0] == nil: result = toVoid
else: result = toNil

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

0
examples/0mq/client.nim Normal file → Executable file
View File

0
examples/0mq/server.nim Normal file → Executable file
View File

View File

@@ -185,6 +185,8 @@ if [ $# -eq 1 ] ; then
chmod 644 $libdir/system/gc.nim
cp lib/system/hti.nim $libdir/system/hti.nim || exit 1
chmod 644 $libdir/system/hti.nim
cp lib/system/inboxes.nim $libdir/system/inboxes.nim || exit 1
chmod 644 $libdir/system/inboxes.nim
cp lib/system/inclrtl.nim $libdir/system/inclrtl.nim || exit 1
chmod 644 $libdir/system/inclrtl.nim
cp lib/system/mmdisp.nim $libdir/system/mmdisp.nim || exit 1
@@ -197,6 +199,8 @@ if [ $# -eq 1 ] ; then
chmod 644 $libdir/system/sets.nim
cp lib/system/sysio.nim $libdir/system/sysio.nim || exit 1
chmod 644 $libdir/system/sysio.nim
cp lib/system/syslocks.nim $libdir/system/syslocks.nim || exit 1
chmod 644 $libdir/system/syslocks.nim
cp lib/system/sysstr.nim $libdir/system/sysstr.nim || exit 1
chmod 644 $libdir/system/sysstr.nim
cp lib/system/threads.nim $libdir/system/threads.nim || exit 1
@@ -237,8 +241,6 @@ if [ $# -eq 1 ] ; then
chmod 644 $libdir/pure/json.nim
cp lib/pure/lexbase.nim $libdir/pure/lexbase.nim || exit 1
chmod 644 $libdir/pure/lexbase.nim
cp lib/pure/logging.nim $libdir/pure/logging.nim || exit 1
chmod 644 $libdir/pure/logging.nim
cp lib/pure/marshal.nim $libdir/pure/marshal.nim || exit 1
chmod 644 $libdir/pure/marshal.nim
cp lib/pure/math.nim $libdir/pure/math.nim || exit 1
@@ -301,8 +303,6 @@ if [ $# -eq 1 ] ; then
chmod 644 $libdir/pure/xmlparser.nim
cp lib/pure/xmltree.nim $libdir/pure/xmltree.nim || exit 1
chmod 644 $libdir/pure/xmltree.nim
cp lib/pure/yamllexer.nim $libdir/pure/yamllexer.nim || exit 1
chmod 644 $libdir/pure/yamllexer.nim
cp lib/impure/db_mysql.nim $libdir/impure/db_mysql.nim || exit 1
chmod 644 $libdir/impure/db_mysql.nim
cp lib/impure/db_postgres.nim $libdir/impure/db_postgres.nim || exit 1

16
lib/core/typeinfo.nim Normal file → Executable file
View File

@@ -45,8 +45,8 @@ type
TAny* = object {.pure.} ## can represent any nimrod value; NOTE: the wrapped
## value can be modified with its wrapper! This means
## that ``TAny`` keeps a non-traced pointer to its
## wrapped value and MUST not live longer than its
## wrapped value.
## wrapped value and **must not** live longer than
## its wrapped value.
value: pointer
rawType: PNimType
@@ -97,7 +97,7 @@ proc newAny(value: pointer, rawType: PNimType): TAny =
proc toAny*[T](x: var T): TAny {.inline.} =
## constructs a ``TAny`` object from `x`. This captures `x`'s address, so
## `x` can be modified with its ``TAny`` wrapper! The client needs to ensure
## that the wrapper DOES NOT live longer than `x`!
## that the wrapper **does not** live longer than `x`!
result.value = addr(x)
result.rawType = cast[PNimType](getTypeInfo(x))
@@ -106,7 +106,7 @@ proc kind*(x: TAny): TAnyKind {.inline.} =
result = TAnyKind(ord(x.rawType.kind))
proc baseTypeKind*(x: TAny): TAnyKind {.inline.} =
## get the base type's kind; akNone is returned if `x` has no base type.
## get the base type's kind; ``akNone`` is returned if `x` has no base type.
if x.rawType.base != nil:
result = TAnyKind(ord(x.rawType.base.kind))
@@ -586,13 +586,13 @@ when isMainModule:
block:
# gimme a new scope dammit
var myarr: array[0..4, array[0..4, string]] = [
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
var myarr: array[0..4, array[0..4, string]] = [
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
["test", "1", "2", "3", "4"], ["test", "1", "2", "3", "4"],
["test", "1", "2", "3", "4"]]
var m = toAny(myArr)
for i in 0 .. m.len-1:
for j in 0 .. m[i].len-1:
echo getString(m[i][j])

View File

@@ -287,7 +287,7 @@ proc replacef*(s: string, sub: TRegEx, by: string): string =
## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
##
## .. code-block:: nimrod
## "var1=key; var2=key2".replace(re"(\w+)'='(\w+)", "$1<-$2$2")
## "var1=key; var2=key2".replacef(re"(\w+)'='(\w+)", "$1<-$2$2")
##
## Results in:
##

0
lib/prelude.nim Normal file → Executable file
View File

4
lib/pure/collections/intsets.nim Normal file → Executable file
View File

@@ -9,8 +9,8 @@
## The ``intsets`` module implements an efficient int set implemented as a
## sparse bit set.
## **Note**: Since Nimrod does not allow the assignment operator to be
## overloaded, ``=`` for int sets performs some rather meaningless shallow
## **Note**: Since Nimrod currently does not allow the assignment operator to
## be overloaded, ``=`` for int sets performs some rather meaningless shallow
## copy.
import

0
lib/pure/collections/queues.nim Normal file → Executable file
View File

6
lib/pure/collections/sets.nim Normal file → Executable file
View File

@@ -9,9 +9,9 @@
## The ``sets`` module implements an efficient hash set and ordered hash set.
##
## Note: The data types declared here have *value semantics*: This means that
## ``=`` performs a copy of the hash table. If you are overly concerned with
## efficiency and know what you do (!), you can define the symbol
## **Note**: The data types declared here have *value semantics*: This means
## that ``=`` performs a copy of the hash table. If you are overly concerned
## with efficiency and know what you do (!), you can define the symbol
## ``shallowADT`` to compile a version that uses shallow copies instead.
import

8
lib/pure/collections/tables.nim Normal file → Executable file
View File

@@ -10,9 +10,9 @@
## The ``tables`` module implements an efficient hash table that is
## a mapping from keys to values.
##
## Note: The data types declared here have *value semantics*: This means that
## ``=`` performs a copy of the hash table. If you are overly concerned with
## efficiency and know what you do (!), you can define the symbol
## **Note:** The data types declared here have *value semantics*: This means
## that ``=`` performs a copy of the hash table. If you are overly concerned
## with efficiency and know what you do (!), you can define the symbol
## ``shallowADT`` to compile a version that uses shallow copies instead.
import
@@ -27,7 +27,7 @@ type
TSlotEnum = enum seEmpty, seFilled, seDeleted
TKeyValuePair[A, B] = tuple[slot: TSlotEnum, key: A, val: B]
TKeyValuePairSeq[A, B] = seq[TKeyValuePair[A, B]]
TTable* {.final, myShallow.}[A, B] = object
TTable* {.final, myShallow.}[A, B] = object ## generic hash table
data: TKeyValuePairSeq[A, B]
counter: int

View File

@@ -366,10 +366,12 @@ when defined(Windows) and not defined(useNimRtl):
result.id = procInfo.dwProcessID
proc close(p: PProcess) =
discard CloseHandle(p.inputHandle)
discard CloseHandle(p.outputHandle)
discard CloseHandle(p.errorHandle)
discard CloseHandle(p.FProcessHandle)
when false:
# somehow this does not work on Windows:
discard CloseHandle(p.inputHandle)
discard CloseHandle(p.outputHandle)
discard CloseHandle(p.errorHandle)
discard CloseHandle(p.FProcessHandle)
proc suspend(p: PProcess) =
discard SuspendThread(p.FProcessHandle)

0
lib/pure/redis.nim Normal file → Executable file
View File

0
lib/pure/romans.nim Normal file → Executable file
View File

View File

@@ -168,6 +168,7 @@ proc createMessage*(mSubject, mBody: string, mTo,
result.msgOtherHeaders = newStringTable()
proc `$`*(msg: TMessage): string =
## stringify for ``TMessage``.
result = ""
if msg.msgTo.len() > 0:
result = "TO: " & msg.msgTo.join(", ") & "\c\L"

View File

@@ -1456,7 +1456,7 @@ else:
`x`[0][len] = 0
"""
proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo".}
proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo", noSideEffect.}
## special built-in that takes a variable number of arguments. Each argument
## is converted to a string via ``$``, so it works for user-defined
## types that have an overloaded ``$`` operator.

View File

@@ -65,9 +65,12 @@ elif defined(windows):
PAGE_READWRITE)
if result == nil: raiseOutOfMem()
proc osDeallocPages(p: pointer, size: int) {.inline.} =
# according to Microsoft, 0 is the only correct value here:
when reallyOsDealloc: VirtualFree(p, 0, MEM_RELEASE)
proc osDeallocPages(p: pointer, size: int) {.inline.} =
# according to Microsoft, 0 is the only correct value for MEM_RELEASE:
# This means that the OS has some different view over how big the block is
# that we want to free! So, we cannot reliably release the memory back to
# Windows :-(. We have to live with MEM_DECOMMIT instead.
when reallyOsDealloc: VirtualFree(p, size, MEM_DECOMMIT)
else:
{.error: "Port memory manager to your platform".}

3
lib/system/atomics.nim Normal file → Executable file
View File

@@ -9,7 +9,8 @@
## Atomic operations for Nimrod.
when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport and
not defined(windows):
proc sync_add_and_fetch(p: var int, val: int): int {.
importc: "__sync_add_and_fetch", nodecl.}
proc sync_sub_and_fetch(p: var int, val: int): int {.

36
lib/system/inboxes.nim Normal file → Executable file
View File

@@ -7,8 +7,12 @@
# distribution, for details about the copyright.
#
## Message passing for threads. The current implementation is slow and does
## not work with cyclic data structures. But hey, it's better than nothing.
## Message passing for threads. **Note**: This is part of the system module.
## Do not import it directly. To activate thread support you need to compile
## with the ``--threads:on`` command line switch.
##
## **Note:** The current implementation of message passing is slow and does
## not work with cyclic data structures.
type
pbytes = ptr array[0.. 0xffff, byte]
@@ -18,6 +22,7 @@ type
lock: TSysLock
cond: TSysCond
elemType: PNimType
ready: bool
region: TMemRegion
PInbox = ptr TInbox
TLoadStoreMode = enum mStore, mLoad
@@ -178,9 +183,7 @@ template lockInbox(q: expr, action: stmt) =
action
releaseSys(q.lock)
proc send*[TMsg](receiver: var TThread[TMsg], msg: TMsg) =
## sends a message to a thread. `msg` is deeply copied.
var q = cast[PInbox](getInBoxMem(receiver))
template sendImpl(q: expr) =
if q.mask == ThreadDeadMask:
raise newException(EDeadThread, "cannot send message; thread died")
acquireSys(q.lock)
@@ -192,12 +195,24 @@ proc send*[TMsg](receiver: var TThread[TMsg], msg: TMsg) =
releaseSys(q.lock)
SignalSysCond(q.cond)
proc send*[TMsg](receiver: var TThread[TMsg], msg: TMsg) =
## sends a message to a thread. `msg` is deeply copied.
var q = cast[PInbox](getInBoxMem(receiver))
sendImpl(q)
proc send*[TMsg](receiver: TThreadId[TMsg], msg: TMsg) =
## sends a message to a thread. `msg` is deeply copied.
var q = cast[PInbox](getInBoxMem(receiver[]))
sendImpl(q)
proc llRecv(res: pointer, typ: PNimType) =
# to save space, the generic is as small as possible
var q = cast[PInbox](getInBoxMem())
acquireSys(q.lock)
q.ready = true
while q.count <= 0:
WaitSysCond(q.cond, q.lock)
q.ready = false
if typ != q.elemType:
releaseSys(q.lock)
raise newException(EInvalidValue, "cannot receive message of wrong type")
@@ -215,4 +230,15 @@ proc peek*(): int =
lockInbox(q):
result = q.count
proc peek*[TMsg](t: var TThread[TMsg]): int =
## returns the current number of messages in the inbox of thread `t`.
var q = cast[PInbox](getInBoxMem(t))
if q.mask != ThreadDeadMask:
lockInbox(q):
result = q.count
proc ready*[TMsg](t: var TThread[TMsg]): bool =
## returns true iff the thread `t` is waiting on ``recv`` for new messages.
var q = cast[PInbox](getInBoxMem(t))
result = q.ready

2
lib/system/syslocks.nim Normal file → Executable file
View File

@@ -47,7 +47,7 @@ when defined(Windows):
proc CreateEvent(lpEventAttributes: pointer,
bManualReset, bInitialState: int32,
lpName: cstring): TSysCond {.stdcall, noSideEffect,
dynlib: "kernel32", importc: "CreateEvent".}
dynlib: "kernel32", importc: "CreateEventA".}
proc CloseHandle(hObject: THandle) {.stdcall, noSideEffect,
dynlib: "kernel32", importc: "CloseHandle".}

View File

@@ -8,7 +8,7 @@
#
## Thread support for Nimrod. **Note**: This is part of the system module.
## Do not import it directly. To active thread support you need to compile
## Do not import it directly. To activate thread support you need to compile
## with the ``--threads:on`` command line switch.
##
## Nimrod's memory model for threads is quite different from other common
@@ -39,8 +39,8 @@
const
maxRegisters = 256 # don't think there is an arch with more registers
maxLocksPerThread* = 10 ## max number of locks a thread can hold
## at the same time
maxLocksPerThread = 10 ## max number of locks a thread can hold
## at the same time
useStackMaskHack = false ## use the stack mask hack for better performance
StackGuardSize = 4096
ThreadStackMask = 1024*256*sizeof(int)-1
@@ -167,14 +167,17 @@ type
PGcThread = ptr TGcThread
TGcThread {.pure.} = object
sys: TSysThread
next, prev: PGcThread
stackBottom, stackTop: pointer
stackSize: int
inbox: TThreadLocalStorage
when emulatedThreadVars and not useStackMaskHack:
tls: TThreadLocalStorage
else:
nil
when hasSharedHeap:
next, prev: PGcThread
stackBottom, stackTop: pointer
stackSize: int
else:
nil
# XXX it'd be more efficient to not use a global variable for the
# thread storage slot, but to rely on the implementation to assign slot 0
@@ -201,44 +204,45 @@ when not defined(useNimRtl):
ThreadVarSetValue(globalsSlot, addr(mainThread))
initStackBottom()
initGC()
var heapLock: TSysLock
InitSysLock(HeapLock)
when emulatedThreadVars:
if NimThreadVarsSize() > sizeof(TThreadLocalStorage):
echo "too large thread local storage size requested"
quit 1
var
threadList: PGcThread
proc registerThread(t: PGcThread) =
# we need to use the GC global lock here!
AcquireSys(HeapLock)
t.prev = nil
t.next = threadList
if threadList != nil:
sysAssert(threadList.prev == nil)
threadList.prev = t
threadList = t
ReleaseSys(HeapLock)
proc unregisterThread(t: PGcThread) =
# we need to use the GC global lock here!
AcquireSys(HeapLock)
if t == threadList: threadList = t.next
if t.next != nil: t.next.prev = t.prev
if t.prev != nil: t.prev.next = t.next
# so that a thread can be unregistered twice which might happen if the
# code executes `destroyThread`:
t.next = nil
t.prev = nil
ReleaseSys(HeapLock)
when hasSharedHeap:
var heapLock: TSysLock
InitSysLock(HeapLock)
var
threadList: PGcThread
proc registerThread(t: PGcThread) =
# we need to use the GC global lock here!
AcquireSys(HeapLock)
t.prev = nil
t.next = threadList
if threadList != nil:
sysAssert(threadList.prev == nil)
threadList.prev = t
threadList = t
ReleaseSys(HeapLock)
# on UNIX, the GC uses ``SIGFREEZE`` to tell every thread to stop so that
# the GC can examine the stacks?
proc stopTheWord() = nil
proc unregisterThread(t: PGcThread) =
# we need to use the GC global lock here!
AcquireSys(HeapLock)
if t == threadList: threadList = t.next
if t.next != nil: t.next.prev = t.prev
if t.prev != nil: t.prev.next = t.next
# so that a thread can be unregistered twice which might happen if the
# code executes `destroyThread`:
t.next = nil
t.prev = nil
ReleaseSys(HeapLock)
# on UNIX, the GC uses ``SIGFREEZE`` to tell every thread to stop so that
# the GC can examine the stacks?
proc stopTheWord() = nil
# We jump through some hops here to ensure that Nimrod thread procs can have
# the Nimrod calling convention. This is needed because thread procs are
@@ -248,10 +252,15 @@ when not defined(useNimRtl):
# GC'ed closures in Nimrod.
type
TThread* {.pure, final.}[TParam] = object of TGcThread ## Nimrod thread.
TThread* {.pure, final.}[TMsg] =
object of TGcThread ## Nimrod thread. A thread is a heavy object (~14K)
## that should not be part of a message! Use
## a ``TThreadId`` for that.
emptyFn: proc ()
dataFn: proc (p: TParam)
data: TParam
dataFn: proc (p: TMsg)
data: TMsg
TThreadId*[TMsg] = ptr TThread[TMsg] ## the current implementation uses
## a pointer as a thread ID.
proc initInbox(p: pointer)
proc freeInbox(p: pointer)
@@ -260,47 +269,47 @@ when not defined(boehmgc) and not hasSharedHeap:
template ThreadProcWrapperBody(closure: expr) =
ThreadVarSetValue(globalsSlot, closure)
var t = cast[ptr TThread[TParam]](closure)
var t = cast[ptr TThread[TMsg]](closure)
when useStackMaskHack:
var tls: TThreadLocalStorage
when not defined(boehmgc) and not hasSharedHeap:
# init the GC for this thread:
setStackBottom(addr(t))
initGC()
t.stackBottom = addr(t)
registerThread(t)
try:
when false:
var a = addr(tls)
var b = MaskStackPointer(1293920-372736-303104-36864)
c_fprintf(c_stdout, "TLS: %p\nmasked: %p\ndiff: %ld\n",
a, b, cast[int](a) - cast[int](b))
if t.emptyFn == nil: t.dataFn(t.data)
else: t.emptyFn()
finally:
# XXX shut-down is not executed when the thread is forced down!
freeInbox(addr(t.inbox))
unregisterThread(t)
when defined(deallocOsPages): deallocOsPages()
when hasSharedHeap:
t.stackBottom = addr(t)
registerThread(t)
if t.emptyFn == nil: t.dataFn(t.data)
else: t.emptyFn()
#finally:
# XXX shut-down is not executed when the thread is forced down!
freeInbox(addr(t.inbox))
when hasSharedHeap: unregisterThread(t)
when defined(deallocOsPages): deallocOsPages()
# Since an unhandled exception terminates the whole process (!), there is
# no need for a ``try finally`` here, nor would it be correct: The current
# exception is tried to be re-raised by the code-gen after the ``finally``!
# However this is doomed to fail, because we already unmapped every heap
# page!
{.push stack_trace:off.}
when defined(windows):
proc threadProcWrapper[TParam](closure: pointer): int32 {.stdcall.} =
proc threadProcWrapper[TMsg](closure: pointer): int32 {.stdcall.} =
ThreadProcWrapperBody(closure)
# implicitely return 0
else:
proc threadProcWrapper[TParam](closure: pointer) {.noconv.} =
proc threadProcWrapper[TMsg](closure: pointer) {.noconv.} =
ThreadProcWrapperBody(closure)
{.pop.}
proc joinThread*[TParam](t: TThread[TParam]) {.inline.} =
proc joinThread*[TMsg](t: TThread[TMsg]) {.inline.} =
## waits for the thread `t` to finish.
when hostOS == "windows":
discard WaitForSingleObject(t.sys, -1'i32)
else:
discard pthread_join(t.sys, nil)
proc joinThreads*[TParam](t: openArray[TThread[TParam]]) =
proc joinThreads*[TMsg](t: openArray[TThread[TMsg]]) =
## waits for every thread in `t` to finish.
when hostOS == "windows":
var a: array[0..255, TSysThread]
@@ -312,7 +321,7 @@ proc joinThreads*[TParam](t: openArray[TThread[TParam]]) =
when false:
# XXX a thread should really release its heap here somehow:
proc destroyThread*[TParam](t: var TThread[TParam]) =
proc destroyThread*[TMsg](t: var TThread[TMsg]) =
## forces the thread `t` to terminate. This is potentially dangerous if
## you don't have full control over `t` and its acquired resources.
when hostOS == "windows":
@@ -321,18 +330,18 @@ when false:
discard pthread_cancel(t.sys)
unregisterThread(addr(t))
proc createThread*[TParam](t: var TThread[TParam],
tp: proc (param: TParam) {.thread.},
param: TParam) =
proc createThread*[TMsg](t: var TThread[TMsg],
tp: proc (msg: TMsg) {.thread.},
param: TMsg) =
## creates a new thread `t` and starts its execution. Entry point is the
## proc `tp`. `param` is passed to `tp`.
t.data = param
t.dataFn = tp
t.stackSize = ThreadStackSize
when hasSharedHeap: t.stackSize = ThreadStackSize
initInbox(addr(t.inbox))
when hostOS == "windows":
var dummyThreadId: int32
t.sys = CreateThread(nil, ThreadStackSize, threadProcWrapper[TParam],
t.sys = CreateThread(nil, ThreadStackSize, threadProcWrapper[TMsg],
addr(t), 0'i32, dummyThreadId)
if t.sys <= 0:
raise newException(EResourceExhausted, "cannot create thread")
@@ -340,18 +349,18 @@ proc createThread*[TParam](t: var TThread[TParam],
var a: Tpthread_attr
pthread_attr_init(a)
pthread_attr_setstacksize(a, ThreadStackSize)
if pthread_create(t.sys, a, threadProcWrapper[TParam], addr(t)) != 0:
if pthread_create(t.sys, a, threadProcWrapper[TMsg], addr(t)) != 0:
raise newException(EResourceExhausted, "cannot create thread")
proc createThread*[TParam](t: var TThread[TParam], tp: proc () {.thread.}) =
proc createThread*[TMsg](t: var TThread[TMsg], tp: proc () {.thread.}) =
## creates a new thread `t` and starts its execution. Entry point is the
## proc `tp`.
t.emptyFn = tp
t.stackSize = ThreadStackSize
when hasSharedHeap: t.stackSize = ThreadStackSize
initInbox(addr(t.inbox))
when hostOS == "windows":
var dummyThreadId: int32
t.sys = CreateThread(nil, ThreadStackSize, threadProcWrapper[TParam],
t.sys = CreateThread(nil, ThreadStackSize, threadProcWrapper[TMsg],
addr(t), 0'i32, dummyThreadId)
if t.sys <= 0:
raise newException(EResourceExhausted, "cannot create thread")
@@ -359,9 +368,17 @@ proc createThread*[TParam](t: var TThread[TParam], tp: proc () {.thread.}) =
var a: Tpthread_attr
pthread_attr_init(a)
pthread_attr_setstacksize(a, ThreadStackSize)
if pthread_create(t.sys, a, threadProcWrapper[TParam], addr(t)) != 0:
if pthread_create(t.sys, a, threadProcWrapper[TMsg], addr(t)) != 0:
raise newException(EResourceExhausted, "cannot create thread")
proc threadId*[TMsg](t: var TThread[TMsg]): TThreadId[TMsg] {.inline.} =
## returns the thread ID of `t`.
result = addr(t)
proc myThreadId*[TMsg](): TThreadId[TMsg] =
## returns the thread ID of the thread that calls this proc.
result = cast[TThreadId[TMsg]](ThreadVarGetValue(globalsSlot))
when useStackMaskHack:
proc runMain(tp: proc () {.thread.}) {.compilerproc.} =
var mainThread: TThread[pointer]
@@ -371,7 +388,7 @@ when useStackMaskHack:
# --------------------------- lock handling ----------------------------------
type
TLock* = TSysLock ## Nimrod lock
TLock* = TSysLock ## Nimrod lock; not re-entrant!
const
noDeadlocks = false # compileOption("deadlockPrevention")

0
lib/wrappers/sphinx.nim Normal file → Executable file
View File

27
lib/wrappers/zmq.nim Normal file → Executable file
View File

@@ -27,7 +27,32 @@
## Nimrod 0mq wrapper. This file contains the low level C wrappers as well as
## some higher level constructs. The higher level constructs are easily
## recognizable because they are the only ones that have documentation.
##
## Example of a client:
##
## .. code-block:: nimrod
## import zmq
##
## var connection = zmq.open("tcp://localhost:5555", server=false)
## echo("Connecting...")
## for i in 0..10:
## echo("Sending hello...", i)
## send(connection, "Hello")
## var reply = receive(connection)
## echo("Received ...", reply)
## close(connection)
##
## Example of a server:
##
## .. code-block:: nimrod
##
## import zmq
## var connection = zmq.open("tcp://*:5555", server=true)
## while True:
## var request = receive(connection)
## echo("Received: ", request)
## send(connection, "World")
## close(connection)
{.deadCodeElim: on.}
when defined(windows):

0
tests/accept/compile/tcan_alias_generic.nim Normal file → Executable file
View File

View File

0
tests/accept/compile/tcan_inherit_generic.nim Normal file → Executable file
View File

0
tests/accept/compile/tcan_specialise_generic.nim Normal file → Executable file
View File

0
tests/accept/compile/tcodegenbug1.nim Normal file → Executable file
View File

0
tests/accept/compile/tconstraints.nim Normal file → Executable file
View File

0
tests/accept/compile/teval1.nim Normal file → Executable file
View File

0
tests/accept/compile/tgenericmatcher.nim Normal file → Executable file
View File

0
tests/accept/compile/tgenericmatcher2.nim Normal file → Executable file
View File

0
tests/accept/compile/tgenericrefs.nim Normal file → Executable file
View File

0
tests/accept/compile/titer2.nim Normal file → Executable file
View File

0
tests/accept/compile/titer_no_tuple_unpack.nim Normal file → Executable file
View File

0
tests/accept/compile/tmacrostmt.nim Normal file → Executable file
View File

0
tests/accept/compile/tmarshal.nim Normal file → Executable file
View File

0
tests/accept/compile/tnimrodnode_for_runtime.nim Normal file → Executable file
View File

0
tests/accept/compile/tshadow_magic_type.nim Normal file → Executable file
View File

0
tests/accept/compile/tspecialised_is_equivalent.nim Normal file → Executable file
View File

0
tests/accept/compile/ttableconstr.nim Normal file → Executable file
View File

0
tests/accept/compile/ttempl4.nim Normal file → Executable file
View File

0
tests/accept/compile/ttemplreturntype.nim Normal file → Executable file
View File

0
tests/accept/compile/ttypeconverter1.nim Normal file → Executable file
View File

0
tests/accept/run/tcase_setconstr.nim Normal file → Executable file
View File

0
tests/accept/run/tfielditerator.nim Normal file → Executable file
View File

0
tests/accept/run/tgenericassign.nim Normal file → Executable file
View File

0
tests/accept/run/tgenericassigntuples.nim Normal file → Executable file
View File

0
tests/accept/run/tkoeniglookup.nim Normal file → Executable file
View File

0
tests/accept/run/tlists.nim Normal file → Executable file
View File

0
tests/accept/run/tmacro4.nim Normal file → Executable file
View File

0
tests/accept/run/tmethods1.nim Normal file → Executable file
View File

0
tests/accept/run/tnewderef.nim Normal file → Executable file
View File

0
tests/accept/run/trepr.nim Normal file → Executable file
View File

0
tests/accept/run/tsets2.nim Normal file → Executable file
View File

0
tests/accept/run/tsimplesort.nim Normal file → Executable file
View File

0
tests/accept/run/tslices.nim Normal file → Executable file
View File

3
tests/accept/run/ttables.nim Normal file → Executable file
View File

@@ -80,5 +80,8 @@ block countTableTest1:
else: break
inc i
block SyntaxTest:
var x = toTable[int, string]({:})
echo "true"

0
tests/reject/tconstraints.nim Normal file → Executable file
View File

0
tests/reject/temptycaseobj.nim Normal file → Executable file
View File

0
tests/reject/tno_int_in_bool_context.nim Normal file → Executable file
View File

0
tests/reject/tprocvar.nim Normal file → Executable file
View File

44
tests/threads/threadex.nim Executable file
View File

@@ -0,0 +1,44 @@
type
TMsgKind = enum
mLine, mEof
TMsg = object {.pure, final.}
case k: TMsgKind
of mEof: backTo: TThreadId[int]
of mLine: data: string
var
consumer: TThread[TMsg]
producer: TThread[int]
printedLines = 0
proc consume() {.thread.} =
while true:
var x = recv[TMsg]()
if x.k == mEof:
x.backTo.send(printedLines)
break
echo x.data
discard atomicInc(printedLines)
proc produce() {.thread.} =
var m: TMsg
var input = open("readme.txt")
while not endOfFile(input):
if consumer.ready:
m.data = input.readLine()
consumer.send(m)
close(input)
m.k = mEof
m.backTo = myThreadId[int]()
consumer.send(m)
var result = recv[int]()
echo result
createThread(consumer, consume)
createThread(producer, produce)
joinThread(consumer)
joinThread(producer)
echo printedLines

View File

@@ -37,7 +37,7 @@ proc echoLeTree(n: PNode) =
echo it.data
it = it.le
proc threadFunc(interval: tuple[a, b: int]) {.procvar.} =
proc threadFunc(interval: tuple[a, b: int]) {.thread.} =
doNothing()
for i in interval.a..interval.b:
var r = buildTree(i)

View File

@@ -1,7 +1,7 @@
discard """
file: "tthreadanalysis2.nim"
line: 45
errormsg: "possible inconsistency of thread local heaps"
errormsg: "write to foreign heap"
cmd: "nimrod cc --hints:on --threads:on $# $#"
"""
@@ -37,7 +37,7 @@ proc echoLeTree(n: PNode) =
echo it.data
it = it.le
proc threadFunc(interval: tuple[a, b: int]) {.procvar.} =
proc threadFunc(interval: tuple[a, b: int]) {.thread.} =
doNothing()
for i in interval.a..interval.b:
var r = buildTree(i)

View File

@@ -0,0 +1,14 @@
var
global: string = "test string"
t: TThread[string]
proc horrible() {.thread.} =
global = "string in thread local heap!"
var x = global
var mydata = (x, "my string too")
echo global
createThread(t, horrible)
joinThread(t)

View File

@@ -1,25 +1,11 @@
High priority (version 0.8.12)
==============================
* ``force_nosideEffect`` or some similar pragma is needed (``loophole``?)
* test threads on windows
* test thread analysis:
var x = globalString # ok, copied; `x` is mine!
vs
var x = globalRef # read access, `x` is theirs!
* make threadvar efficient again on linux after testing
* document Nimrod's threads
* document Nimrod's two phase symbol lookup for generics
* bug: {:}.toTable[int, string]()
version 0.9.0
=============
- ``var T`` as a return type; easy to prove that location is not on the stack
- document Nimrod's two phase symbol lookup for generics
- add --deadlock_prevention:on|off switch? timeout for locks?
- bug: tfFinal not passed to generic
- bug: forward proc for generic seems broken
- ``var T`` as a return type; easy to prove that location is not on the stack
- test the sort implementation again
- warning for implicit openArray -> varargs convention
- implement explicit varargs
@@ -28,6 +14,7 @@ version 0.9.0
- fix overloading resolution
- make ^ available as operator
- implement closures; implement proper coroutines
- make threadvar efficient again on linux after testing
Bugs
----
@@ -57,7 +44,7 @@ version 0.9.XX
- test branch coverage
- checked exceptions
- fix implicit generic routines
- think about ``{:}.toTable[int, string]()``
Library
-------

View File

@@ -3,8 +3,8 @@
Here you can download the latest version of the Nimrod Compiler.
Please choose your platform:
* source-based installation: `<download/nimrod_0.8.10.zip>`_
* installer for Windows XP/Vista (i386): `<download/nimrod_0.8.10.exe>`_
* source-based installation: `<download/nimrod_0.8.12.zip>`_
* installer for Windows XP/Vista (i386): `<download/nimrod_0.8.12.exe>`_
(includes GCC and everything else you need)
The source-based installation has been tested on these systems:

View File

@@ -3,7 +3,7 @@ News
====
2011-XX-XX Version 0.8.12 released
2011-07-10 Version 0.8.12 released
==================================
Version 0.8.12 has been released! Get it `here <download.html>`_.
@@ -22,6 +22,8 @@ Bugfixes
- Bugfix: The compiler does not emit very inaccurate floating point literals
anymore.
- Bugfix: Subclasses are taken into account for ``try except`` matching.
- Bugfix: Generics and macros are more stable. There are still known bugs left
though.
- Bugfix: Generated type information for tuples was sometimes wrong, causing
random crashes.
- Lots of other bugfixes: Too many to list them all.
@@ -38,7 +40,7 @@ Changes affecting backwards compatibility
- Changed and documented how generalized string literals work: The syntax
``module.re"abc"`` is now supported.
- Changed the behaviour of ``strutils.%``, ``ropes.%``
if both ``$#`` and ``$i`` are involved.
if both notations ``$#`` and ``$i`` are involved.
- The ``pegs`` and ``re`` modules distinguish between ``replace``
and ``replacef`` operations.
- The pointer dereference operation ``p^`` is deprecated and might become
@@ -50,8 +52,42 @@ Changes affecting backwards compatibility
- Unsound co-/contravariance for procvars has been removed.
Additions
---------
Language Additions
------------------
- Source code filters are now documented.
- Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas.
- Added ``emit`` pragma for direct code generator control.
- Case statement branches support constant sets for programming convenience.
- Tuple unpacking is not enforced in ``for`` loops anymore.
- The compiler now supports array, sequence and string slicing.
- A field in an ``enum`` may be given an explicit string representation.
This yields more maintainable code than using a constant
``array[TMyEnum, string]`` mapping.
- Indices in array literals may be explicitly given, enhancing readability:
``[enumValueA: "a", enumValueB: "b"]``.
- Added thread support via the ``threads`` core module and
the ``--threads:on`` command line switch.
- The built-in iterators ``system.fields`` and ``system.fieldPairs`` can be
used to iterate over any field of a tuple. With this mechanism operations
like ``==`` and ``hash`` are lifted to tuples.
- The slice ``..`` is now a first-class operator, allowing code like:
``x in 1000..100_000``.
Compiler Additions
------------------
- The compiler supports IDEs via the new group of ``idetools`` command line
options.
- The *interactive mode* (REPL) has been improved and documented for the
first time.
- The compiler now might use hashing for string case statements depending
on the number of string literals in the case statement.
Library Additions
-----------------
- Added ``lists`` module which contains generic linked lists.
- Added ``sets`` module which contains generic hash sets.
@@ -70,37 +106,20 @@ Additions
``\title``, ``\white``.
- Pegs support the new built-in ``\skip`` operation.
- Pegs support the ``$`` and ``^`` anchors.
- Source code filters are now documented.
- Added ``emit`` pragma for direct code generator control.
- Additional operations were added to the ``complex`` module.
- Added ``strutils.formatFloat``, ``strutils.formatBiggestFloat``.
- A field in an ``enum`` may be given an explicit string representation.
This yields more maintainable code than using a constant
``array[TMyEnum, string]`` mapping.
- Indices in array literals may be explicitly given, enhancing readability:
``[enumValueA: "a", enumValueB: "b"]``.
- Added basic thread support via the ``threads`` core module and
the ``--threads:on`` command line switch.
- Added unary ``<`` for nice looking excluding upper bounds in ranges.
- Added ``math.floor``.
- The *interactive mode* (REPL) has been improved and documented for the
first time.
- Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas.
- Added ``system.reset`` and a version of ``system.open`` that
returns a ``TFile`` and raises an exception in case of an error.
- The compiler now might use hashing for string case statements depending
on the number of string literals in the case statement.
- Tuple unpacking is not enforced in ``for`` loops anymore.
- Added a wrapper for ``redis``.
- Added a wrapper for ``0mq`` via the ``zmq`` module.
- Added a wrapper for ``sphinx``.
- The compiler now supports array, sequence and string slicing.
- Added ``system.newStringOfCap``.
- Added ``system.raiseHook`` and ``system.outOfMemHook``.
- Added ``system.writeFile``.
- Added ``system.shallowCopy``.
- ``system.echo`` is guaranteed to be thread-safe.
- Case statement branches support constant sets for programming convenience.
- Added ``prelude`` include file for scripting convenience.
- Added ``typeinfo`` core module for access to runtime type information.
- Added ``marshal`` module for JSON serialization.

View File

@@ -25,8 +25,9 @@ doc: "endb;intern;apis;lib;manual;tut1;tut2;nimrodc;overview"
doc: "tools;c2nim;niminst"
pdf: "manual;lib;tut1;tut2;nimrodc;c2nim;niminst"
srcdoc: "core/macros;pure/marshal;core/typeinfo"
srcdoc: "impure/graphics;pure/sockets"
srcdoc: "system.nim;system/threads.nim;pure/os;pure/strutils;pure/math"
srcdoc: "impure/graphics;impure/re;pure/sockets"
srcdoc: "system.nim;system/threads.nim;system/inboxes.nim"
srcdoc: "pure/os;pure/strutils;pure/math"
srcdoc: "pure/complex;pure/times;pure/osproc;pure/pegs;pure/dynlib"
srcdoc: "pure/parseopt;pure/hashes;pure/strtabs;pure/lexbase"
srcdoc: "pure/parsecfg;pure/parsexml;pure/parsecsv;pure/parsesql"

View File

@@ -1,6 +1,9 @@
| `2011-07-10`:newsdate:
| Nimrod version 0.8.12 has been released!
Get it `here <./download.html>`_.
| `2010-10-20`:newsdate:
| Nimrod version 0.8.10 has been released!
Get it `here <./download.html>`_.
| `2010-03-14`:newsdate:
| Nimrod version 0.8.8 has been released!