summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2019-09-02 10:27:35 +0200
committerAraq <rumpf_a@web.de>2019-09-02 10:27:35 +0200
commite76568764698be7561501c4809e996f3f1608f74 (patch)
tree04700154851f27af457836751a8425882b50e97d /lib
parente6ec88d4c39c458404061198b2a2f6b86c2caeaf (diff)
parentad82e65387f39970b0f12cbcb12d8b382236f3da (diff)
downloadNim-e76568764698be7561501c4809e996f3f1608f74.tar.gz
Merge branch 'devel' into uint-range-checks
Diffstat (limited to 'lib')
-rw-r--r--lib/core/locks.nim4
-rw-r--r--lib/core/seqs.nim2
-rw-r--r--lib/core/strs.nim49
-rw-r--r--lib/impure/rdstdin.nim40
-rw-r--r--lib/nimbase.h12
-rw-r--r--lib/nimhcr.nim3
-rw-r--r--lib/pure/complex.nim2
-rw-r--r--lib/pure/hashes.nim196
-rw-r--r--lib/pure/httpclient.nim132
-rw-r--r--lib/pure/json.nim17
-rw-r--r--lib/pure/lexbase.nim7
-rw-r--r--lib/pure/net.nim6
-rw-r--r--lib/pure/unicode.nim7
-rw-r--r--lib/system.nim92
-rw-r--r--lib/system/alloc.nim12
-rw-r--r--lib/system/ansi_c.nim2
-rw-r--r--lib/system/assertions.nim10
-rw-r--r--lib/system/debugger.nim303
-rw-r--r--lib/system/endb.nim579
-rw-r--r--lib/system/excpt.nim12
-rw-r--r--lib/system/gc_ms.nim2
-rw-r--r--lib/system/iterators.nim9
22 files changed, 250 insertions, 1248 deletions
diff --git a/lib/core/locks.nim b/lib/core/locks.nim
index d6d579ba0..0143957ce 100644
--- a/lib/core/locks.nim
+++ b/lib/core/locks.nim
@@ -60,11 +60,11 @@ template withLock*(a: Lock, body: untyped) =
   ## Acquires the given lock, executes the statements in body and
   ## releases the lock after the statements finish executing.
   mixin acquire, release
-  a.acquire()
+  acquire(a)
   {.locks: [a].}:
     try:
       body
     finally:
-      a.release()
+      release(a)
 
 {.pop.}
diff --git a/lib/core/seqs.nim b/lib/core/seqs.nim
index 2892e4d8a..01839a4de 100644
--- a/lib/core/seqs.nim
+++ b/lib/core/seqs.nim
@@ -202,7 +202,7 @@ when false:
     assert i < x.len
     x.data[i] = y
 
-  proc `@`*[T](elems: openArray[T]): NimSeqV2[T] =
+  proc `@`*[T](elems: sink openArray[T]): NimSeqV2[T] =
     result.cap = elems.len
     result.len = elems.len
     result.data = cast[type(result.data)](alloc(result.cap * sizeof(T)))
diff --git a/lib/core/strs.nim b/lib/core/strs.nim
index 92c39331f..3b7a46ff1 100644
--- a/lib/core/strs.nim
+++ b/lib/core/strs.nim
@@ -9,20 +9,6 @@
 
 ## Default new string implementation used by Nim's core.
 
-when false:
-  # these are to be implemented or changed in the code generator.
-
-  #proc rawNewStringNoInit(space: int): NimString {.compilerproc.}
-  # seems to be unused.
-  proc copyDeepString(src: NimString): NimString {.inline.}
-  # ----------------- sequences ----------------------------------------------
-
-  proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerproc.}
-  proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
-      compilerRtl.}
-  proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.}
-  proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.}
-
 import allocators
 
 type
@@ -45,41 +31,6 @@ template frees(s) =
   if not isLiteral(s):
     s.p.allocator.dealloc(s.p.allocator, s.p, contentSize(s.p.cap))
 
-when not defined(nimV2):
-  proc `=destroy`(s: var string) =
-    var a = cast[ptr NimStringV2](addr s)
-    frees(a)
-    a.len = 0
-    a.p = nil
-
-  proc `=sink`(x: var string, y: string) =
-    var a = cast[ptr NimStringV2](addr x)
-    var b = cast[ptr NimStringV2](unsafeAddr y)
-    # we hope this is optimized away for not yet alive objects:
-    if unlikely(a.p == b.p): return
-    frees(a)
-    a.len = b.len
-    a.p = b.p
-
-  proc `=`(x: var string, y: string) =
-    var a = cast[ptr NimStringV2](addr x)
-    var b = cast[ptr NimStringV2](unsafeAddr y)
-    if unlikely(a.p == b.p): return
-    frees(a)
-    a.len = b.len
-    if isLiteral(b):
-      # we can shallow copy literals:
-      a.p = b.p
-    else:
-      let allocator = if a.p != nil and a.p.allocator != nil: a.p.allocator else: getLocalAllocator()
-      # we have to allocate the 'cap' here, consider
-      # 'let y = newStringOfCap(); var x = y'
-      # on the other hand... These get turned into moves now.
-      a.p = cast[ptr NimStrPayload](allocator.alloc(allocator, contentSize(b.len)))
-      a.p.allocator = allocator
-      a.p.cap = b.len
-      copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
-
 proc resize(old: int): int {.inline.} =
   if old <= 0: result = 4
   elif old < 65536: result = old * 2
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index 742db0cc6..b78c0d8cf 100644
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -33,46 +33,6 @@ when defined(Windows):
     stdout.write(prompt)
     result = readLine(stdin, line)
 
-  import winlean
-
-  const
-    VK_SHIFT* = 16
-    VK_CONTROL* = 17
-    VK_MENU* = 18
-    KEY_EVENT* = 1
-
-  type
-    KEY_EVENT_RECORD = object
-      bKeyDown: WINBOOL
-      wRepeatCount: uint16
-      wVirtualKeyCode: uint16
-      wVirtualScanCode: uint16
-      unicodeChar: uint16
-      dwControlKeyState: uint32
-    INPUT_RECORD = object
-      eventType*: int16
-      reserved*: int16
-      event*: KEY_EVENT_RECORD
-      safetyBuffer: array[0..5, DWORD]
-
-  proc readConsoleInputW*(hConsoleInput: Handle, lpBuffer: var INPUT_RECORD,
-                          nLength: uint32,
-                          lpNumberOfEventsRead: var uint32): WINBOOL{.
-      stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
-
-  proc getch(): uint16 =
-    let hStdin = getStdHandle(STD_INPUT_HANDLE)
-    var
-      irInputRecord: INPUT_RECORD
-      dwEventsRead: uint32
-
-    while readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead) != 0:
-      if irInputRecord.eventType == KEY_EVENT and
-          irInputRecord.event.wVirtualKeyCode notin {VK_SHIFT, VK_MENU, VK_CONTROL}:
-         result = irInputRecord.event.unicodeChar
-         discard readConsoleInputW(hStdin, irInputRecord, 1, dwEventsRead)
-         return result
-
 elif defined(genode):
   proc readLineFromStdin*(prompt: string): TaintedString {.
                           tags: [ReadIOEffect, WriteIOEffect].} =
diff --git a/lib/nimbase.h b/lib/nimbase.h
index a4bde0bd4..eadc34f66 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -374,18 +374,6 @@ typedef char* NCSTRING;
 #  define NIM_IMAN 0
 #endif
 
-static N_INLINE(NI, float64ToInt32)(double x) {
-  /* nowadays no hack necessary anymore */
-  return x >= 0 ? (NI)(x+0.5) : (NI)(x-0.5);
-}
-
-static N_INLINE(NI32, float32ToInt32)(float x) {
-  /* nowadays no hack necessary anymore */
-  return x >= 0 ? (NI32)(x+0.5) : (NI32)(x-0.5);
-}
-
-#define float64ToInt64(x) ((NI64) (x))
-
 #define NIM_STRLIT_FLAG ((NU)(1) << ((NIM_INTBITS) - 2)) /* This has to be the same as system.strlitFlag! */
 
 #define STRING_LITERAL(name, str, length) \
diff --git a/lib/nimhcr.nim b/lib/nimhcr.nim
index 79f3fd350..396747527 100644
--- a/lib/nimhcr.nim
+++ b/lib/nimhcr.nim
@@ -111,6 +111,7 @@
 # - ARM support for the trampolines
 # - investigate:
 #   - soon the system module might be importing other modules - the init order...?
+#     (revert https://github.com/nim-lang/Nim/pull/11971 when working on this)
 #   - rethink the closure iterators
 #     - ability to keep old versions of dynamic libraries alive
 #       - because of async server code
@@ -421,7 +422,7 @@ when defined(createNimHcr):
       modules.add(name, newModuleDesc())
 
     let copiedName = name & ".copy." & dllExt
-    copyFile(name, copiedName)
+    copyFileWithPermissions(name, copiedName)
 
     let lib = loadLib(copiedName)
     assert lib != nil
diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim
index 442bf62db..7c669cd6d 100644
--- a/lib/pure/complex.nim
+++ b/lib/pure/complex.nim
@@ -372,7 +372,7 @@ when isMainModule:
   doAssert((a+b) == z)
   doAssert((a+b) =~ 0.0)
   doAssert((a/b) == m1)
-  doAssert((1.0/a) == complex(0.2, -0.4))
+  doAssert((1.0/a) =~ complex(0.2, -0.4))
   doAssert((a*b) == complex(3.0, -4.0))
   doAssert(10.0*a == tt)
   doAssert(a*10.0 == tt)
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 6af515609..c1338376e 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -49,9 +49,6 @@ type
                ## always have a size of a power of two and can use the ``and``
                ## operator instead of ``mod`` for truncation of the hash value.
 
-const
-  IntSize = sizeof(int)
-
 proc `!&`*(h: Hash, val: int): Hash {.inline.} =
   ## Mixes a hash value `h` with `val` to produce a new hash value.
   ##
@@ -108,13 +105,12 @@ proc hash*(x: pointer): Hash {.inline.} =
   else:
     result = cast[Hash](cast[uint](x) shr 3) # skip the alignment
 
