resolved system.nim conflicts

This commit is contained in:
Andreas Rumpf
2010-05-29 00:39:33 +02:00
37 changed files with 28956 additions and 28481 deletions

View File

@@ -10,7 +10,7 @@ Advanced options:
--warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints on|off
--hint[X]:on|off turn specific hint X on|off
--lib:PATH set the system library path
--lib:PATH set the path to the system.nim library
-c, --compileOnly compile only; do not assemble or link
--noLinking compile but do not link
--noMain do not generate a main procedure

View File

@@ -10,21 +10,21 @@ a `base type`:idx:.
Use case 1: SQL strings
-----------------------
An SQL statement that is passed from Nimrod to an SQL database might be
An SQL statement that is passed from Nimrod to an SQL database might be
modelled as a string. However, using string templates and filling in the
values is vulnerable to the famous `SQL injection attack`:idx:\:
values is vulnerable to the famous `SQL injection attack`:idx:\:
.. code-block:: nimrod
proc query(db: TDbHandle, statement: TSQL) = ...
var
username: string
db.query("SELECT FROM users WHERE name = '$1'" % username)
# Horrible security whole, but the compiler does not mind!
This can be avoided by distinguishing strings that contain SQL from strings
that don't. Abstract types provide a means to introduce a new string type
# Horrible security hole, but the compiler does not mind!
This can be avoided by distinguishing strings that contain SQL from strings
that don't. Abstract types provide a means to introduce a new string type
``TSQL`` that is incompatible with ``string``:
.. code-block:: nimrod
@@ -35,26 +35,26 @@ that don't. Abstract types provide a means to introduce a new string type
var
username: string
db.query("SELECT FROM users WHERE name = '$1'" % username)
# Error at compile time: `query` expects an SQL string!
It is an essential property of abstract types that they **do not** imply a
subtype relation between the abtract type and its base type. Explict type
conversions from ``string`` to ``TSQL`` are allowed:
conversions from ``string`` to ``TSQL`` are allowed:
.. code-block:: nimrod
proc properQuote(s: string): TSQL =
proc properQuote(s: string): TSQL =
# quotes a string properly for an SQL statement
...
proc `%` (frmt: TSQL, values: openarray[string]): TSQL =
proc `%` (frmt: TSQL, values: openarray[string]): TSQL =
# quote each argument:
var v = values.each(properQuote)
# we need a temporary type for the type conversion :-(
type TStrSeq = seq[string]
# call strutils.`%`:
# call strutils.`%`:
result = TSQL(string(frmt) % TStrSeq(v))
db.query("SELECT FROM users WHERE name = $1".TSQL % username)
@@ -68,43 +68,43 @@ for nice looking ``TSQL`` string literals.
Use case 2: Money
-----------------
Different currencies should not be mixed in monetary calculations. Abstract
types are a perfect tool to model different currencies:
types are a perfect tool to model different currencies:
.. code-block:: nimrod
type
TDollar = abstract int
TEuro = abstract int
var
d: TDollar
e: TEuro
echo d + 12
echo d + 12
# Error: cannot add a number with no unit with a ``TDollar``
Unfortunetaly, ``d + 12.TDollar`` is not allowed either,
Unfortunetaly, ``d + 12.TDollar`` is not allowed either,
because ``+`` is defined for ``int`` (among others), not for ``TDollar``. So
we define our own ``+`` for dollars:
we define our own ``+`` for dollars:
.. code-block::
proc `+` (x, y: TDollar): TDollar =
.. code-block::
proc `+` (x, y: TDollar): TDollar =
result = TDollar(int(x) + int(y))
It does not make sense to multiply a dollar with a dollar, but with a
number without unit; and the same holds for division:
.. code-block::
proc `*` (x: TDollar, y: int): TDollar =
.. code-block::
proc `*` (x: TDollar, y: int): TDollar =
result = TDollar(int(x) * y)
proc `*` (x: int, y: TDollar): TDollar =
proc `*` (x: int, y: TDollar): TDollar =
result = TDollar(x * int(y))
proc `div` ...
This quickly gets tedious. The implementations are trivial and the compiler
This quickly gets tedious. The implementations are trivial and the compiler
should not generate all this code only to optimize it away later - after all
``+`` for dollars should produce the same binary code as ``+`` for ints.
``+`` for dollars should produce the same binary code as ``+`` for ints.
The pragma ``borrow`` has been designed to solve this problem; in principle
it generates the trivial implementation for us:
@@ -113,40 +113,40 @@ it generates the trivial implementation for us:
proc `*` (x: int, y: TDollar): TDollar {.borrow.}
proc `div` (x: TDollar, y: int): TDollar {.borrow.}
The ``borrow`` pragma makes the compiler use the same implementation as
The ``borrow`` pragma makes the compiler to use the same implementation as
the proc that deals with the abstract type's base type, so no code is
generated.
generated.
But it seems we still have to repeat all this boilerplate code for
the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
the ``TEuro`` currency. Fortunately, Nimrod has a template mechanism:
.. code-block:: nimrod
template Additive(typ: typeDesc): stmt =
proc `+` *(x, y: typ): typ {.borrow.}
proc `-` *(x, y: typ): typ {.borrow.}
# unary operators:
proc `+` *(x: typ): typ {.borrow.}
proc `-` *(x: typ): typ {.borrow.}
template Multiplicative(typ, base: typeDesc): stmt =
template Multiplicative(typ, base: typeDesc): stmt =
proc `*` *(x: typ, y: base): typ {.borrow.}
proc `*` *(x: base, y: typ): typ {.borrow.}
proc `div` *(x: typ, y: base): typ {.borrow.}
proc `mod` *(x: typ, y: base): typ {.borrow.}
template Comparable(typ: typeDesc): stmt =
template Comparable(typ: typeDesc): stmt =
proc `<` * (x, y: typ): bool {.borrow.}
proc `<=` * (x, y: typ): bool {.borrow.}
proc `==` * (x, y: typ): bool {.borrow.}
template DefineCurrency(typ, base: expr): stmt =
template DefineCurrency(typ, base: expr): stmt =
type
typ* = abstract base
Additive(typ)
Multiplicative(typ, base)
Comparable(typ)
DefineCurrency(TDollar, int)
DefineCurrency(TEuro, int)

View File

@@ -9,7 +9,7 @@ explicit like in Haskell?
The idea is that side effects and partial evaluation belong together:
Iff a proc is side effect free and all its argument are evaluable at
compile time, it can be evaluated by the compiler. However, really
difficult is the ``newString`` proc: If it is simply wrapped, it
difficult is the ``newString`` proc: If it is simply wrapped, it
should not be evaluated at compile time! On other occasions it can
and should be evaluted:
@@ -20,22 +20,22 @@ and should be evaluted:
result[i] = toUpper(s[i])
No, it really can always be evaluated. The code generator should transform
``s = "\0\0\0..."`` back into ``s = newString(...)``.
``s = "\0\0\0..."`` back into ``s = newString(...)``.
``new`` cannot be evaluated at compile time either.
``new`` cannot be evaluated at compile time either.
Raise statement
===============
It is impractical to consider ``raise`` a statement with side effects.
It is impractical to consider ``raise`` as a statement with side effects.
Solution
========
Being side effect free does not suffice for compile time evaluation. However,
the evaluator can attempt to evaluate at compile time.
the evaluator can attempt to evaluate at compile time.

View File

@@ -23,7 +23,7 @@ available for the debugger.
If you start your program the debugger will immediately show
a prompt on the console. You can now enter a command. The next sections
deal with the possible commands. As usual for Nimrod for all commands
deal with the possible commands. As usual in Nimrod in all commands
underscores and case do not matter. Optional components of a command
are listed in brackets ``[...]`` here.

View File

