summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorrumpf_a@web.de <>2009-10-27 22:28:02 +0100
committerrumpf_a@web.de <>2009-10-27 22:28:02 +0100
commitd5acb88cccecf54bcc9a7c13f4fbaa095a8b37d4 (patch)
treeda88c98e8bd063f7991d2e2cba5797351d301eba
parent053309e60aee1eda594a4817ac8ac2fb8c18fb04 (diff)
downloadNim-d5acb88cccecf54bcc9a7c13f4fbaa095a8b37d4.tar.gz
bugfixes: macros; splitFile; strutils.split; iterator.method
-rwxr-xr-xdata/magic.yml1
-rwxr-xr-xdata/messages.yml2
-rwxr-xr-xdoc/intern.txt2
-rwxr-xr-xdoc/lib.txt2
-rwxr-xr-xdoc/manual.txt4
-rwxr-xr-xdoc/nimrodc.txt2
-rwxr-xr-xdoc/tut1.txt8
-rwxr-xr-xkoch.py13
-rwxr-xr-xlib/pure/macros.nim5
-rwxr-xr-xlib/pure/os.nim30
-rwxr-xr-xlib/pure/strutils.nim9
-rwxr-xr-xnim/ast.pas6
-rwxr-xr-xnim/cgen.pas2
-rwxr-xr-xnim/commands.pas4
-rwxr-xr-xnim/depends.pas6
-rwxr-xr-xnim/evals.pas27
-rwxr-xr-xnim/extccomp.pas8
-rwxr-xr-xnim/main.pas9
-rwxr-xr-xnim/msgs.pas2
-rwxr-xr-xnim/nimrod.pas2
-rwxr-xr-xnim/nos.pas45
-rwxr-xr-xnim/nversion.pas4
-rwxr-xr-xnim/options.pas5
-rwxr-xr-xnim/pragmas.pas11
-rwxr-xr-xnim/rst.pas6
-rwxr-xr-xnim/sem.pas7
-rwxr-xr-xnim/semexprs.pas27
-rwxr-xr-xnim/strutils.pas8
-rwxr-xr-xtests/titer5.nim8
-rwxr-xr-xtools/nimweb.nim2
-rwxr-xr-xweb/index.txt5
31 files changed, 177 insertions, 95 deletions
diff --git a/data/magic.yml b/data/magic.yml
index d44296966..857a24088 100755
--- a/data/magic.yml
+++ b/data/magic.yml
@@ -247,6 +247,7 @@
 'StrToIdent',
 'IdentToStr',
 'EqIdent',
+'EqNimrodNode',
 'NHint',
 'NWarning',
 'NError'
diff --git a/data/messages.yml b/data/messages.yml
index ac41b5031..51ec2b088 100755
--- a/data/messages.yml
+++ b/data/messages.yml
@@ -201,7 +201,7 @@
 {'errXNeedsReturnType': '$1 needs a return type'},
 {'errInvalidCommandX': "invalid command: '$1'"},
 {'errXOnlyAtModuleScope': "'$1' is only allowed at top level"},
-{'errTemplateInstantiationTooNested': 'template instantiation too nested'},
+{'errTemplateInstantiationTooNested': 'template/macro instantiation too nested'},
 {'errInstantiationFrom': 'instantiation from here'},
 {'errInvalidIndexValueForTuple': 'invalid index value for tuple subscript'},
 {'errCommandExpectsFilename': 'command expects a filename argument'},
diff --git a/doc/intern.txt b/doc/intern.txt
index 58879c659..e62378e1d 100755
--- a/doc/intern.txt
+++ b/doc/intern.txt
@@ -8,7 +8,7 @@
 
 .. contents::
 
-  Abstraction is layering ignorance on top of reality. -- unknown
+  "Abstraction is layering ignorance on top of reality." -- unknown
 
 
 Directory structure
diff --git a/doc/lib.txt b/doc/lib.txt
index b75dd446b..d523bf559 100755
--- a/doc/lib.txt
+++ b/doc/lib.txt
@@ -7,7 +7,7 @@ Nimrod Standard Library
 
 ..
 
