summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <andreas@andreas-desktop>2009-11-26 00:32:07 +0100
committerAndreas Rumpf <andreas@andreas-desktop>2009-11-26 00:32:07 +0100
commit196ef92c86d8b8971d4b316f7c18e404842c4b9b (patch)
tree03506a36422f8ae7543b492978067263beea8502
parent3710309d39f65718ab5990d53a977acb241432a9 (diff)
downloadNim-196ef92c86d8b8971d4b316f7c18e404842c4b9b.tar.gz
bug concerning constant evaluation fixed
-rwxr-xr-xdata/advopt.txt24
-rwxr-xr-xdata/basicopt.txt22
-rwxr-xr-xdoc/intern.txt7
-rwxr-xr-xdoc/manual.txt8
-rwxr-xr-xdoc/nimrodc.txt47
-rwxr-xr-xlib/impure/db_postgres.nim137
-rwxr-xr-xlib/impure/zipfiles.nim2
-rwxr-xr-xlib/pure/pegs.nim4
-rwxr-xr-xlib/pure/re.nim2
-rwxr-xr-xlib/system/profiler.nim8
-rwxr-xr-xlib/wrappers/postgres.nim2
-rwxr-xr-xnim/commands.pas49
-rwxr-xr-xnim/evals.pas228
-rwxr-xr-xrod/nimrod.ini1
14 files changed, 296 insertions, 245 deletions
diff --git a/data/advopt.txt b/data/advopt.txt
index 975c09af8..1fe4e0e6e 100755
--- a/data/advopt.txt
+++ b/data/advopt.txt
@@ -1,9 +1,9 @@
 Advanced commands::
   pas                       convert a Pascal file to Nimrod syntax
   pretty                    pretty print the inputfile
-  gen_depend                generate a DOT file containing the
+  genDepend                 generate a DOT file containing the
                             module dependency graph
-  list_def                  list all defined conditionals and exit
+  listDef                   list all defined conditionals and exit
   check                     checks the project for syntax and semantic
   parse                     parses a single file (for debugging Nimrod)
 Advanced options:
@@ -12,27 +12,27 @@ Advanced options:
   --hints:on|off            hints ON|OFF
   --hint[X]:on|off          specific hint X ON|OFF
   --lib:PATH                set the system library path
-  -c, --compile_only        compile only; do not assemble or link
-  --no_linking              compile but do not link
-  --no_main                 do not generate a main procedure
-  --gen_script              generate a compile script (in the 'nimcache'
+  -c, --compileOnly         compile only; do not assemble or link
+  --noLinking               compile but do not link
+  --noMain                  do not generate a main procedure
+  --genScript               generate a compile script (in the 'nimcache'
                             subdirectory named 'compile_$project$scriptext')
   --os:SYMBOL               set the target operating system (cross-compilation)
   --cpu:SYMBOL              set the target processor (cross-compilation)
   --debuginfo               enables debug information
   -t, --passc:OPTION        pass an option to the C compiler
   -l, --passl:OPTION        pass an option to the linker
-  --gen_mapping             generate a mapping file containing
+  --genMapping              generate a mapping file containing
                             (Nimrod, mangled) identifier pairs
-  --line_dir:on|off         generation of #line directive ON|OFF
+  --lineDir:on|off          generation of #line directive ON|OFF
   --checkpoints:on|off      turn on|off checkpoints; for debugging Nimrod
-  --skip_cfg                do not read the general configuration file
-  --skip_proj_cfg           do not read the project's configuration file
+  --skipCfg                 do not read the general configuration file
+  --skipProjCfg             do not read the project's configuration file
   --gc:refc|boehm|none      use Nimrod's native GC|Boehm GC|no GC
   --index:FILE              use FILE to generate a documenation index file
   --putenv:key=value        set an environment variable
-  --list_cmd                list the commands used to execute external programs
-  --parallel_build=0|1|...  perform a parallel build
+  --listCmd                 list the commands used to execute external programs
+  --parallelBuild=0|1|...   perform a parallel build
                             value = number of processors (0 for auto-detect)
   --verbosity:0|1|2|3       set Nimrod's verbosity level (0 is default)
   -v, --version             show detailed version information
diff --git a/data/basicopt.txt b/data/basicopt.txt
index af3f541ad..136c058c0 100755
--- a/data/basicopt.txt
+++ b/data/basicopt.txt
@@ -2,7 +2,7 @@ Usage::
   nimrod command [options] inputfile [arguments]
 Command::
   compile, c                compile project with default code generator (C)
-  compile_to_c, cc          compile project with C code generator
+  compileToC, cc            compile project with C code generator
   doc                       generate the documentation for inputfile
   rst2html                  converts a reStructuredText file to HTML
   rst2tex                   converts a reStructuredText file to TeX
@@ -13,19 +13,19 @@ Options:
   -o, --out:FILE            set the output filename
   -d, --define:SYMBOL       define a conditional symbol
   -u, --undef:SYMBOL        undefine a conditional symbol
-  -f, --force_build         force rebuilding of all modules
-  --symbol_files:on|off     use symbol files to speed up compilation (buggy!)
-  --stack_trace:on|off      code generation for stack trace ON|OFF
-  --line_trace:on|off       code generation for line trace ON|OFF
+  -f, --forceBuild          force rebuilding of all modules
+  --symbolFiles:on|off      use symbol files to speed up compilation (buggy!)
+  --stackTrace:on|off       code generation for stack trace ON|OFF
+  --lineTrace:on|off        code generation for line trace ON|OFF
   --debugger:on|off         turn Embedded Nimrod Debugger ON|OFF
   -x, --checks:on|off       code generation for all runtime checks ON|OFF
-  --obj_checks:on|off       code generation for obj conversion checks ON|OFF
-  --field_checks:on|off     code generation for case variant fields ON|OFF
-  --range_checks:on|off     code generation for range checks ON|OFF
-  --bound_checks:on|off     code generation for bound checks ON|OFF
-  --overflow_checks:on|off  code generation for over-/underflow checks ON|OFF
+  --objChecks:on|off        code generation for obj conversion checks ON|OFF
+  --fieldChecks:on|off      code generation for case variant fields ON|OFF
+  --rangeChecks:on|off      code generation for range checks ON|OFF
+  --boundChecks:on|off      code generation for bound checks ON|OFF
+  --overflowChecks:on|off   code generation for over-/underflow checks ON|OFF
   -a, --assertions:on|off   code generation for assertions ON|OFF
-  --dead_code_elim:on|off   whole program dead code elimination ON|OFF
+  --deadCodeElim:on|off     whole program dead code elimination ON|OFF
   --opt:none|speed|size     optimize not at all or for speed|size
   --app:console|gui|lib     generate a console|GUI application|dynamic library
   -r, --run                 run the compiled program with given arguments
diff --git a/doc/intern.txt b/doc/intern.txt
index e62378e1d..dfdc33ae9 100755
--- a/doc/intern.txt
+++ b/doc/intern.txt
@@ -29,12 +29,11 @@ Path           Purpose
                version
 ``data``       data files that are used for generating source
                code
-``doc``        the documentation lives here; it is a bunch of
+``doc``        the documentation; it is a bunch of
                reStructuredText files
 ``dist``       additional packages for the distribution
 ``config``     configuration files for Nimrod
-``lib``        the Nimrod library lives here; ``rod`` depends
-               on it!
+``lib``        the Nimrod library; ``rod`` depends on it!
 ``web``        website of Nimrod; generated by ``koch.py``
                from the ``*.txt`` and ``*.tmpl`` files
 ``obj``        generated ``*.obj`` files
@@ -183,7 +182,7 @@ I use the term *cell* here to refer to everything that is traced
 This section describes how the new GC works.
 
 The basic algorithm is *Deferrent Reference Counting* with cycle detection.
-References in the stack are not counted for better performance and easier C
+References on the stack are not counted for better performance and easier C
 code generation.
 
 Each cell has a header consisting of a RC and a pointer to its type
diff --git a/doc/manual.txt b/doc/manual.txt
index 647ce2774..5b04a3b52 100755
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -666,7 +666,7 @@ The notation ``x[i]`` can be used to access the i-th element of ``x``.
 
 Arrays are always bounds checked (at compile-time or at runtime). These
 checks can be disabled via pragmas or invoking the compiler with the
-``--bound_checks:off`` command line switch.
+``--boundChecks:off`` command line switch.
 
 An open array is  also a means to implement passing a variable number of
 arguments to a procedure. The compiler converts the list of arguments
@@ -2450,11 +2450,11 @@ pragma           allowed values   description
 ===============  ===============  ============================================
 checks           on|off           Turns the code generation for all runtime
                                   checks on or off.
-bound_checks     on|off           Turns the code generation for array bound
+boundChecks      on|off           Turns the code generation for array bound
                                   checks on or off.
-overflow_checks  on|off           Turns the code generation for over- or
+overflowChecks   on|off           Turns the code generation for over- or
                                   underflow checks on or off.
-nil_checks       on|off           Turns the code generation for nil pointer
+nilChecks        on|off           Turns the code generation for nil pointer
                                   checks on or off.
 assertions       on|off           Turns the code generation for assertions
                                   on or off.
diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt
index 88ca52939..3720fc5cb 100755
--- a/doc/nimrodc.txt
+++ b/doc/nimrodc.txt
@@ -12,7 +12,7 @@ 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).
+programming language (therefore is the `manual <manual>`_).
 
 Nimrod is free software; it is licensed under the
 `GNU General Public License <gpl.html>`_.