@@ -12,7 +12,7 @@ Nimrod Standard Library
Though the Nimrod Standard Library is still evolving, it is already quite
usable. It is divided into *pure libraries*, *impure libraries* and *wrappers*.
Pure libraries do not depend on any external ``*.dll`` or ``lib*.so`` binary
Pure libraries do not depend on any external ``*.dll`` or ``lib*.so`` binary
while impure libraries do. A wrapper is an impure library that is a very
low-level interface to a C library.
@@ -31,7 +31,7 @@ Core
implicitly by the compiler. Do not import it directly. It relies on compiler
magic to work.
* `macros <macros.html>`_
* `macros <macros.html>`_
Contains the AST API and documentation of Nimrod for writing macros.
@@ -39,8 +39,8 @@ String handling
---------------
* `strutils <strutils.html>`_
This module contains common string handling operations like converting a
string into uppercase, splitting a string into substrings, searching for
This module contains common string handling operations like changing
case of a string, splitting a string into substrings, searching for
substrings, replacing substrings.
* `parseutils <parseutils.html>`_
@@ -52,7 +52,7 @@ String handling
style-insensitive mode. An efficient string substitution operator ``%``
for the string table is also provided.
* `unicode <unicode.html>`_
* `unicode <unicode.html>`_
This module provides support to handle the Unicode UTF-8 encoding.
* `re <re.html>`_
@@ -67,11 +67,11 @@ String handling
Ropes can represent very long strings efficiently; especially concatenation
is done in O(1) instead of O(n).
* `unidecode <unidecode.html>`_
* `unidecode <unidecode.html>`_
This module provides Unicode to ASCII transliterations:
It finds the sequence of ASCII characters that is the closest approximation
to the Unicode string.
Generic Operating System Services
---------------------------------
@@ -97,8 +97,8 @@ Generic Operating System Services
may provide other implementations for this standard stream interface.
* `terminal <terminal.html>`_
This module contains a few procedures to control the *terminal*
(also called *console*). The implementation simply uses ANSI escape
This module contains a few procedures to control the *terminal*
(also called *console*). The implementation simply uses ANSI escape
sequences and does not depend on any other module.
@@ -117,20 +117,20 @@ Internet Protocols and Support
------------------------------
* `cgi <cgi.html>`_
This module implements helpers for CGI applictions.
This module implements helpers for CGI applictions.
* `sockets <sockets.html>`_
This module implements a simple portable type-safe sockets layer.
* `browsers <browsers.html>`_
This module implements procs for opening URLs with the user's default
This module implements procs for opening URLs with the user's default
browser.
* `httpserver <httpserver.html>`_
This module implements a simple HTTP server.
* `httpclient <httpclient.html>`_
This module implements a simple HTTP client.
This module implements a simple HTTP client.
Parsers
@@ -149,14 +149,14 @@ Parsers
as in the Nimrod programming language.
* `parsexml <parsexml.html>`_
The ``parsexml`` module implements a simple high performance XML/HTML parser.
The ``parsexml`` module implements a simple high performance XML/HTML parser.
The only encoding that is supported is UTF-8. The parser has been designed
to be somewhat error correcting, so that even some "wild HTML" found on the
web can be parsed with it.
to be somewhat error correcting, so that even some "wild HTML" found on the
Web can be parsed with it.
* `parsecsv <parsecsv.html>`_
* `parsecsv <parsecsv.html>`_
The ``parsecsv`` module implements a simple high performance CSV parser.
* `parsesql <parsesql.html>`_
The ``parsesql`` module implements a simple high performance SQL parser.
@@ -168,20 +168,20 @@ Parsers
XML Processing
--------------
* `xmldom <xmldom.html>`_
* `xmldom <xmldom.html>`_
This module implements the XML DOM Level 2.
* `xmldomparser <xmldomparser.html>`_
This module parses an XML Document into a XML DOM Document representation.
* `xmltree <xmltree.html>`_
A simple XML tree. More efficient and simpler than the DOM. It also
A simple XML tree. More efficient and simpler than the DOM. It also
contains a macro for XML/HTML code generation.
* `xmlparser <xmlparser.html>`_
* `xmlparser <xmlparser.html>`_
This module parses an XML document and creates its XML tree representation.
* `htmlparser <htmlparser.html>`_
* `htmlparser <htmlparser.html>`_
This module parses an HTML document and creates its XML tree representation.
@@ -199,8 +199,8 @@ Cryptography and Hashing
Multimedia support
------------------
* `colors <colors.html>`_
This module implements color handling for Nimrod. It is used by
* `colors <colors.html>`_
This module implements color handling for Nimrod. It is used by
the ``graphics`` module.
@@ -211,7 +211,7 @@ Impure libraries
* `graphics <graphics.html>`_
This module implements graphical output for Nimrod; the current
implementation uses SDL but the interface is meant to support multiple
backends some day.
backends some day.
* `dialogs <dialogs.html>`_
This module implements portable dialogs for Nimrod; the implementation
@@ -220,10 +220,10 @@ Impure libraries
* `zipfiles <zipfiles.html>`_
This module implements a zip archive creator/reader/modifier.
* `web <web.html>`_
This module contains simple high-level procedures for dealing with the
web like loading the contents of a web page from an URL.
Web like loading the contents of a Web page from an URL.
Database support
@@ -232,11 +232,11 @@ Database support
* `db_postgres <db_postgres.html>`_
A higher level PostgreSQL database wrapper. The same interface is implemented
for other databases too.
* `db_mysql <db_mysql.html>`_
A higher level mySQL database wrapper. The same interface is implemented
A higher level MySQL database wrapper. The same interface is implemented
for other databases too.
* `db_sqlite <db_sqlite.html>`_
A higher level SQLite database wrapper. The same interface is implemented
for other databases too.
@@ -255,7 +255,7 @@ not contained in the distribution. You can then find them on the website.
Contains a wrapper for the Win32 API.
* `mysql <mysql.html>`_
Contains a wrapper for the mySQL API.
* `sqlite3 <sqlite3.html>`_
* `sqlite3 <sqlite3.html>`_
Contains a wrapper for SQLite 3 API.
* `libcurl <libcurl.html>`_
Contains a wrapper for the libcurl library.
@@ -317,14 +317,14 @@ not contained in the distribution. You can then find them on the website.
Part of the wrapper for Lua.
* `lauxlib <lauxlib.html>`_
Part of the wrapper for Lua.
* `tcl <tcl.html>`_
* `tcl <tcl.html>`_
Wrapper for the TCL programming language.
* `python <python.html>`_
Wrapper for the Python programming language.
* `odbcsql <odbcsql.html>`_
interface to the ODBC driver.
* `zlib <zlib.html>`_
Wrapper for the zlib library.
Wrapper for the zlib library.
* `sdl <sdl.html>`_
Part of the wrapper for SDL.
* `sdl_gfx <sdl_gfx.html>`_
@@ -379,7 +379,7 @@ not contained in the distribution. You can then find them on the website.
Part of the wrapper for X11.
* `libzip <libzip.html>`_
Interface to the `lib zip <http://www.nih.at/libzip/index.html>`_ library by
Dieter Baron and Thomas Klausner.
* `iup <iup.html>`_
Dieter Baron and Thomas Klausner.
* `iup <iup.html>`_
Wrapper of the IUP GUI library.

File diff suppressed because it is too large Load Diff

View File

