Integrating my changes, mostly minor/cosmetic fixes; plus a big Windows lib update

This commit is contained in:
PhiLho 2010-05-21 16:03:21 +02:00
commit 286e5958d6
37 changed files with 30552 additions and 30077 deletions

View file

@ -10,7 +10,7 @@ Advanced options:
--warning[X]:on|off turn specific warning X on|off --warning[X]:on|off turn specific warning X on|off
--hints:on|off turn all hints on|off --hints:on|off turn all hints on|off
--hint[X]:on|off turn specific hint X 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 -c, --compileOnly compile only; do not assemble or link
--noLinking compile but do not link --noLinking compile but do not link
--noMain do not generate a main procedure --noMain do not generate a main procedure

View file

@ -10,21 +10,21 @@ a `base type`:idx:.
Use case 1: SQL strings 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 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 .. code-block:: nimrod
proc query(db: TDbHandle, statement: TSQL) = ... proc query(db: TDbHandle, statement: TSQL) = ...
var var
username: string username: string
db.query("SELECT FROM users WHERE name = '$1'" % username) db.query("SELECT FROM users WHERE name = '$1'" % username)
# Horrible security whole, but the compiler does not mind! # Horrible security hole, but the compiler does not mind!
This can be avoided by distinguishing strings that contain SQL from strings 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 that don't. Abstract types provide a means to introduce a new string type
``TSQL`` that is incompatible with ``string``: ``TSQL`` that is incompatible with ``string``:
.. code-block:: nimrod .. code-block:: nimrod
@ -35,26 +35,26 @@ that don't. Abstract types provide a means to introduce a new string type
var var
username: string username: string
db.query("SELECT FROM users WHERE name = '$1'" % username) db.query("SELECT FROM users WHERE name = '$1'" % username)
# Error at compile time: `query` expects an SQL string! # Error at compile time: `query` expects an SQL string!
It is an essential property of abstract types that they **do not** imply a 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 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 .. code-block:: nimrod
proc properQuote(s: string): TSQL = proc properQuote(s: string): TSQL =
# quotes a string properly for an SQL statement # 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: # quote each argument:
var v = values.each(properQuote) var v = values.each(properQuote)
# we need a temporary type for the type conversion :-( # we need a temporary type for the type conversion :-(
type TStrSeq = seq[string] type TStrSeq = seq[string]
# call strutils.`%`: # call strutils.`%`:
result = TSQL(string(frmt) % TStrSeq(v)) result = TSQL(string(frmt) % TStrSeq(v))
db.query("SELECT FROM users WHERE name = $1".TSQL % username) db.query("SELECT FROM users WHERE name = $1".TSQL % username)
@ -68,43 +68,43 @@ for nice looking ``TSQL`` string literals.
Use case 2: Money Use case 2: Money
----------------- -----------------
Different currencies should not be mixed in monetary calculations. Abstract 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 .. code-block:: nimrod
type type
TDollar = abstract int TDollar = abstract int
TEuro = abstract int TEuro = abstract int
var var
d: TDollar d: TDollar
e: TEuro e: TEuro
echo d + 12 echo d + 12
# Error: cannot add a number with no unit with a ``TDollar`` # 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 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:: .. code-block::
proc `+` (x, y: TDollar): TDollar = proc `+` (x, y: TDollar): TDollar =
result = TDollar(int(x) + int(y)) result = TDollar(int(x) + int(y))
It does not make sense to multiply a dollar with a dollar, but with a It does not make sense to multiply a dollar with a dollar, but with a
number without unit; and the same holds for division: number without unit; and the same holds for division:
.. code-block:: .. code-block::
proc `*` (x: TDollar, y: int): TDollar = proc `*` (x: TDollar, y: int): TDollar =
result = TDollar(int(x) * y) result = TDollar(int(x) * y)
proc `*` (x: int, y: TDollar): TDollar = proc `*` (x: int, y: TDollar): TDollar =
result = TDollar(x * int(y)) result = TDollar(x * int(y))
proc `div` ... 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 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 The pragma ``borrow`` has been designed to solve this problem; in principle
it generates the trivial implementation for us: 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 `*` (x: int, y: TDollar): TDollar {.borrow.}
proc `div` (x: TDollar, y: int): 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 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 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 .. code-block:: nimrod
template Additive(typ: typeDesc): stmt = template Additive(typ: typeDesc): stmt =
proc `+` *(x, y: typ): typ {.borrow.} proc `+` *(x, y: typ): typ {.borrow.}
proc `-` *(x, y: typ): typ {.borrow.} proc `-` *(x, y: typ): typ {.borrow.}
# unary operators: # unary operators:
proc `+` *(x: typ): typ {.borrow.} proc `+` *(x: typ): typ {.borrow.}
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: typ, y: base): typ {.borrow.}
proc `*` *(x: base, y: typ): typ {.borrow.} proc `*` *(x: base, y: typ): typ {.borrow.}
proc `div` *(x: typ, y: base): typ {.borrow.} proc `div` *(x: typ, y: base): typ {.borrow.}
proc `mod` *(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.} 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 type
typ* = abstract base typ* = abstract base
Additive(typ) Additive(typ)
Multiplicative(typ, base) Multiplicative(typ, base)
Comparable(typ) Comparable(typ)
DefineCurrency(TDollar, int) DefineCurrency(TDollar, int)
DefineCurrency(TEuro, 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: 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 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 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 should not be evaluated at compile time! On other occasions it can
and should be evaluted: and should be evaluted:
@ -20,22 +20,22 @@ and should be evaluted:
result[i] = toUpper(s[i]) result[i] = toUpper(s[i])
No, it really can always be evaluated. The code generator should transform 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 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 Solution
======== ========
Being side effect free does not suffice for compile time evaluation. However, 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 If you start your program the debugger will immediately show
a prompt on the console. You can now enter a command. The next sections 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 underscores and case do not matter. Optional components of a command
are listed in brackets ``[...]`` here. 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 Though the Nimrod Standard Library is still evolving, it is already quite
usable. It is divided into *pure libraries*, *impure libraries* and *wrappers*. 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 while impure libraries do. A wrapper is an impure library that is a very
low-level interface to a C library. 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 implicitly by the compiler. Do not import it directly. It relies on compiler
magic to work. magic to work.
* `macros <macros.html>`_ * `macros <macros.html>`_
Contains the AST API and documentation of Nimrod for writing macros. Contains the AST API and documentation of Nimrod for writing macros.
@ -39,8 +39,8 @@ String handling
--------------- ---------------
* `strutils <strutils.html>`_ * `strutils <strutils.html>`_
This module contains common string handling operations like converting a This module contains common string handling operations like changing
string into uppercase, splitting a string into substrings, searching for case of a string, splitting a string into substrings, searching for
substrings, replacing substrings. substrings, replacing substrings.
* `parseutils <parseutils.html>`_ * `parseutils <parseutils.html>`_
@ -52,7 +52,7 @@ String handling
style-insensitive mode. An efficient string substitution operator ``%`` style-insensitive mode. An efficient string substitution operator ``%``
for the string table is also provided. for the string table is also provided.
* `unicode <unicode.html>`_ * `unicode <unicode.html>`_
This module provides support to handle the Unicode UTF-8 encoding. This module provides support to handle the Unicode UTF-8 encoding.
* `re <re.html>`_ * `re <re.html>`_
@ -67,11 +67,11 @@ String handling
Ropes can represent very long strings efficiently; especially concatenation Ropes can represent very long strings efficiently; especially concatenation
is done in O(1) instead of O(n). is done in O(1) instead of O(n).
* `unidecode <unidecode.html>`_ * `unidecode <unidecode.html>`_
This module provides Unicode to ASCII transliterations: This module provides Unicode to ASCII transliterations:
It finds the sequence of ASCII characters that is the closest approximation It finds the sequence of ASCII characters that is the closest approximation
to the Unicode string. to the Unicode string.
Generic Operating System Services Generic Operating System Services
--------------------------------- ---------------------------------
@ -97,8 +97,8 @@ Generic Operating System Services
may provide other implementations for this standard stream interface. may provide other implementations for this standard stream interface.
* `terminal <terminal.html>`_ * `terminal <terminal.html>`_
This module contains a few procedures to control the *terminal* This module contains a few procedures to control the *terminal*
(also called *console*). The implementation simply uses ANSI escape (also called *console*). The implementation simply uses ANSI escape
sequences and does not depend on any other module. sequences and does not depend on any other module.
@ -117,20 +117,20 @@ Internet Protocols and Support
------------------------------ ------------------------------
* `cgi <cgi.html>`_ * `cgi <cgi.html>`_
This module implements helpers for CGI applictions. This module implements helpers for CGI applictions.
* `sockets <sockets.html>`_ * `sockets <sockets.html>`_
This module implements a simple portable type-safe sockets layer. This module implements a simple portable type-safe sockets layer.
* `browsers <browsers.html>`_ * `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. browser.
* `httpserver <httpserver.html>`_ * `httpserver <httpserver.html>`_
This module implements a simple HTTP server. This module implements a simple HTTP server.
* `httpclient <httpclient.html>`_ * `httpclient <httpclient.html>`_
This module implements a simple HTTP client. This module implements a simple HTTP client.
Parsers Parsers
@ -149,14 +149,14 @@ Parsers
as in the Nimrod programming language. as in the Nimrod programming language.
* `parsexml <parsexml.html>`_ * `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 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 to be somewhat error correcting, so that even some "wild HTML" found on the
web can be parsed with it. Web can be parsed with it.
* `parsecsv <parsecsv.html>`_ * `parsecsv <parsecsv.html>`_
The ``parsecsv`` module implements a simple high performance CSV parser. The ``parsecsv`` module implements a simple high performance CSV parser.
* `parsesql <parsesql.html>`_ * `parsesql <parsesql.html>`_
The ``parsesql`` module implements a simple high performance SQL parser. The ``parsesql`` module implements a simple high performance SQL parser.
@ -168,20 +168,20 @@ Parsers
XML Processing XML Processing
-------------- --------------
* `xmldom <xmldom.html>`_ * `xmldom <xmldom.html>`_
This module implements the XML DOM Level 2. This module implements the XML DOM Level 2.
* `xmldomparser <xmldomparser.html>`_ * `xmldomparser <xmldomparser.html>`_
This module parses an XML Document into a XML DOM Document representation. This module parses an XML Document into a XML DOM Document representation.
* `xmltree <xmltree.html>`_ * `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. 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. 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. This module parses an HTML document and creates its XML tree representation.
@ -199,8 +199,8 @@ Cryptography and Hashing
Multimedia support Multimedia support
------------------ ------------------
* `colors <colors.html>`_ * `colors <colors.html>`_
This module implements color handling for Nimrod. It is used by This module implements color handling for Nimrod. It is used by
the ``graphics`` module. the ``graphics`` module.
@ -211,7 +211,7 @@ Impure libraries
* `graphics <graphics.html>`_ * `graphics <graphics.html>`_
This module implements graphical output for Nimrod; the current This module implements graphical output for Nimrod; the current
implementation uses SDL but the interface is meant to support multiple implementation uses SDL but the interface is meant to support multiple
backends some day. backends some day.
* `dialogs <dialogs.html>`_ * `dialogs <dialogs.html>`_
This module implements portable dialogs for Nimrod; the implementation This module implements portable dialogs for Nimrod; the implementation
@ -220,10 +220,10 @@ Impure libraries
* `zipfiles <zipfiles.html>`_ * `zipfiles <zipfiles.html>`_
This module implements a zip archive creator/reader/modifier. This module implements a zip archive creator/reader/modifier.
* `web <web.html>`_ * `web <web.html>`_
This module contains simple high-level procedures for dealing with the 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 Database support
@ -232,13 +232,13 @@ Database support
* `db_postgres <db_postgres.html>`_ * `db_postgres <db_postgres.html>`_
A higher level PostgreSQL database wrapper. The same interface is implemented A higher level PostgreSQL database wrapper. The same interface is implemented
for other databases too. for other databases too.
* `db_mysql <db_mysql.html>`_ * `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. for other databases too.
* `db_sqlite <db_sqlite.html>`_ * `db_sqlite <db_sqlite.html>`_
A higher level mySQL database wrapper. The same interface is implemented A higher level SQLite database wrapper. The same interface is implemented
for other databases too. 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. Contains a wrapper for the Win32 API.
* `mysql <mysql.html>`_ * `mysql <mysql.html>`_
Contains a wrapper for the mySQL API. Contains a wrapper for the mySQL API.
* `sqlite3 <sqlite3.html>`_ * `sqlite3 <sqlite3.html>`_
Contains a wrapper for SQLite 3 API. Contains a wrapper for SQLite 3 API.
* `libcurl <libcurl.html>`_ * `libcurl <libcurl.html>`_
Contains a wrapper for the libcurl library. 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. Part of the wrapper for Lua.
* `lauxlib <lauxlib.html>`_ * `lauxlib <lauxlib.html>`_
Part of the wrapper for Lua. Part of the wrapper for Lua.
* `tcl <tcl.html>`_ * `tcl <tcl.html>`_
Wrapper for the TCL programming language. Wrapper for the TCL programming language.
* `python <python.html>`_ * `python <python.html>`_
Wrapper for the Python programming language. Wrapper for the Python programming language.
* `odbcsql <odbcsql.html>`_ * `odbcsql <odbcsql.html>`_
interface to the ODBC driver. interface to the ODBC driver.
* `zlib <zlib.html>`_ * `zlib <zlib.html>`_
Wrapper for the zlib library. Wrapper for the zlib library.
* `sdl <sdl.html>`_ * `sdl <sdl.html>`_
Part of the wrapper for SDL. Part of the wrapper for SDL.
* `sdl_gfx <sdl_gfx.html>`_ * `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. Part of the wrapper for X11.
* `libzip <libzip.html>`_ * `libzip <libzip.html>`_
Interface to the `lib zip <http://www.nih.at/libzip/index.html>`_ library by Interface to the `lib zip <http://www.nih.at/libzip/index.html>`_ library by
Dieter Baron and Thomas Klausner. Dieter Baron and Thomas Klausner.
* `iup <iup.html>`_ * `iup <iup.html>`_
Wrapper of the IUP GUI library. 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 Nimrod Compiler User Guide
=================================== ===================================
:Author: Andreas Rumpf :Author: Andreas Rumpf
:Version: |nimrodversion| :Version: |nimrodversion|
.. contents:: .. contents::
"Look at you, hacker. A pathetic creature of meat and bone, panting and "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, sweating as you run through my corridors. How can you challenge a perfect,
immortal machine?" immortal machine?"
Introduction Introduction
============ ============
This document describes the usage of the *Nimrod compiler* This document describes the usage of the *Nimrod compiler*
on the different supported platforms. It is not a definition of the Nimrod on the different supported platforms. It is not a definition of the Nimrod
programming language (therefore is the `manual <manual>`_). programming language (therefore is the `manual <manual>`_).
Nimrod is free software; it is licensed under the Nimrod is free software; it is licensed under the
`GNU General Public License <gpl.html>`_. `GNU General Public License <gpl.html>`_.
Compiler Usage Compiler Usage
============== ==============
Command line switches Command line switches
--------------------- ---------------------
Basis command line switches are: Basis command line switches are:
.. include:: ../data/basicopt.txt .. include:: ../data/basicopt.txt
Advanced command line switches are: Advanced command line switches are:
.. include:: ../data/advopt.txt .. include:: ../data/advopt.txt
Configuration file Configuration file
------------------ ------------------
The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable The default configuration file is ``nimrod.cfg``. The ``nimrod`` executable
looks for it in the following directories (in this order): looks for it in the following directories (in this order):
1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``%APPDATA%/nimrod.cfg`` (Windows) 1. ``/home/$user/.config/nimrod.cfg`` (UNIX) or ``%APPDATA%/nimrod.cfg`` (Windows)
2. ``$nimrod/config/nimrod.cfg`` (UNIX, Windows) 2. ``$nimrod/config/nimrod.cfg`` (UNIX), ``%NIMROD%/config/nimrod.cfg`` (Windows)
3. ``/etc/nimrod.cfg`` (UNIX) 3. ``/etc/nimrod.cfg`` (UNIX)
The search stops as soon as a configuration file has been found. The reading 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. 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 **Note:** The *project file name* is the name of the ``.nim`` file that is
passed as a command line argument to the compiler. passed as a command line argument to the compiler.
Configuration settings can be overwritten in a project specific Configuration settings can be overwritten individually in a project specific
configuration file that is read automatically. This specific file has to 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 be in the same directory as the project and be of the same name, except
that its extension should be ``.cfg``. that its extension should be ``.cfg``.
Command line settings have priority over configuration file settings. Command line settings have priority over configuration file settings.
Generated C code directory Generated C code directory
-------------------------- --------------------------
The generated files that Nimrod produces all go into a subdirectory called The generated files that Nimrod produces all go into a subdirectory called
``nimcache`` in your project directory. This makes it easy to delete all ``nimcache`` in your project directory. This makes it easy to delete all
generated files. generated files.
However, the generated C code is not platform independant. C code generated for 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 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. C file lists the OS, CPU and CC the file has been compiled for.
Additional Features Additional Features
=================== ===================
This section describes Nimrod's additional features that are not listed in the 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 Nimrod manual. Some of the features here only make sense for the C code
generator and are subject to change. generator and are subject to change.
NoDecl pragma NoDecl pragma
------------- -------------
The `noDecl`:idx: pragma can be applied to almost any symbol (variable, proc, The `noDecl`:idx: pragma can be applied to almost any symbol (variable, proc,
type, etc.) and is sometimes useful for interoperability with C: type, etc.) and is sometimes useful for interoperability with C:
It tells Nimrod that it should not generate a declaration for the symbol in It tells Nimrod that it should not generate a declaration for the symbol in
the C code. For example: the C code. For example:
.. code-block:: Nimrod .. code-block:: Nimrod
var var
EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as EACCES {.importc, noDecl.}: cint # pretend EACCES was a variable, as
# Nimrod does not know its value # Nimrod does not know its value
However, the ``header`` pragma is often the better alternative. However, the ``header`` pragma is often the better alternative.
**Note**: This will not work for the LLVM backend. **Note**: This will not work for the LLVM backend.
Header pragma Header pragma
------------- -------------
The `header`:idx: pragma is very similar to the ``noDecl`` pragma: It can be 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 applied to almost any symbol and specifies that it should not be declared
and instead the generated code should contain an ``#include``: and instead the generated code should contain an ``#include``:
.. code-block:: Nimrod .. code-block:: Nimrod
type type
PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer PFile {.importc: "FILE*", header: "<stdio.h>".} = distinct pointer
# import C's FILE* type; Nimrod will treat it as a new pointer type # 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 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 contains the header file: As usual for C, a system header file is enclosed
in angle brackets: ``<>``. If no angle brackets are given, Nimrod in angle brackets: ``<>``. If no angle brackets are given, Nimrod
encloses the header file in ``""`` in the generated C code. encloses the header file in ``""`` in the generated C code.
**Note**: This will not work for the LLVM backend. **Note**: This will not work for the LLVM backend.
LineDir option LineDir option
-------------- --------------
The `lineDir`:idx: option can be turned on or off. If turned on the 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 generated C code contains ``#line`` directives. This may be helpful for
debugging with GDB. debugging with GDB.
StackTrace option StackTrace option
----------------- -----------------
If the `stackTrace`:idx: option is turned on, the generated C contains code to 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 ensure that proper stack traces are given if the program crashes or an
uncaught exception is raised. uncaught exception is raised.
LineTrace option LineTrace option
---------------- ----------------
The `lineTrace`:idx: option implies the ``stackTrace`` option. If turned on, The `lineTrace`:idx: option implies the ``stackTrace`` option. If turned on,
the generated C contains code to ensure that proper stack traces with line 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 number information are given if the program crashes or an uncaught exception
is raised. is raised.
Debugger option Debugger option
--------------- ---------------
The `debugger`:idx: option enables or disables the *Embedded Nimrod Debugger*. The `debugger`:idx: option enables or disables the *Embedded Nimrod Debugger*.
See the documentation of endb_ for further information. See the documentation of endb_ for further information.
Breakpoint pragma Breakpoint pragma
----------------- -----------------
The *breakpoint* pragma was specially added for the sake of debugging with The *breakpoint* pragma was specially added for the sake of debugging with
ENDB. See the documentation of `endb <endb.html>`_ for further information. ENDB. See the documentation of `endb <endb.html>`_ for further information.
Volatile pragma Volatile pragma
--------------- ---------------
The `volatile`:idx: pragma is for variables only. It declares the variable as The `volatile`:idx: pragma is for variables only. It declares the variable as
``volatile``, whatever that means in C/C++. ``volatile``, whatever that means in C/C++.
**Note**: This pragma will not exist for the LLVM backend. **Note**: This pragma will not exist for the LLVM backend.
Debugging with Nimrod Debugging with Nimrod
===================== =====================
Nimrod comes with its own *Embedded Nimrod Debugger*. See Nimrod comes with its own *Embedded Nimrod Debugger*. See
the documentation of endb_ for further information. the documentation of endb_ for further information.
Optimizing for Nimrod Optimizing for Nimrod
===================== =====================
Nimrod has no separate optimizer, but the C code that is produced is very 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 efficient. Most C compilers have excellent optimizers, so usually it is
not needed to optimize one's code. Nimrod has been designed to encourage 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 efficient code: The most readable code in Nimrod is often the most efficient
too. too.
However, sometimes one has to optimize. Do it in the following order: However, sometimes one has to optimize. Do it in the following order:
1. switch off the embedded debugger (it is **slow**!) 1. switch off the embedded debugger (it is **slow**!)
2. turn on the optimizer and turn off runtime checks 2. turn on the optimizer and turn off runtime checks
3. profile your code to find where the bottlenecks are 3. profile your code to find where the bottlenecks are
4. try to find a better algorithm 4. try to find a better algorithm
5. do low-level optimizations 5. do low-level optimizations
This section can only help you with the last item. This section can only help you with the last item.
Optimizing string handling Optimizing string handling
-------------------------- --------------------------
String assignments are sometimes expensive in Nimrod: They are required to 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 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 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 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. a procedure call, because the callee returns a new string anyway.
Thus it is efficient to do: Thus it is efficient to do:
.. code-block:: Nimrod .. code-block:: Nimrod
var s = procA() # assignment will not copy the string; procA allocates a new var s = procA() # assignment will not copy the string; procA allocates a new
# string already # string already
However it is not efficient to do: However it is not efficient to do:
.. code-block:: Nimrod .. code-block:: Nimrod
var s = varA # assignment has to copy the whole string into a new buffer! 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 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 if several different string constants are used. This is likely to be more
efficient than any hand-coded scheme. efficient than any hand-coded scheme.
.. ..
The ECMAScript code generator The ECMAScript code generator
============================= =============================
Note: As of version 0.7.0 the ECMAScript code generator is not maintained any Note: As of version 0.7.0 the ECMAScript code generator is not maintained any
longer. Help if you are interested. longer. Help if you are interested.
Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:, Note: I use the term `ECMAScript`:idx: here instead of `JavaScript`:idx:,
since it is the proper term. since it is the proper term.
The ECMAScript code generator is experimental! The ECMAScript code generator is experimental!
Nimrod targets ECMAScript 1.5 which is supported by any widely used browser. 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, Since ECMAScript does not have a portable means to include another module,
Nimrod just generates a long ``.js`` file. Nimrod just generates a long ``.js`` file.
Features or modules that the ECMAScript platform does not support are not Features or modules that the ECMAScript platform does not support are not
available. This includes: available. This includes:
* manual memory management (``alloc``, etc.) * manual memory management (``alloc``, etc.)
* casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.) * casting and other unsafe operations (``cast`` operator, ``zeroMem``, etc.)
* file management * file management
* most modules of the Standard library * most modules of the Standard library
* proper 64 bit integer arithmetic * proper 64 bit integer arithmetic
* proper unsigned integer arithmetic * proper unsigned integer arithmetic
However, the modules `strutils`:idx:, `math`:idx:, and `times`:idx: are 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! To access the DOM, use the `dom`:idx: module that is only
available for the ECMAScript platform. available for the ECMAScript platform.