-when not defined(booting):
-  proc hash*[T: proc](x: T): Hash {.inline.} =
-    ## Efficient hashing of proc vars. Closures are supported too.
-    when T is "closure":
-      result = hash(rawProc(x)) !& hash(rawEnv(x))
-    else:
-      result = hash(pointer(x))
+proc hash*[T: proc](x: T): Hash {.inline.} =
+  ## Efficient hashing of proc vars. Closures are supported too.
+  when T is "closure":
+    result = hash(rawProc(x)) !& hash(rawEnv(x))
+  else:
+    result = hash(pointer(x))
 
 proc hash*(x: int): Hash {.inline.} =
   ## Efficient hashing of integers.
@@ -151,27 +147,87 @@ proc hash*(x: float): Hash {.inline.} =
 proc hash*[A](x: openArray[A]): Hash
 proc hash*[A](x: set[A]): Hash
 
-template bytewiseHashing(result: Hash, x: typed, start, stop: int) =
-  for i in start .. stop:
-    result = result !& hash(x[i])
-  result = !$result
 
-template hashImpl(result: Hash, x: typed, start, stop: int) =
+when defined(JS):
+  proc imul(a, b: uint32): uint32 =
+    # https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
+    let mask = 0xffff'u32
+    var
+      aHi = (a shr 16) and mask
+      aLo = a and mask
+      bHi = (b shr 16) and mask
+      bLo = b and mask
+    result = (aLo * bLo) + (aHi * bLo + aLo * bHi) shl 16
+else:
+  template imul(a, b: uint32): untyped = a * b
+
+proc rotl32(x: uint32, r: int): uint32 {.inline.} =
+  (x shl r) or (x shr (32 - r))
+
+proc murmurHash(x: openArray[byte]): Hash =
+  # https://github.com/PeterScott/murmur3/blob/master/murmur3.c
+  const
+    c1 = 0xcc9e2d51'u32
+    c2 = 0x1b873593'u32
+    n1 = 0xe6546b64'u32
+    m1 = 0x85ebca6b'u32
+    m2 = 0xc2b2ae35'u32
   let
-    elementSize = sizeof(x[start])
-    stepSize = IntSize div elementSize
-  var i = start
-  while i <= stop+1 - stepSize:
-    var n = 0
-    when nimvm:
-      # we cannot cast in VM, so we do it manually
-      for j in countdown(stepSize-1, 0):
-        n = (n shl (8*elementSize)) or ord(x[i+j])
+    size = len(x)
+    stepSize = 4 # 32-bit
+    n = size div stepSize
+  var
+    h1: uint32
+    i = 0
+
+  # body
+  while i < n * stepSize:
+    var k1: uint32
+    when defined(js):
+      var j = stepSize
+      while j > 0:
+        dec j
+        k1 = (k1 shl 8) or (ord(x[i+j])).uint32
     else:
-      n = cast[ptr Hash](unsafeAddr x[i])[]
-    result = result !& n
-    i += stepSize
-  bytewiseHashing(result, x, i, stop) # hash the remaining elements and finish
+      k1 = cast[ptr uint32](unsafeAddr x[i])[]
+    inc i, stepSize
+
+    k1 = imul(k1, c1)
+    k1 = rotl32(k1, 15)
+    k1 = imul(k1, c2)
+
+    h1 = h1 xor k1
+    h1 = rotl32(h1, 13)
+    h1 = h1*5 + n1
+
+  # tail
+  var k1: uint32
+  var rem = size mod stepSize
+  while rem > 0:
+    dec rem
+    k1 = (k1 shl 8) or (ord(x[i+rem])).uint32
+  k1 = imul(k1, c1)
+  k1 = rotl32(k1, 15)
+  k1 = imul(k1, c2)
+  h1 = h1 xor k1
+
+  # finalization
+  h1 = h1 xor size.uint32
+  h1 = h1 xor (h1 shr 16)
+  h1 = imul(h1, m1)
+  h1 = h1 xor (h1 shr 13)
+  h1 = imul(h1, m2)
+  h1 = h1 xor (h1 shr 16)
+  return cast[Hash](h1)
+
+proc hashVmImpl(x: string, sPos, ePos: int): Hash =
+  doAssert false, "implementation override in compiler/vmops.nim"
+
+proc hashVmImplChar(x: openArray[char], sPos, ePos: int): Hash =
+  doAssert false, "implementation override in compiler/vmops.nim"
+
+proc hashVmImplByte(x: openArray[byte], sPos, ePos: int): Hash =
+  doAssert false, "implementation override in compiler/vmops.nim"
 
 proc hash*(x: string): Hash =
   ## Efficient hashing of strings.
@@ -182,7 +238,16 @@ proc hash*(x: string): Hash =
   runnableExamples:
     doAssert hash("abracadabra") != hash("AbracadabrA")
 
-  hashImpl(result, x, 0, high(x))
+  when not defined(nimToOpenArrayCString):
+    result = 0
+    for c in x:
+      result = result !& ord(c)
+    result = !$result
+  else:
+    when nimvm:
+      result = hashVmImpl(x, 0, high(x))
+    else:
+      result = murmurHash(toOpenArrayByte(x, 0, high(x)))
 
 proc hash*(x: cstring): Hash =
   ## Efficient hashing of null-terminated strings.
@@ -191,7 +256,19 @@ proc hash*(x: cstring): Hash =
     doAssert hash(cstring"AbracadabrA") == hash("AbracadabrA")
     doAssert hash(cstring"abracadabra") != hash(cstring"AbracadabrA")
 
-  hashImpl(result, x, 0, high(x))
+  when not defined(nimToOpenArrayCString):
+    result = 0
+    var i = 0
+    while x[i] != '\0':
+      result = result !& ord(x[i])
+      inc i
+    result = !$result
+  else:
+    when not defined(JS) and defined(nimToOpenArrayCString):
+      murmurHash(toOpenArrayByte(x, 0, x.high))
+    else:
+      let xx = $x
+      murmurHash(toOpenArrayByte(xx, 0, high(xx)))
 
 proc hash*(sBuf: string, sPos, ePos: int): Hash =
   ## Efficient hashing of a string buffer, from starting
@@ -202,7 +279,13 @@ proc hash*(sBuf: string, sPos, ePos: int): Hash =
     var a = "abracadabra"
     doAssert hash(a, 0, 3) == hash(a, 7, 10)
 
-  hashImpl(result, sBuf, sPos, ePos)
+  when not defined(nimToOpenArrayCString):
+    result = 0
+    for i in sPos..ePos:
+      result = result !& ord(sBuf[i])
+    result = !$result
+  else:
+    murmurHash(toOpenArrayByte(sBuf, sPos, ePos))
 
 proc hashIgnoreStyle*(x: string): Hash =
   ## Efficient hashing of strings; style is ignored.
@@ -300,12 +383,20 @@ proc hash*[T: tuple](x: T): Hash =
     result = result !& hash(f)
   result = !$result
 
+
 proc hash*[A](x: openArray[A]): Hash =
   ## Efficient hashing of arrays and sequences.
-  when A is char|SomeInteger:
-    hashImpl(result, x, 0, x.high)
+  when A is byte:
+    result = murmurHash(x)
+  elif A is char:
+    when nimvm:
+      result = hashVmImplChar(x, 0, x.high)
+    else:
+      result = murmurHash(toOpenArrayByte(x, 0, x.high))
   else:
-    bytewiseHashing(result, x, 0, x.high)
+    for a in x:
+      result = result !& hash(a)
+    result = !$result
 
 proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash =
   ## Efficient hashing of portions of arrays and sequences, from starting
@@ -316,10 +407,20 @@ proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash =
     let a = [1, 2, 5, 1, 2, 6]
     doAssert hash(a, 0, 1) == hash(a, 3, 4)
 
-  when A is char|SomeInteger:
-    hashImpl(result, aBuf, sPos, ePos)
+  when A is byte:
+    when nimvm:
+      result = hashVmImplByte(aBuf, sPos, ePos)
+    else:
+      result = murmurHash(toOpenArray(aBuf, sPos, ePos))
+  elif A is char:
+    when nimvm:
+      result = hashVmImplChar(aBuf, sPos, ePos)
+    else:
+      result = murmurHash(toOpenArrayByte(aBuf, sPos, ePos))
   else:
-    bytewiseHashing(result, aBuf, sPos, ePos)
+    for i in sPos .. ePos:
+      result = result !& hash(aBuf[i])
+    result = !$result
 
 proc hash*[A](x: set[A]): Hash =
   ## Efficient hashing of sets.
@@ -334,11 +435,15 @@ when isMainModule:
       a = ""
       b = newSeq[char]()
       c = newSeq[int]()
+      d = cstring""
+      e = "abcd"
     doAssert hash(a) == 0
     doAssert hash(b) == 0
     doAssert hash(c) == 0
+    doAssert hash(d) == 0
     doAssert hashIgnoreCase(a) == 0
     doAssert hashIgnoreStyle(a) == 0
+    doAssert hash(e, 3, 2) == 0
   block sameButDifferent:
     doAssert hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13)
     doAssert hash("aa bb aaaa1234") == hash(cstring"aa bb aaaa1234")
@@ -346,14 +451,14 @@ when isMainModule:
     doAssert hashIgnoreStyle("aa_bb_AAaa1234") == hashIgnoreCase("aaBBAAAa1234")
   block smallSize: # no multibyte hashing
     let