@@ -1,239 +1,239 @@
===================================
Nimrod Compiler User Guide
===================================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
"Look at you, hacker. A pathetic creature of meat and bone, panting and
sweating as you run through my corridors. How can you challenge a perfect,
immortal machine?"
Introduction
============
This document describes the usage of the *Nimrod compiler*
on the different supported platforms. It is not a definition of the Nimrod
programming language (therefore is the `manual <manual>`_).
Nimrod is free software; it is licensed under the
`GNU General Public License <gpl.html>`_.
Compiler Usage
==============
Command line switches
---------------------
Basis command line switches are:
.. include:: ../data/basicopt.txt
Advanced command line switches are:
.. include:: ../data/advopt.txt
Configuration file
------------------
The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
looks for it in the following directories (in this order):
1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``%APPDATA%/nimrod.cfg`` (Windows)
2. ``$nimrod/config/nimrod.cfg`` (UNIX, Windows)
3. ``/etc/nimrod.cfg`` (UNIX)
The search stops as soon as a configuration file has been found. The reading
of ``nimrod.cfg`` can be suppressed by the ``--skipCfg`` command line option.
**Note:** The *project file name* is the name of the ``.nim`` file that is
passed as a command line argument to the compiler.
Configuration settings can be overwritten in a project specific
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.
Generated C code directory
--------------------------
The generated files that Nimrod produces all go into a subdirectory called
``nimcache`` in your project directory. This makes it easy to delete all
generated files.
However, the generated C code is not platform independant. 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.
Additional Features
===================
This section describes Nimrod's additional features that are not listed in the
Nimrod manual. Some of the features here only make sense for the C code
generator and are subject to change.
NoDecl pragma
-------------
The `noDecl`:idx: pragma can be applied to almost any symbol (variable, proc,
type, etc.) and is sometimes useful for interoperability with C:
It tells Nimrod that it should not generate a declaration for the symbol in
the C code. For example:
.. code-block:: Nimrod
var
EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as
# Nimrod does not know its value
However, the ``header`` pragma is often the better alternative.
**Note**: This will not work for the LLVM backend.
Header pragma
-------------
The `header`:idx: pragma is very similar to the ``noDecl`` pragma: It can be
applied to almost any symbol and specifies that it should not be declared
and instead the generated code should contain an ``#include``:
.. code-block:: Nimrod
type
PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer
# import C's FILE* type; Nimrod will treat it as a new pointer type
The ``header`` pragma always expects a string constant. The string contant
contains the header file: As usual for C, a system header file is enclosed
in angle brackets: ``<>``. If no angle brackets are given, Nimrod
encloses the header file in ``""`` in the generated C code.
**Note**: This will not work for the LLVM backend.
LineDir option
--------------
The `lineDir`:idx: option can be turned on or off. If turned on the
generated C code contains ``#line`` directives. This may be helpful for
debugging with GDB.
StackTrace option
-----------------
If the `stackTrace`:idx: option is turned on, the generated C contains code to
ensure that proper stack traces are given if the program crashes or an
uncaught exception is raised.
LineTrace option
----------------
The `lineTrace`:idx: option implies the ``stackTrace`` option. If turned on,
the generated C contains code to ensure that proper stack traces with line
number information are given if the program crashes or an uncaught exception
is raised.
Debugger option
---------------
The `debugger`:idx: option enables or disables the *Embedded Nimrod Debugger*.
See the documentation of endb_ for further information.
Breakpoint pragma
-----------------
The *breakpoint* pragma was specially added for the sake of debugging with
ENDB. See the documentation of `endb <endb.html>`_ for further information.
Volatile pragma
---------------
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.
Debugging with Nimrod
=====================
Nimrod comes with its own *Embedded Nimrod Debugger*. See
the documentation of endb_ for further information.
Optimizing for Nimrod
=====================
Nimrod has no separate optimizer, but the C code that is produced is very
efficient. Most C compilers have excellent optimizers, so usually it is
not needed to optimize one's code. Nimrod has been designed to encourage
efficient code: The most readable code in Nimrod is often the most efficient
too.
However, sometimes one has to optimize. Do it in the following order:
1. switch off the embedded debugger (it is **slow**!)
2. turn on the optimizer and turn off runtime checks
3. profile your code to find where the bottlenecks are
4. try to find a better algorithm
5. do low-level optimizations
This section can only help you with the last item.
Optimizing string handling
--------------------------
String assignments are sometimes expensive in Nimrod: They are required to
copy the whole string. However, the compiler is often smart enough to not copy
strings. Due to the argument passing semantics, strings are never copied when
passed to subroutines. The compiler does not copy strings that are a result from
a procedure call, because the callee returns a new string anyway.
Thus it is efficient to do:
.. code-block:: Nimrod
var s = procA() # assignment will not copy the string; procA allocates a new
# string already
However it is not efficient to do:
.. code-block:: Nimrod
var s = varA # assignment has to copy the whole string into a new buffer!
..
String case statements are optimized too. A hashing scheme is used for them
if several different string constants are used. This is likely to be more
efficient than any hand-coded scheme.
..
The ECMAScript code generator
=============================
Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
longer. Help if you are interested.
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:,
since it is the proper term.
The ECMAScript code generator is experimental!
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
Since ECMAScript does not have a portable means to include another module,
Nimrod just generates a long ``.js`` file.
Features or modules that the ECMAScript platform does not support are not
available. This includes:
* manual memory management (``alloc``, etc.)
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
* file management
* most modules of the Standard library
* proper 64 bit integer arithmetic
* proper unsigned integer arithmetic
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
available! To access the DOM, use the `dom`:idx: module that is only
available for the ECMAScript platform.
===================================
Nimrod Compiler User Guide
===================================
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
"Look at you, hacker. A pathetic creature of meat and bone, panting and
sweating as you run through my corridors. How can you challenge a perfect,
immortal machine?"
Introduction
============
This document describes the usage of the *Nimrod compiler*
on the different supported platforms. It is not a definition of the Nimrod
programming language (therefore is the `manual <manual>`_).
Nimrod is free software; it is licensed under the
`GNU General Public License <gpl.html>`_.
Compiler Usage
==============
Command line switches
---------------------
Basis command line switches are:
.. include:: ../data/basicopt.txt
Advanced command line switches are:
.. include:: ../data/advopt.txt
Configuration file
------------------
The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
looks for it in the following directories (in this order):
1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``%APPDATA%/nimrod.cfg`` (Windows)
2. ``$nimrod/config/nimrod.cfg`` (UNIX), ``%NIMROD%/config/nimrod.cfg`` (Windows)
3. ``/etc/nimrod.cfg`` (UNIX)
The search stops as soon as a configuration file has been found. The reading
of ``nimrod.cfg`` can be suppressed by the ``--skipCfg`` command line option.
**Note:** The *project file name* is the name of the ``.nim`` file that is
passed as a command line argument to the compiler.
Configuration settings can be overwritten individually in a project specific
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.
Generated C code directory
--------------------------
The generated files that Nimrod produces all go into a subdirectory called
``nimcache`` in your project directory. This makes it easy to delete all
generated files.
However, the generated C code is not platform independant. 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.
Additional Features
===================
This section describes Nimrod's additional features that are not listed in the
Nimrod manual. Some of the features here only make sense for the C code
generator and are subject to change.
NoDecl pragma
-------------
The `noDecl`:idx: pragma can be applied to almost any symbol (variable, proc,
type, etc.) and is sometimes useful for interoperability with C:
It tells Nimrod that it should not generate a declaration for the symbol in
the C code. For example:
.. code-block:: Nimrod
var
EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as
# Nimrod does not know its value
However, the ``header`` pragma is often the better alternative.
**Note**: This will not work for the LLVM backend.
Header pragma
-------------
The `header`:idx: pragma is very similar to the ``noDecl`` pragma: It can be
applied to almost any symbol and specifies that it should not be declared
and instead the generated code should contain an ``#include``:
.. code-block:: Nimrod
type
PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer
# import C's FILE* type; Nimrod will treat it as a new pointer type
The ``header`` pragma always expects a string constant. The string contant
contains the header file: As usual for C, a system header file is enclosed
in angle brackets: ``<>``. If no angle brackets are given, Nimrod
encloses the header file in ``""`` in the generated C code.
**Note**: This will not work for the LLVM backend.
LineDir option
--------------
The `lineDir`:idx: option can be turned on or off. If turned on the
generated C code contains ``#line`` directives. This may be helpful for
debugging with GDB.
StackTrace option
-----------------
If the `stackTrace`:idx: option is turned on, the generated C contains code to
ensure that proper stack traces are given if the program crashes or an
uncaught exception is raised.
LineTrace option
----------------
The `lineTrace`:idx: option implies the ``stackTrace`` option. If turned on,
the generated C contains code to ensure that proper stack traces with line
number information are given if the program crashes or an uncaught exception
is raised.
Debugger option
---------------
The `debugger`:idx: option enables or disables the *Embedded Nimrod Debugger*.
See the documentation of endb_ for further information.
Breakpoint pragma
-----------------
The *breakpoint* pragma was specially added for the sake of debugging with
ENDB. See the documentation of `endb <endb.html>`_ for further information.
Volatile pragma
---------------
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.
Debugging with Nimrod
=====================
Nimrod comes with its own *Embedded Nimrod Debugger*. See
the documentation of endb_ for further information.
Optimizing for Nimrod
=====================
Nimrod has no separate optimizer, but the C code that is produced is very
efficient. Most C compilers have excellent optimizers, so usually it is
not needed to optimize one's code. Nimrod has been designed to encourage
efficient code: The most readable code in Nimrod is often the most efficient
too.
However, sometimes one has to optimize. Do it in the following order:
1. switch off the embedded debugger (it is **slow**!)
2. turn on the optimizer and turn off runtime checks
3. profile your code to find where the bottlenecks are
4. try to find a better algorithm
5. do low-level optimizations
This section can only help you with the last item.
Optimizing string handling
--------------------------
String assignments are sometimes expensive in Nimrod: They are required to
copy the whole string. However, the compiler is often smart enough to not copy
strings. Due to the argument passing semantics, strings are never copied when
passed to subroutines. The compiler does not copy strings that are a result from
a procedure call, because the callee returns a new string anyway.
Thus it is efficient to do:
.. code-block:: Nimrod
var s = procA() # assignment will not copy the string; procA allocates a new
# string already
However it is not efficient to do:
.. code-block:: Nimrod
var s = varA # assignment has to copy the whole string into a new buffer!
..
String case statements are optimized too. A hashing scheme is used for them
if several different string constants are used. This is likely to be more
efficient than any hand-coded scheme.
..
The ECMAScript code generator
=============================
Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
longer. Help if you are interested.
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:,
since it is the proper term.
The ECMAScript code generator is experimental!
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser.
Since ECMAScript does not have a portable means to include another module,
Nimrod just generates a long ``.js`` file.
Features or modules that the ECMAScript platform does not support are not
available. This includes:
* manual memory management (``alloc``, etc.)
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
* file management
* most modules of the Standard library
* proper 64 bit integer arithmetic
* proper unsigned integer arithmetic
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are
available! To access the DOM, use the `dom`:idx: module that is only
available for the ECMAScript platform.

View File