-  The good thing about reinventing the wheel is that you can get a round one.
+  "The good thing about reinventing the wheel is that you can get a round one."
 
 Though the Nimrod Standard Library is still evolving, it is already quite
 usable. It is divided into *pure libraries*, *impure libraries* and *wrappers*.
diff --git a/doc/manual.txt b/doc/manual.txt
index 9cf1f3bc2..978ef1496 100755
--- a/doc/manual.txt
+++ b/doc/manual.txt
@@ -760,7 +760,7 @@ An example:
       nkIf            # an if statement
     PNode = ref TNode
     TNode = object
-      case kind: TNodeKind  # the ``kind`` field is the discriminator
+      case kind: TNodeKind  # the ``kind`` field is the discriminant
       of nkInt: intVal: int
       of nkFloat: floavVal: float
       of nkString: strVal: string
@@ -1648,7 +1648,7 @@ required. ``Elif`` parts are also allowed (but unlikely to be good
 style).
 
 
-Type convertions
+Type conversions
 ~~~~~~~~~~~~~~~~
 Syntactically a `type conversion` is like a procedure call, but a
 type name replaces the procedure name. A type conversion is always
diff --git a/doc/nimrodc.txt b/doc/nimrodc.txt
index f43994cb8..3200b135b 100755
--- a/doc/nimrodc.txt
+++ b/doc/nimrodc.txt
@@ -6,7 +6,7 @@
 :Version: |nimrodversion|
 
 .. contents::
-
+  
 Introduction
 ============
 
diff --git a/doc/tut1.txt b/doc/tut1.txt
index c3d7b0039..ad46281d8 100755
--- a/doc/tut1.txt
+++ b/doc/tut1.txt
@@ -871,7 +871,7 @@ type:
   var
     x = 0.0      # x is of type ``float``
     y = 0.0'f32  # y is of type ``float32``
-    z = 0.0'f64  # z is of type ``int64``
+    z = 0.0'f64  # z is of type ``float64``
 
 The common operators ``+ - * /  <  <=  ==  !=  >  >=`` are defined for
 floats and follow the IEEE standard.
@@ -1318,7 +1318,7 @@ This is best illustrated by an example:
 
   main()
 
-
+.. code-block:: nimrod
   # Module B
   import A  # A is not parsed here! Only the already known symbols
             # of A are imported.
@@ -1338,9 +1338,11 @@ imported by a third one:
   # Module A
   var x*: string
 
+.. code-block:: nimrod
   # Module B
   var x*: int
 
+.. code-block:: nimrod
   # Module C
   import A, B
   write(stdout, x) # error: x is ambiguous
@@ -1357,9 +1359,11 @@ rules apply:
   # Module A
   proc x*(a: int): string = return $a
 
+.. code-block:: nimrod
   # Module B
   proc x*(a: string): string = return $a
 
+.. code-block:: nimrod
   # Module C
   import A, B
   write(stdout, x(3))   # no error: A.x is called
diff --git a/koch.py b/koch.py
index 9a9f38649..8323c97bb 100755
--- a/koch.py
+++ b/koch.py
@@ -12,7 +12,7 @@ from pycompab import *
 
 # --------------------- constants  ----------------------------------------
 
-NIMROD_VERSION = '0.8.2'
+NIMROD_VERSION = '0.8.3'
 # This string contains Nimrod's version. It is the only place
 # where the version needs to be updated. The rest is done by
 # the build process automatically. It is replaced **everywhere**!
@@ -362,7 +362,7 @@ def cmd_rod(options):
     if Exists(ExeExt("bin/nimrod")):
       c.success()
 