-      xx = @['H','e','l','l','o']
-      ii = @[72'i8, 101, 108, 108, 111]
-      ss = "Hello"
+      xx = @['H','i']
+      ii = @[72'u8, 105]
+      ss = "Hi"
     doAssert hash(xx) == hash(ii)
     doAssert hash(xx) == hash(ss)
     doAssert hash(xx) == hash(xx, 0, xx.high)
     doAssert hash(ss) == hash(ss, 0, ss.high)
-  block largeSize: # longer than 8 characters, should trigger multibyte hashing
+  block largeSize: # longer than 4 characters
     let
       xx = @['H','e','l','l','o']
       xxl = @['H','e','l','l','o','w','e','e','n','s']
@@ -362,9 +467,6 @@ when isMainModule:
     doAssert hash(xxl) == hash(xxl, 0, xxl.high)
     doAssert hash(ssl) == hash(ssl, 0, ssl.high)
     doAssert hash(xx) == hash(xxl, 0, 4)
-  block misc:
-    let
-      a = [1'u8, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4]
-      b = [1'i8, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4]
-    doAssert hash(a) == hash(b)
-    doAssert hash(a, 2, 5) == hash(b, 2, 5)
+    doAssert hash(xx) == hash(ssl, 0, 4)
+    doAssert hash(xx, 0, 3) == hash(xxl, 0, 3)
+    doAssert hash(xx, 0, 3) == hash(ssl, 0, 3)
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index 5a98c5ede..f89a928ab 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -1,7 +1,7 @@
 #
 #
 #            Nim's Runtime Library
-#        (c) Copyright 2016 Dominik Picheta, Andreas Rumpf
+#        (c) Copyright 2019 Nim Contributors
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -175,7 +175,7 @@
 ##    let client = newHttpClient(maxRedirects = 0)
 ##
 
-import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes,
+import net, strutils, uri, parseutils, base64, os, mimetypes,
   math, random, httpcore, times, tables, streams, std/monotimes
 import asyncnet, asyncdispatch, asyncfile
 import nativesockets
@@ -276,134 +276,6 @@ proc fileError(msg: string) =
   e.msg = msg
   raise e
 
-proc parseChunks(s: Socket, timeout: int): string =
-  result = ""
-  var ri = 0
-  while true:
-    var chunkSizeStr = ""
-    var chunkSize = 0
-    s.readLine(chunkSizeStr, timeout)
-    var i = 0
-    if chunkSizeStr == "":
-      httpError("Server terminated connection prematurely")
-    while i < chunkSizeStr.len:
-      case chunkSizeStr[i]
-      of '0'..'9':
-        chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('0'))
-      of 'a'..'f':
-        chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('a') + 10)
-      of 'A'..'F':
-        chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
-      of ';':
-        # http://tools.ietf.org/html/rfc2616#section-3.6.1
-        # We don't care about chunk-extensions.
-        break
-      else:
-        httpError("Invalid chunk size: " & chunkSizeStr)
-      inc(i)
-    if chunkSize <= 0:
-      s.skip(2, timeout) # Skip \c\L
-      break
-    result.setLen(ri+chunkSize)
-    var bytesRead = 0
-    while bytesRead != chunkSize:
-      let ret = recv(s, addr(result[ri]), chunkSize-bytesRead, timeout)
-      ri += ret
-      bytesRead += ret
-    s.skip(2, timeout) # Skip \c\L
-    # Trailer headers will only be sent if the request specifies that we want
-    # them: http://tools.ietf.org/html/rfc2616#section-3.6.1
-
-proc parseBody(s: Socket, headers: HttpHeaders, httpVersion: string, timeout: int): string =
-  result = ""
-  if headers.getOrDefault"Transfer-Encoding" == "chunked":
-    result = parseChunks(s, timeout)
-  else:
-    # -REGION- Content-Length
-    # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.3
-    var contentLengthHeader = headers.getOrDefault"Content-Length"
-    if contentLengthHeader != "":
-      var length = contentLengthHeader.parseInt()
-      if length > 0:
-        result = newString(length)
-        var received = 0
-        while true:
-          if received >= length: break
-          let r = s.recv(addr(result[received]), length-received, timeout)
-          if r == 0: break
-          received += r
-        if received != length:
-          httpError("Got invalid content length. Expected: " & $length &
-                    " got: " & $received)
-    else:
-      # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.4 TODO
-
-      # -REGION- Connection: Close
-      # (http://tools.ietf.org/html/rfc2616#section-4.4) NR.5
-      let implicitConnectionClose =
-        httpVersion == "1.0" or
-        # This doesn't match the HTTP spec, but it fixes issues for non-conforming servers.
-        (httpVersion == "1.1" and headers.getOrDefault"Connection" == "")
-      if headers.getOrDefault"Connection" == "close" or implicitConnectionClose:
-        var buf = ""
-        while true:
-          buf = newString(4000)
-          let r = s.recv(addr(buf[0]), 4000, timeout)
-          if r == 0: break
-          buf.setLen(r)
-          result.add(buf)
-
-proc parseResponse(s: Socket, getBody: bool, timeout: int): Response =
-  new result
-  var parsedStatus = false
-  var linei = 0
-  var fullyRead = false
-  var line = ""
-  result.headers = newHttpHeaders()
-  while true:
-    line = ""
-    linei = 0
-    s.readLine(line, timeout)
-    if line == "": break # We've been disconnected.
-    if line == "\c\L":
-      fullyRead = true
-      break
-    if not parsedStatus:
-      # Parse HTTP version info and status code.
-      var le = skipIgnoreCase(line, "HTTP/", linei)
-      if le <= 0: httpError("invalid http version")
-      inc(linei, le)
-      le = skipIgnoreCase(line, "1.1", linei)
-      if le > 0: result.version = "1.1"
-      else:
-        le = skipIgnoreCase(line, "1.0", linei)
-        if le <= 0: httpError("unsupported http version")
-        result.version = "1.0"
-      inc(linei, le)
-      # Status code
-      linei.inc skipWhitespace(line, linei)
-      result.status = line[linei .. ^1]
-      parsedStatus = true
-    else:
-      # Parse headers
-      var name = ""
-      var le = parseUntil(line, name, ':', linei)
-      if le <= 0: httpError("invalid headers")
-      inc(linei, le)
-      if line[linei] != ':': httpError("invalid headers")
-      inc(linei) # Skip :
-
-      result.headers.add(name, line[linei.. ^1].strip())
-      # Ensure the server isn't trying to DoS us.
-      if result.headers.len > headerLimit:
-        httpError("too many headers")
-
-  if not fullyRead:
-    httpError("Connection was closed before full request has been made")
-  if getBody:
-    result.body = parseBody(s, result.headers, result.version, timeout)
-  else:
-    result.body = ""
 
 when not defined(ssl):
   type SSLContext = ref object
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index 1ef08f547..23b23b4a4 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -1369,11 +1369,20 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
           for `forLoopI` in 0 ..< `jsonNode`.len: list[`forLoopI`] =`constructorNode`;
           list
         )
-
+    of "tuple":
+      let typeNode = getTypeImpl(typeSym)
+      result = createConstructor(typeNode, jsonNode)
     else:
-      # Generic type.
+      # Generic type or some `seq[T]` alias
       let obj = getType(typeSym)
-      result = processType(typeSym, obj, jsonNode, false)
+      case obj.kind
+      of nnkBracketExpr:
+        # probably a `seq[T]` alias
+        let typeNode = getTypeImpl(typeSym)
+        result = createConstructor(typeNode, jsonNode)
+      else:
+        # generic type
+        result = processType(typeSym, obj, jsonNode, false)
   of nnkSym:
     # Handle JsonNode.
     if ($typeSym).cmpIgnoreStyle("jsonnode") == 0:
@@ -1385,7 +1394,7 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode =
     if typeNode.typeKind == ntyDistinct:
       result = createConstructor(typeNode, jsonNode)
     elif obj.kind == nnkBracketExpr:
-      # When `Sym "Foo"` turns out to be a `ref object`.
+      # When `Sym "Foo"` turns out to be a `ref object` or `tuple`
       result = createConstructor(obj, jsonNode)
     else:
       result = processType(typeSym, obj, jsonNode, false)
diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim
index 11ec45a37..0ef4a147a 100644
--- a/lib/pure/lexbase.nim
+++ b/lib/pure/lexbase.nim
@@ -100,7 +100,7 @@ proc fillBaseLexer(L: var BaseLexer, pos: int): int =
     result = 0
 
 proc handleCR*(L: var BaseLexer, pos: int): int =
-  ## Call this if you scanned over '\c' in the buffer; it returns the the
+  ## Call this if you scanned over '\c' in the buffer; it returns the
   ## position to continue the scanning from. `pos` must be the position
   ## of the '\c'.
   assert(L.buf[pos] == '\c')
@@ -111,7 +111,7 @@ proc handleCR*(L: var BaseLexer, pos: int): int =
   L.lineStart = result
 
 proc handleLF*(L: var BaseLexer, pos: int): int =
-  ## Call this if you scanned over '\L' in the buffer; it returns the the
+  ## Call this if you scanned over '\L' in the buffer; it returns the
   ## position to continue the scanning from. `pos` must be the position
   ## of the '\L'.
   assert(L.buf[pos] == '\L')
@@ -120,7 +120,8 @@ proc handleLF*(L: var BaseLexer, pos: int): int =
   L.lineStart = result
 
 proc handleRefillChar*(L: var BaseLexer, pos: int): int =
-  ## To be documented.
+  ## Call this if a terminator character other than a new line is scanned
+  ## at `pos`; it returns the position to continue the scanning from.
   assert(L.buf[pos] in L.refillChars)
   result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
 
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 8c4229c88..c337680f1 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -530,8 +530,12 @@ when defineSsl:
     ##
     ## The last two parameters specify the certificate file path and the key file
     ## path, a server socket will most likely not work without these.
+    ##
     ## Certificates can be generated using the following command:
-    ## ``openssl req -x509 -nodes -days 365 -newkey rsa:1024 -keyout mycert.pem -out mycert.pem``.
+    ## - ``openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout mykey.pem -out mycert.pem``
+    ## or using ECDSA:
+    ## - ``openssl ecparam -out mykey.pem -name secp256k1 -genkey``
+    ## - ``openssl req -new -key mykey.pem -x509 -nodes -days 365 -out mycert.pem``
     var newCTX: SSL_CTX
     case protVersion
     of protSSLv23:
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index 35c364221..30d805334 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -31,11 +31,6 @@ type
     ## Type that can hold a single Unicode code point.
     ##
     ## A Rune may be composed with other Runes to a character on the screen.
-  Rune16* = distinct int16 ## \
-    ## Type that can hold a single UTF-16 encoded character.
-    ##
-    ## A single Rune16 may not be enough to hold an arbitrary Unicode code point.
-
 
 template ones(n: untyped): untyped = ((1 shl n)-1)
 
@@ -388,7 +383,7 @@ proc runeStrAtPos*(s: string, pos: Natural): string =
   ## * `runeAtPos proc <#runeAtPos,string,int>`_
   ## * `fastRuneAt template <#fastRuneAt.t,string,int,untyped>`_
   let o = runeOffset(s, pos)
-  s[o.. (o+runeLenAt(s, o)-1)]
+  s[o .. (o+runeLenAt(s, o)-1)]
 
 proc runeSubStr*(s: string, pos: int, len: int = int.high): string =
   ## Returns the UTF-8 substring starting at code point ``pos``
diff --git a/lib/system.nim b/lib/system.nim
index 61c9ee57f..9605049fc 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1132,57 +1132,57 @@ proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.}
 # built-in operators
 
 when defined(nimNoZeroExtendMagic):
