summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcontributors.txt1
-rwxr-xr-xlib/ecmas/dom.nim3
-rwxr-xr-xlib/system.nim21
-rwxr-xr-xlib/system/ecmasys.nim77
-rwxr-xr-xlib/system/excpt.nim72
-rwxr-xr-xlib/system/gc.nim28
-rwxr-xr-xlib/system/systhread.nim21
-rwxr-xr-xrod/ecmasgen.nim26
-rwxr-xr-xrod/main.nim2
-rwxr-xr-xrod/wordrecg.nim4
-rwxr-xr-xtests/ecmas.html6
-rwxr-xr-xtests/ecmas.nim11
-rwxr-xr-xtinyc/libtcc.c6
-rwxr-xr-xtodo.txt2
-rwxr-xr-xtools/nimrepl.nim63
15 files changed, 208 insertions, 135 deletions
diff --git a/contributors.txt b/contributors.txt
index 2f025f422..97a27f746 100755
--- a/contributors.txt
+++ b/contributors.txt
@@ -1,3 +1,4 @@
+Comex
 Philippe Lhoste
 Mario Ray Mahardhika
 Dominik Picheta
diff --git a/lib/ecmas/dom.nim b/lib/ecmas/dom.nim
index 6d9224c26..e9c587928 100755
--- a/lib/ecmas/dom.nim
+++ b/lib/ecmas/dom.nim
@@ -1,14 +1,13 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2006 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
 ## Declaration of the Document Object Model for the ECMAScript backend.
-##  (c) 2008 Andreas Rumpf
 
 when not defined(ecmascript):
   {.error: "This module only works on the ECMAScript platform".}
diff --git a/lib/system.nim b/lib/system.nim
index 9eabeb2af..abb3dd6e0 100755
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1605,10 +1605,8 @@ when not defined(EcmaScript) and not defined(NimrodVM):
     ## can be used to mark a condition to be unlikely. This is a hint for the 
     ## optimizer.
 
-elif defined(ecmaScript):
-  include "system/ecmasys"
-elif defined(NimrodVM):
-  # Stubs for the GC interface:
+elif defined(ecmaScript) or defined(NimrodVM):
+  # Stubs:
   proc GC_disable() = nil
   proc GC_enable() = nil
   proc GC_fullCollect() = nil
@@ -1620,16 +1618,19 @@ elif defined(NimrodVM):
   proc getOccupiedMem(): int = return -1
   proc getFreeMem(): int = return -1
   proc getTotalMem(): int = return -1
-  
-  proc cmp(x, y: string): int =
-    if x == y: return 0
-    if x < y: return -1
-    return 1
-    
+
   proc dealloc(p: pointer) = nil
   proc alloc(size: int): pointer = nil
   proc alloc0(size: int): pointer = nil
   proc realloc(p: Pointer, newsize: int): pointer = nil
 
+  when defined(ecmaScript):
+    include "system/ecmasys"
+  elif defined(NimrodVM):
+    proc cmp(x, y: string): int =
+      if x == y: return 0
+      if x < y: return -1
+      return 1
+
 {.pop.} # checks
 {.pop.} # hints
diff --git a/lib/system/ecmasys.nim b/lib/system/ecmasys.nim
index c0d0a5fd6..e2ecb370a 100755
--- a/lib/system/ecmasys.nim
+++ b/lib/system/ecmasys.nim
@@ -1,26 +1,12 @@
 #
 #
 #            Nimrod's Runtime Library
-#        (c) Copyright 2008 Andreas Rumpf
+#        (c) Copyright 2010 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
 #
 
-## Stubs for the GC interface:
-
-proc GC_disable() = nil
-proc GC_enable() = nil
-proc GC_fullCollect() = nil
-proc GC_setStrategy(strategy: TGC_Strategy) = nil
-proc GC_enableMarkAndSweep() = nil
-proc GC_disableMarkAndSweep() = nil
-proc GC_getStatistics(): string = return ""
-
-proc getOccupiedMem(): int = return -1
-proc getFreeMem(): int = return -1
-proc getTotalMem(): int = return -1
-
 proc alert(s: cstring) {.importc, nodecl.}
 
 type