-# ------------------- constants -----------------------------------------------
+# -----------------------------------------------------------------------------
 
 HELP = Subs("""\
 +-----------------------------------------------------------------+
@@ -426,6 +426,7 @@ def main(args):
     elif cmd == "inno": cmd_inno()
     elif cmd == "csource": cmd_csource(join(args[i+1:]))
     elif cmd == "install": cmd_install() # for backwards compability
+    #elif cmd == "llvmdebug": cmd_llvm(debug=true)
     else: Error("illegal command: " + cmd)
     
 def cmd_csource(args):
@@ -443,6 +444,14 @@ def cmd_inno():
 
 def cmd_install():
   Exec("sh ./build.sh")
+  
+def cmd_llvm(debug=true):
+  if not debug: release = "--enable-optimized"
+  else: release = ""
+  Exec(Subs("./configure --enable-bindings $1 --enable-shared" +
+            " --enable-targets=host", release))
+  Exec("make")
+  Echo("Type [sudo] make install!")
 
 # -------------------------- bootstrap ----------------------------------------
 
diff --git a/lib/pure/macros.nim b/lib/pure/macros.nim
index 5129cde1b..677469ed2 100755
--- a/lib/pure/macros.nim
+++ b/lib/pure/macros.nim
@@ -122,8 +122,11 @@ proc `!` *(s: string): TNimrodIdent {.magic: "StrToIdent".}
 proc `$`*(i: TNimrodIdent): string {.magic: "IdentToStr".}

   ## converts a Nimrod identifier to a string

 

-proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent".}

+proc `==`* (a, b: TNimrodIdent): bool {.magic: "EqIdent", noSideEffect.}

   ## compares two Nimrod identifiers

+
+proc `==`* (a, b: PNimrodNode): bool {.magic: "EqNimrodNode", noSideEffect.}

+  ## compares two Nimrod nodes

 

 proc len*(n: PNimrodNode): int {.magic: "NLen".}

   ## returns the number of children of `n`.

diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index a2a1830f7..c5d683975 100755
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -10,7 +10,6 @@
 ## This module contains basic operating system facilities like
 ## retrieving environment variables, reading command line arguments,
 ## working with directories, running shell commands, etc.
-## This module is -- like any other basic library -- platform independant.
 {.deadCodeElim: on.}
 
 {.push debugger: off.}
@@ -384,10 +383,13 @@ proc SplitPath*(path: string): tuple[head, tail: string] {.noSideEffect.} =
   ## Splits a directory into (head, tail), so that
   ## ``JoinPath(head, tail) == path``.
   ##
-  ## Example: After ``SplitPath("usr/local/bin", head, tail)``,
-  ## `head` is "usr/local" and `tail` is "bin".
-  ## Example: After ``SplitPath("usr/local/bin/", head, tail)``,
-  ## `head` is "usr/local/bin" and `tail` is "".
+  ## Examples: 
+  ## .. code-block:: nimrod
+  ##   SplitPath("usr/local/bin") -> ("usr/local", "bin")
+  ##   SplitPath("usr/local/bin/") -> ("usr/local/bin", "")
+  ##   SplitPath("bin") -> ("", "bin")
+  ##   SplitPath("/bin") -> ("", "bin")
+  ##   SplitPath("") -> ("", "")
   var
     sepPos = -1
   for i in countdown(len(path)-1, 0):
@@ -431,8 +433,9 @@ proc normExt(ext: string): string =
   else: result = extSep & ext
 
 proc searchExtPos(s: string): int =
+  # BUGFIX: do not search until 0! .DS_Store is no file extension!
   result = -1
-  for i in countdown(len(s)-1, 0):
+  for i in countdown(len(s)-1, 1):
     if s[i] == extsep:
       result = i
       break
@@ -447,10 +450,11 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {.noSideEffect.} =
   ## Example:
   ##
   ## .. code-block:: nimrod
-  ## var (dir, name, ext) = splitFile("usr/local/nimrodc.html")
-  ## assert dir == "usr/local"
-  ## assert name == "nimrodc"
-  ## assert ext == ".html"
+  ##   var (dir, name, ext) = splitFile("usr/local/nimrodc.html")
+  ##   assert dir == "usr/local"
+  ##   assert name == "nimrodc"
+  ##   assert ext == ".html"
+  ##
   ## If `path` has no extension, `ext` is the empty string.
   ## If `path` has no directory component, `dir` is the empty string.
   ## If `path` has no filename component, `name` and `ext` are empty strings.
@@ -461,7 +465,7 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {.noSideEffect.} =
     var dotPos = path.len
     for i in countdown(len(path)-1, 0):
       if path[i] == ExtSep:
-        if dotPos == path.len: dotPos = i
+        if dotPos == path.len and i > 0: dotPos = i
       elif path[i] in {dirsep, altsep}:
         sepPos = i
         break
@@ -877,9 +881,9 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string =
   ## filter                  meaning
   ## ---------------------   ---------------------------------------------
   ## ``pcFile``              yield real files
-  ## ``pcLinkToFile``        yield symbol links to files
+  ## ``pcLinkToFile``        yield symbolic links to files
   ## ``pcDir``               follow real directories
-  ## ``pcLinkToDir``         follow symbol links to directories
+  ## ``pcLinkToDir``         follow symbolic links to directories
   ## ---------------------   ---------------------------------------------
   ## 
   var stack = @[dir]
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 25b495f10..d17c48740 100755
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -169,15 +169,14 @@ iterator split*(s: string, seps: set[char] = Whitespace): string =
   ##     writeln(stdout, word)
   ##
   ## produces the same output.
-  var
-    first: int = 0
-    last: int = 0
+  var last = 0
   assert(not ('\0' in seps))
   while last < len(s):
     while s[last] in seps: inc(last)
-    first = last
+    var first = last
     while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX!
-    yield copy(s, first, last-1)
+    if first <= last-1:
+      yield copy(s, first, last-1)
 
 iterator split*(s: string, sep: char): string =
   ## Splits the string `s` into substrings.
diff --git a/nim/ast.pas b/nim/ast.pas
index 8927fc862..277d7d061 100755
--- a/nim/ast.pas
+++ b/nim/ast.pas
@@ -262,7 +262,8 @@ type
     mNAddMultiple, mNDel, mNKind, mNIntVal, mNFloatVal, mNSymbol, 
     mNIdent, mNGetType, mNStrVal, mNSetIntVal, mNSetFloatVal, mNSetSymbol, 
     mNSetIdent, mNSetType, mNSetStrVal, mNNewNimNode, mNCopyNimNode, mNCopyNimTree, 
-    mStrToIdent, mIdentToStr, mEqIdent, mNHint, mNWarning, mNError
+    mStrToIdent, mIdentToStr, mEqIdent, mEqNimrodNode, mNHint, mNWarning, 
+    mNError
     //[[[end]]]
   );
 
@@ -521,7 +522,8 @@ const // "MagicToStr" array:
     'NAddMultiple', 'NDel', 'NKind', 'NIntVal', 'NFloatVal', 'NSymbol', 
     'NIdent', 'NGetType', 'NStrVal', 'NSetIntVal', 'NSetFloatVal', 'NSetSymbol', 
     'NSetIdent', 'NSetType', 'NSetStrVal', 'NNewNimNode', 'NCopyNimNode', 'NCopyNimTree', 
-    'StrToIdent', 'IdentToStr', 'EqIdent', 'NHint', 'NWarning', 'NError'
+    'StrToIdent', 'IdentToStr', 'EqIdent', 'EqNimrodNode', 'NHint', 'NWarning', 
+    'NError'
     //[[[end]]]
   );
 
diff --git a/nim/cgen.pas b/nim/cgen.pas
index 0b74f25b7..83c34241a 100755
--- a/nim/cgen.pas
+++ b/nim/cgen.pas
@@ -43,7 +43,7 @@ type
     cfsProcs,          // section for C procs that are not inline
     cfsTypeInit1,      // section 1 for declarations of type information
     cfsTypeInit2,      // section 2 for initialization of type information
-    cfsTypeInit3,      // section 3 for init of type information
+    cfsTypeInit3,      // section 3 for initialization of type information
     cfsDebugInit,      // section for initialization of debug information
     cfsDynLibInit,     // section for initialization of dynamic library binding
     cfsDynLibDeinit    // section for deinitialization of dynamic libraries
diff --git a/nim/commands.pas b/nim/commands.pas
index 1663b6b93..e88fc6b8c 100755
--- a/nim/commands.pas
+++ b/nim/commands.pas
@@ -309,11 +309,11 @@ end;
 

 procedure processCompile(const filename: string);

 var

-  found, trunc, ext: string;

+  found, trunc: string;

 begin

   found := findFile(filename);

   if found = '' then found := filename;

-  splitFilename(found, trunc, ext);

+  trunc := changeFileExt(found, '');

   extccomp.addExternalFileToCompile(trunc);

   extccomp.addFileToLink(completeCFilePath(trunc, false));

 end;

diff --git a/nim/depends.pas b/nim/depends.pas
index c5b844044..6711875fe 100755
--- a/nim/depends.pas
+++ b/nim/depends.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -51,12 +51,12 @@ begin
   case n.kind of
     nkImportStmt: begin
       for i := 0 to sonsLen(n)-1 do begin
-        imported := extractFileTrunk(getModuleFile(n.sons[i]));
+        imported := splitFile(getModuleFile(n.sons[i])).name;
         addDependencyAux(g.module.name.s, imported);
       end
     end;
     nkFromStmt: begin
-      imported := extractFileTrunk(getModuleFile(n.sons[0]));
+      imported := splitFile(getModuleFile(n.sons[0])).name;
       addDependencyAux(g.module.name.s, imported);
     end;
     nkStmtList, nkBlockStmt, nkStmtListExpr, nkBlockExpr: begin
diff --git a/nim/evals.pas b/nim/evals.pas
index bb6c8a2b1..43494f929 100755
--- a/nim/evals.pas
+++ b/nim/evals.pas
@@ -994,9 +994,11 @@ begin
       result := evalAux(c, n.sons[2]);
       if result.kind = nkExceptBranch then exit;
       k := getOrdValue(result);
-      if (k >= 0) and (k < sonsLen(a))
-      and not (a.kind in [nkEmpty..nkNilLit]) then
-        result := a.sons[int(k)]
+      if not (a.kind in [nkEmpty..nkNilLit]) and (k >= 0) 
+      and (k < sonsLen(a)) then begin
+        result := a.sons[int(k)];
+        if result = nil then result := newNode(nkEmpty)
+      end
       else begin
         stackTrace(c, n, errIndexOutOfBounds);
         result := emptyNode
@@ -1013,8 +1015,10 @@ begin
       if result.kind = nkExceptBranch then exit;
       k := getOrdValue(b);
       if (k >= 0) and (k < sonsLen(a))
-      and not (a.kind in [nkEmpty..nkNilLit]) then
-        a.sons[int(k)] := result
+      and not (a.kind in [nkEmpty..nkNilLit]) then begin
+        if result.kind = nkEmpty then a.sons[int(k)] := nil
+        else a.sons[int(k)] := result
+      end
       else
         stackTrace(c, n, errIndexOutOfBounds);
       result := emptyNode;
@@ -1205,6 +1209,19 @@ begin
       if (a.kind = nkIdent) and (b.kind = nkIdent) then
         if a.ident.id = b.ident.id then result.intVal := 1
     end;
+    mEqNimrodNode: begin
+      result := evalAux(c, n.sons[1]);
+      if result.kind = nkExceptBranch then exit;
+      a := result;
+      result := evalAux(c, n.sons[2]);
+      if result.kind = nkExceptBranch then exit;
+      b := result;
+      result := newNodeIT(nkIntLit, n.info, n.typ);
+      if (a = b) 
+      or (b.kind in [nkNilLit, nkEmpty]) 
+      and (a.kind in [nkNilLit, nkEmpty]) then
+        result.intVal := 1
+    end;
     mNHint: begin
       result := evalAux(c, n.sons[1]);
       if result.kind = nkExceptBranch then exit;
diff --git a/nim/extccomp.pas b/nim/extccomp.pas
index aab4febb7..7df3e8748 100755
--- a/nim/extccomp.pas
+++ b/nim/extccomp.pas
@@ -438,7 +438,7 @@ var
 begin
   c := ccompiler;
   options := compileOptions;
-  trunk := extractFileTrunk(cfilename);
+  trunk := splitFile(cfilename).name;
   if optCDebug in gGlobalOptions then begin
     key := trunk + '.debug';
     if existsConfigVar(key) then
@@ -594,15 +594,15 @@ begin
       
     if optGenDynLib in gGlobalOptions then begin
       exefile := format(platform.os[targetOS].dllFrmt,
-                        [extractFileTrunk(projectFile)]);
+                        [splitFile(projectFile).name]);
       buildDll := cc[c].buildDll;
     end
     else begin
-      exefile := extractFileTrunk(projectFile) +{&} platform.os[targetOS].exeExt;
+      exefile := splitFile(projectFile).name +{&} platform.os[targetOS].exeExt;
       buildDll := '';
     end;
     if targetOS = platform.hostOS then
-      exefile := joinPath(extractDir(projectFile), exefile);
+      exefile := joinPath(splitFile(projectFile).dir, exefile);
     exefile := quoteIfContainsWhite(exefile);
 
     it := PStrEntry(toLink.head);
diff --git a/nim/main.pas b/nim/main.pas
index c3f2cbd85..4b35513c5 100755
--- a/nim/main.pas
+++ b/nim/main.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -69,7 +69,7 @@ begin
 {@emit}
   result.id := -1; // for better error checking
   result.kind := skModule;
-  result.name := getIdent(extractFileTrunk(filename));
+  result.name := getIdent(splitFile(filename).name);
   result.owner := result; // a module belongs to itself
   result.info := newLineInfo(filename, 1, 1);
   include(result.flags, sfUsed);
@@ -321,14 +321,11 @@ begin
 end;
 
 procedure MainCommand(const cmd, filename: string);
-var
-  dir, f: string;
 begin
   appendStr(searchPaths, options.libpath);
   if filename <> '' then begin
-    splitPath(filename, dir, f);
     // current path is always looked first for modules
-    prependStr(searchPaths, dir);
+    prependStr(searchPaths, splitFile(filename).dir);
   end;
   setID(100);
   passes.gIncludeFile := syntaxes.parseFile;
diff --git a/nim/msgs.pas b/nim/msgs.pas
index f1a3a200a..55ccdda5e 100755
--- a/nim/msgs.pas
+++ b/nim/msgs.pas
@@ -467,7 +467,7 @@ const
     '$1 needs a return type',
     'invalid command: ''$1''',
     '''$1'' is only allowed at top level',
-    'template instantiation too nested',
+    'template/macro instantiation too nested',
     'instantiation from here',
     'invalid index value for tuple subscript',
     'command expects a filename argument',
diff --git a/nim/nimrod.pas b/nim/nimrod.pas
index b3247bff0..8d7db04b2 100755
--- a/nim/nimrod.pas
+++ b/nim/nimrod.pas
@@ -84,7 +84,7 @@ begin
     command := '';
     filename := '';
     ProcessCmdLine(passCmd1, command, filename);
-    if filename <> '' then options.projectPath := extractDir(filename);
+    if filename <> '' then options.projectPath := splitFile(filename).dir;
     nimconf.LoadConfig(filename); // load the right config file
     // now process command line arguments again, because some options in the
     // command line can overwite the config file's settings
diff --git a/nim/nos.pas b/nim/nos.pas
index 7b9d2ee09..7c74ba1bc 100755
--- a/nim/nos.pas
+++ b/nim/nos.pas
@@ -29,6 +29,13 @@ uses
 type
   EOSError = class(exception)
   end;
+  
+  TSplitFileResult = record
+    dir, name, ext: string;
+  end;
+  TSplitPathResult = record
+    head, tail: string;
+  end;
 
 const
   curdir = '.';
@@ -59,7 +66,7 @@ procedure putEnv(const name, val: string);
 function JoinPath(const head, tail: string): string; overload;
 function JoinPath(const parts: array of string): string; overload;
 
-procedure SplitPath(const path: string; out head, tail: string);
+procedure SplitPath(const path: string; out head, tail: string); overload;
 
 function extractDir(const f: string): string;
 function extractFilename(const f: string): string;
@@ -87,9 +94,38 @@ function sameFile(const path1, path2: string): boolean;
 
 function extractFileTrunk(const filename: string): string;
 
+function splitFile(const path: string): TSplitFileResult;
+function splitPath(const path: string): TSplitPathResult; overload;
+
 
 implementation
 
+function splitFile(const path: string): TSplitFileResult;
+var
+  sepPos, dotPos, i: int;
+begin
+  if (path = '') or (path[length(path)] in [dirSep, altSep]) then begin
+    result.dir := path;
+    result.name := '';
+    result.ext := '';
+  end
+  else begin
+    sepPos := 0;
+    dotPos := length(path)+1;
+    for i := length(path) downto 1 do begin
+      if path[i] = ExtSep then begin
+        if (dotPos = length(path)+1) and (i > 1) then dotPos := i
+      end
+      else if path[i] in [dirsep, altsep] then begin
+        sepPos := i; break
+      end
+    end;
+    result.dir := ncopy(path, 1, sepPos-1);
+    result.name := ncopy(path, sepPos+1, dotPos-1);
+    result.ext := ncopy(path, dotPos)
+  end
+end;
+
 function extractFileTrunk(const filename: string): string;
 var
   f, e, dir: string;
@@ -146,7 +182,7 @@ var
   i: int;
 begin
   result := -1;
-  for i := length(s) downto 1 do
+  for i := length(s) downto 2 do
     if s[i] = extsep then begin
       result := i;
       break
@@ -219,6 +255,11 @@ begin
   end
 end;
 
+function SplitPath(const path: string): TSplitPathResult;
+begin
+  SplitPath(path, result.head, result.tail);
+end;
+
 function getApplicationFilename(): string;
 {$ifdef darwin}
 var
diff --git a/nim/nversion.pas b/nim/nversion.pas
index 20ab5cc77..c9bdd24fb 100755
--- a/nim/nversion.pas
+++ b/nim/nversion.pas
@@ -31,10 +31,10 @@ const
   //cog.outl('VersionMinor = %s;' % ver[1])

   //cog.outl('VersionPatch = %s;' % ver[2])

   //]]]

-  VersionAsString = '0.8.2';
+  VersionAsString = '0.8.3';
   VersionMajor = 0;
   VersionMinor = 8;
-  VersionPatch = 2;
+  VersionPatch = 3;
   //[[[[end]]]]

 

 implementation

diff --git a/nim/options.pas b/nim/options.pas
index d03a24f2a..3a7d4a669 100755
--- a/nim/options.pas
+++ b/nim/options.pas
@@ -176,11 +176,8 @@ begin
 end;
 
 function getPrefixDir: string;
-var
-  appdir, bin: string;
 begin
-  appdir := getApplicationDir();
-  SplitPath(appdir, result, bin);
+  result := SplitPath(getApplicationDir()).head;
 end;
 
 function shortenDir(const dir: string): string;
diff --git a/nim/pragmas.pas b/nim/pragmas.pas
index e8d07d52d..8411a319f 100755
--- a/nim/pragmas.pas
+++ b/nim/pragmas.pas
@@ -415,24 +415,23 @@ type
 
 procedure processCompile(c: PContext; n: PNode);
 var
-  s, found, trunc, ext: string;
+  s, found, trunc: string;
 begin
   s := expectStrLit(c, n);
   found := findFile(s);
   if found = '' then found := s;
-  splitFilename(found, trunc, ext);
+  trunc := ChangeFileExt(found, '');
   extccomp.addExternalFileToCompile(trunc);
   extccomp.addFileToLink(completeCFilePath(trunc, false));
 end;
 
 procedure processCommonLink(c: PContext; n: PNode; feature: TLinkFeature);
 var
-  f, tmp, ext, found: string;
+  f, found: string;
 begin
   f := expectStrLit(c, n);
-  splitFilename(f, tmp, ext);
-  if (ext = '') then
-    f := toObjFile(tmp);
+  if splitFile(f).ext = '' then
+    f := toObjFile(f);
   found := findFile(f);
   if found = '' then
     found := f; // use the default
diff --git a/nim/rst.pas b/nim/rst.pas
index fb29b7d9f..89ef2c501 100755
--- a/nim/rst.pas
+++ b/nim/rst.pas
@@ -1,15 +1,15 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
 //
 unit rst;
 
-// This module implements a *reStructuredText* parser. Currently, only a
-// subset is provided. Later, there will be additions.
+// This module implements a *reStructuredText* parser. A larget
+// subset is provided.
 
 interface
 
diff --git a/nim/sem.pas b/nim/sem.pas
index 64cdbd436..a5d28d734 100755
--- a/nim/sem.pas
+++ b/nim/sem.pas
@@ -130,12 +130,17 @@ begin
   end
 end;
 
+{$include 'semtempl.pas'}
+
 function semMacroExpr(c: PContext; n: PNode; sym: PSym;
                       semCheck: bool = true): PNode;
 var
   p: PEvalContext;
   s: PStackFrame;
 begin
+  inc(evalTemplateCounter);
+  if evalTemplateCounter > 100 then
+    liMessage(n.info, errTemplateInstantiationTooNested);
   markUsed(n, sym);
   p := newEvalContext(c.module, '', false);
   s := newStackFrame();
@@ -150,9 +155,9 @@ begin
   if cyclicTree(result) then liMessage(n.info, errCyclicTree);
   if semCheck then
     result := semAfterMacroCall(c, result, sym);
+  dec(evalTemplateCounter);
 end;
 
-{$include 'semtempl.pas'}
 {$include 'seminst.pas'}
 {$include 'sigmatch.pas'}
 
diff --git a/nim/semexprs.pas b/nim/semexprs.pas
index 91c909dfd..2d1d0a957 100755
--- a/nim/semexprs.pas
+++ b/nim/semexprs.pas
@@ -517,20 +517,19 @@ begin
   result := nil;
   prc := n.sons[0];
   checkMinSonsLen(n, 1);
-  case n.sons[0].kind of
-    nkDotExpr: begin
-      checkSonsLen(n.sons[0], 2);
-      n.sons[0] := semDotExpr(c, n.sons[0]);
-      if n.sons[0].kind = nkDotCall then begin // it is a static call!
-        result := n.sons[0];
-        result.kind := nkCall;
-        for i := 1 to sonsLen(n)-1 do addSon(result, n.sons[i]);
-        result := semExpr(c, result);
-        exit
-      end
-    end;
-    else n.sons[0] := semExpr(c, n.sons[0]);
-  end; 
+  if n.sons[0].kind = nkDotExpr then begin
+    checkSonsLen(n.sons[0], 2);
+    n.sons[0] := semDotExpr(c, n.sons[0]);
+    if n.sons[0].kind = nkDotCall then begin // it is a static call!
+      result := n.sons[0];
+      result.kind := nkCall;
+      for i := 1 to sonsLen(n)-1 do addSon(result, n.sons[i]);
+      result := semExpr(c, result, flags);
+      exit
+    end
+  end
+  else 
+    n.sons[0] := semExpr(c, n.sons[0]);
   semOpAux(c, n);
   if (n.sons[0].typ <> nil) then t := skipTypes(n.sons[0].typ, abstractInst)
   else t := nil;
diff --git a/nim/strutils.pas b/nim/strutils.pas
index afd8b4766..96c07d365 100755
--- a/nim/strutils.pas
+++ b/nim/strutils.pas
@@ -162,9 +162,11 @@ begin
     while (last <= length(s)) and (s[last] in seps) do inc(last);
     first := last;
     while (last <= length(s)) and not (s[last] in seps) do inc(last);
-    len := length(result);
-    setLength(result, len+1);
-    result[len] := ncopy(s, first, last-1);
+    if first >= last-1 then begin
+      len := length(result);
+      setLength(result, len+1);
+      result[len] := ncopy(s, first, last-1);
+    end
   end
 end;
 
diff --git a/tests/titer5.nim b/tests/titer5.nim
new file mode 100755
index 000000000..c84c5c807
--- /dev/null
+++ b/tests/titer5.nim
@@ -0,0 +1,8 @@
+# Test method call syntax for iterators:
+const lines = """abc  xyz"""
+
+for x in lines.split():
+  stdout.write(x)
+
+#OUT abcxyz
+
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index bc074af74..249ec5f61 100755
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -220,7 +220,7 @@ proc main(c: var TConfigData) =
   buildAddDoc(c, "web/upload")
   buildDoc(c, "web/upload")
   buildDoc(c, "doc")
-  #buildPdfDoc(c, "doc")
+  buildPdfDoc(c, "doc")
 
 var c: TConfigData
 initConfigData(c)
diff --git a/web/index.txt b/web/index.txt
index dc9f9133a..320332679 100755
--- a/web/index.txt
+++ b/web/index.txt
@@ -94,11 +94,6 @@ Nimrod plays nice with others
   New bindings are easily generated in a semi-automatic way.
 * A Pascal to Nimrod conversion utility: A large subset of Object Pascal
   can be translated to Nimrod automatically!
-* Nimrod's documentation syntax is a subset of the wonderfully readable plaintext 
-  markup syntax 
-  `reStructuredText <http://docutils.sourceforge.net/docs/user/rst/quickref.html>`_.
-  The documentation generator is very flexible; this website has been generated
-  with it!
   
 
 Roadmap to 1.0