-  proc ze*(x: int8): int =
+  proc ze*(x: int8): int {.deprecated.} =
     ## zero extends a smaller integer type to ``int``. This treats `x` as
     ## unsigned.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
 
     cast[int](uint(cast[uint8](x)))
 
-  proc ze*(x: int16): int =
+  proc ze*(x: int16): int {.deprecated.} =
     ## zero extends a smaller integer type to ``int``. This treats `x` as
     ## unsigned.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
     cast[int](uint(cast[uint16](x)))
 
-  proc ze64*(x: int8): int64 =
+  proc ze64*(x: int8): int64 {.deprecated.} =
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
     cast[int64](uint64(cast[uint8](x)))
 
-  proc ze64*(x: int16): int64 =
+  proc ze64*(x: int16): int64 {.deprecated.} =
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
     cast[int64](uint64(cast[uint16](x)))
 
-  proc ze64*(x: int32): int64 =
+  proc ze64*(x: int32): int64 {.deprecated.} =
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
     cast[int64](uint64(cast[uint32](x)))
 
-  proc ze64*(x: int): int64 =
+  proc ze64*(x: int): int64 {.deprecated.} =
     ## zero extends a smaller integer type to ``int64``. This treats `x` as
     ## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
     ## (This is the case on 64 bit processors.)
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
     cast[int64](uint64(cast[uint](x)))
 
-  proc toU8*(x: int): int8 =
+  proc toU8*(x: int): int8 {.deprecated.} =
     ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
     ## from `x`.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
     cast[int8](x)
 
-  proc toU16*(x: int): int16 =
+  proc toU16*(x: int): int16 {.deprecated.} =
     ## treats `x` as unsigned and converts it to an ``int16`` by taking the last
     ## 16 bits from `x`.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
     cast[int16](x)
 
-  proc toU32*(x: int64): int32 =
+  proc toU32*(x: int64): int32 {.deprecated.} =
     ## treats `x` as unsigned and converts it to an ``int32`` by taking the
     ## last 32 bits from `x`.
     ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
@@ -1794,21 +1794,25 @@ proc cmp*(x, y: string): int {.noSideEffect, procvar.}
   ## **Note**: The precise result values depend on the used C runtime library and
   ## can differ between operating systems!
 
-proc `@`* [IDX, T](a: array[IDX, T]): seq[T] {.
-  magic: "ArrToSeq", noSideEffect.}
-  ## Turns an array into a sequence.
-  ##
-  ## This most often useful for constructing
-  ## sequences with the array constructor: ``@[1, 2, 3]`` has the type
-  ## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``.
-  ##
-  ## .. code-block:: Nim
-  ##   let
-  ##     a = [1, 3, 5]
-  ##     b = "foo"
-  ##
-  ##   echo @a # => @[1, 3, 5]
-  ##   echo @b # => @['f', 'o', 'o']
+when defined(nimHasDefault):
+  proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {.
+    magic: "ArrToSeq", noSideEffect.}
+    ## Turns an array into a sequence.
+    ##
+    ## This most often useful for constructing
+    ## sequences with the array constructor: ``@[1, 2, 3]`` has the type
+    ## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``.
+    ##
+    ## .. code-block:: Nim
+    ##   let
+    ##     a = [1, 3, 5]
+    ##     b = "foo"
+    ##
+    ##   echo @a # => @[1, 3, 5]
+    ##   echo @b # => @['f', 'o', 'o']
+else:
+  proc `@`* [IDX, T](a: array[IDX, T]): seq[T] {.
+    magic: "ArrToSeq", noSideEffect.}
 
 when defined(nimHasDefault):
   proc default*(T: typedesc): T {.magic: "Default", noSideEffect.}
@@ -2089,7 +2093,7 @@ when not defined(JS) and not defined(nimscript) and hostOS != "standalone":
 when not defined(JS) and not defined(nimscript) and hasAlloc and not defined(gcDestructors):
   proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.}
 
-when not defined(gcDestructors):
+when not defined(gcDestructors) or defined(nimscript):
   proc add*[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.}
     ## Generic proc for adding a data item `y` to a container `x`.
     ##
@@ -2277,8 +2281,7 @@ type # these work for most platforms:
   PInt64* = ptr int64        ## An alias for ``ptr int64``.
   PInt32* = ptr int32        ## An alias for ``ptr int32``.
 
-proc toFloat*(i: int): float {.
-  magic: "ToFloat", noSideEffect, importc: "toFloat".}
+proc toFloat*(i: int): float {.noSideEffect, inline.} =
   ## Converts an integer `i` into a ``float``.
   ##
   ## If the conversion fails, `ValueError` is raised.