@@ -42,7 +42,7 @@ looks for it in the following directories (in this order):
 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 ``--skip_cfg`` command line option.
+of ``nimrod.cfg`` can be suppressed by the ``--skipCfg`` command line option.
 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
@@ -125,24 +125,24 @@ At runtime the dynamic library is searched for (in this order)::
   libtcl8.3.so.0
 
 
-No_decl Pragma
-~~~~~~~~~~~~~~
-The `no_decl`:idx: pragma can be applied to almost any symbol (variable, proc,
+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, no_decl.}: cint # pretend EACCES was a variable, as
-                                      # Nimrod does not know its value
+    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.
 
 
 Header Pragma
 ~~~~~~~~~~~~~
-The `header`:idx: pragma is very similar to the ``no_decl`` 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 
 and instead the generated code should contain an ``#include``:
 
@@ -170,22 +170,23 @@ strings automatically:
   printf("hallo %s", "world") # "world" will be passed as C string
 
 
-Line_dir Option
-~~~~~~~~~~~~~~~
-The `line_dir`:idx: option can be turned on or off. If on the generated C code
-contains ``#line`` directives. This may be helpful for debugging with GDB.
+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.
 
 
-Stack_trace Option
-~~~~~~~~~~~~~~~~~~
-If the `stack_trace`:idx: option is turned on, the generated C contains code to
+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.
 
 
-Line_trace Option
-~~~~~~~~~~~~~~~~~
-The `line_trace`:idx: option implies the ``stack_trace`` option. If turned on,
+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.
@@ -239,21 +240,21 @@ information that this cannot happen to the GC. If the programmer uses the
 memory, but nothing worse happens.
 
 
-Dead_code_elim Pragma
+DeadCodeElim Pragma
 ~~~~~~~~~~~~~~~~~~~~~
-The `dead_code_elim`:idx: pragma only applies to whole modules: It tells the
+The `deadCodeElim`:idx: pragma only applies to whole modules: It tells the
 compiler to activate (or deactivate) dead code elimination for the module the
 pragma appers in.
 
-The ``--dead_code_elim:on`` command line switch has the same effect as marking
-every module with ``{.dead_code_elim:on}``. However, for some modules such as
+The ``--deadCodeElim:on`` command line switch has the same effect as marking
+every module with ``{.deadCodeElim:on}``. However, for some modules such as
 the GTK wrapper it makes sense to *always* turn on dead code elimination -
 no matter if it is globally active or not.
 
 Example:
 
 .. code-block:: nimrod
-  {.dead_code_elim: on.}
+  {.deadCodeElim: on.}
 
 
 Disabling certain messages
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
index 197250d9c..b9d0b068f 100755
--- a/lib/impure/db_postgres.nim
+++ b/lib/impure/db_postgres.nim
@@ -4,11 +4,20 @@
 import strutils, postgres
 
 type