View file

@ -5,16 +5,16 @@
:Author: Andreas Rumpf :Author: Andreas Rumpf
:Version: |nimrodversion| :Version: |nimrodversion|
.. contents:: .. contents::
Introduction 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. 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 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 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 usable. The missing features can easily be circumvented. An indication of this
@ -26,13 +26,13 @@ Docutils' parser.)
Inline elements Inline elements
=============== ===============
Ordinary text may contain *inline elements*. Ordinary text may contain *inline elements*.
Bullet lists Bullet lists
============ ============
*Bullet lists* look like this:: *Bullet lists* look like this::
* Item 1 * Item 1
* Item 2 that * Item 2 that
@ -60,8 +60,8 @@ Enumerated lists
*Enumerated lists* *Enumerated lists*
Defintion lists Definition lists
=============== ================
Save this code to the file "greeting.nim". Now compile and run it: 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 Tables
====== ======
Nimrod only implements simple tables of the form:: Nimrod only implements simple tables of the form::
================== =============== =================== ================== =============== ===================
header 1 header 2 header n header 1 header 2 header n
================== =============== =================== ================== =============== ===================
Cell 1 Cell 2 Cell 3 Cell 1 Cell 2 Cell 3
Cell 4 Cell 5; any Cell 6 Cell 4 Cell 5; any Cell 6
cell that is cell that is
not in column 1 not in column 1
may span over may span over
multiple lines multiple lines
@ -97,7 +97,7 @@ header 1 header 2 header n
================== =============== =================== ================== =============== ===================
Cell 1 Cell 2 Cell 3 Cell 1 Cell 2 Cell 3
Cell 4 Cell 5; any Cell 6 Cell 4 Cell 5; any Cell 6
cell that is cell that is
not in column 1 not in column 1
may span over may span over
multiple lines 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) var dlg = Iup.Dialog(box)
Iup.SetAttribute(dlg, "TITLE", "IupTabs") Iup.SetAttribute(dlg, "TITLE", "IupTabs")
Iup.SetAttribute(dlg, "SIZE", "200x80") Iup.SetAttribute(dlg, "SIZE", "200x100")
discard ShowXY(dlg, IUP_CENTER, IUP_CENTER) discard ShowXY(dlg, IUP_CENTER, IUP_CENTER)
discard MainLoop() discard MainLoop()