@@ -2290,13 +2293,13 @@ proc toFloat*(i: int): float {.
   ##     b = 3.7
   ##
   ##   echo a.toFloat + b # => 5.7
+  float(i)
 
-proc toBiggestFloat*(i: BiggestInt): BiggestFloat {.
-  magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".}
+proc toBiggestFloat*(i: BiggestInt): BiggestFloat {.noSideEffect, inline.} =
   ## Same as `toFloat <#toFloat,int>`_ but for ``BiggestInt`` to ``BiggestFloat``.
+  BiggestFloat(i)
 
-proc toInt*(f: float): int {.
-  magic: "ToInt", noSideEffect, importc: "toInt".}
+proc toInt*(f: float): int {.noSideEffect.} =
   ## Converts a floating point number `f` into an ``int``.
   ##
   ## Conversion rounds `f` half away from 0, see
@@ -2310,10 +2313,11 @@ proc toInt*(f: float): int {.
   ##   doAssert toInt(0.49) == 0
   ##   doAssert toInt(0.5) == 1
   ##   doAssert toInt(-0.5) == -1 # rounding is symmetrical
+  if f >= 0: int(f+0.5) else: int(f-0.5)
 
-proc toBiggestInt*(f: BiggestFloat): BiggestInt {.
-  magic: "ToBiggestInt", noSideEffect, importc: "toBiggestInt".}
+proc toBiggestInt*(f: BiggestFloat): BiggestInt {.noSideEffect.} =
   ## Same as `toInt <#toInt,float>`_ but for ``BiggestFloat`` to ``BiggestInt``.
+  if f >= 0: BiggestInt(f+0.5) else: BiggestInt(f-0.5)
 
 proc addQuitProc*(quitProc: proc() {.noconv.}) {.
   importc: "atexit", header: "<stdlib.h>".}
@@ -2677,6 +2681,7 @@ when defined(nimNewRoof):
     ##
     ##   for i in countup(2, 9, 3):
     ##     echo i # => 2; 5; 8
+    mixin inc
     when T is IntLikeForCount:
       var res = int(a)
       while res <= int(b):
@@ -2697,6 +2702,7 @@ when defined(nimNewRoof):
     ## .. code-block:: Nim
     ##   for i in 3 .. 7:
     ##     echo i # => 3; 4; 5; 6; 7
+    mixin inc
     when T is IntLikeForCount:
       var res = int(a)
       while res <= int(b):
@@ -2726,6 +2732,7 @@ when defined(nimNewRoof):
   dotdotImpl(uint32)
 
   iterator `..<`*[T](a, b: T): T {.inline.} =
+    mixin inc
     var i = T(a)
     while i < b:
       yield i
@@ -2781,6 +2788,7 @@ else:
     ## .. code-block:: Nim
     ##   for i in 3 .. 7:
     ##     echo i # => 3; 4; 5; 6; 7
+    mixin inc
     when T is IntLikeForCount:
       var res = int(a)
       while res <= int(b):
@@ -2793,6 +2801,7 @@ else:
         inc(res)
 
   iterator `..<`*[S, T](a: S, b: T): T {.inline.} =
+    mixin inc
     var i = T(a)
     while i < b:
       yield i
@@ -3630,10 +3639,6 @@ when not defined(JS): #and not defined(nimscript):
         if result == 0:
           result = x.len - y.len
 
-  when not defined(nimscript) and hostOS != "standalone":
-    when defined(endb):
-      proc endbStep()
-
   when declared(newSeq):
     proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
       ## Converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
@@ -3807,9 +3812,6 @@ when not defined(JS): #and not defined(nimscript):
       currException = exc
 
   {.push stack_trace: off, profiler:off.}
-  when defined(endb) and not defined(nimscript):
-    include "system/debugger"
-
   when (defined(profiler) or defined(memProfiler)) and not defined(nimscript):
     include "system/profiler"
   {.pop.} # stacktrace
@@ -4499,6 +4501,11 @@ when defined(nimconfig):
 when not defined(js):
   proc toOpenArray*[T](x: ptr UncheckedArray[T]; first, last: int): openArray[T] {.
     magic: "Slice".}
+  when defined(nimToOpenArrayCString):
+    proc toOpenArray*(x: cstring; first, last: int): openArray[char] {.
+      magic: "Slice".}
+    proc toOpenArrayByte*(x: cstring; first, last: int): openArray[byte] {.
+      magic: "Slice".}
 
 proc toOpenArray*[T](x: seq[T]; first, last: int): openArray[T] {.
   magic: "Slice".}
@@ -4508,8 +4515,13 @@ proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openArray[T] {.
   magic: "Slice".}
 proc toOpenArray*(x: string; first, last: int): openArray[char] {.
   magic: "Slice".}
+
 proc toOpenArrayByte*(x: string; first, last: int): openArray[byte] {.
   magic: "Slice".}
+proc toOpenArrayByte*(x: openArray[char]; first, last: int): openArray[byte] {.
+  magic: "Slice".}
+proc toOpenArrayByte*(x: seq[char]; first, last: int): openArray[byte] {.
+  magic: "Slice".}
 
 type
   ForLoopStmt* {.compilerproc.} = object ## \
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 9c47d9de9..efbd95089 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -984,7 +984,7 @@ when defined(nimTypeNames):
 
 # ---------------------- thread memory region -------------------------------
 
-template instantiateForRegion(allocator: untyped) =
+template instantiateForRegion(allocator: untyped) {.dirty.} =
   {.push stackTrace: off.}
 
   when defined(fulldebug):
@@ -1006,8 +1006,8 @@ template instantiateForRegion(allocator: untyped) =
   proc dealloc(p: pointer) =
     dealloc(allocator, p)
 
-  proc realloc(p: pointer, newsize: Natural): pointer =
-    result = realloc(allocator, p, newsize)
+  proc realloc(p: pointer, newSize: Natural): pointer =
+    result = realloc(allocator, p, newSize)
 
   when false:
     proc countFreeMem(): int =
@@ -1054,13 +1054,13 @@ template instantiateForRegion(allocator: untyped) =
     else:
       dealloc(p)
 
-  proc reallocShared(p: pointer, newsize: Natural): pointer =
+  proc reallocShared(p: pointer, newSize: Natural): pointer =
     when hasThreadSupport:
       acquireSys(heapLock)
-      result = realloc(sharedHeap, p, newsize)
+      result = realloc(sharedHeap, p, newSize)
       releaseSys(heapLock)
     else:
-      result = realloc(p, newsize)
+      result = realloc(p, newSize)
 
   when hasThreadSupport:
     template sharedMemStatsShared(v: int) =
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index 76c78a3b9..16e7a14d6 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -30,7 +30,7 @@ proc c_strcmp*(a, b: cstring): cint {.
 proc c_strlen*(a: cstring): csize {.
   importc: "strlen", header: "<string.h>", noSideEffect.}
 proc c_abort*() {.
-  importc: "abort", header: "<stdlib.h>", noSideEffect.}
+  importc: "abort", header: "<stdlib.h>", noSideEffect, noreturn.}
 
 
 when defined(linux) and defined(amd64):
diff --git a/lib/system/assertions.nim b/lib/system/assertions.nim
index 0deb957c9..2131394e0 100644
--- a/lib/system/assertions.nim
+++ b/lib/system/assertions.nim
@@ -27,12 +27,12 @@ proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
   Hide(raiseAssert)(msg)
 
 template assertImpl(cond: bool, msg: string, expr: string, enabled: static[bool]) =
-  const
-    loc = instantiationInfo(fullPaths = compileOption("excessiveStackTrace"))
-    ploc = $loc
-  bind instantiationInfo
-  mixin failedAssertImpl
   when enabled:
+    const
+      loc = instantiationInfo(fullPaths = compileOption("excessiveStackTrace"))
+      ploc = $loc
+    bind instantiationInfo
+    mixin failedAssertImpl
     {.line: loc.}:
       if not cond:
         failedAssertImpl(ploc & " `" & expr & "` " & msg)
diff --git a/lib/system/debugger.nim b/lib/system/debugger.nim
deleted file mode 100644
index fd0ae2399..000000000
--- a/lib/system/debugger.nim
+++ /dev/null
@@ -1,303 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This file implements basic features for any debugger.
-
-type
-  VarSlot* {.compilerproc, final.} = object ## a slot in a frame
-    address*: pointer ## the variable's address
-    typ*: PNimType    ## the variable's type
-    name*: cstring    ## the variable's name; for globals this is "module.name"
-
-  PExtendedFrame = ptr ExtendedFrame
-  ExtendedFrame = object  # If the debugger is enabled the compiler
-                           # provides an extended frame. Of course
-                           # only slots that are
-                           # needed are allocated and not 10_000,
-                           # except for the global data description.
-    f: TFrame
-    slots: array[0..10_000, VarSlot]
-
-var
-  dbgGlobalData: ExtendedFrame  # this reserves much space, but
-                                # for now it is the most practical way
-
-proc dbgRegisterGlobal(name: cstring, address: pointer,
-                       typ: PNimType) {.compilerproc.} =
-  let i = dbgGlobalData.f.len
-  if i >= high(dbgGlobalData.slots):
-    #debugOut("[Warning] cannot register global ")
-    return
-  dbgGlobalData.slots[i].name = name
-  dbgGlobalData.slots[i].typ = typ
-  dbgGlobalData.slots[i].address = address
-  inc(dbgGlobalData.f.len)
-
-proc getLocal*(frame: PFrame; slot: int): VarSlot {.inline.} =
-  ## retrieves the meta data for the local variable at `slot`. CAUTION: An
-  ## invalid `slot` value causes a corruption!
-  result = cast[PExtendedFrame](frame).slots[slot]
-
-proc getGlobalLen*(): int {.inline.} =
-  ## gets the number of registered globals.
-  result = dbgGlobalData.f.len
-
-proc getGlobal*(slot: int): VarSlot {.inline.} =
-  ## retrieves the meta data for the global variable at `slot`. CAUTION: An
-  ## invalid `slot` value causes a corruption!
-  result = dbgGlobalData.slots[slot]
-
-# ------------------- breakpoint support ------------------------------------
-
-type
-  Breakpoint* = object   ## represents a break point
-    low*, high*: int     ## range from low to high; if disabled
-                         ## both low and high are set to their negative values
-    filename*: cstring   ## the filename of the breakpoint
-
-var
-  dbgBP: array[0..127, Breakpoint] # breakpoints
-  dbgBPlen: int
-  dbgBPbloom: int64  # we use a bloom filter to speed up breakpoint checking
-
-  dbgFilenames*: array[0..300, cstring] ## registered filenames;
-                                        ## 'nil' terminated
-  dbgFilenameLen: int
-
-proc dbgRegisterFilename(filename: cstring) {.compilerproc.} =
-  # XXX we could check for duplicates here for DLL support
-  dbgFilenames[dbgFilenameLen] = filename
-  inc dbgFilenameLen
-
-proc dbgRegisterBreakpoint(line: int,
-                           filename, name: cstring) {.compilerproc.} =
-  let x = dbgBPlen
-  if x >= high(dbgBP):
-    #debugOut("[Warning] cannot register breakpoint")
-    return
-  inc(dbgBPlen)
-  dbgBP[x].filename = filename
-  dbgBP[x].low = line
-  dbgBP[x].high = line
-  dbgBPbloom = dbgBPbloom or line
-
-proc addBreakpoint*(filename: cstring, lo, hi: int): bool =
-  let x = dbgBPlen
-  if x >= high(dbgBP): return false
-  inc(dbgBPlen)
-  result = true
-  dbgBP[x].filename = filename
-  dbgBP[x].low = lo
-  dbgBP[x].high = hi
-  for line in lo..hi: dbgBPbloom = dbgBPbloom or line
-
-const
-  FileSystemCaseInsensitive = defined(windows) or defined(dos) or defined(os2)
-
-proc fileMatches(c, bp: cstring): bool =
-  # bp = breakpoint filename
-  # c = current filename
-  # we consider it a match if bp is a suffix of c
-  # and the character for the suffix does not exist or
-  # is one of: \  /  :
-  # depending on the OS case does not matter!
-  var blen: int = bp.len
-  var clen: int = c.len
-  if blen > clen: return false
-  # check for \ /  :
-  if clen-blen-1 >= 0 and c[clen-blen-1] notin {'\\', '/', ':'}:
-    return false
-  var i = 0
-  while i < blen:
-    var x = bp[i]
-    var y = c[i+clen-blen]
-    when FileSystemCaseInsensitive:
-      if x >= 'A' and x <= 'Z': x = chr(ord(x) - ord('A') + ord('a'))
-      if y >= 'A' and y <= 'Z': y = chr(ord(y) - ord('A') + ord('a'))
-    if x != y: return false
-    inc(i)
-  return true
-
-proc canonFilename*(filename: cstring): cstring =
-  ## returns 'nil' if the filename cannot be found.
-  for i in 0 .. dbgFilenameLen-1:
-    result = dbgFilenames[i]
-    if fileMatches(result, filename): return result
-  result = nil
-
-iterator listBreakpoints*(): ptr Breakpoint =
-  ## lists all breakpoints.
-  for i in 0..dbgBPlen-1: yield addr(dbgBP[i])
-
-proc isActive*(b: ptr Breakpoint): bool = b.low > 0
-proc flip*(b: ptr Breakpoint) =
-  ## enables or disables 'b' depending on its current state.
-  b.low = -b.low; b.high = -b.high
-
-proc checkBreakpoints*(filename: cstring, line: int): ptr Breakpoint =
-  ## in which breakpoint (if any) we are.
-  if (dbgBPbloom and line) != line: return nil
-  for b in listBreakpoints():
-    if line >= b.low and line <= b.high and filename == b.filename: return b
-
-# ------------------- watchpoint support ------------------------------------
-
-type
-  Hash = int
-  Watchpoint {.pure, final.} = object
-    name: cstring
-    address: pointer
-    typ: PNimType
-    oldValue: Hash
-
-var
-  watchpoints: array[0..99, Watchpoint]
-  watchpointsLen: int
-
-proc `!&`(h: Hash, val: int): Hash {.inline.} =
-  result = h +% val
-  result = result +% result shl 10
-  result = result xor (result shr 6)
-
-proc `!$`(h: Hash): Hash {.inline.} =
-  result = h +% h shl 3
-  result = result xor (result shr 11)
-  result = result +% result shl 15
-
-proc hash(data: pointer, size: int): Hash =
-  var h: Hash = 0
-  var p = cast[cstring](data)
-  var i = 0
-  var s = size
-  while s > 0:
-    h = h !& ord(p[i])
-    inc(i)
-    dec(s)
-  result = !$h
-
-proc hashGcHeader(data: pointer): Hash =
-  const headerSize = sizeof(int)*2
-  result = hash(cast[pointer](cast[int](data) -% headerSize), headerSize)
-
-proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool,
-                    h: Hash): Hash
-proc genericHashAux(dest: pointer, n: ptr TNimNode, shallow: bool,
-                    h: Hash): Hash =
-  var d = cast[ByteAddress](dest)
-  case n.kind
-  of nkSlot:
-    result = genericHashAux(cast[pointer](d +% n.offset), n.typ, shallow, h)
-  of nkList:
-    result = h
-    for i in 0..n.len-1:
-      result = result !& genericHashAux(dest, n.sons[i], shallow, result)
-  of nkCase:
-    result = h !& hash(cast[pointer](d +% n.offset), n.typ.size)
-    var m = selectBranch(dest, n)
-    if m != nil: result = genericHashAux(dest, m, shallow, result)
-  of nkNone: sysAssert(false, "genericHashAux")
-
-proc genericHashAux(dest: pointer, mt: PNimType, shallow: bool,
-                    h: Hash): Hash =
-  sysAssert(mt != nil, "genericHashAux 2")
-  case mt.kind
-  of tyString:
-    var x = cast[PPointer](dest)[]
-    result = h
-    if x != nil:
-      let s = cast[NimString](x)
-      when defined(trackGcHeaders):
-        result = result !& hashGcHeader(x)
-      else:
-        result = result !& hash(x, s.len)
-  of tySequence:
-    var x = cast[PPointer](dest)
-    var dst = cast[ByteAddress](cast[PPointer](dest)[])
-    result = h
-    if dst != 0:
-      when defined(trackGcHeaders):
-        result = result !& hashGcHeader(cast[PPointer](dest)[])
-      else:
-        for i in 0..cast[PGenericSeq](dst).len-1:
-          result = result !& genericHashAux(
-            cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize),
-            mt.base, shallow, result)
-  of tyObject, tyTuple:
-    # we don't need to copy m_type field for tyObject, as they are equal anyway
-    result = genericHashAux(dest, mt.node, shallow, h)
-  of tyArray, tyArrayConstr:
-    let d = cast[ByteAddress](dest)
-    result = h
-    for i in 0..(mt.size div mt.base.size)-1:
-      result = result !& genericHashAux(cast[pointer](d +% i*% mt.base.size),
-                                        mt.base, shallow, result)
-  of tyRef:
-    when defined(trackGcHeaders):
-      var s = cast[PPointer](dest)[]
-      if s != nil:
-        result = result !& hashGcHeader(s)
-    else:
-      if shallow:
-        result = h !& hash(dest, mt.size)
-      else:
-        result = h
-        var s = cast[PPointer](dest)[]
-        if s != nil:
-          result = result !& genericHashAux(s, mt.base, shallow, result)
-  else:
-    result = h !& hash(dest, mt.size) # hash raw bits
-
-proc genericHash(dest: pointer, mt: PNimType): int =
-  result = genericHashAux(dest, mt, false, 0)
-
-proc dbgRegisterWatchpoint(address: pointer, name: cstring,
-                           typ: PNimType) {.compilerproc.} =
-  let L = watchPointsLen
-  for i in 0 .. pred(L):
-    if watchPoints[i].name == name:
-      # address may have changed:
-      watchPoints[i].address = address
-      return
-  if L >= watchPoints.high:
-    #debugOut("[Warning] cannot register watchpoint")
-    return
-  watchPoints[L].name = name
-  watchPoints[L].address = address
-  watchPoints[L].typ = typ
-  watchPoints[L].oldValue = genericHash(address, typ)
-  inc watchPointsLen
-
-proc dbgUnregisterWatchpoints*() =
-  watchPointsLen = 0
-
-var
-  dbgLineHook*: proc () {.nimcall.}
-    ## set this variable to provide a procedure that should be called before
-    ## each executed instruction. This should only be used by debuggers!
-    ## Only code compiled with the ``debugger:on`` switch calls this hook.
-
-  dbgWatchpointHook*: proc (watchpointName: cstring) {.nimcall.}
-
-proc checkWatchpoints =
-  let L = watchPointsLen
-  for i in 0 .. pred(L):
-    let newHash = genericHash(watchPoints[i].address, watchPoints[i].typ)
-    if newHash != watchPoints[i].oldValue:
-      dbgWatchpointHook(watchPoints[i].name)
-      watchPoints[i].oldValue = newHash
-
-proc endb(line: int, file: cstring) {.compilerproc, noinline.} =
-  # This proc is called before every Nim code line!
-  if framePtr == nil: return
-  if dbgWatchpointHook != nil: checkWatchpoints()
-  framePtr.line = line # this is done here for smaller code size!
-  framePtr.filename = file
-  if dbgLineHook != nil: dbgLineHook()
-
-include "system/endb"
diff --git a/lib/system/endb.nim b/lib/system/endb.nim
deleted file mode 100644
index 6c99f8d12..000000000
--- a/lib/system/endb.nim
+++ /dev/null
@@ -1,579 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2013 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This file implements the embedded debugger that can be linked
-# with the application. Mostly we do not use dynamic memory here as that
-# would interfere with the GC and trigger ON/OFF errors if the
-# user program corrupts memory. Unfortunately, for dispaying
-# variables we use the ``system.repr()`` proc which uses Nim
-# strings and thus allocates memory from the heap. Pity, but
-# I do not want to implement ``repr()`` twice.
-
-const
-  EndbBeg = "*** endb"
-  EndbEnd = "***\n"
-
-type
-  StaticStr = object
-    len: int
-    data: array[0..100, char]
-
-  BreakpointFilename = object
-    b: ptr Breakpoint
-    filename: StaticStr
-
-  DbgState = enum
-    dbOff,        # debugger is turned off
-    dbStepInto,   # debugger is in tracing mode
-    dbStepOver,
-    dbSkipCurrent,
-    dbQuiting,    # debugger wants to quit
-    dbBreakpoints # debugger is only interested in breakpoints
-
-var
-  dbgUser: StaticStr    # buffer for user input; first command is ``step_into``
-                        # needs to be global cause we store the last command
-                        # in it
-  dbgState: DbgState    # state of debugger
-  dbgSkipToFrame: PFrame # frame to be skipped to
-
-  maxDisplayRecDepth: int = 5 # do not display too much data!
-
-  brkPoints: array[0..127, BreakpointFilename]
-
-proc setLen(s: var StaticStr, newLen=0) =
-  s.len = newLen
-  s.data[newLen] = '\0'
-
-proc add(s: var StaticStr, c: char) =
-  if s.len < high(s.data)-1:
-    s.data[s.len] = c
-    s.data[s.len+1] = '\0'
-    inc s.len
-
-proc add(s: var StaticStr, c: cstring) =
-  var i = 0
-  while c[i] != '\0':
-    add s, c[i]
-    inc i
-
-proc assign(s: var StaticStr, c: cstring) =
-  setLen(s)
-  add s, c
-
-proc `==`(a, b: StaticStr): bool =
-  if a.len == b.len:
-    for i in 0 .. a.len-1:
-      if a.data[i] != b.data[i]: return false
-    return true
-
-proc `==`(a: StaticStr, b: cstring): bool =
-  result = c_strcmp(unsafeAddr a.data, b) == 0
-
-proc write(f: CFilePtr, s: cstring) = c_fputs(s, f)
-proc writeLine(f: CFilePtr, s: cstring) =
-  c_fputs(s, f)
-  c_fputs("\n", f)
-
-proc write(f: CFilePtr, s: StaticStr) =
-  write(f, cstring(unsafeAddr s.data))
-
-proc write(f: CFilePtr, i: int) =
-  when sizeof(int) == 8:
-    discard c_fprintf(f, "%lld", i)
-  else:
-    discard c_fprintf(f, "%ld", i)
-
-proc close(f: CFilePtr): cint {.
-  importc: "fclose", header: "<stdio.h>", discardable.}
-
-proc c_fgetc(stream: CFilePtr): cint {.
-  importc: "fgetc", header: "<stdio.h>".}
-proc c_ungetc(c: cint, f: CFilePtr): cint {.
-  importc: "ungetc", header: "<stdio.h>", discardable.}
-
-var
-  cstdin* {.importc: "stdin", header: "<stdio.h>".}: CFilePtr
-
-proc listBreakPoints() =
-  write(cstdout, EndbBeg)
-  write(cstdout, "| Breakpoints:\n")
-  for b in listBreakpoints():
-    write(cstdout, abs(b.low))
-    if b.high != b.low:
-      write(cstdout, "..")
-      write(cstdout, abs(b.high))
-    write(cstdout, " ")
-    write(cstdout, b.filename)
-    if b.isActive:
-      write(cstdout, " [disabled]\n")
-    else:
-      write(cstdout, "\n")
-  write(cstdout, EndbEnd)
-
-proc openAppend(filename: cstring): CFilePtr =
-  proc fopen(filename, mode: cstring): CFilePtr {.importc: "fopen", header: "<stdio.h>".}
-
-  result = fopen(filename, "ab")
-  if result != nil:
-    write(result, "----------------------------------------\n")
-
-proc dbgRepr(p: pointer, typ: PNimType): string =
-  var cl: ReprClosure
-  initReprClosure(cl)
-  cl.recDepth = maxDisplayRecDepth
-  # locks for the GC turned out to be a bad idea...
-  # inc(recGcLock)
-  result = ""
-  reprAux(result, p, typ, cl)
-  # dec(recGcLock)
-  deinitReprClosure(cl)
-
-proc writeVariable(stream: CFilePtr, slot: VarSlot) =
-  write(stream, slot.name)
-  write(stream, " = ")
-  writeLine(stream, dbgRepr(slot.address, slot.typ))
-
-proc listFrame(stream: CFilePtr, f: PFrame) =
-  write(stream, EndbBeg)
-  write(stream, "| Frame (")
-  write(stream, f.len)
-  write(stream, " slots):\n")
-  for i in 0 .. f.len-1:
-    writeLine(stream, getLocal(f, i).name)
-  write(stream, EndbEnd)
-
-proc listLocals(stream: CFilePtr, f: PFrame) =
-  write(stream, EndbBeg)
-  write(stream, "| Frame (")
-  write(stream, f.len)
-  write(stream, " slots):\n")
-  for i in 0 .. f.len-1:
-    writeVariable(stream, getLocal(f, i))
-  write(stream, EndbEnd)
-
-proc listGlobals(stream: CFilePtr) =
-  write(stream, EndbBeg)
-  write(stream, "| Globals:\n")
-  for i in 0 .. getGlobalLen()-1:
-    writeLine(stream, getGlobal(i).name)
-  write(stream, EndbEnd)
-
-proc debugOut(msg: cstring) =
-  # the *** *** markers are for easy recognition of debugger
-  # output for external frontends.
-  write(cstdout, EndbBeg)
-  write(cstdout, "| ")
-  write(cstdout, msg)
-  write(cstdout, EndbEnd)
-
-proc dbgFatal(msg: cstring) =
-  debugOut(msg)
-  dbgAborting = true # the debugger wants to abort
-  quit(1)
-
-proc dbgShowCurrentProc(dbgFramePointer: PFrame) =
-  if dbgFramePointer != nil:
-    write(cstdout, "*** endb| now in proc: ")
-    write(cstdout, dbgFramePointer.procname)
-    write(cstdout, " ***\n")
-  else:
-    write(cstdout, "*** endb| (proc name not available) ***\n")
-
-proc dbgShowExecutionPoint() =
-  write(cstdout, "*** endb| ")
-  write(cstdout, framePtr.filename)
-  write(cstdout, "(")
-  write(cstdout, framePtr.line)
-  write(cstdout, ") ")
-  write(cstdout, framePtr.procname)
-  write(cstdout, " ***\n")
-
-proc scanAndAppendWord(src: cstring, a: var StaticStr, start: int): int =
-  result = start
-  # skip whitespace:
-  while src[result] in {'\t', ' '}: inc(result)
-  while true:
-    case src[result]
-    of 'a'..'z', '0'..'9': add(a, src[result])
-    of '_': discard # just skip it
-    of 'A'..'Z': add(a, chr(ord(src[result]) - ord('A') + ord('a')))
-    else: break
-    inc(result)
-
-proc scanWord(src: cstring, a: var StaticStr, start: int): int =
-  setlen(a)
-  result = scanAndAppendWord(src, a, start)
-
-proc scanFilename(src: cstring, a: var StaticStr, start: int): int =
-  result = start
-  setLen a
-  while src[result] in {'\t', ' '}: inc(result)
-  while src[result] notin {'\t', ' ', '\0'}:
-    add(a, src[result])
-    inc(result)
-
-proc scanNumber(src: cstring, a: var int, start: int): int =
-  result = start
-  a = 0
-  while src[result] in {'\t', ' '}: inc(result)
-  while true:
-    case src[result]
-    of '0'..'9': a = a * 10 + ord(src[result]) - ord('0')
-    of '_': discard # skip underscores (nice for long line numbers)
-    else: break
-    inc(result)
-
-proc dbgHelp() =
-  debugOut("""
-list of commands (see the manual for further help):
-              GENERAL
-h, help                 display this help message
-q, quit                 quit the debugger and the program
-<ENTER>                 repeat the previous debugger command
-              EXECUTING
-s, step                 single step, stepping into routine calls
-n, next                 single step, without stepping into routine calls
-f, skipcurrent          continue execution until the current routine finishes
-c, continue, r, run     continue execution until the next breakpoint
-i, ignore               continue execution, ignore all breakpoints
-              BREAKPOINTS
-b, break [fromline [toline]] [file]
-                        set a new breakpoint for line and file
-                        if line or file are omitted the current one is used
-breakpoints             display the entire breakpoint list
-toggle fromline [file]  enable or disable a breakpoint
-filenames               list all valid filenames
-              DATA DISPLAY
-e, eval <expr>          evaluate the expression <expr>
-o, out <file> <expr>    evaluate <expr> and write it to <file>
-w, where                display the current execution point
-stackframe [file]       display current stack frame [and write it to file]
-u, up                   go up in the call stack
-d, down                 go down in the call stack
-bt, backtrace           display the entire call stack
-l, locals               display available local variables
-g, globals              display available global variables
-maxdisplay <integer>    set the display's recursion maximum
-""")
-
-proc invalidCommand() =
-  debugOut("[Warning] invalid command ignored (type 'h' for help) ")
-
-proc hasExt(s: cstring): bool =
-  # returns true if s has a filename extension
-  var i = 0
-  while s[i] != '\0':
-    if s[i] == '.': return true
-    inc i
-
-proc parseBreakpoint(s: cstring, start: int): Breakpoint =
-  var dbgTemp: StaticStr
-  var i = scanNumber(s, result.low, start)
-  if result.low == 0: result.low = framePtr.line
-  i = scanNumber(s, result.high, i)
-  if result.high == 0: result.high = result.low
-  i = scanFilename(s, dbgTemp, i)
-  if dbgTemp.len != 0:
-    if not hasExt(addr dbgTemp.data): add(dbgTemp, ".nim")
-    result.filename = canonFilename(addr dbgTemp.data)
-    if result.filename.isNil:
-      debugOut("[Warning] no breakpoint could be set; unknown filename ")
-      return
-  else:
-    result.filename = framePtr.filename
-
-proc createBreakPoint(s: cstring, start: int) =
-  let br = parseBreakpoint(s, start)
-  if not br.filename.isNil:
-    if not addBreakpoint(br.filename, br.low, br.high):
-      debugOut("[Warning] no breakpoint could be set; out of breakpoint space ")
-
-proc breakpointToggle(s: cstring, start: int) =
-  var a = parseBreakpoint(s, start)
-  if not a.filename.isNil:
-    var b = checkBreakpoints(a.filename, a.low)
-    if not b.isNil: b.flip
-    else: debugOut("[Warning] unknown breakpoint ")
-
-proc dbgEvaluate(stream: CFilePtr, s: cstring, start: int, f: PFrame) =
-  var dbgTemp: StaticStr
-  var i = scanWord(s, dbgTemp, start)
-  while s[i] in {' ', '\t'}: inc(i)
-  var v: VarSlot
-  if s[i] == '.':
-    inc(i)
-    add(dbgTemp, '.')
-    i = scanAndAppendWord(s, dbgTemp, i)
-    for i in 0 .. getGlobalLen()-1:
-      let v = getGlobal(i)
-      if c_strcmp(v.name, addr dbgTemp.data) == 0:
-        writeVariable(stream, v)
-  else:
-    for i in 0 .. f.len-1:
-      let v = getLocal(f, i)
-      if c_strcmp(v.name, addr dbgTemp.data) == 0:
-        writeVariable(stream, v)
-
-proc dbgOut(s: cstring, start: int, currFrame: PFrame) =
-  var dbgTemp: StaticStr
-  var i = scanFilename(s, dbgTemp, start)
-  if dbgTemp.len == 0:
-    invalidCommand()
-    return
-  var stream = openAppend(addr dbgTemp.data)
-  if stream == nil:
-    debugOut("[Warning] could not open or create file ")
-    return
-  dbgEvaluate(stream, s, i, currFrame)
-  close(stream)
-
-proc dbgStackFrame(s: cstring, start: int, currFrame: PFrame) =
-  var dbgTemp: StaticStr
-  var i = scanFilename(s, dbgTemp, start)
-  if dbgTemp.len == 0:
-    # just write it to cstdout:
-    listFrame(cstdout, currFrame)
-  else:
-    var stream = openAppend(addr dbgTemp.data)
-    if stream == nil:
-      debugOut("[Warning] could not open or create file ")
-      return
-    listFrame(stream, currFrame)
-    close(stream)
-
-proc readLine(f: CFilePtr, line: var StaticStr): bool =
-  while true:
-    var c = c_fgetc(f)
-    if c < 0'i32:
-      if line.len > 0: break
-      else: return false
-    if c == 10'i32: break # LF
-    if c == 13'i32:  # CR
-      c = c_fgetc(f) # is the next char LF?
-      if c != 10'i32: discard c_ungetc(c, f) # no, put the character back
-      break
-    add line, chr(int(c))
-  result = true
-
-proc listFilenames() =
-  write(cstdout, EndbBeg)
-  write(cstdout, "| Files:\n")
-  var i = 0
-  while true:
-    let x = dbgFilenames[i]
-    if x.isNil: break
-    write(cstdout, x)
-    write(cstdout, "\n")
-    inc i
-  write(cstdout, EndbEnd)
-
-proc dbgWriteStackTrace(f: PFrame)
-proc commandPrompt() =
-  # if we return from this routine, user code executes again
-  var
-    again = true
-    dbgFramePtr = framePtr # for going down and up the stack
-    dbgDown = 0 # how often we did go down
-    dbgTemp: StaticStr
-
-  while again:
-    write(cstdout, "*** endb| >>")
-    let oldLen = dbgUser.len
-    dbgUser.len = 0
-    if not readLine(cstdin, dbgUser): break
-    if dbgUser.len == 0: dbgUser.len = oldLen
-    # now look what we have to do:
-    var i = scanWord(addr dbgUser.data, dbgTemp, 0)
-    template `?`(x: untyped): untyped = dbgTemp == cstring(x)
-    if ?"s" or ?"step":
-      dbgState = dbStepInto
-      again = false
-    elif ?"n" or ?"next":
-      dbgState = dbStepOver
-      dbgSkipToFrame = framePtr
-      again = false
-    elif ?"f" or ?"skipcurrent":
-      dbgState = dbSkipCurrent
-      dbgSkipToFrame = framePtr.prev
-      again = false
-    elif ?"c" or ?"continue" or ?"r" or ?"run":
-      dbgState = dbBreakpoints
-      again = false
-    elif ?"i" or ?"ignore":
-      dbgState = dbOff
-      again = false
-    elif ?"h" or ?"help":
-      dbgHelp()
-    elif ?"q" or ?"quit":
-      dbgState = dbQuiting
-      dbgAborting = true
-      again = false
-      quit(1) # BUGFIX: quit with error code > 0
-    elif ?"e" or ?"eval":
-      var
-        prevState = dbgState
-        prevSkipFrame = dbgSkipToFrame
-      dbgState = dbSkipCurrent
-      dbgEvaluate(cstdout, addr dbgUser.data, i, dbgFramePtr)
-      dbgState = prevState
-      dbgSkipToFrame = prevSkipFrame
-    elif ?"o" or ?"out":
-      dbgOut(addr dbgUser.data, i, dbgFramePtr)
-    elif ?"stackframe":
-      dbgStackFrame(addr dbgUser.data, i, dbgFramePtr)
-    elif ?"w" or ?"where":
-      dbgShowExecutionPoint()
-    elif ?"l" or ?"locals":
-      var
-        prevState = dbgState
-        prevSkipFrame = dbgSkipToFrame
-      dbgState = dbSkipCurrent
-      listLocals(cstdout, dbgFramePtr)
-      dbgState = prevState
-      dbgSkipToFrame = prevSkipFrame
-    elif ?"g" or ?"globals":
-      var
-        prevState = dbgState
-        prevSkipFrame = dbgSkipToFrame
-      dbgState = dbSkipCurrent
-      listGlobals(cstdout)
-      dbgState = prevState
-      dbgSkipToFrame = prevSkipFrame
-    elif ?"u" or ?"up":
-      if dbgDown <= 0:
-        debugOut("[Warning] cannot go up any further ")
-      else:
-        dbgFramePtr = framePtr
-        for j in 0 .. dbgDown-2: # BUGFIX
-          dbgFramePtr = dbgFramePtr.prev
-        dec(dbgDown)
-      dbgShowCurrentProc(dbgFramePtr)
-    elif ?"d" or ?"down":
-      if dbgFramePtr != nil:
-        inc(dbgDown)
-        dbgFramePtr = dbgFramePtr.prev
-        dbgShowCurrentProc(dbgFramePtr)
-      else:
-        debugOut("[Warning] cannot go down any further ")
-    elif ?"bt" or ?"backtrace":
-      dbgWriteStackTrace(framePtr)
-    elif ?"b" or ?"break":
-      createBreakPoint(addr dbgUser.data, i)
-    elif ?"breakpoints":
-      listBreakPoints()
-    elif ?"toggle":
-      breakpointToggle(addr dbgUser.data, i)
-    elif ?"filenames":
-      listFilenames()
-    elif ?"maxdisplay":
-      var parsed: int
-      i = scanNumber(addr dbgUser.data, parsed, i)
-      if dbgUser.data[i-1] in {'0'..'9'}:
-        if parsed == 0: maxDisplayRecDepth = -1
-        else: maxDisplayRecDepth = parsed
-      else:
-        invalidCommand()
-    else: invalidCommand()
-
-proc endbStep() =
-  # we get into here if an unhandled exception has been raised
-  # XXX: do not allow the user to run the program any further?
-  # XXX: BUG: the frame is lost here!
-  dbgShowExecutionPoint()
-  commandPrompt()
-
-proc dbgWriteStackTrace(f: PFrame) =
-  const
-    firstCalls = 32
-  var
-    it = f
-    i = 0
-    total = 0
-    tempFrames: array[0..127, PFrame]
-  # setup long head:
-  while it != nil and i <= high(tempFrames)-firstCalls:
-    tempFrames[i] = it
-    inc(i)
-    inc(total)
-    it = it.prev
-  # go up the stack to count 'total':
-  var b = it
-  while it != nil:
-    inc(total)
-    it = it.prev
-  var skipped = 0
-  if total > len(tempFrames):
-    # skip N
-    skipped = total-i-firstCalls+1
-    for j in 1..skipped:
-      if b != nil: b = b.prev
-    # create '...' entry:
-    tempFrames[i] = nil
-    inc(i)
-  # setup short tail:
-  while b != nil and i <= high(tempFrames):
-    tempFrames[i] = b
-    inc(i)
-    b = b.prev
-  for j in countdown(i-1, 0):
-    if tempFrames[j] == nil:
-      write(cstdout, "(")
-      write(cstdout, skipped)
-      write(cstdout, " calls omitted) ...")
-    else:
-      write(cstdout, tempFrames[j].filename)
-      if tempFrames[j].line > 0:
-        write(cstdout, "(")
-        write(cstdout, tempFrames[j].line)
-        write(cstdout, ")")
-      write(cstdout, " ")
-      write(cstdout, tempFrames[j].procname)
-    write(cstdout, "\n")
-
-proc checkForBreakpoint =
-  let b = checkBreakpoints(framePtr.filename, framePtr.line)
-  if b != nil:
-    write(cstdout, "*** endb| reached ")
-    write(cstdout, framePtr.filename)
-    write(cstdout, "(")
-    write(cstdout, framePtr.line)
-    write(cstdout, ") ")
-    write(cstdout, framePtr.procname)
-    write(cstdout, " ***\n")
-    commandPrompt()
-
-proc lineHookImpl() {.nimcall.} =
-  case dbgState
-  of dbStepInto:
-    # we really want the command prompt here:
-    dbgShowExecutionPoint()
-    commandPrompt()
-  of dbSkipCurrent, dbStepOver: # skip current routine
-    if framePtr == dbgSkipToFrame:
-      dbgShowExecutionPoint()
-      commandPrompt()
-    else:
-      # breakpoints are wanted though (I guess)
-      checkForBreakpoint()
-  of dbBreakpoints:
-    # debugger is only interested in breakpoints
-    checkForBreakpoint()
-  else: discard
-
-proc watchpointHookImpl(name: cstring) {.nimcall.} =
-  dbgWriteStackTrace(framePtr)
-  debugOut(name)
-
-proc initDebugger {.inline.} =
-  dbgState = dbStepInto
-  dbgUser.len = 1
-  dbgUser.data[0] = 's'
-  dbgWatchpointHook = watchpointHookImpl
-  dbgLineHook = lineHookImpl
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 0898ad0fd..1eb4cedc8 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -38,10 +38,7 @@ proc showErrorMessage(data: cstring) {.gcsafe.} =
       writeToStdErr(data)
 
 proc quitOrDebug() {.inline.} =
-  when defined(endb):
-    endbStep() # call the debugger
-  else:
-    quit(1)
+  quit(1)
 
 proc chckIndx(i, a, b: int): int {.inline, compilerproc, benign.}
 proc chckRange(i, a, b: int): int {.inline, compilerproc, benign.}
@@ -469,10 +466,6 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl.} =
   framePtr = s
   if s.calldepth == nimCallDepthLimit: callDepthLimitReached()
 