-  TDbHandle* = PGconn
-  TRow* = seq[string]
-  EDb* = object of EIO
+  TDbConn* = PPGconn  ## encapsulates a database connection
+  TRow* = seq[string]  ## a row of a dataset
+  EDb* = object of EIO ## exception that is raised if a database error occurs
   
-proc dbError(db: TDbHandle) {.noreturn.} = 
+  TSqlQuery* = distinct string ## an SQL query string
+  
+proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
+  ## constructs a TSqlQuery from the string `query`: If assertions are turned 
+  ## off, it does nothing. If assertions are turned on, the string is checked
+  ## for SQL security holes. This is supposed to be used as a 
+  ## raw-string-literal modifier: ``sql"update user set counter = counter + 1"``
+  result = TSqlQuery(query)
+ 
+proc dbError(db: TDbConn) {.noreturn.} = 
   ## raises an EDb exception.
   var e: ref EDb
   new(e)
@@ -23,13 +32,13 @@ proc dbError*(msg: string) {.noreturn.} =
   raise e
 
 when false:
-  proc dbQueryOpt*(db: TDbHandle, query: string, args: openarray[string]) =
+  proc dbQueryOpt*(db: TDbConn, query: string, args: openarray[string]) =
     var stmt = mysql_stmt_init(db)
     if stmt == nil: dbError(db)
     if mysql_stmt_prepare(stmt, query, len(query)) != 0: 
       dbError(db)
     var 
-      bind: seq[MYSQL_BIND]
+      bindings: seq[MYSQL_BIND]
     discard mysql_stmt_close(stmt)
 
 proc dbQuote(s: string): string =
@@ -39,91 +48,123 @@ proc dbQuote(s: string): string =
     else: add(result, c)
   add(result, '\'')
 
-proc dbFormat(formatstr: string, args: openarray[string]): string =
+proc dbFormat(formatstr: TSqlQuery, args: openarray[string]): string =
   result = ""
   var a = 0
-  for c in items(formatstr):
+  for c in items(string(formatstr)):
     if c == '?':
       add(result, dbQuote(args[a]))
       inc(a)
     else: 
       add(result, c)
   
-proc dbTryQuery*(db: TDbHandle, query: string, args: openarray[string]): bool =
+proc dbTryQuery*(db: TDbConn, query: TSqlQuery, 
+                 args: openarray[string]): bool =
+  ## tries to execute the query and returns true if successful, false otherwise.
   var q = dbFormat(query, args)
   var res = PQExec(db, q)
   result = PQresultStatus(res) == PGRES_COMMAND_OK
   PQclear(res)
 
-proc dbQuery*(db: TDbHandle, query: string, args: openarray[string]) =
-  var q = dbFormat(query, args)
-  var res = PQExec(db, q)
-  if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  PQclear(res)
-  
-proc dbTryInsertID*(db: TDbHandle, query: string, 
-                    args: openarray[string]): int64 =
-  var q = dbFormat(query, args)
-  
-  
-  if mysqlRealQuery(db, q, q.len) != 0'i32: 
-    result = -1'i64
-  else:
-    result = mysql_insert_id(db)
-  LAST_INSERT_ID()
-
-proc dbInsertID*(db: TDbHandle, query: string, args: openArray[string]): int64 = 
-  result = dbTryInsertID(db, query, args)
-  if result < 0: dbError(db)
-  
-proc dbQueryAffectedRows*(db: TDbHandle, query: string, 
-                          args: openArray[string]): int64 = 
-  ## runs the query (typically "UPDATE") and returns the
-  ## number of affected rows
+proc dbQuery*(db: TDbConn, query: TSqlQuery, args: openarray[string]) =
+  ## executes the query and raises EDB if not successful.
   var q = dbFormat(query, args)
   var res = PQExec(db, q)
   if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  result = parseBiggestInt($PQcmdTuples(res))
   PQclear(res)
   
 proc newRow(L: int): TRow =
   newSeq(result, L)
   for i in 0..L-1: result[i] = ""
   
-iterator dbFastRows*(db: TDbHandle, query: string,
-                     args: openarray[string]): TRow =
+proc setupQuery(db: TDbConn, query: TSqlQuery, 
+                args: openarray[string]): PPGresult = 
   var q = dbFormat(query, args)
-  var res = PQExec(db, q)
-  if PQresultStatus(res) != PGRES_TUPLES_OK: dbError(db)
+  result = PQExec(db, q)
+  if PQresultStatus(result) != PGRES_TUPLES_OK: dbError(db)
+  
+proc setRow(res: PPGresult, r: var TRow, line, cols: int) =
+  for col in 0..cols-1:
+    setLen(r[col], 0)
+    add(r[col], PQgetvalue(res, line, cols))    
+  
+iterator dbFastRows*(db: TDbConn, query: TSqlQuery,
+                     args: openarray[string]): TRow =
+  ## executes the query and iterates over the result dataset. This is very 
+  ## fast, but potenially dangerous: If the for-loop-body executes another
+  ## query, the results can be undefined. For Postgres it is safe though.
+  var res = setupQuery(db, query, args)
   var L = int(PQnfields(res))
   var result = newRow(L)
   for i in 0..PQntuples(res)-1:
-    for j in 0..L-1:
-      setLen(result[j], 0)
-      add(result[j], PQgetvalue(res, i, j))
+    setRow(res, result, i, L)
     yield result
   PQclear(res)
 