View file

@ -6,4 +6,4 @@ import
#proc MessageBox(hWnd: int, lpText, lpCaption: CString, uType: uint): int #proc MessageBox(hWnd: int, lpText, lpCaption: CString, uType: uint): int
# {stdcall, import: "MessageBox", header: "<windows.h>"} # {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, proc on_about_menu_item_activate(menuItem: PGtkMenuItem,
e: var TMyTextEditor) {.cdecl.} = e: var TMyTextEditor) {.cdecl.} =
gtk_show_about_dialog(e.window, gtk_show_about_dialog(e.window,
"comments", "A fast and leight-weight IDE for Nimrod", "comments", "A fast and lightweight IDE for Nimrod",
"copyright", "Copyright \xc2\xa9 2008 Andreas Rumpf", "copyright", "Copyright \xc2\xa9 2010 Andreas Rumpf",
"version", "0.1", "version", "0.1",
"website", "http://nimrod.ethexor.com", "website", "http://force7.de/nimrod/",
"program-name", "Nimrod IDE", "program-name", "Nimrod IDE",
nil) nil)
@ -70,7 +70,7 @@ proc write_file(e: var TMyTextEditor, filename: string) =
buffer: PGtkTextBuffer buffer: PGtkTextBuffer
start, ende: TGtkTextIter start, ende: TGtkTextIter
# add Saving message to status bar and ensure GUI is current # 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() while gtk_events_pending(): gtk_main_iteration()
# disable text view and get contents of buffer # disable text view and get contents of buffer