@@ -5,16 +5,16 @@
:Author: Andreas Rumpf
:Version: |nimrodversion|
.. contents::
.. contents::
Introduction
============
This document describes the subset of `Docutils`_' `reStructuredText`_ as it
This document describes the subset of `Docutils`_' `reStructuredText`_ as it
has been implemented in the Nimrod compiler for generating documentation.
Elements of |rst| that are not listed here have not been implemented.
Elements of |rst| that are not listed here have not been implemented.
Unfortunately, the specification of |rst| is quite vague, so Nimrod is not as
compatible to the original implementation as one would like.
compatible to the original implementation as one would like.
Even though Nimrod's |rst| parser does not parse all constructs, it is pretty
usable. The missing features can easily be circumvented. An indication of this
@@ -26,13 +26,13 @@ Docutils' parser.)
Inline elements
===============
Ordinary text may contain *inline elements*.
Ordinary text may contain *inline elements*.
Bullet lists
============
*Bullet lists* look like this::
*Bullet lists* look like this::
* Item 1
* Item 2 that
@@ -60,8 +60,8 @@ Enumerated lists
*Enumerated lists*
Defintion lists
===============
Definition lists
================
Save this code to the file "greeting.nim". Now compile and run it:
@@ -77,14 +77,14 @@ appending them after the filename that is to be compiled and run:
Tables
======
Nimrod only implements simple tables of the form::
Nimrod only implements simple tables of the form::
================== =============== ===================
header 1 header 2 header n
================== =============== ===================
Cell 1 Cell 2 Cell 3
Cell 4 Cell 5; any Cell 6
cell that is
cell that is
not in column 1
may span over
multiple lines
@@ -97,7 +97,7 @@ header 1 header 2 header n
================== =============== ===================
Cell 1 Cell 2 Cell 3
Cell 4 Cell 5; any Cell 6
cell that is
cell that is
not in column 1
may span over
multiple lines

View File

@@ -1,3 +1,3 @@
# Hallo world program
# Hello world program
echo "Hallo world!"
echo "Hello world!"

View File

@@ -29,7 +29,7 @@ Iup.SetAttribute(box, "GAP", "10")
var dlg = Iup.Dialog(box)
Iup.SetAttribute(dlg, "TITLE", "IupTabs")
Iup.SetAttribute(dlg, "SIZE", "200x80")
Iup.SetAttribute(dlg, "SIZE", "200x100")
discard ShowXY(dlg, IUP_CENTER, IUP_CENTER)
discard MainLoop()

View File

@@ -6,4 +6,4 @@ import
#proc MessageBox(hWnd: int, lpText, lpCaption: CString, uType: uint): int
# {stdcall, import: "MessageBox", header: "<windows.h>"}
discard MessageBox(0, "Hallo World!", "Nimrod GUI application", 0)
discard MessageBox(0, "Hello World!", "Nimrod GUI Application", 0)

View File

@@ -26,10 +26,10 @@ type
proc on_about_menu_item_activate(menuItem: PGtkMenuItem,
e: var TMyTextEditor) {.cdecl.} =
gtk_show_about_dialog(e.window,
"comments", "A fast and leight-weight IDE for Nimrod",
"copyright", "Copyright \xc2\xa9 2008 Andreas Rumpf",
"comments", "A fast and lightweight IDE for Nimrod",
"copyright", "Copyright \xc2\xa9 2010 Andreas Rumpf",
"version", "0.1",
"website", "http://nimrod.ethexor.com",
"website", "http://force7.de/nimrod/",
"program-name", "Nimrod IDE",
nil)
@@ -70,7 +70,7 @@ proc write_file(e: var TMyTextEditor, filename: string) =
buffer: PGtkTextBuffer
start, ende: TGtkTextIter
# add Saving message to status bar and ensure GUI is current
gtk_statusbar_push(e.statusbar, e.statusbar_context_id, "Saving....")
gtk_statusbar_push(e.statusbar, e.statusbar_context_id, "Saving...")
while gtk_events_pending(): gtk_main_iteration()
# disable text view and get contents of buffer

View File