-proc dbGetAllRows*(db: TDbHandle, query: string, 
+proc dbGetAllRows*(db: TDbConn, query: TSqlQuery, 
                    args: openarray[string]): seq[TRow] =
+  ## executes the query and returns the whole result dataset.
   result = @[]
   for r in dbFastRows(db, query, args):
     result.add(r)
 
-iterator dbRows*(db: TDbHandle, query: string, 
+iterator dbRows*(db: TDbConn, query: TSqlQuery, 
                  args: openarray[string]): TRow =
+  ## same as `dbFastRows`, but slower and safe.
   for r in items(dbGetAllRows(db, query, args)): yield r
 
-proc dbGetValue*(db: TDbHandle, query: string, 
+proc dbGetValue*(db: TDbConn, query: TSqlQuery, 
                  args: openarray[string]): string = 
+  ## executes the query and returns the result dataset's the first column 
+  ## of the first row. Returns "" if the dataset contains no rows. This uses
+  ## `dbFastRows`, so it inherits its fragile behaviour.
   result = ""
   for row in dbFastRows(db, query, args): 
     result = row[0]
     break
+  
+proc dbTryInsertID*(db: TDbConn, query: TSqlQuery, 
+                    args: openarray[string]): int64 =
+  ## executes the query (typically "INSERT") and returns the 
+  ## generated ID for the row or -1 in case of an error. For Postgre this adds
+  ## ``RETURNING id`` to the query, so it only works if your primary key is
+  ## named ``id``. 
+  var val = dbGetValue(db, TSqlQuery(string(query) & " RETURNING id"), args)
+  if val.len > 0:
+    result = ParseBiggestInt(val)
+  else:
+    result = -1
+  #if mysqlRealQuery(db, q, q.len) != 0'i32: 
+  #  result = -1'i64
+  #else:
+  #  result = mysql_insert_id(db)
+  #LAST_INSERT_ID()
+
+proc dbInsertID*(db: TDbConn, query: TSqlQuery, 
+                 args: openArray[string]): int64 = 
+  ## executes the query (typically "INSERT") and returns the 
+  ## generated ID for the row. For Postgre this adds
+  ## ``RETURNING id`` to the query, so it only works if your primary key is
+  ## named ``id``. 
+  result = dbTryInsertID(db, query, args)
+  if result < 0: dbError(db)
+  
+proc dbQueryAffectedRows*(db: TDbConn, query: TSqlQuery, 
+                          args: openArray[string]): int64 = 
+  ## executes the query (typically "UPDATE") and returns the
+  ## number of affected rows.
+  var q = dbFormat(query, args)
+  var res = PQExec(db, q)
+  if PQresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
+  result = parseBiggestInt($PQcmdTuples(res))
+  PQclear(res)
 
-proc dbClose*(db: TDbHandle) = 
+proc dbClose*(db: TDbConn) = 
+  ## closes the database connection.
   if db != nil: PQfinish(db)
 
-proc dbOpen*(connection, user, password, database: string): TDbHandle =
+proc dbOpen*(connection, user, password, database: string): TDbConn =
+  ## opens a database connection. Returns nil in case of an error.
   result = PQsetdbLogin(nil, nil, nil, nil, database, user, password)
-  if PQStatus(result) != CONNECTION_OK: result = nil
+  if PQStatus(result) != CONNECTION_OK: dbError(result) # result = nil
+
diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim
index e48b0f08e..07fe41a04 100755
--- a/lib/impure/zipfiles.nim
+++ b/lib/impure/zipfiles.nim
@@ -43,7 +43,7 @@ proc close*(z: var TZipArchive) =
   zip_close(z.w)
  
 proc createDir*(z: var TZipArchive, dir: string) = 
-  ## Creates a directory within the `z` archive. This does not fails if the
+  ## Creates a directory within the `z` archive. This does not fail if the
   ## directory already exists. Note that for adding a file like 
   ## ``"path1/path2/filename"`` it is not necessary
   ## to create the ``"path/path2"`` subdirectories - it will be done 
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 21205bdb2..488e42c7d 100755
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -148,7 +148,7 @@ proc sequence*(a: openArray[TPeg]): TPeg =
   multipleOp(pkSequence, addSequence)
  
 proc `?`*(a: TPeg): TPeg =
-  ## constructs an optional piece with the PEG `a`
+  ## constructs an optional for the PEG `a`
   if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar,
                 pkGreedyRepSet}:
     # a* ?  --> a*
@@ -159,7 +159,7 @@ proc `?`*(a: TPeg): TPeg =
     result.sons = @[a]
 
 proc `*`*(a: TPeg): TPeg =
-  ## constructs a "greedy repetition" piece the PEG `a`
+  ## constructs a "greedy repetition" for the PEG `a`
   case a.kind
   of pkGreedyRep, pkGreedyRepChar, pkGreedyRepSet, pkGreedyAny, pkOption:
     assert false
diff --git a/lib/pure/re.nim b/lib/pure/re.nim
index f854c07e5..87fe79a04 100755
--- a/lib/pure/re.nim
+++ b/lib/pure/re.nim
@@ -224,7 +224,7 @@ proc replace*(s: string, sub: TRegEx, by: string): string =
   ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
   ##
   ## .. code-block:: nimrod
-  ##   "var1=key; var2=key2".replace(p"{\ident}'='{\ident}", "$1<-$2$2")
+  ##   "var1=key; var2=key2".replace(re"{\ident}'='{\ident}", "$1<-$2$2")
   ##
   ## Results in:
   ##
diff --git a/lib/system/profiler.nim b/lib/system/profiler.nim
index 97c7dcfeb..b87b30d4a 100755
--- a/lib/system/profiler.nim
+++ b/lib/system/profiler.nim
@@ -41,10 +41,10 @@ proc writeProfile() {.noconv.} =
   var i = 0
   var f: TFile
   var j = 1
-  while openFile(f, filename & $j & ".txt"):
-    closeFile(f)
+  while open(f, filename & $j & ".txt"):
+    close(f)
     inc(j)
-  if openFile(f, filename & $j & ".txt", fmWrite):
+  if open(f, filename & $j & ".txt", fmWrite):
     var N = 0
     # we have to compute the actual length of the array:
     while profileData[N].procname != nil: inc(N)
@@ -56,6 +56,6 @@ proc writeProfile() {.noconv.} =
       write(f, ": ")
       writeln(f, profileData[i].total)
       inc(i)
-    closeFile(f)
+    close(f)
 
 addQuitProc(writeProfile)
diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim
index d3c5e265b..26526b6c8 100755
--- a/lib/wrappers/postgres.nim
+++ b/lib/wrappers/postgres.nim
@@ -11,7 +11,7 @@ when defined(windows):
 elif defined(macosx):
   const dllName = "libpq.dylib"
 else:
-  const dllName = "libpq.so"
+  const dllName = "libpq.so(.5|)"
   
 type
   POid* = ptr Oid
diff --git a/nim/commands.pas b/nim/commands.pas
index e88fc6b8c..19f79fb4a 100755
--- a/nim/commands.pas
+++ b/nim/commands.pas
@@ -60,7 +60,7 @@ const
 +{&} '  nimrod command [options] inputfile [arguments]' +{&} nl
 +{&} 'Command::' +{&} nl
 +{&} '  compile, c                compile project with default code generator (C)' +{&} nl
-+{&} '  compile_to_c, cc          compile project with C code generator' +{&} nl
++{&} '  compileToC, cc            compile project with C code generator' +{&} nl
 +{&} '  doc                       generate the documentation for inputfile' +{&} nl
 +{&} '  rst2html                  converts a reStructuredText file to HTML' +{&} nl
 +{&} '  rst2tex                   converts a reStructuredText file to TeX' +{&} nl
@@ -71,19 +71,19 @@ const
 +{&} '  -o, --out:FILE            set the output filename' +{&} nl
 +{&} '  -d, --define:SYMBOL       define a conditional symbol' +{&} nl
 +{&} '  -u, --undef:SYMBOL        undefine a conditional symbol' +{&} nl
-+{&} '  -f, --force_build         force rebuilding of all modules' +{&} nl
-+{&} '  --symbol_files:on|off     use symbol files to speed up compilation (buggy!)' +{&} nl
-+{&} '  --stack_trace:on|off      code generation for stack trace ON|OFF' +{&} nl
-+{&} '  --line_trace:on|off       code generation for line trace ON|OFF' +{&} nl
++{&} '  -f, --forceBuild          force rebuilding of all modules' +{&} nl
++{&} '  --symbolFiles:on|off      use symbol files to speed up compilation (buggy!)' +{&} nl
++{&} '  --stackTrace:on|off       code generation for stack trace ON|OFF' +{&} nl
++{&} '  --lineTrace:on|off        code generation for line trace ON|OFF' +{&} nl
 +{&} '  --debugger:on|off         turn Embedded Nimrod Debugger ON|OFF' +{&} nl
 +{&} '  -x, --checks:on|off       code generation for all runtime checks ON|OFF' +{&} nl
-+{&} '  --obj_checks:on|off       code generation for obj conversion checks ON|OFF' +{&} nl
-+{&} '  --field_checks:on|off     code generation for case variant fields ON|OFF' +{&} nl
-+{&} '  --range_checks:on|off     code generation for range checks ON|OFF' +{&} nl
-+{&} '  --bound_checks:on|off     code generation for bound checks ON|OFF' +{&} nl
-+{&} '  --overflow_checks:on|off  code generation for over-/underflow checks ON|OFF' +{&} nl
++{&} '  --objChecks:on|off        code generation for obj conversion checks ON|OFF' +{&} nl
++{&} '  --fieldChecks:on|off      code generation for case variant fields ON|OFF' +{&} nl
++{&} '  --rangeChecks:on|off      code generation for range checks ON|OFF' +{&} nl
++{&} '  --boundChecks:on|off      code generation for bound checks ON|OFF' +{&} nl
++{&} '  --overflowChecks:on|off   code generation for over-/underflow checks ON|OFF' +{&} nl
 +{&} '  -a, --assertions:on|off   code generation for assertions ON|OFF' +{&} nl
-+{&} '  --dead_code_elim:on|off   whole program dead code elimination ON|OFF' +{&} nl
++{&} '  --deadCodeElim:on|off     whole program dead code elimination ON|OFF' +{&} nl
 +{&} '  --opt:none|speed|size     optimize not at all or for speed|size' +{&} nl
 +{&} '  --app:console|gui|lib     generate a console|GUI application|dynamic library' +{&} nl
 +{&} '  -r, --run                 run the compiled program with given arguments' +{&} nl
@@ -100,9 +100,9 @@ const
 +{&} 'Advanced commands::' +{&} nl
 +{&} '  pas                       convert a Pascal file to Nimrod syntax' +{&} nl
 +{&} '  pretty                    pretty print the inputfile' +{&} nl
-+{&} '  gen_depend                generate a DOT file containing the' +{&} nl
++{&} '  genDepend                 generate a DOT file containing the' +{&} nl
 +{&} '                            module dependency graph' +{&} nl
-+{&} '  list_def                  list all defined conditionals and exit' +{&} nl
++{&} '  listDef                   list all defined conditionals and exit' +{&} nl
 +{&} '  check                     checks the project for syntax and semantic' +{&} nl
 +{&} '  parse                     parses a single file (for debugging Nimrod)' +{&} nl
 +{&} 'Advanced options:' +{&} nl
@@ -111,27 +111,27 @@ const
 +{&} '  --hints:on|off            hints ON|OFF' +{&} nl
 +{&} '  --hint[X]:on|off          specific hint X ON|OFF' +{&} nl
 +{&} '  --lib:PATH                set the system library path' +{&} nl
-+{&} '  -c, --compile_only        compile only; do not assemble or link' +{&} nl
-+{&} '  --no_linking              compile but do not link' +{&} nl
-+{&} '  --no_main                 do not generate a main procedure' +{&} nl
-+{&} '  --gen_script              generate a compile script (in the ''nimcache''' +{&} nl
++{&} '  -c, --compileOnly         compile only; do not assemble or link' +{&} nl
++{&} '  --noLinking               compile but do not link' +{&} nl
++{&} '  --noMain                  do not generate a main procedure' +{&} nl
++{&} '  --genScript               generate a compile script (in the ''nimcache''' +{&} nl
 +{&} '                            subdirectory named ''compile_$project$scriptext'')' +{&} nl
 +{&} '  --os:SYMBOL               set the target operating system (cross-compilation)' +{&} nl
 +{&} '  --cpu:SYMBOL              set the target processor (cross-compilation)' +{&} nl
 +{&} '  --debuginfo               enables debug information' +{&} nl
 +{&} '  -t, --passc:OPTION        pass an option to the C compiler' +{&} nl
 +{&} '  -l, --passl:OPTION        pass an option to the linker' +{&} nl
-+{&} '  --gen_mapping             generate a mapping file containing' +{&} nl
++{&} '  --genMapping              generate a mapping file containing' +{&} nl
 +{&} '                            (Nimrod, mangled) identifier pairs' +{&} nl
-+{&} '  --line_dir:on|off         generation of #line directive ON|OFF' +{&} nl
++{&} '  --lineDir:on|off          generation of #line directive ON|OFF' +{&} nl
 +{&} '  --checkpoints:on|off      turn on|off checkpoints; for debugging Nimrod' +{&} nl
-+{&} '  --skip_cfg                do not read the general configuration file' +{&} nl
-+{&} '  --skip_proj_cfg           do not read the project''s configuration file' +{&} nl
++{&} '  --skipCfg                 do not read the general configuration file' +{&} nl
++{&} '  --skipProjCfg             do not read the project''s configuration file' +{&} nl
 +{&} '  --gc:refc|boehm|none      use Nimrod''s native GC|Boehm GC|no GC' +{&} nl
 +{&} '  --index:FILE              use FILE to generate a documenation index file' +{&} nl
 +{&} '  --putenv:key=value        set an environment variable' +{&} nl
-+{&} '  --list_cmd                list the commands used to execute external programs' +{&} nl
-+{&} '  --parallel_build=0|1|...  perform a parallel build' +{&} nl
++{&} '  --listCmd                 list the commands used to execute external programs' +{&} nl
++{&} '  --parallelBuild=0|1|...   perform a parallel build' +{&} nl
 +{&} '                            value = number of processors (0 for auto-detect)' +{&} nl
 +{&} '  --verbosity:0|1|2|3       set Nimrod''s verbosity level (0 is default)' +{&} nl
 +{&} '  -v, --version             show detailed version information' +{&} nl
@@ -180,7 +180,8 @@ begin
     helpWritten := true;

     messageOut(format(HelpMessage, [VersionAsString, 

                                     platform.os[platform.hostOS].name,

-                                    cpu[platform.hostCPU].name]))

+                                    cpu[platform.hostCPU].name]));
+    halt(0);

   end

 end;

 