@@ -130,8 +116,6 @@ proc raiseIndexError() {.compilerproc, noreturn.} =
 proc raiseFieldError(f: string) {.compilerproc, noreturn.} =
   raise newException(EInvalidField, f & " is not accessible")
 
-
-
 proc SetConstr() {.varargs, pure, compilerproc.} =
   asm """
     var result = {};
@@ -317,61 +301,58 @@ proc ewriteln(x: cstring) =
   else: 
     raise newException(EInvalidValue, "<body> element does not exist yet!")
 
-proc echo*(x: int) = ewriteln($x)
-proc echo*(x: float) = ewriteln($x)
-proc echo*(x: bool) = ewriteln(if x: cstring("true") else: cstring("false"))
-proc echo*(x: string) = ewriteln(x)
-proc echo*(x: cstring) = ewriteln(x)
-
-proc echo[Ty](x: Ty) =
-  echo(x)
-
-proc echo[Ty](x: openArray[Ty]) =
-  for a in items(x): echo(a)
+proc rawEcho {.compilerproc.} =
+  var node = document.getElementsByTagName("body")[0]
+  if node == nil: raise newException(EIO, "<body> element does not exist yet!")
+  asm """
+    for (var i = 0; i < arguments.length; ++i) {
+      var x = `toEcmaStr`(arguments[i]);
+      `node`.appendChild(document.createTextNode(x))
+    }
+  """
+  node.appendChild(document.createElement("br"))
 
 # Arithmetic:
 proc addInt(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` + `b`;
-    if (result > 2147483647 || result < -2147483648) raiseOverflow();
+    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
     return result;
   """
 
 proc subInt(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` - `b`;
-    if (result > 2147483647 || result < -2147483648) raiseOverflow();
+    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
     return result;
   """
 
 proc mulInt(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` * `b`;
-    if (result > 2147483647 || result < -2147483648) raiseOverflow();
+    if (result > 2147483647 || result < -2147483648) `raiseOverflow`();
     return result;
   """
 
 proc divInt(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 2147483647) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
     return Math.floor(`a` / `b`);
   """
 
 proc modInt(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 2147483647) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
     return Math.floor(`a` % `b`);
   """
 
-
-
 proc addInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` + `b`;
     if (result > 9223372036854775807
-    || result < -9223372036854775808) raiseOverflow();
+    || result < -9223372036854775808) `raiseOverflow`();
     return result;
   """
 
@@ -379,7 +360,7 @@ proc subInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` - `b`;
     if (result > 9223372036854775807
-    || result < -9223372036854775808) raiseOverflow();
+    || result < -9223372036854775808) `raiseOverflow`();
     return result;
   """
 
@@ -387,21 +368,21 @@ proc mulInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
     var result = `a` * `b`;
     if (result > 9223372036854775807
-    || result < -9223372036854775808) raiseOverflow();
+    || result < -9223372036854775808) `raiseOverflow`();
     return result;
   """
 
 proc divInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
     return Math.floor(`a` / `b`);
   """
 
 proc modInt64(a, b: int): int {.pure, compilerproc.} =
   asm """
-    if (`b` == 0) raiseDivByZero();
-    if (`b` == -1 && `a` == 9223372036854775807) raiseOverflow();
+    if (`b` == 0) `raiseDivByZero`();
+    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
     return Math.floor(`a` % `b`);
   """
 
@@ -415,13 +396,13 @@ proc internalAssert(file: cstring, line: int) {.pure, compilerproc.} =
   asm """`e`.message = "[Assertion failure] file: "+`file`+", line: "+`line`"""
   raise e
 
-include hti
+include "system/hti"
 
 proc isFatPointer(ti: PNimType): bool =
   # This has to be consistent with the code generator!
-  return ti.base.kind notin {tyRecord, tyRecordConstr, tyObject,
+  return ti.base.kind notin {tyObject,
     tyArray, tyArrayConstr, tyPureObject, tyTuple,
-    tyEmptySet, tyOpenArray, tySet, tyVar, tyRef, tyPtr}
+    tyOpenArray, tySet, tyVar, tyRef, tyPtr}
 
 proc NimCopy(x: pointer, ti: PNimType): pointer {.compilerproc.}
 
@@ -452,7 +433,7 @@ proc NimCopy(x: pointer, ti: PNimType): pointer =
         `result`[0] = `x`[0];
         `result`[1] = `x`[1];
       """
-  of tyEmptySet, tySet:
+  of tySet:
     asm """
       `result` = {};
       for (var key in `x`) { `result`[key] = `x`[key]; }
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index c473c42f0..65e233476 100755
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -10,6 +10,10 @@
 # Exception handling code. This is difficult because it has
 # to work if there is no more memory (but it doesn't yet!).
 
+var
+  stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
+                            ## for CGI applications
+
 when not defined(windows) or not defined(guiapp):
   proc writeToStdErr(msg: CString) = write(stdout, msg)
 
@@ -32,7 +36,7 @@ type
   TSafePoint {.compilerproc, final.} = object
     prev: PSafePoint # points to next safe point ON THE STACK
     status: int
-    exc: ref E_Base  # XXX only needed for bootstrapping
+    exc: ref E_Base  # XXX only needed for bootstrapping; unused
     context: C_JmpBuf
 
 var
@@ -55,6 +59,58 @@ proc pushCurrentException(e: ref E_Base) {.compilerRtl, inl.} =
 proc popCurrentException {.compilerRtl, inl.} =
   currException = currException.parent
 
+# some platforms have native support for stack traces:
+const
+  nimrodStackTrace = compileOption("stacktrace")
+  nativeStackTrace = (defined(macosx) or defined(linux)) and 
+                     not nimrodStackTrace and false
+
+# `nativeStackTrace` does not work for me --> deactivated for now. Maybe for 
+# the next release version.
+
+when nativeStacktrace:
+  type
+    TDl_info {.importc: "Dl_info", header: "<dlfcn.h>", 
+               final, pure.} = object
+      dli_fname: CString
+      dli_fbase: pointer
+      dli_sname: CString
+      dli_saddr: pointer
+
+  proc backtrace(symbols: ptr pointer, size: int): int {.
+    importc: "backtrace", header: "<execinfo.h>".}
+  proc dladdr(addr1: pointer, info: ptr TDl_info): int {.
+    importc: "dladdr", header: "<dlfcn.h>".}
+
+  var
+    tempAddresses: array [0..127, pointer] # cannot be allocated on the stack!
+    tempDlInfo: TDl_info
+
+  proc auxWriteStackTraceWithBacktrace(s: var string) =
+    # This is allowed to be expensive since it only happens during crashes
+    # (but this way you don't need manual stack tracing)
+    var size = backtrace(cast[ptr pointer](addr(tempAddresses)), 
+                         len(tempAddresses))
+    var enabled = false
+    for i in 0..size-1:
+      var dlresult = dladdr(tempAddresses[i], addr(tempDlInfo))
+      if enabled:
+        if dlresult != 0:
+          var oldLen = s.len
+          add(s, tempDlInfo.dli_fname)
+          if tempDlInfo.dli_sname != nil:
+            for k in 1..max(1, 25-(s.len-oldLen)): add(s, ' ')
+            add(s, tempDlInfo.dli_sname)
+        else:
+          add(s, '?')
+        add(s, stackTraceNewLine)
+      else:
+        if dlresult != 0 and tempDlInfo.dli_sname != nil and
+            c_strcmp(tempDlInfo.dli_sname, "signalHandler") == 0'i32:
+          # Once we're past signalHandler, we're at what the user is
+          # interested in
+          enabled = true
+
 type
   PFrame = ptr TFrame
   TFrame {.importc, nodecl, final.} = object
@@ -74,9 +130,6 @@ var
 
   tempFrames: array [0..127, PFrame] # cannot be allocated on the stack!
   
-  stackTraceNewLine* = "\n" ## undocumented feature; it is replaced by ``<br>``
-                            ## for CGI applications
-
 proc auxWriteStackTrace(f: PFrame, s: var string) =
   const 
     firstCalls = 32
@@ -120,7 +173,7 @@ proc auxWriteStackTrace(f: PFrame, s: var string) =
     add(s, stackTraceNewLine)
 
 proc rawWriteStackTrace(s: var string) =
-  when compileOption("stacktrace") or compileOption("linetrace"):
+  when nimrodStackTrace:
     if framePtr == nil:
       add(s, "No stack traceback available")
       add(s, stackTraceNewLine)
@@ -128,6 +181,10 @@ proc rawWriteStackTrace(s: var string) =
       add(s, "Traceback (most recent call last)")
       add(s, stackTraceNewLine)
       auxWriteStackTrace(framePtr, s)
+  elif nativeStackTrace:
+    add(s, "Traceback from system (most recent call last)")
+    add(s, stackTraceNewLine)
+    auxWriteStackTraceWithBacktrace(s)
   else:
     add(s, "No stack traceback available")
     add(s, stackTraceNewLine)
@@ -197,11 +254,6 @@ proc WriteStackTrace() =
   rawWriteStackTrace(s)
   writeToStdErr(s)
 
-#proc stackTraceWrapper {.noconv.} =
-#  writeStackTrace()
-
-#addQuitProc(stackTraceWrapper)
-
 var
   dbgAborting: bool # whether the debugger wants to abort
 
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index 0c403b4bc..c0461d89d 100755
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -77,14 +77,16 @@ var
     # collection, not a lock for threads!
 
 proc lock(gch: var TGcHeap) {.inline.} = 
-  if isMultiThreaded: 
-    Lock(gch.zctLock)
-    lock(gch.cycleRootsLock)
+  when hasThreadSupport:
+    if isMultiThreaded: 
+      Lock(gch.zctLock)
+      lock(gch.cycleRootsLock)
 
 proc unlock(gch: var TGcHeap) {.inline.} = 
-  if isMultiThreaded: 
-    unlock(gch.zctLock)
-    unlock(gch.cycleRootsLock)
+  when hasThreadSupport:
+    if isMultiThreaded: 
+      unlock(gch.zctLock)
+      unlock(gch.cycleRootsLock)
 
 proc addZCT(s: var TCellSeq, c: PCell) {.noinline.} =
   if (c.refcount and rcZct) == 0:
@@ -202,15 +204,19 @@ proc prepareDealloc(cell: PCell) =
 
 proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = 
   # we MUST access gch as a global here, because this crosses DLL boundaries!
-  if isMultiThreaded: Lock(gch.cycleRootsLock)
+  when hasThreadSupport:
+    if isMultiThreaded: Lock(gch.cycleRootsLock)
   incl(gch.cycleRoots, c)
-  if isMultiThreaded: Unlock(gch.cycleRootsLock)
+  when hasThreadSupport:  
+    if isMultiThreaded: Unlock(gch.cycleRootsLock)
 
 proc rtlAddZCT(c: PCell) {.rtl, inl.} =
   # we MUST access gch as a global here, because this crosses DLL boundaries!
-  if isMultiThreaded: Lock(gch.zctLock)
+  when hasThreadSupport:
+    if isMultiThreaded: Lock(gch.zctLock)
   addZCT(gch.zct, c)
-  if isMultiThreaded: Unlock(gch.zctLock)
+  when hasThreadSupport:
+    if isMultiThreaded: Unlock(gch.zctLock)
 
 proc decRef(c: PCell) {.inline.} =
   when stressGC:
@@ -480,7 +486,7 @@ proc gcMark(p: pointer) {.inline.} =
       add(gch.decStack, cell)
 
 proc markThreadStacks(gch: var TGcHeap) = 
-  when isMultiThreaded:
+  when hasThreadSupport:
     nil
 
 # ----------------- stack management --------------------------------------
diff --git a/lib/system/systhread.nim b/lib/system/systhread.nim
index 583cd2a43..af001985e 100755
--- a/lib/system/systhread.nim
+++ b/lib/system/systhread.nim
@@ -7,12 +7,17 @@
 #    distribution, for details about the copyright.
 #
 
-when defined(gcc) or defined(llvm_gcc):
+const
+  hasThreadSupport = false # deactivate for now: thread stack walking
+                           # is missing!
+  maxThreads = 256
+
+when (defined(gcc) or defined(llvm_gcc)) and hasThreadSupport:
   proc sync_add_and_fetch(p: var int, val: int): int {.
     importc: "__sync_add_and_fetch", nodecl.}
   proc sync_sub_and_fetch(p: var int, val: int): int {.
     importc: "__sync_sub_and_fetch", nodecl.}
-elif defined(vcc):
+elif defined(vcc) and hasThreadSupport:
   proc sync_add_and_fetch(p: var int, val: int): int {.
     importc: "NimXadd", nodecl.}
 else:
@@ -20,19 +25,18 @@ else:
     inc(p, val)
     result = p
 
-const
-  isMultiThreaded* = true
-  maxThreads = 256
+var
+  isMultiThreaded: bool # true when prog created at least 1 thread
 
 proc atomicInc(memLoc: var int, x: int): int =
-  when isMultiThreaded:
+  when hasThreadSupport:
     result = sync_add_and_fetch(memLoc, x)
   else:
     inc(memLoc, x)
     result = memLoc
   
 proc atomicDec(memLoc: var int, x: int): int =
-  when isMultiThreaded:
+  when hasThreadSupport:
     when defined(sync_sub_and_fetch):
       result = sync_sub_and_fetch(memLoc, x)
     else:
@@ -85,11 +89,8 @@ type
   TThreadFunc* = proc (closure: pointer) {.cdecl.}
   
 proc createThread*(t: var TThread, fn: TThreadFunc) = 
-  
   nil
   
 proc destroyThread*(t: var TThread) =
   nil
 
-
-
diff --git a/rod/ecmasgen.nim b/rod/ecmasgen.nim
index 91acb98b2..c57ee3879 100755
--- a/rod/ecmasgen.nim
+++ b/rod/ecmasgen.nim
@@ -12,9 +12,9 @@
 # code!**
 
 import 
-  ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp, options, 
-  nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os, times, ropes, 
-  math, passes, ccgutils, wordrecg, rnimsyn, rodread
+  ast, astalgo, strutils, nhashes, trees, platform, magicsys, extccomp,
+  options, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, os,
+  times, ropes, math, passes, ccgutils, wordrecg, rnimsyn, rodread
 
 proc ecmasgenPass*(): TPass
 # implementation
@@ -39,7 +39,8 @@ type
     kind*: TEcmasTypeKind
     com*: PRope               # computation part
                               # address if this is a (address, index)-tuple
-    res*: PRope               # result part; index if this is a (address, index)-tuple
+    res*: PRope               # result part; index if this is an
+                              # (address, index)-tuple
   
   TBlock{.final.} = object 
     id*: int                  # the ID of the label; positive means that it
@@ -886,12 +887,11 @@ proc genDeref(p: var TProc, n: PNode, r: var TCompRes) =
     if a.kind != etyBaseIndex: InternalError(n.info, "genDeref")
     r.res = ropef("$1[$2]", [a.com, a.res])
 
-proc genCall(p: var TProc, n: PNode, r: var TCompRes) = 
-  var a: TCompRes
-  gen(p, n.sons[0], r)
+proc genArgs(p: var TProc, n: PNode, r: var TCompRes) =
   app(r.res, "(")
   for i in countup(1, sonsLen(n) - 1): 
     if i > 1: app(r.res, ", ")
+    var a: TCompRes
     gen(p, n.sons[i], a)
     if a.kind == etyBaseIndex: 
       app(r.res, a.com)
@@ -901,6 +901,14 @@ proc genCall(p: var TProc, n: PNode, r: var TCompRes) =
       app(r.res, mergeExpr(a))
   app(r.res, ")")
 
+proc genCall(p: var TProc, n: PNode, r: var TCompRes) = 
+  gen(p, n.sons[0], r)
+  genArgs(p, n, r)
+
+proc genEcho(p: var TProc, n: PNode, r: var TCompRes) =
+  app(r.res, "rawEcho")
+  genArgs(p, n, r)
+
 proc putToSeq(s: string, indirect: bool): PRope = 
   result = toRope(s)
   if indirect: result = ropef("[$1]", [result])
@@ -1124,6 +1132,8 @@ proc genMagic(p: var TProc, n: PNode, r: var TCompRes) =
   of mInSet: binaryExpr(p, n, r, "", "($1[$2] != undefined)")
   of mNLen..mNError: 
     liMessage(n.info, errCannotGenerateCodeForX, n.sons[0].sym.name.s)
+  of mNewSeq: binaryStmt(p, n, r, "", "$1 = new Array($2)")
+  of mEcho: genEcho(p, n, r)
   else: 
     genCall(p, n, r)          
     #else internalError(e.info, 'genMagic: ' + magicToStr[op]);
@@ -1389,7 +1399,7 @@ proc newModule(module: PSym, filename: string): BModule =
   
 proc genHeader(): PRope = 
   result = ropef("/* Generated by the Nimrod Compiler v$1 */$n" &
-      "/*   (c) 2008 Andreas Rumpf */$n$n" & "$nvar Globals = this;$n" &
+      "/*   (c) 2010 Andreas Rumpf */$n$n" & "$nvar Globals = this;$n" &
       "var framePtr = null;$n" & "var excHandler = null;$n", 
                  [toRope(versionAsString)])
 
diff --git a/rod/main.nim b/rod/main.nim
index 2a261bfe5..46f01ddf5 100755
--- a/rod/main.nim
+++ b/rod/main.nim
@@ -203,7 +203,7 @@ proc MainCommand(cmd, filename: string) =
     gCmd = cmdCompileToCpp
     wantFile(filename)
     CommandCompileToC(filename)
-  of wCompileToEcmaScript: 
+  of wCompileToEcmaScript, wJs: 
     gCmd = cmdCompileToEcmaScript
     wantFile(filename)
     CommandCompileToEcmaScript(filename)
diff --git a/rod/wordrecg.nim b/rod/wordrecg.nim
index bf2aa84f7..c64985846 100755
--- a/rod/wordrecg.nim
+++ b/rod/wordrecg.nim
@@ -55,7 +55,7 @@ type
     wCc, wGenscript, wCheckPoint, wCheckPoints, wNoMain, wSubsChar, 
     wAcyclic, wIndex, 
     wCompileToC, wCompileToCpp, wCompileToEcmaScript, wCompileToLLVM, wPretty, 
-    wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wLazy, 
+    wDoc, wGenDepend, wListDef, wCheck, wParse, wScan, wJs, 
     wRst2html, wRst2tex, wI,
     wWrite, wPutEnv, wPrependEnv, wAppendEnv, wThreadVar
     
@@ -103,7 +103,7 @@ const
     "nomain", "subschar", "acyclic", "index", 
     "compiletoc", "compiletocpp", "compiletoecmascript", "compiletollvm", 
     "pretty", "doc", "gendepend", "listdef", "check", "parse", "scan", 
-    "lazy", "rst2html", "rst2tex", "i", 
+    "js", "rst2html", "rst2tex", "i", 
     "write", "putenv", "prependenv", "appendenv", "threadvar"]
 
 proc whichKeyword*(id: PIdent): TSpecialWord
diff --git a/tests/ecmas.html b/tests/ecmas.html
index 1cb56e72a..2004387a1 100755
--- a/tests/ecmas.html
+++ b/tests/ecmas.html
@@ -2,18 +2,18 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<!--  This has been written by hand. (c) 2008 Andreas Rumpf -->
+<!--  This has been written by hand. (c) 2010 Andreas Rumpf -->
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <title>Nimrod ECMAScript Generator Test</title>
 <style type="text/css">
 span.DecNumber {color: blue}
 </style>
-<script src="nimrcache/ecmas.js" type="text/javascript"></script>
+<script src="nimcache/ecmas.js" type="text/javascript"></script>
 </head>
 <body onload="OnLoad()">
 <form name="form1" action="ecmas.html">
-  <input type="text" name="input" size="3" />
+  <input type="text" name="input1" size="10" />
   <input type="button" value="Calculate square" onclick="OnButtonClick()" />
 </form>
 
diff --git a/tests/ecmas.nim b/tests/ecmas.nim
index 59e7ae1e8..c25d063c1 100755
--- a/tests/ecmas.nim
+++ b/tests/ecmas.nim
@@ -6,11 +6,14 @@ import
 # We need to declare the used elements here. This is annoying but
 # prevents any kind of typo:
 var
-  inputElement {.importc: "document.form1.input", nodecl.}: ref TElement
+  inputElement {.importc: "document.form1.input1", nodecl.}: ref TElement
 
 proc OnButtonClick() {.exportc.} =
-  var x: int = parseInt($inputElement.value)
-  echo($(x * x))
+  #var x = parseInt($inputElement.value)
+  #echo($(x * x))
+  var input = $inputElement.value
+  echo "Test"
+  echo "Hi, ", input
 
 proc OnLoad() {.exportc.} = 
-  echo("Welcome! Please take your time to fill in this formular!")
+  echo "Welcome! Please take your time to fill in this formular!"
diff --git a/tinyc/libtcc.c b/tinyc/libtcc.c
index ade77c0dc..0d8702b5f 100755
--- a/tinyc/libtcc.c
+++ b/tinyc/libtcc.c
@@ -808,11 +808,11 @@ void error1(TCCState *s1, int is_warning, const char *fmt, va_list ap)
     if (!s1->error_func) {
         /* default case: stderr */
         fprintf(stderr, "%s\n", buf);
-    } else {
+    } 
+    if (!is_warning || s1->warn_error) {
         s1->error_func(s1->error_opaque, buf);
-    }
-    if (!is_warning || s1->warn_error)
         s1->nb_errors++;
+    }
 }
 
 void tcc_set_error_func(TCCState *s, void *error_opaque,
diff --git a/todo.txt b/todo.txt
index 14f1c1f02..bd02a31ee 100755
--- a/todo.txt
+++ b/todo.txt
@@ -3,6 +3,8 @@ For version 0.8.10
 
 - fix implicit generic routines
 - bugfix: ccgexprs
+- bugfix: make ``finally`` more robust
+- bugfix: tiny C broken again!
 
 
 High priority (version 0.9.0)
diff --git a/tools/nimrepl.nim b/tools/nimrepl.nim
index 247bf0d10..989689add 100755
--- a/tools/nimrepl.nim
+++ b/tools/nimrepl.nim
@@ -7,17 +7,38 @@
 #    distribution, for details about the copyright.
 #
 
-import glib2, gtk2, gdk2, osproc, dialogs, strutils
+import glib2, gtk2, gdk2, os, osproc, dialogs, strutils
+
+when defined(tinyc):
+  const runCmd = "run"
+else:
+  const runCmd = "c -r"
+
+when not defined(findExe): 
+  # candidate for the stdlib:
+  proc findExe(exe: string): string = 
+    ## returns exe if the exe cannot be found
+    result = addFileExt(exe, os.exeExt)
+    if ExistsFile(result): return
+    var path = os.getEnv("PATH")
+    for candidate in split(path, pathSep): 
+      var x = candidate / result
+      if ExistsFile(x): return x
+    result = ""
+
+var nimExe = findExe("nimrod")
+if nimExe.len == 0: nimExe = "../bin" / addFileExt("nimrod", os.exeExt)
 
 proc execCode(code: string): string =
   var f: TFile
   if open(f, "temp.nim", fmWrite):
     f.write(code)
     f.close()
+    result = osproc.execProcess(
+      "$# $# --verbosity:0 --hint[Conf]:off temp.nim" % [nimExe, runCmd],
+      {poStdErrToStdOut})
   else:
-    raise newException(EIO, "Unable to open file")    
-  result = osproc.execProcess(
-      "nimrod c -r --verbosity:0 --hint[Conf]:off temp.nim")
+    result = "cannot open file 'temp.nim'"
 
 var shiftPressed = False
 var w: gtk2.PWindow
@@ -29,33 +50,29 @@ proc destroy(widget: PWidget, data: pgpointer){.cdecl.} =
 
 proc FileOpenClicked(menuitem: PMenuItem, userdata: pgpointer) {.cdecl.} =
   var path = ChooseFileToOpen(w)
-  
   if path != "":
-
     var file: string = readFile(path)
     if file != nil:
       set_text(InputTextBuffer, file, len(file))
-      
     else:
       error(w, "Unable to read from file")
 
 proc FileSaveClicked(menuitem: PMenuItem, userdata: pgpointer) {.cdecl.} =
   var path = ChooseFileToSave(w)
   
-  if path != "":
-    var startIter: TTextIter
-    var endIter: TTextIter
-    get_start_iter(InputTextBuffer, addr(startIter))
-    get_end_iter(InputTextBuffer, addr(endIter))
-    var InputText = get_text(InputTextBuffer, addr(startIter), 
-                             addr(endIter), False)
-    var f: TFile
-    if open(f, path, fmWrite):
-      f.write(InputText)
-      f.close()
-    else:
-      error(w, "Unable to write to file")
-
+  if path == "": return
+  var startIter: TTextIter
+  var endIter: TTextIter
+  get_start_iter(InputTextBuffer, addr(startIter))
+  get_end_iter(InputTextBuffer, addr(endIter))
+  var InputText = get_text(InputTextBuffer, addr(startIter), 
+                           addr(endIter), False)
+  var f: TFile
+  if open(f, path, fmWrite):
+    f.write(InputText)
+    f.close()
+  else:
+    error(w, "Unable to write to file")
 
 proc inputKeyPressed(widget: PWidget, event: PEventKey, 
                      userdata: pgpointer): bool =
@@ -68,13 +85,13 @@ proc setError(msg: string) =
   
 proc inputKeyReleased(widget: PWidget, event: PEventKey, 
                       userdata: pgpointer): bool =
-  echo(keyval_name(event.keyval))
+  #echo(keyval_name(event.keyval))
   if ($keyval_name(event.keyval)).tolower() == "shift_l":
     # SHIFT is released
     shiftPressed = False
     
   if ($keyval_name(event.keyval)).tolower() == "return":
-    echo($keyval_name(event.keyval), "Shift_L")
+    #echo($keyval_name(event.keyval), "Shift_L")
     # Enter pressed
     if shiftPressed == False:
       var startIter: TTextIter