@@ -15,7 +15,7 @@ type
hbox: PGtkHBox
e: PEditor
PTab = ptr TTab
TEditor = object of TObject
window: PGtkWindow
statusbar: PGtkStatusBar
@@ -26,20 +26,20 @@ type
currTab: int
PEditor = ptr TEditor
proc onWindowDestroy(obj: PGtkObject, event: PGdkEvent,
proc onWindowDestroy(obj: PGtkObject, event: PGdkEvent,
data: pointer): gboolean {.cdecl.} =
gtkMainQuit()
proc onAboutMenuItemActivate(menuItem: PGtkMenuItem, e: PEditor) {.cdecl.} =
gtkShowAboutDialog(e.window,
"comments", "A fast and leight-weight IDE for Nimrod",
"copyright", "Copyright \xc2\xa9 2009 Andreas Rumpf",
"comments", "A fast and lightweight IDE for Nimrod",
"copyright", "Copyright \xc2\xa9 2010 Andreas Rumpf",
"version", "0.1",
"website", "http://nimrod.ethexor.com",
"website", "http://force7.de/nimrod/",
"program-name", "Nimrod IDE",
nil)
proc getTabIndex(e: PEditor, tab: PTab): int =
proc getTabIndex(e: PEditor, tab: PTab): int =
var i = 0
while true:
var w = gtkNotebookGetNthPage(e.notebook, i)
@@ -47,43 +47,43 @@ proc getTabIndex(e: PEditor, tab: PTab): int =
var v = gtkNotebookGetTabLabel(e.notebook, w)
if tab.hbox == v: return i
inc(i)
proc getActiveTab(e: PEditor): PTab =
proc getActiveTab(e: PEditor): PTab =
nil
type
TAnswer = enum
answerYes, answerNo, answerCancel
proc askWhetherToSave(e: PEditor): TAnswer =
var dialog = gtkDialogNewWithButtons("Should the changes be saved?",
proc askWhetherToSave(e: PEditor): TAnswer =
var dialog = gtkDialogNewWithButtons("Should the changes be saved?",
e.window, GTK_DIALOG_MODAL, GTK_STOCK_SAVE, 1, "gtk-discard", 2,
GTK_STOCK_CANCEL, 3, nil)
result = TAnswer(gtkDialogRun(dialog)+1)
gtkWidgetDestroy(dialog)
proc saveTab(tab: PTab) =
if tab.untitled:
proc saveTab(tab: PTab) =
if tab.untitled:
tab.filename = ChooseFileToSave(tab.e.window, getRoot(tab))
tab.untitled = false
XXX
proc OnCloseTab(button: PGtkButton, tab: PTab) {.cdecl.} =
proc OnCloseTab(button: PGtkButton, tab: PTab) {.cdecl.} =
var idx = -1
for i in 0..high(tab.e.tabs):
if tab.e.tabs[i] == tab:
for i in 0..high(tab.e.tabs):
if tab.e.tabs[i] == tab:
idx = i
break
if idx >= 0:
if idx >= 0:
if gtkTextBufferGetModified(gtkTextViewGetBuffer(tab.textView)):
case askWhetherToSave(tab.e)
of answerCancel: return
of answerYes: saveTab(tab)
of answerNo: nil
gtkNotebookRemovePage(tab.e.notebook, idx)
if idx < high(tab.e.tabs):
for i in idx..high(tab.e.tabs)-1:
for i in idx..high(tab.e.tabs)-1:
tab.e.tabs[i] = tab.e.tabs[i+1]
else:
dec currTab
@@ -92,7 +92,7 @@ proc OnCloseTab(button: PGtkButton, tab: PTab) {.cdecl.} =
#var idx = getTabIndex(tab.e, tab)
#if idx >= 0: gtk_notebook_remove_page(tab.e.notebook, idx)
proc createTab(e: PEditor, filename: string, untitled: bool) =
proc createTab(e: PEditor, filename: string, untitled: bool) =
var t = cast[PTab](alloc0(sizeof(TTab)))
t.textview = gtkTextViewNewWithBuffer(gtkTextBufferNew(nil))
var fontDesc = pangoFontDescriptionFromString("monospace 10")
@@ -104,7 +104,7 @@ proc createTab(e: PEditor, filename: string, untitled: bool) =
var scroll = gtkScrolledWindowNew(nil, nil)
gtkContainerAdd(scroll, t.textview)
gtkWidgetShow(scroll)
t.e = e
t.hbox = gtkHboxNew(false, 0)
var image = gtkImageNewFromStock(GTK_STOCK_CLOSE, GTK_ICON_SIZE_MENU)
@@ -114,16 +114,16 @@ proc createTab(e: PEditor, filename: string, untitled: bool) =
gtkButtonSetRelief(button, GTK_RELIEF_NONE)
gtkBoxPackStart(t.hbox, lab, false, false, 2)
gtkBoxPackEnd(t.hbox, button, false, false, 0)
discard gSignalConnect(button, "clicked", G_Callback(onCloseTab), t)
gtkWidgetShow(button)
gtkWidgetShow(lab)
var idx = gtkNotebookAppendPage(e.notebook, scroll, t.hbox)
e.currTab = idx
add(e.tabs, t)
gtkNotebookSetCurrentPage(e.notebook, idx)
proc onOpenMenuItemActivate(menuItem: PGtkMenuItem, e: PEditor) {.cdecl.} =
var files = ChooseFilesToOpen(e.window, getRoot(getActiveTab(e)))
@@ -131,8 +131,8 @@ proc onOpenMenuItemActivate(menuItem: PGtkMenuItem, e: PEditor) {.cdecl.} =
proc onSaveMenuItemActivate(menuItem: PGtkMenuItem, e: PEditor) {.cdecl.} =
var cp = gtkNotebookGetCurrentPage(e.notebook)
proc onSaveAsMenuItemActivate(menuItem: PGtkMenuItem, e: PEditor) {.cdecl.} =
nil
@@ -140,7 +140,7 @@ proc onNewMenuItemActivate(menuItem: PGtkMenuItem, e: PEditor) {.cdecl.} =
inc(e.tabname)
createTab(e, "untitled-" & $e.tabname, true)
proc main(e: PEditor) =
proc main(e: PEditor) =
var builder = gladeXmlNew(getApplicationDir() / GuiTemplate, nil, nil)
if builder == nil: quit("cannot open: " & GuiTemplate)
# get the components:
@@ -155,27 +155,27 @@ proc main(e: PEditor) =
gladeXmlSignalConnect(builder, "on_window_destroy",
GCallback(onWindowDestroy))
var about = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "about_menu_item"))
discard gSignalConnect(about, "activate",
discard gSignalConnect(about, "activate",
G_CALLBACK(onAboutMenuItemActivate), e)
var newItem = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "new_menu_item"))
discard gSignalConnect(newItem, "activate",
discard gSignalConnect(newItem, "activate",
G_CALLBACK(onNewMenuItemActivate), e)
var quitItem = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "quit_menu_item"))
discard gSignalConnect(quitItem, "activate",
discard gSignalConnect(quitItem, "activate",
G_CALLBACK(onWindowDestroy), e)
var openItem = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "open_menu_item"))
discard gSignalConnect(openItem, "activate",
discard gSignalConnect(openItem, "activate",
G_CALLBACK(onOpenMenuItemActivate), e)
var saveItem = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "save_menu_item"))
discard gSignalConnect(saveItem, "activate",
var saveItem = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "save_menu_item"))
discard gSignalConnect(saveItem, "activate",
G_CALLBACK(onSaveMenuItemActivate), e)
var saveAsItem = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "save_as_menu_item"))
discard gSignalConnect(saveAsItem, "activate",
var saveAsItem = GTK_MENU_ITEM(gladeXmlGetWidget(builder, "save_as_menu_item"))
discard gSignalConnect(saveAsItem, "activate",
G_CALLBACK(onSaveAsMenuItemActivate), e)
gtkWindowSetDefaultIconName(GTK_STOCK_EDIT)

View File

@@ -7,19 +7,19 @@
# distribution, for details about the copyright.
#
## This module implements a simple HTTP-Server.
## This module implements a simple HTTP-Server.
##
## Example:
## Example:
##
## .. code-block:: nimrod
## import strutils, sockets, httpserver
##
##
## var counter = 0
## proc handleRequest(client: TSocket, path, query: string): bool {.procvar.} =
## inc(counter)
## client.send("Hallo for the $#th time." % $counter & wwwNL)
## client.send("Hello for the $#th time." % $counter & wwwNL)
## return false # do not stop processing
##
##
## run(handleRequest, TPort(80))
##
@@ -47,7 +47,7 @@ proc cannotExec(client: TSocket) =
sendTextContentType(client)
send(client, "<P>Error prohibited CGI execution." & wwwNL)
proc headers(client: TSocket, filename: string) =
proc headers(client: TSocket, filename: string) =
# XXX could use filename to determine file type
send(client, "HTTP/1.0 200 OK" & wwwNL)
send(client, ServerSig)
@@ -60,16 +60,16 @@ proc notFound(client: TSocket) =
send(client, "<html><title>Not Found</title>" & wwwNL)
send(client, "<body><p>The server could not fulfill" & wwwNL)
send(client, "your request because the resource specified" & wwwNL)
send(client, "is unavailable or nonexistent." & wwwNL)
send(client, "is unavailable or nonexistent.</p>" & wwwNL)
send(client, "</body></html>" & wwwNL)
proc unimplemented(client: TSocket) =
send(client, "HTTP/1.0 501 Method Not Implemented" & wwwNL)
send(client, ServerSig)
sendTextContentType(client)
send(client, "<html><head><title>Method Not Implemented" &
send(client, "<html><head><title>Method Not Implemented" &
"</title></head>" &
"<body><p>HTTP request method not supported." &
"<body><p>HTTP request method not supported.</p>" &
"</body></HTML>" & wwwNL)
# ----------------- file serving ---------------------------------------------
@@ -78,7 +78,7 @@ proc discardHeaders(client: TSocket) = skip(client)
proc serveFile(client: TSocket, filename: string) =
discardHeaders(client)
var f: TFile
if open(f, filename):
headers(client, filename)
@@ -109,7 +109,7 @@ proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) =
case meth
of reqGet:
discardHeaders(client)
env["REQUEST_METHOD"] = "GET"
env["QUERY_STRING"] = query
of reqPost:
@@ -122,16 +122,16 @@ proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) =
var i = len("content-length:")
while L[i] in Whitespace: inc(i)
contentLength = parseInt(copy(L, i))
if contentLength < 0:
badRequest(client)
return
env["REQUEST_METHOD"] = "POST"
env["CONTENT_LENGTH"] = $contentLength
send(client, "HTTP/1.0 200 OK" & wwwNL)
var process = startProcess(command=path, env=env)
if meth == reqPost:
# get from client and post to CGI program:
@@ -139,7 +139,7 @@ proc executeCgi(client: TSocket, path, query: string, meth: TRequestMethod) =
if recv(client, buf, contentLength) != contentLength: OSError()
var inp = process.inputStream
inp.writeData(inp, buf, contentLength)
var outp = process.outputStream
while running(process) or not outp.atEnd(outp):
var line = outp.readLine()
@@ -165,11 +165,11 @@ proc acceptRequest(client: TSocket) =
meth = reqPost
else:
unimplemented(client)
var path = data[1]
if path[path.len-1] == '/' or existsDir(path):
path = path / "index.html"
if not ExistsFile(path):
discardHeaders(client)
notFound(client)
@@ -193,15 +193,15 @@ type
port: TPort
client*: TSocket ## the socket to write the file data to
path*, query*: string ## path and query the client requested
proc open*(s: var TServer, port = TPort(80)) =
proc open*(s: var TServer, port = TPort(80)) =
## creates a new server at port `port`. If ``port == 0`` a free port is
## aquired that can be accessed later by the ``port`` proc.
## acquired that can be accessed later by the ``port`` proc.
s.socket = socket(AF_INET)
if s.socket == InvalidSocket: OSError()
bindAddr(s.socket, port)
listen(s.socket)
if port == TPort(0):
s.port = getSockName(s.socket)
else:
@@ -209,12 +209,12 @@ proc open*(s: var TServer, port = TPort(80)) =
s.client = InvalidSocket
s.path = ""
s.query = ""
proc port*(s: var TServer): TPort =
## get the port number the server has aquired.
proc port*(s: var TServer): TPort =
## get the port number the server has acquired.
result = s.port
proc next*(s: var TServer) =
proc next*(s: var TServer) =
## proceed to the first/next request.
s.client = accept(s.socket)
headers(s.client, "")
@@ -236,13 +236,13 @@ proc close*(s: TServer) =
## closes the server (and the socket the server uses).
close(s.socket)
proc run*(handleRequest: proc (client: TSocket, path, query: string): bool,
proc run*(handleRequest: proc (client: TSocket, path, query: string): bool,
port = TPort(80)) =
## encapsulates the server object and main loop
var s: TServer
open(s, port)
#echo("httpserver running on port ", s.port)
while true:
while true:
next(s)
if handleRequest(s.client, s.path, s.query): break
close(s.client)
@@ -252,8 +252,8 @@ when isMainModule:
var counter = 0
proc handleRequest(client: TSocket, path, query: string): bool {.procvar.} =
inc(counter)
client.send("Hallo, Andreas for the $#th time." % $counter & wwwNL)
client.send("Hello, Andreas, for the $#th time." % $counter & wwwNL)
return false # do not stop processing
run(handleRequest, TPort(80))

View File

@@ -57,7 +57,7 @@ proc execCmd*(command: string): int
proc executeCommand*(command: string): int {.deprecated.} =
## **Deprecated since version 0.8.2**: Use `execCmd` instead.
result = execCmd(command)
proc startProcess*(command: string,
workingDir: string = "",
@@ -115,7 +115,7 @@ when defined(macosx) or defined(bsd):
a: var int, b: pointer, c: int): cint {.
importc: "sysctl", header: "<sys/sysctl.h>".}
proc countProcessors*(): int =
proc countProcessors*(): int =
## returns the numer of the processors/cores the machine has.
## Returns 0 if it cannot be determined.
when defined(windows):
@@ -186,7 +186,7 @@ proc execProcesses*(cmds: openArray[string],
inc(i)
if i > high(cmds): break
for i in 0..m-1:
result = max(waitForExit(q[i]), result)
result = max(waitForExit(q[i]), result)
else:
for i in 0..high(cmds):
var p = startProcessAux(cmds[i], options=options)
@@ -243,7 +243,7 @@ when defined(Windows):
if a == 0 and br != 0: OSError()
s.atTheEnd = br < bufLen
result = br
proc hsWriteData(s: PFileHandleStream, buffer: pointer, bufLen: int) =
var bytesWritten: int32
var a = winlean.writeFile(s.handle, buffer, bufLen, bytesWritten, nil)
@@ -256,10 +256,10 @@ when defined(Windows):
result.atEnd = hsAtEnd
result.readData = hsReadData
result.writeData = hsWriteData
proc buildCommandLine(a: string, args: openarray[string]): cstring =
var res = quoteIfContainsWhite(a)
for i in 0..high(args):
for i in 0..high(args):
res.add(' ')
res.add(quoteIfContainsWhite(args[i]))
result = cast[cstring](alloc0(res.len+1))
@@ -324,7 +324,7 @@ when defined(Windows):
result.inputHandle = si.hStdInput
result.outputHandle = si.hStdOutput
result.errorHandle = si.hStdError
var cmdl: cstring
if false: # poUseShell in options:
cmdl = buildCommandLine(getEnv("COMSPEC"), @["/c", command] & args)
@@ -337,13 +337,13 @@ when defined(Windows):
if poEchoCmd in options: echo($cmdl)
success = winlean.CreateProcess(nil,
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo)
if poParentStreams notin options:
FileClose(si.hStdInput)
FileClose(si.hStdOutput)
if poStdErrToStdOut notin options:
FileClose(si.hStdError)
if e != nil: dealloc(e)
dealloc(cmdl)
if success == 0: OSError()
@@ -382,7 +382,7 @@ when defined(Windows):
proc errorStream(p: PProcess): PStream =
result = newFileHandleStream(p.errorHandle)
proc execCmd(command: string): int =
proc execCmd(command: string): int =
var
SI: TStartupInfo
ProcInfo: TProcessInformation
@@ -535,7 +535,7 @@ else:
proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
proc execCmd(command: string): int =
proc execCmd(command: string): int =
result = csystem(command)
when isMainModule:

File diff suppressed because it is too large Load Diff

View File

@@ -9,12 +9,12 @@
## This module implements Nimrod's support for the ``variant`` datatype.
## `TVariant` shows how the flexibility of dynamic typing is achieved
## within a static type system.
## within a static type system.
type
TVarType* = enum
vtNone,
vtBool,
vtBool,
vtChar,
vtEnum,
vtInt,
@@ -31,7 +31,7 @@ type
of vtString: vstring: string
of vtSet, vtSeq: q: seq[TVariant]
of vtDict: d: seq[tuple[key, val: TVariant]]
iterator objectFields*[T](x: T, skipInherited: bool): tuple[
key: string, val: TVariant] {.magic: "ObjectFields"}
@@ -74,10 +74,10 @@ proc `?`* [T: object](x: T): TVariant {.magic: "ToVariant".}
proc `><`*[T](v: TVariant, typ: T): T {.magic: "FromVariant".}
?[?5, ?67, ?"hallo"]
?[?5, ?67, ?"hello"]
myVar?int
proc `==`* (x, y: TVariant): bool =
if x.vtype == y.vtype:
case x.vtype
@@ -139,7 +139,7 @@ proc `[]=`* (a, b, c: TVariant) =
a.d[b.vint].val = c
variantError()
else: variantError()
proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[?b]
proc `[]`* (a: TVariant, b: string): TVariant {.inline} = return a[?b]
proc `[]=`* (a: TVariant, b: int, c: TVariant) {.inline} = a[?b] = c
@@ -154,9 +154,9 @@ proc `+`* (x, y: TVariant): TVariant =
else:
case y.vtype
of vtBool, vtChar, vtEnum, vtInt:
vint: int64
of vtFloat: vfloat: float64
of vtString: vstring: string
@@ -171,11 +171,11 @@ proc `mod`* (x, y: TVariant): TVariant
proc `&`* (x, y: TVariant): TVariant
proc `$`* (x: TVariant): string =
# uses JS notation
proc parseVariant*(s: string): TVariant
proc `<`* (x, y: TVariant): bool
proc `<=`* (x, y: TVariant): bool
proc hash*(x: TVariant): int =

19
lib/system.nim Executable file → Normal file
View File

@@ -10,7 +10,7 @@
## The compiler depends on the System module to work properly and the System
## module depends on the compiler. Most of the routines listed here use
## special compiler magic.
## Each module implicitly imports the System module; it may not be listed
## Each module implicitly imports the System module; it must not be listed
## explicitly. Because of this there cannot be a user-defined module named
## ``system``.
@@ -45,7 +45,7 @@ type
## a type description (for templates)
proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
## Special comile-time procedure that checks whether `x` is
## Special compile-time procedure that checks whether `x` is
## defined. `x` has to be an identifier or a qualified identifier.
## This can be used to check whether a library provides a certain
## feature or not:
@@ -57,7 +57,7 @@ proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.}
proc definedInScope*[T](x: T): bool {.
magic: "DefinedInScope", noSideEffect.}
## Special comile-time procedure that checks whether `x` is
## Special compile-time procedure that checks whether `x` is
## defined in the current scope. `x` has to be an identifier.
proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
@@ -65,11 +65,11 @@ proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.}
proc `and`*(x, y: bool): bool {.magic: "And", noSideEffect.}
## Boolean ``and``; returns true iff ``x == y == true``.
## Evaluation is short-circuited: This means that if ``x`` is false,
## Evaluation is short-circuited: this means that if ``x`` is false,
## ``y`` will not even be evaluated.
proc `or`*(x, y: bool): bool {.magic: "Or", noSideEffect.}
## Boolean ``or``; returns true iff ``not (not x and not y)``.
## Evaluation is short-circuited: This means that if ``x`` is true,
## Evaluation is short-circuited: this means that if ``x`` is true,
## ``y`` will not even be evaluated.
proc `xor`*(x, y: bool): bool {.magic: "Xor", noSideEffect.}
## Boolean `exclusive or`; returns true iff ``x != y``.
@@ -165,7 +165,7 @@ type
EOS* = object of ESystem ## raised if an operating system service failed.
EInvalidLibrary* = object of EOS ## raised if a dynamic library
## could not be loaded.
ERessourceExhausted* = object of ESystem ## raised if a ressource request
EResourceExhausted* = object of ESystem ## raised if a resource request
## could not be fullfilled.
EArithmetic* = object of ESynch ## raised if any kind of arithmetic
## error occured.
@@ -962,7 +962,7 @@ proc `$` *(x: Cstring): string {.magic: "CStrToStr", noSideEffect.}
proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.}
## The stingify operator for a string argument. Returns `x`
## as it is. This operator is useful for generic code, so
## that ``$expr`` also works if ``expr`` already is a string.
## that ``$expr`` also works if ``expr`` is already a string.
proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.}
## The stingify operator for an enumeration argument. This works for
@@ -1191,6 +1191,11 @@ proc each*[T, S](data: openArray[T], op: proc (x: T): S): seq[S] {.
newSeq(result, data.len)
for i in 0..data.len-1: result[i] = op(data[i])
proc each*[T](data: openArray[T], op: proc (x: T)) =
## The well-known ``map`` operation from functional programming. Applies
## `op` to every item in `data`.
for i in 0..data.len-1: op(data[i])
# ----------------- FPU ------------------------------------------------------

View File

@@ -104,7 +104,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
# These routines should be used like following:
# <Nimrod code>
# s &= "hallo " & name & " how do you feel?"
# s &= "Hello " & name & ", how do you feel?"
#
# <generated C code>
# {
@@ -115,7 +115,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
# }
#
# <Nimrod code>
# s = "hallo " & name & " how do you feel?"
# s = "Hello " & name & ", how do you feel?"
#
# <generated C code>
# {
@@ -180,8 +180,8 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
result = cast[PGenericSeq](newSeq(extGetCellType(seq), s))
genericSeqAssign(result, seq, XXX)
#copyMem(result, seq, seq.len * elemSize + GenericSeqSize)
inc(result.len)
else:
inc(result.len)
else:
result = seq
if result.len >= result.space:
result.space = resize(result.space)
@@ -214,7 +214,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
# we need to decref here, otherwise the GC leaks!
when not defined(boehmGC) and not defined(nogc):
for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
GenericSeqSize +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef)
# and set the memory to nil:

197
lib/windows/psapi.nim Normal file
View File

@@ -0,0 +1,197 @@
#
#
# Nimrod's Runtime Library
# (c) Copyright 2009 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
# PSAPI interface unit
# Contains the definitions for the APIs provided by PSAPI.DLL
import # Data structure templates
Windows
proc EnumProcesses*(lpidProcess: ptr DWORD, cb: DWORD, cbNeeded: ptr DWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EnumProcesses".}
proc EnumProcessModules*(hProcess: HANDLE, lphModule: ptr HMODULE, cb: DWORD, lpcbNeeded: LPDWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EnumProcessModules".}
proc GetModuleBaseNameA*(hProcess: HANDLE, hModule: HMODULE, lpBaseName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleBaseNameA".}
proc GetModuleBaseNameW*(hProcess: HANDLE, hModule: HMODULE, lpBaseName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleBaseNameW".}
when defined(winUnicode):
proc GetModuleBaseName*(hProcess: HANDLE, hModule: HMODULE, lpBaseName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleBaseNameW".}
else:
proc GetModuleBaseName*(hProcess: HANDLE, hModule: HMODULE, lpBaseName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleBaseNameA".}
proc GetModuleFileNameExA*(hProcess: HANDLE, hModule: HMODULE, lpFileNameEx: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleFileNameExA".}
proc GetModuleFileNameExW*(hProcess: HANDLE, hModule: HMODULE, lpFileNameEx: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleFileNameExW".}
when defined(winUnicode):
proc GetModuleFileNameEx*(hProcess: HANDLE, hModule: HMODULE, lpFileNameEx: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleFileNameExW".}
else:
proc GetModuleFileNameEx*(hProcess: HANDLE, hModule: HMODULE, lpFileNameEx: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleFileNameExA".}
type
MODULEINFO* {.final.} = object
lpBaseOfDll*: LPVOID
SizeOfImage*: DWORD
EntryPoint*: LPVOID
LPMODULEINFO* = ptr MODULEINFO
proc GetModuleInformation*(hProcess: HANDLE, hModule: HMODULE, lpmodinfo: LPMODULEINFO, cb: DWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "GetModuleInformation".}
proc EmptyWorkingSet*(hProcess: HANDLE): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EmptyWorkingSet".}
proc QueryWorkingSet*(hProcess: HANDLE, pv: PVOID, cb: DWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "QueryWorkingSet".}
proc QueryWorkingSetEx*(hProcess: HANDLE, pv: PVOID, cb: DWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "QueryWorkingSetEx".}
proc InitializeProcessForWsWatch*(hProcess: HANDLE): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "InitializeProcessForWsWatch".}
type
PSAPI_WS_WATCH_INFORMATION* {.final.} = object
FaultingPc*: LPVOID
FaultingVa*: LPVOID
PPSAPI_WS_WATCH_INFORMATION* = ptr PSAPI_WS_WATCH_INFORMATION
proc GetWsChanges*(hProcess: HANDLE, lpWatchInfo: PPSAPI_WS_WATCH_INFORMATION, cb: DWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "GetWsChanges".}
proc GetMappedFileNameA*(hProcess: HANDLE, lpv: LPVOID, lpFilename: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetMappedFileNameA".}
proc GetMappedFileNameW*(hProcess: HANDLE, lpv: LPVOID, lpFilename: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetMappedFileNameW".}
when defined(winUnicode):
proc GetMappedFileName*(hProcess: HANDLE, lpv: LPVOID, lpFilename: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetMappedFileNameW".}
else:
proc GetMappedFileName*(hProcess: HANDLE, lpv: LPVOID, lpFilename: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetMappedFileNameA".}
proc EnumDeviceDrivers*(lpImageBase: LPVOID, cb: DWORD, lpcbNeeded: LPDWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EnumDeviceDrivers".}
proc GetDeviceDriverBaseNameA*(ImageBase: LPVOID, lpBaseName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverBaseNameA".}
proc GetDeviceDriverBaseNameW*(ImageBase: LPVOID, lpBaseName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverBaseNameW".}
when defined(winUnicode):
proc GetDeviceDriverBaseName*(ImageBase: LPVOID, lpBaseName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverBaseNameW".}
else:
proc GetDeviceDriverBaseName*(ImageBase: LPVOID, lpBaseName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverBaseNameA".}
proc GetDeviceDriverFileNameA*(ImageBase: LPVOID, lpFileName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverFileNameA".}
proc GetDeviceDriverFileNameW*(ImageBase: LPVOID, lpFileName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverFileNameW".}
when defined(winUnicode):
proc GetDeviceDriverFileName*(ImageBase: LPVOID, lpFileName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverFileNameW".}
else:
proc GetDeviceDriverFileName*(ImageBase: LPVOID, lpFileName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetDeviceDriverFileNameA".}
type
PROCESS_MEMORY_COUNTERS* {.final.} = object
cb*: DWORD
PageFaultCount*: DWORD
PeakWorkingSetSize: SIZE_T
WorkingSetSize: SIZE_T
QuotaPeakPagedPoolUsage: SIZE_T
QuotaPagedPoolUsage: SIZE_T
QuotaPeakNonPagedPoolUsage: SIZE_T
QuotaNonPagedPoolUsage: SIZE_T
PagefileUsage: SIZE_T
PeakPagefileUsage: SIZE_T
PPROCESS_MEMORY_COUNTERS* = ptr PROCESS_MEMORY_COUNTERS
type
PROCESS_MEMORY_COUNTERS_EX* {.final.} = object
cb*: DWORD
PageFaultCount*: DWORD
PeakWorkingSetSize: SIZE_T
WorkingSetSize: SIZE_T
QuotaPeakPagedPoolUsage: SIZE_T
QuotaPagedPoolUsage: SIZE_T
QuotaPeakNonPagedPoolUsage: SIZE_T
QuotaNonPagedPoolUsage: SIZE_T
PagefileUsage: SIZE_T
PeakPagefileUsage: SIZE_T
PrivateUsage: SIZE_T
PPROCESS_MEMORY_COUNTERS_EX* = ptr PROCESS_MEMORY_COUNTERS_EX
proc GetProcessMemoryInfo*(hProcess: HANDLE, ppsmemCounters: PPROCESS_MEMORY_COUNTERS, cb: DWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "GetProcessMemoryInfo".}
type
PERFORMANCE_INFORMATION* {.final.} = object
cb*: DWORD
CommitTotal: SIZE_T
CommitLimit: SIZE_T
CommitPeak: SIZE_T
PhysicalTotal: SIZE_T
PhysicalAvailable: SIZE_T
SystemCache: SIZE_T
KernelTotal: SIZE_T
KernelPaged: SIZE_T
KernelNonpaged: SIZE_T
PageSize: SIZE_T
HandleCount*: DWORD
ProcessCount*: DWORD
ThreadCount*: DWORD
PPERFORMANCE_INFORMATION* = ptr PERFORMANCE_INFORMATION
# Skip definition of PERFORMACE_INFORMATION...
proc GetPerformanceInfo*(pPerformanceInformation: PPERFORMANCE_INFORMATION, cb: DWORD): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "GetPerformanceInfo".}
type
ENUM_PAGE_FILE_INFORMATION* {.final.} = object
cb*: DWORD
Reserved*: DWORD
TotalSize: SIZE_T
TotalInUse: SIZE_T
PeakUsage: SIZE_T
PENUM_PAGE_FILE_INFORMATION* = ptr ENUM_PAGE_FILE_INFORMATION
# Callback procedure
type
PENUM_PAGE_FILE_CALLBACKW* = proc (pContext: LPVOID, pPageFileInfo: PENUM_PAGE_FILE_INFORMATION, lpFilename: LPCWSTR): WINBOOL{.stdcall.}
PENUM_PAGE_FILE_CALLBACKA* = proc (pContext: LPVOID, pPageFileInfo: PENUM_PAGE_FILE_INFORMATION, lpFilename: LPCSTR): WINBOOL{.stdcall.}
#TODO
proc EnumPageFilesA*(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKA, pContext: LPVOID): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EnumPageFilesA".}
proc EnumPageFilesW*(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKW, pContext: LPVOID): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EnumPageFilesW".}
when defined(winUnicode):
proc EnumPageFiles*(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKW, pContext: LPVOID): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EnumPageFilesW".}
type PENUM_PAGE_FILE_CALLBACK* = proc (pContext: LPVOID, pPageFileInfo: PENUM_PAGE_FILE_INFORMATION, lpFilename: LPCWSTR): WINBOOL{.stdcall.}
else:
proc EnumPageFiles*(pCallBackRoutine: PENUM_PAGE_FILE_CALLBACKA, pContext: LPVOID): WINBOOL {.stdcall,
dynlib: "psapi.dll", importc: "EnumPageFilesA".}
type PENUM_PAGE_FILE_CALLBACK* = proc (pContext: LPVOID, pPageFileInfo: PENUM_PAGE_FILE_INFORMATION, lpFilename: LPCSTR): WINBOOL{.stdcall.}
proc GetProcessImageFileNameA*(hProcess: HANDLE, lpImageFileName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetProcessImageFileNameA".}
proc GetProcessImageFileNameW*(hProcess: HANDLE, lpImageFileName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetProcessImageFileNameW".}
when defined(winUnicode):
proc GetProcessImageFileName*(hProcess: HANDLE, lpImageFileName: LPWSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetProcessImageFileNameW".}
else:
proc GetProcessImageFileName*(hProcess: HANDLE, lpImageFileName: LPSTR, nSize: DWORD): DWORD {.stdcall,
dynlib: "psapi.dll", importc: "GetProcessImageFileNameA".}

File diff suppressed because it is too large Load Diff

View File

@@ -9,12 +9,12 @@
## This module implements Nimrod's support for the ``variant`` datatype.
## `TVariant` shows how the flexibility of dynamic typing is achieved
## within a static type system.
## within a static type system.
type
TVarType* = enum
vtNone,
vtBool,
vtBool,
vtChar,
vtEnum,
vtInt,
@@ -31,7 +31,7 @@ type
of vtString: vstring: string
of vtSet, vtSeq: q: seq[TVariant]
of vtDict: d: seq[tuple[key, val: TVariant]]
iterator objectFields*[T](x: T, skipInherited: bool): tuple[
key: string, val: TVariant] {.magic: "ObjectFields"}
@@ -74,10 +74,10 @@ proc `<>`* [T: object](x: T): TVariant {.magic: "ToVariant".}
proc `><`*[T](v: TVariant, typ: T): T {.magic: "FromVariant".}
[<>5, <>67, <>"hallo"]
[<>5, <>67, <>"hello"]
myVar><int
proc `==`* (x, y: TVariant): bool =
if x.vtype == y.vtype:
case x.vtype
@@ -139,7 +139,7 @@ proc `[]=`* (a, b, c: TVariant) =
a.d[b.vint].val = c
variantError()
else: variantError()
proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[<>b]
proc `[]`* (a: TVariant, b: string): TVariant {.inline} = return a[<>b]
proc `[]=`* (a: TVariant, b: int, c: TVariant) {.inline} = a[<>b] = c
@@ -154,9 +154,9 @@ proc `+`* (x, y: TVariant): TVariant =
else:
case y.vtype
of vtBool, vtChar, vtEnum, vtInt:
vint: int64
of vtFloat: vfloat: float64
of vtString: vstring: string
@@ -171,11 +171,11 @@ proc `mod`* (x, y: TVariant): TVariant
proc `&`* (x, y: TVariant): TVariant
proc `$`* (x: TVariant): string =
# uses JS notation
proc parseVariant*(s: string): TVariant
proc `<`* (x, y: TVariant): bool
proc `<=`* (x, y: TVariant): bool
proc hash*(x: TVariant): int =

View File

@@ -104,7 +104,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
# These routines should be used like following:
# <Nimrod code>
# s &= "hallo " & name & " how do you feel?"
# s &= "Hello " & name & ", how do you feel?"
#
# <generated C code>
# {
@@ -115,7 +115,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
# }
#
# <Nimrod code>
# s = "hallo " & name & " how do you feel?"
# s = "Hello " & name & ", how do you feel?"
#
# <generated C code>
# {
@@ -180,8 +180,8 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
result = cast[PGenericSeq](newSeq(extGetCellType(seq), s))
genericSeqAssign(result, seq, XXX)
#copyMem(result, seq, seq.len * elemSize + GenericSeqSize)
inc(result.len)
else:
inc(result.len)
else:
result = seq
if result.len >= result.space:
result.space = resize(result.space)
@@ -214,7 +214,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
# we need to decref here, otherwise the GC leaks!
when not defined(boehmGC) and not defined(nogc):
for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
GenericSeqSize +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef)
# and set the memory to nil:

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,3 @@
# Simplest Nimrod program
echo "Hallo, World!"
echo "Hello, World!"

View File

@@ -36,7 +36,7 @@ macrotest(stdout)
#GC_disable()
echo("This was compiled by Nimrod version " & system.nimrodVersion)
writeln(stdout, "Hallo", " World", "!")
writeln(stdout, "Hello", " World", "!")
echo(["a", "b", "c", "d"].len)
for x in items(["What's", "your", "name", "?", ]):
@@ -51,7 +51,7 @@ var testseq: seq[string] = @[
]
echo(repr(testseq))
var dummy = "hallo"
var dummy = "hello"
echo(copy(dummy, 2, 3))
echo($meC)
@@ -60,11 +60,11 @@ echo($meC)
for x, y in items([(1, 2), (3, 4), (6, 1), (5, 2)]):
echo x
echo y
proc simpleConst(): int = return 34
# test constant evaluation:
const
# test constant evaluation:
const
constEval3 = simpleConst()
constEval = "abc".contains('b')
constEval2 = fac(7)

View File

@@ -1,7 +1,7 @@
# test the file-IO
proc main() =
for line in lines("thallo.nim"):
for line in lines("thello.nim"):
writeln(stdout, line)
main()

View File

@@ -57,7 +57,7 @@ proc Foo(n: int): int =
while b:
a = a + 3
a = a + 5
write(stdout, "Hallo!")
write(stdout, "Hello!")
# We should come till here :-)

View File

@@ -2,6 +2,6 @@ import streams
var outp = newFileStream(stdout)
var inp = newFileStream(stdin)
write(outp, "Hallo! What is your name?")
write(outp, "Hello! What is your name?")
var line = readLine(inp)
write(outp, "nice name: " & line)
write(outp, "Nice name: " & line)

View File

@@ -1,2 +1,2 @@
# Test the new initialization for modules
write(stdout, "Hallo from module! ")
write(stdout, "Hello from module! ")

View File

@@ -4,7 +4,7 @@ import tbintree
var
root: PBinaryTree[string]
x = newNode("hallo")
x = newNode("hello")
add(root, x)
add(root, "world")
if find(root, "world"):
@@ -21,5 +21,5 @@ add(r2, 99)
for y in items(r2):
stdout.write(y)
#OUT halloworld99110223
#OUT helloworld99110223

View File

@@ -35,12 +35,12 @@ proc add*[Ty](root: var PBinaryTree[Ty], data: Ty) =
# convenience proc:
add(root, newNode(data))
proc find*[Ty2](b: PBinaryTree[Ty2], data: Ty2): bool =
proc find*[Ty2](b: PBinaryTree[Ty2], data: Ty2): bool =
# for testing this needs to be recursive, so that the
# instantiated type is checked for proper tyGenericInst envelopes
if b == nil:
if b == nil:
result = false
else:
else:
var c = cmp(data, b.data)
if c < 0: result = find(b.le, data)
elif c > 0: result = find(b.ri, data)
@@ -66,7 +66,7 @@ iterator items*[T](root: PBinaryTree[T]): T =
while n != nil:
add(stack, n)
n = n.le
if stack.len > 0:
if stack.len > 0:
n = stack.pop()
yield n.data
n = n.ri
@@ -81,7 +81,7 @@ proc debug[T](a: PBinaryTree[T]) =
when isMainModule:
var
root: PBinaryTree[string]
x = newNode("hallo")
x = newNode("hello")
add(root, x)
add(root, "world")
if find(root, "world"):
@@ -89,7 +89,7 @@ when isMainModule:
stdout.write(str)
else:
stdout.writeln("BUG")
var
r2: PBinaryTree[int]
add(r2, newNode(110))
@@ -98,4 +98,4 @@ when isMainModule:
for y in items(r2):
stdout.write(y)
#OUT halloworld99110223
#OUT helloworld99110223

View File

@@ -2,5 +2,5 @@
import minit
write(stdout, "Hallo from main module!\n")
#OUT Hallo from module! Hallo from main module!
write(stdout, "Hello from main module!\n")
#OUT Hello from module! Hello from main module!

View File

@@ -3,5 +3,5 @@
proc write(t: TFile, s: string) =
nil # a nop
system.write(stdout, "hallo")
#OUT hallo
system.write(stdout, "hello")
#OUT hello

View File

@@ -23,7 +23,7 @@ proc mypos(sub, s: string, start: int = 0): int =
else:
result = -1
var sub = "hallo"
var s = "world hallo"
var sub = "hello"
var s = "world hello"
write(stdout, mypos(sub, s))
#OUT 6

View File

@@ -2,7 +2,7 @@
import strutils
var x = "hallo world!".toLower.toUpper
var x = "hello world!".toLower.toUpper
x.echo()
#OUT HALLO WORLD!
#OUT HELLO WORLD!

10
tests/tenuminh.nim Normal file
View File

@@ -0,0 +1,10 @@
type
TCardPts = enum
North, West, South, East
TCardPts2 = enum of TCardPts
N, W, S, E
# If I do:
var y = W
echo($y & "=" & $ord(y)) #OUT W=5