diff --git a/nim/evals.pas b/nim/evals.pas
index 43494f929..b9672ba37 100755
--- a/nim/evals.pas
+++ b/nim/evals.pas
@@ -117,6 +117,11 @@ begin
   liMessage(n.info, msg, arg);
 end;
 
+function isSpecial(n: PNode): bool;
+begin
+  result := (n.kind = nkExceptBranch) or (n.kind = nkEmpty)
+end;
+
 function evalIf(c: PEvalContext; n: PNode): PNode;
 var
   i, len: int;
@@ -125,7 +130,7 @@ begin
   len := sonsLen(n);
   while (i < len) and (sonsLen(n.sons[i]) >= 2) do begin
     result := evalAux(c, n.sons[i].sons[0]);
-    if result.kind = nkExceptBranch then exit;
+    if isSpecial(result) then exit;
     if (result.kind = nkIntLit) and (result.intVal <> 0) then begin
       result := evalAux(c, n.sons[i].sons[1]);
       exit
@@ -144,7 +149,7 @@ var
   res: PNode;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   res := result;
   result := emptyNode;
   for i := 1 to sonsLen(n)-1 do begin
@@ -173,7 +178,7 @@ function evalWhile(c: PEvalContext; n: PNode): PNode;
 begin
   while true do begin
     result := evalAux(c, n.sons[0]);