View file

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

View file

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

View file

@ -57,7 +57,7 @@ proc execCmd*(command: string): int
proc executeCommand*(command: string): int {.deprecated.} = proc executeCommand*(command: string): int {.deprecated.} =
## **Deprecated since version 0.8.2**: Use `execCmd` instead. ## **Deprecated since version 0.8.2**: Use `execCmd` instead.
result = execCmd(command) result = execCmd(command)
proc startProcess*(command: string, proc startProcess*(command: string,
workingDir: string = "", workingDir: string = "",
@ -115,7 +115,7 @@ when defined(macosx) or defined(bsd):
a: var int, b: pointer, c: int): cint {. a: var int, b: pointer, c: int): cint {.
importc: "sysctl", header: "<sys/sysctl.h>".} importc: "sysctl", header: "<sys/sysctl.h>".}
proc countProcessors*(): int = proc countProcessors*(): int =
## returns the numer of the processors/cores the machine has. ## returns the numer of the processors/cores the machine has.
## Returns 0 if it cannot be determined. ## Returns 0 if it cannot be determined.
when defined(windows): when defined(windows):
@ -186,7 +186,7 @@ proc execProcesses*(cmds: openArray[string],
inc(i) inc(i)
if i > high(cmds): break if i > high(cmds): break
for i in 0..m-1: for i in 0..m-1:
result = max(waitForExit(q[i]), result) result = max(waitForExit(q[i]), result)
else: else:
for i in 0..high(cmds): for i in 0..high(cmds):
var p = startProcessAux(cmds[i], options=options) var p = startProcessAux(cmds[i], options=options)
@ -243,7 +243,7 @@ when defined(Windows):
if a == 0 and br != 0: OSError() if a == 0 and br != 0: OSError()
s.atTheEnd = br < bufLen s.atTheEnd = br < bufLen
result = br result = br
proc hsWriteData(s: PFileHandleStream, buffer: pointer, bufLen: int) = proc hsWriteData(s: PFileHandleStream, buffer: pointer, bufLen: int) =
var bytesWritten: int32 var bytesWritten: int32
var a = winlean.writeFile(s.handle, buffer, bufLen, bytesWritten, nil) var a = winlean.writeFile(s.handle, buffer, bufLen, bytesWritten, nil)
@ -256,10 +256,10 @@ when defined(Windows):
result.atEnd = hsAtEnd result.atEnd = hsAtEnd
result.readData = hsReadData result.readData = hsReadData
result.writeData = hsWriteData result.writeData = hsWriteData
proc buildCommandLine(a: string, args: openarray[string]): cstring = proc buildCommandLine(a: string, args: openarray[string]): cstring =
var res = quoteIfContainsWhite(a) var res = quoteIfContainsWhite(a)
for i in 0..high(args): for i in 0..high(args):
res.add(' ') res.add(' ')
res.add(quoteIfContainsWhite(args[i])) res.add(quoteIfContainsWhite(args[i]))
result = cast[cstring](alloc0(res.len+1)) result = cast[cstring](alloc0(res.len+1))
@ -324,7 +324,7 @@ when defined(Windows):
result.inputHandle = si.hStdInput result.inputHandle = si.hStdInput
result.outputHandle = si.hStdOutput result.outputHandle = si.hStdOutput
result.errorHandle = si.hStdError result.errorHandle = si.hStdError
var cmdl: cstring var cmdl: cstring
if false: # poUseShell in options: if false: # poUseShell in options:
cmdl = buildCommandLine(getEnv("COMSPEC"), @["/c", command] & args) cmdl = buildCommandLine(getEnv("COMSPEC"), @["/c", command] & args)
@ -337,13 +337,13 @@ when defined(Windows):
if poEchoCmd in options: echo($cmdl) if poEchoCmd in options: echo($cmdl)
success = winlean.CreateProcess(nil, success = winlean.CreateProcess(nil,
cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo) cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo)
if poParentStreams notin options: if poParentStreams notin options:
FileClose(si.hStdInput) FileClose(si.hStdInput)
FileClose(si.hStdOutput) FileClose(si.hStdOutput)
if poStdErrToStdOut notin options: if poStdErrToStdOut notin options:
FileClose(si.hStdError) FileClose(si.hStdError)
if e != nil: dealloc(e) if e != nil: dealloc(e)
dealloc(cmdl) dealloc(cmdl)
if success == 0: OSError() if success == 0: OSError()
@ -382,7 +382,7 @@ when defined(Windows):
proc errorStream(p: PProcess): PStream = proc errorStream(p: PProcess): PStream =
result = newFileHandleStream(p.errorHandle) result = newFileHandleStream(p.errorHandle)
proc execCmd(command: string): int = proc execCmd(command: string): int =
var var
SI: TStartupInfo SI: TStartupInfo
ProcInfo: TProcessInformation ProcInfo: TProcessInformation
@ -535,7 +535,7 @@ else:
proc csystem(cmd: cstring): cint {.nodecl, importc: "system".} proc csystem(cmd: cstring): cint {.nodecl, importc: "system".}
proc execCmd(command: string): int = proc execCmd(command: string): int =
result = csystem(command) result = csystem(command)
when isMainModule: 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. ## This module implements Nimrod's support for the ``variant`` datatype.
## `TVariant` shows how the flexibility of dynamic typing is achieved ## `TVariant` shows how the flexibility of dynamic typing is achieved
## within a static type system. ## within a static type system.
type type
TVarType* = enum TVarType* = enum
vtNone, vtNone,
vtBool, vtBool,
vtChar, vtChar,
vtEnum, vtEnum,
vtInt, vtInt,
@ -31,7 +31,7 @@ type
of vtString: vstring: string of vtString: vstring: string
of vtSet, vtSeq: q: seq[TVariant] of vtSet, vtSeq: q: seq[TVariant]
of vtDict: d: seq[tuple[key, val: TVariant]] of vtDict: d: seq[tuple[key, val: TVariant]]
iterator objectFields*[T](x: T, skipInherited: bool): tuple[ iterator objectFields*[T](x: T, skipInherited: bool): tuple[
key: string, val: TVariant] {.magic: "ObjectFields"} 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".} proc `><`*[T](v: TVariant, typ: T): T {.magic: "FromVariant".}
?[?5, ?67, ?"hallo"] ?[?5, ?67, ?"hello"]
myVar?int myVar?int
proc `==`* (x, y: TVariant): bool = proc `==`* (x, y: TVariant): bool =
if x.vtype == y.vtype: if x.vtype == y.vtype:
case x.vtype case x.vtype
@ -139,7 +139,7 @@ proc `[]=`* (a, b, c: TVariant) =
a.d[b.vint].val = c a.d[b.vint].val = c
variantError() variantError()
else: variantError() else: variantError()
proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[?b] proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[?b]
proc `[]`* (a: TVariant, b: string): 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 proc `[]=`* (a: TVariant, b: int, c: TVariant) {.inline} = a[?b] = c
@ -154,9 +154,9 @@ proc `+`* (x, y: TVariant): TVariant =
else: else:
case y.vtype case y.vtype
of vtBool, vtChar, vtEnum, vtInt: of vtBool, vtChar, vtEnum, vtInt:
vint: int64 vint: int64
of vtFloat: vfloat: float64 of vtFloat: vfloat: float64
of vtString: vstring: string of vtString: vstring: string
@ -171,11 +171,11 @@ proc `mod`* (x, y: TVariant): TVariant
proc `&`* (x, y: TVariant): TVariant proc `&`* (x, y: TVariant): TVariant
proc `$`* (x: TVariant): string = proc `$`* (x: TVariant): string =
# uses JS notation # uses JS notation
proc parseVariant*(s: string): TVariant proc parseVariant*(s: string): TVariant
proc `<`* (x, y: TVariant): bool proc `<`* (x, y: TVariant): bool
proc `<=`* (x, y: TVariant): bool proc `<=`* (x, y: TVariant): bool
proc hash*(x: TVariant): int = proc hash*(x: TVariant): int =

File diff suppressed because it is too large Load diff

View file

@ -104,7 +104,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
# These routines should be used like following: # These routines should be used like following:
# <Nimrod code> # <Nimrod code>
# s &= "hallo " & name & " how do you feel?" # s &= "Hello " & name & ", how do you feel?"
# #
# <generated C code> # <generated C code>
# { # {
@ -115,7 +115,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
# } # }
# #
# <Nimrod code> # <Nimrod code>
# s = "hallo " & name & " how do you feel?" # s = "Hello " & name & ", how do you feel?"
# #
# <generated C code> # <generated C code>
# { # {
@ -180,8 +180,8 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
result = cast[PGenericSeq](newSeq(extGetCellType(seq), s)) result = cast[PGenericSeq](newSeq(extGetCellType(seq), s))
genericSeqAssign(result, seq, XXX) genericSeqAssign(result, seq, XXX)
#copyMem(result, seq, seq.len * elemSize + GenericSeqSize) #copyMem(result, seq, seq.len * elemSize + GenericSeqSize)
inc(result.len) inc(result.len)
else: else:
result = seq result = seq
if result.len >= result.space: if result.len >= result.space:
result.space = resize(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! # we need to decref here, otherwise the GC leaks!
when not defined(boehmGC) and not defined(nogc): when not defined(boehmGC) and not defined(nogc):
for i in newLen..result.len-1: for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[TAddress](result) +% forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
GenericSeqSize +% (i*%elemSize)), GenericSeqSize +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef) extGetCellType(result).base, waZctDecRef)
# and set the memory to nil: # 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. ## This module implements Nimrod's support for the ``variant`` datatype.
## `TVariant` shows how the flexibility of dynamic typing is achieved ## `TVariant` shows how the flexibility of dynamic typing is achieved
## within a static type system. ## within a static type system.
type type
TVarType* = enum TVarType* = enum
vtNone, vtNone,
vtBool, vtBool,
vtChar, vtChar,
vtEnum, vtEnum,
vtInt, vtInt,
@ -31,7 +31,7 @@ type
of vtString: vstring: string of vtString: vstring: string
of vtSet, vtSeq: q: seq[TVariant] of vtSet, vtSeq: q: seq[TVariant]
of vtDict: d: seq[tuple[key, val: TVariant]] of vtDict: d: seq[tuple[key, val: TVariant]]
iterator objectFields*[T](x: T, skipInherited: bool): tuple[ iterator objectFields*[T](x: T, skipInherited: bool): tuple[
key: string, val: TVariant] {.magic: "ObjectFields"} 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".} proc `><`*[T](v: TVariant, typ: T): T {.magic: "FromVariant".}
[<>5, <>67, <>"hallo"] [<>5, <>67, <>"hello"]
myVar><int myVar><int
proc `==`* (x, y: TVariant): bool = proc `==`* (x, y: TVariant): bool =
if x.vtype == y.vtype: if x.vtype == y.vtype:
case x.vtype case x.vtype
@ -139,7 +139,7 @@ proc `[]=`* (a, b, c: TVariant) =
a.d[b.vint].val = c a.d[b.vint].val = c
variantError() variantError()
else: variantError() else: variantError()
proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[<>b] proc `[]`* (a: TVariant, b: int): TVariant {.inline} = return a[<>b]
proc `[]`* (a: TVariant, b: string): 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 proc `[]=`* (a: TVariant, b: int, c: TVariant) {.inline} = a[<>b] = c
@ -154,9 +154,9 @@ proc `+`* (x, y: TVariant): TVariant =
else: else:
case y.vtype case y.vtype
of vtBool, vtChar, vtEnum, vtInt: of vtBool, vtChar, vtEnum, vtInt:
vint: int64 vint: int64
of vtFloat: vfloat: float64 of vtFloat: vfloat: float64
of vtString: vstring: string of vtString: vstring: string
@ -171,11 +171,11 @@ proc `mod`* (x, y: TVariant): TVariant
proc `&`* (x, y: TVariant): TVariant proc `&`* (x, y: TVariant): TVariant
proc `$`* (x: TVariant): string = proc `$`* (x: TVariant): string =
# uses JS notation # uses JS notation
proc parseVariant*(s: string): TVariant proc parseVariant*(s: string): TVariant
proc `<`* (x, y: TVariant): bool proc `<`* (x, y: TVariant): bool
proc `<=`* (x, y: TVariant): bool proc `<=`* (x, y: TVariant): bool
proc hash*(x: TVariant): int = 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: # These routines should be used like following:
# <Nimrod code> # <Nimrod code>
# s &= "hallo " & name & " how do you feel?" # s &= "Hello " & name & ", how do you feel?"
# #
# <generated C code> # <generated C code>
# { # {
@ -115,7 +115,7 @@ proc addChar(s: NimString, c: char): NimString {.compilerProc.} =
# } # }
# #
# <Nimrod code> # <Nimrod code>
# s = "hallo " & name & " how do you feel?" # s = "Hello " & name & ", how do you feel?"
# #
# <generated C code> # <generated C code>
# { # {
@ -180,8 +180,8 @@ proc incrSeq(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
result = cast[PGenericSeq](newSeq(extGetCellType(seq), s)) result = cast[PGenericSeq](newSeq(extGetCellType(seq), s))
genericSeqAssign(result, seq, XXX) genericSeqAssign(result, seq, XXX)
#copyMem(result, seq, seq.len * elemSize + GenericSeqSize) #copyMem(result, seq, seq.len * elemSize + GenericSeqSize)
inc(result.len) inc(result.len)
else: else:
result = seq result = seq
if result.len >= result.space: if result.len >= result.space:
result.space = resize(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! # we need to decref here, otherwise the GC leaks!
when not defined(boehmGC) and not defined(nogc): when not defined(boehmGC) and not defined(nogc):
for i in newLen..result.len-1: for i in newLen..result.len-1:
forAllChildrenAux(cast[pointer](cast[TAddress](result) +% forAllChildrenAux(cast[pointer](cast[TAddress](result) +%
GenericSeqSize +% (i*%elemSize)), GenericSeqSize +% (i*%elemSize)),
extGetCellType(result).base, waZctDecRef) extGetCellType(result).base, waZctDecRef)
# and set the memory to nil: # 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 # Simplest Nimrod program
echo "Hallo, World!" echo "Hello, World!"

View file

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

View file

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

View file

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

View file

@ -2,6 +2,6 @@ import streams
var outp = newFileStream(stdout) var outp = newFileStream(stdout)
var inp = newFileStream(stdin) var inp = newFileStream(stdin)
write(outp, "Hallo! What is your name?") write(outp, "Hello! What is your name?")
var line = readLine(inp) 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 # 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 var
root: PBinaryTree[string] root: PBinaryTree[string]
x = newNode("hallo") x = newNode("hello")
add(root, x) add(root, x)
add(root, "world") add(root, "world")
if find(root, "world"): if find(root, "world"):
@ -21,5 +21,5 @@ add(r2, 99)
for y in items(r2): for y in items(r2):
stdout.write(y) stdout.write(y)
#OUT halloworld99110223 #OUT helloworld99110223

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,7 @@
import strutils import strutils
var x = "hallo world!".toLower.toUpper var x = "hello world!".toLower.toUpper
x.echo() 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