-when defined(endb):
-  var
-    dbgAborting: bool # whether the debugger wants to abort
-
 when defined(cpp) and appType != "lib" and
     not defined(js) and not defined(nimscript) and
     hostOS != "standalone" and not defined(noCppExceptions):
@@ -515,8 +508,6 @@ when not defined(noSignalHandler) and not defined(useNimRtl):
       elif s == SIGSEGV:
         action("SIGSEGV: Illegal storage access. (Attempt to read from nil?)\n")
       elif s == SIGABRT:
-        when defined(endb):
-          if dbgAborting: return # the debugger wants to abort
         action("SIGABRT: Abnormal termination.\n")
       elif s == SIGFPE: action("SIGFPE: Arithmetic error.\n")
       elif s == SIGILL: action("SIGILL: Illegal operation.\n")
@@ -546,7 +537,6 @@ when not defined(noSignalHandler) and not defined(useNimRtl):
         msg = y
       processSignal(sign, asgn)
       showErrorMessage(msg)
-    when defined(endb): dbgAborting = true
     quit(1) # always quit when SIGABRT
 
   proc registerSignalHandler() =
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index 87d803485..3ce428930 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -511,7 +511,7 @@ when not defined(useNimRtl):
       gch.tracing = true
 
   proc GC_fullCollect() =