-    if result.kind = nkExceptBranch then exit;
+    if isSpecial(result) then exit;
     if getOrdValue(result) = 0 then break;
     result := evalAux(c, n.sons[1]);
     case result.kind of
@@ -183,7 +188,7 @@ begin
           break
         end
       end;
-      nkExceptBranch, nkReturnToken: break;
+      nkExceptBranch, nkReturnToken, nkEmpty: break;
       else begin end
     end;
     dec(gWhileCounter);
@@ -314,7 +319,7 @@ begin
     v := a.sons[0].sym;
     if a.sons[2] <> nil then begin
       result := evalAux(c, a.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
     end
     else
       result := getNullValue(a.sons[0].typ, a.sons[0].info);
@@ -330,7 +335,7 @@ var
   i: int;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   prc := result;
   // bind the actual params to the local parameter
   // of a new binding
@@ -344,13 +349,13 @@ begin
   setLength(d.params, sonsLen(n));
   for i := 1 to sonsLen(n)-1 do begin
     result := evalAux(c, n.sons[i]);
-    if result.kind = nkExceptBranch then exit;
+    if isSpecial(result) then exit;
     d.params[i] := result;
   end;
   if n.typ <> nil then d.params[0] := getNullValue(n.typ, n.info);
   pushStackFrame(c, d);
   result := evalAux(c, prc);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   if n.typ <> nil then result := d.params[0];
   popStackFrame(c);
 end;
@@ -380,10 +385,10 @@ var
   idx: biggestInt;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   x := result;
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   idx := getOrdValue(result);
   result := emptyNode;
   case x.kind of
@@ -416,7 +421,7 @@ var
   i: int;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   x := result;
   if x.kind <> nkPar then InternalError(n.info, 'evalFieldAccess');
   field := n.sons[1].sym;
@@ -437,10 +442,10 @@ var
   i: int;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   x := result;
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   x.kind := result.kind;
   x.typ := result.typ;
   case x.kind of
@@ -469,10 +474,10 @@ var
   tmpn: PNode;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   x := result;
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   if (x.kind <> result.kind) then
     stackTrace(c, n, errCannotInterpretNodeX, nodeKindToStr[n.kind])
   else begin
@@ -527,10 +532,10 @@ var
   a, b: PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
   case a.kind of
     nkCharLit..nkInt64Lit: a.intval := a.intVal + sign * getOrdValue(b);
@@ -553,7 +558,7 @@ var
 begin
   for i := 1 to sonsLen(n)-1 do begin
     result := evalAux(c, n.sons[i]);
-    if result.kind = nkExceptBranch then exit;
+    if isSpecial(result) then exit;
     Write(output, getStrValue(result));
   end;
   writeln(output, '');
@@ -563,7 +568,7 @@ end;
 function evalExit(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   liMessage(n.info, hintQuitCalled);
   halt(int(getOrdValue(result)));
 end;
@@ -571,7 +576,7 @@ end;
 function evalOr(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   if result.kind <> nkIntLit then InternalError(n.info, 'evalOr');
   if result.intVal = 0 then result := evalAux(c, n.sons[2])
 end;
@@ -579,7 +584,7 @@ end;
 function evalAnd(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   if result.kind <> nkIntLit then InternalError(n.info, 'evalAnd');
   if result.intVal <> 0 then result := evalAux(c, n.sons[2])
 end;
@@ -607,9 +612,8 @@ end;
 function evalDeref(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   case result.kind of
-    nkExceptBranch: exit;
     nkNilLit: stackTrace(c, n, errNilAccess);
     nkRefTy: result := result.sons[0];
     else InternalError(n.info, 'evalDeref ' + nodeKindToStr[result.kind]);
@@ -622,7 +626,7 @@ var
   t: PType;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   t := newType(tyPtr, c.module);
   addSon(t, a.typ);
@@ -647,7 +651,7 @@ var
   dest, src: PType;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   dest := skipTypes(n.typ, abstractPtrs);
   src := skipTypes(result.typ, abstractPtrs);
   if inheritanceDiff(src, dest) > 0 then
@@ -659,13 +663,13 @@ var
   x, a, b: PNode;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   x := result;
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
 
   if leValueConv(a, x) and leValueConv(x, b) then begin
@@ -681,14 +685,14 @@ end;
 function evalConvStrToCStr(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   result.typ := n.typ;
 end;
 
 function evalConvCStrToStr(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[0]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   result.typ := n.typ;
 end;
 
@@ -698,7 +702,7 @@ var
 begin
   if n.sons[0] <> nil then begin
     result := evalAux(c, n.sons[0]);
-    if result.kind = nkExceptBranch then exit;
+    if isSpecial(result) then exit;
     a := result;
     result := newNodeIT(nkExceptBranch, n.info, a.typ);
     addSon(result, a);
@@ -717,7 +721,7 @@ function evalReturn(c: PEvalContext; n: PNode): PNode;
 begin
   if n.sons[0] <> nil then begin
     result := evalAsgn(c, n.sons[0]);
-    if result.kind = nkExceptBranch then exit;
+    if isSpecial(result) then exit;
   end;
   result := newNodeIT(nkReturnToken, n.info, nil);
 end;
@@ -743,7 +747,7 @@ end;
 function evalHigh(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   case skipTypes(n.sons[1].typ, abstractVar).kind of
     tyOpenArray, tySequence:
       result := newIntNodeT(sonsLen(result), n);
@@ -756,7 +760,7 @@ end;
 function evalIs(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   result := newIntNodeT(ord(inheritanceDiff(result.typ, n.sons[2].typ) >= 0), n)
 end;
 
@@ -766,10 +770,10 @@ var
   oldLen, newLen: int;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
   case a.kind of
     nkStrLit..nkTripleStrLit: begin
@@ -793,10 +797,10 @@ var
   newLen, oldLen, i: int;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
   if a.kind <> nkBracket then InternalError(n.info, 'evalSetLengthSeq');
   newLen := int(getOrdValue(b));
@@ -814,10 +818,10 @@ var
   i: int;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
 
   t := skipTypes(n.sons[1].typ, abstractVar);
@@ -833,7 +837,7 @@ end;
 function evalAssert(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   if getOrdValue(result) <> 0 then
     result := emptyNode
   else
@@ -845,10 +849,10 @@ var
   a, b: PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
   if not inSet(a, b) then addSon(a, copyTree(b));
   result := emptyNode;
@@ -860,10 +864,10 @@ var
   i: int;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := newNodeIT(nkCurly, n.info, n.sons[1].typ);
   addSon(b, result);
   r := diffSets(a, b);
@@ -877,10 +881,10 @@ var
   a, b: PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
   case a.kind of
     nkStrLit..nkTripleStrLit: addChar(a.strVal, chr(int(getOrdValue(b))));
@@ -896,11 +900,11 @@ var
   i: int;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   for i := 2 to sonsLen(n)-1 do begin
     result := evalAux(c, n.sons[i]);
-    if result.kind = nkExceptBranch then exit;
+    if isSpecial(result) then exit;
     a.strVal := getStrValue(a) +{&} getStrValue(result);
   end;
   result := a;
@@ -911,10 +915,10 @@ var
   a, b: PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
   case a.kind of
     nkStrLit..nkTripleStrLit: a.strVal := a.strVal +{&} getStrValue(b);
@@ -928,10 +932,10 @@ var
   a, b: PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   a := result;
   result := evalAux(c, n.sons[2]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   b := result;
   if a.kind = nkBracket then addSon(a, copyTree(b))
   else InternalError(n.info, 'evalAppendSeqElem');
@@ -941,10 +945,15 @@ end;
 function evalRepr(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
-  if result.kind = nkExceptBranch then exit;
+  if isSpecial(result) then exit;
   result := newStrNodeT(renderTree(result, {@set}[renderNoComments]), n);
 end;
 
+function isEmpty(n: PNode): bool;
+begin
+  result := (n <> nil) and (n.kind = nkEmpty)
+end;
+
 function evalMagicOrCall(c: PEvalContext; n: PNode): PNode;
 var
   m: TMagic;
@@ -979,7 +988,7 @@ begin
 
     mNLen: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := newNodeIT(nkIntLit, n.info, n.typ);
       case a.kind of
@@ -989,10 +998,10 @@ begin
     end;
     mNChild: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       k := getOrdValue(result);
       if not (a.kind in [nkEmpty..nkNilLit]) and (k >= 0) 
       and (k < sonsLen(a)) then begin
@@ -1006,13 +1015,13 @@ begin
     end;
     mNSetChild: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       b := result;
       result := evalAux(c, n.sons[3]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       k := getOrdValue(b);
       if (k >= 0) and (k < sonsLen(a))
       and not (a.kind in [nkEmpty..nkNilLit]) then begin
@@ -1025,45 +1034,45 @@ begin
     end;
     mNAdd: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       addSon(a, result);
       result := emptyNode
     end;
     mNAddMultiple: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       for i := 0 to sonsLen(result)-1 do addSon(a, result.sons[i]);
       result := emptyNode
     end;
     mNDel: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       b := result;
       result := evalAux(c, n.sons[3]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       for i := 0 to int(getOrdValue(result))-1 do
         delSon(a, int(getOrdValue(b)));
       result := emptyNode;
     end;
     mNKind: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := newNodeIT(nkIntLit, n.info, n.typ);
       result.intVal := ord(a.kind);
     end;
     mNIntVal: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := newNodeIT(nkIntLit, n.info, n.typ);
       case a.kind of
@@ -1073,7 +1082,7 @@ begin
     end;
     mNFloatVal: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := newNodeIT(nkFloatLit, n.info, n.typ);
       case a.kind of
@@ -1083,18 +1092,18 @@ begin
     end;
     mNSymbol: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       if result.kind <> nkSym then InternalError(n.info, 'no symbol')
     end;
     mNIdent: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       if result.kind <> nkIdent then InternalError(n.info, 'no symbol')
     end;
     mNGetType: result := evalAux(c, n.sons[1]);
     mNStrVal: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := newNodeIT(nkStrLit, n.info, n.typ);
       case a.kind of
@@ -1104,64 +1113,64 @@ begin
     end;
     mNSetIntVal: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a.intVal := result.intVal; // XXX: exception handling?
       result := emptyNode
     end;
     mNSetFloatVal: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a.floatVal := result.floatVal; // XXX: exception handling?
       result := emptyNode
     end;
     mNSetSymbol: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a.sym := result.sym; // XXX: exception handling?
       result := emptyNode
     end;
     mNSetIdent: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a.ident := result.ident; // XXX: exception handling?
       result := emptyNode
     end;
     mNSetType: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a.typ := result.typ; // XXX: exception handling?
       result := emptyNode
     end;
     mNSetStrVal: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a.strVal := result.strVal; // XXX: exception handling?
       result := emptyNode
     end;
     mNNewNimNode: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       k := getOrdValue(result);
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       if (k < 0) or (k > ord(high(TNodeKind))) then
         internalError(n.info, 'request to create a NimNode with invalid kind');
@@ -1172,17 +1181,17 @@ begin
     end;
     mNCopyNimNode: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       result := copyNode(result);
     end;
     mNCopyNimTree: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       result := copyTree(result);
     end;
     mStrToIdent: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       if not (result.kind in [nkStrLit..nkTripleStrLit]) then
         InternalError(n.info, 'no string node');
       a := result;
@@ -1191,7 +1200,7 @@ begin
     end;
     mIdentToStr: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       if result.kind <> nkIdent then
         InternalError(n.info, 'no ident node');
       a := result;
@@ -1200,10 +1209,10 @@ begin
     end;
     mEqIdent: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       b := result;
       result := newNodeIT(nkIntLit, n.info, n.typ);
       if (a.kind = nkIdent) and (b.kind = nkIdent) then
@@ -1211,10 +1220,10 @@ begin
     end;
     mEqNimrodNode: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := evalAux(c, n.sons[2]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       b := result;
       result := newNodeIT(nkIntLit, n.info, n.typ);
       if (a = b) 
@@ -1224,19 +1233,19 @@ begin
     end;
     mNHint: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       liMessage(n.info, hintUser, getStrValue(result));
       result := emptyNode
     end;
     mNWarning: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       liMessage(n.info, warnUser, getStrValue(result));
       result := emptyNode
     end;
     mNError: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       stackTrace(c, n, errUser, getStrValue(result));
       result := emptyNode
     end;
@@ -1244,28 +1253,31 @@ begin
     mRepr: result := evalRepr(c, n);
     mNewString: begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       result := newNodeIT(nkStrLit, n.info, n.typ);
       result.strVal := newString(int(getOrdValue(a)));
     end;
     else begin
       result := evalAux(c, n.sons[1]);
-      if result.kind = nkExceptBranch then exit;
+      if isSpecial(result) then exit;
       a := result;
       b := nil;
       cc := nil;
       if sonsLen(n) > 2 then begin
         result := evalAux(c, n.sons[2]);
-        if result.kind = nkExceptBranch then exit;
+        if isSpecial(result) then exit;
         b := result;
         if sonsLen(n) > 3 then begin
           result := evalAux(c, n.sons[3]);
-          if result.kind = nkExceptBranch then exit;
+          if isSpecial(result) then exit;
           cc := result;
         end
       end;
-      result := evalOp(m, n, a, b, cc);
+      if isEmpty(a) or isEmpty(b) or isEmpty(cc) then
+        result := emptyNode
+      else
+        result := evalOp(m, n, a, b, cc);
     end
   end
 end;
@@ -1290,7 +1302,7 @@ begin
       a := copyNode(n);
       for i := 0 to sonsLen(n)-1 do begin
         result := evalAux(c, n.sons[i]);
-        if result.kind = nkExceptBranch then exit;        
+        if isSpecial(result) then exit;        
         addSon(a, result);
       end;
       result := a
@@ -1299,7 +1311,7 @@ begin
       a := copyTree(n);
       for i := 0 to sonsLen(n)-1 do begin
         result := evalAux(c, n.sons[i].sons[1]);
-        if result.kind = nkExceptBranch then exit;
+        if isSpecial(result) then exit;
         a.sons[i].sons[1] := result;
       end;
       result := a
@@ -1397,9 +1409,5 @@ begin
 end;
 
 initialization
-  new(emptyNode);
-{@ignore}
-  fillChar(emptyNode^, sizeof(emptyNode^), 0);
-{@emit}
-  emptyNode.kind := nkEmpty;
+  emptyNode := newNode(nkEmpty);
 end.
diff --git a/rod/nimrod.ini b/rod/nimrod.ini
index 78b736721..1046f400f 100755
--- a/rod/nimrod.ini
+++ b/rod/nimrod.ini
@@ -35,6 +35,7 @@ Files: "configure;makefile"
 Files: "*.html"
 Files: "*.py"
 Files: "*.ini"
+Files: "*.nim"
 
 Files: "rod/readme.txt"
 Files: "rod/nimrod.ini"