-    var oldThreshold = gch.cycleThreshold
+    let oldThreshold = gch.cycleThreshold
     gch.cycleThreshold = 0 # forces cycle collection
     collectCT(gch, 0)
     gch.cycleThreshold = oldThreshold
diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim
index dafd56cb3..549aa5886 100644
--- a/lib/system/iterators.nim
+++ b/lib/system/iterators.nim
@@ -85,7 +85,7 @@ iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} =
     yield (i, a[i])
     inc(i)
 
-iterator mpairs*[T](a: var openArray[T]): tuple[key:int, val:var T]{.inline.} =
+iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.} =
   ## Iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
   ## ``a[index]`` can be modified.
   var i = 0
@@ -102,7 +102,7 @@ iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
       if i >= high(IX): break
       inc(i)
 
-iterator mpairs*[IX, T](a:var array[IX, T]):tuple[key:IX,val:var T] {.inline.} =
+iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inline.} =
   ## Iterates over each item of `a`. Yields ``(index, a[index])`` pairs.
   ## ``a[index]`` can be modified.
   var i = low(IX)
@@ -179,7 +179,6 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
       yield (i, a[i])
       inc(i)
 
-
 iterator items*[T](a: seq[T]): T {.inline.} =
   ## Iterates over each item of `a`.
   var i = 0
@@ -224,7 +223,7 @@ iterator fields*[T: tuple|object](x: T): RootObj {.
   ## **Warning**: This really transforms the 'for' and unrolls the loop.
   ## The current implementation also has a bug
   ## that affects symbol binding in the loop body.
-iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a,b: untyped] {.
+iterator fields*[S:tuple|object, T:tuple|object](x: S, y: T): tuple[a, b: RootObj] {.
   magic: "Fields", noSideEffect.}
   ## Iterates over every field of `x` and `y`.
   ##
@@ -266,7 +265,7 @@ iterator fieldPairs*[T: tuple|object](x: T): RootObj {.
   ## loop body.
 
 iterator fieldPairs*[S: tuple|object, T: tuple|object](x: S, y: T): tuple[
-  a, b: untyped] {.
+  a, b: RootObj] {.
   magic: "FieldPairs", noSideEffect.}
   ## Iterates over every field of `x` and `y`.
   ##