summary refs log tree commit diff stats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/core/hotcodereloading.nim2
-rw-r--r--lib/core/locks.nim4
-rw-r--r--lib/core/macrocache.nim39
-rw-r--r--lib/core/macros.nim90
-rw-r--r--lib/core/rlocks.nim2
-rw-r--r--lib/core/typeinfo.nim21
-rw-r--r--lib/deprecated/pure/future.nim2
-rw-r--r--lib/deprecated/pure/ospaths.nim2
-rw-r--r--lib/deprecated/pure/oswalkdir.nim6
-rw-r--r--lib/deprecated/pure/securehash.nim6
-rw-r--r--lib/experimental/diff.nim2
-rw-r--r--lib/impure/db_mysql.nim418
-rw-r--r--lib/impure/db_odbc.nim529
-rw-r--r--lib/impure/db_postgres.nim647
-rw-r--r--lib/impure/db_sqlite.nim940
-rw-r--r--lib/impure/nre.nim20
-rw-r--r--lib/impure/nre/private/util.nim2
-rw-r--r--lib/impure/rdstdin.nim4
-rw-r--r--lib/impure/re.nim22
-rw-r--r--lib/js/asyncjs.nim16
-rw-r--r--lib/js/dom.nim19
-rw-r--r--lib/js/jscore.nim26
-rw-r--r--lib/js/jsffi.nim53
-rw-r--r--lib/js/jsre.nim7
-rw-r--r--lib/nimbase.h85
-rw-r--r--lib/nimhcr.nim18
-rw-r--r--lib/nimrtl.nim4
-rw-r--r--lib/packages/docutils/dochelpers.nim28
-rw-r--r--lib/packages/docutils/highlite.nim30
-rw-r--r--lib/packages/docutils/rst.nim697
-rw-r--r--lib/packages/docutils/rstast.nim2
-rw-r--r--lib/packages/docutils/rstgen.nim213
-rw-r--r--lib/packages/docutils/rstidx.nim141
-rw-r--r--lib/posix/epoll.nim2
-rw-r--r--lib/posix/inotify.nim37
-rw-r--r--lib/posix/kqueue.nim2
-rw-r--r--lib/posix/linux.nim2
-rw-r--r--lib/posix/posix.nim44
-rw-r--r--lib/posix/posix_linux_amd64.nim10
-rw-r--r--lib/posix/posix_linux_amd64_consts.nim2
-rw-r--r--lib/posix/posix_macos_amd64.nim18
-rw-r--r--lib/posix/posix_openbsd_amd64.nim18
-rw-r--r--lib/posix/posix_other.nim13
-rw-r--r--lib/posix/posix_other_consts.nim15
-rw-r--r--lib/posix/posix_utils.nim28
-rw-r--r--lib/posix/termios.nim2
-rw-r--r--lib/pure/algorithm.nim2
-rw-r--r--lib/pure/async.nim4
-rw-r--r--lib/pure/asyncdispatch.nim73
-rw-r--r--lib/pure/asyncfile.nim51
-rw-r--r--lib/pure/asyncfutures.nim46
-rw-r--r--lib/pure/asynchttpserver.nim37
-rw-r--r--lib/pure/asyncmacro.nim90
-rw-r--r--lib/pure/asyncnet.nim22
-rw-r--r--lib/pure/asyncstreams.nim4
-rw-r--r--lib/pure/base64.nim18
-rw-r--r--lib/pure/bitops.nim16
-rw-r--r--lib/pure/browsers.nim56
-rw-r--r--lib/pure/cgi.nim2
-rw-r--r--lib/pure/collections/deques.nim126
-rw-r--r--lib/pure/collections/hashcommon.nim15
-rw-r--r--lib/pure/collections/heapqueue.nim17
-rw-r--r--lib/pure/collections/lists.nim83
-rw-r--r--lib/pure/collections/sequtils.nim40
-rw-r--r--lib/pure/collections/setimpl.nim5
-rw-r--r--lib/pure/collections/sets.nim38
-rw-r--r--lib/pure/collections/sharedlist.nim2
-rw-r--r--lib/pure/collections/sharedtables.nim6
-rw-r--r--lib/pure/collections/tableimpl.nim49
-rw-r--r--lib/pure/collections/tables.nim150
-rw-r--r--lib/pure/colors.nim11
-rw-r--r--lib/pure/complex.nim89
-rw-r--r--lib/pure/concurrency/atomics.nim68
-rw-r--r--lib/pure/concurrency/cpuinfo.nim141
-rw-r--r--lib/pure/concurrency/cpuload.nim6
-rw-r--r--lib/pure/concurrency/threadpool.nim6
-rw-r--r--lib/pure/cookies.nim2
-rw-r--r--lib/pure/coro.nim15
-rw-r--r--lib/pure/db_common.nim100
-rw-r--r--lib/pure/distros.nim10
-rw-r--r--lib/pure/dynlib.nim4
-rw-r--r--lib/pure/encodings.nim8
-rw-r--r--lib/pure/endians.nim2
-rw-r--r--lib/pure/fenv.nim2
-rw-r--r--lib/pure/hashes.nim281
-rw-r--r--lib/pure/htmlgen.nim7
-rw-r--r--lib/pure/htmlparser.nim20
-rw-r--r--lib/pure/httpclient.nim180
-rw-r--r--lib/pure/httpcore.nim29
-rw-r--r--lib/pure/includes/unicode_ranges.nim3913
-rw-r--r--lib/pure/ioselects/ioselectors_epoll.nim11
-rw-r--r--lib/pure/ioselects/ioselectors_kqueue.nim10
-rw-r--r--lib/pure/ioselects/ioselectors_poll.nim2
-rw-r--r--lib/pure/ioselects/ioselectors_select.nim8
-rw-r--r--lib/pure/json.nim642
-rw-r--r--lib/pure/lexbase.nim10
-rw-r--r--lib/pure/logging.nim72
-rw-r--r--lib/pure/marshal.nim9
-rw-r--r--lib/pure/math.nim254
-rw-r--r--lib/pure/md5.nim25
-rw-r--r--lib/pure/memfiles.nim193
-rw-r--r--lib/pure/mimetypes.nim2576
-rw-r--r--lib/pure/nativesockets.nim64
-rw-r--r--lib/pure/net.nim80
-rw-r--r--lib/pure/nimprof.nim7
-rw-r--r--lib/pure/nimtracker.nim88
-rw-r--r--lib/pure/oids.nim6
-rw-r--r--lib/pure/options.nim23
-rw-r--r--lib/pure/os.nim160
-rw-r--r--lib/pure/osproc.nim296
-rw-r--r--lib/pure/parsecfg.nim11
-rw-r--r--lib/pure/parsecsv.nim10
-rw-r--r--lib/pure/parsejson.nim2
-rw-r--r--lib/pure/parseopt.nim130
-rw-r--r--lib/pure/parsesql.nim15
-rw-r--r--lib/pure/parseutils.nim124
-rw-r--r--lib/pure/parsexml.nim172
-rw-r--r--lib/pure/pegs.nim177
-rw-r--r--lib/pure/punycode.nim209
-rw-r--r--lib/pure/random.nim69
-rw-r--r--lib/pure/rationals.nim34
-rw-r--r--lib/pure/reservedmem.nim4
-rw-r--r--lib/pure/ropes.nim2
-rw-r--r--lib/pure/segfaults.nim4
-rw-r--r--lib/pure/selectors.nim41
-rw-r--r--lib/pure/smtp.nim.cfg1
-rw-r--r--lib/pure/ssl_certs.nim4
-rw-r--r--lib/pure/stats.nim2
-rw-r--r--lib/pure/streams.nim109
-rw-r--r--lib/pure/streamwrapper.nim6
-rw-r--r--lib/pure/strformat.nim188
-rw-r--r--lib/pure/strmisc.nim15
-rw-r--r--lib/pure/strscans.nim40
-rw-r--r--lib/pure/strtabs.nim7
-rw-r--r--lib/pure/strutils.nim361
-rw-r--r--lib/pure/sugar.nim9
-rw-r--r--lib/pure/terminal.nim113
-rw-r--r--lib/pure/times.nim243
-rw-r--r--lib/pure/typetraits.nim55
-rw-r--r--lib/pure/unicode.nim23
-rw-r--r--lib/pure/unittest.nim111
-rw-r--r--lib/pure/uri.nim2
-rw-r--r--lib/pure/volatile.nim12
-rw-r--r--lib/pure/xmlparser.nim4
-rw-r--r--lib/pure/xmltree.nim233
-rw-r--r--lib/std/appdirs.nim19
-rw-r--r--lib/std/assertions.nim20
-rw-r--r--lib/std/cmdline.nim28
-rw-r--r--lib/std/decls.nim2
-rw-r--r--lib/std/dirs.nim4
-rw-r--r--lib/std/editdistance.nim4
-rw-r--r--lib/std/effecttraits.nim2
-rw-r--r--lib/std/enumerate.nim4
-rw-r--r--lib/std/enumutils.nim40
-rw-r--r--lib/std/envvars.nim45
-rw-r--r--lib/std/exitprocs.nim34
-rw-r--r--lib/std/files.nim7
-rw-r--r--lib/std/formatfloat.nim43
-rw-r--r--lib/std/genasts.nim4
-rw-r--r--lib/std/isolation.nim6
-rw-r--r--lib/std/jsbigints.nim14
-rw-r--r--lib/std/jsonutils.nim65
-rw-r--r--lib/std/monotimes.nim4
-rw-r--r--lib/std/oserrors.nim17
-rw-r--r--lib/std/outparams.nim2
-rw-r--r--lib/std/packedsets.nim33
-rw-r--r--lib/std/paths.nim15
-rw-r--r--lib/std/private/dbutils.nim15
-rw-r--r--lib/std/private/digitsutils.nim11
-rw-r--r--lib/std/private/dragonbox.nim14
-rw-r--r--lib/std/private/gitutils.nim13
-rw-r--r--lib/std/private/globs.nim8
-rw-r--r--lib/std/private/jsutils.nim23
-rw-r--r--lib/std/private/miscdollars.nim16
-rw-r--r--lib/std/private/osappdirs.nim29
-rw-r--r--lib/std/private/oscommon.nim79
-rw-r--r--lib/std/private/osdirs.nim44
-rw-r--r--lib/std/private/osfiles.nim95
-rw-r--r--lib/std/private/ospaths2.nim82
-rw-r--r--lib/std/private/osseps.nim2
-rw-r--r--lib/std/private/ossymlinks.nim37
-rw-r--r--lib/std/private/schubfach.nim12
-rw-r--r--lib/std/private/since.nim10
-rw-r--r--lib/std/private/strimpl.nim4
-rw-r--r--lib/std/private/syslocks.nim28
-rw-r--r--lib/std/private/underscored_calls.nim22
-rw-r--r--lib/std/private/win_setenv.nim26
-rw-r--r--lib/std/setutils.nim2
-rw-r--r--lib/std/sha1.nim9
-rw-r--r--lib/std/socketstreams.nim63
-rw-r--r--lib/std/staticos.nim13
-rw-r--r--lib/std/strbasics.nim4
-rw-r--r--lib/std/symlinks.nim7
-rw-r--r--lib/std/syncio.nim51
-rw-r--r--lib/std/sysatomics.nim6
-rw-r--r--lib/std/sysrand.nim13
-rw-r--r--lib/std/tasks.nim111
-rw-r--r--lib/std/tempfiles.nim6
-rw-r--r--lib/std/time_t.nim4
-rw-r--r--lib/std/typedthreads.nim105
-rw-r--r--lib/std/varints.nim12
-rw-r--r--lib/std/widestrs.nim22
-rw-r--r--lib/std/with.nim11
-rw-r--r--lib/std/wordwrap.nim2
-rw-r--r--lib/std/wrapnils.nim4
-rw-r--r--lib/system.nim639
-rw-r--r--lib/system/alloc.nim347
-rw-r--r--lib/system/ansi_c.nim9
-rw-r--r--lib/system/arc.nim94
-rw-r--r--lib/system/arithm.nim425
-rw-r--r--lib/system/arithmetics.nim106
-rw-r--r--lib/system/assign.nim36
-rw-r--r--lib/system/cellseqs_v1.nim19
-rw-r--r--lib/system/cellseqs_v2.nim23
-rw-r--r--lib/system/cellsets.nim4
-rw-r--r--lib/system/cgprocs.nim10
-rw-r--r--lib/system/channels_builtin.nim20
-rw-r--r--lib/system/chcks.nim4
-rw-r--r--lib/system/comparisons.nim4
-rw-r--r--lib/system/compilation.nim69
-rw-r--r--lib/system/ctypes.nim14
-rw-r--r--lib/system/deepcopy.nim16
-rw-r--r--lib/system/dollars.nim27
-rw-r--r--lib/system/dyncalls.nim2
-rw-r--r--lib/system/embedded.nim5
-rw-r--r--lib/system/excpt.nim91
-rw-r--r--lib/system/fatal.nim21
-rw-r--r--lib/system/gc.nim32
-rw-r--r--lib/system/gc2.nim749
-rw-r--r--lib/system/gc_common.nim25
-rw-r--r--lib/system/gc_ms.nim20
-rw-r--r--lib/system/hti.nim2
-rw-r--r--lib/system/inclrtl.nim3
-rw-r--r--lib/system/indices.nim18
-rw-r--r--lib/system/iterators.nim64
-rw-r--r--lib/system/iterators_1.nim17
-rw-r--r--lib/system/jssys.nim247
-rw-r--r--lib/system/memory.nim1
-rw-r--r--lib/system/mm/go.nim2
-rw-r--r--lib/system/mm/malloc.nim4
-rw-r--r--lib/system/nimscript.nim59
-rw-r--r--lib/system/orc.nim92
-rw-r--r--lib/system/osalloc.nim10
-rw-r--r--lib/system/rawquits.nim27
-rw-r--r--lib/system/repr.nim12
-rw-r--r--lib/system/repr_v2.nim47
-rw-r--r--lib/system/reprjs.nim12
-rw-r--r--lib/system/seqs_v2.nim138
-rw-r--r--lib/system/setops.nim4
-rw-r--r--lib/system/sets.nim12
-rw-r--r--lib/system/strmantle.nim21
-rw-r--r--lib/system/strs_v2.nim121
-rw-r--r--lib/system/sysstr.nim75
-rw-r--r--lib/system/threadimpl.nim5
-rw-r--r--lib/system_overview.rst1
-rw-r--r--lib/windows/winlean.nim286
-rw-r--r--lib/wrappers/mysql.nim1115
-rw-r--r--lib/wrappers/odbcsql.nim844
-rw-r--r--lib/wrappers/openssl.nim36
-rw-r--r--lib/wrappers/postgres.nim378
-rw-r--r--lib/wrappers/sqlite3.nim392
261 files changed, 10104 insertions, 15393 deletions
diff --git a/lib/core/hotcodereloading.nim b/lib/core/hotcodereloading.nim
index 73f38402d..3a876885c 100644
--- a/lib/core/hotcodereloading.nim
+++ b/lib/core/hotcodereloading.nim
@@ -11,7 +11,7 @@
 
 when defined(hotcodereloading):
   import
-    macros
+    std/macros
 
   template beforeCodeReload*(body: untyped) =
     hcrAddEventHandler(true, proc = body) {.executeOnReload.}
diff --git a/lib/core/locks.nim b/lib/core/locks.nim
index ad0bff44d..523727479 100644
--- a/lib/core/locks.nim
+++ b/lib/core/locks.nim
@@ -37,7 +37,7 @@ proc initLock*(lock: var Lock) {.inline.} =
   when not defined(js):
     initSysLock(lock)
 
-proc deinitLock*(lock: var Lock) {.inline.} =
+proc deinitLock*(lock: Lock) {.inline.} =
   ## Frees the resources associated with the lock.
   deinitSys(lock)
 
@@ -60,7 +60,7 @@ proc initCond*(cond: var Cond) {.inline.} =
   ## Initializes the given condition variable.
   initSysCond(cond)
 
-proc deinitCond*(cond: var Cond) {.inline.} =
+proc deinitCond*(cond: Cond) {.inline.} =
   ## Frees the resources associated with the condition variable.
   deinitSysCond(cond)
 
diff --git a/lib/core/macrocache.nim b/lib/core/macrocache.nim
index d4b103793..39999fa11 100644
--- a/lib/core/macrocache.nim
+++ b/lib/core/macrocache.nim
@@ -127,6 +127,19 @@ proc `[]`*(s: CacheSeq; i: int): NimNode {.magic: "NcsAt".} =
       mySeq.add(newLit(42))
       assert mySeq[0].intVal == 42
 
+proc `[]`*(s: CacheSeq; i: BackwardsIndex): NimNode =
+  ## Returns the `i`th last value from `s`.
+  runnableExamples:
+    import std/macros
+
+    const mySeq = CacheSeq"backTest"
+    static:
+      mySeq &= newLit(42)
+      mySeq &= newLit(7)
+      assert mySeq[^1].intVal == 7  # Last item
+      assert mySeq[^2].intVal == 42 # Second last item
+  s[s.len - int(i)]
+
 iterator items*(s: CacheSeq): NimNode =
   ## Iterates over each item in `s`.
   runnableExamples:
@@ -181,6 +194,32 @@ proc `[]`*(t: CacheTable; key: string): NimNode {.magic: "NctGet".} =
       # get the NimNode back
       assert mcTable["toAdd"].kind == nnkStmtList
 
+proc hasKey*(t: CacheTable; key: string): bool =
+  ## Returns true if `key` is in the table `t`.
+  ##
+  ## See also:
+  ## * [contains proc][contains(CacheTable, string)] for use with the `in` operator
+  runnableExamples:
+    import std/macros
+    const mcTable = CacheTable"hasKeyEx"
+    static:
+      assert not mcTable.hasKey("foo")
+      mcTable["foo"] = newEmptyNode()
+      # Will now be true since we inserted a value
+      assert mcTable.hasKey("foo")
+  discard "Implemented in vmops"
+
+proc contains*(t: CacheTable; key: string): bool {.inline.} =
+  ## Alias of [hasKey][hasKey(CacheTable, string)] for use with the `in` operator.
+  runnableExamples:
+    import std/macros
+    const mcTable = CacheTable"containsEx"
+    static:
+      mcTable["foo"] = newEmptyNode()
+      # Will be true since we gave it a value before
+      assert "foo" in mcTable
+  t.hasKey(key)
+
 proc hasNext(t: CacheTable; iter: int): bool {.magic: "NctHasNext".}
 proc next(t: CacheTable; iter: int): (string, NimNode, int) {.magic: "NctNext".}
 
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index b26264405..7646b165c 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -23,6 +23,8 @@ when defined(nimPreviewSlimSystem):
 
 ## .. include:: ../../doc/astspec.txt
 
+## .. importdoc:: system.nim
+
 # If you look for the implementation of the magic symbol
 # ``{.magic: "Foo".}``, search for `mFoo` and `opcFoo`.
 
@@ -91,6 +93,8 @@ type
     nnkFuncDef,
     nnkTupleConstr,
     nnkError,  ## erroneous AST node
+    nnkModuleRef, nnkReplayAction, nnkNilRodNode ## internal IC nodes
+    nnkOpenSym
 
   NimNodeKinds* = set[NimNodeKind]
   NimTypeKind* = enum  # some types are no longer used, see ast.nim
@@ -143,8 +147,9 @@ type
 
 const
   nnkLiterals* = {nnkCharLit..nnkNilLit}
+  # see matching set CallNodes below
   nnkCallKinds* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
-                   nnkCallStrLit}
+                   nnkCallStrLit, nnkHiddenCallConv}
   nnkPragmaCallKinds = {nnkExprColonExpr, nnkCall, nnkCallStrLit}
 
 {.push warnings: off.}
@@ -205,7 +210,7 @@ template `or`*(x, y: NimNode): NimNode =
   ## Evaluate `x` and when it is not an empty node, return
   ## it. Otherwise evaluate to `y`. Can be used to chain several
   ## expressions to get the first expression that is not empty.
-  ##   ```
+  ##   ```nim
   ##   let node = mightBeEmpty() or mightAlsoBeEmpty() or fallbackNode
   ##   ```
 
@@ -274,7 +279,7 @@ when (NimMajor, NimMinor, NimPatch) >= (1, 3, 5) or defined(nimSymImplTransform)
     ## note that code transformations are implementation dependent and subject to change.
     ## See an example in `tests/macros/tmacros_various.nim`.
 
-proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect.}
+proc owner*(sym: NimNode): NimNode {.magic: "SymOwner", noSideEffect, deprecated.}
   ## Accepts a node of kind `nnkSym` and returns its owner's symbol.
   ## The meaning of 'owner' depends on `sym`'s `NimSymKind` and declaration
   ## context. For top level declarations this is an `nskModule` symbol,
@@ -344,8 +349,7 @@ proc getTypeImpl*(n: NimNode): NimNode {.magic: "NGetType", noSideEffect.} =
       newLit(x.getTypeImpl.repr)
     let t = """
 object
-  arr: array[0 .. 3, float32]
-"""
+  arr: array[0 .. 3, float32]"""
     doAssert(dumpTypeImpl(a) == t)
     doAssert(dumpTypeImpl(b) == t)
     doAssert(dumpTypeImpl(c) == t)
@@ -424,7 +428,12 @@ proc copyNimTree*(n: NimNode): NimNode {.magic: "NCopyNimTree", noSideEffect.} =
       let x = 12
       echo x
 
-proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign.}
+when defined(nimHasNoReturnError):
+  {.pragma: errorNoReturn, noreturn.}
+else:
+  {.pragma: errorNoReturn.}
+
+proc error*(msg: string, n: NimNode = nil) {.magic: "NError", benign, errorNoReturn.}
   ## Writes an error message at compile time. The optional `n: NimNode`
   ## parameter is used as the source for file and line number information in
   ## the compilation error message.
@@ -533,6 +542,22 @@ proc getFile(arg: NimNode): string {.magic: "NLineInfo", noSideEffect.}
 proc copyLineInfo*(arg: NimNode, info: NimNode) {.magic: "NLineInfo", noSideEffect.}
   ## Copy lineinfo from `info`.
 
+proc setLine(arg: NimNode, line: uint16) {.magic: "NLineInfo", noSideEffect.}
+proc setColumn(arg: NimNode, column: int16) {.magic: "NLineInfo", noSideEffect.}
+proc setFile(arg: NimNode, file: string) {.magic: "NLineInfo", noSideEffect.}
+
+proc setLineInfo*(arg: NimNode, file: string, line: int, column: int) =
+  ## Sets the line info on the NimNode. The file needs to exists, but can be a
+  ## relative path. If you want to attach line info to a block using `quote`
+  ## you'll need to add the line information after the quote block.
+  arg.setFile(file)
+  arg.setLine(line.uint16)
+  arg.setColumn(column.int16)
+
+proc setLineInfo*(arg: NimNode, lineInfo: LineInfo) =
+  ## See `setLineInfo proc<#setLineInfo,NimNode,string,int,int>`_
+  setLineInfo(arg, lineInfo.filename, lineInfo.line, lineInfo.column)
+
 proc lineInfoObj*(n: NimNode): LineInfo =
   ## Returns `LineInfo` of `n`, using absolute path for `filename`.
   result = LineInfo(filename: n.getFile, line: n.getLine, column: n.getColumn)
@@ -571,7 +596,7 @@ proc getAst*(macroOrTemplate: untyped): NimNode {.magic: "ExpandToAst", noSideEf
   ## Obtains the AST nodes returned from a macro or template invocation.
   ## See also `genasts.genAst`.
   ## Example:
-  ##   ```
+  ##   ```nim
   ##   macro FooMacro() =
   ##     var ast = getAst(BarTemplate())
   ##   ```
@@ -929,6 +954,8 @@ proc treeTraverse(n: NimNode; res: var string; level = 0; isLisp = false, indent
     discard # same as nil node in this representation
   of nnkCharLit .. nnkInt64Lit:
     res.add(" " & $n.intVal)
+  of nnkUIntLit .. nnkUInt64Lit:
+    res.add(" " & $cast[uint64](n.intVal))
   of nnkFloatLit .. nnkFloat64Lit:
     res.add(" " & $n.floatVal)
   of nnkStrLit .. nnkTripleStrLit, nnkCommentStmt, nnkIdent, nnkSym:
@@ -1028,7 +1055,7 @@ macro dumpTree*(s: untyped): untyped = echo s.treeRepr
   ## a certain expression/statement.
   ##
   ## For example:
-  ##   ```
+  ##   ```nim
   ##   dumpTree:
   ##     echo "Hello, World!"
   ##   ```
@@ -1052,7 +1079,7 @@ macro dumpLisp*(s: untyped): untyped = echo s.lispRepr(indented = true)
   ## a certain expression/statement.
   ##
   ## For example:
-  ##   ```
+  ##   ```nim
   ##   dumpLisp:
   ##     echo "Hello, World!"
   ##   ```
@@ -1075,7 +1102,7 @@ macro dumpAstGen*(s: untyped): untyped = echo s.astGenRepr
   ## outputs and then copying the snippets into the macro for modification.
   ##
   ## For example:
-  ##   ```
+  ##   ```nim
   ##   dumpAstGen:
   ##     echo "Hello, World!"
   ##   ```
@@ -1158,7 +1185,7 @@ proc newIdentDefs*(name, kind: NimNode;
   ## `let` or `var` blocks may have an empty `kind` node if the
   ## identifier is being assigned a value. Example:
   ##
-  ##   ```
+  ##   ```nim
   ##   var varSection = newNimNode(nnkVarSection).add(
   ##     newIdentDefs(ident("a"), ident("string")),
   ##     newIdentDefs(ident("b"), newEmptyNode(), newLit(3)))
@@ -1169,7 +1196,7 @@ proc newIdentDefs*(name, kind: NimNode;
   ##
   ## If you need to create multiple identifiers you need to use the lower level
   ## `newNimNode`:
-  ##   ```
+  ##   ```nim
   ##   result = newNimNode(nnkIdentDefs).add(
   ##     ident("a"), ident("b"), ident("c"), ident("string"),
   ##       newStrLitNode("Hello"))
@@ -1188,8 +1215,8 @@ const
   RoutineNodes* = {nnkProcDef, nnkFuncDef, nnkMethodDef, nnkDo, nnkLambda,
                    nnkIteratorDef, nnkTemplateDef, nnkConverterDef, nnkMacroDef}
   AtomicNodes* = {nnkNone..nnkNilLit}
-  CallNodes* = {nnkCall, nnkInfix, nnkPrefix, nnkPostfix, nnkCommand,
-    nnkCallStrLit, nnkHiddenCallConv}
+  # see matching set nnkCallKinds above
+  CallNodes* = nnkCallKinds
 
 proc expectKind*(n: NimNode; k: set[NimNodeKind]) =
   ## Checks that `n` is of kind `k`. If this is not the case,
@@ -1220,7 +1247,7 @@ proc newProc*(name = newEmptyNode();
 
 proc newIfStmt*(branches: varargs[tuple[cond, body: NimNode]]): NimNode =
   ## Constructor for `if` statements.
-  ##   ```
+  ##   ```nim
   ##   newIfStmt(
   ##     (Ident, StmtList),
   ##     ...
@@ -1237,7 +1264,7 @@ proc newEnum*(name: NimNode, fields: openArray[NimNode],
 
   ## Creates a new enum. `name` must be an ident. Fields are allowed to be
   ## either idents or EnumFieldDef:
-  ##   ```
+  ##   ```nim
   ##   newEnum(
   ##     name    = ident("Colors"),
   ##     fields  = [ident("Blue"), ident("Red")],
@@ -1382,7 +1409,7 @@ proc `$`*(node: NimNode): string =
     result = node.basename.strVal & "*"
   of nnkStrLit..nnkTripleStrLit, nnkCommentStmt, nnkSym, nnkIdent:
     result = node.strVal
-  of nnkOpenSymChoice, nnkClosedSymChoice:
+  of nnkOpenSymChoice, nnkClosedSymChoice, nnkOpenSym:
     result = $node[0]
   of nnkAccQuoted:
     result = ""
@@ -1408,7 +1435,7 @@ iterator children*(n: NimNode): NimNode {.inline.} =
 
 template findChild*(n: NimNode; cond: untyped): NimNode {.dirty.} =
   ## Find the first child node matching condition (or nil).
-  ##   ```
+  ##   ```nim
   ##   var res = findChild(n, it.kind == nnkPostfix and
   ##                          it.basename.ident == ident"foo")
   ##   ```
@@ -1503,11 +1530,10 @@ proc boolVal*(n: NimNode): bool {.noSideEffect.} =
   if n.kind == nnkIntLit: n.intVal != 0
   else: n == bindSym"true" # hacky solution for now
 
-when defined(nimMacrosGetNodeId):
-  proc nodeID*(n: NimNode): int {.magic: "NodeId".}
-    ## Returns the id of `n`, when the compiler has been compiled
-    ## with the flag `-d:useNodeids`, otherwise returns `-1`. This
-    ## proc is for the purpose to debug the compiler only.
+proc nodeID*(n: NimNode): int {.magic: "NodeId".}
+  ## Returns the id of `n`, when the compiler has been compiled
+  ## with the flag `-d:useNodeids`, otherwise returns `-1`. This
+  ## proc is for the purpose to debug the compiler only.
 
 macro expandMacros*(body: typed): untyped =
   ## Expands one level of macro - useful for debugging.
@@ -1516,7 +1542,7 @@ macro expandMacros*(body: typed): untyped =
   ##
   ## For instance,
   ##
-  ##   ```
+  ##   ```nim
   ##   import std/[sugar, macros]
   ##
   ##   let
@@ -1574,7 +1600,7 @@ proc customPragmaNode(n: NimNode): NimNode =
     elif impl.kind in {nnkIdentDefs, nnkConstDef} and impl[0].kind == nnkPragmaExpr:
       return impl[0][1]
     else:
-      let timpl = typ.getImpl()
+      let timpl = getImpl(if typ.kind == nnkBracketExpr: typ[0] else: typ)
       if timpl.len>0 and timpl[0].len>1:
         return timpl[0][1]
       else:
@@ -1582,11 +1608,9 @@ proc customPragmaNode(n: NimNode): NimNode =
 
   if n.kind in {nnkDotExpr, nnkCheckedFieldExpr}:
     let name = $(if n.kind == nnkCheckedFieldExpr: n[0][1] else: n[1])
-    let typInst = getTypeInst(if n.kind == nnkCheckedFieldExpr or n[0].kind == nnkHiddenDeref: n[0][0] else: n[0])
-    var typDef = getImpl(
-      if typInst.kind in {nnkVarTy, nnkBracketExpr}: typInst[0]
-      else: typInst
-    )
+    var typInst = getTypeInst(if n.kind == nnkCheckedFieldExpr or n[0].kind == nnkHiddenDeref: n[0][0] else: n[0])
+    while typInst.kind in {nnkVarTy, nnkBracketExpr}: typInst = typInst[0]
+    var typDef = getImpl(typInst)
     while typDef != nil:
       typDef.expectKind(nnkTypeDef)
       let typ = typDef[2].extractTypeImpl()
@@ -1634,7 +1658,7 @@ macro hasCustomPragma*(n: typed, cp: typed{nkSym}): untyped =
   ##
   ## See also `getCustomPragmaVal`_.
   ##
-  ##   ```
+  ##   ```nim
   ##   template myAttr() {.pragma.}
   ##   type
   ##     MyObj = object
@@ -1659,7 +1683,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped =
   ##
   ## See also `hasCustomPragma`_.
   ##
-  ##   ```
+  ##   ```nim
   ##   template serializationKey(key: string) {.pragma.}
   ##   type
   ##     MyObj {.serializationKey: "mo".} = object
@@ -1755,7 +1779,7 @@ proc extractDocCommentsAndRunnables*(n: NimNode): NimNode =
   ## runnableExamples in `a`, stopping at the first child that is neither.
   ## Example:
   ##
-  ##   ```
+  ##   ```nim
   ##   import std/macros
   ##   macro transf(a): untyped =
   ##     result = quote do:
diff --git a/lib/core/rlocks.nim b/lib/core/rlocks.nim
index bee5c1655..8cb0cef05 100644
--- a/lib/core/rlocks.nim
+++ b/lib/core/rlocks.nim
@@ -31,7 +31,7 @@ proc initRLock*(lock: var RLock) {.inline.} =
   else:
     initSysLock(lock)
 
-proc deinitRLock*(lock: var RLock) {.inline.} =
+proc deinitRLock*(lock: RLock) {.inline.} =
   ## Frees the resources associated with the lock.
   deinitSys(lock)
 
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim
index 89b1deb31..f2fee91c4 100644
--- a/lib/core/typeinfo.nim
+++ b/lib/core/typeinfo.nim
@@ -129,15 +129,17 @@ when not defined(gcDestructors):
 else:
   proc nimNewObj(size, align: int): pointer {.importCompilerProc.}
   proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.importCompilerProc.}
-  proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
+  proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
+    importCompilerProc.}
+  proc zeroNewElements(len: int; p: pointer; addlen, elemSize, elemAlign: int) {.
     importCompilerProc.}
 
-template `+!!`(a, b): untyped = cast[pointer](cast[ByteAddress](a) + b)
+template `+!!`(a, b): untyped = cast[pointer](cast[int](a) + b)
 
 proc getDiscriminant(aa: pointer, n: ptr TNimNode): int =
   assert(n.kind == nkCase)
   var d: int
-  let a = cast[ByteAddress](aa)
+  let a = cast[int](aa)
   case n.typ.size
   of 1: d = int(cast[ptr uint8](a +% n.offset)[])
   of 2: d = int(cast[ptr uint16](a +% n.offset)[])
@@ -159,16 +161,6 @@ proc newAny(value: pointer, rawType: PNimType): Any {.inline.} =
   result.value = value
   result.rawType = rawType
 
-when declared(system.VarSlot):
-  proc toAny*(x: VarSlot): Any {.inline.} =
-    ## Constructs an `Any` object from a variable slot `x`.
-    ## This captures `x`'s address, so `x` can be modified with its
-    ## `Any` wrapper! The caller needs to ensure that the wrapper
-    ## **does not** live longer than `x`!
-    ## This is provided for easier reflection capabilities of a debugger.
-    result.value = x.address
-    result.rawType = x.typ
-
 proc toAny*[T](x: var T): Any {.inline.} =
   ## Constructs an `Any` object from `x`. This captures `x`'s address, so
   ## `x` can be modified with its `Any` wrapper! The caller needs to ensure
@@ -221,7 +213,8 @@ proc extendSeq*(x: Any) =
     var s = cast[ptr NimSeqV2Reimpl](x.value)
     let elem = x.rawType.base
     if s.p == nil or s.p.cap < s.len+1:
-      s.p = cast[ptr NimSeqPayloadReimpl](prepareSeqAdd(s.len, s.p, 1, elem.size, elem.align))
+      s.p = cast[ptr NimSeqPayloadReimpl](prepareSeqAddUninit(s.len, s.p, 1, elem.size, elem.align))
+    zeroNewElements(s.len, s.p, 1, elem.size, elem.align)
     inc s.len
   else:
     var y = cast[ptr PGenSeq](x.value)[]
diff --git a/lib/deprecated/pure/future.nim b/lib/deprecated/pure/future.nim
index 3f7b63a30..0e06161f2 100644
--- a/lib/deprecated/pure/future.nim
+++ b/lib/deprecated/pure/future.nim
@@ -2,5 +2,5 @@
 
 {.deprecated: "Use the new 'sugar' module instead".}
 
-import sugar
+import std/sugar
 export sugar
diff --git a/lib/deprecated/pure/ospaths.nim b/lib/deprecated/pure/ospaths.nim
index b57839d1a..43fcb17cc 100644
--- a/lib/deprecated/pure/ospaths.nim
+++ b/lib/deprecated/pure/ospaths.nim
@@ -11,7 +11,7 @@
 
 {.deprecated: "use `std/os` instead".}
 
-import os
+import std/os
 export ReadEnvEffect, WriteEnvEffect, ReadDirEffect, WriteDirEffect, OSErrorCode,
   doslikeFileSystem, CurDir, ParDir, DirSep, AltSep, PathSep, FileSystemCaseSensitive,
   ExeExt, ScriptExt, DynlibFormat, ExtSep, joinPath, `/`, splitPath, parentDir,
diff --git a/lib/deprecated/pure/oswalkdir.nim b/lib/deprecated/pure/oswalkdir.nim
index 866f9ed70..57a2cb81d 100644
--- a/lib/deprecated/pure/oswalkdir.nim
+++ b/lib/deprecated/pure/oswalkdir.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-## This module is deprecated, `import os` instead.
-{.deprecated: "import os.nim instead".}
-import os
+## This module is deprecated, `import std/os` instead.
+{.deprecated: "import 'std/os' instead".}
+import std/os
 export PathComponent, walkDir, walkDirRec
diff --git a/lib/deprecated/pure/securehash.nim b/lib/deprecated/pure/securehash.nim
deleted file mode 100644
index b4749ad75..000000000
--- a/lib/deprecated/pure/securehash.nim
+++ /dev/null
@@ -1,6 +0,0 @@
-## This module is a deprecated alias for the `sha1` module. Deprecated since 0.18.1.
-
-{.deprecated: "use `std/sha1` instead".}
-
-import "../std/sha1"
-export sha1
diff --git a/lib/experimental/diff.nim b/lib/experimental/diff.nim
index 4ca5eb319..669e9f613 100644
--- a/lib/experimental/diff.nim
+++ b/lib/experimental/diff.nim
@@ -43,7 +43,7 @@ jkl"""
 # "An O(ND) Difference Algorithm and its Variations" by Eugene Myers
 # Algorithmica Vol. 1 No. 2, 1986, p 251.
 
-import tables, strutils
+import std/[tables, strutils]
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
deleted file mode 100644
index 279aebda5..000000000
--- a/lib/impure/db_mysql.nim
+++ /dev/null
@@ -1,418 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## A higher level `mySQL`:idx: database wrapper. The same interface is
-## implemented for other databases too.
-##
-## See also: `db_odbc <db_odbc.html>`_, `db_sqlite <db_sqlite.html>`_,
-## `db_postgres <db_postgres.html>`_.
-##
-## Parameter substitution
-## ======================
-##
-## All `db_*` modules support the same form of parameter substitution.
-## That is, using the `?` (question mark) to signify the place where a
-## value should be placed. For example:
-##   ```
-##   sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)"
-##   ```
-##
-## Examples
-## ========
-##
-## Opening a connection to a database
-## ----------------------------------
-##
-##   ```
-##   import std/db_mysql
-##   let db = open("localhost", "user", "password", "dbname")
-##   db.close()
-##   ```
-##
-## Creating a table
-## ----------------
-##
-##   ```
-##   db.exec(sql"DROP TABLE IF EXISTS myTable")
-##   db.exec(sql("""CREATE TABLE myTable (
-##                    id integer,
-##                    name varchar(50) not null)"""))
-##   ```
-##
-## Inserting data
-## --------------
-##
-##   ```
-##   db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
-##           "Dominik")
-##   ```
-##
-## Larger example
-## --------------
-##
-##   ```
-##   import std/[db_mysql, math]
-##
-##   let theDb = open("localhost", "nim", "nim", "test")
-##
-##   theDb.exec(sql"Drop table if exists myTestTbl")
-##   theDb.exec(sql("create table myTestTbl (" &
-##       " Id    INT(11)     NOT NULL AUTO_INCREMENT PRIMARY KEY, " &
-##       " Name  VARCHAR(50) NOT NULL, " &
-##       " i     INT(11), " &
-##       " f     DECIMAL(18,10))"))
-##
-##   theDb.exec(sql"START TRANSACTION")
-##   for i in 1..1000:
-##     theDb.exec(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
-##           "Item#" & $i, i, sqrt(i.float))
-##   theDb.exec(sql"COMMIT")
-##
-##   for x in theDb.fastRows(sql"select * from myTestTbl"):
-##     echo x
-##
-##   let id = theDb.tryInsertId(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
-##           "Item#1001", 1001, sqrt(1001.0))
-##   echo "Inserted item: ", theDb.getValue(sql"SELECT name FROM myTestTbl WHERE id=?", id)
-##
-##   theDb.close()
-##   ```
-
-
-import strutils, mysql
-
-import db_common
-export db_common
-
-import std/private/[since, dbutils]
-
-type
-  DbConn* = distinct PMySQL ## encapsulates a database connection
-  Row* = seq[string]   ## a row of a dataset. NULL database values will be
-                       ## converted to nil.
-  InstantRow* = object ## a handle that can be used to get a row's
-                       ## column text on demand
-    row: cstringArray
-    len: int
-
-proc dbError*(db: DbConn) {.noreturn.} =
-  ## raises a DbError exception.
-  var e: ref DbError
-  new(e)
-  e.msg = $mysql.error(PMySQL db)
-  raise e
-
-when false:
-  proc dbQueryOpt*(db: DbConn, query: string, args: varargs[string, `$`]) =
-    var stmt = mysql_stmt_init(db)
-    if stmt == nil: dbError(db)
-    if mysql_stmt_prepare(stmt, query, len(query)) != 0:
-      dbError(db)
-    var
-      binding: seq[MYSQL_BIND]
-    discard mysql_stmt_close(stmt)
-
-proc dbQuote*(s: string): string =
-  ## DB quotes the string. Note that this doesn't escape `%` and `_`.
-  result = newStringOfCap(s.len + 2)
-  result.add "'"
-  for c in items(s):
-    # see https://cheatsheetseries.owasp.org/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.html#mysql-escaping
-    case c
-    of '\0': result.add "\\0"
-    of '\b': result.add "\\b"
-    of '\t': result.add "\\t"
-    of '\l': result.add "\\n"
-    of '\r': result.add "\\r"
-    of '\x1a': result.add "\\Z"
-    of '"': result.add "\\\""
-    of '\'': result.add "\\'"
-    of '\\': result.add "\\\\"
-    else: result.add c
-  add(result, '\'')
-
-proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
-  dbFormatImpl(formatstr, dbQuote, args)
-
-proc tryExec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {.
-  tags: [ReadDbEffect, WriteDbEffect].} =
-  ## tries to execute the query and returns true if successful, false otherwise.
-  var q = dbFormat(query, args)
-  return mysql.real_query(PMySQL db, q.cstring, q.len) == 0'i32
-
-proc rawExec(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) =
-  var q = dbFormat(query, args)
-  if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32: dbError(db)
-
-proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
-  tags: [ReadDbEffect, WriteDbEffect].} =
-  ## executes the query and raises EDB if not successful.
-  var q = dbFormat(query, args)
-  if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32: dbError(db)
-
-proc newRow(L: int): Row =
-  newSeq(result, L)
-  for i in 0..L-1: result[i] = ""
-
-proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) =
-  if row != nil:
-    while mysql.fetch_row(sqlres) != nil: discard
-  mysql.freeResult(sqlres)
-
-iterator fastRows*(db: DbConn, query: SqlQuery,
-                   args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## executes the query and iterates over the result dataset.
-  ##
-  ## This is very fast, but potentially dangerous.  Use this iterator only
-  ## if you require **ALL** the rows.
-  ##
-  ## Breaking the fastRows() iterator during a loop will cause the next
-  ## database query to raise an `EDb` exception `Commands out of sync`.
-  rawExec(db, query, args)
-  var sqlres = mysql.useResult(PMySQL db)
-  if sqlres != nil:
-    var
-      L = int(mysql.numFields(sqlres))
-      row: cstringArray
-      result: Row
-      backup: Row
-    newSeq(result, L)
-    while true:
-      row = mysql.fetch_row(sqlres)
-      if row == nil: break
-      for i in 0..L-1:
-        setLen(result[i], 0)
-        result[i].add row[i]
-      yield result
-    properFreeResult(sqlres, row)
-
-iterator instantRows*(db: DbConn, query: SqlQuery,
-                      args: varargs[string, `$`]): InstantRow
-                      {.tags: [ReadDbEffect].} =
-  ## Same as fastRows but returns a handle that can be used to get column text
-  ## on demand using `[]`. Returned handle is valid only within the iterator body.
-  rawExec(db, query, args)
-  var sqlres = mysql.useResult(PMySQL db)
-  if sqlres != nil:
-    let L = int(mysql.numFields(sqlres))
-    var row: cstringArray
-    while true:
-      row = mysql.fetch_row(sqlres)
-      if row == nil: break
-      yield InstantRow(row: row, len: L)
-    properFreeResult(sqlres, row)
-
-proc setTypeName(t: var DbType; f: PFIELD) =
-  t.name = $f.name
-  t.maxReprLen = Natural(f.max_length)
-  if (NOT_NULL_FLAG and f.flags) != 0: t.notNull = true
-  case f.ftype
-  of TYPE_DECIMAL:
-    t.kind = dbDecimal
-  of TYPE_TINY:
-    t.kind = dbInt
-    t.size = 1
-  of TYPE_SHORT:
-    t.kind = dbInt
-    t.size = 2
-  of TYPE_LONG:
-    t.kind = dbInt
-    t.size = 4
-  of TYPE_FLOAT:
-    t.kind = dbFloat
-    t.size = 4
-  of TYPE_DOUBLE:
-    t.kind = dbFloat
-    t.size = 8
-  of TYPE_NULL:
-    t.kind = dbNull
-  of TYPE_TIMESTAMP:
-    t.kind = dbTimestamp
-  of TYPE_LONGLONG:
-    t.kind = dbInt
-    t.size = 8
-  of TYPE_INT24:
-    t.kind = dbInt
-    t.size = 3
-  of TYPE_DATE:
-    t.kind = dbDate
-  of TYPE_TIME:
-    t.kind = dbTime
-  of TYPE_DATETIME:
-    t.kind = dbDatetime
-  of TYPE_YEAR:
-    t.kind = dbDate
-  of TYPE_NEWDATE:
-    t.kind = dbDate
-  of TYPE_VARCHAR, TYPE_VAR_STRING, TYPE_STRING:
-    t.kind = dbVarchar
-  of TYPE_BIT:
-    t.kind = dbBit
-  of TYPE_NEWDECIMAL:
-    t.kind = dbDecimal
-  of TYPE_ENUM: t.kind = dbEnum
-  of TYPE_SET: t.kind = dbSet
-  of TYPE_TINY_BLOB, TYPE_MEDIUM_BLOB, TYPE_LONG_BLOB,
-     TYPE_BLOB: t.kind = dbBlob
-  of TYPE_GEOMETRY:
-    t.kind = dbGeometry
-
-proc setColumnInfo(columns: var DbColumns; res: PRES; L: int) =
-  setLen(columns, L)
-  for i in 0..<L:
-    let fp = mysql.fetch_field_direct(res, cint(i))
-    setTypeName(columns[i].typ, fp)
-    columns[i].name = $fp.name
-    columns[i].tableName = $fp.table
-    columns[i].primaryKey = (fp.flags and PRI_KEY_FLAG) != 0
-    #columns[i].foreignKey = there is no such thing in mysql
-
-iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery;
-                      args: varargs[string, `$`]): InstantRow =
-  ## Same as fastRows but returns a handle that can be used to get column text
-  ## on demand using `[]`. Returned handle is valid only within the iterator body.
-  rawExec(db, query, args)
-  var sqlres = mysql.useResult(PMySQL db)
-  if sqlres != nil:
-    let L = int(mysql.numFields(sqlres))
-    setColumnInfo(columns, sqlres, L)
-    var row: cstringArray
-    while true:
-      row = mysql.fetch_row(sqlres)
-      if row == nil: break
-      yield InstantRow(row: row, len: L)
-    properFreeResult(sqlres, row)
-
-
-proc `[]`*(row: InstantRow, col: int): string {.inline.} =
-  ## Returns text for given column of the row.
-  $row.row[col]
-
-proc unsafeColumnAt*(row: InstantRow, index: int): cstring {.inline.} =
-  ## Return cstring of given column of the row
-  row.row[index]
-
-proc len*(row: InstantRow): int {.inline.} =
-  ## Returns number of columns in the row.
-  row.len
-
-proc getRow*(db: DbConn, query: SqlQuery,
-             args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## Retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a Row with empty strings for each column.
-  rawExec(db, query, args)
-  var sqlres = mysql.useResult(PMySQL db)
-  if sqlres != nil:
-    var L = int(mysql.numFields(sqlres))
-    result = newRow(L)
-    var row = mysql.fetch_row(sqlres)
-    if row != nil:
-      for i in 0..L-1:
-        setLen(result[i], 0)
-        add(result[i], row[i])
-    properFreeResult(sqlres, row)
-
-proc getAllRows*(db: DbConn, query: SqlQuery,
-                 args: varargs[string, `$`]): seq[Row] {.tags: [ReadDbEffect].} =
-  ## executes the query and returns the whole result dataset.
-  result = @[]
-  rawExec(db, query, args)
-  var sqlres = mysql.useResult(PMySQL db)
-  if sqlres != nil:
-    var L = int(mysql.numFields(sqlres))
-    var row: cstringArray
-    var j = 0
-    while true:
-      row = mysql.fetch_row(sqlres)
-      if row == nil: break
-      setLen(result, j+1)
-      newSeq(result[j], L)
-      for i in 0..L-1:
-        result[j][i] = $row[i]
-      inc(j)
-    mysql.freeResult(sqlres)
-
-iterator rows*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## same as `fastRows`, but slower and safe.
-  for r in items(getAllRows(db, query, args)): yield r
-
-proc getValue*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): string {.tags: [ReadDbEffect].} =
-  ## executes the query and returns the first column of the first row of the
-  ## result dataset. Returns "" if the dataset contains no rows or the database
-  ## value is NULL.
-  result = getRow(db, query, args)[0]
-
-proc tryInsertId*(db: DbConn, query: SqlQuery,
-                  args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect], raises: [DbError].} =
-  ## executes the query (typically "INSERT") and returns the
-  ## generated ID for the row or -1 in case of an error.
-  var q = dbFormat(query, args)
-  if mysql.real_query(PMySQL db, q.cstring, q.len) != 0'i32:
-    result = -1'i64
-  else:
-    result = mysql.insertId(PMySQL db)
-
-proc insertId*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect].} =
-  ## executes the query (typically "INSERT") and returns the
-  ## generated ID for the row.
-  result = tryInsertID(db, query, args)
-  if result < 0: dbError(db)
-
-proc tryInsert*(db: DbConn, query: SqlQuery, pkName: string,
-                args: varargs[string, `$`]): int64
-               {.tags: [WriteDbEffect], raises: [DbError], since: (1, 3).} =
-  ## same as tryInsertID
-  tryInsertID(db, query, args)
-
-proc insert*(db: DbConn, query: SqlQuery, pkName: string,
-             args: varargs[string, `$`]): int64
-            {.tags: [WriteDbEffect], since: (1, 3).} =
-  ## same as insertId
-  result = tryInsert(db, query,pkName, args)
-  if result < 0: dbError(db)
-
-proc execAffectedRows*(db: DbConn, query: SqlQuery,
-                       args: varargs[string, `$`]): int64 {.
-                       tags: [ReadDbEffect, WriteDbEffect].} =
-  ## runs the query (typically "UPDATE") and returns the
-  ## number of affected rows
-  rawExec(db, query, args)
-  result = mysql.affectedRows(PMySQL db)
-
-proc close*(db: DbConn) {.tags: [DbEffect].} =
-  ## closes the database connection.
-  if PMySQL(db) != nil: mysql.close(PMySQL db)
-
-proc open*(connection, user, password, database: string): DbConn {.
-  tags: [DbEffect].} =
-  ## opens a database connection. Raises `EDb` if the connection could not
-  ## be established.
-  var res = mysql.init(nil)
-  if res == nil: dbError("could not open database connection")
-  let
-    colonPos = connection.find(':')
-    host = if colonPos < 0: connection
-           else: substr(connection, 0, colonPos-1)
-    port: int32 = if colonPos < 0: 0'i32
-                  else: substr(connection, colonPos+1).parseInt.int32
-  if mysql.realConnect(res, host.cstring, user, password, database,
-                       port, nil, 0) == nil:
-    var errmsg = $mysql.error(res)
-    mysql.close(res)
-    dbError(errmsg)
-  result = DbConn(res)
-
-proc setEncoding*(connection: DbConn, encoding: string): bool {.
-  tags: [DbEffect].} =
-  ## sets the encoding of a database connection, returns true for
-  ## success, false for failure.
-  result = mysql.set_character_set(PMySQL connection, encoding) == 0
diff --git a/lib/impure/db_odbc.nim b/lib/impure/db_odbc.nim
deleted file mode 100644
index 62f047b49..000000000
--- a/lib/impure/db_odbc.nim
+++ /dev/null
@@ -1,529 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Nim Contributors
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## A higher level `ODBC` database wrapper.
-##
-## This is the same interface that is implemented for other databases.
-##
-## This has NOT yet been (extensively) tested against ODBC drivers for
-## Teradata, Oracle, Sybase, MSSqlvSvr, et. al.  databases.
-##
-## Currently all queries are ANSI calls, not Unicode.
-##
-## See also: `db_postgres <db_postgres.html>`_, `db_sqlite <db_sqlite.html>`_,
-## `db_mysql <db_mysql.html>`_.
-##
-## Parameter substitution
-## ======================
-##
-## All `db_*` modules support the same form of parameter substitution.
-## That is, using the `?` (question mark) to signify the place where a
-## value should be placed. For example:
-##
-##   ```Nim
-##   sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)"
-##   ```
-##
-##
-## Examples
-## ========
-##
-## Opening a connection to a database
-## ----------------------------------
-##
-##   ```Nim
-##   import std/db_odbc
-##   var db = open("localhost", "user", "password", "dbname")
-##   db.close()
-##   ```
-##
-## Creating a table
-## ----------------
-##
-##   ```Nim
-##   db.exec(sql"DROP TABLE IF EXISTS myTable")
-##   db.exec(sql("""CREATE TABLE myTable (
-##                    id integer,
-##                    name varchar(50) not null)"""))
-##   ```
-##
-## Inserting data
-## --------------
-##
-##   ```Nim
-##   db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
-##           "Andreas")
-##   ```
-##
-## Large example
-## -------------
-##
-##   ```Nim
-##   import std/[db_odbc, math]
-##
-##   var theDb = open("localhost", "nim", "nim", "test")
-##
-##   theDb.exec(sql"Drop table if exists myTestTbl")
-##   theDb.exec(sql("create table myTestTbl (" &
-##       " Id    INT(11)     NOT NULL AUTO_INCREMENT PRIMARY KEY, " &
-##       " Name  VARCHAR(50) NOT NULL, " &
-##       " i     INT(11), " &
-##       " f     DECIMAL(18,10))"))
-##
-##   theDb.exec(sql"START TRANSACTION")
-##   for i in 1..1000:
-##     theDb.exec(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
-##           "Item#" & $i, i, sqrt(i.float))
-##   theDb.exec(sql"COMMIT")
-##
-##   for x in theDb.fastRows(sql"select * from myTestTbl"):
-##     echo x
-##
-##   let id = theDb.tryInsertId(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)",
-##           "Item#1001", 1001, sqrt(1001.0))
-##   echo "Inserted item: ", theDb.getValue(sql"SELECT name FROM myTestTbl WHERE id=?", id)
-##
-##   theDb.close()
-##   ```
-
-import strutils, odbcsql
-import db_common
-export db_common
-
-import std/private/[since, dbutils]
-
-type
-  OdbcConnTyp = tuple[hDb: SqlHDBC, env: SqlHEnv, stmt: SqlHStmt]
-  DbConn* = OdbcConnTyp    ## encapsulates a database connection
-  Row* = seq[string]   ## a row of a dataset. NULL database values will be
-                       ## converted to nil.
-  InstantRow* = tuple[row: seq[string], len: int]  ## a handle that can be
-                                                    ## used to get a row's
-                                                    ## column text on demand
-
-var
-  buf: array[0..4096, char]
-
-proc properFreeResult(hType: int, sqlres: var SqlHandle) {.
-          tags: [WriteDbEffect], raises: [].} =
-  try:
-    discard SQLFreeHandle(hType.TSqlSmallInt, sqlres)
-    sqlres = nil
-  except: discard
-
-proc getErrInfo(db: var DbConn): tuple[res: int, ss, ne, msg: string] {.
-          tags: [ReadDbEffect], raises: [].} =
-  ## Returns ODBC error information
-  var
-    sqlState: array[0..512, char]
-    nativeErr: array[0..512, char]
-    errMsg: array[0..512, char]
-    retSz: TSqlSmallInt = 0
-    res: TSqlSmallInt = 0
-  try:
-    sqlState[0] = '\0'
-    nativeErr[0] = '\0'
-    errMsg[0] = '\0'
-    res = SQLErr(db.env, db.hDb, db.stmt,
-              cast[PSQLCHAR](sqlState.addr),
-              cast[PSQLCHAR](nativeErr.addr),
-              cast[PSQLCHAR](errMsg.addr),
-              511.TSqlSmallInt, retSz.addr)
-  except:
-    discard
-  return (res.int, $(cast[cstring](addr sqlState)), $cast[cstring](addr nativeErr), $cast[cstring](addr errMsg))
-
-proc dbError*(db: var DbConn) {.
-          tags: [ReadDbEffect, WriteDbEffect], raises: [DbError] .} =
-  ## Raises an `[DbError]` exception with ODBC error information
-  var
-    e: ref DbError
-    ss, ne, msg: string = ""
-    isAnError = false
-    res: int = 0
-    prevSs = ""
-  while true:
-    prevSs = ss
-    (res, ss, ne, msg) = db.getErrInfo()
-    if prevSs == ss:
-      break
-    # sqlState of 00000 is not an error
-    elif ss == "00000":
-      break
-    elif ss == "01000":
-      echo "\nWarning: ", ss, " ", msg
-      continue
-    else:
-      isAnError = true
-      echo "\nError: ", ss, " ", msg
-  if isAnError:
-    new(e)
-    e.msg = "ODBC Error"
-    if db.stmt != nil:
-      properFreeResult(SQL_HANDLE_STMT, db.stmt)
-    properFreeResult(SQL_HANDLE_DBC, db.hDb)
-    properFreeResult(SQL_HANDLE_ENV, db.env)
-    raise e
-
-proc sqlCheck(db: var DbConn, resVal: TSqlSmallInt) {.raises: [DbError]} =
-  ## Wrapper that raises `EDb` if `resVal` is neither SQL_SUCCESS or SQL_NO_DATA
-  if resVal notIn [SQL_SUCCESS, SQL_NO_DATA]: dbError(db)
-
-proc sqlGetDBMS(db: var DbConn): string {.
-        tags: [ReadDbEffect, WriteDbEffect], raises: [] .} =
-  ## Returns the ODBC SQL_DBMS_NAME string
-  const
-    SQL_DBMS_NAME = 17.SqlUSmallInt
-  var
-    sz: TSqlSmallInt = 0
-  buf[0] = '\0'
-  try:
-    db.sqlCheck(SQLGetInfo(db.hDb, SQL_DBMS_NAME, cast[SqlPointer](buf.addr),
-                        4095.TSqlSmallInt, sz.addr))
-  except: discard
-  return $(cast[cstring](addr buf))
-
-proc dbQuote*(s: string): string {.noSideEffect.} =
-  ## DB quotes the string.
-  result = "'"
-  for c in items(s):
-    if c == '\'': add(result, "''")
-    else: add(result, c)
-  add(result, '\'')
-
-proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string {.
-                  noSideEffect.} =
-  ## Replace any `?` placeholders with `args`,
-  ## and quotes the arguments
-  dbFormatImpl(formatstr, dbQuote, args)
-
-proc prepareFetch(db: var DbConn, query: SqlQuery,
-                args: varargs[string, `$`]): TSqlSmallInt {.
-                tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  # Prepare a statement, execute it and fetch the data to the driver
-  # ready for retrieval of the data
-  # Used internally by iterators and retrieval procs
-  # requires calling
-  #      properFreeResult(SQL_HANDLE_STMT, db.stmt)
-  # when finished
-  db.sqlCheck(SQLAllocHandle(SQL_HANDLE_STMT, db.hDb, db.stmt))
-  var q = dbFormat(query, args)
-  db.sqlCheck(SQLPrepare(db.stmt, q.PSQLCHAR, q.len.TSqlSmallInt))
-  db.sqlCheck(SQLExecute(db.stmt))
-  result = SQLFetch(db.stmt)
-  db.sqlCheck(result)
-
-proc prepareFetchDirect(db: var DbConn, query: SqlQuery,
-                args: varargs[string, `$`]) {.
-                tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  # Prepare a statement, execute it and fetch the data to the driver
-  # ready for retrieval of the data
-  # Used internally by iterators and retrieval procs
-  # requires calling
-  #      properFreeResult(SQL_HANDLE_STMT, db.stmt)
-  # when finished
-  db.sqlCheck(SQLAllocHandle(SQL_HANDLE_STMT, db.hDb, db.stmt))
-  var q = dbFormat(query, args)
-  db.sqlCheck(SQLExecDirect(db.stmt, q.PSQLCHAR, q.len.TSqlSmallInt))
-  db.sqlCheck(SQLFetch(db.stmt))
-
-proc tryExec*(db: var DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {.
-  tags: [ReadDbEffect, WriteDbEffect], raises: [].} =
-  ## Tries to execute the query and returns true if successful, false otherwise.
-  var
-    res:TSqlSmallInt = -1
-  try:
-    db.prepareFetchDirect(query, args)
-    var
-      rCnt:TSqlLen = -1
-    res = SQLRowCount(db.stmt, rCnt)
-    properFreeResult(SQL_HANDLE_STMT, db.stmt)
-    if res != SQL_SUCCESS: dbError(db)
-  except: discard
-  return res == SQL_SUCCESS
-
-proc rawExec(db: var DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
-            tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  db.prepareFetchDirect(query, args)
-
-proc exec*(db: var DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
-            tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Executes the query and raises EDB if not successful.
-  db.prepareFetchDirect(query, args)
-  properFreeResult(SQL_HANDLE_STMT, db.stmt)
-
-proc newRow(L: int): Row {.noSideEFfect.} =
-  newSeq(result, L)
-  for i in 0..L-1: result[i] = ""
-
-iterator fastRows*(db: var DbConn, query: SqlQuery,
-                   args: varargs[string, `$`]): Row {.
-                tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Executes the query and iterates over the result dataset.
-  ##
-  ## This is very fast, but potentially dangerous.  Use this iterator only
-  ## if you require **ALL** the rows.
-  ##
-  ## Breaking the fastRows() iterator during a loop may cause a driver error
-  ## for subsequent queries
-  ##
-  ## Rows are retrieved from the server at each iteration.
-  var
-    rowRes: Row
-    sz: TSqlLen = 0
-    cCnt: TSqlSmallInt = 0
-    res: TSqlSmallInt = 0
-  res = db.prepareFetch(query, args)
-  if res == SQL_NO_DATA:
-    discard
-  elif res == SQL_SUCCESS:
-    res = SQLNumResultCols(db.stmt, cCnt)
-    rowRes = newRow(cCnt)
-    rowRes.setLen(max(cCnt,0))
-    while res == SQL_SUCCESS:
-      for colId in 1..cCnt:
-        buf[0] = '\0'
-        db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
-                                 cast[cstring](buf.addr), 4095, sz.addr))
-        rowRes[colId-1] = $cast[cstring]((addr buf))
-      yield rowRes
-      res = SQLFetch(db.stmt)
-  properFreeResult(SQL_HANDLE_STMT, db.stmt)
-  db.sqlCheck(res)
-
-iterator instantRows*(db: var DbConn, query: SqlQuery,
-                      args: varargs[string, `$`]): InstantRow
-                {.tags: [ReadDbEffect, WriteDbEffect].} =
-  ## Same as fastRows but returns a handle that can be used to get column text
-  ## on demand using `[]`. Returned handle is valid only within the iterator body.
-  var
-    rowRes: Row = @[]
-    sz: TSqlLen = 0
-    cCnt: TSqlSmallInt = 0
-    res: TSqlSmallInt = 0
-  res = db.prepareFetch(query, args)
-  if res == SQL_NO_DATA:
-    discard
-  elif res == SQL_SUCCESS:
-    res = SQLNumResultCols(db.stmt, cCnt)
-    rowRes = newRow(cCnt)
-    rowRes.setLen(max(cCnt,0))
-    while res == SQL_SUCCESS:
-      for colId in 1..cCnt:
-        buf[0] = '\0'
-        db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
-                                 cast[cstring](buf.addr), 4095, sz.addr))
-        rowRes[colId-1] = $cast[cstring](addr buf)
-      yield (row: rowRes, len: cCnt.int)
-      res = SQLFetch(db.stmt)
-  properFreeResult(SQL_HANDLE_STMT, db.stmt)
-  db.sqlCheck(res)
-
-proc `[]`*(row: InstantRow, col: int): string {.inline.} =
-  ## Returns text for given column of the row
-  $row.row[col]
-
-proc unsafeColumnAt*(row: InstantRow, index: int): cstring {.inline.} =
-  ## Return cstring of given column of the row
-  row.row[index].cstring
-
-proc len*(row: InstantRow): int {.inline.} =
-  ## Returns number of columns in the row
-  row.len
-
-proc getRow*(db: var DbConn, query: SqlQuery,
-             args: varargs[string, `$`]): Row {.
-          tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a Row with empty strings for each column.
-  var
-    rowRes: Row
-    sz: TSqlLen = 0
-    cCnt: TSqlSmallInt = 0
-    res: TSqlSmallInt = 0
-  res = db.prepareFetch(query, args)
-  if res == SQL_NO_DATA:
-    result = @[]
-  elif res == SQL_SUCCESS:
-    res = SQLNumResultCols(db.stmt, cCnt)
-    rowRes = newRow(cCnt)
-    rowRes.setLen(max(cCnt,0))
-    for colId in 1..cCnt:
-      buf[0] = '\0'
-      db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
-                               cast[cstring](buf.addr), 4095, sz.addr))
-      rowRes[colId-1] = $cast[cstring](addr buf)
-    res = SQLFetch(db.stmt)
-    result = rowRes
-  properFreeResult(SQL_HANDLE_STMT, db.stmt)
-  db.sqlCheck(res)
-
-proc getAllRows*(db: var DbConn, query: SqlQuery,
-                 args: varargs[string, `$`]): seq[Row] {.
-           tags: [ReadDbEffect, WriteDbEffect], raises: [DbError] .} =
-  ## Executes the query and returns the whole result dataset.
-  var
-    rows: seq[Row] = @[]
-    rowRes: Row
-    sz: TSqlLen = 0
-    cCnt: TSqlSmallInt = 0
-    res: TSqlSmallInt = 0
-  res = db.prepareFetch(query, args)
-  if res == SQL_NO_DATA:
-    result = @[]
-  elif res == SQL_SUCCESS:
-    res = SQLNumResultCols(db.stmt, cCnt)
-    rowRes = newRow(cCnt)
-    rowRes.setLen(max(cCnt,0))
-    while res == SQL_SUCCESS:
-      for colId in 1..cCnt:
-        buf[0] = '\0'
-        db.sqlCheck(SQLGetData(db.stmt, colId.SqlUSmallInt, SQL_C_CHAR,
-                                 cast[cstring](buf.addr), 4095, sz.addr))
-        rowRes[colId-1] = $cast[cstring](addr buf)
-      rows.add(rowRes)
-      res = SQLFetch(db.stmt)
-    result = rows
-  properFreeResult(SQL_HANDLE_STMT, db.stmt)
-  db.sqlCheck(res)
-
-iterator rows*(db: var DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): Row {.
-         tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Same as `fastRows`, but slower and safe.
-  ##
-  ## This retrieves ALL rows into memory before
-  ## iterating through the rows.
-  ## Large dataset queries will impact on memory usage.
-  for r in items(getAllRows(db, query, args)): yield r
-
-proc getValue*(db: var DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): string {.
-           tags: [ReadDbEffect, WriteDbEffect], raises: [].} =
-  ## Executes the query and returns the first column of the first row of the
-  ## result dataset. Returns "" if the dataset contains no rows or the database
-  ## value is NULL.
-  result = ""
-  try:
-    result = getRow(db, query, args)[0]
-  except: discard
-
-proc tryInsertId*(db: var DbConn, query: SqlQuery,
-                  args: varargs[string, `$`]): int64 {.
-            tags: [ReadDbEffect, WriteDbEffect], raises: [].} =
-  ## Executes the query (typically "INSERT") and returns the
-  ## generated ID for the row or -1 in case of an error.
-  if not tryExec(db, query, args):
-    result = -1'i64
-  else:
-    result = -1'i64
-    try:
-      case sqlGetDBMS(db).toLower():
-      of "postgresql":
-        result = getValue(db, sql"SELECT LASTVAL();", []).parseInt
-      of "mysql":
-        result = getValue(db, sql"SELECT LAST_INSERT_ID();", []).parseInt
-      of "sqlite":
-        result = getValue(db, sql"SELECT LAST_INSERT_ROWID();", []).parseInt
-      of "microsoft sql server":
-        result = getValue(db, sql"SELECT SCOPE_IDENTITY();", []).parseInt
-      of "oracle":
-        result = getValue(db, sql"SELECT id.currval FROM DUAL;", []).parseInt
-      else: result = -1'i64
-    except: discard
-
-proc insertId*(db: var DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): int64 {.
-         tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Executes the query (typically "INSERT") and returns the
-  ## generated ID for the row.
-  result = tryInsertID(db, query, args)
-  if result < 0: dbError(db)
-
-proc tryInsert*(db: var DbConn, query: SqlQuery,pkName: string,
-                args: varargs[string, `$`]): int64
-               {.tags: [ReadDbEffect, WriteDbEffect], raises: [], since: (1, 3).} =
-  ## same as tryInsertID
-  tryInsertID(db, query, args)
-
-proc insert*(db: var DbConn, query: SqlQuery, pkName: string,
-             args: varargs[string, `$`]): int64 
-            {.tags: [ReadDbEffect, WriteDbEffect], since: (1, 3).} =
-  ## same as insertId
-  result = tryInsert(db, query,pkName, args)
-  if result < 0: dbError(db)
-
-proc execAffectedRows*(db: var DbConn, query: SqlQuery,
-                       args: varargs[string, `$`]): int64 {.
-             tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Runs the query (typically "UPDATE") and returns the
-  ## number of affected rows
-  result = -1
-  db.sqlCheck(SQLAllocHandle(SQL_HANDLE_STMT, db.hDb, db.stmt.SqlHandle))
-  var q = dbFormat(query, args)
-  db.sqlCheck(SQLPrepare(db.stmt, q.PSQLCHAR, q.len.TSqlSmallInt))
-  rawExec(db, query, args)
-  var rCnt:TSqlLen = -1
-  db.sqlCheck(SQLRowCount(db.hDb, rCnt))
-  properFreeResult(SQL_HANDLE_STMT, db.stmt)
-  result = rCnt.int64
-
-proc close*(db: var DbConn) {.
-      tags: [WriteDbEffect], raises: [].} =
-  ## Closes the database connection.
-  if db.hDb != nil:
-    try:
-      var res = SQLDisconnect(db.hDb)
-      if db.stmt != nil:
-        res = SQLFreeHandle(SQL_HANDLE_STMT, db.stmt)
-      res = SQLFreeHandle(SQL_HANDLE_DBC, db.hDb)
-      res = SQLFreeHandle(SQL_HANDLE_ENV, db.env)
-      db = (hDb: nil, env: nil, stmt: nil)
-    except:
-      discard
-
-proc open*(connection, user, password, database: string): DbConn {.
-  tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Opens a database connection.
-  ##
-  ## Raises `EDb` if the connection could not be established.
-  ##
-  ## Currently the database parameter is ignored,
-  ## but included to match `open()` in the other db_xxxxx library modules.
-  var
-    val = SQL_OV_ODBC3
-    resLen = 0
-  result = (hDb: nil, env: nil, stmt: nil)
-  # allocate environment handle
-  var res = SQLAllocHandle(SQL_HANDLE_ENV, result.env, result.env)
-  if res != SQL_SUCCESS: dbError("Error: unable to initialise ODBC environment.")
-  res = SQLSetEnvAttr(result.env,
-                      SQL_ATTR_ODBC_VERSION.TSqlInteger,
-                      cast[SqlPointer](val), resLen.TSqlInteger)
-  if res != SQL_SUCCESS: dbError("Error: unable to set ODBC driver version.")
-  # allocate hDb handle
-  res = SQLAllocHandle(SQL_HANDLE_DBC, result.env, result.hDb)
-  if res != SQL_SUCCESS: dbError("Error: unable to allocate connection handle.")
-
-  # Connect: connection = dsn str,
-  res = SQLConnect(result.hDb,
-                  connection.PSQLCHAR , connection.len.TSqlSmallInt,
-                  user.PSQLCHAR, user.len.TSqlSmallInt,
-                  password.PSQLCHAR, password.len.TSqlSmallInt)
-  if res != SQL_SUCCESS:
-    result.dbError()
-
-proc setEncoding*(connection: DbConn, encoding: string): bool {.
-  tags: [ReadDbEffect, WriteDbEffect], raises: [DbError].} =
-  ## Currently not implemented for ODBC.
-  ##
-  ## Sets the encoding of a database connection, returns true for
-  ## success, false for failure.
-  ##result = set_character_set(connection, encoding) == 0
-  dbError("setEncoding() is currently not implemented by the db_odbc module")
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
deleted file mode 100644
index 43ab94dbc..000000000
--- a/lib/impure/db_postgres.nim
+++ /dev/null
@@ -1,647 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## A higher level `PostgreSQL`:idx: database wrapper. This interface
-## is implemented for other databases also.
-##
-## See also: `db_odbc <db_odbc.html>`_, `db_sqlite <db_sqlite.html>`_,
-## `db_mysql <db_mysql.html>`_.
-##
-## Parameter substitution
-## ======================
-##
-## All `db_*` modules support the same form of parameter substitution.
-## That is, using the `?` (question mark) to signify the place where a
-## value should be placed. For example:
-##
-##   ```Nim
-##   sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)"
-##   ```
-##
-## **Note**: There are two approaches to parameter substitution support by
-## this module.
-##
-## 1. `SqlQuery` using `?, ?, ?, ...` (same as all the `db_*` modules)
-##
-## 2. `SqlPrepared` using `$1, $2, $3, ...`
-##
-##   ```Nim
-##   prepare(db, "myExampleInsert",
-##           sql"""INSERT INTO myTable
-##                 (colA, colB, colC)
-##                 VALUES ($1, $2, $3)""",
-##           3)
-##   ```
-##
-##
-## Unix Socket
-## ===========
-##
-## Using Unix sockets instead of TCP connection can
-## `improve performance up to 30% ~ 175% for some operations <https://momjian.us/main/blogs/pgblog/2012.html#June_6_2012>`_.
-##
-## To use Unix sockets with `db_postgres`, change the server address to the socket file path:
-##
-##   ```Nim
-##   import std/db_postgres ## Change "localhost" or "127.0.0.1" to the socket file path
-##   let db = db_postgres.open("/run/postgresql", "user", "password", "database")
-##   echo db.getAllRows(sql"SELECT version();")
-##   db.close()
-##   ```
-##
-## The socket file path is operating system specific and distribution specific,
-## additional configuration may or may not be needed on your `postgresql.conf`.
-## The Postgres server must be on the same computer and only works for Unix-like operating systems.
-##
-##
-## Examples
-## ========
-##
-## Opening a connection to a database
-## ----------------------------------
-##
-##   ```Nim
-##   import std/db_postgres
-##   let db = open("localhost", "user", "password", "dbname")
-##   db.close()
-##   ```
-##
-## Creating a table
-## ----------------
-##
-##   ```Nim
-##   db.exec(sql"DROP TABLE IF EXISTS myTable")
-##   db.exec(sql("""CREATE TABLE myTable (
-##                    id integer,
-##                    name varchar(50) not null)"""))
-##   ```
-##
-## Inserting data
-## --------------
-##
-##   ```Nim
-##   db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)",
-##           "Dominik")
-##   ```
-import strutils, postgres
-
-import db_common
-export db_common
-
-import std/private/[since, dbutils]
-
-type
-  DbConn* = PPGconn    ## encapsulates a database connection
-  Row* = seq[string]   ## a row of a dataset. NULL database values will be
-                       ## converted to nil.
-  InstantRow* = object ## a handle that can be
-    res: PPGresult     ## used to get a row's
-  SqlPrepared* = distinct string ## a identifier for the prepared queries
-
-proc dbError*(db: DbConn) {.noreturn.} =
-  ## raises a DbError exception.
-  var e: ref DbError
-  new(e)
-  e.msg = $pqErrorMessage(db)
-  raise e
-
-proc dbQuote*(s: string): string =
-  ## DB quotes the string.
-  result = "'"
-  for c in items(s):
-    case c
-    of '\'': add(result, "''")
-    of '\0': add(result, "\\0")
-    else: add(result, c)
-  add(result, '\'')
-
-proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
-  dbFormatImpl(formatstr, dbQuote, args)
-
-proc tryExec*(db: DbConn, query: SqlQuery,
-              args: varargs[string, `$`]): bool {.tags: [ReadDbEffect, WriteDbEffect].} =
-  ## tries to execute the query and returns true if successful, false otherwise.
-  var res = pqexecParams(db, dbFormat(query, args).cstring, 0, nil, nil,
-                        nil, nil, 0)
-  result = pqresultStatus(res) == PGRES_COMMAND_OK
-  pqclear(res)
-
-proc tryExec*(db: DbConn, stmtName: SqlPrepared,
-              args: varargs[string, `$`]): bool {.tags: [
-              ReadDbEffect, WriteDbEffect].} =
-  ## tries to execute the query and returns true if successful, false otherwise.
-  var arr = allocCStringArray(args)
-  var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
-                           nil, nil, 0)
-  deallocCStringArray(arr)
-  result = pqresultStatus(res) == PGRES_COMMAND_OK
-  pqclear(res)
-
-proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
-  tags: [ReadDbEffect, WriteDbEffect].} =
-  ## executes the query and raises EDB if not successful.
-  var res = pqexecParams(db, dbFormat(query, args).cstring, 0, nil, nil,
-                        nil, nil, 0)
-  if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  pqclear(res)
-
-proc exec*(db: DbConn, stmtName: SqlPrepared,
-          args: varargs[string]) {.tags: [ReadDbEffect, WriteDbEffect].} =
-  var arr = allocCStringArray(args)
-  var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
-                           nil, nil, 0)
-  deallocCStringArray(arr)
-  if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  pqclear(res)
-
-proc newRow(L: int): Row =
-  newSeq(result, L)
-  for i in 0..L-1: result[i] = ""
-
-proc setupQuery(db: DbConn, query: SqlQuery,
-                args: varargs[string]): PPGresult =
-  result = pqexec(db, dbFormat(query, args).cstring)
-  if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
-
-proc setupQuery(db: DbConn, stmtName: SqlPrepared,
-                 args: varargs[string]): PPGresult =
-  var arr = allocCStringArray(args)
-  result = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
-                          nil, nil, 0)
-  deallocCStringArray(arr)
-  if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
-
-proc setupSingeRowQuery(db: DbConn, query: SqlQuery,
-                        args: varargs[string]) =
-  if pqsendquery(db, dbFormat(query, args).cstring) != 1:
-    dbError(db)
-  if pqSetSingleRowMode(db) != 1:
-    dbError(db)
-
-proc setupSingeRowQuery(db: DbConn, stmtName: SqlPrepared,
-                       args: varargs[string]) =
-  var arr = allocCStringArray(args)
-  if pqsendqueryprepared(db, stmtName.cstring, int32(args.len), arr, nil, nil, 0) != 1:
-    dbError(db)
-  if pqSetSingleRowMode(db) != 1:
-    dbError(db)
-  deallocCStringArray(arr)
-
-proc prepare*(db: DbConn; stmtName: string, query: SqlQuery;
-              nParams: int): SqlPrepared =
-  ## Creates a new `SqlPrepared` statement. Parameter substitution is done
-  ## via `$1`, `$2`, `$3`, etc.
-  if nParams > 0 and not string(query).contains("$1"):
-    dbError("parameter substitution expects \"$1\"")
-  var res = pqprepare(db, stmtName, query.cstring, int32(nParams), nil)
-  if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  result = SqlPrepared(stmtName)
-  pqclear(res)
-
-proc setRow(res: PPGresult, r: var Row, line, cols: int32) =
-  for col in 0'i32..cols-1:
-    setLen(r[col], 0)
-    let x = pqgetvalue(res, line, col)
-    if x.isNil:
-      r[col] = ""
-    else:
-      add(r[col], x)
-
-template fetchRows(db: DbConn): untyped =
-  var res: PPGresult = nil
-  while true:
-    res = pqgetresult(db)
-    if res == nil:
-      break
-    let status = pqresultStatus(res)
-    if status == PGRES_TUPLES_OK:
-      discard
-    elif status != PGRES_SINGLE_TUPLE:
-      dbError(db)
-    else:
-      let L = pqNfields(res)
-      var result = newRow(L)
-      setRow(res, result, 0, L)
-      yield result
-    pqclear(res)
-
-iterator fastRows*(db: DbConn, query: SqlQuery,
-                   args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## executes the query and iterates over the result dataset. This is very
-  ## fast, but potentially dangerous: If the for-loop-body executes another
-  ## query, the results can be undefined. For Postgres it is safe though.
-  setupSingeRowQuery(db, query, args)
-  fetchRows(db)
-
-iterator fastRows*(db: DbConn, stmtName: SqlPrepared,
-                   args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## executes the query and iterates over the result dataset. This is very
-  ## fast, but potentially dangerous: If the for-loop-body executes another
-  ## query, the results can be undefined. For Postgres it is safe though.
-  setupSingeRowQuery(db, stmtName, args)
-  fetchRows(db)
-
-template fetchinstantRows(db: DbConn): untyped =
-  var res: PPGresult = nil
-  while true:
-    res = pqgetresult(db)
-    if res == nil:
-      break
-    let status = pqresultStatus(res)
-    if status == PGRES_TUPLES_OK:
-     discard
-    elif status != PGRES_SINGLE_TUPLE:
-      dbError(db)
-    else:
-      yield InstantRow(res: res)
-    pqclear(res)
-
-iterator instantRows*(db: DbConn, query: SqlQuery,
-                      args: varargs[string, `$`]): InstantRow
-                      {.tags: [ReadDbEffect].} =
-  ## same as fastRows but returns a handle that can be used to get column text
-  ## on demand using `[]`. Returned handle is valid only within iterator body.
-  setupSingeRowQuery(db, query, args)
-  fetchinstantRows(db)
-
-iterator instantRows*(db: DbConn, stmtName: SqlPrepared,
-                      args: varargs[string, `$`]): InstantRow
-                      {.tags: [ReadDbEffect].} =
-  ## same as fastRows but returns a handle that can be used to get column text
-  ## on demand using `[]`. Returned handle is valid only within iterator body.
-  setupSingeRowQuery(db, stmtName, args)
-  fetchinstantRows(db)
-
-proc getColumnType(res: PPGresult, col: int) : DbType =
-  ## returns DbType for given column in the row
-  ## defined in pg_type.h file in the postgres source code
-  ## Wire representation for types: http://www.npgsql.org/dev/types.html
-  var oid = pqftype(res, int32(col))
-  ## The integer returned is the internal OID number of the type
-  case oid
-  of 16: return DbType(kind: DbTypeKind.dbBool, name: "bool")
-  of 17: return DbType(kind: DbTypeKind.dbBlob, name: "bytea")
-
-  of 21:   return DbType(kind: DbTypeKind.dbInt, name: "int2", size: 2)
-  of 23:   return DbType(kind: DbTypeKind.dbInt, name: "int4", size: 4)
-  of 20:   return DbType(kind: DbTypeKind.dbInt, name: "int8", size: 8)
-  of 1560: return DbType(kind: DbTypeKind.dbBit, name: "bit")
-  of 1562: return DbType(kind: DbTypeKind.dbInt, name: "varbit")
-
-  of 18:   return DbType(kind: DbTypeKind.dbFixedChar, name: "char")
-  of 19:   return DbType(kind: DbTypeKind.dbFixedChar, name: "name")
-  of 1042: return DbType(kind: DbTypeKind.dbFixedChar, name: "bpchar")
-
-  of 25:   return DbType(kind: DbTypeKind.dbVarchar, name: "text")
-  of 1043: return DbType(kind: DbTypeKind.dbVarChar, name: "varchar")
-  of 2275: return DbType(kind: DbTypeKind.dbVarchar, name: "cstring")
-
-  of 700: return DbType(kind: DbTypeKind.dbFloat, name: "float4")
-  of 701: return DbType(kind: DbTypeKind.dbFloat, name: "float8")
-
-  of 790:  return DbType(kind: DbTypeKind.dbDecimal, name: "money")
-  of 1700: return DbType(kind: DbTypeKind.dbDecimal, name: "numeric")
-
-  of 704:  return DbType(kind: DbTypeKind.dbTimeInterval, name: "tinterval")
-  of 702:  return DbType(kind: DbTypeKind.dbTimestamp, name: "abstime")
-  of 703:  return DbType(kind: DbTypeKind.dbTimeInterval, name: "reltime")
-  of 1082: return DbType(kind: DbTypeKind.dbDate, name: "date")
-  of 1083: return DbType(kind: DbTypeKind.dbTime, name: "time")
-  of 1114: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamp")
-  of 1184: return DbType(kind: DbTypeKind.dbTimestamp, name: "timestamptz")
-  of 1186: return DbType(kind: DbTypeKind.dbTimeInterval, name: "interval")
-  of 1266: return DbType(kind: DbTypeKind.dbTime, name: "timetz")
-
-  of 114:  return DbType(kind: DbTypeKind.dbJson, name: "json")
-  of 142:  return DbType(kind: DbTypeKind.dbXml, name: "xml")
-  of 3802: return DbType(kind: DbTypeKind.dbJson, name: "jsonb")
-
-  of 600: return DbType(kind: DbTypeKind.dbPoint, name: "point")
-  of 601: return DbType(kind: DbTypeKind.dbLseg, name: "lseg")
-  of 602: return DbType(kind: DbTypeKind.dbPath, name: "path")
-  of 603: return DbType(kind: DbTypeKind.dbBox, name: "box")
-  of 604: return DbType(kind: DbTypeKind.dbPolygon, name: "polygon")
-  of 628: return DbType(kind: DbTypeKind.dbLine, name: "line")
-  of 718: return DbType(kind: DbTypeKind.dbCircle, name: "circle")
-
-  of 650: return DbType(kind: DbTypeKind.dbInet, name: "cidr")
-  of 829: return DbType(kind: DbTypeKind.dbMacAddress, name: "macaddr")
-  of 869: return DbType(kind: DbTypeKind.dbInet, name: "inet")
-
-  of 2950: return DbType(kind: DbTypeKind.dbVarchar, name: "uuid")
-  of 3614: return DbType(kind: DbTypeKind.dbVarchar, name: "tsvector")
-  of 3615: return DbType(kind: DbTypeKind.dbVarchar, name: "tsquery")
-  of 2970: return DbType(kind: DbTypeKind.dbVarchar, name: "txid_snapshot")
-
-  of 27:   return DbType(kind: DbTypeKind.dbComposite, name: "tid")
-  of 1790: return DbType(kind: DbTypeKind.dbComposite, name: "refcursor")
-  of 2249: return DbType(kind: DbTypeKind.dbComposite, name: "record")
-  of 3904: return DbType(kind: DbTypeKind.dbComposite, name: "int4range")
-  of 3906: return DbType(kind: DbTypeKind.dbComposite, name: "numrange")
-  of 3908: return DbType(kind: DbTypeKind.dbComposite, name: "tsrange")
-  of 3910: return DbType(kind: DbTypeKind.dbComposite, name: "tstzrange")
-  of 3912: return DbType(kind: DbTypeKind.dbComposite, name: "daterange")
-  of 3926: return DbType(kind: DbTypeKind.dbComposite, name: "int8range")
-
-  of 22:   return DbType(kind: DbTypeKind.dbArray, name: "int2vector")
-  of 30:   return DbType(kind: DbTypeKind.dbArray, name: "oidvector")
-  of 143:  return DbType(kind: DbTypeKind.dbArray, name: "xml[]")
-  of 199:  return DbType(kind: DbTypeKind.dbArray, name: "json[]")
-  of 629:  return DbType(kind: DbTypeKind.dbArray, name: "line[]")
-  of 651:  return DbType(kind: DbTypeKind.dbArray, name: "cidr[]")
-  of 719:  return DbType(kind: DbTypeKind.dbArray, name: "circle[]")
-  of 791:  return DbType(kind: DbTypeKind.dbArray, name: "money[]")
-  of 1000: return DbType(kind: DbTypeKind.dbArray, name: "bool[]")
-  of 1001: return DbType(kind: DbTypeKind.dbArray, name: "bytea[]")
-  of 1002: return DbType(kind: DbTypeKind.dbArray, name: "char[]")
-  of 1003: return DbType(kind: DbTypeKind.dbArray, name: "name[]")
-  of 1005: return DbType(kind: DbTypeKind.dbArray, name: "int2[]")
-  of 1006: return DbType(kind: DbTypeKind.dbArray, name: "int2vector[]")
-  of 1007: return DbType(kind: DbTypeKind.dbArray, name: "int4[]")
-  of 1008: return DbType(kind: DbTypeKind.dbArray, name: "regproc[]")
-  of 1009: return DbType(kind: DbTypeKind.dbArray, name: "text[]")
-  of 1028: return DbType(kind: DbTypeKind.dbArray, name: "oid[]")
-  of 1010: return DbType(kind: DbTypeKind.dbArray, name: "tid[]")
-  of 1011: return DbType(kind: DbTypeKind.dbArray, name: "xid[]")
-  of 1012: return DbType(kind: DbTypeKind.dbArray, name: "cid[]")
-  of 1013: return DbType(kind: DbTypeKind.dbArray, name: "oidvector[]")
-  of 1014: return DbType(kind: DbTypeKind.dbArray, name: "bpchar[]")
-  of 1015: return DbType(kind: DbTypeKind.dbArray, name: "varchar[]")
-  of 1016: return DbType(kind: DbTypeKind.dbArray, name: "int8[]")
-  of 1017: return DbType(kind: DbTypeKind.dbArray, name: "point[]")
-  of 1018: return DbType(kind: DbTypeKind.dbArray, name: "lseg[]")
-  of 1019: return DbType(kind: DbTypeKind.dbArray, name: "path[]")
-  of 1020: return DbType(kind: DbTypeKind.dbArray, name: "box[]")
-  of 1021: return DbType(kind: DbTypeKind.dbArray, name: "float4[]")
-  of 1022: return DbType(kind: DbTypeKind.dbArray, name: "float8[]")
-  of 1023: return DbType(kind: DbTypeKind.dbArray, name: "abstime[]")
-  of 1024: return DbType(kind: DbTypeKind.dbArray, name: "reltime[]")
-  of 1025: return DbType(kind: DbTypeKind.dbArray, name: "tinterval[]")
-  of 1027: return DbType(kind: DbTypeKind.dbArray, name: "polygon[]")
-  of 1040: return DbType(kind: DbTypeKind.dbArray, name: "macaddr[]")
-  of 1041: return DbType(kind: DbTypeKind.dbArray, name: "inet[]")
-  of 1263: return DbType(kind: DbTypeKind.dbArray, name: "cstring[]")
-  of 1115: return DbType(kind: DbTypeKind.dbArray, name: "timestamp[]")
-  of 1182: return DbType(kind: DbTypeKind.dbArray, name: "date[]")
-  of 1183: return DbType(kind: DbTypeKind.dbArray, name: "time[]")
-  of 1185: return DbType(kind: DbTypeKind.dbArray, name: "timestamptz[]")
-  of 1187: return DbType(kind: DbTypeKind.dbArray, name: "interval[]")
-  of 1231: return DbType(kind: DbTypeKind.dbArray, name: "numeric[]")
-  of 1270: return DbType(kind: DbTypeKind.dbArray, name: "timetz[]")
-  of 1561: return DbType(kind: DbTypeKind.dbArray, name: "bit[]")
-  of 1563: return DbType(kind: DbTypeKind.dbArray, name: "varbit[]")
-  of 2201: return DbType(kind: DbTypeKind.dbArray, name: "refcursor[]")
-  of 2951: return DbType(kind: DbTypeKind.dbArray, name: "uuid[]")
-  of 3643: return DbType(kind: DbTypeKind.dbArray, name: "tsvector[]")
-  of 3645: return DbType(kind: DbTypeKind.dbArray, name: "tsquery[]")
-  of 3807: return DbType(kind: DbTypeKind.dbArray, name: "jsonb[]")
-  of 2949: return DbType(kind: DbTypeKind.dbArray, name: "txid_snapshot[]")
-  of 3905: return DbType(kind: DbTypeKind.dbArray, name: "int4range[]")
-  of 3907: return DbType(kind: DbTypeKind.dbArray, name: "numrange[]")
-  of 3909: return DbType(kind: DbTypeKind.dbArray, name: "tsrange[]")
-  of 3911: return DbType(kind: DbTypeKind.dbArray, name: "tstzrange[]")
-  of 3913: return DbType(kind: DbTypeKind.dbArray, name: "daterange[]")
-  of 3927: return DbType(kind: DbTypeKind.dbArray, name: "int8range[]")
-  of 2287: return DbType(kind: DbTypeKind.dbArray, name: "record[]")
-
-  of 705:  return DbType(kind: DbTypeKind.dbUnknown, name: "unknown")
-  else: return DbType(kind: DbTypeKind.dbUnknown, name: $oid) ## Query the system table pg_type to determine exactly which type is referenced.
-
-proc setColumnInfo(columns: var DbColumns; res: PPGresult, L: int32) =
-  setLen(columns, L)
-  for i in 0'i32..<L:
-    columns[i].name = $pqfname(res, i)
-    columns[i].typ = getColumnType(res, i)
-    columns[i].tableName = $(pqftable(res, i)) ## Returns the OID of the table from which the given column was fetched.
-                                               ## Query the system table pg_class to determine exactly which table is referenced.
-    #columns[i].primaryKey = libpq does not have a function for that
-    #columns[i].foreignKey = libpq does not have a function for that
-
-iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery;
-                      args: varargs[string, `$`]): InstantRow
-                      {.tags: [ReadDbEffect].} =
-  setupSingeRowQuery(db, query, args)
-  var res: PPGresult = nil
-  var colsObtained = false
-  while true:
-    res = pqgetresult(db)
-    if not colsObtained:
-      setColumnInfo(columns, res, pqnfields(res))
-      colsObtained = true
-    if res == nil:
-      break
-    let status = pqresultStatus(res)
-    if status == PGRES_TUPLES_OK:
-      discard
-    elif status != PGRES_SINGLE_TUPLE:
-      dbError(db)
-    else:
-      yield InstantRow(res: res)
-    pqclear(res)
-
-proc `[]`*(row: InstantRow; col: int): string {.inline.} =
-  ## returns text for given column of the row
-  $pqgetvalue(row.res, int32(0), int32(col))
-
-proc unsafeColumnAt*(row: InstantRow, index: int): cstring {.inline.} =
-  ## Return cstring of given column of the row
-  pqgetvalue(row.res, int32(0), int32(index))
-
-proc len*(row: InstantRow): int {.inline.} =
-  ## returns number of columns in the row
-  int(pqNfields(row.res))
-
-proc getRow(res: PPGresult): Row =
-  let L = pqnfields(res)
-  result = newRow(L)
-  if pqntuples(res) > 0:
-    setRow(res, result, 0, L)
-  pqclear(res)
-
-proc getRow*(db: DbConn, query: SqlQuery,
-             args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a Row with empty strings for each column.
-  let res = setupQuery(db, query, args)
-  result = getRow(res)
-
-proc getRow*(db: DbConn, stmtName: SqlPrepared,
-             args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  let res = setupQuery(db, stmtName, args)
-  result = getRow(res)
-
-proc getAllRows(res: PPGresult): seq[Row] =
-  let N = pqntuples(res)
-  let L = pqnfields(res)
-  result = newSeqOfCap[Row](N)
-  var row = newRow(L)
-  for i in 0'i32..N-1:
-    setRow(res, row, i, L)
-    result.add(row)
-  pqclear(res)
-
-proc getAllRows*(db: DbConn, query: SqlQuery,
-                 args: varargs[string, `$`]): seq[Row] {.
-                 tags: [ReadDbEffect].} =
-  ## executes the query and returns the whole result dataset.
-  let res = setupQuery(db, query, args)
-  result = getAllRows(res)
-
-proc getAllRows*(db: DbConn, stmtName: SqlPrepared,
-                 args: varargs[string, `$`]): seq[Row] {.tags:
-                 [ReadDbEffect].} =
-  ## executes the prepared query and returns the whole result dataset.
-  let res = setupQuery(db, stmtName, args)
-  result = getAllRows(res)
-
-iterator rows*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## same as `fastRows`, but slower and safe.
-  for r in items(getAllRows(db, query, args)): yield r
-
-iterator rows*(db: DbConn, stmtName: SqlPrepared,
-               args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## same as `fastRows`, but slower and safe.
-  for r in items(getAllRows(db, stmtName, args)): yield r
-
-proc getValue(res: PPGresult): string =
-  if pqntuples(res) > 0:
-    var x = pqgetvalue(res, 0, 0)
-    result = if isNil(x): "" else: $x
-  else:
-    result = ""
-
-proc getValue*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): string {.
-               tags: [ReadDbEffect].} =
-  ## executes the query and returns the first column of the first row of the
-  ## result dataset. Returns "" if the dataset contains no rows or the database
-  ## value is NULL.
-  let res = setupQuery(db, query, args)
-  result = getValue(res)
-  pqclear(res)
-
-proc getValue*(db: DbConn, stmtName: SqlPrepared,
-               args: varargs[string, `$`]): string {.
-               tags: [ReadDbEffect].} =
-  ## executes the query and returns the first column of the first row of the
-  ## result dataset. Returns "" if the dataset contains no rows or the database
-  ## value is NULL.
-  let res = setupQuery(db, stmtName, args)
-  result = getValue(res)
-  pqclear(res)
-
-proc tryInsertID*(db: DbConn, query: SqlQuery,
-                  args: varargs[string, `$`]): int64 {.
-                  tags: [WriteDbEffect].}=
-  ## executes the query (typically "INSERT") and returns the
-  ## generated ID for the row or -1 in case of an error. For Postgre this adds
-  ## `RETURNING id` to the query, so it only works if your primary key is
-  ## named `id`.
-  let res = setupQuery(db, SqlQuery(string(query) & " RETURNING id"),
-                       args)
-  var x = pqgetvalue(res, 0, 0)
-  if not isNil(x):
-    result = parseBiggestInt($x)
-  else:
-    result = -1
-  pqclear(res)
-
-proc insertID*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): int64 {.
-               tags: [WriteDbEffect].} =
-  ## executes the query (typically "INSERT") and returns the
-  ## generated ID for the row. For Postgre this adds
-  ## `RETURNING id` to the query, so it only works if your primary key is
-  ## named `id`.
-  result = tryInsertID(db, query, args)
-  if result < 0: dbError(db)
-
-proc tryInsert*(db: DbConn, query: SqlQuery,pkName: string,
-                args: varargs[string, `$`]): int64
-               {.tags: [WriteDbEffect], since: (1, 3).}=
-  ## executes the query (typically "INSERT") and returns the
-  ## generated ID for the row or -1 in case of an error.
-  let res = setupQuery(db, SqlQuery(string(query) & " RETURNING " & pkName),
-                       args)
-  var x = pqgetvalue(res, 0, 0)
-  if not isNil(x):
-    result = parseBiggestInt($x)
-  else:
-    result = -1
-  pqclear(res)
-
-proc insert*(db: DbConn, query: SqlQuery, pkName: string,
-             args: varargs[string, `$`]): int64
-            {.tags: [WriteDbEffect], since: (1, 3).} =
-  ## executes the query (typically "INSERT") and returns the
-  ## generated ID
-  result = tryInsert(db, query, pkName, args)
-  if result < 0: dbError(db)
-
-proc execAffectedRows*(db: DbConn, query: SqlQuery,
-                       args: varargs[string, `$`]): int64 {.tags: [
-                       ReadDbEffect, WriteDbEffect].} =
-  ## executes the query (typically "UPDATE") and returns the
-  ## number of affected rows.
-  var q = dbFormat(query, args)
-  var res = pqExec(db, q.cstring)
-  if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  result = parseBiggestInt($pqcmdTuples(res))
-  pqclear(res)
-
-proc execAffectedRows*(db: DbConn, stmtName: SqlPrepared,
-                       args: varargs[string, `$`]): int64 {.tags: [
-                       ReadDbEffect, WriteDbEffect].} =
-  ## executes the query (typically "UPDATE") and returns the
-  ## number of affected rows.
-  var arr = allocCStringArray(args)
-  var res = pqexecPrepared(db, stmtName.cstring, int32(args.len), arr,
-                           nil, nil, 0)
-  deallocCStringArray(arr)
-  if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  result = parseBiggestInt($pqcmdTuples(res))
-  pqclear(res)
-
-proc close*(db: DbConn) {.tags: [DbEffect].} =
-  ## closes the database connection.
-  if db != nil: pqfinish(db)
-
-proc open*(connection, user, password, database: string): DbConn {.
-  tags: [DbEffect].} =
-  ## opens a database connection. Raises `EDb` if the connection could not
-  ## be established.
-  ##
-  ## Clients can also use Postgres keyword/value connection strings to
-  ## connect.
-  ##
-  ## Example:
-  ##   ```nim
-  ##   con = open("", "", "", "host=localhost port=5432 dbname=mydb")
-  ##   ```
-  ##
-  ## See http://www.postgresql.org/docs/current/static/libpq-connect.html#LIBPQ-CONNSTRING
-  ## for more information.
-  let
-    colonPos = connection.find(':')
-    host = if colonPos < 0: connection
-           else: substr(connection, 0, colonPos-1)
-    port = if colonPos < 0: ""
-           else: substr(connection, colonPos+1)
-  result = pqsetdbLogin(host.cstring, port.cstring, nil, nil, database, user, password)
-  if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil
-
-proc setEncoding*(connection: DbConn, encoding: string): bool {.
-  tags: [DbEffect].} =
-  ## sets the encoding of a database connection, returns true for
-  ## success, false for failure.
-  return pqsetClientEncoding(connection, encoding) == 0
-
-
-# Tests are in ../../tests/untestable/tpostgres.
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim
deleted file mode 100644
index f4661c9e1..000000000
--- a/lib/impure/db_sqlite.nim
+++ /dev/null
@@ -1,940 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## A higher level `SQLite`:idx: database wrapper. This interface
-## is implemented for other databases too.
-##
-## Basic usage
-## ===========
-##
-## The basic flow of using this module is:
-##
-## 1. Open database connection
-## 2. Execute SQL query
-## 3. Close database connection
-##
-## Parameter substitution
-## ----------------------
-##
-## All `db_*` modules support the same form of parameter substitution.
-## That is, using the `?` (question mark) to signify the place where a
-## value should be placed. For example:
-##
-##   ```Nim
-##   sql"INSERT INTO my_table (colA, colB, colC) VALUES (?, ?, ?)"
-##   ```
-##
-## Opening a connection to a database
-## ----------------------------------
-##
-##   ```Nim
-##   import std/db_sqlite
-##
-##   # user, password, database name can be empty.
-##   # These params are not used on db_sqlite module.
-##   let db = open("mytest.db", "", "", "")
-##   db.close()
-##   ```
-##
-## Creating a table
-## ----------------
-##
-##   ```Nim
-##   db.exec(sql"DROP TABLE IF EXISTS my_table")
-##   db.exec(sql"""CREATE TABLE my_table (
-##                    id   INTEGER,
-##                    name VARCHAR(50) NOT NULL
-##                 )""")
-##   ```
-##
-## Inserting data
-## --------------
-##
-##   ```Nim
-##   db.exec(sql"INSERT INTO my_table (id, name) VALUES (0, ?)",
-##           "Jack")
-##   ```
-##
-## Larger example
-## --------------
-##
-##   ```Nim
-##   import std/[db_sqlite, math]
-##
-##   let db = open("mytest.db", "", "", "")
-##
-##   db.exec(sql"DROP TABLE IF EXISTS my_table")
-##   db.exec(sql"""CREATE TABLE my_table (
-##                    id    INTEGER PRIMARY KEY,
-##                    name  VARCHAR(50) NOT NULL,
-##                    i     INT(11),
-##                    f     DECIMAL(18, 10)
-##                 )""")
-##
-##   db.exec(sql"BEGIN")
-##   for i in 1..1000:
-##     db.exec(sql"INSERT INTO my_table (name, i, f) VALUES (?, ?, ?)",
-##             "Item#" & $i, i, sqrt(i.float))
-##   db.exec(sql"COMMIT")
-##
-##   for x in db.fastRows(sql"SELECT * FROM my_table"):
-##     echo x
-##
-##   let id = db.tryInsertId(sql"""INSERT INTO my_table (name, i, f)
-##                                 VALUES (?, ?, ?)""",
-##                           "Item#1001", 1001, sqrt(1001.0))
-##   echo "Inserted item: ", db.getValue(sql"SELECT name FROM my_table WHERE id=?", id)
-##
-##   db.close()
-##   ```
-##
-## Storing binary data example
-##----------------------------
-##
-##   ```nim
-##   import std/random
-##
-##   ## Generate random float datas
-##   var orig = newSeq[float64](150)
-##   randomize()
-##   for x in orig.mitems:
-##     x = rand(1.0)/10.0
-##
-##   let db = open("mysqlite.db", "", "", "")
-##   block: ## Create database
-##     ## Binary datas needs to be of type BLOB in SQLite
-##     let createTableStr = sql"""CREATE TABLE test(
-##       id INTEGER NOT NULL PRIMARY KEY,
-##       data BLOB
-##     )
-##     """
-##     db.exec(createTableStr)
-##
-##   block: ## Insert data
-##     var id = 1
-##     ## Data needs to be converted to seq[byte] to be interpreted as binary by bindParams
-##     var dbuf = newSeq[byte](orig.len*sizeof(float64))
-##     copyMem(unsafeAddr(dbuf[0]), unsafeAddr(orig[0]), dbuf.len)
-##
-##     ## Use prepared statement to insert binary data into database
-##     var insertStmt = db.prepare("INSERT INTO test (id, data) VALUES (?, ?)")
-##     insertStmt.bindParams(id, dbuf)
-##     let bres = db.tryExec(insertStmt)
-##     ## Check insert
-##     doAssert(bres)
-##     # Destroy statement
-##     finalize(insertStmt)
-##
-##   block: ## Use getValue to select data
-##     var dataTest = db.getValue(sql"SELECT data FROM test WHERE id = ?", 1)
-##     ## Calculate sequence size from buffer size
-##     let seqSize = int(dataTest.len*sizeof(byte)/sizeof(float64))
-##     ## Copy binary string data in dataTest into a seq
-##     var res: seq[float64] = newSeq[float64](seqSize)
-##     copyMem(unsafeAddr(res[0]), addr(dataTest[0]), dataTest.len)
-##
-##     ## Check datas obtained is identical
-##     doAssert res == orig
-##
-##   db.close()
-##   ```
-##
-##
-## Note
-## ====
-## This module does not implement any ORM features such as mapping the types from the schema.
-## Instead, a `seq[string]` is returned for each row.
-##
-## The reasoning is as follows:
-## 1. it's close to what many DBs offer natively (`char**`:c:)
-## 2. it hides the number of types that the DB supports
-##    (int? int64? decimal up to 10 places? geo coords?)
-## 3. it's convenient when all you do is to forward the data to somewhere else (echo, log, put the data into a new query)
-##
-## See also
-## ========
-##
-## * `db_odbc module <db_odbc.html>`_ for ODBC database wrapper
-## * `db_mysql module <db_mysql.html>`_ for MySQL database wrapper
-## * `db_postgres module <db_postgres.html>`_ for PostgreSQL database wrapper
-
-{.experimental: "codeReordering".}
-
-import sqlite3, macros
-
-import db_common
-export db_common
-
-import std/private/[since, dbutils]
-when defined(nimPreviewSlimSystem):
-  import std/assertions
-
-type
-  DbConn* = PSqlite3  ## Encapsulates a database connection.
-  Row* = seq[string]  ## A row of a dataset. `NULL` database values will be
-                      ## converted to an empty string.
-  InstantRow* = PStmt ## A handle that can be used to get a row's column
-                      ## text on demand.
-  SqlPrepared* = distinct PStmt ## a identifier for the prepared queries
-
-proc dbError*(db: DbConn) {.noreturn.} =
-  ## Raises a `DbError` exception.
-  ##
-  ## **Examples:**
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##   if not db.tryExec(sql"SELECT * FROM not_exist_table"):
-  ##     dbError(db)
-  ##   db.close()
-  ##   ```
-  var e: ref DbError
-  new(e)
-  e.msg = $sqlite3.errmsg(db)
-  raise e
-
-proc dbQuote*(s: string): string =
-  ## Escapes the `'` (single quote) char to `''`.
-  ## Because single quote is used for defining `VARCHAR` in SQL.
-  runnableExamples:
-    doAssert dbQuote("'") == "''''"
-    doAssert dbQuote("A Foobar's pen.") == "'A Foobar''s pen.'"
-
-  result = "'"
-  for c in items(s):
-    if c == '\'': add(result, "''")
-    else: add(result, c)
-  add(result, '\'')
-
-proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
-  dbFormatImpl(formatstr, dbQuote, args)
-
-proc prepare*(db: DbConn; q: string): SqlPrepared {.since: (1, 3).} =
-  ## Creates a new `SqlPrepared` statement.
-  if prepare_v2(db, q, q.len.cint,result.PStmt, nil) != SQLITE_OK:
-    discard finalize(result.PStmt)
-    dbError(db)
-
-proc tryExec*(db: DbConn, query: SqlQuery,
-              args: varargs[string, `$`]): bool {.
-              tags: [ReadDbEffect, WriteDbEffect].} =
-  ## Tries to execute the query and returns `true` if successful, `false` otherwise.
-  ##
-  ## **Examples:**
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##   if not db.tryExec(sql"SELECT * FROM my_table"):
-  ##     dbError(db)
-  ##   db.close()
-  ##   ```
-  assert(not db.isNil, "Database not connected.")
-  var q = dbFormat(query, args)
-  var stmt: sqlite3.PStmt
-  if prepare_v2(db, q.cstring, q.len.cint, stmt, nil) == SQLITE_OK:
-    let x = step(stmt)
-    if x in {SQLITE_DONE, SQLITE_ROW}:
-      result = finalize(stmt) == SQLITE_OK
-    else:
-      discard finalize(stmt)
-      result = false
-
-proc tryExec*(db: DbConn, stmtName: SqlPrepared): bool {.
-              tags: [ReadDbEffect, WriteDbEffect].} =
-    let x = step(stmtName.PStmt)
-    if x in {SQLITE_DONE, SQLITE_ROW}:
-      result = true
-    else:
-      discard finalize(stmtName.PStmt)
-      result = false
-
-proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`])  {.
-  tags: [ReadDbEffect, WriteDbEffect].} =
-  ## Executes the query and raises a `DbError` exception if not successful.
-  ##
-  ## **Examples:**
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##   try:
-  ##     db.exec(sql"INSERT INTO my_table (id, name) VALUES (?, ?)",
-  ##             1, "item#1")
-  ##   except:
-  ##     stderr.writeLine(getCurrentExceptionMsg())
-  ##   finally:
-  ##     db.close()
-  ##   ```
-  if not tryExec(db, query, args): dbError(db)
-
-proc newRow(L: int): Row =
-  newSeq(result, L)
-  for i in 0..L-1: result[i] = ""
-
-proc setupQuery(db: DbConn, query: SqlQuery,
-                args: varargs[string]): PStmt =
-  assert(not db.isNil, "Database not connected.")
-  var q = dbFormat(query, args)
-  if prepare_v2(db, q.cstring, q.len.cint, result, nil) != SQLITE_OK: dbError(db)
-
-proc setupQuery(db: DbConn, stmtName: SqlPrepared): SqlPrepared {.since: (1, 3).} =
-  assert(not db.isNil, "Database not connected.")
-  result = stmtName
-
-proc setRow(stmt: PStmt, r: var Row, cols: cint) =
-  for col in 0'i32..cols-1:
-    let cb = column_bytes(stmt, col)
-    setLen(r[col], cb) # set capacity
-    if column_type(stmt, col) == SQLITE_BLOB:
-      copyMem(addr(r[col][0]), column_blob(stmt, col), cb)
-    else:
-      setLen(r[col], 0)
-      let x = column_text(stmt, col)
-      if not isNil(x): add(r[col], x)
-
-iterator fastRows*(db: DbConn, query: SqlQuery,
-                   args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## Executes the query and iterates over the result dataset.
-  ##
-  ## This is very fast, but potentially dangerous. Use this iterator only
-  ## if you require **ALL** the rows.
-  ##
-  ## **Note:** Breaking the `fastRows()` iterator during a loop will cause the
-  ## next database query to raise a `DbError` exception `unable to close due
-  ## to ...`.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##
-  ##   # Records of my_table:
-  ##   # | id | name     |
-  ##   # |----|----------|
-  ##   # |  1 | item#1   |
-  ##   # |  2 | item#2   |
-  ##
-  ##   for row in db.fastRows(sql"SELECT id, name FROM my_table"):
-  ##     echo row
-  ##
-  ##   # Output:
-  ##   # @["1", "item#1"]
-  ##   # @["2", "item#2"]
-  ##
-  ##   db.close()
-  ##   ```
-  var stmt = setupQuery(db, query, args)
-  var L = (column_count(stmt))
-  var result = newRow(L)
-  try:
-    while step(stmt) == SQLITE_ROW:
-      setRow(stmt, result, L)
-      yield result
-  finally:
-    if finalize(stmt) != SQLITE_OK: dbError(db)
-
-iterator fastRows*(db: DbConn, stmtName: SqlPrepared): Row
-                  {.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
-  discard setupQuery(db, stmtName)
-  var L = (column_count(stmtName.PStmt))
-  var result = newRow(L)
-  try:
-    while step(stmtName.PStmt) == SQLITE_ROW:
-      setRow(stmtName.PStmt, result, L)
-      yield result
-  except:
-    dbError(db)
-
-iterator instantRows*(db: DbConn, query: SqlQuery,
-                      args: varargs[string, `$`]): InstantRow
-                      {.tags: [ReadDbEffect].} =
-  ## Similar to `fastRows iterator <#fastRows.i,DbConn,SqlQuery,varargs[string,]>`_
-  ## but returns a handle that can be used to get column text
-  ## on demand using `[]`. Returned handle is valid only within the iterator body.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##    let db = open("mytest.db", "", "", "")
-  ##
-  ##    # Records of my_table:
-  ##    # | id | name     |
-  ##    # |----|----------|
-  ##    # |  1 | item#1   |
-  ##    # |  2 | item#2   |
-  ##
-  ##    for row in db.instantRows(sql"SELECT * FROM my_table"):
-  ##      echo "id:" & row[0]
-  ##      echo "name:" & row[1]
-  ##      echo "length:" & $len(row)
-  ##
-  ##    # Output:
-  ##    # id:1
-  ##    # name:item#1
-  ##    # length:2
-  ##    # id:2
-  ##    # name:item#2
-  ##    # length:2
-  ##
-  ##    db.close()
-  ##    ```
-  var stmt = setupQuery(db, query, args)
-  try:
-    while step(stmt) == SQLITE_ROW:
-      yield stmt
-  finally:
-    if finalize(stmt) != SQLITE_OK: dbError(db)
-
-iterator instantRows*(db: DbConn, stmtName: SqlPrepared): InstantRow
-                      {.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
-  var stmt = setupQuery(db, stmtName).PStmt
-  try:
-    while step(stmt) == SQLITE_ROW:
-      yield stmt
-  except:
-    dbError(db)
-
-proc toTypeKind(t: var DbType; x: int32) =
-  case x
-  of SQLITE_INTEGER:
-    t.kind = dbInt
-    t.size = 8
-  of SQLITE_FLOAT:
-    t.kind = dbFloat
-    t.size = 8
-  of SQLITE_BLOB: t.kind = dbBlob
-  of SQLITE_NULL: t.kind = dbNull
-  of SQLITE_TEXT: t.kind = dbVarchar
-  else: t.kind = dbUnknown
-
-proc setColumns(columns: var DbColumns; x: PStmt) =
-  let L = column_count(x)
-  setLen(columns, L)
-  for i in 0'i32 ..< L:
-    columns[i].name = $column_name(x, i)
-    columns[i].typ.name = $column_decltype(x, i)
-    toTypeKind(columns[i].typ, column_type(x, i))
-    columns[i].tableName = $column_table_name(x, i)
-
-iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery,
-                      args: varargs[string, `$`]): InstantRow
-                      {.tags: [ReadDbEffect].} =
-  ## Similar to `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_,
-  ## but sets information about columns to `columns`.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##
-  ##   # Records of my_table:
-  ##   # | id | name     |
-  ##   # |----|----------|
-  ##   # |  1 | item#1   |
-  ##   # |  2 | item#2   |
-  ##
-  ##   var columns: DbColumns
-  ##   for row in db.instantRows(columns, sql"SELECT * FROM my_table"):
-  ##     discard
-  ##   echo columns[0]
-  ##
-  ##   # Output:
-  ##   # (name: "id", tableName: "my_table", typ: (kind: dbNull,
-  ##   # notNull: false, name: "INTEGER", size: 0, maxReprLen: 0, precision: 0,
-  ##   # scale: 0, min: 0, max: 0, validValues: @[]), primaryKey: false,
-  ##   # foreignKey: false)
-  ##
-  ##   db.close()
-  ##   ```
-  var stmt = setupQuery(db, query, args)
-  setColumns(columns, stmt)
-  try:
-    while step(stmt) == SQLITE_ROW:
-      yield stmt
-  finally:
-    if finalize(stmt) != SQLITE_OK: dbError(db)
-
-proc `[]`*(row: InstantRow, col: int32): string {.inline.} =
-  ## Returns text for given column of the row.
-  ##
-  ## See also:
-  ## * `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_
-  ##   example code
-  $column_text(row, col)
-
-proc unsafeColumnAt*(row: InstantRow, index: int32): cstring {.inline.} =
-  ## Returns cstring for given column of the row.
-  ##
-  ## See also:
-  ## * `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_
-  ##   example code
-  column_text(row, index)
-
-proc len*(row: InstantRow): int32 {.inline.} =
-  ## Returns number of columns in a row.
-  ##
-  ## See also:
-  ## * `instantRows iterator <#instantRows.i,DbConn,SqlQuery,varargs[string,]>`_
-  ##   example code
-  column_count(row)
-
-proc getRow*(db: DbConn, query: SqlQuery,
-             args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## Retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a `Row` with empty strings for each column.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##
-  ##   # Records of my_table:
-  ##   # | id | name     |
-  ##   # |----|----------|
-  ##   # |  1 | item#1   |
-  ##   # |  2 | item#2   |
-  ##
-  ##   doAssert db.getRow(sql"SELECT id, name FROM my_table"
-  ##                      ) == Row(@["1", "item#1"])
-  ##   doAssert db.getRow(sql"SELECT id, name FROM my_table WHERE id = ?",
-  ##                      2) == Row(@["2", "item#2"])
-  ##
-  ##   # Returns empty.
-  ##   doAssert db.getRow(sql"INSERT INTO my_table (id, name) VALUES (?, ?)",
-  ##                      3, "item#3") == @[]
-  ##   doAssert db.getRow(sql"DELETE FROM my_table WHERE id = ?", 3) == @[]
-  ##   doAssert db.getRow(sql"UPDATE my_table SET name = 'ITEM#1' WHERE id = ?",
-  ##                      1) == @[]
-  ##   db.close()
-  ##   ```
-  var stmt = setupQuery(db, query, args)
-  var L = (column_count(stmt))
-  result = newRow(L)
-  if step(stmt) == SQLITE_ROW:
-    setRow(stmt, result, L)
-  if finalize(stmt) != SQLITE_OK: dbError(db)
-
-proc getAllRows*(db: DbConn, query: SqlQuery,
-                 args: varargs[string, `$`]): seq[Row] {.tags: [ReadDbEffect].} =
-  ## Executes the query and returns the whole result dataset.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##
-  ##   # Records of my_table:
-  ##   # | id | name     |
-  ##   # |----|----------|
-  ##   # |  1 | item#1   |
-  ##   # |  2 | item#2   |
-  ##
-  ##   doAssert db.getAllRows(sql"SELECT id, name FROM my_table") == @[Row(@["1", "item#1"]), Row(@["2", "item#2"])]
-  ##   db.close()
-  ##   ```
-  result = @[]
-  for r in fastRows(db, query, args):
-    result.add(r)
-
-proc getAllRows*(db: DbConn, stmtName: SqlPrepared): seq[Row]
-                {.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
-  result = @[]
-  for r in fastRows(db, stmtName):
-    result.add(r)
-
-iterator rows*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
-  ## Similar to `fastRows iterator <#fastRows.i,DbConn,SqlQuery,varargs[string,]>`_,
-  ## but slower and safe.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##
-  ##   # Records of my_table:
-  ##   # | id | name     |
-  ##   # |----|----------|
-  ##   # |  1 | item#1   |
-  ##   # |  2 | item#2   |
-  ##
-  ##   for row in db.rows(sql"SELECT id, name FROM my_table"):
-  ##     echo row
-  ##
-  ##   ## Output:
-  ##   ## @["1", "item#1"]
-  ##   ## @["2", "item#2"]
-  ##
-  ##   db.close()
-  ##   ```
-  for r in fastRows(db, query, args): yield r
-
-iterator rows*(db: DbConn, stmtName: SqlPrepared): Row
-              {.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
-  for r in fastRows(db, stmtName): yield r
-
-proc getValue*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): string {.tags: [ReadDbEffect].} =
-  ## Executes the query and returns the first column of the first row of the
-  ## result dataset. Returns `""` if the dataset contains no rows or the database
-  ## value is `NULL`.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##
-  ##   # Records of my_table:
-  ##   # | id | name     |
-  ##   # |----|----------|
-  ##   # |  1 | item#1   |
-  ##   # |  2 | item#2   |
-  ##
-  ##   doAssert db.getValue(sql"SELECT name FROM my_table WHERE id = ?",
-  ##                        2) == "item#2"
-  ##   doAssert db.getValue(sql"SELECT id, name FROM my_table") == "1"
-  ##   doAssert db.getValue(sql"SELECT name, id FROM my_table") == "item#1"
-  ##
-  ##   db.close()
-  ##   ```
-  var stmt = setupQuery(db, query, args)
-  if step(stmt) == SQLITE_ROW:
-    let cb = column_bytes(stmt, 0)
-    if cb == 0:
-      result = ""
-    else:
-      if column_type(stmt, 0) == SQLITE_BLOB:
-        result.setLen(cb)
-        copyMem(addr(result[0]), column_blob(stmt, 0), cb)
-      else:
-        result = newStringOfCap(cb)
-        add(result, column_text(stmt, 0))
-  else:
-    result = ""
-  if finalize(stmt) != SQLITE_OK: dbError(db)
-
-proc getValue*(db: DbConn,  stmtName: SqlPrepared): string
-              {.tags: [ReadDbEffect,WriteDbEffect], since: (1, 3).} =
-  var stmt = setupQuery(db, stmtName).PStmt
-  if step(stmt) == SQLITE_ROW:
-    let cb = column_bytes(stmt, 0)
-    if cb == 0:
-      result = ""
-    else:
-      if column_type(stmt, 0) == SQLITE_BLOB:
-        result.setLen(cb)
-        copyMem(addr(result[0]), column_blob(stmt, 0), cb)
-      else:
-        result = newStringOfCap(cb)
-        add(result, column_text(stmt, 0))
-  else:
-    result = ""
-
-proc tryInsertID*(db: DbConn, query: SqlQuery,
-                  args: varargs[string, `$`]): int64
-                  {.tags: [WriteDbEffect], raises: [DbError].} =
-  ## Executes the query (typically "INSERT") and returns the
-  ## generated ID for the row or -1 in case of an error.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##   db.exec(sql"CREATE TABLE my_table (id INTEGER, name VARCHAR(50) NOT NULL)")
-  ##
-  ##   doAssert db.tryInsertID(sql"INSERT INTO not_exist_table (id, name) VALUES (?, ?)",
-  ##                           1, "item#1") == -1
-  ##   db.close()
-  ##   ```
-  assert(not db.isNil, "Database not connected.")
-  var q = dbFormat(query, args)
-  var stmt: sqlite3.PStmt
-  result = -1
-  if prepare_v2(db, q.cstring, q.len.cint, stmt, nil) == SQLITE_OK:
-    if step(stmt) == SQLITE_DONE:
-      result = last_insert_rowid(db)
-    if finalize(stmt) != SQLITE_OK:
-      result = -1
-  else:
-    discard finalize(stmt)
-
-proc insertID*(db: DbConn, query: SqlQuery,
-               args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect].} =
-  ## Executes the query (typically "INSERT") and returns the
-  ## generated ID for the row.
-  ##
-  ## Raises a `DbError` exception when failed to insert row.
-  ## For Postgre this adds `RETURNING id` to the query, so it only works
-  ## if your primary key is named `id`.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##   db.exec(sql"CREATE TABLE my_table (id INTEGER, name VARCHAR(50) NOT NULL)")
-  ##
-  ##   for i in 0..2:
-  ##     let id = db.insertID(sql"INSERT INTO my_table (id, name) VALUES (?, ?)", i, "item#" & $i)
-  ##     echo "LoopIndex = ", i, ", InsertID = ", id
-  ##
-  ##   # Output:
-  ##   # LoopIndex = 0, InsertID = 1
-  ##   # LoopIndex = 1, InsertID = 2
-  ##   # LoopIndex = 2, InsertID = 3
-  ##
-  ##   db.close()
-  ##   ```
-  result = tryInsertID(db, query, args)
-  if result < 0: dbError(db)
-
-proc tryInsert*(db: DbConn, query: SqlQuery, pkName: string,
-                args: varargs[string, `$`]): int64
-               {.tags: [WriteDbEffect], raises: [DbError], since: (1, 3).} =
-  ## same as tryInsertID
-  tryInsertID(db, query, args)
-
-proc insert*(db: DbConn, query: SqlQuery, pkName: string,
-             args: varargs[string, `$`]): int64
-            {.tags: [WriteDbEffect], since: (1, 3).} =
-  ## same as insertId
-  result = tryInsert(db, query, pkName, args)
-  if result < 0: dbError(db)
-
-proc execAffectedRows*(db: DbConn, query: SqlQuery,
-                       args: varargs[string, `$`]): int64 {.
-                       tags: [ReadDbEffect, WriteDbEffect].} =
-  ## Executes the query (typically "UPDATE") and returns the
-  ## number of affected rows.
-  ##
-  ## **Examples:**
-  ##
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##
-  ##   # Records of my_table:
-  ##   # | id | name     |
-  ##   # |----|----------|
-  ##   # |  1 | item#1   |
-  ##   # |  2 | item#2   |
-  ##
-  ##   doAssert db.execAffectedRows(sql"UPDATE my_table SET name = 'TEST'") == 2
-  ##
-  ##   db.close()
-  ##   ```
-  exec(db, query, args)
-  result = changes(db)
-
-proc execAffectedRows*(db: DbConn, stmtName: SqlPrepared): int64
-                      {.tags: [ReadDbEffect, WriteDbEffect],since: (1, 3).} =
-  exec(db, stmtName)
-  result = changes(db)
-
-proc close*(db: DbConn) {.tags: [DbEffect].} =
-  ## Closes the database connection.
-  ##
-  ## **Examples:**
-  ##   ```Nim
-  ##   let db = open("mytest.db", "", "", "")
-  ##   db.close()
-  ##   ```
-  if sqlite3.close(db) != SQLITE_OK: dbError(db)
-
-proc open*(connection, user, password, database: string): DbConn {.
-  tags: [DbEffect].} =
-  ## Opens a database connection. Raises a `DbError` exception if the connection
-  ## could not be established.
-  ##
-  ## **Note:** Only the `connection` parameter is used for `sqlite`.
-  ##
-  ## **Examples:**
-  ##   ```Nim
-  ##   try:
-  ##     let db = open("mytest.db", "", "", "")
-  ##     ## do something...
-  ##     ## db.getAllRows(sql"SELECT * FROM my_table")
-  ##     db.close()
-  ##   except:
-  ##     stderr.writeLine(getCurrentExceptionMsg())
-  ##   ```
-  var db: DbConn
-  if sqlite3.open(connection, db) == SQLITE_OK:
-    result = db
-  else:
-    dbError(db)
-
-proc setEncoding*(connection: DbConn, encoding: string): bool {.
-  tags: [DbEffect].} =
-  ## Sets the encoding of a database connection, returns `true` for
-  ## success, `false` for failure.
-  ##
-  ## **Note:** The encoding cannot be changed once it's been set.
-  ## According to SQLite3 documentation, any attempt to change
-  ## the encoding after the database is created will be silently
-  ## ignored.
-  exec(connection, sql"PRAGMA encoding = ?", [encoding])
-  result = connection.getValue(sql"PRAGMA encoding") == encoding
-
-proc finalize*(sqlPrepared:SqlPrepared) {.discardable, since: (1, 3).} =
-  discard finalize(sqlPrepared.PStmt)
-
-template dbBindParamError*(paramIdx: int, val: varargs[untyped]) =
-  ## Raises a `DbError` exception.
-  var e: ref DbError
-  new(e)
-  e.msg = "error binding param in position " & $paramIdx
-  raise e
-
-proc bindParam*(ps: SqlPrepared, paramIdx: int, val: int32) {.since: (1, 3).} =
-  ## Binds a int32  to the specified paramIndex.
-  if bind_int(ps.PStmt, paramIdx.int32, val) != SQLITE_OK:
-    dbBindParamError(paramIdx, val)
-
-proc bindParam*(ps: SqlPrepared, paramIdx: int, val: int64) {.since: (1, 3).} =
-  ## Binds a int64  to the specified paramIndex.
-  if bind_int64(ps.PStmt, paramIdx.int32, val) != SQLITE_OK:
-    dbBindParamError(paramIdx, val)
-
-proc bindParam*(ps: SqlPrepared, paramIdx: int, val: int) {.since: (1, 3).} =
-  ## Binds a int  to the specified paramIndex.
-  when sizeof(int) == 8:
-    bindParam(ps, paramIdx, val.int64)
-  else:
-    bindParam(ps, paramIdx, val.int32)
-
-proc bindParam*(ps: SqlPrepared, paramIdx: int, val: float64) {.since: (1, 3).} =
-  ## Binds a 64bit float to the specified paramIndex.
-  if bind_double(ps.PStmt, paramIdx.int32, val) != SQLITE_OK:
-    dbBindParamError(paramIdx, val)
-
-proc bindNull*(ps: SqlPrepared, paramIdx: int) {.since: (1, 3).} =
-  ## Sets the bindparam at the specified paramIndex to null
-  ## (default behaviour by sqlite).
-  if bind_null(ps.PStmt, paramIdx.int32) != SQLITE_OK:
-    dbBindParamError(paramIdx)
-
-proc bindParam*(ps: SqlPrepared, paramIdx: int, val: string, copy = true) {.since: (1, 3).} =
-  ## Binds a string to the specified paramIndex.
-  ## if copy is true then SQLite makes its own private copy of the data immediately
-  if bind_text(ps.PStmt, paramIdx.int32, val.cstring, val.len.int32, if copy: SQLITE_TRANSIENT else: SQLITE_STATIC) != SQLITE_OK:
-    dbBindParamError(paramIdx, val)
-
-proc bindParam*(ps: SqlPrepared, paramIdx: int,val: openArray[byte], copy = true) {.since: (1, 3).} =
-  ## binds a blob to the specified paramIndex.
-  ## if copy is true then SQLite makes its own private copy of the data immediately
-  let len = val.len
-  if bind_blob(ps.PStmt, paramIdx.int32, val[0].unsafeAddr, len.int32, if copy: SQLITE_TRANSIENT else: SQLITE_STATIC) != SQLITE_OK:
-    dbBindParamError(paramIdx, val)
-
-macro bindParams*(ps: SqlPrepared, params: varargs[untyped]): untyped {.since: (1, 3).} =
-  let bindParam = bindSym("bindParam", brOpen)
-  let bindNull = bindSym("bindNull")
-  let preparedStatement = genSym()
-  result = newStmtList()
-  # Store `ps` in a temporary variable. This prevents `ps` from being evaluated every call.
-  result.add newNimNode(nnkLetSection).add(newIdentDefs(preparedStatement, newEmptyNode(), ps))
-  for idx, param in params:
-    if param.kind != nnkNilLit:
-      result.add newCall(bindParam, preparedStatement, newIntLitNode idx + 1, param)
-    else:
-      result.add newCall(bindNull, preparedStatement, newIntLitNode idx + 1)
-
-macro untypedLen(args: varargs[untyped]): int =
-  newLit(args.len)
-
-template exec*(db: DbConn, stmtName: SqlPrepared,
-          args: varargs[typed]): untyped =
-  when untypedLen(args) > 0:
-    if reset(stmtName.PStmt) != SQLITE_OK:
-      dbError(db)
-    if clear_bindings(stmtName.PStmt) != SQLITE_OK:
-      dbError(db)
-    stmtName.bindParams(args)
-  if not tryExec(db, stmtName): dbError(db)
-
-when not defined(testing) and isMainModule:
-  var db = open(":memory:", "", "", "")
-  exec(db, sql"create table tbl1(one varchar(10), two smallint)", [])
-  exec(db, sql"insert into tbl1 values('hello!',10)", [])
-  exec(db, sql"insert into tbl1 values('goodbye', 20)", [])
-  var p1 = db.prepare "create table tbl2(one varchar(10), two smallint)"
-  exec(db, p1)
-  finalize(p1)
-  var p2 = db.prepare "insert into tbl2 values('hello!',10)"
-  exec(db, p2)
-  finalize(p2)
-  var p3 = db.prepare "insert into tbl2 values('goodbye', 20)"
-  exec(db, p3)
-  finalize(p3)
-  #db.query("create table tbl1(one varchar(10), two smallint)")
-  #db.query("insert into tbl1 values('hello!',10)")
-  #db.query("insert into tbl1 values('goodbye', 20)")
-  for r in db.rows(sql"select * from tbl1", []):
-    echo(r[0], r[1])
-  for r in db.instantRows(sql"select * from tbl1", []):
-    echo(r[0], r[1])
-  var p4 =  db.prepare "select * from tbl2"
-  for r in db.rows(p4):
-    echo(r[0], r[1])
-  finalize(p4)
-  var i5 = 0
-  var p5 =  db.prepare "select * from tbl2"
-  for r in db.instantRows(p5):
-    inc i5
-    echo(r[0], r[1])
-  assert i5 == 2
-  finalize(p5)
-
-  for r in db.rows(sql"select * from tbl2", []):
-    echo(r[0], r[1])
-  for r in db.instantRows(sql"select * from tbl2", []):
-    echo(r[0], r[1])
-  var p6 = db.prepare "select * from tbl2 where one = ? "
-  p6.bindParams("goodbye")
-  var rowsP3 = 0
-  for r in db.rows(p6):
-    rowsP3 = 1
-    echo(r[0], r[1])
-  assert rowsP3 == 1
-  finalize(p6)
-
-  var p7 = db.prepare "select * from tbl2 where two=?"
-  p7.bindParams(20'i32)
-  when sizeof(int) == 4:
-    p7.bindParams(20)
-  var rowsP = 0
-  for r in db.rows(p7):
-    rowsP = 1
-    echo(r[0], r[1])
-  assert rowsP == 1
-  finalize(p7)
-
-  exec(db, sql"CREATE TABLE photos(ID INTEGER PRIMARY KEY AUTOINCREMENT, photo BLOB)")
-  var p8 = db.prepare "INSERT INTO photos (ID,PHOTO) VALUES (?,?)"
-  var d = "abcdefghijklmnopqrstuvwxyz"
-  p8.bindParams(1'i32, "abcdefghijklmnopqrstuvwxyz")
-  exec(db, p8)
-  finalize(p8)
-  var p10 = db.prepare "INSERT INTO photos (ID,PHOTO) VALUES (?,?)"
-  p10.bindParams(2'i32,nil)
-  exec(db, p10)
-  exec( db, p10, 3, nil)
-  finalize(p10)
-  for r in db.rows(sql"select * from photos where ID = 1", []):
-    assert r[1].len == d.len
-    assert r[1] == d
-  var i6 = 0
-  for r in db.rows(sql"select * from photos where ID = 3", []):
-    i6 = 1
-  assert i6 == 1
-  var p9 = db.prepare("select * from photos where PHOTO is ?")
-  p9.bindParams(nil)
-  var rowsP2 = 0
-  for r in db.rows(p9):
-    rowsP2 = 1
-    echo(r[0], repr r[1])
-  assert rowsP2 == 1
-  finalize(p9)
-
-  db_sqlite.close(db)
diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim
index e9dd49df0..39d238055 100644
--- a/lib/impure/nre.nim
+++ b/lib/impure/nre.nim
@@ -20,15 +20,17 @@ when defined(js):
 ## search the internet for a wide variety of third-party documentation and
 ## tools.
 ##
-## **Note**: If you love `sequtils.toSeq` we have bad news for you. This
-## library doesn't work with it due to documented compiler limitations. As
-## a workaround, use this:
+## .. warning:: If you love `sequtils.toSeq` we have bad news for you. This
+##   library doesn't work with it due to documented compiler limitations. As
+##   a workaround, use this:
 runnableExamples:
   # either `import std/nre except toSeq` or fully qualify `sequtils.toSeq`:
   import std/sequtils
   iterator iota(n: int): int =
     for i in 0..<n: yield i
   assert sequtils.toSeq(iota(3)) == @[0, 1, 2]
+## .. note:: There are also alternative nimble packages such as [tinyre](https://github.com/khchen/tinyre)
+##   and [regex](https://github.com/nitely/nim-regex).
 ## Licencing
 ## ---------
 ##
@@ -59,12 +61,12 @@ runnableExamples:
   assert find("uxabc", re"(?<=x|y)ab", start = 1).get.captures[-1] == "ab"
   assert find("uxabc", re"ab", start = 3).isNone
 
-from pcre import nil
+from std/pcre import nil
 import nre/private/util
-import tables
-from strutils import `%`
-import options
-from unicode import runeLenAt
+import std/tables
+from std/strutils import `%`
+import std/options
+from std/unicode import runeLenAt
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -215,9 +217,11 @@ type
     ## code.
 
 proc destroyRegex(pattern: Regex) =
+  `=destroy`(pattern.pattern)
   pcre.free_substring(cast[cstring](pattern.pcreObj))
   if pattern.pcreExtra != nil:
     pcre.free_study(pattern.pcreExtra)
+  `=destroy`(pattern.captureNameToId)
 
 proc getinfo[T](pattern: Regex, opt: cint): T =
   let retcode = pcre.fullinfo(pattern.pcreObj, pattern.pcreExtra, opt, addr result)
diff --git a/lib/impure/nre/private/util.nim b/lib/impure/nre/private/util.nim
index d227dcba3..ed8420776 100644
--- a/lib/impure/nre/private/util.nim
+++ b/lib/impure/nre/private/util.nim
@@ -1,5 +1,5 @@
 ## INTERNAL FILE FOR USE ONLY BY nre.nim.
-import tables
+import std/tables
 
 const Ident = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
 const StartIdent = Ident - {'0'..'9'}
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index 935c83671..f4fc26380 100644
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -22,8 +22,6 @@ runnableExamples("-r:off"):
     if line.len > 0: echo line
   echo "exiting"
 
-when defined(nimPreviewSlimSystem):
-  import std/syncio
 
 when defined(windows):
   when defined(nimPreviewSlimSystem):
@@ -57,7 +55,7 @@ elif defined(genode):
     stdin.readLine(line)
 
 else:
-  import linenoise
+  import std/linenoise
 
   proc readLineFromStdin*(prompt: string, line: var string): bool {.
                           tags: [ReadIOEffect, WriteIOEffect].} =
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index c647b9442..053c6ab55 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -17,6 +17,10 @@ when defined(js):
 ## C library. This means that your application will depend on the PCRE
 ## library's licence when using this module, which should not be a problem
 ## though.
+##
+## .. note:: There are also alternative nimble packages such as [tinyre](https://github.com/khchen/tinyre)
+##   and [regex](https://github.com/nitely/nim-regex).
+##
 ## PCRE's licence follows:
 ##
 ## .. include:: ../../doc/regexprs.txt
@@ -32,7 +36,7 @@ runnableExamples:
     # can't match start of string since we're starting at 1
 
 import
-  pcre, strutils, rtarrays
+  std/[pcre, strutils, rtarrays]
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -61,10 +65,16 @@ type
     ## is raised if the pattern is no valid regular expression.
 
 when defined(gcDestructors):
-  proc `=destroy`(x: var RegexDesc) =
-    pcre.free_substring(cast[cstring](x.h))
-    if not isNil(x.e):
-      pcre.free_study(x.e)
+  when defined(nimAllowNonVarDestructor):
+    proc `=destroy`(x: RegexDesc) =
+      pcre.free_substring(cast[cstring](x.h))
+      if not isNil(x.e):
+        pcre.free_study(x.e)
+  else:
+    proc `=destroy`(x: var RegexDesc) =
+      pcre.free_substring(cast[cstring](x.h))
+      if not isNil(x.e):
+        pcre.free_study(x.e)
 
 proc raiseInvalidRegex(msg: string) {.noinline, noreturn.} =
   var e: ref RegexError
@@ -450,7 +460,7 @@ template `=~` *(s: string, pattern: Regex): untyped =
       elif line =~ re"\s*(\#.*)": # matches a comment
         # note that the implicit `matches` array is different from 1st branch
         result = $(matches[0],)
-      else: doAssert false
+      else: raiseAssert "unreachable"
       doAssert not declared(matches)
     doAssert parse("NAME = LENA") == """("NAME", "LENA")"""
     doAssert parse("   # comment ... ") == """("# comment ... ",)"""
diff --git a/lib/js/asyncjs.nim b/lib/js/asyncjs.nim
index 364f7a21a..9b043f3e5 100644
--- a/lib/js/asyncjs.nim
+++ b/lib/js/asyncjs.nim
@@ -90,6 +90,8 @@ proc replaceReturn(node: var NimNode) =
       node[z] = nnkReturnStmt.newTree(value)
     elif son.kind == nnkAsgn and son[0].kind == nnkIdent and $son[0] == "result":
       node[z] = nnkAsgn.newTree(son[0], nnkCall.newTree(jsResolve, son[1]))
+    elif son.kind in RoutineNodes:
+      discard
     else:
       replaceReturn(son)
     inc z
@@ -100,10 +102,18 @@ proc isFutureVoid(node: NimNode): bool =
            node[1].kind == nnkIdent and $node[1] == "void"
 
 proc generateJsasync(arg: NimNode): NimNode =
-  if arg.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}:
+  if arg.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo, nnkProcTy}:
       error("Cannot transform this node kind into an async proc." &
             " proc/method definition or lambda node expected.")
 
+  # Transform type X = proc (): something {.async.}
+  # into      type X = proc (): Future[something]
+  if arg.kind == nnkProcTy:
+    result = arg
+    if arg[0][0].kind == nnkEmpty:
+      result[0][0] = quote do: Future[void]
+    return result
+
   result = arg
   var isVoid = false
   let jsResolve = ident("jsResolve")
@@ -233,7 +243,7 @@ since (1, 5, 1):
     else:
       type A = impl(onSuccess(default(T)))
     var ret: A
-    asm "`ret` = `future`.then(`onSuccess`, `onReject`)"
+    {.emit: "`ret` = `future`.then(`onSuccess`, `onReject`);".}
     return ret
 
   proc catch*[T](future: Future[T], onReject: OnReject): Future[void] =
@@ -256,4 +266,4 @@ since (1, 5, 1):
 
       discard main()
 
-    asm "`result` = `future`.catch(`onReject`)"
+    {.emit: "`result` = `future`.catch(`onReject`);".}
diff --git a/lib/js/dom.nim b/lib/js/dom.nim
index 36434846a..be2a34db1 100644
--- a/lib/js/dom.nim
+++ b/lib/js/dom.nim
@@ -1423,7 +1423,7 @@ when defined(nodejs):
         parent.childNodes[i] = newNode
         return
       inc i
-    doAssert false, "old node not in node list"
+    raiseAssert "old node not in node list"
 
   proc removeChild*(parent, child: Node) =
     child.parentNode = nil
@@ -1433,7 +1433,7 @@ when defined(nodejs):
         parent.childNodes.delete(i)
         return
       inc i
-    doAssert false, "old node not in node list"
+    raiseAssert "old node not in node list"
 
   proc insertBefore*(parent, newNode, before: Node) =
     appendChild(parent, newNode)
@@ -1445,7 +1445,7 @@ when defined(nodejs):
         parent.childNodes[i-1] = newNode
         return
       inc i
-    #doAssert false, "before not in node list"
+    #raiseAssert "before not in node list"
 
   proc createElement*(d: Document, identifier: cstring): Element =
     new(result)
@@ -1503,7 +1503,7 @@ proc confirm*(w: Window, msg: cstring): bool
 proc disableExternalCapture*(w: Window)
 proc enableExternalCapture*(w: Window)
 proc find*(w: Window, text: cstring, caseSensitive = false,
-           backwards = false)
+           backwards = false): bool
 proc focus*(w: Window)
 proc forward*(w: Window)
 proc getComputedStyle*(w: Window, e: Node, pe: Node = nil): Style
@@ -1655,7 +1655,7 @@ proc item*(list: TouchList, i: int): Touch
 proc clearData*(dt: DataTransfer, format: cstring)
 proc getData*(dt: DataTransfer, format: cstring): cstring
 proc setData*(dt: DataTransfer, format: cstring, data: cstring)
-proc setDragImage*(dt: DataTransfer, img: Element, xOffset: int64, yOffset: int64)
+proc setDragImage*(dt: DataTransfer, img: Element, xOffset: int, yOffset: int)
 
 # DataTransferItem "methods"
 proc getAsFile*(dti: DataTransferItem): File
@@ -1682,7 +1682,6 @@ proc `$`*(s: Selection): string = $(s.toString())
 # Storage "methods"
 proc getItem*(s: Storage, key: cstring): cstring
 proc setItem*(s: Storage, key, value: cstring)
-proc hasItem*(s: Storage, key: cstring): bool
 proc clear*(s: Storage)
 proc removeItem*(s: Storage, key: cstring)
 
@@ -1832,3 +1831,11 @@ since (1, 7):
 
   proc matches*(self: Node; cssSelector: cstring): bool {.importjs: "(#.$1(#) || false)".}
     ## https://developer.mozilla.org/en-US/docs/Web/API/Element/matches
+
+
+since (2, 1):
+  type VisualViewport* {.importc.} = ref object of EventTarget
+    offsetLeft*, offsetTop*, pageLeft*, pageTop*, width*, height*, scale*: float
+    onResize*, onScroll*: proc (event: Event) {.closure.}
+
+  func visualViewport*(self: Window): VisualViewport {.importjs: "#.$1", nodecl.}
diff --git a/lib/js/jscore.nim b/lib/js/jscore.nim
index 781e8fd57..be353875c 100644
--- a/lib/js/jscore.nim
+++ b/lib/js/jscore.nim
@@ -13,7 +13,7 @@
 ## specific requirements and solely targets JavaScript, you should be using
 ## the relevant functions in the `math`, `json`, and `times` stdlib
 ## modules instead.
-import std/private/since
+import std/private/[since, jsutils]
 
 when not defined(js):
   {.error: "This module only works on the JavaScript platform".}
@@ -74,9 +74,16 @@ proc parse*(d: DateLib, s: cstring): int {.importcpp.}
 proc newDate*(): DateTime {.
   importcpp: "new Date()".}
 
-proc newDate*(date: int|int64|string): DateTime {.
+proc newDate*(date: int|string): DateTime {.
   importcpp: "new Date(#)".}
 
+whenJsNoBigInt64:
+  proc newDate*(date: int64): DateTime {.
+    importcpp: "new Date(#)".}
+do:
+  proc newDate*(date: int64): DateTime {.
+    importcpp: "new Date(Number(#))".}
+
 proc newDate*(year, month, day, hours, minutes,
              seconds, milliseconds: int): DateTime {.
   importcpp: "new Date(#,#,#,#,#,#,#)".}
@@ -88,20 +95,27 @@ proc getMilliseconds*(d: DateTime): int {.importcpp.}
 proc getMinutes*(d: DateTime): int {.importcpp.}
 proc getMonth*(d: DateTime): int {.importcpp.}
 proc getSeconds*(d: DateTime): int {.importcpp.}
-proc getYear*(d: DateTime): int {.importcpp.}
 proc getTime*(d: DateTime): int {.importcpp.}
-proc toString*(d: DateTime): cstring {.importcpp.}
+proc getTimezoneOffset*(d: DateTime): int {.importcpp.}
 proc getUTCDate*(d: DateTime): int {.importcpp.}
+proc getUTCDay*(d: DateTime): int {.importcpp.}
 proc getUTCFullYear*(d: DateTime): int {.importcpp.}
 proc getUTCHours*(d: DateTime): int {.importcpp.}
 proc getUTCMilliseconds*(d: DateTime): int {.importcpp.}
 proc getUTCMinutes*(d: DateTime): int {.importcpp.}
 proc getUTCMonth*(d: DateTime): int {.importcpp.}
 proc getUTCSeconds*(d: DateTime): int {.importcpp.}
-proc getUTCDay*(d: DateTime): int {.importcpp.}
-proc getTimezoneOffset*(d: DateTime): int {.importcpp.}
+proc getYear*(d: DateTime): int {.importcpp.}
+
 proc setFullYear*(d: DateTime, year: int) {.importcpp.}
 
+func toDateString*(d: DateTime): cstring {.importcpp.}
+func toISOString*(d: DateTime): cstring {.importcpp.}
+func toJSON*(d: DateTime): cstring {.importcpp.}
+proc toString*(d: DateTime): cstring {.importcpp.}
+func toTimeString*(d: DateTime): cstring {.importcpp.}
+func toUTCString*(d: DateTime): cstring {.importcpp.}
+
 #JSON library
 proc stringify*(l: JsonLib, s: JsRoot): cstring {.importcpp.}
 proc parse*(l: JsonLib, s: cstring): JsRoot {.importcpp.}
diff --git a/lib/js/jsffi.nim b/lib/js/jsffi.nim
index db40e7515..d50d58ae5 100644
--- a/lib/js/jsffi.nim
+++ b/lib/js/jsffi.nim
@@ -227,36 +227,40 @@ macro `.`*(obj: JsObject, field: untyped): JsObject =
     assert obj.a.to(int) == 20
   if validJsName($field):
     let importString = "#." & $field
+    let helperName = genSym(nskProc, "helper")
     result = quote do:
-      proc helper(o: JsObject): JsObject
-        {.importjs: `importString`, gensym.}
-      helper(`obj`)
+      proc `helperName`(o: JsObject): JsObject
+        {.importjs: `importString`.}
+      `helperName`(`obj`)
   else:
     if not mangledNames.hasKey($field):
       mangledNames[$field] = mangleJsName($field)
     let importString = "#." & mangledNames[$field]
+    let helperName = genSym(nskProc, "helper")
     result = quote do:
-      proc helper(o: JsObject): JsObject
-        {.importjs: `importString`, gensym.}
-      helper(`obj`)
+      proc `helperName`(o: JsObject): JsObject
+        {.importjs: `importString`.}
+      `helperName`(`obj`)
 
 macro `.=`*(obj: JsObject, field, value: untyped): untyped =
   ## Experimental dot accessor (set) for type JsObject.
   ## Sets the value of a property of name `field` in a JsObject `x` to `value`.
   if validJsName($field):
     let importString = "#." & $field & " = #"
+    let helperName = genSym(nskProc, "helper")
     result = quote do:
-      proc helper(o: JsObject, v: auto)
-        {.importjs: `importString`, gensym.}
-      helper(`obj`, `value`)
+      proc `helperName`(o: JsObject, v: auto)
+        {.importjs: `importString`.}
+      `helperName`(`obj`, `value`)
   else:
     if not mangledNames.hasKey($field):
       mangledNames[$field] = mangleJsName($field)
     let importString = "#." & mangledNames[$field] & " = #"
+    let helperName = genSym(nskProc, "helper")
     result = quote do:
-      proc helper(o: JsObject, v: auto)
-        {.importjs: `importString`, gensym.}
-      helper(`obj`, `value`)
+      proc `helperName`(o: JsObject, v: auto)
+        {.importjs: `importString`.}
+      `helperName`(`obj`, `value`)
 
 macro `.()`*(obj: JsObject,
              field: untyped,
@@ -283,10 +287,11 @@ macro `.()`*(obj: JsObject,
     if not mangledNames.hasKey($field):
       mangledNames[$field] = mangleJsName($field)
     importString = "#." & mangledNames[$field] & "(@)"
-  result = quote:
-    proc helper(o: JsObject): JsObject
-      {.importjs: `importString`, gensym, discardable.}
-    helper(`obj`)
+  let helperName = genSym(nskProc, "helper")
+  result = quote do:
+    proc `helperName`(o: JsObject): JsObject
+      {.importjs: `importString`, discardable.}
+    `helperName`(`obj`)
   for idx in 0 ..< args.len:
     let paramName = newIdentNode("param" & $idx)
     result[0][3].add newIdentDefs(paramName, newIdentNode("JsObject"))
@@ -303,10 +308,11 @@ macro `.`*[K: cstring, V](obj: JsAssoc[K, V],
     if not mangledNames.hasKey($field):
       mangledNames[$field] = mangleJsName($field)
     importString = "#." & mangledNames[$field]
+  let helperName = genSym(nskProc, "helper")
   result = quote do:
-    proc helper(o: type(`obj`)): `obj`.V
-      {.importjs: `importString`, gensym.}
-    helper(`obj`)
+    proc `helperName`(o: type(`obj`)): `obj`.V
+      {.importjs: `importString`.}
+    `helperName`(`obj`)
 
 macro `.=`*[K: cstring, V](obj: JsAssoc[K, V],
                                     field: untyped,
@@ -320,10 +326,11 @@ macro `.=`*[K: cstring, V](obj: JsAssoc[K, V],
     if not mangledNames.hasKey($field):
       mangledNames[$field] = mangleJsName($field)
     importString = "#." & mangledNames[$field] & " = #"
+  let helperName = genSym(nskProc, "helper")
   result = quote do:
-    proc helper(o: type(`obj`), v: `obj`.V)
-      {.importjs: `importString`, gensym.}
-    helper(`obj`, `value`)
+    proc `helperName`(o: type(`obj`), v: `obj`.V)
+      {.importjs: `importString`.}
+    `helperName`(`obj`, `value`)
 
 macro `.()`*[K: cstring, V: proc](obj: JsAssoc[K, V],
                                            field: untyped,
@@ -461,7 +468,7 @@ proc replaceSyms(n: NimNode): NimNode =
     for i in 0..<n.len:
       result[i] = replaceSyms(n[i])
 
-macro bindMethod*(procedure: typed): auto =
+macro bindMethod*(procedure: typed): auto {.deprecated: "Don't use it with closures".} =
   ## Takes the name of a procedure and wraps it into a lambda missing the first
   ## argument, which passes the JavaScript builtin `this` as the first
   ## argument to the procedure. Returns the resulting lambda.
diff --git a/lib/js/jsre.nim b/lib/js/jsre.nim
index 19888aaa9..2d931eb20 100644
--- a/lib/js/jsre.nim
+++ b/lib/js/jsre.nim
@@ -34,6 +34,9 @@ func compile*(self: RegExp; pattern: cstring; flags: cstring) {.importjs: "#.com
 func replace*(pattern: cstring; self: RegExp; replacement: cstring): cstring {.importjs: "#.replace(#, #)".}
   ## Returns a new string with some or all matches of a pattern replaced by given replacement
 
+func replace*(pattern: cstring, self: RegExp, cb: proc (args: varargs[cstring]): cstring): cstring {.importcpp.}
+  ## Returns a new string with some or all matches of a pattern replaced by given callback function
+
 func split*(pattern: cstring; self: RegExp): seq[cstring] {.importjs: "(#.split(#) || [])".}
   ## Divides a string into an ordered list of substrings and returns the array
 
@@ -55,7 +58,7 @@ func contains*(pattern: cstring; self: RegExp): bool =
     assert jsregex in r"abc"
     assert jsregex notin r"abcd"
     assert "xabc".contains jsregex
-  asm "`result` = `self`.test(`pattern`);"
+  {.emit: "`result` = `self`.test(`pattern`);".}
 
 func startsWith*(pattern: cstring; self: RegExp): bool =
   ## Tests if string starts with given RegExp
@@ -88,5 +91,7 @@ runnableExamples:
   assert "do1ne".split(jsregex) == @["do".cstring, "ne".cstring]
   jsregex.compile(r"[lw]", r"i")
   assert "hello world".replace(jsregex,"X") == "heXlo world"
+  jsregex.compile(r"([a-z])\1*", r"g")
+  assert "abbcccdddd".replace(jsregex, proc (m: varargs[cstring]): cstring = ($m[0] & $(m.len)).cstring) == "a1b2c3d4"
   let digitsRegex: RegExp = newRegExp(r"\d")
   assert "foo".match(digitsRegex) == @[]
diff --git a/lib/nimbase.h b/lib/nimbase.h
index b9b2695c9..cf0c8002b 100644
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -10,14 +10,12 @@
 /* compiler symbols:
 __BORLANDC__
 _MSC_VER
-__WATCOMC__
-__LCC__
 __GNUC__
-__DMC__
-__POCC__
 __TINYC__
 __clang__
 __AVR__
+__arm__
+__EMSCRIPTEN__
 */
 
 
@@ -89,11 +87,8 @@ __AVR__
 #endif
 
 /* calling convention mess ----------------------------------------------- */
-#if defined(__GNUC__) || defined(__LCC__) || defined(__POCC__) \
-                      || defined(__TINYC__)
+#if defined(__GNUC__) || defined(__TINYC__)
   /* these should support C99's inline */
-  /* the test for __POCC__ has to come before the test for _MSC_VER,
-     because PellesC defines _MSC_VER too. This is brain-dead. */
 #  define N_INLINE(rettype, name) inline rettype name
 #elif defined(__BORLANDC__) || defined(_MSC_VER)
 /* Borland's compiler is really STRANGE here; note that the __fastcall
@@ -101,21 +96,13 @@ __AVR__
    the return type, so we do not handle this mess in the code generator
    but rather here. */
 #  define N_INLINE(rettype, name) __inline rettype name
-#elif defined(__DMC__)
-#  define N_INLINE(rettype, name) inline rettype name
-#elif defined(__WATCOMC__)
-#  define N_INLINE(rettype, name) __inline rettype name
 #else /* others are less picky: */
 #  define N_INLINE(rettype, name) rettype __inline name
 #endif
 
 #define N_INLINE_PTR(rettype, name) rettype (*name)
 
-#if defined(__POCC__)
-#  define NIM_CONST /* PCC is really picky with const modifiers */
-#  undef _MSC_VER /* Yeah, right PCC defines _MSC_VER even if it is
-                     not that compatible. Well done. */
-#elif defined(__cplusplus)
+#if defined(__cplusplus)
 #  define NIM_CONST /* C++ is picky with const modifiers */
 #else
 #  define NIM_CONST  const
@@ -125,12 +112,17 @@ __AVR__
   NIM_THREADVAR declaration based on
   http://stackoverflow.com/questions/18298280/how-to-declare-a-variable-as-thread-local-portably
 */
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
+#if defined _WIN32
+#  if defined _MSC_VER || defined __BORLANDC__
+#    define NIM_THREADVAR __declspec(thread)
+#  else
+#    define NIM_THREADVAR __thread
+#  endif
+#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112 && !defined __STDC_NO_THREADS__
 #  define NIM_THREADVAR _Thread_local
 #elif defined _WIN32 && ( \
        defined _MSC_VER || \
        defined __ICL || \
-       defined __DMC__ || \
        defined __BORLANDC__ )
 #  define NIM_THREADVAR __declspec(thread)
 #elif defined(__TINYC__) || defined(__GENODE__)
@@ -149,8 +141,7 @@ __AVR__
 #endif
 
 /* --------------- how int64 constants should be declared: ----------- */
-#if defined(__GNUC__) || defined(__LCC__) || \
-    defined(__POCC__) || defined(__DMC__) || defined(_MSC_VER)
+#if defined(__GNUC__) || defined(_MSC_VER)
 #  define IL64(x) x##LL
 #else /* works only without LL */
 #  define IL64(x) ((NI64)x)
@@ -188,12 +179,13 @@ __AVR__
 #  define N_THISCALL_PTR(rettype, name) rettype (__thiscall *name)
 #  define N_SAFECALL_PTR(rettype, name) rettype (__stdcall *name)
 
-#  ifdef __cplusplus
-#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport)
+#  ifdef __EMSCRIPTEN__
+#    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport) __attribute__((used))
+#    define N_LIB_EXPORT_VAR  __declspec(dllexport) __attribute__((used))
 #  else
 #    define N_LIB_EXPORT  NIM_EXTERNC __declspec(dllexport)
+#    define N_LIB_EXPORT_VAR  __declspec(dllexport)
 #  endif
-#  define N_LIB_EXPORT_VAR  __declspec(dllexport)
 #  define N_LIB_IMPORT  extern __declspec(dllimport)
 #else
 #  define N_LIB_PRIVATE __attribute__((visibility("hidden")))
@@ -222,8 +214,13 @@ __AVR__
 #    define N_FASTCALL_PTR(rettype, name) rettype (*name)
 #    define N_SAFECALL_PTR(rettype, name) rettype (*name)
 #  endif
-#  define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default")))
-#  define N_LIB_EXPORT_VAR  __attribute__((visibility("default")))
+#  ifdef __EMSCRIPTEN__
+#    define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default"), used))
+#    define N_LIB_EXPORT_VAR  __attribute__((visibility("default"), used))
+#  else
+#    define N_LIB_EXPORT NIM_EXTERNC __attribute__((visibility("default")))
+#    define N_LIB_EXPORT_VAR  __attribute__((visibility("default")))
+#  endif
 #  define N_LIB_IMPORT  extern
 #endif
 
@@ -241,8 +238,7 @@ __AVR__
 
 #define N_NOINLINE_PTR(rettype, name) rettype (*name)
 
-#if defined(__BORLANDC__) || defined(__WATCOMC__) || \
-    defined(__POCC__) || defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
+#if defined(__BORLANDC__) || defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
 /* these compilers have a fastcall so use it: */
 #  ifdef __TINYC__
 #    define N_NIMCALL(rettype, name) rettype __attribute((__fastcall)) name
@@ -277,11 +273,15 @@ __AVR__
 #elif defined(__cplusplus)
 #define NIM_STATIC_ASSERT(x, msg) static_assert((x), msg)
 #else
-#define NIM_STATIC_ASSERT(x, msg) typedef int NIM_STATIC_ASSERT_AUX[(x) ? 1 : -1];
+#define _NIM_STATIC_ASSERT_FINAL(x, append_name) typedef int NIM_STATIC_ASSERT_AUX ## append_name[(x) ? 1 : -1];
+#define _NIM_STATIC_ASSERT_STAGE_3(x, line)      _NIM_STATIC_ASSERT_FINAL(x, _AT_LINE_##line)
+#define _NIM_STATIC_ASSERT_STAGE_2(x, line)      _NIM_STATIC_ASSERT_STAGE_3(x, line)
+#define NIM_STATIC_ASSERT(x, msg)                _NIM_STATIC_ASSERT_STAGE_2(x,__LINE__)
 // On failure, your C compiler will say something like:
-//   "error: 'NIM_STATIC_ASSERT_AUX' declared as an array with a negative size"
-// we could use a better fallback to also show line number, using:
-// http://www.pixelbeat.org/programming/gcc/static_assert.html
+//   "error: 'NIM_STATIC_ASSERT_AUX_AT_LINE_XXX' declared as an array with a negative size"
+// Adding the line number helps to avoid redefinitions which are not allowed in
+// old GCC versions, however the order of evaluation for __LINE__ is a little tricky,
+// hence all the helper macros. See https://stackoverflow.com/a/3385694 for more info.
 #endif
 
 /* C99 compiler? */
@@ -290,8 +290,7 @@ __AVR__
 #endif
 
 /* Known compiler with stdint.h that doesn't fit the general pattern? */
-#if defined(__LCC__) || defined(__DMC__) || defined(__POCC__) || \
-  defined(__AVR__) || (defined(__cplusplus) && (__cplusplus < 201103))
+#if defined(__AVR__) || (defined(__cplusplus) && (__cplusplus < 201103))
 #  define HAVE_STDINT_H
 #endif
 
@@ -351,8 +350,7 @@ NIM_STATIC_ASSERT(CHAR_BIT == 8, "");
                               the generated code does not rely on it anymore */
 #endif
 
-#if defined(__BORLANDC__) || defined(__DMC__) \
-   || defined(__WATCOMC__) || defined(_MSC_VER)
+#if defined(__BORLANDC__) || defined(_MSC_VER)
 typedef signed char NI8;
 typedef signed short int NI16;
 typedef signed int NI32;
@@ -480,7 +478,7 @@ typedef char* NCSTRING;
 /* declared size of a sequence/variable length array: */
 #if defined(__cplusplus) && defined(__clang__)
 #  define SEQ_DECL_SIZE 1
-#elif defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER)
+#elif defined(__GNUC__) || defined(_MSC_VER)
 #  define SEQ_DECL_SIZE /* empty is correct! */
 #else
 #  define SEQ_DECL_SIZE 1000000
@@ -587,9 +585,16 @@ NIM_STATIC_ASSERT(sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8, "P
   #define nimMulInt64(a, b, res) __builtin_smulll_overflow(a, b, (long long int*)res)
 
   #if NIM_INTBITS == 32
-    #define nimAddInt(a, b, res) __builtin_sadd_overflow(a, b, res)
-    #define nimSubInt(a, b, res) __builtin_ssub_overflow(a, b, res)
-    #define nimMulInt(a, b, res) __builtin_smul_overflow(a, b, res)
+    #if defined(__arm__) && defined(__GNUC__)
+      /* arm-none-eabi-gcc targets defines int32_t as long int */
+      #define nimAddInt(a, b, res) __builtin_saddl_overflow(a, b, res)
+      #define nimSubInt(a, b, res) __builtin_ssubl_overflow(a, b, res)
+      #define nimMulInt(a, b, res) __builtin_smull_overflow(a, b, res)
+    #else
+      #define nimAddInt(a, b, res) __builtin_sadd_overflow(a, b, res)
+      #define nimSubInt(a, b, res) __builtin_ssub_overflow(a, b, res)
+      #define nimMulInt(a, b, res) __builtin_smul_overflow(a, b, res)
+    #endif
   #else
     /* map it to the 'long long' variant */
     #define nimAddInt(a, b, res) __builtin_saddll_overflow(a, b, (long long int*)res)
diff --git a/lib/nimhcr.nim b/lib/nimhcr.nim
index 8bccfc22e..e87bb2413 100644
--- a/lib/nimhcr.nim
+++ b/lib/nimhcr.nim
@@ -219,7 +219,7 @@ when defined(createNimHcr):
   when system.appType != "lib":
     {.error: "This file has to be compiled as a library!".}
 
-  import os, tables, sets, times, strutils, reservedmem, dynlib
+  import std/[os, tables, sets, times, strutils, reservedmem, dynlib]
 
   template trace(args: varargs[untyped]) =
     when defined(testNimHcr) or defined(traceHcr):
@@ -305,7 +305,7 @@ when defined(createNimHcr):
       hash: string
       gen: int
       lastModification: Time
-      handlers: seq[tuple[isBefore: bool, cb: proc ()]]
+      handlers: seq[tuple[isBefore: bool, cb: proc () {.nimcall.}]]
 
   proc newModuleDesc(): ModuleDesc =
     result.procs = initTable[string, ProcSym]()
@@ -557,8 +557,12 @@ when defined(createNimHcr):
     # Future versions of NIMHCR won't use the GC, because all globals and the
     # metadata needed to access them will be placed in shared memory, so they
     # can be manipulated from external programs without reloading.
-    GC_disable()
-    defer: GC_enable()
+    when declared(GC_disable):
+      GC_disable()
+      defer: GC_enable()
+    elif declared(GC_disableOrc):
+      GC_disableOrc()
+      defer: GC_enableOrc()
 
     inc(generation)
     trace "HCR RELOADING: ", generation
@@ -598,7 +602,7 @@ when defined(createNimHcr):
       hashToModuleMap.del(modules[name].hash)
       modules.del(name)
 
-  proc hcrAddEventHandler*(isBefore: bool, cb: proc ()) {.nimhcr.} =
+  proc hcrAddEventHandler*(isBefore: bool, cb: proc () {.nimcall.}) {.nimhcr.} =
     modules[currentModule].handlers.add(
       (isBefore: isBefore, cb: cb))
 
@@ -649,7 +653,7 @@ elif defined(hotcodereloading) or defined(testNimHcr):
 
     proc hcrPerformCodeReload*() {.nimhcr.}
 
-    proc hcrAddEventHandler*(isBefore: bool, cb: proc ()) {.nimhcr.}
+    proc hcrAddEventHandler*(isBefore: bool, cb: proc () {.nimcall.}) {.nimhcr.}
 
     proc hcrMarkGlobals*() {.raises: [], nimhcr, nimcall, gcsafe.}
 
@@ -661,7 +665,7 @@ elif defined(hotcodereloading) or defined(testNimHcr):
       # TODO
       false
 
-    proc hcrAddEventHandler*(isBefore: bool, cb: proc ()) =
+    proc hcrAddEventHandler*(isBefore: bool, cb: proc () {.nimcall.}) =
       # TODO
       discard
 
diff --git a/lib/nimrtl.nim b/lib/nimrtl.nim
index 93349b287..a2fb6ce60 100644
--- a/lib/nimrtl.nim
+++ b/lib/nimrtl.nim
@@ -36,5 +36,5 @@ when not defined(createNimRtl):
   {.error: "This file has to be compiled with '-d:createNimRtl'".}
 
 import
-  parseutils, strutils, parseopt, parsecfg, strtabs, unicode, pegs, ropes,
-  os, osproc, times, cstrutils
+  std/[parseutils, strutils, parseopt, parsecfg, strtabs, unicode, pegs, ropes,
+  os, osproc, times, cstrutils]
diff --git a/lib/packages/docutils/dochelpers.nim b/lib/packages/docutils/dochelpers.nim
index c7f7f73f5..0a41d85b5 100644
--- a/lib/packages/docutils/dochelpers.nim
+++ b/lib/packages/docutils/dochelpers.nim
@@ -14,6 +14,7 @@
 ## matches it with `generated`, produced from `PNode` by ``docgen.rst``.
 
 import rstast
+import std/strutils
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio]
@@ -35,6 +36,12 @@ type
                                ## name-type seq, e.g. for proc
     outType*: string           ## result type, e.g. for proc
 
+proc `$`*(s: LangSymbol): string =  # for debug
+  ("(symkind=$1, symTypeKind=$2, name=$3, generics=$4, isGroup=$5, " &
+   "parametersProvided=$6, parameters=$7, outType=$8)") % [
+      s.symKind, s.symTypeKind , s.name, s.generics, $s.isGroup,
+      $s.parametersProvided, $s.parameters, s.outType]
+
 func nimIdentBackticksNormalize*(s: string): string =
   ## Normalizes the string `s` as a Nim identifier.
   ##
@@ -71,6 +78,12 @@ func nimIdentBackticksNormalize*(s: string): string =
     else: discard  # just omit '`' or ' '
   if j != s.len: setLen(result, j)
 
+proc langSymbolGroup*(kind: string, name: string): LangSymbol =
+  if kind notin ["proc", "func", "macro", "method", "iterator",
+                 "template", "converter"]:
+    raise newException(ValueError, "unknown symbol kind $1" % [kind])
+  result = LangSymbol(symKind: kind, name: name, isGroup: true)
+
 proc toLangSymbol*(linkText: PRstNode): LangSymbol =
   ## Parses `linkText` into a more structured form using a state machine.
   ##
@@ -82,11 +95,14 @@ proc toLangSymbol*(linkText: PRstNode): LangSymbol =
   ##
   ## This proc should be kept in sync with the `renderTypes` proc from
   ## ``compiler/typesrenderer.nim``.
-  assert linkText.kind in {rnRstRef, rnInner}
+  template fail(msg: string) =
+    raise newException(ValueError, msg)
+  if linkText.kind notin {rnRstRef, rnInner}:
+    fail("toLangSymbol: wrong input kind " & $linkText.kind)
 
   const NimDefs = ["proc", "func", "macro", "method", "iterator",
                    "template", "converter", "const", "type", "var",
-                   "enum", "object", "tuple"]
+                   "enum", "object", "tuple", "module"]
   template resolveSymKind(x: string) =
     if x in ["enum", "object", "tuple"]:
       result.symKind = "type"
@@ -109,11 +125,11 @@ proc toLangSymbol*(linkText: PRstNode): LangSymbol =
   template flushIdent() =
     if curIdent != "":
       case state
-      of inBeginning:  doAssert false, "incorrect state inBeginning"
+      of inBeginning:  fail("incorrect state inBeginning")
       of afterSymKind:  resolveSymKind curIdent
-      of beforeSymbolName:  doAssert false, "incorrect state beforeSymbolName"
+      of beforeSymbolName:  fail("incorrect state beforeSymbolName")
       of atSymbolName: result.name = curIdent.nimIdentBackticksNormalize
-      of afterSymbolName: doAssert false, "incorrect state afterSymbolName"
+      of afterSymbolName: fail("incorrect state afterSymbolName")
       of genericsPar: result.generics = curIdent
       of parameterName: result.parameters.add (curIdent, "")
       of parameterType:
@@ -273,7 +289,7 @@ proc match*(generated: LangSymbol, docLink: LangSymbol): bool =
         if g.`type` == d.name:
           onlyType = true  # only types, not names, are provided in `docLink`
       if onlyType:
-        result = g.`type` == d.name:
+        result = g.`type` == d.name
       else:
         if d.`type` != "":
           result = g.`type` == d.`type`
diff --git a/lib/packages/docutils/highlite.nim b/lib/packages/docutils/highlite.nim
index 3f65c8cc4..f8376f46c 100644
--- a/lib/packages/docutils/highlite.nim
+++ b/lib/packages/docutils/highlite.nim
@@ -57,8 +57,8 @@
 ## as program output.
 
 import
-  strutils
-from algorithm import binarySearch
+  std/strutils
+from std/algorithm import binarySearch
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio]
@@ -324,17 +324,18 @@ proc nimNextToken(g: var GeneralTokenizer, keywords: openArray[string] = @[]) =
       pos = nimNumber(g, pos)
     of '\'':
       inc(pos)
-      g.kind = gtCharLit
-      while true:
-        case g.buf[pos]
-        of '\0', '\r', '\n':
-          break
-        of '\'':
-          inc(pos)
-          break
-        of '\\':
-          inc(pos, 2)
-        else: inc(pos)
+      if g.kind != gtPunctuation:
+        g.kind = gtCharLit
+        while true:
+          case g.buf[pos]
+          of '\0', '\r', '\n':
+            break
+          of '\'':
+            inc(pos)
+            break
+          of '\\':
+            inc(pos, 2)
+          else: inc(pos)
     of '\"':
       inc(pos)
       if (g.buf[pos] == '\"') and (g.buf[pos + 1] == '\"'):
@@ -498,6 +499,9 @@ proc clikeNextToken(g: var GeneralTokenizer, keywords: openArray[string],
           of '\0':
             break
           else: inc(pos)
+      else:
+        g.kind = gtOperator
+        while g.buf[pos] in OpChars: inc(pos)
     of '#':
       inc(pos)
       if hasPreprocessor in flags:
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index f81be7a50..706c50689 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -21,8 +21,10 @@
 ## turned on by passing ``options:`` [RstParseOptions] to [proc rstParse].
 
 import
-  os, strutils, rstast, dochelpers, std/enumutils, algorithm, lists, sequtils,
-  std/private/miscdollars, tables, strscans
+  std/[os, strutils, enumutils, algorithm, lists, sequtils,
+  tables, strscans]
+import dochelpers, rstidx, rstast
+import std/private/miscdollars
 from highlite import SourceLanguage, getSourceLanguage
 
 when defined(nimPreviewSlimSystem):
@@ -40,7 +42,7 @@ type
     roNimFile                 ## set for Nim files where default interpreted
                               ## text role should be :nim:
     roSandboxDisabled         ## this option enables certain options
-                              ## (e.g. raw, include)
+                              ## (e.g. raw, include, importdoc)
                               ## which are disabled by default as they can
                               ## enable users to read arbitrary data and
                               ## perform XSS if the parser is used in a web
@@ -73,11 +75,17 @@ type
     mwUnsupportedLanguage = "language '$1' not supported",
     mwUnsupportedField = "field '$1' not supported",
     mwRstStyle = "RST style: $1",
+    mwUnusedImportdoc = "importdoc for '$1' is not used",
     meSandboxedDirective = "disabled directive: '$1'",
 
   MsgHandler* = proc (filename: string, line, col: int, msgKind: MsgKind,
                        arg: string) {.closure, gcsafe.} ## what to do in case of an error
   FindFileHandler* = proc (filename: string): string {.closure, gcsafe.}
+  FindRefFileHandler* =
+    proc (targetRelPath: string):
+         tuple[targetPath: string, linkRelPath: string] {.closure, gcsafe.}
+    ## returns where .html or .idx file should be found by its relative path;
+    ## `linkRelPath` is a prefix to be added before a link anchor from such file
 
 proc rstnodeToRefname*(n: PRstNode): string
 proc addNodes*(n: PRstNode): string
@@ -333,7 +341,8 @@ type
     arInternalRst,  ## For automatically generated RST anchors (from
                     ## headings, footnotes, inline internal targets):
                     ## case-insensitive, 1-space-significant (by RST spec)
-    arNim   ## For anchors generated by ``docgen.rst``: Nim-style case
+    arExternalRst,  ## For external .nim doc comments or .rst/.md
+    arNim   ## For anchors generated by ``docgen.nim``: Nim-style case
             ## sensitivity, etc. (see `proc normalizeNimName`_ for details)
     arHyperlink,  ## For links with manually set anchors in
                   ## form `text <pagename.html#anchor>`_
@@ -343,17 +352,22 @@ type
     footnoteAnchor = "footnote anchor",
     headlineAnchor = "implicitly-generated headline anchor"
   AnchorSubst = object
-    info: TLineInfo         # where the anchor was defined
+    info: TLineInfo         # the file where the anchor was defined
     priority: int
     case kind: range[arInternalRst .. arNim]
     of arInternalRst:
       anchorType: RstAnchorKind
       target: PRstNode
+    of arExternalRst:
+      anchorTypeExt: RstAnchorKind
+      refnameExt: string
     of arNim:
+      module: FileIndex     # anchor's module (generally not the same as file)
       tooltip: string       # displayed tooltip for Nim-generated anchors
       langSym: LangSymbol
       refname: string     # A reference name that will be inserted directly
                           # into HTML/Latex.
+      external: bool
   AnchorSubstTable = Table[string, seq[AnchorSubst]]
                          # use `seq` to account for duplicate anchors
   FootnoteType = enum
@@ -366,12 +380,18 @@ type
     kind: FootnoteType  # discriminator
     number: int         # valid for fnManualNumber (always) and fnAutoNumber,
                         # fnAutoNumberLabel after resolveSubs is called
-    autoNumIdx: int     # order of occurence: fnAutoNumber, fnAutoNumberLabel
-    autoSymIdx: int     # order of occurence: fnAutoSymbol
+    autoNumIdx: int     # order of occurrence: fnAutoNumber, fnAutoNumberLabel
+    autoSymIdx: int     # order of occurrence: fnAutoSymbol
     label: string       # valid for fnAutoNumberLabel
   RstFileTable* = object
     filenameToIdx*: Table[string, FileIndex]
     idxToFilename*: seq[string]
+  ImportdocInfo = object
+    used: bool             # was this import used?
+    fromInfo: TLineInfo    # place of `.. importdoc::` directive
+    idxPath: string        # full path to ``.idx`` file
+    linkRelPath: string    # prefix before target anchor
+    title: string          # document title obtained from ``.idx``
   RstSharedState = object
     options*: RstParseOptions   # parsing options
     hLevels: LevelMap           # hierarchy of heading styles
@@ -393,12 +413,17 @@ type
     footnotes: seq[FootnoteSubst] # correspondence b/w footnote label,
                                   # number, order of occurrence
     msgHandler: MsgHandler      # How to handle errors.
-    findFile: FindFileHandler   # How to find files.
+    findFile: FindFileHandler   # How to find files for include.
+    findRefFile: FindRefFileHandler
+                                # How to find files imported by importdoc.
     filenames*: RstFileTable    # map file name <-> FileIndex (for storing
                                 # file names for warnings after 1st stage)
     currFileIdx*: FileIndex     # current index in `filenames`
     tocPart*: seq[PRstNode]     # all the headings of a document
     hasToc*: bool
+    idxImports*: Table[string, ImportdocInfo]
+                                # map `importdoc`ed filename -> it's info
+    nimFileImported*: bool      # Was any ``.nim`` module `importdoc`ed ?
 
   PRstSharedState* = ref RstSharedState
   ManualAnchor = object
@@ -419,6 +444,7 @@ type
                                 ## because RST can have >1 alias per 1 anchor
 
   EParseError* = object of ValueError
+  SectionParser = proc (p: var RstParser): PRstNode {.nimcall, gcsafe.}
 
 const
   LineRstInit* = 1  ## Initial line number for standalone RST text
@@ -452,6 +478,9 @@ proc defaultFindFile*(filename: string): string =
   if fileExists(filename): result = filename
   else: result = ""
 
+proc defaultFindRefFile*(filename: string): (string, string) =
+  (filename, "")
+
 proc defaultRole(options: RstParseOptions): string =
   if roNimFile in options: "nim" else: "literal"
 
@@ -492,12 +521,19 @@ proc getFilename(filenames: RstFileTable, fid: FileIndex): string =
         $fid.int, $(filenames.len - 1)])
   result = filenames.idxToFilename[fid.int]
 
+proc getFilename(s: PRstSharedState, subst: AnchorSubst): string =
+  getFilename(s.filenames, subst.info.fileIndex)
+
+proc getModule(s: PRstSharedState, subst: AnchorSubst): string =
+  result = getFilename(s.filenames, subst.module)
+
 proc currFilename(s: PRstSharedState): string =
   getFilename(s.filenames, s.currFileIdx)
 
 proc newRstSharedState*(options: RstParseOptions,
                         filename: string,
                         findFile: FindFileHandler,
+                        findRefFile: FindRefFileHandler,
                         msgHandler: MsgHandler,
                         hasToc: bool): PRstSharedState =
   let r = defaultRole(options)
@@ -507,6 +543,9 @@ proc newRstSharedState*(options: RstParseOptions,
       options: options,
       msgHandler: if not isNil(msgHandler): msgHandler else: defaultMsgHandler,
       findFile: if not isNil(findFile): findFile else: defaultFindFile,
+      findRefFile:
+        if not isNil(findRefFile): findRefFile
+        else: defaultFindRefFile,
       hasToc: hasToc
   )
   setCurrFilename(result, filename)
@@ -525,6 +564,14 @@ proc rstMessage(p: RstParser, msgKind: MsgKind, arg: string) =
 proc rstMessage(s: PRstSharedState, msgKind: MsgKind, arg: string) =
   s.msgHandler(s.currFilename, LineRstInit, ColRstInit, msgKind, arg)
 
+proc rstMessage(s: PRstSharedState, msgKind: MsgKind, arg: string;
+                line, col: int) =
+  s.msgHandler(s.currFilename, line, col, msgKind, arg)
+
+proc rstMessage(s: PRstSharedState, filename: string, msgKind: MsgKind,
+                arg: string) =
+  s.msgHandler(filename, LineRstInit, ColRstInit, msgKind, arg)
+
 proc rstMessage*(filenames: RstFileTable, f: MsgHandler,
                  info: TLineInfo, msgKind: MsgKind, arg: string) =
   ## Print warnings using `info`, i.e. in 2nd-pass warnings for
@@ -541,6 +588,31 @@ proc rstMessage(p: RstParser, msgKind: MsgKind) =
                              p.col + currentTok(p).col, msgKind,
                              currentTok(p).symbol)
 
+# Functions `isPureRst` & `stopOrWarn` address differences between
+# Markdown and RST:
+# * Markdown always tries to continue working. If it is really impossible
+#   to parse a markup element, its proc just returns `nil` and parsing
+#   continues for it as for normal text paragraph.
+#   The downside is that real mistakes/typos are often silently ignored.
+#   The same applies to legacy `RstMarkdown` mode for nimforum.
+# * RST really signals errors. The downside is that it's more intrusive -
+#   the user must escape special syntax with \ explicitly.
+#
+# TODO: we need to apply this strategy to all markup elements eventually.
+
+func isPureRst(p: RstParser): bool = roSupportMarkdown notin p.s.options
+func isRst(p: RstParser): bool = roPreferMarkdown notin p.s.options
+func isMd(p: RstParser): bool = roPreferMarkdown in p.s.options
+func isMd(s: PRstSharedState): bool = roPreferMarkdown in s.options
+
+proc stopOrWarn(p: RstParser, errorType: MsgKind, arg: string) =
+  let realMsgKind = if isPureRst(p): errorType else: mwRstStyle
+  rstMessage(p, realMsgKind, arg)
+
+proc stopOrWarn(p: RstParser, errorType: MsgKind, arg: string, line, col: int) =
+  let realMsgKind = if isPureRst(p): errorType else: mwRstStyle
+  rstMessage(p, realMsgKind, arg, line, col)
+
 proc currInd(p: RstParser): int =
   result = p.indentStack[high(p.indentStack)]
 
@@ -756,6 +828,14 @@ proc internalRefPriority(k: RstAnchorKind): int =
   of footnoteAnchor: result = 4
   of headlineAnchor: result = 3
 
+proc `$`(subst: AnchorSubst): string =  # for debug
+  let s =
+    case subst.kind
+    of arInternalRst: "type=" & $subst.anchorType
+    of arExternalRst: "type=" & $subst.anchorTypeExt
+    of arNim: "langsym=" & $subst.langSym
+  result = "(kind=$1, priority=$2, $3)" % [$subst.kind, $subst.priority, s]
+
 proc addAnchorRst(p: var RstParser, name: string, target: PRstNode,
                   anchorType: RstAnchorKind) =
   ## Associates node `target` (which has field `anchor`) with an
@@ -771,31 +851,49 @@ proc addAnchorRst(p: var RstParser, name: string, target: PRstNode,
                     info: prevLineInfo(p), anchorType: anchorType))
   p.curAnchors.setLen 0
 
-proc addAnchorNim*(s: var PRstSharedState, refn: string, tooltip: string,
+proc addAnchorExtRst(s: var PRstSharedState, key: string, refn: string,
+                  anchorType: RstAnchorKind, info: TLineInfo) =
+  let name = key.toLowerAscii
+  let prio = internalRefPriority(anchorType)
+  s.anchors.mgetOrPut(name, newSeq[AnchorSubst]()).add(
+      AnchorSubst(kind: arExternalRst, refnameExt: refn, priority: prio,
+                  info: info,
+                  anchorTypeExt: anchorType))
+
+proc addAnchorNim*(s: var PRstSharedState, external: bool, refn: string, tooltip: string,
                    langSym: LangSymbol, priority: int,
-                   info: TLineInfo) =
+                   info: TLineInfo, module: FileIndex) =
   ## Adds an anchor `refn`, which follows
   ## the rule `arNim` (i.e. a symbol in ``*.nim`` file)
   s.anchors.mgetOrPut(langSym.name, newSeq[AnchorSubst]()).add(
-      AnchorSubst(kind: arNim, refname: refn, langSym: langSym,
+      AnchorSubst(kind: arNim, external: external, refname: refn, langSym: langSym,
                   tooltip: tooltip, priority: priority,
                   info: info))
 
 proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
                        info: TLineInfo):
                       seq[AnchorSubst] =
-  let langSym = toLangSymbol(signature)
+  var langSym: LangSymbol
+  try:
+    langSym = toLangSymbol(signature)
+  except ValueError:  # parsing failed, not a Nim symbol
+    return
   let substitutions = s.anchors.getOrDefault(langSym.name,
                                              newSeq[AnchorSubst]())
   if substitutions.len == 0:
     return
-  # map symKind (like "proc") -> found symbols/groups:
-  var found: Table[string, seq[AnchorSubst]]
-  for s in substitutions:
-    if s.kind == arNim:
-      if match(s.langSym, langSym):
-        found.mgetOrPut(s.langSym.symKind, newSeq[AnchorSubst]()).add s
-  for symKind, sList in found:
+  # logic to select only groups instead of concrete symbols
+  # with overloads, note that the same symbol can be defined
+  # in multiple modules and `importdoc`ed:
+  type GroupKey = tuple[symKind: string, origModule: string]
+  # map (symKind, file) (like "proc", "os.nim") -> found symbols/groups:
+  var found: Table[GroupKey, seq[AnchorSubst]]
+  for subst in substitutions:
+    if subst.kind == arNim:
+      if match(subst.langSym, langSym):
+        let key: GroupKey = (subst.langSym.symKind, getModule(s, subst))
+        found.mgetOrPut(key, newSeq[AnchorSubst]()).add subst
+  for key, sList in found:
     if sList.len == 1:
       result.add sList[0]
     else:  # > 1, there are overloads, potential ambiguity in this `symKind`
@@ -812,14 +910,16 @@ proc findMainAnchorNim(s: PRstSharedState, signature: PRstNode,
             result.add s
             foundGroup = true
             break
-        doAssert foundGroup, "docgen has not generated the group"
+        doAssert(foundGroup,
+                 "docgen has not generated the group for $1 (file $2)" % [
+                 langSym.name, getModule(s, sList[0]) ])
 
 proc findMainAnchorRst(s: PRstSharedState, linkText: string, info: TLineInfo):
                       seq[AnchorSubst] =
   let name = linkText.toLowerAscii
   let substitutions = s.anchors.getOrDefault(name, newSeq[AnchorSubst]())
   for s in substitutions:
-    if s.kind == arInternalRst:
+    if s.kind in {arInternalRst, arExternalRst}:
       result.add s
 
 proc addFootnoteNumManual(p: var RstParser, num: int) =
@@ -1426,7 +1526,7 @@ proc parseMarkdownCodeblockFields(p: var RstParser): PRstNode =
     result = nil
   else:
     result = newRstNode(rnFieldList)
-  while currentTok(p).kind != tkIndent:
+  while currentTok(p).kind notin {tkIndent, tkEof}:
     if currentTok(p).kind == tkWhite:
       inc p.idx
     else:
@@ -1503,6 +1603,7 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode =
   else:
     args = nil
   var n = newLeaf("")
+  var isFirstLine = true
   while true:
     if currentTok(p).kind == tkEof:
       rstMessage(p, meMissingClosing,
@@ -1514,7 +1615,8 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode =
       inc p.idx, 2
       break
     elif currentTok(p).kind == tkIndent:
-      n.text.add "\n"
+      if not isFirstLine:
+        n.text.add "\n"
       if currentTok(p).ival > baseCol:
         n.text.add " ".repeat(currentTok(p).ival - baseCol)
       elif currentTok(p).ival < baseCol:
@@ -1524,6 +1626,7 @@ proc parseMarkdownCodeblock(p: var RstParser): PRstNode =
     else:
       n.text.add(currentTok(p).symbol)
       inc p.idx
+    isFirstLine = false
   result.sons[0] = args
   if result.sons[2] == nil:
     var lb = newRstNode(rnLiteralBlock)
@@ -1597,7 +1700,7 @@ proc parseMarkdownLink(p: var RstParser; father: PRstNode): bool =
   else:
     result = false
 
-proc getFootnoteType(label: PRstNode): (FootnoteType, int) =
+proc getRstFootnoteType(label: PRstNode): (FootnoteType, int) =
   if label.sons.len >= 1 and label.sons[0].kind == rnLeaf and
       label.sons[0].text == "#":
     if label.sons.len == 1:
@@ -1610,12 +1713,23 @@ proc getFootnoteType(label: PRstNode): (FootnoteType, int) =
   elif label.len == 1 and label.sons[0].kind == rnLeaf:
     try:
       result = (fnManualNumber, parseInt(label.sons[0].text))
-    except:
+    except ValueError:
       result = (fnCitation, -1)
   else:
     result = (fnCitation, -1)
 
-proc parseFootnoteName(p: var RstParser, reference: bool): PRstNode =
+proc getMdFootnoteType(label: PRstNode): (FootnoteType, int) =
+  try:
+    result = (fnManualNumber, parseInt(label.sons[0].text))
+  except ValueError:
+    result = (fnAutoNumberLabel, -1)
+
+proc getFootnoteType(s: PRstSharedState, label: PRstNode): (FootnoteType, int) =
+  ## Returns footnote/citation type and manual number (if present).
+  if isMd(s): getMdFootnoteType(label)
+  else: getRstFootnoteType(label)
+
+proc parseRstFootnoteName(p: var RstParser, reference: bool): PRstNode =
   ## parse footnote/citation label. Precondition: start at `[`.
   ## Label text should be valid ref. name symbol, otherwise nil is returned.
   var i = p.idx + 1
@@ -1645,6 +1759,41 @@ proc parseFootnoteName(p: var RstParser, reference: bool): PRstNode =
     inc i
   p.idx = i
 
+proc isMdFootnoteName(p: RstParser, reference: bool): bool =
+  ## Pandoc Markdown footnote extension.
+  let j = p.idx
+  result = p.tok[j].symbol == "[" and p.tok[j+1].symbol == "^" and
+           p.tok[j+2].kind == tkWord
+
+proc parseMdFootnoteName(p: var RstParser, reference: bool): PRstNode =
+  if isMdFootnoteName(p, reference):
+    result = newRstNode(rnInner)
+    var j = p.idx + 2
+    while p.tok[j].kind in {tkWord, tkOther} or
+        validRefnamePunct(p.tok[j].symbol):
+      result.add newLeaf(p.tok[j].symbol)
+      inc j
+    if j == p.idx + 2:
+      return nil
+    if p.tok[j].symbol == "]":
+      if reference:
+        p.idx = j + 1  # skip ]
+      else:
+        if p.tok[j+1].symbol == ":":
+          p.idx = j + 2  # skip ]:
+        else:
+          result = nil
+    else:
+      result = nil
+  else:
+    result = nil
+
+proc parseFootnoteName(p: var RstParser, reference: bool): PRstNode =
+  if isMd(p): parseMdFootnoteName(p, reference)
+  else:
+    if isInlineMarkupStart(p, "["): parseRstFootnoteName(p, reference)
+    else: nil
+
 proc isMarkdownCodeBlock(p: RstParser, idx: int): bool =
   let tok = p.tok[idx]
   template allowedSymbol: bool =
@@ -1711,16 +1860,12 @@ proc parseInline(p: var RstParser, father: PRstNode) =
       var n = newRstNode(rnSubstitutionReferences, info=lineInfo(p, p.idx+1))
       parseUntil(p, n, "|", false)
       father.add(n)
-    elif roSupportMarkdown in p.s.options and
-        currentTok(p).symbol == "[" and nextTok(p).symbol != "[" and
-        parseMarkdownLink(p, father):
-      discard "parseMarkdownLink already processed it"
-    elif isInlineMarkupStart(p, "[") and nextTok(p).symbol != "[" and
+    elif currentTok(p).symbol == "[" and nextTok(p).symbol != "[" and
          (n = parseFootnoteName(p, reference=true); n != nil):
       var nn = newRstNode(rnFootnoteRef)
       nn.info = lineInfo(p, saveIdx+1)
       nn.add n
-      let (fnType, _) = getFootnoteType(n)
+      let (fnType, _) = getFootnoteType(p.s, n)
       case fnType
       of fnAutoSymbol:
         p.s.lineFootnoteSymRef.add lineInfo(p)
@@ -1728,6 +1873,10 @@ proc parseInline(p: var RstParser, father: PRstNode) =
         p.s.lineFootnoteNumRef.add lineInfo(p)
       else: discard
       father.add(nn)
+    elif roSupportMarkdown in p.s.options and
+        currentTok(p).symbol == "[" and nextTok(p).symbol != "[" and
+        parseMarkdownLink(p, father):
+      discard "parseMarkdownLink already processed it"
     else:
       if roSupportSmilies in p.s.options:
         let n = parseSmiley(p)
@@ -1865,8 +2014,26 @@ proc getMdBlockIndent(p: RstParser): int =
     else:
       result = nextIndent                 # allow parsing next lines [case.3]
 
-template isRst(p: RstParser): bool = roPreferMarkdown notin p.s.options
-template isMd(p: RstParser): bool = roPreferMarkdown in p.s.options
+proc indFollows(p: RstParser): bool =
+  result = currentTok(p).kind == tkIndent and currentTok(p).ival > currInd(p)
+
+proc parseBlockContent(p: var RstParser, father: var PRstNode,
+                       contentParser: SectionParser): bool {.gcsafe.} =
+  ## parse the final content part of explicit markup blocks (directives,
+  ## footnotes, etc). Returns true if succeeded.
+  if currentTok(p).kind != tkIndent or indFollows(p):
+    let blockIndent = getWrappableIndent(p)
+    pushInd(p, blockIndent)
+    let content = contentParser(p)
+    popInd(p)
+    father.add content
+    result = true
+
+proc parseSectionWrapper(p: var RstParser): PRstNode =
+  result = newRstNode(rnInner)
+  parseSection(p, result)
+  while result.kind == rnInner and result.len == 1:
+    result = result.sons[0]
 
 proc parseField(p: var RstParser): PRstNode =
   ## Returns a parsed rnField node.
@@ -2052,17 +2219,20 @@ proc isAdornmentHeadline(p: RstParser, adornmentIdx: int): bool =
     while p.tok[i].kind notin {tkEof, tkIndent}:
       headlineLen += p.tok[i].symbol.len
       inc i
-    result = p.tok[adornmentIdx].symbol.len >= headlineLen and
-         headlineLen != 0
-    if result:
-      result = result and p.tok[i].kind == tkIndent and
-         p.tok[i+1].kind == tkAdornment and
-         p.tok[i+1].symbol == p.tok[adornmentIdx].symbol
-      if not result:
-        failure = "(underline '" & p.tok[i+1].symbol & "' does not match " &
-            "overline '" & p.tok[adornmentIdx].symbol & "')"
-    else:
-      failure = "(overline '" & p.tok[adornmentIdx].symbol & "' is too short)"
+    if p.tok[i].kind == tkIndent and
+       p.tok[i+1].kind == tkAdornment and
+       p.tok[i+1].symbol[0] == p.tok[adornmentIdx].symbol[0]:
+      result = p.tok[adornmentIdx].symbol.len >= headlineLen and
+           headlineLen != 0
+      if result:
+        result = p.tok[i+1].symbol == p.tok[adornmentIdx].symbol
+        if not result:
+          failure = "(underline '" & p.tok[i+1].symbol & "' does not match " &
+              "overline '" & p.tok[adornmentIdx].symbol & "')"
+      else:
+        failure = "(overline '" & p.tok[adornmentIdx].symbol & "' is too short)"
+    else:  # it's not overline/underline section, not reporting error
+      return false
   if not result:
     rstMessage(p, meNewSectionExpected, failure)
 
@@ -2189,16 +2359,19 @@ proc whichSection(p: RstParser): RstNodeKind =
       result = rnLineBlock
     elif roSupportMarkdown in p.s.options and isMarkdownBlockQuote(p):
       result = rnMarkdownBlockQuote
-    elif match(p, p.idx + 1, "i") and isAdornmentHeadline(p, p.idx):
+    elif (match(p, p.idx + 1, "i") and not match(p, p.idx + 2, "I")) and
+         isAdornmentHeadline(p, p.idx):
       result = rnOverline
     else:
-      result = rnLeaf
+      result = rnParagraph
   of tkPunct:
     if isMarkdownHeadline(p):
       result = rnMarkdownHeadline
     elif roSupportMarkdown in p.s.options and predNL(p) and
         match(p, p.idx, "| w") and findPipe(p, p.idx+3):
       result = rnMarkdownTable
+    elif isMd(p) and isMdFootnoteName(p, reference=false):
+      result = rnFootnote
     elif currentTok(p).symbol == "|" and isLineBlock(p):
       result = rnLineBlock
     elif roSupportMarkdown in p.s.options and isMarkdownBlockQuote(p):
@@ -2375,7 +2548,9 @@ proc parseParagraph(p: var RstParser, result: PRstNode) =
           result.addIfNotNil(parseLineBlock(p))
         of rnMarkdownBlockQuote:
           result.addIfNotNil(parseMarkdownBlockQuote(p))
-        else: break
+        else:
+          dec p.idx  # allow subsequent block to be parsed as another section
+          break
       else:
         break
     of tkPunct:
@@ -2518,11 +2693,11 @@ proc getColumns(p: RstParser, cols: var RstCols, startIdx: int): int =
 proc checkColumns(p: RstParser, cols: RstCols) =
   var i = p.idx
   if p.tok[i].symbol[0] != '=':
-    rstMessage(p, mwRstStyle,
+    stopOrWarn(p, meIllformedTable,
                "only tables with `=` columns specification are allowed")
   for col in 0 ..< cols.len:
     if tokEnd(p, i) != cols[col].stop:
-      rstMessage(p, meIllformedTable,
+      stopOrWarn(p, meIllformedTable,
                  "end of table column #$1 should end at position $2" % [
                    $(col+1), $(cols[col].stop+ColRstOffset)],
                  p.tok[i].line, tokEnd(p, i))
@@ -2531,12 +2706,12 @@ proc checkColumns(p: RstParser, cols: RstCols) =
       if p.tok[i].kind == tkWhite:
         inc i
       if p.tok[i].kind notin {tkIndent, tkEof}:
-        rstMessage(p, meIllformedTable, "extraneous column specification")
+        stopOrWarn(p, meIllformedTable, "extraneous column specification")
     elif p.tok[i].kind == tkWhite:
       inc i
     else:
-      rstMessage(p, meIllformedTable, "no enough table columns",
-                 p.tok[i].line, p.tok[i].col)
+      stopOrWarn(p, meIllformedTable,
+                 "no enough table columns", p.tok[i].line, p.tok[i].col)
 
 proc getSpans(p: RstParser, nextLine: int,
               cols: RstCols, unitedCols: RstCols): seq[int] =
@@ -2591,17 +2766,18 @@ proc parseSimpleTableRow(p: var RstParser, cols: RstCols, colChar: char): PRstNo
       if tokEnd(p) <= colEnd(nCell):
         if tokStart(p) < colStart(nCell):
           if currentTok(p).kind != tkWhite:
-            rstMessage(p, meIllformedTable,
+            stopOrWarn(p, meIllformedTable,
                        "this word crosses table column from the left")
-          else:
-            inc p.idx
+            row[nCell].add(currentTok(p).symbol)
         else:
           row[nCell].add(currentTok(p).symbol)
-          inc p.idx
+        inc p.idx
       else:
         if tokStart(p) < colEnd(nCell) and currentTok(p).kind != tkWhite:
-          rstMessage(p, meIllformedTable,
+          stopOrWarn(p, meIllformedTable,
                      "this word crosses table column from the right")
+          row[nCell].add(currentTok(p).symbol)
+          inc p.idx
         inc nCell
     if currentTok(p).kind == tkIndent: inc p.idx
     if tokEnd(p) <= colEnd(0): break
@@ -2764,7 +2940,7 @@ proc parseOptionList(p: var RstParser): PRstNode =
       break
 
 proc parseMdDefinitionList(p: var RstParser): PRstNode =
-  ## Parses (Pandoc/kramdown/PHPextra) Mardkown definition lists.
+  ## Parses (Pandoc/kramdown/PHPextra) Markdown definition lists.
   result = newRstNodeA(p, rnMdDefList)
   let termCol = currentTok(p).col
   while true:
@@ -2899,13 +3075,13 @@ proc parseEnumList(p: var RstParser): PRstNode =
       let enumerator = p.tok[p.idx + 1 + wildIndex[w]].symbol
       # check that it's in sequence: enumerator == next(prevEnum)
       if "n" in wildcards[w]:  # arabic numeral
-        let prevEnumI = try: parseInt(prevEnum) except: 1
+        let prevEnumI = try: parseInt(prevEnum) except ValueError: 1
         if enumerator in autoEnums:
           if prevAE != "" and enumerator != prevAE:
             break
           prevAE = enumerator
           curEnum = prevEnumI + 1
-        else: curEnum = (try: parseInt(enumerator) except: 1)
+        else: curEnum = (try: parseInt(enumerator) except ValueError: 1)
         if curEnum - prevEnumI != 1:
           break
         prevEnum = enumerator
@@ -2920,6 +3096,57 @@ proc parseEnumList(p: var RstParser): PRstNode =
     else:
       break
 
+proc prefix(ftnType: FootnoteType): string =
+  case ftnType
+  of fnManualNumber: result = "footnote-"
+  of fnAutoNumber: result = "footnoteauto-"
+  of fnAutoNumberLabel: result = "footnote-"
+  of fnAutoSymbol: result = "footnotesym-"
+  of fnCitation: result = "citation-"
+
+proc parseFootnote(p: var RstParser): PRstNode {.gcsafe.} =
+  ## Parses footnotes and citations, always returns 2 sons:
+  ##
+  ## 1) footnote label, always containing rnInner with 1 or more sons
+  ## 2) footnote body, which may be nil
+  var label: PRstNode
+  if isRst(p):
+    inc p.idx  # skip space after `..`
+  label = parseFootnoteName(p, reference=false)
+  if label == nil:
+    if isRst(p):
+      dec p.idx
+    return nil
+  result = newRstNode(rnFootnote)
+  result.add label
+  let (fnType, i) = getFootnoteType(p.s, label)
+  var name = ""
+  var anchor = fnType.prefix
+  case fnType
+  of fnManualNumber:
+    addFootnoteNumManual(p, i)
+    anchor.add $i
+  of fnAutoNumber, fnAutoNumberLabel:
+    name = rstnodeToRefname(label)
+    addFootnoteNumAuto(p, name)
+    if fnType == fnAutoNumberLabel:
+      anchor.add name
+    else:  # fnAutoNumber
+      result.order = p.s.lineFootnoteNum.len
+      anchor.add $result.order
+  of fnAutoSymbol:
+    addFootnoteSymAuto(p)
+    result.order = p.s.lineFootnoteSym.len
+    anchor.add $p.s.lineFootnoteSym.len
+  of fnCitation:
+    anchor.add rstnodeToRefname(label)
+  addAnchorRst(p, anchor, target = result, anchorType = footnoteAnchor)
+  result.anchor = anchor
+  if currentTok(p).kind == tkWhite: inc p.idx
+  discard parseBlockContent(p, result, parseSectionWrapper)
+  if result.len < 2:
+    result.add nil
+
 proc sonKind(father: PRstNode, i: int): RstNodeKind =
   result = rnLeaf
   if i < father.len: result = father.sons[i].kind
@@ -2962,6 +3189,7 @@ proc parseSection(p: var RstParser, result: PRstNode) =
     of rnLineBlock: a = parseLineBlock(p)
     of rnMarkdownBlockQuote: a = parseMarkdownBlockQuote(p)
     of rnDirective: a = parseDotDot(p)
+    of rnFootnote: a = parseFootnote(p)
     of rnEnumList: a = parseEnumList(p)
     of rnLeaf: rstMessage(p, meNewSectionExpected, "(syntax error)")
     of rnParagraph: discard
@@ -2987,12 +3215,6 @@ proc parseSection(p: var RstParser, result: PRstNode) =
     result.sons[0] = newRstNode(rnInner, result.sons[0].sons,
                                 anchor=result.sons[0].anchor)
 
-proc parseSectionWrapper(p: var RstParser): PRstNode =
-  result = newRstNode(rnInner)
-  parseSection(p, result)
-  while result.kind == rnInner and result.len == 1:
-    result = result.sons[0]
-
 proc parseDoc(p: var RstParser): PRstNode =
   result = parseSectionWrapper(p)
   if currentTok(p).kind != tkEof:
@@ -3002,7 +3224,6 @@ type
   DirFlag = enum
     hasArg, hasOptions, argIsFile, argIsWord
   DirFlags = set[DirFlag]
-  SectionParser = proc (p: var RstParser): PRstNode {.nimcall, gcsafe.}
 
 proc parseDirective(p: var RstParser, k: RstNodeKind, flags: DirFlags): PRstNode =
   ## Parses arguments and options for a directive block.
@@ -3045,21 +3266,6 @@ proc parseDirective(p: var RstParser, k: RstNodeKind, flags: DirFlags): PRstNode
       popInd(p)
   result.add(options)
 
-proc indFollows(p: RstParser): bool =
-  result = currentTok(p).kind == tkIndent and currentTok(p).ival > currInd(p)
-
-proc parseBlockContent(p: var RstParser, father: var PRstNode,
-                       contentParser: SectionParser): bool {.gcsafe.} =
-  ## parse the final content part of explicit markup blocks (directives,
-  ## footnotes, etc). Returns true if succeeded.
-  if currentTok(p).kind != tkIndent or indFollows(p):
-    let blockIndent = getWrappableIndent(p)
-    pushInd(p, blockIndent)
-    let content = contentParser(p)
-    popInd(p)
-    father.add content
-    result = true
-
 proc parseDirective(p: var RstParser, k: RstNodeKind, flags: DirFlags,
                     contentParser: SectionParser): PRstNode =
   ## A helper proc that does main work for specific directive procs.
@@ -3251,6 +3457,15 @@ proc dirRaw(p: var RstParser): PRstNode =
   else:
     dirRawAux(p, result, rnRaw, parseSectionWrapper)
 
+proc dirImportdoc(p: var RstParser): PRstNode =
+  result = parseDirective(p, rnDirective, {}, parseLiteralBlock)
+  assert result.sons[2].kind == rnLiteralBlock
+  assert result.sons[2].sons[0].kind == rnLeaf
+  let filenames: seq[string] = split(result.sons[2].sons[0].text, seps = {','})
+  proc rmSpaces(s: string): string = s.split.join("")
+  for origFilename in filenames:
+    p.s.idxImports[origFilename.rmSpaces] = ImportdocInfo(fromInfo: lineInfo(p))
+
 proc selectDir(p: var RstParser, d: string): PRstNode =
   result = nil
   let tok = p.tok[p.idx-2] # report on directive in ".. directive::"
@@ -3271,6 +3486,7 @@ proc selectDir(p: var RstParser, d: string): PRstNode =
   of "hint": result = dirAdmonition(p, d)
   of "image": result = dirImage(p)
   of "important": result = dirAdmonition(p, d)
+  of "importdoc": result = dirImportdoc(p)
   of "include": result = dirInclude(p)
   of "index": result = dirIndex(p)
   of "note": result = dirAdmonition(p, d)
@@ -3286,54 +3502,6 @@ proc selectDir(p: var RstParser, d: string): PRstNode =
   else:
     rstMessage(p, meInvalidDirective, d, tok.line, tok.col)
 
-proc prefix(ftnType: FootnoteType): string =
-  case ftnType
-  of fnManualNumber: result = "footnote-"
-  of fnAutoNumber: result = "footnoteauto-"
-  of fnAutoNumberLabel: result = "footnote-"
-  of fnAutoSymbol: result = "footnotesym-"
-  of fnCitation: result = "citation-"
-
-proc parseFootnote(p: var RstParser): PRstNode {.gcsafe.} =
-  ## Parses footnotes and citations, always returns 2 sons:
-  ##
-  ## 1) footnote label, always containing rnInner with 1 or more sons
-  ## 2) footnote body, which may be nil
-  inc p.idx
-  let label = parseFootnoteName(p, reference=false)
-  if label == nil:
-    dec p.idx
-    return nil
-  result = newRstNode(rnFootnote)
-  result.add label
-  let (fnType, i) = getFootnoteType(label)
-  var name = ""
-  var anchor = fnType.prefix
-  case fnType
-  of fnManualNumber:
-    addFootnoteNumManual(p, i)
-    anchor.add $i
-  of fnAutoNumber, fnAutoNumberLabel:
-    name = rstnodeToRefname(label)
-    addFootnoteNumAuto(p, name)
-    if fnType == fnAutoNumberLabel:
-      anchor.add name
-    else:  # fnAutoNumber
-      result.order = p.s.lineFootnoteNum.len
-      anchor.add $result.order
-  of fnAutoSymbol:
-    addFootnoteSymAuto(p)
-    result.order = p.s.lineFootnoteSym.len
-    anchor.add $p.s.lineFootnoteSym.len
-  of fnCitation:
-    anchor.add rstnodeToRefname(label)
-  addAnchorRst(p, anchor, target = result, anchorType = footnoteAnchor)
-  result.anchor = anchor
-  if currentTok(p).kind == tkWhite: inc p.idx
-  discard parseBlockContent(p, result, parseSectionWrapper)
-  if result.len < 2:
-    result.add nil
-
 proc parseDotDot(p: var RstParser): PRstNode =
   # parse "explicit markup blocks"
   result = nil
@@ -3401,77 +3569,200 @@ proc rstParsePass1*(fragment: string,
   getTokens(fragment, p.tok)
   result = parseDoc(p)
 
-proc preparePass2*(s: PRstSharedState, mainNode: PRstNode) =
+proc extractLinkEnd(x: string): string =
+  ## From links like `path/to/file.html#/%` extract `file.html#/%`.
+  let i = find(x, '#')
+  let last =
+    if i >= 0: i
+    else: x.len - 1
+  let j = rfind(x, '/', start=0, last=last)
+  if j >= 0:
+    result = x[j+1 .. ^1]
+  else:
+    result = x
+
+proc loadIdxFile(s: var PRstSharedState, origFilename: string) =
+  doAssert roSandboxDisabled in s.options
+  var info: TLineInfo
+  info.fileIndex = addFilename(s, origFilename)
+  var (dir, basename, ext) = origFilename.splitFile
+  if ext notin [".md", ".rst", ".nim", ""]:
+    rstMessage(s.filenames, s.msgHandler, s.idxImports[origFilename].fromInfo,
+               meCannotOpenFile, origFilename & ": unknown extension")
+  let idxFilename = dir / basename & ".idx"
+  let (idxPath, linkRelPath) = s.findRefFile(idxFilename)
+  s.idxImports[origFilename].linkRelPath = linkRelPath
+  var
+    fileEntries: seq[IndexEntry]
+    title: IndexEntry
+  try:
+    (fileEntries, title) = parseIdxFile(idxPath)
+  except IOError:
+    rstMessage(s.filenames, s.msgHandler, s.idxImports[origFilename].fromInfo,
+               meCannotOpenFile, idxPath)
+  except ValueError as e:
+    s.msgHandler(idxPath, LineRstInit, ColRstInit, meInvalidField, e.msg)
+
+  var isMarkup = false  # for sanity check to avoid mixing .md <-> .nim
+  for entry in fileEntries:
+    # Though target .idx already has inside it the path to HTML relative
+    # project's root, we won't rely on it and use `linkRelPath` instead.
+    let refn = extractLinkEnd(entry.link)
+    # select either markup (rst/md) or Nim cases:
+    if entry.kind in {ieMarkupTitle, ieNimTitle}:
+      s.idxImports[origFilename].title = entry.keyword
+    case entry.kind
+    of ieIdxRole, ieHeading, ieMarkupTitle:
+      if ext == ".nim" and entry.kind == ieMarkupTitle:
+        rstMessage(s, idxPath, meInvalidField,
+                   $ieMarkupTitle & " in supposedly .nim-derived file")
+      if entry.kind == ieMarkupTitle:
+        isMarkup = true
+      info.line = entry.line.uint16
+      addAnchorExtRst(s, key = entry.keyword, refn = refn,
+                      anchorType = headlineAnchor, info=info)
+    of ieNim, ieNimGroup, ieNimTitle:
+      if ext in [".md", ".rst"] or isMarkup:
+        rstMessage(s, idxPath, meInvalidField,
+                   $entry.kind & " in supposedly markup-derived file")
+      s.nimFileImported = true
+      var langSym: LangSymbol
+      if entry.kind in {ieNim, ieNimTitle}:
+        var q: RstParser
+        initParser(q, s)
+        info.line = entry.line.uint16
+        setLen(q.tok, 0)
+        q.idx = 0
+        getTokens(entry.linkTitle, q.tok)
+        var sons = newSeq[PRstNode](q.tok.len)
+        for i in 0 ..< q.tok.len: sons[i] = newLeaf(q.tok[i].symbol)
+        let linkTitle = newRstNode(rnInner, sons)
+        langSym = linkTitle.toLangSymbol
+      else:  # entry.kind == ieNimGroup
+        langSym = langSymbolGroup(kind=entry.linkTitle, name=entry.keyword)
+      addAnchorNim(s, external = true, refn = refn, tooltip = entry.linkDesc,
+                   langSym = langSym, priority = -4, # lowest
+                   info = info, module = info.fileIndex)
+  doAssert s.idxImports[origFilename].title != ""
+
+proc preparePass2*(s: var PRstSharedState, mainNode: PRstNode, importdoc = true) =
   ## Records titles in node `mainNode` and orders footnotes.
   countTitles(s, mainNode)
   fixHeadlines(s)
   orderFootnotes(s)
+  if importdoc:
+    for origFilename in s.idxImports.keys:
+      loadIdxFile(s, origFilename)
 
 proc resolveLink(s: PRstSharedState, n: PRstNode) : PRstNode =
-    # Associate this link alias with its target and change node kind to
-    # rnHyperlink or rnInternalRef appropriately.
-    var desc, alias: PRstNode
-    if n.kind == rnPandocRef:  # link like [desc][alias]
-      desc = n.sons[0]
-      alias = n.sons[1]
-    else:  # n.kind == rnRstRef, link like `desc=alias`_
-      desc = n
-      alias = n
-    type LinkDef = object
-      ar: AnchorRule
-      priority: int
-      tooltip: string
-      target: PRstNode
-      info: TLineInfo
-    proc cmp(x, y: LinkDef): int =
-      result = cmp(x.priority, y.priority)
-      if result == 0:
-        result = cmp(x.target, y.target)
-    var foundLinks: seq[LinkDef]
-    let refn = rstnodeToRefname(alias)
-    var hyperlinks = findRef(s, refn)
-    for y in hyperlinks:
-      foundLinks.add LinkDef(ar: arHyperlink, priority: refPriority(y.kind),
-                             target: y.value, info: y.info,
-                             tooltip: "(" & $y.kind & ")")
-    let substRst = findMainAnchorRst(s, alias.addNodes, n.info)
-    for subst in substRst:
-      foundLinks.add LinkDef(ar: arInternalRst, priority: subst.priority,
-                             target: newLeaf(subst.target.anchor),
-                             info: subst.info,
-                             tooltip: "(" & $subst.anchorType & ")")
-    # find anchors automatically generated from Nim symbols
-    if roNimFile in s.options:
-      let substNim = findMainAnchorNim(s, signature=alias, n.info)
-      for subst in substNim:
-        foundLinks.add LinkDef(ar: arNim, priority: subst.priority,
-                               target: newLeaf(subst.refname),
-                               info: subst.info, tooltip: subst.tooltip)
-    foundLinks.sort(cmp = cmp, order = Descending)
-    let aliasStr = addNodes(alias)
-    if foundLinks.len >= 1:
-      let kind = if foundLinks[0].ar == arHyperlink: rnHyperlink
-                 elif foundLinks[0].ar == arNim: rnNimdocRef
-                 else: rnInternalRef
-      result = newRstNode(kind)
-      result.sons = @[newRstNode(rnInner, desc.sons), foundLinks[0].target]
-      if kind == rnNimdocRef: result.tooltip = foundLinks[0].tooltip
-      if foundLinks.len > 1:  # report ambiguous link
-        var targets = newSeq[string]()
-        for l in foundLinks:
-          var t = "    "
-          if s.filenames.len > 1:
-            t.add getFilename(s.filenames, l.info.fileIndex)
-          let n = l.info.line
-          let c = l.info.col + ColRstOffset
-          t.add "($1, $2): $3" % [$n, $c, l.tooltip]
-          targets.add t
-        rstMessage(s.filenames, s.msgHandler, n.info, mwAmbiguousLink,
-                   "`$1`\n  clash:\n$2" % [
-                     aliasStr, targets.join("\n")])
-    else:  # nothing found
-      result = n
-      rstMessage(s.filenames, s.msgHandler, n.info, mwBrokenLink, aliasStr)
+  # Associate this link alias with its target and change node kind to
+  # rnHyperlink or rnInternalRef appropriately.
+  var desc, alias: PRstNode
+  if n.kind == rnPandocRef:  # link like [desc][alias]
+    desc = n.sons[0]
+    alias = n.sons[1]
+  else:  # n.kind == rnRstRef, link like `desc=alias`_
+    desc = n
+    alias = n
+  type LinkDef = object
+    ar: AnchorRule
+    priority: int
+    tooltip: string
+    target: PRstNode
+    info: TLineInfo
+    externFilename: string
+      # when external anchor: origin filename where anchor was defined
+    isTitle: bool
+  proc cmp(x, y: LinkDef): int =
+    result = cmp(x.priority, y.priority)
+    if result == 0:
+      result = cmp(x.target, y.target)
+  var foundLinks: seq[LinkDef]
+  let refn = rstnodeToRefname(alias)
+  var hyperlinks = findRef(s, refn)
+  for y in hyperlinks:
+    foundLinks.add LinkDef(ar: arHyperlink, priority: refPriority(y.kind),
+                           target: y.value, info: y.info,
+                           tooltip: "(" & $y.kind & ")")
+  let substRst = findMainAnchorRst(s, alias.addNodes, n.info)
+  template getExternFilename(subst: AnchorSubst): string =
+    if subst.kind == arExternalRst or
+        (subst.kind == arNim and subst.external):
+      getFilename(s, subst)
+    else: ""
+  for subst in substRst:
+    var refname, fullRefname: string
+    if subst.kind == arInternalRst:
+      refname = subst.target.anchor
+      fullRefname = refname
+    else:  # arExternalRst
+      refname = subst.refnameExt
+      fullRefname = s.idxImports[getFilename(s, subst)].linkRelPath &
+                      "/" & refname
+    let anchorType =
+      if subst.kind == arInternalRst: subst.anchorType
+      else: subst.anchorTypeExt  # arExternalRst
+    foundLinks.add LinkDef(ar: subst.kind, priority: subst.priority,
+                           target: newLeaf(fullRefname),
+                           info: subst.info,
+                           externFilename: getExternFilename(subst),
+                           isTitle: isDocumentationTitle(refname),
+                           tooltip: "(" & $anchorType & ")")
+  # find anchors automatically generated from Nim symbols
+  if roNimFile in s.options or s.nimFileImported:
+    let substNim = findMainAnchorNim(s, signature=alias, n.info)
+    for subst in substNim:
+      let fullRefname =
+        if subst.external:
+          s.idxImports[getFilename(s, subst)].linkRelPath &
+              "/" & subst.refname
+        else: subst.refname
+      foundLinks.add LinkDef(ar: subst.kind, priority: subst.priority,
+                             target: newLeaf(fullRefname),
+                             externFilename: getExternFilename(subst),
+                             isTitle: isDocumentationTitle(subst.refname),
+                             info: subst.info, tooltip: subst.tooltip)
+  foundLinks.sort(cmp = cmp, order = Descending)
+  let aliasStr = addNodes(alias)
+  if foundLinks.len >= 1:
+    if foundLinks[0].externFilename != "":
+      s.idxImports[foundLinks[0].externFilename].used = true
+    let kind = if foundLinks[0].ar in {arHyperlink, arExternalRst}: rnHyperlink
+               elif foundLinks[0].ar == arNim:
+                 if foundLinks[0].externFilename == "": rnNimdocRef
+                 else: rnHyperlink
+               else: rnInternalRef
+    result = newRstNode(kind)
+    let documentName =  # filename without ext for `.nim`, title for `.md`
+      if foundLinks[0].ar == arNim:
+        changeFileExt(foundLinks[0].externFilename.extractFilename, "")
+      elif foundLinks[0].externFilename != "":
+        s.idxImports[foundLinks[0].externFilename].title
+      else: foundLinks[0].externFilename.extractFilename
+    let linkText =
+      if foundLinks[0].externFilename != "":
+        if foundLinks[0].isTitle: newLeaf(addNodes(desc))
+        else: newLeaf(documentName & ": " & addNodes(desc))
+      else:
+        newRstNode(rnInner, desc.sons)
+    result.sons = @[linkText, foundLinks[0].target]
+    if kind == rnNimdocRef: result.tooltip = foundLinks[0].tooltip
+    if foundLinks.len > 1:  # report ambiguous link
+      var targets = newSeq[string]()
+      for l in foundLinks:
+        var t = "    "
+        if s.filenames.len > 1:
+          t.add getFilename(s.filenames, l.info.fileIndex)
+        let n = l.info.line
+        let c = l.info.col + ColRstOffset
+        t.add "($1, $2): $3" % [$n, $c, l.tooltip]
+        targets.add t
+      rstMessage(s.filenames, s.msgHandler, n.info, mwAmbiguousLink,
+                 "`$1`\n  clash:\n$2" % [
+                   aliasStr, targets.join("\n")])
+  else:  # nothing found
+    result = n
+    rstMessage(s.filenames, s.msgHandler, n.info, mwBrokenLink, aliasStr)
 
 proc resolveSubs*(s: PRstSharedState, n: PRstNode): PRstNode =
   ## Makes pass 2 of RST parsing.
@@ -3494,7 +3785,7 @@ proc resolveSubs*(s: PRstSharedState, n: PRstNode): PRstNode =
   of rnRstRef, rnPandocRef:
     result = resolveLink(s, n)
   of rnFootnote:
-    var (fnType, num) = getFootnoteType(n.sons[0])
+    var (fnType, num) = getFootnoteType(s, n.sons[0])
     case fnType
     of fnManualNumber, fnCitation:
       discard "no need to alter fixed text"
@@ -3512,7 +3803,7 @@ proc resolveSubs*(s: PRstSharedState, n: PRstNode): PRstNode =
       n.sons[0].sons[0].text = sym
     n.sons[1] = resolveSubs(s, n.sons[1])
   of rnFootnoteRef:
-    var (fnType, num) = getFootnoteType(n.sons[0])
+    var (fnType, num) = getFootnoteType(s, n.sons[0])
     template addLabel(number: int | string) =
       var nn = newRstNode(rnInner)
       nn.add newLeaf($number)
@@ -3568,20 +3859,28 @@ proc resolveSubs*(s: PRstSharedState, n: PRstNode): PRstNode =
           inc i
       result.sons = newSons
 
+proc completePass2*(s: PRstSharedState) =
+  for (filename, importdocInfo) in s.idxImports.pairs:
+    if not importdocInfo.used:
+      rstMessage(s.filenames, s.msgHandler, importdocInfo.fromInfo,
+                 mwUnusedImportdoc, filename)
+
 proc rstParse*(text, filename: string,
                line, column: int,
                options: RstParseOptions,
                findFile: FindFileHandler = nil,
+               findRefFile: FindRefFileHandler = nil,
                msgHandler: MsgHandler = nil):
               tuple[node: PRstNode, filenames: RstFileTable, hasToc: bool] =
   ## Parses the whole `text`. The result is ready for `rstgen.renderRstToOut`,
   ## note that 2nd tuple element should be fed to `initRstGenerator`
   ## argument `filenames` (it is being filled here at least with `filename`
   ## and possibly with other files from RST ``.. include::`` statement).
-  var sharedState = newRstSharedState(options, filename, findFile,
+  var sharedState = newRstSharedState(options, filename, findFile, findRefFile,
                                       msgHandler, hasToc=false)
   let unresolved = rstParsePass1(text, line, column, sharedState)
   preparePass2(sharedState, unresolved)
   result.node = resolveSubs(sharedState, unresolved)
+  completePass2(sharedState)
   result.filenames = sharedState.filenames
   result.hasToc = sharedState.hasToc
diff --git a/lib/packages/docutils/rstast.nim b/lib/packages/docutils/rstast.nim
index c808318b5..2bbb0d0b8 100644
--- a/lib/packages/docutils/rstast.nim
+++ b/lib/packages/docutils/rstast.nim
@@ -9,7 +9,7 @@
 
 ## This module implements an AST for the `reStructuredText`:idx: parser.
 
-import strutils, json
+import std/[strutils, json]
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim
index 597ee1553..7fc0ac03a 100644
--- a/lib/packages/docutils/rstgen.nim
+++ b/lib/packages/docutils/rstgen.nim
@@ -39,9 +39,10 @@
 ##   No backreferences are generated since finding all references of a footnote
 ##   can be done by simply searching for ``[footnoteName]``.
 
-import strutils, os, hashes, strtabs, rstast, rst, highlite, tables, sequtils,
-  algorithm, parseutils, std/strbasics
+import std/[strutils, os, hashes, strtabs, tables, sequtils,
+  algorithm, parseutils, strbasics]
 
+import rstast, rst, rstidx, highlite
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio, formatfloat]
@@ -59,7 +60,7 @@ type
     outLatex            # output is Latex
 
   MetaEnum* = enum
-    metaNone, metaTitle, metaSubtitle, metaAuthor, metaVersion
+    metaNone, metaTitleRaw, metaTitle, metaSubtitle, metaAuthor, metaVersion
 
   EscapeMode* = enum  # in Latex text inside options [] and URLs is
                       # escaped slightly differently than in normal text
@@ -321,31 +322,8 @@ proc renderAux(d: PDoc, n: PRstNode, html, tex: string, result: var string) =
 
 # ---------------- index handling --------------------------------------------
 
-proc quoteIndexColumn(text: string): string =
-  ## Returns a safe version of `text` for serialization to the ``.idx`` file.
-  ##
-  ## The returned version can be put without worries in a line based tab
-  ## separated column text file. The following character sequence replacements
-  ## will be performed for that goal:
-  ##
-  ## * ``"\\"`` => ``"\\\\"``
-  ## * ``"\n"`` => ``"\\n"``
-  ## * ``"\t"`` => ``"\\t"``
-  result = newStringOfCap(text.len + 3)
-  for c in text:
-    case c
-    of '\\': result.add "\\"
-    of '\L': result.add "\\n"
-    of '\C': discard
-    of '\t': result.add "\\t"
-    else: result.add c
-
-proc unquoteIndexColumn(text: string): string =
-  ## Returns the unquoted version generated by ``quoteIndexColumn``.
-  result = text.multiReplace(("\\t", "\t"), ("\\n", "\n"), ("\\\\", "\\"))
-
-proc setIndexTerm*(d: var RstGenerator, htmlFile, id, term: string,
-                   linkTitle, linkDesc = "") =
+proc setIndexTerm*(d: var RstGenerator; k: IndexEntryKind, htmlFile, id, term: string,
+                   linkTitle, linkDesc = "", line = 0) =
   ## Adds a `term` to the index using the specified hyperlink identifier.
   ##
   ## A new entry will be added to the index using the format
@@ -368,21 +346,8 @@ proc setIndexTerm*(d: var RstGenerator, htmlFile, id, term: string,
   ## <#writeIndexFile,RstGenerator,string>`_. The purpose of the index is
   ## documented in the `docgen tools guide
   ## <docgen.html#related-options-index-switch>`_.
-  var
-    entry = term
-    isTitle = false
-  entry.add('\t')
-  entry.add(htmlFile)
-  if id.len > 0:
-    entry.add('#')
-    entry.add(id)
-  else:
-    isTitle = true
-  if linkTitle.len > 0 or linkDesc.len > 0:
-    entry.add('\t' & linkTitle.quoteIndexColumn)
-    entry.add('\t' & linkDesc.quoteIndexColumn)
-  entry.add("\n")
-
+  let (entry, isTitle) = formatIndexEntry(k, htmlFile, id, term,
+                                          linkTitle, linkDesc, line)
   if isTitle: d.theIndex.insert(entry)
   else: d.theIndex.add(entry)
 
@@ -395,6 +360,15 @@ proc hash(n: PRstNode): int =
       result = result !& hash(n.sons[i])
     result = !$result
 
+proc htmlFileRelPath(d: PDoc): string =
+  if d.outDir.len == 0:
+    # /foo/bar/zoo.nim -> zoo.html
+    changeFileExt(extractFilename(d.filename), HtmlExt)
+  else: # d is initialized in docgen.nim
+    # outDir   = /foo              -\
+    # destFile = /foo/bar/zoo.html -|-> bar/zoo.html
+    d.destFile.relativePath(d.outDir, '/')
+
 proc renderIndexTerm*(d: PDoc, n: PRstNode, result: var string) =
   ## Renders the string decorated within \`foobar\`\:idx\: markers.
   ##
@@ -411,17 +385,12 @@ proc renderIndexTerm*(d: PDoc, n: PRstNode, result: var string) =
 
   var term = ""
   renderAux(d, n, term)
-  setIndexTerm(d, changeFileExt(extractFilename(d.filename), HtmlExt), id, term, d.currentSection)
+  setIndexTerm(d, ieIdxRole,
+  htmlFileRelPath(d), id, term, d.currentSection)
   dispA(d.target, result, "<span id=\"$1\">$2</span>", "\\nimindexterm{$1}{$2}",
         [id, term])
 
 type
-  IndexEntry* = object
-    keyword*: string
-    link*: string
-    linkTitle*: string ## contains a prettier text for the href
-    linkDesc*: string ## the title attribute of the final href
-
   IndexedDocs* = Table[IndexEntry, seq[IndexEntry]] ## \
     ## Contains the index sequences for doc types.
     ##
@@ -432,21 +401,6 @@ type
     ## The value indexed by this IndexEntry is a sequence with the real index
     ## entries found in the ``.idx`` file.
 
-proc cmp(a, b: IndexEntry): int =
-  ## Sorts two ``IndexEntry`` first by `keyword` field, then by `link`.
-  result = cmpIgnoreStyle(a.keyword, b.keyword)
-  if result == 0:
-    result = cmpIgnoreStyle(a.link, b.link)
-
-proc hash(x: IndexEntry): Hash =
-  ## Returns the hash for the combined fields of the type.
-  ##
-  ## The hash is computed as the chained hash of the individual string hashes.
-  result = x.keyword.hash !& x.link.hash
-  result = result !& x.linkTitle.hash
-  result = result !& x.linkDesc.hash
-  result = !$result
-
 when defined(gcDestructors):
   template `<-`(a, b: var IndexEntry) = a = move(b)
 else:
@@ -455,6 +409,7 @@ else:
     shallowCopy a.link, b.link
     shallowCopy a.linkTitle, b.linkTitle
     shallowCopy a.linkDesc, b.linkDesc
+    shallowCopy a.module, b.module
 
 proc sortIndex(a: var openArray[IndexEntry]) =
   # we use shellsort here; fast and simple
@@ -494,16 +449,20 @@ proc generateSymbolIndex(symbols: seq[IndexEntry]): string =
   result = "<dl>"
   var i = 0
   while i < symbols.len:
-    let keyword = symbols[i].keyword
+    let keyword = esc(outHtml, symbols[i].keyword)
     let cleanedKeyword = keyword.escapeLink
     result.addf("<dt><a name=\"$2\" href=\"#$2\"><span>$1:</span></a></dt><dd><ul class=\"simple\">\n",
                 [keyword, cleanedKeyword])
     var j = i
-    while j < symbols.len and keyword == symbols[j].keyword:
+    while j < symbols.len and symbols[i].keyword == symbols[j].keyword:
       let
         url = symbols[j].link.escapeLink
-        text = if symbols[j].linkTitle.len > 0: symbols[j].linkTitle else: url
-        desc = if symbols[j].linkDesc.len > 0: symbols[j].linkDesc else: ""
+        module = symbols[j].module
+        text =
+          if symbols[j].linkTitle.len > 0:
+            esc(outHtml, module & ": " & symbols[j].linkTitle)
+          else: url
+        desc = symbols[j].linkDesc
       if desc.len > 0:
         result.addf("""<li><a class="reference external"
           title="$3" data-doc-search-tag="$2" href="$1">$2</a></li>
@@ -517,13 +476,6 @@ proc generateSymbolIndex(symbols: seq[IndexEntry]): string =
     i = j
   result.add("</dl>")
 
-proc isDocumentationTitle(hyperlink: string): bool =
-  ## Returns true if the hyperlink is actually a documentation title.
-  ##
-  ## Documentation titles lack the hash. See `mergeIndexes()
-  ## <#mergeIndexes,string>`_ for a more detailed explanation.
-  result = hyperlink.find('#') < 0
-
 proc stripTocLevel(s: string): tuple[level: int, text: string] =
   ## Returns the *level* of the toc along with the text without it.
   for c in 0 ..< s.len:
@@ -557,17 +509,15 @@ proc generateDocumentationToc(entries: seq[IndexEntry]): string =
     level = 1
   levels.newSeq(entries.len)
   for entry in entries:
-    let (rawLevel, rawText) = stripTocLevel(entry.linkTitle or entry.keyword)
+    let (rawLevel, rawText) = stripTocLevel(entry.linkTitle)
     if rawLevel < 1:
       # This is a normal symbol, push it *inside* one level from the last one.
       levels[L].level = level + 1
-      # Also, ignore the linkTitle and use directly the keyword.
-      levels[L].text = entry.keyword
     else:
       # The level did change, update the level indicator.
       level = rawLevel
       levels[L].level = rawLevel
-      levels[L].text = rawText
+    levels[L].text = rawText
     inc L
 
   # Now generate hierarchical lists based on the precalculated levels.
@@ -598,7 +548,7 @@ proc generateDocumentationIndex(docs: IndexedDocs): string =
   for title in titles:
     let tocList = generateDocumentationToc(docs.getOrDefault(title))
     result.add("<ul><li><a href=\"" &
-      title.link & "\">" & title.keyword & "</a>\n" & tocList & "</li></ul>\n")
+      title.link & "\">" & title.linkTitle & "</a>\n" & tocList & "</li></ul>\n")
 
 proc generateDocumentationJumps(docs: IndexedDocs): string =
   ## Returns a plain list of hyperlinks to documentation TOCs in HTML.
@@ -610,7 +560,7 @@ proc generateDocumentationJumps(docs: IndexedDocs): string =
 
   var chunks: seq[string] = @[]
   for title in titles:
-    chunks.add("<a href=\"" & title.link & "\">" & title.keyword & "</a>")
+    chunks.add("<a href=\"" & title.link & "\">" & title.linkTitle & "</a>")
 
   result.add(chunks.join(", ") & ".<br/>")
 
@@ -639,39 +589,12 @@ proc readIndexDir*(dir: string):
   # Scan index files and build the list of symbols.
   for path in walkDirRec(dir):
     if path.endsWith(IndexExt):
-      var
-        fileEntries: seq[IndexEntry]
-        title: IndexEntry
-        f = 0
-      newSeq(fileEntries, 500)
-      setLen(fileEntries, 0)
-      for line in lines(path):
-        let s = line.find('\t')
-        if s < 0: continue
-        setLen(fileEntries, f+1)
-        fileEntries[f].keyword = line.substr(0, s-1)
-        fileEntries[f].link = line.substr(s+1)
-        # See if we detect a title, a link without a `#foobar` trailing part.
-        if title.keyword.len == 0 and fileEntries[f].link.isDocumentationTitle:
-          title.keyword = fileEntries[f].keyword
-          title.link = fileEntries[f].link
-
-        if fileEntries[f].link.find('\t') > 0:
-          let extraCols = fileEntries[f].link.split('\t')
-          fileEntries[f].link = extraCols[0]
-          assert extraCols.len == 3
-          fileEntries[f].linkTitle = extraCols[1].unquoteIndexColumn
-          fileEntries[f].linkDesc = extraCols[2].unquoteIndexColumn
-        else:
-          fileEntries[f].linkTitle = ""
-          fileEntries[f].linkDesc = ""
-        inc f
+      var (fileEntries, title) = parseIdxFile(path)
       # Depending on type add this to the list of symbols or table of APIs.
-      if title.keyword.len == 0:
-        for i in 0 ..< f:
-          # Don't add to symbols TOC entries (they start with a whitespace).
-          let toc = fileEntries[i].linkTitle
-          if toc.len > 0 and toc[0] == ' ':
+
+      if title.kind == ieNimTitle:
+        for i in 0 ..< fileEntries.len:
+          if fileEntries[i].kind != ieNim:
             continue
           # Ok, non TOC entry, add it.
           setLen(result.symbols, L + 1)
@@ -687,9 +610,17 @@ proc readIndexDir*(dir: string):
             result.modules.add(x.changeFileExt(""))
       else:
         # Generate the symbolic anchor for index quickjumps.
-        title.linkTitle = "doc_toc_" & $result.docs.len
+        title.aux = "doc_toc_" & $result.docs.len
         result.docs[title] = fileEntries
 
+      for i in 0 ..< fileEntries.len:
+        if fileEntries[i].kind != ieIdxRole:
+          continue
+
+        setLen(result.symbols, L + 1)
+        result.symbols[L] = fileEntries[i]
+        inc L
+
 proc mergeIndexes*(dir: string): string =
   ## Merges all index files in `dir` and returns the generated index as HTML.
   ##
@@ -747,24 +678,6 @@ proc mergeIndexes*(dir: string): string =
 
 # ----------------------------------------------------------------------------
 
-proc stripTocHtml(s: string): string =
-  ## Ugly quick hack to remove HTML tags from TOC titles.
-  ##
-  ## A TocEntry.header field already contains rendered HTML tags. Instead of
-  ## implementing a proper version of renderRstToOut() which recursively
-  ## renders an rst tree to plain text, we simply remove text found between
-  ## angled brackets. Given the limited possibilities of rst inside TOC titles
-  ## this should be enough.
-  result = s
-  var first = result.find('<')
-  while first >= 0:
-    let last = result.find('>', first)
-    if last < 0:
-      # Abort, since we didn't found a closing angled bracket.
-      return
-    result.delete(first..last)
-    first = result.find('<', first)
-
 proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
   var tmp = ""
   for i in countup(0, len(n) - 1): renderRstToOut(d, n.sons[i], tmp)
@@ -785,19 +698,12 @@ proc renderHeadline(d: PDoc, n: PRstNode, result: var string) =
 
   # Generate index entry using spaces to indicate TOC level for the output HTML.
   assert n.level >= 0
-  let
-    htmlFileRelPath = if d.outDir.len == 0:
-                        # /foo/bar/zoo.nim -> zoo.html
-                        changeFileExt(extractFilename(d.filename), HtmlExt)
-                      else: # d is initialized in docgen.nim
-                        # outDir   = /foo              -\
-                        # destFile = /foo/bar/zoo.html -|-> bar/zoo.html
-                        d.destFile.relativePath(d.outDir, '/')
-  setIndexTerm(d, htmlFileRelPath, n.anchor, tmp.stripTocHtml,
-    spaces(max(0, n.level)) & tmp)
+  setIndexTerm(d, ieHeading, htmlFile = d.htmlFileRelPath, id = n.anchor,
+               term = n.addNodes, linkTitle = spaces(max(0, n.level)) & tmp)
 
 proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
   if n.level == 0 and d.meta[metaTitle].len == 0:
+    d.meta[metaTitleRaw] = n.addNodes
     for i in countup(0, len(n)-1):
       renderRstToOut(d, n.sons[i], d.meta[metaTitle])
     d.currentSection = d.meta[metaTitle]
@@ -813,6 +719,8 @@ proc renderOverline(d: PDoc, n: PRstNode, result: var string) =
     dispA(d.target, result, "<h$1$2><center>$3</center></h$1>",
                    "\\rstov$4[$5]{$3}$2\n", [$n.level,
                    n.anchor.idS, tmp, $chr(n.level - 1 + ord('A')), tocName])
+    setIndexTerm(d, ieHeading, htmlFile = d.htmlFileRelPath, id = n.anchor,
+                 term = n.addNodes, linkTitle = spaces(max(0, n.level)) & tmp)
 
 proc renderTocEntry(d: PDoc, n: PRstNode, result: var string) =
   var header = ""
@@ -1197,6 +1105,18 @@ proc renderHyperlink(d: PDoc, text, link: PRstNode, result: var string,
       "\\hyperlink{$2}{$1} (p.~\\pageref{$2})",
       [textStr, linkStr, nimDocStr, tooltipStr])
 
+proc traverseForIndex*(d: PDoc, n: PRstNode) =
+  ## A version of [renderRstToOut] that only fills entries for ``.idx`` files.
+  var discarded: string
+  if n == nil: return
+  case n.kind
+  of rnIdx: renderIndexTerm(d, n, discarded)
+  of rnHeadline, rnMarkdownHeadline: renderHeadline(d, n, discarded)
+  of rnOverline: renderOverline(d, n, discarded)
+  else:
+    for i in 0 ..< len(n):
+      traverseForIndex(d, n.sons[i])
+
 proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   if n == nil: return
   case n.kind
@@ -1255,7 +1175,7 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
     renderAux(d, n, "<div class=\"option-list-description\">$1</div>",
         " $1\n", result)
   of rnOption, rnOptionString, rnOptionArgument:
-    doAssert false, "renderRstToOut"
+    raiseAssert "renderRstToOut"
   of rnLiteralBlock:
     renderAux(d, n, "<pre$2>$1</pre>\n",
                     "\n\n$2\\begin{rstpre}\n$1\n\\end{rstpre}\n\n", result)
@@ -1451,6 +1371,7 @@ proc renderRstToOut(d: PDoc, n: PRstNode, result: var string) =
   of rnTitle:
     d.meta[metaTitle] = ""
     renderRstToOut(d, n.sons[0], d.meta[metaTitle])
+    d.meta[metaTitleRaw] = n.sons[0].addNodes
 
 # -----------------------------------------------------------------------------
 
@@ -1616,11 +1537,13 @@ proc rstToHtml*(s: string, options: RstParseOptions,
   proc myFindFile(filename: string): string =
     # we don't find any files in online mode:
     result = ""
+  proc myFindRefFile(filename: string): (string, string) =
+    result = ("", "")
 
   const filen = "input"
   let (rst, filenames, t) = rstParse(s, filen,
                                      line=LineRstInit, column=ColRstInit,
-                                     options, myFindFile, msgHandler)
+                                     options, myFindFile, myFindRefFile, msgHandler)
   var d: RstGenerator
   initRstGenerator(d, outHtml, config, filen, myFindFile, msgHandler,
                    filenames, hasToc = t)
diff --git a/lib/packages/docutils/rstidx.nim b/lib/packages/docutils/rstidx.nim
new file mode 100644
index 000000000..1472d28fd
--- /dev/null
+++ b/lib/packages/docutils/rstidx.nim
@@ -0,0 +1,141 @@
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2022 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+
+## Nim `idx`:idx: file format related definitions.
+
+import std/[strutils, syncio, hashes]
+from std/os import splitFile
+
+type
+  IndexEntryKind* = enum ## discriminator tag
+    ieMarkupTitle = "markupTitle"
+                           ## RST/Markdown title, text in `keyword` +
+                           ## HTML text in `linkTitle`
+    ieNimTitle = "nimTitle"
+                           ## Nim title
+    ieHeading = "heading"  ## RST/Markdown markup heading, escaped
+    ieIdxRole = "idx"      ## RST :idx: definition, escaped
+    ieNim = "nim"          ## Nim symbol, unescaped
+    ieNimGroup = "nimgrp"  ## Nim overload group, unescaped
+  IndexEntry* = object
+    kind*: IndexEntryKind  ## 0.
+    keyword*: string       ## 1.
+    link*: string          ## 2.
+    linkTitle*: string     ## 3. contains a prettier text for the href
+    linkDesc*: string      ## 4. the title attribute of the final href
+    line*: int             ## 5.
+    module*: string        ## origin file, NOT a field in ``.idx`` file
+    aux*: string           ## auxuliary field, NOT a field in ``.idx`` file
+
+proc isDocumentationTitle*(hyperlink: string): bool =
+  ## Returns true if the hyperlink is actually a documentation title.
+  ##
+  ## Documentation titles lack the hash. See `mergeIndexes()
+  ## <#mergeIndexes,string>`_ for a more detailed explanation.
+  result = hyperlink.find('#') < 0
+
+proc `$`*(e: IndexEntry): string =
+  """("$1", "$2", "$3", "$4", $5)""" % [
+      e.keyword, e.link, e.linkTitle, e.linkDesc, $e.line]
+
+proc quoteIndexColumn(text: string): string =
+  ## Returns a safe version of `text` for serialization to the ``.idx`` file.
+  ##
+  ## The returned version can be put without worries in a line based tab
+  ## separated column text file. The following character sequence replacements
+  ## will be performed for that goal:
+  ##
+  ## * ``"\\"`` => ``"\\\\"``
+  ## * ``"\n"`` => ``"\\n"``
+  ## * ``"\t"`` => ``"\\t"``
+  result = newStringOfCap(text.len + 3)
+  for c in text:
+    case c
+    of '\\': result.add "\\"
+    of '\L': result.add "\\n"
+    of '\C': discard
+    of '\t': result.add "\\t"
+    else: result.add c
+
+proc unquoteIndexColumn*(text: string): string =
+  ## Returns the unquoted version generated by ``quoteIndexColumn``.
+  result = text.multiReplace(("\\t", "\t"), ("\\n", "\n"), ("\\\\", "\\"))
+
+proc formatIndexEntry*(kind: IndexEntryKind; htmlFile, id, term, linkTitle,
+                       linkDesc: string, line: int):
+                      tuple[entry: string, isTitle: bool] =
+  result.entry = $kind
+  result.entry.add('\t')
+  result.entry.add term
+  result.entry.add('\t')
+  result.entry.add(htmlFile)
+  if id.len > 0:
+    result.entry.add('#')
+    result.entry.add(id)
+    result.isTitle = false
+  else:
+    result.isTitle = true
+  result.entry.add('\t' & linkTitle.quoteIndexColumn)
+  result.entry.add('\t' & linkDesc.quoteIndexColumn)
+  result.entry.add('\t' & $line)
+  result.entry.add("\n")
+
+proc parseIndexEntryKind(s: string): IndexEntryKind =
+  result = case s:
+    of "nim": ieNim
+    of "nimgrp": ieNimGroup
+    of "heading": ieHeading
+    of "idx": ieIdxRole
+    of "nimTitle": ieNimTitle
+    of "markupTitle": ieMarkupTitle
+    else: raise newException(ValueError, "unknown index entry value $1" % [s])
+
+proc parseIdxFile*(path: string):
+    tuple[fileEntries: seq[IndexEntry], title: IndexEntry] =
+  var
+    f = 0
+  newSeq(result.fileEntries, 500)
+  setLen(result.fileEntries, 0)
+  let (_, base, _) = path.splitFile
+  for line in lines(path):
+    let s = line.find('\t')
+    if s < 0: continue
+    setLen(result.fileEntries, f+1)
+    let cols = line.split('\t')
+    result.fileEntries[f].kind = parseIndexEntryKind(cols[0])
+    result.fileEntries[f].keyword = cols[1]
+    result.fileEntries[f].link = cols[2]
+    if result.fileEntries[f].kind == ieIdxRole:
+      result.fileEntries[f].module = base
+    else:
+      if result.title.keyword.len == 0:
+        result.fileEntries[f].module = base
+      else:
+        result.fileEntries[f].module = result.title.keyword
+
+    result.fileEntries[f].linkTitle = cols[3].unquoteIndexColumn
+    result.fileEntries[f].linkDesc = cols[4].unquoteIndexColumn
+    result.fileEntries[f].line = parseInt(cols[5])
+
+    if result.fileEntries[f].kind in {ieNimTitle, ieMarkupTitle}:
+      result.title = result.fileEntries[f]
+    inc f
+
+proc cmp*(a, b: IndexEntry): int =
+  ## Sorts two ``IndexEntry`` first by `keyword` field, then by `link`.
+  result = cmpIgnoreStyle(a.keyword, b.keyword)
+  if result == 0:
+    result = cmpIgnoreStyle(a.link, b.link)
+
+proc hash*(x: IndexEntry): Hash =
+  ## Returns the hash for the combined fields of the type.
+  ##
+  ## The hash is computed as the chained hash of the individual string hashes.
+  result = x.keyword.hash !& x.link.hash
+  result = result !& x.linkTitle.hash
+  result = result !& x.linkDesc.hash
+  result = !$result
diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim
index 7ee062e4f..007488354 100644
--- a/lib/posix/epoll.nim
+++ b/lib/posix/epoll.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-from posix import SocketHandle
+from std/posix import SocketHandle
 
 const
   EPOLLIN* = 0x00000001
diff --git a/lib/posix/inotify.nim b/lib/posix/inotify.nim
index 109d3680e..575accc18 100644
--- a/lib/posix/inotify.nim
+++ b/lib/posix/inotify.nim
@@ -14,12 +14,13 @@ when defined(nimPreviewSlimSystem):
 # Structure describing an inotify event.
 type
   InotifyEvent* {.pure, final, importc: "struct inotify_event",
-                  header: "<sys/inotify.h>".} = object ## An Inotify event.
+                  header: "<sys/inotify.h>",
+                  completeStruct.} = object            ## An Inotify event.
     wd* {.importc: "wd".}: FileHandle                  ## Watch descriptor.
     mask* {.importc: "mask".}: uint32                  ## Watch mask.
     cookie* {.importc: "cookie".}: uint32              ## Cookie to synchronize two events.
     len* {.importc: "len".}: uint32                    ## Length (including NULs) of name.
-    name* {.importc: "name".}: char                    ## Name.
+    name* {.importc: "name".}: UncheckedArray[char]    ## Name.
 
 # Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH.
 const
@@ -66,7 +67,8 @@ proc inotify_init*(): FileHandle {.cdecl, importc: "inotify_init",
 
 proc inotify_init1*(flags: cint): FileHandle {.cdecl, importc: "inotify_init1",
     header: "<sys/inotify.h>".}
-  ## Create and initialize inotify instance.
+  ## Like `inotify_init<#inotify_init>`_ ,
+  ## but has a flags argument that provides access to some extra functionality.
 
 proc inotify_add_watch*(fd: cint; name: cstring; mask: uint32): cint {.cdecl,
     importc: "inotify_add_watch", header: "<sys/inotify.h>".}
@@ -78,11 +80,18 @@ proc inotify_rm_watch*(fd: cint; wd: cint): cint {.cdecl,
 
 iterator inotify_events*(evs: pointer, n: int): ptr InotifyEvent =
   ## Abstract the packed buffer interface to yield event object pointers.
-  ##   ```Nim
-  ##   var evs = newSeq[byte](8192)        # Already did inotify_init+add_watch
-  ##   while (let n = read(fd, evs[0].addr, 8192); n) > 0:     # read forever
-  ##     for e in inotify_events(evs[0].addr, n): echo e[].len # echo name lens
-  ##   ```
+  runnableExamples("-r:off"):
+    when defined(linux):
+       import std/posix  # needed for FileHandle read procedure
+       const MaxWatches = 8192
+
+       let inotifyFd = inotify_init()  # create new inotify instance and get it's FileHandle
+       let wd = inotifyFd.inotify_add_watch("/tmp", IN_CREATE or IN_DELETE)  # Add new watch
+
+       var events: array[MaxWatches, byte]  # event buffer
+       while (let n = read(inotifyFd, addr events, MaxWatches); n) > 0:  # blocks until any events have been read
+         for e in inotify_events(addr events, n):
+           echo (e[].wd, e[].mask, cast[cstring](addr e[].name))    # echo watch id, mask, and name value of each event
   var ev: ptr InotifyEvent = cast[ptr InotifyEvent](evs)
   var n = n
   while n > 0:
@@ -93,8 +102,10 @@ iterator inotify_events*(evs: pointer, n: int): ptr InotifyEvent =
 
 runnableExamples:
   when defined(linux):
-    let inoty: FileHandle = inotify_init()           ## Create 1 Inotify.
-    doAssert inoty >= 0                              ## Check for errors (FileHandle is alias to cint).
-    let watchdoge: cint = inotify_add_watch(inoty, ".", IN_ALL_EVENTS) ## Add directory to watchdog.
-    doAssert watchdoge >= 0                          ## Check for errors.
-    doAssert inotify_rm_watch(inoty, watchdoge) >= 0 ## Remove directory from the watchdog
+    let inotifyFd = inotify_init()  # create and get new inotify FileHandle
+    doAssert inotifyFd >= 0         # check for errors
+
+    let wd = inotifyFd.inotify_add_watch("/tmp", IN_CREATE or IN_DELETE)  # Add new watch
+    doAssert wd >= 0                 # check for errors
+
+    discard inotifyFd.inotify_rm_watch(wd) # remove watch
diff --git a/lib/posix/kqueue.nim b/lib/posix/kqueue.nim
index c83ae33ea..2450cdb42 100644
--- a/lib/posix/kqueue.nim
+++ b/lib/posix/kqueue.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-from posix import Timespec
+from std/posix import Timespec
 
 when defined(macosx) or defined(freebsd) or defined(openbsd) or
      defined(dragonfly):
diff --git a/lib/posix/linux.nim b/lib/posix/linux.nim
index 9a5e9f062..29fd4288d 100644
--- a/lib/posix/linux.nim
+++ b/lib/posix/linux.nim
@@ -1,4 +1,4 @@
-import posix
+import std/posix
 
 ## Flags of `clone` syscall.
 ## See `clone syscall manual
diff --git a/lib/posix/posix.nim b/lib/posix/posix.nim
index ddf00cbb7..fbe945df3 100644
--- a/lib/posix/posix.nim
+++ b/lib/posix/posix.nim
@@ -195,8 +195,29 @@ proc open*(a1: cstring, a2: cint, mode: Mode | cint = 0.Mode): cint {.inline.} =
 
 proc posix_fadvise*(a1: cint, a2, a3: Off, a4: cint): cint {.
   importc, header: "<fcntl.h>".}
-proc posix_fallocate*(a1: cint, a2, a3: Off): cint {.
-  importc, header: "<fcntl.h>".}
+
+proc ftruncate*(a1: cint, a2: Off): cint {.importc, header: "<unistd.h>".}
+when defined(osx):              # 2001 POSIX evidently does not concern Apple
+  type FStore {.importc: "fstore_t", header: "<fcntl.h>", bycopy.} = object
+    fst_flags: uint32           ## IN: flags word
+    fst_posmode: cint           ## IN: indicates offset field
+    fst_offset,                 ## IN: start of the region
+      fst_length,               ## IN: size of the region
+      fst_bytesalloc: Off       ## OUT: number of bytes allocated
+  var F_PEOFPOSMODE {.importc, header: "<fcntl.h>".}: cint
+  var F_ALLOCATEALL {.importc, header: "<fcntl.h>".}: uint32
+  var F_PREALLOCATE {.importc, header: "<fcntl.h>".}: cint
+  proc posix_fallocate*(a1: cint, a2, a3: Off): cint =
+    var fst = FStore(fst_flags: F_ALLOCATEALL, fst_posmode: F_PEOFPOSMODE,
+                     fst_offset: a2, fst_length: a3)
+    # Must also call ftruncate to match what POSIX does. Unlike posix_fallocate,
+    # this can shrink files.  Could guard w/getFileSize, but caller likely knows
+    # present size & has no good reason to call this unless it is growing.
+    if fcntl(a1, F_PREALLOCATE, fst.addr) != cint(-1): ftruncate(a1, a2 + a3)
+    else: cint(-1)
+else:
+  proc posix_fallocate*(a1: cint, a2, a3: Off): cint {.
+    importc, header: "<fcntl.h>".}
 
 when not defined(haiku) and not defined(openbsd):
   proc fmtmsg*(a1: int, a2: cstring, a3: cint,
@@ -511,7 +532,6 @@ proc fpathconf*(a1, a2: cint): int {.importc, header: "<unistd.h>".}
 proc fsync*(a1: cint): cint {.importc, header: "<unistd.h>".}
  ## synchronize a file's buffer cache to the storage device
 
-proc ftruncate*(a1: cint, a2: Off): cint {.importc, header: "<unistd.h>".}
 proc getcwd*(a1: cstring, a2: int): cstring {.importc, header: "<unistd.h>", sideEffect.}
 proc getuid*(): Uid {.importc, header: "<unistd.h>", sideEffect.}
  ## returns the real user ID of the calling process
@@ -564,7 +584,8 @@ proc pread*(a1: cint, a2: pointer, a3: int, a4: Off): int {.
 proc pwrite*(a1: cint, a2: pointer, a3: int, a4: Off): int {.
   importc, header: "<unistd.h>".}
 proc read*(a1: cint, a2: pointer, a3: int): int {.importc, header: "<unistd.h>".}
-proc readlink*(a1, a2: cstring, a3: int): int {.importc, header: "<unistd.h>".}
+when not defined(nintendoswitch):
+  proc readlink*(a1, a2: cstring, a3: int): int {.importc, header: "<unistd.h>".}
 proc ioctl*(f: FileHandle, device: uint): int {.importc: "ioctl",
       header: "<sys/ioctl.h>", varargs, tags: [WriteIOEffect].}
   ## A system call for device-specific input/output operations and other
@@ -583,7 +604,10 @@ proc setsid*(): Pid {.importc, header: "<unistd.h>".}
 proc setuid*(a1: Uid): cint {.importc, header: "<unistd.h>".}
 proc sleep*(a1: cint): cint {.importc, header: "<unistd.h>".}
 proc swab*(a1, a2: pointer, a3: int) {.importc, header: "<unistd.h>".}
-proc symlink*(a1, a2: cstring): cint {.importc, header: "<unistd.h>".}
+when not defined(nintendoswitch):
+  proc symlink*(a1, a2: cstring): cint {.importc, header: "<unistd.h>".}
+else:
+  proc symlink*(a1, a2: cstring): cint = -1
 proc sync*() {.importc, header: "<unistd.h>".}
 proc sysconf*(a1: cint): int {.importc, header: "<unistd.h>".}
 proc tcgetpgrp*(a1: cint): Pid {.importc, header: "<unistd.h>".}
@@ -934,7 +958,7 @@ proc `==`*(x, y: SocketHandle): bool {.borrow.}
 proc accept*(a1: SocketHandle, a2: ptr SockAddr, a3: ptr SockLen): SocketHandle {.
   importc, header: "<sys/socket.h>", sideEffect.}
 
-when defined(linux) or defined(bsd):
+when defined(linux) or defined(bsd) or defined(nuttx):
   proc accept4*(a1: SocketHandle, a2: ptr SockAddr, a3: ptr SockLen,
                 flags: cint): SocketHandle {.importc, header: "<sys/socket.h>".}
 
@@ -1140,12 +1164,12 @@ type
   ## The getrlimit() and setrlimit() system calls get and set resource limits respectively.
   ## Each resource has an associated soft and hard limit, as defined by the RLimit structure
 
-proc setrlimit*(resource: cint, rlp: var RLimit): cint
-      {.importc: "setrlimit",header: "<sys/resource.h>".}
+proc setrlimit*(resource: cint, rlp: var RLimit): cint {.
+  importc: "setrlimit", header: "<sys/resource.h>".}
   ## The setrlimit() system calls sets resource limits.
 
-proc getrlimit*(resource: cint, rlp: var RLimit): cint
-      {.importc: "getrlimit",header: "<sys/resource.h>".}
+proc getrlimit*(resource: cint, rlp: var RLimit): cint {.
+  importc: "getrlimit", header: "<sys/resource.h>".}
   ## The getrlimit() system call gets resource limits.
 
 when defined(nimHasStyleChecks):
diff --git a/lib/posix/posix_linux_amd64.nim b/lib/posix/posix_linux_amd64.nim
index 4eb357d62..8d11c507d 100644
--- a/lib/posix/posix_linux_amd64.nim
+++ b/lib/posix/posix_linux_amd64.nim
@@ -309,7 +309,7 @@ type
     sa_mask*: Sigset ## Set of signals to be blocked during execution of
                       ## the signal handling function.
     sa_flags*: cint   ## Special flags.
-    sa_sigaction*: proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.}
+    sa_restorer: proc() {.noconv.}   ## not intended for application use.
 
   Stack* {.importc: "stack_t",
             header: "<signal.h>", final, pure.} = object ## stack_t
@@ -325,9 +325,9 @@ type
   SigInfo* {.importc: "siginfo_t",
               header: "<signal.h>", final, pure.} = object ## siginfo_t
     si_signo*: cint    ## Signal number.
-    si_code*: cint     ## Signal code.
     si_errno*: cint    ## If non-zero, an errno value associated with
                        ## this signal, as defined in <errno.h>.
+    si_code*: cint     ## Signal code.
     si_pid*: Pid       ## Sending process ID.
     si_uid*: Uid       ## Real user ID of sending process.
     si_addr*: pointer  ## Address of faulting instruction.
@@ -336,6 +336,12 @@ type
     si_value*: SigVal  ## Signal value.
     pad {.importc: "_pad".}: array[128 - 56, uint8]
 
+template sa_sigaction*(v: Sigaction): proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.} =
+  cast[proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.}](v.sa_handler)
+proc `sa_sigaction=`*(v: var Sigaction, x: proc (x: cint, y: ptr SigInfo, z: pointer) {.noconv.}) =
+  v.sa_handler = cast[proc (x: cint) {.noconv.}](x)
+
+type
   Nl_item* {.importc: "nl_item", header: "<nl_types.h>".} = cint
   Nl_catd* {.importc: "nl_catd", header: "<nl_types.h>".} = pointer
 
diff --git a/lib/posix/posix_linux_amd64_consts.nim b/lib/posix/posix_linux_amd64_consts.nim
index f3230f71d..fbe8d0666 100644
--- a/lib/posix/posix_linux_amd64_consts.nim
+++ b/lib/posix/posix_linux_amd64_consts.nim
@@ -453,6 +453,7 @@ const MAP_POPULATE* = cint(32768)
 
 # <sys/resource.h>
 const RLIMIT_NOFILE* = cint(7)
+const RLIMIT_STACK* = cint(3)
 
 # <sys/select.h>
 const FD_SETSIZE* = cint(1024)
@@ -464,6 +465,7 @@ const MSG_EOR* = cint(128)
 const MSG_OOB* = cint(1)
 const SCM_RIGHTS* = cint(1)
 const SO_ACCEPTCONN* = cint(30)
+const SO_BINDTODEVICE* = cint(25)
 const SO_BROADCAST* = cint(6)
 const SO_DEBUG* = cint(1)
 const SO_DONTROUTE* = cint(5)
diff --git a/lib/posix/posix_macos_amd64.nim b/lib/posix/posix_macos_amd64.nim
index d6b5834cb..a4b64ed62 100644
--- a/lib/posix/posix_macos_amd64.nim
+++ b/lib/posix/posix_macos_amd64.nim
@@ -122,10 +122,14 @@ type
     ## used for block sizes
   Clock* {.importc: "clock_t", header: "<sys/types.h>".} = int
   ClockId* {.importc: "clockid_t", header: "<sys/types.h>".} = int
-  Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32
+  Dev* {.importc: "dev_t", header: "<sys/types.h>".} = (
+    when defined(freebsd):
+      uint32
+    else:
+      int32)
   Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int
   Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int
-  Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32
+  Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32
   Id* {.importc: "id_t", header: "<sys/types.h>".} = int
   Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int
   Key* {.importc: "key_t", header: "<sys/types.h>".} = int
@@ -135,7 +139,7 @@ type
     else:
       uint16
   )
-  Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = int16
+  Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = uint16
   Off* {.importc: "off_t", header: "<sys/types.h>".} = int64
   Pid* {.importc: "pid_t", header: "<sys/types.h>".} = int32
   Pthread_attr* {.importc: "pthread_attr_t", header: "<sys/types.h>".} = int
@@ -167,7 +171,7 @@ type
   Trace_event_set* {.importc: "trace_event_set_t",
                       header: "<sys/types.h>".} = int
   Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int
-  Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32
+  Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32
   Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
 
   Utsname* {.importc: "struct utsname",
@@ -462,9 +466,9 @@ type
                    header: "<netinet/in.h>".} = object ## struct sockaddr_in6
     sin6_family*: TSa_Family ## AF_INET6.
     sin6_port*: InPort      ## Port number.
-    sin6_flowinfo*: int32    ## IPv6 traffic class and flow information.
+    sin6_flowinfo*: uint32    ## IPv6 traffic class and flow information.
     sin6_addr*: In6Addr     ## IPv6 address.
-    sin6_scope_id*: int32    ## Set of interfaces for a scope.
+    sin6_scope_id*: uint32    ## Set of interfaces for a scope.
 
   Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
                 header: "<netinet/in.h>".} = object ## struct ipv6_mreq
@@ -491,7 +495,7 @@ type
                              ## alternative network names, terminated by a
                              ## null pointer.
     n_addrtype*: cint        ## The address type of the network.
-    n_net*: int32            ## The network number, in host byte order.
+    n_net*: uint32            ## The network number, in host byte order.
 
   Protoent* {.importc: "struct protoent", pure, final,
               header: "<netdb.h>".} = object ## struct protoent
diff --git a/lib/posix/posix_openbsd_amd64.nim b/lib/posix/posix_openbsd_amd64.nim
index 1ef4a4182..184cd89c0 100644
--- a/lib/posix/posix_openbsd_amd64.nim
+++ b/lib/posix/posix_openbsd_amd64.nim
@@ -131,15 +131,19 @@ type
     ## used for block sizes
   Clock* {.importc: "clock_t", header: "<sys/types.h>".} = int
   ClockId* {.importc: "clockid_t", header: "<sys/types.h>".} = int
-  Dev* {.importc: "dev_t", header: "<sys/types.h>".} = int32
+  Dev* {.importc: "dev_t", header: "<sys/types.h>".} = (
+    when defined(freebsd):
+      uint32
+    else:
+      int32)
   Fsblkcnt* {.importc: "fsblkcnt_t", header: "<sys/types.h>".} = int
   Fsfilcnt* {.importc: "fsfilcnt_t", header: "<sys/types.h>".} = int
-  Gid* {.importc: "gid_t", header: "<sys/types.h>".} = int32
+  Gid* {.importc: "gid_t", header: "<sys/types.h>".} = uint32
   Id* {.importc: "id_t", header: "<sys/types.h>".} = int
   Ino* {.importc: "ino_t", header: "<sys/types.h>".} = int
   Key* {.importc: "key_t", header: "<sys/types.h>".} = int
   Mode* {.importc: "mode_t", header: "<sys/types.h>".} = uint32
-  Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = int16
+  Nlink* {.importc: "nlink_t", header: "<sys/types.h>".} = uint32
   Off* {.importc: "off_t", header: "<sys/types.h>".} = int64
   Pid* {.importc: "pid_t", header: "<sys/types.h>".} = int32
   Pthread_attr* {.importc: "pthread_attr_t", header: "<pthread.h>".} = int
@@ -171,7 +175,7 @@ type
   Trace_event_set* {.importc: "trace_event_set_t",
                       header: "<sys/types.h>".} = int
   Trace_id* {.importc: "trace_id_t", header: "<sys/types.h>".} = int
-  Uid* {.importc: "uid_t", header: "<sys/types.h>".} = int32
+  Uid* {.importc: "uid_t", header: "<sys/types.h>".} = uint32
   Useconds* {.importc: "useconds_t", header: "<sys/types.h>".} = int
 
   Utsname* {.importc: "struct utsname",
@@ -446,9 +450,9 @@ type
                    header: "<netinet/in.h>".} = object ## struct sockaddr_in6
     sin6_family*: TSa_Family ## AF_INET6.
     sin6_port*: InPort      ## Port number.
-    sin6_flowinfo*: int32    ## IPv6 traffic class and flow information.
+    sin6_flowinfo*: uint32    ## IPv6 traffic class and flow information.
     sin6_addr*: In6Addr     ## IPv6 address.
-    sin6_scope_id*: int32    ## Set of interfaces for a scope.
+    sin6_scope_id*: uint32    ## Set of interfaces for a scope.
 
   Tipv6_mreq* {.importc: "struct ipv6_mreq", pure, final,
                 header: "<netinet/in.h>".} = object ## struct ipv6_mreq
@@ -475,7 +479,7 @@ type
                              ## alternative network names, terminated by a
                              ## null pointer.
     n_addrtype*: cint        ## The address type of the network.
-    n_net*: int32            ## The network number, in host byte order.
+    n_net*: uint32            ## The network number, in host byte order.
 
   Protoent* {.importc: "struct protoent", pure, final,
               header: "<netdb.h>".} = object ## struct protoent
diff --git a/lib/posix/posix_other.nim b/lib/posix/posix_other.nim
index 941e13192..ea8731405 100644
--- a/lib/posix/posix_other.nim
+++ b/lib/posix/posix_other.nim
@@ -640,10 +640,13 @@ when defined(linux) or defined(nimdoc):
       ## or UDP packets. (Requires Linux kernel > 3.9)
   else:
     const SO_REUSEPORT* = cint(15)
+elif defined(nuttx):
+  # Not supported, use SO_REUSEADDR to avoid compilation errors.
+  var SO_REUSEPORT* {.importc: "SO_REUSEADDR", header: "<sys/socket.h>".}: cint
 else:
   var SO_REUSEPORT* {.importc, header: "<sys/socket.h>".}: cint
 
-when defined(linux) or defined(bsd):
+when defined(linux) or defined(bsd) or defined(nuttx):
   var SOCK_CLOEXEC* {.importc, header: "<sys/socket.h>".}: cint
 
 when defined(macosx):
@@ -672,14 +675,14 @@ when defined(haiku):
 
 when hasSpawnH:
   when defined(linux):
-    # better be safe than sorry; Linux has this flag, macosx doesn't, don't
-    # know about the other OSes
+    # better be safe than sorry; Linux has this flag, macosx and NuttX don't,
+    # don't know about the other OSes
 
-    # Non-GNU systems like TCC and musl-libc  don't define __USE_GNU, so we
+    # Non-GNU systems like TCC and musl-libc don't define __USE_GNU, so we
     # can't get the magic number from spawn.h
     const POSIX_SPAWN_USEVFORK* = cint(0x40)
   else:
-    # macosx lacks this, so we define the constant to be 0 to not affect
+    # macosx and NuttX lack this, so we define the constant to be 0 to not affect
     # OR'ing of flags:
     const POSIX_SPAWN_USEVFORK* = cint(0)
 
diff --git a/lib/posix/posix_other_consts.nim b/lib/posix/posix_other_consts.nim
index 59ac6f9ed..d346b4150 100644
--- a/lib/posix/posix_other_consts.nim
+++ b/lib/posix/posix_other_consts.nim
@@ -99,7 +99,10 @@ var EXDEV* {.importc: "EXDEV", header: "<errno.h>".}: cint
 
 # <fcntl.h>
 var F_DUPFD* {.importc: "F_DUPFD", header: "<fcntl.h>".}: cint
-var F_DUPFD_CLOEXEC* {.importc: "F_DUPFD", header: "<fcntl.h>".}: cint
+when defined(nuttx):
+  var F_DUPFD_CLOEXEC* {.importc: "F_DUPFD_CLOEXEC", header: "<fcntl.h>".}: cint
+else:
+  var F_DUPFD_CLOEXEC* {.importc: "F_DUPFD", header: "<fcntl.h>".}: cint
 var F_GETFD* {.importc: "F_GETFD", header: "<fcntl.h>".}: cint
 var F_SETFD* {.importc: "F_SETFD", header: "<fcntl.h>".}: cint
 var F_GETFL* {.importc: "F_GETFL", header: "<fcntl.h>".}: cint
@@ -127,6 +130,11 @@ var O_RDONLY* {.importc: "O_RDONLY", header: "<fcntl.h>".}: cint
 var O_RDWR* {.importc: "O_RDWR", header: "<fcntl.h>".}: cint
 var O_WRONLY* {.importc: "O_WRONLY", header: "<fcntl.h>".}: cint
 var O_CLOEXEC* {.importc: "O_CLOEXEC", header: "<fcntl.h>".}: cint
+when defined(nuttx):
+  var O_DIRECT* {.importc: "O_DIRECT", header: "<fcntl.h>".}: cint
+  var O_PATH* {.importc: "O_PATH", header: "<fcntl.h>".}: cint
+  var O_NOATIME* {.importc: "O_NOATIME", header: "<fcntl.h>".}: cint
+  var O_TMPFILE* {.importc: "O_TMPFILE", header: "<fcntl.h>".}: cint
 var POSIX_FADV_NORMAL* {.importc: "POSIX_FADV_NORMAL", header: "<fcntl.h>".}: cint
 var POSIX_FADV_SEQUENTIAL* {.importc: "POSIX_FADV_SEQUENTIAL", header: "<fcntl.h>".}: cint
 var POSIX_FADV_RANDOM* {.importc: "POSIX_FADV_RANDOM", header: "<fcntl.h>".}: cint
@@ -459,6 +467,7 @@ var POSIX_TYPED_MEM_MAP_ALLOCATABLE* {.importc: "POSIX_TYPED_MEM_MAP_ALLOCATABLE
 
 # <sys/resource.h>
 var RLIMIT_NOFILE* {.importc: "RLIMIT_NOFILE", header: "<sys/resource.h>".}: cint
+var RLIMIT_STACK* {.importc: "RLIMIT_STACK", header: "<sys/resource.h>".}: cint
 
 # <sys/select.h>
 var FD_SETSIZE* {.importc: "FD_SETSIZE", header: "<sys/select.h>".}: cint
@@ -473,6 +482,7 @@ var MSG_EOR* {.importc: "MSG_EOR", header: "<sys/socket.h>".}: cint
 var MSG_OOB* {.importc: "MSG_OOB", header: "<sys/socket.h>".}: cint
 var SCM_RIGHTS* {.importc: "SCM_RIGHTS", header: "<sys/socket.h>".}: cint
 var SO_ACCEPTCONN* {.importc: "SO_ACCEPTCONN", header: "<sys/socket.h>".}: cint
+var SO_BINDTODEVICE* {.importc: "SO_BINDTODEVICE", header: "<sys/socket.h>".}: cint
 var SO_BROADCAST* {.importc: "SO_BROADCAST", header: "<sys/socket.h>".}: cint
 var SO_DEBUG* {.importc: "SO_DEBUG", header: "<sys/socket.h>".}: cint
 var SO_DONTROUTE* {.importc: "SO_DONTROUTE", header: "<sys/socket.h>".}: cint
@@ -742,3 +752,6 @@ var SEEK_SET* {.importc: "SEEK_SET", header: "<unistd.h>".}: cint
 var SEEK_CUR* {.importc: "SEEK_CUR", header: "<unistd.h>".}: cint
 var SEEK_END* {.importc: "SEEK_END", header: "<unistd.h>".}: cint
 
+# <nuttx/config.h>
+when defined(nuttx):
+  var NEPOLL_MAX* {.importc: "CONFIG_FS_NEPOLL_DESCRIPTORS", header: "<nuttx/config.h>".}: cint
diff --git a/lib/posix/posix_utils.nim b/lib/posix/posix_utils.nim
index 92fe0940d..0c668246f 100644
--- a/lib/posix/posix_utils.nim
+++ b/lib/posix/posix_utils.nim
@@ -11,7 +11,7 @@
 
 # Where possible, contribute OS-independent procs in `os <os.html>`_ instead.
 
-import posix, parsecfg, os
+import std/[posix, parsecfg, os]
 import std/private/since
 
 when defined(nimPreviewSlimSystem):
@@ -34,7 +34,7 @@ proc uname*(): Uname =
 
   var u: Utsname
   if uname(u) != 0:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
 
   result.sysname = charArrayToString u.sysname
   result.nodename = charArrayToString u.nodename
@@ -43,19 +43,19 @@ proc uname*(): Uname =
   result.machine = charArrayToString u.machine
 
 proc fsync*(fd: int) =
- ## synchronize a file's buffer cache to the storage device
- if fsync(fd.cint) != 0:
-    raise newException(OSError, $strerror(errno))
+  ## synchronize a file's buffer cache to the storage device
+  if fsync(fd.cint) != 0:
+    raiseOSError(OSErrorCode(errno))
 
 proc stat*(path: string): Stat =
   ## Returns file status in a `Stat` structure
   if stat(path.cstring, result) != 0:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
 
 proc memoryLock*(a1: pointer, a2: int) =
   ## Locks pages starting from a1 for a1 bytes and prevent them from being swapped.
   if mlock(a1, a2) != 0:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
 
 proc memoryLockAll*(flags: int) =
   ## Locks all memory for the running process to prevent swapping.
@@ -65,23 +65,23 @@ proc memoryLockAll*(flags: int) =
   ##   memoryLockAll(MCL_CURRENT or MCL_FUTURE)
   ##   ```
   if mlockall(flags.cint) != 0:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
 
 proc memoryUnlock*(a1: pointer, a2: int) =
   ## Unlock pages starting from a1 for a1 bytes and allow them to be swapped.
   if munlock(a1, a2) != 0:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
 
 proc memoryUnlockAll*() =
   ## Unlocks all memory for the running process to allow swapping.
   if munlockall() != 0:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
 
 proc sendSignal*(pid: Pid, signal: int) =
   ## Sends a signal to a running process by calling `kill`.
   ## Raise exception in case of failure e.g. process not running.
   if kill(pid, signal.cint) != 0:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
 
 proc mkstemp*(prefix: string, suffix=""): (string, File) =
   ## Creates a unique temporary file from a prefix string. A six-character string
@@ -90,7 +90,7 @@ proc mkstemp*(prefix: string, suffix=""): (string, File) =
   ## Returns the filename and a file opened in r/w mode.
   var tmpl = cstring(prefix & "XXXXXX" & suffix)
   let fd =
-    if len(suffix)==0:
+    if len(suffix) == 0:
       when declared(mkostemp):
         mkostemp(tmpl, O_CLOEXEC)
       else:
@@ -103,14 +103,14 @@ proc mkstemp*(prefix: string, suffix=""): (string, File) =
   var f: File
   if open(f, fd, fmReadWrite):
     return ($tmpl, f)
-  raise newException(OSError, $strerror(errno))
+  raiseOSError(OSErrorCode(errno))
 
 proc mkdtemp*(prefix: string): string =
   ## Creates a unique temporary directory from a prefix string. Adds a six chars suffix.
   ## The directory is created with permissions 0700. Returns the directory name.
   var tmpl = cstring(prefix & "XXXXXX")
   if mkdtemp(tmpl) == nil:
-    raise newException(OSError, $strerror(errno))
+    raiseOSError(OSErrorCode(errno))
   return $tmpl
 
 proc osReleaseFile*(): Config {.since: (1, 5).} =
diff --git a/lib/posix/termios.nim b/lib/posix/termios.nim
index f755c720d..7fb6bb81c 100644
--- a/lib/posix/termios.nim
+++ b/lib/posix/termios.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-import posix
+import std/posix
 
 type
   Speed* = cuint
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 65402e9fb..b12ed7cdd 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -387,7 +387,7 @@ func sort*[T](a: var openArray[T],
   ##   ```
   ##
   ## You can inline adhoc comparison procs with the `do notation
-  ## <manual_experimental.html#do-notation>`_. Example:
+  ## <manual.html#procedures-do-notation>`_. Example:
   ##
   ##   ```nim
   ##   people.sort do (x, y: Person) -> int:
diff --git a/lib/pure/async.nim b/lib/pure/async.nim
index 249c5f639..e4d8d41c3 100644
--- a/lib/pure/async.nim
+++ b/lib/pure/async.nim
@@ -2,8 +2,8 @@
 ## and [asyncjs](asyncjs.html) on the JS backend. 
 
 when defined(js):
-  import asyncjs
+  import std/asyncjs
   export asyncjs
 else:
-  import asyncmacro, asyncfutures
+  import std/[asyncmacro, asyncfutures]
   export asyncmacro, asyncfutures
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index 214b7d12c..126db7a7f 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -226,11 +226,11 @@
 ## ``none`` can be used when a library supports both a synchronous and
 ## asynchronous API, to disable the latter.
 
-import os, tables, strutils, times, heapqueue, options, asyncstreams
-import options, math, std/monotimes
-import asyncfutures except callSoon
+import std/[os, tables, strutils, times, heapqueue, options, asyncstreams]
+import std/[math, monotimes]
+import std/asyncfutures except callSoon
 
-import nativesockets, net, deques
+import std/[nativesockets, net, deques]
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio]
@@ -302,7 +302,7 @@ template implementSetInheritable() {.dirty.} =
       fd.FileHandle.setInheritable(inheritable)
 
 when defined(windows) or defined(nimdoc):
-  import winlean, sets, hashes
+  import std/[winlean, sets, hashes]
   type
     CompletionKey = ULONG_PTR
 
@@ -533,7 +533,7 @@ when defined(windows) or defined(nimdoc):
             if flags.isDisconnectionError(errcode):
               retFuture.complete("")
             else:
-              retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+              retFuture.fail(newOSError(errcode))
         if dataBuf.buf != nil:
           dealloc dataBuf.buf
           dataBuf.buf = nil
@@ -551,7 +551,7 @@ when defined(windows) or defined(nimdoc):
         if flags.isDisconnectionError(err):
           retFuture.complete("")
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(err)))
+          retFuture.fail(newOSError(err))
     elif ret == 0:
       # Request completed immediately.
       if bytesReceived != 0:
@@ -603,7 +603,7 @@ when defined(windows) or defined(nimdoc):
             if flags.isDisconnectionError(errcode):
               retFuture.complete(0)
             else:
-              retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+              retFuture.fail(newOSError(errcode))
         if dataBuf.buf != nil:
           dataBuf.buf = nil
     )
@@ -619,7 +619,7 @@ when defined(windows) or defined(nimdoc):
         if flags.isDisconnectionError(err):
           retFuture.complete(0)
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(err)))
+          retFuture.fail(newOSError(err))
     elif ret == 0:
       # Request completed immediately.
       if bytesReceived != 0:
@@ -667,7 +667,7 @@ when defined(windows) or defined(nimdoc):
         if flags.isDisconnectionError(err):
           retFuture.complete()
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(err)))
+          retFuture.fail(newOSError(err))
     else:
       retFuture.complete()
       # We don't deallocate `ol` here because even though this completed
@@ -702,7 +702,7 @@ when defined(windows) or defined(nimdoc):
           if errcode == OSErrorCode(-1):
             retFuture.complete()
           else:
-            retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+            retFuture.fail(newOSError(errcode))
     )
 
     let ret = WSASendTo(socket.SocketHandle, addr dataBuf, 1, addr bytesSent,
@@ -712,7 +712,7 @@ when defined(windows) or defined(nimdoc):
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
         GC_unref(ol)
-        retFuture.fail(newException(OSError, osErrorMsg(err)))
+        retFuture.fail(newOSError(err))
     else:
       retFuture.complete()
       # We don't deallocate `ol` here because even though this completed
@@ -746,7 +746,7 @@ when defined(windows) or defined(nimdoc):
           else:
             # datagram sockets don't have disconnection,
             # so we can just raise an exception
-            retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+            retFuture.fail(newOSError(errcode))
     )
 
     let res = WSARecvFrom(socket.SocketHandle, addr dataBuf, 1,
@@ -757,7 +757,7 @@ when defined(windows) or defined(nimdoc):
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
         GC_unref(ol)
-        retFuture.fail(newException(OSError, osErrorMsg(err)))
+        retFuture.fail(newOSError(err))
     else:
       # Request completed immediately.
       if bytesReceived != 0:
@@ -808,7 +808,7 @@ when defined(windows) or defined(nimdoc):
             else:
               retFuture.complete(newAcceptFut.read)
       else:
-        retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+        retFuture.fail(newOSError(errcode))
 
     template completeAccept() {.dirty.} =
       var listenSock = socket
@@ -1166,11 +1166,11 @@ when defined(windows) or defined(nimdoc):
 
   initAll()
 else:
-  import selectors
-  from posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
+  import std/selectors
+  from std/posix import EINTR, EAGAIN, EINPROGRESS, EWOULDBLOCK, MSG_PEEK,
                     MSG_NOSIGNAL
   when declared(posix.accept4):
-    from posix import accept4, SOCK_CLOEXEC
+    from std/posix import accept4, SOCK_CLOEXEC
   when defined(genode):
     import genode/env # get the implicit Genode env
     import genode/signals
@@ -1216,6 +1216,15 @@ else:
 
   var gDisp{.threadvar.}: owned PDispatcher ## Global dispatcher
 
+  when defined(nuttx):
+    import std/exitprocs
+
+    proc cleanDispatcher() {.noconv.} =
+      gDisp = nil
+
+    proc addFinalyzer() =
+      addExitProc(cleanDispatcher)
+
   proc setGlobalDispatcher*(disp: owned PDispatcher) =
     if not gDisp.isNil:
       assert gDisp.callbacks.len == 0
@@ -1225,6 +1234,8 @@ else:
   proc getGlobalDispatcher*(): PDispatcher =
     if gDisp.isNil:
       setGlobalDispatcher(newDispatcher())
+      when defined(nuttx):
+        addFinalyzer()
     result = gDisp
 
   proc getIoHandler*(disp: PDispatcher): Selector[AsyncData] =
@@ -1457,7 +1468,7 @@ else:
           if flags.isDisconnectionError(lastError):
             retFuture.complete("")
           else:
-            retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+            retFuture.fail(newOSError(lastError))
         else:
           result = false # We still want this callback to be called.
       elif res == 0:
@@ -1486,7 +1497,7 @@ else:
           if flags.isDisconnectionError(lastError):
             retFuture.complete(0)
           else:
-            retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+            retFuture.fail(newOSError(lastError))
         else:
           result = false # We still want this callback to be called.
       else:
@@ -1552,7 +1563,7 @@ else:
         let lastError = osLastError()
         if lastError.int32 != EINTR and lastError.int32 != EWOULDBLOCK and
            lastError.int32 != EAGAIN:
-          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+          retFuture.fail(newOSError(lastError))
         else:
           result = false # We still want this callback to be called.
       else:
@@ -1578,7 +1589,7 @@ else:
         let lastError = osLastError()
         if lastError.int32 != EINTR and lastError.int32 != EWOULDBLOCK and
            lastError.int32 != EAGAIN:
-          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+          retFuture.fail(newOSError(lastError))
         else:
           result = false
       else:
@@ -1591,7 +1602,7 @@ else:
       owned(Future[tuple[address: string, client: AsyncFD]]) =
     var retFuture = newFuture[tuple[address: string,
         client: AsyncFD]]("acceptAddr")
-    proc cb(sock: AsyncFD): bool =
+    proc cb(sock: AsyncFD): bool {.gcsafe.} =
       result = true
       var sockAddress: Sockaddr_storage
       var addrLen = sizeof(sockAddress).SockLen
@@ -1619,7 +1630,7 @@ else:
           if flags.isDisconnectionError(lastError):
             return false
           else:
-            retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+            retFuture.fail(newOSError(lastError))
       else:
         try:
           let address = getAddrString(cast[ptr SockAddr](addr sockAddress))
@@ -1752,7 +1763,7 @@ when defined(windows) or defined(nimdoc):
             socket.SocketHandle.setSockOptInt(SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, 1) # 15022
             retFuture.complete()
           else:
-            retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+            retFuture.fail(newOSError(errcode))
     )
 
     let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr,
@@ -1770,7 +1781,7 @@ when defined(windows) or defined(nimdoc):
         # With ERROR_IO_PENDING `ol` will be deallocated in `poll`,
         # and the future will be completed/failed there, too.
         GC_unref(ol)
-        retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+        retFuture.fail(newOSError(lastError))
 else:
   proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): owned(Future[void]) =
     let retFuture = newFuture[void]("doConnect")
@@ -1787,7 +1798,7 @@ else:
         # interrupted, keep waiting
         return false
       else:
-        retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret))))
+        retFuture.fail(newOSError(OSErrorCode(ret)))
         return true
 
     let ret = connect(socket.SocketHandle,
@@ -1801,7 +1812,7 @@ else:
       if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
         addWrite(socket, cb)
       else:
-        retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+        retFuture.fail(newOSError(lastError))
 
 template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped,
                            protocol: Protocol = IPPROTO_RAW) =
@@ -1983,7 +1994,7 @@ proc send*(socket: AsyncFD, data: string,
   return retFuture
 
 # -- Await Macro
-import asyncmacro
+import std/asyncmacro
 export asyncmacro
 
 proc readAll*(future: FutureStream[string]): owned(Future[string]) {.async.} =
@@ -2021,10 +2032,10 @@ proc activeDescriptors*(): int {.inline.} =
     result = getGlobalDispatcher().selector.count
 
 when defined(posix):
-  import posix
+  import std/posix
 
 when defined(linux) or defined(windows) or defined(macosx) or defined(bsd) or
-       defined(solaris) or defined(zephyr) or defined(freertos):
+       defined(solaris) or defined(zephyr) or defined(freertos) or defined(nuttx) or defined(haiku):
   proc maxDescriptors*(): int {.raises: OSError.} =
     ## Returns the maximum number of active file descriptors for the current
     ## process. This involves a system call. For now `maxDescriptors` is
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim
index 88fa90406..0f6504342 100644
--- a/lib/pure/asyncfile.nim
+++ b/lib/pure/asyncfile.nim
@@ -23,7 +23,7 @@
 ##   waitFor main()
 ##   ```
 
-import asyncdispatch, os
+import std/[asyncdispatch, os]
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio]
@@ -33,9 +33,9 @@ when defined(nimPreviewSlimSystem):
 # TODO: Fix duplication introduced by PR #4683.
 
 when defined(windows) or defined(nimdoc):
-  import winlean
+  import std/winlean
 else:
-  import posix
+  import std/posix
 
 type
   AsyncFile* = ref object
@@ -102,14 +102,9 @@ proc openAsync*(filename: string, mode = fmRead): AsyncFile =
     let flags = FILE_FLAG_OVERLAPPED or FILE_ATTRIBUTE_NORMAL
     let desiredAccess = getDesiredAccess(mode)
     let creationDisposition = getCreationDisposition(mode, filename)
-    when useWinUnicode:
-      let fd = createFileW(newWideCString(filename), desiredAccess,
-          FILE_SHARE_READ,
-          nil, creationDisposition, flags, 0)
-    else:
-      let fd = createFileA(filename, desiredAccess,
-          FILE_SHARE_READ,
-          nil, creationDisposition, flags, 0)
+    let fd = createFileW(newWideCString(filename), desiredAccess,
+        FILE_SHARE_READ,
+        nil, creationDisposition, flags, 0)
 
     if fd == INVALID_HANDLE_VALUE:
       raiseOSError(osLastError())
@@ -151,7 +146,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] =
             if errcode.int32 == ERROR_HANDLE_EOF:
               retFuture.complete(0)
             else:
-              retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+              retFuture.fail(newOSError(errcode))
     )
     ol.offset = DWORD(f.offset and 0xffffffff)
     ol.offsetHigh = DWORD(f.offset shr 32)
@@ -167,7 +162,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] =
           # This happens in Windows Server 2003
           retFuture.complete(0)
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(err)))
+          retFuture.fail(newOSError(err))
     else:
       # Request completed immediately.
       var bytesRead: DWORD
@@ -178,7 +173,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] =
         if err.int32 == ERROR_HANDLE_EOF:
           retFuture.complete(0)
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(osLastError())))
+          retFuture.fail(newOSError(osLastError()))
       else:
         assert bytesRead > 0
         assert bytesRead <= size
@@ -191,7 +186,7 @@ proc readBuffer*(f: AsyncFile, buf: pointer, size: int): Future[int] =
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 != EAGAIN:
-          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+          retFuture.fail(newOSError(lastError))
         else:
           result = false # We still want this callback to be called.
       elif res == 0:
@@ -233,7 +228,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
             if errcode.int32 == ERROR_HANDLE_EOF:
               retFuture.complete("")
             else:
-              retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+              retFuture.fail(newOSError(errcode))
         if buffer != nil:
           dealloc buffer
           buffer = nil
@@ -256,7 +251,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
           # This happens in Windows Server 2003
           retFuture.complete("")
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(err)))
+          retFuture.fail(newOSError(err))
     else:
       # Request completed immediately.
       var bytesRead: DWORD
@@ -267,7 +262,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
         if err.int32 == ERROR_HANDLE_EOF:
           retFuture.complete("")
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(osLastError())))
+          retFuture.fail(newOSError(osLastError()))
       else:
         assert bytesRead > 0
         assert bytesRead <= size
@@ -284,7 +279,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 != EAGAIN:
-          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+          retFuture.fail(newOSError(lastError))
         else:
           result = false # We still want this callback to be called.
       elif res == 0:
@@ -306,6 +301,8 @@ proc readLine*(f: AsyncFile): Future[string] {.async.} =
   result = ""
   while true:
     var c = await read(f, 1)
+    if c.len == 0:
+      break
     if c[0] == '\c':
       c = await read(f, 1)
       break
@@ -353,7 +350,7 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] =
             assert bytesCount == size.int32
             retFuture.complete()
           else:
-            retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+            retFuture.fail(newOSError(errcode))
     )
     # passing -1 here should work according to MSDN, but doesn't. For more
     # information see
@@ -370,14 +367,14 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] =
       let err = osLastError()
       if err.int32 != ERROR_IO_PENDING:
         GC_unref(ol)
-        retFuture.fail(newException(OSError, osErrorMsg(err)))
+        retFuture.fail(newOSError(err))
     else:
       # Request completed immediately.
       var bytesWritten: DWORD
       let overlappedRes = getOverlappedResult(f.fd.Handle,
           cast[POVERLAPPED](ol), bytesWritten, false.WINBOOL)
       if not overlappedRes.bool:
-        retFuture.fail(newException(OSError, osErrorMsg(osLastError())))
+        retFuture.fail(newOSError(osLastError()))
       else:
         assert bytesWritten == size.int32
         retFuture.complete()
@@ -392,7 +389,7 @@ proc writeBuffer*(f: AsyncFile, buf: pointer, size: int): Future[void] =
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 != EAGAIN:
-          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+          retFuture.fail(newOSError(lastError))
         else:
           result = false # We still want this callback to be called.
       else:
@@ -426,7 +423,7 @@ proc write*(f: AsyncFile, data: string): Future[void] =
             assert bytesCount == data.len.int32
             retFuture.complete()
           else:
-            retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+            retFuture.fail(newOSError(errcode))
         if buffer != nil:
           dealloc buffer
           buffer = nil
@@ -445,14 +442,14 @@ proc write*(f: AsyncFile, data: string): Future[void] =
           dealloc buffer
           buffer = nil
         GC_unref(ol)
-        retFuture.fail(newException(OSError, osErrorMsg(err)))
+        retFuture.fail(newOSError(err))
     else:
       # Request completed immediately.
       var bytesWritten: DWORD
       let overlappedRes = getOverlappedResult(f.fd.Handle,
           cast[POVERLAPPED](ol), bytesWritten, false.WINBOOL)
       if not overlappedRes.bool:
-        retFuture.fail(newException(OSError, osErrorMsg(osLastError())))
+        retFuture.fail(newOSError(osLastError()))
       else:
         assert bytesWritten == data.len.int32
         retFuture.complete()
@@ -473,7 +470,7 @@ proc write*(f: AsyncFile, data: string): Future[void] =
       if res < 0:
         let lastError = osLastError()
         if lastError.int32 != EAGAIN:
-          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+          retFuture.fail(newOSError(lastError))
         else:
           result = false # We still want this callback to be called.
       else:
diff --git a/lib/pure/asyncfutures.nim b/lib/pure/asyncfutures.nim
index 035b6182d..29ebf8f89 100644
--- a/lib/pure/asyncfutures.nim
+++ b/lib/pure/asyncfutures.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-import os, tables, strutils, times, heapqueue, options, deques, cstrutils
+import std/[os, tables, strutils, times, heapqueue, options, deques, cstrutils, typetraits]
 
 import system/stacktraces
 
@@ -29,7 +29,7 @@ type
     finished: bool
     error*: ref Exception              ## Stored exception
     errorStackTrace*: string
-    when not defined(release):
+    when not defined(release) or defined(futureLogging):
       stackTrace: seq[StackTraceEntry] ## For debugging purposes only.
       id: int
       fromProc: string
@@ -51,7 +51,7 @@ const
   NimAsyncContinueSuffix* = "NimAsyncContinue" ## For internal usage. Do not use.
 
 when isFutureLoggingEnabled:
-  import hashes
+  import std/hashes
   type
     FutureInfo* = object
       stackTrace*: seq[StackTraceEntry]
@@ -193,7 +193,7 @@ proc add(callbacks: var CallbackList, function: CallbackFunc) =
         last = last.next
       last.next = newCallback
 
-proc completeImpl[T, U](future: Future[T], val: U, isVoid: static bool) =
+proc completeImpl[T, U](future: Future[T], val: sink U, isVoid: static bool) =
   #assert(not future.finished, "Future already finished, cannot finish twice.")
   checkFinished(future)
   assert(future.error == nil)
@@ -203,7 +203,7 @@ proc completeImpl[T, U](future: Future[T], val: U, isVoid: static bool) =
   future.callbacks.call()
   when isFutureLoggingEnabled: logFutureFinish(future)
 
-proc complete*[T](future: Future[T], val: T) =
+proc complete*[T](future: Future[T], val: sink T) =
   ## Completes `future` with value `val`.
   completeImpl(future, val, false)
 
@@ -219,7 +219,7 @@ proc complete*[T](future: FutureVar[T]) =
   fut.callbacks.call()
   when isFutureLoggingEnabled: logFutureFinish(Future[T](future))
 
-proc complete*[T](future: FutureVar[T], val: T) =
+proc complete*[T](future: FutureVar[T], val: sink T) =
   ## Completes a `FutureVar` with value `val`.
   ##
   ## Any previously stored value will be overwritten.
@@ -329,29 +329,21 @@ proc `$`*(stackTraceEntries: seq[StackTraceEntry]): string =
     if leftLen > longestLeft:
       longestLeft = leftLen
 
-  var indent = 2
   # Format the entries.
   for entry in entries:
     let (filename, procname) = getFilenameProcname(entry)
 
-    if procname == "":
-      if entry.line == reraisedFromBegin:
-        result.add(spaces(indent) & "#[\n")
-        indent.inc(2)
-      elif entry.line == reraisedFromEnd:
-        indent.dec(2)
-        result.add(spaces(indent) & "]#\n")
-      continue
+    if procname == "" and entry.line == reraisedFromBegin:
+      break
 
     let left = "$#($#)" % [filename, $entry.line]
-    result.add((spaces(indent) & "$#$# $#\n") % [
+    result.add((spaces(2) & "$# $#\n") % [
       left,
-      spaces(longestLeft - left.len + 2),
       procname
     ])
     let hint = getHint(entry)
     if hint.len > 0:
-      result.add(spaces(indent+2) & "## " & hint & "\n")
+      result.add(spaces(4) & "## " & hint & "\n")
 
 proc injectStacktrace[T](future: Future[T]) =
   when not defined(release):
@@ -378,11 +370,7 @@ proc injectStacktrace[T](future: Future[T]) =
     #   newMsg.add "\n" & $entry
     future.error.msg = newMsg
 
-proc read*[T](future: Future[T] | FutureVar[T]): T =
-  ## Retrieves the value of `future`. Future must be finished otherwise
-  ## this function will fail with a `ValueError` exception.
-  ##
-  ## If the result of the future is an error then that error will be raised.
+template readImpl(future, T) =
   when future is Future[T]:
     let fut {.cursor.} = future
   else:
@@ -392,11 +380,21 @@ proc read*[T](future: Future[T] | FutureVar[T]): T =
       injectStacktrace(fut)
       raise fut.error
     when T isnot void:
-      result = fut.value
+      result = distinctBase(future).value
   else:
     # TODO: Make a custom exception type for this?
     raise newException(ValueError, "Future still in progress.")
 
+proc read*[T](future: Future[T] | FutureVar[T]): lent T =
+  ## Retrieves the value of `future`. Future must be finished otherwise
+  ## this function will fail with a `ValueError` exception.
+  ##
+  ## If the result of the future is an error then that error will be raised.
+  readImpl(future, T)
+
+proc read*(future: Future[void] | FutureVar[void]) =
+  readImpl(future, void)
+
 proc readError*[T](future: Future[T]): ref Exception =
   ## Retrieves the exception stored in `future`.
   ##
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 6694c4bc2..39e945d5e 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -39,9 +39,9 @@ runnableExamples("-r:off"):
 
   waitFor main()
 
-import asyncnet, asyncdispatch, parseutils, uri, strutils
-import httpcore
-from nativesockets import getLocalAddr, Domain, AF_INET, AF_INET6
+import std/[asyncnet, asyncdispatch, parseutils, uri, strutils]
+import std/httpcore
+from std/nativesockets import getLocalAddr, Domain, AF_INET, AF_INET6
 import std/private/since
 
 when defined(nimPreviewSlimSystem):
@@ -110,16 +110,16 @@ proc respond*(req: Request, code: HttpCode, content: string,
   ## This procedure will **not** close the client socket.
   ##
   ## Example:
-  ##
-  ## .. code-block:: Nim
-  ##    import std/json
-  ##    proc handler(req: Request) {.async.} =
-  ##      if req.url.path == "/hello-world":
-  ##        let msg = %* {"message": "Hello World"}
-  ##        let headers = newHttpHeaders([("Content-Type","application/json")])
-  ##        await req.respond(Http200, $msg, headers)
-  ##      else:
-  ##        await req.respond(Http404, "Not Found")
+  ##   ```Nim
+  ##   import std/json
+  ##   proc handler(req: Request) {.async.} =
+  ##     if req.url.path == "/hello-world":
+  ##       let msg = %* {"message": "Hello World"}
+  ##       let headers = newHttpHeaders([("Content-Type","application/json")])
+  ##       await req.respond(Http200, $msg, headers)
+  ##     else:
+  ##       await req.respond(Http404, "Not Found")
+  ##   ```
   var msg = "HTTP/1.1 " & $code & "\c\L"
 
   if headers != nil:
@@ -158,7 +158,7 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] =
 proc sendStatus(client: AsyncSocket, status: string): Future[void] =
   client.send("HTTP/1.1 " & status & "\c\L\c\L")
 
-func hasChunkedEncoding(request: Request): bool = 
+func hasChunkedEncoding(request: Request): bool =
   ## Searches for a chunked transfer encoding
   const transferEncoding = "Transfer-Encoding"
 
@@ -187,7 +187,7 @@ proc processRequest(
   # \n
   request.headers.clear()
   request.body = ""
-  when defined(gcArc) or defined(gcOrc):
+  when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
     request.hostname = address
   else:
     request.hostname.shallowCopy(address)
@@ -300,7 +300,7 @@ proc processRequest(
     while true:
       lineFut.mget.setLen(0)
       lineFut.clean()
-      
+
       # The encoding format alternates between specifying a number of bytes to read
       # and the data to be read, of the previously specified size
       if sizeOrData mod 2 == 0:
@@ -387,8 +387,9 @@ proc listen*(server: AsyncHttpServer; port: Port; address = ""; domain = AF_INET
   server.socket = newAsyncSocket(domain)
   if server.reuseAddr:
     server.socket.setSockOpt(OptReuseAddr, true)
-  if server.reusePort:
-    server.socket.setSockOpt(OptReusePort, true)
+  when not defined(nuttx):
+    if server.reusePort:
+      server.socket.setSockOpt(OptReusePort, true)
   server.socket.bindAddr(port, address)
   server.socket.listen()
 
diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim
index 7ee324369..d4e72c28a 100644
--- a/lib/pure/asyncmacro.nim
+++ b/lib/pure/asyncmacro.nim
@@ -9,7 +9,12 @@
 
 ## Implements the `async` and `multisync` macros for `asyncdispatch`.
 
-import macros, strutils, asyncfutures
+import std/[macros, strutils, asyncfutures]
+
+type
+  Context = ref object
+    inTry: int
+    hasRet: bool
 
 # TODO: Ref https://github.com/nim-lang/Nim/issues/5617
 # TODO: Add more line infos
@@ -20,9 +25,8 @@ proc newCallWithLineInfo(fromNode: NimNode; theProc: NimNode, args: varargs[NimN
 template createCb(retFutureSym, iteratorNameSym,
                   strName, identName, futureVarCompletions: untyped) =
   bind finished
-
   var nameIterVar = iteratorNameSym
-  proc identName {.closure.} =
+  proc identName {.closure, stackTrace: off.} =
     try:
       if not nameIterVar.finished:
         var next = nameIterVar()
@@ -64,7 +68,7 @@ proc createFutureVarCompletions(futureVarIdents: seq[NimNode], fromNode: NimNode
       )
     )
 
-proc processBody(node, retFutureSym: NimNode, futureVarIdents: seq[NimNode]): NimNode =
+proc processBody(ctx: Context; node, needsCompletionSym, retFutureSym: NimNode, futureVarIdents: seq[NimNode]): NimNode =
   result = node
   case node.kind
   of nnkReturnStmt:
@@ -73,23 +77,53 @@ proc processBody(node, retFutureSym: NimNode, futureVarIdents: seq[NimNode]): Ni
     # As I've painfully found out, the order here really DOES matter.
     result.add createFutureVarCompletions(futureVarIdents, node)
 
+    ctx.hasRet = true
     if node[0].kind == nnkEmpty:
-      result.add newCall(newIdentNode("complete"), retFutureSym, newIdentNode("result"))
+      if ctx.inTry == 0:
+        result.add newCallWithLineInfo(node, newIdentNode("complete"), retFutureSym, newIdentNode("result"))
+      else:
+        result.add newAssignment(needsCompletionSym, newLit(true))
     else:
-      let x = node[0].processBody(retFutureSym, futureVarIdents)
+      let x = processBody(ctx, node[0], needsCompletionSym, retFutureSym, futureVarIdents)
       if x.kind == nnkYieldStmt: result.add x
+      elif ctx.inTry == 0:
+        result.add newCallWithLineInfo(node, newIdentNode("complete"), retFutureSym, x)
       else:
-        result.add newCall(newIdentNode("complete"), retFutureSym, x)
+        result.add newAssignment(newIdentNode("result"), x)
+        result.add newAssignment(needsCompletionSym, newLit(true))
 
     result.add newNimNode(nnkReturnStmt, node).add(newNilLit())
     return # Don't process the children of this return stmt
   of RoutineNodes-{nnkTemplateDef}:
     # skip all the nested procedure definitions
     return
-  else: discard
-
-  for i in 0 ..< result.len:
-    result[i] = processBody(result[i], retFutureSym, futureVarIdents)
+  of nnkTryStmt:
+    if result[^1].kind == nnkFinally:
+      inc ctx.inTry
+      result[0] = processBody(ctx, result[0], needsCompletionSym, retFutureSym, futureVarIdents)
+      dec ctx.inTry
+      for i in 1 ..< result.len:
+        result[i] = processBody(ctx, result[i], needsCompletionSym, retFutureSym, futureVarIdents)
+      if ctx.inTry == 0 and ctx.hasRet:
+        let finallyNode = copyNimNode(result[^1])
+        let stmtNode = newNimNode(nnkStmtList)
+        for child in result[^1]:
+          stmtNode.add child
+        stmtNode.add newIfStmt(
+          ( needsCompletionSym,
+            newCallWithLineInfo(node, newIdentNode("complete"), retFutureSym,
+            newIdentNode("result")
+            )
+          )
+        )
+        finallyNode.add stmtNode
+        result[^1] = finallyNode
+    else:
+      for i in 0 ..< result.len:
+        result[i] = processBody(ctx, result[i], needsCompletionSym, retFutureSym, futureVarIdents)
+  else:
+    for i in 0 ..< result.len:
+      result[i] = processBody(ctx, result[i], needsCompletionSym, retFutureSym, futureVarIdents)
 
   # echo result.repr
 
@@ -151,6 +185,10 @@ proc asyncSingleProc(prc: NimNode): NimNode =
       result[0][0] = quote do: Future[void]
     return result
 
+  if prc.kind in RoutineNodes and prc.name.kind != nnkEmpty:
+    # Only non anonymous functions need/can have stack trace disabled
+    prc.addPragma(nnkExprColonExpr.newTree(ident"stackTrace", ident"off"))
+
   if prc.kind notin {nnkProcDef, nnkLambda, nnkMethodDef, nnkDo}:
     error("Cannot transform this node kind into an async proc." &
           " proc/method definition or lambda node expected.", prc)
@@ -209,14 +247,23 @@ proc asyncSingleProc(prc: NimNode): NimNode =
   # ->   {.pop.}
   # ->   <proc_body>
   # ->   complete(retFuture, result)
-  var iteratorNameSym = genSym(nskIterator, $prcName & "Iter")
-  var procBody = prc.body.processBody(retFutureSym, futureVarIdents)
+  var iteratorNameSym = genSym(nskIterator, $prcName & " (Async)")
+  var needsCompletionSym = genSym(nskVar, "needsCompletion")
+  var ctx = Context()
+  var procBody = processBody(ctx, prc.body, needsCompletionSym, retFutureSym, futureVarIdents)
   # don't do anything with forward bodies (empty)
   if procBody.kind != nnkEmpty:
     # fix #13899, defer should not escape its original scope
-    procBody = newStmtList(newTree(nnkBlockStmt, newEmptyNode(), procBody))
-    procBody.add(createFutureVarCompletions(futureVarIdents, nil))
+    let blockStmt = newStmtList(newTree(nnkBlockStmt, newEmptyNode(), procBody))
+    procBody = newStmtList()
     let resultIdent = ident"result"
+    procBody.add quote do:
+      # Check whether there is an implicit return
+      when typeof(`blockStmt`) is void:
+        `blockStmt`
+      else:
+        `resultIdent` = `blockStmt`
+    procBody.add(createFutureVarCompletions(futureVarIdents, nil))
     procBody.insert(0): quote do:
       {.push warning[resultshadowed]: off.}
       when `subRetType` isnot void:
@@ -224,6 +271,8 @@ proc asyncSingleProc(prc: NimNode): NimNode =
       else:
         var `resultIdent`: Future[void]
       {.pop.}
+
+      var `needsCompletionSym` = false
     procBody.add quote do:
       complete(`retFutureSym`, `resultIdent`)
 
@@ -242,9 +291,10 @@ proc asyncSingleProc(prc: NimNode): NimNode =
     # friendlier stack traces:
     var cbName = genSym(nskProc, prcName & NimAsyncContinueSuffix)
     var procCb = getAst createCb(retFutureSym, iteratorNameSym,
-                         newStrLitNode(prcName),
-                         cbName,
-                         createFutureVarCompletions(futureVarIdents, nil))
+                          newStrLitNode(prcName),
+                          cbName,
+                          createFutureVarCompletions(futureVarIdents, nil)
+                        )
     outerProcBody.add procCb
 
     # -> return retFuture
@@ -277,8 +327,8 @@ macro async*(prc: untyped): untyped =
 proc splitParamType(paramType: NimNode, async: bool): NimNode =
   result = paramType
   if paramType.kind == nnkInfix and paramType[0].strVal in ["|", "or"]:
-    let firstAsync = "async" in paramType[1].strVal.normalize
-    let secondAsync = "async" in paramType[2].strVal.normalize
+    let firstAsync = "async" in paramType[1].toStrLit().strVal.normalize
+    let secondAsync = "async" in paramType[2].toStrLit().strVal.normalize
 
     if firstAsync:
       result = paramType[if async: 1 else: 2]
diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim
index 982459af7..ee07e599e 100644
--- a/lib/pure/asyncnet.nim
+++ b/lib/pure/asyncnet.nim
@@ -99,17 +99,18 @@ import std/private/since
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio]
 
-import asyncdispatch, nativesockets, net, os
+import std/[asyncdispatch, nativesockets, net, os]
 
 export SOBool
 
 # TODO: Remove duplication introduced by PR #4683.
 
 const defineSsl = defined(ssl) or defined(nimdoc)
-const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr)
+const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr) or
+    defined(nuttx)
 
 when defineSsl:
-  import openssl
+  import std/openssl
 
 type
   # TODO: I would prefer to just do:
@@ -264,14 +265,17 @@ when defineSsl:
       ErrClearError()
       # Call the desired operation.
       opResult = op
-
+      let err =
+        if opResult < 0:
+          getSslError(socket, opResult.cint)
+        else:
+          SSL_ERROR_NONE
       # Send any remaining pending SSL data.
       await sendPendingSslData(socket, flags)
 
       # If the operation failed, try to see if SSL has some data to read
       # or write.
       if opResult < 0:
-        let err = getSslError(socket, opResult.cint)
         let fut = appeaseSsl(socket, flags, err.cint)
         yield fut
         if not fut.read():
@@ -678,12 +682,12 @@ when defined(posix) and not useNimNetLite:
         elif ret == EINTR:
           return false
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret))))
+          retFuture.fail(newOSError(OSErrorCode(ret)))
           return true
 
       var socketAddr = makeUnixAddr(path)
       let ret = socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
-                        (sizeof(socketAddr.sun_family) + path.len).SockLen)
+                        (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen)
       if ret == 0:
         # Request to connect completed immediately.
         retFuture.complete()
@@ -692,7 +696,7 @@ when defined(posix) and not useNimNetLite:
         if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
           addWrite(AsyncFD(socket.fd), cb)
         else:
-          retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+          retFuture.fail(newOSError(lastError))
 
   proc bindUnix*(socket: AsyncSocket, path: string) {.
     tags: [ReadIOEffect].} =
@@ -701,7 +705,7 @@ when defined(posix) and not useNimNetLite:
     when not defined(nimdoc):
       var socketAddr = makeUnixAddr(path)
       if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
-          (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32:
+          (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen) != 0'i32:
         raiseOSError(osLastError())
 
 elif defined(nimdoc):
diff --git a/lib/pure/asyncstreams.nim b/lib/pure/asyncstreams.nim
index 3f7774ed8..c97b98d55 100644
--- a/lib/pure/asyncstreams.nim
+++ b/lib/pure/asyncstreams.nim
@@ -9,12 +9,12 @@
 
 ## Unstable API.
 
-import asyncfutures
+import std/asyncfutures
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
-import deques
+import std/deques
 
 type
   FutureStream*[T] = ref object ## Special future that acts as
diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim
index 795820433..591d22cc0 100644
--- a/lib/pure/base64.nim
+++ b/lib/pure/base64.nim
@@ -66,15 +66,11 @@ template cbBase(a, b): untyped = [
   'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
   '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', a, b]
 
-let
+const
   cb64 = cbBase('+', '/')
   cb64safe = cbBase('-', '_')
 
 const
-  cb64VM = cbBase('+', '/')
-  cb64safeVM = cbBase('-', '_')
-
-const
   invalidChar = 255
 
 template encodeSize(size: int): int = (size * 4 div 3) + 6
@@ -134,14 +130,10 @@ template encodeInternal(s, alphabet: typed): untyped =
   result.setLen(outputIndex)
 
 template encodeImpl() {.dirty.} =
-  when nimvm:
-    block:
-      let lookupTableVM = if safe: cb64safeVM else: cb64VM
-      encodeInternal(s, lookupTableVM)
+  if safe:
+    encodeInternal(s, cb64safe)
   else:
-    block:
-      let lookupTable = if safe: unsafeAddr(cb64safe) else: unsafeAddr(cb64)
-      encodeInternal(s, lookupTable)
+    encodeInternal(s, cb64)
 
 proc encode*[T: byte|char](s: openArray[T], safe = false): string =
   ## Encodes `s` into base64 representation.
@@ -252,7 +244,7 @@ proc decode*(s: string): string =
     inputLen = s.len
     inputEnds = 0
   # strip trailing characters
-  while s[inputLen - 1] in {'\n', '\r', ' ', '='}:
+  while inputLen > 0 and s[inputLen - 1] in {'\n', '\r', ' ', '='}:
     dec inputLen
   # hot loop: read 4 characters at at time
   inputEnds = inputLen - 4
diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim
index a518c25d2..0d3351ee5 100644
--- a/lib/pure/bitops.nim
+++ b/lib/pure/bitops.nim
@@ -25,7 +25,7 @@
 ## At this time only `fastLog2`, `firstSetBit`, `countLeadingZeroBits` and `countTrailingZeroBits`
 ## may return undefined and/or platform dependent values if given invalid input.
 
-import macros
+import std/macros
 import std/private/since
 from std/private/bitops_utils import forwardImpl, castToUnsigned
 
@@ -63,6 +63,12 @@ macro bitxor*[T: SomeInteger](x, y: T; z: varargs[T]): T =
 type BitsRange*[T] = range[0..sizeof(T)*8-1]
   ## A range with all bit positions for type `T`.
 
+template typeMasked[T: SomeInteger](x: T): T =
+  when defined(js):
+    T(x and ((0xffffffff_ffffffff'u shr (64 - sizeof(T) * 8))))
+  else:
+    x
+
 func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1, 3).} =
   ## Returns an extracted (and shifted) slice of bits from `v`.
   runnableExamples:
@@ -73,7 +79,7 @@ func bitsliced*[T: SomeInteger](v: T; slice: Slice[int]): T {.inline, since: (1,
   let
     upmost = sizeof(T) * 8 - 1
     uv     = v.castToUnsigned
-  (uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
+  ((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
 
 proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1, 3).} =
   ## Mutates `v` into an extracted (and shifted) slice of bits from `v`.
@@ -85,7 +91,7 @@ proc bitslice*[T: SomeInteger](v: var T; slice: Slice[int]) {.inline, since: (1,
   let
     upmost = sizeof(T) * 8 - 1
     uv     = v.castToUnsigned
-  v = (uv shl (upmost - slice.b) shr (upmost - slice.b + slice.a)).T
+  v = ((uv shl (upmost - slice.b)).typeMasked shr (upmost - slice.b + slice.a)).T
 
 func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
   ## Creates a bitmask based on a slice of bits.
@@ -96,7 +102,7 @@ func toMask*[T: SomeInteger](slice: Slice[int]): T {.inline, since: (1, 3).} =
   let
     upmost = sizeof(T) * 8 - 1
     bitmask = bitnot(0.T).castToUnsigned
-  (bitmask shl (upmost - slice.b + slice.a) shr (upmost - slice.b)).T
+  ((bitmask shl (upmost - slice.b + slice.a)).typeMasked shr (upmost - slice.b)).T
 
 proc masked*[T: SomeInteger](v, mask :T): T {.inline, since: (1, 3).} =
   ## Returns `v`, with only the `1` bits from `mask` matching those of
@@ -457,7 +463,7 @@ elif useVCC_builtins:
       importc: "_BitScanForward64", header: "<intrin.h>".}
 
   template vcc_scan_impl(fnc: untyped; v: untyped): int =
-    var index: culong
+    var index {.inject.}: culong = 0
     discard fnc(index.addr, v)
     index.int
 
diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim
index b78034fe3..59e2078df 100644
--- a/lib/pure/browsers.nim
+++ b/lib/pure/browsers.nim
@@ -12,22 +12,22 @@
 ##
 ## Unstable API.
 
-import std/private/since
+import std/private/since # used by the deprecated `openDefaultBrowser()`
 
-import strutils
+import std/strutils
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
 when defined(windows):
-  import winlean
-  when useWinUnicode and defined(nimPreviewSlimSystem):
+  import std/winlean
+  when defined(nimPreviewSlimSystem):
     import std/widestrs
-  from os import absolutePath
+  from std/os import absolutePath
 else:
-  import os
+  import std/os
   when not defined(osx):
-    import osproc
+    import std/osproc
 
 const osOpenCmd* =
   when defined(macos) or defined(macosx) or defined(windows): "open" else: "xdg-open" ## \
@@ -40,15 +40,17 @@ proc prepare(s: string): string =
   else:
     result = "file://" & absolutePath(s)
 
-proc openDefaultBrowserImpl(url: string) =
+proc openDefaultBrowserRaw(url: string) =
+  ## note the url argument should be alreadly prepared, i.e. the url is passed "AS IS"
+
   when defined(windows):
     var o = newWideCString(osOpenCmd)
-    var u = newWideCString(prepare url)
+    var u = newWideCString(url)
     discard shellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL)
   elif defined(macosx):
-    discard execShellCmd(osOpenCmd & " " & quoteShell(prepare url))
+    discard execShellCmd(osOpenCmd & " " & quoteShell(url))
   else:
-    var u = quoteShell(prepare url)
+    var u = quoteShell(url)
     if execShellCmd(osOpenCmd & " " & u) == 0: return
     for b in getEnv("BROWSER").split(PathSep):
       try:
@@ -73,16 +75,30 @@ proc openDefaultBrowser*(url: string) =
   ##   block: openDefaultBrowser("https://nim-lang.org")
   ##   ```
   doAssert url.len > 0, "URL must not be empty string"
-  openDefaultBrowserImpl(url)
+  openDefaultBrowserRaw(url)
 
-proc openDefaultBrowser*() {.since: (1, 1).} =
-  ## Opens the user's default browser without any `url` (blank page). This does not block.
-  ## Implements IETF RFC-6694 Section 3, "about:blank" must be reserved for a blank page.
+proc openDefaultBrowser*() {.since: (1, 1), deprecated: 
+  "not implemented, please open with a specific url instead".} =
+  ## Intends to open the user's default browser without any `url` (blank page).
+  ## This does not block.
+  ## Intends to implement IETF RFC-6694 Section 3,
+  ## ("about:blank" is reserved for a blank page).
   ##
-  ## Under Windows, `ShellExecute` is used. Under Mac OS X the `open`
-  ## command is used. Under Unix, it is checked if `xdg-open` exists and
-  ## used if it does. Otherwise the environment variable `BROWSER` is
-  ## used to determine the default browser to use.
+  ## Beware that this intended behavior is **not** implemented and 
+  ## considered not worthy to implement here.
+  ##
+  ## The following describes the behavior of current implementation:
+  ## 
+  ##  - Under Windows, this will only cause a pop-up dialog \
+  ## asking the assocated application with `about` \
+  ## (as Windows simply treats `about:` as a protocol like `http`).
+  ##  - Under Mac OS X the `open "about:blank"` command is used.
+  ##  - Under Unix, it is checked if `xdg-open` exists and used \
+  ## if it does and open the application assocated with `text/html` mime \
+  ## (not `x-scheme-handler/http`, so maybe html-viewer \
+  ## other than your default browser is opened). \
+  ## Otherwise the environment variable `BROWSER` is used \
+  ## to determine the default browser to use.
   ##
   ## This proc doesn't raise an exception on error, beware.
   ##
@@ -93,4 +109,4 @@ proc openDefaultBrowser*() {.since: (1, 1).} =
   ## **See also:**
   ##
   ## * https://tools.ietf.org/html/rfc6694#section-3
-  openDefaultBrowserImpl("http:about:blank")  # See IETF RFC-6694 Section 3.
+  openDefaultBrowserRaw("about:blank")  # See IETF RFC-6694 Section 3.
diff --git a/lib/pure/cgi.nim b/lib/pure/cgi.nim
index e761569a1..034f224ac 100644
--- a/lib/pure/cgi.nim
+++ b/lib/pure/cgi.nim
@@ -29,7 +29,7 @@
 ##   writeLine(stdout, "</body></html>")
 ##   ```
 
-import strutils, os, strtabs, cookies, uri
+import std/[strutils, os, strtabs, cookies, uri]
 export uri.encodeUrl, uri.decodeUrl
 
 when defined(nimPreviewSlimSystem):
diff --git a/lib/pure/collections/deques.nim b/lib/pure/collections/deques.nim
index 7e9ed32f3..d2b0099f2 100644
--- a/lib/pure/collections/deques.nim
+++ b/lib/pure/collections/deques.nim
@@ -50,7 +50,7 @@ runnableExamples:
 
 import std/private/since
 
-import math
+import std/[assertions, hashes, math]
 
 type
   Deque*[T] = object
@@ -59,20 +59,28 @@ type
     ## To initialize an empty deque,
     ## use the `initDeque proc <#initDeque,int>`_.
     data: seq[T]
-    head, tail, count, mask: int
+
+    # `head` and `tail` are masked only when accessing an element of `data`
+    # so that `tail - head == data.len` when the deque is full.
+    # They are uint so that incrementing/decrementing them doesn't cause
+    # over/underflow. You can get a number of items with `tail - head`
+    # even if `tail` or `head` is wraps around and `tail < head`, because
+    # `tail - head == (uint.high + 1 + tail) - head` when `tail < head`.
+    head, tail: uint
 
 const
   defaultInitialSize* = 4
 
 template initImpl(result: typed, initialSize: int) =
   let correctSize = nextPowerOfTwo(initialSize)
-  result.mask = correctSize - 1
   newSeq(result.data, correctSize)
 
 template checkIfInitialized(deq: typed) =
-  when compiles(defaultInitialSize):
-    if deq.mask == 0:
-      initImpl(deq, defaultInitialSize)
+  if deq.data.len == 0:
+    initImpl(deq, defaultInitialSize)
+
+func mask[T](deq: Deque[T]): uint {.inline.} =
+  uint(deq.data.len) - 1
 
 proc initDeque*[T](initialSize: int = defaultInitialSize): Deque[T] =
   ## Creates a new empty deque.
@@ -86,22 +94,22 @@ proc initDeque*[T](initialSize: int = defaultInitialSize): Deque[T] =
   ## * `toDeque proc <#toDeque,openArray[T]>`_
   result.initImpl(initialSize)
 
-proc len*[T](deq: Deque[T]): int {.inline.} =
+func len*[T](deq: Deque[T]): int {.inline.} =
   ## Returns the number of elements of `deq`.
-  result = deq.count
+  int(deq.tail - deq.head)
 
 template emptyCheck(deq) =
   # Bounds check for the regular deque access.
   when compileOption("boundChecks"):
-    if unlikely(deq.count < 1):
+    if unlikely(deq.len < 1):
       raise newException(IndexDefect, "Empty deque.")
 
 template xBoundsCheck(deq, i) =
   # Bounds check for the array like accesses.
   when compileOption("boundChecks"): # `-d:danger` or `--checks:off` should disable this.
-    if unlikely(i >= deq.count): # x < deq.low is taken care by the Natural parameter
+    if unlikely(i >= deq.len): # x < deq.low is taken care by the Natural parameter
       raise newException(IndexDefect,
-                         "Out of bounds: " & $i & " > " & $(deq.count - 1))
+                         "Out of bounds: " & $i & " > " & $(deq.len - 1))
     if unlikely(i < 0): # when used with BackwardsIndex
       raise newException(IndexDefect,
                          "Out of bounds: " & $i & " < 0")
@@ -115,7 +123,7 @@ proc `[]`*[T](deq: Deque[T], i: Natural): lent T {.inline.} =
     doAssertRaises(IndexDefect, echo a[8])
 
   xBoundsCheck(deq, i)
-  return deq.data[(deq.head + i) and deq.mask]
+  return deq.data[(deq.head + i.uint) and deq.mask]
 
 proc `[]`*[T](deq: var Deque[T], i: Natural): var T {.inline.} =
   ## Accesses the `i`-th element of `deq` and returns a mutable
@@ -126,7 +134,7 @@ proc `[]`*[T](deq: var Deque[T], i: Natural): var T {.inline.} =
     assert a[0] == 11
 
   xBoundsCheck(deq, i)
-  return deq.data[(deq.head + i) and deq.mask]
+  return deq.data[(deq.head + i.uint) and deq.mask]
 
 proc `[]=`*[T](deq: var Deque[T], i: Natural, val: sink T) {.inline.} =
   ## Sets the `i`-th element of `deq` to `val`.
@@ -138,7 +146,7 @@ proc `[]=`*[T](deq: var Deque[T], i: Natural, val: sink T) {.inline.} =
 
   checkIfInitialized(deq)
   xBoundsCheck(deq, i)
-  deq.data[(deq.head + i) and deq.mask] = val
+  deq.data[(deq.head + i.uint) and deq.mask] = val
 
 proc `[]`*[T](deq: Deque[T], i: BackwardsIndex): lent T {.inline.} =
   ## Accesses the backwards indexed `i`-th element.
@@ -191,10 +199,8 @@ iterator items*[T](deq: Deque[T]): lent T =
     let a = [10, 20, 30, 40, 50].toDeque
     assert toSeq(a.items) == @[10, 20, 30, 40, 50]
 
-  var i = deq.head
-  for c in 0 ..< deq.count:
-    yield deq.data[i]
-    i = (i + 1) and deq.mask
+  for c in 0 ..< deq.len:
+    yield deq.data[(deq.head + c.uint) and deq.mask]
 
 iterator mitems*[T](deq: var Deque[T]): var T =
   ## Yields every element of `deq`, which can be modified.
@@ -208,10 +214,8 @@ iterator mitems*[T](deq: var Deque[T]): var T =
       x = 5 * x - 1
     assert $a == "[49, 99, 149, 199, 249]"
 
-  var i = deq.head
-  for c in 0 ..< deq.count:
-    yield deq.data[i]
-    i = (i + 1) and deq.mask
+  for c in 0 ..< deq.len:
+    yield deq.data[(deq.head + c.uint) and deq.mask]
 
 iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] =
   ## Yields every `(position, value)`-pair of `deq`.
@@ -221,10 +225,8 @@ iterator pairs*[T](deq: Deque[T]): tuple[key: int, val: T] =
     let a = [10, 20, 30].toDeque
     assert toSeq(a.pairs) == @[(0, 10), (1, 20), (2, 30)]
 
-  var i = deq.head
-  for c in 0 ..< deq.count:
-    yield (c, deq.data[i])
-    i = (i + 1) and deq.mask
+  for c in 0 ..< deq.len:
+    yield (c, deq.data[(deq.head + c.uint) and deq.mask])
 
 proc contains*[T](deq: Deque[T], item: T): bool {.inline.} =
   ## Returns true if `item` is in `deq` or false if not found.
@@ -243,8 +245,9 @@ proc contains*[T](deq: Deque[T], item: T): bool {.inline.} =
 
 proc expandIfNeeded[T](deq: var Deque[T]) =
   checkIfInitialized(deq)
-  var cap = deq.mask + 1
-  if unlikely(deq.count >= cap):
+  let cap = deq.data.len
+  assert deq.len <= cap
+  if unlikely(deq.len == cap):
     var n = newSeq[T](cap * 2)
     var i = 0
     for x in mitems(deq):
@@ -252,8 +255,7 @@ proc expandIfNeeded[T](deq: var Deque[T]) =
       else: n[i] = move(x)
       inc i
     deq.data = move(n)
-    deq.mask = cap * 2 - 1
-    deq.tail = deq.count
+    deq.tail = cap.uint
     deq.head = 0
 
 proc addFirst*[T](deq: var Deque[T], item: sink T) =
@@ -268,9 +270,8 @@ proc addFirst*[T](deq: var Deque[T], item: sink T) =
     assert $a == "[50, 40, 30, 20, 10]"
 
   expandIfNeeded(deq)
-  inc deq.count
-  deq.head = (deq.head - 1) and deq.mask
-  deq.data[deq.head] = item
+  dec deq.head
+  deq.data[deq.head and deq.mask] = item
 
 proc addLast*[T](deq: var Deque[T], item: sink T) =
   ## Adds an `item` to the end of `deq`.
@@ -284,9 +285,8 @@ proc addLast*[T](deq: var Deque[T], item: sink T) =
     assert $a == "[10, 20, 30, 40, 50]"
 
   expandIfNeeded(deq)
-  inc deq.count
-  deq.data[deq.tail] = item
-  deq.tail = (deq.tail + 1) and deq.mask
+  deq.data[deq.tail and deq.mask] = item
+  inc deq.tail
 
 proc toDeque*[T](x: openArray[T]): Deque[T] {.since: (1, 3).} =
   ## Creates a new deque that contains the elements of `x` (in the same order).
@@ -315,7 +315,7 @@ proc peekFirst*[T](deq: Deque[T]): lent T {.inline.} =
     assert len(a) == 5
 
   emptyCheck(deq)
-  result = deq.data[deq.head]
+  result = deq.data[deq.head and deq.mask]
 
 proc peekLast*[T](deq: Deque[T]): lent T {.inline.} =
   ## Returns the last element of `deq`, but does not remove it from the deque.
@@ -345,7 +345,7 @@ proc peekFirst*[T](deq: var Deque[T]): var T {.inline, since: (1, 3).} =
     assert $a == "[99, 20, 30, 40, 50]"
 
   emptyCheck(deq)
-  result = deq.data[deq.head]
+  result = deq.data[deq.head and deq.mask]
 
 proc peekLast*[T](deq: var Deque[T]): var T {.inline, since: (1, 3).} =
   ## Returns a mutable reference to the last element of `deq`,
@@ -378,9 +378,8 @@ proc popFirst*[T](deq: var Deque[T]): T {.inline, discardable.} =
     assert $a == "[20, 30, 40, 50]"
 
   emptyCheck(deq)
-  dec deq.count
-  result = move deq.data[deq.head]
-  deq.head = (deq.head + 1) and deq.mask
+  result = move deq.data[deq.head and deq.mask]
+  inc deq.head
 
 proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
   ## Removes and returns the last element of the `deq`.
@@ -395,9 +394,8 @@ proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
     assert $a == "[10, 20, 30, 40]"
 
   emptyCheck(deq)
-  dec deq.count
-  deq.tail = (deq.tail - 1) and deq.mask
-  result = move deq.data[deq.tail]
+  dec deq.tail
+  result = move deq.data[deq.tail and deq.mask]
 
 proc clear*[T](deq: var Deque[T]) {.inline.} =
   ## Resets the deque so that it is empty.
@@ -411,7 +409,6 @@ proc clear*[T](deq: var Deque[T]) {.inline.} =
     assert len(a) == 0
 
   for el in mitems(deq): destroy(el)
-  deq.count = 0
   deq.tail = deq.head
 
 proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) =
@@ -431,19 +428,17 @@ proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) =
     a.shrink(fromFirst = 2, fromLast = 1)
     assert $a == "[30, 40]"
 
-  if fromFirst + fromLast > deq.count:
+  if fromFirst + fromLast > deq.len:
     clear(deq)
     return
 
   for i in 0 ..< fromFirst:
-    destroy(deq.data[deq.head])
-    deq.head = (deq.head + 1) and deq.mask
+    destroy(deq.data[deq.head and deq.mask])
+    inc deq.head
 
   for i in 0 ..< fromLast:
-    destroy(deq.data[deq.tail])
-    deq.tail = (deq.tail - 1) and deq.mask
-
-  dec deq.count, fromFirst + fromLast
+    destroy(deq.data[(deq.tail - 1) and deq.mask])
+    dec deq.tail
 
 proc `$`*[T](deq: Deque[T]): string =
   ## Turns a deque into its string representation.
@@ -456,3 +451,30 @@ proc `$`*[T](deq: Deque[T]): string =
     if result.len > 1: result.add(", ")
     result.addQuoted(x)
   result.add("]")
+
+func `==`*[T](deq1, deq2: Deque[T]): bool =
+  ## The `==` operator for Deque.
+  ## Returns `true` if both deques contains the same values in the same order.
+  runnableExamples:
+    var a, b = initDeque[int]()
+    a.addFirst(2)
+    a.addFirst(1)
+    b.addLast(1)
+    b.addLast(2)
+    doAssert a == b
+
+  if deq1.len != deq2.len:
+    return false
+
+  for i in 0 ..< deq1.len:
+    if deq1.data[(deq1.head + i.uint) and deq1.mask] != deq2.data[(deq2.head + i.uint) and deq2.mask]:
+      return false
+
+  true
+
+func hash*[T](deq: Deque[T]): Hash =
+  ## Hashing of Deque.
+  var h: Hash = 0
+  for x in deq:
+    h = h !& hash(x)
+  !$h
diff --git a/lib/pure/collections/hashcommon.nim b/lib/pure/collections/hashcommon.nim
index 02312e2dc..17785c8c7 100644
--- a/lib/pure/collections/hashcommon.nim
+++ b/lib/pure/collections/hashcommon.nim
@@ -38,16 +38,6 @@ proc slotsNeeded(count: Natural): int {.inline.} =
   # Make sure to synchronize with `mustRehash` above
   result = nextPowerOfTwo(count * 3 div 2 + 4)
 
-proc rightSize*(count: Natural): int {.inline, deprecated: "Deprecated since 1.4.0".} =
-  ## It is not needed anymore because
-  ## picking the correct size is done internally.
-  ##
-  ## Returns the value of `initialSize` to support `count` items.
-  ##
-  ## If more items are expected to be added, simply add that
-  ## expected extra amount to the parameter before calling this.
-  result = count
-
 template rawGetKnownHCImpl() {.dirty.} =
   if t.dataLen == 0:
     return -1
@@ -68,7 +58,10 @@ proc rawGetKnownHC[X, A](t: X, key: A, hc: Hash): int {.inline.} =
 template genHashImpl(key, hc: typed) =
   hc = hash(key)
   if hc == 0: # This almost never taken branch should be very predictable.
-    hc = 314159265 # Value doesn't matter; Any non-zero favorite is fine.
+    when sizeof(int) < 4:
+      hc = 31415 # Value doesn't matter; Any non-zero favorite is fine <= 16-bit.
+    else:
+      hc = 314159265 # Value doesn't matter; Any non-zero favorite is fine.
 
 template genHash(key: typed): Hash =
   var res: Hash
diff --git a/lib/pure/collections/heapqueue.nim b/lib/pure/collections/heapqueue.nim
index 89e532951..96f9b4430 100644
--- a/lib/pure/collections/heapqueue.nim
+++ b/lib/pure/collections/heapqueue.nim
@@ -47,6 +47,9 @@ runnableExamples:
 
 import std/private/since
 
+when defined(nimPreviewSlimSystem):
+  import std/assertions
+
 type HeapQueue*[T] = object
   ## A heap queue, commonly known as a priority queue.
   data: seq[T]
@@ -59,7 +62,7 @@ proc initHeapQueue*[T](): HeapQueue[T] =
   ##
   ## **See also:**
   ## * `toHeapQueue proc <#toHeapQueue,openArray[T]>`_
-  discard
+  result = default(HeapQueue[T])
 
 proc len*[T](heap: HeapQueue[T]): int {.inline.} =
   ## Returns the number of elements of `heap`.
@@ -73,6 +76,13 @@ proc `[]`*[T](heap: HeapQueue[T], i: Natural): lent T {.inline.} =
   ## Accesses the i-th element of `heap`.
   heap.data[i]
 
+iterator items*[T](heap: HeapQueue[T]): lent T {.inline, since: (2, 1, 1).} =
+  ## Iterates over each item of `heap`.
+  let L = len(heap)
+  for i in 0 .. high(heap.data):
+    yield heap.data[i]
+    assert(len(heap) == L, "the length of the HeapQueue changed while iterating over it")
+
 proc heapCmp[T](x, y: T): bool {.inline.} = x < y
 
 proc siftup[T](heap: var HeapQueue[T], startpos, p: int) =
@@ -178,6 +188,11 @@ proc find*[T](heap: HeapQueue[T], x: T): int {.since: (1, 3).} =
   for i in 0 ..< heap.len:
     if heap[i] == x: return i
 
+proc contains*[T](heap: HeapQueue[T], x: T): bool {.since: (2, 1, 1).} =
+  ## Returns true if `x` is in `heap` or false if not found. This is a shortcut
+  ## for `find(heap, x) >= 0`.
+  result = find(heap, x) >= 0
+
 proc del*[T](heap: var HeapQueue[T], index: Natural) =
   ## Removes the element at `index` from `heap`, maintaining the heap invariant.
   runnableExamples:
diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim
index 829ec2ccb..6b88747ef 100644
--- a/lib/pure/collections/lists.nim
+++ b/lib/pure/collections/lists.nim
@@ -62,9 +62,6 @@ import std/private/since
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
-when not defined(nimHasCursor):
-  {.pragma: cursor.}
-
 type
   DoublyLinkedNodeObj*[T] = object
     ## A node of a doubly linked list.
@@ -168,36 +165,14 @@ proc newSinglyLinkedNode*[T](value: T): SinglyLinkedNode[T] =
   new(result)
   result.value = value
 
-func toSinglyLinkedList*[T](elems: openArray[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} =
-  ## Creates a new `SinglyLinkedList` from the members of `elems`.
-  runnableExamples:
-    from std/sequtils import toSeq
-    let a = [1, 2, 3, 4, 5].toSinglyLinkedList
-    assert a.toSeq == [1, 2, 3, 4, 5]
-
-  result = initSinglyLinkedList[T]()
-  for elem in elems.items:
-    result.add(elem)
-
-func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} =
-  ## Creates a new `DoublyLinkedList` from the members of `elems`.
-  runnableExamples:
-    from std/sequtils import toSeq
-    let a = [1, 2, 3, 4, 5].toDoublyLinkedList
-    assert a.toSeq == [1, 2, 3, 4, 5]
-
-  result = initDoublyLinkedList[T]()
-  for elem in elems.items:
-    result.add(elem)
-
 template itemsListImpl() {.dirty.} =
-  var it = L.head
+  var it {.cursor.} = L.head
   while it != nil:
     yield it.value
     it = it.next
 
 template itemsRingImpl() {.dirty.} =
-  var it = L.head
+  var it {.cursor.} = L.head
   if it != nil:
     while true:
       yield it.value
@@ -289,7 +264,7 @@ iterator nodes*[T](L: SomeLinkedList[T]): SomeLinkedNode[T] =
         x.value = 5 * x.value - 1
     assert $a == "[49, 99, 199, 249]"
 
-  var it = L.head
+  var it {.cursor.} = L.head
   while it != nil:
     let nxt = it.next
     yield it
@@ -314,7 +289,7 @@ iterator nodes*[T](L: SomeLinkedRing[T]): SomeLinkedNode[T] =
         x.value = 5 * x.value - 1
     assert $a == "[49, 99, 199, 249]"
 
-  var it = L.head
+  var it {.cursor.} = L.head
   if it != nil:
     while true:
       let nxt = it.next
@@ -409,9 +384,7 @@ proc prependMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} =
     assert s == [0, 1, 0, 1, 0, 1]
 
   b.addMoved(a)
-  when defined(js): # XXX: swap broken in js; bug #16771
-    (b, a) = (a, b)
-  else: swap a, b
+  swap a, b
 
 proc add*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]) {.inline.} =
   ## Appends (adds to the end) a node `n` to `L`. Efficiency: O(1).
@@ -736,7 +709,7 @@ proc remove*[T](L: var SinglyLinkedList[T], n: SinglyLinkedNode[T]): bool {.disc
     if L.tail.next == n:
       L.tail.next = L.head # restore cycle
   else:
-    var prev = L.head
+    var prev {.cursor.} = L.head
     while prev.next != n and prev.next != nil:
       prev = prev.next
     if prev.next == nil:
@@ -996,3 +969,47 @@ proc appendMoved*[T: SomeLinkedList](a, b: var T) {.since: (1, 5, 1).} =
   ## * `addMoved proc <#addMoved,SinglyLinkedList[T],SinglyLinkedList[T]>`_
   ## * `addMoved proc <#addMoved,DoublyLinkedList[T],DoublyLinkedList[T]>`_
   a.addMoved(b)
+
+func toSinglyLinkedList*[T](elems: openArray[T]): SinglyLinkedList[T] {.since: (1, 5, 1).} =
+  ## Creates a new `SinglyLinkedList` from the members of `elems`.
+  runnableExamples:
+    from std/sequtils import toSeq
+    let a = [1, 2, 3, 4, 5].toSinglyLinkedList
+    assert a.toSeq == [1, 2, 3, 4, 5]
+
+  result = initSinglyLinkedList[T]()
+  for elem in elems.items:
+    result.add(elem)
+
+func toSinglyLinkedRing*[T](elems: openArray[T]): SinglyLinkedRing[T] =
+  ## Creates a new `SinglyLinkedRing` from the members of `elems`.
+  runnableExamples:
+    from std/sequtils import toSeq
+    let a = [1, 2, 3, 4, 5].toSinglyLinkedRing
+    assert a.toSeq == [1, 2, 3, 4, 5]
+
+  result = initSinglyLinkedRing[T]()
+  for elem in elems.items:
+    result.add(elem)
+
+func toDoublyLinkedList*[T](elems: openArray[T]): DoublyLinkedList[T] {.since: (1, 5, 1).} =
+  ## Creates a new `DoublyLinkedList` from the members of `elems`.
+  runnableExamples:
+    from std/sequtils import toSeq
+    let a = [1, 2, 3, 4, 5].toDoublyLinkedList
+    assert a.toSeq == [1, 2, 3, 4, 5]
+
+  result = initDoublyLinkedList[T]()
+  for elem in elems.items:
+    result.add(elem)
+
+func toDoublyLinkedRing*[T](elems: openArray[T]): DoublyLinkedRing[T] =
+  ## Creates a new `DoublyLinkedRing` from the members of `elems`.
+  runnableExamples:
+    from std/sequtils import toSeq
+    let a = [1, 2, 3, 4, 5].toDoublyLinkedRing
+    assert a.toSeq == [1, 2, 3, 4, 5]
+
+  result = initDoublyLinkedRing[T]()
+  for elem in elems.items:
+    result.add(elem)
diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim
index 1773e827b..3c0d8dc0e 100644
--- a/lib/pure/collections/sequtils.nim
+++ b/lib/pure/collections/sequtils.nim
@@ -82,7 +82,8 @@ runnableExamples:
 
 import std/private/since
 
-import macros
+import std/macros
+from std/typetraits import supportsCopyMem
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -140,6 +141,22 @@ func concat*[T](seqs: varargs[seq[T]]): seq[T] =
       result[i] = itm
       inc(i)
 
+func addUnique*[T](s: var seq[T], x: sink T) =
+  ## Adds `x` to the container `s` if it is not already present. 
+  ## Uses `==` to check if the item is already present.
+  runnableExamples:
+    var a = @[1, 2, 3]
+    a.addUnique(4)
+    a.addUnique(4)
+    assert a == @[1, 2, 3, 4]
+
+  for i in 0..high(s):
+    if s[i] == x: return
+  when declared(ensureMove):
+    s.add ensureMove(x)
+  else:
+    s.add x
+
 func count*[T](s: openArray[T], x: T): int =
   ## Returns the number of occurrences of the item `x` in the container `s`.
   ##
@@ -248,6 +265,15 @@ func maxIndex*[T](s: openArray[T]): int {.since: (1, 1).} =
   for i in 1..high(s):
     if s[i] > s[result]: result = i
 
+func minmax*[T](x: openArray[T]): (T, T) =
+  ## The minimum and maximum values of `x`. `T` needs to have a `<` operator.
+  var l = x[0]
+  var h = x[0]
+  for i in 1..high(x):
+    if x[i] < l: l = x[i]
+    if h < x[i]: h = x[i]
+  result = (l, h)
+
 
 template zipImpl(s1, s2, retType: untyped): untyped =
   proc zip*[S, T](s1: openArray[S], s2: openArray[T]): retType =
@@ -851,7 +877,7 @@ template toSeq*(iter: untyped): untyped =
           inc i
         result
     else:
-      var result: seq[typeof(iter)]# = @[]
+      var result: seq[typeof(iter)] = @[]
       for x in iter:
         result.add(x)
       result
@@ -1077,9 +1103,13 @@ template newSeqWith*(len: int, init: untyped): untyped =
     import std/random
     var seqRand = newSeqWith(20, rand(1.0))
     assert seqRand[0] != seqRand[1]
-
-  var result = newSeq[typeof(init)](len)
-  for i in 0 ..< len:
+  type T = typeof(init)
+  let newLen = len
+  when supportsCopyMem(T) and declared(newSeqUninit):
+    var result = newSeqUninit[T](newLen)
+  else: # TODO: use `newSeqUnsafe` when that's available
+    var result = newSeq[T](newLen)
+  for i in 0 ..< newLen:
     result[i] = init
   move(result) # refs bug #7295
 
diff --git a/lib/pure/collections/setimpl.nim b/lib/pure/collections/setimpl.nim
index 7ebd22760..360a075d6 100644
--- a/lib/pure/collections/setimpl.nim
+++ b/lib/pure/collections/setimpl.nim
@@ -62,6 +62,7 @@ template containsOrInclImpl() {.dirty.} =
   if index >= 0:
     result = true
   else:
+    result = false
     if mustRehash(s):
       enlarge(s)
       index = rawGetKnownHC(s, key, hc)
@@ -86,7 +87,9 @@ proc exclImpl[A](s: var HashSet[A], key: A): bool {.inline.} =
       var j = i # The correctness of this depends on (h+1) in nextTry,
       var r = j # though may be adaptable to other simple sequences.
       s.data[i].hcode = 0 # mark current EMPTY
-      s.data[i].key = default(typeof(s.data[i].key))
+      {.push warning[UnsafeDefault]:off.}
+      reset(s.data[i].key)
+      {.pop.}
       doWhile((i >= r and r > j) or (r > j and j > i) or (j > i and i >= r)):
         i = (i + 1) and msk # increment mod table size
         if isEmpty(s.data[i].hcode): # end of collision cluster; So all done
diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim
index 09648ea65..af13135aa 100644
--- a/lib/pure/collections/sets.nim
+++ b/lib/pure/collections/sets.nim
@@ -25,7 +25,9 @@
 ##   `difference <#difference,HashSet[A],HashSet[A]>`_, and
 ##   `symmetric difference <#symmetricDifference,HashSet[A],HashSet[A]>`_
 ##
-## .. code-block::
+## **Examples:**
+##
+##   ```Nim
 ##   echo toHashSet([9, 5, 1])     # {9, 1, 5}
 ##   echo toOrderedSet([9, 5, 1])  # {9, 5, 1}
 ##
@@ -37,7 +39,7 @@
 ##   echo s1 - s2    # {1, 9}
 ##   echo s1 * s2    # {5}
 ##   echo s1 -+- s2  # {9, 1, 3, 7}
-##
+##   ```
 ##
 ## Note: The data types declared here have *value semantics*: This means
 ## that `=` performs a copy of the set.
@@ -48,7 +50,7 @@
 
 
 import
-  hashes, math
+  std/[hashes, math]
 
 when not defined(nimHasEffectsOf):
   {.pragma: effectsOf.}
@@ -128,7 +130,7 @@ proc initHashSet*[A](initialSize = defaultInitialSize): HashSet[A] =
     var a = initHashSet[int]()
     a.incl(3)
     assert len(a) == 1
-
+  result = default(HashSet[A])
   result.init(initialSize)
 
 proc `[]`*[A](s: var HashSet[A], key: A): var A =
@@ -249,7 +251,7 @@ iterator items*[A](s: HashSet[A]): A =
   ## If you need a sequence with the elements you can use `sequtils.toSeq
   ## template <sequtils.html#toSeq.t,untyped>`_.
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   type
   ##     pair = tuple[a, b: int]
   ##   var
@@ -262,6 +264,7 @@ iterator items*[A](s: HashSet[A]): A =
   ##   assert a.len == 2
   ##   echo b
   ##   # --> {(a: 1, b: 3), (a: 0, b: 4)}
+  ##   ```
   let length = s.len
   for h in 0 .. high(s.data):
     if isFilled(s.data[h].hcode):
@@ -347,7 +350,7 @@ proc missingOrExcl*[A](s: var HashSet[A], key: A): bool =
 proc pop*[A](s: var HashSet[A]): A =
   ## Removes and returns an arbitrary element from the set `s`.
   ##
-  ## Raises KeyError if the set `s` is empty.
+  ## Raises `KeyError` if the set `s` is empty.
   ##
   ## See also:
   ## * `clear proc <#clear,HashSet[A]>`_
@@ -379,7 +382,9 @@ proc clear*[A](s: var HashSet[A]) =
   s.counter = 0
   for i in 0 ..< s.data.len:
     s.data[i].hcode = 0
-    s.data[i].key = default(typeof(s.data[i].key))
+    {.push warning[UnsafeDefault]:off.}
+    reset(s.data[i].key)
+    {.pop.}
 
 
 proc union*[A](s1, s2: HashSet[A]): HashSet[A] =
@@ -425,7 +430,7 @@ proc intersection*[A](s1, s2: HashSet[A]): HashSet[A] =
     assert c == toHashSet(["b"])
 
   result = initHashSet[A](max(min(s1.data.len, s2.data.len), 2))
-  
+
   # iterate over the elements of the smaller set
   if s1.data.len < s2.data.len:
     for item in s1:
@@ -433,7 +438,7 @@ proc intersection*[A](s1, s2: HashSet[A]): HashSet[A] =
   else:
     for item in s2:
       if item in s1: incl(result, item)
-  
+
 
 proc difference*[A](s1, s2: HashSet[A]): HashSet[A] =
   ## Returns the difference of the sets `s1` and `s2`.
@@ -586,12 +591,12 @@ proc `$`*[A](s: HashSet[A]): string =
   ## any moment and values are not escaped.
   ##
   ## **Examples:**
-  ##
-  ## .. code-block::
+  ##   ```Nim
   ##   echo toHashSet([2, 4, 5])
   ##   # --> {2, 4, 5}
   ##   echo toHashSet(["no", "esc'aping", "is \" provided"])
   ##   # --> {no, esc'aping, is " provided}
+  ##   ```
   dollarImpl()
 
 
@@ -813,7 +818,9 @@ proc clear*[A](s: var OrderedSet[A]) =
   for i in 0 ..< s.data.len:
     s.data[i].hcode = 0
     s.data[i].next = 0
-    s.data[i].key = default(typeof(s.data[i].key))
+    {.push warning[UnsafeDefault]:off.}
+    reset(s.data[i].key)
+    {.pop.}
 
 proc len*[A](s: OrderedSet[A]): int {.inline.} =
   ## Returns the number of elements in `s`.
@@ -874,12 +881,12 @@ proc `$`*[A](s: OrderedSet[A]): string =
   ## any moment and values are not escaped.
   ##
   ## **Examples:**
-  ##
-  ## .. code-block::
+  ##   ```Nim
   ##   echo toOrderedSet([2, 4, 5])
   ##   # --> {2, 4, 5}
   ##   echo toOrderedSet(["no", "esc'aping", "is \" provided"])
   ##   # --> {no, esc'aping, is " provided}
+  ##   ```
   dollarImpl()
 
 
@@ -890,7 +897,7 @@ iterator items*[A](s: OrderedSet[A]): A =
   ## If you need a sequence with the elements you can use `sequtils.toSeq
   ## template <sequtils.html#toSeq.t,untyped>`_.
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var a = initOrderedSet[int]()
   ##   for value in [9, 2, 1, 5, 1, 8, 4, 2]:
   ##     a.incl(value)
@@ -902,6 +909,7 @@ iterator items*[A](s: OrderedSet[A]): A =
   ##   # --> Got 5
   ##   # --> Got 8
   ##   # --> Got 4
+  ##   ```
   let length = s.len
   forAllOrderedPairs:
     yield s.data[h].key
diff --git a/lib/pure/collections/sharedlist.nim b/lib/pure/collections/sharedlist.nim
index e61883220..ec8f1cd86 100644
--- a/lib/pure/collections/sharedlist.nim
+++ b/lib/pure/collections/sharedlist.nim
@@ -16,7 +16,7 @@
 {.push stackTrace: off.}
 
 import
-  locks
+  std/locks
 
 const
   ElemsPerNode = 100
diff --git a/lib/pure/collections/sharedtables.nim b/lib/pure/collections/sharedtables.nim
index 816ab49ab..b474ecd31 100644
--- a/lib/pure/collections/sharedtables.nim
+++ b/lib/pure/collections/sharedtables.nim
@@ -17,7 +17,7 @@
 {.deprecated.}
 
 import
-  hashes, math, locks
+  std/[hashes, math, locks]
 
 type
   KeyValuePair[A, B] = tuple[hcode: Hash, key: A, val: B]
@@ -191,8 +191,7 @@ proc withKey*[A, B](t: var SharedTable[A, B], key: A,
   ##
   ## Example usage:
   ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   # If value exists, decrement it.
   ##   # If it becomes zero or less, delete the key
   ##   t.withKey(1'i64) do (k: int64, v: var int, pairExists: var bool):
@@ -200,6 +199,7 @@ proc withKey*[A, B](t: var SharedTable[A, B], key: A,
   ##       dec v
   ##       if v <= 0:
   ##         pairExists = false
+  ##   ```
   withLock t:
     var hc: Hash
     var index = rawGet(t, key, hc)
diff --git a/lib/pure/collections/tableimpl.nim b/lib/pure/collections/tableimpl.nim
index 81079a3d1..3542741fa 100644
--- a/lib/pure/collections/tableimpl.nim
+++ b/lib/pure/collections/tableimpl.nim
@@ -11,6 +11,9 @@
 
 include hashcommon
 
+const
+  defaultInitialSize* = 32
+
 template rawGetDeepImpl() {.dirty.} =   # Search algo for unconditional add
   genHashImpl(key, hc)
   var h: Hash = hc and maxHash(t)
@@ -31,9 +34,8 @@ proc rawInsert[X, A, B](t: var X, data: var KeyValuePairSeq[A, B],
   rawInsertImpl()
 
 template checkIfInitialized() =
-  when compiles(defaultInitialSize):
-    if t.dataLen == 0:
-      initImpl(t, defaultInitialSize)
+  if t.dataLen == 0:
+    initImpl(t, defaultInitialSize)
 
 template addImpl(enlarge) {.dirty.} =
   checkIfInitialized()
@@ -43,7 +45,7 @@ template addImpl(enlarge) {.dirty.} =
   rawInsert(t, t.data, key, val, hc, j)
   inc(t.counter)
 
-template maybeRehashPutImpl(enlarge) {.dirty.} =
+template maybeRehashPutImpl(enlarge, val) {.dirty.} =
   checkIfInitialized()
   if mustRehash(t):
     enlarge(t)
@@ -54,28 +56,41 @@ template maybeRehashPutImpl(enlarge) {.dirty.} =
 
 template putImpl(enlarge) {.dirty.} =
   checkIfInitialized()
-  var hc: Hash
+  var hc: Hash = default(Hash)
   var index = rawGet(t, key, hc)
   if index >= 0: t.data[index].val = val
-  else: maybeRehashPutImpl(enlarge)
+  else: maybeRehashPutImpl(enlarge, val)
 
 template mgetOrPutImpl(enlarge) {.dirty.} =
   checkIfInitialized()
-  var hc: Hash
+  var hc: Hash = default(Hash)
   var index = rawGet(t, key, hc)
   if index < 0:
     # not present: insert (flipping index)
-    maybeRehashPutImpl(enlarge)
+    when declared(val):
+      maybeRehashPutImpl(enlarge, val)
+    else:
+      maybeRehashPutImpl(enlarge, default(B))
   # either way return modifiable val
   result = t.data[index].val
 
+# template mgetOrPutDefaultImpl(enlarge) {.dirty.} =
+#   checkIfInitialized()
+#   var hc: Hash = default(Hash)
+#   var index = rawGet(t, key, hc)
+#   if index < 0:
+#     # not present: insert (flipping index)
+#     maybeRehashPutImpl(enlarge, default(B))
+#   # either way return modifiable val
+#   result = t.data[index].val
+
 template hasKeyOrPutImpl(enlarge) {.dirty.} =
   checkIfInitialized()
-  var hc: Hash
+  var hc: Hash = default(Hash)
   var index = rawGet(t, key, hc)
   if index < 0:
     result = false
-    maybeRehashPutImpl(enlarge)
+    maybeRehashPutImpl(enlarge, val)
   else: result = true
 
 # delImplIdx is KnuthV3 Algo6.4R adapted to i=i+1 (from i=i-1) which has come to
@@ -117,8 +132,10 @@ template delImplIdx(t, i, makeEmpty, cellEmpty, cellHash) =
         var j = i         # The correctness of this depends on (h+1) in nextTry
         var r = j         # though may be adaptable to other simple sequences.
         makeEmpty(i)                     # mark current EMPTY
-        t.data[i].key = default(typeof(t.data[i].key))
-        t.data[i].val = default(typeof(t.data[i].val))
+        {.push warning[UnsafeDefault]:off.}
+        reset(t.data[i].key)
+        reset(t.data[i].val)
+        {.pop.}
         while true:
           i = (i + 1) and msk            # increment mod table size
           if cellEmpty(i):               # end of collision cluster; So all done
@@ -149,8 +166,10 @@ template clearImpl() {.dirty.} =
   for i in 0 ..< t.dataLen:
     when compiles(t.data[i].hcode): # CountTable records don't contain a hcode
       t.data[i].hcode = 0
-    t.data[i].key = default(typeof(t.data[i].key))
-    t.data[i].val = default(typeof(t.data[i].val))
+    {.push warning[UnsafeDefault]:off.}
+    reset(t.data[i].key)
+    reset(t.data[i].val)
+    {.pop.}
   t.counter = 0
 
 template ctAnd(a, b): bool =
@@ -208,3 +227,5 @@ template equalsImpl(s, t: typed) =
       if not t.hasKey(key): return false
       if t.getOrDefault(key) != val: return false
     return true
+  else:
+    return false
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index cd08dcb9a..d414caeed 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -136,14 +136,11 @@ runnableExamples:
 ## a more complex object as a key you will be greeted by a strange compiler
 ## error:
 ##
-## .. code::
-##
-##   Error: type mismatch: got (Person)
-##   but expected one of:
-##   hashes.hash(x: openArray[A]): Hash
-##   hashes.hash(x: int): Hash
-##   hashes.hash(x: float): Hash
-##   …
+##     Error: type mismatch: got (Person)
+##     but expected one of:
+##     hashes.hash(x: openArray[A]): Hash
+##     hashes.hash(x: int): Hash
+##     hashes.hash(x: float): Hash
 ##
 ## What is happening here is that the types used for table keys require to have
 ## a `hash()` proc which will convert them to a `Hash <hashes.html#Hash>`_
@@ -197,7 +194,7 @@ runnableExamples:
 
 
 import std/private/since
-import hashes, math, algorithm
+import std/[hashes, math, algorithm]
 
 
 when not defined(nimHasEffectsOf):
@@ -220,8 +217,6 @@ type
     ## For creating a new empty TableRef, use `newTable proc
     ## <#newTable>`_.
 
-const
-  defaultInitialSize* = 32
 
 # ------------------------------ helpers ---------------------------------
 
@@ -283,6 +278,7 @@ proc initTable*[A, B](initialSize = defaultInitialSize): Table[A, B] =
     let
       a = initTable[int, string]()
       b = initTable[char, seq[int]]()
+  result = default(Table[A, B])
   initImpl(result, initialSize)
 
 proc `[]=`*[A, B](t: var Table[A, B], key: A, val: sink B) =
@@ -317,7 +313,7 @@ proc toTable*[A, B](pairs: openArray[(A, B)]): Table[A, B] =
   result = initTable[A, B](pairs.len)
   for key, val in items(pairs): result[key] = val
 
-proc `[]`*[A, B](t: Table[A, B], key: A): B =
+proc `[]`*[A, B](t: Table[A, B], key: A): lent B =
   ## Retrieves the value at `t[key]`.
   ##
   ## If `key` is not in `t`, the `KeyError` exception is raised.
@@ -420,7 +416,7 @@ proc getOrDefault*[A, B](t: Table[A, B], key: A): B =
     let a = {'a': 5, 'b': 9}.toTable
     doAssert a.getOrDefault('a') == 5
     doAssert a.getOrDefault('z') == 0
-
+  result = default(B)
   getOrDefaultImpl(t, key)
 
 proc getOrDefault*[A, B](t: Table[A, B], key: A, default: B): B =
@@ -438,7 +434,7 @@ proc getOrDefault*[A, B](t: Table[A, B], key: A, default: B): B =
     let a = {'a': 5, 'b': 9}.toTable
     doAssert a.getOrDefault('a', 99) == 5
     doAssert a.getOrDefault('z', 99) == 99
-
+  result = default(B)
   getOrDefaultImpl(t, key, default)
 
 proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
@@ -447,7 +443,7 @@ proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
   ##
   ##
   ## Note that while the value returned is of type `var B`,
-  ## it is easy to accidentally create an copy of the value at `t[key]`.
+  ## it is easy to accidentally create a copy of the value at `t[key]`.
   ## Remember that seqs and strings are value types, and therefore
   ## cannot be copied into a separate variable for modification.
   ## See the example below.
@@ -479,6 +475,18 @@ proc mgetOrPut*[A, B](t: var Table[A, B], key: A, val: B): var B =
 
   mgetOrPutImpl(enlarge)
 
+proc mgetOrPut*[A, B](t: var Table[A, B], key: A): var B =
+  ## Retrieves the value at `t[key]` or puts the
+  ## default initialization value for type `B` (e.g. 0 for any
+  ## integer type).
+  runnableExamples:
+    var a = {'a': 5}.newTable
+    doAssert a.mgetOrPut('a') == 5
+    a.mgetOrPut('z').inc
+    doAssert a == {'a': 5, 'z': 1}.newTable
+
+  mgetOrPutImpl(enlarge)
+
 proc len*[A, B](t: Table[A, B]): int =
   ## Returns the number of keys in `t`.
   runnableExamples:
@@ -680,7 +688,7 @@ iterator pairs*[A, B](t: Table[A, B]): (A, B) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   let a = {
   ##     'o': [1, 5, 7, 9],
   ##     'e': [2, 4, 6, 8]
@@ -694,6 +702,7 @@ iterator pairs*[A, B](t: Table[A, B]): (A, B) =
   ##   # value: [2, 4, 6, 8]
   ##   # key: o
   ##   # value: [1, 5, 7, 9]
+  ##   ```
   let L = len(t)
   for h in 0 .. high(t.data):
     if isFilled(t.data[h].hcode):
@@ -828,7 +837,8 @@ proc newTable*[A, B](initialSize = defaultInitialSize): TableRef[A, B] =
       b = newTable[char, seq[int]]()
 
   new(result)
-  result[] = initTable[A, B](initialSize)
+  {.noSideEffect.}:
+    result[] = initTable[A, B](initialSize)
 
 proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] =
   ## Creates a new ref hash table that contains the given `pairs`.
@@ -844,14 +854,16 @@ proc newTable*[A, B](pairs: openArray[(A, B)]): TableRef[A, B] =
     assert b == {'a': 5, 'b': 9}.newTable
 
   new(result)
-  result[] = toTable[A, B](pairs)
+  {.noSideEffect.}:
+    result[] = toTable[A, B](pairs)
 
 proc newTableFrom*[A, B, C](collection: A, index: proc(x: B): C): TableRef[C, B] =
   ## Index the collection with the proc provided.
   # TODO: As soon as supported, change collection: A to collection: A[B]
   result = newTable[C, B]()
-  for item in collection:
-    result[index(item)] = item
+  {.noSideEffect.}:
+    for item in collection:
+      result[index(item)] = item
 
 proc `[]`*[A, B](t: TableRef[A, B], key: A): var B =
   ## Retrieves the value at `t[key]`.
@@ -1014,6 +1026,18 @@ proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
     doAssert t[25] == @[25, 35]
   t[].mgetOrPut(key, val)
 
+proc mgetOrPut*[A, B](t: TableRef[A, B], key: A): var B =
+  ## Retrieves the value at `t[key]` or puts the
+  ## default initialization value for type `B` (e.g. 0 for any
+  ## integer type).
+  runnableExamples:
+    var a = {'a': 5}.newTable
+    doAssert a.mgetOrPut('a') == 5
+    a.mgetOrPut('z').inc
+    doAssert a == {'a': 5, 'z': 1}.newTable
+
+  t[].mgetOrPut(key)
+
 proc len*[A, B](t: TableRef[A, B]): int =
   ## Returns the number of keys in `t`.
   runnableExamples:
@@ -1126,7 +1150,7 @@ iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   let a = {
   ##     'o': [1, 5, 7, 9],
   ##     'e': [2, 4, 6, 8]
@@ -1140,6 +1164,7 @@ iterator pairs*[A, B](t: TableRef[A, B]): (A, B) =
   ##   # value: [2, 4, 6, 8]
   ##   # key: o
   ##   # value: [1, 5, 7, 9]
+  ##   ```
   let L = len(t)
   for h in 0 .. high(t.data):
     if isFilled(t.data[h].hcode):
@@ -1322,6 +1347,7 @@ proc initOrderedTable*[A, B](initialSize = defaultInitialSize): OrderedTable[A,
     let
       a = initOrderedTable[int, string]()
       b = initOrderedTable[char, seq[int]]()
+  result = default(OrderedTable[A, B])
   initImpl(result, initialSize)
 
 proc `[]=`*[A, B](t: var OrderedTable[A, B], key: A, val: sink B) =
@@ -1357,7 +1383,7 @@ proc toOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTable[A, B] =
   result = initOrderedTable[A, B](pairs.len)
   for key, val in items(pairs): result[key] = val
 
-proc `[]`*[A, B](t: OrderedTable[A, B], key: A): B =
+proc `[]`*[A, B](t: OrderedTable[A, B], key: A): lent B =
   ## Retrieves the value at `t[key]`.
   ##
   ## If `key` is not in `t`, the  `KeyError` exception is raised.
@@ -1413,7 +1439,7 @@ proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
     doAssert a.hasKey('a') == true
     doAssert a.hasKey('z') == false
 
-  var hc: Hash
+  var hc: Hash = default(Hash)
   result = rawGet(t, key, hc) >= 0
 
 proc contains*[A, B](t: OrderedTable[A, B], key: A): bool =
@@ -1462,7 +1488,7 @@ proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A): B =
     let a = {'a': 5, 'b': 9}.toOrderedTable
     doAssert a.getOrDefault('a') == 5
     doAssert a.getOrDefault('z') == 0
-
+  result = default(B)
   getOrDefaultImpl(t, key)
 
 proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A, default: B): B =
@@ -1480,7 +1506,7 @@ proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A, default: B): B =
     let a = {'a': 5, 'b': 9}.toOrderedTable
     doAssert a.getOrDefault('a', 99) == 5
     doAssert a.getOrDefault('z', 99) == 99
-
+  result = default(B)
   getOrDefaultImpl(t, key, default)
 
 proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B =
@@ -1503,6 +1529,18 @@ proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A, val: B): var B =
 
   mgetOrPutImpl(enlarge)
 
+proc mgetOrPut*[A, B](t: var OrderedTable[A, B], key: A): var B =
+  ## Retrieves the value at `t[key]` or puts the
+  ## default initialization value for type `B` (e.g. 0 for any
+  ## integer type).
+  runnableExamples:
+    var a = {'a': 5}.toOrderedTable
+    doAssert a.mgetOrPut('a') == 5
+    a.mgetOrPut('z').inc
+    doAssert a == {'a': 5, 'z': 1}.toOrderedTable
+
+  mgetOrPutImpl(enlarge)
+
 proc len*[A, B](t: OrderedTable[A, B]): int {.inline.} =
   ## Returns the number of keys in `t`.
   runnableExamples:
@@ -1702,7 +1740,7 @@ iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   let a = {
   ##     'o': [1, 5, 7, 9],
   ##     'e': [2, 4, 6, 8]
@@ -1716,6 +1754,7 @@ iterator pairs*[A, B](t: OrderedTable[A, B]): (A, B) =
   ##   # value: [1, 5, 7, 9]
   ##   # key: e
   ##   # value: [2, 4, 6, 8]
+  ##   ```
 
   let L = len(t)
   forAllOrderedPairs:
@@ -1825,7 +1864,8 @@ proc newOrderedTable*[A, B](initialSize = defaultInitialSize): OrderedTableRef[A
       a = newOrderedTable[int, string]()
       b = newOrderedTable[char, seq[int]]()
   new(result)
-  result[] = initOrderedTable[A, B](initialSize)
+  {.noSideEffect.}:
+    result[] = initOrderedTable[A, B](initialSize)
 
 proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] =
   ## Creates a new ordered ref hash table that contains the given `pairs`.
@@ -1842,7 +1882,8 @@ proc newOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTableRef[A, B] =
     assert b == {'a': 5, 'b': 9}.newOrderedTable
 
   result = newOrderedTable[A, B](pairs.len)
-  for key, val in items(pairs): result[key] = val
+  {.noSideEffect.}:
+    for key, val in items(pairs): result[key] = val
 
 
 proc `[]`*[A, B](t: OrderedTableRef[A, B], key: A): var B =
@@ -1989,6 +2030,18 @@ proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
 
   result = t[].mgetOrPut(key, val)
 
+proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A): var B =
+  ## Retrieves the value at `t[key]` or puts the
+  ## default initialization value for type `B` (e.g. 0 for any
+  ## integer type).
+  runnableExamples:
+    var a = {'a': 5}.toOrderedTable
+    doAssert a.mgetOrPut('a') == 5
+    a.mgetOrPut('z').inc
+    doAssert a == {'a': 5, 'z': 1}.toOrderedTable
+
+  t[].mgetOrPut(key)
+
 proc len*[A, B](t: OrderedTableRef[A, B]): int {.inline.} =
   ## Returns the number of keys in `t`.
   runnableExamples:
@@ -2110,7 +2163,7 @@ iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   let a = {
   ##     'o': [1, 5, 7, 9],
   ##     'e': [2, 4, 6, 8]
@@ -2124,6 +2177,7 @@ iterator pairs*[A, B](t: OrderedTableRef[A, B]): (A, B) =
   ##   # value: [1, 5, 7, 9]
   ##   # key: e
   ##   # value: [2, 4, 6, 8]
+  ##   ```
 
   let L = len(t)
   forAllOrderedPairs:
@@ -2284,6 +2338,7 @@ proc initCountTable*[A](initialSize = defaultInitialSize): CountTable[A] =
   ## * `toCountTable proc<#toCountTable,openArray[A]>`_
   ## * `newCountTable proc<#newCountTable>`_ for creating a
   ##   `CountTableRef`
+  result = default(CountTable[A])
   initImpl(result, initialSize)
 
 proc toCountTable*[A](keys: openArray[A]): CountTable[A] =
@@ -2393,7 +2448,7 @@ proc contains*[A](t: CountTable[A], key: A): bool =
   return hasKey[A](t, key)
 
 proc getOrDefault*[A](t: CountTable[A], key: A; default: int = 0): int =
-  ## Retrieves the value at `t[key]` if`key` is in `t`. Otherwise, the
+  ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
   ## integer value of `default` is returned.
   ##
   ## See also:
@@ -2523,7 +2578,7 @@ iterator pairs*[A](t: CountTable[A]): (A, int) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   let a = toCountTable("abracadabra")
   ##
   ##   for k, v in pairs(a):
@@ -2540,6 +2595,7 @@ iterator pairs*[A](t: CountTable[A]): (A, int) =
   ##   # value: 1
   ##   # key: r
   ##   # value: 2
+  ##   ```
   let L = len(t)
   for h in 0 .. high(t.data):
     if t.data[h].val != 0:
@@ -2641,13 +2697,15 @@ proc newCountTable*[A](initialSize = defaultInitialSize): CountTableRef[A] =
   ## * `initCountTable proc<#initCountTable>`_ for creating a
   ##   `CountTable`
   new(result)
-  result[] = initCountTable[A](initialSize)
+  {.noSideEffect.}:
+    result[] = initCountTable[A](initialSize)
 
 proc newCountTable*[A](keys: openArray[A]): CountTableRef[A] =
   ## Creates a new ref count table with every member of a container `keys`
   ## having a count of how many times it occurs in that container.
   result = newCountTable[A](keys.len)
-  for key in items(keys): result.inc(key)
+  {.noSideEffect.}:
+    for key in items(keys): result.inc(key)
 
 proc `[]`*[A](t: CountTableRef[A], key: A): int =
   ## Retrieves the value at `t[key]` if `key` is in `t`.
@@ -2671,7 +2729,8 @@ proc `[]=`*[A](t: CountTableRef[A], key: A, val: int) =
   ## * `inc proc<#inc,CountTableRef[A],A,int>`_ for incrementing a
   ##   value of a key
   assert val > 0
-  t[][key] = val
+  {.noSideEffect.}:
+    t[][key] = val
 
 proc inc*[A](t: CountTableRef[A], key: A, val = 1) =
   ## Increments `t[key]` by `val` (default: 1).
@@ -2680,7 +2739,8 @@ proc inc*[A](t: CountTableRef[A], key: A, val = 1) =
     a.inc('a')
     a.inc('b', 10)
     doAssert a == newCountTable("aaabbbbbbbbbbb")
-  t[].inc(key, val)
+  {.noSideEffect.}:
+    t[].inc(key, val)
 
 proc smallest*[A](t: CountTableRef[A]): tuple[key: A, val: int] =
   ## Returns the `(key, value)` pair with the smallest `val`. Efficiency: O(n)
@@ -2713,7 +2773,7 @@ proc contains*[A](t: CountTableRef[A], key: A): bool =
   return hasKey[A](t, key)
 
 proc getOrDefault*[A](t: CountTableRef[A], key: A, default: int): int =
-  ## Retrieves the value at `t[key]` if`key` is in `t`. Otherwise, the
+  ## Retrieves the value at `t[key]` if `key` is in `t`. Otherwise, the
   ## integer value of `default` is returned.
   ##
   ## See also:
@@ -2799,7 +2859,7 @@ iterator pairs*[A](t: CountTableRef[A]): (A, int) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   let a = newCountTable("abracadabra")
   ##
   ##   for k, v in pairs(a):
@@ -2816,6 +2876,7 @@ iterator pairs*[A](t: CountTableRef[A]): (A, int) =
   ##   # value: 1
   ##   # key: r
   ##   # value: 2
+  ##   ```
   let L = len(t)
   for h in 0 .. high(t.data):
     if t.data[h].val != 0:
@@ -2894,3 +2955,18 @@ iterator mvalues*[A](t: CountTableRef[A]): var int =
     if t.data[h].val != 0:
       yield t.data[h].val
       assert(len(t) == L, "the length of the table changed while iterating over it")
+
+proc hash*[K,V](s: Table[K,V]): Hash =
+  for p in pairs(s):
+    result = result xor hash(p)
+  result = !$result
+
+proc hash*[K,V](s: OrderedTable[K,V]): Hash =
+  for p in pairs(s):
+    result = result !& hash(p)
+  result = !$result
+
+proc hash*[V](s: CountTable[V]): Hash =
+  for p in pairs(s):
+    result = result xor hash(p)
+  result = !$result
diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim
index b688fad54..d3e6dc063 100644
--- a/lib/pure/colors.nim
+++ b/lib/pure/colors.nim
@@ -9,8 +9,8 @@
 ## This module implements color handling for Nim,
 ## namely color mixing and parsing the CSS color names.
 
-import strutils
-from algorithm import binarySearch
+import std/strutils
+from std/algorithm import binarySearch
 
 type
   Color* = distinct int ## A color stored as RGB, e.g. `0xff00cc`.
@@ -18,13 +18,14 @@ type
 proc `==`*(a, b: Color): bool {.borrow.}
   ## Compares two colors.
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var
   ##     a = Color(0xff_00_ff)
   ##     b = colFuchsia
   ##     c = Color(0x00_ff_cc)
   ##   assert a == b
   ##   assert not (a == c)
+  ##   ```
 
 template extract(a: Color, r, g, b: untyped) =
   var r = a.int shr 16 and 0xff
@@ -200,8 +201,8 @@ const
   colGoldenRod* = Color(0xDAA520)
   colGray* = Color(0x808080)
   colGreen* = Color(0x008000)
-  colGrey* = Color(0x808080)
   colGreenYellow* = Color(0xADFF2F)
+  colGrey* = Color(0x808080)
   colHoneyDew* = Color(0xF0FFF0)
   colHotPink* = Color(0xFF69B4)
   colIndianRed* = Color(0xCD5C5C)
@@ -350,8 +351,8 @@ const
     "goldenrod": colGoldenRod,
     "gray": colGray,
     "green": colGreen,
-    "grey": colGrey,
     "greenyellow": colGreenYellow,
+    "grey": colGrey,
     "honeydew": colHoneyDew,
     "hotpink": colHotPink,
     "indianred": colIndianRed,
diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim
index 1e8349ef6..b48811eae 100644
--- a/lib/pure/complex.nim
+++ b/lib/pure/complex.nim
@@ -15,9 +15,6 @@
 runnableExamples:
   from std/math import almostEqual, sqrt
 
-  func almostEqual(a, b: Complex): bool =
-    almostEqual(a.re, b.re) and almostEqual(a.im, b.im)
-
   let
     z1 = complex(1.0, 2.0)
     z2 = complex(3.0, -4.0)
@@ -36,7 +33,7 @@ runnableExamples:
 {.push checks: off, line_dir: off, stack_trace: off, debugger: off.}
 # the user does not want to trace a part of the standard library!
 
-import math
+import std/[math, strformat]
 
 type
   Complex*[T: SomeFloat] = object
@@ -81,7 +78,7 @@ func abs2*[T](z: Complex[T]): T =
   ## that is the squared distance from (0, 0) to `z`.
   ## This is more efficient than `abs(z) ^ 2`.
   result = z.re * z.re + z.im * z.im
-  
+
 func sgn*[T](z: Complex[T]): Complex[T] =
   ## Returns the phase of `z` as a unit complex number,
   ## or 0 if `z` is 0.
@@ -249,10 +246,31 @@ func pow*[T](x, y: Complex[T]): Complex[T] =
     else:
       result.re = 0.0
       result.im = 0.0
-  elif y.re == 1.0 and y.im == 0.0:
-    result = x
-  elif y.re == -1.0 and y.im == 0.0:
-    result = T(1.0) / x
+  elif y.im == 0.0:
+    if y.re == 1.0:
+      result = x
+    elif y.re == -1.0:
+      result = T(1.0) / x
+    elif y.re == 2.0:
+      result = x * x
+    elif y.re == 0.5:
+      result = sqrt(x)
+    elif x.im == 0.0:
+      # Revert to real pow when both base and exponent are real
+      result.re = pow(x.re, y.re)
+      result.im = 0.0
+    else:
+      # Special case when the exponent is real
+      let
+        rho = abs(x)
+        theta = arctan2(x.im, x.re)
+        s = pow(rho, y.re)
+        r = y.re * theta
+      result.re = s * cos(r)
+      result.im = s * sin(r)
+  elif x.im == 0.0 and x.re == E:
+   # Special case Euler's formula
+   result = exp(y)
   else:
     let
       rho = abs(x)
@@ -391,6 +409,24 @@ func rect*[T](r, phi: T): Complex[T] =
   ## * `polar func<#polar,Complex[T]>`_ for the inverse operation
   complex(r * cos(phi), r * sin(phi))
 
+func almostEqual*[T: SomeFloat](x, y: Complex[T]; unitsInLastPlace: Natural = 4): bool =
+  ## Checks if two complex values are almost equal, using the
+  ## [machine epsilon](https://en.wikipedia.org/wiki/Machine_epsilon).
+  ##
+  ## Two complex values are considered almost equal if their real and imaginary
+  ## components are almost equal.
+  ##
+  ## `unitsInLastPlace` is the max number of
+  ## [units in the last place](https://en.wikipedia.org/wiki/Unit_in_the_last_place)
+  ## difference tolerated when comparing two numbers. The larger the value, the
+  ## more error is allowed. A `0` value means that two numbers must be exactly the
+  ## same to be considered equal.
+  ##
+  ## The machine epsilon has to be scaled to the magnitude of the values used
+  ## and multiplied by the desired precision in ULPs unless the difference is
+  ## subnormal.
+  almostEqual(x.re, y.re, unitsInLastPlace = unitsInLastPlace) and
+  almostEqual(x.im, y.im, unitsInLastPlace = unitsInLastPlace)
 
 func `$`*(z: Complex): string =
   ## Returns `z`'s string representation as `"(re, im)"`.
@@ -399,4 +435,39 @@ func `$`*(z: Complex): string =
 
   result = "(" & $z.re & ", " & $z.im & ")"
 
+proc formatValueAsTuple(result: var string; value: Complex; specifier: string) =
+  ## Format implementation for `Complex` representing the value as a (real, imaginary) tuple.
+  result.add "("
+  formatValue(result, value.re, specifier)
+  result.add ", "
+  formatValue(result, value.im, specifier)
+  result.add ")"
+
+proc formatValueAsComplexNumber(result: var string; value: Complex; specifier: string) =
+  ## Format implementation for `Complex` representing the value as a (RE+IMj) number
+  ## By default, the real and imaginary parts are formatted using the general ('g') format
+  let specifier = if specifier.contains({'e', 'E', 'f', 'F', 'g', 'G'}):
+      specifier.replace("j")
+    else:
+      specifier.replace('j', 'g')
+  result.add "("
+  formatValue(result, value.re, specifier)
+  if value.im >= 0 and not specifier.contains({'+', '-'}):
+    result.add "+"
+  formatValue(result, value.im, specifier)
+  result.add "j)"
+
+proc formatValue*(result: var string; value: Complex; specifier: string) =
+  ## Standard format implementation for `Complex`. It makes little
+  ## sense to call this directly, but it is required to exist
+  ## by the `&` macro.
+  ## For complex numbers, we add a specific 'j' specifier, which formats
+  ## the value as (A+Bj) like in mathematics.
+  if specifier.len == 0:
+    result.add $value
+  elif 'j' in specifier:
+    formatValueAsComplexNumber(result, value, specifier)
+  else:
+    formatValueAsTuple(result, value, specifier)
+
 {.pop.}
diff --git a/lib/pure/concurrency/atomics.nim b/lib/pure/concurrency/atomics.nim
index c7b881bc5..818f1b37a 100644
--- a/lib/pure/concurrency/atomics.nim
+++ b/lib/pure/concurrency/atomics.nim
@@ -10,6 +10,9 @@
 ## Types and operations for atomic operations and lockless algorithms.
 ##
 ## Unstable API.
+## 
+## By default, C++ uses C11 atomic primitives. To use C++ `std::atomic`,
+## `-d:nimUseCppAtomics` can be defined.
 
 runnableExamples:
   # Atomic
@@ -50,8 +53,7 @@ runnableExamples:
   flag.clear(moRelaxed)
   assert not flag.testAndSet
 
-
-when defined(cpp) or defined(nimdoc):
+when (defined(cpp) and defined(nimUseCppAtomics)) or defined(nimdoc):
   # For the C++ backend, types and operations map directly to C++11 atomics.
 
   {.push, header: "<atomic>".}
@@ -274,10 +276,17 @@ else:
       cast[T](interlockedXor(addr(location.value), cast[nonAtomicType(T)](value)))
 
   else:
-    {.push, header: "<stdatomic.h>".}
+    when defined(cpp):
+      {.push, header: "<atomic>".}
+      template maybeWrapStd(x: string): string =
+        "std::" & x
+    else:
+      {.push, header: "<stdatomic.h>".}
+      template maybeWrapStd(x: string): string =
+        x
 
     type
-      MemoryOrder* {.importc: "memory_order".} = enum
+      MemoryOrder* {.importc: "memory_order".maybeWrapStd.} = enum
         moRelaxed
         moConsume
         moAcquire
@@ -285,16 +294,25 @@ else:
         moAcquireRelease
         moSequentiallyConsistent
 
-    type
-      # Atomic*[T] {.importcpp: "_Atomic('0)".} = object
+    when defined(cpp):
+      type
+        # Atomic*[T] {.importcpp: "_Atomic('0)".} = object
+
+        AtomicInt8 {.importc: "std::atomic<NI8>".} = int8
+        AtomicInt16 {.importc: "std::atomic<NI16>".} = int16
+        AtomicInt32 {.importc: "std::atomic<NI32>".} = int32
+        AtomicInt64 {.importc: "std::atomic<NI64>".} = int64
+    else:
+      type
+        # Atomic*[T] {.importcpp: "_Atomic('0)".} = object
 
-      AtomicInt8 {.importc: "_Atomic NI8".} = int8
-      AtomicInt16 {.importc: "_Atomic NI16".} = int16
-      AtomicInt32 {.importc: "_Atomic NI32".} = int32
-      AtomicInt64 {.importc: "_Atomic NI64".} = int64
+        AtomicInt8 {.importc: "_Atomic NI8".} = int8
+        AtomicInt16 {.importc: "_Atomic NI16".} = int16
+        AtomicInt32 {.importc: "_Atomic NI32".} = int32
+        AtomicInt64 {.importc: "_Atomic NI64".} = int64
 
     type
-      AtomicFlag* {.importc: "atomic_flag", size: 1.} = object
+      AtomicFlag* {.importc: "atomic_flag".maybeWrapStd, size: 1.} = object
 
       Atomic*[T] = object
         when T is Trivial:
@@ -308,27 +326,27 @@ else:
           guard: AtomicFlag
 
     #proc init*[T](location: var Atomic[T]; value: T): T {.importcpp: "atomic_init(@)".}
-    proc atomic_load_explicit[T, A](location: ptr A; order: MemoryOrder): T {.importc.}
-    proc atomic_store_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.importc.}
-    proc atomic_exchange_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
-    proc atomic_compare_exchange_strong_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc.}
-    proc atomic_compare_exchange_weak_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc.}
+    proc atomic_load_explicit[T, A](location: ptr A; order: MemoryOrder): T {.importc: "atomic_load_explicit".maybeWrapStd.}
+    proc atomic_store_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_store_explicit".maybeWrapStd.}
+    proc atomic_exchange_explicit[T, A](location: ptr A; desired: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_exchange_explicit".maybeWrapStd.}
+    proc atomic_compare_exchange_strong_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_strong_explicit".maybeWrapStd.}
+    proc atomic_compare_exchange_weak_explicit[T, A](location: ptr A; expected: ptr T; desired: T; success, failure: MemoryOrder): bool {.importc: "atomic_compare_exchange_weak_explicit".maybeWrapStd.}
 
     # Numerical operations
-    proc atomic_fetch_add_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
-    proc atomic_fetch_sub_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
-    proc atomic_fetch_and_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
-    proc atomic_fetch_or_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
-    proc atomic_fetch_xor_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc.}
+    proc atomic_fetch_add_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_add_explicit".maybeWrapStd.}
+    proc atomic_fetch_sub_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_sub_explicit".maybeWrapStd.}
+    proc atomic_fetch_and_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_and_explicit".maybeWrapStd.}
+    proc atomic_fetch_or_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_or_explicit".maybeWrapStd.}
+    proc atomic_fetch_xor_explicit[T, A](location: ptr A; value: T; order: MemoryOrder = moSequentiallyConsistent): T {.importc: "atomic_fetch_xor_explicit".maybeWrapStd.}
 
     # Flag operations
     # var ATOMIC_FLAG_INIT {.importc, nodecl.}: AtomicFlag
     # proc init*(location: var AtomicFlag) {.inline.} = location = ATOMIC_FLAG_INIT
-    proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importc: "atomic_flag_test_and_set_explicit".}
-    proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_flag_clear_explicit".}
+    proc testAndSet*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent): bool {.importc: "atomic_flag_test_and_set_explicit".maybeWrapStd.}
+    proc clear*(location: var AtomicFlag; order: MemoryOrder = moSequentiallyConsistent) {.importc: "atomic_flag_clear_explicit".maybeWrapStd.}
 
-    proc fence*(order: MemoryOrder) {.importc: "atomic_thread_fence".}
-    proc signalFence*(order: MemoryOrder) {.importc: "atomic_signal_fence".}
+    proc fence*(order: MemoryOrder) {.importc: "atomic_thread_fence".maybeWrapStd.}
+    proc signalFence*(order: MemoryOrder) {.importc: "atomic_signal_fence".maybeWrapStd.}
 
     {.pop.}
 
diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim
index 1d2ff63e1..9bc3fd579 100644
--- a/lib/pure/concurrency/cpuinfo.nim
+++ b/lib/pure/concurrency/cpuinfo.nim
@@ -15,75 +15,96 @@ runnableExamples:
 
 include "system/inclrtl"
 
-when defined(posix) and not (defined(macosx) or defined(bsd)):
-  import posix
+when defined(js):
+  import std/jsffi
+  proc countProcessorsImpl(): int =
+    when defined(nodejs):
+      let jsOs = require("os")
+      let jsObj = jsOs.cpus().length
+    else:
+      # `navigator.hardwareConcurrency`
+      # works on browser as well as deno.
+      let navigator{.importcpp.}: JsObject
+      let jsObj = navigator.hardwareConcurrency
+    result = jsObj.to int
+else:
+  when defined(posix) and not (defined(macosx) or defined(bsd)):
+    import std/posix
 
-when defined(windows):
-  import std/private/win_getsysteminfo
+  when defined(windows):
+    import std/private/win_getsysteminfo
+
+  when defined(freebsd) or defined(macosx):
+    {.emit: "#include <sys/types.h>".}
+
+  when defined(openbsd) or defined(netbsd):
+    {.emit: "#include <sys/param.h>".}
 
-when defined(freebsd) or defined(macosx):
-  {.emit: "#include <sys/types.h>".}
+  when defined(macosx) or defined(bsd):
+    # we HAVE to emit param.h before sysctl.h so we cannot use .header here
+    # either. The amount of archaic bullshit in Poonix based OSes is just insane.
+    {.emit: "#include <sys/sysctl.h>".}
+    {.push nodecl.}
+    when defined(macosx):
+      proc sysctlbyname(name: cstring,
+        oldp: pointer, oldlenp: var csize_t,
+        newp: pointer, newlen: csize_t): cint {.importc.}
+    let
+      CTL_HW{.importc.}: cint
+      HW_NCPU{.importc.}: cint
+    proc sysctl[I: static[int]](name: var array[I, cint], namelen: cuint,
+      oldp: pointer, oldlenp: var csize_t,
+      newp: pointer, newlen: csize_t): cint {.importc.}
+    {.pop.}
 
-when defined(openbsd) or defined(netbsd):
-  {.emit: "#include <sys/param.h>".}
+  when defined(genode):
+    import genode/env
 
-when defined(macosx) or defined(bsd):
-  # we HAVE to emit param.h before sysctl.h so we cannot use .header here
-  # either. The amount of archaic bullshit in Poonix based OSes is just insane.
-  {.emit: "#include <sys/sysctl.h>".}
-  const
-    CTL_HW = 6
-    HW_AVAILCPU = 25
-    HW_NCPU = 3
-  proc sysctl(x: ptr array[0..3, cint], y: cint, z: pointer,
-              a: var csize_t, b: pointer, c: csize_t): cint {.
-              importc: "sysctl", nodecl.}
+    proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
+      importcpp: "@->cpu().affinity_space().total()".}
 
-when defined(genode):
-  import genode/env
+  when defined(haiku):
+    type
+      SystemInfo {.importc: "system_info", header: "<OS.h>".} = object
+        cpuCount {.importc: "cpu_count".}: uint32
 
-  proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {.
-    importcpp: "@->cpu().affinity_space().total()".}
+    proc getSystemInfo(info: ptr SystemInfo): int32 {.importc: "get_system_info",
+                                                      header: "<OS.h>".}
+
+  proc countProcessorsImpl(): int {.inline.} =
+    when defined(windows):
+      var
+        si: SystemInfo
+      getSystemInfo(addr si)
+      result = int(si.dwNumberOfProcessors)
+    elif defined(macosx) or defined(bsd):
+      let dest = addr result
+      var len = sizeof(result).csize_t
+      when defined(macosx):
+        # alias of "hw.activecpu"
+        if sysctlbyname("hw.logicalcpu", dest, len, nil, 0) == 0:
+          return
+      var mib = [CTL_HW, HW_NCPU]
+      if sysctl(mib, 2, dest, len, nil, 0) == 0:
+        return
+    elif defined(hpux):
+      result = mpctl(MPC_GETNUMSPUS, nil, nil)
+    elif defined(irix):
+      var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint
+      result = sysconf(SC_NPROC_ONLN)
+    elif defined(genode):
+      result = runtimeEnv.affinitySpaceTotal().int
+    elif defined(haiku):
+      var sysinfo: SystemInfo
+      if getSystemInfo(addr sysinfo) == 0:
+        result = sysinfo.cpuCount.int
+    else:
+      result = sysconf(SC_NPROCESSORS_ONLN)
+    if result < 0: result = 0
 
-when defined(haiku):
-  type
-    SystemInfo {.importc: "system_info", header: "<OS.h>".} = object
-      cpuCount {.importc: "cpu_count".}: uint32
 
-  proc getSystemInfo(info: ptr SystemInfo): int32 {.importc: "get_system_info",
-                                                    header: "<OS.h>".}
 
 proc countProcessors*(): int {.rtl, extern: "ncpi$1".} =
   ## Returns the number of the processors/cores the machine has.
   ## Returns 0 if it cannot be detected.
-  when defined(windows):
-    var
-      si: SystemInfo
-    getSystemInfo(addr si)
-    result = int(si.dwNumberOfProcessors)
-  elif defined(macosx) or defined(bsd):
-    var
-      mib: array[0..3, cint]
-      numCPU: int
-    mib[0] = CTL_HW
-    mib[1] = HW_AVAILCPU
-    var len = sizeof(numCPU).csize_t
-    discard sysctl(addr(mib), 2, addr(numCPU), len, nil, 0)
-    if numCPU < 1:
-      mib[1] = HW_NCPU
-      discard sysctl(addr(mib), 2, addr(numCPU), len, nil, 0)
-    result = numCPU
-  elif defined(hpux):
-    result = mpctl(MPC_GETNUMSPUS, nil, nil)
-  elif defined(irix):
-    var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "<unistd.h>".}: cint
-    result = sysconf(SC_NPROC_ONLN)
-  elif defined(genode):
-    result = runtimeEnv.affinitySpaceTotal().int
-  elif defined(haiku):
-    var sysinfo: SystemInfo
-    if getSystemInfo(addr sysinfo) == 0:
-      result = sysinfo.cpuCount.int
-  else:
-    result = sysconf(SC_NPROCESSORS_ONLN)
-  if result <= 0: result = 0
+  countProcessorsImpl()
diff --git a/lib/pure/concurrency/cpuload.nim b/lib/pure/concurrency/cpuload.nim
index 137dd67ad..bfbf16721 100644
--- a/lib/pure/concurrency/cpuload.nim
+++ b/lib/pure/concurrency/cpuload.nim
@@ -13,11 +13,11 @@
 ## Unstable API.
 
 when defined(windows):
-  import winlean, os, strutils, math
+  import std/[winlean, os, strutils, math]
 
   proc `-`(a, b: FILETIME): int64 = a.rdFileTime - b.rdFileTime
 elif defined(linux):
-  from cpuinfo import countProcessors
+  from std/cpuinfo import countProcessors
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -87,7 +87,7 @@ proc advice*(s: var ThreadPoolState): ThreadPoolAdvice =
   inc s.calls
 
 when not defined(testing) and isMainModule and not defined(nimdoc):
-  import random
+  import std/random
 
   proc busyLoop() =
     while true:
diff --git a/lib/pure/concurrency/threadpool.nim b/lib/pure/concurrency/threadpool.nim
index 0eb20dc9a..06ed2fe54 100644
--- a/lib/pure/concurrency/threadpool.nim
+++ b/lib/pure/concurrency/threadpool.nim
@@ -7,20 +7,22 @@
 #    distribution, for details about the copyright.
 #
 
+{.deprecated: "use the nimble packages `malebolgia`, `taskpools` or `weave` instead".}
+
 ## Implements Nim's `parallel & spawn statements <manual_experimental.html#parallel-amp-spawn>`_.
 ##
 ## Unstable API.
 ##
 ## See also
 ## ========
-## * `threads module <threads.html>`_ for basic thread support
+## * `threads module <typedthreads.html>`_ for basic thread support
 ## * `locks module <locks.html>`_ for locks and condition variables
 ## * `asyncdispatch module <asyncdispatch.html>`_ for asynchronous IO
 
 when not compileOption("threads"):
   {.error: "Threadpool requires --threads:on option.".}
 
-import cpuinfo, cpuload, locks, os
+import std/[cpuinfo, cpuload, locks, os]
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, typedthreads, sysatomics]
diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim
index 22704e434..f628aaf6b 100644
--- a/lib/pure/cookies.nim
+++ b/lib/pure/cookies.nim
@@ -9,7 +9,7 @@
 
 ## This module implements helper procs for parsing Cookies.
 
-import strtabs, times, options
+import std/[strtabs, times, options]
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
diff --git a/lib/pure/coro.nim b/lib/pure/coro.nim
index 47dfdd791..24836e316 100644
--- a/lib/pure/coro.nim
+++ b/lib/pure/coro.nim
@@ -29,15 +29,14 @@ when not nimCoroutines and not defined(nimdoc):
   else:
     {.error: "Coroutines require -d:nimCoroutines".}
 
-import os
-import lists
+import std/[os, lists]
 include system/timers
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
 const defaultStackSize = 512 * 1024
-const useOrcArc = defined(gcArc) or defined(gcOrc)
+const useOrcArc = defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc)
 
 when useOrcArc:
   proc nimGC_setStackBottom*(theStackBottom: pointer) = discard
@@ -68,7 +67,7 @@ else:
   const coroBackend = CORO_BACKEND_UCONTEXT
 
 when coroBackend == CORO_BACKEND_FIBERS:
-  import windows/winlean
+  import std/winlean
   type
     Context = pointer
 
@@ -224,7 +223,7 @@ proc switchTo(current, to: CoroutinePtr) =
         elif to.state == CORO_CREATED:
           # Coroutine is started.
           coroExecWithStack(runCurrentTask, to.stack.bottom)
-          #doAssert false
+          #raiseAssert "unreachable"
     else:
       {.error: "Invalid coroutine backend set.".}
   # Execution was just resumed. Restore frame information and set active stack.
@@ -266,7 +265,7 @@ proc runCurrentTask() =
     current.state = CORO_FINISHED
   nimGC_setStackBottom(ctx.ncbottom)
   suspend(0) # Exit coroutine without returning from coroExecWithStack()
-  doAssert false
+  raiseAssert "unreachable"
 
 proc start*(c: proc(), stacksize: int = defaultStackSize): CoroutineRef {.discardable.} =
   ## Schedule coroutine for execution. It does not run immediately.
@@ -281,8 +280,8 @@ proc start*(c: proc(), stacksize: int = defaultStackSize): CoroutineRef {.discar
       (proc(p: pointer) {.stdcall.} = runCurrentTask()), nil)
   else:
     coro = cast[CoroutinePtr](alloc0(sizeof(Coroutine) + stacksize))
-    coro.stack.top = cast[pointer](cast[ByteAddress](coro) + sizeof(Coroutine))
-    coro.stack.bottom = cast[pointer](cast[ByteAddress](coro.stack.top) + stacksize)
+    coro.stack.top = cast[pointer](cast[int](coro) + sizeof(Coroutine))
+    coro.stack.bottom = cast[pointer](cast[int](coro.stack.top) + stacksize)
     when coroBackend == CORO_BACKEND_UCONTEXT:
       discard getcontext(coro.execContext)
       coro.execContext.uc_stack.ss_sp = coro.stack.top
diff --git a/lib/pure/db_common.nim b/lib/pure/db_common.nim
deleted file mode 100644
index 852c8e1c3..000000000
--- a/lib/pure/db_common.nim
+++ /dev/null
@@ -1,100 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## Common datatypes and definitions for all `db_*.nim` (
-## `db_mysql <db_mysql.html>`_, `db_postgres <db_postgres.html>`_,
-## and `db_sqlite <db_sqlite.html>`_) modules.
-
-type
-  DbError* = object of IOError ## exception that is raised if a database error occurs
-
-  SqlQuery* = distinct string ## an SQL query string
-
-
-  DbEffect* = object of IOEffect ## effect that denotes a database operation
-  ReadDbEffect* = object of DbEffect ## effect that denotes a read operation
-  WriteDbEffect* = object of DbEffect ## effect that denotes a write operation
-
-  DbTypeKind* = enum ## a superset of datatypes that might be supported.
-    dbUnknown,       ## unknown datatype
-    dbSerial,        ## datatype used for primary auto-increment keys
-    dbNull,          ## datatype used for the NULL value
-    dbBit,           ## bit datatype
-    dbBool,          ## boolean datatype
-    dbBlob,          ## blob datatype
-    dbFixedChar,     ## string of fixed length
-    dbVarchar,       ## string datatype
-    dbJson,          ## JSON datatype
-    dbXml,           ## XML datatype
-    dbInt,           ## some integer type
-    dbUInt,          ## some unsigned integer type
-    dbDecimal,       ## decimal numbers (fixed-point number)
-    dbFloat,         ## some floating point type
-    dbDate,          ## a year-month-day description
-    dbTime,          ## HH:MM:SS information
-    dbDatetime,      ## year-month-day and HH:MM:SS information,
-                     ## plus optional time or timezone information
-    dbTimestamp,     ## Timestamp values are stored as the number of seconds
-                     ## since the epoch ('1970-01-01 00:00:00' UTC).
-    dbTimeInterval,  ## an interval [a,b] of times
-    dbEnum,          ## some enum
-    dbSet,           ## set of enum values
-    dbArray,         ## an array of values
-    dbComposite,     ## composite type (record, struct, etc)
-    dbUrl,           ## a URL
-    dbUuid,          ## a UUID
-    dbInet,          ## an IP address
-    dbMacAddress,    ## a MAC address
-    dbGeometry,      ## some geometric type
-    dbPoint,         ## Point on a plane   (x,y)
-    dbLine,          ## Infinite line ((x1,y1),(x2,y2))
-    dbLseg,          ## Finite line segment   ((x1,y1),(x2,y2))
-    dbBox,           ## Rectangular box   ((x1,y1),(x2,y2))
-    dbPath,          ## Closed or open path (similar to polygon) ((x1,y1),...)
-    dbPolygon,       ## Polygon (similar to closed path)   ((x1,y1),...)
-    dbCircle,        ## Circle   <(x,y),r> (center point and radius)
-    dbUser1,         ## user definable datatype 1 (for unknown extensions)
-    dbUser2,         ## user definable datatype 2 (for unknown extensions)
-    dbUser3,         ## user definable datatype 3 (for unknown extensions)
-    dbUser4,         ## user definable datatype 4 (for unknown extensions)
-    dbUser5          ## user definable datatype 5 (for unknown extensions)
-
-  DbType* = object              ## describes a database type
-    kind*: DbTypeKind           ## the kind of the described type
-    notNull*: bool              ## does the type contain NULL?
-    name*: string               ## the name of the type
-    size*: Natural              ## the size of the datatype; 0 if of variable size
-    maxReprLen*: Natural        ## maximal length required for the representation
-    precision*, scale*: Natural ## precision and scale of the number
-    min*, max*: BiggestInt      ## the minimum and maximum of allowed values
-    validValues*: seq[string]   ## valid values of an enum or a set
-
-  DbColumn* = object   ## information about a database column
-    name*: string      ## name of the column
-    tableName*: string ## name of the table the column belongs to (optional)
-    typ*: DbType       ## type of the column
-    primaryKey*: bool  ## is this a primary key?
-    foreignKey*: bool  ## is this a foreign key?
-  DbColumns* = seq[DbColumn]
-
-template sql*(query: string): SqlQuery =
-  ## constructs a SqlQuery from the string `query`. This is supposed to be
-  ## used as a raw-string-literal modifier:
-  ## `sql"update user set counter = counter + 1"`
-  ##
-  ## If assertions are turned off, it does nothing. If assertions are turned
-  ## on, later versions will check the string for valid syntax.
-  SqlQuery(query)
-
-proc dbError*(msg: string) {.noreturn, noinline.} =
-  ## raises an DbError exception with message `msg`.
-  var e: ref DbError
-  new(e)
-  e.msg = msg
-  raise e
diff --git a/lib/pure/distros.nim b/lib/pure/distros.nim
index 25c961197..9e71d4ce0 100644
--- a/lib/pure/distros.nim
+++ b/lib/pure/distros.nim
@@ -18,12 +18,11 @@
 ##
 ## The above output could be the result of a code snippet like:
 ##
-## .. code-block:: nim
-##
+##   ```nim
 ##   if detectOs(Ubuntu):
 ##     foreignDep "lbiblas-dev"
 ##     foreignDep "libvoodoo"
-##
+##   ```
 ##
 ## See `packaging <packaging.html>`_ for hints on distributing Nim using OS packages.
 
@@ -128,6 +127,7 @@ type
 
     BSD
     FreeBSD
+    NetBSD
     OpenBSD
     DragonFlyBSD
 
@@ -169,7 +169,7 @@ proc detectOsImpl(d: Distribution): bool =
   else:
     when defined(bsd):
       case d
-      of Distribution.FreeBSD, Distribution.OpenBSD:
+      of Distribution.FreeBSD, Distribution.NetBSD, Distribution.OpenBSD:
         result = $d in uname()
       else:
         result = false
@@ -252,7 +252,7 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
       result = ("nix-env -i " & p, false)
     elif detectOs(Solaris) or detectOs(FreeBSD):
       result = ("pkg install " & p, true)
-    elif detectOs(OpenBSD):
+    elif detectOs(NetBSD) or detectOs(OpenBSD):
       result = ("pkg_add " & p, true)
     elif detectOs(PCLinuxOS):
       result = ("rpm -ivh " & p, true)
diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim
index 48fd91b8f..a162fe37f 100644
--- a/lib/pure/dynlib.nim
+++ b/lib/pure/dynlib.nim
@@ -105,7 +105,7 @@ when defined(posix) and not defined(nintendoswitch):
   # as an emulation layer on top of native functions.
   # =========================================================================
   #
-  import posix
+  import std/posix
 
   proc loadLib(path: string, globalSymbols = false): LibHandle =
     let flags =
@@ -148,7 +148,7 @@ elif defined(genode):
   #
 
   template raiseErr(prc: string) =
-    raise newException(OSError, prc & " not implemented, compile with POSIX suport")
+    raise newException(OSError, prc & " not implemented, compile with POSIX support")
 
   proc dlclose(lib: LibHandle) =
     raiseErr(OSError, "dlclose")
diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim
index 26b6e1f22..bbadca655 100644
--- a/lib/pure/encodings.nim
+++ b/lib/pure/encodings.nim
@@ -39,7 +39,7 @@ runnableExamples:
     assert fromGB2312.convert(second) == "有白头如新,倾盖如故"
 
 
-import os
+import std/os
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
@@ -59,7 +59,7 @@ type
                                         ## for encoding errors.
 
 when defined(windows):
-  import parseutils, strutils
+  import std/[parseutils, strutils]
   proc eqEncodingNames(a, b: string): bool =
     var i = 0
     var j = 0
@@ -339,10 +339,10 @@ proc getCurrentEncoding*(uiApp = false): string =
 
 proc open*(destEncoding = "UTF-8", srcEncoding = "CP1252"): EncodingConverter =
   ## Opens a converter that can convert from `srcEncoding` to `destEncoding`.
-  ## Raises `IOError` if it cannot fulfill the request.
+  ## Raises `EncodingError` if it cannot fulfill the request.
   when not defined(windows):
     result = iconvOpen(destEncoding, srcEncoding)
-    if result == nil:
+    if result == cast[EncodingConverter](-1):
       raise newException(EncodingError,
         "cannot create encoding converter from " &
         srcEncoding & " to " & destEncoding)
diff --git a/lib/pure/endians.nim b/lib/pure/endians.nim
index a0dc97c1d..4c1d45ae5 100644
--- a/lib/pure/endians.nim
+++ b/lib/pure/endians.nim
@@ -10,7 +10,7 @@
 ## This module contains helpers that deal with different byte orders
 ## (`endian`:idx:).
 ##
-## Endianess is the order of bytes of a value in memory. Big-endian means that
+## Endianness is the order of bytes of a value in memory. Big-endian means that
 ## the most significant byte is stored at the smallest memory address,
 ## while little endian means that the least-significant byte is stored
 ## at the smallest address. See also https://en.wikipedia.org/wiki/Endianness.
diff --git a/lib/pure/fenv.nim b/lib/pure/fenv.nim
index ddb6a1a0c..1d96fd6be 100644
--- a/lib/pure/fenv.nim
+++ b/lib/pure/fenv.nim
@@ -12,7 +12,7 @@
 ## The types, vars and procs are bindings for the C standard library
 ## [<fenv.h>](https://en.cppreference.com/w/c/numeric/fenv) header.
 
-when defined(posix) and not defined(genode):
+when defined(posix) and not defined(genode) and not defined(macosx):
   {.passl: "-lm".}
 
 var
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index e88210757..1038d55a1 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -62,7 +62,7 @@ runnableExamples:
 ## ========
 ## * `md5 module <md5.html>`_ for the MD5 checksum algorithm
 ## * `base64 module <base64.html>`_ for a Base64 encoder and decoder
-## * `std/sha1 module <sha1.html>`_ for the SHA-1 checksum algorithm
+## * `sha1 module <sha1.html>`_ for the SHA-1 checksum algorithm
 ## * `tables module <tables.html>`_ for hash tables
 
 import std/private/since
@@ -190,7 +190,7 @@ proc hashData*(data: pointer, size: int): Hash =
   var h: Hash = 0
   when defined(js):
     var p: cstring
-    asm """`p` = `Data`"""
+    {.emit: """`p` = `Data`;""".}
   else:
     var p = cast[cstring](data)
   var i = 0
@@ -217,7 +217,7 @@ else:
 when defined(js):
   var objectID = 0
   proc getObjectId(x: pointer): int =
-    asm """
+    {.emit: """
       if (typeof `x` == "object") {
         if ("_NimID" in `x`)
           `result` = `x`["_NimID"];
@@ -226,7 +226,7 @@ when defined(js):
           `x`["_NimID"] = `result`;
         }
       }
-    """
+    """.}
 
 proc hash*(x: pointer): Hash {.inline.} =
   ## Efficient `hash` overload.
@@ -247,7 +247,7 @@ proc hash*[T](x: ptr[T]): Hash {.inline.} =
 when defined(nimPreviewHashRef) or defined(nimdoc):
   proc hash*[T](x: ref[T]): Hash {.inline.} =
     ## Efficient `hash` overload.
-    ## 
+    ##
     ## .. important:: Use `-d:nimPreviewHashRef` to
     ##    enable hashing `ref`s. It is expected that this behavior
     ##    becomes the new default in upcoming versions.
@@ -319,16 +319,24 @@ proc murmurHash(x: openArray[byte]): Hash =
     h1: uint32
     i = 0
 
+
+  template impl =
+    var j = stepSize
+    while j > 0:
+      dec j
+      k1 = (k1 shl 8) or (ord(x[i+j])).uint32
+
   # body
   while i < n * stepSize:
     var k1: uint32
-    when defined(js) or defined(sparc) or defined(sparc64):
-      var j = stepSize
-      while j > 0:
-        dec j
-        k1 = (k1 shl 8) or (ord(x[i+j])).uint32
+
+    when nimvm:
+      impl()
     else:
-      k1 = cast[ptr uint32](unsafeAddr x[i])[]
+      when declared(copyMem):
+        copyMem(addr k1, addr x[i], 4)
+      else:
+        impl()
     inc i, stepSize
 
     k1 = imul(k1, c1)
@@ -360,16 +368,168 @@ proc murmurHash(x: openArray[byte]): Hash =
   return cast[Hash](h1)
 
 proc hashVmImpl(x: cstring, sPos, ePos: int): Hash =
-  doAssert false, "implementation override in compiler/vmops.nim"
+  raiseAssert "implementation override in compiler/vmops.nim"
 
 proc hashVmImpl(x: string, sPos, ePos: int): Hash =
-  doAssert false, "implementation override in compiler/vmops.nim"
+  raiseAssert "implementation override in compiler/vmops.nim"
 
 proc hashVmImplChar(x: openArray[char], sPos, ePos: int): Hash =
-  doAssert false, "implementation override in compiler/vmops.nim"
+  raiseAssert "implementation override in compiler/vmops.nim"
 
 proc hashVmImplByte(x: openArray[byte], sPos, ePos: int): Hash =
-  doAssert false, "implementation override in compiler/vmops.nim"
+  raiseAssert "implementation override in compiler/vmops.nim"
+
+const k0 = 0xc3a5c85c97cb3127u64 # Primes on (2^63, 2^64) for various uses
+const k1 = 0xb492b66fbe98f273u64
+const k2 = 0x9ae16a3b2f90404fu64
+
+proc load4e(s: openArray[byte], o=0): uint32 {.inline.} =
+  uint32(s[o + 3]) shl 24 or uint32(s[o + 2]) shl 16 or
+  uint32(s[o + 1]) shl  8 or uint32(s[o + 0])
+
+proc load8e(s: openArray[byte], o=0): uint64 {.inline.} =
+  uint64(s[o + 7]) shl 56 or uint64(s[o + 6]) shl 48 or
+  uint64(s[o + 5]) shl 40 or uint64(s[o + 4]) shl 32 or
+  uint64(s[o + 3]) shl 24 or uint64(s[o + 2]) shl 16 or
+  uint64(s[o + 1]) shl  8 or uint64(s[o + 0])
+
+proc load4(s: openArray[byte], o=0): uint32 {.inline.} =
+  when nimvm: result = load4e(s, o)
+  else:
+    when declared copyMem: copyMem result.addr, s[o].addr, result.sizeof
+    else: result = load4e(s, o)
+
+proc load8(s: openArray[byte], o=0): uint64 {.inline.} =
+  when nimvm: result = load8e(s, o)
+  else:
+    when declared copyMem: copyMem result.addr, s[o].addr, result.sizeof
+    else: result = load8e(s, o)
+
+proc lenU(s: openArray[byte]): uint64 {.inline.} = s.len.uint64
+
+proc shiftMix(v: uint64): uint64 {.inline.} = v xor (v shr 47)
+
+proc rotR(v: uint64; bits: cint): uint64 {.inline.} =
+  (v shr bits) or (v shl (64 - bits))
+
+proc len16(u: uint64; v: uint64; mul: uint64): uint64 {.inline.} =
+  var a = (u xor v)*mul
+  a = a xor (a shr 47)
+  var b = (v xor a)*mul
+  b = b xor (b shr 47)
+  b*mul
+
+proc len0_16(s: openArray[byte]): uint64 {.inline.} =
+  if s.len >= 8:
+    let mul = k2 + 2*s.lenU
+    let a   = load8(s) + k2
+    let b   = load8(s, s.len - 8)
+    let c   = rotR(b, 37)*mul + a
+    let d   = (rotR(a, 25) + b)*mul
+    len16 c, d, mul
+  elif s.len >= 4:
+    let mul = k2 + 2*s.lenU
+    let a   = load4(s).uint64
+    len16 s.lenU + (a shl 3), load4(s, s.len - 4), mul
+  elif s.len > 0:
+    let a = uint32(s[0])
+    let b = uint32(s[s.len shr 1])
+    let c = uint32(s[s.len - 1])
+    let y = a      + (b shl 8)
+    let z = s.lenU + (c shl 2)
+    shiftMix(y*k2 xor z*k0)*k2
+  else: k2      # s.len == 0
+
+proc len17_32(s: openArray[byte]): uint64 {.inline.} =
+  let mul = k2 + 2*s.lenU
+  let a = load8(s)*k1
+  let b = load8(s, 8)
+  let c = load8(s, s.len - 8)*mul
+  let d = load8(s, s.len - 16)*k2
+  len16 rotR(a + b, 43) + rotR(c, 30) + d, a + rotR(b + k2, 18) + c, mul
+
+proc len33_64(s: openArray[byte]): uint64 {.inline.} =
+  let mul = k2 + 2*s.lenU
+  let a = load8(s)*k2
+  let b = load8(s, 8)
+  let c = load8(s, s.len - 8)*mul
+  let d = load8(s, s.len - 16)*k2
+  let y = rotR(a + b, 43) + rotR(c, 30) + d
+  let z = len16(y, a + rotR(b + k2, 18) + c, mul)
+  let e = load8(s, 16)*mul
+  let f = load8(s, 24)
+  let g = (y + load8(s, s.len - 32))*mul
+  let h = (z + load8(s, s.len - 24))*mul
+  len16 rotR(e + f, 43) + rotR(g, 30) + h, e + rotR(f + a, 18) + g, mul
+
+type Pair = tuple[first, second: uint64]
+
+proc weakLen32withSeeds2(w, x, y, z, a, b: uint64): Pair {.inline.} =
+  var a = a + w
+  var b = rotR(b + a + z, 21)
+  let c = a
+  a += x
+  a += y
+  b += rotR(a, 44)
+  result[0] = a + z
+  result[1] = b + c
+
+proc weakLen32withSeeds(s: openArray[byte]; o: int; a,b: uint64): Pair {.inline.} =
+  weakLen32withSeeds2 load8(s, o     ), load8(s, o + 8),
+                      load8(s, o + 16), load8(s, o + 24), a, b
+
+proc hashFarm(s: openArray[byte]): uint64 {.inline.} =
+  if s.len <= 16: return len0_16(s)
+  if s.len <= 32: return len17_32(s)
+  if s.len <= 64: return len33_64(s)
+  const seed = 81u64 # not const to use input `h`
+  var
+    o = 0         # s[] ptr arith -> variable origin variable `o`
+    x = seed
+    y = seed*k1 + 113
+    z = shiftMix(y*k2 + 113)*k2
+    v, w: Pair
+  x = x*k2 + load8(s)
+  let eos    = ((s.len - 1) div 64)*64
+  let last64 = eos + ((s.len - 1) and 63) - 63
+  while true:
+    x = rotR(x + y + v[0] + load8(s, o+8), 37)*k1
+    y = rotR(y + v[1] + load8(s, o+48), 42)*k1
+    x = x xor w[1]
+    y += v[0] + load8(s, o+40)
+    z = rotR(z + w[0], 33)*k1
+    v = weakLen32withSeeds(s, o+0 , v[1]*k1, x + w[0])
+    w = weakLen32withSeeds(s, o+32, z + w[1], y + load8(s, o+16))
+    swap z, x
+    inc o, 64
+    if o == eos: break
+  let mul = k1 + ((z and 0xff) shl 1)
+  o = last64
+  w[0] += (s.lenU - 1) and 63
+  v[0] += w[0]
+  w[0] += v[0]
+  x = rotR(x + y + v[0] + load8(s, o+8), 37)*mul
+  y = rotR(y + v[1] + load8(s, o+48), 42)*mul
+  x = x xor w[1]*9
+  y += v[0]*9 + load8(s, o+40)
+  z = rotR(z + w[0], 33)*mul
+  v = weakLen32withSeeds(s, o+0 , v[1]*mul, x + w[0])
+  w = weakLen32withSeeds(s, o+32, z + w[1], y + load8(s, o+16))
+  swap z, x
+  len16 len16(v[0],w[0],mul) + shiftMix(y)*k0 + z, len16(v[1],w[1],mul) + x, mul
+
+template jsNoInt64: untyped =
+  when defined js:
+    when compiles(compileOption("jsbigint64")):
+      when not compileOption("jsbigint64"): true
+      else: false
+    else: false
+  else: false
+const sHash2 = (when defined(nimStringHash2) or jsNoInt64(): true else: false)
+
+template maybeFailJS_Number =
+  when jsNoInt64() and not defined(nimStringHash2):
+    {.error: "Must use `-d:nimStringHash2` when using `--jsbigint64:off`".}
 
 proc hash*(x: string): Hash =
   ## Efficient hashing of strings.
@@ -379,16 +539,13 @@ proc hash*(x: string): Hash =
   ## * `hashIgnoreCase <#hashIgnoreCase,string>`_
   runnableExamples:
     doAssert hash("abracadabra") != hash("AbracadabrA")
-
-  when not defined(nimToOpenArrayCString):
-    result = 0
-    for c in x:
-      result = result !& ord(c)
-    result = !$result
+  maybeFailJS_Number()
+  when not sHash2:
+    result = cast[Hash](hashFarm(toOpenArrayByte(x, 0, x.high)))
   else:
-    when nimvm:
-      result = hashVmImpl(x, 0, high(x))
-    else:
+    #when nimvm:
+    #  result = hashVmImpl(x, 0, high(x))
+    when true:
       result = murmurHash(toOpenArrayByte(x, 0, high(x)))
 
 proc hash*(x: cstring): Hash =
@@ -398,22 +555,22 @@ proc hash*(x: cstring): Hash =
     doAssert hash(cstring"AbracadabrA") == hash("AbracadabrA")
     doAssert hash(cstring"abracadabra") != hash(cstring"AbracadabrA")
 
-  when not defined(nimToOpenArrayCString):
-    result = 0
-    var i = 0
-    while x[i] != '\0':
-      result = result !& ord(x[i])
-      inc i
-    result = !$result
-  else:
-    when nimvm:
-      hashVmImpl(x, 0, high(x))
+  maybeFailJS_Number()
+  when not sHash2:
+    when defined js:
+      let xx = $x
+      result = cast[Hash](hashFarm(toOpenArrayByte(xx, 0, xx.high)))
     else:
-      when not defined(js) and defined(nimToOpenArrayCString):
-        murmurHash(toOpenArrayByte(x, 0, x.high))
+      result = cast[Hash](hashFarm(toOpenArrayByte(x, 0, x.high)))
+  else:
+    #when nimvm:
+    #  result = hashVmImpl(x, 0, high(x))
+    when true:
+      when not defined(js):
+        result = murmurHash(toOpenArrayByte(x, 0, x.high))
       else:
         let xx = $x
-        murmurHash(toOpenArrayByte(xx, 0, high(xx)))
+        result = murmurHash(toOpenArrayByte(xx, 0, high(xx)))
 
 proc hash*(sBuf: string, sPos, ePos: int): Hash =
   ## Efficient hashing of a string buffer, from starting
@@ -424,11 +581,9 @@ proc hash*(sBuf: string, sPos, ePos: int): Hash =
     var a = "abracadabra"
     doAssert hash(a, 0, 3) == hash(a, 7, 10)
 
-  when not defined(nimToOpenArrayCString):
-    result = 0
-    for i in sPos..ePos:
-      result = result !& ord(sBuf[i])
-    result = !$result
+  maybeFailJS_Number()
+  when not sHash2:
+    result = cast[Hash](hashFarm(toOpenArrayByte(sBuf, sPos, ePos)))
   else:
     murmurHash(toOpenArrayByte(sBuf, sPos, ePos))
 
@@ -521,7 +676,7 @@ proc hashIgnoreCase*(sBuf: string, sPos, ePos: int): Hash =
     h = h !& ord(c)
   result = !$h
 
-proc hash*[T: tuple | object | proc](x: T): Hash =
+proc hash*[T: tuple | object | proc | iterator {.closure.}](x: T): Hash =
   ## Efficient `hash` overload.
   runnableExamples:
     # for `tuple|object`, `hash` must be defined for each component of `x`.
@@ -554,8 +709,9 @@ proc hash*[T: tuple | object | proc](x: T): Hash =
   when T is "closure":
     result = hash((rawProc(x), rawEnv(x)))
   elif T is (proc):
-    result = hash(pointer(x))
+    result = hash(cast[pointer](x))
   else:
+    result = 0
     for f in fields(x):
       result = result !& hash(f)
     result = !$result
@@ -564,13 +720,20 @@ proc hash*[A](x: openArray[A]): Hash =
   ## Efficient hashing of arrays and sequences.
   ## There must be a `hash` proc defined for the element type `A`.
   when A is byte:
-    result = murmurHash(x)
+    when not sHash2:
+      result = cast[Hash](hashFarm(x))
+    else:
+      result = murmurHash(x)
   elif A is char:
-    when nimvm:
-      result = hashVmImplChar(x, 0, x.high)
+    when not sHash2:
+      result = cast[Hash](hashFarm(toOpenArrayByte(x, 0, x.high)))
     else:
-      result = murmurHash(toOpenArrayByte(x, 0, x.high))
+      #when nimvm:
+      #  result = hashVmImplChar(x, 0, x.high)
+      when true:
+        result = murmurHash(toOpenArrayByte(x, 0, x.high))
   else:
+    result = 0
     for a in x:
       result = result !& hash(a)
     result = !$result
@@ -584,17 +747,24 @@ proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash =
   runnableExamples:
     let a = [1, 2, 5, 1, 2, 6]
     doAssert hash(a, 0, 1) == hash(a, 3, 4)
-
   when A is byte:
-    when nimvm:
-      result = hashVmImplByte(aBuf, sPos, ePos)
+    maybeFailJS_Number()
+    when not sHash2:
+      result = cast[Hash](hashFarm(toOpenArray(aBuf, sPos, ePos)))
     else:
-      result = murmurHash(toOpenArray(aBuf, sPos, ePos))
+      #when nimvm:
+      #  result = hashVmImplByte(aBuf, sPos, ePos)
+      when true:
+        result = murmurHash(toOpenArray(aBuf, sPos, ePos))
   elif A is char:
-    when nimvm:
-      result = hashVmImplChar(aBuf, sPos, ePos)
+    maybeFailJS_Number()
+    when not sHash2:
+      result = cast[Hash](hashFarm(toOpenArrayByte(aBuf, sPos, ePos)))
     else:
-      result = murmurHash(toOpenArrayByte(aBuf, sPos, ePos))
+      #when nimvm:
+      #  result = hashVmImplChar(aBuf, sPos, ePos)
+      when true:
+        result = murmurHash(toOpenArrayByte(aBuf, sPos, ePos))
   else:
     for i in sPos .. ePos:
       result = result !& hash(aBuf[i])
@@ -603,6 +773,7 @@ proc hash*[A](aBuf: openArray[A], sPos, ePos: int): Hash =
 proc hash*[A](x: set[A]): Hash =
   ## Efficient hashing of sets.
   ## There must be a `hash` proc defined for the element type `A`.
+  result = 0
   for it in items(x):
     result = result !& hash(it)
   result = !$result
diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim
index bf31c0239..fafa72463 100644
--- a/lib/pure/htmlgen.nim
+++ b/lib/pure/htmlgen.nim
@@ -8,7 +8,7 @@
 #
 
 ## Do yourself a favor and import the module
-## as `from htmlgen import nil` and then fully qualify the macros.
+## as `from std/htmlgen import nil` and then fully qualify the macros.
 ##
 ## *Note*: The Karax project (`nimble install karax`) has a better
 ## way to achieve the same, see https://github.com/pragmagic/karax/blob/master/tests/nativehtmlgen.nim
@@ -30,9 +30,10 @@
 ## Examples
 ## ========
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   var nim = "Nim"
 ##   echo h1(a(href="https://nim-lang.org", nim))
+##   ```
 ##
 ## Writes the string:
 ##
@@ -40,7 +41,7 @@
 ##
 
 import
-  macros, strutils
+  std/[macros, strutils]
 
 const
   coreAttr* = " accesskey class contenteditable dir hidden id lang " &
diff --git a/lib/pure/htmlparser.nim b/lib/pure/htmlparser.nim
index 6b1300f11..62919546f 100644
--- a/lib/pure/htmlparser.nim
+++ b/lib/pure/htmlparser.nim
@@ -12,10 +12,9 @@
 ##
 ## It can be used to parse a wild HTML document and output it as valid XHTML
 ## document (well, if you are lucky):
-##
-## .. code-block:: Nim
-##
+##   ```Nim
 ##   echo loadHtml("mydirty.html")
+##   ```
 ##
 ## Every tag in the resulting tree is in lower case.
 ##
@@ -29,9 +28,7 @@
 ## and write back the modified version. In this case we look for hyperlinks
 ## ending with the extension `.rst` and convert them to `.html`.
 ##
-## .. code-block:: Nim
-##     :test:
-##
+##   ```Nim test
 ##   import std/htmlparser
 ##   import std/xmltree  # To use '$' for XmlNode
 ##   import std/strtabs  # To access XmlAttributes
@@ -48,8 +45,11 @@
 ##           a.attrs["href"] = dir / filename & ".html"
 ##
 ##     writeFile("output.html", $html)
+##   ```
+
+{.deprecated: "use `nimble install htmlparser` and import `pkg/htmlparser` instead".}
 
-import strutils, streams, parsexml, xmltree, unicode, strtabs
+import std/[strutils, streams, parsexml, xmltree, unicode, strtabs]
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -394,10 +394,10 @@ proc entityToRune*(entity: string): Rune =
     case entity[1]
     of '0'..'9':
       try: runeValue = parseInt(entity[1..^1])
-      except: discard
+      except ValueError: discard
     of 'x', 'X': # not case sensitive here
       try: runeValue = parseHexInt(entity[2..^1])
-      except: discard
+      except ValueError: discard
     else: discard # other entities are not defined with prefix `#`
     if runeValue notin 0..0x10FFFF: runeValue = 0 # only return legal values
     return Rune(runeValue)
@@ -2064,7 +2064,7 @@ proc loadHtml*(path: string): XmlNode =
   result = loadHtml(path, errors)
 
 when not defined(testing) and isMainModule:
-  import os
+  import std/os
 
   var errors: seq[string] = @[]
   var x = loadHtml(paramStr(1), errors)
diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim
index c832d4285..08ea99627 100644
--- a/lib/pure/httpclient.nim
+++ b/lib/pure/httpclient.nim
@@ -10,24 +10,27 @@
 ## This module implements a simple HTTP client that can be used to retrieve
 ## webpages and other data.
 ##
+## .. warning:: Validate untrusted inputs: URI parsers and getters are not detecting malicious URIs.
+##
 ## Retrieving a website
 ## ====================
 ##
 ## This example uses HTTP GET to retrieve
 ## `http://google.com`:
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/httpclient
 ##   var client = newHttpClient()
 ##   try:
 ##     echo client.getContent("http://google.com")
 ##   finally:
 ##     client.close()
+##   ```
 ##
 ## The same action can also be performed asynchronously, simply use the
 ## `AsyncHttpClient`:
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/[asyncdispatch, httpclient]
 ##
 ##   proc asyncProc(): Future[string] {.async.} =
@@ -38,6 +41,7 @@
 ##       client.close()
 ##
 ##   echo waitFor asyncProc()
+##   ```
 ##
 ## The functionality implemented by `HttpClient` and `AsyncHttpClient`
 ## is the same, so you can use whichever one suits you best in the examples
@@ -46,6 +50,10 @@
 ## **Note:** You need to run asynchronous examples in an async proc
 ## otherwise you will get an `Undeclared identifier: 'await'` error.
 ##
+## **Note:** An asynchronous client instance can only deal with one
+## request at a time. To send multiple requests in parallel, use
+## multiple client instances.
+##
 ## Using HTTP POST
 ## ===============
 ##
@@ -53,7 +61,7 @@
 ## uses `multipart/form-data` as the `Content-Type` to send the HTML to be
 ## validated to the server.
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   var client = newHttpClient()
 ##   var data = newMultipartData()
 ##   data["output"] = "soap12"
@@ -63,13 +71,14 @@
 ##     echo client.postContent("http://validator.w3.org/check", multipart=data)
 ##   finally:
 ##     client.close()
+##   ```
 ##
 ## To stream files from disk when performing the request, use `addFiles`.
 ##
 ## **Note:** This will allocate a new `Mimetypes` database every time you call
 ## it, you can pass your own via the `mimeDb` parameter to avoid this.
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   let mimes = newMimetypes()
 ##   var client = newHttpClient()
 ##   var data = newMultipartData()
@@ -78,12 +87,13 @@
 ##     echo client.postContent("http://validator.w3.org/check", multipart=data)
 ##   finally:
 ##     client.close()
+##   ```
 ##
 ## You can also make post requests with custom headers.
 ## This example sets `Content-Type` to `application/json`
 ## and uses a json object for the body
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/[httpclient, json]
 ##
 ##   let client = newHttpClient()
@@ -96,6 +106,7 @@
 ##     echo response.status
 ##   finally:
 ##     client.close()
+##   ```
 ##
 ## Progress reporting
 ## ==================
@@ -104,27 +115,29 @@
 ## This callback will be executed every second with information about the
 ## progress of the HTTP request.
 ##
-## .. code-block:: Nim
-##    import std/[asyncdispatch, httpclient]
+##   ```Nim
+##   import std/[asyncdispatch, httpclient]
 ##
-##    proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
-##      echo("Downloaded ", progress, " of ", total)
-##      echo("Current rate: ", speed div 1000, "kb/s")
+##   proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
+##     echo("Downloaded ", progress, " of ", total)
+##     echo("Current rate: ", speed div 1000, "kb/s")
 ##
-##    proc asyncProc() {.async.} =
-##      var client = newAsyncHttpClient()
-##      client.onProgressChanged = onProgressChanged
-##      try:
-##        discard await client.getContent("http://speedtest-ams2.digitalocean.com/100mb.test")
-##      finally:
-##        client.close()
+##   proc asyncProc() {.async.} =
+##     var client = newAsyncHttpClient()
+##     client.onProgressChanged = onProgressChanged
+##     try:
+##       discard await client.getContent("http://speedtest-ams2.digitalocean.com/100mb.test")
+##     finally:
+##       client.close()
 ##
-##    waitFor asyncProc()
+##   waitFor asyncProc()
+##   ```
 ##
 ## If you would like to remove the callback simply set it to `nil`.
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   client.onProgressChanged = nil
+##   ```
 ##
 ## .. warning:: The `total` reported by httpclient may be 0 in some cases.
 ##
@@ -146,9 +159,10 @@
 ##
 ## Example of setting SSL verification parameters in a new client:
 ##
-## .. code-block:: Nim
-##    import httpclient
-##    var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeer))
+##   ```Nim
+##   import httpclient
+##   var client = newHttpClient(sslContext=newContext(verifyMode=CVerifyPeer))
+##   ```
 ##
 ## There are three options for verify mode:
 ##
@@ -177,10 +191,11 @@
 ##
 ## Here is how to set a timeout when creating an `HttpClient` instance:
 ##
-## .. code-block:: Nim
-##    import std/httpclient
+##   ```Nim
+##   import std/httpclient
 ##
-##    let client = newHttpClient(timeout = 42)
+##   let client = newHttpClient(timeout = 42)
+##   ```
 ##
 ## Proxy
 ## =====
@@ -191,36 +206,39 @@
 ##
 ## Some examples on how to configure a Proxy for `HttpClient`:
 ##
-## .. code-block:: Nim
-##    import std/httpclient
+##   ```Nim
+##   import std/httpclient
 ##
-##    let myProxy = newProxy("http://myproxy.network")
-##    let client = newHttpClient(proxy = myProxy)
+##   let myProxy = newProxy("http://myproxy.network")
+##   let client = newHttpClient(proxy = myProxy)
+##   ```
 ##
 ## Use proxies with basic authentication:
 ##
-## .. code-block:: Nim
-##    import std/httpclient
-##    
-##    let myProxy = newProxy("http://myproxy.network", auth="user:password")
-##    let client = newHttpClient(proxy = myProxy)
+##   ```Nim
+##   import std/httpclient
+##
+##   let myProxy = newProxy("http://myproxy.network", auth="user:password")
+##   let client = newHttpClient(proxy = myProxy)
+##   ```
 ##
 ## Get Proxy URL from environment variables:
 ##
-## .. code-block:: Nim
-##    import std/httpclient
+##   ```Nim
+##   import std/httpclient
 ##
-##    var url = ""
-##    try:
-##      if existsEnv("http_proxy"):
-##        url = getEnv("http_proxy")
-##      elif existsEnv("https_proxy"):
-##        url = getEnv("https_proxy")
-##    except ValueError:
-##      echo "Unable to parse proxy from environment variables."
+##   var url = ""
+##   try:
+##     if existsEnv("http_proxy"):
+##       url = getEnv("http_proxy")
+##     elif existsEnv("https_proxy"):
+##       url = getEnv("https_proxy")
+##   except ValueError:
+##     echo "Unable to parse proxy from environment variables."
 ##
-##    let myProxy = newProxy(url = url)
-##    let client = newHttpClient(proxy = myProxy)
+##   let myProxy = newProxy(url = url)
+##   let client = newHttpClient(proxy = myProxy)
+##   ```
 ##
 ## Redirects
 ## =========
@@ -231,10 +249,11 @@
 ##
 ## Here you can see an example about how to set the `maxRedirects` of `HttpClient`:
 ##
-## .. code-block:: Nim
-##    import std/httpclient
+##   ```Nim
+##   import std/httpclient
 ##
-##    let client = newHttpClient(maxRedirects = 0)
+##   let client = newHttpClient(maxRedirects = 0)
+##   ```
 ##
 
 import std/private/since
@@ -286,7 +305,7 @@ proc contentLength*(response: Response | AsyncResponse): int =
   ##
   ## A `ValueError` exception will be raised if the value is not an integer.
   ## If the Content-Length header is not set in the response, ContentLength is set to the value -1.
-  var contentLengthHeader = response.headers.getOrDefault("Content-Length", @["-1"])
+  var contentLengthHeader = response.headers.getOrDefault("Content-Length", HttpHeaderValues(@["-1"]))
   result = contentLengthHeader.parseInt()
 
 proc lastModified*(response: Response | AsyncResponse): DateTime =
@@ -340,7 +359,7 @@ type
                                         ## and `postContent` proc,
                                         ## when the server returns an error
 
-const defUserAgent* = "Nim httpclient/" & NimVersion
+const defUserAgent* = "Nim-httpclient/" & NimVersion
 
 proc httpError(msg: string) =
   var e: ref ProtocolError
@@ -423,8 +442,9 @@ proc add*(p: MultipartData, xs: MultipartEntries): MultipartData
   ## Add a list of multipart entries to the multipart data `p`. All values are
   ## added without a filename and without a content type.
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   data.add({"action": "login", "format": "json"})
+  ##   ```
   for name, content in xs.items:
     p.add(name, content)
   result = p
@@ -433,8 +453,9 @@ proc newMultipartData*(xs: MultipartEntries): MultipartData =
   ## Create a new multipart data object and fill it with the entries `xs`
   ## directly.
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   var data = newMultipartData({"action": "login", "format": "json"})
+  ##   ```
   result = MultipartData()
   for entry in xs:
     result.add(entry.name, entry.content)
@@ -449,8 +470,9 @@ proc addFiles*(p: MultipartData, xs: openArray[tuple[name, file: string]],
   ## Raises an `IOError` if the file cannot be opened or reading fails. To
   ## manually specify file content, filename and MIME type, use `[]=` instead.
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   data.addFiles({"uploaded_file": "public/test.html"})
+  ##   ```
   for name, file in xs.items:
     var contentType: string
     let (_, fName, ext) = splitFile(file)
@@ -464,8 +486,9 @@ proc `[]=`*(p: MultipartData, name, content: string) {.inline.} =
   ## Add a multipart entry to the multipart data `p`. The value is added
   ## without a filename and without a content type.
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   data["username"] = "NimUser"
+  ##   ```
   p.add(name, content)
 
 proc `[]=`*(p: MultipartData, name: string,
@@ -473,9 +496,10 @@ proc `[]=`*(p: MultipartData, name: string,
   ## Add a file to the multipart data `p`, specifying filename, contentType
   ## and content manually.
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   data["uploaded_file"] = ("test.html", "text/html",
   ##     "<html><head></head><body><p>test</p></body></html>")
+  ##   ```
   p.add(name, file.content, file.name, file.contentType, useStream = false)
 
 proc getBoundary(p: MultipartData): string =
@@ -682,15 +706,15 @@ proc close*(client: HttpClient | AsyncHttpClient) =
     client.connected = false
 
 proc getSocket*(client: HttpClient): Socket {.inline.} =
-  ## Get network socket, useful if you want to find out more details about the connection
+  ## Get network socket, useful if you want to find out more details about the connection.
   ##
-  ## this example shows info about local and remote endpoints
+  ## This example shows info about local and remote endpoints:
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   if client.connected:
   ##     echo client.getSocket.getLocalAddr
   ##     echo client.getSocket.getPeerAddr
-  ##
+  ##   ```
   return client.socket
 
 proc getSocket*(client: AsyncHttpClient): AsyncSocket {.inline.} =
@@ -832,6 +856,7 @@ proc parseResponse(client: HttpClient | AsyncHttpClient,
   var parsedStatus = false
   var linei = 0
   var fullyRead = false
+  var lastHeaderName = ""
   var line = ""
   result.headers = newHttpHeaders()
   while true:
@@ -866,16 +891,29 @@ proc parseResponse(client: HttpClient | AsyncHttpClient,
       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())
-      if result.headers.len > headerLimit:
-        httpError("too many headers")
+      # There's at least one char because empty lines are handled above (with client.close)
+      if line[0] in {' ', '\t'}:
+        # Check if it's a multiline header value, if so, append to the header we're currently parsing
+        # This works because a line with a header must start with the header name without any leading space
+        # See https://datatracker.ietf.org/doc/html/rfc7230, section 3.2 and 3.2.4
+        # Multiline headers are deprecated in the spec, but it's better to parse them than crash
+        if lastHeaderName == "":
+          # Some extra unparsable lines in the HTTP output - we ignore them
+          discard
+        else:
+          result.headers.table[result.headers.toCaseInsensitive(lastHeaderName)][^1].add "\n" & line
+      else:
+        var name = ""
+        var le = parseUntil(line, name, ':', linei)
+        if le <= 0: httpError("Invalid headers - received empty header name")
+        if line.len == le: httpError("Invalid headers - no colon after header name")
+        inc(linei, le) # Skip the parsed header name
+        inc(linei) # Skip :
+        # If we want to be HTTP spec compliant later, error on linei == line.len (for empty header value)
+        lastHeaderName = name # Remember the header name for the possible multi-line header
+        result.headers.add(name, line[linei .. ^1].strip())
+        if result.headers.len > headerLimit:
+          httpError("too many headers")
 
   if not fullyRead:
     httpError("Connection was closed before full request has been made")
@@ -1194,7 +1232,7 @@ proc responseContent(resp: Response | AsyncResponse): Future[string] {.multisync
   ## A `HttpRequestError` will be raised if the server responds with a
   ## client error (status code 4xx) or a server error (status code 5xx).
   if resp.code.is4xx or resp.code.is5xx:
-    raise newException(HttpRequestError, resp.status)
+    raise newException(HttpRequestError, resp.status.move)
   else:
     return await resp.bodyStream.readAll()
 
diff --git a/lib/pure/httpcore.nim b/lib/pure/httpcore.nim
index 7e995ac46..5ccab379c 100644
--- a/lib/pure/httpcore.nim
+++ b/lib/pure/httpcore.nim
@@ -12,7 +12,7 @@
 ##
 ## Unstable API.
 import std/private/since
-import tables, strutils, parseutils
+import std/[tables, strutils, parseutils]
 
 type
   HttpHeaders* = ref object
@@ -126,23 +126,20 @@ func toTitleCase(s: string): string =
     result[i] = if upper: toUpperAscii(s[i]) else: toLowerAscii(s[i])
     upper = s[i] == '-'
 
-func toCaseInsensitive(headers: HttpHeaders, s: string): string {.inline.} =
+func toCaseInsensitive*(headers: HttpHeaders, s: string): string {.inline.} =
+  ## For internal usage only. Do not use.
   return if headers.isTitleCase: toTitleCase(s) else: toLowerAscii(s)
 
 func newHttpHeaders*(titleCase=false): HttpHeaders =
   ## Returns a new `HttpHeaders` object. if `titleCase` is set to true,
   ## headers are passed to the server in title case (e.g. "Content-Length")
-  new result
-  result.table = newTable[string, seq[string]]()
-  result.isTitleCase = titleCase
+  result = HttpHeaders(table: newTable[string, seq[string]](), isTitleCase: titleCase)
 
 func newHttpHeaders*(keyValuePairs:
     openArray[tuple[key: string, val: string]], titleCase=false): HttpHeaders =
   ## Returns a new `HttpHeaders` object from an array. if `titleCase` is set to true,
   ## headers are passed to the server in title case (e.g. "Content-Length")
-  new result
-  result.table = newTable[string, seq[string]]()
-  result.isTitleCase = titleCase
+  result = HttpHeaders(table: newTable[string, seq[string]](), isTitleCase: titleCase)
 
   for pair in keyValuePairs:
     let key = result.toCaseInsensitive(pair.key)
@@ -167,7 +164,8 @@ func `[]`*(headers: HttpHeaders, key: string): HttpHeaderValues =
   ## To access multiple values of a key, use the overloaded `[]` below or
   ## to get all of them access the `table` field directly.
   {.cast(noSideEffect).}:
-    return headers.table[headers.toCaseInsensitive(key)].HttpHeaderValues
+    let tmp = headers.table[headers.toCaseInsensitive(key)]
+    return HttpHeaderValues(tmp)
 
 converter toString*(values: HttpHeaderValues): string =
   return seq[string](values)[0]
@@ -237,10 +235,9 @@ func parseList(line: string, list: var seq[string], start: int): int =
   while start+i < line.len and line[start + i] notin {'\c', '\l'}:
     i += line.skipWhitespace(start + i)
     i += line.parseUntil(current, {'\c', '\l', ','}, start + i)
-    list.add(current)
+    list.add(move current)  # implicit current.setLen(0)
     if start+i < line.len and line[start + i] == ',':
       i.inc # Skip ,
-    current.setLen(0)
 
 func parseHeader*(line: string): tuple[key: string, value: seq[string]] =
   ## Parses a single raw header HTTP line into key value pairs.
@@ -352,20 +349,20 @@ func is1xx*(code: HttpCode): bool {.inline, since: (1, 5).} =
   runnableExamples:
     doAssert is1xx(HttpCode(103))
 
-  code.int in {100 .. 199}
+  code.int in 100 .. 199
 
 func is2xx*(code: HttpCode): bool {.inline.} =
   ## Determines whether `code` is a 2xx HTTP status code.
-  code.int in {200 .. 299}
+  code.int in 200 .. 299
 
 func is3xx*(code: HttpCode): bool {.inline.} =
   ## Determines whether `code` is a 3xx HTTP status code.
-  code.int in {300 .. 399}
+  code.int in 300 .. 399
 
 func is4xx*(code: HttpCode): bool {.inline.} =
   ## Determines whether `code` is a 4xx HTTP status code.
-  code.int in {400 .. 499}
+  code.int in 400 .. 499
 
 func is5xx*(code: HttpCode): bool {.inline.} =
   ## Determines whether `code` is a 5xx HTTP status code.
-  code.int in {500 .. 599}
+  code.int in 500 .. 599
diff --git a/lib/pure/includes/unicode_ranges.nim b/lib/pure/includes/unicode_ranges.nim
index 74c8c6399..04ccfb747 100644
--- a/lib/pure/includes/unicode_ranges.nim
+++ b/lib/pure/includes/unicode_ranges.nim
@@ -2,1988 +2,1979 @@
 
 const
   toLowerRanges = [
-    0x00041, 0x0005A, 532,
-    0x000C0, 0x000D6, 532,
-    0x000D8, 0x000DE, 532,
-    0x00189, 0x0018A, 705,
-    0x001B1, 0x001B2, 717,
-    0x00388, 0x0038A, 537,
-    0x0038E, 0x0038F, 563,
-    0x00391, 0x003A1, 532,
-    0x003A3, 0x003AB, 532,
-    0x003FD, 0x003FF, 370,
-    0x00400, 0x0040F, 580,
-    0x00410, 0x0042F, 532,
-    0x00531, 0x00556, 548,
-    0x010A0, 0x010C5, 7764,
-    0x013A0, 0x013EF, 39364,
-    0x013F0, 0x013F5, 508,
-    0x01C90, 0x01CBA, -2508,
-    0x01CBD, 0x01CBF, -2508,
-    0x01F08, 0x01F0F, 492,
-    0x01F18, 0x01F1D, 492,
-    0x01F28, 0x01F2F, 492,
-    0x01F38, 0x01F3F, 492,
-    0x01F48, 0x01F4D, 492,
-    0x01F68, 0x01F6F, 492,
-    0x01F88, 0x01F8F, 492,
-    0x01F98, 0x01F9F, 492,
-    0x01FA8, 0x01FAF, 492,
-    0x01FB8, 0x01FB9, 492,
-    0x01FBA, 0x01FBB, 426,
-    0x01FC8, 0x01FCB, 414,
-    0x01FD8, 0x01FD9, 492,
-    0x01FDA, 0x01FDB, 400,
-    0x01FE8, 0x01FE9, 492,
-    0x01FEA, 0x01FEB, 388,
-    0x01FF8, 0x01FF9, 372,
-    0x01FFA, 0x01FFB, 374,
-    0x02C00, 0x02C2E, 548,
-    0x02C7E, 0x02C7F, -10315,
-    0x0FF21, 0x0FF3A, 532,
-    0x10400, 0x10427, 540,
-    0x104B0, 0x104D3, 540,
-    0x10C80, 0x10CB2, 564,
-    0x118A0, 0x118BF, 532,
-    0x16E40, 0x16E5F, 532,
-    0x1E900, 0x1E921, 534,
+    0x00041'i32, 0x0005A'i32, 532,
+    0x000C0'i32, 0x000D6'i32, 532,
+    0x000D8'i32, 0x000DE'i32, 532,
+    0x00189'i32, 0x0018A'i32, 705,
+    0x001B1'i32, 0x001B2'i32, 717,
+    0x00388'i32, 0x0038A'i32, 537,
+    0x0038E'i32, 0x0038F'i32, 563,
+    0x00391'i32, 0x003A1'i32, 532,
+    0x003A3'i32, 0x003AB'i32, 532,
+    0x003FD'i32, 0x003FF'i32, 370,
+    0x00400'i32, 0x0040F'i32, 580,
+    0x00410'i32, 0x0042F'i32, 532,
+    0x00531'i32, 0x00556'i32, 548,
+    0x010A0'i32, 0x010C5'i32, 7764,
+    0x013A0'i32, 0x013EF'i32, 39364,
+    0x013F0'i32, 0x013F5'i32, 508,
+    0x01C90'i32, 0x01CBA'i32, -2508,
+    0x01CBD'i32, 0x01CBF'i32, -2508,
+    0x01F08'i32, 0x01F0F'i32, 492,
+    0x01F18'i32, 0x01F1D'i32, 492,
+    0x01F28'i32, 0x01F2F'i32, 492,
+    0x01F38'i32, 0x01F3F'i32, 492,
+    0x01F48'i32, 0x01F4D'i32, 492,
+    0x01F68'i32, 0x01F6F'i32, 492,
+    0x01F88'i32, 0x01F8F'i32, 492,
+    0x01F98'i32, 0x01F9F'i32, 492,
+    0x01FA8'i32, 0x01FAF'i32, 492,
+    0x01FB8'i32, 0x01FB9'i32, 492,
+    0x01FBA'i32, 0x01FBB'i32, 426,
+    0x01FC8'i32, 0x01FCB'i32, 414,
+    0x01FD8'i32, 0x01FD9'i32, 492,
+    0x01FDA'i32, 0x01FDB'i32, 400,
+    0x01FE8'i32, 0x01FE9'i32, 492,
+    0x01FEA'i32, 0x01FEB'i32, 388,
+    0x01FF8'i32, 0x01FF9'i32, 372,
+    0x01FFA'i32, 0x01FFB'i32, 374,
+    0x02C00'i32, 0x02C2E'i32, 548,
+    0x02C7E'i32, 0x02C7F'i32, -10315,
+    0x0FF21'i32, 0x0FF3A'i32, 532,
+    0x10400'i32, 0x10427'i32, 540,
+    0x104B0'i32, 0x104D3'i32, 540,
+    0x10C80'i32, 0x10CB2'i32, 564,
+    0x118A0'i32, 0x118BF'i32, 532,
+    0x16E40'i32, 0x16E5F'i32, 532,
+    0x1E900'i32, 0x1E921'i32, 534,
   ]
 
   toLowerSinglets = [
-    0x00100, 501,
-    0x00102, 501,
-    0x00104, 501,
-    0x00106, 501,
-    0x00108, 501,
-    0x0010A, 501,
-    0x0010C, 501,
-    0x0010E, 501,
-    0x00110, 501,
-    0x00112, 501,
-    0x00114, 501,
-    0x00116, 501,
-    0x00118, 501,
-    0x0011A, 501,
-    0x0011C, 501,
-    0x0011E, 501,
-    0x00120, 501,
-    0x00122, 501,
-    0x00124, 501,
-    0x00126, 501,
-    0x00128, 501,
-    0x0012A, 501,
-    0x0012C, 501,
-    0x0012E, 501,
-    0x00130, 301,
-    0x00132, 501,
-    0x00134, 501,
-    0x00136, 501,
-    0x00139, 501,
-    0x0013B, 501,
-    0x0013D, 501,
-    0x0013F, 501,
-    0x00141, 501,
-    0x00143, 501,
-    0x00145, 501,
-    0x00147, 501,
-    0x0014A, 501,
-    0x0014C, 501,
-    0x0014E, 501,
-    0x00150, 501,
-    0x00152, 501,
-    0x00154, 501,
-    0x00156, 501,
-    0x00158, 501,
-    0x0015A, 501,
-    0x0015C, 501,
-    0x0015E, 501,
-    0x00160, 501,
-    0x00162, 501,
-    0x00164, 501,
-    0x00166, 501,
-    0x00168, 501,
-    0x0016A, 501,
-    0x0016C, 501,
-    0x0016E, 501,
-    0x00170, 501,
-    0x00172, 501,
-    0x00174, 501,
-    0x00176, 501,
-    0x00178, 379,
-    0x00179, 501,
-    0x0017B, 501,
-    0x0017D, 501,
-    0x00181, 710,
-    0x00182, 501,
-    0x00184, 501,
-    0x00186, 706,
-    0x00187, 501,
-    0x0018B, 501,
-    0x0018E, 579,
-    0x0018F, 702,
-    0x00190, 703,
-    0x00191, 501,
-    0x00193, 705,
-    0x00194, 707,
-    0x00196, 711,
-    0x00197, 709,
-    0x00198, 501,
-    0x0019C, 711,
-    0x0019D, 713,
-    0x0019F, 714,
-    0x001A0, 501,
-    0x001A2, 501,
-    0x001A4, 501,
-    0x001A6, 718,
-    0x001A7, 501,
-    0x001A9, 718,
-    0x001AC, 501,
-    0x001AE, 718,
-    0x001AF, 501,
-    0x001B3, 501,
-    0x001B5, 501,
-    0x001B7, 719,
-    0x001B8, 501,
-    0x001BC, 501,
-    0x001C4, 502,
-    0x001C5, 501,
-    0x001C7, 502,
-    0x001C8, 501,
-    0x001CA, 502,
-    0x001CB, 501,
-    0x001CD, 501,
-    0x001CF, 501,
-    0x001D1, 501,
-    0x001D3, 501,
-    0x001D5, 501,
-    0x001D7, 501,
-    0x001D9, 501,
-    0x001DB, 501,
-    0x001DE, 501,
-    0x001E0, 501,
-    0x001E2, 501,
-    0x001E4, 501,
-    0x001E6, 501,
-    0x001E8, 501,
-    0x001EA, 501,
-    0x001EC, 501,
-    0x001EE, 501,
-    0x001F1, 502,
-    0x001F2, 501,
-    0x001F4, 501,
-    0x001F6, 403,
-    0x001F7, 444,
-    0x001F8, 501,
-    0x001FA, 501,
-    0x001FC, 501,
-    0x001FE, 501,
-    0x00200, 501,
-    0x00202, 501,
-    0x00204, 501,
-    0x00206, 501,
-    0x00208, 501,
-    0x0020A, 501,
-    0x0020C, 501,
-    0x0020E, 501,
-    0x00210, 501,
-    0x00212, 501,
-    0x00214, 501,
-    0x00216, 501,
-    0x00218, 501,
-    0x0021A, 501,
-    0x0021C, 501,
-    0x0021E, 501,
-    0x00220, 370,
-    0x00222, 501,
-    0x00224, 501,
-    0x00226, 501,
-    0x00228, 501,
-    0x0022A, 501,
-    0x0022C, 501,
-    0x0022E, 501,
-    0x00230, 501,
-    0x00232, 501,
-    0x0023A, 11295,
-    0x0023B, 501,
-    0x0023D, 337,
-    0x0023E, 11292,
-    0x00241, 501,
-    0x00243, 305,
-    0x00244, 569,
-    0x00245, 571,
-    0x00246, 501,
-    0x00248, 501,
-    0x0024A, 501,
-    0x0024C, 501,
-    0x0024E, 501,
-    0x00370, 501,
-    0x00372, 501,
-    0x00376, 501,
-    0x0037F, 616,
-    0x00386, 538,
-    0x0038C, 564,
-    0x003CF, 508,
-    0x003D8, 501,
-    0x003DA, 501,
-    0x003DC, 501,
-    0x003DE, 501,
-    0x003E0, 501,
-    0x003E2, 501,
-    0x003E4, 501,
-    0x003E6, 501,
-    0x003E8, 501,
-    0x003EA, 501,
-    0x003EC, 501,
-    0x003EE, 501,
-    0x003F4, 440,
-    0x003F7, 501,
-    0x003F9, 493,
-    0x003FA, 501,
-    0x00460, 501,
-    0x00462, 501,
-    0x00464, 501,
-    0x00466, 501,
-    0x00468, 501,
-    0x0046A, 501,
-    0x0046C, 501,
-    0x0046E, 501,
-    0x00470, 501,
-    0x00472, 501,
-    0x00474, 501,
-    0x00476, 501,
-    0x00478, 501,
-    0x0047A, 501,
-    0x0047C, 501,
-    0x0047E, 501,
-    0x00480, 501,
-    0x0048A, 501,
-    0x0048C, 501,
-    0x0048E, 501,
-    0x00490, 501,
-    0x00492, 501,
-    0x00494, 501,
-    0x00496, 501,
-    0x00498, 501,
-    0x0049A, 501,
-    0x0049C, 501,
-    0x0049E, 501,
-    0x004A0, 501,
-    0x004A2, 501,
-    0x004A4, 501,
-    0x004A6, 501,
-    0x004A8, 501,
-    0x004AA, 501,
-    0x004AC, 501,
-    0x004AE, 501,
-    0x004B0, 501,
-    0x004B2, 501,
-    0x004B4, 501,
-    0x004B6, 501,
-    0x004B8, 501,
-    0x004BA, 501,
-    0x004BC, 501,
-    0x004BE, 501,
-    0x004C0, 515,
-    0x004C1, 501,
-    0x004C3, 501,
-    0x004C5, 501,
-    0x004C7, 501,
-    0x004C9, 501,
-    0x004CB, 501,
-    0x004CD, 501,
-    0x004D0, 501,
-    0x004D2, 501,
-    0x004D4, 501,
-    0x004D6, 501,
-    0x004D8, 501,
-    0x004DA, 501,
-    0x004DC, 501,
-    0x004DE, 501,
-    0x004E0, 501,
-    0x004E2, 501,
-    0x004E4, 501,
-    0x004E6, 501,
-    0x004E8, 501,
-    0x004EA, 501,
-    0x004EC, 501,
-    0x004EE, 501,
-    0x004F0, 501,
-    0x004F2, 501,
-    0x004F4, 501,
-    0x004F6, 501,
-    0x004F8, 501,
-    0x004FA, 501,
-    0x004FC, 501,
-    0x004FE, 501,
-    0x00500, 501,
-    0x00502, 501,
-    0x00504, 501,
-    0x00506, 501,
-    0x00508, 501,
-    0x0050A, 501,
-    0x0050C, 501,
-    0x0050E, 501,
-    0x00510, 501,
-    0x00512, 501,
-    0x00514, 501,
-    0x00516, 501,
-    0x00518, 501,
-    0x0051A, 501,
-    0x0051C, 501,
-    0x0051E, 501,
-    0x00520, 501,
-    0x00522, 501,
-    0x00524, 501,
-    0x00526, 501,
-    0x00528, 501,
-    0x0052A, 501,
-    0x0052C, 501,
-    0x0052E, 501,
-    0x010C7, 7764,
-    0x010CD, 7764,
-    0x01E00, 501,
-    0x01E02, 501,
-    0x01E04, 501,
-    0x01E06, 501,
-    0x01E08, 501,
-    0x01E0A, 501,
-    0x01E0C, 501,
-    0x01E0E, 501,
-    0x01E10, 501,
-    0x01E12, 501,
-    0x01E14, 501,
-    0x01E16, 501,
-    0x01E18, 501,
-    0x01E1A, 501,
-    0x01E1C, 501,
-    0x01E1E, 501,
-    0x01E20, 501,
-    0x01E22, 501,
-    0x01E24, 501,
-    0x01E26, 501,
-    0x01E28, 501,
-    0x01E2A, 501,
-    0x01E2C, 501,
-    0x01E2E, 501,
-    0x01E30, 501,
-    0x01E32, 501,
-    0x01E34, 501,
-    0x01E36, 501,
-    0x01E38, 501,
-    0x01E3A, 501,
-    0x01E3C, 501,
-    0x01E3E, 501,
-    0x01E40, 501,
-    0x01E42, 501,
-    0x01E44, 501,
-    0x01E46, 501,
-    0x01E48, 501,
-    0x01E4A, 501,
-    0x01E4C, 501,
-    0x01E4E, 501,
-    0x01E50, 501,
-    0x01E52, 501,
-    0x01E54, 501,
-    0x01E56, 501,
-    0x01E58, 501,
-    0x01E5A, 501,
-    0x01E5C, 501,
-    0x01E5E, 501,
-    0x01E60, 501,
-    0x01E62, 501,
-    0x01E64, 501,
-    0x01E66, 501,
-    0x01E68, 501,
-    0x01E6A, 501,
-    0x01E6C, 501,
-    0x01E6E, 501,
-    0x01E70, 501,
-    0x01E72, 501,
-    0x01E74, 501,
-    0x01E76, 501,
-    0x01E78, 501,
-    0x01E7A, 501,
-    0x01E7C, 501,
-    0x01E7E, 501,
-    0x01E80, 501,
-    0x01E82, 501,
-    0x01E84, 501,
-    0x01E86, 501,
-    0x01E88, 501,
-    0x01E8A, 501,
-    0x01E8C, 501,
-    0x01E8E, 501,
-    0x01E90, 501,
-    0x01E92, 501,
-    0x01E94, 501,
-    0x01E9E, -7115,
-    0x01EA0, 501,
-    0x01EA2, 501,
-    0x01EA4, 501,
-    0x01EA6, 501,
-    0x01EA8, 501,
-    0x01EAA, 501,
-    0x01EAC, 501,
-    0x01EAE, 501,
-    0x01EB0, 501,
-    0x01EB2, 501,
-    0x01EB4, 501,
-    0x01EB6, 501,
-    0x01EB8, 501,
-    0x01EBA, 501,
-    0x01EBC, 501,
-    0x01EBE, 501,
-    0x01EC0, 501,
-    0x01EC2, 501,
-    0x01EC4, 501,
-    0x01EC6, 501,
-    0x01EC8, 501,
-    0x01ECA, 501,
-    0x01ECC, 501,
-    0x01ECE, 501,
-    0x01ED0, 501,
-    0x01ED2, 501,
-    0x01ED4, 501,
-    0x01ED6, 501,
-    0x01ED8, 501,
-    0x01EDA, 501,
-    0x01EDC, 501,
-    0x01EDE, 501,
-    0x01EE0, 501,
-    0x01EE2, 501,
-    0x01EE4, 501,
-    0x01EE6, 501,
-    0x01EE8, 501,
-    0x01EEA, 501,
-    0x01EEC, 501,
-    0x01EEE, 501,
-    0x01EF0, 501,
-    0x01EF2, 501,
-    0x01EF4, 501,
-    0x01EF6, 501,
-    0x01EF8, 501,
-    0x01EFA, 501,
-    0x01EFC, 501,
-    0x01EFE, 501,
-    0x01F59, 492,
-    0x01F5B, 492,
-    0x01F5D, 492,
-    0x01F5F, 492,
-    0x01FBC, 491,
-    0x01FCC, 491,
-    0x01FEC, 493,
-    0x01FFC, 491,
-    0x02126, -7017,
-    0x0212A, -7883,
-    0x0212B, -7762,
-    0x02132, 528,
-    0x02183, 501,
-    0x02C60, 501,
-    0x02C62, -10243,
-    0x02C63, -3314,
-    0x02C64, -10227,
-    0x02C67, 501,
-    0x02C69, 501,
-    0x02C6B, 501,
-    0x02C6D, -10280,
-    0x02C6E, -10249,
-    0x02C6F, -10283,
-    0x02C70, -10282,
-    0x02C72, 501,
-    0x02C75, 501,
-    0x02C80, 501,
-    0x02C82, 501,
-    0x02C84, 501,
-    0x02C86, 501,
-    0x02C88, 501,
-    0x02C8A, 501,
-    0x02C8C, 501,
-    0x02C8E, 501,
-    0x02C90, 501,
-    0x02C92, 501,
-    0x02C94, 501,
-    0x02C96, 501,
-    0x02C98, 501,
-    0x02C9A, 501,
-    0x02C9C, 501,
-    0x02C9E, 501,
-    0x02CA0, 501,
-    0x02CA2, 501,
-    0x02CA4, 501,
-    0x02CA6, 501,
-    0x02CA8, 501,
-    0x02CAA, 501,
-    0x02CAC, 501,
-    0x02CAE, 501,
-    0x02CB0, 501,
-    0x02CB2, 501,
-    0x02CB4, 501,
-    0x02CB6, 501,
-    0x02CB8, 501,
-    0x02CBA, 501,
-    0x02CBC, 501,
-    0x02CBE, 501,
-    0x02CC0, 501,
-    0x02CC2, 501,
-    0x02CC4, 501,
-    0x02CC6, 501,
-    0x02CC8, 501,
-    0x02CCA, 501,
-    0x02CCC, 501,
-    0x02CCE, 501,
-    0x02CD0, 501,
-    0x02CD2, 501,
-    0x02CD4, 501,
-    0x02CD6, 501,
-    0x02CD8, 501,
-    0x02CDA, 501,
-    0x02CDC, 501,
-    0x02CDE, 501,
-    0x02CE0, 501,
-    0x02CE2, 501,
-    0x02CEB, 501,
-    0x02CED, 501,
-    0x02CF2, 501,
-    0x0A640, 501,
-    0x0A642, 501,
-    0x0A644, 501,
-    0x0A646, 501,
-    0x0A648, 501,
-    0x0A64A, 501,
-    0x0A64C, 501,
-    0x0A64E, 501,
-    0x0A650, 501,
-    0x0A652, 501,
-    0x0A654, 501,
-    0x0A656, 501,
-    0x0A658, 501,
-    0x0A65A, 501,
-    0x0A65C, 501,
-    0x0A65E, 501,
-    0x0A660, 501,
-    0x0A662, 501,
-    0x0A664, 501,
-    0x0A666, 501,
-    0x0A668, 501,
-    0x0A66A, 501,
-    0x0A66C, 501,
-    0x0A680, 501,
-    0x0A682, 501,
-    0x0A684, 501,
-    0x0A686, 501,
-    0x0A688, 501,
-    0x0A68A, 501,
-    0x0A68C, 501,
-    0x0A68E, 501,
-    0x0A690, 501,
-    0x0A692, 501,
-    0x0A694, 501,
-    0x0A696, 501,
-    0x0A698, 501,
-    0x0A69A, 501,
-    0x0A722, 501,
-    0x0A724, 501,
-    0x0A726, 501,
-    0x0A728, 501,
-    0x0A72A, 501,
-    0x0A72C, 501,
-    0x0A72E, 501,
-    0x0A732, 501,
-    0x0A734, 501,
-    0x0A736, 501,
-    0x0A738, 501,
-    0x0A73A, 501,
-    0x0A73C, 501,
-    0x0A73E, 501,
-    0x0A740, 501,
-    0x0A742, 501,
-    0x0A744, 501,
-    0x0A746, 501,
-    0x0A748, 501,
-    0x0A74A, 501,
-    0x0A74C, 501,
-    0x0A74E, 501,
-    0x0A750, 501,
-    0x0A752, 501,
-    0x0A754, 501,
-    0x0A756, 501,
-    0x0A758, 501,
-    0x0A75A, 501,
-    0x0A75C, 501,
-    0x0A75E, 501,
-    0x0A760, 501,
-    0x0A762, 501,
-    0x0A764, 501,
-    0x0A766, 501,
-    0x0A768, 501,
-    0x0A76A, 501,
-    0x0A76C, 501,
-    0x0A76E, 501,
-    0x0A779, 501,
-    0x0A77B, 501,
-    0x0A77D, -34832,
-    0x0A77E, 501,
-    0x0A780, 501,
-    0x0A782, 501,
-    0x0A784, 501,
-    0x0A786, 501,
-    0x0A78B, 501,
-    0x0A78D, -41780,
-    0x0A790, 501,
-    0x0A792, 501,
-    0x0A796, 501,
-    0x0A798, 501,
-    0x0A79A, 501,
-    0x0A79C, 501,
-    0x0A79E, 501,
-    0x0A7A0, 501,
-    0x0A7A2, 501,
-    0x0A7A4, 501,
-    0x0A7A6, 501,
-    0x0A7A8, 501,
-    0x0A7AA, -41808,
-    0x0A7AB, -41819,
-    0x0A7AC, -41815,
-    0x0A7AD, -41805,
-    0x0A7AE, -41808,
-    0x0A7B0, -41758,
-    0x0A7B1, -41782,
-    0x0A7B2, -41761,
-    0x0A7B3, 1428,
-    0x0A7B4, 501,
-    0x0A7B6, 501,
-    0x0A7B8, 501,
-    0x0A7BA, 501,
-    0x0A7BC, 501,
-    0x0A7BE, 501,
-    0x0A7C2, 501,
-    0x0A7C4, 452,
-    0x0A7C5, -41807,
-    0x0A7C6, -34884,
+    0x00100'i32, 501,
+    0x00102'i32, 501,
+    0x00104'i32, 501,
+    0x00106'i32, 501,
+    0x00108'i32, 501,
+    0x0010A'i32, 501,
+    0x0010C'i32, 501,
+    0x0010E'i32, 501,
+    0x00110'i32, 501,
+    0x00112'i32, 501,
+    0x00114'i32, 501,
+    0x00116'i32, 501,
+    0x00118'i32, 501,
+    0x0011A'i32, 501,
+    0x0011C'i32, 501,
+    0x0011E'i32, 501,
+    0x00120'i32, 501,
+    0x00122'i32, 501,
+    0x00124'i32, 501,
+    0x00126'i32, 501,
+    0x00128'i32, 501,
+    0x0012A'i32, 501,
+    0x0012C'i32, 501,
+    0x0012E'i32, 501,
+    0x00130'i32, 301,
+    0x00132'i32, 501,
+    0x00134'i32, 501,
+    0x00136'i32, 501,
+    0x00139'i32, 501,
+    0x0013B'i32, 501,
+    0x0013D'i32, 501,
+    0x0013F'i32, 501,
+    0x00141'i32, 501,
+    0x00143'i32, 501,
+    0x00145'i32, 501,
+    0x00147'i32, 501,
+    0x0014A'i32, 501,
+    0x0014C'i32, 501,
+    0x0014E'i32, 501,
+    0x00150'i32, 501,
+    0x00152'i32, 501,
+    0x00154'i32, 501,
+    0x00156'i32, 501,
+    0x00158'i32, 501,
+    0x0015A'i32, 501,
+    0x0015C'i32, 501,
+    0x0015E'i32, 501,
+    0x00160'i32, 501,
+    0x00162'i32, 501,
+    0x00164'i32, 501,
+    0x00166'i32, 501,
+    0x00168'i32, 501,
+    0x0016A'i32, 501,
+    0x0016C'i32, 501,
+    0x0016E'i32, 501,
+    0x00170'i32, 501,
+    0x00172'i32, 501,
+    0x00174'i32, 501,
+    0x00176'i32, 501,
+    0x00178'i32, 379,
+    0x00179'i32, 501,
+    0x0017B'i32, 501,
+    0x0017D'i32, 501,
+    0x00181'i32, 710,
+    0x00182'i32, 501,
+    0x00184'i32, 501,
+    0x00186'i32, 706,
+    0x00187'i32, 501,
+    0x0018B'i32, 501,
+    0x0018E'i32, 579,
+    0x0018F'i32, 702,
+    0x00190'i32, 703,
+    0x00191'i32, 501,
+    0x00193'i32, 705,
+    0x00194'i32, 707,
+    0x00196'i32, 711,
+    0x00197'i32, 709,
+    0x00198'i32, 501,
+    0x0019C'i32, 711,
+    0x0019D'i32, 713,
+    0x0019F'i32, 714,
+    0x001A0'i32, 501,
+    0x001A2'i32, 501,
+    0x001A4'i32, 501,
+    0x001A6'i32, 718,
+    0x001A7'i32, 501,
+    0x001A9'i32, 718,
+    0x001AC'i32, 501,
+    0x001AE'i32, 718,
+    0x001AF'i32, 501,
+    0x001B3'i32, 501,
+    0x001B5'i32, 501,
+    0x001B7'i32, 719,
+    0x001B8'i32, 501,
+    0x001BC'i32, 501,
+    0x001C4'i32, 502,
+    0x001C5'i32, 501,
+    0x001C7'i32, 502,
+    0x001C8'i32, 501,
+    0x001CA'i32, 502,
+    0x001CB'i32, 501,
+    0x001CD'i32, 501,
+    0x001CF'i32, 501,
+    0x001D1'i32, 501,
+    0x001D3'i32, 501,
+    0x001D5'i32, 501,
+    0x001D7'i32, 501,
+    0x001D9'i32, 501,
+    0x001DB'i32, 501,
+    0x001DE'i32, 501,
+    0x001E0'i32, 501,
+    0x001E2'i32, 501,
+    0x001E4'i32, 501,
+    0x001E6'i32, 501,
+    0x001E8'i32, 501,
+    0x001EA'i32, 501,
+    0x001EC'i32, 501,
+    0x001EE'i32, 501,
+    0x001F1'i32, 502,
+    0x001F2'i32, 501,
+    0x001F4'i32, 501,
+    0x001F6'i32, 403,
+    0x001F7'i32, 444,
+    0x001F8'i32, 501,
+    0x001FA'i32, 501,
+    0x001FC'i32, 501,
+    0x001FE'i32, 501,
+    0x00200'i32, 501,
+    0x00202'i32, 501,
+    0x00204'i32, 501,
+    0x00206'i32, 501,
+    0x00208'i32, 501,
+    0x0020A'i32, 501,
+    0x0020C'i32, 501,
+    0x0020E'i32, 501,
+    0x00210'i32, 501,
+    0x00212'i32, 501,
+    0x00214'i32, 501,
+    0x00216'i32, 501,
+    0x00218'i32, 501,
+    0x0021A'i32, 501,
+    0x0021C'i32, 501,
+    0x0021E'i32, 501,
+    0x00220'i32, 370,
+    0x00222'i32, 501,
+    0x00224'i32, 501,
+    0x00226'i32, 501,
+    0x00228'i32, 501,
+    0x0022A'i32, 501,
+    0x0022C'i32, 501,
+    0x0022E'i32, 501,
+    0x00230'i32, 501,
+    0x00232'i32, 501,
+    0x0023A'i32, 11295,
+    0x0023B'i32, 501,
+    0x0023D'i32, 337,
+    0x0023E'i32, 11292,
+    0x00241'i32, 501,
+    0x00243'i32, 305,
+    0x00244'i32, 569,
+    0x00245'i32, 571,
+    0x00246'i32, 501,
+    0x00248'i32, 501,
+    0x0024A'i32, 501,
+    0x0024C'i32, 501,
+    0x0024E'i32, 501,
+    0x00370'i32, 501,
+    0x00372'i32, 501,
+    0x00376'i32, 501,
+    0x0037F'i32, 616,
+    0x00386'i32, 538,
+    0x0038C'i32, 564,
+    0x003CF'i32, 508,
+    0x003D8'i32, 501,
+    0x003DA'i32, 501,
+    0x003DC'i32, 501,
+    0x003DE'i32, 501,
+    0x003E0'i32, 501,
+    0x003E2'i32, 501,
+    0x003E4'i32, 501,
+    0x003E6'i32, 501,
+    0x003E8'i32, 501,
+    0x003EA'i32, 501,
+    0x003EC'i32, 501,
+    0x003EE'i32, 501,
+    0x003F4'i32, 440,
+    0x003F7'i32, 501,
+    0x003F9'i32, 493,
+    0x003FA'i32, 501,
+    0x00460'i32, 501,
+    0x00462'i32, 501,
+    0x00464'i32, 501,
+    0x00466'i32, 501,
+    0x00468'i32, 501,
+    0x0046A'i32, 501,
+    0x0046C'i32, 501,
+    0x0046E'i32, 501,
+    0x00470'i32, 501,
+    0x00472'i32, 501,
+    0x00474'i32, 501,
+    0x00476'i32, 501,
+    0x00478'i32, 501,
+    0x0047A'i32, 501,
+    0x0047C'i32, 501,
+    0x0047E'i32, 501,
+    0x00480'i32, 501,
+    0x0048A'i32, 501,
+    0x0048C'i32, 501,
+    0x0048E'i32, 501,
+    0x00490'i32, 501,
+    0x00492'i32, 501,
+    0x00494'i32, 501,
+    0x00496'i32, 501,
+    0x00498'i32, 501,
+    0x0049A'i32, 501,
+    0x0049C'i32, 501,
+    0x0049E'i32, 501,
+    0x004A0'i32, 501,
+    0x004A2'i32, 501,
+    0x004A4'i32, 501,
+    0x004A6'i32, 501,
+    0x004A8'i32, 501,
+    0x004AA'i32, 501,
+    0x004AC'i32, 501,
+    0x004AE'i32, 501,
+    0x004B0'i32, 501,
+    0x004B2'i32, 501,
+    0x004B4'i32, 501,
+    0x004B6'i32, 501,
+    0x004B8'i32, 501,
+    0x004BA'i32, 501,
+    0x004BC'i32, 501,
+    0x004BE'i32, 501,
+    0x004C0'i32, 515,
+    0x004C1'i32, 501,
+    0x004C3'i32, 501,
+    0x004C5'i32, 501,
+    0x004C7'i32, 501,
+    0x004C9'i32, 501,
+    0x004CB'i32, 501,
+    0x004CD'i32, 501,
+    0x004D0'i32, 501,
+    0x004D2'i32, 501,
+    0x004D4'i32, 501,
+    0x004D6'i32, 501,
+    0x004D8'i32, 501,
+    0x004DA'i32, 501,
+    0x004DC'i32, 501,
+    0x004DE'i32, 501,
+    0x004E0'i32, 501,
+    0x004E2'i32, 501,
+    0x004E4'i32, 501,
+    0x004E6'i32, 501,
+    0x004E8'i32, 501,
+    0x004EA'i32, 501,
+    0x004EC'i32, 501,
+    0x004EE'i32, 501,
+    0x004F0'i32, 501,
+    0x004F2'i32, 501,
+    0x004F4'i32, 501,
+    0x004F6'i32, 501,
+    0x004F8'i32, 501,
+    0x004FA'i32, 501,
+    0x004FC'i32, 501,
+    0x004FE'i32, 501,
+    0x00500'i32, 501,
+    0x00502'i32, 501,
+    0x00504'i32, 501,
+    0x00506'i32, 501,
+    0x00508'i32, 501,
+    0x0050A'i32, 501,
+    0x0050C'i32, 501,
+    0x0050E'i32, 501,
+    0x00510'i32, 501,
+    0x00512'i32, 501,
+    0x00514'i32, 501,
+    0x00516'i32, 501,
+    0x00518'i32, 501,
+    0x0051A'i32, 501,
+    0x0051C'i32, 501,
+    0x0051E'i32, 501,
+    0x00520'i32, 501,
+    0x00522'i32, 501,
+    0x00524'i32, 501,
+    0x00526'i32, 501,
+    0x00528'i32, 501,
+    0x0052A'i32, 501,
+    0x0052C'i32, 501,
+    0x0052E'i32, 501,
+    0x010C7'i32, 7764,
+    0x010CD'i32, 7764,
+    0x01E00'i32, 501,
+    0x01E02'i32, 501,
+    0x01E04'i32, 501,
+    0x01E06'i32, 501,
+    0x01E08'i32, 501,
+    0x01E0A'i32, 501,
+    0x01E0C'i32, 501,
+    0x01E0E'i32, 501,
+    0x01E10'i32, 501,
+    0x01E12'i32, 501,
+    0x01E14'i32, 501,
+    0x01E16'i32, 501,
+    0x01E18'i32, 501,
+    0x01E1A'i32, 501,
+    0x01E1C'i32, 501,
+    0x01E1E'i32, 501,
+    0x01E20'i32, 501,
+    0x01E22'i32, 501,
+    0x01E24'i32, 501,
+    0x01E26'i32, 501,
+    0x01E28'i32, 501,
+    0x01E2A'i32, 501,
+    0x01E2C'i32, 501,
+    0x01E2E'i32, 501,
+    0x01E30'i32, 501,
+    0x01E32'i32, 501,
+    0x01E34'i32, 501,
+    0x01E36'i32, 501,
+    0x01E38'i32, 501,
+    0x01E3A'i32, 501,
+    0x01E3C'i32, 501,
+    0x01E3E'i32, 501,
+    0x01E40'i32, 501,
+    0x01E42'i32, 501,
+    0x01E44'i32, 501,
+    0x01E46'i32, 501,
+    0x01E48'i32, 501,
+    0x01E4A'i32, 501,
+    0x01E4C'i32, 501,
+    0x01E4E'i32, 501,
+    0x01E50'i32, 501,
+    0x01E52'i32, 501,
+    0x01E54'i32, 501,
+    0x01E56'i32, 501,
+    0x01E58'i32, 501,
+    0x01E5A'i32, 501,
+    0x01E5C'i32, 501,
+    0x01E5E'i32, 501,
+    0x01E60'i32, 501,
+    0x01E62'i32, 501,
+    0x01E64'i32, 501,
+    0x01E66'i32, 501,
+    0x01E68'i32, 501,
+    0x01E6A'i32, 501,
+    0x01E6C'i32, 501,
+    0x01E6E'i32, 501,
+    0x01E70'i32, 501,
+    0x01E72'i32, 501,
+    0x01E74'i32, 501,
+    0x01E76'i32, 501,
+    0x01E78'i32, 501,
+    0x01E7A'i32, 501,
+    0x01E7C'i32, 501,
+    0x01E7E'i32, 501,
+    0x01E80'i32, 501,
+    0x01E82'i32, 501,
+    0x01E84'i32, 501,
+    0x01E86'i32, 501,
+    0x01E88'i32, 501,
+    0x01E8A'i32, 501,
+    0x01E8C'i32, 501,
+    0x01E8E'i32, 501,
+    0x01E90'i32, 501,
+    0x01E92'i32, 501,
+    0x01E94'i32, 501,
+    0x01E9E'i32, -7115,
+    0x01EA0'i32, 501,
+    0x01EA2'i32, 501,
+    0x01EA4'i32, 501,
+    0x01EA6'i32, 501,
+    0x01EA8'i32, 501,
+    0x01EAA'i32, 501,
+    0x01EAC'i32, 501,
+    0x01EAE'i32, 501,
+    0x01EB0'i32, 501,
+    0x01EB2'i32, 501,
+    0x01EB4'i32, 501,
+    0x01EB6'i32, 501,
+    0x01EB8'i32, 501,
+    0x01EBA'i32, 501,
+    0x01EBC'i32, 501,
+    0x01EBE'i32, 501,
+    0x01EC0'i32, 501,
+    0x01EC2'i32, 501,
+    0x01EC4'i32, 501,
+    0x01EC6'i32, 501,
+    0x01EC8'i32, 501,
+    0x01ECA'i32, 501,
+    0x01ECC'i32, 501,
+    0x01ECE'i32, 501,
+    0x01ED0'i32, 501,
+    0x01ED2'i32, 501,
+    0x01ED4'i32, 501,
+    0x01ED6'i32, 501,
+    0x01ED8'i32, 501,
+    0x01EDA'i32, 501,
+    0x01EDC'i32, 501,
+    0x01EDE'i32, 501,
+    0x01EE0'i32, 501,
+    0x01EE2'i32, 501,
+    0x01EE4'i32, 501,
+    0x01EE6'i32, 501,
+    0x01EE8'i32, 501,
+    0x01EEA'i32, 501,
+    0x01EEC'i32, 501,
+    0x01EEE'i32, 501,
+    0x01EF0'i32, 501,
+    0x01EF2'i32, 501,
+    0x01EF4'i32, 501,
+    0x01EF6'i32, 501,
+    0x01EF8'i32, 501,
+    0x01EFA'i32, 501,
+    0x01EFC'i32, 501,
+    0x01EFE'i32, 501,
+    0x01F59'i32, 492,
+    0x01F5B'i32, 492,
+    0x01F5D'i32, 492,
+    0x01F5F'i32, 492,
+    0x01FBC'i32, 491,
+    0x01FCC'i32, 491,
+    0x01FEC'i32, 493,
+    0x01FFC'i32, 491,
+    0x02126'i32, -7017,
+    0x0212A'i32, -7883,
+    0x0212B'i32, -7762,
+    0x02132'i32, 528,
+    0x02183'i32, 501,
+    0x02C60'i32, 501,
+    0x02C62'i32, -10243,
+    0x02C63'i32, -3314,
+    0x02C64'i32, -10227,
+    0x02C67'i32, 501,
+    0x02C69'i32, 501,
+    0x02C6B'i32, 501,
+    0x02C6D'i32, -10280,
+    0x02C6E'i32, -10249,
+    0x02C6F'i32, -10283,
+    0x02C70'i32, -10282,
+    0x02C72'i32, 501,
+    0x02C75'i32, 501,
+    0x02C80'i32, 501,
+    0x02C82'i32, 501,
+    0x02C84'i32, 501,
+    0x02C86'i32, 501,
+    0x02C88'i32, 501,
+    0x02C8A'i32, 501,
+    0x02C8C'i32, 501,
+    0x02C8E'i32, 501,
+    0x02C90'i32, 501,
+    0x02C92'i32, 501,
+    0x02C94'i32, 501,
+    0x02C96'i32, 501,
+    0x02C98'i32, 501,
+    0x02C9A'i32, 501,
+    0x02C9C'i32, 501,
+    0x02C9E'i32, 501,
+    0x02CA0'i32, 501,
+    0x02CA2'i32, 501,
+    0x02CA4'i32, 501,
+    0x02CA6'i32, 501,
+    0x02CA8'i32, 501,
+    0x02CAA'i32, 501,
+    0x02CAC'i32, 501,
+    0x02CAE'i32, 501,
+    0x02CB0'i32, 501,
+    0x02CB2'i32, 501,
+    0x02CB4'i32, 501,
+    0x02CB6'i32, 501,
+    0x02CB8'i32, 501,
+    0x02CBA'i32, 501,
+    0x02CBC'i32, 501,
+    0x02CBE'i32, 501,
+    0x02CC0'i32, 501,
+    0x02CC2'i32, 501,
+    0x02CC4'i32, 501,
+    0x02CC6'i32, 501,
+    0x02CC8'i32, 501,
+    0x02CCA'i32, 501,
+    0x02CCC'i32, 501,
+    0x02CCE'i32, 501,
+    0x02CD0'i32, 501,
+    0x02CD2'i32, 501,
+    0x02CD4'i32, 501,
+    0x02CD6'i32, 501,
+    0x02CD8'i32, 501,
+    0x02CDA'i32, 501,
+    0x02CDC'i32, 501,
+    0x02CDE'i32, 501,
+    0x02CE0'i32, 501,
+    0x02CE2'i32, 501,
+    0x02CEB'i32, 501,
+    0x02CED'i32, 501,
+    0x02CF2'i32, 501,
+    0x0A640'i32, 501,
+    0x0A642'i32, 501,
+    0x0A644'i32, 501,
+    0x0A646'i32, 501,
+    0x0A648'i32, 501,
+    0x0A64A'i32, 501,
+    0x0A64C'i32, 501,
+    0x0A64E'i32, 501,
+    0x0A650'i32, 501,
+    0x0A652'i32, 501,
+    0x0A654'i32, 501,
+    0x0A656'i32, 501,
+    0x0A658'i32, 501,
+    0x0A65A'i32, 501,
+    0x0A65C'i32, 501,
+    0x0A65E'i32, 501,
+    0x0A660'i32, 501,
+    0x0A662'i32, 501,
+    0x0A664'i32, 501,
+    0x0A666'i32, 501,
+    0x0A668'i32, 501,
+    0x0A66A'i32, 501,
+    0x0A66C'i32, 501,
+    0x0A680'i32, 501,
+    0x0A682'i32, 501,
+    0x0A684'i32, 501,
+    0x0A686'i32, 501,
+    0x0A688'i32, 501,
+    0x0A68A'i32, 501,
+    0x0A68C'i32, 501,
+    0x0A68E'i32, 501,
+    0x0A690'i32, 501,
+    0x0A692'i32, 501,
+    0x0A694'i32, 501,
+    0x0A696'i32, 501,
+    0x0A698'i32, 501,
+    0x0A69A'i32, 501,
+    0x0A722'i32, 501,
+    0x0A724'i32, 501,
+    0x0A726'i32, 501,
+    0x0A728'i32, 501,
+    0x0A72A'i32, 501,
+    0x0A72C'i32, 501,
+    0x0A72E'i32, 501,
+    0x0A732'i32, 501,
+    0x0A734'i32, 501,
+    0x0A736'i32, 501,
+    0x0A738'i32, 501,
+    0x0A73A'i32, 501,
+    0x0A73C'i32, 501,
+    0x0A73E'i32, 501,
+    0x0A740'i32, 501,
+    0x0A742'i32, 501,
+    0x0A744'i32, 501,
+    0x0A746'i32, 501,
+    0x0A748'i32, 501,
+    0x0A74A'i32, 501,
+    0x0A74C'i32, 501,
+    0x0A74E'i32, 501,
+    0x0A750'i32, 501,
+    0x0A752'i32, 501,
+    0x0A754'i32, 501,
+    0x0A756'i32, 501,
+    0x0A758'i32, 501,
+    0x0A75A'i32, 501,
+    0x0A75C'i32, 501,
+    0x0A75E'i32, 501,
+    0x0A760'i32, 501,
+    0x0A762'i32, 501,
+    0x0A764'i32, 501,
+    0x0A766'i32, 501,
+    0x0A768'i32, 501,
+    0x0A76A'i32, 501,
+    0x0A76C'i32, 501,
+    0x0A76E'i32, 501,
+    0x0A779'i32, 501,
+    0x0A77B'i32, 501,
+    0x0A77D'i32, -34832,
+    0x0A77E'i32, 501,
+    0x0A780'i32, 501,
+    0x0A782'i32, 501,
+    0x0A784'i32, 501,
+    0x0A786'i32, 501,
+    0x0A78B'i32, 501,
+    0x0A78D'i32, -41780,
+    0x0A790'i32, 501,
+    0x0A792'i32, 501,
+    0x0A796'i32, 501,
+    0x0A798'i32, 501,
+    0x0A79A'i32, 501,
+    0x0A79C'i32, 501,
+    0x0A79E'i32, 501,
+    0x0A7A0'i32, 501,
+    0x0A7A2'i32, 501,
+    0x0A7A4'i32, 501,
+    0x0A7A6'i32, 501,
+    0x0A7A8'i32, 501,
+    0x0A7AA'i32, -41808,
+    0x0A7AB'i32, -41819,
+    0x0A7AC'i32, -41815,
+    0x0A7AD'i32, -41805,
+    0x0A7AE'i32, -41808,
+    0x0A7B0'i32, -41758,
+    0x0A7B1'i32, -41782,
+    0x0A7B2'i32, -41761,
+    0x0A7B3'i32, 1428,
+    0x0A7B4'i32, 501,
+    0x0A7B6'i32, 501,
+    0x0A7B8'i32, 501,
+    0x0A7BA'i32, 501,
+    0x0A7BC'i32, 501,
+    0x0A7BE'i32, 501,
+    0x0A7C2'i32, 501,
+    0x0A7C4'i32, 452,
+    0x0A7C5'i32, -41807,
+    0x0A7C6'i32, -34884,
   ]
 
   toUpperRanges = [
-    0x00061, 0x0007A, 468,
-    0x000E0, 0x000F6, 468,
-    0x000F8, 0x000FE, 468,
-    0x0023F, 0x00240, 11315,
-    0x00256, 0x00257, 295,
-    0x0028A, 0x0028B, 283,
-    0x0037B, 0x0037D, 630,
-    0x003AD, 0x003AF, 463,
-    0x003B1, 0x003C1, 468,
-    0x003C3, 0x003CB, 468,
-    0x003CD, 0x003CE, 437,
-    0x00430, 0x0044F, 468,
-    0x00450, 0x0045F, 420,
-    0x00561, 0x00586, 452,
-    0x010D0, 0x010FA, 3508,
-    0x010FD, 0x010FF, 3508,
-    0x013F8, 0x013FD, 492,
-    0x01C83, 0x01C84, -5742,
-    0x01F00, 0x01F07, 508,
-    0x01F10, 0x01F15, 508,
-    0x01F20, 0x01F27, 508,
-    0x01F30, 0x01F37, 508,
-    0x01F40, 0x01F45, 508,
-    0x01F60, 0x01F67, 508,
-    0x01F70, 0x01F71, 574,
-    0x01F72, 0x01F75, 586,
-    0x01F76, 0x01F77, 600,
-    0x01F78, 0x01F79, 628,
-    0x01F7A, 0x01F7B, 612,
-    0x01F7C, 0x01F7D, 626,
-    0x01F80, 0x01F87, 508,
-    0x01F90, 0x01F97, 508,
-    0x01FA0, 0x01FA7, 508,
-    0x01FB0, 0x01FB1, 508,
-    0x01FD0, 0x01FD1, 508,
-    0x01FE0, 0x01FE1, 508,
-    0x02C30, 0x02C5E, 452,
-    0x02D00, 0x02D25, -6764,
-    0x0AB70, 0x0ABBF, -38364,
-    0x0FF41, 0x0FF5A, 468,
-    0x10428, 0x1044F, 460,
-    0x104D8, 0x104FB, 460,
-    0x10CC0, 0x10CF2, 436,
-    0x118C0, 0x118DF, 468,
-    0x16E60, 0x16E7F, 468,
-    0x1E922, 0x1E943, 466,
+    0x00061'i32, 0x0007A'i32, 468,
+    0x000E0'i32, 0x000F6'i32, 468,
+    0x000F8'i32, 0x000FE'i32, 468,
+    0x0023F'i32, 0x00240'i32, 11315,
+    0x00256'i32, 0x00257'i32, 295,
+    0x0028A'i32, 0x0028B'i32, 283,
+    0x0037B'i32, 0x0037D'i32, 630,
+    0x003AD'i32, 0x003AF'i32, 463,
+    0x003B1'i32, 0x003C1'i32, 468,
+    0x003C3'i32, 0x003CB'i32, 468,
+    0x003CD'i32, 0x003CE'i32, 437,
+    0x00430'i32, 0x0044F'i32, 468,
+    0x00450'i32, 0x0045F'i32, 420,
+    0x00561'i32, 0x00586'i32, 452,
+    0x010D0'i32, 0x010FA'i32, 3508,
+    0x010FD'i32, 0x010FF'i32, 3508,
+    0x013F8'i32, 0x013FD'i32, 492,
+    0x01C83'i32, 0x01C84'i32, -5742,
+    0x01F00'i32, 0x01F07'i32, 508,
+    0x01F10'i32, 0x01F15'i32, 508,
+    0x01F20'i32, 0x01F27'i32, 508,
+    0x01F30'i32, 0x01F37'i32, 508,
+    0x01F40'i32, 0x01F45'i32, 508,
+    0x01F60'i32, 0x01F67'i32, 508,
+    0x01F70'i32, 0x01F71'i32, 574,
+    0x01F72'i32, 0x01F75'i32, 586,
+    0x01F76'i32, 0x01F77'i32, 600,
+    0x01F78'i32, 0x01F79'i32, 628,
+    0x01F7A'i32, 0x01F7B'i32, 612,
+    0x01F7C'i32, 0x01F7D'i32, 626,
+    0x01F80'i32, 0x01F87'i32, 508,
+    0x01F90'i32, 0x01F97'i32, 508,
+    0x01FA0'i32, 0x01FA7'i32, 508,
+    0x01FB0'i32, 0x01FB1'i32, 508,
+    0x01FD0'i32, 0x01FD1'i32, 508,
+    0x01FE0'i32, 0x01FE1'i32, 508,
+    0x02C30'i32, 0x02C5E'i32, 452,
+    0x02D00'i32, 0x02D25'i32, -6764,
+    0x0AB70'i32, 0x0ABBF'i32, -38364,
+    0x0FF41'i32, 0x0FF5A'i32, 468,
+    0x10428'i32, 0x1044F'i32, 460,
+    0x104D8'i32, 0x104FB'i32, 460,
+    0x10CC0'i32, 0x10CF2'i32, 436,
+    0x118C0'i32, 0x118DF'i32, 468,
+    0x16E60'i32, 0x16E7F'i32, 468,
+    0x1E922'i32, 0x1E943'i32, 466,
   ]
 
   toUpperSinglets = [
-    0x000B5, 1243,
-    0x000FF, 621,
-    0x00101, 499,
-    0x00103, 499,
-    0x00105, 499,
-    0x00107, 499,
-    0x00109, 499,
-    0x0010B, 499,
-    0x0010D, 499,
-    0x0010F, 499,
-    0x00111, 499,
-    0x00113, 499,
-    0x00115, 499,
-    0x00117, 499,
-    0x00119, 499,
-    0x0011B, 499,
-    0x0011D, 499,
-    0x0011F, 499,
-    0x00121, 499,
-    0x00123, 499,
-    0x00125, 499,
-    0x00127, 499,
-    0x00129, 499,
-    0x0012B, 499,
-    0x0012D, 499,
-    0x0012F, 499,
-    0x00131, 268,
-    0x00133, 499,
-    0x00135, 499,
-    0x00137, 499,
-    0x0013A, 499,
-    0x0013C, 499,
-    0x0013E, 499,
-    0x00140, 499,
-    0x00142, 499,
-    0x00144, 499,
-    0x00146, 499,
-    0x00148, 499,
-    0x0014B, 499,
-    0x0014D, 499,
-    0x0014F, 499,
-    0x00151, 499,
-    0x00153, 499,
-    0x00155, 499,
-    0x00157, 499,
-    0x00159, 499,
-    0x0015B, 499,
-    0x0015D, 499,
-    0x0015F, 499,
-    0x00161, 499,
-    0x00163, 499,
-    0x00165, 499,
-    0x00167, 499,
-    0x00169, 499,
-    0x0016B, 499,
-    0x0016D, 499,
-    0x0016F, 499,
-    0x00171, 499,
-    0x00173, 499,
-    0x00175, 499,
-    0x00177, 499,
-    0x0017A, 499,
-    0x0017C, 499,
-    0x0017E, 499,
-    0x0017F, 200,
-    0x00180, 695,
-    0x00183, 499,
-    0x00185, 499,
-    0x00188, 499,
-    0x0018C, 499,
-    0x00192, 499,
-    0x00195, 597,
-    0x00199, 499,
-    0x0019A, 663,
-    0x0019E, 630,
-    0x001A1, 499,
-    0x001A3, 499,
-    0x001A5, 499,
-    0x001A8, 499,
-    0x001AD, 499,
-    0x001B0, 499,
-    0x001B4, 499,
-    0x001B6, 499,
-    0x001B9, 499,
-    0x001BD, 499,
-    0x001BF, 556,
-    0x001C5, 499,
-    0x001C6, 498,
-    0x001C8, 499,
-    0x001C9, 498,
-    0x001CB, 499,
-    0x001CC, 498,
-    0x001CE, 499,
-    0x001D0, 499,
-    0x001D2, 499,
-    0x001D4, 499,
-    0x001D6, 499,
-    0x001D8, 499,
-    0x001DA, 499,
-    0x001DC, 499,
-    0x001DD, 421,
-    0x001DF, 499,
-    0x001E1, 499,
-    0x001E3, 499,
-    0x001E5, 499,
-    0x001E7, 499,
-    0x001E9, 499,
-    0x001EB, 499,
-    0x001ED, 499,
-    0x001EF, 499,
-    0x001F2, 499,
-    0x001F3, 498,
-    0x001F5, 499,
-    0x001F9, 499,
-    0x001FB, 499,
-    0x001FD, 499,
-    0x001FF, 499,
-    0x00201, 499,
-    0x00203, 499,
-    0x00205, 499,
-    0x00207, 499,
-    0x00209, 499,
-    0x0020B, 499,
-    0x0020D, 499,
-    0x0020F, 499,
-    0x00211, 499,
-    0x00213, 499,
-    0x00215, 499,
-    0x00217, 499,
-    0x00219, 499,
-    0x0021B, 499,
-    0x0021D, 499,
-    0x0021F, 499,
-    0x00223, 499,
-    0x00225, 499,
-    0x00227, 499,
-    0x00229, 499,
-    0x0022B, 499,
-    0x0022D, 499,
-    0x0022F, 499,
-    0x00231, 499,
-    0x00233, 499,
-    0x0023C, 499,
-    0x00242, 499,
-    0x00247, 499,
-    0x00249, 499,
-    0x0024B, 499,
-    0x0024D, 499,
-    0x0024F, 499,
-    0x00250, 11283,
-    0x00251, 11280,
-    0x00252, 11282,
-    0x00253, 290,
-    0x00254, 294,
-    0x00259, 298,
-    0x0025B, 297,
-    0x0025C, 42819,
-    0x00260, 295,
-    0x00261, 42815,
-    0x00263, 293,
-    0x00265, 42780,
-    0x00266, 42808,
-    0x00268, 291,
-    0x00269, 289,
-    0x0026A, 42808,
-    0x0026B, 11243,
-    0x0026C, 42805,
-    0x0026F, 289,
-    0x00271, 11249,
-    0x00272, 287,
-    0x00275, 286,
-    0x0027D, 11227,
-    0x00280, 282,
-    0x00282, 42807,
-    0x00283, 282,
-    0x00287, 42782,
-    0x00288, 282,
-    0x00289, 431,
-    0x0028C, 429,
-    0x00292, 281,
-    0x0029D, 42761,
-    0x0029E, 42758,
-    0x00371, 499,
-    0x00373, 499,
-    0x00377, 499,
-    0x003AC, 462,
-    0x003C2, 469,
-    0x003CC, 436,
-    0x003D0, 438,
-    0x003D1, 443,
-    0x003D5, 453,
-    0x003D6, 446,
-    0x003D7, 492,
-    0x003D9, 499,
-    0x003DB, 499,
-    0x003DD, 499,
-    0x003DF, 499,
-    0x003E1, 499,
-    0x003E3, 499,
-    0x003E5, 499,
-    0x003E7, 499,
-    0x003E9, 499,
-    0x003EB, 499,
-    0x003ED, 499,
-    0x003EF, 499,
-    0x003F0, 414,
-    0x003F1, 420,
-    0x003F2, 507,
-    0x003F3, 384,
-    0x003F5, 404,
-    0x003F8, 499,
-    0x003FB, 499,
-    0x00461, 499,
-    0x00463, 499,
-    0x00465, 499,
-    0x00467, 499,
-    0x00469, 499,
-    0x0046B, 499,
-    0x0046D, 499,
-    0x0046F, 499,
-    0x00471, 499,
-    0x00473, 499,
-    0x00475, 499,
-    0x00477, 499,
-    0x00479, 499,
-    0x0047B, 499,
-    0x0047D, 499,
-    0x0047F, 499,
-    0x00481, 499,
-    0x0048B, 499,
-    0x0048D, 499,
-    0x0048F, 499,
-    0x00491, 499,
-    0x00493, 499,
-    0x00495, 499,
-    0x00497, 499,
-    0x00499, 499,
-    0x0049B, 499,
-    0x0049D, 499,
-    0x0049F, 499,
-    0x004A1, 499,
-    0x004A3, 499,
-    0x004A5, 499,
-    0x004A7, 499,
-    0x004A9, 499,
-    0x004AB, 499,
-    0x004AD, 499,
-    0x004AF, 499,
-    0x004B1, 499,
-    0x004B3, 499,
-    0x004B5, 499,
-    0x004B7, 499,
-    0x004B9, 499,
-    0x004BB, 499,
-    0x004BD, 499,
-    0x004BF, 499,
-    0x004C2, 499,
-    0x004C4, 499,
-    0x004C6, 499,
-    0x004C8, 499,
-    0x004CA, 499,
-    0x004CC, 499,
-    0x004CE, 499,
-    0x004CF, 485,
-    0x004D1, 499,
-    0x004D3, 499,
-    0x004D5, 499,
-    0x004D7, 499,
-    0x004D9, 499,
-    0x004DB, 499,
-    0x004DD, 499,
-    0x004DF, 499,
-    0x004E1, 499,
-    0x004E3, 499,
-    0x004E5, 499,
-    0x004E7, 499,
-    0x004E9, 499,
-    0x004EB, 499,
-    0x004ED, 499,
-    0x004EF, 499,
-    0x004F1, 499,
-    0x004F3, 499,
-    0x004F5, 499,
-    0x004F7, 499,
-    0x004F9, 499,
-    0x004FB, 499,
-    0x004FD, 499,
-    0x004FF, 499,
-    0x00501, 499,
-    0x00503, 499,
-    0x00505, 499,
-    0x00507, 499,
-    0x00509, 499,
-    0x0050B, 499,
-    0x0050D, 499,
-    0x0050F, 499,
-    0x00511, 499,
-    0x00513, 499,
-    0x00515, 499,
-    0x00517, 499,
-    0x00519, 499,
-    0x0051B, 499,
-    0x0051D, 499,
-    0x0051F, 499,
-    0x00521, 499,
-    0x00523, 499,
-    0x00525, 499,
-    0x00527, 499,
-    0x00529, 499,
-    0x0052B, 499,
-    0x0052D, 499,
-    0x0052F, 499,
-    0x01C80, -5754,
-    0x01C81, -5753,
-    0x01C82, -5744,
-    0x01C85, -5743,
-    0x01C86, -5736,
-    0x01C87, -5681,
-    0x01C88, 35766,
-    0x01D79, 35832,
-    0x01D7D, 4314,
-    0x01D8E, 35884,
-    0x01E01, 499,
-    0x01E03, 499,
-    0x01E05, 499,
-    0x01E07, 499,
-    0x01E09, 499,
-    0x01E0B, 499,
-    0x01E0D, 499,
-    0x01E0F, 499,
-    0x01E11, 499,
-    0x01E13, 499,
-    0x01E15, 499,
-    0x01E17, 499,
-    0x01E19, 499,
-    0x01E1B, 499,
-    0x01E1D, 499,
-    0x01E1F, 499,
-    0x01E21, 499,
-    0x01E23, 499,
-    0x01E25, 499,
-    0x01E27, 499,
-    0x01E29, 499,
-    0x01E2B, 499,
-    0x01E2D, 499,
-    0x01E2F, 499,
-    0x01E31, 499,
-    0x01E33, 499,
-    0x01E35, 499,
-    0x01E37, 499,
-    0x01E39, 499,
-    0x01E3B, 499,
-    0x01E3D, 499,
-    0x01E3F, 499,
-    0x01E41, 499,
-    0x01E43, 499,
-    0x01E45, 499,
-    0x01E47, 499,
-    0x01E49, 499,
-    0x01E4B, 499,
-    0x01E4D, 499,
-    0x01E4F, 499,
-    0x01E51, 499,
-    0x01E53, 499,
-    0x01E55, 499,
-    0x01E57, 499,
-    0x01E59, 499,
-    0x01E5B, 499,
-    0x01E5D, 499,
-    0x01E5F, 499,
-    0x01E61, 499,
-    0x01E63, 499,
-    0x01E65, 499,
-    0x01E67, 499,
-    0x01E69, 499,
-    0x01E6B, 499,
-    0x01E6D, 499,
-    0x01E6F, 499,
-    0x01E71, 499,
-    0x01E73, 499,
-    0x01E75, 499,
-    0x01E77, 499,
-    0x01E79, 499,
-    0x01E7B, 499,
-    0x01E7D, 499,
-    0x01E7F, 499,
-    0x01E81, 499,
-    0x01E83, 499,
-    0x01E85, 499,
-    0x01E87, 499,
-    0x01E89, 499,
-    0x01E8B, 499,
-    0x01E8D, 499,
-    0x01E8F, 499,
-    0x01E91, 499,
-    0x01E93, 499,
-    0x01E95, 499,
-    0x01E9B, 441,
-    0x01EA1, 499,
-    0x01EA3, 499,
-    0x01EA5, 499,
-    0x01EA7, 499,
-    0x01EA9, 499,
-    0x01EAB, 499,
-    0x01EAD, 499,
-    0x01EAF, 499,
-    0x01EB1, 499,
-    0x01EB3, 499,
-    0x01EB5, 499,
-    0x01EB7, 499,
-    0x01EB9, 499,
-    0x01EBB, 499,
-    0x01EBD, 499,
-    0x01EBF, 499,
-    0x01EC1, 499,
-    0x01EC3, 499,
-    0x01EC5, 499,
-    0x01EC7, 499,
-    0x01EC9, 499,
-    0x01ECB, 499,
-    0x01ECD, 499,
-    0x01ECF, 499,
-    0x01ED1, 499,
-    0x01ED3, 499,
-    0x01ED5, 499,
-    0x01ED7, 499,
-    0x01ED9, 499,
-    0x01EDB, 499,
-    0x01EDD, 499,
-    0x01EDF, 499,
-    0x01EE1, 499,
-    0x01EE3, 499,
-    0x01EE5, 499,
-    0x01EE7, 499,
-    0x01EE9, 499,
-    0x01EEB, 499,
-    0x01EED, 499,
-    0x01EEF, 499,
-    0x01EF1, 499,
-    0x01EF3, 499,
-    0x01EF5, 499,
-    0x01EF7, 499,
-    0x01EF9, 499,
-    0x01EFB, 499,
-    0x01EFD, 499,
-    0x01EFF, 499,
-    0x01F51, 508,
-    0x01F53, 508,
-    0x01F55, 508,
-    0x01F57, 508,
-    0x01FB3, 509,
-    0x01FBE, -6705,
-    0x01FC3, 509,
-    0x01FE5, 507,
-    0x01FF3, 509,
-    0x0214E, 472,
-    0x02184, 499,
-    0x02C61, 499,
-    0x02C65, -10295,
-    0x02C66, -10292,
-    0x02C68, 499,
-    0x02C6A, 499,
-    0x02C6C, 499,
-    0x02C73, 499,
-    0x02C76, 499,
-    0x02C81, 499,
-    0x02C83, 499,
-    0x02C85, 499,
-    0x02C87, 499,
-    0x02C89, 499,
-    0x02C8B, 499,
-    0x02C8D, 499,
-    0x02C8F, 499,
-    0x02C91, 499,
-    0x02C93, 499,
-    0x02C95, 499,
-    0x02C97, 499,
-    0x02C99, 499,
-    0x02C9B, 499,
-    0x02C9D, 499,
-    0x02C9F, 499,
-    0x02CA1, 499,
-    0x02CA3, 499,
-    0x02CA5, 499,
-    0x02CA7, 499,
-    0x02CA9, 499,
-    0x02CAB, 499,
-    0x02CAD, 499,
-    0x02CAF, 499,
-    0x02CB1, 499,
-    0x02CB3, 499,
-    0x02CB5, 499,
-    0x02CB7, 499,
-    0x02CB9, 499,
-    0x02CBB, 499,
-    0x02CBD, 499,
-    0x02CBF, 499,
-    0x02CC1, 499,
-    0x02CC3, 499,
-    0x02CC5, 499,
-    0x02CC7, 499,
-    0x02CC9, 499,
-    0x02CCB, 499,
-    0x02CCD, 499,
-    0x02CCF, 499,
-    0x02CD1, 499,
-    0x02CD3, 499,
-    0x02CD5, 499,
-    0x02CD7, 499,
-    0x02CD9, 499,
-    0x02CDB, 499,
-    0x02CDD, 499,
-    0x02CDF, 499,
-    0x02CE1, 499,
-    0x02CE3, 499,
-    0x02CEC, 499,
-    0x02CEE, 499,
-    0x02CF3, 499,
-    0x02D27, -6764,
-    0x02D2D, -6764,
-    0x0A641, 499,
-    0x0A643, 499,
-    0x0A645, 499,
-    0x0A647, 499,
-    0x0A649, 499,
-    0x0A64B, 499,
-    0x0A64D, 499,
-    0x0A64F, 499,
-    0x0A651, 499,
-    0x0A653, 499,
-    0x0A655, 499,
-    0x0A657, 499,
-    0x0A659, 499,
-    0x0A65B, 499,
-    0x0A65D, 499,
-    0x0A65F, 499,
-    0x0A661, 499,
-    0x0A663, 499,
-    0x0A665, 499,
-    0x0A667, 499,
-    0x0A669, 499,
-    0x0A66B, 499,
-    0x0A66D, 499,
-    0x0A681, 499,
-    0x0A683, 499,
-    0x0A685, 499,
-    0x0A687, 499,
-    0x0A689, 499,
-    0x0A68B, 499,
-    0x0A68D, 499,
-    0x0A68F, 499,
-    0x0A691, 499,
-    0x0A693, 499,
-    0x0A695, 499,
-    0x0A697, 499,
-    0x0A699, 499,
-    0x0A69B, 499,
-    0x0A723, 499,
-    0x0A725, 499,
-    0x0A727, 499,
-    0x0A729, 499,
-    0x0A72B, 499,
-    0x0A72D, 499,
-    0x0A72F, 499,
-    0x0A733, 499,
-    0x0A735, 499,
-    0x0A737, 499,
-    0x0A739, 499,
-    0x0A73B, 499,
-    0x0A73D, 499,
-    0x0A73F, 499,
-    0x0A741, 499,
-    0x0A743, 499,
-    0x0A745, 499,
-    0x0A747, 499,
-    0x0A749, 499,
-    0x0A74B, 499,
-    0x0A74D, 499,
-    0x0A74F, 499,
-    0x0A751, 499,
-    0x0A753, 499,
-    0x0A755, 499,
-    0x0A757, 499,
-    0x0A759, 499,
-    0x0A75B, 499,
-    0x0A75D, 499,
-    0x0A75F, 499,
-    0x0A761, 499,
-    0x0A763, 499,
-    0x0A765, 499,
-    0x0A767, 499,
-    0x0A769, 499,
-    0x0A76B, 499,
-    0x0A76D, 499,
-    0x0A76F, 499,
-    0x0A77A, 499,
-    0x0A77C, 499,
-    0x0A77F, 499,
-    0x0A781, 499,
-    0x0A783, 499,
-    0x0A785, 499,
-    0x0A787, 499,
-    0x0A78C, 499,
-    0x0A791, 499,
-    0x0A793, 499,
-    0x0A794, 548,
-    0x0A797, 499,
-    0x0A799, 499,
-    0x0A79B, 499,
-    0x0A79D, 499,
-    0x0A79F, 499,
-    0x0A7A1, 499,
-    0x0A7A3, 499,
-    0x0A7A5, 499,
-    0x0A7A7, 499,
-    0x0A7A9, 499,
-    0x0A7B5, 499,
-    0x0A7B7, 499,
-    0x0A7B9, 499,
-    0x0A7BB, 499,
-    0x0A7BD, 499,
-    0x0A7BF, 499,
-    0x0A7C3, 499,
-    0x0AB53, -428,
+    0x000B5'i32, 1243,
+    0x000FF'i32, 621,
+    0x00101'i32, 499,
+    0x00103'i32, 499,
+    0x00105'i32, 499,
+    0x00107'i32, 499,
+    0x00109'i32, 499,
+    0x0010B'i32, 499,
+    0x0010D'i32, 499,
+    0x0010F'i32, 499,
+    0x00111'i32, 499,
+    0x00113'i32, 499,
+    0x00115'i32, 499,
+    0x00117'i32, 499,
+    0x00119'i32, 499,
+    0x0011B'i32, 499,
+    0x0011D'i32, 499,
+    0x0011F'i32, 499,
+    0x00121'i32, 499,
+    0x00123'i32, 499,
+    0x00125'i32, 499,
+    0x00127'i32, 499,
+    0x00129'i32, 499,
+    0x0012B'i32, 499,
+    0x0012D'i32, 499,
+    0x0012F'i32, 499,
+    0x00131'i32, 268,
+    0x00133'i32, 499,
+    0x00135'i32, 499,
+    0x00137'i32, 499,
+    0x0013A'i32, 499,
+    0x0013C'i32, 499,
+    0x0013E'i32, 499,
+    0x00140'i32, 499,
+    0x00142'i32, 499,
+    0x00144'i32, 499,
+    0x00146'i32, 499,
+    0x00148'i32, 499,
+    0x0014B'i32, 499,
+    0x0014D'i32, 499,
+    0x0014F'i32, 499,
+    0x00151'i32, 499,
+    0x00153'i32, 499,
+    0x00155'i32, 499,
+    0x00157'i32, 499,
+    0x00159'i32, 499,
+    0x0015B'i32, 499,
+    0x0015D'i32, 499,
+    0x0015F'i32, 499,
+    0x00161'i32, 499,
+    0x00163'i32, 499,
+    0x00165'i32, 499,
+    0x00167'i32, 499,
+    0x00169'i32, 499,
+    0x0016B'i32, 499,
+    0x0016D'i32, 499,
+    0x0016F'i32, 499,
+    0x00171'i32, 499,
+    0x00173'i32, 499,
+    0x00175'i32, 499,
+    0x00177'i32, 499,
+    0x0017A'i32, 499,
+    0x0017C'i32, 499,
+    0x0017E'i32, 499,
+    0x0017F'i32, 200,
+    0x00180'i32, 695,
+    0x00183'i32, 499,
+    0x00185'i32, 499,
+    0x00188'i32, 499,
+    0x0018C'i32, 499,
+    0x00192'i32, 499,
+    0x00195'i32, 597,
+    0x00199'i32, 499,
+    0x0019A'i32, 663,
+    0x0019E'i32, 630,
+    0x001A1'i32, 499,
+    0x001A3'i32, 499,
+    0x001A5'i32, 499,
+    0x001A8'i32, 499,
+    0x001AD'i32, 499,
+    0x001B0'i32, 499,
+    0x001B4'i32, 499,
+    0x001B6'i32, 499,
+    0x001B9'i32, 499,
+    0x001BD'i32, 499,
+    0x001BF'i32, 556,
+    0x001C5'i32, 499,
+    0x001C6'i32, 498,
+    0x001C8'i32, 499,
+    0x001C9'i32, 498,
+    0x001CB'i32, 499,
+    0x001CC'i32, 498,
+    0x001CE'i32, 499,
+    0x001D0'i32, 499,
+    0x001D2'i32, 499,
+    0x001D4'i32, 499,
+    0x001D6'i32, 499,
+    0x001D8'i32, 499,
+    0x001DA'i32, 499,
+    0x001DC'i32, 499,
+    0x001DD'i32, 421,
+    0x001DF'i32, 499,
+    0x001E1'i32, 499,
+    0x001E3'i32, 499,
+    0x001E5'i32, 499,
+    0x001E7'i32, 499,
+    0x001E9'i32, 499,
+    0x001EB'i32, 499,
+    0x001ED'i32, 499,
+    0x001EF'i32, 499,
+    0x001F2'i32, 499,
+    0x001F3'i32, 498,
+    0x001F5'i32, 499,
+    0x001F9'i32, 499,
+    0x001FB'i32, 499,
+    0x001FD'i32, 499,
+    0x001FF'i32, 499,
+    0x00201'i32, 499,
+    0x00203'i32, 499,
+    0x00205'i32, 499,
+    0x00207'i32, 499,
+    0x00209'i32, 499,
+    0x0020B'i32, 499,
+    0x0020D'i32, 499,
+    0x0020F'i32, 499,
+    0x00211'i32, 499,
+    0x00213'i32, 499,
+    0x00215'i32, 499,
+    0x00217'i32, 499,
+    0x00219'i32, 499,
+    0x0021B'i32, 499,
+    0x0021D'i32, 499,
+    0x0021F'i32, 499,
+    0x00223'i32, 499,
+    0x00225'i32, 499,
+    0x00227'i32, 499,
+    0x00229'i32, 499,
+    0x0022B'i32, 499,
+    0x0022D'i32, 499,
+    0x0022F'i32, 499,
+    0x00231'i32, 499,
+    0x00233'i32, 499,
+    0x0023C'i32, 499,
+    0x00242'i32, 499,
+    0x00247'i32, 499,
+    0x00249'i32, 499,
+    0x0024B'i32, 499,
+    0x0024D'i32, 499,
+    0x0024F'i32, 499,
+    0x00250'i32, 11283,
+    0x00251'i32, 11280,
+    0x00252'i32, 11282,
+    0x00253'i32, 290,
+    0x00254'i32, 294,
+    0x00259'i32, 298,
+    0x0025B'i32, 297,
+    0x0025C'i32, 42819,
+    0x00260'i32, 295,
+    0x00261'i32, 42815,
+    0x00263'i32, 293,
+    0x00265'i32, 42780,
+    0x00266'i32, 42808,
+    0x00268'i32, 291,
+    0x00269'i32, 289,
+    0x0026A'i32, 42808,
+    0x0026B'i32, 11243,
+    0x0026C'i32, 42805,
+    0x0026F'i32, 289,
+    0x00271'i32, 11249,
+    0x00272'i32, 287,
+    0x00275'i32, 286,
+    0x0027D'i32, 11227,
+    0x00280'i32, 282,
+    0x00282'i32, 42807,
+    0x00283'i32, 282,
+    0x00287'i32, 42782,
+    0x00288'i32, 282,
+    0x00289'i32, 431,
+    0x0028C'i32, 429,
+    0x00292'i32, 281,
+    0x0029D'i32, 42761,
+    0x0029E'i32, 42758,
+    0x00371'i32, 499,
+    0x00373'i32, 499,
+    0x00377'i32, 499,
+    0x003AC'i32, 462,
+    0x003C2'i32, 469,
+    0x003CC'i32, 436,
+    0x003D0'i32, 438,
+    0x003D1'i32, 443,
+    0x003D5'i32, 453,
+    0x003D6'i32, 446,
+    0x003D7'i32, 492,
+    0x003D9'i32, 499,
+    0x003DB'i32, 499,
+    0x003DD'i32, 499,
+    0x003DF'i32, 499,
+    0x003E1'i32, 499,
+    0x003E3'i32, 499,
+    0x003E5'i32, 499,
+    0x003E7'i32, 499,
+    0x003E9'i32, 499,
+    0x003EB'i32, 499,
+    0x003ED'i32, 499,
+    0x003EF'i32, 499,
+    0x003F0'i32, 414,
+    0x003F1'i32, 420,
+    0x003F2'i32, 507,
+    0x003F3'i32, 384,
+    0x003F5'i32, 404,
+    0x003F8'i32, 499,
+    0x003FB'i32, 499,
+    0x00461'i32, 499,
+    0x00463'i32, 499,
+    0x00465'i32, 499,
+    0x00467'i32, 499,
+    0x00469'i32, 499,
+    0x0046B'i32, 499,
+    0x0046D'i32, 499,
+    0x0046F'i32, 499,
+    0x00471'i32, 499,
+    0x00473'i32, 499,
+    0x00475'i32, 499,
+    0x00477'i32, 499,
+    0x00479'i32, 499,
+    0x0047B'i32, 499,
+    0x0047D'i32, 499,
+    0x0047F'i32, 499,
+    0x00481'i32, 499,
+    0x0048B'i32, 499,
+    0x0048D'i32, 499,
+    0x0048F'i32, 499,
+    0x00491'i32, 499,
+    0x00493'i32, 499,
+    0x00495'i32, 499,
+    0x00497'i32, 499,
+    0x00499'i32, 499,
+    0x0049B'i32, 499,
+    0x0049D'i32, 499,
+    0x0049F'i32, 499,
+    0x004A1'i32, 499,
+    0x004A3'i32, 499,
+    0x004A5'i32, 499,
+    0x004A7'i32, 499,
+    0x004A9'i32, 499,
+    0x004AB'i32, 499,
+    0x004AD'i32, 499,
+    0x004AF'i32, 499,
+    0x004B1'i32, 499,
+    0x004B3'i32, 499,
+    0x004B5'i32, 499,
+    0x004B7'i32, 499,
+    0x004B9'i32, 499,
+    0x004BB'i32, 499,
+    0x004BD'i32, 499,
+    0x004BF'i32, 499,
+    0x004C2'i32, 499,
+    0x004C4'i32, 499,
+    0x004C6'i32, 499,
+    0x004C8'i32, 499,
+    0x004CA'i32, 499,
+    0x004CC'i32, 499,
+    0x004CE'i32, 499,
+    0x004CF'i32, 485,
+    0x004D1'i32, 499,
+    0x004D3'i32, 499,
+    0x004D5'i32, 499,
+    0x004D7'i32, 499,
+    0x004D9'i32, 499,
+    0x004DB'i32, 499,
+    0x004DD'i32, 499,
+    0x004DF'i32, 499,
+    0x004E1'i32, 499,
+    0x004E3'i32, 499,
+    0x004E5'i32, 499,
+    0x004E7'i32, 499,
+    0x004E9'i32, 499,
+    0x004EB'i32, 499,
+    0x004ED'i32, 499,
+    0x004EF'i32, 499,
+    0x004F1'i32, 499,
+    0x004F3'i32, 499,
+    0x004F5'i32, 499,
+    0x004F7'i32, 499,
+    0x004F9'i32, 499,
+    0x004FB'i32, 499,
+    0x004FD'i32, 499,
+    0x004FF'i32, 499,
+    0x00501'i32, 499,
+    0x00503'i32, 499,
+    0x00505'i32, 499,
+    0x00507'i32, 499,
+    0x00509'i32, 499,
+    0x0050B'i32, 499,
+    0x0050D'i32, 499,
+    0x0050F'i32, 499,
+    0x00511'i32, 499,
+    0x00513'i32, 499,
+    0x00515'i32, 499,
+    0x00517'i32, 499,
+    0x00519'i32, 499,
+    0x0051B'i32, 499,
+    0x0051D'i32, 499,
+    0x0051F'i32, 499,
+    0x00521'i32, 499,
+    0x00523'i32, 499,
+    0x00525'i32, 499,
+    0x00527'i32, 499,
+    0x00529'i32, 499,
+    0x0052B'i32, 499,
+    0x0052D'i32, 499,
+    0x0052F'i32, 499,
+    0x01C80'i32, -5754,
+    0x01C81'i32, -5753,
+    0x01C82'i32, -5744,
+    0x01C85'i32, -5743,
+    0x01C86'i32, -5736,
+    0x01C87'i32, -5681,
+    0x01C88'i32, 35766,
+    0x01D79'i32, 35832,
+    0x01D7D'i32, 4314,
+    0x01D8E'i32, 35884,
+    0x01E01'i32, 499,
+    0x01E03'i32, 499,
+    0x01E05'i32, 499,
+    0x01E07'i32, 499,
+    0x01E09'i32, 499,
+    0x01E0B'i32, 499,
+    0x01E0D'i32, 499,
+    0x01E0F'i32, 499,
+    0x01E11'i32, 499,
+    0x01E13'i32, 499,
+    0x01E15'i32, 499,
+    0x01E17'i32, 499,
+    0x01E19'i32, 499,
+    0x01E1B'i32, 499,
+    0x01E1D'i32, 499,
+    0x01E1F'i32, 499,
+    0x01E21'i32, 499,
+    0x01E23'i32, 499,
+    0x01E25'i32, 499,
+    0x01E27'i32, 499,
+    0x01E29'i32, 499,
+    0x01E2B'i32, 499,
+    0x01E2D'i32, 499,
+    0x01E2F'i32, 499,
+    0x01E31'i32, 499,
+    0x01E33'i32, 499,
+    0x01E35'i32, 499,
+    0x01E37'i32, 499,
+    0x01E39'i32, 499,
+    0x01E3B'i32, 499,
+    0x01E3D'i32, 499,
+    0x01E3F'i32, 499,
+    0x01E41'i32, 499,
+    0x01E43'i32, 499,
+    0x01E45'i32, 499,
+    0x01E47'i32, 499,
+    0x01E49'i32, 499,
+    0x01E4B'i32, 499,
+    0x01E4D'i32, 499,
+    0x01E4F'i32, 499,
+    0x01E51'i32, 499,
+    0x01E53'i32, 499,
+    0x01E55'i32, 499,
+    0x01E57'i32, 499,
+    0x01E59'i32, 499,
+    0x01E5B'i32, 499,
+    0x01E5D'i32, 499,
+    0x01E5F'i32, 499,
+    0x01E61'i32, 499,
+    0x01E63'i32, 499,
+    0x01E65'i32, 499,
+    0x01E67'i32, 499,
+    0x01E69'i32, 499,
+    0x01E6B'i32, 499,
+    0x01E6D'i32, 499,
+    0x01E6F'i32, 499,
+    0x01E71'i32, 499,
+    0x01E73'i32, 499,
+    0x01E75'i32, 499,
+    0x01E77'i32, 499,
+    0x01E79'i32, 499,
+    0x01E7B'i32, 499,
+    0x01E7D'i32, 499,
+    0x01E7F'i32, 499,
+    0x01E81'i32, 499,
+    0x01E83'i32, 499,
+    0x01E85'i32, 499,
+    0x01E87'i32, 499,
+    0x01E89'i32, 499,
+    0x01E8B'i32, 499,
+    0x01E8D'i32, 499,
+    0x01E8F'i32, 499,
+    0x01E91'i32, 499,
+    0x01E93'i32, 499,
+    0x01E95'i32, 499,
+    0x01E9B'i32, 441,
+    0x01EA1'i32, 499,
+    0x01EA3'i32, 499,
+    0x01EA5'i32, 499,
+    0x01EA7'i32, 499,
+    0x01EA9'i32, 499,
+    0x01EAB'i32, 499,
+    0x01EAD'i32, 499,
+    0x01EAF'i32, 499,
+    0x01EB1'i32, 499,
+    0x01EB3'i32, 499,
+    0x01EB5'i32, 499,
+    0x01EB7'i32, 499,
+    0x01EB9'i32, 499,
+    0x01EBB'i32, 499,
+    0x01EBD'i32, 499,
+    0x01EBF'i32, 499,
+    0x01EC1'i32, 499,
+    0x01EC3'i32, 499,
+    0x01EC5'i32, 499,
+    0x01EC7'i32, 499,
+    0x01EC9'i32, 499,
+    0x01ECB'i32, 499,
+    0x01ECD'i32, 499,
+    0x01ECF'i32, 499,
+    0x01ED1'i32, 499,
+    0x01ED3'i32, 499,
+    0x01ED5'i32, 499,
+    0x01ED7'i32, 499,
+    0x01ED9'i32, 499,
+    0x01EDB'i32, 499,
+    0x01EDD'i32, 499,
+    0x01EDF'i32, 499,
+    0x01EE1'i32, 499,
+    0x01EE3'i32, 499,
+    0x01EE5'i32, 499,
+    0x01EE7'i32, 499,
+    0x01EE9'i32, 499,
+    0x01EEB'i32, 499,
+    0x01EED'i32, 499,
+    0x01EEF'i32, 499,
+    0x01EF1'i32, 499,
+    0x01EF3'i32, 499,
+    0x01EF5'i32, 499,
+    0x01EF7'i32, 499,
+    0x01EF9'i32, 499,
+    0x01EFB'i32, 499,
+    0x01EFD'i32, 499,
+    0x01EFF'i32, 499,
+    0x01F51'i32, 508,
+    0x01F53'i32, 508,
+    0x01F55'i32, 508,
+    0x01F57'i32, 508,
+    0x01FB3'i32, 509,
+    0x01FBE'i32, -6705,
+    0x01FC3'i32, 509,
+    0x01FE5'i32, 507,
+    0x01FF3'i32, 509,
+    0x0214E'i32, 472,
+    0x02184'i32, 499,
+    0x02C61'i32, 499,
+    0x02C65'i32, -10295,
+    0x02C66'i32, -10292,
+    0x02C68'i32, 499,
+    0x02C6A'i32, 499,
+    0x02C6C'i32, 499,
+    0x02C73'i32, 499,
+    0x02C76'i32, 499,
+    0x02C81'i32, 499,
+    0x02C83'i32, 499,
+    0x02C85'i32, 499,
+    0x02C87'i32, 499,
+    0x02C89'i32, 499,
+    0x02C8B'i32, 499,
+    0x02C8D'i32, 499,
+    0x02C8F'i32, 499,
+    0x02C91'i32, 499,
+    0x02C93'i32, 499,
+    0x02C95'i32, 499,
+    0x02C97'i32, 499,
+    0x02C99'i32, 499,
+    0x02C9B'i32, 499,
+    0x02C9D'i32, 499,
+    0x02C9F'i32, 499,
+    0x02CA1'i32, 499,
+    0x02CA3'i32, 499,
+    0x02CA5'i32, 499,
+    0x02CA7'i32, 499,
+    0x02CA9'i32, 499,
+    0x02CAB'i32, 499,
+    0x02CAD'i32, 499,
+    0x02CAF'i32, 499,
+    0x02CB1'i32, 499,
+    0x02CB3'i32, 499,
+    0x02CB5'i32, 499,
+    0x02CB7'i32, 499,
+    0x02CB9'i32, 499,
+    0x02CBB'i32, 499,
+    0x02CBD'i32, 499,
+    0x02CBF'i32, 499,
+    0x02CC1'i32, 499,
+    0x02CC3'i32, 499,
+    0x02CC5'i32, 499,
+    0x02CC7'i32, 499,
+    0x02CC9'i32, 499,
+    0x02CCB'i32, 499,
+    0x02CCD'i32, 499,
+    0x02CCF'i32, 499,
+    0x02CD1'i32, 499,
+    0x02CD3'i32, 499,
+    0x02CD5'i32, 499,
+    0x02CD7'i32, 499,
+    0x02CD9'i32, 499,
+    0x02CDB'i32, 499,
+    0x02CDD'i32, 499,
+    0x02CDF'i32, 499,
+    0x02CE1'i32, 499,
+    0x02CE3'i32, 499,
+    0x02CEC'i32, 499,
+    0x02CEE'i32, 499,
+    0x02CF3'i32, 499,
+    0x02D27'i32, -6764,
+    0x02D2D'i32, -6764,
+    0x0A641'i32, 499,
+    0x0A643'i32, 499,
+    0x0A645'i32, 499,
+    0x0A647'i32, 499,
+    0x0A649'i32, 499,
+    0x0A64B'i32, 499,
+    0x0A64D'i32, 499,
+    0x0A64F'i32, 499,
+    0x0A651'i32, 499,
+    0x0A653'i32, 499,
+    0x0A655'i32, 499,
+    0x0A657'i32, 499,
+    0x0A659'i32, 499,
+    0x0A65B'i32, 499,
+    0x0A65D'i32, 499,
+    0x0A65F'i32, 499,
+    0x0A661'i32, 499,
+    0x0A663'i32, 499,
+    0x0A665'i32, 499,
+    0x0A667'i32, 499,
+    0x0A669'i32, 499,
+    0x0A66B'i32, 499,
+    0x0A66D'i32, 499,
+    0x0A681'i32, 499,
+    0x0A683'i32, 499,
+    0x0A685'i32, 499,
+    0x0A687'i32, 499,
+    0x0A689'i32, 499,
+    0x0A68B'i32, 499,
+    0x0A68D'i32, 499,
+    0x0A68F'i32, 499,
+    0x0A691'i32, 499,
+    0x0A693'i32, 499,
+    0x0A695'i32, 499,
+    0x0A697'i32, 499,
+    0x0A699'i32, 499,
+    0x0A69B'i32, 499,
+    0x0A723'i32, 499,
+    0x0A725'i32, 499,
+    0x0A727'i32, 499,
+    0x0A729'i32, 499,
+    0x0A72B'i32, 499,
+    0x0A72D'i32, 499,
+    0x0A72F'i32, 499,
+    0x0A733'i32, 499,
+    0x0A735'i32, 499,
+    0x0A737'i32, 499,
+    0x0A739'i32, 499,
+    0x0A73B'i32, 499,
+    0x0A73D'i32, 499,
+    0x0A73F'i32, 499,
+    0x0A741'i32, 499,
+    0x0A743'i32, 499,
+    0x0A745'i32, 499,
+    0x0A747'i32, 499,
+    0x0A749'i32, 499,
+    0x0A74B'i32, 499,
+    0x0A74D'i32, 499,
+    0x0A74F'i32, 499,
+    0x0A751'i32, 499,
+    0x0A753'i32, 499,
+    0x0A755'i32, 499,
+    0x0A757'i32, 499,
+    0x0A759'i32, 499,
+    0x0A75B'i32, 499,
+    0x0A75D'i32, 499,
+    0x0A75F'i32, 499,
+    0x0A761'i32, 499,
+    0x0A763'i32, 499,
+    0x0A765'i32, 499,
+    0x0A767'i32, 499,
+    0x0A769'i32, 499,
+    0x0A76B'i32, 499,
+    0x0A76D'i32, 499,
+    0x0A76F'i32, 499,
+    0x0A77A'i32, 499,
+    0x0A77C'i32, 499,
+    0x0A77F'i32, 499,
+    0x0A781'i32, 499,
+    0x0A783'i32, 499,
+    0x0A785'i32, 499,
+    0x0A787'i32, 499,
+    0x0A78C'i32, 499,
+    0x0A791'i32, 499,
+    0x0A793'i32, 499,
+    0x0A794'i32, 548,
+    0x0A797'i32, 499,
+    0x0A799'i32, 499,
+    0x0A79B'i32, 499,
+    0x0A79D'i32, 499,
+    0x0A79F'i32, 499,
+    0x0A7A1'i32, 499,
+    0x0A7A3'i32, 499,
+    0x0A7A5'i32, 499,
+    0x0A7A7'i32, 499,
+    0x0A7A9'i32, 499,
+    0x0A7B5'i32, 499,
+    0x0A7B7'i32, 499,
+    0x0A7B9'i32, 499,
+    0x0A7BB'i32, 499,
+    0x0A7BD'i32, 499,
+    0x0A7BF'i32, 499,
+    0x0A7C3'i32, 499,
+    0x0AB53'i32, -428,
   ]
 
   toTitleSinglets = [
-    0x001C4, 501,
-    0x001C6, 499,
-    0x001C7, 501,
-    0x001C9, 499,
-    0x001CA, 501,
-    0x001CC, 499,
-    0x001F1, 501,
-    0x001F3, 499,
+    0x001C4'i32, 501,
+    0x001C6'i32, 499,
+    0x001C7'i32, 501,
+    0x001C9'i32, 499,
+    0x001CA'i32, 501,
+    0x001CC'i32, 499,
+    0x001F1'i32, 501,
+    0x001F3'i32, 499,
   ]
 
   alphaRanges = [
-    0x00041, 0x0005A,
-    0x00061, 0x0007A,
-    0x000C0, 0x000D6,
-    0x000D8, 0x000F6,
-    0x000F8, 0x002C1,
-    0x002C6, 0x002D1,
-    0x002E0, 0x002E4,
-    0x00370, 0x00374,
-    0x00376, 0x00377,
-    0x0037A, 0x0037D,
-    0x00388, 0x0038A,
-    0x0038E, 0x003A1,
-    0x003A3, 0x003F5,
-    0x003F7, 0x00481,
-    0x0048A, 0x0052F,
-    0x00531, 0x00556,
-    0x00560, 0x00588,
-    0x005D0, 0x005EA,
-    0x005EF, 0x005F2,
-    0x00620, 0x0064A,
-    0x0066E, 0x0066F,
-    0x00671, 0x006D3,
-    0x006E5, 0x006E6,
-    0x006EE, 0x006EF,
-    0x006FA, 0x006FC,
-    0x00712, 0x0072F,
-    0x0074D, 0x007A5,
-    0x007CA, 0x007EA,
-    0x007F4, 0x007F5,
-    0x00800, 0x00815,
-    0x00840, 0x00858,
-    0x00860, 0x0086A,
-    0x008A0, 0x008B4,
-    0x008B6, 0x008BD,
-    0x00904, 0x00939,
-    0x00958, 0x00961,
-    0x00971, 0x00980,
-    0x00985, 0x0098C,
-    0x0098F, 0x00990,
-    0x00993, 0x009A8,
-    0x009AA, 0x009B0,
-    0x009B6, 0x009B9,
-    0x009DC, 0x009DD,
-    0x009DF, 0x009E1,
-    0x009F0, 0x009F1,
-    0x00A05, 0x00A0A,
-    0x00A0F, 0x00A10,
-    0x00A13, 0x00A28,
-    0x00A2A, 0x00A30,
-    0x00A32, 0x00A33,
-    0x00A35, 0x00A36,
-    0x00A38, 0x00A39,
-    0x00A59, 0x00A5C,
-    0x00A72, 0x00A74,
-    0x00A85, 0x00A8D,
-    0x00A8F, 0x00A91,
-    0x00A93, 0x00AA8,
-    0x00AAA, 0x00AB0,
-    0x00AB2, 0x00AB3,
-    0x00AB5, 0x00AB9,
-    0x00AE0, 0x00AE1,
-    0x00B05, 0x00B0C,
-    0x00B0F, 0x00B10,
-    0x00B13, 0x00B28,
-    0x00B2A, 0x00B30,
-    0x00B32, 0x00B33,
-    0x00B35, 0x00B39,
-    0x00B5C, 0x00B5D,
-    0x00B5F, 0x00B61,
-    0x00B85, 0x00B8A,
-    0x00B8E, 0x00B90,
-    0x00B92, 0x00B95,
-    0x00B99, 0x00B9A,
-    0x00B9E, 0x00B9F,
-    0x00BA3, 0x00BA4,
-    0x00BA8, 0x00BAA,
-    0x00BAE, 0x00BB9,
-    0x00C05, 0x00C0C,
-    0x00C0E, 0x00C10,
-    0x00C12, 0x00C28,
-    0x00C2A, 0x00C39,
-    0x00C58, 0x00C5A,
-    0x00C60, 0x00C61,
-    0x00C85, 0x00C8C,
-    0x00C8E, 0x00C90,
-    0x00C92, 0x00CA8,
-    0x00CAA, 0x00CB3,
-    0x00CB5, 0x00CB9,
-    0x00CE0, 0x00CE1,
-    0x00CF1, 0x00CF2,
-    0x00D05, 0x00D0C,
-    0x00D0E, 0x00D10,
-    0x00D12, 0x00D3A,
-    0x00D54, 0x00D56,
-    0x00D5F, 0x00D61,
-    0x00D7A, 0x00D7F,
-    0x00D85, 0x00D96,
-    0x00D9A, 0x00DB1,
-    0x00DB3, 0x00DBB,
-    0x00DC0, 0x00DC6,
-    0x00E01, 0x00E30,
-    0x00E32, 0x00E33,
-    0x00E40, 0x00E46,
-    0x00E81, 0x00E82,
-    0x00E86, 0x00E8A,
-    0x00E8C, 0x00EA3,
-    0x00EA7, 0x00EB0,
-    0x00EB2, 0x00EB3,
-    0x00EC0, 0x00EC4,
-    0x00EDC, 0x00EDF,
-    0x00F40, 0x00F47,
-    0x00F49, 0x00F6C,
-    0x00F88, 0x00F8C,
-    0x01000, 0x0102A,
-    0x01050, 0x01055,
-    0x0105A, 0x0105D,
-    0x01065, 0x01066,
-    0x0106E, 0x01070,
-    0x01075, 0x01081,
-    0x010A0, 0x010C5,
-    0x010D0, 0x010FA,
-    0x010FC, 0x01248,
-    0x0124A, 0x0124D,
-    0x01250, 0x01256,
-    0x0125A, 0x0125D,
-    0x01260, 0x01288,
-    0x0128A, 0x0128D,
-    0x01290, 0x012B0,
-    0x012B2, 0x012B5,
-    0x012B8, 0x012BE,
-    0x012C2, 0x012C5,
-    0x012C8, 0x012D6,
-    0x012D8, 0x01310,
-    0x01312, 0x01315,
-    0x01318, 0x0135A,
-    0x01380, 0x0138F,
-    0x013A0, 0x013F5,
-    0x013F8, 0x013FD,
-    0x01401, 0x0166C,
-    0x0166F, 0x0167F,
-    0x01681, 0x0169A,
-    0x016A0, 0x016EA,
-    0x016F1, 0x016F8,
-    0x01700, 0x0170C,
-    0x0170E, 0x01711,
-    0x01720, 0x01731,
-    0x01740, 0x01751,
-    0x01760, 0x0176C,
-    0x0176E, 0x01770,
-    0x01780, 0x017B3,
-    0x01820, 0x01878,
-    0x01880, 0x01884,
-    0x01887, 0x018A8,
-    0x018B0, 0x018F5,
-    0x01900, 0x0191E,
-    0x01950, 0x0196D,
-    0x01970, 0x01974,
-    0x01980, 0x019AB,
-    0x019B0, 0x019C9,
-    0x01A00, 0x01A16,
-    0x01A20, 0x01A54,
-    0x01B05, 0x01B33,
-    0x01B45, 0x01B4B,
-    0x01B83, 0x01BA0,
-    0x01BAE, 0x01BAF,
-    0x01BBA, 0x01BE5,
-    0x01C00, 0x01C23,
-    0x01C4D, 0x01C4F,
-    0x01C5A, 0x01C7D,
-    0x01C80, 0x01C88,
-    0x01C90, 0x01CBA,
-    0x01CBD, 0x01CBF,
-    0x01CE9, 0x01CEC,
-    0x01CEE, 0x01CF3,
-    0x01CF5, 0x01CF6,
-    0x01D00, 0x01DBF,
-    0x01E00, 0x01F15,
-    0x01F18, 0x01F1D,
-    0x01F20, 0x01F45,
-    0x01F48, 0x01F4D,
-    0x01F50, 0x01F57,
-    0x01F5F, 0x01F7D,
-    0x01F80, 0x01FB4,
-    0x01FB6, 0x01FBC,
-    0x01FC2, 0x01FC4,
-    0x01FC6, 0x01FCC,
-    0x01FD0, 0x01FD3,
-    0x01FD6, 0x01FDB,
-    0x01FE0, 0x01FEC,
-    0x01FF2, 0x01FF4,
-    0x01FF6, 0x01FFC,
-    0x02090, 0x0209C,
-    0x0210A, 0x02113,
-    0x02119, 0x0211D,
-    0x0212A, 0x0212D,
-    0x0212F, 0x02139,
-    0x0213C, 0x0213F,
-    0x02145, 0x02149,
-    0x02183, 0x02184,
-    0x02C00, 0x02C2E,
-    0x02C30, 0x02C5E,
-    0x02C60, 0x02CE4,
-    0x02CEB, 0x02CEE,
-    0x02CF2, 0x02CF3,
-    0x02D00, 0x02D25,
-    0x02D30, 0x02D67,
-    0x02D80, 0x02D96,
-    0x02DA0, 0x02DA6,
-    0x02DA8, 0x02DAE,
-    0x02DB0, 0x02DB6,
-    0x02DB8, 0x02DBE,
-    0x02DC0, 0x02DC6,
-    0x02DC8, 0x02DCE,
-    0x02DD0, 0x02DD6,
-    0x02DD8, 0x02DDE,
-    0x03005, 0x03006,
-    0x03031, 0x03035,
-    0x0303B, 0x0303C,
-    0x03041, 0x03096,
-    0x0309D, 0x0309F,
-    0x030A1, 0x030FA,
-    0x030FC, 0x030FF,
-    0x03105, 0x0312F,
-    0x03131, 0x0318E,
-    0x031A0, 0x031BA,
-    0x031F0, 0x031FF,
-    0x0A000, 0x0A48C,
-    0x0A4D0, 0x0A4FD,
-    0x0A500, 0x0A60C,
-    0x0A610, 0x0A61F,
-    0x0A62A, 0x0A62B,
-    0x0A640, 0x0A66E,
-    0x0A67F, 0x0A69D,
-    0x0A6A0, 0x0A6E5,
-    0x0A717, 0x0A71F,
-    0x0A722, 0x0A788,
-    0x0A78B, 0x0A7BF,
-    0x0A7C2, 0x0A7C6,
-    0x0A7F7, 0x0A801,
-    0x0A803, 0x0A805,
-    0x0A807, 0x0A80A,
-    0x0A80C, 0x0A822,
-    0x0A840, 0x0A873,
-    0x0A882, 0x0A8B3,
-    0x0A8F2, 0x0A8F7,
-    0x0A8FD, 0x0A8FE,
-    0x0A90A, 0x0A925,
-    0x0A930, 0x0A946,
-    0x0A960, 0x0A97C,
-    0x0A984, 0x0A9B2,
-    0x0A9E0, 0x0A9E4,
-    0x0A9E6, 0x0A9EF,
-    0x0A9FA, 0x0A9FE,
-    0x0AA00, 0x0AA28,
-    0x0AA40, 0x0AA42,
-    0x0AA44, 0x0AA4B,
-    0x0AA60, 0x0AA76,
-    0x0AA7E, 0x0AAAF,
-    0x0AAB5, 0x0AAB6,
-    0x0AAB9, 0x0AABD,
-    0x0AADB, 0x0AADD,
-    0x0AAE0, 0x0AAEA,
-    0x0AAF2, 0x0AAF4,
-    0x0AB01, 0x0AB06,
-    0x0AB09, 0x0AB0E,
-    0x0AB11, 0x0AB16,
-    0x0AB20, 0x0AB26,
-    0x0AB28, 0x0AB2E,
-    0x0AB30, 0x0AB5A,
-    0x0AB5C, 0x0AB67,
-    0x0AB70, 0x0ABE2,
-    0x0D7B0, 0x0D7C6,
-    0x0D7CB, 0x0D7FB,
-    0x0F900, 0x0FA6D,
-    0x0FA70, 0x0FAD9,
-    0x0FB00, 0x0FB06,
-    0x0FB13, 0x0FB17,
-    0x0FB1F, 0x0FB28,
-    0x0FB2A, 0x0FB36,
-    0x0FB38, 0x0FB3C,
-    0x0FB40, 0x0FB41,
-    0x0FB43, 0x0FB44,
-    0x0FB46, 0x0FBB1,
-    0x0FBD3, 0x0FD3D,
-    0x0FD50, 0x0FD8F,
-    0x0FD92, 0x0FDC7,
-    0x0FDF0, 0x0FDFB,
-    0x0FE70, 0x0FE74,
-    0x0FE76, 0x0FEFC,
-    0x0FF21, 0x0FF3A,
-    0x0FF41, 0x0FF5A,
-    0x0FF66, 0x0FFBE,
-    0x0FFC2, 0x0FFC7,
-    0x0FFCA, 0x0FFCF,
-    0x0FFD2, 0x0FFD7,
-    0x0FFDA, 0x0FFDC,
-    0x10000, 0x1000B,
-    0x1000D, 0x10026,
-    0x10028, 0x1003A,
-    0x1003C, 0x1003D,
-    0x1003F, 0x1004D,
-    0x10050, 0x1005D,
-    0x10080, 0x100FA,
-    0x10280, 0x1029C,
-    0x102A0, 0x102D0,
-    0x10300, 0x1031F,
-    0x1032D, 0x10340,
-    0x10342, 0x10349,
-    0x10350, 0x10375,
-    0x10380, 0x1039D,
-    0x103A0, 0x103C3,
-    0x103C8, 0x103CF,
-    0x10400, 0x1049D,
-    0x104B0, 0x104D3,
-    0x104D8, 0x104FB,
-    0x10500, 0x10527,
-    0x10530, 0x10563,
-    0x10600, 0x10736,
-    0x10740, 0x10755,
-    0x10760, 0x10767,
-    0x10800, 0x10805,
-    0x1080A, 0x10835,
-    0x10837, 0x10838,
-    0x1083F, 0x10855,
-    0x10860, 0x10876,
-    0x10880, 0x1089E,
-    0x108E0, 0x108F2,
-    0x108F4, 0x108F5,
-    0x10900, 0x10915,
-    0x10920, 0x10939,
-    0x10980, 0x109B7,
-    0x109BE, 0x109BF,
-    0x10A10, 0x10A13,
-    0x10A15, 0x10A17,
-    0x10A19, 0x10A35,
-    0x10A60, 0x10A7C,
-    0x10A80, 0x10A9C,
-    0x10AC0, 0x10AC7,
-    0x10AC9, 0x10AE4,
-    0x10B00, 0x10B35,
-    0x10B40, 0x10B55,
-    0x10B60, 0x10B72,
-    0x10B80, 0x10B91,
-    0x10C00, 0x10C48,
-    0x10C80, 0x10CB2,
-    0x10CC0, 0x10CF2,
-    0x10D00, 0x10D23,
-    0x10F00, 0x10F1C,
-    0x10F30, 0x10F45,
-    0x10FE0, 0x10FF6,
-    0x11003, 0x11037,
-    0x11083, 0x110AF,
-    0x110D0, 0x110E8,
-    0x11103, 0x11126,
-    0x11150, 0x11172,
-    0x11183, 0x111B2,
-    0x111C1, 0x111C4,
-    0x11200, 0x11211,
-    0x11213, 0x1122B,
-    0x11280, 0x11286,
-    0x1128A, 0x1128D,
-    0x1128F, 0x1129D,
-    0x1129F, 0x112A8,
-    0x112B0, 0x112DE,
-    0x11305, 0x1130C,
-    0x1130F, 0x11310,
-    0x11313, 0x11328,
-    0x1132A, 0x11330,
-    0x11332, 0x11333,
-    0x11335, 0x11339,
-    0x1135D, 0x11361,
-    0x11400, 0x11434,
-    0x11447, 0x1144A,
-    0x11480, 0x114AF,
-    0x114C4, 0x114C5,
-    0x11580, 0x115AE,
-    0x115D8, 0x115DB,
-    0x11600, 0x1162F,
-    0x11680, 0x116AA,
-    0x11700, 0x1171A,
-    0x11800, 0x1182B,
-    0x118A0, 0x118DF,
-    0x119A0, 0x119A7,
-    0x119AA, 0x119D0,
-    0x11A0B, 0x11A32,
-    0x11A5C, 0x11A89,
-    0x11AC0, 0x11AF8,
-    0x11C00, 0x11C08,
-    0x11C0A, 0x11C2E,
-    0x11C72, 0x11C8F,
-    0x11D00, 0x11D06,
-    0x11D08, 0x11D09,
-    0x11D0B, 0x11D30,
-    0x11D60, 0x11D65,
-    0x11D67, 0x11D68,
-    0x11D6A, 0x11D89,
-    0x11EE0, 0x11EF2,
-    0x12000, 0x12399,
-    0x12480, 0x12543,
-    0x13000, 0x1342E,
-    0x14400, 0x14646,
-    0x16800, 0x16A38,
-    0x16A40, 0x16A5E,
-    0x16AD0, 0x16AED,
-    0x16B00, 0x16B2F,
-    0x16B40, 0x16B43,
-    0x16B63, 0x16B77,
-    0x16B7D, 0x16B8F,
-    0x16E40, 0x16E7F,
-    0x16F00, 0x16F4A,
-    0x16F93, 0x16F9F,
-    0x16FE0, 0x16FE1,
-    0x18800, 0x18AF2,
-    0x1B000, 0x1B11E,
-    0x1B150, 0x1B152,
-    0x1B164, 0x1B167,
-    0x1B170, 0x1B2FB,
-    0x1BC00, 0x1BC6A,
-    0x1BC70, 0x1BC7C,
-    0x1BC80, 0x1BC88,
-    0x1BC90, 0x1BC99,
-    0x1D400, 0x1D454,
-    0x1D456, 0x1D49C,
-    0x1D49E, 0x1D49F,
-    0x1D4A5, 0x1D4A6,
-    0x1D4A9, 0x1D4AC,
-    0x1D4AE, 0x1D4B9,
-    0x1D4BD, 0x1D4C3,
-    0x1D4C5, 0x1D505,
-    0x1D507, 0x1D50A,
-    0x1D50D, 0x1D514,
-    0x1D516, 0x1D51C,
-    0x1D51E, 0x1D539,
-    0x1D53B, 0x1D53E,
-    0x1D540, 0x1D544,
-    0x1D54A, 0x1D550,
-    0x1D552, 0x1D6A5,
-    0x1D6A8, 0x1D6C0,
-    0x1D6C2, 0x1D6DA,
-    0x1D6DC, 0x1D6FA,
-    0x1D6FC, 0x1D714,
-    0x1D716, 0x1D734,
-    0x1D736, 0x1D74E,
-    0x1D750, 0x1D76E,
-    0x1D770, 0x1D788,
-    0x1D78A, 0x1D7A8,
-    0x1D7AA, 0x1D7C2,
-    0x1D7C4, 0x1D7CB,
-    0x1E100, 0x1E12C,
-    0x1E137, 0x1E13D,
-    0x1E2C0, 0x1E2EB,
-    0x1E800, 0x1E8C4,
-    0x1E900, 0x1E943,
-    0x1EE00, 0x1EE03,
-    0x1EE05, 0x1EE1F,
-    0x1EE21, 0x1EE22,
-    0x1EE29, 0x1EE32,
-    0x1EE34, 0x1EE37,
-    0x1EE4D, 0x1EE4F,
-    0x1EE51, 0x1EE52,
-    0x1EE61, 0x1EE62,
-    0x1EE67, 0x1EE6A,
-    0x1EE6C, 0x1EE72,
-    0x1EE74, 0x1EE77,
-    0x1EE79, 0x1EE7C,
-    0x1EE80, 0x1EE89,
-    0x1EE8B, 0x1EE9B,
-    0x1EEA1, 0x1EEA3,
-    0x1EEA5, 0x1EEA9,
-    0x1EEAB, 0x1EEBB,
-    0x2F800, 0x2FA1D,
+    0x00041'i32, 0x0005A'i32,
+    0x00061'i32, 0x0007A'i32,
+    0x000C0'i32, 0x000D6'i32,
+    0x000D8'i32, 0x000F6'i32,
+    0x000F8'i32, 0x002C1'i32,
+    0x002C6'i32, 0x002D1'i32,
+    0x002E0'i32, 0x002E4'i32,
+    0x00370'i32, 0x00374'i32,
+    0x00376'i32, 0x00377'i32,
+    0x0037A'i32, 0x0037D'i32,
+    0x00388'i32, 0x0038A'i32,
+    0x0038E'i32, 0x003A1'i32,
+    0x003A3'i32, 0x003F5'i32,
+    0x003F7'i32, 0x00481'i32,
+    0x0048A'i32, 0x0052F'i32,
+    0x00531'i32, 0x00556'i32,
+    0x00560'i32, 0x00588'i32,
+    0x005D0'i32, 0x005EA'i32,
+    0x005EF'i32, 0x005F2'i32,
+    0x00620'i32, 0x0064A'i32,
+    0x0066E'i32, 0x0066F'i32,
+    0x00671'i32, 0x006D3'i32,
+    0x006E5'i32, 0x006E6'i32,
+    0x006EE'i32, 0x006EF'i32,
+    0x006FA'i32, 0x006FC'i32,
+    0x00712'i32, 0x0072F'i32,
+    0x0074D'i32, 0x007A5'i32,
+    0x007CA'i32, 0x007EA'i32,
+    0x007F4'i32, 0x007F5'i32,
+    0x00800'i32, 0x00815'i32,
+    0x00840'i32, 0x00858'i32,
+    0x00860'i32, 0x0086A'i32,
+    0x008A0'i32, 0x008B4'i32,
+    0x008B6'i32, 0x008BD'i32,
+    0x00904'i32, 0x00939'i32,
+    0x00958'i32, 0x00961'i32,
+    0x00971'i32, 0x00980'i32,
+    0x00985'i32, 0x0098C'i32,
+    0x0098F'i32, 0x00990'i32,
+    0x00993'i32, 0x009A8'i32,
+    0x009AA'i32, 0x009B0'i32,
+    0x009B6'i32, 0x009B9'i32,
+    0x009DC'i32, 0x009DD'i32,
+    0x009DF'i32, 0x009E1'i32,
+    0x009F0'i32, 0x009F1'i32,
+    0x00A05'i32, 0x00A0A'i32,
+    0x00A0F'i32, 0x00A10'i32,
+    0x00A13'i32, 0x00A28'i32,
+    0x00A2A'i32, 0x00A30'i32,
+    0x00A32'i32, 0x00A33'i32,
+    0x00A35'i32, 0x00A36'i32,
+    0x00A38'i32, 0x00A39'i32,
+    0x00A59'i32, 0x00A5C'i32,
+    0x00A72'i32, 0x00A74'i32,
+    0x00A85'i32, 0x00A8D'i32,
+    0x00A8F'i32, 0x00A91'i32,
+    0x00A93'i32, 0x00AA8'i32,
+    0x00AAA'i32, 0x00AB0'i32,
+    0x00AB2'i32, 0x00AB3'i32,
+    0x00AB5'i32, 0x00AB9'i32,
+    0x00AE0'i32, 0x00AE1'i32,
+    0x00B05'i32, 0x00B0C'i32,
+    0x00B0F'i32, 0x00B10'i32,
+    0x00B13'i32, 0x00B28'i32,
+    0x00B2A'i32, 0x00B30'i32,
+    0x00B32'i32, 0x00B33'i32,
+    0x00B35'i32, 0x00B39'i32,
+    0x00B5C'i32, 0x00B5D'i32,
+    0x00B5F'i32, 0x00B61'i32,
+    0x00B85'i32, 0x00B8A'i32,
+    0x00B8E'i32, 0x00B90'i32,
+    0x00B92'i32, 0x00B95'i32,
+    0x00B99'i32, 0x00B9A'i32,
+    0x00B9E'i32, 0x00B9F'i32,
+    0x00BA3'i32, 0x00BA4'i32,
+    0x00BA8'i32, 0x00BAA'i32,
+    0x00BAE'i32, 0x00BB9'i32,
+    0x00C05'i32, 0x00C0C'i32,
+    0x00C0E'i32, 0x00C10'i32,
+    0x00C12'i32, 0x00C28'i32,
+    0x00C2A'i32, 0x00C39'i32,
+    0x00C58'i32, 0x00C5A'i32,
+    0x00C60'i32, 0x00C61'i32,
+    0x00C85'i32, 0x00C8C'i32,
+    0x00C8E'i32, 0x00C90'i32,
+    0x00C92'i32, 0x00CA8'i32,
+    0x00CAA'i32, 0x00CB3'i32,
+    0x00CB5'i32, 0x00CB9'i32,
+    0x00CE0'i32, 0x00CE1'i32,
+    0x00CF1'i32, 0x00CF2'i32,
+    0x00D05'i32, 0x00D0C'i32,
+    0x00D0E'i32, 0x00D10'i32,
+    0x00D12'i32, 0x00D3A'i32,
+    0x00D54'i32, 0x00D56'i32,
+    0x00D5F'i32, 0x00D61'i32,
+    0x00D7A'i32, 0x00D7F'i32,
+    0x00D85'i32, 0x00D96'i32,
+    0x00D9A'i32, 0x00DB1'i32,
+    0x00DB3'i32, 0x00DBB'i32,
+    0x00DC0'i32, 0x00DC6'i32,
+    0x00E01'i32, 0x00E30'i32,
+    0x00E32'i32, 0x00E33'i32,
+    0x00E40'i32, 0x00E46'i32,
+    0x00E81'i32, 0x00E82'i32,
+    0x00E86'i32, 0x00E8A'i32,
+    0x00E8C'i32, 0x00EA3'i32,
+    0x00EA7'i32, 0x00EB0'i32,
+    0x00EB2'i32, 0x00EB3'i32,
+    0x00EC0'i32, 0x00EC4'i32,
+    0x00EDC'i32, 0x00EDF'i32,
+    0x00F40'i32, 0x00F47'i32,
+    0x00F49'i32, 0x00F6C'i32,
+    0x00F88'i32, 0x00F8C'i32,
+    0x01000'i32, 0x0102A'i32,
+    0x01050'i32, 0x01055'i32,
+    0x0105A'i32, 0x0105D'i32,
+    0x01065'i32, 0x01066'i32,
+    0x0106E'i32, 0x01070'i32,
+    0x01075'i32, 0x01081'i32,
+    0x010A0'i32, 0x010C5'i32,
+    0x010D0'i32, 0x010FA'i32,
+    0x010FC'i32, 0x01248'i32,
+    0x0124A'i32, 0x0124D'i32,
+    0x01250'i32, 0x01256'i32,
+    0x0125A'i32, 0x0125D'i32,
+    0x01260'i32, 0x01288'i32,
+    0x0128A'i32, 0x0128D'i32,
+    0x01290'i32, 0x012B0'i32,
+    0x012B2'i32, 0x012B5'i32,
+    0x012B8'i32, 0x012BE'i32,
+    0x012C2'i32, 0x012C5'i32,
+    0x012C8'i32, 0x012D6'i32,
+    0x012D8'i32, 0x01310'i32,
+    0x01312'i32, 0x01315'i32,
+    0x01318'i32, 0x0135A'i32,
+    0x01380'i32, 0x0138F'i32,
+    0x013A0'i32, 0x013F5'i32,
+    0x013F8'i32, 0x013FD'i32,
+    0x01401'i32, 0x0166C'i32,
+    0x0166F'i32, 0x0167F'i32,
+    0x01681'i32, 0x0169A'i32,
+    0x016A0'i32, 0x016EA'i32,
+    0x016F1'i32, 0x016F8'i32,
+    0x01700'i32, 0x0170C'i32,
+    0x0170E'i32, 0x01711'i32,
+    0x01720'i32, 0x01731'i32,
+    0x01740'i32, 0x01751'i32,
+    0x01760'i32, 0x0176C'i32,
+    0x0176E'i32, 0x01770'i32,
+    0x01780'i32, 0x017B3'i32,
+    0x01820'i32, 0x01878'i32,
+    0x01880'i32, 0x01884'i32,
+    0x01887'i32, 0x018A8'i32,
+    0x018B0'i32, 0x018F5'i32,
+    0x01900'i32, 0x0191E'i32,
+    0x01950'i32, 0x0196D'i32,
+    0x01970'i32, 0x01974'i32,
+    0x01980'i32, 0x019AB'i32,
+    0x019B0'i32, 0x019C9'i32,
+    0x01A00'i32, 0x01A16'i32,
+    0x01A20'i32, 0x01A54'i32,
+    0x01B05'i32, 0x01B33'i32,
+    0x01B45'i32, 0x01B4B'i32,
+    0x01B83'i32, 0x01BA0'i32,
+    0x01BAE'i32, 0x01BAF'i32,
+    0x01BBA'i32, 0x01BE5'i32,
+    0x01C00'i32, 0x01C23'i32,
+    0x01C4D'i32, 0x01C4F'i32,
+    0x01C5A'i32, 0x01C7D'i32,
+    0x01C80'i32, 0x01C88'i32,
+    0x01C90'i32, 0x01CBA'i32,
+    0x01CBD'i32, 0x01CBF'i32,
+    0x01CE9'i32, 0x01CEC'i32,
+    0x01CEE'i32, 0x01CF3'i32,
+    0x01CF5'i32, 0x01CF6'i32,
+    0x01D00'i32, 0x01DBF'i32,
+    0x01E00'i32, 0x01F15'i32,
+    0x01F18'i32, 0x01F1D'i32,
+    0x01F20'i32, 0x01F45'i32,
+    0x01F48'i32, 0x01F4D'i32,
+    0x01F50'i32, 0x01F57'i32,
+    0x01F5F'i32, 0x01F7D'i32,
+    0x01F80'i32, 0x01FB4'i32,
+    0x01FB6'i32, 0x01FBC'i32,
+    0x01FC2'i32, 0x01FC4'i32,
+    0x01FC6'i32, 0x01FCC'i32,
+    0x01FD0'i32, 0x01FD3'i32,
+    0x01FD6'i32, 0x01FDB'i32,
+    0x01FE0'i32, 0x01FEC'i32,
+    0x01FF2'i32, 0x01FF4'i32,
+    0x01FF6'i32, 0x01FFC'i32,
+    0x02090'i32, 0x0209C'i32,
+    0x0210A'i32, 0x02113'i32,
+    0x02119'i32, 0x0211D'i32,
+    0x0212A'i32, 0x0212D'i32,
+    0x0212F'i32, 0x02139'i32,
+    0x0213C'i32, 0x0213F'i32,
+    0x02145'i32, 0x02149'i32,
+    0x02183'i32, 0x02184'i32,
+    0x02C00'i32, 0x02C2E'i32,
+    0x02C30'i32, 0x02C5E'i32,
+    0x02C60'i32, 0x02CE4'i32,
+    0x02CEB'i32, 0x02CEE'i32,
+    0x02CF2'i32, 0x02CF3'i32,
+    0x02D00'i32, 0x02D25'i32,
+    0x02D30'i32, 0x02D67'i32,
+    0x02D80'i32, 0x02D96'i32,
+    0x02DA0'i32, 0x02DA6'i32,
+    0x02DA8'i32, 0x02DAE'i32,
+    0x02DB0'i32, 0x02DB6'i32,
+    0x02DB8'i32, 0x02DBE'i32,
+    0x02DC0'i32, 0x02DC6'i32,
+    0x02DC8'i32, 0x02DCE'i32,
+    0x02DD0'i32, 0x02DD6'i32,
+    0x02DD8'i32, 0x02DDE'i32,
+    0x03005'i32, 0x03006'i32,
+    0x03031'i32, 0x03035'i32,
+    0x0303B'i32, 0x0303C'i32,
+    0x03041'i32, 0x03096'i32,
+    0x0309D'i32, 0x0309F'i32,
+    0x030A1'i32, 0x030FA'i32,
+    0x030FC'i32, 0x030FF'i32,
+    0x03105'i32, 0x0312F'i32,
+    0x03131'i32, 0x0318E'i32,
+    0x031A0'i32, 0x031BA'i32,
+    0x031F0'i32, 0x031FF'i32,
+    0x03400'i32, 0x04DB5'i32,
+    0x04E00'i32, 0x09FEF'i32,
+    0x0A000'i32, 0x0A48C'i32,
+    0x0A4D0'i32, 0x0A4FD'i32,
+    0x0A500'i32, 0x0A60C'i32,
+    0x0A610'i32, 0x0A61F'i32,
+    0x0A62A'i32, 0x0A62B'i32,
+    0x0A640'i32, 0x0A66E'i32,
+    0x0A67F'i32, 0x0A69D'i32,
+    0x0A6A0'i32, 0x0A6E5'i32,
+    0x0A717'i32, 0x0A71F'i32,
+    0x0A722'i32, 0x0A788'i32,
+    0x0A78B'i32, 0x0A7BF'i32,
+    0x0A7C2'i32, 0x0A7C6'i32,
+    0x0A7F7'i32, 0x0A801'i32,
+    0x0A803'i32, 0x0A805'i32,
+    0x0A807'i32, 0x0A80A'i32,
+    0x0A80C'i32, 0x0A822'i32,
+    0x0A840'i32, 0x0A873'i32,
+    0x0A882'i32, 0x0A8B3'i32,
+    0x0A8F2'i32, 0x0A8F7'i32,
+    0x0A8FD'i32, 0x0A8FE'i32,
+    0x0A90A'i32, 0x0A925'i32,
+    0x0A930'i32, 0x0A946'i32,
+    0x0A960'i32, 0x0A97C'i32,
+    0x0A984'i32, 0x0A9B2'i32,
+    0x0A9E0'i32, 0x0A9E4'i32,
+    0x0A9E6'i32, 0x0A9EF'i32,
+    0x0A9FA'i32, 0x0A9FE'i32,
+    0x0AA00'i32, 0x0AA28'i32,
+    0x0AA40'i32, 0x0AA42'i32,
+    0x0AA44'i32, 0x0AA4B'i32,
+    0x0AA60'i32, 0x0AA76'i32,
+    0x0AA7E'i32, 0x0AAAF'i32,
+    0x0AAB5'i32, 0x0AAB6'i32,
+    0x0AAB9'i32, 0x0AABD'i32,
+    0x0AADB'i32, 0x0AADD'i32,
+    0x0AAE0'i32, 0x0AAEA'i32,
+    0x0AAF2'i32, 0x0AAF4'i32,
+    0x0AB01'i32, 0x0AB06'i32,
+    0x0AB09'i32, 0x0AB0E'i32,
+    0x0AB11'i32, 0x0AB16'i32,
+    0x0AB20'i32, 0x0AB26'i32,
+    0x0AB28'i32, 0x0AB2E'i32,
+    0x0AB30'i32, 0x0AB5A'i32,
+    0x0AB5C'i32, 0x0AB67'i32,
+    0x0AB70'i32, 0x0ABE2'i32,
+    0x0AC00'i32, 0x0D7A3'i32,
+    0x0D7B0'i32, 0x0D7C6'i32,
+    0x0D7CB'i32, 0x0D7FB'i32,
+    0x0F900'i32, 0x0FA6D'i32,
+    0x0FA70'i32, 0x0FAD9'i32,
+    0x0FB00'i32, 0x0FB06'i32,
+    0x0FB13'i32, 0x0FB17'i32,
+    0x0FB1F'i32, 0x0FB28'i32,
+    0x0FB2A'i32, 0x0FB36'i32,
+    0x0FB38'i32, 0x0FB3C'i32,
+    0x0FB40'i32, 0x0FB41'i32,
+    0x0FB43'i32, 0x0FB44'i32,
+    0x0FB46'i32, 0x0FBB1'i32,
+    0x0FBD3'i32, 0x0FD3D'i32,
+    0x0FD50'i32, 0x0FD8F'i32,
+    0x0FD92'i32, 0x0FDC7'i32,
+    0x0FDF0'i32, 0x0FDFB'i32,
+    0x0FE70'i32, 0x0FE74'i32,
+    0x0FE76'i32, 0x0FEFC'i32,
+    0x0FF21'i32, 0x0FF3A'i32,
+    0x0FF41'i32, 0x0FF5A'i32,
+    0x0FF66'i32, 0x0FFBE'i32,
+    0x0FFC2'i32, 0x0FFC7'i32,
+    0x0FFCA'i32, 0x0FFCF'i32,
+    0x0FFD2'i32, 0x0FFD7'i32,
+    0x0FFDA'i32, 0x0FFDC'i32,
+    0x10000'i32, 0x1000B'i32,
+    0x1000D'i32, 0x10026'i32,
+    0x10028'i32, 0x1003A'i32,
+    0x1003C'i32, 0x1003D'i32,
+    0x1003F'i32, 0x1004D'i32,
+    0x10050'i32, 0x1005D'i32,
+    0x10080'i32, 0x100FA'i32,
+    0x10280'i32, 0x1029C'i32,
+    0x102A0'i32, 0x102D0'i32,
+    0x10300'i32, 0x1031F'i32,
+    0x1032D'i32, 0x10340'i32,
+    0x10342'i32, 0x10349'i32,
+    0x10350'i32, 0x10375'i32,
+    0x10380'i32, 0x1039D'i32,
+    0x103A0'i32, 0x103C3'i32,
+    0x103C8'i32, 0x103CF'i32,
+    0x10400'i32, 0x1049D'i32,
+    0x104B0'i32, 0x104D3'i32,
+    0x104D8'i32, 0x104FB'i32,
+    0x10500'i32, 0x10527'i32,
+    0x10530'i32, 0x10563'i32,
+    0x10600'i32, 0x10736'i32,
+    0x10740'i32, 0x10755'i32,
+    0x10760'i32, 0x10767'i32,
+    0x10800'i32, 0x10805'i32,
+    0x1080A'i32, 0x10835'i32,
+    0x10837'i32, 0x10838'i32,
+    0x1083F'i32, 0x10855'i32,
+    0x10860'i32, 0x10876'i32,
+    0x10880'i32, 0x1089E'i32,
+    0x108E0'i32, 0x108F2'i32,
+    0x108F4'i32, 0x108F5'i32,
+    0x10900'i32, 0x10915'i32,
+    0x10920'i32, 0x10939'i32,
+    0x10980'i32, 0x109B7'i32,
+    0x109BE'i32, 0x109BF'i32,
+    0x10A10'i32, 0x10A13'i32,
+    0x10A15'i32, 0x10A17'i32,
+    0x10A19'i32, 0x10A35'i32,
+    0x10A60'i32, 0x10A7C'i32,
+    0x10A80'i32, 0x10A9C'i32,
+    0x10AC0'i32, 0x10AC7'i32,
+    0x10AC9'i32, 0x10AE4'i32,
+    0x10B00'i32, 0x10B35'i32,
+    0x10B40'i32, 0x10B55'i32,
+    0x10B60'i32, 0x10B72'i32,
+    0x10B80'i32, 0x10B91'i32,
+    0x10C00'i32, 0x10C48'i32,
+    0x10C80'i32, 0x10CB2'i32,
+    0x10CC0'i32, 0x10CF2'i32,
+    0x10D00'i32, 0x10D23'i32,
+    0x10F00'i32, 0x10F1C'i32,
+    0x10F30'i32, 0x10F45'i32,
+    0x10FE0'i32, 0x10FF6'i32,
+    0x11003'i32, 0x11037'i32,
+    0x11083'i32, 0x110AF'i32,
+    0x110D0'i32, 0x110E8'i32,
+    0x11103'i32, 0x11126'i32,
+    0x11150'i32, 0x11172'i32,
+    0x11183'i32, 0x111B2'i32,
+    0x111C1'i32, 0x111C4'i32,
+    0x11200'i32, 0x11211'i32,
+    0x11213'i32, 0x1122B'i32,
+    0x11280'i32, 0x11286'i32,
+    0x1128A'i32, 0x1128D'i32,
+    0x1128F'i32, 0x1129D'i32,
+    0x1129F'i32, 0x112A8'i32,
+    0x112B0'i32, 0x112DE'i32,
+    0x11305'i32, 0x1130C'i32,
+    0x1130F'i32, 0x11310'i32,
+    0x11313'i32, 0x11328'i32,
+    0x1132A'i32, 0x11330'i32,
+    0x11332'i32, 0x11333'i32,
+    0x11335'i32, 0x11339'i32,
+    0x1135D'i32, 0x11361'i32,
+    0x11400'i32, 0x11434'i32,
+    0x11447'i32, 0x1144A'i32,
+    0x11480'i32, 0x114AF'i32,
+    0x114C4'i32, 0x114C5'i32,
+    0x11580'i32, 0x115AE'i32,
+    0x115D8'i32, 0x115DB'i32,
+    0x11600'i32, 0x1162F'i32,
+    0x11680'i32, 0x116AA'i32,
+    0x11700'i32, 0x1171A'i32,
+    0x11800'i32, 0x1182B'i32,
+    0x118A0'i32, 0x118DF'i32,
+    0x119A0'i32, 0x119A7'i32,
+    0x119AA'i32, 0x119D0'i32,
+    0x11A0B'i32, 0x11A32'i32,
+    0x11A5C'i32, 0x11A89'i32,
+    0x11AC0'i32, 0x11AF8'i32,
+    0x11C00'i32, 0x11C08'i32,
+    0x11C0A'i32, 0x11C2E'i32,
+    0x11C72'i32, 0x11C8F'i32,
+    0x11D00'i32, 0x11D06'i32,
+    0x11D08'i32, 0x11D09'i32,
+    0x11D0B'i32, 0x11D30'i32,
+    0x11D60'i32, 0x11D65'i32,
+    0x11D67'i32, 0x11D68'i32,
+    0x11D6A'i32, 0x11D89'i32,
+    0x11EE0'i32, 0x11EF2'i32,
+    0x12000'i32, 0x12399'i32,
+    0x12480'i32, 0x12543'i32,
+    0x13000'i32, 0x1342E'i32,
+    0x14400'i32, 0x14646'i32,
+    0x16800'i32, 0x16A38'i32,
+    0x16A40'i32, 0x16A5E'i32,
+    0x16AD0'i32, 0x16AED'i32,
+    0x16B00'i32, 0x16B2F'i32,
+    0x16B40'i32, 0x16B43'i32,
+    0x16B63'i32, 0x16B77'i32,
+    0x16B7D'i32, 0x16B8F'i32,
+    0x16E40'i32, 0x16E7F'i32,
+    0x16F00'i32, 0x16F4A'i32,
+    0x16F93'i32, 0x16F9F'i32,
+    0x16FE0'i32, 0x16FE1'i32,
+    0x17000'i32, 0x187F7'i32,
+    0x18800'i32, 0x18AF2'i32,
+    0x1B000'i32, 0x1B11E'i32,
+    0x1B150'i32, 0x1B152'i32,
+    0x1B164'i32, 0x1B167'i32,
+    0x1B170'i32, 0x1B2FB'i32,
+    0x1BC00'i32, 0x1BC6A'i32,
+    0x1BC70'i32, 0x1BC7C'i32,
+    0x1BC80'i32, 0x1BC88'i32,
+    0x1BC90'i32, 0x1BC99'i32,
+    0x1D400'i32, 0x1D454'i32,
+    0x1D456'i32, 0x1D49C'i32,
+    0x1D49E'i32, 0x1D49F'i32,
+    0x1D4A5'i32, 0x1D4A6'i32,
+    0x1D4A9'i32, 0x1D4AC'i32,
+    0x1D4AE'i32, 0x1D4B9'i32,
+    0x1D4BD'i32, 0x1D4C3'i32,
+    0x1D4C5'i32, 0x1D505'i32,
+    0x1D507'i32, 0x1D50A'i32,
+    0x1D50D'i32, 0x1D514'i32,
+    0x1D516'i32, 0x1D51C'i32,
+    0x1D51E'i32, 0x1D539'i32,
+    0x1D53B'i32, 0x1D53E'i32,
+    0x1D540'i32, 0x1D544'i32,
+    0x1D54A'i32, 0x1D550'i32,
+    0x1D552'i32, 0x1D6A5'i32,
+    0x1D6A8'i32, 0x1D6C0'i32,
+    0x1D6C2'i32, 0x1D6DA'i32,
+    0x1D6DC'i32, 0x1D6FA'i32,
+    0x1D6FC'i32, 0x1D714'i32,
+    0x1D716'i32, 0x1D734'i32,
+    0x1D736'i32, 0x1D74E'i32,
+    0x1D750'i32, 0x1D76E'i32,
+    0x1D770'i32, 0x1D788'i32,
+    0x1D78A'i32, 0x1D7A8'i32,
+    0x1D7AA'i32, 0x1D7C2'i32,
+    0x1D7C4'i32, 0x1D7CB'i32,
+    0x1E100'i32, 0x1E12C'i32,
+    0x1E137'i32, 0x1E13D'i32,
+    0x1E2C0'i32, 0x1E2EB'i32,
+    0x1E800'i32, 0x1E8C4'i32,
+    0x1E900'i32, 0x1E943'i32,
+    0x1EE00'i32, 0x1EE03'i32,
+    0x1EE05'i32, 0x1EE1F'i32,
+    0x1EE21'i32, 0x1EE22'i32,
+    0x1EE29'i32, 0x1EE32'i32,
+    0x1EE34'i32, 0x1EE37'i32,
+    0x1EE4D'i32, 0x1EE4F'i32,
+    0x1EE51'i32, 0x1EE52'i32,
+    0x1EE61'i32, 0x1EE62'i32,
+    0x1EE67'i32, 0x1EE6A'i32,
+    0x1EE6C'i32, 0x1EE72'i32,
+    0x1EE74'i32, 0x1EE77'i32,
+    0x1EE79'i32, 0x1EE7C'i32,
+    0x1EE80'i32, 0x1EE89'i32,
+    0x1EE8B'i32, 0x1EE9B'i32,
+    0x1EEA1'i32, 0x1EEA3'i32,
+    0x1EEA5'i32, 0x1EEA9'i32,
+    0x1EEAB'i32, 0x1EEBB'i32,
+    0x20000'i32, 0x2A6D6'i32,
+    0x2A700'i32, 0x2B734'i32,
+    0x2B740'i32, 0x2B81D'i32,
+    0x2B820'i32, 0x2CEA1'i32,
+    0x2CEB0'i32, 0x2EBE0'i32,
+    0x2F800'i32, 0x2FA1D'i32,
   ]
 
   alphaSinglets = [
-    0x000AA,
-    0x000B5,
-    0x000BA,
-    0x002EC,
-    0x002EE,
-    0x0037F,
-    0x00386,
-    0x0038C,
-    0x00559,
-    0x006D5,
-    0x006FF,
-    0x00710,
-    0x007B1,
-    0x007FA,
-    0x0081A,
-    0x00824,
-    0x00828,
-    0x0093D,
-    0x00950,
-    0x009B2,
-    0x009BD,
-    0x009CE,
-    0x009FC,
-    0x00A5E,
-    0x00ABD,
-    0x00AD0,
-    0x00AF9,
-    0x00B3D,
-    0x00B71,
-    0x00B83,
-    0x00B9C,
-    0x00BD0,
-    0x00C3D,
-    0x00C80,
-    0x00CBD,
-    0x00CDE,
-    0x00D3D,
-    0x00D4E,
-    0x00DBD,
-    0x00E84,
-    0x00EA5,
-    0x00EBD,
-    0x00EC6,
-    0x00F00,
-    0x0103F,
-    0x01061,
-    0x0108E,
-    0x010C7,
-    0x010CD,
-    0x01258,
-    0x012C0,
-    0x017D7,
-    0x017DC,
-    0x018AA,
-    0x01AA7,
-    0x01CFA,
-    0x01F59,
-    0x01F5B,
-    0x01F5D,
-    0x01FBE,
-    0x02071,
-    0x0207F,
-    0x02102,
-    0x02107,
-    0x02115,
-    0x02124,
-    0x02126,
-    0x02128,
-    0x0214E,
-    0x02D27,
-    0x02D2D,
-    0x02D6F,
-    0x02E2F,
-    0x03400,
-    0x04DB5,
-    0x04E00,
-    0x09FEF,
-    0x0A8FB,
-    0x0A9CF,
-    0x0AA7A,
-    0x0AAB1,
-    0x0AAC0,
-    0x0AAC2,
-    0x0AC00,
-    0x0D7A3,
-    0x0FB1D,
-    0x0FB3E,
-    0x10808,
-    0x1083C,
-    0x10A00,
-    0x10F27,
-    0x11144,
-    0x11176,
-    0x111DA,
-    0x111DC,
-    0x11288,
-    0x1133D,
-    0x11350,
-    0x1145F,
-    0x114C7,
-    0x11644,
-    0x116B8,
-    0x118FF,
-    0x119E1,
-    0x119E3,
-    0x11A00,
-    0x11A3A,
-    0x11A50,
-    0x11A9D,
-    0x11C40,
-    0x11D46,
-    0x11D98,
-    0x16F50,
-    0x16FE3,
-    0x17000,
-    0x187F7,
-    0x1D4A2,
-    0x1D4BB,
-    0x1D546,
-    0x1E14E,
-    0x1E94B,
-    0x1EE24,
-    0x1EE27,
-    0x1EE39,
-    0x1EE3B,
-    0x1EE42,
-    0x1EE47,
-    0x1EE49,
-    0x1EE4B,
-    0x1EE54,
-    0x1EE57,
-    0x1EE59,
-    0x1EE5B,
-    0x1EE5D,
-    0x1EE5F,
-    0x1EE64,
-    0x1EE7E,
-    0x20000,
-    0x2A6D6,
-    0x2A700,
-    0x2B734,
-    0x2B740,
-    0x2B81D,
-    0x2B820,
-    0x2CEA1,
-    0x2CEB0,
-    0x2EBE0,
+    0x000AA'i32,
+    0x000B5'i32,
+    0x000BA'i32,
+    0x002EC'i32,
+    0x002EE'i32,
+    0x0037F'i32,
+    0x00386'i32,
+    0x0038C'i32,
+    0x00559'i32,
+    0x006D5'i32,
+    0x006FF'i32,
+    0x00710'i32,
+    0x007B1'i32,
+    0x007FA'i32,
+    0x0081A'i32,
+    0x00824'i32,
+    0x00828'i32,
+    0x0093D'i32,
+    0x00950'i32,
+    0x009B2'i32,
+    0x009BD'i32,
+    0x009CE'i32,
+    0x009FC'i32,
+    0x00A5E'i32,
+    0x00ABD'i32,
+    0x00AD0'i32,
+    0x00AF9'i32,
+    0x00B3D'i32,
+    0x00B71'i32,
+    0x00B83'i32,
+    0x00B9C'i32,
+    0x00BD0'i32,
+    0x00C3D'i32,
+    0x00C80'i32,
+    0x00CBD'i32,
+    0x00CDE'i32,
+    0x00D3D'i32,
+    0x00D4E'i32,
+    0x00DBD'i32,
+    0x00E84'i32,
+    0x00EA5'i32,
+    0x00EBD'i32,
+    0x00EC6'i32,
+    0x00F00'i32,
+    0x0103F'i32,
+    0x01061'i32,
+    0x0108E'i32,
+    0x010C7'i32,
+    0x010CD'i32,
+    0x01258'i32,
+    0x012C0'i32,
+    0x017D7'i32,
+    0x017DC'i32,
+    0x018AA'i32,
+    0x01AA7'i32,
+    0x01CFA'i32,
+    0x01F59'i32,
+    0x01F5B'i32,
+    0x01F5D'i32,
+    0x01FBE'i32,
+    0x02071'i32,
+    0x0207F'i32,
+    0x02102'i32,
+    0x02107'i32,
+    0x02115'i32,
+    0x02124'i32,
+    0x02126'i32,
+    0x02128'i32,
+    0x0214E'i32,
+    0x02D27'i32,
+    0x02D2D'i32,
+    0x02D6F'i32,
+    0x02E2F'i32,
+    0x0A8FB'i32,
+    0x0A9CF'i32,
+    0x0AA7A'i32,
+    0x0AAB1'i32,
+    0x0AAC0'i32,
+    0x0AAC2'i32,
+    0x0FB1D'i32,
+    0x0FB3E'i32,
+    0x10808'i32,
+    0x1083C'i32,
+    0x10A00'i32,
+    0x10F27'i32,
+    0x11144'i32,
+    0x11176'i32,
+    0x111DA'i32,
+    0x111DC'i32,
+    0x11288'i32,
+    0x1133D'i32,
+    0x11350'i32,
+    0x1145F'i32,
+    0x114C7'i32,
+    0x11644'i32,
+    0x116B8'i32,
+    0x118FF'i32,
+    0x119E1'i32,
+    0x119E3'i32,
+    0x11A00'i32,
+    0x11A3A'i32,
+    0x11A50'i32,
+    0x11A9D'i32,
+    0x11C40'i32,
+    0x11D46'i32,
+    0x11D98'i32,
+    0x16F50'i32,
+    0x16FE3'i32,
+    0x1D4A2'i32,
+    0x1D4BB'i32,
+    0x1D546'i32,
+    0x1E14E'i32,
+    0x1E94B'i32,
+    0x1EE24'i32,
+    0x1EE27'i32,
+    0x1EE39'i32,
+    0x1EE3B'i32,
+    0x1EE42'i32,
+    0x1EE47'i32,
+    0x1EE49'i32,
+    0x1EE4B'i32,
+    0x1EE54'i32,
+    0x1EE57'i32,
+    0x1EE59'i32,
+    0x1EE5B'i32,
+    0x1EE5D'i32,
+    0x1EE5F'i32,
+    0x1EE64'i32,
+    0x1EE7E'i32,
   ]
 
   spaceRanges = [
-    0x00009, 0x0000D,
-    0x00020, 0x00020,
-    0x00085, 0x00085,
-    0x000A0, 0x000A0,
-    0x01680, 0x01680,
-    0x02000, 0x0200A,
-    0x02028, 0x02029,
-    0x0202F, 0x0202F,
-    0x0205F, 0x0205F,
-    0x03000, 0x03000,
+    0x00009'i32, 0x0000D'i32,
+    0x00020'i32, 0x00020'i32,
+    0x00085'i32, 0x00085'i32,
+    0x000A0'i32, 0x000A0'i32,
+    0x01680'i32, 0x01680'i32,
+    0x02000'i32, 0x0200A'i32,
+    0x02028'i32, 0x02029'i32,
+    0x0202F'i32, 0x0202F'i32,
+    0x0205F'i32, 0x0205F'i32,
+    0x03000'i32, 0x03000'i32,
   ]
 
   unicodeSpaces = [
diff --git a/lib/pure/ioselects/ioselectors_epoll.nim b/lib/pure/ioselects/ioselectors_epoll.nim
index 8526eb8a3..10658b78e 100644
--- a/lib/pure/ioselects/ioselectors_epoll.nim
+++ b/lib/pure/ioselects/ioselectors_epoll.nim
@@ -9,7 +9,7 @@
 
 # This module implements Linux epoll().
 
-import posix, times, epoll
+import std/[posix, times, epoll]
 
 # Maximum number of events that can be returned
 const MAX_EPOLL_EVENTS = 64
@@ -72,11 +72,16 @@ type
   SelectEvent* = ptr SelectEventImpl
 
 proc newSelector*[T](): Selector[T] =
+  proc initialNumFD(): int {.inline.} =
+    when defined(nuttx):
+      result = NEPOLL_MAX
+    else:
+      result = 1024
   # Retrieve the maximum fd count (for current OS) via getrlimit()
   var maxFD = maxDescriptors()
   doAssert(maxFD > 0)
   # Start with a reasonable size, checkFd() will grow this on demand
-  const numFD = 1024
+  let numFD = initialNumFD()
 
   var epollFD = epoll_create1(O_CLOEXEC)
   if epollFD < 0:
@@ -133,7 +138,7 @@ template checkFd(s, f) =
     var numFD = s.numFD
     while numFD <= f: numFD *= 2
     when hasThreadSupport:
-      s.fds = reallocSharedArray(s.fds, numFD)
+      s.fds = reallocSharedArray(s.fds, s.numFD, numFD)
     else:
       s.fds.setLen(numFD)
     for i in s.numFD ..< numFD:
diff --git a/lib/pure/ioselects/ioselectors_kqueue.nim b/lib/pure/ioselects/ioselectors_kqueue.nim
index 68be969c7..513578eda 100644
--- a/lib/pure/ioselects/ioselectors_kqueue.nim
+++ b/lib/pure/ioselects/ioselectors_kqueue.nim
@@ -9,7 +9,7 @@
 
 #  This module implements BSD kqueue().
 
-import posix, times, kqueue, nativesockets
+import std/[posix, times, kqueue, nativesockets]
 
 const
   # Maximum number of events that can be returned.
@@ -194,7 +194,9 @@ when hasThreadSupport:
         if s.changesLength > 0:
           if kevent(s.kqFD, addr(s.changes[0]), cint(s.changesLength),
                     nil, 0, nil) == -1:
-            raiseIOSelectorsError(osLastError())
+            let res = osLastError()
+            if cint(res) != ENOENT: # ignore pipes whose read end is closed
+              raiseIOSelectorsError(res)
           s.changesLength = 0
 else:
   template modifyKQueue[T](s: Selector[T], nident: uint, nfilter: cshort,
@@ -211,7 +213,9 @@ else:
       if length > 0:
         if kevent(s.kqFD, addr(s.changes[0]), length,
                   nil, 0, nil) == -1:
-          raiseIOSelectorsError(osLastError())
+          let res = osLastError()
+          if cint(res) != ENOENT: # ignore pipes whose read end is closed
+            raiseIOSelectorsError(res)
         s.changes.setLen(0)
 
 proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle,
diff --git a/lib/pure/ioselects/ioselectors_poll.nim b/lib/pure/ioselects/ioselectors_poll.nim
index 12812ac80..7c5347156 100644
--- a/lib/pure/ioselects/ioselectors_poll.nim
+++ b/lib/pure/ioselects/ioselectors_poll.nim
@@ -9,7 +9,7 @@
 
 # This module implements Posix poll().
 
-import posix, times
+import std/[posix, times]
 
 # Maximum number of events that can be returned
 const MAX_POLL_EVENTS = 64
diff --git a/lib/pure/ioselects/ioselectors_select.nim b/lib/pure/ioselects/ioselectors_select.nim
index 34c88d85e..6c516395b 100644
--- a/lib/pure/ioselects/ioselectors_select.nim
+++ b/lib/pure/ioselects/ioselectors_select.nim
@@ -9,10 +9,10 @@
 
 # This module implements Posix and Windows select().
 
-import times, nativesockets
+import std/[times, nativesockets]
 
 when defined(windows):
-  import winlean
+  import std/winlean
   when defined(gcc):
     {.passl: "-lws2_32".}
   elif defined(vcc):
@@ -313,8 +313,8 @@ proc selectInto*[T](s: Selector[T], timeout: int,
   verifySelectParams(timeout)
 
   if timeout != -1:
-    when defined(genode) or defined(freertos) or defined(zephyr):
-      tv.tv_sec = Time(timeout div 1_000)
+    when defined(genode) or defined(freertos) or defined(zephyr) or defined(nuttx):
+      tv.tv_sec = posix.Time(timeout div 1_000)
     else:
       tv.tv_sec = timeout.int32 div 1_000
     tv.tv_usec = (timeout.int32 %% 1_000) * 1_000
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index d0b1a4051..53fa7553a 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -41,13 +41,14 @@
 ## For a `JsonNode` who's kind is `JObject`, you can access its fields using
 ## the `[]` operator. The following example shows how to do this:
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/json
 ##
 ##   let jsonNode = parseJson("""{"key": 3.14}""")
 ##
 ##   doAssert jsonNode.kind == JObject
 ##   doAssert jsonNode["key"].kind == JFloat
+##   ```
 ##
 ## Reading values
 ## --------------
@@ -62,12 +63,13 @@
 ##
 ## To retrieve the value of `"key"` you can do the following:
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/json
 ##
 ##   let jsonNode = parseJson("""{"key": 3.14}""")
 ##
 ##   doAssert jsonNode["key"].getFloat() == 3.14
+##   ```
 ##
 ## **Important:** The `[]` operator will raise an exception when the
 ## specified field does not exist.
@@ -79,7 +81,7 @@
 ## when the field is not found. The `get`-family of procedures will return a
 ## type's default value when called on `nil`.
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/json
 ##
 ##   let jsonNode = parseJson("{}")
@@ -88,6 +90,7 @@
 ##   doAssert jsonNode{"nope"}.getFloat() == 0
 ##   doAssert jsonNode{"nope"}.getStr() == ""
 ##   doAssert jsonNode{"nope"}.getBool() == false
+##   ```
 ##
 ## Using default values
 ## --------------------
@@ -95,7 +98,7 @@
 ## The `get`-family helpers also accept an additional parameter which allow
 ## you to fallback to a default value should the key's values be `null`:
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/json
 ##
 ##   let jsonNode = parseJson("""{"key": 3.14, "key2": null}""")
@@ -103,6 +106,7 @@
 ##   doAssert jsonNode["key"].getFloat(6.28) == 3.14
 ##   doAssert jsonNode["key2"].getFloat(3.14) == 3.14
 ##   doAssert jsonNode{"nope"}.getFloat(3.14) == 3.14 # note the {}
+##   ```
 ##
 ## Unmarshalling
 ## -------------
@@ -113,7 +117,7 @@
 ## Note: Use `Option <options.html#Option>`_ for keys sometimes missing in json
 ## responses, and backticks around keys with a reserved keyword as name.
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   import std/json
 ##   import std/options
 ##
@@ -127,6 +131,7 @@
 ##   let user = to(userJson, User)
 ##   if user.`type`.isSome():
 ##     assert user.`type`.get() != "robot"
+##   ```
 ##
 ## Creating JSON
 ## =============
@@ -134,7 +139,7 @@
 ## This module can also be used to comfortably create JSON using the `%*`
 ## operator:
 ##
-## .. code-block:: nim
+##   ```nim
 ##   import std/json
 ##
 ##   var hisName = "John"
@@ -148,6 +153,7 @@
 ##   var j2 = %* {"name": "Isaac", "books": ["Robot Dreams"]}
 ##   j2["details"] = %* {"age":35, "pi":3.1415}
 ##   echo j2
+##   ```
 ##
 ## See also: std/jsonutils for hookable json serialization/deserialization
 ## of arbitrary types.
@@ -159,9 +165,9 @@ runnableExamples:
     a1, a2, a0, a3, a4: int
   doAssert $(%* Foo()) == """{"a1":0,"a2":0,"a0":0,"a3":0,"a4":0}"""
 
-import hashes, tables, strutils, lexbase, streams, macros, parsejson
+import std/[hashes, tables, strutils, lexbase, streams, macros, parsejson]
 
-import options # xxx remove this dependency using same approach as https://github.com/nim-lang/Nim/pull/14563
+import std/options # xxx remove this dependency using same approach as https://github.com/nim-lang/Nim/pull/14563
 import std/private/since
 
 when defined(nimPreviewSlimSystem):
@@ -438,7 +444,7 @@ macro `%*`*(x: untyped): untyped =
   ## `%` for every element.
   result = toJsonImpl(x)
 
-proc `==`*(a, b: JsonNode): bool {.noSideEffect.} =
+proc `==`*(a, b: JsonNode): bool {.noSideEffect, raises: [].} =
   ## Check two nodes for equality
   if a.isNil:
     if b.isNil: return true
@@ -458,18 +464,20 @@ proc `==`*(a, b: JsonNode): bool {.noSideEffect.} =
     of JNull:
       result = true
     of JArray:
-      result = a.elems == b.elems
+      {.cast(raises: []).}: # bug #19303
+        result = a.elems == b.elems
     of JObject:
       # we cannot use OrderedTable's equality here as
       # the order does not matter for equality here.
       if a.fields.len != b.fields.len: return false
       for key, val in a.fields:
         if not b.fields.hasKey(key): return false
-        when defined(nimHasEffectsOf):
-          {.noSideEffect.}:
+        {.cast(raises: []).}:
+          when defined(nimHasEffectsOf):
+            {.noSideEffect.}:
+              if b.fields[key] != val: return false
+          else:
             if b.fields[key] != val: return false
-        else:
-          if b.fields[key] != val: return false
       result = true
 
 proc hash*(n: OrderedTable[string, JsonNode]): Hash {.noSideEffect.}
@@ -541,7 +549,7 @@ proc `[]`*[U, V](a: JsonNode, x: HSlice[U, V]): JsonNode =
   ##
   ## Returns the inclusive range `[a[x.a], a[x.b]]`:
   runnableExamples:
-    import json
+    import std/json
     let arr = %[0,1,2,3,4,5]
     doAssert arr[2..4] == %[2,3,4]
     doAssert arr[2..^2] == %[2,3,4]
@@ -626,7 +634,7 @@ proc delete*(obj: JsonNode, key: string) =
   obj.fields.del(key)
 
 proc copy*(p: JsonNode): JsonNode =
-  ## Performs a deep copy of `a`.
+  ## Performs a deep copy of `p`.
   case p.kind
   of JString:
     result = newJString(p.str)
@@ -855,7 +863,7 @@ proc parseJson(p: var JsonParser; rawIntegers, rawFloats: bool, depth = 0): Json
   case p.tok
   of tkString:
     # we capture 'p.a' here, so we need to give it a fresh buffer afterwards:
-    when defined(gcArc) or defined(gcOrc):
+    when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
       result = JsonNode(kind: JString, str: move p.a)
     else:
       result = JsonNode(kind: JString)
@@ -957,7 +965,7 @@ proc parseJson*(s: Stream, filename: string = ""; rawIntegers = false, rawFloats
     p.close()
 
 when defined(js):
-  from math import `mod`
+  from std/math import `mod`
   from std/jsffi import JsObject, `[]`, to
   from std/private/jsutils import getProtoName, isInteger, isSafeInteger
 
@@ -983,9 +991,9 @@ when defined(js):
     else: assert false
 
   proc len(x: JsObject): int =
-    asm """
+    {.emit: """
       `result` = `x`.length;
-    """
+    """.}
 
   proc convertObject(x: JsObject): JsonNode =
     var isRawNumber = false
@@ -996,14 +1004,15 @@ when defined(js):
         result.add(x[i].convertObject())
     of JObject:
       result = newJObject()
-      asm """for (var property in `x`) {
+      {.emit: """for (var property in `x`) {
         if (`x`.hasOwnProperty(property)) {
-      """
+      """.}
+
       var nimProperty: cstring
       var nimValue: JsObject
-      asm "`nimProperty` = property; `nimValue` = `x`[property];"
+      {.emit: "`nimProperty` = property; `nimValue` = `x`[property];".}
       result[$nimProperty] = nimValue.convertObject()
-      asm "}}"
+      {.emit: "}}".}
     of JInt:
       result = newJInt(x.to(int))
     of JFloat:
@@ -1059,313 +1068,306 @@ template verifyJsonKind(node: JsonNode, kinds: set[JsonNodeKind],
     ]
     raise newException(JsonKindError, msg)
 
-when defined(nimFixedForwardGeneric):
-
-  macro isRefSkipDistinct*(arg: typed): untyped =
-    ## internal only, do not use
-    var impl = getTypeImpl(arg)
-    if impl.kind == nnkBracketExpr and impl[0].eqIdent("typeDesc"):
-      impl = getTypeImpl(impl[1])
-    while impl.kind == nnkDistinctTy:
-      impl = getTypeImpl(impl[0])
-    result = newLit(impl.kind == nnkRefTy)
-
-  # The following forward declarations don't work in older versions of Nim
-
-  # forward declare all initFromJson
-
-  proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string)
-  proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[S, T](dst: var array[S, T]; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T](dst: var Table[string, T]; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T](dst: var OrderedTable[string, T]; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string)
-  proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string)
-
-  # initFromJson definitions
-
-  proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string) =
-    verifyJsonKind(jsonNode, {JString, JNull}, jsonPath)
-    # since strings don't have a nil state anymore, this mapping of
-    # JNull to the default string is questionable. `none(string)` and
-    # `some("")` have the same potentional json value `JNull`.
-    if jsonNode.kind == JNull:
-      dst = ""
-    else:
-      dst = jsonNode.str
-
-  proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string) =
-    verifyJsonKind(jsonNode, {JBool}, jsonPath)
-    dst = jsonNode.bval
-
-  proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string) =
-    if jsonNode == nil:
-      raise newException(KeyError, "key not found: " & jsonPath)
-    dst = jsonNode.copy
-
-  proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) =
-    when T is uint|uint64 or (not defined(js) and int.sizeof == 4):
-      verifyJsonKind(jsonNode, {JInt, JString}, jsonPath)
-      case jsonNode.kind
-      of JString:
-        let x = parseBiggestUInt(jsonNode.str)
-        dst = cast[T](x)
-      else:
-        dst = T(jsonNode.num)
-    else:
-      verifyJsonKind(jsonNode, {JInt}, jsonPath)
-      dst = cast[T](jsonNode.num)
-
-  proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
-    if jsonNode.kind == JString:
-      case jsonNode.str
-      of "nan":
-        let b = NaN
-        dst = T(b)
-        # dst = NaN # would fail some tests because range conversions would cause CT error
-        # in some cases; but this is not a hot-spot inside this branch and backend can optimize this.
-      of "inf":
-        let b = Inf
-        dst = T(b)
-      of "-inf":
-        let b = -Inf
-        dst = T(b)
-      else: raise newException(JsonKindError, "expected 'nan|inf|-inf', got " & jsonNode.str)
-    else:
-      verifyJsonKind(jsonNode, {JInt, JFloat}, jsonPath)
-      if jsonNode.kind == JFloat:
-        dst = T(jsonNode.fnum)
-      else:
-        dst = T(jsonNode.num)
-
-  proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
-    verifyJsonKind(jsonNode, {JString}, jsonPath)
-    dst = parseEnum[T](jsonNode.getStr)
-
-  proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string) =
-    verifyJsonKind(jsonNode, {JArray}, jsonPath)
-    dst.setLen jsonNode.len
-    let orignalJsonPathLen = jsonPath.len
-    for i in 0 ..< jsonNode.len:
-      jsonPath.add '['
-      jsonPath.addInt i
-      jsonPath.add ']'
-      initFromJson(dst[i], jsonNode[i], jsonPath)
-      jsonPath.setLen orignalJsonPathLen
-
-  proc initFromJson[S,T](dst: var array[S,T]; jsonNode: JsonNode; jsonPath: var string) =
-    verifyJsonKind(jsonNode, {JArray}, jsonPath)
-    let originalJsonPathLen = jsonPath.len
-    for i in 0 ..< jsonNode.len:
-      jsonPath.add '['
-      jsonPath.addInt i
-      jsonPath.add ']'
-      initFromJson(dst[i.S], jsonNode[i], jsonPath) # `.S` for enum indexed arrays
-      jsonPath.setLen originalJsonPathLen
-
-  proc initFromJson[T](dst: var Table[string,T]; jsonNode: JsonNode; jsonPath: var string) =
-    dst = initTable[string, T]()
-    verifyJsonKind(jsonNode, {JObject}, jsonPath)
-    let originalJsonPathLen = jsonPath.len
-    for key in keys(jsonNode.fields):
-      jsonPath.add '.'
-      jsonPath.add key
-      initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
-      jsonPath.setLen originalJsonPathLen
-
-  proc initFromJson[T](dst: var OrderedTable[string,T]; jsonNode: JsonNode; jsonPath: var string) =
-    dst = initOrderedTable[string,T]()
-    verifyJsonKind(jsonNode, {JObject}, jsonPath)
-    let originalJsonPathLen = jsonPath.len
-    for key in keys(jsonNode.fields):
-      jsonPath.add '.'
-      jsonPath.add key
-      initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
-      jsonPath.setLen originalJsonPathLen
-
-  proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string) =
-    verifyJsonKind(jsonNode, {JObject, JNull}, jsonPath)
-    if jsonNode.kind == JNull:
-      dst = nil
-    else:
-      dst = new(T)
-      initFromJson(dst[], jsonNode, jsonPath)
+macro isRefSkipDistinct*(arg: typed): untyped =
+  ## internal only, do not use
+  var impl = getTypeImpl(arg)
+  if impl.kind == nnkBracketExpr and impl[0].eqIdent("typeDesc"):
+    impl = getTypeImpl(impl[1])
+  while impl.kind == nnkDistinctTy:
+    impl = getTypeImpl(impl[0])
+  result = newLit(impl.kind == nnkRefTy)
+
+# The following forward declarations don't work in older versions of Nim
+
+# forward declare all initFromJson
+
+proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string)
+proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[S, T](dst: var array[S, T]; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T](dst: var Table[string, T]; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T](dst: var OrderedTable[string, T]; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string)
+proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string)
+
+# initFromJson definitions
+
+proc initFromJson(dst: var string; jsonNode: JsonNode; jsonPath: var string) =
+  verifyJsonKind(jsonNode, {JString, JNull}, jsonPath)
+  # since strings don't have a nil state anymore, this mapping of
+  # JNull to the default string is questionable. `none(string)` and
+  # `some("")` have the same potentional json value `JNull`.
+  if jsonNode.kind == JNull:
+    dst = ""
+  else:
+    dst = jsonNode.str
 
-  proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string) =
-    if jsonNode != nil and jsonNode.kind != JNull:
-      when T is ref:
-        dst = some(new(T))
-      else:
-        dst = some(default(T))
-      initFromJson(dst.get, jsonNode, jsonPath)
+proc initFromJson(dst: var bool; jsonNode: JsonNode; jsonPath: var string) =
+  verifyJsonKind(jsonNode, {JBool}, jsonPath)
+  dst = jsonNode.bval
+
+proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string) =
+  if jsonNode == nil:
+    raise newException(KeyError, "key not found: " & jsonPath)
+  dst = jsonNode.copy
 
-  macro assignDistinctImpl[T: distinct](dst: var T;jsonNode: JsonNode; jsonPath: var string) =
-    let typInst = getTypeInst(dst)
-    let typImpl = getTypeImpl(dst)
-    let baseTyp = typImpl[0]
+proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) =
+  when T is uint|uint64 or int.sizeof == 4:
+    verifyJsonKind(jsonNode, {JInt, JString}, jsonPath)
+    case jsonNode.kind
+    of JString:
+      let x = parseBiggestUInt(jsonNode.str)
+      dst = cast[T](x)
+    else:
+      dst = T(jsonNode.num)
+  else:
+    verifyJsonKind(jsonNode, {JInt}, jsonPath)
+    dst = cast[T](jsonNode.num)
+
+proc initFromJson[T: SomeFloat](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
+  verifyJsonKind(jsonNode, {JInt, JFloat, JString}, jsonPath)
+  if jsonNode.kind == JString:
+    case jsonNode.str
+    of "nan":
+      let b = NaN
+      dst = T(b)
+      # dst = NaN # would fail some tests because range conversions would cause CT error
+      # in some cases; but this is not a hot-spot inside this branch and backend can optimize this.
+    of "inf":
+      let b = Inf
+      dst = T(b)
+    of "-inf":
+      let b = -Inf
+      dst = T(b)
+    else: raise newException(JsonKindError, "expected 'nan|inf|-inf', got " & jsonNode.str)
+  else:
+    if jsonNode.kind == JFloat:
+      dst = T(jsonNode.fnum)
+    else:
+      dst = T(jsonNode.num)
+
+proc initFromJson[T: enum](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
+  verifyJsonKind(jsonNode, {JString}, jsonPath)
+  dst = parseEnum[T](jsonNode.getStr)
+
+proc initFromJson[T](dst: var seq[T]; jsonNode: JsonNode; jsonPath: var string) =
+  verifyJsonKind(jsonNode, {JArray}, jsonPath)
+  dst.setLen jsonNode.len
+  let orignalJsonPathLen = jsonPath.len
+  for i in 0 ..< jsonNode.len:
+    jsonPath.add '['
+    jsonPath.addInt i
+    jsonPath.add ']'
+    initFromJson(dst[i], jsonNode[i], jsonPath)
+    jsonPath.setLen orignalJsonPathLen
+
+proc initFromJson[S,T](dst: var array[S,T]; jsonNode: JsonNode; jsonPath: var string) =
+  verifyJsonKind(jsonNode, {JArray}, jsonPath)
+  let originalJsonPathLen = jsonPath.len
+  for i in 0 ..< jsonNode.len:
+    jsonPath.add '['
+    jsonPath.addInt i
+    jsonPath.add ']'
+    initFromJson(dst[i.S], jsonNode[i], jsonPath) # `.S` for enum indexed arrays
+    jsonPath.setLen originalJsonPathLen
+
+proc initFromJson[T](dst: var Table[string,T]; jsonNode: JsonNode; jsonPath: var string) =
+  dst = initTable[string, T]()
+  verifyJsonKind(jsonNode, {JObject}, jsonPath)
+  let originalJsonPathLen = jsonPath.len
+  for key in keys(jsonNode.fields):
+    jsonPath.add '.'
+    jsonPath.add key
+    initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
+    jsonPath.setLen originalJsonPathLen
+
+proc initFromJson[T](dst: var OrderedTable[string,T]; jsonNode: JsonNode; jsonPath: var string) =
+  dst = initOrderedTable[string,T]()
+  verifyJsonKind(jsonNode, {JObject}, jsonPath)
+  let originalJsonPathLen = jsonPath.len
+  for key in keys(jsonNode.fields):
+    jsonPath.add '.'
+    jsonPath.add key
+    initFromJson(mgetOrPut(dst, key, default(T)), jsonNode[key], jsonPath)
+    jsonPath.setLen originalJsonPathLen
+
+proc initFromJson[T](dst: var ref T; jsonNode: JsonNode; jsonPath: var string) =
+  verifyJsonKind(jsonNode, {JObject, JNull}, jsonPath)
+  if jsonNode.kind == JNull:
+    dst = nil
+  else:
+    dst = new(T)
+    initFromJson(dst[], jsonNode, jsonPath)
 
-    result = quote do:
+proc initFromJson[T](dst: var Option[T]; jsonNode: JsonNode; jsonPath: var string) =
+  if jsonNode != nil and jsonNode.kind != JNull:
+    when T is ref:
+      dst = some(new(T))
+    else:
+      dst = some(default(T))
+    initFromJson(dst.get, jsonNode, jsonPath)
+
+macro assignDistinctImpl[T: distinct](dst: var T;jsonNode: JsonNode; jsonPath: var string) =
+  let typInst = getTypeInst(dst)
+  let typImpl = getTypeImpl(dst)
+  let baseTyp = typImpl[0]
+
+  result = quote do:
+    initFromJson(`baseTyp`(`dst`), `jsonNode`, `jsonPath`)
+
+proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
+  assignDistinctImpl(dst, jsonNode, jsonPath)
+
+proc detectIncompatibleType(typeExpr, lineinfoNode: NimNode) =
+  if typeExpr.kind == nnkTupleConstr:
+    error("Use a named tuple instead of: " & typeExpr.repr, lineinfoNode)
+
+proc foldObjectBody(dst, typeNode, tmpSym, jsonNode, jsonPath, originalJsonPathLen: NimNode) =
+  case typeNode.kind
+  of nnkEmpty:
+    discard
+  of nnkRecList, nnkTupleTy:
+    for it in typeNode:
+      foldObjectBody(dst, it, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
+
+  of nnkIdentDefs:
+    typeNode.expectLen 3
+    let fieldSym = typeNode[0]
+    let fieldNameLit = newLit(fieldSym.strVal)
+    let fieldPathLit = newLit("." & fieldSym.strVal)
+    let fieldType = typeNode[1]
+
+    # Detecting incompatiple tuple types in `assignObjectImpl` only
+    # would be much cleaner, but the ast for tuple types does not
+    # contain usable type information.
+    detectIncompatibleType(fieldType, fieldSym)
+
+    dst.add quote do:
+      jsonPath.add `fieldPathLit`
       when nimvm:
-        # workaround #12282
-        var tmp: `baseTyp`
-        initFromJson( tmp, `jsonNode`, `jsonPath`)
-        `dst` = `typInst`(tmp)
-      else:
-        initFromJson( `baseTyp`(`dst`), `jsonNode`, `jsonPath`)
-
-  proc initFromJson[T: distinct](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
-    assignDistinctImpl(dst, jsonNode, jsonPath)
-
-  proc detectIncompatibleType(typeExpr, lineinfoNode: NimNode) =
-    if typeExpr.kind == nnkTupleConstr:
-      error("Use a named tuple instead of: " & typeExpr.repr, lineinfoNode)
-
-  proc foldObjectBody(dst, typeNode, tmpSym, jsonNode, jsonPath, originalJsonPathLen: NimNode) =
-    case typeNode.kind
-    of nnkEmpty:
-      discard
-    of nnkRecList, nnkTupleTy:
-      for it in typeNode:
-        foldObjectBody(dst, it, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
-
-    of nnkIdentDefs:
-      typeNode.expectLen 3
-      let fieldSym = typeNode[0]
-      let fieldNameLit = newLit(fieldSym.strVal)
-      let fieldPathLit = newLit("." & fieldSym.strVal)
-      let fieldType = typeNode[1]
-
-      # Detecting incompatiple tuple types in `assignObjectImpl` only
-      # would be much cleaner, but the ast for tuple types does not
-      # contain usable type information.
-      detectIncompatibleType(fieldType, fieldSym)
-
-      dst.add quote do:
-        jsonPath.add `fieldPathLit`
-        when nimvm:
-          when isRefSkipDistinct(`tmpSym`.`fieldSym`):
-            # workaround #12489
-            var tmp: `fieldType`
-            initFromJson(tmp, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
-            `tmpSym`.`fieldSym` = tmp
-          else:
-            initFromJson(`tmpSym`.`fieldSym`, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
+        when isRefSkipDistinct(`tmpSym`.`fieldSym`):
+          # workaround #12489
+          var tmp: `fieldType`
+          initFromJson(tmp, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
+          `tmpSym`.`fieldSym` = tmp
         else:
           initFromJson(`tmpSym`.`fieldSym`, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
-        jsonPath.setLen `originalJsonPathLen`
-
-    of nnkRecCase:
-      let kindSym = typeNode[0][0]
-      let kindNameLit = newLit(kindSym.strVal)
-      let kindPathLit = newLit("." & kindSym.strVal)
-      let kindType = typeNode[0][1]
-      let kindOffsetLit = newLit(uint(getOffset(kindSym)))
-      dst.add quote do:
-        var kindTmp: `kindType`
-        jsonPath.add `kindPathLit`
-        initFromJson(kindTmp, `jsonNode`[`kindNameLit`], `jsonPath`)
-        jsonPath.setLen `originalJsonPathLen`
-        when defined js:
+      else:
+        initFromJson(`tmpSym`.`fieldSym`, getOrDefault(`jsonNode`,`fieldNameLit`), `jsonPath`)
+      jsonPath.setLen `originalJsonPathLen`
+
+  of nnkRecCase:
+    let kindSym = typeNode[0][0]
+    let kindNameLit = newLit(kindSym.strVal)
+    let kindPathLit = newLit("." & kindSym.strVal)
+    let kindType = typeNode[0][1]
+    let kindOffsetLit = newLit(uint(getOffset(kindSym)))
+    dst.add quote do:
+      var kindTmp: `kindType`
+      jsonPath.add `kindPathLit`
+      initFromJson(kindTmp, `jsonNode`[`kindNameLit`], `jsonPath`)
+      jsonPath.setLen `originalJsonPathLen`
+      when defined js:
+        `tmpSym`.`kindSym` = kindTmp
+      else:
+        when nimvm:
           `tmpSym`.`kindSym` = kindTmp
         else:
-          when nimvm:
-            `tmpSym`.`kindSym` = kindTmp
-          else:
-            # fuck it, assign kind field anyway
-            ((cast[ptr `kindType`](cast[uint](`tmpSym`.addr) + `kindOffsetLit`))[]) = kindTmp
-      dst.add nnkCaseStmt.newTree(nnkDotExpr.newTree(tmpSym, kindSym))
-      for i in 1 ..< typeNode.len:
-        foldObjectBody(dst, typeNode[i], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
-
-    of nnkOfBranch, nnkElse:
-      let ofBranch = newNimNode(typeNode.kind)
-      for i in 0 ..< typeNode.len-1:
-        ofBranch.add copyNimTree(typeNode[i])
-      let dstInner = newNimNode(nnkStmtListExpr)
-      foldObjectBody(dstInner, typeNode[^1], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
-      # resOuter now contains the inner stmtList
-      ofBranch.add dstInner
-      dst[^1].expectKind nnkCaseStmt
-      dst[^1].add ofBranch
-
-    of nnkObjectTy:
-      typeNode[0].expectKind nnkEmpty
-      typeNode[1].expectKind {nnkEmpty, nnkOfInherit}
-      if typeNode[1].kind == nnkOfInherit:
-        let base = typeNode[1][0]
-        var impl = getTypeImpl(base)
-        while impl.kind in {nnkRefTy, nnkPtrTy}:
-          impl = getTypeImpl(impl[0])
-        foldObjectBody(dst, impl, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
-      let body = typeNode[2]
-      foldObjectBody(dst, body, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
+          # fuck it, assign kind field anyway
+          ((cast[ptr `kindType`](cast[uint](`tmpSym`.addr) + `kindOffsetLit`))[]) = kindTmp
+    dst.add nnkCaseStmt.newTree(nnkDotExpr.newTree(tmpSym, kindSym))
+    for i in 1 ..< typeNode.len:
+      foldObjectBody(dst, typeNode[i], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
+
+  of nnkOfBranch, nnkElse:
+    let ofBranch = newNimNode(typeNode.kind)
+    for i in 0 ..< typeNode.len-1:
+      ofBranch.add copyNimTree(typeNode[i])
+    let dstInner = newNimNode(nnkStmtListExpr)
+    foldObjectBody(dstInner, typeNode[^1], tmpSym, jsonNode, jsonPath, originalJsonPathLen)
+    # resOuter now contains the inner stmtList
+    ofBranch.add dstInner
+    dst[^1].expectKind nnkCaseStmt
+    dst[^1].add ofBranch
+
+  of nnkObjectTy:
+    typeNode[0].expectKind nnkEmpty
+    typeNode[1].expectKind {nnkEmpty, nnkOfInherit}
+    if typeNode[1].kind == nnkOfInherit:
+      let base = typeNode[1][0]
+      var impl = getTypeImpl(base)
+      while impl.kind in {nnkRefTy, nnkPtrTy}:
+        impl = getTypeImpl(impl[0])
+      foldObjectBody(dst, impl, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
+    let body = typeNode[2]
+    foldObjectBody(dst, body, tmpSym, jsonNode, jsonPath, originalJsonPathLen)
 
-    else:
-      error("unhandled kind: " & $typeNode.kind, typeNode)
-
-  macro assignObjectImpl[T](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
-    let typeSym = getTypeInst(dst)
-    let originalJsonPathLen = genSym(nskLet, "originalJsonPathLen")
-    result = newStmtList()
-    result.add quote do:
-      let `originalJsonPathLen` = len(`jsonPath`)
-    if typeSym.kind in {nnkTupleTy, nnkTupleConstr}:
-      # both, `dst` and `typeSym` don't have good lineinfo. But nothing
-      # else is available here.
-      detectIncompatibleType(typeSym, dst)
-      foldObjectBody(result, typeSym, dst, jsonNode, jsonPath, originalJsonPathLen)
-    else:
-      foldObjectBody(result, typeSym.getTypeImpl, dst, jsonNode, jsonPath, originalJsonPathLen)
-
-  proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
-    assignObjectImpl(dst, jsonNode, jsonPath)
-
-  proc to*[T](node: JsonNode, t: typedesc[T]): T =
-    ## `Unmarshals`:idx: the specified node into the object type specified.
-    ##
-    ## Known limitations:
-    ##
-    ##   * Heterogeneous arrays are not supported.
-    ##   * Sets in object variants are not supported.
-    ##   * Not nil annotations are not supported.
-    ##
-    runnableExamples:
-      let jsonNode = parseJson("""
-        {
-          "person": {
-            "name": "Nimmer",
-            "age": 21
-          },
-          "list": [1, 2, 3, 4]
-        }
-      """)
-
-      type
-        Person = object
-          name: string
-          age: int
-
-        Data = object
-          person: Person
-          list: seq[int]
-
-      var data = to(jsonNode, Data)
-      doAssert data.person.name == "Nimmer"
-      doAssert data.person.age == 21
-      doAssert data.list == @[1, 2, 3, 4]
-
-    var jsonPath = ""
-    initFromJson(result, node, jsonPath)
+  else:
+    error("unhandled kind: " & $typeNode.kind, typeNode)
+
+macro assignObjectImpl[T](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
+  let typeSym = getTypeInst(dst)
+  let originalJsonPathLen = genSym(nskLet, "originalJsonPathLen")
+  result = newStmtList()
+  result.add quote do:
+    let `originalJsonPathLen` = len(`jsonPath`)
+  if typeSym.kind in {nnkTupleTy, nnkTupleConstr}:
+    # both, `dst` and `typeSym` don't have good lineinfo. But nothing
+    # else is available here.
+    detectIncompatibleType(typeSym, dst)
+    foldObjectBody(result, typeSym, dst, jsonNode, jsonPath, originalJsonPathLen)
+  else:
+    foldObjectBody(result, typeSym.getTypeImpl, dst, jsonNode, jsonPath, originalJsonPathLen)
+
+proc initFromJson[T: object|tuple](dst: var T; jsonNode: JsonNode; jsonPath: var string) =
+  assignObjectImpl(dst, jsonNode, jsonPath)
+
+proc to*[T](node: JsonNode, t: typedesc[T]): T =
+  ## `Unmarshals`:idx: the specified node into the object type specified.
+  ##
+  ## Known limitations:
+  ##
+  ##   * Heterogeneous arrays are not supported.
+  ##   * Sets in object variants are not supported.
+  ##   * Not nil annotations are not supported.
+  ##
+  runnableExamples:
+    let jsonNode = parseJson("""
+      {
+        "person": {
+          "name": "Nimmer",
+          "age": 21
+        },
+        "list": [1, 2, 3, 4]
+      }
+    """)
+
+    type
+      Person = object
+        name: string
+        age: int
+
+      Data = object
+        person: Person
+        list: seq[int]
+
+    var data = to(jsonNode, Data)
+    doAssert data.person.name == "Nimmer"
+    doAssert data.person.age == 21
+    doAssert data.list == @[1, 2, 3, 4]
+
+  var jsonPath = ""
+  result = default(T)
+  initFromJson(result, node, jsonPath)
 
 when false:
-  import os
+  import std/os
   var s = newFileStream(paramStr(1), fmRead)
   if s == nil: quit("cannot open the file" & paramStr(1))
   var x: JsonParser
diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim
index 336a57ec1..1efd97b24 100644
--- a/lib/pure/lexbase.nim
+++ b/lib/pure/lexbase.nim
@@ -12,7 +12,7 @@
 ## needs refilling.
 
 import
-  strutils, streams
+  std/[strutils, streams]
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -104,9 +104,9 @@ 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
+  ## 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'.
+  ## of the `'\c'`.
   assert(L.buf[pos] == '\c')
   inc(L.lineNumber)
   result = fillBaseLexer(L, pos)
@@ -115,9 +115,9 @@ 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
+  ## 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'.
+  ## of the `'\L'`.
   assert(L.buf[pos] == '\L')
   inc(L.lineNumber)
   result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result;
diff --git a/lib/pure/logging.nim b/lib/pure/logging.nim
index 46b59b750..c30f68af8 100644
--- a/lib/pure/logging.nim
+++ b/lib/pure/logging.nim
@@ -17,10 +17,11 @@
 ##
 ## To get started, first create a logger:
 ##
-## .. code-block::
+##   ```Nim
 ##   import std/logging
 ##
 ##   var logger = newConsoleLogger()
+##   ```
 ##
 ## The logger that was created above logs to the console, but this module
 ## also provides loggers that log to files, such as the
@@ -30,9 +31,10 @@
 ## Once a logger has been created, call its `log proc
 ## <#log.e,ConsoleLogger,Level,varargs[string,]>`_ to log a message:
 ##
-## .. code-block::
+##   ```Nim
 ##   logger.log(lvlInfo, "a log message")
 ##   # Output: INFO a log message
+##   ```
 ##
 ## The ``INFO`` within the output is the result of a format string being
 ## prepended to the message, and it will differ depending on the message's
@@ -58,7 +60,7 @@
 ## used with the `addHandler proc<#addHandler,Logger>`_, which is demonstrated
 ## in the following example:
 ##
-## .. code-block::
+##   ```Nim
 ##   import std/logging
 ##
 ##   var consoleLog = newConsoleLogger()
@@ -68,17 +70,19 @@
 ##   addHandler(consoleLog)
 ##   addHandler(fileLog)
 ##   addHandler(rollingLog)
+##   ```
 ##
 ## After doing this, use either the `log template
 ## <#log.t,Level,varargs[string,]>`_ or one of the level-specific templates,
 ## such as the `error template<#error.t,varargs[string,]>`_, to log messages
 ## to all registered handlers at once.
 ##
-## .. code-block::
+##   ```Nim
 ##   # This example uses the loggers created above
 ##   log(lvlError, "an error occurred")
 ##   error("an error occurred")  # Equivalent to the above line
 ##   info("something normal happened")  # Will not be written to errors.log
+##   ```
 ##
 ## Note that a message's level is still checked against each handler's
 ## ``levelThreshold`` and the global log filter.
@@ -116,12 +120,13 @@
 ##
 ## The following example illustrates how to use format strings:
 ##
-## .. code-block::
+##   ```Nim
 ##   import std/logging
 ##
 ##   var logger = newConsoleLogger(fmtStr="[$time] - $levelname: ")
 ##   logger.log(lvlInfo, "this is a message")
 ##   # Output: [19:50:13] - INFO: this is a message
+##   ```
 ##
 ## Notes when using multiple threads
 ## ---------------------------------
@@ -141,9 +146,9 @@
 ## * `strscans module<strscans.html>`_ for ``scanf`` and ``scanp`` macros, which
 ##   offer easier substring extraction than regular expressions
 
-import strutils, times
+import std/[strutils, times]
 when not defined(js):
-  import os
+  import std/os
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -372,10 +377,11 @@ method log*(logger: ConsoleLogger, level: Level, args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var consoleLog = newConsoleLogger()
   ##   consoleLog.log(lvlInfo, "this is a message")
   ##   consoleLog.log(lvlError, "error code is: ", 404)
+  ##   ```
   if level >= logging.level and level >= logger.levelThreshold:
     let ln = substituteLog(logger.fmtStr, level, args)
     when defined(js):
@@ -414,10 +420,11 @@ proc newConsoleLogger*(levelThreshold = lvlAll, fmtStr = defaultFmtStr,
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var normalLog = newConsoleLogger()
   ##   var formatLog = newConsoleLogger(fmtStr=verboseFmtStr)
   ##   var errorLog = newConsoleLogger(levelThreshold=lvlError, useStderr=true)
+  ##   ```
   new result
   result.fmtStr = fmtStr
   result.levelThreshold = levelThreshold
@@ -450,10 +457,11 @@ when not defined(js):
     ##
     ## **Examples:**
     ##
-    ## .. code-block::
+    ##   ```Nim
     ##   var fileLog = newFileLogger("messages.log")
     ##   fileLog.log(lvlInfo, "this is a message")
     ##   fileLog.log(lvlError, "error code is: ", 404)
+    ##   ```
     if level >= logging.level and level >= logger.levelThreshold:
       writeLine(logger.file, substituteLog(logger.fmtStr, level, args))
       if level >= logger.flushThreshold: flushFile(logger.file)
@@ -481,7 +489,7 @@ when not defined(js):
     ##
     ## **Examples:**
     ##
-    ## .. code-block::
+    ##   ```Nim
     ##   var messages = open("messages.log", fmWrite)
     ##   var formatted = open("formatted.log", fmWrite)
     ##   var errors = open("errors.log", fmWrite)
@@ -489,6 +497,7 @@ when not defined(js):
     ##   var normalLog = newFileLogger(messages)
     ##   var formatLog = newFileLogger(formatted, fmtStr=verboseFmtStr)
     ##   var errorLog = newFileLogger(errors, levelThreshold=lvlError)
+    ##   ```
     new(result)
     result.file = file
     result.levelThreshold = levelThreshold
@@ -519,10 +528,11 @@ when not defined(js):
     ##
     ## **Examples:**
     ##
-    ## .. code-block::
+    ##   ```Nim
     ##   var normalLog = newFileLogger("messages.log")
     ##   var formatLog = newFileLogger("formatted.log", fmtStr=verboseFmtStr)
     ##   var errorLog = newFileLogger("errors.log", levelThreshold=lvlError)
+    ##   ```
     let file = open(filename, mode, bufSize = bufSize)
     newFileLogger(file, levelThreshold, fmtStr, flushThreshold)
 
@@ -579,11 +589,12 @@ when not defined(js):
     ##
     ## **Examples:**
     ##
-    ## .. code-block::
+    ##   ```Nim
     ##   var normalLog = newRollingFileLogger("messages.log")
     ##   var formatLog = newRollingFileLogger("formatted.log", fmtStr=verboseFmtStr)
     ##   var shortLog = newRollingFileLogger("short.log", maxLines=200)
     ##   var errorLog = newRollingFileLogger("errors.log", levelThreshold=lvlError)
+    ##   ```
     new(result)
     result.levelThreshold = levelThreshold
     result.fmtStr = fmtStr
@@ -633,10 +644,11 @@ when not defined(js):
     ##
     ## **Examples:**
     ##
-    ## .. code-block::
+    ##   ```Nim
     ##   var rollingLog = newRollingFileLogger("messages.log")
     ##   rollingLog.log(lvlInfo, "this is a message")
     ##   rollingLog.log(lvlError, "error code is: ", 404)
+    ##   ```
     if level >= logging.level and level >= logger.levelThreshold:
       if logger.curLine >= logger.maxLines:
         logger.file.close()
@@ -666,11 +678,12 @@ template log*(level: Level, args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var logger = newConsoleLogger()
   ##   addHandler(logger)
   ##
   ##   log(lvlInfo, "This is an example.")
+  ##   ```
   ##
   ## See also:
   ## * `debug template<#debug.t,varargs[string,]>`_
@@ -695,11 +708,12 @@ template debug*(args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var logger = newConsoleLogger()
   ##   addHandler(logger)
   ##
   ##   debug("myProc called with arguments: foo, 5")
+  ##   ```
   ##
   ## See also:
   ## * `log template<#log.t,Level,varargs[string,]>`_
@@ -716,11 +730,12 @@ template info*(args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var logger = newConsoleLogger()
   ##   addHandler(logger)
   ##
   ##   info("Application started successfully.")
+  ##   ```
   ##
   ## See also:
   ## * `log template<#log.t,Level,varargs[string,]>`_
@@ -737,11 +752,12 @@ template notice*(args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var logger = newConsoleLogger()
   ##   addHandler(logger)
   ##
   ##   notice("An important operation has completed.")
+  ##   ```
   ##
   ## See also:
   ## * `log template<#log.t,Level,varargs[string,]>`_
@@ -757,11 +773,12 @@ template warn*(args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var logger = newConsoleLogger()
   ##   addHandler(logger)
   ##
   ##   warn("The previous operation took too long to process.")
+  ##   ```
   ##
   ## See also:
   ## * `log template<#log.t,Level,varargs[string,]>`_
@@ -779,11 +796,12 @@ template error*(args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var logger = newConsoleLogger()
   ##   addHandler(logger)
   ##
   ##   error("An exception occurred while processing the form.")
+  ##   ```
   ##
   ## See also:
   ## * `log template<#log.t,Level,varargs[string,]>`_
@@ -800,11 +818,12 @@ template fatal*(args: varargs[string, `$`]) =
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var logger = newConsoleLogger()
   ##   addHandler(logger)
   ##
   ##   fatal("Can't open database -- exiting.")
+  ##   ```
   ##
   ## See also:
   ## * `log template<#log.t,Level,varargs[string,]>`_
@@ -820,6 +839,7 @@ proc addHandler*(handler: Logger) =
   ##   each of those threads.
   ##
   ## See also:
+  ## * `removeHandler proc`_
   ## * `getHandlers proc<#getHandlers>`_
   runnableExamples:
     var logger = newConsoleLogger()
@@ -827,6 +847,16 @@ proc addHandler*(handler: Logger) =
     doAssert logger in getHandlers()
   handlers.add(handler)
 
+proc removeHandler*(handler: Logger) =
+  ## Removes a logger from the list of registered handlers.
+  ##
+  ## Note that for n times a logger is registered, n calls to this proc
+  ## are required to remove that logger.
+  for i, hnd in handlers:
+    if hnd == handler:
+      handlers.delete(i)
+      return
+
 proc getHandlers*(): seq[Logger] =
   ## Returns a list of all the registered handlers.
   ##
diff --git a/lib/pure/marshal.nim b/lib/pure/marshal.nim
index 848d7e3fb..f9b3d3e4c 100644
--- a/lib/pure/marshal.nim
+++ b/lib/pure/marshal.nim
@@ -54,7 +54,7 @@ Please use alternative packages for serialization.
 It is possible to reimplement this module using generics and type traits.
 Please contribute a new implementation.""".}
 
-import streams, typeinfo, json, intsets, tables, unicode
+import std/[streams, typeinfo, json, intsets, tables, unicode]
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, formatfloat]
@@ -210,7 +210,8 @@ proc loadAny(p: var JsonParser, a: Any, t: var Table[BiggestInt, pointer]) =
       setPointer(a, nil)
       next(p)
     of jsonInt:
-      setPointer(a, t.getOrDefault(p.getInt))
+      var raw = t.getOrDefault(p.getInt)
+      setPointer(a, addr raw)
       next(p)
     of jsonArrayStart:
       next(p)
@@ -304,7 +305,7 @@ proc store*[T](s: Stream, data: sink T) =
 
   var stored = initIntSet()
   var d: T
-  when defined(gcArc) or defined(gcOrc):
+  when defined(gcArc) or defined(gcOrc)or defined(gcAtomicArc):
     d = data
   else:
     shallowCopy(d, data)
@@ -333,7 +334,7 @@ proc `$$`*[T](x: sink T): string =
   else:
     var stored = initIntSet()
     var d: T
-    when defined(gcArc) or defined(gcOrc):
+    when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
       d = x
     else:
       shallowCopy(d, x)
diff --git a/lib/pure/math.nim b/lib/pure/math.nim
index bea655a0e..ed7d2382f 100644
--- a/lib/pure/math.nim
+++ b/lib/pure/math.nim
@@ -57,13 +57,14 @@ import std/private/since
 {.push debugger: off.} # the user does not want to trace a part
                        # of the standard library!
 
-import bitops, fenv
+import std/[bitops, fenv]
+import system/countbits_impl
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
 
-when defined(c) or defined(cpp):
+when not defined(js) and not defined(nimscript): # C
   proc c_isnan(x: float): bool {.importc: "isnan", header: "<math.h>".}
     # a generic like `x: SomeFloat` might work too if this is implemented via a C macro.
 
@@ -77,6 +78,41 @@ when defined(c) or defined(cpp):
       importc: "frexpf", header: "<math.h>".}
   func c_frexp2(x: cdouble, exponent: var cint): cdouble {.
       importc: "frexp", header: "<math.h>".}
+  
+  type
+    div_t {.importc, header: "<stdlib.h>".} = object
+      quot: cint
+      rem: cint
+    ldiv_t {.importc, header: "<stdlib.h>".} = object
+      quot: clong
+      rem: clong
+    lldiv_t {.importc, header: "<stdlib.h>".} = object
+      quot: clonglong
+      rem: clonglong
+  
+  when cint isnot clong:
+    func divmod_c(x, y: cint): div_t {.importc: "div", header: "<stdlib.h>".}
+  when clong isnot clonglong:
+    func divmod_c(x, y: clonglong): lldiv_t {.importc: "lldiv", header: "<stdlib.h>".}
+  func divmod_c(x, y: clong): ldiv_t {.importc: "ldiv", header: "<stdlib.h>".}
+  func divmod*[T: SomeInteger](x, y: T): (T, T) {.inline.} = 
+    ## Specialized instructions for computing both division and modulus.
+    ## Return structure is: (quotient, remainder)
+    runnableExamples:
+      doAssert divmod(5, 2) == (2, 1)
+      doAssert divmod(5, -3) == (-1, 2)
+    when T is cint | clong | clonglong:
+      when compileOption("overflowChecks"):
+        if y == 0:
+          raise new(DivByZeroDefect)
+        elif (x == T.low and y == -1.T):
+          raise new(OverflowDefect)
+      let res = divmod_c(x, y)
+      result[0] = res.quot
+      result[1] = res.rem
+    else:
+      result[0] = x div y
+      result[1] = x mod y
 
 func binom*(n, k: int): int =
   ## Computes the [binomial coefficient](https://en.wikipedia.org/wiki/Binomial_coefficient).
@@ -120,7 +156,7 @@ func fac*(n: int): int =
 
 {.push checks: off, line_dir: off, stack_trace: off.}
 
-when defined(posix) and not defined(genode):
+when defined(posix) and not defined(genode) and not defined(macosx):
   {.passl: "-lm".}
 
 const
@@ -165,7 +201,7 @@ func isNaN*(x: SomeFloat): bool {.inline, since: (1,5,1).} =
   template fn: untyped = result = x != x
   when nimvm: fn()
   else:
-    when defined(js): fn()
+    when defined(js) or defined(nimscript): fn()
     else: result = c_isnan(x)
 
 when defined(js):
@@ -184,13 +220,13 @@ when defined(js):
     let a = newFloat64Array(buffer)
     let b = newUint32Array(buffer)
     a[0] = x
-    asm """
+    {.emit: """
     function updateBit(num, bitPos, bitVal) {
       return (num & ~(1 << bitPos)) | (bitVal << bitPos);
     }
     `b`[1] = updateBit(`b`[1], 31, `sgn`);
-    `result` = `a`[0]
-    """
+    `result` = `a`[0];
+    """.}
 
 proc signbit*(x: SomeFloat): bool {.inline, since: (1, 5, 1).} =
   ## Returns true if `x` is negative, false otherwise.
@@ -235,7 +271,6 @@ func classify*(x: float): FloatClass =
   ## Classifies a floating point value.
   ##
   ## Returns `x`'s class as specified by the `FloatClass enum<#FloatClass>`_.
-  ## Doesn't work with `--passc:-ffast-math`.
   runnableExamples:
     doAssert classify(0.3) == fcNormal
     doAssert classify(0.0) == fcZero
@@ -244,6 +279,7 @@ func classify*(x: float): FloatClass =
     doAssert classify(5.0e-324) == fcSubnormal
 
   # JavaScript and most C compilers have no classify:
+  if isNan(x): return fcNan
   if x == 0.0:
     if 1.0 / x == Inf:
       return fcZero
@@ -252,7 +288,6 @@ func classify*(x: float): FloatClass =
   if x * 0.5 == x:
     if x > 0.0: return fcInf
     else: return fcNegInf
-  if x != x: return fcNan
   if abs(x) < MinFloatNormal:
     return fcSubnormal
   return fcNormal
@@ -326,68 +361,8 @@ func nextPowerOfTwo*(x: int): int =
   result = result or (result shr 1)
   result += 1 + ord(x <= 0)
 
-func sum*[T](x: openArray[T]): T =
-  ## Computes the sum of the elements in `x`.
-  ##
-  ## If `x` is empty, 0 is returned.
-  ##
-  ## **See also:**
-  ## * `prod func <#prod,openArray[T]>`_
-  ## * `cumsum func <#cumsum,openArray[T]>`_
-  ## * `cumsummed func <#cumsummed,openArray[T]>`_
-  runnableExamples:
-    doAssert sum([1, 2, 3, 4]) == 10
-    doAssert sum([-4, 3, 5]) == 4
-
-  for i in items(x): result = result + i
-
-func prod*[T](x: openArray[T]): T =
-  ## Computes the product of the elements in `x`.
-  ##
-  ## If `x` is empty, 1 is returned.
-  ##
-  ## **See also:**
-  ## * `sum func <#sum,openArray[T]>`_
-  ## * `fac func <#fac,int>`_
-  runnableExamples:
-    doAssert prod([1, 2, 3, 4]) == 24
-    doAssert prod([-4, 3, 5]) == -60
-
-  result = T(1)
-  for i in items(x): result = result * i
-
-func cumsummed*[T](x: openArray[T]): seq[T] =
-  ## Returns the cumulative (aka prefix) summation of `x`.
-  ##
-  ## If `x` is empty, `@[]` is returned.
-  ##
-  ## **See also:**
-  ## * `sum func <#sum,openArray[T]>`_
-  ## * `cumsum func <#cumsum,openArray[T]>`_ for the in-place version
-  runnableExamples:
-    doAssert cumsummed([1, 2, 3, 4]) == @[1, 3, 6, 10]
-
-  let xLen = x.len
-  if xLen == 0:
-    return @[]
-  result.setLen(xLen)
-  result[0] = x[0]
-  for i in 1 ..< xLen: result[i] = result[i - 1] + x[i]
 
-func cumsum*[T](x: var openArray[T]) =
-  ## Transforms `x` in-place (must be declared as `var`) into its
-  ## cumulative (aka prefix) summation.
-  ##
-  ## **See also:**
-  ## * `sum func <#sum,openArray[T]>`_
-  ## * `cumsummed func <#cumsummed,openArray[T]>`_ for a version which
-  ##   returns a cumsummed sequence
-  runnableExamples:
-    var a = [1, 2, 3, 4]
-    cumsum(a)
-    doAssert a == @[1, 3, 6, 10]
 
-  for i in 1 ..< x.len: x[i] = x[i - 1] + x[i]
 
 when not defined(js): # C
   func sqrt*(x: float32): float32 {.importc: "sqrtf", header: "<math.h>".}
@@ -853,6 +828,14 @@ else: # JS
       doAssert -6.5 mod  2.5 == -1.5
       doAssert  6.5 mod -2.5 ==  1.5
       doAssert -6.5 mod -2.5 == -1.5
+  
+  func divmod*[T:SomeInteger](num, denom: T): (T, T) = 
+    runnableExamples:
+      doAssert  divmod(5, 2) ==  (2, 1)
+      doAssert divmod(5, -3) == (-1, 2)
+    result[0] = num div denom
+    result[1] = num mod denom
+  
 
 func round*[T: float32|float64](x: T, places: int): T =
   ## Decimal rounding on a binary floating point number.
@@ -1133,6 +1116,69 @@ func sgn*[T: SomeNumber](x: T): int {.inline.} =
 {.pop.}
 {.pop.}
 
+func sum*[T](x: openArray[T]): T =
+  ## Computes the sum of the elements in `x`.
+  ##
+  ## If `x` is empty, 0 is returned.
+  ##
+  ## **See also:**
+  ## * `prod func <#prod,openArray[T]>`_
+  ## * `cumsum func <#cumsum,openArray[T]>`_
+  ## * `cumsummed func <#cumsummed,openArray[T]>`_
+  runnableExamples:
+    doAssert sum([1, 2, 3, 4]) == 10
+    doAssert sum([-4, 3, 5]) == 4
+
+  for i in items(x): result = result + i
+
+func prod*[T](x: openArray[T]): T =
+  ## Computes the product of the elements in `x`.
+  ##
+  ## If `x` is empty, 1 is returned.
+  ##
+  ## **See also:**
+  ## * `sum func <#sum,openArray[T]>`_
+  ## * `fac func <#fac,int>`_
+  runnableExamples:
+    doAssert prod([1, 2, 3, 4]) == 24
+    doAssert prod([-4, 3, 5]) == -60
+
+  result = T(1)
+  for i in items(x): result = result * i
+
+func cumsummed*[T](x: openArray[T]): seq[T] =
+  ## Returns the cumulative (aka prefix) summation of `x`.
+  ##
+  ## If `x` is empty, `@[]` is returned.
+  ##
+  ## **See also:**
+  ## * `sum func <#sum,openArray[T]>`_
+  ## * `cumsum func <#cumsum,openArray[T]>`_ for the in-place version
+  runnableExamples:
+    doAssert cumsummed([1, 2, 3, 4]) == @[1, 3, 6, 10]
+
+  let xLen = x.len
+  if xLen == 0:
+    return @[]
+  result.setLen(xLen)
+  result[0] = x[0]
+  for i in 1 ..< xLen: result[i] = result[i - 1] + x[i]
+
+func cumsum*[T](x: var openArray[T]) =
+  ## Transforms `x` in-place (must be declared as `var`) into its
+  ## cumulative (aka prefix) summation.
+  ##
+  ## **See also:**
+  ## * `sum func <#sum,openArray[T]>`_
+  ## * `cumsummed func <#cumsummed,openArray[T]>`_ for a version which
+  ##   returns a cumsummed sequence
+  runnableExamples:
+    var a = [1, 2, 3, 4]
+    cumsum(a)
+    doAssert a == @[1, 3, 6, 10]
+
+  for i in 1 ..< x.len: x[i] = x[i - 1] + x[i]
+
 func `^`*[T: SomeNumber](x: T, y: Natural): T =
   ## Computes `x` to the power of `y`.
   ##
@@ -1184,40 +1230,42 @@ func gcd*[T](x, y: T): T =
     swap x, y
   abs x
 
-func gcd*(x, y: SomeInteger): SomeInteger =
-  ## Computes the greatest common (positive) divisor of `x` and `y`,
-  ## using the binary GCD (aka Stein's) algorithm.
-  ##
-  ## **See also:**
-  ## * `gcd func <#gcd,T,T>`_ for a float version
-  ## * `lcm func <#lcm,T,T>`_
-  runnableExamples:
-    doAssert gcd(12, 8) == 4
-    doAssert gcd(17, 63) == 1
-
-  when x is SomeSignedInt:
-    var x = abs(x)
-  else:
-    var x = x
-  when y is SomeSignedInt:
-    var y = abs(y)
-  else:
-    var y = y
-
-  if x == 0:
-    return y
-  if y == 0:
-    return x
-
-  let shift = countTrailingZeroBits(x or y)
-  y = y shr countTrailingZeroBits(y)
-  while x != 0:
-    x = x shr countTrailingZeroBits(x)
-    if y > x:
-      swap y, x
-    x -= y
-  y shl shift
-
+when useBuiltins:
+  ## this func uses bitwise comparisons from C compilers, which are not always available.
+  func gcd*(x, y: SomeInteger): SomeInteger =
+    ## Computes the greatest common (positive) divisor of `x` and `y`,
+    ## using the binary GCD (aka Stein's) algorithm.
+    ##
+    ## **See also:**
+    ## * `gcd func <#gcd,T,T>`_ for a float version
+    ## * `lcm func <#lcm,T,T>`_
+    runnableExamples:
+      doAssert gcd(12, 8) == 4
+      doAssert gcd(17, 63) == 1
+  
+    when x is SomeSignedInt:
+      var x = abs(x)
+    else:
+      var x = x
+    when y is SomeSignedInt:
+      var y = abs(y)
+    else:
+      var y = y
+  
+    if x == 0:
+      return y
+    if y == 0:
+      return x
+  
+    let shift = countTrailingZeroBits(x or y)
+    y = y shr countTrailingZeroBits(y)
+    while x != 0:
+      x = x shr countTrailingZeroBits(x)
+      if y > x:
+        swap y, x
+      x -= y
+    y shl shift
+  
 func gcd*[T](x: openArray[T]): T {.since: (1, 1).} =
   ## Computes the greatest common (positive) divisor of the elements of `x`.
   ##
diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim
index cd4d1e6b8..9c3f6d51b 100644
--- a/lib/pure/md5.nim
+++ b/lib/pure/md5.nim
@@ -14,10 +14,12 @@
 ## See also
 ## ========
 ## * `base64 module<base64.html>`_ for a Base64 encoder and decoder
-## * `std/sha1 module <sha1.html>`_ for the SHA-1 checksum algorithm
+## * `sha1 module <sha1.html>`_ for the SHA-1 checksum algorithm
 ## * `hashes module<hashes.html>`_ for efficient computations of hash values
 ##   for diverse Nim types
 
+{.deprecated: "use command `nimble install checksums` and import `checksums/md5` instead".}
+
 when defined(nimHasStyleChecks):
   {.push styleChecks: off.}
 
@@ -98,32 +100,19 @@ proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
     dest[i+3] = uint8(src[j] shr 24 and 0xff'u32)
     inc(i, 4)
 
-template slice(s: string, a, b): openArray[uint8] =
-  when nimvm:
-    # toOpenArray is not implemented in VM
-    var s2 = newSeq[uint8](s.len)
-    for i in 0 ..< s2.len:
-      s2[i] = uint8(s[i])
-    s2
-  else:
-    s.toOpenArrayByte(a, b)
-
 template slice(s: cstring, a, b): openArray[uint8] =
   when nimvm:
     # toOpenArray is not implemented in VM
-    slice($s, a, b)
+    toOpenArrayByte($s, a, b)
   else:
     when defined(js):
       # toOpenArrayByte for cstring is not implemented in JS
-      slice($s, a, b)
+      toOpenArrayByte($s, a, b)
     else:
       s.toOpenArrayByte(a, b)
 
 template slice(s: openArray[uint8], a, b): openArray[uint8] =
-  when nimvm:
-    s[a .. b]
-  else:
-    s.toOpenArray(a, b)
+  s.toOpenArray(a, b)
 
 const useMem = declared(copyMem)
 
@@ -343,4 +332,4 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
 
 
 when defined(nimHasStyleChecks):
-  {.pop.} #{.push styleChecks: off.}
+  {.pop.} #{.push styleChecks: off.}
\ No newline at end of file
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index 48c07b149..8eec551c4 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -16,15 +16,15 @@
 ## other "line-like", variable length, delimited records).
 
 when defined(windows):
-  import winlean
-  when useWinUnicode and defined(nimPreviewSlimSystem):
+  import std/winlean
+  when defined(nimPreviewSlimSystem):
     import std/widestrs
 elif defined(posix):
-  import posix
+  import std/posix
 else:
   {.error: "the memfiles module is not supported on your operating system!".}
 
-import streams
+import std/streams
 import std/oserrors
 
 when defined(nimPreviewSlimSystem):
@@ -35,6 +35,35 @@ proc newEIO(msg: string): ref IOError =
   new(result)
   result.msg = msg
 
+proc setFileSize(fh: FileHandle, newFileSize = -1, oldSize = -1): OSErrorCode =
+  ## Set the size of open file pointed to by `fh` to `newFileSize` if != -1,
+  ## allocating | freeing space from the file system.  This routine returns the
+  ## last OSErrorCode found rather than raising to support old rollback/clean-up
+  ## code style. [ Should maybe move to std/osfiles. ]
+  if newFileSize < 0 or newFileSize == oldSize:
+    return
+  when defined(windows):
+    var sizeHigh = int32(newFileSize shr 32)
+    let sizeLow = int32(newFileSize and 0xffffffff)
+    let status = setFilePointer(fh, sizeLow, addr(sizeHigh), FILE_BEGIN)
+    let lastErr = osLastError()
+    if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
+        setEndOfFile(fh) == 0:
+      result = lastErr
+  else:
+    if newFileSize > oldSize: # grow the file
+      var e: cint # posix_fallocate truncates up when needed.
+      when declared(posix_fallocate):
+        while (e = posix_fallocate(fh, 0, newFileSize); e == EINTR):
+          discard
+      if e in [EINVAL, EOPNOTSUPP] and ftruncate(fh, newFileSize) == -1:
+        result = osLastError() # fallback arguable; Most portable BUT allows SEGV
+      elif e != 0:
+        result = osLastError()
+    else: # shrink the file
+      if ftruncate(fh.cint, newFileSize) == -1:
+        result = osLastError()
+
 type
   MemFile* = object      ## represents a memory mapped file
     mem*: pointer        ## a pointer to the memory mapped file. The pointer
@@ -125,7 +154,7 @@ proc open*(filename: string, mode: FileMode = fmRead,
   ##
   ## Example:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   var
   ##     mm, mm_full, mm_half: MemFile
   ##
@@ -137,6 +166,7 @@ proc open*(filename: string, mode: FileMode = fmRead,
   ##
   ##   # Read the first 512 bytes
   ##   mm_half = memfiles.open("/tmp/test.mmap", mode = fmReadWrite, mappedSize = 512)
+  ##   ```
 
   # The file can be resized only when write mode is used:
   if mode == fmAppend:
@@ -174,25 +204,13 @@ proc open*(filename: string, mode: FileMode = fmRead,
         else: FILE_ATTRIBUTE_NORMAL or flags,
         0)
 
-    when useWinUnicode:
-      result.fHandle = callCreateFile(createFileW, newWideCString(filename))
-    else:
-      result.fHandle = callCreateFile(createFileA, filename)
+    result.fHandle = callCreateFile(createFileW, newWideCString(filename))
 
     if result.fHandle == INVALID_HANDLE_VALUE:
       fail(osLastError(), "error opening file")
 
-    if newFileSize != -1:
-      var
-        sizeHigh = int32(newFileSize shr 32)
-        sizeLow = int32(newFileSize and 0xffffffff)
-
-      var status = setFilePointer(result.fHandle, sizeLow, addr(sizeHigh),
-                                  FILE_BEGIN)
-      let lastErr = osLastError()
-      if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or
-          (setEndOfFile(result.fHandle) == 0):
-        fail(lastErr, "error setting file size")
+    if (let e = setFileSize(result.fHandle.FileHandle, newFileSize);
+        e != 0.OSErrorCode): fail(e, "error setting file size")
 
     # since the strings are always 'nil', we simply always call
     # CreateFileMappingW which should be slightly faster anyway:
@@ -226,7 +244,7 @@ proc open*(filename: string, mode: FileMode = fmRead,
 
     result.wasOpened = true
     if not allowRemap and result.fHandle != INVALID_HANDLE_VALUE:
-      if closeHandle(result.fHandle) == 0:
+      if closeHandle(result.fHandle) != 0:
         result.fHandle = INVALID_HANDLE_VALUE
 
   else:
@@ -241,42 +259,31 @@ proc open*(filename: string, mode: FileMode = fmRead,
       flags = flags or O_CREAT or O_TRUNC
       var permissionsMode = S_IRUSR or S_IWUSR
       result.handle = open(filename, flags, permissionsMode)
+      if result.handle != -1:
+        if (let e = setFileSize(result.handle.FileHandle, newFileSize);
+            e != 0.OSErrorCode): fail(e, "error setting file size")
     else:
       result.handle = open(filename, flags)
 
     if result.handle == -1:
-      # XXX: errno is supposed to be set here
-      # Is there an exception that wraps it?
       fail(osLastError(), "error opening file")
 
-    if newFileSize != -1:
-      if ftruncate(result.handle, newFileSize) == -1:
-        fail(osLastError(), "error setting file size")
-
-    if mappedSize != -1:
-      result.size = mappedSize
-    else:
-      var stat: Stat
+    if mappedSize != -1: #XXX Logic here differs from `when windows` branch ..
+      result.size = mappedSize #.. which always fstats&Uses min(mappedSize, st).
+    else: # if newFileSize!=-1: result.size=newFileSize # if trust setFileSize
+      var stat: Stat  #^^.. BUT some FSes (eg. Linux HugeTLBfs) round to 2MiB.
       if fstat(result.handle, stat) != -1:
-        # XXX: Hmm, this could be unsafe
-        # Why is mmap taking int anyway?
-        result.size = int(stat.st_size)
+        result.size = stat.st_size.int # int may be 32-bit-unsafe for 2..<4 GiB
       else:
         fail(osLastError(), "error getting file size")
 
     result.flags = if mapFlags == cint(-1): MAP_SHARED else: mapFlags
-    #Ensure exactly one of MAP_PRIVATE cr MAP_SHARED is set
+    # Ensure exactly one of MAP_PRIVATE cr MAP_SHARED is set
     if int(result.flags and MAP_PRIVATE) == 0:
       result.flags = result.flags or MAP_SHARED
 
-    result.mem = mmap(
-      nil,
-      result.size,
-      if readonly: PROT_READ else: PROT_READ or PROT_WRITE,
-      result.flags,
-      result.handle,
-      offset)
-
+    let pr = if readonly: PROT_READ else: PROT_READ or PROT_WRITE
+    result.mem = mmap(nil, result.size, pr, result.flags, result.handle, offset)
     if result.mem == cast[pointer](MAP_FAILED):
       fail(osLastError(), "file mapping failed")
 
@@ -306,34 +313,58 @@ proc flush*(f: var MemFile; attempts: Natural = 3) =
       if lastErr != EBUSY.OSErrorCode:
         raiseOSError(lastErr, "error flushing mapping")
 
-when defined(posix) or defined(nimdoc):
-  proc resize*(f: var MemFile, newFileSize: int) {.raises: [IOError, OSError].} =
-    ## resize and re-map the file underlying an `allowRemap MemFile`.
-    ## **Note**: this assumes the entire file is mapped read-write at offset zero.
-    ## Also, the value of `.mem` will probably change.
-    ## **Note**: This is not (yet) available on Windows.
-    when defined(posix):
-      if f.handle == -1:
-        raise newException(IOError,
-                            "Cannot resize MemFile opened with allowRemap=false")
-      if ftruncate(f.handle, newFileSize) == -1:
-        raiseOSError(osLastError())
-      when defined(linux): #Maybe NetBSD, too?
-        #On Linux this can be over 100 times faster than a munmap,mmap cycle.
-        proc mremap(old: pointer; oldSize, newSize: csize_t; flags: cint):
-            pointer {.importc: "mremap", header: "<sys/mman.h>".}
-        let newAddr = mremap(f.mem, csize_t(f.size), csize_t(newFileSize), cint(1))
-        if newAddr == cast[pointer](MAP_FAILED):
-          raiseOSError(osLastError())
-      else:
-        if munmap(f.mem, f.size) != 0:
-          raiseOSError(osLastError())
-        let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE,
-                           f.flags, f.handle, 0)
-        if newAddr == cast[pointer](MAP_FAILED):
-          raiseOSError(osLastError())
-      f.mem = newAddr
+proc resize*(f: var MemFile, newFileSize: int) {.raises: [IOError, OSError].} =
+  ## Resize & re-map the file underlying an `allowRemap MemFile`.  If the OS/FS
+  ## supports it, file space is reserved to ensure room for new virtual pages.
+  ## Caller should wait often enough for `flush` to finish to limit use of
+  ## system RAM for write buffering, perhaps just prior to this call.
+  ## **Note**: this assumes the entire file is mapped read-write at offset 0.
+  ## Also, the value of `.mem` will probably change.
+  if newFileSize < 1: # Q: include system/bitmasks & use PageSize ?
+    raise newException(IOError, "Cannot resize MemFile to < 1 byte")
+  when defined(windows):
+    if not f.wasOpened:
+      raise newException(IOError, "Cannot resize unopened MemFile")
+    if f.fHandle == INVALID_HANDLE_VALUE:
+      raise newException(IOError,
+                         "Cannot resize MemFile opened with allowRemap=false")
+    if unmapViewOfFile(f.mem) == 0 or closeHandle(f.mapHandle) == 0: # Un-do map
+      raiseOSError(osLastError())
+    if newFileSize != f.size: # Seek to size & `setEndOfFile` => allocated.
+      if (let e = setFileSize(f.fHandle.FileHandle, newFileSize);
+          e != 0.OSErrorCode): raiseOSError(e)
+    f.mapHandle = createFileMappingW(f.fHandle, nil, PAGE_READWRITE, 0,0,nil)
+    if f.mapHandle == 0:                                             # Re-do map
+      raiseOSError(osLastError())
+    if (let m = mapViewOfFileEx(f.mapHandle, FILE_MAP_READ or FILE_MAP_WRITE,
+                                0, 0, WinSizeT(newFileSize), nil); m != nil):
+      f.mem  = m
       f.size = newFileSize
+    else:
+      raiseOSError(osLastError())
+  elif defined(posix):
+    if f.handle == -1:
+      raise newException(IOError,
+                         "Cannot resize MemFile opened with allowRemap=false")
+    if newFileSize != f.size:
+      if (let e = setFileSize(f.handle.FileHandle, newFileSize, f.size);
+          e != 0.OSErrorCode): raiseOSError(e)
+    when defined(linux): #Maybe NetBSD, too?
+      # On Linux this can be over 100 times faster than a munmap,mmap cycle.
+      proc mremap(old: pointer; oldSize, newSize: csize_t; flags: cint):
+          pointer {.importc: "mremap", header: "<sys/mman.h>".}
+      let newAddr = mremap(f.mem, csize_t(f.size), csize_t(newFileSize), 1.cint)
+      if newAddr == cast[pointer](MAP_FAILED):
+        raiseOSError(osLastError())
+    else:
+      if munmap(f.mem, f.size) != 0:
+        raiseOSError(osLastError())
+      let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE,
+                         f.flags, f.handle, 0)
+      if newAddr == cast[pointer](MAP_FAILED):
+        raiseOSError(osLastError())
+    f.mem = newAddr
+    f.size = newFileSize
 
 proc close*(f: var MemFile) =
   ## closes the memory mapped file `f`. All changes are written back to the
@@ -381,7 +412,7 @@ proc `==`*(x, y: MemSlice): bool =
 proc `$`*(ms: MemSlice): string {.inline.} =
   ## Return a Nim string built from a MemSlice.
   result.setLen(ms.size)
-  copyMem(addr(result[0]), ms.data, ms.size)
+  copyMem(result.cstring, ms.data, ms.size)
 
 iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline.} =
   ## Iterates over \[optional `eat`] `delim`-delimited slices in MemFile `mfile`.
@@ -407,13 +438,13 @@ iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline
   ## functions, not str* functions).
   ##
   ## Example:
-  ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   var count = 0
   ##   for slice in memSlices(memfiles.open("foo")):
   ##     if slice.size > 0 and cast[cstring](slice.data)[0] != '#':
   ##       inc(count)
   ##   echo count
+  ##   ```
 
   proc c_memchr(cstr: pointer, c: char, n: csize_t): pointer {.
        importc: "memchr", header: "<string.h>".}
@@ -443,11 +474,11 @@ iterator lines*(mfile: MemFile, buf: var string, delim = '\l',
   ## <#memSlices.i,MemFile,char,char>`_, but Nim strings are returned.
   ##
   ## Example:
-  ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   var buffer: string = ""
   ##   for line in lines(memfiles.open("foo"), buffer):
   ##     echo line
+  ##   ```
 
   for ms in memSlices(mfile, delim, eat):
     setLen(buf, ms.size)
@@ -462,10 +493,10 @@ iterator lines*(mfile: MemFile, delim = '\l', eat = '\r'): string {.inline.} =
   ## <#memSlices.i,MemFile,char,char>`_, but Nim strings are returned.
   ##
   ## Example:
-  ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for line in lines(memfiles.open("foo")):
   ##     echo line
+  ##   ```
 
   var buf = newStringOfCap(80)
   for line in lines(mfile, buf, delim, eat):
@@ -495,8 +526,8 @@ proc mmsSetPosition(s: Stream, pos: int) =
 proc mmsGetPosition(s: Stream): int = MemMapFileStream(s).pos
 
 proc mmsPeekData(s: Stream, buffer: pointer, bufLen: int): int =
-  let startAddress = cast[ByteAddress](MemMapFileStream(s).mf.mem)
-  let p = cast[ByteAddress](MemMapFileStream(s).pos)
+  let startAddress = cast[int](MemMapFileStream(s).mf.mem)
+  let p = cast[int](MemMapFileStream(s).pos)
   let l = min(bufLen, MemMapFileStream(s).mf.size - p)
   moveMem(buffer, cast[pointer](startAddress + p), l)
   result = l
@@ -511,8 +542,8 @@ proc mmsWriteData(s: Stream, buffer: pointer, bufLen: int) =
   let size = MemMapFileStream(s).mf.size
   if MemMapFileStream(s).pos + bufLen > size:
     raise newEIO("cannot write to stream")
-  let p = cast[ByteAddress](MemMapFileStream(s).mf.mem) +
-          cast[ByteAddress](MemMapFileStream(s).pos)
+  let p = cast[int](MemMapFileStream(s).mf.mem) +
+          cast[int](MemMapFileStream(s).pos)
   moveMem(cast[pointer](p), buffer, bufLen)
   inc(MemMapFileStream(s).pos, bufLen)
 
diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim
index 346fb39ee..ff639e8e5 100644
--- a/lib/pure/mimetypes.nim
+++ b/lib/pure/mimetypes.nim
@@ -26,8 +26,8 @@ runnableExamples:
   doAssert m.getMimetype("fakext") == "text/fakelang"
   doAssert m.getMimetype("FaKeXT") == "text/fakelang"
 
-import tables
-from strutils import startsWith, toLowerAscii, strip
+import std/tables
+from std/strutils import startsWith, toLowerAscii, strip
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -38,1848 +38,704 @@ type
     mimes: OrderedTable[string, string]
 
 const mimes* = {
-  "123": "application/vnd.lotus-1-2-3",
-  "1km": "application/vnd.1000minds.decision-model+xml",
-  "323": "text/h323",
-  "3dm": "text/vnd.in3d.3dml",
-  "3dmf": "x-world/x-3dmf",
-  "3dml": "text/vnd.in3d.3dml",
-  "3ds": "image/x-3ds",
-  "3g2": "video/3gpp2",
-  "3gp": "video/3gpp",
-  "3gpp": "audio/3gpp",
-  "3gpp2": "video/3gpp2",
-  "3mf": "application/vnd.ms-3mfdocument",
-  "669": "audio/x-mod",
-  "726": "audio/32kadpcm",
-  "7z": "application/x-7z-compressed",
-  "a": "text/plain",
-  "a2l": "application/a2l",
-  "aa3": "audio/atrac3",
-  "aab": "application/x-authorware-bin",
-  "aac": "audio/x-aac",
-  "aal": "audio/atrac-advanced-lossless",
-  "aam": "application/x-authorware-map",
-  "aas": "application/x-authorware-seg",
-  "abc": "text/vnd.abc",
-  "abw": "application/x-abiword",
+  "ez": "application/andrew-inset",
+  "aw": "application/applixware",
+  "atom": "application/atom+xml",
+  "atomcat": "application/atomcat+xml",
+  "atomsvc": "application/atomsvc+xml",
+  "ccxml": "application/ccxml+xml",
+  "cdmia": "application/cdmi-capability",
+  "cdmic": "application/cdmi-container",
+  "cdmid": "application/cdmi-domain",
+  "cdmio": "application/cdmi-object",
+  "cdmiq": "application/cdmi-queue",
+  "cu": "application/cu-seeme",
+  "davmount": "application/davmount+xml",
+  "dbk": "application/docbook+xml",
+  "dssc": "application/dssc+der",
+  "xdssc": "application/dssc+xml",
+  "ecma": "application/ecmascript",
+  "emma": "application/emma+xml",
+  "epub": "application/epub+zip",
+  "exi": "application/exi",
+  "pfr": "application/font-tdpfr",
+  "gml": "application/gml+xml",
+  "gpx": "application/gpx+xml",
+  "gxf": "application/gxf",
+  "stk": "application/hyperstudio",
+  "ink": "application/inkml+xml",
+  "inkml": "application/inkml+xml",
+  "ipfix": "application/ipfix",
+  "jar": "application/java-archive",
+  "ser": "application/java-serialized-object",
+  "class": "application/java-vm",
+  "json": "application/json",
+  "jsonml": "application/jsonml+json",
+  "lostxml": "application/lost+xml",
+  "hqx": "application/mac-binhex40",
+  "cpt": "application/mac-compactpro",
+  "mads": "application/mads+xml",
+  "mrc": "application/marc",
+  "mrcx": "application/marcxml+xml",
+  "ma": "application/mathematica",
+  "nb": "application/mathematica",
+  "mb": "application/mathematica",
+  "mathml": "application/mathml+xml",
+  "mbox": "application/mbox",
+  "mscml": "application/mediaservercontrol+xml",
+  "metalink": "application/metalink+xml",
+  "meta4": "application/metalink4+xml",
+  "mets": "application/mets+xml",
+  "mods": "application/mods+xml",
+  "m21": "application/mp21",
+  "mp21": "application/mp21",
+  "mp4s": "application/mp4",
+  "doc": "application/msword",
+  "dot": "application/msword",
+  "mxf": "application/mxf",
+  "bin": "application/octet-stream",
+  "dms": "application/octet-stream",
+  "lrf": "application/octet-stream",
+  "mar": "application/octet-stream",
+  "so": "application/octet-stream",
+  "dist": "application/octet-stream",
+  "distz": "application/octet-stream",
+  "pkg": "application/octet-stream",
+  "bpk": "application/octet-stream",
+  "dump": "application/octet-stream",
+  "elc": "application/octet-stream",
+  "deploy": "application/octet-stream",
+  "oda": "application/oda",
+  "opf": "application/oebps-package+xml",
+  "ogx": "application/ogg",
+  "omdoc": "application/omdoc+xml",
+  "onetoc": "application/onenote",
+  "onetoc2": "application/onenote",
+  "onetmp": "application/onenote",
+  "onepkg": "application/onenote",
+  "oxps": "application/oxps",
+  "xer": "application/patch-ops-error+xml",
+  "pdf": "application/pdf",
+  "pgp": "application/pgp-encrypted",
+  "asc": "application/pgp-signature",
+  "sig": "application/pgp-signature",
+  "prf": "application/pics-rules",
+  "p10": "application/pkcs10",
+  "p7m": "application/pkcs7-mime",
+  "p7c": "application/pkcs7-mime",
+  "p7s": "application/pkcs7-signature",
+  "p8": "application/pkcs8",
   "ac": "application/pkix-attr-cert",
-  "ac3": "audio/ac3",
-  "acc": "application/vnd.americandynamics.acc",
-  "ace": "application/x-ace-compressed",
-  "acn": "audio/asc",
-  "acu": "application/vnd.acucobol",
-  "acutc": "application/vnd.acucorp",
-  "acx": "application/internet-property-stream",
-  "adp": "audio/adpcm",
-  "aep": "application/vnd.audiograph",
-  "afl": "video/animaflex",
-  "afm": "application/x-font-type1",
-  "afp": "application/vnd.ibm.modcap",
-  "ahead": "application/vnd.ahead.space",
+  "cer": "application/pkix-cert",
+  "crl": "application/pkix-crl",
+  "pkipath": "application/pkix-pkipath",
+  "pki": "application/pkixcmp",
+  "pls": "application/pls+xml",
   "ai": "application/postscript",
-  "aif": "audio/x-aiff",
-  "aifc": "audio/x-aiff",
-  "aiff": "audio/x-aiff",
-  "aim": "application/x-aim",
-  "aip": "text/x-audiosoft-intra",
-  "air": "application/vnd.adobe.air-application-installer-package+zip",
-  "ait": "application/vnd.dvb.ait",
-  "alc": "chemical/x-alchemy",
-  "ami": "application/vnd.amiga.ami",
-  "aml": "application/aml",
-  "amr": "audio/amr",
-  "ani": "application/x-navi-animation",
-  "anx": "application/x-annodex",
-  "aos": "application/x-nokia-9000-communicator-add-on-software",
-  "apinotes": "text/apinotes",
-  "apk": "application/vnd.android.package-archive",
-  "apkg": "application/vnd.anki",
-  "apng": "image/apng",
-  "appcache": "text/cache-manifest",
-  "appimage": "application/appimage",
-  "application": "application/x-ms-application",
-  "apr": "application/vnd.lotus-approach",
-  "aps": "application/mime",
-  "apxml": "application/auth-policy+xml",
-  "arc": "application/x-freearc",
-  "arj": "application/x-arj",
-  "art": "message/rfc822",
-  "asar": "binary/asar",
-  "asc": "text/plain",
-  "ascii": "text/vnd.ascii-art",
-  "asf": "application/vnd.ms-asf",
-  "asice": "application/vnd.etsi.asic-e+zip",
-  "asics": "application/vnd.etsi.asic-s+zip",
-  "asm": "text/x-asm",
-  "asn": "chemical/x-ncbi-asn1-spec",
+  "eps": "application/postscript",
+  "ps": "application/postscript",
+  "cww": "application/prs.cww",
+  "pskcxml": "application/pskc+xml",
+  "rdf": "application/rdf+xml",
+  "rif": "application/reginfo+xml",
+  "rnc": "application/relax-ng-compact-syntax",
+  "rl": "application/resource-lists+xml",
+  "rld": "application/resource-lists-diff+xml",
+  "rs": "application/rls-services+xml",
+  "gbr": "application/rpki-ghostbusters",
+  "mft": "application/rpki-manifest",
+  "roa": "application/rpki-roa",
+  "rsd": "application/rsd+xml",
+  "rss": "application/rss+xml",
+  "rtf": "application/rtf",
+  "sbml": "application/sbml+xml",
+  "scq": "application/scvp-cv-request",
+  "scs": "application/scvp-cv-response",
+  "spq": "application/scvp-vp-request",
+  "spp": "application/scvp-vp-response",
+  "sdp": "application/sdp",
+  "setpay": "application/set-payment-initiation",
+  "setreg": "application/set-registration-initiation",
+  "shf": "application/shf+xml",
+  "smi": "application/smil+xml",
+  "smil": "application/smil+xml",
+  "rq": "application/sparql-query",
+  "srx": "application/sparql-results+xml",
+  "gram": "application/srgs",
+  "grxml": "application/srgs+xml",
+  "sru": "application/sru+xml",
+  "ssdl": "application/ssdl+xml",
+  "ssml": "application/ssml+xml",
+  "tei": "application/tei+xml",
+  "teicorpus": "application/tei+xml",
+  "tfi": "application/thraud+xml",
+  "tsd": "application/timestamped-data",
+  "plb": "application/vnd.3gpp.pic-bw-large",
+  "psb": "application/vnd.3gpp.pic-bw-small",
+  "pvb": "application/vnd.3gpp.pic-bw-var",
+  "tcap": "application/vnd.3gpp2.tcap",
+  "pwn": "application/vnd.3m.post-it-notes",
   "aso": "application/vnd.accpac.simply.aso",
-  "asp": "text/asp",
-  "asr": "video/x-ms-asf",
-  "asx": "video/x-ms-asf",
-  "at3": "audio/atrac3",
+  "imp": "application/vnd.accpac.simply.imp",
+  "acu": "application/vnd.acucobol",
   "atc": "application/vnd.acucorp",
-  "atf": "application/atf",
-  "atfx": "application/atfx",
-  "atom": "application/atom+xml",
-  "atomcat": "application/atomcat+xml",
-  "atomdeleted": "application/atomdeleted+xml",
-  "atomsrv": "application/atomserv+xml",
-  "atomsvc": "application/atomsvc+xml",
-  "atx": "application/vnd.antix.game-component",
-  "atxml": "application/atxml",
-  "au": "audio/basic",
-  "auc": "application/tamp-apex-update-confirm",
-  "avi": "video/x-msvideo",
-  "avs": "video/avs-video",
-  "aw": "application/applixware",
-  "awb": "audio/amr-wb",
-  "axa": "audio/x-annodex",
-  "axs": "application/olescript",
-  "axv": "video/x-annodex",
+  "acutc": "application/vnd.acucorp",
+  "air": "application/vnd.adobe.air-application-installer-package+zip",
+  "fcdt": "application/vnd.adobe.formscentral.fcdt",
+  "fxp": "application/vnd.adobe.fxp",
+  "fxpl": "application/vnd.adobe.fxp",
+  "xdp": "application/vnd.adobe.xdp+xml",
+  "xfdf": "application/vnd.adobe.xfdf",
+  "ahead": "application/vnd.ahead.space",
   "azf": "application/vnd.airzip.filesecure.azf",
   "azs": "application/vnd.airzip.filesecure.azs",
-  "azv": "image/vnd.airzip.accelerator.azv",
   "azw": "application/vnd.amazon.ebook",
-  "azw3": "application/vnd.amazon.mobi8-ebook",
-  "b": "chemical/x-molconn-Z",
-  "bak": "application/x-trash",
-  "bar": "application/vnd.qualcomm.brew-app-res",
-  "bas": "text/plain",
-  "bash": "text/shell",
-  "bat": "application/x-msdos-program",
-  "bcpio": "application/x-bcpio",
-  "bdf": "application/x-font-bdf",
-  "bdm": "application/vnd.syncml.dm+wbxml",
-  "bdoc": "application/bdoc",
-  "bed": "application/vnd.realvnc.bed",
-  "bh2": "application/vnd.fujitsu.oasysprs",
-  "bib": "text/x-bibtex",
-  "bik": "video/vnd.radgamettools.bink",
-  "bin": "application/octet-stream",
-  "bk2": "video/vnd.radgamettools.bink",
-  "bkm": "application/vnd.nervana",
-  "blb": "application/x-blorb",
-  "blend": "binary/blender",
-  "blorb": "application/x-blorb",
-  "bm": "image/bmp",
-  "bmed": "multipart/vnd.bint.med-plus",
+  "acc": "application/vnd.americandynamics.acc",
+  "ami": "application/vnd.amiga.ami",
+  "apk": "application/vnd.android.package-archive",
+  "cii": "application/vnd.anser-web-certificate-issue-initiation",
+  "fti": "application/vnd.anser-web-funds-transfer-initiation",
+  "atx": "application/vnd.antix.game-component",
+  "mpkg": "application/vnd.apple.installer+xml",
+  "m3u8": "application/vnd.apple.mpegurl",
+  "swi": "application/vnd.aristanetworks.swi",
+  "iota": "application/vnd.astraea-software.iota",
+  "aep": "application/vnd.audiograph",
+  "mpm": "application/vnd.blueice.multipass",
   "bmi": "application/vnd.bmi",
-  "bmml": "application/vnd.balsamiq.bmml+xml",
-  "bmp": "image/bmp",
-  "bmpr": "application/vnd.balsamiq.bmpr",
-  "boo": "application/book",
-  "book": "application/book",
-  "box": "application/vnd.previewsystems.box",
-  "boz": "application/x-bzip2",
-  "bpd": "application/vnd.hbci",
-  "bpk": "application/octet-stream",
-  "brf": "text/plain",
-  "bsd": "chemical/x-crossfire",
-  "bsh": "application/x-bsh",
-  "bsp": "model/vnd.valve.source.compiled-map",
-  "btf": "image/prs.btif",
-  "btif": "image/prs.btif",
-  "bz": "application/x-bzip",
-  "bz2": "application/x-bzip2",
-  "c": "text/x-csrc",
-  "c++": "text/x-c++src",
-  "c11amc": "application/vnd.cluetrust.cartomobile-config",
-  "c11amz": "application/vnd.cluetrust.cartomobile-config-pkg",
-  "c3d": "chemical/x-chem3d",
-  "c3ex": "application/cccex",
+  "rep": "application/vnd.businessobjects",
+  "cdxml": "application/vnd.chemdraw+xml",
+  "mmd": "application/vnd.chipnuts.karaoke-mmd",
+  "cdy": "application/vnd.cinderella",
+  "cla": "application/vnd.claymore",
+  "rp9": "application/vnd.cloanto.rp9",
+  "c4g": "application/vnd.clonk.c4group",
   "c4d": "application/vnd.clonk.c4group",
   "c4f": "application/vnd.clonk.c4group",
-  "c4g": "application/vnd.clonk.c4group",
   "c4p": "application/vnd.clonk.c4group",
   "c4u": "application/vnd.clonk.c4group",
-  "cab": "application/vnd.ms-cab-compressed",
-  "cac": "chemical/x-cache",
-  "cache": "application/x-cache",
-  "caf": "audio/x-caf",
-  "cap": "application/vnd.tcpdump.pcap",
-  "car": "application/vnd.curl.car",
-  "cascii": "chemical/x-cactvs-binary",
-  "cat": "application/vnd.ms-pki.seccat",
-  "cb7": "application/x-cbr",
-  "cba": "application/x-cbr",
-  "cbin": "chemical/x-cactvs-binary",
-  "cbor": "application/cbor",
-  "cbr": "application/x-cbr",
-  "cbt": "application/x-cbr",
-  "cbz": "application/vnd.comicbook+zip",
-  "cc": "text/plain",
-  "ccad": "application/clariscad",
-  "ccc": "text/vnd.net2phone.commcenter.command",
-  "ccmp": "application/ccmp+xml",
-  "cco": "application/x-cocoa",
-  "cct": "application/x-director",
-  "ccxml": "application/ccxml+xml",
-  "cda": "application/x-cdf",
+  "c11amc": "application/vnd.cluetrust.cartomobile-config",
+  "c11amz": "application/vnd.cluetrust.cartomobile-config-pkg",
+  "csp": "application/vnd.commonspace",
   "cdbcmsg": "application/vnd.contact.cmsg",
-  "cdf": "application/x-netcdf",
-  "cdfx": "application/cdfx+xml",
-  "cdkey": "application/vnd.mediastation.cdkey",
-  "cdmia": "application/cdmi-capability",
-  "cdmic": "application/cdmi-container",
-  "cdmid": "application/cdmi-domain",
-  "cdmio": "application/cdmi-object",
-  "cdmiq": "application/cdmi-queue",
-  "cdr": "image/x-coreldraw",
-  "cdt": "image/x-coreldrawtemplate",
-  "cdx": "chemical/x-cdx",
-  "cdxml": "application/vnd.chemdraw+xml",
-  "cdy": "application/vnd.cinderella",
-  "cea": "application/cea",
-  "cef": "chemical/x-cxf",
-  "cellml": "application/cellml+xml",
-  "cer": "application/pkix-cert",
-  "cfg": "text/cfg",
-  "cfs": "application/x-cfs-compressed",
-  "cgm": "image/cgm",
-  "cha": "application/x-chat",
-  "chat": "application/x-chat",
-  "chm": "application/vnd.ms-htmlhelp",
-  "chrt": "application/vnd.kde.kchart",
-  "cif": "chemical/x-cif",
-  "cii": "application/vnd.anser-web-certificate-issue-initiation",
-  "cil": "application/vnd.ms-artgalry",
-  "cl": "application/simple-filter+xml",
-  "cla": "application/vnd.claymore",
-  "class": "application/java-vm",
+  "cmc": "application/vnd.cosmocaller",
+  "clkx": "application/vnd.crick.clicker",
   "clkk": "application/vnd.crick.clicker.keyboard",
   "clkp": "application/vnd.crick.clicker.palette",
   "clkt": "application/vnd.crick.clicker.template",
   "clkw": "application/vnd.crick.clicker.wordbank",
-  "clkx": "application/vnd.crick.clicker",
-  "clp": "application/x-msclip",
-  "cls": "text/x-tex",
-  "clue": "application/clue_info+xml",
-  "cmake": "text/cmake",
-  "cmc": "application/vnd.cosmocaller",
-  "cmdf": "chemical/x-cmdf",
-  "cml": "chemical/x-cml",
-  "cmp": "application/vnd.yellowriver-custom-menu",
-  "cmsc": "application/cms",
-  "cmx": "image/x-cmx",
-  "cnd": "text/jcr-cnd",
-  "cnf": "text/cnf",
-  "cod": "application/vnd.rim.cod",
-  "coffee": "application/vnd.coffeescript",
-  "com": "application/x-msdos-program",
-  "conf": "text/plain",
-  "copyright": "text/vnd.debian.copyright",
-  "cpa": "chemical/x-compass",
-  "cpio": "application/x-cpio",
-  "cpkg": "application/vnd.xmpie.cpkg",
-  "cpl": "application/cpl+xml",
-  "cpp": "text/x-c++src",
-  "cpt": "application/mac-compactpro",
-  "cr2": "image/x-canon-cr2",
-  "crd": "application/x-mscardfile",
-  "crl": "application/pkix-crl",
-  "crt": "application/x-x509-ca-cert",
-  "crtr": "application/vnd.multiad.creator",
-  "crw": "image/x-canon-crw",
-  "crx": "application/x-chrome-extension",
-  "cryptonote": "application/vnd.rig.cryptonote",
-  "cs": "text/c#",
-  "csf": "chemical/x-cache-csf",
-  "csh": "application/x-csh",
-  "csl": "application/vnd.citationstyles.style+xml",
-  "csm": "chemical/x-csml",
-  "csml": "chemical/x-csml",
-  "cson": "text/cson",
-  "csp": "application/vnd.commonspace",
-  "csrattrs": "application/csrattrs",
-  "css": "text/css",
-  "cst": "application/vnd.commonspace",
-  "csv": "text/csv",
-  "csvs": "text/csv-schema",
-  "ctab": "chemical/x-cactvs-binary",
-  "ctx": "chemical/x-ctx",
-  "cu": "application/cu-seeme",
-  "cub": "chemical/x-gaussian-cube",
-  "cuc": "application/tamp-community-update-confirm",
-  "curl": "text/vnd.curl",
-  "cw": "application/prs.cww",
-  "cww": "application/prs.cww",
-  "cxf": "chemical/x-cxf",
-  "cxt": "application/x-director",
-  "cxx": "text/plain",
-  "d": "text/x-dsrc",
-  "dae": "model/vnd.collada+xml",
-  "daf": "application/vnd.mobius.daf",
+  "wbs": "application/vnd.criticaltools.wbs+xml",
+  "pml": "application/vnd.ctc-posml",
+  "ppd": "application/vnd.cups-ppd",
+  "car": "application/vnd.curl.car",
+  "pcurl": "application/vnd.curl.pcurl",
   "dart": "application/vnd.dart",
-  "dat": "application/x-ns-proxy-autoconfig",
-  "dataless": "application/vnd.fdsn.seed",
-  "davmount": "application/davmount+xml",
-  "dbk": "application/docbook+xml",
-  "dcd": "application/dcd",
-  "dcf": "application/vnd.oma.drm.content",
-  "dcm": "application/dicom",
-  "dcr": "application/x-director",
-  "dcurl": "text/vnd.curl.dcurl",
-  "dd": "application/vnd.oma.dd+xml",
-  "dd2": "application/vnd.oma.dd2+xml",
-  "ddd": "application/vnd.fujixerox.ddd",
-  "ddf": "application/vnd.syncml.dmddf+xml",
-  "deb": "application/vnd.debian.binary-package",
-  "deepv": "application/x-deepv",
-  "def": "text/plain",
-  "deploy": "application/octet-stream",
-  "der": "application/x-x509-ca-cert",
-  "dfac": "application/vnd.dreamfactory",
-  "dgc": "application/x-dgc-compressed",
-  "dib": "image/bmp",
-  "dic": "text/x-c",
-  "dif": "video/x-dv",
-  "diff": "text/x-diff",
-  "dii": "application/dii",
-  "dim": "application/vnd.fastcopy-disk-image",
-  "dir": "application/x-director",
-  "dis": "application/vnd.mobius.dis",
-  "disposition-notification": "message/disposition-notification",
-  "dist": "application/vnd.apple.installer+xml",
-  "distz": "application/vnd.apple.installer+xml",
-  "dit": "application/dit",
-  "djv": "image/vnd.djvu",
-  "djvu": "image/vnd.djvu",
-  "dl": "video/dl",
-  "dll": "application/x-msdos-program",
-  "dls": "audio/dls",
-  "dm": "application/vnd.oma.drm.message",
-  "dmg": "application/x-apple-diskimage",
-  "dmp": "application/vnd.tcpdump.pcap",
-  "dms": "text/vnd.dmclientscript",
+  "rdz": "application/vnd.data-vision.rdz",
+  "uvf": "application/vnd.dece.data",
+  "uvvf": "application/vnd.dece.data",
+  "uvd": "application/vnd.dece.data",
+  "uvvd": "application/vnd.dece.data",
+  "uvt": "application/vnd.dece.ttml+xml",
+  "uvvt": "application/vnd.dece.ttml+xml",
+  "uvx": "application/vnd.dece.unspecified",
+  "uvvx": "application/vnd.dece.unspecified",
+  "uvz": "application/vnd.dece.zip",
+  "uvvz": "application/vnd.dece.zip",
+  "fe_launch": "application/vnd.denovo.fcselayout-link",
   "dna": "application/vnd.dna",
-  "doc": "application/msword",
-  "docjson": "application/vnd.document+json",
-  "docm": "application/vnd.ms-word.document.macroenabled.12",
-  "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
-  "dor": "model/vnd.gdl",
-  "dot": "text/vnd.graphviz",
-  "dotm": "application/vnd.ms-word.template.macroenabled.12",
-  "dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
-  "dp": "application/vnd.osgi.dp",
+  "mlp": "application/vnd.dolby.mlp",
   "dpg": "application/vnd.dpgraph",
-  "dpgraph": "application/vnd.dpgraph",
-  "dpkg": "application/vnd.xmpie.dpkg",
-  "dr": "application/vnd.oma.drm.rights+xml",
-  "dra": "audio/vnd.dra",
-  "drc": "application/vnd.oma.drm.rights+wbxml",
-  "drle": "image/dicom-rle",
-  "drw": "application/drafting",
-  "dsc": "text/prs.lines.tag",
-  "dsm": "application/vnd.desmume.movie",
-  "dssc": "application/dssc+der",
-  "dtb": "application/x-dtbook+xml",
-  "dtd": "application/xml-dtd",
-  "dts": "audio/vnd.dts",
-  "dtshd": "audio/vnd.dts.hd",
-  "dump": "application/octet-stream",
-  "dv": "video/x-dv",
-  "dvb": "video/vnd.dvb.file",
-  "dvc": "application/dvcs",
-  "dvi": "application/x-dvi",
-  "dwf": "model/vnd.dwf",
-  "dwg": "image/vnd.dwg",
-  "dx": "chemical/x-jcamp-dx",
-  "dxf": "image/vnd.dxf",
-  "dxp": "application/vnd.spotfire.dxp",
-  "dxr": "application/x-director",
-  "dzr": "application/vnd.dzr",
-  "ear": "binary/zip",
-  "ecelp4800": "audio/vnd.nuera.ecelp4800",
-  "ecelp7470": "audio/vnd.nuera.ecelp7470",
-  "ecelp9600": "audio/vnd.nuera.ecelp9600",
-  "ecig": "application/vnd.evolv.ecig.settings",
-  "ecigprofile": "application/vnd.evolv.ecig.profile",
-  "ecigtheme": "application/vnd.evolv.ecig.theme",
-  "ecma": "application/ecmascript",
-  "edm": "application/vnd.novadigm.edm",
-  "edx": "application/vnd.novadigm.edx",
-  "efi": "application/efi",
-  "efif": "application/vnd.picsel",
-  "ei6": "application/vnd.pg.osasli",
-  "ejs": "text/ejs",
-  "el": "text/plain",
-  "elc": "application/x-bytecode.elisp",
-  "emb": "chemical/x-embl-dl-nucleotide",
-  "embl": "chemical/x-embl-dl-nucleotide",
-  "emf": "image/emf",
-  "eml": "message/rfc822",
-  "emm": "application/vnd.ibm.electronic-media",
-  "emma": "application/emma+xml",
-  "emotionml": "application/emotionml+xml",
-  "emz": "application/x-msmetafile",
-  "ent": "text/xml-external-parsed-entity",
-  "entity": "application/vnd.nervana",
-  "env": "application/x-envoy",
-  "enw": "audio/evrcnw",
-  "eol": "audio/vnd.digital-winds",
-  "eot": "application/vnd.ms-fontobject",
-  "ep": "application/vnd.bluetooth.ep.oob",
-  "eps": "application/postscript",
-  "eps2": "application/postscript",
-  "eps3": "application/postscript",
-  "epsf": "application/postscript",
-  "epsi": "application/postscript",
-  "epub": "application/epub+zip",
-  "erb": "text/erb",
-  "erf": "image/x-epson-erf",
-  "es": "application/ecmascript",
-  "es3": "application/vnd.eszigno3+xml",
-  "esa": "application/vnd.osgi.subsystem",
-  "escn": "text/godot",
+  "dfac": "application/vnd.dreamfactory",
+  "kpxx": "application/vnd.ds-keypoint",
+  "ait": "application/vnd.dvb.ait",
+  "svc": "application/vnd.dvb.service",
+  "geo": "application/vnd.dynageo",
+  "mag": "application/vnd.ecowin.chart",
+  "nml": "application/vnd.enliven",
   "esf": "application/vnd.epson.esf",
-  "espass": "application/vnd.espass-espass+zip",
+  "msf": "application/vnd.epson.msf",
+  "qam": "application/vnd.epson.quickanime",
+  "slt": "application/vnd.epson.salt",
+  "ssf": "application/vnd.epson.ssf",
+  "es3": "application/vnd.eszigno3+xml",
   "et3": "application/vnd.eszigno3+xml",
-  "etx": "text/x-setext",
-  "eva": "application/x-eva",
-  "evb": "audio/evrcb",
-  "evc": "audio/evrc",
-  "evw": "audio/evrcwb",
-  "evy": "application/x-envoy",
-  "exe": "application/x-msdos-program",
-  "exi": "application/exi",
-  "exr": "image/aces",
-  "ext": "application/vnd.novadigm.ext",
-  "eyaml": "text/yaml",
-  "ez": "application/andrew-inset",
   "ez2": "application/vnd.ezpix-album",
   "ez3": "application/vnd.ezpix-package",
-  "f": "text/x-fortran",
-  "f4v": "video/x-f4v",
-  "f77": "text/x-fortran",
-  "f90": "text/plain",
-  "fb": "application/x-maker",
-  "fbdoc": "application/x-maker",
-  "fbs": "image/vnd.fastbidsheet",
-  "fbx": "model/filmbox",
-  "fcdt": "application/vnd.adobe.formscentral.fcdt",
-  "fch": "chemical/x-gaussian-checkpoint",
-  "fchk": "chemical/x-gaussian-checkpoint",
-  "fcs": "application/vnd.isac.fcs",
   "fdf": "application/vnd.fdf",
-  "fdt": "application/fdt+xml",
-  "fe_launch": "application/vnd.denovo.fcselayout-link",
-  "feature": "text/gherkin",
-  "fg5": "application/vnd.fujitsu.oasysgp",
-  "fgd": "application/x-director",
-  "fh": "image/x-freehand",
-  "fh4": "image/x-freehand",
-  "fh5": "image/x-freehand",
-  "fh7": "image/x-freehand",
-  "fhc": "image/x-freehand",
-  "fif": "image/fif",
-  "fig": "application/x-xfig",
-  "finf": "application/fastinfoset",
-  "fish": "text/fish",
-  "fit": "image/fits",
-  "fits": "image/fits",
-  "fla": "application/vnd.dtg.local.flash",
-  "flac": "audio/x-flac",
-  "fli": "video/x-fli",
-  "flo": "application/vnd.micrografx.flo",
-  "flr": "x-world/x-vrml",
-  "flv": "video/x-flv",
-  "flw": "application/vnd.kde.kivio",
-  "flx": "text/vnd.fmi.flexstor",
-  "fly": "text/vnd.fly",
+  "mseed": "application/vnd.fdsn.mseed",
+  "seed": "application/vnd.fdsn.seed",
+  "dataless": "application/vnd.fdsn.seed",
+  "gph": "application/vnd.flographit",
+  "ftc": "application/vnd.fluxtime.clip",
   "fm": "application/vnd.framemaker",
-  "fmf": "video/x-atomic3d-feature",
-  "fnc": "application/vnd.frogans.fnc",
-  "fo": "application/vnd.software602.filler.form+xml",
-  "for": "text/x-fortran",
-  "fpx": "image/vnd.fpx",
   "frame": "application/vnd.framemaker",
-  "frl": "application/freeloader",
-  "frm": "application/vnd.ufdl",
+  "maker": "application/vnd.framemaker",
+  "book": "application/vnd.framemaker",
+  "fnc": "application/vnd.frogans.fnc",
+  "ltf": "application/vnd.frogans.ltf",
   "fsc": "application/vnd.fsc.weblaunch",
-  "fst": "image/vnd.fst",
-  "ftc": "application/vnd.fluxtime.clip",
-  "fti": "application/vnd.anser-web-funds-transfer-initiation",
-  "fts": "image/fits",
-  "funk": "audio/make",
-  "fvt": "video/vnd.fvt",
-  "fxm": "video/x-javafx",
-  "fxp": "application/vnd.adobe.fxp",
-  "fxpl": "application/vnd.adobe.fxp",
+  "oas": "application/vnd.fujitsu.oasys",
+  "oa2": "application/vnd.fujitsu.oasys2",
+  "oa3": "application/vnd.fujitsu.oasys3",
+  "fg5": "application/vnd.fujitsu.oasysgp",
+  "bh2": "application/vnd.fujitsu.oasysprs",
+  "ddd": "application/vnd.fujixerox.ddd",
+  "xdw": "application/vnd.fujixerox.docuworks",
+  "xbd": "application/vnd.fujixerox.docuworks.binder",
   "fzs": "application/vnd.fuzzysheet",
-  "g": "text/plain",
-  "g2w": "application/vnd.geoplan",
-  "g3": "image/g3fax",
-  "g3w": "application/vnd.geospace",
-  "gac": "application/vnd.groove-account",
-  "gal": "chemical/x-gaussian-log",
-  "gam": "application/x-tads",
-  "gamin": "chemical/x-gamess-input",
-  "gau": "chemical/x-gaussian-input",
-  "gbr": "application/rpki-ghostbusters",
-  "gca": "application/x-gca-compressed",
-  "gcd": "text/x-pcs-gcd",
-  "gcf": "application/x-graphing-calculator",
-  "gcg": "chemical/x-gcg8-sequence",
-  "gdl": "model/vnd.gdl",
-  "gdoc": "application/vnd.google-apps.document",
-  "gemspec": "text/ruby",
-  "gen": "chemical/x-genbank",
-  "geo": "application/vnd.dynageo",
-  "geojson": "application/geo+json",
-  "gex": "application/vnd.geometry-explorer",
-  "gf": "application/x-tex-gf",
+  "txd": "application/vnd.genomatix.tuxedo",
   "ggb": "application/vnd.geogebra.file",
+  "ggs": "application/vnd.geogebra.slides",
   "ggt": "application/vnd.geogebra.tool",
-  "ghf": "application/vnd.groove-help",
-  "gif": "image/gif",
-  "gim": "application/vnd.groove-identity-message",
-  "gjc": "chemical/x-gaussian-input",
-  "gjf": "chemical/x-gaussian-input",
-  "gl": "video/gl",
-  "glb": "model/gltf-binary",
-  "gltf": "model/gltf+json",
-  "gml": "application/gml+xml",
+  "gex": "application/vnd.geometry-explorer",
+  "gre": "application/vnd.geometry-explorer",
+  "gxt": "application/vnd.geonext",
+  "g2w": "application/vnd.geoplan",
+  "g3w": "application/vnd.geospace",
   "gmx": "application/vnd.gmx",
-  "gnumeric": "application/x-gnumeric",
-  "go": "text/go",
-  "gotmpl": "text/gotmpl",
-  "gph": "application/vnd.flographit",
-  "gpt": "chemical/x-mopac-graph",
-  "gpx": "application/gpx+xml",
+  "kml": "application/vnd.google-earth.kml+xml",
+  "kmz": "application/vnd.google-earth.kmz",
   "gqf": "application/vnd.grafeq",
   "gqs": "application/vnd.grafeq",
-  "gradle": "text/groovy",
-  "gram": "application/srgs",
-  "gramps": "application/x-gramps-xml",
-  "gre": "application/vnd.geometry-explorer",
-  "groovy": "text/groovy",
+  "gac": "application/vnd.groove-account",
+  "ghf": "application/vnd.groove-help",
+  "gim": "application/vnd.groove-identity-message",
   "grv": "application/vnd.groove-injector",
-  "grxml": "application/srgs+xml",
-  "gsd": "audio/x-gsm",
-  "gsf": "application/x-font-ghostscript",
-  "gsheet": "application/vnd.google-apps.spreadsheet",
-  "gslides": "application/vnd.google-apps.presentation",
-  "gsm": "model/vnd.gdl",
-  "gsp": "application/x-gsp",
-  "gss": "application/x-gss",
-  "gtar": "application/x-gtar",
   "gtm": "application/vnd.groove-tool-message",
-  "gtw": "model/vnd.gtw",
-  "gv": "text/vnd.graphviz",
-  "gxf": "application/gxf",
-  "gxt": "application/vnd.geonext",
-  "gyb": "text/gyb",
-  "gyp": "text/gyp",
-  "gypi": "text/gyp",
-  "gz": "application/gzip",
-  "h": "text/x-chdr",
-  "h++": "text/x-c++hdr",
-  "h261": "video/h261",
-  "h263": "video/h263",
-  "h264": "video/h264",
+  "tpl": "application/vnd.groove-tool-template",
+  "vcg": "application/vnd.groove-vcard",
   "hal": "application/vnd.hal+xml",
-  "hbc": "application/vnd.hbci",
+  "zmm": "application/vnd.handheld-entertainment+xml",
   "hbci": "application/vnd.hbci",
-  "hbs": "text/x-handlebars-template",
-  "hdd": "application/x-virtualbox-hdd",
-  "hdf": "application/x-hdf",
-  "hdr": "image/vnd.radiance",
-  "hdt": "application/vnd.hdt",
-  "heic": "image/heic",
-  "heics": "image/heic-sequence",
-  "heif": "image/heif",
-  "heifs": "image/heif-sequence",
-  "help": "application/x-helpfile",
-  "hgl": "application/vnd.hp-hpgl",
-  "hh": "text/plain",
-  "hin": "chemical/x-hin",
-  "hjson": "application/hjson",
-  "hlb": "text/x-script",
-  "hlp": "application/winhlp",
-  "hpg": "application/vnd.hp-hpgl",
+  "les": "application/vnd.hhe.lesson-player",
   "hpgl": "application/vnd.hp-hpgl",
-  "hpi": "application/vnd.hp-hpid",
   "hpid": "application/vnd.hp-hpid",
-  "hpp": "text/x-c++hdr",
   "hps": "application/vnd.hp-hps",
-  "hpub": "application/prs.hpub+zip",
-  "hqx": "application/mac-binhex40",
-  "hs": "text/x-haskell",
-  "hta": "application/hta",
-  "htc": "text/x-component",
-  "htke": "application/vnd.kenameaapp",
-  "html": "text/html",
-  "htt": "text/webviewhtml",
-  "hvd": "application/vnd.yamaha.hv-dic",
-  "hvp": "application/vnd.yamaha.hv-voice",
-  "hvs": "application/vnd.yamaha.hv-script",
-  "hx": "text/haxe",
-  "hxml": "text/haxe",
-  "hxx": "text/plain",
-  "i2g": "application/vnd.intergeo",
-  "ic0": "application/vnd.commerce-battelle",
-  "ic1": "application/vnd.commerce-battelle",
-  "ic2": "application/vnd.commerce-battelle",
-  "ic3": "application/vnd.commerce-battelle",
-  "ic4": "application/vnd.commerce-battelle",
-  "ic5": "application/vnd.commerce-battelle",
-  "ic6": "application/vnd.commerce-battelle",
-  "ic7": "application/vnd.commerce-battelle",
-  "ic8": "application/vnd.commerce-battelle",
-  "ica": "application/vnd.commerce-battelle",
+  "jlt": "application/vnd.hp-jlyt",
+  "pcl": "application/vnd.hp-pcl",
+  "pclxl": "application/vnd.hp-pclxl",
+  "sfd-hdstx": "application/vnd.hydrostatix.sof-data",
+  "mpy": "application/vnd.ibm.minipay",
+  "afp": "application/vnd.ibm.modcap",
+  "listafp": "application/vnd.ibm.modcap",
+  "list3820": "application/vnd.ibm.modcap",
+  "irm": "application/vnd.ibm.rights-management",
+  "sc": "application/vnd.ibm.secure-container",
   "icc": "application/vnd.iccprofile",
-  "icd": "application/vnd.commerce-battelle",
-  "ice": "x-conference/x-cooltalk",
-  "icf": "application/vnd.commerce-battelle",
   "icm": "application/vnd.iccprofile",
-  "icns": "binary/icns",
-  "ico": "image/x-icon",
-  "ics": "text/calendar",
-  "icz": "text/calendar",
-  "idc": "text/plain",
-  "idl": "text/idl",
-  "ief": "image/ief",
-  "iefs": "image/ief",
-  "ifb": "text/calendar",
-  "ifm": "application/vnd.shana.informed.formdata",
-  "iges": "model/iges",
   "igl": "application/vnd.igloader",
-  "igm": "application/vnd.insors.igm",
-  "ign": "application/vnd.coreos.ignition+json",
-  "ignition": "application/vnd.coreos.ignition+json",
-  "igs": "model/iges",
-  "igx": "application/vnd.micrografx.igx",
-  "iif": "application/vnd.shana.informed.interchange",
-  "iii": "application/x-iphone",
-  "ima": "application/x-ima",
-  "imap": "application/x-httpd-imap",
-  "imf": "application/vnd.imagemeter.folder+zip",
-  "img": "application/octet-stream",
-  "imgcal": "application/vnd.3lightssoftware.imagescal",
-  "imi": "application/vnd.imagemeter.image+zip",
-  "imp": "application/vnd.accpac.simply.imp",
-  "ims": "application/vnd.ms-ims",
-  "imscc": "application/vnd.ims.imsccv1p1",
-  "in": "text/plain",
-  "inc": "text/inc",
-  "inf": "application/inf",
-  "info": "application/x-info",
-  "ini": "text/ini",
-  "ink": "application/inkml+xml",
-  "inkml": "application/inkml+xml",
-  "inp": "chemical/x-gamess-input",
-  "ins": "application/x-internet-signup",
-  "install": "application/x-install-instructions",
-  "iota": "application/vnd.astraea-software.iota",
-  "ip": "application/x-ip2",
-  "ipfix": "application/ipfix",
-  "ipk": "application/vnd.shana.informed.package",
-  "irm": "application/vnd.ibm.rights-management",
-  "irp": "application/vnd.irepository.package+xml",
-  "ism": "model/vnd.gdl",
-  "iso": "application/x-iso9660-image",
-  "isp": "application/x-internet-signup",
-  "ist": "chemical/x-isostar",
-  "istr": "chemical/x-isostar",
-  "isu": "video/x-isvideo",
-  "it": "audio/it",
-  "itp": "application/vnd.shana.informed.formtemplate",
-  "its": "application/its+xml",
-  "iv": "application/x-inventor",
   "ivp": "application/vnd.immervision-ivp",
-  "ivr": "i-world/i-vrml",
   "ivu": "application/vnd.immervision-ivu",
-  "ivy": "application/x-livescreen",
-  "j2": "text/jinja",
-  "jad": "text/vnd.sun.j2me.app-descriptor",
-  "jade": "text/jade",
+  "igm": "application/vnd.insors.igm",
+  "xpw": "application/vnd.intercon.formnet",
+  "xpx": "application/vnd.intercon.formnet",
+  "i2g": "application/vnd.intergeo",
+  "qbo": "application/vnd.intu.qbo",
+  "qfx": "application/vnd.intu.qfx",
+  "rcprofile": "application/vnd.ipunplugged.rcprofile",
+  "irp": "application/vnd.irepository.package+xml",
+  "xpr": "application/vnd.is-xpr",
+  "fcs": "application/vnd.isac.fcs",
   "jam": "application/vnd.jam",
-  "jar": "application/x-java-archive",
-  "jardiff": "application/x-java-archive-diff",
-  "java": "text/x-java-source",
-  "jcm": "application/x-java-commerce",
-  "jdx": "chemical/x-jcamp-dx",
-  "jenkinsfile": "text/groovy",
-  "jfif": "image/jpeg",
-  "jinja": "text/jinja",
-  "jinja2": "text/jinja",
+  "rms": "application/vnd.jcp.javame.midlet-rms",
   "jisp": "application/vnd.jisp",
-  "jls": "image/jls",
-  "jlt": "application/vnd.hp-jlyt",
-  "jl": "text/julia",
-  "jmz": "application/x-jmol",
-  "jng": "image/x-jng",
-  "jnlp": "application/x-java-jnlp-file",
   "joda": "application/vnd.joost.joda-archive",
-  "jp2": "image/jp2",
-  "jpe": "image/jpeg",
-  "jpeg": "image/jpeg",
-  "jpf": "image/jpx",
-  "jpg": "image/jpeg",
-  "jpg2": "image/jp2",
-  "jpgm": "image/jpm",
-  "jpgv": "video/jpeg",
-  "jpm": "image/jpm",
-  "jps": "image/x-jps",
-  "jpx": "image/jpx",
-  "jrd": "application/jrd+json",
-  "js": "application/javascript",
-  "json": "application/json",
-  "json-patch": "application/json-patch+json",
-  "json5": "application/json5",
-  "jsonld": "application/ld+json",
-  "jsonml": "application/jsonml+json",
-  "jsx": "text/jsx",
-  "jtd": "text/vnd.esmertec.theme-descriptor",
-  "jut": "image/jutvision",
-  "kar": "audio/midi",
+  "ktz": "application/vnd.kahootz",
+  "ktr": "application/vnd.kahootz",
   "karbon": "application/vnd.kde.karbon",
-  "kcm": "application/vnd.nervana",
-  "key": "application/pgp-keys",
-  "keynote": "application/vnd.apple.keynote",
+  "chrt": "application/vnd.kde.kchart",
   "kfo": "application/vnd.kde.kformula",
-  "kia": "application/vnd.kidspiration",
-  "kil": "application/x-killustrator",
-  "kin": "chemical/x-kinemage",
-  "kml": "application/vnd.google-earth.kml+xml",
-  "kmz": "application/vnd.google-earth.kmz",
-  "kne": "application/vnd.kinar",
-  "knp": "application/vnd.kinar",
-  "kom": "application/vnd.hbci",
+  "flw": "application/vnd.kde.kivio",
   "kon": "application/vnd.kde.kontour",
-  "koz": "audio/vnd.audikoz",
   "kpr": "application/vnd.kde.kpresenter",
   "kpt": "application/vnd.kde.kpresenter",
-  "kpxx": "application/vnd.ds-keypoint",
-  "ksh": "application/x-ksh",
   "ksp": "application/vnd.kde.kspread",
-  "kt": "text/kotlin",
-  "ktr": "application/vnd.kahootz",
-  "ktx": "image/ktx",
-  "ktz": "application/vnd.kahootz",
   "kwd": "application/vnd.kde.kword",
   "kwt": "application/vnd.kde.kword",
-  "l16": "audio/l16",
-  "la": "audio/nspaudio",
-  "lam": "audio/x-liveaudio",
-  "lasjson": "application/vnd.las.las+json",
+  "htke": "application/vnd.kenameaapp",
+  "kia": "application/vnd.kidspiration",
+  "kne": "application/vnd.kinar",
+  "knp": "application/vnd.kinar",
+  "skp": "application/vnd.koan",
+  "skd": "application/vnd.koan",
+  "skt": "application/vnd.koan",
+  "skm": "application/vnd.koan",
+  "sse": "application/vnd.kodak-descriptor",
   "lasxml": "application/vnd.las.las+xml",
-  "latex": "application/x-latex",
-  "lbc": "audio/ilbc",
   "lbd": "application/vnd.llamagraphics.life-balance.desktop",
   "lbe": "application/vnd.llamagraphics.life-balance.exchange+xml",
-  "le": "application/vnd.bluetooth.le.oob",
-  "les": "application/vnd.hhe.lesson-player",
-  "less": "text/less",
-  "lgr": "application/lgr+xml",
-  "lha": "application/octet-stream",
-  "lhs": "text/x-literate-haskell",
-  "lhx": "application/octet-stream",
-  "lin": "application/bbolin",
-  "link66": "application/vnd.route66.link66+xml",
-  "list": "text/plain",
-  "list3820": "application/vnd.ibm.modcap",
-  "listafp": "application/vnd.ibm.modcap",
-  "lmp": "model/vnd.gdl",
-  "lnk": "application/x-ms-shortcut",
-  "log": "text/plain",
-  "lostsyncxml": "application/lostsync+xml",
-  "lostxml": "application/lost+xml",
-  "lrf": "application/octet-stream",
-  "lrm": "application/vnd.ms-lrm",
-  "lsf": "video/x-la-asf",
-  "lsp": "text/x-script.lisp",
-  "lst": "text/plain",
-  "lsx": "video/x-la-asf",
-  "ltf": "application/vnd.frogans.ltf",
-  "ltx": "application/x-latex",
-  "lua": "text/x-lua",
-  "luac": "application/x-lua-bytecode",
-  "lvp": "audio/vnd.lucent.voice",
+  "123": "application/vnd.lotus-1-2-3",
+  "apr": "application/vnd.lotus-approach",
+  "pre": "application/vnd.lotus-freelance",
+  "nsf": "application/vnd.lotus-notes",
+  "org": "application/vnd.lotus-organizer",
+  "scm": "application/vnd.lotus-screencam",
   "lwp": "application/vnd.lotus-wordpro",
-  "lxf": "application/lxf",
-  "lyx": "application/x-lyx",
-  "lzh": "application/octet-stream",
-  "lzx": "application/x-lzx",
-  "m": "application/vnd.wolfram.mathematica.package",
-  "m13": "application/x-msmediaview",
-  "m14": "application/x-msmediaview",
-  "m15": "audio/x-mod",
-  "m1v": "video/mpeg",
-  "m21": "application/mp21",
-  "m2a": "audio/mpeg",
-  "m2v": "video/mpeg",
-  "m3a": "audio/mpeg",
-  "m3g": "application/m3g",
-  "m3u": "audio/x-mpegurl",
-  "m3u8": "application/vnd.apple.mpegurl",
-  "m4a": "audio/x-m4a",
-  "m4s": "video/iso.segment",
-  "m4u": "video/vnd.mpegurl",
-  "m4v": "video/x-m4v",
-  "ma": "application/mathematica",
-  "mads": "application/mads+xml",
-  "mag": "application/vnd.ecowin.chart",
-  "mail": "message/rfc822",
-  "maker": "application/vnd.framemaker",
-  "man": "application/x-troff-man",
-  "manifest": "text/cache-manifest",
-  "map": "application/x-navimap",
-  "mar": "text/plain",
-  "markdown": "text/markdown",
-  "mathml": "application/mathml+xml",
-  "mb": "application/mathematica",
-  "mbd": "application/mbedlet",
-  "mbk": "application/vnd.mobius.mbk",
-  "mbox": "application/mbox",
-  "mc$": "application/x-magic-cap-package-1.0",
-  "mc1": "application/vnd.medcalcdata",
+  "portpkg": "application/vnd.macports.portpkg",
   "mcd": "application/vnd.mcd",
-  "mcf": "image/vasa",
-  "mcif": "chemical/x-mmcif",
-  "mcm": "chemical/x-macmolecule",
-  "mcp": "application/netmc",
-  "mcurl": "text/vnd.curl.mcurl",
-  "md": "text/markdown",
-  "mdb": "application/x-msaccess",
-  "mdc": "application/vnd.marlin.drm.mdcf",
-  "mdi": "image/vnd.ms-modi",
-  "me": "application/x-troff-me",
-  "med": "audio/x-mod",
-  "mesh": "model/mesh",
-  "meta4": "application/metalink4+xml",
-  "metalink": "application/metalink+xml",
-  "mets": "application/mets+xml",
-  "mf4": "application/mf4",
+  "mc1": "application/vnd.medcalcdata",
+  "cdkey": "application/vnd.mediastation.cdkey",
+  "mwf": "application/vnd.mfer",
   "mfm": "application/vnd.mfmp",
-  "mft": "application/rpki-manifest",
-  "mgp": "application/vnd.osgeo.mapguide.package",
-  "mgz": "application/vnd.proteus.magazine",
-  "mht": "message/rfc822",
-  "mhtml": "message/rfc822",
-  "mib": "text/mib",
-  "mid": "audio/midi",
-  "midi": "audio/midi",
-  "mie": "application/x-mie",
-  "mif": "application/x-mif",
-  "mime": "message/rfc822",
-  "miz": "text/mizar",
-  "mj2": "video/mj2",
-  "mjf": "audio/x-vnd.audioexplosion.mjuicemediafile",
-  "mjp2": "video/mj2",
-  "mjpg": "video/x-motion-jpeg",
-  "mjs": "application/javascript",
-  "mk": "text/makefile",
-  "mk3d": "video/x-matroska-3d",
-  "mka": "audio/x-matroska",
-  "mkd": "text/x-markdown",
-  "mks": "video/x-matroska",
-  "mkv": "video/x-matroska",
-  "mlp": "application/vnd.dolby.mlp",
-  "mm": "application/x-freemind",
-  "mmd": "application/vnd.chipnuts.karaoke-mmd",
-  "mmdb": "application/vnd.maxmind.maxmind-db",
-  "mme": "application/base64",
-  "mmf": "application/vnd.smaf",
-  "mml": "text/mathml",
-  "mmod": "chemical/x-macromodel-input",
-  "mmr": "image/vnd.fujixerox.edmics-mmr",
-  "mms": "application/vnd.wap.mms-message",
-  "mng": "video/x-mng",
-  "mny": "application/x-msmoney",
-  "mobi": "application/x-mobipocket-ebook",
-  "moc": "text/x-moc",
-  "mod": "audio/x-mod",
-  "model-inter": "application/vnd.vd-study",
-  "mods": "application/mods+xml",
-  "modulemap": "text/modulemap",
-  "mol": "chemical/x-mdl-molfile",
-  "mol2": "chemical/x-mol2",
-  "moml": "model/vnd.moml+xml",
-  "moo": "chemical/x-mopac-out",
-  "moov": "video/quicktime",
-  "mop": "chemical/x-mopac-input",
-  "mopcrt": "chemical/x-mopac-input",
-  "mov": "video/quicktime",
-  "movie": "video/x-sgi-movie",
-  "mp1": "audio/mpeg",
-  "mp2": "audio/mpeg",
-  "mp21": "application/mp21",
-  "mp2a": "audio/mpeg",
-  "mp3": "audio/mp3",
-  "mp4": "video/mp4",
-  "mp4a": "audio/mp4",
-  "mp4s": "application/mp4",
-  "mp4v": "video/mp4",
-  "mpa": "video/mpeg",
-  "mpc": "application/vnd.mophun.certificate",
-  "mpd": "application/dash+xml",
-  "mpdd": "application/dashdelta",
-  "mpe": "video/mpeg",
-  "mpeg": "video/mpeg",
-  "mpega": "audio/mpeg",
-  "mpf": "text/vnd.ms-mediapackage",
-  "mpg": "video/mpeg",
-  "mpg4": "video/mp4",
-  "mpga": "audio/mpeg",
-  "mpkg": "application/vnd.apple.installer+xml",
-  "mpm": "application/vnd.blueice.multipass",
+  "flo": "application/vnd.micrografx.flo",
+  "igx": "application/vnd.micrografx.igx",
+  "mif": "application/vnd.mif",
+  "daf": "application/vnd.mobius.daf",
+  "dis": "application/vnd.mobius.dis",
+  "mbk": "application/vnd.mobius.mbk",
+  "mqy": "application/vnd.mobius.mqy",
+  "msl": "application/vnd.mobius.msl",
+  "plc": "application/vnd.mobius.plc",
+  "txf": "application/vnd.mobius.txf",
   "mpn": "application/vnd.mophun.application",
+  "mpc": "application/vnd.mophun.certificate",
+  "xul": "application/vnd.mozilla.xul+xml",
+  "cil": "application/vnd.ms-artgalry",
+  "cab": "application/vnd.ms-cab-compressed",
+  "xls": "application/vnd.ms-excel",
+  "xlm": "application/vnd.ms-excel",
+  "xla": "application/vnd.ms-excel",
+  "xlc": "application/vnd.ms-excel",
+  "xlt": "application/vnd.ms-excel",
+  "xlw": "application/vnd.ms-excel",
+  "xlam": "application/vnd.ms-excel.addin.macroenabled.12",
+  "xlsb": "application/vnd.ms-excel.sheet.binary.macroenabled.12",
+  "xlsm": "application/vnd.ms-excel.sheet.macroenabled.12",
+  "xltm": "application/vnd.ms-excel.template.macroenabled.12",
+  "eot": "application/vnd.ms-fontobject",
+  "chm": "application/vnd.ms-htmlhelp",
+  "ims": "application/vnd.ms-ims",
+  "lrm": "application/vnd.ms-lrm",
+  "thmx": "application/vnd.ms-officetheme",
+  "cat": "application/vnd.ms-pki.seccat",
+  "stl": "application/vnd.ms-pki.stl",
+  "ppt": "application/vnd.ms-powerpoint",
+  "pps": "application/vnd.ms-powerpoint",
+  "pot": "application/vnd.ms-powerpoint",
+  "ppam": "application/vnd.ms-powerpoint.addin.macroenabled.12",
+  "pptm": "application/vnd.ms-powerpoint.presentation.macroenabled.12",
+  "sldm": "application/vnd.ms-powerpoint.slide.macroenabled.12",
+  "ppsm": "application/vnd.ms-powerpoint.slideshow.macroenabled.12",
+  "potm": "application/vnd.ms-powerpoint.template.macroenabled.12",
   "mpp": "application/vnd.ms-project",
   "mpt": "application/vnd.ms-project",
-  "mpv": "application/x-project",
-  "mpv2": "video/mpeg",
-  "mpx": "application/x-project",
-  "mpy": "application/vnd.ibm.minipay",
-  "mqy": "application/vnd.mobius.mqy",
-  "mrc": "application/marc",
-  "mrcx": "application/marcxml+xml",
-  "ms": "application/x-troff-ms",
-  "msa": "application/vnd.msa-disk-image",
-  "mscml": "application/mediaservercontrol+xml",
-  "msd": "application/vnd.fdsn.mseed",
-  "mseed": "application/vnd.fdsn.mseed",
+  "docm": "application/vnd.ms-word.document.macroenabled.12",
+  "dotm": "application/vnd.ms-word.template.macroenabled.12",
+  "wps": "application/vnd.ms-works",
+  "wks": "application/vnd.ms-works",
+  "wcm": "application/vnd.ms-works",
+  "wdb": "application/vnd.ms-works",
+  "wpl": "application/vnd.ms-wpl",
+  "xps": "application/vnd.ms-xpsdocument",
   "mseq": "application/vnd.mseq",
-  "msf": "application/vnd.epson.msf",
-  "msg": "application/vnd.ms-outlook",
-  "msh": "model/mesh",
-  "msi": "application/x-msi",
-  "msl": "application/vnd.mobius.msl",
-  "msm": "model/vnd.gdl",
-  "msty": "application/vnd.muvee.style",
-  "mtm": "audio/x-mod",
-  "mts": "model/vnd.mts",
-  "multitrack": "audio/vnd.presonus.multitrack",
   "mus": "application/vnd.musician",
-  "musd": "application/mmt-usd+xml",
-  "musicxml": "application/vnd.recordare.musicxml+xml",
-  "mv": "video/x-sgi-movie",
-  "mvb": "application/x-msmediaview",
-  "mvt": "application/vnd.mapbox-vector-tile",
-  "mwc": "application/vnd.dpgraph",
-  "mwf": "application/vnd.mfer",
-  "mxf": "application/mxf",
-  "mxi": "application/vnd.vd-study",
-  "mxl": "application/vnd.recordare.musicxml",
-  "mxmf": "audio/mobile-xmf",
-  "mxml": "application/xv+xml",
-  "mxs": "application/vnd.triscape.mxs",
-  "mxu": "video/vnd.mpegurl",
-  "my": "audio/make",
-  "mzz": "application/x-vnd.audioexplosion.mzz",
-  "n-gage": "application/vnd.nokia.n-gage.symbian.install",
-  "n3": "text/n3",
-  "nap": "image/naplps",
-  "naplps": "image/naplps",
-  "nb": "application/mathematica",
-  "nbp": "application/vnd.wolfram.player",
-  "nc": "application/x-netcdf",
-  "ncm": "application/vnd.nokia.configuration-message",
-  "ncx": "application/x-dtbncx+xml",
-  "ndc": "application/vnd.osa.netdeploy",
-  "ndjson": "application/json",
-  "ndl": "application/vnd.lotus-notes",
-  "nds": "application/vnd.nintendo.nitro.rom",
-  "nef": "image/x-nikon-nef",
-  "nfo": "text/x-nfo",
-  "ngdat": "application/vnd.nokia.n-gage.data",
-  "ngdoc": "text/ngdoc",
-  "nif": "image/x-niff",
-  "niff": "image/x-niff",
+  "msty": "application/vnd.muvee.style",
+  "taglet": "application/vnd.mynfc",
+  "nlu": "application/vnd.neurolanguage.nlu",
   "nim": "text/nim",
   "nimble": "text/nimble",
   "nimf": "text/nim",
   "nims": "text/nim",
+  "ntf": "application/vnd.nitf",
   "nitf": "application/vnd.nitf",
-  "nix": "application/x-mix-transfer",
-  "nlu": "application/vnd.neurolanguage.nlu",
-  "nml": "application/vnd.enliven",
   "nnd": "application/vnd.noblenet-directory",
   "nns": "application/vnd.noblenet-sealer",
   "nnw": "application/vnd.noblenet-web",
-  "notebook": "application/vnd.smart.notebook",
-  "npx": "image/vnd.net-fpx",
-  "nq": "application/n-quads",
-  "ns2": "application/vnd.lotus-notes",
-  "ns3": "application/vnd.lotus-notes",
-  "ns4": "application/vnd.lotus-notes",
-  "nsc": "application/x-conference",
-  "nsf": "application/vnd.lotus-notes",
-  "nsg": "application/vnd.lotus-notes",
-  "nsh": "application/vnd.lotus-notes",
-  "nt": "application/n-triples",
-  "ntf": "application/vnd.lotus-notes",
-  "numbers": "application/vnd.apple.numbers",
-  "nvd": "application/x-navidoc",
-  "nwc": "application/x-nwc",
-  "nws": "message/rfc822",
-  "nzb": "application/x-nzb",
-  "o": "application/x-object",
-  "o4a": "application/vnd.oma.drm.dcf",
-  "o4v": "application/vnd.oma.drm.dcf",
-  "oa2": "application/vnd.fujitsu.oasys2",
-  "oa3": "application/vnd.fujitsu.oasys3",
-  "oas": "application/vnd.fujitsu.oasys",
-  "obd": "application/x-msbinder",
-  "obg": "application/vnd.openblox.game-binary",
-  "obgx": "application/vnd.openblox.game+xml",
-  "obj": "application/x-tgif",
-  "oda": "application/oda",
-  "odb": "application/vnd.oasis.opendocument.database",
+  "ngdat": "application/vnd.nokia.n-gage.data",
+  "n-gage": "application/vnd.nokia.n-gage.symbian.install",
+  "rpst": "application/vnd.nokia.radio-preset",
+  "rpss": "application/vnd.nokia.radio-presets",
+  "edm": "application/vnd.novadigm.edm",
+  "edx": "application/vnd.novadigm.edx",
+  "ext": "application/vnd.novadigm.ext",
   "odc": "application/vnd.oasis.opendocument.chart",
-  "odd": "application/tei+xml",
+  "otc": "application/vnd.oasis.opendocument.chart-template",
+  "odb": "application/vnd.oasis.opendocument.database",
   "odf": "application/vnd.oasis.opendocument.formula",
   "odft": "application/vnd.oasis.opendocument.formula-template",
   "odg": "application/vnd.oasis.opendocument.graphics",
-  "odi": "application/vnd.oasis.opendocument.image",
-  "odm": "application/vnd.oasis.opendocument.text-master",
-  "odp": "application/vnd.oasis.opendocument.presentation",
-  "ods": "application/vnd.oasis.opendocument.spreadsheet",
-  "odt": "application/vnd.oasis.opendocument.text",
-  "odx": "application/odx",
-  "oeb": "application/vnd.openeye.oeb",
-  "oga": "audio/ogg",
-  "ogex": "model/vnd.opengex",
-  "ogg": "audio/ogg",
-  "ogv": "video/ogg",
-  "ogx": "application/ogg",
-  "old": "application/x-trash",
-  "omc": "application/x-omc",
-  "omcd": "application/x-omcdatamaker",
-  "omcr": "application/x-omcregerator",
-  "omdoc": "application/omdoc+xml",
-  "omg": "audio/atrac3",
-  "onepkg": "application/onenote",
-  "onetmp": "application/onenote",
-  "onetoc": "application/onenote",
-  "onetoc2": "application/onenote",
-  "opf": "application/oebps-package+xml",
-  "opml": "text/x-opml",
-  "oprc": "application/vnd.palm",
-  "opus": "audio/ogg",
-  "or2": "application/vnd.lotus-organizer",
-  "or3": "application/vnd.lotus-organizer",
-  "orf": "image/x-olympus-orf",
-  "org": "text/x-org",
-  "orq": "application/ocsp-request",
-  "ors": "application/ocsp-response",
-  "osf": "application/vnd.yamaha.openscoreformat",
-  "osfpvg": "application/vnd.yamaha.openscoreformat.osfpvg+xml",
-  "osm": "application/vnd.openstreetmap.data+xml",
-  "otc": "application/vnd.oasis.opendocument.chart-template",
-  "otf": "font/otf",
   "otg": "application/vnd.oasis.opendocument.graphics-template",
-  "oth": "application/vnd.oasis.opendocument.text-web",
+  "odi": "application/vnd.oasis.opendocument.image",
   "oti": "application/vnd.oasis.opendocument.image-template",
+  "odp": "application/vnd.oasis.opendocument.presentation",
   "otp": "application/vnd.oasis.opendocument.presentation-template",
+  "ods": "application/vnd.oasis.opendocument.spreadsheet",
   "ots": "application/vnd.oasis.opendocument.spreadsheet-template",
+  "odt": "application/vnd.oasis.opendocument.text",
+  "odm": "application/vnd.oasis.opendocument.text-master",
   "ott": "application/vnd.oasis.opendocument.text-template",
-  "ova": "application/x-virtualbox-ova",
-  "ovf": "application/x-virtualbox-ovf",
-  "owx": "application/owl+xml",
-  "oxlicg": "application/vnd.oxli.countgraph",
-  "oxps": "application/oxps",
+  "oth": "application/vnd.oasis.opendocument.text-web",
+  "xo": "application/vnd.olpc-sugar",
+  "dd2": "application/vnd.oma.dd2+xml",
   "oxt": "application/vnd.openofficeorg.extension",
-  "oza": "application/x-oz-application",
-  "p": "text/x-pascal",
-  "p10": "application/pkcs10",
-  "p12": "application/pkcs12",
-  "p2p": "application/vnd.wfa.p2p",
-  "p7a": "application/x-pkcs7-signature",
-  "p7b": "application/x-pkcs7-certificates",
-  "p7c": "application/pkcs7-mime",
-  "p7m": "application/pkcs7-mime",
-  "p7r": "application/x-pkcs7-certreqresp",
-  "p7s": "application/pkcs7-signature",
-  "p8": "application/pkcs8",
-  "pac": "application/x-ns-proxy-autoconfig",
-  "pack": "application/x-java-pack200",
-  "package": "application/vnd.autopackage",
-  "pages": "application/vnd.apple.pages",
-  "par": "text/plain-bas",
-  "part": "application/pro_eng",
-  "pas": "text/pascal",
-  "pat": "image/x-coreldrawpattern",
-  "patch": "text/x-diff",
-  "paw": "application/vnd.pawaafile",
-  "pbd": "application/vnd.powerbuilder6",
-  "pbm": "image/x-portable-bitmap",
-  "pcap": "application/vnd.tcpdump.pcap",
-  "pcf": "application/x-font-pcf",
-  "pcl": "application/vnd.hp-pcl",
-  "pclxl": "application/vnd.hp-pclxl",
-  "pct": "image/x-pict",
-  "pcurl": "application/vnd.curl.pcurl",
-  "pcx": "image/x-pcx",
-  "pdb": "application/vnd.palm",
-  "pde": "text/x-processing",
-  "pdf": "application/pdf",
-  "pdx": "application/pdx",
-  "pem": "text/pem",
-  "pfa": "application/x-font-type1",
-  "pfb": "application/x-font-type1",
-  "pfm": "application/x-font-type1",
-  "pfr": "application/font-tdpfr",
-  "pfunk": "audio/make",
-  "pfx": "application/pkcs12",
-  "pgb": "image/vnd.globalgraphics.pgb",
-  "pgm": "image/x-portable-graymap",
-  "pgn": "application/x-chess-pgn",
-  "pgp": "application/pgp-encrypted",
-  "php": "application/x-httpd-php",
-  "php3": "application/x-httpd-php3",
-  "php3p": "application/x-httpd-php3-preprocessed",
-  "php4": "application/x-httpd-php4",
-  "php5": "application/x-httpd-php5",
-  "phps": "application/x-httpd-php-source",
-  "pht": "application/x-httpd-php",
-  "phtml": "application/x-httpd-php",
-  "pic": "image/pict",
-  "pict": "image/pict",
-  "pil": "application/vnd.piaccess.application-license",
-  "pk": "application/x-tex-pk",
-  "pkd": "application/vnd.hbci",
-  "pkg": "application/vnd.apple.installer+xml",
-  "pki": "application/pkixcmp",
-  "pkipath": "application/pkix-pkipath",
-  "pko": "application/ynd.ms-pkipko",
-  "pkpass": "application/vnd.apple.pkpass",
-  "pl": "application/x-perl",
-  "plantuml": "text/plantuml",
-  "plb": "application/vnd.3gpp.pic-bw-large",
-  "plc": "application/vnd.mobius.plc",
-  "plf": "application/vnd.pocketlearn",
-  "plj": "audio/vnd.everad.plj",
-  "plp": "application/vnd.panoply",
-  "pls": "application/pls+xml",
-  "plx": "application/x-pixclscript",
-  "ply": "model/stanford",
-  "pm": "text/plain",
-  "pm4": "application/x-pagemaker",
-  "pm5": "application/x-pagemaker",
-  "pma": "application/x-perfmon",
-  "pmc": "application/x-perfmon",
-  "pml": "application/vnd.ctc-posml",
-  "pmr": "application/x-perfmon",
-  "pmw": "application/x-perfmon",
-  "png": "image/png",
-  "pnm": "image/x-portable-anymap",
-  "po": "text/pofile",
-  "pod": "text/x-pod",
-  "portpkg": "application/vnd.macports.portpkg",
-  "pot": "application/vnd.ms-powerpoint",
-  "potm": "application/vnd.ms-powerpoint.template.macroenabled.12",
-  "potx": "application/vnd.openxmlformats-officedocument.presentationml.template",
-  "pov": "model/x-pov",
-  "pp": "text/puppet",
-  "ppa": "application/vnd.ms-powerpoint",
-  "ppam": "application/vnd.ms-powerpoint.addin.macroenabled.12",
-  "ppd": "application/vnd.cups-ppd",
-  "ppkg": "application/vnd.xmpie.ppkg",
-  "ppm": "image/x-portable-pixmap",
-  "pps": "application/vnd.ms-powerpoint",
-  "ppsm": "application/vnd.ms-powerpoint.slideshow.macroenabled.12",
-  "ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
-  "ppt": "application/vnd.ms-powerpoint",
-  "pptm": "application/vnd.ms-powerpoint.presentation.macroenabled.12",
   "pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
-  "ppz": "application/mspowerpoint",
+  "sldx": "application/vnd.openxmlformats-officedocument.presentationml.slide",
+  "ppsx": "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
+  "potx": "application/vnd.openxmlformats-officedocument.presentationml.template",
+  "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
+  "xltx": "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
+  "docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
+  "dotx": "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
+  "mgp": "application/vnd.osgeo.mapguide.package",
+  "dp": "application/vnd.osgi.dp",
+  "esa": "application/vnd.osgi.subsystem",
+  "pdb": "application/vnd.palm",
   "pqa": "application/vnd.palm",
-  "prc": "application/vnd.palm",
-  "pre": "application/vnd.lotus-freelance",
-  "preminet": "application/vnd.preminet",
-  "prf": "application/pics-rules",
-  "proto": "text/proto",
-  "provn": "text/provenance-notation",
-  "provx": "application/provenance+xml",
-  "prt": "application/pro_eng",
-  "prz": "application/vnd.lotus-freelance",
-  "ps": "application/postscript",
-  "psb": "application/vnd.3gpp.pic-bw-small",
-  "psd": "image/vnd.adobe.photoshop",
-  "pseg3820": "application/vnd.ibm.modcap",
-  "psf": "application/x-font-linux-psf",
-  "psid": "audio/prs.sid",
-  "pskcxml": "application/pskc+xml",
-  "pti": "image/prs.pti",
-  "ptid": "application/vnd.pvi.ptid1",
-  "pub": "application/x-mspublisher",
-  "purs": "text/purescript",
-  "pvb": "application/vnd.3gpp.pic-bw-var",
-  "pvu": "paleovu/x-pv",
-  "pwn": "application/vnd.3m.post-it-notes",
-  "pwz": "application/vnd.ms-powerpoint",
-  "pxd": "text/cython",
-  "pxi": "text/cython",
-  "py": "text/x-script.phyton",
-  "pya": "audio/vnd.ms-playready.media.pya",
-  "pyc": "application/x-python-code",
-  "pyi": "text/pyi",
-  "pyo": "application/x-python-code",
-  "pyv": "video/vnd.ms-playready.media.pyv",
-  "pyx": "text/cython",
-  "qam": "application/vnd.epson.quickanime",
-  "qbo": "application/vnd.intu.qbo",
-  "qca": "application/vnd.ericsson.quickcall",
-  "qcall": "application/vnd.ericsson.quickcall",
-  "qcp": "audio/qcelp",
-  "qd3": "x-world/x-3dmf",
-  "qd3d": "x-world/x-3dmf",
-  "qfx": "application/vnd.intu.qfx",
-  "qgs": "application/x-qgis",
-  "qif": "image/x-quicktime",
+  "oprc": "application/vnd.palm",
+  "paw": "application/vnd.pawaafile",
+  "str": "application/vnd.pg.format",
+  "ei6": "application/vnd.pg.osasli",
+  "efif": "application/vnd.picsel",
+  "wg": "application/vnd.pmi.widget",
+  "plf": "application/vnd.pocketlearn",
+  "pbd": "application/vnd.powerbuilder6",
+  "box": "application/vnd.previewsystems.box",
+  "mgz": "application/vnd.proteus.magazine",
   "qps": "application/vnd.publishare-delta-tree",
-  "qt": "video/quicktime",
-  "qtc": "video/x-qtc",
-  "qti": "image/x-quicktime",
-  "qtif": "image/x-quicktime",
-  "qtl": "application/x-quicktimeplayer",
-  "quiz": "application/vnd.quobject-quoxdocument",
-  "quox": "application/vnd.quobject-quoxdocument",
-  "qvd": "application/vnd.theqvd",
+  "ptid": "application/vnd.pvi.ptid1",
+  "qxd": "application/vnd.quark.quarkxpress",
+  "qxt": "application/vnd.quark.quarkxpress",
   "qwd": "application/vnd.quark.quarkxpress",
   "qwt": "application/vnd.quark.quarkxpress",
-  "qxb": "application/vnd.quark.quarkxpress",
-  "qxd": "application/vnd.quark.quarkxpress",
   "qxl": "application/vnd.quark.quarkxpress",
-  "qxt": "application/vnd.quark.quarkxpress",
-  "r": "text/r",
-  "ra": "audio/x-realaudio",
-  "ram": "audio/x-pn-realaudio",
-  "raml": "application/raml+yaml",
-  "rapd": "application/route-apd+xml",
-  "rar": "application/x-rar-compressed",
-  "ras": "image/x-cmu-raster",
-  "rast": "image/cmu-raster",
-  "rb": "application/x-ruby",
-  "rcprofile": "application/vnd.ipunplugged.rcprofile",
-  "rct": "application/prs.nprend",
-  "rd": "chemical/x-mdl-rdfile",
-  "rda": "text/r",
-  "rdata": "text/r",
-  "rds": "text/r",
-  "rdf": "application/rdf+xml",
-  "rdf-crypt": "application/prs.rdf-xml-crypt",
-  "rdz": "application/vnd.data-vision.rdz",
-  "relo": "application/p2p-overlay+xml",
-  "rep": "application/vnd.businessobjects",
-  "request": "application/vnd.nervana",
-  "res": "application/x-dtbresource+xml",
-  "rexx": "text/x-script.rexx",
-  "rf": "image/vnd.rn-realflash",
-  "rfcxml": "application/rfc+xml",
-  "rgb": "image/x-rgb",
-  "rgbe": "image/vnd.radiance",
-  "rhtml": "application/x-httpd-eruby",
-  "rif": "application/reginfo+xml",
-  "rip": "audio/vnd.rip",
-  "ris": "application/x-research-info-systems",
-  "rl": "application/resource-lists+xml",
-  "rlc": "image/vnd.fujixerox.edmics-rlc",
-  "rld": "application/resource-lists-diff+xml",
-  "rlib": "text/rust",
+  "qxb": "application/vnd.quark.quarkxpress",
+  "bed": "application/vnd.realvnc.bed",
+  "mxl": "application/vnd.recordare.musicxml",
+  "musicxml": "application/vnd.recordare.musicxml+xml",
+  "cryptonote": "application/vnd.rig.cryptonote",
+  "cod": "application/vnd.rim.cod",
   "rm": "application/vnd.rn-realmedia",
-  "rmi": "audio/mid",
-  "rmm": "audio/x-pn-realaudio",
-  "rmp": "audio/x-pn-realaudio-plugin",
-  "rms": "application/vnd.jcp.javame.midlet-rms",
   "rmvb": "application/vnd.rn-realmedia-vbr",
-  "rnc": "application/relax-ng-compact-syntax",
-  "rnd": "application/prs.nprend",
-  "rng": "text/xml",
-  "rnx": "application/vnd.rn-realplayer",
-  "roa": "application/rpki-roa",
-  "roff": "text/troff",
-  "ros": "chemical/x-rosdal",
-  "rp": "image/vnd.rn-realpix",
-  "rp9": "application/vnd.cloanto.rp9",
-  "rpm": "application/x-redhat-package-manager",
-  "rpss": "application/vnd.nokia.radio-presets",
-  "rpst": "application/vnd.nokia.radio-preset",
-  "rq": "application/sparql-query",
-  "rs": "application/rls-services+xml",
-  "rsd": "application/rsd+xml",
-  "rsheet": "application/urc-ressheet+xml",
-  "rsm": "model/vnd.gdl",
-  "rss": "application/rss+xml",
-  "rst": "text/prs.fallenstein.rst",
-  "rt": "text/richtext",
-  "rtf": "text/rtf",
-  "rtx": "text/richtext",
-  "run": "application/x-makeself",
-  "rusd": "application/route-usd+xml",
-  "rv": "video/vnd.rn-realvideo",
-  "rxn": "chemical/x-mdl-rxnfile",
-  "s": "text/x-asm",
-  "s11": "video/vnd.sealed.mpeg1",
-  "s14": "video/vnd.sealed.mpeg4",
-  "s1a": "application/vnd.sealedmedia.softseal.pdf",
-  "s1e": "application/vnd.sealed.xls",
-  "s1g": "image/vnd.sealedmedia.softseal.gif",
-  "s1h": "application/vnd.sealedmedia.softseal.html",
-  "s1j": "image/vnd.sealedmedia.softseal.jpg",
-  "s1m": "audio/vnd.sealedmedia.softseal.mpeg",
-  "s1n": "image/vnd.sealed.png",
-  "s1p": "application/vnd.sealed.ppt",
-  "s1q": "video/vnd.sealedmedia.softseal.mov",
-  "s1w": "application/vnd.sealed.doc",
-  "s3df": "application/vnd.sealed.3df",
-  "s3m": "audio/s3m",
-  "sac": "application/tamp-sequence-adjust-confirm",
-  "saf": "application/vnd.yamaha.smaf-audio",
-  "sam": "application/vnd.lotus-wordpro",
-  "sandboxed": "text/html-sandboxed",
-  "sass": "text/x-sass",
-  "saveme": "application/octet-stream",
-  "sbk": "application/x-tbook",
-  "sbml": "application/sbml+xml",
-  "sc": "application/vnd.ibm.secure-container",
-  "scala": "text/x-scala",
-  "scd": "application/x-msschedule",
-  "sce": "application/vnd.etsi.asic-e+zip",
-  "scim": "application/scim+json",
-  "scld": "application/vnd.doremir.scorecloud-binary-document",
-  "scm": "application/vnd.lotus-screencam",
-  "scq": "application/scvp-cv-request",
-  "scr": "application/x-silverlight",
-  "scs": "application/scvp-cv-response",
-  "scsf": "application/vnd.sealed.csf",
-  "scss": "text/x-scss",
-  "sct": "text/scriptlet",
-  "scurl": "text/vnd.curl.scurl",
-  "sd": "chemical/x-mdl-sdfile",
-  "sd2": "audio/x-sd2",
-  "sda": "application/vnd.stardivision.draw",
-  "sdc": "application/vnd.stardivision.calc",
-  "sdd": "application/vnd.stardivision.impress",
-  "sdf": "application/vnd.kinar",
-  "sdkd": "application/vnd.solent.sdkm+xml",
-  "sdkm": "application/vnd.solent.sdkm+xml",
-  "sdml": "text/plain",
-  "sdo": "application/vnd.sealed.doc",
-  "sdoc": "application/vnd.sealed.doc",
-  "sdp": "application/sdp",
-  "sdr": "application/sounder",
-  "sdw": "application/vnd.stardivision.writer",
-  "sea": "application/x-sea",
+  "link66": "application/vnd.route66.link66+xml",
+  "st": "application/vnd.sailingtracker.track",
   "see": "application/vnd.seemail",
-  "seed": "application/vnd.fdsn.seed",
-  "sem": "application/vnd.sealed.eml",
   "sema": "application/vnd.sema",
   "semd": "application/vnd.semd",
   "semf": "application/vnd.semf",
-  "seml": "application/vnd.sealed.eml",
-  "ser": "application/java-serialized-object",
-  "set": "application/set",
-  "setpay": "application/set-payment-initiation",
-  "setreg": "application/set-registration-initiation",
-  "sfc": "application/vnd.nintendo.snes.rom",
-  "sfd": "application/vnd.font-fontforge-sfd",
-  "sfd-hdstx": "application/vnd.hydrostatix.sof-data",
+  "ifm": "application/vnd.shana.informed.formdata",
+  "itp": "application/vnd.shana.informed.formtemplate",
+  "iif": "application/vnd.shana.informed.interchange",
+  "ipk": "application/vnd.shana.informed.package",
+  "twd": "application/vnd.simtech-mindmapper",
+  "twds": "application/vnd.simtech-mindmapper",
+  "mmf": "application/vnd.smaf",
+  "teacher": "application/vnd.smart.teacher",
+  "sdkm": "application/vnd.solent.sdkm+xml",
+  "sdkd": "application/vnd.solent.sdkm+xml",
+  "dxp": "application/vnd.spotfire.dxp",
   "sfs": "application/vnd.spotfire.sfs",
-  "sfv": "text/x-sfv",
-  "sgf": "application/x-go-sgf",
-  "sgi": "image/sgi",
-  "sgif": "image/vnd.sealedmedia.softseal.gif",
-  "sgl": "application/vnd.stardivision.writer-global",
-  "sgm": "text/sgml",
-  "sgml": "text/sgml",
-  "sh": "application/x-sh",
-  "shar": "application/x-shar",
-  "shex": "text/shex",
-  "shf": "application/shf+xml",
-  "shp": "application/x-qgis",
-  "shx": "application/x-qgis",
-  "si": "text/vnd.wap.si",
-  "sic": "application/vnd.wap.sic",
-  "sid": "image/x-mrsid-image",
-  "sieve": "application/sieve",
-  "sig": "application/pgp-signature",
-  "sik": "application/x-trash",
-  "sil": "audio/silk",
-  "silo": "model/mesh",
-  "sis": "application/vnd.symbian.install",
-  "sisx": "x-epoc/x-sisx-app",
-  "sit": "application/x-stuffit",
-  "sitx": "application/x-stuffitx",
-  "siv": "application/sieve",
-  "sjp": "image/vnd.sealedmedia.softseal.jpg",
-  "sjpg": "image/vnd.sealedmedia.softseal.jpg",
-  "skd": "application/vnd.koan",
-  "skm": "application/vnd.koan",
-  "skp": "application/vnd.koan",
-  "skt": "application/vnd.koan",
-  "sl": "text/vnd.wap.sl",
-  "sla": "application/vnd.scribus",
-  "slaz": "application/vnd.scribus",
-  "slc": "application/vnd.wap.slc",
-  "sldm": "application/vnd.ms-powerpoint.slide.macroenabled.12",
-  "sldx": "application/vnd.openxmlformats-officedocument.presentationml.slide",
-  "sls": "application/route-s-tsid+xml",
-  "slt": "application/vnd.epson.salt",
-  "sm": "application/vnd.stepmania.stepchart",
-  "smc": "application/vnd.nintendo.snes.rom",
+  "sdc": "application/vnd.stardivision.calc",
+  "sda": "application/vnd.stardivision.draw",
+  "sdd": "application/vnd.stardivision.impress",
   "smf": "application/vnd.stardivision.math",
-  "smh": "application/vnd.sealed.mht",
-  "smht": "application/vnd.sealed.mht",
-  "smi": "application/smil+xml",
-  "smil": "application/smil+xml",
-  "smk": "video/vnd.radgamettools.smacker",
-  "sml": "application/smil+xml",
-  "smo": "video/vnd.sealedmedia.softseal.mov",
-  "smov": "video/vnd.sealedmedia.softseal.mov",
-  "smp": "audio/vnd.sealedmedia.softseal.mpeg",
-  "smp3": "audio/vnd.sealedmedia.softseal.mpeg",
-  "smpg": "video/vnd.sealed.mpeg1",
-  "sms": "application/vnd.3gpp2.sms",
-  "smv": "video/x-smv",
+  "sdw": "application/vnd.stardivision.writer",
+  "vor": "application/vnd.stardivision.writer",
+  "sgl": "application/vnd.stardivision.writer-global",
   "smzip": "application/vnd.stepmania.package",
-  "snd": "audio/basic",
-  "snf": "application/x-font-snf",
-  "so": "application/octet-stream",
-  "soa": "text/dns",
-  "soc": "application/sgml-open-catalog",
-  "sol": "application/solids",
-  "spc": "text/x-speech",
-  "spd": "application/vnd.sealedmedia.softseal.pdf",
-  "spdf": "application/vnd.sealedmedia.softseal.pdf",
-  "spec": "text/spec",
-  "spf": "application/vnd.yamaha.smaf-phrase",
-  "spl": "application/x-futuresplash",
-  "spn": "image/vnd.sealed.png",
-  "spng": "image/vnd.sealed.png",
-  "spo": "text/vnd.in3d.spot",
-  "spot": "text/vnd.in3d.spot",
-  "spp": "application/scvp-vp-response",
-  "sppt": "application/vnd.sealed.ppt",
-  "spq": "application/scvp-vp-request",
-  "spr": "application/x-sprite",
-  "sprite": "application/x-sprite",
-  "spx": "audio/ogg",
-  "sql": "application/x-sql",
-  "sr": "application/vnd.sigrok.session",
-  "src": "application/x-wais-source",
-  "srt": "application/x-subrip",
-  "sru": "application/sru+xml",
-  "srx": "application/sparql-results+xml",
-  "ssdl": "application/ssdl+xml",
-  "sse": "application/vnd.kodak-descriptor",
-  "ssf": "application/vnd.epson.ssf",
-  "ssi": "text/x-server-parsed-html",
-  "ssm": "application/streamingmedia",
-  "ssml": "application/ssml+xml",
-  "sst": "application/vnd.ms-pki.certstore",
-  "ssw": "video/vnd.sealed.swf",
-  "sswf": "video/vnd.sealed.swf",
-  "st": "application/vnd.sailingtracker.track",
+  "sm": "application/vnd.stepmania.stepchart",
+  "sxc": "application/vnd.sun.xml.calc",
   "stc": "application/vnd.sun.xml.calc.template",
+  "sxd": "application/vnd.sun.xml.draw",
   "std": "application/vnd.sun.xml.draw.template",
-  "step": "application/step",
-  "stf": "application/vnd.wt.stf",
+  "sxi": "application/vnd.sun.xml.impress",
   "sti": "application/vnd.sun.xml.impress.template",
-  "stif": "application/vnd.sealed.tiff",
-  "stk": "application/hyperstudio",
-  "stl": "application/vnd.ms-pki.stl",
-  "stm": "audio/x-stm",
-  "stml": "application/vnd.sealedmedia.softseal.html",
-  "stp": "application/step",
-  "str": "application/vnd.pg.format",
-  "study-inter": "application/vnd.vd-study",
+  "sxm": "application/vnd.sun.xml.math",
+  "sxw": "application/vnd.sun.xml.writer",
+  "sxg": "application/vnd.sun.xml.writer.global",
   "stw": "application/vnd.sun.xml.writer.template",
-  "sty": "text/x-tex",
-  "styl": "text/stylus",
-  "sub": "text/vnd.dvb.subtitle",
   "sus": "application/vnd.sus-calendar",
   "susp": "application/vnd.sus-calendar",
-  "sv4cpio": "application/x-sv4cpio",
-  "sv4crc": "application/x-sv4crc",
-  "svc": "application/vnd.dvb.service",
   "svd": "application/vnd.svd",
-  "svf": "image/x-dwg",
-  "svg": "image/svg+xml",
-  "svgz": "image/svg+xml",
-  "sw": "chemical/x-swissprot",
-  "swa": "application/x-director",
-  "swf": "application/x-shockwave-flash",
-  "swfl": "application/x-shockwave-flash",
-  "swi": "application/vnd.aristanetworks.swi",
-  "swift": "text/swift",
-  "swiftdeps": "text/swiftdeps",
-  "sxc": "application/vnd.sun.xml.calc",
-  "sxd": "application/vnd.sun.xml.draw",
-  "sxg": "application/vnd.sun.xml.writer.global",
-  "sxi": "application/vnd.sun.xml.impress",
-  "sxl": "application/vnd.sealed.xls",
-  "sxls": "application/vnd.sealed.xls",
-  "sxm": "application/vnd.sun.xml.math",
-  "sxw": "application/vnd.sun.xml.writer",
-  "t": "text/troff",
-  "t3": "application/x-t3vm-image",
-  "t38": "image/t38",
-  "tac": "text/twisted",
-  "tag": "text/prs.lines.tag",
-  "taglet": "application/vnd.mynfc",
-  "talk": "text/x-speech",
-  "tam": "application/vnd.onepager",
-  "tamp": "application/vnd.onepagertamp",
-  "tamx": "application/vnd.onepagertamx",
+  "sis": "application/vnd.symbian.install",
+  "sisx": "application/vnd.symbian.install",
+  "xsm": "application/vnd.syncml+xml",
+  "bdm": "application/vnd.syncml.dm+wbxml",
+  "xdm": "application/vnd.syncml.dm+xml",
   "tao": "application/vnd.tao.intent-module-archive",
-  "tap": "image/vnd.tencent.tap",
-  "tar": "application/x-tar",
-  "tat": "application/vnd.onepagertat",
-  "tatp": "application/vnd.onepagertatp",
-  "tatx": "application/vnd.onepagertatx",
-  "tau": "application/tamp-apex-update",
-  "taz": "application/x-gtar",
-  "tbk": "application/toolbook",
-  "tcap": "application/vnd.3gpp2.tcap",
-  "tcl": "application/x-tcl",
-  "tcsh": "text/x-script.tcsh",
-  "tcu": "application/tamp-community-update",
-  "td": "application/urc-targetdesc+xml",
-  "teacher": "application/vnd.smart.teacher",
-  "tei": "application/tei+xml",
-  "teicorpus": "application/tei+xml",
-  "ter": "application/tamp-error",
-  "tex": "application/x-tex",
-  "texi": "application/x-texinfo",
-  "texinfo": "application/x-texinfo",
-  "text": "text/plain",
-  "tf": "text/terraform",
-  "tfi": "application/thraud+xml",
-  "tfm": "application/x-tex-tfm",
-  "tfx": "image/tiff-fx",
-  "tga": "image/x-tga",
-  "tgf": "chemical/x-mdl-tgf",
-  "tgz": "application/gzip",
-  "thmx": "application/vnd.ms-officetheme",
-  "thrift": "text/thrift",
-  "tif": "image/tiff",
-  "tiff": "image/tiff",
-  "tk": "text/x-tcl",
-  "tlclient": "application/vnd.cendio.thinlinc.clientconf",
-  "tm": "text/texmacs",
+  "pcap": "application/vnd.tcpdump.pcap",
+  "cap": "application/vnd.tcpdump.pcap",
+  "dmp": "application/vnd.tcpdump.pcap",
   "tmo": "application/vnd.tmobile-livetv",
-  "tnef": "application/vnd.ms-tnef",
-  "tnf": "application/vnd.ms-tnef",
-  "toml": "text/toml",
-  "torrent": "application/x-bittorrent",
-  "tpl": "application/vnd.groove-tool-template",
   "tpt": "application/vnd.trid.tpt",
-  "tr": "text/troff",
+  "mxs": "application/vnd.triscape.mxs",
   "tra": "application/vnd.trueapp",
-  "tree": "application/vnd.rainstor.data",
-  "trig": "application/trig",
-  "trm": "application/x-msterminal",
-  "ts": "video/mp2t",
-  "tsa": "application/tamp-sequence-adjust",
-  "tscn": "text/godot",
-  "tsd": "application/timestamped-data",
-  "tsi": "audio/tsp-audio",
-  "tsp": "audio/tsplayer",
-  "tsq": "application/timestamp-query",
-  "tsr": "application/timestamp-reply",
-  "tst": "application/vnd.etsi.timestamp-token",
-  "tsv": "text/tab-separated-values",
-  "tsx": "text/tsx",
-  "ttc": "font/collection",
-  "ttf": "font/ttf",
-  "ttl": "text/turtle",
-  "ttml": "application/ttml+xml",
-  "tuc": "application/tamp-update-confirm",
-  "tur": "application/tamp-update",
-  "turbot": "image/florian",
-  "twd": "application/vnd.simtech-mindmapper",
-  "twds": "application/vnd.simtech-mindmapper",
-  "txd": "application/vnd.genomatix.tuxedo",
-  "txf": "application/vnd.mobius.txf",
-  "txt": "text/plain",
-  "u32": "application/x-authorware-bin",
-  "u8dsn": "message/global-delivery-status",
-  "u8hdr": "message/global-headers",
-  "u8mdn": "message/global-disposition-notification",
-  "u8msg": "message/global",
-  "udeb": "application/vnd.debian.binary-package",
   "ufd": "application/vnd.ufdl",
   "ufdl": "application/vnd.ufdl",
-  "uil": "text/x-uil",
-  "uis": "application/urc-uisocketdesc+xml",
-  "uls": "text/iuls",
-  "ult": "audio/x-mod",
-  "ulx": "application/x-glulx",
+  "utz": "application/vnd.uiq.theme",
   "umj": "application/vnd.umajin",
-  "uni": "audio/x-mod",
-  "unis": "text/uri-list",
   "unityweb": "application/vnd.unity",
-  "unv": "application/i-deas",
-  "uo": "application/vnd.uoml+xml",
   "uoml": "application/vnd.uoml+xml",
-  "upa": "application/vnd.hbci",
-  "uri": "text/uri-list",
-  "uric": "text/vnd.si.uricatalogue",
-  "urim": "application/vnd.uri-map",
-  "urimap": "application/vnd.uri-map",
-  "uris": "text/uri-list",
-  "urls": "text/uri-list",
-  "ustar": "application/x-ustar",
-  "utz": "application/vnd.uiq.theme",
-  "uu": "text/x-uuencode",
-  "uue": "text/x-uuencode",
-  "uva": "audio/vnd.dece.audio",
-  "uvd": "application/vnd.dece.data",
-  "uvf": "application/vnd.dece.data",
-  "uvg": "image/vnd.dece.graphic",
-  "uvh": "video/vnd.dece.hd",
-  "uvi": "image/vnd.dece.graphic",
-  "uvm": "video/vnd.dece.mobile",
-  "uvp": "video/vnd.dece.pd",
-  "uvs": "video/vnd.dece.sd",
-  "uvt": "application/vnd.dece.ttml+xml",
-  "uvu": "video/vnd.dece.mp4",
-  "uvv": "video/vnd.dece.video",
-  "uvva": "audio/vnd.dece.audio",
-  "uvvd": "application/vnd.dece.data",
-  "uvvf": "application/vnd.dece.data",
-  "uvvg": "image/vnd.dece.graphic",
-  "uvvh": "video/vnd.dece.hd",
-  "uvvi": "image/vnd.dece.graphic",
-  "uvvm": "video/vnd.dece.mobile",
-  "uvvp": "video/vnd.dece.pd",
-  "uvvs": "video/vnd.dece.sd",
-  "uvvt": "application/vnd.dece.ttml+xml",
-  "uvvu": "video/vnd.dece.mp4",
-  "uvvv": "video/vnd.dece.video",
-  "uvvx": "application/vnd.dece.unspecified",
-  "uvvz": "application/vnd.dece.zip",
-  "uvx": "application/vnd.dece.unspecified",
-  "uvz": "application/vnd.dece.zip",
-  "val": "chemical/x-ncbi-asn1-binary",
-  "vbk": "audio/vnd.nortel.vbk",
-  "vbox": "application/x-virtualbox-vbox",
-  "vbox-extpack": "application/x-virtualbox-vbox-extpack",
-  "vcard": "text/vcard",
-  "vcd": "application/x-cdlink",
-  "vcf": "text/x-vcard",
-  "vcg": "application/vnd.groove-vcard",
-  "vcs": "text/x-vcalendar",
   "vcx": "application/vnd.vcx",
-  "vda": "application/vda",
-  "vdi": "application/x-virtualbox-vdi",
-  "vdo": "video/vdo",
-  "vdx": "text/vdx",
-  "vew": "application/vnd.lotus-approach",
-  "vfr": "application/vnd.tml",
-  "vhd": "application/x-virtualbox-vhd",
-  "viaframe": "application/vnd.tml",
-  "vim": "text/vim",
-  "vis": "application/vnd.visionary",
-  "viv": "video/vnd.vivo",
-  "vivo": "video/vivo",
-  "vmd": "application/vocaltec-media-desc",
-  "vmdk": "application/x-virtualbox-vmdk",
-  "vmf": "application/vocaltec-media-file",
-  "vms": "chemical/x-vamas-iso14976",
-  "vmt": "application/vnd.valve.source.material",
-  "vob": "video/x-ms-vob",
-  "voc": "audio/voc",
-  "vor": "application/vnd.stardivision.writer",
-  "vos": "video/vosaic",
-  "vox": "audio/voxware",
-  "vpm": "multipart/voice-message",
-  "vqe": "audio/x-twinvq-plugin",
-  "vqf": "audio/x-twinvq",
-  "vql": "audio/x-twinvq-plugin",
-  "vrm": "x-world/x-vrml",
-  "vrml": "model/vrml",
-  "vrt": "x-world/x-vrt",
-  "vsc": "application/vnd.vidsoft.vidconference",
   "vsd": "application/vnd.visio",
-  "vsf": "application/vnd.vsf",
-  "vss": "application/vnd.visio",
   "vst": "application/vnd.visio",
+  "vss": "application/vnd.visio",
   "vsw": "application/vnd.visio",
-  "vtf": "image/vnd.valve.source.texture",
-  "vtt": "text/vtt",
-  "vtu": "model/vnd.vtu",
-  "vue": "text/vue",
-  "vwx": "application/vnd.vectorworks",
-  "vxml": "application/voicexml+xml",
-  "w3d": "application/x-director",
-  "w60": "application/wordperfect6.0",
-  "w61": "application/wordperfect6.1",
-  "w6w": "application/msword",
-  "wad": "application/x-doom",
-  "wadl": "application/vnd.sun.wadl+xml",
-  "war": "binary/zip",
-  "wasm": "application/wasm",
-  "wav": "audio/wave",
-  "wax": "audio/x-ms-wax",
-  "wb1": "application/x-qpro",
-  "wbmp": "image/vnd.wap.wbmp",
-  "wbs": "application/vnd.criticaltools.wbs+xml",
+  "vis": "application/vnd.visionary",
+  "vsf": "application/vnd.vsf",
   "wbxml": "application/vnd.wap.wbxml",
-  "wcm": "application/vnd.ms-works",
-  "wdb": "application/vnd.ms-works",
-  "wdp": "image/vnd.ms-photo",
-  "web": "application/vnd.xara",
-  "weba": "audio/webm",
-  "webapp": "application/x-web-app-manifest+json",
-  "webm": "video/webm",
-  "webmanifest": "application/manifest+json",
-  "webp": "image/webp",
-  "wg": "application/vnd.pmi.widget",
-  "wgt": "application/widget",
-  "whl": "binary/wheel",
-  "wif": "application/watcherinfo+xml",
-  "win": "model/vnd.gdl",
-  "wiz": "application/msword",
-  "wk": "application/x-123",
-  "wk1": "application/vnd.lotus-1-2-3",
-  "wk3": "application/vnd.lotus-1-2-3",
-  "wk4": "application/vnd.lotus-1-2-3",
-  "wks": "application/vnd.ms-works",
-  "wkt": "text/wkt",
-  "wlnk": "application/link-format",
-  "wm": "video/x-ms-wm",
-  "wma": "audio/x-ms-wma",
-  "wmc": "application/vnd.wmc",
-  "wmd": "application/x-ms-wmd",
-  "wmf": "image/wmf",
-  "wml": "text/vnd.wap.wml",
   "wmlc": "application/vnd.wap.wmlc",
-  "wmls": "text/vnd.wap.wmlscript",
   "wmlsc": "application/vnd.wap.wmlscriptc",
-  "wmv": "video/x-ms-wmv",
-  "wmx": "video/x-ms-wmx",
-  "wmz": "application/x-ms-wmz",
-  "woff": "font/woff",
-  "woff2": "font/woff2",
-  "word": "application/msword",
-  "wp": "application/wordperfect",
-  "wp5": "application/wordperfect",
-  "wp6": "application/wordperfect",
+  "wtb": "application/vnd.webturbo",
+  "nbp": "application/vnd.wolfram.player",
   "wpd": "application/vnd.wordperfect",
-  "wpl": "application/vnd.ms-wpl",
-  "wps": "application/vnd.ms-works",
-  "wq1": "application/x-lotus",
   "wqd": "application/vnd.wqd",
-  "wri": "application/x-mswrite",
-  "wrl": "model/vrml",
-  "wrz": "model/vrml",
-  "wsc": "message/vnd.wfa.wsc",
+  "stf": "application/vnd.wt.stf",
+  "xar": "application/vnd.xara",
+  "xfdl": "application/vnd.xfdl",
+  "hvd": "application/vnd.yamaha.hv-dic",
+  "hvs": "application/vnd.yamaha.hv-script",
+  "hvp": "application/vnd.yamaha.hv-voice",
+  "osf": "application/vnd.yamaha.openscoreformat",
+  "osfpvg": "application/vnd.yamaha.openscoreformat.osfpvg+xml",
+  "saf": "application/vnd.yamaha.smaf-audio",
+  "spf": "application/vnd.yamaha.smaf-phrase",
+  "cmp": "application/vnd.yellowriver-custom-menu",
+  "zir": "application/vnd.zul",
+  "zirz": "application/vnd.zul",
+  "zaz": "application/vnd.zzazz.deck+xml",
+  "vxml": "application/voicexml+xml",
+  "wasm": "application/wasm",
+  "wgt": "application/widget",
+  "hlp": "application/winhlp",
   "wsdl": "application/wsdl+xml",
-  "wsgi": "text/wsgi",
   "wspolicy": "application/wspolicy+xml",
-  "wsrc": "application/x-wais-source",
-  "wtb": "application/vnd.webturbo",
-  "wtk": "application/x-wintalk",
-  "wv": "application/vnd.wv.csp+wbxml",
-  "wvx": "video/x-ms-wvx",
-  "wz": "application/x-wingz",
-  "x-png": "image/png",
+  "7z": "application/x-7z-compressed",
+  "abw": "application/x-abiword",
+  "ace": "application/x-ace-compressed",
+  "dmg": "application/x-apple-diskimage",
+  "aab": "application/x-authorware-bin",
   "x32": "application/x-authorware-bin",
-  "x3d": "application/vnd.hzn-3d-crossword",
-  "x3db": "model/x3d+xml",
-  "x3dbz": "model/x3d+binary",
-  "x3dv": "model/x3d-vrml",
-  "x3dvz": "model/x3d-vrml",
-  "x3dz": "model/x3d+xml",
-  "x_b": "model/vnd.parasolid.transmit.binary",
-  "x_t": "model/vnd.parasolid.transmit.text",
-  "xaf": "x-world/x-vrml",
-  "xaml": "application/xaml+xml",
-  "xap": "application/x-silverlight-app",
-  "xar": "application/vnd.xara",
-  "xav": "application/xcap-att+xml",
+  "u32": "application/x-authorware-bin",
+  "vox": "application/x-authorware-bin",
+  "aam": "application/x-authorware-map",
+  "aas": "application/x-authorware-seg",
+  "bcpio": "application/x-bcpio",
+  "torrent": "application/x-bittorrent",
+  "blb": "application/x-blorb",
+  "blorb": "application/x-blorb",
+  "bz": "application/x-bzip",
+  "bz2": "application/x-bzip2",
+  "boz": "application/x-bzip2",
+  "cbr": "application/x-cbr",
+  "cba": "application/x-cbr",
+  "cbt": "application/x-cbr",
+  "cbz": "application/x-cbr",
+  "cb7": "application/x-cbr",
+  "vcd": "application/x-cdlink",
+  "cfs": "application/x-cfs-compressed",
+  "chat": "application/x-chat",
+  "pgn": "application/x-chess-pgn",
+  "nsc": "application/x-conference",
+  "cpio": "application/x-cpio",
+  "csh": "application/x-csh",
+  "deb": "application/x-debian-package",
+  "udeb": "application/x-debian-package",
+  "dgc": "application/x-dgc-compressed",
+  "dir": "application/x-director",
+  "dcr": "application/x-director",
+  "dxr": "application/x-director",
+  "cst": "application/x-director",
+  "cct": "application/x-director",
+  "cxt": "application/x-director",
+  "w3d": "application/x-director",
+  "fgd": "application/x-director",
+  "swa": "application/x-director",
+  "wad": "application/x-doom",
+  "ncx": "application/x-dtbncx+xml",
+  "dtb": "application/x-dtbook+xml",
+  "res": "application/x-dtbresource+xml",
+  "dvi": "application/x-dvi",
+  "evy": "application/x-envoy",
+  "eva": "application/x-eva",
+  "bdf": "application/x-font-bdf",
+  "gsf": "application/x-font-ghostscript",
+  "psf": "application/x-font-linux-psf",
+  "pcf": "application/x-font-pcf",
+  "snf": "application/x-font-snf",
+  "pfa": "application/x-font-type1",
+  "pfb": "application/x-font-type1",
+  "pfm": "application/x-font-type1",
+  "afm": "application/x-font-type1",
+  "arc": "application/x-freearc",
+  "spl": "application/x-futuresplash",
+  "gca": "application/x-gca-compressed",
+  "ulx": "application/x-glulx",
+  "gnumeric": "application/x-gnumeric",
+  "gramps": "application/x-gramps-xml",
+  "gtar": "application/x-gtar",
+  "hdf": "application/x-hdf",
+  "install": "application/x-install-instructions",
+  "iso": "application/x-iso9660-image",
+  "jnlp": "application/x-java-jnlp-file",
+  "latex": "application/x-latex",
+  "lzh": "application/x-lzh-compressed",
+  "lha": "application/x-lzh-compressed",
+  "mie": "application/x-mie",
+  "prc": "application/x-mobipocket-ebook",
+  "mobi": "application/x-mobipocket-ebook",
+  "application": "application/x-ms-application",
+  "lnk": "application/x-ms-shortcut",
+  "wmd": "application/x-ms-wmd",
+  "wmz": "application/x-ms-wmz",
   "xbap": "application/x-ms-xbap",
-  "xbd": "application/vnd.fujixerox.docuworks.binder",
-  "xbm": "image/x-xbitmap",
-  "xca": "application/xcap-caps+xml",
-  "xcf": "application/x-xcf",
-  "xcs": "application/calendar+xml",
-  "xct": "application/vnd.fujixerox.docuworks.container",
-  "xdd": "application/bacnet-xdd+zip",
-  "xdf": "application/xcap-diff+xml",
-  "xdm": "application/vnd.syncml.dm+xml",
-  "xdp": "application/vnd.adobe.xdp+xml",
-  "xdr": "video/x-amt-demorun",
-  "xdssc": "application/dssc+xml",
-  "xdw": "application/vnd.fujixerox.docuworks",
-  "xel": "application/xcap-el+xml",
-  "xenc": "application/xenc+xml",
-  "xer": "application/patch-ops-error+xml",
-  "xfd": "application/vnd.xfdl",
-  "xfdf": "application/vnd.adobe.xfdf",
-  "xfdl": "application/vnd.xfdl",
-  "xgz": "xgl/drawing",
-  "xht": "application/xhtml+xml",
-  "xhtm": "application/xhtml+xml",
-  "xhtml": "application/xhtml+xml",
-  "xhvml": "application/xv+xml",
-  "xif": "image/vnd.xiff",
-  "xl": "application/excel",
-  "xla": "application/vnd.ms-excel",
-  "xlam": "application/vnd.ms-excel.addin.macroenabled.12",
-  "xlb": "application/vndms-excel",
-  "xlc": "application/vnd.ms-excel",
+  "mdb": "application/x-msaccess",
+  "obd": "application/x-msbinder",
+  "crd": "application/x-mscardfile",
+  "clp": "application/x-msclip",
+  "exe": "application/x-msdownload",
+  "dll": "application/x-msdownload",
+  "com": "application/x-msdownload",
+  "bat": "application/x-msdownload",
+  "msi": "application/x-msdownload",
+  "mvb": "application/x-msmediaview",
+  "m13": "application/x-msmediaview",
+  "m14": "application/x-msmediaview",
+  "wmf": "application/x-msmetafile",
+  "wmz": "application/x-msmetafile",
+  "emf": "application/x-msmetafile",
+  "emz": "application/x-msmetafile",
+  "mny": "application/x-msmoney",
+  "pub": "application/x-mspublisher",
+  "scd": "application/x-msschedule",
+  "trm": "application/x-msterminal",
+  "wri": "application/x-mswrite",
+  "nc": "application/x-netcdf",
+  "cdf": "application/x-netcdf",
+  "nzb": "application/x-nzb",
+  "p12": "application/x-pkcs12",
+  "pfx": "application/x-pkcs12",
+  "p7b": "application/x-pkcs7-certificates",
+  "spc": "application/x-pkcs7-certificates",
+  "p7r": "application/x-pkcs7-certreqresp",
+  "rar": "application/x-rar-compressed",
+  "ris": "application/x-research-info-systems",
+  "sh": "application/x-sh",
+  "shar": "application/x-shar",
+  "swf": "application/x-shockwave-flash",
+  "xap": "application/x-silverlight-app",
+  "sql": "application/x-sql",
+  "sit": "application/x-stuffit",
+  "sitx": "application/x-stuffitx",
+  "srt": "application/x-subrip",
+  "sv4cpio": "application/x-sv4cpio",
+  "sv4crc": "application/x-sv4crc",
+  "t3": "application/x-t3vm-image",
+  "gam": "application/x-tads",
+  "tar": "application/x-tar",
+  "tcl": "application/x-tcl",
+  "tex": "application/x-tex",
+  "tfm": "application/x-tex-tfm",
+  "texinfo": "application/x-texinfo",
+  "texi": "application/x-texinfo",
+  "obj": "application/x-tgif",
+  "ustar": "application/x-ustar",
+  "src": "application/x-wais-source",
+  "der": "application/x-x509-ca-cert",
+  "crt": "application/x-x509-ca-cert",
+  "fig": "application/x-xfig",
   "xlf": "application/x-xliff+xml",
-  "xlim": "application/vnd.xmpie.xlim",
-  "xlm": "application/vnd.ms-excel",
-  "xls": "application/vnd.ms-excel",
-  "xlsb": "application/vnd.ms-excel.sheet.binary.macroenabled.12",
-  "xlsm": "application/vnd.ms-excel.sheet.macroenabled.12",
-  "xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
-  "xlt": "application/vnd.ms-excel",
-  "xltm": "application/vnd.ms-excel.template.macroenabled.12",
-  "xltx": "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
-  "xlw": "application/vnd.ms-excel",
-  "xm": "audio/xm",
-  "xml": "text/xml",
-  "xmls": "application/dskpp+xml",
-  "xmt_bin": "model/vnd.parasolid.transmit.binary",
-  "xmt_txt": "model/vnd.parasolid.transmit.text",
-  "xmz": "xgl/movie",
-  "xns": "application/xcap-ns+xml",
-  "xo": "application/vnd.olpc-sugar",
-  "xof": "x-world/x-vrml",
-  "xop": "application/xop+xml",
-  "xpdl": "application/xml",
   "xpi": "application/x-xpinstall",
-  "xpix": "application/x-vnd.ls-xpix",
-  "xpl": "application/xproc+xml",
-  "xpm": "image/x-xpixmap",
-  "xpr": "application/vnd.is-xpr",
-  "xps": "application/vnd.ms-xpsdocument",
-  "xpw": "application/vnd.intercon.formnet",
-  "xpx": "application/vnd.intercon.formnet",
-  "xq": "text/xquery",
-  "xql": "text/xquery",
-  "xqm": "text/xquery",
-  "xqu": "text/xquery",
-  "xquery": "text/xquery",
-  "xqy": "text/xquery",
-  "xsd": "text/xml",
-  "xsf": "application/prs.xsf+xml",
-  "xsl": "application/xslt+xml",
-  "xslt": "application/xslt+xml",
-  "xsm": "application/vnd.syncml+xml",
-  "xspf": "application/xspf+xml",
-  "xsr": "video/x-amt-showrun",
-  "xtel": "chemical/x-xtel",
-  "xul": "application/vnd.mozilla.xul+xml",
-  "xvm": "application/xv+xml",
-  "xvml": "application/xv+xml",
-  "xwd": "image/x-xwindowdump",
-  "xyz": "chemical/x-xyz",
-  "xyze": "image/vnd.radiance",
   "xz": "application/x-xz",
-  "yaml": "text/yaml",
-  "yang": "application/yang",
-  "yin": "application/yin+xml",
-  "yme": "application/vnd.yaoweme",
-  "yml": "text/yaml",
-  "ymp": "text/x-suse-ymp",
   "z1": "application/x-zmachine",
   "z2": "application/x-zmachine",
   "z3": "application/x-zmachine",
@@ -1888,19 +744,293 @@ const mimes* = {
   "z6": "application/x-zmachine",
   "z7": "application/x-zmachine",
   "z8": "application/x-zmachine",
-  "zaz": "application/vnd.zzazz.deck+xml",
-  "zfc": "application/vnd.filmit.zfc",
-  "zfo": "application/vnd.software602.filler.form-xml-zip",
-  "zig": "text/zig",
+  "xaml": "application/xaml+xml",
+  "xdf": "application/xcap-diff+xml",
+  "xenc": "application/xenc+xml",
+  "xhtml": "application/xhtml+xml",
+  "xht": "application/xhtml+xml",
+  "xml": "application/xml",
+  "xsl": "application/xml",
+  "dtd": "application/xml-dtd",
+  "xop": "application/xop+xml",
+  "xpl": "application/xproc+xml",
+  "xslt": "application/xslt+xml",
+  "xspf": "application/xspf+xml",
+  "mxml": "application/xv+xml",
+  "xhvml": "application/xv+xml",
+  "xvml": "application/xv+xml",
+  "xvm": "application/xv+xml",
+  "yang": "application/yang",
+  "yin": "application/yin+xml",
   "zip": "application/zip",
-  "zir": "application/vnd.zul",
-  "zirz": "application/vnd.zul",
-  "zmm": "application/vnd.handheld-entertainment+xml",
-  "zmt": "chemical/x-mopac-input",
-  "zone": "text/dns",
-  "zoo": "application/octet-stream",
-  "zsh": "text/x-script.zsh",
-  "~": "application/x-trash"
+  "adp": "audio/adpcm",
+  "au": "audio/basic",
+  "snd": "audio/basic",
+  "mid": "audio/midi",
+  "midi": "audio/midi",
+  "kar": "audio/midi",
+  "rmi": "audio/midi",
+  "m4a": "audio/mp4",
+  "mp4a": "audio/mp4",
+  "mpga": "audio/mpeg",
+  "mp2": "audio/mpeg",
+  "mp2a": "audio/mpeg",
+  "mp3": "audio/mpeg",
+  "m2a": "audio/mpeg",
+  "m3a": "audio/mpeg",
+  "oga": "audio/ogg",
+  "ogg": "audio/ogg",
+  "spx": "audio/ogg",
+  "opus": "audio/ogg",
+  "s3m": "audio/s3m",
+  "sil": "audio/silk",
+  "uva": "audio/vnd.dece.audio",
+  "uvva": "audio/vnd.dece.audio",
+  "eol": "audio/vnd.digital-winds",
+  "dra": "audio/vnd.dra",
+  "dts": "audio/vnd.dts",
+  "dtshd": "audio/vnd.dts.hd",
+  "lvp": "audio/vnd.lucent.voice",
+  "pya": "audio/vnd.ms-playready.media.pya",
+  "ecelp4800": "audio/vnd.nuera.ecelp4800",
+  "ecelp7470": "audio/vnd.nuera.ecelp7470",
+  "ecelp9600": "audio/vnd.nuera.ecelp9600",
+  "rip": "audio/vnd.rip",
+  "weba": "audio/webm",
+  "aac": "audio/x-aac",
+  "aif": "audio/x-aiff",
+  "aiff": "audio/x-aiff",
+  "aifc": "audio/x-aiff",
+  "caf": "audio/x-caf",
+  "flac": "audio/x-flac",
+  "mka": "audio/x-matroska",
+  "m3u": "audio/x-mpegurl",
+  "wax": "audio/x-ms-wax",
+  "wma": "audio/x-ms-wma",
+  "ram": "audio/x-pn-realaudio",
+  "ra": "audio/x-pn-realaudio",
+  "rmp": "audio/x-pn-realaudio-plugin",
+  "wav": "audio/x-wav",
+  "xm": "audio/xm",
+  "cdx": "chemical/x-cdx",
+  "cif": "chemical/x-cif",
+  "cmdf": "chemical/x-cmdf",
+  "cml": "chemical/x-cml",
+  "csml": "chemical/x-csml",
+  "xyz": "chemical/x-xyz",
+  "ttc": "font/collection",
+  "otf": "font/otf",
+  "ttf": "font/ttf",
+  "woff": "font/woff",
+  "woff2": "font/woff2",
+  "bmp": "image/bmp",
+  "cgm": "image/cgm",
+  "g3": "image/g3fax",
+  "gif": "image/gif",
+  "ief": "image/ief",
+  "jpeg": "image/jpeg",
+  "jpg": "image/jpeg",
+  "jpe": "image/jpeg",
+  "ktx": "image/ktx",
+  "png": "image/png",
+  "btif": "image/prs.btif",
+  "sgi": "image/sgi",
+  "svg": "image/svg+xml",
+  "svgz": "image/svg+xml",
+  "tiff": "image/tiff",
+  "tif": "image/tiff",
+  "psd": "image/vnd.adobe.photoshop",
+  "uvi": "image/vnd.dece.graphic",
+  "uvvi": "image/vnd.dece.graphic",
+  "uvg": "image/vnd.dece.graphic",
+  "uvvg": "image/vnd.dece.graphic",
+  "djvu": "image/vnd.djvu",
+  "djv": "image/vnd.djvu",
+  "sub": "image/vnd.dvb.subtitle",
+  "dwg": "image/vnd.dwg",
+  "dxf": "image/vnd.dxf",
+  "fbs": "image/vnd.fastbidsheet",
+  "fpx": "image/vnd.fpx",
+  "fst": "image/vnd.fst",
+  "mmr": "image/vnd.fujixerox.edmics-mmr",
+  "rlc": "image/vnd.fujixerox.edmics-rlc",
+  "mdi": "image/vnd.ms-modi",
+  "wdp": "image/vnd.ms-photo",
+  "npx": "image/vnd.net-fpx",
+  "wbmp": "image/vnd.wap.wbmp",
+  "xif": "image/vnd.xiff",
+  "webp": "image/webp",
+  "3ds": "image/x-3ds",
+  "ras": "image/x-cmu-raster",
+  "cmx": "image/x-cmx",
+  "fh": "image/x-freehand",
+  "fhc": "image/x-freehand",
+  "fh4": "image/x-freehand",
+  "fh5": "image/x-freehand",
+  "fh7": "image/x-freehand",
+  "ico": "image/x-icon",
+  "sid": "image/x-mrsid-image",
+  "pcx": "image/x-pcx",
+  "pic": "image/x-pict",
+  "pct": "image/x-pict",
+  "pnm": "image/x-portable-anymap",
+  "pbm": "image/x-portable-bitmap",
+  "pgm": "image/x-portable-graymap",
+  "ppm": "image/x-portable-pixmap",
+  "rgb": "image/x-rgb",
+  "tga": "image/x-tga",
+  "xbm": "image/x-xbitmap",
+  "xpm": "image/x-xpixmap",
+  "xwd": "image/x-xwindowdump",
+  "eml": "message/rfc822",
+  "mime": "message/rfc822",
+  "igs": "model/iges",
+  "iges": "model/iges",
+  "msh": "model/mesh",
+  "mesh": "model/mesh",
+  "silo": "model/mesh",
+  "dae": "model/vnd.collada+xml",
+  "dwf": "model/vnd.dwf",
+  "gdl": "model/vnd.gdl",
+  "gtw": "model/vnd.gtw",
+  "mts": "model/vnd.mts",
+  "vtu": "model/vnd.vtu",
+  "wrl": "model/vrml",
+  "vrml": "model/vrml",
+  "x3db": "model/x3d+binary",
+  "x3dbz": "model/x3d+binary",
+  "x3dv": "model/x3d+vrml",
+  "x3dvz": "model/x3d+vrml",
+  "x3d": "model/x3d+xml",
+  "x3dz": "model/x3d+xml",
+  "appcache": "text/cache-manifest",
+  "ics": "text/calendar",
+  "ifb": "text/calendar",
+  "css": "text/css",
+  "csv": "text/csv",
+  "html": "text/html",
+  "htm": "text/html",
+  "js": "text/javascript",
+  "mjs": "text/javascript",
+  "n3": "text/n3",
+  "txt": "text/plain",
+  "text": "text/plain",
+  "conf": "text/plain",
+  "def": "text/plain",
+  "list": "text/plain",
+  "log": "text/plain",
+  "in": "text/plain",
+  "dsc": "text/prs.lines.tag",
+  "rtx": "text/richtext",
+  "sgml": "text/sgml",
+  "sgm": "text/sgml",
+  "tsv": "text/tab-separated-values",
+  "t": "text/troff",
+  "tr": "text/troff",
+  "roff": "text/troff",
+  "man": "text/troff",
+  "me": "text/troff",
+  "ms": "text/troff",
+  "ttl": "text/turtle",
+  "uri": "text/uri-list",
+  "uris": "text/uri-list",
+  "urls": "text/uri-list",
+  "vcard": "text/vcard",
+  "curl": "text/vnd.curl",
+  "dcurl": "text/vnd.curl.dcurl",
+  "mcurl": "text/vnd.curl.mcurl",
+  "scurl": "text/vnd.curl.scurl",
+  "sub": "text/vnd.dvb.subtitle",
+  "fly": "text/vnd.fly",
+  "flx": "text/vnd.fmi.flexstor",
+  "gv": "text/vnd.graphviz",
+  "3dml": "text/vnd.in3d.3dml",
+  "spot": "text/vnd.in3d.spot",
+  "jad": "text/vnd.sun.j2me.app-descriptor",
+  "wml": "text/vnd.wap.wml",
+  "wmls": "text/vnd.wap.wmlscript",
+  "s": "text/x-asm",
+  "asm": "text/x-asm",
+  "c": "text/x-c",
+  "cc": "text/x-c",
+  "cxx": "text/x-c",
+  "cpp": "text/x-c",
+  "h": "text/x-c",
+  "hh": "text/x-c",
+  "dic": "text/x-c",
+  "f": "text/x-fortran",
+  "for": "text/x-fortran",
+  "f77": "text/x-fortran",
+  "f90": "text/x-fortran",
+  "java": "text/x-java-source",
+  "nfo": "text/x-nfo",
+  "opml": "text/x-opml",
+  "p": "text/x-pascal",
+  "pas": "text/x-pascal",
+  "etx": "text/x-setext",
+  "sfv": "text/x-sfv",
+  "uu": "text/x-uuencode",
+  "vcs": "text/x-vcalendar",
+  "vcf": "text/x-vcard",
+  "3gp": "video/3gpp",
+  "3g2": "video/3gpp2",
+  "h261": "video/h261",
+  "h263": "video/h263",
+  "h264": "video/h264",
+  "jpgv": "video/jpeg",
+  "jpm": "video/jpm",
+  "jpgm": "video/jpm",
+  "mj2": "video/mj2",
+  "mjp2": "video/mj2",
+  "mp4": "video/mp4",
+  "mp4v": "video/mp4",
+  "mpg4": "video/mp4",
+  "mpeg": "video/mpeg",
+  "mpg": "video/mpeg",
+  "mpe": "video/mpeg",
+  "m1v": "video/mpeg",
+  "m2v": "video/mpeg",
+  "ogv": "video/ogg",
+  "qt": "video/quicktime",
+  "mov": "video/quicktime",
+  "uvh": "video/vnd.dece.hd",
+  "uvvh": "video/vnd.dece.hd",
+  "uvm": "video/vnd.dece.mobile",
+  "uvvm": "video/vnd.dece.mobile",
+  "uvp": "video/vnd.dece.pd",
+  "uvvp": "video/vnd.dece.pd",
+  "uvs": "video/vnd.dece.sd",
+  "uvvs": "video/vnd.dece.sd",
+  "uvv": "video/vnd.dece.video",
+  "uvvv": "video/vnd.dece.video",
+  "dvb": "video/vnd.dvb.file",
+  "fvt": "video/vnd.fvt",
+  "mxu": "video/vnd.mpegurl",
+  "m4u": "video/vnd.mpegurl",
+  "pyv": "video/vnd.ms-playready.media.pyv",
+  "uvu": "video/vnd.uvvu.mp4",
+  "uvvu": "video/vnd.uvvu.mp4",
+  "viv": "video/vnd.vivo",
+  "webm": "video/webm",
+  "f4v": "video/x-f4v",
+  "fli": "video/x-fli",
+  "flv": "video/x-flv",
+  "m4v": "video/x-m4v",
+  "mkv": "video/x-matroska",
+  "mk3d": "video/x-matroska",
+  "mks": "video/x-matroska",
+  "mng": "video/x-mng",
+  "asf": "video/x-ms-asf",
+  "asx": "video/x-ms-asf",
+  "vob": "video/x-ms-vob",
+  "wm": "video/x-ms-wm",
+  "wmv": "video/x-ms-wmv",
+  "wmx": "video/x-ms-wmx",
+  "wvx": "video/x-ms-wvx",
+  "avi": "video/x-msvideo",
+  "movie": "video/x-sgi-movie",
+  "smv": "video/x-smv",
+  "ice": "x-conference/x-cooltalk",
 }
 
 
diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim
index 14a318412..656c98a20 100644
--- a/lib/pure/nativesockets.nim
+++ b/lib/pure/nativesockets.nim
@@ -12,7 +12,7 @@
 
 # TODO: Clean up the exports a bit and everything else in general.
 
-import os, options
+import std/[os, options]
 import std/private/since
 import std/strbasics
 
@@ -23,15 +23,16 @@ when hostOS == "solaris":
   {.passl: "-lsocket -lnsl".}
 
 const useWinVersion = defined(windows) or defined(nimdoc)
-const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr)
+const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr) or
+    defined(nuttx)
 
 when useWinVersion:
-  import winlean
+  import std/winlean
   export WSAEWOULDBLOCK, WSAECONNRESET, WSAECONNABORTED, WSAENETRESET,
          WSANOTINITIALISED, WSAENOTSOCK, WSAEINPROGRESS, WSAEINTR,
          WSAEDISCON, ERROR_NETNAME_DELETED
 else:
-  import posix
+  import std/posix
   export fcntl, F_GETFL, O_NONBLOCK, F_SETFL, EAGAIN, EWOULDBLOCK, MSG_NOSIGNAL,
     EINTR, EINPROGRESS, ECONNRESET, EPIPE, ENETRESET, EBADF
   export Sockaddr_storage, Sockaddr_un, Sockaddr_un_path_length
@@ -66,7 +67,7 @@ type
                    ## some procedures, such as getaddrinfo)
     AF_UNIX = 1,   ## for local socket (using a file). Unsupported on Windows.
     AF_INET = 2,   ## for network protocol IPv4 or
-    AF_INET6 = when defined(macosx): 30 else: 23 ## for network protocol IPv6.
+    AF_INET6 = when defined(macosx): 30 elif defined(windows): 23 else: 10 ## for network protocol IPv6.
 
   SockType* = enum     ## second argument to `socket` proc
     SOCK_STREAM = 1,   ## reliable stream-oriented service or Stream Sockets
@@ -96,6 +97,8 @@ type
     length*: int
     addrList*: seq[string]
 
+const IPPROTO_NONE* = IPPROTO_IP ## Use this if your socket type requires a protocol value of zero (e.g. Unix sockets).
+
 when useWinVersion:
   let
     osInvalidSocket* = winlean.INVALID_SOCKET
@@ -304,7 +307,7 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
   let socketPort = if sockType == SOCK_RAW: "" else: $port
   var gaiResult = getaddrinfo(address, socketPort.cstring, addr(hints), result)
   if gaiResult != 0'i32:
-    when useWinVersion or defined(freertos):
+    when useWinVersion or defined(freertos) or defined(nuttx):
       raiseOSError(osLastError())
     else:
       raiseOSError(osLastError(), $gai_strerror(gaiResult))
@@ -351,7 +354,7 @@ proc getSockDomain*(socket: SocketHandle): Domain =
   else:
     raise newException(IOError, "Unknown socket family in getSockDomain")
 
-when not useNimNetLite: 
+when not useNimNetLite:
   proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
     ## Searches the database from the beginning and finds the first entry for
     ## which the service name specified by `name` matches the s_name member
@@ -386,21 +389,37 @@ when not useNimNetLite:
 
   proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
     ## This function will lookup the hostname of an IP Address.
-    var myaddr: InAddr
-    myaddr.s_addr = inet_addr(ip)
+    var
+      addrInfo = getAddrInfo(ip, Port(0), AF_UNSPEC)
+      myAddr: pointer
+      addrLen = 0
+      family = 0
+    
+    defer: freeAddrInfo(addrInfo)
+
+    if addrInfo.ai_addr.sa_family.cint == nativeAfInet:
+      family = nativeAfInet
+      myAddr = addr cast[ptr Sockaddr_in](addrInfo.ai_addr).sin_addr
+      addrLen = 4
+    elif addrInfo.ai_addr.sa_family.cint == nativeAfInet6:
+      family = nativeAfInet6
+      myAddr = addr cast[ptr Sockaddr_in6](addrInfo.ai_addr).sin6_addr
+      addrLen = 16
+    else:
+      raise newException(IOError, "Unknown socket family in `getHostByAddr()`")
 
     when useWinVersion:
-      var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
-                                    cint(AF_INET))
+      var s = winlean.gethostbyaddr(cast[ptr InAddr](myAddr), addrLen.cuint,
+                                    cint(family))
       if s == nil: raiseOSError(osLastError())
     else:
       var s =
         when defined(android4):
-          posix.gethostbyaddr(cast[cstring](addr(myaddr)), sizeof(myaddr).cint,
-                              cint(posix.AF_INET))
+          posix.gethostbyaddr(cast[cstring](myAddr), addrLen.cint,
+                              cint(family))
         else:
-          posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).SockLen,
-                              cint(posix.AF_INET))
+          posix.gethostbyaddr(myAddr, addrLen.SockLen,
+                              cint(family))
       if s == nil:
         raiseOSError(osLastError(), $hstrerror(h_errno))
 
@@ -423,7 +442,20 @@ when not useNimNetLite:
         result.addrList.add($inet_ntoa(inaddrPtr[]))
         inc(i)
     else:
-      result.addrList = cstringArrayToSeq(s.h_addr_list)
+      let strAddrLen = when not useWinVersion: posix.INET6_ADDRSTRLEN.int
+                       else: 46
+      var i = 0
+      while not isNil(s.h_addr_list[i]):
+        var ipStr = newString(strAddrLen)
+        if inet_ntop(nativeAfInet6, cast[pointer](s.h_addr_list[i]),
+                     cstring(ipStr), len(ipStr).int32) == nil:
+          raiseOSError(osLastError())
+        when not useWinVersion:
+          if posix.IN6_IS_ADDR_V4MAPPED(cast[ptr In6Addr](s.h_addr_list[i])) != 0:
+            ipStr.setSlice("::ffff:".len..<strAddrLen)
+        setLen(ipStr, len(cstring(ipStr)))
+        result.addrList.add(ipStr)
+        inc(i)
     result.length = int(s.h_length)
 
   proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} =
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 1dfdbbbe6..24c94b651 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -93,23 +93,24 @@ import std/private/since
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
-import nativesockets
-import os, strutils, times, sets, options, std/monotimes
-import ssl_config
+import std/nativesockets
+import std/[os, strutils, times, sets, options, monotimes]
+import std/ssl_config
 export nativesockets.Port, nativesockets.`$`, nativesockets.`==`
-export Domain, SockType, Protocol
+export Domain, SockType, Protocol, IPPROTO_NONE
 
 const useWinVersion = defined(windows) or defined(nimdoc)
-const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr)
+const useNimNetLite = defined(nimNetLite) or defined(freertos) or defined(zephyr) or
+    defined(nuttx)
 const defineSsl = defined(ssl) or defined(nimdoc)
 
 when useWinVersion:
-  from winlean import WSAESHUTDOWN
+  from std/winlean import WSAESHUTDOWN
 
 when defineSsl:
-  import openssl
+  import std/openssl
   when not defined(nimDisableCertificateValidation):
-    from ssl_certs import scanSSLCertificates
+    from std/ssl_certs import scanSSLCertificates
 
 # Note: The enumerations are mapped to Window's constants.
 
@@ -208,7 +209,7 @@ when defined(nimHasStyleChecks):
 
 
 when defined(posix) and not defined(lwip):
-  from posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds
+  from std/posix import TPollfd, POLLIN, POLLPRI, POLLOUT, POLLWRBAND, Tnfds
 
   template monitorPollEvent(x: var SocketHandle, y: cint, timeout: int): int =
     var tpollfd: TPollfd
@@ -621,7 +622,7 @@ when defineSsl:
 
   proc newContext*(protVersion = protSSLv23, verifyMode = CVerifyPeer,
                    certFile = "", keyFile = "", cipherList = CiphersIntermediate,
-                   caDir = "", caFile = ""): SslContext =
+                   caDir = "", caFile = "", ciphersuites = CiphersModern): SslContext =
     ## Creates an SSL context.
     ##
     ## Protocol version is currently ignored by default and TLS is used.
@@ -675,16 +676,16 @@ when defineSsl:
       raiseSSLError()
     when not defined(openssl10) and not defined(libressl):
       let sslVersion = getOpenSSLVersion()
-      if sslVersion >= 0x010101000 and not sslVersion == 0x020000000:
+      if sslVersion >= 0x010101000 and sslVersion != 0x020000000:
         # In OpenSSL >= 1.1.1, TLSv1.3 cipher suites can only be configured via
         # this API.
-        if newCTX.SSL_CTX_set_ciphersuites(cipherList) != 1:
+        if newCTX.SSL_CTX_set_ciphersuites(ciphersuites) != 1:
           raiseSSLError()
     # Automatically the best ECDH curve for client exchange. Without this, ECDH
     # ciphers will be ignored by the server.
     #
     # From OpenSSL >= 1.1.0, this setting is set by default and can't be
-    # overriden.
+    # overridden.
     if newCTX.SSL_CTX_set_ecdh_auto(1) != 1:
       raiseSSLError()
 
@@ -1153,7 +1154,7 @@ proc accept*(server: Socket, client: var owned(Socket),
   acceptAddr(server, client, addrDummy, flags)
 
 when defined(posix) and not defined(lwip):
-  from posix import Sigset, sigwait, sigismember, sigemptyset, sigaddset,
+  from std/posix import Sigset, sigwait, sigismember, sigemptyset, sigaddset,
     sigprocmask, pthread_sigmask, SIGPIPE, SIG_BLOCK, SIG_UNBLOCK
 
 template blockSigpipe(body: untyped): untyped =
@@ -1267,9 +1268,9 @@ proc close*(socket: Socket, flags = {SocketFlag.SafeDisconn}) =
     socket.fd = osInvalidSocket
 
 when defined(posix):
-  from posix import TCP_NODELAY
+  from std/posix import TCP_NODELAY
 else:
-  from winlean import TCP_NODELAY
+  from std/winlean import TCP_NODELAY
 
 proc toCInt*(opt: SOBool): cint =
   ## Converts a `SOBool` into its Socket Option cint representation.
@@ -1320,7 +1321,7 @@ when defined(nimdoc) or (defined(posix) and not useNimNetLite):
     when not defined(nimdoc):
       var socketAddr = makeUnixAddr(path)
       if socket.fd.connect(cast[ptr SockAddr](addr socketAddr),
-          (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32:
+          (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen) != 0'i32:
         raiseOSError(osLastError())
 
   proc bindUnix*(socket: Socket, path: string) =
@@ -1329,7 +1330,7 @@ when defined(nimdoc) or (defined(posix) and not useNimNetLite):
     when not defined(nimdoc):
       var socketAddr = makeUnixAddr(path)
       if socket.fd.bindAddr(cast[ptr SockAddr](addr socketAddr),
-          (sizeof(socketAddr.sun_family) + path.len).SockLen) != 0'i32:
+          (offsetOf(socketAddr, sun_path) + path.len + 1).SockLen) != 0'i32:
         raiseOSError(osLastError())
 
 when defineSsl:
@@ -1735,15 +1736,36 @@ proc send*(socket: Socket, data: pointer, size: int): int {.
     result = send(socket.fd, data, size, int32(MSG_NOSIGNAL))
 
 proc send*(socket: Socket, data: string,
-           flags = {SocketFlag.SafeDisconn}) {.tags: [WriteIOEffect].} =
-  ## sends data to a socket.
-  let sent = send(socket, cstring(data), data.len)
-  if sent < 0:
-    let lastError = osLastError()
-    socketError(socket, lastError = lastError, flags = flags)
+           flags = {SocketFlag.SafeDisconn}, maxRetries = 100) {.tags: [WriteIOEffect].} =
+  ## Sends data to a socket. Will try to send all the data by handling interrupts
+  ## and incomplete writes up to `maxRetries`.
+  var written = 0
+  var attempts = 0
+  while data.len - written > 0:
+    let sent = send(socket, cstring(data), data.len)
+
+    if sent < 0:
+      let lastError = osLastError()
+      let isBlockingErr =
+        when defined(nimdoc):
+          false
+        elif useWinVersion:
+          lastError.int32 == WSAEINTR or
+          lastError.int32 == WSAEWOULDBLOCK
+        else:
+          lastError.int32 == EINTR or
+          lastError.int32 == EWOULDBLOCK or
+          lastError.int32 == EAGAIN
 
-  if sent != data.len:
-    raiseOSError(osLastError(), "Could not send all data.")
+      if not isBlockingErr:
+        let lastError = osLastError()
+        socketError(socket, lastError = lastError, flags = flags)
+      else:
+        attempts.inc()
+        if attempts > maxRetries:
+          raiseOSError(osLastError(), "Could not send all data.")
+    else:
+      written.inc(sent)
 
 template `&=`*(socket: Socket; data: typed) =
   ## an alias for 'send'.
@@ -1900,7 +1922,7 @@ proc `$`*(address: IpAddress): string =
   ## Converts an IpAddress into the textual representation
   case address.family
   of IpAddressFamily.IPv4:
-    result = newStringOfCap(16)
+    result = newStringOfCap(15)
     result.addInt address.address_v4[0]
     result.add '.'
     result.addInt address.address_v4[1]
@@ -1909,7 +1931,7 @@ proc `$`*(address: IpAddress): string =
     result.add '.'
     result.addInt address.address_v4[3]
   of IpAddressFamily.IPv6:
-    result = newStringOfCap(48)
+    result = newStringOfCap(39)
     var
       currentZeroStart = -1
       currentZeroCount = 0
@@ -2018,8 +2040,10 @@ proc dial*(address: string, port: Port,
   if success:
     result = newSocket(lastFd, domain, sockType, protocol, buffered)
   elif lastError != 0.OSErrorCode:
+    lastFd.close()
     raiseOSError(lastError)
   else:
+    lastFd.close()
     raise newException(IOError, "Couldn't resolve address: " & address)
 
 proc connect*(socket: Socket, address: string,
diff --git a/lib/pure/nimprof.nim b/lib/pure/nimprof.nim
index 7f493418e..bf8367d1d 100644
--- a/lib/pure/nimprof.nim
+++ b/lib/pure/nimprof.nim
@@ -15,13 +15,12 @@
 when not defined(profiler) and not defined(memProfiler):
   {.error: "Profiling support is turned off! Enable profiling by passing `--profiler:on --stackTrace:on` to the compiler (see the Nim Compiler User Guide for more options).".}
 
-when defined(nimHasUsed):
-  {.used.}
+{.used.}
 
 # We don't want to profile the profiling code ...
 {.push profiler: off.}
 
-import hashes, algorithm, strutils, tables, sets
+import std/[hashes, algorithm, strutils, tables, sets]
 
 when defined(nimPreviewSlimSystem):
   import std/[syncio, sysatomics]
@@ -70,7 +69,7 @@ when not defined(memProfiler):
     else: interval = intervalInUs * 1000 - tickCountCorrection
 
 when withThreads:
-  import locks
+  import std/locks
   var
     profilingLock: Lock
 
diff --git a/lib/pure/nimtracker.nim b/lib/pure/nimtracker.nim
deleted file mode 100644
index 91bb07192..000000000
--- a/lib/pure/nimtracker.nim
+++ /dev/null
@@ -1,88 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2016 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## Memory tracking support for Nim.
-
-when not defined(memTracker) and not isMainModule:
-  {.error: "Memory tracking support is turned off!".}
-
-{.push memtracker: off.}
-# we import the low level wrapper and are careful not to use Nim's
-# memory manager for anything here.
-import sqlite3
-
-var
-  dbHandle: PSqlite3
-  insertStmt {.threadvar.}: Pstmt
-
-const insertQuery = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
-
-template sbind(x: int; value) =
-  when value is cstring:
-    let ret = insertStmt.bindText(x, value, value.len.int32, SQLITE_TRANSIENT)
-    if ret != SQLITE_OK:
-      quit "could not bind value"
-  else:
-    let ret = insertStmt.bindInt64(x, value)
-    if ret != SQLITE_OK:
-      quit "could not bind value"
-
-when defined(memTracker):
-  proc logEntries(log: TrackLog) {.nimcall, tags: [], gcsafe.} =
-    if insertStmt.isNil:
-      if prepare_v2(dbHandle, insertQuery,
-          insertQuery.len, insertStmt, nil) != SQLITE_OK:
-        quit "could not bind query to insertStmt " & $sqlite3.errmsg(dbHandle)
-    for i in 0..log.count-1:
-      var success = false
-      let e = log.data[i]
-      discard sqlite3.reset(insertStmt)
-      discard clearBindings(insertStmt)
-      sbind 1, e.op
-      sbind(2, cast[int](e.address))
-      sbind 3, e.size
-      sbind 4, e.file
-      sbind 5, e.line
-      if step(insertStmt) == SQLITE_DONE:
-        success = true
-      if not success:
-        quit "could not write to database! " & $sqlite3.errmsg(dbHandle)
-
-proc execQuery(q: string) =
-  var s: Pstmt
-  if prepare_v2(dbHandle, q, q.len.int32, s, nil) == SQLITE_OK:
-    discard step(s)
-    if finalize(s) != SQLITE_OK:
-      quit "could not finalize " & $sqlite3.errmsg(dbHandle)
-  else:
-    quit "could not prepare statement " & $sqlite3.errmsg(dbHandle)
-
-proc setupDb() =
-  execQuery """create table if not exists tracking(
-       id integer primary key,
-       op varchar not null,
-       address integer not null,
-       size integer not null,
-       file varchar not null,
-       line integer not null
-     )"""
-  execQuery "delete from tracking"
-
-if sqlite3.open("memtrack.db", dbHandle) == SQLITE_OK:
-  setupDb()
-  const query = "INSERT INTO tracking(op, address, size, file, line) values (?, ?, ?, ?, ?)"
-  if prepare_v2(dbHandle, insertQuery,
-      insertQuery.len, insertStmt, nil) == SQLITE_OK:
-    when defined(memTracker):
-      setTrackLogger logEntries
-  else:
-    quit "could not prepare statement B " & $sqlite3.errmsg(dbHandle)
-else:
-  quit "could not setup sqlite " & $sqlite3.errmsg(dbHandle)
-{.pop.}
diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim
index e6e5e6e56..4d6ceefd7 100644
--- a/lib/pure/oids.nim
+++ b/lib/pure/oids.nim
@@ -14,7 +14,7 @@
 ## This implementation calls `initRand()` for the first call of
 ## `genOid`.
 
-import hashes, times, endians, random
+import std/[hashes, times, endians, random]
 from std/private/decode_helpers import handleHexChar
 
 when defined(nimPreviewSlimSystem):
@@ -44,7 +44,7 @@ proc hexbyte*(hex: char): int {.inline.} =
 
 proc parseOid*(str: cstring): Oid =
   ## Parses an OID.
-  var bytes = cast[cstring](cast[pointer](cast[ByteAddress](addr(result.time)) + 4))
+  var bytes = cast[cstring](cast[pointer](cast[int](addr(result.time)) + 4))
   var i = 0
   while i < 12:
     bytes[i] = chr((hexbyte(str[2 * i]) shl 4) or hexbyte(str[2 * i + 1]))
@@ -57,7 +57,7 @@ proc `$`*(oid: Oid): string =
   result.setLen 24
 
   var o = oid
-  var bytes = cast[cstring](cast[pointer](cast[ByteAddress](addr(o)) + 4))
+  var bytes = cast[cstring](cast[pointer](cast[int](addr(o)) + 4))
   var i = 0
   while i < 12:
     let b = bytes[i].ord
diff --git a/lib/pure/options.nim b/lib/pure/options.nim
index 9dc4e096b..b34ff72c0 100644
--- a/lib/pure/options.nim
+++ b/lib/pure/options.nim
@@ -53,7 +53,7 @@ Pattern matching
 supports pattern matching on `Option`s, with the `Some(<pattern>)` and
 `None()` patterns.
 
-.. code-block:: nim
+  ```nim
   {.experimental: "caseStmtMacros".}
 
   import fusion/matching
@@ -65,6 +65,7 @@ supports pattern matching on `Option`s, with the `Some(<pattern>)` and
     assert false
 
   assertMatch(some(some(none(int))), Some(Some(None())))
+  ```
 ]##
 # xxx pending https://github.com/timotheecour/Nim/issues/376 use `runnableExamples` and `whichModule`
 
@@ -73,7 +74,7 @@ when defined(nimHasEffectsOf):
 else:
   {.pragma: effectsOf.}
 
-import typetraits
+import std/typetraits
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -81,7 +82,7 @@ when defined(nimPreviewSlimSystem):
 
 when (NimMajor, NimMinor) >= (1, 1):
   type
-    SomePointer = ref | ptr | pointer | proc
+    SomePointer = ref | ptr | pointer | proc | iterator {.closure.}
 else:
   type
     SomePointer = ref | ptr | pointer
@@ -89,7 +90,7 @@ else:
 type
   Option*[T] = object
     ## An optional type that may or may not contain a value of type `T`.
-    ## When `T` is a a pointer type (`ptr`, `pointer`, `ref` or `proc`),
+    ## When `T` is a a pointer type (`ptr`, `pointer`, `ref`, `proc` or `iterator {.closure.}`),
     ## `none(T)` is represented as `nil`.
     when T is SomePointer:
       val: T
@@ -116,9 +117,10 @@ proc option*[T](val: sink T): Option[T] {.inline.} =
     assert option[Foo](nil).isNone
     assert option(42).isSome
 
-  result.val = val
-  when T isnot SomePointer:
-    result.has = true
+  when T is SomePointer:
+    result = Option[T](val: val)
+  else:
+    result = Option[T](has: true, val: val)
 
 proc some*[T](val: sink T): Option[T] {.inline.} =
   ## Returns an `Option` that has the value `val`.
@@ -135,10 +137,9 @@ proc some*[T](val: sink T): Option[T] {.inline.} =
 
   when T is SomePointer:
     assert not val.isNil
-    result.val = val
+    result = Option[T](val: val)
   else:
-    result.has = true
-    result.val = val
+    result = Option[T](has: true, val: val)
 
 proc none*(T: typedesc): Option[T] {.inline.} =
   ## Returns an `Option` for this type that has no value.
@@ -151,7 +152,7 @@ proc none*(T: typedesc): Option[T] {.inline.} =
     assert none(int).isNone
 
   # the default is the none type
-  discard
+  result = Option[T]()
 
 proc none*[T]: Option[T] {.inline.} =
   ## Alias for `none(T) <#none,typedesc>`_.
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index 5f8f116d3..78ebb1c88 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -8,9 +8,11 @@
 #
 
 ## This module contains basic operating system facilities like
-## retrieving environment variables, working with directories, 
+## retrieving environment variables, working with directories,
 ## running shell commands, etc.
 
+## .. importdoc:: symlinks.nim, appdirs.nim, dirs.nim, ospaths2.nim
+
 runnableExamples:
   let myFile = "/path/to/my/file.nim"
   assert splitPath(myFile) == (head: "/path/to/my", tail: "file.nim")
@@ -20,6 +22,7 @@ runnableExamples:
   assert myFile.changeFileExt("c") == "/path/to/my/file.c"
 
 ## **See also:**
+## * `paths <paths.html>`_ and `files <files.html>`_ modules for high-level file manipulation
 ## * `osproc module <osproc.html>`_ for process communication beyond
 ##   `execShellCmd proc`_
 ## * `uri module <uri.html>`_
@@ -49,7 +52,7 @@ import std/private/since
 import std/cmdline
 export cmdline
 
-import strutils, pathnorm
+import std/[strutils, pathnorm]
 
 when defined(nimPreviewSlimSystem):
   import std/[syncio, assertions, widestrs]
@@ -73,9 +76,9 @@ since (1, 1):
 when weirdTarget:
   discard
 elif defined(windows):
-  import winlean, times
+  import std/[winlean, times]
 elif defined(posix):
-  import posix, times
+  import std/[posix, times]
 
   proc toTime(ts: Timespec): times.Time {.inline.} =
     result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
@@ -252,7 +255,7 @@ proc findExe*(exe: string, followSymlinks: bool = true;
     for ext in extensions:
       var x = addFileExt(x, ext)
       if fileExists(x):
-        when not defined(windows):
+        when not (defined(windows) or defined(nintendoswitch)):
           while followSymlinks: # doubles as if here
             if x.symlinkExists:
               var r = newString(maxSymlinkLen)
@@ -408,9 +411,9 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1",
   ## <osproc.html#execProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_.
   ##
   ## **Examples:**
-  ##
-  ## .. code-block::
+  ##   ```Nim
   ##   discard execShellCmd("ls -la")
+  ##   ```
   result = exitStatusLikeShell(c_system(command))
 
 proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
@@ -420,32 +423,18 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
   ## Raises `OSError` in case of an error. Follows symlinks.
   when defined(windows):
     var bufsize = MAX_PATH.int32
-    when useWinUnicode:
-      var unused: WideCString = nil
-      var res = newWideCString("", bufsize)
-      while true:
-        var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused)
-        if L == 0'i32:
-          raiseOSError(osLastError(), filename)
-        elif L > bufsize:
-          res = newWideCString("", L)
-          bufsize = L
-        else:
-          result = res$L
-          break
-    else:
-      var unused: cstring = nil
-      result = newString(bufsize)
-      while true:
-        var L = getFullPathNameA(filename, bufsize, result, unused)
-        if L == 0'i32:
-          raiseOSError(osLastError(), filename)
-        elif L > bufsize:
-          result = newString(L)
-          bufsize = L
-        else:
-          setLen(result, L)
-          break
+    var unused: WideCString = nil
+    var res = newWideCString(bufsize)
+    while true:
+      var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused)
+      if L == 0'i32:
+        raiseOSError(osLastError(), filename)
+      elif L > bufsize:
+        res = newWideCString(L)
+        bufsize = L
+      else:
+        result = res$L
+        break
     # getFullPathName doesn't do case corrections, so we have to use this convoluted
     # way of retrieving the true filename
     for x in walkFiles(result):
@@ -464,7 +453,7 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1",
       c_free(cast[pointer](r))
 
 proc getCurrentCompilerExe*(): string {.compileTime.} = discard
-  ## This is `getAppFilename()`_ at compile time.
+  ## Returns the path of the currently running Nim compiler or nimble executable.
   ##
   ## Can be used to retrieve the currently executing
   ## Nim compiler from a Nim or nimscript program, or the nimble binary
@@ -481,14 +470,10 @@ proc createHardlink*(src, dest: string) {.noWeirdTarget.} =
   ## See also:
   ## * `createSymlink proc`_
   when defined(windows):
-    when useWinUnicode:
-      var wSrc = newWideCString(src)
-      var wDst = newWideCString(dest)
-      if createHardLinkW(wDst, wSrc, nil) == 0:
-        raiseOSError(osLastError(), $(src, dest))
-    else:
-      if createHardLinkA(dest, src, nil) == 0:
-        raiseOSError(osLastError(), $(src, dest))
+    var wSrc = newWideCString(src)
+    var wDst = newWideCString(dest)
+    if createHardLinkW(wDst, wSrc, nil) == 0:
+      raiseOSError(osLastError(), $(src, dest))
   else:
     if link(src, dest) != 0:
       raiseOSError(osLastError(), $(src, dest))
@@ -497,18 +482,18 @@ proc inclFilePermissions*(filename: string,
                           permissions: set[FilePermission]) {.
   rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], noWeirdTarget.} =
   ## A convenience proc for:
-  ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   setFilePermissions(filename, getFilePermissions(filename)+permissions)
+  ##   ```
   setFilePermissions(filename, getFilePermissions(filename)+permissions)
 
 proc exclFilePermissions*(filename: string,
                           permissions: set[FilePermission]) {.
   rtl, extern: "nos$1", tags: [ReadDirEffect, WriteDirEffect], noWeirdTarget.} =
   ## A convenience proc for:
-  ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   setFilePermissions(filename, getFilePermissions(filename)-permissions)
+  ##   ```
   setFilePermissions(filename, getFilePermissions(filename)-permissions)
 
 when not weirdTarget and (defined(freebsd) or defined(dragonfly) or defined(netbsd)):
@@ -639,10 +624,12 @@ when defined(haiku):
     else:
       result = ""
 
-proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noWeirdTarget.} =
+proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noWeirdTarget, raises: [].} =
   ## Returns the filename of the application's executable.
   ## This proc will resolve symlinks.
   ##
+  ## Returns empty string when name is unavailable
+  ##
   ## See also:
   ## * `getAppDir proc`_
   ## * `getCurrentCompilerExe proc`_
@@ -653,32 +640,18 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noW
   # /proc/<pid>/path/a.out (complete pathname)
   when defined(windows):
     var bufsize = int32(MAX_PATH)
-    when useWinUnicode:
-      var buf = newWideCString("", bufsize)
-      while true:
-        var L = getModuleFileNameW(0, buf, bufsize)
-        if L == 0'i32:
-          result = "" # error!
-          break
-        elif L > bufsize:
-          buf = newWideCString("", L)
-          bufsize = L
-        else:
-          result = buf$L
-          break
-    else:
-      result = newString(bufsize)
-      while true:
-        var L = getModuleFileNameA(0, result, bufsize)
-        if L == 0'i32:
-          result = "" # error!
-          break
-        elif L > bufsize:
-          result = newString(L)
-          bufsize = L
-        else:
-          setLen(result, L)
-          break
+    var buf = newWideCString(bufsize)
+    while true:
+      var L = getModuleFileNameW(0, buf, bufsize)
+      if L == 0'i32:
+        result = "" # error!
+        break
+      elif L > bufsize:
+        buf = newWideCString(L)
+        bufsize = L
+      else:
+        result = buf$L
+        break
   elif defined(macosx):
     var size = cuint32(0)
     getExecPath1(nil, size)
@@ -686,24 +659,29 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noW
     if getExecPath2(result.cstring, size):
       result = "" # error!
     if result.len > 0:
-      result = result.expandFilename
+      try:
+        result = result.expandFilename
+      except OSError:
+        result = ""
   else:
     when defined(linux) or defined(aix):
       result = getApplAux("/proc/self/exe")
     elif defined(solaris):
       result = getApplAux("/proc/" & $getpid() & "/path/a.out")
     elif defined(genode):
-      raiseOSError(OSErrorCode(-1), "POSIX command line not supported")
+      result = "" # Not supported
     elif defined(freebsd) or defined(dragonfly) or defined(netbsd):
       result = getApplFreebsd()
     elif defined(haiku):
       result = getApplHaiku()
     elif defined(openbsd):
-      result = getApplOpenBsd()
+      result = try: getApplOpenBsd() except OSError: ""
+    elif defined(nintendoswitch):
+      result = ""
 
     # little heuristic that may work on other POSIX-like systems:
     if result.len == 0:
-      result = getApplHeuristic()
+      result = try: getApplHeuristic() except OSError: ""
 
 proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noWeirdTarget.} =
   ## Returns the directory of the application's executable.
@@ -714,7 +692,10 @@ proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noWeirdT
 
 proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [TimeEffect], noWeirdTarget.} =
   ## Sleeps `milsecs` milliseconds.
+  ## A negative `milsecs` causes sleep to return immediately.
   when defined(windows):
+    if milsecs < 0:
+      return  # fixes #23732
     winlean.sleep(int32(milsecs))
   else:
     var a, b: Timespec
@@ -776,14 +757,14 @@ template rawToFormalFileInfo(rawInfo, path, formalInfo): untyped =
   ## 'rawInfo' is either a 'BY_HANDLE_FILE_INFORMATION' structure on Windows,
   ## or a 'Stat' structure on posix
   when defined(windows):
-    template merge(a, b): untyped =
-      int64(
+    template merge[T](a, b): untyped =
+       cast[T](
         (uint64(cast[uint32](a))) or
         (uint64(cast[uint32](b)) shl 32)
        )
     formalInfo.id.device = rawInfo.dwVolumeSerialNumber
-    formalInfo.id.file = merge(rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh)
-    formalInfo.size = merge(rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh)
+    formalInfo.id.file = merge[FileId](rawInfo.nFileIndexLow, rawInfo.nFileIndexHigh)
+    formalInfo.size = merge[BiggestInt](rawInfo.nFileSizeLow, rawInfo.nFileSizeHigh)
     formalInfo.linkCount = rawInfo.nNumberOfLinks
     formalInfo.lastAccessTime = fromWinTime(rdFileTime(rawInfo.ftLastAccessTime))
     formalInfo.lastWriteTime = fromWinTime(rdFileTime(rawInfo.ftLastWriteTime))
@@ -973,10 +954,7 @@ proc isHidden*(path: string): bool {.noWeirdTarget.} =
       assert ".foo/".isHidden
 
   when defined(windows):
-    when useWinUnicode:
-      wrapUnary(attributes, getFileAttributesW, path)
-    else:
-      var attributes = getFileAttributesA(path)
+    wrapUnary(attributes, getFileAttributesW, path)
     if attributes != -1'i32:
       result = (attributes and FILE_ATTRIBUTE_HIDDEN) != 0'i32
   else:
@@ -1047,10 +1025,8 @@ func isValidFilename*(filename: string, maxLen = 259.Positive): bool {.since: (1
 
 
 # deprecated declarations
-when not defined(nimscript):
-  when not defined(js): # `noNimJs` doesn't work with templates, this should improve.
-    template existsFile*(args: varargs[untyped]): untyped {.deprecated: "use fileExists".} =
-      fileExists(args)
-    template existsDir*(args: varargs[untyped]): untyped {.deprecated: "use dirExists".} =
-      dirExists(args)
-  # {.deprecated: [existsFile: fileExists].} # pending bug #14819; this would avoid above mentioned issue
+when not weirdTarget:
+  template existsFile*(args: varargs[untyped]): untyped {.deprecated: "use fileExists".} =
+    fileExists(args)
+  template existsDir*(args: varargs[untyped]): untyped {.deprecated: "use dirExists".} =
+    dirExists(args)
diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim
index 5e130b47a..c304ecca6 100644
--- a/lib/pure/osproc.nim
+++ b/lib/pure/osproc.nim
@@ -18,18 +18,18 @@
 include "system/inclrtl"
 
 import
-  strutils, os, strtabs, streams, cpuinfo, streamwrapper,
-  std/private/since
+  std/[strutils, os, strtabs, streams, cpuinfo, streamwrapper,
+  private/since]
 
 export quoteShell, quoteShellWindows, quoteShellPosix
 
 when defined(windows):
-  import winlean
+  import std/winlean
 else:
-  import posix
+  import std/posix
 
 when defined(linux) and defined(useClone):
-  import linux
+  import std/linux
 
 when defined(nimPreviewSlimSystem):
   import std/[syncio, assertions]
@@ -76,7 +76,7 @@ type
 proc execProcess*(command: string, workingDir: string = "",
     args: openArray[string] = [], env: StringTableRef = nil,
     options: set[ProcessOption] = {poStdErrToStdOut, poUsePath, poEvalCommand}):
-  string {.rtl, extern: "nosp$1",
+  string {.rtl, extern: "nosp$1", raises: [OSError, IOError],
                   tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
   ## A convenience procedure that executes ``command`` with ``startProcess``
   ## and returns its output as a string.
@@ -91,12 +91,12 @@ proc execProcess*(command: string, workingDir: string = "",
   ## * `execCmd proc <#execCmd,string>`_
   ##
   ## Example:
-  ##
-  ## .. code-block:: Nim
-  ##  let outp = execProcess("nim", args=["c", "-r", "mytestfile.nim"], options={poUsePath})
-  ##  let outp_shell = execProcess("nim c -r mytestfile.nim")
-  ##  # Note: outp may have an interleave of text from the nim compile
-  ##  # and any output from mytestfile when it runs
+  ##   ```Nim
+  ##   let outp = execProcess("nim", args=["c", "-r", "mytestfile.nim"], options={poUsePath})
+  ##   let outp_shell = execProcess("nim c -r mytestfile.nim")
+  ##   # Note: outp may have an interleave of text from the nim compile
+  ##   # and any output from mytestfile when it runs
+  ##   ```
 
 proc execCmd*(command: string): int {.rtl, extern: "nosp$1",
     tags: [ExecIOEffect, ReadIOEffect, RootEffect].}
@@ -113,14 +113,14 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1",
   ##   <#execProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_
   ##
   ## Example:
-  ##
-  ## .. code-block:: Nim
-  ##  let errC = execCmd("nim c -r mytestfile.nim")
+  ##   ```Nim
+  ##   let errC = execCmd("nim c -r mytestfile.nim")
+  ##   ```
 
 proc startProcess*(command: string, workingDir: string = "",
     args: openArray[string] = [], env: StringTableRef = nil,
     options: set[ProcessOption] = {poStdErrToStdOut}):
-  owned(Process) {.rtl, extern: "nosp$1",
+  owned(Process) {.rtl, extern: "nosp$1", raises: [OSError, IOError],
                    tags: [ExecIOEffect, ReadEnvEffect, RootEffect].}
   ## Starts a process. `Command` is the executable file, `workingDir` is the
   ## process's working directory. If ``workingDir == ""`` the current directory
@@ -152,7 +152,7 @@ proc startProcess*(command: string, workingDir: string = "",
   ##   <#execProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_
   ## * `execCmd proc <#execCmd,string>`_
 
-proc close*(p: Process) {.rtl, extern: "nosp$1", tags: [WriteIOEffect].}
+proc close*(p: Process) {.rtl, extern: "nosp$1", raises: [IOError, OSError], tags: [WriteIOEffect].}
   ## When the process has finished executing, cleanup related handles.
   ##
   ## .. warning:: If the process has not finished executing, this will forcibly
@@ -201,7 +201,7 @@ proc kill*(p: Process) {.rtl, extern: "nosp$1", tags: [].}
   ## * `terminate proc <#terminate,Process>`_
   ## * `posix_utils.sendSignal(pid: Pid, signal: int) <posix_utils.html#sendSignal,Pid,int>`_
 
-proc running*(p: Process): bool {.rtl, extern: "nosp$1", tags: [].}
+proc running*(p: Process): bool {.rtl, extern: "nosp$1", raises: [OSError], tags: [].}
   ## Returns true if the process `p` is still running. Returns immediately.
 
 proc processID*(p: Process): int {.rtl, extern: "nosp$1".} =
@@ -212,7 +212,7 @@ proc processID*(p: Process): int {.rtl, extern: "nosp$1".} =
   return p.id
 
 proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
-    extern: "nosp$1", tags: [].}
+    extern: "nosp$1", raises: [OSError, ValueError], tags: [TimeEffect].}
   ## Waits for the process to finish and returns `p`'s error code.
   ##
   ## .. warning:: Be careful when using `waitForExit` for processes created without
@@ -220,8 +220,12 @@ proc waitForExit*(p: Process, timeout: int = -1): int {.rtl,
   ##
   ## On posix, if the process has exited because of a signal, 128 + signal
   ## number will be returned.
+  ##
+  ## .. warning:: When working with `timeout` parameters, remember that the value is 
+  ##   typically expressed in milliseconds, and ensure that the correct unit of time
+  ##   is used to avoid unexpected behavior.
 
-proc peekExitCode*(p: Process): int {.rtl, extern: "nosp$1", tags: [].}
+proc peekExitCode*(p: Process): int {.rtl, extern: "nosp$1", raises: [OSError], tags: [].}
   ## Return `-1` if the process is still running. Otherwise the process' exit code.
   ##
   ## On posix, if the process has exited because of a signal, 128 + signal
@@ -237,7 +241,7 @@ proc inputStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [].}
   ## * `outputStream proc <#outputStream,Process>`_
   ## * `errorStream proc <#errorStream,Process>`_
 
-proc outputStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [].}
+proc outputStream*(p: Process): Stream {.rtl, extern: "nosp$1", raises: [IOError, OSError], tags: [].}
   ## Returns ``p``'s output stream for reading from.
   ##
   ## You cannot perform peek/write/setOption operations to this stream.
@@ -289,7 +293,7 @@ proc peekableErrorStream*(p: Process): Stream {.rtl, extern: "nosp$1", tags: [],
   ## * `errorStream proc <#errorStream,Process>`_
   ## * `peekableOutputStream proc <#peekableOutputStream,Process>`_
 
-proc inputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
+proc inputHandle*(p: Process): FileHandle {.rtl, raises: [], extern: "nosp$1",
   tags: [].} =
   ## Returns ``p``'s input file handle for writing to.
   ##
@@ -302,7 +306,7 @@ proc inputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
   result = p.inHandle
 
 proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
-    tags: [].} =
+    raises: [], tags: [].} =
   ## Returns ``p``'s output file handle for reading from.
   ##
   ## .. warning:: The returned `FileHandle` should not be closed manually as
@@ -314,7 +318,7 @@ proc outputHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
   result = p.outHandle
 
 proc errorHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
-    tags: [].} =
+    raises: [], tags: [].} =
   ## Returns ``p``'s error file handle for reading from.
   ##
   ## .. warning:: The returned `FileHandle` should not be closed manually as
@@ -325,7 +329,7 @@ proc errorHandle*(p: Process): FileHandle {.rtl, extern: "nosp$1",
   ## * `outputHandle proc <#outputHandle,Process>`_
   result = p.errHandle
 
-proc countProcessors*(): int {.rtl, extern: "nosp$1".} =
+proc countProcessors*(): int {.rtl, extern: "nosp$1", raises: [].} =
   ## Returns the number of the processors/cores the machine has.
   ## Returns 0 if it cannot be detected.
   ## It is implemented just calling `cpuinfo.countProcessors`.
@@ -339,6 +343,7 @@ proc execProcesses*(cmds: openArray[string],
     beforeRunEvent: proc(idx: int) = nil,
     afterRunEvent: proc(idx: int, p: Process) = nil):
   int {.rtl, extern: "nosp$1",
+        raises: [ValueError, OSError, IOError],
         tags: [ExecIOEffect, TimeEffect, ReadEnvEffect, RootEffect],
         effectsOf: [beforeRunEvent, afterRunEvent].} =
   ## Executes the commands `cmds` in parallel.
@@ -452,7 +457,7 @@ proc execProcesses*(cmds: openArray[string],
       if afterRunEvent != nil: afterRunEvent(i, p)
       close(p)
 
-iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), tags: [ReadIOEffect].} =
+iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), raises: [OSError, IOError, ValueError], tags: [ReadIOEffect, TimeEffect].} =
   ## Convenience iterator for working with `startProcess` to read data from a
   ## background process.
   ##
@@ -460,8 +465,7 @@ iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), tags:
   ## * `readLines proc <#readLines,Process>`_
   ##
   ## Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   const opts = {poUsePath, poDaemon, poStdErrToStdOut}
   ##   var ps: seq[Process]
   ##   for prog in ["a", "b"]: # run 2 progs in parallel
@@ -473,6 +477,7 @@ iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), tags:
   ##       i.inc
   ##       if i > 100: break
   ##     p.close
+  ##   ```
   var outp = p.outputStream
   var line = newStringOfCap(120)
   while outp.readLine(line):
@@ -481,7 +486,8 @@ iterator lines*(p: Process, keepNewLines = false): string {.since: (1, 3), tags:
     yield line
   discard waitForExit(p)
 
-proc readLines*(p: Process): (seq[string], int) {.since: (1, 3).} =
+proc readLines*(p: Process): (seq[string], int) {.since: (1, 3),
+    raises: [OSError, IOError, ValueError], tags: [ReadIOEffect, TimeEffect].} =
   ## Convenience function for working with `startProcess` to read data from a
   ## background process.
   ##
@@ -489,8 +495,7 @@ proc readLines*(p: Process): (seq[string], int) {.since: (1, 3).} =
   ## * `lines iterator <#lines.i,Process>`_
   ##
   ## Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   const opts = {poUsePath, poDaemon, poStdErrToStdOut}
   ##   var ps: seq[Process]
   ##   for prog in ["a", "b"]: # run 2 progs in parallel
@@ -500,6 +505,7 @@ proc readLines*(p: Process): (seq[string], int) {.since: (1, 3).} =
   ##     if exCode != 0:
   ##       for line in lines: echo line
   ##     p.close
+  ##   ```
   for line in p.lines: result[0].add(line)
   result[1] = p.peekExitCode
 
@@ -568,12 +574,8 @@ when defined(windows) and not defined(useNimRtl):
     if a == 0: raiseOSError(osLastError())
 
   proc newFileHandleStream(handle: Handle): owned FileHandleStream =
-    new(result)
-    result.handle = handle
-    result.closeImpl = hsClose
-    result.atEndImpl = hsAtEnd
-    result.readDataImpl = hsReadData
-    result.writeDataImpl = hsWriteData
+    result = FileHandleStream(handle: handle, closeImpl: hsClose, atEndImpl: hsAtEnd,
+      readDataImpl: hsReadData, writeDataImpl: hsWriteData)
 
   proc buildCommandLine(a: string, args: openArray[string]): string =
     result = quoteShell(a)
@@ -716,22 +718,15 @@ when defined(windows) and not defined(useNimRtl):
     if len(workingDir) > 0: wd = workingDir
     if env != nil: e = buildEnv(env)
     if poEchoCmd in options: echo($cmdl)
-    when useWinUnicode:
-      var tmp = newWideCString(cmdl)
-      var ee =
-        if e.str.isNil: newWideCString(cstring(nil))
-        else: newWideCString(e.str, e.len)
-      var wwd = newWideCString(wd)
-      var flags = NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT
-      if poDaemon in options: flags = flags or CREATE_NO_WINDOW
-      success = winlean.createProcessW(nil, tmp, nil, nil, 1, flags,
-        ee, wwd, si, procInfo)
-    else:
-      var ee =
-        if e.str.isNil: cstring(nil)
-        else: cstring(e.str)
-      success = winlean.createProcessA(nil,
-        cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, ee, wd, si, procInfo)
+    var tmp = newWideCString(cmdl)
+    var ee =
+      if e.str.isNil: newWideCString(cstring(nil))
+      else: newWideCString(e.str, e.len)
+    var wwd = newWideCString(wd)
+    var flags = NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT
+    if poDaemon in options: flags = flags or CREATE_NO_WINDOW
+    success = winlean.createProcessW(nil, tmp, nil, nil, 1, flags,
+      ee, wwd, si, procInfo)
     let lastError = osLastError()
 
     if poParentStreams notin options:
@@ -747,7 +742,7 @@ when defined(windows) and not defined(useNimRtl):
       const errFileNotFound = 2.int
       if lastError.int in {errInvalidParameter, errFileNotFound}:
         raiseOSError(lastError,
-            "Requested command not found: '$1'. OS error:" % command)
+              "Requested command not found: '" & command & "'. OS error:")
       else:
         raiseOSError(lastError, command)
     result.fProcessHandle = procInfo.hProcess
@@ -872,13 +867,9 @@ when defined(windows) and not defined(useNimRtl):
     si.hStdError = getStdHandle(STD_ERROR_HANDLE)
     si.hStdInput = getStdHandle(STD_INPUT_HANDLE)
     si.hStdOutput = getStdHandle(STD_OUTPUT_HANDLE)
-    when useWinUnicode:
-      var c = newWideCString(command)
-      var res = winlean.createProcessW(nil, c, nil, nil, 0,
-        NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
-    else:
-      var res = winlean.createProcessA(nil, command, nil, nil, 0,
-        NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
+    var c = newWideCString(command)
+    var res = winlean.createProcessW(nil, c, nil, nil, 0,
+      NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo)
     if res == 0:
       raiseOSError(osLastError())
     else:
@@ -955,13 +946,13 @@ elif not defined(useNimRtl):
                              not defined(useClone) and not defined(linux)
   when useProcessAuxSpawn:
     proc startProcessAuxSpawn(data: StartProcessData): Pid {.
-      tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], gcsafe.}
+      raises: [OSError], tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], gcsafe.}
   else:
     proc startProcessAuxFork(data: StartProcessData): Pid {.
-      tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], gcsafe.}
+      raises: [OSError], tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], gcsafe.}
     {.push stacktrace: off, profiler: off.}
     proc startProcessAfterFork(data: ptr StartProcessData) {.
-      tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.}
+      raises: [OSError], tags: [ExecIOEffect, ReadEnvEffect, ReadDirEffect, RootEffect], cdecl, gcsafe.}
     {.pop.}
 
   proc startProcess(command: string, workingDir: string = "",
@@ -1062,13 +1053,15 @@ elif not defined(useNimRtl):
       var mask: Sigset
       chck sigemptyset(mask)
       chck posix_spawnattr_setsigmask(attr, mask)
-      if poDaemon in data.options:
-        chck posix_spawnattr_setpgroup(attr, 0'i32)
+      when not defined(nuttx):
+        if poDaemon in data.options:
+          chck posix_spawnattr_setpgroup(attr, 0'i32)
 
       var flags = POSIX_SPAWN_USEVFORK or
                   POSIX_SPAWN_SETSIGMASK
-      if poDaemon in data.options:
-        flags = flags or POSIX_SPAWN_SETPGROUP
+      when not defined(nuttx):
+        if poDaemon in data.options:
+          flags = flags or POSIX_SPAWN_SETPGROUP
       chck posix_spawnattr_setflags(attr, flags)
 
       if not (poParentStreams in data.options):
@@ -1130,15 +1123,13 @@ elif not defined(useNimRtl):
       var error: cint
       let sizeRead = read(data.pErrorPipe[readIdx], addr error, sizeof(error))
       if sizeRead == sizeof(error):
-        raiseOSError(osLastError(),
-                     "Could not find command: '$1'. OS error: $2" %
-                      [$data.sysCommand, $strerror(error)])
+        raiseOSError(OSErrorCode(error),
+                      "Could not find command: '" & $data.sysCommand & "'. OS error: " & $strerror(error))
 
       return pid
 
     {.push stacktrace: off, profiler: off.}
-    proc startProcessFail(data: ptr StartProcessData) =
-      var error: cint = errno
+    proc startProcessFail(data: ptr StartProcessData, error: cint = errno) =
       discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
       exitnow(1)
 
@@ -1175,7 +1166,11 @@ elif not defined(useNimRtl):
       if (poUsePath in data.options):
         when defined(uClibc) or defined(linux) or defined(haiku):
           # uClibc environment (OpenWrt included) doesn't have the full execvpe
-          let exe = findExe(data.sysCommand)
+          var exe: string
+          try:
+            exe = findExe(data.sysCommand)
+          except OSError as e:
+            startProcessFail(data, e.errorCode)
           discard execve(exe.cstring, data.sysArgs, data.sysEnv)
         else:
           # MacOSX doesn't have execvpe, so we need workaround.
@@ -1239,7 +1234,7 @@ elif not defined(useNimRtl):
 
   when defined(macosx) or defined(freebsd) or defined(netbsd) or
        defined(openbsd) or defined(dragonfly):
-    import kqueue
+    import std/kqueue
 
     proc waitForExit(p: Process, timeout: int = -1): int =
       if p.exitFlag:
@@ -1356,119 +1351,68 @@ elif not defined(useNimRtl):
             p.exitStatus = status
             break
           else:
-            doAssert false, "unreachable!"
+            raiseAssert "unreachable!"
 
       result = exitStatusLikeShell(p.exitStatus)
 
   else:
-    import times
-
-    const
-      hasThreadSupport = compileOption("threads") and not defined(nimscript)
+    import std/times except getTime
+    import std/monotimes
 
     proc waitForExit(p: Process, timeout: int = -1): int =
-      template adjustTimeout(t, s, e: Timespec) =
-        var diff: int
-        var b: Timespec
-        b.tv_sec = e.tv_sec
-        b.tv_nsec = e.tv_nsec
-        e.tv_sec = e.tv_sec - s.tv_sec
-        if e.tv_nsec >= s.tv_nsec:
-          e.tv_nsec -= s.tv_nsec
-        else:
-          if e.tv_sec == posix.Time(0):
-            raise newException(ValueError, "System time was modified")
-          else:
-            diff = s.tv_nsec - e.tv_nsec
-            e.tv_nsec = 1_000_000_000 - diff
-        t.tv_sec = t.tv_sec - e.tv_sec
-        if t.tv_nsec >= e.tv_nsec:
-          t.tv_nsec -= e.tv_nsec
-        else:
-          t.tv_sec = t.tv_sec - posix.Time(1)
-          diff = e.tv_nsec - t.tv_nsec
-          t.tv_nsec = 1_000_000_000 - diff
-        s.tv_sec = b.tv_sec
-        s.tv_nsec = b.tv_nsec
-
       if p.exitFlag:
         return exitStatusLikeShell(p.exitStatus)
 
-      if timeout == -1:
-        var status: cint = 1
+      if timeout < 0:
+        # Backwards compatibility with previous verison to
+        # handle cases where timeout == -1, but extend
+        # to handle cases where timeout < 0
+        var status: cint
         if waitpid(p.id, status, 0) < 0:
           raiseOSError(osLastError())
         p.exitFlag = true
         p.exitStatus = status
       else:
-        var nmask, omask: Sigset
-        var sinfo: SigInfo
-        var stspec, enspec, tmspec: Timespec
-
-        discard sigemptyset(nmask)
-        discard sigemptyset(omask)
-        discard sigaddset(nmask, SIGCHLD)
-
-        when hasThreadSupport:
-          if pthread_sigmask(SIG_BLOCK, nmask, omask) == -1:
-            raiseOSError(osLastError())
-        else:
-          if sigprocmask(SIG_BLOCK, nmask, omask) == -1:
-            raiseOSError(osLastError())
-
-        if timeout >= 1000:
-          tmspec.tv_sec = posix.Time(timeout div 1_000)
-          tmspec.tv_nsec = (timeout %% 1_000) * 1_000_000
-        else:
-          tmspec.tv_sec = posix.Time(0)
-          tmspec.tv_nsec = (timeout * 1_000_000)
-
-        try:
-          if clock_gettime(CLOCK_REALTIME, stspec) == -1:
-            raiseOSError(osLastError())
-          while true:
-            let res = sigtimedwait(nmask, sinfo, tmspec)
-            if res == SIGCHLD:
-              if sinfo.si_pid == p.id:
-                var status: cint = 1
-                if waitpid(p.id, status, 0) < 0:
-                  raiseOSError(osLastError())
-                p.exitFlag = true
-                p.exitStatus = status
-                break
-              else:
-                # we have SIGCHLD, but not for process we are waiting,
-                # so we need to adjust timeout value and continue
-                if clock_gettime(CLOCK_REALTIME, enspec) == -1:
-                  raiseOSError(osLastError())
-                adjustTimeout(tmspec, stspec, enspec)
-            elif res < 0:
-              let err = osLastError()
-              if err.cint == EINTR:
-                # we have received another signal, so we need to
-                # adjust timeout and continue
-                if clock_gettime(CLOCK_REALTIME, enspec) == -1:
-                  raiseOSError(osLastError())
-                adjustTimeout(tmspec, stspec, enspec)
-              elif err.cint == EAGAIN:
-                # timeout expired, so we trying to kill process
-                if posix.kill(p.id, SIGKILL) == -1:
-                  raiseOSError(osLastError())
-                var status: cint = 1
-                if waitpid(p.id, status, 0) < 0:
-                  raiseOSError(osLastError())
-                p.exitFlag = true
-                p.exitStatus = status
-                break
-              else:
-                raiseOSError(err)
-        finally:
-          when hasThreadSupport:
-            if pthread_sigmask(SIG_UNBLOCK, nmask, omask) == -1:
-              raiseOSError(osLastError())
+        # Max 50ms delay
+        const maxWait = initDuration(milliseconds = 50)
+        let wait = initDuration(milliseconds = timeout)
+        let deadline = getMonoTime() + wait
+        # starting 50μs delay
+        var delay = initDuration(microseconds = 50)
+        
+        while true:
+          var status: cint
+          let pid = waitpid(p.id, status, WNOHANG)
+          if p.id == pid :
+            p.exitFlag = true
+            p.exitStatus = status
+            break
+          elif pid.int == -1:
+            raiseOsError(osLastError())
           else:
-            if sigprocmask(SIG_UNBLOCK, nmask, omask) == -1:
-              raiseOSError(osLastError())
+            # Continue waiting if needed
+            if getMonoTime() >= deadline:
+              # Previous version of `waitForExit`
+              # foricibly killed the process.
+              # We keep this so we don't break programs
+              # that depend on this behavior
+              if posix.kill(p.id, SIGKILL) < 0:
+                raiseOSError(osLastError())
+            else:
+              const max = 1_000_000_000
+              let 
+                newWait = getMonoTime() + delay
+                ticks = newWait.ticks()
+                ns = ticks mod max
+                secs = ticks div max
+              var 
+                waitSpec: TimeSpec
+                unused: Timespec
+              waitSpec.tv_sec = posix.Time(secs)
+              waitSpec.tv_nsec = clong ns 
+              discard posix.clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, waitSpec, unused)
+              let remaining = deadline - getMonoTime()
+              delay = min([delay * 2, remaining, maxWait])
 
       result = exitStatusLikeShell(p.exitStatus)
 
@@ -1578,7 +1522,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
                 poStdErrToStdOut, poUsePath}, env: StringTableRef = nil,
                 workingDir = "", input = ""): tuple[
                 output: string,
-                exitCode: int] {.tags:
+                exitCode: int] {.raises: [OSError, IOError], tags:
                 [ExecIOEffect, ReadIOEffect, RootEffect], gcsafe.} =
   ## A convenience proc that runs the `command`, and returns its `output` and
   ## `exitCode`. `env` and `workingDir` params behave as for `startProcess`.
@@ -1595,8 +1539,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
   ##   <#execProcess,string,string,openArray[string],StringTableRef,set[ProcessOption]>`_
   ##
   ## Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   var result = execCmdEx("nim r --hints:off -", options = {}, input = "echo 3*4")
   ##   import std/[strutils, strtabs]
   ##   stripLineEnd(result[0]) ## portable way to remove trailing newline, if any
@@ -1605,6 +1548,7 @@ proc execCmdEx*(command: string, options: set[ProcessOption] = {
   ##   when defined(posix):
   ##     assert execCmdEx("echo $FO", env = newStringTable({"FO": "B"})) == ("B\n", 0)
   ##     assert execCmdEx("echo $PWD", workingDir = "/") == ("/\n", 0)
+  ##   ```
 
   when (NimMajor, NimMinor, NimPatch) < (1, 3, 5):
     doAssert input.len == 0
diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim
index 54584a253..8a43daf54 100644
--- a/lib/pure/parsecfg.nim
+++ b/lib/pure/parsecfg.nim
@@ -45,9 +45,7 @@ runnableExamples("-r:off"):
 ## Configuration file example
 ]##
 
-##
-## .. code-block:: nim
-##
+##     ```none
 ##     charset = "utf-8"
 ##     [Package]
 ##     name = "hello"
@@ -55,6 +53,7 @@ runnableExamples("-r:off"):
 ##     [Author]
 ##     name = "nim-lang"
 ##     website = "nim-lang.org"
+##     ```
 
 ##[
 ## Creating a configuration file
@@ -171,7 +170,7 @@ runnableExamples:
   assert dict.getSectionValue(section4, "does_that_mean_anything_special") == "False"
   assert dict.getSectionValue(section4, "purpose") == "formatting for readability"
 
-import strutils, lexbase, streams, tables
+import std/[strutils, lexbase, streams, tables]
 import std/private/decode_helpers
 import std/private/since
 
@@ -453,7 +452,7 @@ proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent =
   if c.tok.kind == tkSymbol:
     case kind
     of cfgOption, cfgKeyValuePair:
-      result = CfgEvent(kind: kind, key: c.tok.literal, value: "")
+      result = CfgEvent(kind: kind, key: c.tok.literal.move, value: "")
     else: discard
     rawGetTok(c, c.tok)
     if c.tok.kind in {tkEquals, tkColon}:
@@ -482,7 +481,7 @@ proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} =
   of tkBracketLe:
     rawGetTok(c, c.tok)
     if c.tok.kind == tkSymbol:
-      result = CfgEvent(kind: cfgSectionStart, section: c.tok.literal)
+      result = CfgEvent(kind: cfgSectionStart, section: c.tok.literal.move)
     else:
       result = CfgEvent(kind: cfgError,
         msg: errorStr(c, "symbol expected, but found: " & c.tok.literal))
diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim
index a8d1cfaab..c7bf0c9c1 100644
--- a/lib/pure/parsecsv.nim
+++ b/lib/pure/parsecsv.nim
@@ -13,7 +13,7 @@
 ## Basic usage
 ## ===========
 ##
-## .. code-block:: nim
+##   ```nim
 ##   import std/parsecsv
 ##   from std/os import paramStr
 ##   from std/streams import newFileStream
@@ -29,11 +29,12 @@
 ##     for val in items(x.row):
 ##       echo "##", val, "##"
 ##   close(x)
+##   ```
 ##
 ## For CSV files with a header row, the header can be read and then used as a
 ## reference for item access with `rowEntry <#rowEntry,CsvParser,string>`_:
 ##
-## .. code-block:: nim
+##   ```nim
 ##   import std/parsecsv
 ##
 ##   # Prepare a file
@@ -52,6 +53,7 @@
 ##     for col in items(p.headers):
 ##       echo "##", col, ":", p.rowEntry(col), "##"
 ##   p.close()
+##   ```
 ##
 ## See also
 ## ========
@@ -65,7 +67,7 @@
 ## * `parsesql module <parsesql.html>`_ for a SQL parser
 ## * `other parsers <lib.html#pure-libraries-parsers>`_ for other parsers
 
-import lexbase, streams
+import std/[lexbase, streams]
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -347,7 +349,7 @@ proc rowEntry*(self: var CsvParser, entry: string): var string =
     raise newException(KeyError, "Entry `" & entry & "` doesn't exist")
 
 when not defined(testing) and isMainModule:
-  import os
+  import std/os
   var s = newFileStream(paramStr(1), fmRead)
   if s == nil: quit("cannot open the file" & paramStr(1))
   var x: CsvParser
diff --git a/lib/pure/parsejson.nim b/lib/pure/parsejson.nim
index fcbcf8e36..9292a8596 100644
--- a/lib/pure/parsejson.nim
+++ b/lib/pure/parsejson.nim
@@ -11,7 +11,7 @@
 ## and exported by the `json` standard library
 ## module, but can also be used in its own right.
 
-import strutils, lexbase, streams, unicode
+import std/[strutils, lexbase, streams, unicode]
 import std/private/decode_helpers
 
 when defined(nimPreviewSlimSystem):
diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim
index f8d03e092..03f151b66 100644
--- a/lib/pure/parseopt.nim
+++ b/lib/pure/parseopt.nim
@@ -48,7 +48,7 @@
 ##
 ## Here is an example:
 ##
-## .. code-block::
+##   ```Nim
 ##   import std/parseopt
 ##
 ##   var p = initOptParser("-ab -e:5 --foo --bar=20 file.txt")
@@ -71,10 +71,34 @@
 ##   # Option: foo
 ##   # Option and value: bar, 20
 ##   # Argument: file.txt
+##   ```
 ##
 ## The `getopt iterator<#getopt.i,OptParser>`_, which is provided for
 ## convenience, can be used to iterate through all command line options as well.
 ##
+## To set a default value for a variable assigned through `getopt` and accept arguments from the cmd line.
+## Assign the default value to a variable before parsing.
+## Then set the variable to the new value while parsing.
+##
+## Here is an example:
+##
+##   ```Nim
+##   import std/parseopt
+##
+##   var varName: string = "defaultValue"
+##
+##   for kind, key, val in getopt():
+##     case kind
+##     of cmdArgument:
+##       discard
+##     of cmdLongOption, cmdShortOption:
+##       case key:
+##       of "varName": # --varName:<value> in the console when executing
+##         varName = val # do input sanitization in production systems
+##     of cmdEnd:
+##       discard
+##   ```
+##
 ## `shortNoVal` and `longNoVal`
 ## ============================
 ##
@@ -98,7 +122,7 @@
 ## `shortNoVal` and `longNoVal`, which is the default, and providing
 ## arguments for those two parameters:
 ##
-## .. code-block::
+##   ```Nim
 ##   import std/parseopt
 ##
 ##   proc printToken(kind: CmdLineKind, key: string, val: string) =
@@ -132,6 +156,7 @@
 ##   # Output:
 ##   # Option and value: j, 4
 ##   # Option and value: first, bar
+##   ```
 ##
 ## See also
 ## ========
@@ -151,7 +176,8 @@
 
 include "system/inclrtl"
 
-import os
+import std/strutils
+import std/os
 
 type
   CmdLineKind* = enum ## The detected command line token.
@@ -194,34 +220,6 @@ proc parseWord(s: string, i: int, w: var string,
 
 proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {},
                     longNoVal: seq[string] = @[];
-                    allowWhitespaceAfterColon = true): OptParser
-
-proc initOptParser*(cmdline = "", shortNoVal: set[char] = {},
-                    longNoVal: seq[string] = @[];
-                    allowWhitespaceAfterColon = true): OptParser =
-  ## Initializes the command line parser.
-  ##
-  ## If `cmdline == ""`, the real command line as provided by the
-  ## `os` module is retrieved instead if it is available. If the
-  ## command line is not available, a `ValueError` will be raised.
-  ##
-  ## `shortNoVal` and `longNoVal` are used to specify which options
-  ## do not take values. See the `documentation about these
-  ## parameters<#nimshortnoval-and-nimlongnoval>`_ for more information on
-  ## how this affects parsing.
-  ##
-  ## See also:
-  ## * `getopt iterator<#getopt.i,OptParser>`_
-  runnableExamples:
-    var p = initOptParser()
-    p = initOptParser("--left --debug:3 -l -r:2")
-    p = initOptParser("--left --debug:3 -l -r:2",
-                      shortNoVal = {'l'}, longNoVal = @["left"])
-
-  initOptParser(parseCmdLine(cmdline), shortNoVal, longNoVal, allowWhitespaceAfterColon)
-
-proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {},
-                    longNoVal: seq[string] = @[];
                     allowWhitespaceAfterColon = true): OptParser =
   ## Initializes the command line parser.
   ##
@@ -252,18 +250,55 @@ proc initOptParser*(cmdline: seq[string], shortNoVal: set[char] = {},
       result.cmds[i] = cmdline[i]
   else:
     when declared(paramCount):
-      result.cmds = newSeq[string](paramCount())
-      for i in countup(1, paramCount()):
-        result.cmds[i-1] = paramStr(i)
+      when defined(nimscript):
+        var ctr = 0
+        var firstNimsFound = false
+        for i in countup(0, paramCount()):
+          if firstNimsFound: 
+            result.cmds[ctr] = paramStr(i)
+            inc ctr, 1
+          if paramStr(i).endsWith(".nims") and not firstNimsFound:
+            firstNimsFound = true 
+            result.cmds = newSeq[string](paramCount()-i)
+      else:
+        result.cmds = newSeq[string](paramCount())
+        for i in countup(1, paramCount()):
+          result.cmds[i-1] = paramStr(i)
     else:
       # we cannot provide this for NimRtl creation on Posix, because we can't
       # access the command line arguments then!
-      doAssert false, "empty command line given but" &
+      raiseAssert "empty command line given but" &
         " real command line is not accessible"
   result.kind = cmdEnd
   result.key = ""
   result.val = ""
 
+proc initOptParser*(cmdline = "", shortNoVal: set[char] = {},
+                    longNoVal: seq[string] = @[];
+                    allowWhitespaceAfterColon = true): OptParser =
+  ## Initializes the command line parser.
+  ##
+  ## If `cmdline == ""`, the real command line as provided by the
+  ## `os` module is retrieved instead if it is available. If the
+  ## command line is not available, a `ValueError` will be raised.
+  ##
+  ## `shortNoVal` and `longNoVal` are used to specify which options
+  ## do not take values. See the `documentation about these
+  ## parameters<#nimshortnoval-and-nimlongnoval>`_ for more information on
+  ## how this affects parsing.
+  ##
+  ## This does not provide a way of passing default values to arguments.
+  ##
+  ## See also:
+  ## * `getopt iterator<#getopt.i,OptParser>`_
+  runnableExamples:
+    var p = initOptParser()
+    p = initOptParser("--left --debug:3 -l -r:2")
+    p = initOptParser("--left --debug:3 -l -r:2",
+                      shortNoVal = {'l'}, longNoVal = @["left"])
+
+  initOptParser(parseCmdLine(cmdline), shortNoVal, longNoVal, allowWhitespaceAfterColon)
+
 proc handleShortOption(p: var OptParser; cmd: string) =
   var i = p.pos
   p.kind = cmdShortOption
@@ -356,7 +391,7 @@ proc next*(p: var OptParser) {.rtl, extern: "npo$1".} =
       handleShortOption(p, p.cmds[p.idx])
   else:
     p.kind = cmdArgument
-    p.key =  p.cmds[p.idx]
+    p.key = p.cmds[p.idx]
     inc p.idx
     p.pos = 0
 
@@ -368,15 +403,14 @@ when declared(quoteShellCommand):
     ## * `remainingArgs proc<#remainingArgs,OptParser>`_
     ##
     ## **Examples:**
-    ##
-    ## .. code-block::
+    ##   ```Nim
     ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
     ##   while true:
     ##     p.next()
     ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
     ##       break
-    ##     else: continue
     ##   doAssert p.cmdLineRest == "foo.txt bar.txt"
+    ##   ```
     result = p.cmds[p.idx .. ^1].quoteShellCommand
 
 proc remainingArgs*(p: OptParser): seq[string] {.rtl, extern: "npo$1".} =
@@ -386,15 +420,14 @@ proc remainingArgs*(p: OptParser): seq[string] {.rtl, extern: "npo$1".} =
   ## * `cmdLineRest proc<#cmdLineRest,OptParser>`_
   ##
   ## **Examples:**
-  ##
-  ## .. code-block::
+  ##   ```Nim
   ##   var p = initOptParser("--left -r:2 -- foo.txt bar.txt")
   ##   while true:
   ##     p.next()
   ##     if p.kind == cmdLongOption and p.key == "":  # Look for "--"
   ##       break
-  ##     else: continue
   ##   doAssert p.remainingArgs == @["foo.txt", "bar.txt"]
+  ##   ```
   result = @[]
   for i in p.idx..<p.cmds.len: result.add p.cmds[i]
 
@@ -403,14 +436,15 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
   ## Convenience iterator for iterating over the given
   ## `OptParser<#OptParser>`_.
   ##
-  ## There is no need to check for `cmdEnd` while iterating.
+  ## There is no need to check for `cmdEnd` while iterating. If using `getopt`
+  ## with case switching, checking for `cmdEnd` is required.
   ##
   ## See also:
   ## * `initOptParser proc<#initOptParser,string,set[char],seq[string]>`_
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
+  ##   ```Nim
   ##   # these are placeholders, of course
   ##   proc writeHelp() = discard
   ##   proc writeVersion() = discard
@@ -430,6 +464,7 @@ iterator getopt*(p: var OptParser): tuple[kind: CmdLineKind, key,
   ##   if filename == "":
   ##     # no filename has been given, so we show the help
   ##     writeHelp()
+  ##   ```
   p.pos = 0
   p.idx = 0
   while true:
@@ -451,15 +486,15 @@ iterator getopt*(cmdline: seq[string] = @[],
   ## parameters<#nimshortnoval-and-nimlongnoval>`_ for more information on
   ## how this affects parsing.
   ##
-  ## There is no need to check for `cmdEnd` while iterating.
+  ## There is no need to check for `cmdEnd` while iterating. If using `getopt`
+  ## with case switching, checking for `cmdEnd` is required.
   ##
   ## See also:
   ## * `initOptParser proc<#initOptParser,seq[string],set[char],seq[string]>`_
   ##
   ## **Examples:**
   ##
-  ## .. code-block::
-  ##
+  ##   ```Nim
   ##   # these are placeholders, of course
   ##   proc writeHelp() = discard
   ##   proc writeVersion() = discard
@@ -479,6 +514,7 @@ iterator getopt*(cmdline: seq[string] = @[],
   ##   if filename == "":
   ##     # no filename has been written, so we show the help
   ##     writeHelp()
+  ##   ```
   var p = initOptParser(cmdline, shortNoVal = shortNoVal,
       longNoVal = longNoVal)
   while true:
diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim
index 3af840e29..a7c938d01 100644
--- a/lib/pure/parsesql.nim
+++ b/lib/pure/parsesql.nim
@@ -12,7 +12,7 @@
 ##
 ## Unstable API.
 
-import strutils, lexbase
+import std/[strutils, lexbase]
 import std/private/decode_helpers
 
 when defined(nimPreviewSlimSystem):
@@ -60,7 +60,7 @@ const
 
   reservedKeywords = @[
     # statements
-    "select", "from", "where", "group", "limit", "having",
+    "select", "from", "where", "group", "limit", "offset", "having",
     # functions
     "count",
   ]
@@ -509,6 +509,7 @@ type
     nkFromItemPair,
     nkGroup,
     nkLimit,
+    nkOffset,
     nkHaving,
     nkOrder,
     nkJoin,
@@ -1126,6 +1127,11 @@ proc parseSelect(p: var SqlParser): SqlNode =
     var l = newNode(nkLimit)
     l.add(parseExpr(p))
     result.add(l)
+  if isKeyw(p, "offset"):
+    getTok(p)
+    var o = newNode(nkOffset)
+    o.add(parseExpr(p))
+    result.add(o)
 
 proc parseStmt(p: var SqlParser; parent: SqlNode) =
   if isKeyw(p, "create"):
@@ -1388,6 +1394,9 @@ proc ra(n: SqlNode, s: var SqlWriter) =
   of nkLimit:
     s.addKeyw("limit")
     s.addMulti(n)
+  of nkOffset:
+    s.addKeyw("offset")
+    s.addMulti(n)
   of nkHaving:
     s.addKeyw("having")
     s.addMulti(n)
@@ -1482,7 +1491,7 @@ proc treeRepr*(s: SqlNode): string =
   result = newStringOfCap(128)
   treeReprAux(s, 0, result)
 
-import streams
+import std/streams
 
 proc open(L: var SqlLexer, input: Stream, filename: string) =
   lexbase.open(L, input)
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index 2bb23c626..2ca255fa0 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -12,29 +12,28 @@
 ##
 ## To unpack raw bytes look at the `streams <streams.html>`_ module.
 ##
-## .. code-block:: nim
-##    :test:
+##   ```nim test
+##   let logs = @["2019-01-10: OK_", "2019-01-11: FAIL_", "2019-01: aaaa"]
+##   var outp: seq[string]
 ##
-##    let logs = @["2019-01-10: OK_", "2019-01-11: FAIL_", "2019-01: aaaa"]
-##    var outp: seq[string]
+##   for log in logs:
+##     var res: string
+##     if parseUntil(log, res, ':') == 10: # YYYY-MM-DD == 10
+##       outp.add(res & " - " & captureBetween(log, ' ', '_'))
+##   doAssert outp == @["2019-01-10 - OK", "2019-01-11 - FAIL"]
+##   ```
 ##
-##    for log in logs:
-##      var res: string
-##      if parseUntil(log, res, ':') == 10: # YYYY-MM-DD == 10
-##        outp.add(res & " - " & captureBetween(log, ' ', '_'))
-##    doAssert outp == @["2019-01-10 - OK", "2019-01-11 - FAIL"]
+##   ```nim test
+##   from std/strutils import Digits, parseInt
 ##
-## .. code-block:: nim
-##    :test:
-##    from std/strutils import Digits, parseInt
-##
-##    let
-##      input1 = "2019 school start"
-##      input2 = "3 years back"
-##      startYear = input1[0 .. skipWhile(input1, Digits)-1] # 2019
-##      yearsBack = input2[0 .. skipWhile(input2, Digits)-1] # 3
-##      examYear = parseInt(startYear) + parseInt(yearsBack)
-##    doAssert "Examination is in " & $examYear == "Examination is in 2022"
+##   let
+##     input1 = "2019 school start"
+##     input2 = "3 years back"
+##     startYear = input1[0 .. skipWhile(input1, Digits)-1] # 2019
+##     yearsBack = input2[0 .. skipWhile(input2, Digits)-1] # 3
+##     examYear = parseInt(startYear) + parseInt(yearsBack)
+##   doAssert "Examination is in " & $examYear == "Examination is in 2022"
+##   ```
 ##
 ## **See also:**
 ## * `strutils module<strutils.html>`_ for combined and identical parsing proc's
@@ -461,6 +460,8 @@ proc parseBiggestInt*(s: openArray[char], number: var BiggestInt): int {.
     var res: BiggestInt
     doAssert parseBiggestInt("9223372036854775807", res) == 19
     doAssert res == 9223372036854775807
+    doAssert parseBiggestInt("-2024_05_09", res) == 11
+    doAssert res == -20240509
   var res = BiggestInt(0)
   # use 'res' for exception safety (don't write to 'number' in case of an
   # overflow exception):
@@ -475,10 +476,8 @@ proc parseInt*(s: openArray[char], number: var int): int {.
   ## `ValueError` is raised if the parsed integer is out of the valid range.
   runnableExamples:
     var res: int
-    doAssert parseInt("2019", res, 0) == 4
-    doAssert res == 2019
-    doAssert parseInt("2019", res, 2) == 2
-    doAssert res == 19
+    doAssert parseInt("-2024_05_02", res) == 11
+    doAssert res == -20240502
   var res = BiggestInt(0)
   result = parseBiggestInt(s, res)
   when sizeof(int) <= 4:
@@ -592,6 +591,71 @@ proc parseFloat*(s: openArray[char], number: var float): int {.
   if result != 0:
     number = bf
 
+func toLowerAscii(c: char): char =
+  if c in {'A'..'Z'}: char(uint8(c) xor 0b0010_0000'u8) else: c
+
+func parseSize*(s: openArray[char], size: var int64, alwaysBin=false): int =
+  ## Parse a size qualified by binary or metric units into `size`.  This format
+  ## is often called "human readable".  Result is the number of processed chars
+  ## or 0 on parse errors and size is rounded to the nearest integer.  Trailing
+  ## garbage like "/s" in "1k/s" is allowed and detected by `result < s.len`.
+  ##
+  ## To simplify use, following non-rare wild conventions, and since fractional
+  ## data like milli-bytes is so rare, unit matching is case-insensitive but for
+  ## the 'i' distinguishing binary-metric from metric (which cannot be 'I').
+  ##
+  ## An optional trailing 'B|b' is ignored but processed.  I.e., you must still
+  ## know if units are bytes | bits or infer this fact via the case of s[^1] (if
+  ## users can even be relied upon to use 'B' for byte and 'b' for bit or have
+  ## that be s[^1]).
+  ##
+  ## If `alwaysBin==true` then scales are always binary-metric, but e.g. "KiB"
+  ## is still accepted for clarity.  If the value would exceed the range of
+  ## `int64`, `size` saturates to `int64.high`.  Supported metric prefix chars
+  ## include k, m, g, t, p, e, z, y (but z & y saturate unless the number is a
+  ## small fraction).
+  ##
+  ## **See also:**
+  ## * https://en.wikipedia.org/wiki/Binary_prefix
+  ## * `formatSize module<strutils.html>`_ for formatting
+  runnableExamples:
+    var res: int64  # caller must still know if 'b' refers to bytes|bits
+    doAssert parseSize("10.5 MB", res) == 7
+    doAssert res == 10_500_000  # decimal metric Mega prefix
+    doAssert parseSize("64 mib", res) == 6
+    doAssert res == 67108864    # 64 shl 20
+    doAssert parseSize("1G/h", res, true) == 2 # '/' stops parse
+    doAssert res == 1073741824  # 1 shl 30, forced binary metric
+  const prefix = "b" & "kmgtpezy"       # byte|bit & lowCase metric-ish prefixes
+  const scaleM = [1.0, 1e3, 1e6, 1e9, 1e12, 1e15, 1e18, 1e21, 1e24] # 10^(3*idx)
+  const scaleB = [1.0, 1024, 1048576, 1073741824, 1099511627776.0,  # 2^(10*idx)
+                  1125899906842624.0, 1152921504606846976.0,        # ldexp?
+                  1.180591620717411303424e21, 1.208925819614629174706176e24]
+  var number: float
+  var scale = 1.0
+  result = parseFloat(s, number)
+  if number < 0:                        # While parseFloat accepts negatives ..
+    result = 0                          #.. we do not since sizes cannot be < 0
+  if result > 0:
+    let start = result                  # Save spot to maybe unwind white to EOS
+    while result < s.len and s[result] in Whitespace:
+      inc result
+    if result < s.len:                  # Illegal starting char => unity
+      if (let si = prefix.find(s[result].toLowerAscii); si >= 0):
+        inc result                      # Now parse the scale
+        scale = if alwaysBin: scaleB[si] else: scaleM[si]
+        if result < s.len and s[result] == 'i':
+          scale = scaleB[si]            # Switch from default to binary-metric
+          inc result
+        if result < s.len and s[result].toLowerAscii == 'b':
+          inc result                    # Skip optional '[bB]'
+    else:                               # Unwind result advancement when there..
+      result = start                    #..is no unit to the end of `s`.
+    var sizeF = number * scale + 0.5    # Saturate to int64.high when too big
+    size = if sizeF > 9223372036854774784.0: int64.high else: sizeF.int64
+# Above constant=2^63-1024 avoids C UB; github.com/nim-lang/Nim/issues/20102 or
+# stackoverflow.com/questions/20923556/math-pow2-63-1-math-pow2-63-512-is-true
+
 type
   InterpolatedKind* = enum ## Describes for `interpolatedFragments`
                            ## which part of the interpolated string is
@@ -928,6 +992,10 @@ proc parseBiggestInt*(s: string, number: var BiggestInt, start = 0): int {.noSid
     var res: BiggestInt
     doAssert parseBiggestInt("9223372036854775807", res, 0) == 19
     doAssert res == 9223372036854775807
+    doAssert parseBiggestInt("-2024_05_09", res) == 11
+    doAssert res == -20240509
+    doAssert parseBiggestInt("-2024_05_02", res, 7) == 4
+    doAssert res == 502
   parseBiggestInt(s.toOpenArray(start, s.high), number)
 
 proc parseInt*(s: string, number: var int, start = 0): int {.noSideEffect, raises: [ValueError].} =
@@ -936,10 +1004,10 @@ proc parseInt*(s: string, number: var int, start = 0): int {.noSideEffect, raise
   ## `ValueError` is raised if the parsed integer is out of the valid range.
   runnableExamples:
     var res: int
-    doAssert parseInt("2019", res, 0) == 4
-    doAssert res == 2019
-    doAssert parseInt("2019", res, 2) == 2
-    doAssert res == 19
+    doAssert parseInt("-2024_05_02", res) == 11
+    doAssert res == -20240502
+    doAssert parseInt("-2024_05_02", res, 7) == 4
+    doAssert res == 502
   parseInt(s.toOpenArray(start, s.high), number)
 
 
diff --git a/lib/pure/parsexml.nim b/lib/pure/parsexml.nim
index 884f258f3..c760799a2 100644
--- a/lib/pure/parsexml.nim
+++ b/lib/pure/parsexml.nim
@@ -36,43 +36,43 @@ The file ``examples/htmltitle.nim`` demonstrates how to use the
 XML parser to accomplish a simple task: To determine the title of an HTML
 document.
 
-.. code-block:: nim
+  ```nim
+  # Example program to show the parsexml module
+  # This program reads an HTML file and writes its title to stdout.
+  # Errors and whitespace are ignored.
 
-    # Example program to show the parsexml module
-    # This program reads an HTML file and writes its title to stdout.
-    # Errors and whitespace are ignored.
+  import std/[os, streams, parsexml, strutils]
 
-    import os, streams, parsexml, strutils
+  if paramCount() < 1:
+    quit("Usage: htmltitle filename[.html]")
 
-    if paramCount() < 1:
-      quit("Usage: htmltitle filename[.html]")
-
-    var filename = addFileExt(paramStr(1), "html")
-    var s = newFileStream(filename, fmRead)
-    if s == nil: quit("cannot open the file " & filename)
-    var x: XmlParser
-    open(x, s, filename)
-    while true:
-      x.next()
-      case x.kind
-      of xmlElementStart:
-        if cmpIgnoreCase(x.elementName, "title") == 0:
-          var title = ""
-          x.next()  # skip "<title>"
-          while x.kind == xmlCharData:
-            title.add(x.charData)
-            x.next()
-          if x.kind == xmlElementEnd and cmpIgnoreCase(x.elementName, "title") == 0:
-            echo("Title: " & title)
-            quit(0) # Success!
-          else:
-            echo(x.errorMsgExpected("/title"))
+  var filename = addFileExt(paramStr(1), "html")
+  var s = newFileStream(filename, fmRead)
+  if s == nil: quit("cannot open the file " & filename)
+  var x: XmlParser
+  open(x, s, filename)
+  while true:
+    x.next()
+    case x.kind
+    of xmlElementStart:
+      if cmpIgnoreCase(x.elementName, "title") == 0:
+        var title = ""
+        x.next()  # skip "<title>"
+        while x.kind == xmlCharData:
+          title.add(x.charData)
+          x.next()
+        if x.kind == xmlElementEnd and cmpIgnoreCase(x.elementName, "title") == 0:
+          echo("Title: " & title)
+          quit(0) # Success!
+        else:
+          echo(x.errorMsgExpected("/title"))
 
-      of xmlEof: break # end of file reached
-      else: discard # ignore other events
+    of xmlEof: break # end of file reached
+    else: discard # ignore other events
 
-    x.close()
-    quit("Could not determine title!")
+  x.close()
+  quit("Could not determine title!")
+  ```
 
 ]##
 
@@ -85,69 +85,69 @@ The file ``examples/htmlrefs.nim`` demonstrates how to use the
 XML parser to accomplish another simple task: To determine all the links
 an HTML document contains.
 
-.. code-block:: nim
+  ```nim
+  # Example program to show the new parsexml module
+  # This program reads an HTML file and writes all its used links to stdout.
+  # Errors and whitespace are ignored.
 
-    # Example program to show the new parsexml module
-    # This program reads an HTML file and writes all its used links to stdout.
-    # Errors and whitespace are ignored.
+  import std/[os, streams, parsexml, strutils]
 
-    import os, streams, parsexml, strutils
+  proc `=?=` (a, b: string): bool =
+    # little trick: define our own comparator that ignores case
+    return cmpIgnoreCase(a, b) == 0
 
-    proc `=?=` (a, b: string): bool =
-      # little trick: define our own comparator that ignores case
-      return cmpIgnoreCase(a, b) == 0
+  if paramCount() < 1:
+    quit("Usage: htmlrefs filename[.html]")
 
-    if paramCount() < 1:
-      quit("Usage: htmlrefs filename[.html]")
-
-    var links = 0 # count the number of links
-    var filename = addFileExt(paramStr(1), "html")
-    var s = newFileStream(filename, fmRead)
-    if s == nil: quit("cannot open the file " & filename)
-    var x: XmlParser
-    open(x, s, filename)
-    next(x) # get first event
-    block mainLoop:
-      while true:
-        case x.kind
-        of xmlElementOpen:
-          # the <a href = "xyz"> tag we are interested in always has an attribute,
-          # thus we search for ``xmlElementOpen`` and not for ``xmlElementStart``
-          if x.elementName =?= "a":
-            x.next()
-            if x.kind == xmlAttribute:
-              if x.attrKey =?= "href":
-                var link = x.attrValue
-                inc(links)
-                # skip until we have an ``xmlElementClose`` event
-                while true:
-                  x.next()
-                  case x.kind
-                  of xmlEof: break mainLoop
-                  of xmlElementClose: break
-                  else: discard
-                x.next() # skip ``xmlElementClose``
-                # now we have the description for the ``a`` element
-                var desc = ""
-                while x.kind == xmlCharData:
-                  desc.add(x.charData)
-                  x.next()
-                echo(desc & ": " & link)
-          else:
-            x.next()
-        of xmlEof: break # end of file reached
-        of xmlError:
-          echo(errorMsg(x))
+  var links = 0 # count the number of links
+  var filename = addFileExt(paramStr(1), "html")
+  var s = newFileStream(filename, fmRead)
+  if s == nil: quit("cannot open the file " & filename)
+  var x: XmlParser
+  open(x, s, filename)
+  next(x) # get first event
+  block mainLoop:
+    while true:
+      case x.kind
+      of xmlElementOpen:
+        # the <a href = "xyz"> tag we are interested in always has an attribute,
+        # thus we search for ``xmlElementOpen`` and not for ``xmlElementStart``
+        if x.elementName =?= "a":
+          x.next()
+          if x.kind == xmlAttribute:
+            if x.attrKey =?= "href":
+              var link = x.attrValue
+              inc(links)
+              # skip until we have an ``xmlElementClose`` event
+              while true:
+                x.next()
+                case x.kind
+                of xmlEof: break mainLoop
+                of xmlElementClose: break
+                else: discard
+              x.next() # skip ``xmlElementClose``
+              # now we have the description for the ``a`` element
+              var desc = ""
+              while x.kind == xmlCharData:
+                desc.add(x.charData)
+                x.next()
+              echo(desc & ": " & link)
+        else:
           x.next()
-        else: x.next() # skip other events
+      of xmlEof: break # end of file reached
+      of xmlError:
+        echo(errorMsg(x))
+        x.next()
+      else: x.next() # skip other events
 
-    echo($links & " link(s) found!")
-    x.close()
+  echo($links & " link(s) found!")
+  x.close()
+  ```
 
 ]##
 
 import
-  strutils, lexbase, streams, unicode
+  std/[strutils, lexbase, streams, unicode]
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio]
@@ -792,7 +792,7 @@ proc next*(my: var XmlParser) =
     my.state = stateNormal
 
 when not defined(testing) and isMainModule:
-  import os
+  import std/os
   var s = newFileStream(paramStr(1), fmRead)
   if s == nil: quit("cannot open the file" & paramStr(1))
   var x: XmlParser
diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim
index 5827b7444..2969fd6d7 100644
--- a/lib/pure/pegs.nim
+++ b/lib/pure/pegs.nim
@@ -22,11 +22,11 @@ when defined(nimPreviewSlimSystem):
 const
   useUnicode = true ## change this to deactivate proper UTF-8 support
 
-import strutils, macros
+import std/[strutils, macros]
 import std/private/decode_helpers
 
 when useUnicode:
-  import unicode
+  import std/unicode
   export unicode.`==`
 
 const
@@ -168,8 +168,9 @@ func charSet*(s: set[char]): Peg {.rtl, extern: "npegs$1".} =
   ## constructs a PEG from a character set `s`
   assert '\0' notin s
   result = Peg(kind: pkCharChoice)
-  new(result.charChoice)
-  result.charChoice[] = s
+  {.cast(noSideEffect).}:
+    new(result.charChoice)
+    result.charChoice[] = s
 
 func len(a: Peg): int {.inline.} = return a.sons.len
 func add(d: var Peg, s: Peg) {.inline.} = add(d.sons, s)
@@ -313,21 +314,21 @@ func capture*(a: Peg = Peg(kind: pkEmpty)): Peg {.rtl, extern: "npegsCapture".}
 func backref*(index: range[1..MaxSubpatterns], reverse: bool = false): Peg {.
   rtl, extern: "npegs$1".} =
   ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1. `reverse` specifies wether indexing starts from the end of the
+  ## from 1. `reverse` specifies whether indexing starts from the end of the
   ## capture list.
   result = Peg(kind: pkBackRef, index: (if reverse: -index else: index - 1))
 
 func backrefIgnoreCase*(index: range[1..MaxSubpatterns], reverse: bool = false): Peg {.
   rtl, extern: "npegs$1".} =
   ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1. `reverse` specifies wether indexing starts from the end of the
+  ## from 1. `reverse` specifies whether indexing starts from the end of the
   ## capture list. Ignores case for matching.
   result = Peg(kind: pkBackRefIgnoreCase, index: (if reverse: -index else: index - 1))
 
 func backrefIgnoreStyle*(index: range[1..MaxSubpatterns], reverse: bool = false): Peg {.
   rtl, extern: "npegs$1".} =
   ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1. `reverse` specifies wether indexing starts from the end of the
+  ## from 1. `reverse` specifies whether indexing starts from the end of the
   ## capture list. Ignores style for matching.
   result = Peg(kind: pkBackRefIgnoreStyle, index: (if reverse: -index else: index - 1))
 
@@ -561,7 +562,7 @@ template matchOrParse(mopProc: untyped) =
   # procs. For the former, *enter* and *leave* event handler code generators
   # are provided which just return *discard*.
 
-  proc mopProc(s: string, p: Peg, start: int, c: var Captures): int {.gcsafe.} =
+  proc mopProc(s: string, p: Peg, start: int, c: var Captures): int {.gcsafe, raises: [].} =
     proc matchBackRef(s: string, p: Peg, start: int, c: var Captures): int =
       # Parse handler code must run in an *of* clause of its own for each
       # *PegKind*, so we encapsulate the identical clause body for
@@ -888,7 +889,7 @@ macro mkHandlerTplts(handlers: untyped): untyped =
   # Transforms the handler spec in *handlers* into handler templates.
   # The AST structure of *handlers[0]*:
   #
-  # .. code-block::
+  #   ```
   #   StmtList
   #     Call
   #       Ident "pkNonTerminal"
@@ -909,6 +910,7 @@ macro mkHandlerTplts(handlers: untyped): untyped =
   #           StmtList
   #             <handler code block>
   #     ...
+  #   ```
   func mkEnter(hdName, body: NimNode): NimNode =
     template helper(hdName, body) {.dirty.} =
       template hdName(s, p, start) =
@@ -958,60 +960,61 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) =
   ## match, else the length of the total match. The following example code
   ## evaluates an arithmetic expression defined by a simple PEG:
   ##
-  ## .. code-block:: nim
-  ##  import std/[strutils, pegs]
+  ##   ```nim
+  ##   import std/[strutils, pegs]
   ##
-  ##  let
-  ##    pegAst = """
-  ##  Expr    <- Sum
-  ##  Sum     <- Product (('+' / '-')Product)*
-  ##  Product <- Value (('*' / '/')Value)*
-  ##  Value   <- [0-9]+ / '(' Expr ')'
-  ##    """.peg
-  ##    txt = "(5+3)/2-7*22"
+  ##   let
+  ##     pegAst = """
+  ##   Expr    <- Sum
+  ##   Sum     <- Product (('+' / '-')Product)*
+  ##   Product <- Value (('*' / '/')Value)*
+  ##   Value   <- [0-9]+ / '(' Expr ')'
+  ##     """.peg
+  ##     txt = "(5+3)/2-7*22"
   ##
-  ##  var
-  ##    pStack: seq[string] = @[]
-  ##    valStack: seq[float] = @[]
-  ##    opStack = ""
-  ##  let
-  ##    parseArithExpr = pegAst.eventParser:
-  ##      pkNonTerminal:
-  ##        enter:
-  ##          pStack.add p.nt.name
-  ##        leave:
-  ##          pStack.setLen pStack.high
-  ##          if length > 0:
-  ##            let matchStr = s.substr(start, start+length-1)
-  ##            case p.nt.name
-  ##            of "Value":
-  ##              try:
-  ##                valStack.add matchStr.parseFloat
-  ##                echo valStack
-  ##              except ValueError:
-  ##                discard
-  ##            of "Sum", "Product":
-  ##              try:
-  ##                let val = matchStr.parseFloat
-  ##              except ValueError:
-  ##                if valStack.len > 1 and opStack.len > 0:
-  ##                  valStack[^2] = case opStack[^1]
-  ##                  of '+': valStack[^2] + valStack[^1]
-  ##                  of '-': valStack[^2] - valStack[^1]
-  ##                  of '*': valStack[^2] * valStack[^1]
-  ##                  else: valStack[^2] / valStack[^1]
-  ##                  valStack.setLen valStack.high
-  ##                  echo valStack
-  ##                  opStack.setLen opStack.high
-  ##                  echo opStack
-  ##      pkChar:
-  ##        leave:
-  ##          if length == 1 and "Value" != pStack[^1]:
-  ##            let matchChar = s[start]
-  ##            opStack.add matchChar
-  ##            echo opStack
+  ##   var
+  ##     pStack: seq[string] = @[]
+  ##     valStack: seq[float] = @[]
+  ##     opStack = ""
+  ##   let
+  ##     parseArithExpr = pegAst.eventParser:
+  ##       pkNonTerminal:
+  ##         enter:
+  ##           pStack.add p.nt.name
+  ##         leave:
+  ##           pStack.setLen pStack.high
+  ##           if length > 0:
+  ##             let matchStr = s.substr(start, start+length-1)
+  ##             case p.nt.name
+  ##             of "Value":
+  ##               try:
+  ##                 valStack.add matchStr.parseFloat
+  ##                 echo valStack
+  ##               except ValueError:
+  ##                 discard
+  ##             of "Sum", "Product":
+  ##               try:
+  ##                 let val = matchStr.parseFloat
+  ##               except ValueError:
+  ##                 if valStack.len > 1 and opStack.len > 0:
+  ##                   valStack[^2] = case opStack[^1]
+  ##                   of '+': valStack[^2] + valStack[^1]
+  ##                   of '-': valStack[^2] - valStack[^1]
+  ##                   of '*': valStack[^2] * valStack[^1]
+  ##                   else: valStack[^2] / valStack[^1]
+  ##                   valStack.setLen valStack.high
+  ##                   echo valStack
+  ##                   opStack.setLen opStack.high
+  ##                   echo opStack
+  ##       pkChar:
+  ##         leave:
+  ##           if length == 1 and "Value" != pStack[^1]:
+  ##             let matchChar = s[start]
+  ##             opStack.add matchChar
+  ##             echo opStack
   ##
-  ##  let pLen = parseArithExpr(txt)
+  ##   let pLen = parseArithExpr(txt)
+  ##   ```
   ##
   ## The *handlers* parameter consists of code blocks for *PegKinds*,
   ## which define the grammar elements of interest. Each block can contain
@@ -1041,10 +1044,10 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) =
       # by *mkHandlerTplts*.
       template mkDoEnter(hdPostf, s, pegNode, start) =
         when declared(`enter hdPostf`):
-          `enter hdPostf`(s, pegNode, start):
+          `enter hdPostf`(s, pegNode, start)
         else:
           discard
-      let hdPostf = ident(substr(strVal(pegKind), 2))
+      let hdPostf = ident(substr($pegKind, 2))
       getAst(mkDoEnter(hdPostf, s, pegNode, start))
 
     macro leave(pegKind, s, pegNode, start, length: untyped): untyped =
@@ -1052,10 +1055,10 @@ template eventParser*(pegAst, handlers: untyped): (proc(s: string): int) =
       # a grammar element of kind *pegKind*.
       template mkDoLeave(hdPostf, s, pegNode, start, length) =
         when declared(`leave hdPostf`):
-          `leave hdPostf`(s, pegNode, start, length):
+          `leave hdPostf`(s, pegNode, start, length)
         else:
           discard
-      let hdPostf = ident(substr(strVal(pegKind), 2))
+      let hdPostf = ident(substr($pegKind, 2))
       getAst(mkDoLeave(hdPostf, s, pegNode, start, length))
 
     matchOrParse(parseIt)
@@ -1180,8 +1183,7 @@ template `=~`*(s: string, pattern: Peg): bool =
   ## This calls ``match`` with an implicit declared ``matches`` array that
   ## can be used in the scope of the ``=~`` call:
   ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}":
   ##     # matches a key=value pair:
   ##     echo("Key: ", matches[0])
@@ -1193,10 +1195,10 @@ template `=~`*(s: string, pattern: Peg): bool =
   ##     echo("comment: ", matches[0])
   ##   else:
   ##     echo("syntax error")
-  ##
+  ##   ```
   bind MaxSubpatterns
   when not declaredInScope(matches):
-    var matches {.inject.}: array[0..MaxSubpatterns-1, string]
+    var matches {.inject.} = default(array[0..MaxSubpatterns-1, string])
   match(s, pattern, matches)
 
 # ------------------------- more string handling ------------------------------
@@ -1229,14 +1231,15 @@ func replacef*(s: string, sub: Peg, by: string): string {.
   ## Replaces `sub` in `s` by the string `by`. Captures can be accessed in `by`
   ## with the notation ``$i`` and ``$#`` (see strutils.`%`). Examples:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   "var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2")
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   "var1<-keykey; val2<-key2key2"
+  ##   ```
   result = ""
   var i = 0
   var caps: array[0..MaxSubpatterns-1, string]
@@ -1304,8 +1307,7 @@ func replace*(s: string, sub: Peg, cb: proc(
   ## The callback proc receives the index of the current match (starting with 0),
   ## the count of captures and an open array with the captures of each match. Examples:
   ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   func handleMatches*(m: int, n: int, c: openArray[string]): string =
   ##     result = ""
   ##     if m > 0:
@@ -1317,12 +1319,13 @@ func replace*(s: string, sub: Peg, cb: proc(
   ##
   ##   let s = "Var1=key1;var2=Key2;   VAR3"
   ##   echo s.replace(peg"{\ident}('='{\ident})* ';'* \s*", handleMatches)
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   "var1: 'key1', var2: 'Key2', var3: ''"
+  ##   ```
   result = ""
   var i = 0
   var caps: array[0..MaxSubpatterns-1, string]
@@ -1360,18 +1363,19 @@ iterator split*(s: string, sep: Peg): string =
   ## Substrings are separated by the PEG `sep`.
   ## Examples:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for word in split("00232this02939is39an22example111", peg"\d+"):
   ##     writeLine(stdout, word)
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   "this"
   ##   "is"
   ##   "an"
   ##   "example"
-  ##
+  ##   ```
   var c: Captures
   var
     first = 0
@@ -1823,9 +1827,7 @@ type
     skip: Peg
 
 func pegError(p: PegParser, msg: string, line = -1, col = -1) =
-  var e: ref EInvalidPeg
-  new(e)
-  e.msg = errorStr(p, msg, line, col)
+  var e = (ref EInvalidPeg)(msg: errorStr(p, msg, line, col))
   raise e
 
 func getTok(p: var PegParser) =
@@ -1909,7 +1911,8 @@ func primary(p: var PegParser): Peg =
       getTok(p)
     elif not arrowIsNextTok(p):
       var nt = getNonTerminal(p, p.tok.literal)
-      incl(nt.flags, ntUsed)
+      {.cast(noSideEffect).}:
+        incl(nt.flags, ntUsed)
       result = nonterminal(nt).token(p)
       getTok(p)
     else:
@@ -2002,12 +2005,14 @@ func parseRule(p: var PegParser): NonTerminal =
     result = getNonTerminal(p, p.tok.literal)
     if ntDeclared in result.flags:
       pegError(p, "attempt to redefine: " & result.name)
-    result.line = getLine(p)
-    result.col = getColumn(p)
+    {.cast(noSideEffect).}:
+      result.line = getLine(p)
+      result.col = getColumn(p)
     getTok(p)
     eat(p, tkArrow)
-    result.rule = parseExpr(p)
-    incl(result.flags, ntDeclared) # NOW inlining may be attempted
+    {.cast(noSideEffect).}:
+      result.rule = parseExpr(p)
+      incl(result.flags, ntDeclared) # NOW inlining may be attempted
   else:
     pegError(p, "rule expected, but found: " & p.tok.literal)
 
diff --git a/lib/pure/punycode.nim b/lib/pure/punycode.nim
deleted file mode 100644
index 49e46496e..000000000
--- a/lib/pure/punycode.nim
+++ /dev/null
@@ -1,209 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2016 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## Implements a representation of Unicode with the limited
-## ASCII character subset.
-
-import strutils
-import unicode
-
-# issue #3045
-
-const
-  Base = 36
-  TMin = 1
-  TMax = 26
-  Skew = 38
-  Damp = 700
-  InitialBias = 72
-  InitialN = 128
-  Delimiter = '-'
-
-type
-  PunyError* = object of ValueError
-
-func decodeDigit(x: char): int {.raises: [PunyError].} =
-  if '0' <= x and x <= '9':
-    result = ord(x) - (ord('0') - 26)
-  elif 'A' <= x and x <= 'Z':
-    result = ord(x) - ord('A')
-  elif 'a' <= x and x <= 'z':
-    result = ord(x) - ord('a')
-  else:
-    raise newException(PunyError, "Bad input")
-
-func encodeDigit(digit: int): Rune {.raises: [PunyError].} =
-  if 0 <= digit and digit < 26:
-    result = Rune(digit + ord('a'))
-  elif 26 <= digit and digit < 36:
-    result = Rune(digit + (ord('0') - 26))
-  else:
-    raise newException(PunyError, "internal error in punycode encoding")
-
-func isBasic(c: char): bool = ord(c) < 0x80
-func isBasic(r: Rune): bool = int(r) < 0x80
-
-func adapt(delta, numPoints: int, first: bool): int =
-  var d = if first: delta div Damp else: delta div 2
-  d += d div numPoints
-  var k = 0
-  while d > ((Base-TMin)*TMax) div 2:
-    d = d div (Base - TMin)
-    k += Base
-  result = k + (Base - TMin + 1) * d div (d + Skew)
-
-func encode*(prefix, s: string): string {.raises: [PunyError].} =
-  ## Encode a string that may contain Unicode.
-  ## Prepend `prefix` to the result
-  result = prefix
-  var (d, n, bias) = (0, InitialN, InitialBias)
-  var (b, remaining) = (0, 0)
-  for r in s.runes:
-    if r.isBasic:
-      # basic Ascii character
-      inc b
-      result.add($r)
-    else:
-      # special character
-      inc remaining
-
-  var h = b
-  if b > 0:
-    result.add(Delimiter) # we have some Ascii chars
-  while remaining != 0:
-    var m: int = high(int32)
-    for r in s.runes:
-      if m > int(r) and int(r) >= n:
-        m = int(r)
-    d += (m - n) * (h + 1)
-    if d < 0:
-      raise newException(PunyError, "invalid label " & s)
-    n = m
-    for r in s.runes:
-      if int(r) < n:
-        inc d
-        if d < 0:
-          raise newException(PunyError, "invalid label " & s)
-        continue
-      if int(r) > n:
-        continue
-      var q = d
-      var k = Base
-      while true:
-        var t = k - bias
-        if t < TMin:
-          t = TMin
-        elif t > TMax:
-          t = TMax
-        if q < t:
-          break
-        result.add($encodeDigit(t + (q - t) mod (Base - t)))
-        q = (q - t) div (Base - t)
-        k += Base
-      result.add($encodeDigit(q))
-      bias = adapt(d, h + 1, h == b)
-      d = 0
-      inc h
-      dec remaining
-    inc d
-    inc n
-
-func encode*(s: string): string {.raises: [PunyError].} =
-  ## Encode a string that may contain Unicode. Prefix is empty.
-  result = encode("", s)
-
-func decode*(encoded: string): string {.raises: [PunyError].} =
-  ## Decode a Punycode-encoded string
-  var
-    n = InitialN
-    i = 0
-    bias = InitialBias
-  var d = rfind(encoded, Delimiter)
-  var output: seq[Rune]
-
-  if d > 0:
-    # found Delimiter
-    for j in 0..<d:
-      var c = encoded[j] # char
-      if not c.isBasic:
-        raise newException(PunyError, "Encoded contains a non-basic char")
-      output.add(Rune(c)) # add the character
-    inc d
-  else:
-    d = 0 # set to first index
-
-  while (d < len(encoded)):
-    var oldi = i
-    var w = 1
-    var k = Base
-    while true:
-      if d == len(encoded):
-        raise newException(PunyError, "Bad input: " & encoded)
-      var c = encoded[d]; inc d
-      var digit = int(decodeDigit(c))
-      if digit > (high(int32) - i) div w:
-        raise newException(PunyError, "Too large a value: " & $digit)
-      i += digit * w
-      var t: int
-      if k <= bias:
-        t = TMin
-      elif k >= bias + TMax:
-        t = TMax
-      else:
-        t = k - bias
-      if digit < t:
-        break
-      w *= Base - t
-      k += Base
-    bias = adapt(i - oldi, len(output) + 1, oldi == 0)
-
-    if i div (len(output) + 1) > high(int32) - n:
-      raise newException(PunyError, "Value too large")
-
-    n += i div (len(output) + 1)
-    i = i mod (len(output) + 1)
-    insert(output, Rune(n), i)
-    inc i
-
-  result = $output
-
-runnableExamples:
-  static:
-    block:
-      doAssert encode("") == ""
-      doAssert encode("a") == "a-"
-      doAssert encode("A") == "A-"
-      doAssert encode("3") == "3-"
-      doAssert encode("-") == "--"
-      doAssert encode("--") == "---"
-      doAssert encode("abc") == "abc-"
-      doAssert encode("London") == "London-"
-      doAssert encode("Lloyd-Atkinson") == "Lloyd-Atkinson-"
-      doAssert encode("This has spaces") == "This has spaces-"
-      doAssert encode("ü") == "tda"
-      doAssert encode("München") == "Mnchen-3ya"
-      doAssert encode("Mnchen-3ya") == "Mnchen-3ya-"
-      doAssert encode("München-Ost") == "Mnchen-Ost-9db"
-      doAssert encode("Bahnhof München-Ost") == "Bahnhof Mnchen-Ost-u6b"
-    block:
-      doAssert decode("") == ""
-      doAssert decode("a-") ==  "a"
-      doAssert decode("A-") == "A"
-      doAssert decode("3-") == "3"
-      doAssert decode("--") == "-"
-      doAssert decode("---") == "--"
-      doAssert decode("abc-") == "abc"
-      doAssert decode("London-") == "London"
-      doAssert decode("Lloyd-Atkinson-") == "Lloyd-Atkinson"
-      doAssert decode("This has spaces-") == "This has spaces"
-      doAssert decode("tda") == "ü"
-      doAssert decode("Mnchen-3ya") == "München"
-      doAssert decode("Mnchen-3ya-") == "Mnchen-3ya"
-      doAssert decode("Mnchen-Ost-9db") == "München-Ost"
-      doAssert decode("Bahnhof Mnchen-Ost-u6b") == "Bahnhof München-Ost"
diff --git a/lib/pure/random.nim b/lib/pure/random.nim
index c36ab445b..3ec77d37e 100644
--- a/lib/pure/random.nim
+++ b/lib/pure/random.nim
@@ -71,23 +71,36 @@ runnableExamples:
 ## * `list of cryptographic and hashing modules <lib.html#pure-libraries-hashing>`_
 ##   in the standard library
 
-import algorithm, math
-import std/private/since
+import std/[algorithm, math]
+import std/private/[since, jsutils]
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions]
 
 include system/inclrtl
 {.push debugger: off.}
+template whenHasBigInt64(yes64, no64): untyped =
+  when defined(js):
+    when compiles(compileOption("jsbigint64")):
+      when compileOption("jsbigint64"):
+        yes64
+      else:
+        no64
+    else:
+      no64
+  else:
+    yes64
 
-when defined(js):
-  type Ui = uint32
 
-  const randMax = 4_294_967_295u32
-else:
+whenHasBigInt64:
   type Ui = uint64
 
   const randMax = 18_446_744_073_709_551_615u64
+do:
+  type Ui = uint32
+
+  const randMax = 4_294_967_295u32
+
 
 type
   Rand* = object ## State of a random number generator.
@@ -105,17 +118,17 @@ type
                  ## generator are **not** thread-safe!
     a0, a1: Ui
 
-when defined(js):
-  var state = Rand(
-    a0: 0x69B4C98Cu32,
-    a1: 0xFED1DD30u32) # global for backwards compatibility
-else:
+whenHasBigInt64:
   const DefaultRandSeed = Rand(
     a0: 0x69B4C98CB8530805u64,
     a1: 0xFED1DD3004688D67CAu64)
 
   # racy for multi-threading but good enough for now:
   var state = DefaultRandSeed # global for backwards compatibility
+do:
+  var state = Rand(
+    a0: 0x69B4C98Cu32,
+    a1: 0xFED1DD30u32) # global for backwards compatibility
 
 func isValid(r: Rand): bool {.inline.} =
   ## Check whether state of `r` is valid.
@@ -208,10 +221,10 @@ proc skipRandomNumbers*(s: var Rand) =
     doAssert vals == [501737, 497901, 500683, 500157]
 
 
-  when defined(js):
-    const helper = [0xbeac0467u32, 0xd86b048bu32]
-  else:
+  whenHasBigInt64:
     const helper = [0xbeac0467eba5facbu64, 0xd86b048b86aa9922u64]
+  do:
+    const helper = [0xbeac0467u32, 0xd86b048bu32]
   var
     s0 = Ui 0
     s1 = Ui 0
@@ -231,11 +244,14 @@ proc rand[T: uint | uint64](r: var Rand; max: T): T =
     let max = uint64(max)
     when T.high.uint64 == uint64.high:
       if max == uint64.high: return T(next(r))
+    var iters = 0
     while true:
       let x = next(r)
       # avoid `mod` bias
-      if x <= randMax - (randMax mod max):
+      if x <= randMax - (randMax mod max) or iters > 20:
         return T(x mod (max + 1))
+      else:
+        inc iters
 
 proc rand*(r: var Rand; max: Natural): int {.benign.} =
   ## Returns a random integer in the range `0..max` using the given state.
@@ -291,7 +307,13 @@ proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} =
 
   let x = next(r)
   when defined(js):
-    result = (float(x) / float(high(uint32))) * max
+    when compiles(compileOption("jsbigint64")):
+      when compileOption("jsbigint64"):
+        result = (float(x) / float(high(uint64))) * max
+      else:
+        result = (float(x) / float(high(uint32))) * max
+    else:
+      result = (float(x) / float(high(uint32))) * max
   else:
     let u = (0x3FFu64 shl 52u64) or (x shr 12u64)
     result = (cast[float](u) - 1.0) * max
@@ -337,9 +359,9 @@ proc rand*[T: Ordinal or SomeFloat](r: var Rand; x: HSlice[T, T]): T =
   when T is SomeFloat:
     result = rand(r, x.b - x.a) + x.a
   else: # Integers and Enum types
-    when defined(js):
+    whenJsNoBigInt64:
       result = cast[T](rand(r, cast[uint](x.b) - cast[uint](x.a)) + cast[uint](x.a))
-    else:
+    do:
       result = cast[T](rand(r, cast[uint64](x.b) - cast[uint64](x.a)) + cast[uint64](x.a))
 
 proc rand*[T: Ordinal or SomeFloat](x: HSlice[T, T]): T =
@@ -378,14 +400,11 @@ proc rand*[T: Ordinal](r: var Rand; t: typedesc[T]): T {.since: (1, 7, 1).} =
   when T is range or T is enum:
     result = rand(r, low(T)..high(T))
   elif T is bool:
-    when defined(js):
-      result = (r.next or 0) < 0
-    else:
-      result = cast[int64](r.next) < 0
+    result = r.next < randMax div 2
   else:
-    when defined(js):
+    whenJsNoBigInt64:
       result = cast[T](r.next shr (sizeof(uint)*8 - sizeof(T)*8))
-    else:
+    do:
       result = cast[T](r.next shr (sizeof(uint64)*8 - sizeof(T)*8))
 
 proc rand*[T: Ordinal](t: typedesc[T]): T =
@@ -670,7 +689,7 @@ when not defined(standalone):
       import std/[hashes, os, sysrand, monotimes]
 
       when compileOption("threads"):
-        import locks
+        import std/locks
         var baseSeedLock: Lock
         baseSeedLock.initLock
 
diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim
index aba0f4ce4..5f806bd70 100644
--- a/lib/pure/rationals.nim
+++ b/lib/pure/rationals.nim
@@ -21,7 +21,7 @@ runnableExamples:
   doAssert r1 * r2 == -3 // 8
   doAssert r1 / r2 == -2 // 3
 
-import math, hashes
+import std/[math, hashes]
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
@@ -40,16 +40,16 @@ func reduce*[T: SomeInteger](x: var Rational[T]) =
     reduce(r)
     doAssert r.num == 1
     doAssert r.den == 2
-
+  if x.den == 0:
+    raise newException(DivByZeroDefect, "division by zero")
   let common = gcd(x.num, x.den)
   if x.den > 0:
     x.num = x.num div common
     x.den = x.den div common
-  elif x.den < 0:
-    x.num = -x.num div common
-    x.den = -x.den div common
-  else:
-    raise newException(DivByZeroDefect, "division by zero")
+  when T isnot SomeUnsignedInt:
+    if x.den < 0:
+      x.num = -x.num div common
+      x.den = -x.den div common
 
 func initRational*[T: SomeInteger](num, den: T): Rational[T] =
   ## Creates a new rational number with numerator `num` and denominator `den`.
@@ -318,3 +318,23 @@ func hash*[T](x: Rational[T]): Hash =
   h = h !& hash(copy.num)
   h = h !& hash(copy.den)
   result = !$h
+
+func `^`*[T: SomeInteger](x: Rational[T], y: T): Rational[T] =
+  ## Computes `x` to the power of `y`.
+  ##
+  ## The exponent `y` must be an integer. Negative exponents are supported
+  ## but floating point exponents are not.
+  runnableExamples:
+    doAssert (-3 // 5) ^ 0 == (1 // 1)
+    doAssert (-3 // 5) ^ 1 == (-3 // 5)
+    doAssert (-3 // 5) ^ 2 == (9 // 25)
+    doAssert (-3 // 5) ^ -2 == (25 // 9)
+
+  if y >= 0:
+    result.num = x.num ^ y
+    result.den = x.den ^ y
+  else:
+    result.num = x.den ^ -y
+    result.den = x.num ^ -y
+  # Note that all powers of reduced rationals are already reduced,
+  # so we don't need to call reduce() here
diff --git a/lib/pure/reservedmem.nim b/lib/pure/reservedmem.nim
index 528b0095c..ffa0128dc 100644
--- a/lib/pure/reservedmem.nim
+++ b/lib/pure/reservedmem.nim
@@ -44,7 +44,7 @@ type
     mem: ReservedMem
 
 when defined(windows):
-  import winlean
+  import std/winlean
   import std/private/win_getsysteminfo
 
   proc getAllocationGranularity: uint =
@@ -68,7 +68,7 @@ when defined(windows):
       raiseOSError(osLastError())
 
 else:
-  import posix
+  import std/posix
 
   let allocationGranularity = sysconf(SC_PAGESIZE)
 
diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim
index b973fd222..8750aca87 100644
--- a/lib/pure/ropes.nim
+++ b/lib/pure/ropes.nim
@@ -17,7 +17,7 @@
 ## runtime efficiency.
 
 include system/inclrtl
-import streams
+import std/streams
 
 when defined(nimPreviewSlimSystem):
   import std/[syncio, formatfloat, assertions]
diff --git a/lib/pure/segfaults.nim b/lib/pure/segfaults.nim
index b0eac2299..65b059e86 100644
--- a/lib/pure/segfaults.nim
+++ b/lib/pure/segfaults.nim
@@ -26,7 +26,7 @@ se.msg = "Could not access value because it is nil."
 when defined(windows):
   include "../system/ansi_c"
 
-  import winlean
+  import std/winlean
 
   const
     EXCEPTION_ACCESS_VIOLATION = DWORD(0xc0000005'i32)
@@ -65,7 +65,7 @@ when defined(windows):
     c_signal(SIGSEGV, segfaultHandler)
 
 else:
-  import posix
+  import std/posix
 
   var sa: Sigaction
 
diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim
index be5037fe2..ac180e2bd 100644
--- a/lib/pure/selectors.nim
+++ b/lib/pure/selectors.nim
@@ -27,7 +27,7 @@
 ##
 ## TODO: `/dev/poll`, `event ports` and filesystem events.
 
-import nativesockets
+import std/nativesockets
 import std/oserrors
 
 when defined(nimPreviewSlimSystem):
@@ -37,7 +37,7 @@ const hasThreadSupport = compileOption("threads") and defined(threadsafe)
 
 const ioselSupportedPlatform* = defined(macosx) or defined(freebsd) or
                                 defined(netbsd) or defined(openbsd) or
-                                defined(dragonfly) or
+                                defined(dragonfly) or defined(nuttx) or
                                 (defined(linux) and not defined(android) and not defined(emscripten))
   ## This constant is used to determine whether the destination platform is
   ## fully supported by `ioselectors` module.
@@ -205,12 +205,11 @@ when defined(nimdoc):
     ## to `value`. This `value` can be modified in the scope of
     ## the `withData` call.
     ##
-    ## .. code-block:: nim
-    ##
+    ##   ```nim
     ##   s.withData(fd, value) do:
     ##     # block is executed only if `fd` registered in selector `s`
     ##     value.uid = 1000
-    ##
+    ##   ```
 
   template withData*[T](s: Selector[T], fd: SocketHandle|int, value,
                         body1, body2: untyped) =
@@ -218,15 +217,14 @@ when defined(nimdoc):
     ## to `value`. This `value` can be modified in the scope of
     ## the `withData` call.
     ##
-    ## .. code-block:: nim
-    ##
+    ##   ```nim
     ##   s.withData(fd, value) do:
     ##     # block is executed only if `fd` registered in selector `s`.
     ##     value.uid = 1000
     ##   do:
     ##     # block is executed if `fd` not registered in selector `s`.
     ##     raise
-    ##
+    ##   ```
 
   proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} =
     ## Determines whether selector contains a file descriptor.
@@ -237,9 +235,9 @@ when defined(nimdoc):
     ## For *poll* and *select* selectors `-1` is returned.
 
 else:
-  import strutils
+  import std/strutils
   when hasThreadSupport:
-    import locks
+    import std/locks
 
     type
       SharedArray[T] = UncheckedArray[T]
@@ -247,8 +245,8 @@ else:
     proc allocSharedArray[T](nsize: int): ptr SharedArray[T] =
       result = cast[ptr SharedArray[T]](allocShared0(sizeof(T) * nsize))
 
-    proc reallocSharedArray[T](sa: ptr SharedArray[T], nsize: int): ptr SharedArray[T] =
-      result = cast[ptr SharedArray[T]](reallocShared(sa, sizeof(T) * nsize))
+    proc reallocSharedArray[T](sa: ptr SharedArray[T], oldsize, nsize: int): ptr SharedArray[T] =
+      result = cast[ptr SharedArray[T]](reallocShared0(sa, oldsize * sizeof(T), sizeof(T) * nsize))
 
     proc deallocSharedArray[T](sa: ptr SharedArray[T]) =
       deallocShared(cast[pointer](sa))
@@ -290,7 +288,7 @@ else:
     setBlocking(fd.SocketHandle, false)
 
   when not defined(windows):
-    import posix
+    import std/posix
 
     template setKey(s, pident, pevents, pparam, pdata: untyped) =
       var skey = addr(s.fds[pident])
@@ -328,7 +326,7 @@ else:
     doAssert(timeout >= -1, "Cannot select with a negative value, got: " & $timeout)
 
   when defined(linux) or defined(windows) or defined(macosx) or defined(bsd) or
-       defined(solaris) or defined(zephyr) or defined(freertos):
+       defined(solaris) or defined(zephyr) or defined(freertos) or defined(nuttx) or defined(haiku):
     template maxDescriptors*(): int =
       ## Returns the maximum number of active file descriptors for the current
       ## process. This involves a system call. For now `maxDescriptors` is
@@ -344,7 +342,18 @@ else:
           res = int(fdLim.rlim_cur) - 1
         res
 
-  when defined(linux) and not defined(emscripten):
+  when defined(nimIoselector):
+    when nimIoselector == "epoll":
+      include ioselects/ioselectors_epoll
+    elif nimIoselector == "kqueue":
+      include ioselects/ioselectors_kqueue
+    elif nimIoselector == "poll":
+      include ioselects/ioselectors_poll
+    elif nimIoselector == "select":
+      include ioselects/ioselectors_select
+    else:
+      {.fatal: "Unknown nimIoselector specified by define.".}
+  elif defined(linux) and not defined(emscripten):
     include ioselects/ioselectors_epoll
   elif bsdPlatform:
     include ioselects/ioselectors_kqueue
@@ -360,5 +369,7 @@ else:
     include ioselects/ioselectors_select
   elif defined(zephyr):
     include ioselects/ioselectors_poll
+  elif defined(nuttx):
+    include ioselects/ioselectors_epoll
   else:
     include ioselects/ioselectors_poll
diff --git a/lib/pure/smtp.nim.cfg b/lib/pure/smtp.nim.cfg
deleted file mode 100644
index 521e21de4..000000000
--- a/lib/pure/smtp.nim.cfg
+++ /dev/null
@@ -1 +0,0 @@
--d:ssl
diff --git a/lib/pure/ssl_certs.nim b/lib/pure/ssl_certs.nim
index dd09848be..d60cd22eb 100644
--- a/lib/pure/ssl_certs.nim
+++ b/lib/pure/ssl_certs.nim
@@ -10,7 +10,7 @@
 ## The default locations can be overridden using the SSL_CERT_FILE and
 ## SSL_CERT_DIR environment variables.
 
-import os, strutils
+import std/[os, strutils]
 
 # FWIW look for files before scanning entire dirs.
 
@@ -150,7 +150,7 @@ iterator scanSSLCertificates*(useEnvVars = false): string =
 # Certificates management on windows
 # when defined(windows) or defined(nimdoc):
 #
-#   import openssl
+#   import std/openssl
 #
 #   type
 #     PCCertContext {.final, pure.} = pointer
diff --git a/lib/pure/stats.nim b/lib/pure/stats.nim
index 7f797529d..6a4fd8f01 100644
--- a/lib/pure/stats.nim
+++ b/lib/pure/stats.nim
@@ -53,7 +53,7 @@ runnableExamples:
   doAssert statistics.kurtosis() ~= -1.0
   doAssert statistics.kurtosisS() ~= -0.7000000000000008
 
-from math import FloatClass, sqrt, pow, round
+from std/math import FloatClass, sqrt, pow, round
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, formatfloat]
diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim
index 945e85934..56f49d7b1 100644
--- a/lib/pure/streams.nim
+++ b/lib/pure/streams.nim
@@ -15,6 +15,11 @@
 ## Other modules may provide other implementations for this standard
 ## stream interface.
 ##
+## .. warning:: Due to the use of `pointer`, the `readData`, `peekData` and
+## `writeData` interfaces are not available on the compile-time VM, and must
+## be cast from a `ptr string` on the JS backend. However, `readDataStr` is
+## available generally in place of `readData`.
+##
 ## Basic usage
 ## ===========
 ##
@@ -27,67 +32,67 @@
 ## StringStream example
 ## --------------------
 ##
-## .. code-block:: Nim
-##
-##  import std/streams
+##   ```Nim
+##   import std/streams
 ##
-##  var strm = newStringStream("""The first line
-##  the second line
-##  the third line""")
+##   var strm = newStringStream("""The first line
+##   the second line
+##   the third line""")
 ##
-##  var line = ""
+##   var line = ""
 ##
-##  while strm.readLine(line):
-##    echo line
+##   while strm.readLine(line):
+##     echo line
 ##
-##  # Output:
-##  # The first line
-##  # the second line
-##  # the third line
+##   # Output:
+##   # The first line
+##   # the second line
+##   # the third line
 ##
-##  strm.close()
+##   strm.close()
+##   ```
 ##
 ## FileStream example
 ## ------------------
 ##
 ## Write file stream example:
 ##
-## .. code-block:: Nim
-##
-##  import std/streams
+##   ```Nim
+##   import std/streams
 ##
-##  var strm = newFileStream("somefile.txt", fmWrite)
-##  var line = ""
+##   var strm = newFileStream("somefile.txt", fmWrite)
+##   var line = ""
 ##
-##  if not isNil(strm):
-##    strm.writeLine("The first line")
-##    strm.writeLine("the second line")
-##    strm.writeLine("the third line")
-##    strm.close()
+##   if not isNil(strm):
+##     strm.writeLine("The first line")
+##     strm.writeLine("the second line")
+##     strm.writeLine("the third line")
+##     strm.close()
 ##
-##  # Output (somefile.txt):
-##  # The first line
-##  # the second line
-##  # the third line
+##   # Output (somefile.txt):
+##   # The first line
+##   # the second line
+##   # the third line
+##   ```
 ##
 ## Read file stream example:
 ##
-## .. code-block:: Nim
+##   ```Nim
+##   import std/streams
 ##
-##  import std/streams
+##   var strm = newFileStream("somefile.txt", fmRead)
+##   var line = ""
 ##
-##  var strm = newFileStream("somefile.txt", fmRead)
-##  var line = ""
+##   if not isNil(strm):
+##     while strm.readLine(line):
+##       echo line
+##     strm.close()
 ##
-##  if not isNil(strm):
-##    while strm.readLine(line):
-##      echo line
-##    strm.close()
-##
-##  # Output:
-##  # The first line
-##  # the second line
-##  # the third line
+##   # Output:
+##   # The first line
+##   # the second line
+##   # the third line
+##   ```
 ##
 ## See also
 ## ========
@@ -115,7 +120,7 @@ type
     ## * That these fields here shouldn't be used directly.
     ##   They are accessible so that a stream implementation can override them.
     closeImpl*: proc (s: Stream)
-      {.nimcall, raises: [Exception, IOError, OSError], tags: [WriteIOEffect], gcsafe.}
+      {.nimcall, raises: [IOError, OSError], tags: [WriteIOEffect], gcsafe.}
     atEndImpl*: proc (s: Stream): bool
       {.nimcall, raises: [Defect, IOError, OSError], tags: [], gcsafe.}
     setPositionImpl*: proc (s: Stream, pos: int)
@@ -348,9 +353,9 @@ proc write*[T](s: Stream, x: T) =
   ## **Note:** Not available for JS backend. Use `write(Stream, string)
   ## <#write,Stream,string>`_ for now.
   ##
-  ## .. code-block:: Nim
-  ##
-  ##     s.writeData(s, unsafeAddr(x), sizeof(x))
+  ##   ```Nim
+  ##   s.writeData(s, unsafeAddr(x), sizeof(x))
+  ##   ```
   runnableExamples:
     var strm = newStringStream("")
     strm.write("abcde")
@@ -938,10 +943,14 @@ proc peekFloat64*(s: Stream): float64 =
 
 proc readStrPrivate(s: Stream, length: int, str: var string) =
   if length > len(str): setLen(str, length)
-  when defined(js):
-    let L = readData(s, addr(str), length)
+  var L: int
+  when nimvm:
+    L = readDataStr(s, str, 0..length-1)
   else:
-    let L = readData(s, cstring(str), length)
+    when defined(js):
+      L = readData(s, addr(str), length)
+    else:
+      L = readData(s, cstring(str), length)
   if L != len(str): setLen(str, L)
 
 proc readStr*(s: Stream, length: int, str: var string) {.since: (1, 3).} =
@@ -1482,7 +1491,7 @@ when false:
     # do not import windows as this increases compile times:
     discard
   else:
-    import posix
+    import std/posix
 
     proc hsSetPosition(s: FileHandleStream, pos: int) =
       discard lseek(s.handle, pos, SEEK_SET)
@@ -1530,7 +1539,7 @@ when false:
       of fmReadWrite: flags = O_RDWR or int(O_CREAT)
       of fmReadWriteExisting: flags = O_RDWR
       of fmAppend: flags = O_WRONLY or int(O_CREAT) or O_APPEND
-      static: doAssert false # handle bug #17888
+      static: raiseAssert "unreachable" # handle bug #17888
       var handle = open(filename, flags)
       if handle < 0: raise newEOS("posix.open() call failed")
     result = newFileHandleStream(handle)
diff --git a/lib/pure/streamwrapper.nim b/lib/pure/streamwrapper.nim
index a6c1901d2..99752a9ab 100644
--- a/lib/pure/streamwrapper.nim
+++ b/lib/pure/streamwrapper.nim
@@ -11,7 +11,7 @@
 ##
 ## **Since** version 1.2.
 
-import deques, streams
+import std/[deques, streams]
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -91,14 +91,14 @@ proc newPipeOutStream*[T](s: sink (ref T)): owned PipeOutStream[T] =
   ## when setPosition/getPosition is called or write operation is performed.
   ##
   ## Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   import std/[osproc, streamwrapper]
   ##   var
   ##     p = startProcess(exePath)
   ##     outStream = p.outputStream().newPipeOutStream()
   ##   echo outStream.peekChar
   ##   p.close()
+  ##   ```
 
   assert s.readDataImpl != nil
 
diff --git a/lib/pure/strformat.nim b/lib/pure/strformat.nim
index 216c1ff11..7d093ebb3 100644
--- a/lib/pure/strformat.nim
+++ b/lib/pure/strformat.nim
@@ -133,13 +133,14 @@ runnableExamples:
 
 An expression like `&"{key} is {value:arg} {{z}}"` is transformed into:
 
-.. code-block:: nim
+  ```nim
   var temp = newStringOfCap(educatedCapGuess)
   temp.formatValue(key, "")
   temp.add(" is ")
   temp.formatValue(value, arg)
   temp.add(" {z}")
   temp
+  ```
 
 Parts of the string that are enclosed in the curly braces are interpreted
 as Nim code. To escape a `{` or `}`, double it.
@@ -263,6 +264,12 @@ The available floating point presentation types are:
                          exponent notation.
 `G`                      General format. Same as `g` except it switches to `E`
                          if the number gets to large.
+`i`                      Complex General format. This is only supported for
+                         complex numbers, which it prints using the mathematical
+                         (RE+IMj) format. The real and imaginary parts are printed
+                         using the general format `g` by default, but it is
+                         possible to combine this format with one of the other
+                         formats (e.g `jf`).
 (None)                   Similar to `g`, except that it prints at least one
                          digit after the decimal point.
 =================        ====================================================
@@ -272,13 +279,14 @@ The available floating point presentation types are:
 Because of the well defined order how templates and macros are
 expanded, strformat cannot expand template arguments:
 
-.. code-block:: nim
+  ```nim
   template myTemplate(arg: untyped): untyped =
     echo "arg is: ", arg
     echo &"--- {arg} ---"
 
   let x = "abc"
   myTemplate(x)
+  ```
 
 First the template `myTemplate` is expanded, where every identifier
 `arg` is substituted with its argument. The `arg` inside the
@@ -289,12 +297,13 @@ identifier that cannot be resolved anymore.
 
 The workaround for this is to bind the template argument to a new local variable.
 
-.. code-block:: nim
+  ```nim
   template myTemplate(arg: untyped): untyped =
     block:
       let arg1 {.inject.} = arg
       echo "arg is: ", arg1
       echo &"--- {arg1} ---"
+  ```
 
 The use of `{.inject.}` here is necessary again because of template
 expansion order and hygienic templates. But since we generally want to
@@ -313,8 +322,8 @@ help with readability, since there is only so much you can cram into
 single letter DSLs.
 ]##
 
-import macros, parseutils, unicode
-import strutils except format
+import std/[macros, parseutils, unicode]
+import std/strutils except format
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -472,50 +481,48 @@ proc parseStandardFormatSpecifier*(s: string; start = 0;
     raise newException(ValueError,
       "invalid format string, cannot parse: " & s[i..^1])
 
+proc toRadix(typ: char): int =
+  case typ
+  of 'x', 'X': 16
+  of 'd', '\0': 10
+  of 'o': 8
+  of 'b': 2
+  else:
+    raise newException(ValueError,
+      "invalid type in format string for number, expected one " &
+      " of 'x', 'X', 'b', 'd', 'o' but got: " & typ)
+
 proc formatValue*[T: SomeInteger](result: var string; value: T;
-                                  specifier: string) =
+                                  specifier: static string) =
   ## Standard format implementation for `SomeInteger`. It makes little
   ## sense to call this directly, but it is required to exist
   ## by the `&` macro.
-  if specifier.len == 0:
+  when specifier.len == 0:
     result.add $value
-    return
-  let spec = parseStandardFormatSpecifier(specifier)
-  var radix = 10
-  case spec.typ
-  of 'x', 'X': radix = 16
-  of 'd', '\0': discard
-  of 'b': radix = 2
-  of 'o': radix = 8
   else:
-    raise newException(ValueError,
-      "invalid type in format string for number, expected one " &
-      " of 'x', 'X', 'b', 'd', 'o' but got: " & spec.typ)
-  result.add formatInt(value, radix, spec)
+    const
+      spec = parseStandardFormatSpecifier(specifier)
+      radix = toRadix(spec.typ)
 
-proc formatValue*(result: var string; value: SomeFloat; specifier: string) =
-  ## Standard format implementation for `SomeFloat`. It makes little
+    result.add formatInt(value, radix, spec)
+
+proc formatValue*[T: SomeInteger](result: var string; value: T;
+                                  specifier: string) =
+  ## Standard format implementation for `SomeInteger`. It makes little
   ## sense to call this directly, but it is required to exist
   ## by the `&` macro.
   if specifier.len == 0:
     result.add $value
-    return
-  let spec = parseStandardFormatSpecifier(specifier)
-
-  var fmode = ffDefault
-  case spec.typ
-  of 'e', 'E':
-    fmode = ffScientific
-  of 'f', 'F':
-    fmode = ffDecimal
-  of 'g', 'G':
-    fmode = ffDefault
-  of '\0': discard
   else:
-    raise newException(ValueError,
-      "invalid type in format string for number, expected one " &
-      " of 'e', 'E', 'f', 'F', 'g', 'G' but got: " & spec.typ)
+    let
+      spec = parseStandardFormatSpecifier(specifier)
+      radix = toRadix(spec.typ)
 
+    result.add formatInt(value, radix, spec)
+
+proc formatFloat(
+    result: var string, value: SomeFloat, fmode: FloatFormatMode,
+    spec: StandardFormatSpecifier) =
   var f = formatBiggestFloat(value, fmode, spec.precision)
   var sign = false
   if value >= 0.0:
@@ -550,23 +557,83 @@ proc formatValue*(result: var string; value: SomeFloat; specifier: string) =
   else:
     result.add res
 
+proc toFloatFormatMode(typ: char): FloatFormatMode =
+  case typ
+  of 'e', 'E': ffScientific
+  of 'f', 'F': ffDecimal
+  of 'g', 'G': ffDefault
+  of '\0': ffDefault
+  else:
+    raise newException(ValueError,
+      "invalid type in format string for number, expected one " &
+      " of 'e', 'E', 'f', 'F', 'g', 'G' but got: " & typ)
+
+proc formatValue*(result: var string; value: SomeFloat; specifier: static string) =
+  ## Standard format implementation for `SomeFloat`. It makes little
+  ## sense to call this directly, but it is required to exist
+  ## by the `&` macro.
+  when specifier.len == 0:
+    result.add $value
+  else:
+    const
+      spec = parseStandardFormatSpecifier(specifier)
+      fmode = toFloatFormatMode(spec.typ)
+
+    formatFloat(result, value, fmode, spec)
+
+proc formatValue*(result: var string; value: SomeFloat; specifier: string) =
+  ## Standard format implementation for `SomeFloat`. It makes little
+  ## sense to call this directly, but it is required to exist
+  ## by the `&` macro.
+  if specifier.len == 0:
+    result.add $value
+  else:
+    let
+      spec = parseStandardFormatSpecifier(specifier)
+      fmode = toFloatFormatMode(spec.typ)
+
+    formatFloat(result, value, fmode, spec)
+
+proc formatValue*(result: var string; value: string; specifier: static string) =
+  ## Standard format implementation for `string`. It makes little
+  ## sense to call this directly, but it is required to exist
+  ## by the `&` macro.
+  const spec = parseStandardFormatSpecifier(specifier)
+  var value =
+    when spec.typ in {'s', '\0'}: value
+    else: static:
+      raise newException(ValueError,
+        "invalid type in format string for string, expected 's', but got " &
+        spec.typ)
+  when spec.precision != -1:
+    if spec.precision < runeLen(value):
+      const precision = cast[Natural](spec.precision)
+      setLen(value, Natural(runeOffset(value, precision)))
+
+  result.add alignString(value, spec.minimumWidth, spec.align, spec.fill)
+
 proc formatValue*(result: var string; value: string; specifier: string) =
   ## Standard format implementation for `string`. It makes little
   ## sense to call this directly, but it is required to exist
   ## by the `&` macro.
   let spec = parseStandardFormatSpecifier(specifier)
-  var value = value
-  case spec.typ
-  of 's', '\0': discard
-  else:
-    raise newException(ValueError,
-      "invalid type in format string for string, expected 's', but got " &
-      spec.typ)
+  var value =
+    if spec.typ in {'s', '\0'}: value
+    else:
+      raise newException(ValueError,
+        "invalid type in format string for string, expected 's', but got " &
+        spec.typ)
   if spec.precision != -1:
     if spec.precision < runeLen(value):
-      setLen(value, runeOffset(value, spec.precision))
+      let precision = cast[Natural](spec.precision)
+      setLen(value, Natural(runeOffset(value, precision)))
+
   result.add alignString(value, spec.minimumWidth, spec.align, spec.fill)
 
+proc formatValue[T: not SomeInteger](result: var string; value: T; specifier: static string) =
+  mixin `$`
+  formatValue(result, $value, specifier)
+
 proc formatValue[T: not SomeInteger](result: var string; value: T; specifier: string) =
   mixin `$`
   formatValue(result, $value, specifier)
@@ -577,7 +644,8 @@ template formatValue(result: var string; value: char; specifier: string) =
 template formatValue(result: var string; value: cstring; specifier: string) =
   result.add value
 
-proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
+proc strformatImpl(f: string; openChar, closeChar: char,
+                   lineInfoNode: NimNode = nil): NimNode =
   template missingCloseChar =
     error("invalid format string: missing closing character '" & closeChar & "'")
 
@@ -585,7 +653,7 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
     error "openChar and closeChar must not be ':'"
   var i = 0
   let res = genSym(nskVar, "fmtRes")
-  result = newNimNode(nnkStmtListExpr)
+  result = newNimNode(nnkStmtListExpr, lineInfoNode)
   # XXX: https://github.com/nim-lang/Nim/issues/8405
   # When compiling with -d:useNimRtl, certain procs such as `count` from the strutils
   # module are not accessible at compile-time:
@@ -644,6 +712,7 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
           x = parseExpr(subexpr)
         except ValueError as e:
           error("could not parse `$#` in `$#`.\n$#" % [subexpr, f, e.msg])
+        x.copyLineInfo(lineInfoNode)
         let formatSym = bindSym("formatValue", brOpen)
         var options = ""
         if f[i] == ':':
@@ -661,18 +730,29 @@ proc strformatImpl(f: string; openChar, closeChar: char): NimNode =
         strlit.add closeChar
         inc i, 2
       else:
-        doAssert false, "invalid format string: '$1' instead of '$1$1'" % $closeChar
-        inc i
+        raiseAssert "invalid format string: '$1' instead of '$1$1'" % $closeChar
     else:
       strlit.add f[i]
       inc i
   if strlit.len > 0:
     result.add newCall(bindSym"add", res, newLit(strlit))
   result.add res
+  # workaround for #20381
+  var blockExpr = newNimNode(nnkBlockExpr, lineInfoNode)
+  blockExpr.add(newEmptyNode())
+  blockExpr.add(result)
+  result = blockExpr
   when defined(debugFmtDsl):
     echo repr result
 
-macro fmt*(pattern: static string; openChar: static char, closeChar: static char): string =
+macro fmt(pattern: static string; openChar: static char, closeChar: static char, lineInfoNode: untyped): string =
+  ## version of `fmt` with dummy untyped param for line info
+  strformatImpl(pattern, openChar, closeChar, lineInfoNode)
+
+when not defined(nimHasCallsitePragma):
+  {.pragma: callsite.}
+
+template fmt*(pattern: static string; openChar: static char, closeChar: static char): string {.callsite.} =
   ## Interpolates `pattern` using symbols in scope.
   runnableExamples:
     let x = 7
@@ -689,13 +769,13 @@ macro fmt*(pattern: static string; openChar: static char, closeChar: static char
     assert "<x>".fmt('<', '>') == "7"
     assert "<<<x>>>".fmt('<', '>') == "<7>"
     assert "`x`".fmt('`', '`') == "7"
-  strformatImpl(pattern, openChar, closeChar)
+  fmt(pattern, openChar, closeChar, dummyForLineInfo)
 
-template fmt*(pattern: static string): untyped =
+template fmt*(pattern: static string): untyped {.callsite.} =
   ## Alias for `fmt(pattern, '{', '}')`.
-  fmt(pattern, '{', '}')
+  fmt(pattern, '{', '}', dummyForLineInfo)
 
-macro `&`*(pattern: string{lit}): string =
+template `&`*(pattern: string{lit}): string {.callsite.} =
   ## `&pattern` is the same as `pattern.fmt`.
   ## For a specification of the `&` macro, see the module level documentation.
   # pending bug #18275, bug #18278, use `pattern: static string`
@@ -707,4 +787,4 @@ macro `&`*(pattern: string{lit}): string =
     assert &"{x}\n" == "7\n" # regular string literal
     assert &"{x}\n" == "{x}\n".fmt # `fmt` can be used instead
     assert &"{x}\n" != fmt"{x}\n" # see `fmt` docs, this would use a raw string literal
-  strformatImpl(pattern.strVal, '{', '}')
+  fmt(pattern, '{', '}', dummyForLineInfo)
diff --git a/lib/pure/strmisc.nim b/lib/pure/strmisc.nim
index c8cd839be..a3e539e7e 100644
--- a/lib/pure/strmisc.nim
+++ b/lib/pure/strmisc.nim
@@ -27,20 +27,17 @@ func expandTabs*(s: string, tabSize: int = 8): string =
     doAssert expandTabs("a\tb\n\txy\t", 3) == "a  b\n   xy "
 
   result = newStringOfCap(s.len + s.len shr 2)
-  var pos = 0
 
   template addSpaces(n) =
-    for j in 0 ..< n:
+    for _ in 1..n:
       result.add(' ')
-      pos += 1
+    pos += n
 
-  for i in 0 ..< len(s):
-    let c = s[i]
+  var pos = 0
+  let denominator = if tabSize > 0: tabSize else: 1
+  for c in s:
     if c == '\t':
-      let
-        denominator = if tabSize > 0: tabSize else: 1
-        numSpaces = tabSize - pos mod denominator
-
+      let numSpaces = tabSize - pos mod denominator
       addSpaces(numSpaces)
     else:
       result.add(c)
diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim
index 8a1ea125f..16ef9e642 100644
--- a/lib/pure/strscans.nim
+++ b/lib/pure/strscans.nim
@@ -12,7 +12,7 @@ This module contains a `scanf`:idx: macro that can be used for extracting
 substrings from an input string. This is often easier than regular expressions.
 Some examples as an appetizer:
 
-.. code-block:: nim
+  ```nim
   # check if input string matches a triple of integers:
   const input = "(1,2,4)"
   var x, y, z: int
@@ -26,6 +26,7 @@ Some examples as an appetizer:
   var myfloat: float
   if scanf(input, "$i-$i-$i $w$s$f", year, month, day, identifier, myfloat):
     echo "yes, we have a match!"
+  ```
 
 As can be seen from the examples, strings are matched verbatim except for
 substrings starting with ``$``. These constructions are available:
@@ -83,8 +84,7 @@ matches optional tokens without any result binding.
 In this example, we define a helper proc ``someSep`` that skips some separators
 which we then use in our scanf pattern to help us in the matching process:
 
-.. code-block:: nim
-
+  ```nim
   proc someSep(input: string; start: int; seps: set[char] = {':','-','.'}): int =
     # Note: The parameters and return value must match to what ``scanf`` requires
     result = 0
@@ -92,11 +92,11 @@ which we then use in our scanf pattern to help us in the matching process:
 
   if scanf(input, "$w$[someSep]$w", key, value):
     ...
+  ```
 
-It also possible to pass arguments to a user definable matcher:
-
-.. code-block:: nim
+It is also possible to pass arguments to a user definable matcher:
 
+  ```nim
   proc ndigits(input: string; intVal: var int; start: int; n: int): int =
     # matches exactly ``n`` digits. Matchers need to return 0 if nothing
     # matched or otherwise the number of processed chars.
@@ -115,6 +115,7 @@ It also possible to pass arguments to a user definable matcher:
   var year, month, day: int
   if scanf("2013-01-03", "${ndigits(4)}-${ndigits(2)}-${ndigits(2)}$.", year, month, day):
     ...
+  ```
 
 
 The scanp macro
@@ -145,8 +146,7 @@ not implemented.
 
 Simple example that parses the ``/etc/passwd`` file line by line:
 
-.. code-block:: nim
-
+  ```nim
   const
     etc_passwd = """root:x:0:0:root:/root:/bin/bash
   daemon:x:1:1:daemon:/usr/sbin:/bin/sh
@@ -165,16 +165,16 @@ Simple example that parses the ``/etc/passwd`` file line by line:
         result.add entry
       else:
         break
+  ```
 
 The ``scanp`` maps the grammar code into Nim code that performs the parsing.
 The parsing is performed with the help of 3 helper templates that that can be
 implemented for a custom type.
 
 These templates need to be named ``atom`` and ``nxt``. ``atom`` should be
-overloaded to handle both single characters and sets of character.
-
-.. code-block:: nim
+overloaded to handle both `char` and `set[char]`.
 
+  ```nim
   import std/streams
 
   template atom(input: Stream; idx: int; c: char): bool =
@@ -190,11 +190,11 @@ overloaded to handle both single characters and sets of character.
 
   if scanp(content, idx, +( ~{'\L', '\0'} -> entry.add(peekChar($input))), '\L'):
     result.add entry
+  ```
 
 Calling ordinary Nim procs inside the macro is possible:
 
-.. code-block:: nim
-
+  ```nim
   proc digits(s: string; intVal: var int; start: int): int =
     var x = 0
     while result+start < s.len and s[result+start] in {'0'..'9'} and s[result+start] != ':':
@@ -220,12 +220,12 @@ Calling ordinary Nim procs inside the macro is possible:
           result.add login & " " & homedir
       else:
         break
+  ```
 
 When used for matching, keep in mind that likewise scanf, no backtracking
 is performed.
 
-.. code-block:: nim
-
+  ```nim
   proc skipUntil(s: string; until: string; unless = '\0'; start: int): int =
     # Skips all characters until the string `until` is found. Returns 0
     # if the char `unless` is found first or the end is reached.
@@ -256,12 +256,12 @@ is performed.
 
   for r in collectLinks(body):
     echo r
+  ```
 
 In this example both macros are combined seamlessly in order to maximise
 efficiency and perform different checks.
 
-.. code-block:: nim
-
+  ```nim
   iterator parseIps*(soup: string): string =
     ## ipv4 only!
     const digits = {'0'..'9'}
@@ -279,11 +279,11 @@ efficiency and perform different checks.
           yield buf
       buf.setLen(0) # need to clear `buf` each time, cause it might contain garbage
       idx.inc
-
+  ```
 ]##
 
 
-import macros, parseutils
+import std/[macros, parseutils]
 import std/private/since
 
 when defined(nimPreviewSlimSystem):
@@ -472,7 +472,7 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
 
 macro scanTuple*(input: untyped; pattern: static[string]; matcherTypes: varargs[untyped]): untyped {.since: (1, 5).}=
   ## Works identically as scanf, but instead of predeclaring variables it returns a tuple.
-  ## Tuple is started with a bool which indicates if the scan was successful 
+  ## Tuple is started with a bool which indicates if the scan was successful
   ## followed by the requested data.
   ## If using a user defined matcher, provide the types in order they appear after pattern:
   ## `line.scanTuple("${yourMatcher()}", int)`
diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim
index c72e6f876..4b07aca5a 100644
--- a/lib/pure/strtabs.nim
+++ b/lib/pure/strtabs.nim
@@ -51,7 +51,7 @@ runnableExamples:
 import std/private/since
 
 import
-  hashes, strutils
+  std/[hashes, strutils]
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -261,10 +261,7 @@ proc newStringTable*(mode: StringTableMode): owned(StringTableRef) {.
   ## See also:
   ## * `newStringTable(keyValuePairs) proc
   ##   <#newStringTable,varargs[tuple[string,string]],StringTableMode>`_
-  new(result)
-  result.mode = mode
-  result.counter = 0
-  newSeq(result.data, startSize)
+  result = StringTableRef(mode: mode, counter: 0, data: newSeq[KeyValuePair](startSize))
 
 proc newStringTable*(keyValuePairs: varargs[string],
                      mode: StringTableMode): owned(StringTableRef) {.
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 8b3d36f66..81be7db17 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -70,16 +70,16 @@ runnableExamples:
 ##   easier substring extraction than regular expressions
 
 
-import parseutils
-from math import pow, floor, log10
-from algorithm import fill, reverse
+import std/parseutils
+from std/math import pow, floor, log10
+from std/algorithm import fill, reverse
 import std/enumutils
 
-from unicode import toLower, toUpper
+from std/unicode import toLower, toUpper
 export toLower, toUpper
 
 include "system/inclrtl"
-import std/private/since
+import std/private/[since, jsutils]
 from std/private/strimpl import cmpIgnoreStyleImpl, cmpIgnoreCaseImpl,
     startsWithImpl, endsWithImpl
 
@@ -129,11 +129,11 @@ const
     ## Not very useful by its own, you can use it to create *inverted* sets to
     ## make the `find func<#find,string,set[char],Natural,int>`_
     ## find **invalid** characters in strings. Example:
-    ##
-    ## .. code-block:: nim
+    ##   ```nim
     ##   let invalid = AllChars - Digits
     ##   doAssert "01234".find(invalid) == -1
     ##   doAssert "01A34".find(invalid) == 2
+    ##   ```
 
 func isAlphaAscii*(c: char): bool {.rtl, extern: "nsuIsAlphaAsciiChar".} =
   ## Checks whether or not character `c` is alphabetical.
@@ -334,9 +334,9 @@ func normalize*(s: string): string {.rtl, extern: "nsuNormalize".} =
 func cmpIgnoreCase*(a, b: string): int {.rtl, extern: "nsuCmpIgnoreCase".} =
   ## Compares two strings in a case insensitive manner. Returns:
   ##
-  ## | 0 if a == b
-  ## | < 0 if a < b
-  ## | > 0 if a > b
+  ## | `0` if a == b
+  ## | `< 0` if a < b
+  ## | `> 0` if a > b
   runnableExamples:
     doAssert cmpIgnoreCase("FooBar", "foobar") == 0
     doAssert cmpIgnoreCase("bar", "Foo") < 0
@@ -354,9 +354,9 @@ func cmpIgnoreStyle*(a, b: string): int {.rtl, extern: "nsuCmpIgnoreStyle".} =
   ##
   ## Returns:
   ##
-  ## | 0 if a == b
-  ## | < 0 if a < b
-  ## | > 0 if a > b
+  ## | `0` if a == b
+  ## | `< 0` if a < b
+  ## | `> 0` if a > b
   runnableExamples:
     doAssert cmpIgnoreStyle("foo_bar", "FooBar") == 0
     doAssert cmpIgnoreStyle("foo_bar_5", "FooBar4") > 0
@@ -366,11 +366,14 @@ func cmpIgnoreStyle*(a, b: string): int {.rtl, extern: "nsuCmpIgnoreStyle".} =
 # --------- Private templates for different split separators -----------
 
 func substrEq(s: string, pos: int, substr: string): bool =
-  var i = 0
+  # Always returns false for empty `substr`
   var length = substr.len
-  while i < length and pos+i < s.len and s[pos+i] == substr[i]:
-    inc i
-  return i == length
+  if length > 0:
+    var i = 0
+    while i < length and pos+i < s.len and s[pos+i] == substr[i]:
+      inc i
+    i == length
+  else: false
 
 template stringHasSep(s: string, index: int, seps: set[char]): bool =
   s[index] in seps
@@ -420,14 +423,12 @@ iterator split*(s: string, sep: char, maxsplit: int = -1): string =
   ##
   ## Substrings are separated by the character `sep`.
   ## The code:
-  ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for word in split(";;this;is;an;;example;;;", ';'):
   ##     writeLine(stdout, word)
-  ##
+  ##   ```
   ## Results in:
-  ##
-  ## .. code-block::
+  ##   ```
   ##   ""
   ##   ""
   ##   "this"
@@ -438,6 +439,7 @@ iterator split*(s: string, sep: char, maxsplit: int = -1): string =
   ##   ""
   ##   ""
   ##   ""
+  ##   ```
   ##
   ## See also:
   ## * `rsplit iterator<#rsplit.i,string,char,int>`_
@@ -452,41 +454,49 @@ iterator split*(s: string, seps: set[char] = Whitespace,
   ##
   ## Substrings are separated by a substring containing only `seps`.
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for word in split("this\lis an\texample"):
   ##     writeLine(stdout, word)
+  ##   ```
   ##
   ## ...generates this output:
   ##
-  ## .. code-block::
+  ##   ```
   ##   "this"
   ##   "is"
   ##   "an"
   ##   "example"
+  ##   ```
   ##
   ## And the following code:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for word in split("this:is;an$example", {';', ':', '$'}):
   ##     writeLine(stdout, word)
+  ##   ```
   ##
   ## ...produces the same output as the first example. The code:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   let date = "2012-11-20T22:08:08.398990"
   ##   let separators = {' ', '-', ':', 'T'}
   ##   for number in split(date, separators):
   ##     writeLine(stdout, number)
+  ##   ```
   ##
   ## ...results in:
   ##
-  ## .. code-block::
+  ##   ```
   ##   "2012"
   ##   "11"
   ##   "20"
   ##   "22"
   ##   "08"
   ##   "08.398990"
+  ##   ```
+  ##
+  ##  .. note:: Empty separator set results in returning an original string,
+  ##   following the interpretation "split by no element".
   ##
   ## See also:
   ## * `rsplit iterator<#rsplit.i,string,set[char],int>`_
@@ -501,23 +511,30 @@ iterator split*(s: string, sep: string, maxsplit: int = -1): string =
   ## Substrings are separated by the string `sep`.
   ## The code:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for word in split("thisDATAisDATAcorrupted", "DATA"):
   ##     writeLine(stdout, word)
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block::
+  ##   ```
   ##   "this"
   ##   "is"
   ##   "corrupted"
+  ##   ```
+  ##
+  ##  .. note:: Empty separator string results in returning an original string,
+  ##   following the interpretation "split by no element".
   ##
   ## See also:
   ## * `rsplit iterator<#rsplit.i,string,string,int,bool>`_
   ## * `splitLines iterator<#splitLines.i,string>`_
   ## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_
   ## * `split func<#split,string,string,int>`_
-  splitCommon(s, sep, maxsplit, sep.len)
+  let sepLen = if sep.len == 0: 1 # prevents infinite loop
+    else: sep.len
+  splitCommon(s, sep, maxsplit, sepLen)
 
 
 template rsplitCommon(s, sep, maxsplit, sepLen) =
@@ -548,17 +565,19 @@ iterator rsplit*(s: string, sep: char,
                  maxsplit: int = -1): string =
   ## Splits the string `s` into substrings from the right using a
   ## string separator. Works exactly the same as `split iterator
-  ## <#split.i,string,char,int>`_ except in reverse order.
+  ## <#split.i,string,char,int>`_ except in **reverse** order.
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for piece in "foo:bar".rsplit(':'):
   ##     echo piece
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```
   ##   "bar"
   ##   "foo"
+  ##   ```
   ##
   ## Substrings are separated from the right by the char `sep`.
   ##
@@ -573,20 +592,25 @@ iterator rsplit*(s: string, seps: set[char] = Whitespace,
                  maxsplit: int = -1): string =
   ## Splits the string `s` into substrings from the right using a
   ## string separator. Works exactly the same as `split iterator
-  ## <#split.i,string,char,int>`_ except in reverse order.
+  ## <#split.i,string,char,int>`_ except in **reverse** order.
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for piece in "foo bar".rsplit(WhiteSpace):
   ##     echo piece
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```
   ##   "bar"
   ##   "foo"
+  ##   ```
   ##
   ## Substrings are separated from the right by the set of chars `seps`
   ##
+  ##  .. note:: Empty separator set results in returning an original string,
+  ##   following the interpretation "split by no element".
+  ##
   ## See also:
   ## * `split iterator<#split.i,string,set[char],int>`_
   ## * `splitLines iterator<#splitLines.i,string>`_
@@ -598,44 +622,52 @@ iterator rsplit*(s: string, sep: string, maxsplit: int = -1,
                  keepSeparators: bool = false): string =
   ## Splits the string `s` into substrings from the right using a
   ## string separator. Works exactly the same as `split iterator
-  ## <#split.i,string,string,int>`_ except in reverse order.
+  ## <#split.i,string,string,int>`_ except in **reverse** order.
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for piece in "foothebar".rsplit("the"):
   ##     echo piece
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```
   ##   "bar"
   ##   "foo"
+  ##   ```
   ##
   ## Substrings are separated from the right by the string `sep`
   ##
+  ##  .. note:: Empty separator string results in returning an original string,
+  ##   following the interpretation "split by no element".
+  ##
   ## See also:
   ## * `split iterator<#split.i,string,string,int>`_
   ## * `splitLines iterator<#splitLines.i,string>`_
   ## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_
   ## * `rsplit func<#rsplit,string,string,int>`_
-  rsplitCommon(s, sep, maxsplit, sep.len)
+  let sepLen = if sep.len == 0: 1 # prevents infinite loop
+    else: sep.len
+  rsplitCommon(s, sep, maxsplit, sepLen)
 
 iterator splitLines*(s: string, keepEol = false): string =
   ## Splits the string `s` into its containing lines.
   ##
   ## Every `character literal <manual.html#lexical-analysis-character-literals>`_
   ## newline combination (CR, LF, CR-LF) is supported. The result strings
-  ## contain no trailing end of line characters unless parameter `keepEol`
+  ## contain no trailing end of line characters unless the parameter `keepEol`
   ## is set to `true`.
   ##
   ## Example:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for line in splitLines("\nthis\nis\nan\n\nexample\n"):
   ##     writeLine(stdout, line)
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   ""
   ##   "this"
   ##   "is"
@@ -643,6 +675,7 @@ iterator splitLines*(s: string, keepEol = false): string =
   ##   ""
   ##   "example"
   ##   ""
+  ##   ```
   ##
   ## See also:
   ## * `splitWhitespace iterator<#splitWhitespace.i,string,int>`_
@@ -675,16 +708,17 @@ iterator splitWhitespace*(s: string, maxsplit: int = -1): string =
   ##
   ## The following code:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   let s = "  foo \t bar  baz  "
   ##   for ms in [-1, 1, 2, 3]:
   ##     echo "------ maxsplit = ", ms, ":"
   ##     for item in s.splitWhitespace(maxsplit=ms):
   ##       echo '"', item, '"'
+  ##   ```
   ##
   ## ...results in:
   ##
-  ## .. code-block::
+  ##   ```
   ##   ------ maxsplit = -1:
   ##   "foo"
   ##   "bar"
@@ -700,6 +734,7 @@ iterator splitWhitespace*(s: string, maxsplit: int = -1): string =
   ##   "foo"
   ##   "bar"
   ##   "baz"
+  ##   ```
   ##
   ## See also:
   ## * `splitLines iterator<#splitLines.i,string>`_
@@ -728,6 +763,9 @@ func split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[
   ## The same as the `split iterator <#split.i,string,set[char],int>`_ (see its
   ## documentation), but is a func that returns a sequence of substrings.
   ##
+  ##  .. note:: Empty separator set results in returning an original string,
+  ##   following the interpretation "split by no element".
+  ##
   ## See also:
   ## * `split iterator <#split.i,string,set[char],int>`_
   ## * `rsplit func<#rsplit,string,set[char],int>`_
@@ -736,6 +774,7 @@ func split*(s: string, seps: set[char] = Whitespace, maxsplit: int = -1): seq[
   runnableExamples:
     doAssert "a,b;c".split({',', ';'}) == @["a", "b", "c"]
     doAssert "".split({' '}) == @[""]
+    doAssert "empty seps return unsplit s".split({}) == @["empty seps return unsplit s"]
   accResult(split(s, seps, maxsplit))
 
 func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
@@ -745,6 +784,9 @@ func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
   ## Substrings are separated by the string `sep`. This is a wrapper around the
   ## `split iterator <#split.i,string,string,int>`_.
   ##
+  ##  .. note:: Empty separator string results in returning an original string,
+  ##   following the interpretation "split by no element".
+  ##
   ## See also:
   ## * `split iterator <#split.i,string,string,int>`_
   ## * `rsplit func<#rsplit,string,string,int>`_
@@ -757,14 +799,13 @@ func split*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
     doAssert "a  largely    spaced sentence".split(" ") == @["a", "", "largely",
         "", "", "", "spaced", "sentence"]
     doAssert "a  largely    spaced sentence".split(" ", maxsplit = 1) == @["a", " largely    spaced sentence"]
-  doAssert(sep.len > 0)
-
+    doAssert "empty sep returns unsplit s".split("") == @["empty sep returns unsplit s"]
   accResult(split(s, sep, maxsplit))
 
 func rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string] {.rtl,
     extern: "nsuRSplitChar".} =
   ## The same as the `rsplit iterator <#rsplit.i,string,char,int>`_, but is a func
-  ## that returns a sequence of substrings.
+  ## that returns a sequence of substrings in original order.
   ##
   ## A possible common use case for `rsplit` is path manipulation,
   ## particularly on systems that don't use a common delimiter.
@@ -772,13 +813,15 @@ func rsplit*(s: string, sep: char, maxsplit: int = -1): seq[string] {.rtl,
   ## For example, if a system had `#` as a delimiter, you could
   ## do the following to get the tail of the path:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   var tailSplit = rsplit("Root#Object#Method#Index", '#', maxsplit=1)
+  ##   ```
   ##
   ## Results in `tailSplit` containing:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   @["Root#Object#Method", "Index"]
+  ##   ```
   ##
   ## See also:
   ## * `rsplit iterator <#rsplit.i,string,char,int>`_
@@ -792,7 +835,7 @@ func rsplit*(s: string, seps: set[char] = Whitespace,
              maxsplit: int = -1): seq[string]
              {.rtl, extern: "nsuRSplitCharSet".} =
   ## The same as the `rsplit iterator <#rsplit.i,string,set[char],int>`_, but is a
-  ## func that returns a sequence of substrings.
+  ## func that returns a sequence of substrings in original order.
   ##
   ## A possible common use case for `rsplit` is path manipulation,
   ## particularly on systems that don't use a common delimiter.
@@ -800,13 +843,18 @@ func rsplit*(s: string, seps: set[char] = Whitespace,
   ## For example, if a system had `#` as a delimiter, you could
   ## do the following to get the tail of the path:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   var tailSplit = rsplit("Root#Object#Method#Index", {'#'}, maxsplit=1)
+  ##   ```
   ##
   ## Results in `tailSplit` containing:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   @["Root#Object#Method", "Index"]
+  ##   ```
+  ##
+  ##  .. note:: Empty separator set results in returning an original string,
+  ##   following the interpretation "split by no element".
   ##
   ## See also:
   ## * `rsplit iterator <#rsplit.i,string,set[char],int>`_
@@ -819,7 +867,7 @@ func rsplit*(s: string, seps: set[char] = Whitespace,
 func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
     extern: "nsuRSplitString".} =
   ## The same as the `rsplit iterator <#rsplit.i,string,string,int,bool>`_, but is a func
-  ## that returns a sequence of substrings.
+  ## that returns a sequence of substrings in original order.
   ##
   ## A possible common use case for `rsplit` is path manipulation,
   ## particularly on systems that don't use a common delimiter.
@@ -827,13 +875,18 @@ func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
   ## For example, if a system had `#` as a delimiter, you could
   ## do the following to get the tail of the path:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   var tailSplit = rsplit("Root#Object#Method#Index", "#", maxsplit=1)
+  ##   ```
   ##
   ## Results in `tailSplit` containing:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   @["Root#Object#Method", "Index"]
+  ##   ```
+  ##
+  ##  .. note:: Empty separator string results in returning an original string,
+  ##   following the interpretation "split by no element".
   ##
   ## See also:
   ## * `rsplit iterator <#rsplit.i,string,string,int,bool>`_
@@ -849,6 +902,7 @@ func rsplit*(s: string, sep: string, maxsplit: int = -1): seq[string] {.rtl,
     doAssert "".rsplit("Elon Musk") == @[""]
     doAssert "a  largely    spaced sentence".rsplit(" ") == @["a", "",
         "largely", "", "", "", "spaced", "sentence"]
+    doAssert "empty sep returns unsplit s".rsplit("") == @["empty sep returns unsplit s"]
   accResult(rsplit(s, sep, maxsplit))
   result.reverse()
 
@@ -944,14 +998,26 @@ func toHex*[T: SomeInteger](x: T, len: Positive): string =
     doAssert b.toHex(4) == "1001"
     doAssert toHex(62, 3) == "03E"
     doAssert toHex(-8, 6) == "FFFFF8"
-  toHexImpl(cast[BiggestUInt](x), len, x < 0)
+  whenJsNoBigInt64:
+    toHexImpl(cast[BiggestUInt](x), len, x < 0)
+  do:
+    when T is SomeSignedInt:
+      toHexImpl(cast[BiggestUInt](BiggestInt(x)), len, x < 0)
+    else:
+      toHexImpl(BiggestUInt(x), len, x < 0)
 
 func toHex*[T: SomeInteger](x: T): string =
   ## Shortcut for `toHex(x, T.sizeof * 2)`
   runnableExamples:
     doAssert toHex(1984'i64) == "00000000000007C0"
     doAssert toHex(1984'i16) == "07C0"
-  toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0)
+  whenJsNoBigInt64:
+    toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0)
+  do:
+    when T is SomeSignedInt:
+      toHexImpl(cast[BiggestUInt](BiggestInt(x)), 2*sizeof(T), x < 0)
+    else:
+      toHexImpl(BiggestUInt(x), 2*sizeof(T), x < 0)
 
 func toHex*(s: string): string {.rtl.} =
   ## Converts a bytes string to its hexadecimal representation.
@@ -1241,7 +1307,7 @@ func parseEnum*[T: enum](s: string): T =
   ## type contains multiple fields with the same string value.
   ##
   ## Raises `ValueError` for an invalid value in `s`. The comparison is
-  ## done in a style insensitive way.
+  ## done in a style insensitive way (first letter is still case-sensitive).
   runnableExamples:
     type
       MyEnum = enum
@@ -1261,7 +1327,7 @@ func parseEnum*[T: enum](s: string, default: T): T =
   ## type contains multiple fields with the same string value.
   ##
   ## Uses `default` for an invalid value in `s`. The comparison is done in a
-  ## style insensitive way.
+  ## style insensitive way (first letter is still case-sensitive).
   runnableExamples:
     type
       MyEnum = enum
@@ -1742,8 +1808,9 @@ func addSep*(dest: var string, sep = ", ", startLen: Natural = 0) {.inline.} =
   ##
   ## A shorthand for:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   if dest.len > startLen: add(dest, sep)
+  ##   ```
   ##
   ## This is often useful for generating some code where the items need to
   ## be *separated* by `sep`. `sep` is only added if `dest` is longer than
@@ -1808,7 +1875,7 @@ func join*(a: openArray[string], sep: string = ""): string {.rtl,
   else:
     result = ""
 
-func join*[T: not string](a: openArray[T], sep: string = ""): string =
+proc join*[T: not string](a: openArray[T], sep: string = ""): string =
   ## Converts all elements in the container `a` to strings using `$`,
   ## and concatenates them with `sep`.
   runnableExamples:
@@ -1914,7 +1981,7 @@ func find*(s: string, sub: char, start: Natural = 0, last = -1): int {.rtl,
       if length > 0:
         let found = c_memchr(s[start].unsafeAddr, sub, cast[csize_t](length))
         if not found.isNil:
-          return cast[ByteAddress](found) -% cast[ByteAddress](s.cstring)
+          return cast[int](found) -% cast[int](s.cstring)
     else:
       findImpl()
 
@@ -1970,7 +2037,7 @@ func find*(s, sub: string, start: Natural = 0, last = -1): int {.rtl,
       if last < 0 and start < s.len and subLen != 0:
         let found = memmem(s[start].unsafeAddr, csize_t(s.len - start), sub.cstring, csize_t(subLen))
         result = if not found.isNil:
-            cast[ByteAddress](found) -% cast[ByteAddress](s.cstring)
+            cast[int](found) -% cast[int](s.cstring)
           else:
             -1
       else:
@@ -2214,17 +2281,31 @@ func replaceWord*(s, sub: string, by = ""): string {.rtl,
     add result, substr(s, i)
 
 func multiReplace*(s: string, replacements: varargs[(string, string)]): string =
-  ## Same as replace, but specialized for doing multiple replacements in a single
-  ## pass through the input string.
+  ## Same as `replace<#replace,string,string,string>`_, but specialized for
+  ## doing multiple replacements in a single pass through the input string.
+  ##
+  ## `multiReplace` scans the input string from left to right and replaces the
+  ## matching substrings in the same order as passed in the argument list.
   ##
-  ## `multiReplace` performs all replacements in a single pass, this means it
-  ## can be used to swap the occurrences of "a" and "b", for instance.
+  ## The implications of the order of scanning the string and matching the
+  ## replacements:
+  ##   - In case of multiple matches at a given position, the earliest
+  ##     replacement is applied.
+  ##   - Overlaps are not handled. After performing a replacement, the scan
+  ##     continues from the character after the matched substring. If the
+  ##     resulting string then contains a possible match starting in a newly
+  ##     placed substring, the additional replacement is not performed.
   ##
   ## If the resulting string is not longer than the original input string,
   ## only a single memory allocation is required.
   ##
-  ## The order of the replacements does matter. Earlier replacements are
-  ## preferred over later replacements in the argument list.
+  runnableExamples:
+    # Swapping occurrences of 'a' and 'b':
+    doAssert multireplace("abba", [("a", "b"), ("b", "a")]) == "baab"
+
+    # The second replacement ("ab") is matched and performed first, the scan then
+    # continues from 'c', so the "bc" replacement is never matched and thus skipped.
+    doAssert multireplace("abc", [("bc", "x"), ("ab", "_b")]) == "_bc"
   result = newStringOfCap(s.len)
   var i = 0
   var fastChk: set[char] = {}
@@ -2373,8 +2454,8 @@ func validIdentifier*(s: string): bool {.rtl, extern: "nsuValidIdentifier".} =
 
 # floating point formatting:
 when not defined(js):
-  func c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
-                                     importc: "sprintf", varargs.}
+  func c_snprintf(buf: cstring, n: csize_t, frmt: cstring): cint {.header: "<stdio.h>",
+                                     importc: "snprintf", varargs.}
 
 type
   FloatFormatMode* = enum
@@ -2401,60 +2482,63 @@ func formatBiggestFloat*(f: BiggestFloat, format: FloatFormatMode = ffDefault,
     doAssert x.formatBiggestFloat() == "123.4560000000000"
     doAssert x.formatBiggestFloat(ffDecimal, 4) == "123.4560"
     doAssert x.formatBiggestFloat(ffScientific, 2) == "1.23e+02"
-  when defined(js):
-    var precision = precision
-    if precision == -1:
-      # use the same default precision as c_sprintf
-      precision = 6
-    var res: cstring
-    case format
-    of ffDefault:
-      {.emit: "`res` = `f`.toString();".}
-    of ffDecimal:
-      {.emit: "`res` = `f`.toFixed(`precision`);".}
-    of ffScientific:
-      {.emit: "`res` = `f`.toExponential(`precision`);".}
-    result = $res
-    if 1.0 / f == -Inf:
-      # JavaScript removes the "-" from negative Zero, add it back here
-      result = "-" & $res
-    for i in 0 ..< result.len:
-      # Depending on the locale either dot or comma is produced,
-      # but nothing else is possible:
-      if result[i] in {'.', ','}: result[i] = decimalSep
+  when nimvm:
+    discard "implemented in the vmops"
   else:
-    const floatFormatToChar: array[FloatFormatMode, char] = ['g', 'f', 'e']
-    var
-      frmtstr {.noinit.}: array[0..5, char]
-      buf {.noinit.}: array[0..2500, char]
-      L: cint
-    frmtstr[0] = '%'
-    if precision >= 0:
-      frmtstr[1] = '#'
-      frmtstr[2] = '.'
-      frmtstr[3] = '*'
-      frmtstr[4] = floatFormatToChar[format]
-      frmtstr[5] = '\0'
-      L = c_sprintf(cast[cstring](addr buf), cast[cstring](addr frmtstr), precision, f)
+    when defined(js):
+      var precision = precision
+      if precision == -1:
+        # use the same default precision as c_snprintf
+        precision = 6
+      var res: cstring
+      case format
+      of ffDefault:
+        {.emit: "`res` = `f`.toString();".}
+      of ffDecimal:
+        {.emit: "`res` = `f`.toFixed(`precision`);".}
+      of ffScientific:
+        {.emit: "`res` = `f`.toExponential(`precision`);".}
+      result = $res
+      if 1.0 / f == -Inf:
+        # JavaScript removes the "-" from negative Zero, add it back here
+        result = "-" & $res
+      for i in 0 ..< result.len:
+        # Depending on the locale either dot or comma is produced,
+        # but nothing else is possible:
+        if result[i] in {'.', ','}: result[i] = decimalSep
     else:
-      frmtstr[1] = floatFormatToChar[format]
-      frmtstr[2] = '\0'
-      L = c_sprintf(cast[cstring](addr buf), cast[cstring](addr frmtstr), f)
-    result = newString(L)
-    for i in 0 ..< L:
-      # Depending on the locale either dot or comma is produced,
-      # but nothing else is possible:
-      if buf[i] in {'.', ','}: result[i] = decimalSep
-      else: result[i] = buf[i]
-    when defined(windows):
-      # VS pre 2015 violates the C standard: "The exponent always contains at
-      # least two digits, and only as many more digits as necessary to
-      # represent the exponent." [C11 §7.21.6.1]
-      # The following post-processing fixes this behavior.
-      if result.len > 4 and result[^4] == '+' and result[^3] == '0':
-        result[^3] = result[^2]
-        result[^2] = result[^1]
-        result.setLen(result.len - 1)
+      const floatFormatToChar: array[FloatFormatMode, char] = ['g', 'f', 'e']
+      var
+        frmtstr {.noinit.}: array[0..5, char]
+        buf {.noinit.}: array[0..2500, char]
+        L: cint
+      frmtstr[0] = '%'
+      if precision >= 0:
+        frmtstr[1] = '#'
+        frmtstr[2] = '.'
+        frmtstr[3] = '*'
+        frmtstr[4] = floatFormatToChar[format]
+        frmtstr[5] = '\0'
+        L = c_snprintf(cast[cstring](addr buf), csize_t(2501), cast[cstring](addr frmtstr), precision, f)
+      else:
+        frmtstr[1] = floatFormatToChar[format]
+        frmtstr[2] = '\0'
+        L = c_snprintf(cast[cstring](addr buf), csize_t(2501), cast[cstring](addr frmtstr), f)
+      result = newString(L)
+      for i in 0 ..< L:
+        # Depending on the locale either dot or comma is produced,
+        # but nothing else is possible:
+        if buf[i] in {'.', ','}: result[i] = decimalSep
+        else: result[i] = buf[i]
+      when defined(windows):
+        # VS pre 2015 violates the C standard: "The exponent always contains at
+        # least two digits, and only as many more digits as necessary to
+        # represent the exponent." [C11 §7.21.6.1]
+        # The following post-processing fixes this behavior.
+        if result.len > 4 and result[^4] == '+' and result[^3] == '0':
+          result[^3] = result[^2]
+          result[^2] = result[^1]
+          result.setLen(result.len - 1)
 
 func formatFloat*(f: float, format: FloatFormatMode = ffDefault,
                   precision: range[-1..32] = 16; decimalSep = '.'): string {.
@@ -2587,13 +2671,13 @@ func formatEng*(f: BiggestFloat,
   ## decimal point or (if `trim` is true) the maximum number of digits to be
   ## shown.
   ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##    formatEng(0, 2, trim=false) == "0.00"
   ##    formatEng(0, 2) == "0"
   ##    formatEng(0.053, 0) == "53e-3"
   ##    formatEng(52731234, 2) == "52.73e6"
   ##    formatEng(-52731234, 2) == "-52.73e6"
+  ##    ```
   ##
   ## If `siPrefix` is set to true, the number will be displayed with the SI
   ## prefix corresponding to the exponent. For example 4100 will be displayed
@@ -2608,8 +2692,7 @@ func formatEng*(f: BiggestFloat,
   ## different to appending the unit to the result as the location of the space
   ## is altered depending on whether there is an exponent.
   ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##    formatEng(4100, siPrefix=true, unit="V") == "4.1 kV"
   ##    formatEng(4.1, siPrefix=true, unit="V") == "4.1 V"
   ##    formatEng(4.1, siPrefix=true) == "4.1" # Note lack of space
@@ -2619,6 +2702,7 @@ func formatEng*(f: BiggestFloat,
   ##    formatEng(4100) == "4.1e3"
   ##    formatEng(4100, unit="V") == "4.1e3 V"
   ##    formatEng(4100, unit="", useUnitSpace=true) == "4.1e3 " # Space with useUnitSpace=true
+  ##    ```
   ##
   ## `decimalSep` is used as the decimal separator.
   ##
@@ -2782,13 +2866,15 @@ func `%`*(formatstr: string, a: openArray[string]): string {.rtl,
   ##
   ## This is best explained by an example:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   "$1 eats $2." % ["The cat", "fish"]
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   "The cat eats fish."
+  ##   ```
   ##
   ## The substitution variables (the thing after the `$`) are enumerated
   ## from 1 to `a.len`.
@@ -2796,21 +2882,24 @@ func `%`*(formatstr: string, a: openArray[string]): string {.rtl,
   ## The notation `$#` can be used to refer to the next substitution
   ## variable:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   "$# eats $#." % ["The cat", "fish"]
+  ##   ```
   ##
   ## Substitution variables can also be words (that is
   ## `[A-Za-z_]+[A-Za-z0-9_]*`) in which case the arguments in `a` with even
   ## indices are keys and with odd indices are the corresponding values.
   ## An example:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   "$animal eats $food." % ["animal", "The cat", "food", "fish"]
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   "The cat eats fish."
+  ##   ```
   ##
   ## The variables are compared with `cmpIgnoreStyle`. `ValueError` is
   ## raised if an ill-formed format string has been passed to the `%` operator.
@@ -2908,13 +2997,14 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
   ## Substrings are separated by a substring containing only `seps`.
   ## Example:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   for word in tokenize("  this is an  example  "):
   ##     writeLine(stdout, word)
+  ##   ```
   ##
   ## Results in:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   ("  ", true)
   ##   ("this", false)
   ##   (" ", true)
@@ -2924,6 +3014,7 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
   ##   ("  ", true)
   ##   ("example", false)
   ##   ("  ", true)
+  ##   ```
   var i = 0
   while true:
     var j = i
diff --git a/lib/pure/sugar.nim b/lib/pure/sugar.nim
index d8e00d1f8..90ba20c13 100644
--- a/lib/pure/sugar.nim
+++ b/lib/pure/sugar.nim
@@ -11,7 +11,7 @@
 ## macro system.
 
 import std/private/since
-import macros
+import std/macros
 
 proc checkPragma(ex, prag: var NimNode) =
   since (1, 3):
@@ -203,7 +203,7 @@ proc freshIdentNodes(ast: NimNode): NimNode =
   # see also https://github.com/nim-lang/Nim/pull/8531#issuecomment-410436458
   proc inspect(node: NimNode): NimNode =
     case node.kind:
-    of nnkIdent, nnkSym:
+    of nnkIdent, nnkSym, nnkOpenSymChoice, nnkClosedSymChoice, nnkOpenSym:
       result = ident($node)
     of nnkEmpty, nnkLiterals:
       result = node
@@ -345,9 +345,10 @@ proc collectImpl(init, body: NimNode): NimNode {.since: (1, 1).} =
   let res = genSym(nskVar, "collectResult")
   var bracketExpr: NimNode
   if init != nil:
-    expectKind init, {nnkCall, nnkIdent, nnkSym}
+    expectKind init, {nnkCall, nnkIdent, nnkSym, nnkClosedSymChoice, nnkOpenSymChoice, nnkOpenSym}
     bracketExpr = newTree(nnkBracketExpr,
-      if init.kind == nnkCall: freshIdentNodes(init[0]) else: freshIdentNodes(init))
+      if init.kind in {nnkCall, nnkClosedSymChoice, nnkOpenSymChoice, nnkOpenSym}:
+        freshIdentNodes(init[0]) else: freshIdentNodes(init))
   else:
     bracketExpr = newTree(nnkBracketExpr)
   let (resBody, keyType, valueType) = trans(body, res, bracketExpr)
diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim
index daf470b09..53b3d61da 100644
--- a/lib/pure/terminal.nim
+++ b/lib/pure/terminal.nim
@@ -58,13 +58,13 @@ runnableExamples("-r:off"):
 
   stdout.styledWriteLine(fgRed, "red text ", styleBright, "bold red", fgDefault, " bold text")
 
-import macros
-import strformat
-from strutils import toLowerAscii, `%`
-import colors
+import std/macros
+import std/strformat
+from std/strutils import toLowerAscii, `%`, parseInt
+import std/colors
 
 when defined(windows):
-  import winlean
+  import std/winlean
 
 when defined(nimPreviewSlimSystem):
   import std/[syncio, assertions]
@@ -96,10 +96,11 @@ const
   fgPrefix = "\e[38;2;"
   bgPrefix = "\e[48;2;"
   ansiResetCode* = "\e[0m"
+  getPos = "\e[6n"
   stylePrefix = "\e["
 
 when defined(windows):
-  import winlean, os
+  import std/[winlean, os]
 
   const
     DUPLICATE_SAME_ACCESS = 2
@@ -220,6 +221,9 @@ when defined(windows):
       raiseOSError(osLastError())
     return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y))
 
+  proc getCursorPos*(): tuple [x, y: int] {.raises: [ValueError, IOError, OSError].} =
+    return getCursorPos(getStdHandle(STD_OUTPUT_HANDLE))
+
   proc setCursorPos(h: Handle, x, y: int) =
     var c: COORD
     c.x = int16(x)
@@ -253,7 +257,7 @@ when defined(windows):
     if f == stderr: term.hStderr else: term.hStdout
 
 else:
-  import termios, posix, os, parseutils
+  import std/[termios, posix, os, parseutils]
 
   proc setRaw(fd: FileHandle, time: cint = TCSAFLUSH) =
     var mode: Termios
@@ -267,6 +271,48 @@ else:
     mode.c_cc[VTIME] = 0.cuchar
     discard fd.tcSetAttr(time, addr mode)
 
+  proc getCursorPos*(): tuple [x, y: int] {.raises: [ValueError, IOError].} =
+    ## Returns cursor position (x, y)
+    ## writes to stdout and expects the terminal to respond via stdin
+    var
+      xStr = ""
+      yStr = ""
+      ch: char
+      ct: int
+      readX = false
+
+    # use raw mode to ask terminal for cursor position
+    let fd = getFileHandle(stdin)
+    var oldMode: Termios
+    discard fd.tcGetAttr(addr oldMode)
+    fd.setRaw()
+    stdout.write(getPos)
+    flushFile(stdout)
+
+    try:
+      # parse response format: [yyy;xxxR
+      while true:
+        let n = readBuffer(stdin, addr ch, 1)
+        if n == 0 or ch == 'R':
+          if xStr == "" or yStr == "":
+            raise newException(ValueError, "Got character position message that was missing data")
+          break
+        ct += 1
+        if ct > 16:
+          raise newException(ValueError, "Got unterminated character position message from terminal")
+        if ch == ';':
+          readX = true
+        elif ch in {'0'..'9'}:
+          if readX:
+            xStr.add(ch)
+          else:
+            yStr.add(ch)
+    finally:
+      # restore previous terminal mode
+      discard fd.tcSetAttr(TCSADRAIN, addr oldMode)
+
+    return (parseInt(xStr), parseInt(yStr))
+
   proc terminalWidthIoctl*(fds: openArray[int]): int =
     ## Returns terminal width from first fd that supports the ioctl.
 
@@ -291,25 +337,57 @@ else:
     ## Returns some reasonable terminal width from either standard file
     ## descriptors, controlling terminal, environment variables or tradition.
 
-    var w = terminalWidthIoctl([0, 1, 2]) #Try standard file descriptors
+    # POSIX environment variable takes precendence.
+    # _COLUMNS_: This variable shall represent a decimal integer >0 used
+    # to indicate the user's preferred width in column positions for
+    # the terminal screen or window. If this variable is unset or null,
+    # the implementation determines the number of columns, appropriate
+    # for the terminal or window, in an unspecified manner.
+    # When COLUMNS is set, any terminal-width information implied by TERM
+    # is overridden. Users and conforming applications should not set COLUMNS
+    # unless they wish to override the system selection and produce output
+    # unrelated to the terminal characteristics.
+    # See POSIX Base Definitions Section 8.1 Environment Variable Definition
+
+    var w: int
+    var s = getEnv("COLUMNS") # Try standard env var
+    if len(s) > 0 and parseSaturatedNatural(s, w) > 0 and w > 0:
+      return w
+    w = terminalWidthIoctl([0, 1, 2]) # Try standard file descriptors
     if w > 0: return w
-    var cterm = newString(L_ctermid) #Try controlling tty
+    var cterm = newString(L_ctermid) # Try controlling tty
     var fd = open(ctermid(cstring(cterm)), O_RDONLY)
     if fd != -1:
       w = terminalWidthIoctl([int(fd)])
     discard close(fd)
     if w > 0: return w
-    var s = getEnv("COLUMNS") #Try standard env var
-    if len(s) > 0 and parseInt(s, w) > 0 and w > 0:
-      return w
-    return 80 #Finally default to venerable value
+    return 80 # Finally default to venerable value
 
   proc terminalHeight*(): int =
     ## Returns some reasonable terminal height from either standard file
     ## descriptors, controlling terminal, environment variables or tradition.
     ## Zero is returned if the height could not be determined.
 
-    var h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
+    # POSIX environment variable takes precendence.
+    # _LINES_: This variable shall represent a decimal integer >0 used
+    # to indicate the user's preferred number of lines on a page or
+    # the vertical screen or window size in lines. A line in this case
+    # is a vertical measure large enough to hold the tallest character
+    # in the character set being displayed. If this variable is unset or null,
+    # the implementation determines the number of lines, appropriate
+    # for the terminal or window (size, terminal baud rate, and so on),
+    # in an unspecified manner.
+    # When LINES is set, any terminal-height information implied by TERM
+    # is overridden. Users and conforming applications should not set LINES
+    # unless they wish to override the system selection and produce output
+    # unrelated to the terminal characteristics.
+    # See POSIX Base Definitions Section 8.1 Environment Variable Definition
+
+    var h: int
+    var s = getEnv("LINES") # Try standard env var
+    if len(s) > 0 and parseSaturatedNatural(s, h) > 0 and h > 0:
+      return h
+    h = terminalHeightIoctl([0, 1, 2]) # Try standard file descriptors
     if h > 0: return h
     var cterm = newString(L_ctermid) # Try controlling tty
     var fd = open(ctermid(cstring(cterm)), O_RDONLY)
@@ -317,9 +395,6 @@ else:
       h = terminalHeightIoctl([int(fd)])
     discard close(fd)
     if h > 0: return h
-    var s = getEnv("LINES") # Try standard env var
-    if len(s) > 0 and parseInt(s, h) > 0 and h > 0:
-      return h
     return 0 # Could not determine height
 
 proc terminalSize*(): tuple[w, h: int] =
@@ -847,7 +922,7 @@ when defined(windows):
     stdout.write "\n"
 
 else:
-  import termios
+  import std/termios
 
   proc readPasswordFromStdin*(prompt: string, password: var string):
                             bool {.tags: [ReadIOEffect, WriteIOEffect].} =
@@ -903,7 +978,7 @@ proc isTrueColorSupported*(): bool =
   return getTerminal().trueColorIsSupported
 
 when defined(windows):
-  import os
+  import std/os
 
 proc enableTrueColors*() =
   ## Enables true color.
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 7cd47596d..e59153455 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -20,7 +20,7 @@
   Examples
   ========
 
-  .. code-block:: nim
+    ```nim
     import std/[times, os]
     # Simple benchmarking
     let time = cpuTime()
@@ -37,6 +37,7 @@
     # Arithmetic using TimeInterval
     echo "One year from now      : ", now() + 1.years
     echo "One month from now     : ", now() + 1.months
+    ```
 
   Parsing and Formatting Dates
   ============================
@@ -44,10 +45,10 @@
   The `DateTime` type can be parsed and formatted using the different
   `parse` and `format` procedures.
 
-  .. code-block:: nim
-
+    ```nim
     let dt = parse("2000-01-01", "yyyy-MM-dd")
     echo dt.format("yyyy-MM-dd")
+    ```
 
   The different format patterns that are supported are documented below.
 
@@ -62,6 +63,8 @@
                                                                                                   | `Monday -> Mon`
   `dddd`       Full string for the day of the week.                                               | `Saturday -> Saturday`
                                                                                                   | `Monday -> Monday`
+  `GG`         The last two digits of the Iso Week-Year                                           | `30/12/2012 -> 13`
+  `GGGG`       The Iso week-calendar year padded to four digits                                   | `30/12/2012 -> 2013`
   `h`          The hours in one digit if possible. Ranging from 1-12.                             | `5pm -> 5`
                                                                                                   | `2am -> 2`
   `hh`         The hours in two digits always. If the hour is one digit, 0 is prepended.          | `5pm -> 05`
@@ -104,6 +107,10 @@
                                                                                                   | `24 AD -> 24`
                                                                                                   | `24 BC -> -23`
                                                                                                   | `12345 AD -> 12345`
+  `V`          The Iso Week-Number as one or two digits                                           | `3/2/2012 -> 5`
+                                                                                                  | `1/4/2012 -> 13`
+  `VV`         The Iso Week-Number as two digits always. 0 is prepended if one digit.             | `3/2/2012 -> 05`
+                                                                                                  | `1/4/2012 -> 13`
   `z`          Displays the timezone offset from UTC.                                             | `UTC+7 -> +7`
                                                                                                   | `UTC-5 -> -5`
   `zz`         Same as above but with leading 0.                                                  | `UTC+7 -> +07`
@@ -124,9 +131,10 @@
   ===========  =================================================================================  ==============================================
 
   Other strings can be inserted by putting them in `''`. For example
-  `hh'->'mm` will give `01->56`.  The following characters can be
-  inserted without quoting them: `:` `-` `(` `)` `/` `[` `]`
-  `,`. A literal `'` can be specified with `''`.
+  `hh'->'mm` will give `01->56`.  In addition to spaces,
+  the following characters can be inserted without quoting them:
+  `:` `-` `,` `.` `(` `)` `/` `[` `]`.
+  A literal `'` can be specified with `''`.
 
   However you don't need to necessarily separate format patterns, as an
   unambiguous format string like `yyyyMMddhhmmss` is also valid (although
@@ -196,7 +204,7 @@
   * `monotimes module <monotimes.html>`_
 ]##
 
-import strutils, math, options
+import std/[strutils, math, options]
 
 import std/private/since
 include "system/inclrtl"
@@ -206,7 +214,7 @@ when defined(nimPreviewSlimSystem):
 
 
 when defined(js):
-  import jscore
+  import std/jscore
 
   # This is really bad, but overflow checks are broken badly for
   # ints on the JS backend. See #6752.
@@ -230,7 +238,7 @@ when defined(js):
   {.pop.}
 
 elif defined(posix):
-  import posix
+  import std/posix
 
   type CTime = posix.Time
 
@@ -239,7 +247,7 @@ elif defined(posix):
       {.importc: "gettimeofday", header: "<sys/time.h>", sideEffect.}
 
 elif defined(windows):
-  import winlean, std/time_t
+  import std/winlean, std/time_t
 
   type
     CTime = time_t.Time
@@ -408,6 +416,16 @@ const unitWeights: array[FixedTimeUnit, int64] = [
   7 * secondsInDay * 1e9.int64,
 ]
 
+when (NimMajor, NimMinor) >= (1, 4):
+  # Newer versions of Nim don't track defects
+  {.pragma: parseFormatRaises, raises: [TimeParseError, TimeFormatParseError].}
+  {.pragma: parseRaises, raises: [TimeParseError].}
+else:
+  # Still track when using older versions
+  {.pragma: parseFormatRaises, raises: [TimeParseError, TimeFormatParseError, Defect].}
+  {.pragma: parseRaises, raises: [TimeParseError, Defect].}
+
+
 #
 # Helper procs
 #
@@ -527,7 +545,7 @@ proc getDayOfWeek*(monthday: MonthdayRange, month: Month, year: int): WeekDay
   assertValidDate monthday, month, year
   # 1970-01-01 is a Thursday, we adjust to the previous Monday
   let days = toEpochDay(monthday, month, year) - 3
-  let weeks = floorDiv(days, 7)
+  let weeks = floorDiv(days, 7'i64)
   let wd = days - weeks * 7
   # The value of d is 0 for a Sunday, 1 for a Monday, 2 for a Tuesday, etc.
   # so we must correct for the WeekDay type.
@@ -592,8 +610,8 @@ proc stringifyUnit(value: int | int64, unit: TimeUnit): string =
   ## Stringify time unit with it's name, lowercased
   let strUnit = $unit
   result = ""
-  result.add($value)
-  result.add(" ")
+  result.addInt value
+  result.add ' '
   if abs(value) != 1:
     result.add(strUnit.toLowerAscii())
   else:
@@ -636,11 +654,10 @@ template eqImpl(a: Duration|Time, b: Duration|Time): bool =
 
 const DurationZero* = Duration() ## \
   ## Zero value for durations. Useful for comparisons.
-  ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   doAssert initDuration(seconds = 1) > DurationZero
   ##   doAssert initDuration(seconds = 0) == DurationZero
+  ##   ```
 
 proc initDuration*(nanoseconds, microseconds, milliseconds,
                    seconds, minutes, hours, days, weeks: int64 = 0): Duration =
@@ -953,27 +970,33 @@ proc toWinTime*(t: Time): int64 =
   ## since `1601-01-01T00:00:00Z`).
   result = t.seconds * rateDiff + epochDiff + t.nanosecond div 100
 
+proc getTimeImpl(typ: typedesc[Time]): Time =
+  discard "implemented in the vm"
+
 proc getTime*(): Time {.tags: [TimeEffect], benign.} =
   ## Gets the current time as a `Time` with up to nanosecond resolution.
-  when defined(js):
-    let millis = newDate().getTime()
-    let seconds = convert(Milliseconds, Seconds, millis)
-    let nanos = convert(Milliseconds, Nanoseconds,
-      millis mod convert(Seconds, Milliseconds, 1).int)
-    result = initTime(seconds, nanos)
-  elif defined(macosx):
-    var a {.noinit.}: Timeval
-    gettimeofday(a)
-    result = initTime(a.tv_sec.int64,
-                      convert(Microseconds, Nanoseconds, a.tv_usec.int))
-  elif defined(posix):
-    var ts {.noinit.}: Timespec
-    discard clock_gettime(CLOCK_REALTIME, ts)
-    result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
-  elif defined(windows):
-    var f {.noinit.}: FILETIME
-    getSystemTimeAsFileTime(f)
-    result = fromWinTime(rdFileTime(f))
+  when nimvm:
+    result = getTimeImpl(Time)
+  else:
+    when defined(js):
+      let millis = newDate().getTime()
+      let seconds = convert(Milliseconds, Seconds, millis)
+      let nanos = convert(Milliseconds, Nanoseconds,
+        millis mod convert(Seconds, Milliseconds, 1).int)
+      result = initTime(seconds, nanos)
+    elif defined(macosx):
+      var a {.noinit.}: Timeval
+      gettimeofday(a)
+      result = initTime(a.tv_sec.int64,
+                        convert(Microseconds, Nanoseconds, a.tv_usec.int))
+    elif defined(posix):
+      var ts {.noinit.}: Timespec
+      discard clock_gettime(CLOCK_REALTIME, ts)
+      result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
+    elif defined(windows):
+      var f {.noinit.}: FILETIME
+      getSystemTimeAsFileTime(f)
+      result = fromWinTime(rdFileTime(f))
 
 proc `-`*(a, b: Time): Duration {.operator, extern: "ntDiffTime".} =
   ## Computes the duration between two points in time.
@@ -1476,20 +1499,42 @@ proc `-=`*(a: var DateTime, b: Duration) =
   a = a - b
 
 proc getDateStr*(dt = now()): string {.rtl, extern: "nt$1", tags: [TimeEffect].} =
-  ## Gets the current local date as a string of the format `YYYY-MM-DD`.
+  ## Gets the current local date as a string of the format `YYYY-MM-dd`.
   runnableExamples:
     echo getDateStr(now() - 1.months)
   assertDateTimeInitialized dt
-  result = $dt.year & '-' & intToStr(dt.monthZero, 2) &
-    '-' & intToStr(dt.monthday, 2)
+  result = newStringOfCap(10)  # len("YYYY-MM-dd") == 10
+  result.addInt dt.year
+  result.add '-'
+  result.add intToStr(dt.monthZero, 2)
+  result.add '-'
+  result.add intToStr(dt.monthday, 2)
 
 proc getClockStr*(dt = now()): string {.rtl, extern: "nt$1", tags: [TimeEffect].} =
   ## Gets the current local clock time as a string of the format `HH:mm:ss`.
   runnableExamples:
     echo getClockStr(now() - 1.hours)
   assertDateTimeInitialized dt
-  result = intToStr(dt.hour, 2) & ':' & intToStr(dt.minute, 2) &
-    ':' & intToStr(dt.second, 2)
+  result = newStringOfCap(8)  # len("HH:mm:ss") == 8
+  result.add intToStr(dt.hour, 2)
+  result.add ':'
+  result.add intToStr(dt.minute, 2)
+  result.add ':'
+  result.add intToStr(dt.second, 2)
+
+
+#
+# Iso week forward declarations
+#
+
+proc initDateTime*(weekday: WeekDay, isoweek: IsoWeekRange, isoyear: IsoYear,
+                   hour: HourRange, minute: MinuteRange, second: SecondRange,
+                   nanosecond: NanosecondRange,
+                   zone: Timezone = local()): DateTime {.gcsafe, raises: [], tags: [], since: (1, 5).}
+
+proc initDateTime*(weekday: WeekDay, isoweek: IsoWeekRange, isoyear: IsoYear,
+                   hour: HourRange, minute: MinuteRange, second: SecondRange,
+                   zone: Timezone = local()): DateTime {.gcsafe, raises: [], tags: [], since: (1, 5).}
 
 #
 # TimeFormat
@@ -1521,6 +1566,9 @@ type
     year: Option[int]
     month: Option[int]
     monthday: Option[int]
+    isoyear: Option[int]
+    yearweek: Option[int]
+    weekday: Option[WeekDay]
     utcOffset: Option[int]
 
     # '0' as default for these work fine
@@ -1535,6 +1583,7 @@ type
 
   FormatPattern {.pure.} = enum
     d, dd, ddd, dddd
+    GG, GGGG
     h, hh, H, HH
     m, mm, M, MM, MMM, MMMM
     s, ss
@@ -1544,6 +1593,7 @@ type
     YYYY
     uuuu
     UUUU
+    V, VV
     z, zz, zzz, zzzz
     ZZZ, ZZZZ
     g
@@ -1582,7 +1632,7 @@ const
         "Sunday"],
   )
 
-  FormatLiterals = {' ', '-', '/', ':', '(', ')', '[', ']', ','}
+  FormatLiterals = {' ', '-', '/', ':', '(', ')', '[', ']', ',', '.'}
 
 proc `$`*(f: TimeFormat): string =
   ## Returns the format string that was used to construct `f`.
@@ -1672,6 +1722,8 @@ proc stringToPattern(str: string): FormatPattern =
   of "dd": result = dd
   of "ddd": result = ddd
   of "dddd": result = dddd
+  of "GG": result = GG
+  of "GGGG": result = GGGG
   of "h": result = h
   of "hh": result = hh
   of "H": result = H
@@ -1694,6 +1746,8 @@ proc stringToPattern(str: string): FormatPattern =
   of "YYYY": result = YYYY
   of "uuuu": result = uuuu
   of "UUUU": result = UUUU
+  of "V": result = V
+  of "VV": result = VV
   of "z": result = z
   of "zz": result = zz
   of "zzz": result = zzz
@@ -1743,6 +1797,10 @@ proc formatPattern(dt: DateTime, pattern: FormatPattern, result: var string,
     result.add loc.ddd[dt.weekday]
   of dddd:
     result.add loc.dddd[dt.weekday]
+  of GG:
+    result.add (dt.getIsoWeekAndYear.isoyear.int mod 100).intToStr(2)
+  of GGGG:
+    result.add $dt.getIsoWeekAndYear.isoyear
   of h:
     result.add(
       if dt.hour == 0: "12"
@@ -1806,6 +1864,10 @@ proc formatPattern(dt: DateTime, pattern: FormatPattern, result: var string,
       result.add '+' & $year
   of UUUU:
     result.add $dt.year
+  of V:
+    result.add $dt.getIsoWeekAndYear.isoweek
+  of VV:
+    result.add dt.getIsoWeekAndYear.isoweek.intToStr(2)
   of z, zz, zzz, zzzz, ZZZ, ZZZZ:
     if dt.timezone != nil and dt.timezone.name == "Etc/UTC":
       result.add 'Z'
@@ -1860,18 +1922,30 @@ proc parsePattern(input: string, pattern: FormatPattern, i: var int,
     result = monthday in MonthdayRange
   of ddd:
     result = false
-    for v in loc.ddd:
+    for d, v in loc.ddd:
       if input.substr(i, i+v.len-1).cmpIgnoreCase(v) == 0:
+        parsed.weekday = some(d.WeekDay)
         result = true
         i.inc v.len
         break
   of dddd:
     result = false
-    for v in loc.dddd:
+    for d, v in loc.dddd:
       if input.substr(i, i+v.len-1).cmpIgnoreCase(v) == 0:
+        parsed.weekday = some(d.WeekDay)
         result = true
         i.inc v.len
         break
+  of GG:
+    # Assumes current century
+    var isoyear = takeInt(2..2)
+    var thisCen = now().year div 100
+    parsed.isoyear = some(thisCen*100 + isoyear)
+    result = isoyear > 0
+  of GGGG:
+    let isoyear = takeInt(1..high(int))
+    parsed.isoyear = some(isoyear)
+    result = isoyear > 0
   of h, H:
     parsed.hour = takeInt(1..2)
     result = parsed.hour in HourRange
@@ -1962,6 +2036,14 @@ proc parsePattern(input: string, pattern: FormatPattern, i: var int,
     parsed.year = some(year)
   of UUUU:
     parsed.year = some(takeInt(1..high(int), allowSign = true))
+  of V:
+    let yearweek = takeInt(1..2)
+    parsed.yearweek = some(yearweek)
+    result = yearweek in IsoWeekRange
+  of VV:
+    let yearweek = takeInt(2..2)
+    parsed.yearweek = some(yearweek)
+    result = yearweek in IsoWeekRange
   of z, zz, zzz, zzzz, ZZZ, ZZZZ:
     case input[i]
     of '+', '-':
@@ -2008,7 +2090,7 @@ proc parsePattern(input: string, pattern: FormatPattern, i: var int,
       i.inc 2
     else:
       result = false
-  of Lit: doAssert false, "Can't happen"
+  of Lit: raiseAssert "Can't happen"
 
 proc toDateTime(p: ParsedTime, zone: Timezone, f: TimeFormat,
                 input: string): DateTime =
@@ -2063,6 +2145,38 @@ proc toDateTime(p: ParsedTime, zone: Timezone, f: TimeFormat,
     result = (dateTime(year, month, monthday, hour, minute, second, nanosecond, utc()).toTime +
       initDuration(seconds = p.utcOffset.get())).inZone(zone)
 
+proc toDateTimeByWeek(p: ParsedTime, zone: Timezone, f: TimeFormat,
+                   input: string): DateTime =
+  var isoyear = p.isoyear.get(0)
+  var yearweek = p.yearweek.get(1)
+  var weekday = p.weekday.get(dMon)
+
+  if p.amPm != apUnknown:
+    raiseParseException(f, input, "Parsing iso weekyear dates does not support am/pm")
+
+  if p.year.isSome:
+    raiseParseException(f, input, "Use iso-year GG or GGGG as year with iso week number")
+
+  if p.month.isSome:
+    raiseParseException(f, input, "Use either iso week number V or VV or month")
+
+  if p.monthday.isSome:
+    raiseParseException(f, input, "Use weekday ddd or dddd as day with with iso week number")
+
+  if p.isoyear.isNone:
+    raiseParseException(f, input, "Need iso-year with week number")
+
+  let hour = p.hour
+  let minute = p.minute
+  let second = p.second
+  let nanosecond = p.nanosecond
+
+  if p.utcOffset.isNone:
+    result = initDateTime(weekday, yearweek.IsoWeekRange, isoyear.IsoYear, hour, minute, second, nanosecond, zone)
+  else:
+    result = (initDateTime(weekday, yearweek.IsoWeekRange, isoyear.IsoYear, hour, minute, second, nanosecond, zone).toTime +
+      initDuration(seconds = p.utcOffset.get())).inZone(zone)
+
 proc format*(dt: DateTime, f: TimeFormat,
     loc: DateTimeLocale = DefaultLocale): string {.raises: [].} =
   ## Format `dt` using the format specified by `f`.
@@ -2103,7 +2217,7 @@ proc format*(dt: DateTime, f: static[string]): string {.raises: [].} =
   const f2 = initTimeFormat(f)
   result = dt.format(f2)
 
-proc formatValue*(result: var string; value: DateTime, specifier: string) =
+proc formatValue*(result: var string; value: DateTime | Time, specifier: string) =
   ## adapter for strformat. Not intended to be called directly.
   result.add format(value,
     if specifier.len == 0: "yyyy-MM-dd'T'HH:mm:sszzz" else: specifier)
@@ -2127,13 +2241,8 @@ proc format*(time: Time, f: static[string], zone: Timezone = local()): string
   const f2 = initTimeFormat(f)
   result = time.inZone(zone).format(f2)
 
-template formatValue*(result: var string; value: Time, specifier: string) =
-  ## adapter for `strformat`. Not intended to be called directly.
-  result.add format(value, specifier)
-
 proc parse*(input: string, f: TimeFormat, zone: Timezone = local(),
-    loc: DateTimeLocale = DefaultLocale): DateTime
-    {.raises: [TimeParseError, Defect].} =
+    loc: DateTimeLocale = DefaultLocale): DateTime {.parseRaises.} =
   ## Parses `input` as a `DateTime` using the format specified by `f`.
   ## If no UTC offset was parsed, then `input` is assumed to be specified in
   ## the `zone` timezone. If a UTC offset was parsed, the result will be
@@ -2173,11 +2282,15 @@ proc parse*(input: string, f: TimeFormat, zone: Timezone = local(),
     raiseParseException(f, input,
                             "Parsing ended but there was still patterns remaining")
 
-  result = toDateTime(parsed, zone, f, input)
+  if parsed.yearweek.isSome:
+    result = toDateTimeByWeek(parsed, zone, f, input)
+  elif parsed.isoyear.isSome:
+    raiseParseException(f, input, "Iso year GG or GGGG require iso week V or VV")
+  else:
+    result = toDateTime(parsed, zone, f, input)
 
 proc parse*(input, f: string, tz: Timezone = local(),
-    loc: DateTimeLocale = DefaultLocale): DateTime
-    {.raises: [TimeParseError, TimeFormatParseError, Defect].} =
+    loc: DateTimeLocale = DefaultLocale): DateTime {.parseFormatRaises.} =
   ## Shorthand for constructing a `TimeFormat` and using it to parse
   ## `input` as a `DateTime`.
   ##
@@ -2190,14 +2303,12 @@ proc parse*(input, f: string, tz: Timezone = local(),
   result = input.parse(dtFormat, tz, loc = loc)
 
 proc parse*(input: string, f: static[string], zone: Timezone = local(),
-    loc: DateTimeLocale = DefaultLocale):
-  DateTime {.raises: [TimeParseError, Defect].} =
+    loc: DateTimeLocale = DefaultLocale): DateTime {.parseRaises.} =
   ## Overload that validates `f` at compile time.
   const f2 = initTimeFormat(f)
   result = input.parse(f2, zone, loc = loc)
 
-proc parseTime*(input, f: string, zone: Timezone): Time
-    {.raises: [TimeParseError, TimeFormatParseError, Defect].} =
+proc parseTime*(input, f: string, zone: Timezone): Time {.parseFormatRaises.} =
   ## Shorthand for constructing a `TimeFormat` and using it to parse
   ## `input` as a `DateTime`, then converting it a `Time`.
   ##
@@ -2209,7 +2320,7 @@ proc parseTime*(input, f: string, zone: Timezone): Time
   parse(input, f, zone).toTime()
 
 proc parseTime*(input: string, f: static[string], zone: Timezone): Time
-    {.raises: [TimeParseError, Defect].} =
+    {.parseRaises.} =
   ## Overload that validates `format` at compile time.
   const f2 = initTimeFormat(f)
   result = input.parse(f2, zone).toTime()
@@ -2638,13 +2749,13 @@ proc `-=`*(t: var Time, b: TimeInterval) =
   t = t - b
 
 #
-# Day of year
+# Iso week
 #
 
 proc initDateTime*(weekday: WeekDay, isoweek: IsoWeekRange, isoyear: IsoYear,
                    hour: HourRange, minute: MinuteRange, second: SecondRange,
                    nanosecond: NanosecondRange,
-                   zone: Timezone = local()): DateTime {.since: (1, 5).} =
+                   zone: Timezone = local()): DateTime {.raises: [], tags: [], since: (1, 5).} =
   ## Create a new `DateTime <#DateTime>`_ from a weekday and an ISO 8601 week number and year
   ## in the specified timezone.
   ##
@@ -2656,12 +2767,12 @@ proc initDateTime*(weekday: WeekDay, isoweek: IsoWeekRange, isoyear: IsoYear,
     assert initDateTime(2, mJan, 2021, 00, 00, 00) == initDateTime(dSat, 53, 2020.IsoYear, 00, 00, 00)
 
   # source https://webspace.science.uu.nl/~gent0113/calendar/isocalendar.htm
-  let d = isoweek * 7 + weekday.int - initDateTime(4, mJan, isoyear.int, 00, 00, 00).weekday.int - 4
+  let d = isoweek * 7 + weekday.int - initDateTime(4, mJan, isoyear.int, 00, 00, 00, zone).weekday.int - 4
   initDateTime(1, mJan, isoyear.int, hour, minute, second, nanosecond, zone) + initTimeInterval(days=d)
 
 proc initDateTime*(weekday: WeekDay, isoweek: IsoWeekRange, isoyear: IsoYear,
                    hour: HourRange, minute: MinuteRange, second: SecondRange,
-                   zone: Timezone = local()): DateTime {.since: (1, 5).} =
+                   zone: Timezone = local()): DateTime {.raises: [], tags: [], since: (1, 5).} =
   initDateTime(weekday, isoweek, isoyear, hour, minute, second, 0, zone)
 
 #
@@ -2677,7 +2788,9 @@ proc epochTime*(): float {.tags: [TimeEffect].} =
   ##
   ## .. warning:: Unsuitable for benchmarking (but still better than `now`),
   ##    use `monotimes.getMonoTime` or `cpuTime` instead, depending on the use case.
-  when defined(macosx):
+  when defined(js):
+    result = newDate().getTime() / 1000
+  elif defined(macosx):
     var a {.noinit.}: Timeval
     gettimeofday(a)
     result = toBiggestFloat(a.tv_sec.int64) + toBiggestFloat(
@@ -2694,8 +2807,6 @@ proc epochTime*(): float {.tags: [TimeEffect].} =
     var secs = i64 div rateDiff
     var subsecs = i64 mod rateDiff
     result = toFloat(int(secs)) + toFloat(int(subsecs)) * 0.0000001
-  elif defined(js):
-    result = newDate().getTime() / 1000
   else:
     {.error: "unknown OS".}
 
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index c20f9e645..78af84fdd 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -96,6 +96,23 @@ proc supportsCopyMem*(t: typedesc): bool {.magic: "TypeTrait".}
   ##
   ## Other languages name a type like these `blob`:idx:.
 
+proc hasDefaultValue*(t: typedesc): bool {.magic: "TypeTrait".} =
+  ## Returns true if `t` has a valid default value.
+  runnableExamples:
+    {.experimental: "strictNotNil".}
+    type
+      NilableObject = ref object
+        a: int
+      Object = NilableObject not nil
+      RequiresInit[T] = object
+        a {.requiresInit.}: T
+
+    assert hasDefaultValue(NilableObject)
+    assert not hasDefaultValue(Object)
+    assert hasDefaultValue(string)
+    assert not hasDefaultValue(var string)
+    assert not hasDefaultValue(RequiresInit[int])
+
 proc isNamedTuple*(T: typedesc): bool {.magic: "TypeTrait".} =
   ## Returns true for named tuples, false for any other type.
   runnableExamples:
@@ -113,6 +130,40 @@ template pointerBase*[T](_: typedesc[ptr T | ref T]): typedesc =
     assert (var s = "abc"; s[0].addr).typeof.pointerBase is char
   T
 
+proc rangeBase*(T: typedesc[range]): typedesc {.magic: "TypeTrait".} =
+  ## Returns the base type for range types, or the type itself otherwise.
+  ##
+  ## **See also:**
+  ## * `rangeBase template <#rangeBase.t,T>`_
+  runnableExamples:
+    type MyRange = range[0..5]
+    type MyEnum = enum a, b, c
+    type MyEnumRange = range[b..c]
+    doAssert rangeBase(MyRange) is int
+    doAssert rangeBase(MyEnumRange) is MyEnum
+    doAssert rangeBase(range['a'..'z']) is char
+
+template rangeBase*[T: range](a: T): untyped =
+  ## Overload of `rangeBase <#rangeBase,typedesc,static[bool]>`_ for values.
+  runnableExamples:
+    type MyRange = range[0..5]
+    type MyEnum = enum a, b, c
+    type MyEnumRange = range[b..c]
+    let x = MyRange(3)
+    doAssert rangeBase(x) is int
+    doAssert $typeof(rangeBase(x)) == "int"
+    doAssert rangeBase(x) == 3
+    let y: set[MyEnumRange] = {c}
+    for e in y:
+      doAssert rangeBase(e) is MyEnum
+      doAssert $typeof(rangeBase(e)) == "MyEnum"
+      doAssert rangeBase(e) == c
+    let z: seq[range['a'..'z']] = @['c']
+    doAssert rangeBase(z[0]) is char
+    doAssert $typeof(rangeBase(z[0])) == "char"
+    doAssert rangeBase(z[0]) == 'c'
+  rangeBase(typeof(T))(a)
+
 proc distinctBase*(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".} =
   ## Returns the base type for distinct types, or the type itself otherwise.
   ## If `recursive` is false, only the immediate distinct base will be returned.
@@ -187,7 +238,7 @@ since (1, 3, 5):
 
     typeof(block: (for ai in a: ai))
 
-import macros
+import std/macros
 
 macro enumLen*(T: typedesc[enum]): int =
   ## Returns the number of items in the enum `T`.
@@ -225,7 +276,7 @@ macro genericParamsImpl(T: typedesc): untyped =
         case ai.typeKind
         of ntyTypeDesc:
           ret = ai
-        of ntyStatic: doAssert false
+        of ntyStatic: raiseAssert "unreachable"
         else:
           # getType from a resolved symbol might return a typedesc symbol.
           # If so, use it directly instead of wrapping it in StaticParam.
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index 09233035f..8cbe117bb 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -464,7 +464,7 @@ proc `==`*(a, b: Rune): bool =
 
 include "includes/unicode_ranges"
 
-proc binarySearch(c: RuneImpl, tab: openArray[int], len, stride: int): int =
+proc binarySearch(c: RuneImpl, tab: openArray[int32], len, stride: int): int =
   var n = len
   var t = 0
   while n > 1:
@@ -836,9 +836,9 @@ proc toRunes*(s: openArray[char]): seq[Rune] =
 proc cmpRunesIgnoreCase*(a, b: openArray[char]): int {.rtl, extern: "nuc$1".} =
   ## Compares two UTF-8 strings and ignores the case. Returns:
   ##
-  ## | 0 if a == b
-  ## | < 0 if a < b
-  ## | > 0 if a > b
+  ## | `0` if a == b
+  ## | `< 0` if a < b
+  ## | `> 0` if a > b
   var i = 0
   var j = 0
   var ar, br: Rune
@@ -846,7 +846,12 @@ proc cmpRunesIgnoreCase*(a, b: openArray[char]): int {.rtl, extern: "nuc$1".} =
     # slow path:
     fastRuneAt(a, i, ar)
     fastRuneAt(b, j, br)
-    result = RuneImpl(toLower(ar)) - RuneImpl(toLower(br))
+    when sizeof(int) < 4:
+      const lo = low(int).int32
+      const hi = high(int).int32
+      result = clamp(RuneImpl(toLower(ar)) - RuneImpl(toLower(br)), lo, hi).int
+    else:
+      result = RuneImpl(toLower(ar)) - RuneImpl(toLower(br))
     if result != 0: return
   result = a.len - b.len
 
@@ -887,7 +892,7 @@ proc reversed*(s: openArray[char]): string =
 
 proc graphemeLen*(s: openArray[char]; i: Natural): Natural =
   ## The number of bytes belonging to byte index ``s[i]``,
-  ## including following combining code unit.
+  ## including following combining code units.
   runnableExamples:
     let a = "añyóng"
     doAssert a.graphemeLen(1) == 2 ## ñ
@@ -1370,9 +1375,9 @@ proc toRunes*(s: string): seq[Rune] {.inline.} =
 proc cmpRunesIgnoreCase*(a, b: string): int {.inline.} =
   ## Compares two UTF-8 strings and ignores the case. Returns:
   ##
-  ## | 0 if a == b
-  ## | < 0 if a < b
-  ## | > 0 if a > b
+  ## | `0` if a == b
+  ## | `< 0` if a < b
+  ## | `> 0` if a > b
   cmpRunesIgnoreCase(a.toOa(), b.toOa())
 
 proc reversed*(s: string): string {.inline.} =
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index c87fe38f1..cfb762258 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -34,9 +34,9 @@
 ##
 ## Specify the test name as a command line argument.
 ##
-## .. code::
-##
+##   ```cmd
 ##   nim c -r test "my test name" "another test"
+##   ```
 ##
 ## Multiple arguments can be used.
 ##
@@ -45,9 +45,9 @@
 ##
 ## Specify the suite name delimited by `"::"`.
 ##
-## .. code::
-##
+##   ```cmd
 ##   nim c -r test "my test name::"
+##   ```
 ##
 ## Selecting tests by pattern
 ## ==========================
@@ -58,19 +58,18 @@
 ##
 ## Tests matching **any** of the arguments are executed.
 ##
-## .. code::
-##
+##   ```cmd
 ##   nim c -r test fast_suite::mytest1 fast_suite::mytest2
 ##   nim c -r test "fast_suite::mytest*"
 ##   nim c -r test "auth*::" "crypto::hashing*"
 ##   # Run suites starting with 'bug #' and standalone tests starting with '#'
 ##   nim c -r test 'bug #*::' '::#*'
+##   ```
 ##
 ## Examples
 ## ========
 ##
-## .. code:: nim
-##
+##   ```nim
 ##   suite "description for this stuff":
 ##     echo "suite setup: run once before the tests"
 ##
@@ -96,6 +95,7 @@
 ##         discard v[4]
 ##
 ##     echo "suite teardown: run once after the tests"
+##   ```
 ##
 ## Limitations/Bugs
 ## ================
@@ -111,15 +111,15 @@ import std/exitprocs
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
-import macros, strutils, streams, times, sets, sequtils
+import std/[macros, strutils, streams, times, sets, sequtils]
 
 when declared(stdout):
-  import os
+  import std/os
 
 const useTerminal = not defined(js)
 
 when useTerminal:
-  import terminal
+  import std/terminal
 
 type
   TestStatus* = enum ## The status of a test when it is done.
@@ -235,7 +235,7 @@ proc colorOutput(): bool =
     else: result = false
   of "on": result = true
   of "off": result = false
-  else: doAssert false, $color
+  else: raiseAssert $color
 
   when declared(stdout):
     if existsEnv("NIMTEST_COLOR"):
@@ -473,27 +473,26 @@ template suite*(name, body) {.dirty.} =
   ## common fixture (``setup``, ``teardown``). The fixture is executed
   ## for EACH test.
   ##
-  ## .. code-block:: nim
-  ##  suite "test suite for addition":
-  ##    setup:
-  ##      let result = 4
+  ##   ```nim
+  ##   suite "test suite for addition":
+  ##     setup:
+  ##       let result = 4
   ##
-  ##    test "2 + 2 = 4":
-  ##      check(2+2 == result)
+  ##     test "2 + 2 = 4":
+  ##       check(2+2 == result)
   ##
-  ##    test "(2 + -2) != 4":
-  ##      check(2 + -2 != result)
+  ##     test "(2 + -2) != 4":
+  ##       check(2 + -2 != result)
   ##
-  ##    # No teardown needed
+  ##     # No teardown needed
+  ##   ```
   ##
   ## The suite will run the individual test cases in the order in which
   ## they were listed. With default global settings the above code prints:
   ##
-  ## .. code-block::
-  ##
-  ##  [Suite] test suite for addition
-  ##    [OK] 2 + 2 = 4
-  ##    [OK] (2 + -2) != 4
+  ##     [Suite] test suite for addition
+  ##       [OK] 2 + 2 = 4
+  ##       [OK] (2 + -2) != 4
   bind formatters, ensureInitialized, suiteEnded
 
   block:
@@ -519,20 +518,24 @@ proc exceptionTypeName(e: ref Exception): string {.inline.} =
   if e == nil: "<foreign exception>"
   else: $e.name
 
+when not declared(setProgramResult):
+  {.warning: "setProgramResult not available on platform, unittest will not" &
+    " give failing exit code on test failure".}
+  template setProgramResult(a: int) =
+    discard
+
 template test*(name, body) {.dirty.} =
   ## Define a single test case identified by `name`.
   ##
-  ## .. code-block:: nim
-  ##
-  ##  test "roses are red":
-  ##    let roses = "red"
-  ##    check(roses == "red")
+  ##   ```nim
+  ##   test "roses are red":
+  ##     let roses = "red"
+  ##     check(roses == "red")
+  ##   ```
   ##
   ## The above code outputs:
   ##
-  ## .. code-block::
-  ##
-  ##  [OK] roses are red
+  ##     [OK] roses are red
   bind shouldRun, checkpoints, formatters, ensureInitialized, testEnded, exceptionTypeName, setProgramResult
 
   ensureInitialized()
@@ -544,11 +547,14 @@ template test*(name, body) {.dirty.} =
     for formatter in formatters:
       formatter.testStarted(name)
 
+    {.push warning[BareExcept]:off.}
     try:
       when declared(testSetupIMPLFlag): testSetupIMPL()
       when declared(testTeardownIMPLFlag):
         defer: testTeardownIMPL()
+      {.push warning[BareExcept]:on.}
       body
+      {.pop.}
 
     except:
       let e = getCurrentException()
@@ -570,16 +576,17 @@ template test*(name, body) {.dirty.} =
       )
       testEnded(testResult)
       checkpoints = @[]
+    {.pop.}
 
 proc checkpoint*(msg: string) =
   ## Set a checkpoint identified by `msg`. Upon test failure all
   ## checkpoints encountered so far are printed out. Example:
   ##
-  ## .. code-block:: nim
-  ##
-  ##  checkpoint("Checkpoint A")
-  ##  check((42, "the Answer to life and everything") == (1, "a"))
-  ##  checkpoint("Checkpoint B")
+  ##   ```nim
+  ##   checkpoint("Checkpoint A")
+  ##   check((42, "the Answer to life and everything") == (1, "a"))
+  ##   checkpoint("Checkpoint B")
+  ##   ```
   ##
   ## outputs "Checkpoint A" once it fails.
   checkpoints.add(msg)
@@ -591,11 +598,11 @@ template fail* =
   ## failed (change exit code and test status). This template is useful
   ## for debugging, but is otherwise mostly used internally. Example:
   ##
-  ## .. code-block:: nim
-  ##
-  ##  checkpoint("Checkpoint A")
-  ##  complicatedProcInThread()
-  ##  fail()
+  ##   ```nim
+  ##   checkpoint("Checkpoint A")
+  ##   complicatedProcInThread()
+  ##   fail()
+  ##   ```
   ##
   ## outputs "Checkpoint A" before quitting.
   bind ensureInitialized, setProgramResult
@@ -623,11 +630,10 @@ template skip* =
   ## for reasons depending on outer environment,
   ## or certain application logic conditions or configurations.
   ## The test code is still executed.
-  ##
-  ## .. code-block:: nim
-  ##
-  ##  if not isGLContextCreated():
-  ##    skip()
+  ##   ```nim
+  ##   if not isGLContextCreated():
+  ##     skip()
+  ##   ```
   bind checkpoints
 
   testStatusIMPL = TestStatus.SKIPPED
@@ -757,15 +763,20 @@ macro expect*(exceptions: varargs[typed], body: untyped): untyped =
       defectiveRobot()
 
   template expectBody(errorTypes, lineInfoLit, body): NimNode {.dirty.} =
+    {.push warning[BareExcept]:off.}
     try:
+      {.push warning[BareExcept]:on.}
       body
+      {.pop.}
       checkpoint(lineInfoLit & ": Expect Failed, no exception was thrown.")
       fail()
     except errorTypes:
       discard
     except:
-      checkpoint(lineInfoLit & ": Expect Failed, unexpected exception was thrown.")
+      let err = getCurrentException()
+      checkpoint(lineInfoLit & ": Expect Failed, " & $err.name & " was thrown.")
       fail()
+    {.pop.}
 
   var errorTypes = newNimNode(nnkBracket)
   for exp in exceptions:
diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim
index ebc8b90ef..725d5bbd9 100644
--- a/lib/pure/uri.nim
+++ b/lib/pure/uri.nim
@@ -14,6 +14,8 @@
 ## as a locator, a name, or both. The term "Uniform Resource Locator"
 ## (URL) refers to the subset of URIs.
 ##
+## .. warning:: URI parsers in this module do not perform security validation.
+##
 ## # Basic usage
 
 
diff --git a/lib/pure/volatile.nim b/lib/pure/volatile.nim
index f30d899df..a38247c7d 100644
--- a/lib/pure/volatile.nim
+++ b/lib/pure/volatile.nim
@@ -10,20 +10,18 @@
 ## This module contains code for generating volatile loads and stores,
 ## which are useful in embedded and systems programming.
 
-template volatileLoad*[T](src: ptr T): T =
+proc volatileLoad*[T](src: ptr T): T {.inline, noinit.} =
   ## Generates a volatile load of the value stored in the container `src`.
   ## Note that this only effects code generation on `C` like backends.
   when nimvm:
-    src[]
+    result = src[]
   else:
     when defined(js):
-      src[]
+      result = src[]
     else:
-      var res: T
-      {.emit: [res, " = (*(", typeof(src[]), " volatile*)", src, ");"].}
-      res
+      {.emit: [result, " = (*(", typeof(src[]), " volatile*)", src, ");"].}
 
-template volatileStore*[T](dest: ptr T, val: T) =
+proc volatileStore*[T](dest: ptr T, val: T) {.inline.} =
   ## Generates a volatile store into the container `dest` of the value
   ## `val`. Note that this only effects code generation on `C` like
   ## backends.
diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim
index 6785fa66e..2c1e4e37c 100644
--- a/lib/pure/xmlparser.nim
+++ b/lib/pure/xmlparser.nim
@@ -9,7 +9,7 @@
 
 ## This module parses an XML document and creates its XML tree representation.
 
-import streams, parsexml, strtabs, xmltree
+import std/[streams, parsexml, strtabs, xmltree]
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -151,7 +151,7 @@ proc loadXml*(path: string, options: set[XmlParseOption] = {reportComments}): Xm
 
 when isMainModule:
   when not defined(testing):
-    import os
+    import std/os
 
     var errors: seq[string] = @[]
     var x = loadXml(paramStr(1), errors)
diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim
index 6228bd10f..5c0cbc5e4 100644
--- a/lib/pure/xmltree.nim
+++ b/lib/pure/xmltree.nim
@@ -31,7 +31,7 @@ runnableExamples:
 ## * `htmlgen module <htmlgen.html>`_ for html code generator
 
 import std/private/since
-import macros, strtabs, strutils
+import std/[macros, strtabs, strutils, sequtils]
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -70,6 +70,14 @@ const
   xmlHeader* = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
     ## Header to use for complete XML output.
 
+template expect(node: XmlNode, kind: set[XmlNodeKind]) =
+  ## Check the node's kind is within a set of values
+  assert node.k in kind, "Got " & $node.k
+
+template expect(node: XmlNode, kind: XmlNodeKind) =
+  ## Check the node's kind equals a value
+  assert node.k == kind, "Got " & $node.k
+
 proc newXmlNode(kind: XmlNodeKind): XmlNode =
   ## Creates a new ``XmlNode``.
   result = XmlNode(k: kind)
@@ -182,7 +190,7 @@ proc text*(n: XmlNode): lent string {.inline.} =
     assert $c == "<!-- my comment -->"
     assert c.text == "my comment"
 
-  assert n.k in {xnText, xnComment, xnCData, xnEntity}
+  n.expect {xnText, xnVerbatimText, xnComment, xnCData, xnEntity}
   result = n.fText
 
 proc `text=`*(n: XmlNode, text: sink string) {.inline.} =
@@ -200,7 +208,7 @@ proc `text=`*(n: XmlNode, text: sink string) {.inline.} =
     e.text = "a new entity text"
     assert $e == "&a new entity text;"
 
-  assert n.k in {xnText, xnComment, xnCData, xnEntity}
+  n.expect {xnText, xnVerbatimText, xnComment, xnCData, xnEntity}
   n.fText = text
 
 proc tag*(n: XmlNode): lent string {.inline.} =
@@ -221,7 +229,7 @@ proc tag*(n: XmlNode): lent string {.inline.} =
 </firstTag>"""
     assert a.tag == "firstTag"
 
-  assert n.k == xnElement
+  n.expect xnElement
   result = n.fTag
 
 proc `tag=`*(n: XmlNode, tag: sink string) {.inline.} =
@@ -244,7 +252,7 @@ proc `tag=`*(n: XmlNode, tag: sink string) {.inline.} =
   <childTag />
 </newTag>"""
 
-  assert n.k == xnElement
+  n.expect xnElement
   n.fTag = tag
 
 proc rawText*(n: XmlNode): string {.inline.} =
@@ -298,26 +306,60 @@ proc innerText*(n: XmlNode): string =
 
 proc add*(father, son: XmlNode) {.inline.} =
   ## Adds the child `son` to `father`.
+  ## `father` must be of `xnElement` type
   ##
   ## See also:
+  ## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
   ## * `insert proc <#insert,XmlNode,XmlNode,int>`_
+  ## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
   ## * `delete proc <#delete,XmlNode,Natural>`_
+  ## * `delete proc <#delete.XmlNode,Slice[int]>`_
+  ## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
+  ## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
   runnableExamples:
     var f = newElement("myTag")
     f.add newText("my text")
     f.add newElement("sonTag")
     f.add newEntity("my entity")
     assert $f == "<myTag>my text<sonTag />&my entity;</myTag>"
+
+  father.expect xnElement
   add(father.s, son)
 
+proc add*(father: XmlNode, sons: openArray[XmlNode]) {.inline.} =
+  ## Adds the children `sons` to `father`.
+  ## `father` must be of `xnElement` type
+  ##
+  ## See also:
+  ## * `add proc <#add,XmlNode,XmlNode>`_
+  ## * `insert proc <#insert,XmlNode,XmlNode,int>`_
+  ## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
+  ## * `delete proc <#delete,XmlNode,Natural>`_
+  ## * `delete proc <#delete.XmlNode,Slice[int]>`_
+  ## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
+  ## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
+  runnableExamples:
+    var f = newElement("myTag")
+    f.add(@[newText("my text"), newElement("sonTag"), newEntity("my entity")])
+    assert $f == "<myTag>my text<sonTag />&my entity;</myTag>"
+
+  father.expect xnElement
+  add(father.s, sons)
+
+
 proc insert*(father, son: XmlNode, index: int) {.inline.} =
   ## Inserts the child `son` to a given position in `father`.
   ##
-  ## `father` and `son` must be of `xnElement` kind.
+  ## `father` must be of `xnElement` kind.
   ##
   ## See also:
+  ## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
   ## * `add proc <#add,XmlNode,XmlNode>`_
+  ## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
   ## * `delete proc <#delete,XmlNode,Natural>`_
+  ## * `delete proc <#delete.XmlNode,Slice[int]>`_
+  ## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
+  ## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
   runnableExamples:
     var f = newElement("myTag")
     f.add newElement("first")
@@ -327,18 +369,52 @@ proc insert*(father, son: XmlNode, index: int) {.inline.} =
   <first />
 </myTag>"""
 
-  assert father.k == xnElement and son.k == xnElement
+  father.expect xnElement
   if len(father.s) > index:
     insert(father.s, son, index)
   else:
     insert(father.s, son, len(father.s))
 
+proc insert*(father: XmlNode, sons: openArray[XmlNode], index: int) {.inline.} =
+  ## Inserts the children openArray[`sons`] to a given position in `father`.
+  ##
+  ## `father` must be of `xnElement` kind.
+  ##
+  ## See also:
+  ## * `insert proc <#insert,XmlNode,XmlNode,int>`_
+  ## * `add proc <#add,XmlNode,XmlNode>`_
+  ## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
+  ## * `delete proc <#delete,XmlNode,Natural>`_
+  ## * `delete proc <#delete.XmlNode,Slice[int]>`_
+  ## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
+  ## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
+  runnableExamples:
+    var f = newElement("myTag")
+    f.add newElement("first")
+    f.insert([newElement("second"), newElement("third")], 0)
+    assert $f == """<myTag>
+  <second />
+  <third />
+  <first />
+</myTag>"""
+
+  father.expect xnElement
+  if len(father.s) > index:
+    insert(father.s, sons, index)
+  else:
+    insert(father.s, sons, len(father.s))
+
 proc delete*(n: XmlNode, i: Natural) =
   ## Deletes the `i`'th child of `n`.
   ##
   ## See also:
+  ## * `delete proc <#delete.XmlNode,Slice[int]>`_
   ## * `add proc <#add,XmlNode,XmlNode>`_
+  ## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
   ## * `insert proc <#insert,XmlNode,XmlNode,int>`_
+  ## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
+  ## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
+  ## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
   runnableExamples:
     var f = newElement("myTag")
     f.add newElement("first")
@@ -348,9 +424,88 @@ proc delete*(n: XmlNode, i: Natural) =
   <first />
 </myTag>"""
 
-  assert n.k == xnElement
+  n.expect xnElement
   n.s.delete(i)
 
+proc delete*(n: XmlNode, slice: Slice[int]) =
+  ## Deletes the items `n[slice]` of `n`.
+  ##
+  ## See also:
+  ## * `delete proc <#delete.XmlNode,int>`_
+  ## * `add proc <#add,XmlNode,XmlNode>`_
+  ## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
+  ## * `insert proc <#insert,XmlNode,XmlNode,int>`_
+  ## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
+  ## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
+  ## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
+  runnableExamples:
+    var f = newElement("myTag")
+    f.add newElement("first")
+    f.insert([newElement("second"), newElement("third")], 0)
+    f.delete(0..1)
+    assert $f == """<myTag>
+  <first />
+</myTag>"""
+
+  n.expect xnElement
+  n.s.delete(slice)
+
+proc replace*(n: XmlNode, i: Natural, replacement: openArray[XmlNode]) =
+  ## Replaces the `i`'th child of `n` with `replacement` openArray.
+  ##
+  ## `n` must be of `xnElement` kind.
+  ##
+  ## See also:
+  ## * `replace proc <#replace.XmlNode,Slice[int],openArray[XmlNode]>`_
+  ## * `add proc <#add,XmlNode,XmlNode>`_
+  ## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
+  ## * `delete proc <#delete,XmlNode,Natural>`_
+  ## * `delete proc <#delete.XmlNode,Slice[int]>`_
+  ## * `insert proc <#insert,XmlNode,XmlNode,int>`_
+  ## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
+  runnableExamples:
+    var f = newElement("myTag")
+    f.add newElement("first")
+    f.insert(newElement("second"), 0)
+    f.replace(0, @[newElement("third"), newElement("fourth")])
+    assert $f == """<myTag>
+  <third />
+  <fourth />
+  <first />
+</myTag>"""
+
+  n.expect xnElement
+  n.s.delete(i)
+  n.s.insert(replacement, i)
+
+proc replace*(n: XmlNode, slice: Slice[int], replacement: openArray[XmlNode]) =
+  ## Deletes the items `n[slice]` of `n`.
+  ##
+  ## `n` must be of `xnElement` kind.
+  ##
+  ## See also:
+  ## * `replace proc <#replace.XmlNode,int,openArray[XmlNode]>`_
+  ## * `add proc <#add,XmlNode,XmlNode>`_
+  ## * `add proc <#add,XmlNode,openArray[XmlNode]>`_
+  ## * `delete proc <#delete,XmlNode,Natural>`_
+  ## * `delete proc <#delete.XmlNode,Slice[int]>`_
+  ## * `insert proc <#insert,XmlNode,XmlNode,int>`_
+  ## * `insert proc <#insert,XmlNode,openArray[XmlNode],int>`_
+  runnableExamples:
+    var f = newElement("myTag")
+    f.add newElement("first")
+    f.insert([newElement("second"), newElement("fifth")], 0)
+    f.replace(0..1, @[newElement("third"), newElement("fourth")])
+    assert $f == """<myTag>
+  <third />
+  <fourth />
+  <first />
+</myTag>"""
+
+  n.expect xnElement
+  n.s.delete(slice)
+  n.s.insert(replacement, slice.a)
+
 proc len*(n: XmlNode): int {.inline.} =
   ## Returns the number of `n`'s children.
   runnableExamples:
@@ -378,12 +533,12 @@ proc `[]`*(n: XmlNode, i: int): XmlNode {.inline.} =
     assert $f[1] == "<first />"
     assert $f[0] == "<second />"
 
-  assert n.k == xnElement
+  n.expect xnElement
   result = n.s[i]
 
 proc `[]`*(n: var XmlNode, i: int): var XmlNode {.inline.} =
   ## Returns the `i`'th child of `n` so that it can be modified.
-  assert n.k == xnElement
+  n.expect xnElement
   result = n.s[i]
 
 proc clear*(n: var XmlNode) =
@@ -435,12 +590,12 @@ iterator items*(n: XmlNode): XmlNode {.inline.} =
     # <!-- this is comment -->
     # <secondTag>&some entity;<![CDATA[some cdata]]></secondTag>
 
-  assert n.k == xnElement
+  n.expect xnElement
   for i in 0 .. n.len-1: yield n[i]
 
 iterator mitems*(n: var XmlNode): var XmlNode {.inline.} =
   ## Iterates over all direct children of `n` so that they can be modified.
-  assert n.k == xnElement
+  n.expect xnElement
   for i in 0 .. n.len-1: yield n[i]
 
 proc toXmlAttributes*(keyValuePairs: varargs[tuple[key,
@@ -472,7 +627,7 @@ proc attrs*(n: XmlNode): XmlAttributes {.inline.} =
     j.attrs = att
     assert j.attrs == att
 
-  assert n.k == xnElement
+  n.expect xnElement
   result = n.fAttr
 
 proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} =
@@ -489,7 +644,7 @@ proc `attrs=`*(n: XmlNode, attr: XmlAttributes) {.inline.} =
     j.attrs = att
     assert j.attrs == att
 
-  assert n.k == xnElement
+  n.expect xnElement
   n.fAttr = attr
 
 proc attrsLen*(n: XmlNode): int {.inline.} =
@@ -506,7 +661,7 @@ proc attrsLen*(n: XmlNode): int {.inline.} =
     j.attrs = att
     assert j.attrsLen == 2
 
-  assert n.k == xnElement
+  n.expect xnElement
   if not isNil(n.fAttr): result = len(n.fAttr)
 
 proc attr*(n: XmlNode, name: string): string =
@@ -524,7 +679,7 @@ proc attr*(n: XmlNode, name: string): string =
     assert j.attr("key1") == "first value"
     assert j.attr("key2") == "second value"
 
-  assert n.kind == xnElement
+  n.expect xnElement
   if n.attrs == nil: return ""
   return n.attrs.getOrDefault(name)
 
@@ -576,23 +731,11 @@ proc addIndent(result: var string, indent: int, addNewLines: bool) =
   for i in 1 .. indent:
     result.add(' ')
 
-proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
-          addNewLines = true) =
-  ## Adds the textual representation of `n` to string `result`.
-  runnableExamples:
-    var
-      a = newElement("firstTag")
-      b = newText("my text")
-      c = newComment("my comment")
-      s = ""
-    s.add(c)
-    s.add(a)
-    s.add(b)
-    assert s == "<!-- my comment --><firstTag />my text"
-
+proc addImpl(result: var string, n: XmlNode, indent = 0, indWidth = 2,
+          addNewLines = true, lastNodeIsText = false) =
   proc noWhitespace(n: XmlNode): bool =
     for i in 0 ..< n.len:
-      if n[i].kind in {xnText, xnEntity}: return true
+      if n[i].kind in {xnText, xnVerbatimText, xnEntity}: return true
 
   proc addEscapedAttr(result: var string, s: string) =
     # `addEscaped` alternative with less escaped characters.
@@ -609,7 +752,7 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
 
   case n.k
   of xnElement:
-    if indent > 0:
+    if indent > 0 and not lastNodeIsText:
       result.addIndent(indent, addNewLines)
 
     let
@@ -638,8 +781,10 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
                    else:
                      indent+indWidth
     result.add('>')
+    var lastNodeIsText = false
     for i in 0 ..< n.len:
-      result.add(n[i], indentNext, indWidth, addNewLines)
+      result.addImpl(n[i], indentNext, indWidth, addNewLines, lastNodeIsText)
+      lastNodeIsText = (n[i].kind == xnText) or (n[i].kind == xnVerbatimText)
 
     if not n.noWhitespace():
       result.addIndent(indent, addNewLines)
@@ -664,6 +809,21 @@ proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
     result.add(n.fText)
     result.add(';')
 
+proc add*(result: var string, n: XmlNode, indent = 0, indWidth = 2,
+          addNewLines = true) {.inline.} =
+  ## Adds the textual representation of `n` to string `result`.
+  runnableExamples:
+    var
+      a = newElement("firstTag")
+      b = newText("my text")
+      c = newComment("my comment")
+      s = ""
+    s.add(c)
+    s.add(a)
+    s.add(b)
+    assert s == "<!-- my comment --><firstTag />my text"
+  result.addImpl(n, indent, indWidth, addNewLines)
+
 proc `$`*(n: XmlNode): string =
   ## Converts `n` into its string representation.
   ##
@@ -682,7 +842,7 @@ proc child*(n: XmlNode, name: string): XmlNode =
     f.add newElement("thirdSon")
     assert $(f.child("secondSon")) == "<secondSon />"
 
-  assert n.kind == xnElement
+  n.expect xnElement
   for i in items(n):
     if i.kind == xnElement:
       if i.tag == name:
@@ -718,7 +878,7 @@ proc findAll*(n: XmlNode, tag: string, result: var seq[XmlNode],
     a.findAll("BAD", s, caseInsensitive = true)
     assert $s == "@[<bad>c text</bad>, <BAD>d text</BAD>]"
 
-  assert n.k == xnElement
+  n.expect xnElement
   for child in n.items():
     if child.k != xnElement:
       continue
@@ -775,8 +935,9 @@ proc xmlConstructor(a: NimNode): NimNode =
 macro `<>`*(x: untyped): untyped =
   ## Constructor macro for XML. Example usage:
   ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   <>a(href="http://nim-lang.org", newText("Nim rules."))
+  ##   ```
   ##
   ## Produces an XML tree for:
   ##
diff --git a/lib/std/appdirs.nim b/lib/std/appdirs.nim
index e648fe0c1..963451efe 100644
--- a/lib/std/appdirs.nim
+++ b/lib/std/appdirs.nim
@@ -1,5 +1,7 @@
 ## This module implements helpers for determining special directories used by apps.
 
+## .. importdoc:: paths.nim
+
 from std/private/osappdirs import nil
 import std/paths
 import std/envvars
@@ -15,6 +17,23 @@ proc getHomeDir*(): Path {.inline, tags: [ReadEnvEffect, ReadIOEffect].} =
   ## * `getTempDir proc`_
   result = Path(osappdirs.getHomeDir())
 
+proc getDataDir*(): Path {.inline, tags: [ReadEnvEffect, ReadIOEffect].} =
+  ## Returns the data directory of the current user for applications.
+  ## 
+  ## On non-Windows OSs, this proc conforms to the XDG Base Directory
+  ## spec. Thus, this proc returns the value of the `XDG_DATA_HOME` environment
+  ## variable if it is set, otherwise it returns the default configuration
+  ## directory ("~/.local/share" or "~/Library/Application Support" on macOS).
+  ## 
+  ## See also:
+  ## * `getHomeDir proc`_
+  ## * `getConfigDir proc`_
+  ## * `getTempDir proc`_
+  ## * `expandTilde proc`_
+  ## * `getCurrentDir proc`_
+  ## * `setCurrentDir proc`_
+  result = Path(osappdirs.getDataDir())
+
 proc getConfigDir*(): Path {.inline, tags: [ReadEnvEffect, ReadIOEffect].} =
   ## Returns the config directory of the current user for applications.
   ##
diff --git a/lib/std/assertions.nim b/lib/std/assertions.nim
index 03bab1b1b..56c37d205 100644
--- a/lib/std/assertions.nim
+++ b/lib/std/assertions.nim
@@ -7,6 +7,10 @@
 #    distribution, for details about the copyright.
 #
 
+when not defined(nimPreviewSlimSystem) and not declared(sysFatal):
+  include "system/rawquits"
+  include "system/fatal"
+
 ## This module implements assertion handling.
 
 import std/private/miscdollars
@@ -23,22 +27,18 @@ proc `$`(info: InstantiationInfo): string =
 
 # ---------------------------------------------------------------------------
 
-when not defined(nimHasSinkInference):
-  {.pragma: nosinks.}
 
 proc raiseAssert*(msg: string) {.noinline, noreturn, nosinks.} =
   ## Raises an `AssertionDefect` with `msg`.
-  raise newException(AssertionDefect, msg)
+  when defined(nimPreviewSlimSystem):
+    raise newException(AssertionDefect, msg)
+  else:
+    sysFatal(AssertionDefect, msg)
 
 proc failedAssertImpl*(msg: string) {.raises: [], tags: [].} =
   ## Raises an `AssertionDefect` with `msg`, but this is hidden
   ## from the effect system. Called when an assertion failed.
-  # trick the compiler to not list `AssertionDefect` when called
-  # by `assert`.
-  # xxx simplify this pending bootstrap >= 1.4.0, after which cast not needed
-  # anymore since `Defect` can't be raised.
-  type Hide = proc (msg: string) {.noinline, raises: [], noSideEffect, tags: [].}
-  cast[Hide](raiseAssert)(msg)
+  raiseAssert(msg)
 
 template assertImpl(cond: bool, msg: string, expr: string, enabled: static[bool]) =
   when enabled:
@@ -98,6 +98,7 @@ template doAssertRaises*(exception: typedesc, code: untyped) =
   const begin = "expected raising '" & astToStr(exception) & "', instead"
   const msgEnd = " by: " & astToStr(code)
   template raisedForeign {.gensym.} = raiseAssert(begin & " raised foreign exception" & msgEnd)
+  {.push warning[BareExcept]:off.}
   when Exception is exception:
     try:
       if true:
@@ -116,5 +117,6 @@ template doAssertRaises*(exception: typedesc, code: untyped) =
       mixin `$` # alternatively, we could define $cstring in this module
       raiseAssert(begin & " raised '" & $e.name & "'" & msgEnd)
     except: raisedForeign()
+  {.pop.}
   if wrong:
     raiseAssert(begin & " nothing was raised" & msgEnd)
diff --git a/lib/std/cmdline.nim b/lib/std/cmdline.nim
index 3208da1b8..0ba4619e5 100644
--- a/lib/std/cmdline.nim
+++ b/lib/std/cmdline.nim
@@ -30,9 +30,9 @@ const weirdTarget = defined(nimscript) or defined(js)
 when weirdTarget:

   discard

 elif defined(windows):

-  import winlean

+  import std/winlean

 elif defined(posix):

-  import posix

+  import std/posix

 else:

   {.error: "The cmdline module has not been implemented for the target platform.".}

 

@@ -40,10 +40,7 @@ else:
 # Needed by windows in order to obtain the command line for targets

 # other than command line targets

 when defined(windows) and not weirdTarget:

-  when useWinUnicode:

-    template getCommandLine*(): untyped = getCommandLineW()

-  else:

-    template getCommandLine*(): untyped = getCommandLineA()

+  template getCommandLine*(): untyped = getCommandLineW()

 

 

 proc parseCmdLine*(c: string): seq[string] {.

@@ -141,7 +138,7 @@ proc parseCmdLine*(c: string): seq[string] {.
         while i < c.len and c[i] > ' ':

           add(a, c[i])

           inc(i)

-    add(result, a)

+    add(result, move a)

 

 when defined(nimdoc):

   # Common forward declaration docstring block for parameter retrieval procs.

@@ -166,11 +163,12 @@ when defined(nimdoc):
     ##

     ## **Examples:**

     ##

-    ## .. code-block:: nim

+    ##   ```nim

     ##   when declared(paramCount):

     ##     # Use paramCount() here

     ##   else:

     ##     # Do something else!

+    ##   ```

 

   proc paramStr*(i: int): string {.tags: [ReadIOEffect].} =

     ## Returns the `i`-th `command line argument`:idx: given to the application.

@@ -183,7 +181,7 @@ when defined(nimdoc):
     ## Similarly to `argv`:idx: in C,

     ## it is possible to call `paramStr(0)` but this will return OS specific

     ## contents (usually the name of the invoked executable). You should avoid

-    ## this and call `getAppFilename()`_ instead.

+    ## this and call `getAppFilename() <os.html#getAppFilename>`_ instead.

     ##

     ## **Availability**: When generating a dynamic library (see `--app:lib`) on

     ## Posix this proc is not defined.

@@ -194,15 +192,16 @@ when defined(nimdoc):
     ## * `parseCmdLine proc`_

     ## * `paramCount proc`_

     ## * `commandLineParams proc`_

-    ## * `getAppFilename proc`_

+    ## * `getAppFilename proc <os.html#getAppFilename>`_

     ##

     ## **Examples:**

     ##

-    ## .. code-block:: nim

+    ##   ```nim

     ##   when declared(paramStr):

     ##     # Use paramStr() here

     ##   else:

     ##     # Do something else!

+    ##   ```

 

 elif defined(nimscript): discard

 elif defined(nodejs):

@@ -283,7 +282,7 @@ when declared(paramCount) or defined(nimdoc):
     ## Convenience proc which returns the command line parameters.

     ##

     ## This returns **only** the parameters. If you want to get the application

-    ## executable filename, call `getAppFilename()`_.

+    ## executable filename, call `getAppFilename() <os.html#getAppFilename>`_.

     ##

     ## **Availability**: On Posix there is no portable way to get the command

     ## line from a DLL and thus the proc isn't defined in this environment. You

@@ -295,15 +294,16 @@ when declared(paramCount) or defined(nimdoc):
     ## * `parseCmdLine proc`_

     ## * `paramCount proc`_

     ## * `paramStr proc`_

-    ## * `getAppFilename proc`_

+    ## * `getAppFilename proc <os.html#getAppFilename>`_

     ##

     ## **Examples:**

     ##

-    ## .. code-block:: nim

+    ##   ```nim

     ##   when declared(commandLineParams):

     ##     # Use commandLineParams() here

     ##   else:

     ##     # Do something else!

+    ##   ```

     result = @[]

     for i in 1..paramCount():

       result.add(paramStr(i))

diff --git a/lib/std/decls.nim b/lib/std/decls.nim
index 3f774cd08..bb7ec3593 100644
--- a/lib/std/decls.nim
+++ b/lib/std/decls.nim
@@ -1,6 +1,6 @@
 ## This module implements syntax sugar for some declarations.
 
-import macros
+import std/macros
 
 macro byaddr*(sect) =
   ## Allows a syntax for l-value references, being an exact analog to
diff --git a/lib/std/dirs.nim b/lib/std/dirs.nim
index df6107c51..380d6d08f 100644
--- a/lib/std/dirs.nim
+++ b/lib/std/dirs.nim
@@ -1,6 +1,6 @@
 ## This module implements directory handling.
 
-from paths import Path, ReadDirEffect, WriteDirEffect
+from std/paths import Path, ReadDirEffect, WriteDirEffect
 
 from std/private/osdirs import dirExists, createDir, existsOrCreateDir, removeDir,
                                moveDir, walkDir, setCurrentDir,
@@ -8,7 +8,7 @@ from std/private/osdirs import dirExists, createDir, existsOrCreateDir, removeDi
 
 export PathComponent
 
-proc dirExists*(dir: Path): bool {.inline, tags: [ReadDirEffect].} =
+proc dirExists*(dir: Path): bool {.inline, tags: [ReadDirEffect], sideEffect.} =
   ## Returns true if the directory `dir` exists. If `dir` is a file, false
   ## is returned. Follows symlinks.
   result = dirExists(dir.string)
diff --git a/lib/std/editdistance.nim b/lib/std/editdistance.nim
index 9f29c5c05..40c0017ae 100644
--- a/lib/std/editdistance.nim
+++ b/lib/std/editdistance.nim
@@ -10,7 +10,7 @@
 ## This module implements an algorithm to compute the
 ## `edit distance`:idx: between two Unicode strings.
 
-import unicode
+import std/unicode
 
 proc editDistance*(a, b: string): int {.noSideEffect.} =
   ## Returns the **unicode-rune** edit distance between `a` and `b`.
@@ -18,7 +18,7 @@ proc editDistance*(a, b: string): int {.noSideEffect.} =
   ## This uses the `Levenshtein`:idx: distance algorithm with only a linear
   ## memory overhead.
   runnableExamples: static: doAssert editdistance("Kitten", "Bitten") == 1
-  if len(a) > len(b):
+  if runeLen(a) > runeLen(b):
     # make `b` the longer string
     return editDistance(b, a)
   # strip common prefix
diff --git a/lib/std/effecttraits.nim b/lib/std/effecttraits.nim
index fb057a669..3d1b4ffd3 100644
--- a/lib/std/effecttraits.nim
+++ b/lib/std/effecttraits.nim
@@ -14,7 +14,7 @@
 ## One can test for the existence of this standard module
 ## via `defined(nimHasEffectTraitsModule)`.
 
-import macros
+import std/macros
 
 proc getRaisesListImpl(n: NimNode): NimNode = discard "see compiler/vmops.nim"
 proc getTagsListImpl(n: NimNode): NimNode = discard "see compiler/vmops.nim"
diff --git a/lib/std/enumerate.nim b/lib/std/enumerate.nim
index a8f0e1ba7..beb65ed30 100644
--- a/lib/std/enumerate.nim
+++ b/lib/std/enumerate.nim
@@ -11,7 +11,7 @@
 ## macro system.
 
 import std/private/since
-import macros
+import std/macros
 
 
 macro enumerate*(x: ForLoopStmt): untyped {.since: (1, 3).} =
@@ -21,7 +21,7 @@ macro enumerate*(x: ForLoopStmt): untyped {.since: (1, 3).} =
   ## The default starting count `0` can be manually overridden if needed.
   runnableExamples:
     let a = [10, 20, 30]
-    var b: seq[(int, int)]
+    var b: seq[(int, int)] = @[]
     for i, x in enumerate(a):
       b.add((i, x))
     assert b == @[(0, 10), (1, 20), (2, 30)]
diff --git a/lib/std/enumutils.nim b/lib/std/enumutils.nim
index 9d4ff1bcf..9c338817d 100644
--- a/lib/std/enumutils.nim
+++ b/lib/std/enumutils.nim
@@ -7,8 +7,8 @@
 #    distribution, for details about the copyright.
 #
 
-import macros
-from typetraits import OrdinalEnum, HoleyEnum
+import std/macros
+from std/typetraits import OrdinalEnum, HoleyEnum
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -21,32 +21,34 @@ macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed,
   # Generates a case stmt, which assigns the correct enum field given
   # a normalized string comparison to the `argSym` input.
   # string normalization is done using passed normalizer.
-  # NOTE: for an enum with fields Foo, Bar, ... we cannot generate
-  # `of "Foo".nimIdentNormalize: Foo`.
-  # This will fail, if the enum is not defined at top level (e.g. in a block).
-  # Thus we check for the field value of the (possible holed enum) and convert
-  # the integer value to the generic argument `typ`.
   let typ = typ.getTypeInst[1]
-  let impl = typ.getImpl[2]
+  let typSym = typ.getTypeImpl.getTypeInst # skip aliases etc to get type sym
+  let impl = typSym.getImpl[2]
   expectKind impl, nnkEnumTy
   let normalizerNode = quote: `normalizer`
   expectKind normalizerNode, nnkSym
   result = nnkCaseStmt.newTree(newCall(normalizerNode, argSym))
   # stores all processed field strings to give error msg for ambiguous enums
   var foundFields: seq[string] = @[]
+  var fVal = ""
   var fStr = "" # string of current field
   var fNum = BiggestInt(0) # int value of current field
   for f in impl:
     case f.kind
     of nnkEmpty: continue # skip first node of `enumTy`
-    of nnkSym, nnkIdent: fStr = f.strVal
+    of nnkSym, nnkIdent:
+      fVal = f.strVal
+      fStr = fVal
     of nnkAccQuoted:
-      fStr = ""
+      fVal = ""
       for ch in f:
-        fStr.add ch.strVal
+        fVal.add ch.strVal
+      fStr = fVal
     of nnkEnumFieldDef:
+      fVal = f[0].strVal
       case f[1].kind
-      of nnkStrLit: fStr = f[1].strVal
+      of nnkStrLit:
+        fStr = f[1].strVal
       of nnkTupleConstr:
         fStr = f[1][1].strVal
         fNum = f[1][0].intVal
@@ -64,7 +66,7 @@ macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed,
     if fNum >= userMin and fNum <= userMax:
       fStr = normalizer(fStr)
       if fStr notin foundFields:
-        result.add nnkOfBranch.newTree(newLit fStr,  nnkCall.newTree(typ, newLit fNum))
+        result.add nnkOfBranch.newTree(newLit fStr, newDotExpr(typ, ident fVal))
         foundFields.add fStr
       else:
         error("Ambiguous enums cannot be parsed, field " & $fStr &
@@ -80,7 +82,7 @@ macro genEnumCaseStmt*(typ: typedesc, argSym: typed, default: typed,
     result.add nnkElse.newTree(default)
 
 macro enumFullRange(a: typed): untyped =
-  newNimNode(nnkCurly).add(a.getType[1][1..^1])
+  newNimNode(nnkBracket).add(a.getType[1][1..^1])
 
 macro enumNames(a: typed): untyped =
   # this could be exported too; in particular this could be useful for enum with holes.
@@ -112,9 +114,9 @@ const invalidSlot = uint8.high
 
 proc genLookup[T: typedesc[HoleyEnum]](_: T): auto =
   const n = span(T)
-  var ret: array[n, uint8]
   var i = 0
   assert n <= invalidSlot.int
+  var ret {.noinit.}: array[n, uint8]
   for ai in mitems(ret): ai = invalidSlot
   for ai in items(T):
     ret[ai.ord - T.low.ord] = uint8(i)
@@ -172,6 +174,9 @@ template symbolRank*[T: enum](a: T): int =
   when T is Ordinal: ord(a) - T.low.ord.static
   else: symbolRankImpl(a)
 
+proc rangeBase(T: typedesc): typedesc {.magic: "TypeTrait".}
+  # skip one level of range; return the base type of a range type
+
 func symbolName*[T: enum](a: T): string =
   ## Returns the symbol name of an enum.
   ##
@@ -190,5 +195,8 @@ func symbolName*[T: enum](a: T): string =
       c1 = 4
       c2 = 20
     assert c1.symbolName == "c1"
-  const names = enumNames(T)
+  when T is range:
+    const names = enumNames(rangeBase T)
+  else:
+    const names = enumNames(T)
   names[a.symbolRank]
diff --git a/lib/std/envvars.nim b/lib/std/envvars.nim
index 46595a3cf..a955077ea 100644
--- a/lib/std/envvars.nim
+++ b/lib/std/envvars.nim
@@ -60,12 +60,16 @@ when not defined(nimscript):
     when defined(windows):
       proc c_putenv(envstring: cstring): cint {.importc: "_putenv", header: "<stdlib.h>".}
       from std/private/win_setenv import setEnvImpl
-      import winlean
+      import std/winlean
       when defined(nimPreviewSlimSystem):
         import std/widestrs
-      proc c_wgetenv(varname: WideCString): WideCString {.importc: "_wgetenv",
+
+      type wchar_t {.importc: "wchar_t", header: "<stdlib.h>".} = int16
+      proc c_wgetenv(varname: ptr wchar_t): ptr wchar_t {.importc: "_wgetenv",
           header: "<stdlib.h>".}
-      proc getEnvImpl(env: cstring): WideCString = c_wgetenv(env.newWideCString)
+      proc getEnvImpl(env: cstring): WideCString =
+        let r: WideCString = env.newWideCString
+        cast[WideCString](c_wgetenv(cast[ptr wchar_t](r)))
     else:
       proc c_getenv(env: cstring): cstring {.
         importc: "getenv", header: "<stdlib.h>".}
@@ -90,8 +94,10 @@ when not defined(nimscript):
         assert getEnv("unknownEnv", "doesn't exist") == "doesn't exist"
 
       let env = getEnvImpl(key)
-      if env == nil: return default
-      result = $env
+      if env == nil:
+        result = default
+      else:
+        result = $env
 
     proc existsEnv*(key: string): bool {.tags: [ReadEnvEffect].} =
       ## Checks whether the environment variable named `key` exists.
@@ -105,7 +111,7 @@ when not defined(nimscript):
       runnableExamples:
         assert not existsEnv("unknownEnv")
 
-      return getEnvImpl(key) != nil
+      result = getEnvImpl(key) != nil
 
     proc putEnv*(key, val: string) {.tags: [WriteEnvEffect].} =
       ## Sets the value of the `environment variable`:idx: named `key` to `val`.
@@ -136,7 +142,7 @@ when not defined(nimscript):
       ## * `envPairs iterator`_
       template bail = raiseOSError(osLastError(), key)
       when defined(windows):
-        #[ 
+        #[
         # https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/putenv-s-wputenv-s?view=msvc-160
         > You can remove a variable from the environment by specifying an empty string (that is, "") for value_string
         note that nil is not legal
@@ -173,20 +179,17 @@ when not defined(nimscript):
 
     iterator envPairsImpl(): tuple[key, value: string] {.tags: [ReadEnvEffect].} =
       when defined(windows):
-        block implBlock:
-          template impl(get_fun, typ, size, zero, free_fun) =
-            let env = get_fun()
-            var e = env
-            if e == nil: break implBlock
-            while true:
-              let eend = strEnd(e)
-              let kv = $e
-              let p = find(kv, '=')
-              yield (substr(kv, 0, p-1), substr(kv, p+1))
-              e = cast[typ](cast[ByteAddress](eend)+size)
-              if typeof(zero)(eend[1]) == zero: break
-            discard free_fun(env)
-          impl(getEnvironmentStringsW, WideCString, 2, 0, freeEnvironmentStringsW)
+        let env = getEnvironmentStringsW()
+        var e = env
+        if e != nil:
+          while true:
+            let eend = strEnd(e)
+            let kv = $e
+            let p = find(kv, '=')
+            yield (substr(kv, 0, p-1), substr(kv, p+1))
+            e = cast[WideCString](cast[ByteAddress](eend)+2)
+            if int(eend[1]) == 0: break
+          discard freeEnvironmentStringsW(env)
       else:
         var i = 0
         when defined(macosx) and not defined(ios) and not defined(emscripten):
diff --git a/lib/std/exitprocs.nim b/lib/std/exitprocs.nim
index d63c1abc5..f26368f42 100644
--- a/lib/std/exitprocs.nim
+++ b/lib/std/exitprocs.nim
@@ -9,7 +9,9 @@
 
 ## This module allows adding hooks to program exit.
 
-import locks
+import std/locks
+when defined(js) and not defined(nodejs):
+  import std/assertions
 
 type
   FunKind = enum kClosure, kNoconv # extend as needed
@@ -20,20 +22,20 @@ type
 
 var
   gFunsLock: Lock
-  gFuns: seq[Fun]
+  gFuns {.cursor.}: seq[Fun] #Intentionally use the cursor to break up the lifetime trace and make it compatible with JS.
 
 initLock(gFunsLock)
 
 when defined(js):
   proc addAtExit(quitProc: proc() {.noconv.}) =
     when defined(nodejs):
-      asm """
+      {.emit: """
         process.on('exit', `quitProc`);
-      """
+      """.}
     elif defined(js):
-      asm """
+      {.emit: """
         window.onbeforeunload = `quitProc`;
-      """
+      """.}
 else:
   proc addAtExit(quitProc: proc() {.noconv.}) {.
     importc: "atexit", header: "<stdlib.h>".}
@@ -45,6 +47,7 @@ proc callClosures() {.noconv.} =
       case fun.kind
       of kClosure: fun.fun1()
       of kNoconv: fun.fun2()
+    gFuns.setLen(0)
 
 template fun() =
   if gFuns.len == 0:
@@ -66,24 +69,19 @@ proc addExitProc*(cl: proc() {.noconv.}) =
     fun()
     gFuns.add Fun(kind: kNoconv, fun2: cl)
 
-when not defined(nimscript):
+when not defined(nimscript) and (not defined(js) or defined(nodejs)):
   proc getProgramResult*(): int =
     when defined(js) and defined(nodejs):
-      asm """
+      {.emit: """
 `result` = process.exitCode;
-"""
-    elif not defined(js):
-      result = programResult
+""".}
     else:
-      doAssert false
+      result = programResult
 
   proc setProgramResult*(a: int) =
-    # pending https://github.com/nim-lang/Nim/issues/14674
     when defined(js) and defined(nodejs):
-      asm """
+      {.emit: """
 process.exitCode = `a`;
-"""
-    elif not defined(js):
-      programResult = a
+""".}
     else:
-      doAssert false
+      programResult = a
diff --git a/lib/std/files.nim b/lib/std/files.nim
index 138bb5234..c4e0491c9 100644
--- a/lib/std/files.nim
+++ b/lib/std/files.nim
@@ -1,12 +1,15 @@
 ## This module implements file handling.
+##
+## **See also:**
+## * `paths module <paths.html>`_ for path manipulation
 
-from paths import Path, ReadDirEffect, WriteDirEffect
+from std/paths import Path, ReadDirEffect, WriteDirEffect
 
 from std/private/osfiles import fileExists, removeFile,
                                 moveFile
 
 
-proc fileExists*(filename: Path): bool {.inline, tags: [ReadDirEffect].} =
+proc fileExists*(filename: Path): bool {.inline, tags: [ReadDirEffect], sideEffect.} =
   ## Returns true if `filename` exists and is a regular file or symlink.
   ##
   ## Directories, device files, named pipes and sockets return false.
diff --git a/lib/std/formatfloat.nim b/lib/std/formatfloat.nim
index 8abbe59cd..9258245f6 100644
--- a/lib/std/formatfloat.nim
+++ b/lib/std/formatfloat.nim
@@ -11,8 +11,6 @@
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
-else:
-  {.deprecated: "formatfloat is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/formatfloat`".}
 
 proc c_memcpy(a, b: pointer, size: csize_t): pointer {.importc: "memcpy", header: "<string.h>", discardable.}
 
@@ -37,8 +35,8 @@ proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int
   result = float32ToChars(buf, value, forceTrailingDotZero=true).int
   buf[result] = '\0'
 
-proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>",
-                                    importc: "sprintf", varargs, noSideEffect.}
+proc c_snprintf(buf: cstring, n: csize_t, frmt: cstring): cint {.header: "<stdio.h>",
+                                    importc: "snprintf", varargs, noSideEffect.}
 
 proc writeToBuffer(buf: var array[65, char]; value: cstring) =
   var i = 0
@@ -51,7 +49,7 @@ proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat):
   ##
   ## returns the amount of bytes written to `buf` not counting the
   ## terminating '\0' character.
-  var n = c_sprintf(cast[cstring](addr buf), "%.16g", value).int
+  var n = c_snprintf(cast[cstring](addr buf), 65, "%.16g", value).int
   var hasDot = false
   for i in 0..n-1:
     if buf[i] == ',':
@@ -88,7 +86,7 @@ proc writeFloatToBuffer*(buf: var array[65, char]; value: BiggestFloat | float32
 
 proc addFloatRoundtrip*(result: var string; x: float | float32) =
   when nimvm:
-    doAssert false
+    raiseAssert "unreachable"
   else:
     var buffer {.noinit.}: array[65, char]
     let n = writeFloatToBufferRoundtrip(buffer, x)
@@ -96,28 +94,29 @@ proc addFloatRoundtrip*(result: var string; x: float | float32) =
 
 proc addFloatSprintf*(result: var string; x: float) =
   when nimvm:
-    doAssert false
+    raiseAssert "unreachable"
   else:
     var buffer {.noinit.}: array[65, char]
     let n = writeFloatToBufferSprintf(buffer, x)
     result.addCstringN(cast[cstring](buffer[0].addr), n)
 
-proc nimFloatToString(a: float): cstring =
-  ## ensures the result doesn't print like an integer, i.e. return 2.0, not 2
-  # print `-0.0` properly
-  asm """
-    function nimOnlyDigitsOrMinus(n) {
-      return n.toString().match(/^-?\d+$/);
-    }
-    if (Number.isSafeInteger(`a`))
-      `result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0"
-    else {
-      `result` = `a`+""
-      if(nimOnlyDigitsOrMinus(`result`)){
-        `result` = `a`+".0"
+when defined(js):
+  proc nimFloatToString(a: float): cstring =
+    ## ensures the result doesn't print like an integer, i.e. return 2.0, not 2
+    # print `-0.0` properly
+    {.emit: """
+      function nimOnlyDigitsOrMinus(n) {
+        return n.toString().match(/^-?\d+$/);
       }
-    }
-  """
+      if (Number.isSafeInteger(`a`))
+        `result` = `a` === 0 && 1 / `a` < 0 ? "-0.0" : `a`+".0";
+      else {
+        `result` = `a`+"";
+        if(nimOnlyDigitsOrMinus(`result`)){
+          `result` = `a`+".0";
+        }
+      }
+    """.}
 
 proc addFloat*(result: var string; x: float | float32) {.inline.} =
   ## Converts float to its string representation and appends it to `result`.
diff --git a/lib/std/genasts.nim b/lib/std/genasts.nim
index 05b2823ef..d0f07c527 100644
--- a/lib/std/genasts.nim
+++ b/lib/std/genasts.nim
@@ -1,6 +1,6 @@
 ## This module implements AST generation using captured variables for macros.
 
-import macros
+import std/macros
 
 type GenAstOpt* = enum
   kDirtyTemplate,
@@ -24,7 +24,7 @@ macro genAstOpt*(options: static set[GenAstOpt], args: varargs[untyped]): untype
       result = genAst(cond, s = repr(cond), lhs = cond[1], rhs = cond[2]):
         # each local symbol we access must be explicitly captured
         if not cond:
-          doAssert false, "'$#'' failed: lhs: '$#', rhs: '$#'" % [s, $lhs, $rhs]
+          raiseAssert "'$#'' failed: lhs: '$#', rhs: '$#'" % [s, $lhs, $rhs]
     let a = 3
     check2 a*2 == a+3
     if false: check2 a*2 < a+1 # would error with: 'a * 2 < a + 1'' failed: lhs: '6', rhs: '4'
diff --git a/lib/std/isolation.nim b/lib/std/isolation.nim
index 7d6ac6092..b03e00651 100644
--- a/lib/std/isolation.nim
+++ b/lib/std/isolation.nim
@@ -15,7 +15,7 @@
 ##
 
 type
-  Isolated*[T] = object ## Isolated data can only be moved, not copied.
+  Isolated*[T] {.sendable.} = object ## Isolated data can only be moved, not copied.
     value: T
 
 proc `=copy`*[T](dest: var Isolated[T]; src: Isolated[T]) {.error.}
@@ -38,9 +38,9 @@ func isolate*[T](value: sink T): Isolated[T] {.magic: "Isolate".} =
 
 func unsafeIsolate*[T](value: sink T): Isolated[T] =
   ## Creates an isolated subgraph from the expression `value`.
-  ## 
+  ##
   ## .. warning:: The proc doesn't check whether `value` is isolated.
-  ## 
+  ##
   Isolated[T](value: value)
 
 func extract*[T](src: var Isolated[T]): T =
diff --git a/lib/std/jsbigints.nim b/lib/std/jsbigints.nim
index 04578fc87..4e996ea7b 100644
--- a/lib/std/jsbigints.nim
+++ b/lib/std/jsbigints.nim
@@ -14,7 +14,7 @@ func big*(integer: SomeInteger): JsBigInt {.importjs: "BigInt(#)".} =
   runnableExamples:
     doAssert big(1234567890) == big"1234567890"
     doAssert 0b1111100111.big == 0o1747.big and 0o1747.big == 999.big
-  when nimvm: doAssert false, "JsBigInt can not be used at compile-time nor static context" else: discard
+  when nimvm: raiseAssert "JsBigInt can not be used at compile-time nor static context" else: discard
 
 func `'big`*(num: cstring): JsBigInt {.importjs: "BigInt(#)".} =
   ## Constructor for `JsBigInt`.
@@ -28,11 +28,11 @@ func `'big`*(num: cstring): JsBigInt {.importjs: "BigInt(#)".} =
     doAssert 0xdeadbeaf'big == 0xdeadbeaf.big
     doAssert 0xffffffffffffffff'big == (1'big shl 64'big) - 1'big
     doAssert not compiles(static(12'big))
-  when nimvm: doAssert false, "JsBigInt can not be used at compile-time nor static context" else: discard
+  when nimvm: raiseAssert "JsBigInt can not be used at compile-time nor static context" else: discard
 
 func big*(integer: cstring): JsBigInt {.importjs: "BigInt(#)".} =
   ## Alias for `'big`
-  when nimvm: doAssert false, "JsBigInt can not be used at compile-time nor static context" else: discard
+  when nimvm: raiseAssert "JsBigInt can not be used at compile-time nor static context" else: discard
 
 func toCstring*(this: JsBigInt; radix: 2..36): cstring {.importjs: "#.toString(#)".} =
   ## Converts from `JsBigInt` to `cstring` representation.
@@ -64,10 +64,10 @@ func wrapToUint*(this: JsBigInt; bits: Natural): JsBigInt {.importjs:
   runnableExamples:
     doAssert (big("3") + big("2") ** big("66")).wrapToUint(66) == big("3")
 
-func toNumber*(this: JsBigInt): BiggestInt {.importjs: "Number(#)".} =
+func toNumber*(this: JsBigInt): int {.importjs: "Number(#)".} =
   ## Does not do any bounds check and may or may not return an inexact representation.
   runnableExamples:
-    doAssert toNumber(big"2147483647") == 2147483647.BiggestInt
+    doAssert toNumber(big"2147483647") == 2147483647.int
 
 func `+`*(x, y: JsBigInt): JsBigInt {.importjs: "(# $1 #)".} =
   runnableExamples:
@@ -110,7 +110,7 @@ func `==`*(x, y: JsBigInt): bool {.importjs: "(# == #)".} =
     doAssert big"42" == big"42"
 
 func `**`*(x, y: JsBigInt): JsBigInt {.importjs: "((#) $1 #)".} =
-  # (#) needed, refs https://github.com/nim-lang/Nim/pull/16409#issuecomment-760550812
+  # (#) needed due to unary minus
   runnableExamples:
     doAssert big"2" ** big"64" == big"18446744073709551616"
     doAssert big"-2" ** big"3" == big"-8"
@@ -120,8 +120,6 @@ func `**`*(x, y: JsBigInt): JsBigInt {.importjs: "((#) $1 #)".} =
     try: discard big"2" ** big"-1" # raises foreign `RangeError`
     except: ok = true
     doAssert ok
-  # pending https://github.com/nim-lang/Nim/pull/15940, simplify to:
-  # doAssertRaises: discard big"2" ** big"-1" # raises foreign `RangeError`
 
 func `and`*(x, y: JsBigInt): JsBigInt {.importjs: "(# & #)".} =
   runnableExamples:
diff --git a/lib/std/jsonutils.nim b/lib/std/jsonutils.nim
index eec8dea7d..2d28748ce 100644
--- a/lib/std/jsonutils.nim
+++ b/lib/std/jsonutils.nim
@@ -16,7 +16,7 @@ runnableExamples:
   assert 0.0.toJson.kind == JFloat
   assert Inf.toJson.kind == JString
 
-import json, strutils, tables, sets, strtabs, options, strformat
+import std/[json, strutils, tables, sets, strtabs, options, strformat]
 
 #[
 Future directions:
@@ -30,29 +30,15 @@ add a way to customize serialization, for e.g.:
   objects.
 ]#
 
-import macros
-from enumutils import symbolName
-from typetraits import OrdinalEnum, tupleLen
+import std/macros
+from std/enumutils import symbolName
+from std/typetraits import OrdinalEnum, tupleLen
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
-when not defined(nimFixedForwardGeneric):
-  # xxx remove pending csources_v1 update >= 1.2.0
-  proc to[T](node: JsonNode, t: typedesc[T]): T =
-    when T is string: node.getStr
-    elif T is bool: node.getBool
-    else: static: doAssert false, $T # support as needed (only needed during bootstrap)
-  proc isNamedTuple(T: typedesc): bool = # old implementation
-    when T isnot tuple: result = false
-    else:
-      var t: T
-      for name, _ in t.fieldPairs:
-        when name == "Field0": return compiles(t.Field0)
-        else: return true
-      return false
-else:
-  proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
+
+proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
 
 type
   Joptions* = object # xxx rename FromJsonOptions
@@ -92,19 +78,24 @@ macro getDiscriminants(a: typedesc): seq[string] =
   let sym = a[1]
   let t = sym.getTypeImpl
   let t2 = t[2]
-  doAssert t2.kind == nnkRecList
-  result = newTree(nnkBracket)
-  for ti in t2:
-    if ti.kind == nnkRecCase:
-      let key = ti[0][0]
-      let typ = ti[0][1]
-      result.add newLit key.strVal
-  if result.len > 0:
+  case t2.kind
+  of nnkEmpty: # allow empty objects
     result = quote do:
-      @`result`
+        seq[string].default
+  of nnkRecList:
+    result = newTree(nnkBracket)
+    for ti in t2:
+      if ti.kind == nnkRecCase:
+        let key = ti[0][0]
+        result.add newLit key.strVal
+    if result.len > 0:
+      result = quote do:
+        @`result`
+    else:
+      result = quote do:
+        seq[string].default
   else:
-    result = quote do:
-      seq[string].default
+    raiseAssert "unexpected kind: " & $t2.kind
 
 macro initCaseObject(T: typedesc, fun: untyped): untyped =
   ## does the minimum to construct a valid case object, only initializing
@@ -118,7 +109,7 @@ macro initCaseObject(T: typedesc, fun: untyped): untyped =
   case t.kind
   of nnkObjectTy: t2 = t[2]
   of nnkRefTy: t2 = t[0].getTypeImpl[2]
-  else: doAssert false, $t.kind # xxx `nnkPtrTy` could be handled too
+  else: raiseAssert $t.kind # xxx `nnkPtrTy` could be handled too
   doAssert t2.kind == nnkRecList
   result = newTree(nnkObjConstr)
   result.add sym
@@ -231,12 +222,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
   elif T is uint|uint64: a = T(to(b, uint64))
   elif T is Ordinal: a = cast[T](to(b, int))
   elif T is pointer: a = cast[pointer](to(b, int))
-  elif T is distinct:
-    when nimvm:
-      # bug, potentially related to https://github.com/nim-lang/Nim/issues/12282
-      a = T(jsonTo(b, distinctBase(T)))
-    else:
-      a.distinctBase.fromJson(b)
+  elif T is distinct: a.distinctBase.fromJson(b)
   elif T is string|SomeNumber: a = to(b,T)
   elif T is cstring:
     case b.kind
@@ -303,7 +289,7 @@ proc fromJson*[T](a: var T, b: JsonNode, opt = Joptions()) =
         i.inc
   else:
     # checkJson not appropriate here
-    static: doAssert false, "not yet implemented: " & $T
+    static: raiseAssert "not yet implemented: " & $T
 
 proc jsonTo*(b: JsonNode, T: typedesc, opt = Joptions()): T =
   ## reverse of `toJson`
@@ -385,7 +371,6 @@ proc toJsonHook*[K: string|cstring, V](t: (Table[K, V] | OrderedTable[K, V]), op
   ##
   ## See also:
   ## * `fromJsonHook proc<#fromJsonHook,,JsonNode>`_
-  # pending PR #9217 use: toSeq(a) instead of `collect` in `runnableExamples`.
   runnableExamples:
     import std/[tables, json, sugar]
     let foo = (
diff --git a/lib/std/monotimes.nim b/lib/std/monotimes.nim
index 5c67a5d4c..bf6dc776b 100644
--- a/lib/std/monotimes.nim
+++ b/lib/std/monotimes.nim
@@ -36,7 +36,7 @@ See also
 * `times module <times.html>`_
 ]##
 
-import times
+import std/times
 
 type
   MonoTime* = object ## Represents a monotonic timestamp.
@@ -74,7 +74,7 @@ when defined(js):
   {.pop.}
 
 elif defined(posix) and not defined(osx):
-  import posix
+  import std/posix
 
 when defined(zephyr):
   proc k_uptime_ticks(): int64 {.importc: "k_uptime_ticks", header: "<kernel.h>".}
diff --git a/lib/std/oserrors.nim b/lib/std/oserrors.nim
index 8d06c41da..7b11c5e8e 100644
--- a/lib/std/oserrors.nim
+++ b/lib/std/oserrors.nim
@@ -15,7 +15,7 @@ type
 
 when not defined(nimscript):
   when defined(windows):
-    import winlean
+    import std/winlean
     when defined(nimPreviewSlimSystem):
       import std/widestrs
   else:
@@ -75,17 +75,14 @@ proc newOSError*(
   ## See also:
   ## * `osErrorMsg proc`_
   ## * `osLastError proc`_
-  var e: owned(ref OSError); new(e)
-  e.errorCode = errorCode.int32
-  e.msg = osErrorMsg(errorCode)
+  result = (ref OSError)(errorCode: errorCode.int32, msg: osErrorMsg(errorCode))
   if additionalInfo.len > 0:
-    if e.msg.len > 0 and e.msg[^1] != '\n': e.msg.add '\n'
-    e.msg.add "Additional info: "
-    e.msg.add additionalInfo
+    if result.msg.len > 0 and result.msg[^1] != '\n': result.msg.add '\n'
+    result.msg.add "Additional info: "
+    result.msg.add additionalInfo
       # don't add trailing `.` etc, which negatively impacts "jump to file" in IDEs.
-  if e.msg == "":
-    e.msg = "unknown OS error"
-  return e
+  if result.msg == "":
+    result.msg = "unknown OS error"
 
 proc raiseOSError*(errorCode: OSErrorCode, additionalInfo = "") {.noinline.} =
   ## Raises an `OSError exception <system.html#OSError>`_.
diff --git a/lib/std/outparams.nim b/lib/std/outparams.nim
index 8a0e5ae67..a471fbaa7 100644
--- a/lib/std/outparams.nim
+++ b/lib/std/outparams.nim
@@ -9,7 +9,7 @@
 
 ## `outParamsAt` macro for easy writing code that works with both 2.0 and 1.x.
 
-import macros
+import std/macros
 
 macro outParamsAt*(positions: static openArray[int]; n: untyped): untyped =
   ## Use this macro to annotate `out` parameters in a portable way.
diff --git a/lib/std/packedsets.nim b/lib/std/packedsets.nim
index 1e2892658..3320558f2 100644
--- a/lib/std/packedsets.nim
+++ b/lib/std/packedsets.nim
@@ -12,17 +12,12 @@
 ##
 ## Supports any Ordinal type.
 ##
-## .. note:: Currently the assignment operator `=` for `PackedSet[A]`
-##   performs some rather meaningless shallow copy. Since Nim currently does
-##   not allow the assignment operator to be overloaded, use the `assign proc
-##   <#assign,PackedSet[A],PackedSet[A]>`_ to get a deep copy.
-##
 ## See also
 ## ========
 ## * `sets module <sets.html>`_ for more general hash sets
 
 import std/private/since
-import hashes
+import std/hashes
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -114,7 +109,6 @@ proc intSetPut[A](t: var PackedSet[A], key: int): Trunk =
   t.data[h] = result
 
 proc bitincl[A](s: var PackedSet[A], key: int) {.inline.} =
-  var ret: Trunk
   var t = intSetPut(s, key shr TrunkShift)
   var u = key and TrunkMask
   t.bits[u shr IntShift] = t.bits[u shr IntShift] or
@@ -204,6 +198,7 @@ proc contains*[A](s: PackedSet[A], key: A): bool =
     assert B notin letters
 
   if s.elems <= s.a.len:
+    result = false
     for i in 0..<s.elems:
       if s.a[i] == ord(key): return true
   else:
@@ -412,18 +407,9 @@ proc isNil*[A](x: PackedSet[A]): bool {.inline.} =
 
   x.head.isNil and x.elems == 0
 
-proc assign*[A](dest: var PackedSet[A], src: PackedSet[A]) =
+proc `=copy`*[A](dest: var PackedSet[A], src: PackedSet[A]) =
   ## Copies `src` to `dest`.
   ## `dest` does not need to be initialized by the `initPackedSet proc <#initPackedSet>`_.
-  runnableExamples:
-    var
-      a = initPackedSet[int]()
-      b = initPackedSet[int]()
-    b.incl(5)
-    b.incl(7)
-    a.assign(b)
-    assert len(a) == 2
-
   if src.elems <= src.a.len:
     dest.data = @[]
     dest.max = 0
@@ -452,6 +438,19 @@ proc assign*[A](dest: var PackedSet[A], src: PackedSet[A]) =
       dest.data[h] = n
       it = it.next
 
+proc assign*[A](dest: var PackedSet[A], src: PackedSet[A]) {.inline, deprecated.} =
+  ## Copies `src` to `dest`.
+  ## `dest` does not need to be initialized by the `initPackedSet proc <#initPackedSet>`_.
+  runnableExamples:
+    var
+      a = initPackedSet[int]()
+      b = initPackedSet[int]()
+    b.incl(5)
+    b.incl(7)
+    a.assign(b)
+    assert len(a) == 2
+  `=copy`(dest, src)
+
 proc union*[A](s1, s2: PackedSet[A]): PackedSet[A] =
   ## Returns the union of the sets `s1` and `s2`.
   ##
diff --git a/lib/std/paths.nim b/lib/std/paths.nim
index c29096982..664dedd31 100644
--- a/lib/std/paths.nim
+++ b/lib/std/paths.nim
@@ -1,4 +1,7 @@
 ## This module implements path handling.
+##
+## **See also:**
+## * `files module <files.html>`_ for file access
 
 import std/private/osseps
 export osseps
@@ -6,7 +9,7 @@ export osseps
 import std/envvars
 import std/private/osappdirs
 
-import pathnorm
+import std/[pathnorm, hashes, sugar, strutils]
 
 from std/private/ospaths2 import  joinPath, splitPath,
                                   ReadDirEffect, WriteDirEffect,
@@ -22,6 +25,16 @@ export ReadDirEffect, WriteDirEffect
 type
   Path* = distinct string
 
+func hash*(x: Path): Hash =
+  let x = x.string.dup(normalizePath)
+  if FileSystemCaseSensitive:
+    result = x.hash
+  else:
+    result = x.toLowerAscii.hash
+
+template `$`*(x: Path): string =
+  string(x)
+
 func `==`*(x, y: Path): bool {.inline.} =
   ## Compares two paths.
   ##
diff --git a/lib/std/private/dbutils.nim b/lib/std/private/dbutils.nim
deleted file mode 100644
index 0ae3b3702..000000000
--- a/lib/std/private/dbutils.nim
+++ /dev/null
@@ -1,15 +0,0 @@
-import db_common
-
-
-template dbFormatImpl*(formatstr: SqlQuery, dbQuote: proc (s: string): string, args: varargs[string]): string =
-  var res = ""
-  var a = 0
-  for c in items(string(formatstr)):
-    if c == '?':
-      if a == args.len:
-        dbError("""The number of "?" given exceeds the number of parameters present in the query.""")
-      add(res, dbQuote(args[a]))
-      inc(a)
-    else:
-      add(res, c)
-  res
diff --git a/lib/std/private/digitsutils.nim b/lib/std/private/digitsutils.nim
index b3dc5d14f..f2d0d25cb 100644
--- a/lib/std/private/digitsutils.nim
+++ b/lib/std/private/digitsutils.nim
@@ -19,7 +19,7 @@ const
 
 # Inspired by https://engineering.fb.com/2013/03/15/developer-tools/three-optimization-tips-for-c
 # Generates:
-# .. code-block:: nim
+#   ```nim
 #   var res = ""
 #   for i in 0 .. 99:
 #     if i < 10:
@@ -27,14 +27,15 @@ const
 #     else:
 #       res.add $i
 #   doAssert res == digits100
+#   ```
 
 proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.} =
   buf[pos] = digits100[2 * digits]
   buf[pos+1] = digits100[2 * digits + 1]
   #copyMem(buf, unsafeAddr(digits100[2 * digits]), 2 * sizeof((char)))
 
-proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} =
-  return trailingZeros100[digits.int8]
+proc trailingZeros2Digits*(digits: uint32): int {.inline.} =
+  trailingZeros100[digits]
 
 when defined(js):
   proc numToString(a: SomeInteger): cstring {.importjs: "((#) + \"\")".}
@@ -101,9 +102,7 @@ proc addInt*(result: var string; x: int64) {.enforceNoRaises.} =
         num = cast[uint64](x)
       else:
         num = uint64(-x)
-      let base = result.len
-      setLen(result, base + 1)
-      result[base] = '-'
+      result.add '-'
     else:
       num = uint64(x)
     addInt(result, num)
diff --git a/lib/std/private/dragonbox.nim b/lib/std/private/dragonbox.nim
index 2ba22a751..85ffea84a 100644
--- a/lib/std/private/dragonbox.nim
+++ b/lib/std/private/dragonbox.nim
@@ -75,10 +75,10 @@ const
 const
   signMask*: BitsType = not (not BitsType(0) shr 1)
 
-proc constructDouble*(bits: BitsType): Double {.constructor.} =
+proc constructDouble*(bits: BitsType): Double  =
   result.bits = bits
 
-proc constructDouble*(value: ValueType): Double {.constructor.} =
+proc constructDouble*(value: ValueType): Double  =
   result.bits = cast[typeof(result.bits)](value)
 
 proc physicalSignificand*(this: Double): BitsType {.noSideEffect.} =
@@ -1052,7 +1052,7 @@ when false:
   proc memset(x: cstring; ch: char; L: int) {.importc, nodecl.}
   proc memmove(a, b: cstring; L: int) {.importc, nodecl.}
 
-proc utoa8DigitsSkipTrailingZeros*(buf: var openArray[char]; pos: int; digits: uint32): int32 {.inline.} =
+proc utoa8DigitsSkipTrailingZeros*(buf: var openArray[char]; pos: int; digits: uint32): int {.inline.} =
   dragonbox_Assert(digits >= 1)
   dragonbox_Assert(digits <= 99999999'u32)
   let q: uint32 = digits div 10000
@@ -1070,12 +1070,12 @@ proc utoa8DigitsSkipTrailingZeros*(buf: var openArray[char]; pos: int; digits: u
     utoa2Digits(buf, pos + 6, rL)
     return trailingZeros2Digits(if rL == 0: rH else: rL) + (if rL == 0: 2 else: 0)
 
-proc printDecimalDigitsBackwards*(buf: var openArray[char]; pos: int; output64: uint64): int32 {.inline.} =
+proc printDecimalDigitsBackwards*(buf: var openArray[char]; pos: int; output64: uint64): int {.inline.} =
   var pos = pos
   var output64 = output64
-  var tz: int32 = 0
+  var tz = 0
   ##  number of trailing zeros removed.
-  var nd: int32 = 0
+  var nd = 0
   ##  number of decimal digits processed.
   ##  At most 17 digits remaining
   if output64 >= 100000000'u64:
@@ -1220,7 +1220,7 @@ proc formatDigits*[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint
     ##  dE+123 or d.igitsE+123
     decimalDigitsPosition = 1
   var digitsEnd = pos + int(decimalDigitsPosition + numDigits)
-  let tz: int32 = printDecimalDigitsBackwards(buffer, digitsEnd, digits)
+  let tz = printDecimalDigitsBackwards(buffer, digitsEnd, digits)
   dec(digitsEnd, tz)
   dec(numDigits, tz)
   ##   decimal_exponent += tz; // => decimal_point unchanged.
diff --git a/lib/std/private/gitutils.nim b/lib/std/private/gitutils.nim
index db323bee1..6dc9c8f3b 100644
--- a/lib/std/private/gitutils.nim
+++ b/lib/std/private/gitutils.nim
@@ -4,7 +4,7 @@ internal API for now, API subject to change
 
 # xxx move other git utilities here; candidate for stdlib.
 
-import std/[os, osproc, strutils, tempfiles]
+import std/[os, paths, osproc, strutils, tempfiles]
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, syncio]
@@ -32,15 +32,8 @@ template retryCall*(maxRetry = 3, backoffDuration = 1.0, call: untyped): bool =
   result
 
 proc isGitRepo*(dir: string): bool =
-  ## This command is used to get the relative path to the root of the repository.
-  ## Using this, we can verify whether a folder is a git repository by checking
-  ## whether the command success and if the output is empty.
-  let (output, status) = execCmdEx("git rev-parse --show-cdup", workingDir = dir)
-  # On Windows there will be a trailing newline on success, remove it.
-  # The value of a successful call typically won't have a whitespace (it's
-  # usually a series of ../), so we know that it's safe to unconditionally
-  # remove trailing whitespaces from the result.
-  result = status == 0 and output.strip() == ""
+  ## Avoid calling git since it depends on /bin/sh existing and fails in Nix.
+  return fileExists(dir/".git/HEAD")
 
 proc diffFiles*(path1, path2: string): tuple[output: string, same: bool] =
   ## Returns a human readable diff of files `path1`, `path2`, the exact form of
diff --git a/lib/std/private/globs.nim b/lib/std/private/globs.nim
index 5e3e33cb4..a6d088558 100644
--- a/lib/std/private/globs.nim
+++ b/lib/std/private/globs.nim
@@ -4,9 +4,9 @@ this can eventually be moved to std/os and `walkDirRec` can be implemented in te
 to avoid duplication
 ]##
 
-import os
+import std/os
 when defined(windows):
-  from strutils import replace
+  from std/strutils import replace
 
 when defined(nimPreviewSlimSystem):
   import std/[assertions, objectdollar]
@@ -60,11 +60,11 @@ proc nativeToUnixPath*(path: string): string =
       result[0] = '/'
       result[1] = path[0]
       if path.len > 2 and path[2] != '\\':
-        doAssert false, "paths like `C:foo` are currently unsupported, path: " & path
+        raiseAssert "paths like `C:foo` are currently unsupported, path: " & path
   when DirSep == '\\':
     result = replace(result, '\\', '/')
 
 when isMainModule:
-  import sugar
+  import std/sugar
   for a in walkDirRecFilter(".", follow = a=>a.path.lastPathPart notin ["nimcache", ".git", "csources_v1", "csources", "bin"]):
     echo a
diff --git a/lib/std/private/jsutils.nim b/lib/std/private/jsutils.nim
index 836b3512a..5f79eab27 100644
--- a/lib/std/private/jsutils.nim
+++ b/lib/std/private/jsutils.nim
@@ -37,13 +37,13 @@ when defined(js):
       let a = array[2, float64].default
       assert jsConstructorName(a) == "Float64Array"
       assert jsConstructorName(a.toJs) == "Float64Array"
-    asm """`result` = `a`.constructor.name"""
+    {.emit: """`result` = `a`.constructor.name;""".}
 
   proc hasJsBigInt*(): bool =
-    asm """`result` = typeof BigInt != 'undefined'"""
+    {.emit: """`result` = typeof BigInt != 'undefined';""".}
 
   proc hasBigUint64Array*(): bool =
-    asm """`result` = typeof BigUint64Array != 'undefined'"""
+    {.emit: """`result` = typeof BigUint64Array != 'undefined';""".}
 
   proc getProtoName*[T](a: T): cstring {.importjs: "Object.prototype.toString.call(#)".} =
     runnableExamples:
@@ -79,5 +79,18 @@ when defined(js):
       assert not "123".toJs.isSafeInteger
       assert 123.isSafeInteger
       assert 123.toJs.isSafeInteger
-      assert 9007199254740991.toJs.isSafeInteger
-      assert not 9007199254740992.toJs.isSafeInteger
+      when false:
+        assert 9007199254740991.toJs.isSafeInteger
+        assert not 9007199254740992.toJs.isSafeInteger
+
+template whenJsNoBigInt64*(no64, yes64): untyped =
+  when defined(js):
+    when compiles(compileOption("jsbigint64")):
+      when compileOption("jsbigint64"):
+        yes64
+      else:
+        no64
+    else:
+      no64
+  else:
+    no64
diff --git a/lib/std/private/miscdollars.nim b/lib/std/private/miscdollars.nim
index 47b788ee9..06fda6fa1 100644
--- a/lib/std/private/miscdollars.nim
+++ b/lib/std/private/miscdollars.nim
@@ -13,21 +13,7 @@ template toLocation*(result: var string, file: string | cstring, line: int, col:
       addInt(result, col)
     result.add ")"
 
-when defined(nimHasIsNamedTuple):
-  proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
-else:
-  # for bootstrap; remove after release 1.2
-  proc isNamedTuple(T: typedesc): bool =
-    # Taken from typetraits.
-    when T isnot tuple: result = false
-    else:
-      var t: T
-      for name, _ in t.fieldPairs:
-        when name == "Field0":
-          return compiles(t.Field0)
-        else:
-          return true
-      return false
+proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
 
 template tupleObjectDollar*[T: tuple | object](result: var string, x: T) =
   result = "("
diff --git a/lib/std/private/osappdirs.nim b/lib/std/private/osappdirs.nim
index 8e6ae00f8..07a6809bb 100644
--- a/lib/std/private/osappdirs.nim
+++ b/lib/std/private/osappdirs.nim
@@ -1,3 +1,5 @@
+## .. importdoc:: paths.nim, dirs.nim
+
 include system/inclrtl
 import std/envvars
 import std/private/ospaths2
@@ -10,6 +12,7 @@ proc getHomeDir*(): string {.rtl, extern: "nos$1",
   ## for the convenience of processing paths coming from user configuration files.
   ##
   ## See also:
+  ## * `getDataDir proc`_
   ## * `getConfigDir proc`_
   ## * `getTempDir proc`_
   ## * `expandTilde proc`_
@@ -22,6 +25,30 @@ proc getHomeDir*(): string {.rtl, extern: "nos$1",
   when defined(windows): return getEnv("USERPROFILE") & "\\"
   else: return getEnv("HOME") & "/"
 
+proc getDataDir*(): string {.rtl, extern: "nos$1"
+  tags: [ReadEnvEffect, ReadIOEffect].} =
+  ## Returns the data directory of the current user for applications.
+  ## 
+  ## On non-Windows OSs, this proc conforms to the XDG Base Directory
+  ## spec. Thus, this proc returns the value of the `XDG_DATA_HOME` environment
+  ## variable if it is set, otherwise it returns the default configuration
+  ## directory ("~/.local/share" or "~/Library/Application Support" on macOS).
+  ## 
+  ## See also:
+  ## * `getHomeDir proc`_
+  ## * `getConfigDir proc`_
+  ## * `getTempDir proc`_
+  ## * `expandTilde proc`_
+  ## * `getCurrentDir proc`_
+  ## * `setCurrentDir proc`_
+  when defined(windows):
+    result = getEnv("APPDATA")
+  elif defined(macosx):
+    result = getEnv("XDG_DATA_HOME", getEnv("HOME") / "Library" / "Application Support")
+  else:
+    result = getEnv("XDG_DATA_HOME", getEnv("HOME") / ".local" / "share")
+  result.normalizePathEnd(trailingSep = true)
+
 proc getConfigDir*(): string {.rtl, extern: "nos$1",
   tags: [ReadEnvEffect, ReadIOEffect].} =
   ## Returns the config directory of the current user for applications.
@@ -36,6 +63,7 @@ proc getConfigDir*(): string {.rtl, extern: "nos$1",
   ##
   ## See also:
   ## * `getHomeDir proc`_
+  ## * `getDataDir proc`_
   ## * `getTempDir proc`_
   ## * `expandTilde proc`_
   ## * `getCurrentDir proc`_
@@ -61,6 +89,7 @@ proc getCacheDir*(): string =
   ## * `getHomeDir proc`_
   ## * `getTempDir proc`_
   ## * `getConfigDir proc`_
+  ## * `getDataDir proc`_
   # follows https://crates.io/crates/platform-dirs
   when defined(windows):
     result = getEnv("LOCALAPPDATA")
diff --git a/lib/std/private/oscommon.nim b/lib/std/private/oscommon.nim
index 5b4e1d7e3..c49d52ef2 100644
--- a/lib/std/private/oscommon.nim
+++ b/lib/std/private/oscommon.nim
@@ -5,6 +5,8 @@ import std/[oserrors]
 when defined(nimPreviewSlimSystem):
   import std/[syncio, assertions, widestrs]
 
+## .. importdoc:: osdirs.nim, os.nim
+
 const weirdTarget* = defined(nimscript) or defined(js)
 
 
@@ -20,9 +22,9 @@ type
 when weirdTarget:
   discard
 elif defined(windows):
-  import winlean, times
+  import std/[winlean, times]
 elif defined(posix):
-  import posix
+  import std/posix
   proc c_rename(oldname, newname: cstring): cint {.
     importc: "rename", header: "<stdio.h>".}
 else:
@@ -45,23 +47,17 @@ else:
 
 
 when defined(windows) and not weirdTarget:
-  when useWinUnicode:
-    template wrapUnary*(varname, winApiProc, arg: untyped) =
-      var varname = winApiProc(newWideCString(arg))
-
-    template wrapBinary*(varname, winApiProc, arg, arg2: untyped) =
-      var varname = winApiProc(newWideCString(arg), arg2)
-    proc findFirstFile*(a: string, b: var WIN32_FIND_DATA): Handle =
-      result = findFirstFileW(newWideCString(a), b)
-    template findNextFile*(a, b: untyped): untyped = findNextFileW(a, b)
-
-    template getFilename*(f: untyped): untyped =
-      $cast[WideCString](addr(f.cFileName[0]))
-  else:
-    template findFirstFile*(a, b: untyped): untyped = findFirstFileA(a, b)
-    template findNextFile*(a, b: untyped): untyped = findNextFileA(a, b)
+  template wrapUnary*(varname, winApiProc, arg: untyped) =
+    var varname = winApiProc(newWideCString(arg))
+
+  template wrapBinary*(varname, winApiProc, arg, arg2: untyped) =
+    var varname = winApiProc(newWideCString(arg), arg2)
+  proc findFirstFile*(a: string, b: var WIN32_FIND_DATA): Handle =
+    result = findFirstFileW(newWideCString(a), b)
+  template findNextFile*(a, b: untyped): untyped = findNextFileW(a, b)
 
-    template getFilename*(f: untyped): untyped = $cast[cstring](addr f.cFileName)
+  template getFilename*(f: untyped): untyped =
+    $cast[WideCString](addr(f.cFileName[0]))
 
   proc skipFindData*(f: WIN32_FIND_DATA): bool {.inline.} =
     # Note - takes advantage of null delimiter in the cstring
@@ -102,12 +98,9 @@ proc tryMoveFSObject*(source, dest: string, isDir: bool): bool {.noWeirdTarget.}
   ## In case of other errors `OSError` is raised.
   ## Returns true in case of success.
   when defined(windows):
-    when useWinUnicode:
-      let s = newWideCString(source)
-      let d = newWideCString(dest)
-      result = moveFileExW(s, d, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
-    else:
-      result = moveFileExA(source, dest, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
+    let s = newWideCString(source)
+    let d = newWideCString(dest)
+    result = moveFileExW(s, d, MOVEFILE_COPY_ALLOWED or MOVEFILE_REPLACE_EXISTING) != 0'i32
   else:
     result = c_rename(source, dest) == 0'i32
 
@@ -126,7 +119,7 @@ when not defined(windows):
   const maxSymlinkLen* = 1024
 
 proc fileExists*(filename: string): bool {.rtl, extern: "nos$1",
-                                          tags: [ReadDirEffect], noNimJs.} =
+                                          tags: [ReadDirEffect], noNimJs, sideEffect.} =
   ## Returns true if `filename` exists and is a regular file or symlink.
   ##
   ## Directories, device files, named pipes and sockets return false.
@@ -135,10 +128,7 @@ proc fileExists*(filename: string): bool {.rtl, extern: "nos$1",
   ## * `dirExists proc`_
   ## * `symlinkExists proc`_
   when defined(windows):
-    when useWinUnicode:
-      wrapUnary(a, getFileAttributesW, filename)
-    else:
-      var a = getFileAttributesA(filename)
+    wrapUnary(a, getFileAttributesW, filename)
     if a != -1'i32:
       result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32
   else:
@@ -147,7 +137,7 @@ proc fileExists*(filename: string): bool {.rtl, extern: "nos$1",
 
 
 proc dirExists*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect],
-                                     noNimJs.} =
+                                     noNimJs, sideEffect.} =
   ## Returns true if the directory `dir` exists. If `dir` is a file, false
   ## is returned. Follows symlinks.
   ##
@@ -155,10 +145,7 @@ proc dirExists*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect]
   ## * `fileExists proc`_
   ## * `symlinkExists proc`_
   when defined(windows):
-    when useWinUnicode:
-      wrapUnary(a, getFileAttributesW, dir)
-    else:
-      var a = getFileAttributesA(dir)
+    wrapUnary(a, getFileAttributesW, dir)
     if a != -1'i32:
       result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32
   else:
@@ -168,7 +155,7 @@ proc dirExists*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect]
 
 proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
                                           tags: [ReadDirEffect],
-                                          noWeirdTarget.} =
+                                          noWeirdTarget, sideEffect.} =
   ## Returns true if the symlink `link` exists. Will return true
   ## regardless of whether the link points to a directory or file.
   ##
@@ -176,10 +163,7 @@ proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
   ## * `fileExists proc`_
   ## * `dirExists proc`_
   when defined(windows):
-    when useWinUnicode:
-      wrapUnary(a, getFileAttributesW, link)
-    else:
-      var a = getFileAttributesA(link)
+    wrapUnary(a, getFileAttributesW, link)
     if a != -1'i32:
       # xxx see: bug #16784 (bug9); checking `IO_REPARSE_TAG_SYMLINK`
       # may also be needed.
@@ -195,15 +179,8 @@ when defined(windows) and not weirdTarget:
       flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
     let access = if writeAccess: GENERIC_WRITE else: 0'i32
 
-    when useWinUnicode:
-      result = createFileW(
-        newWideCString(path), access,
-        FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
-        nil, OPEN_EXISTING, flags, 0
-        )
-    else:
-      result = createFileA(
-        path, access,
-        FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
-        nil, OPEN_EXISTING, flags, 0
-        )
+    result = createFileW(
+      newWideCString(path), access,
+      FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE,
+      nil, OPEN_EXISTING, flags, 0
+      )
diff --git a/lib/std/private/osdirs.nim b/lib/std/private/osdirs.nim
index add9ed424..a44cad7d9 100644
--- a/lib/std/private/osdirs.nim
+++ b/lib/std/private/osdirs.nim
@@ -1,3 +1,5 @@
+## .. importdoc:: osfiles.nim, appdirs.nim, paths.nim
+
 include system/inclrtl
 import std/oserrors
 
@@ -14,9 +16,9 @@ when defined(nimPreviewSlimSystem):
 when weirdTarget:
   discard
 elif defined(windows):
-  import winlean, times
+  import std/[winlean, times]
 elif defined(posix):
-  import posix, times
+  import std/[posix, times]
 
 else:
   {.error: "OS module not ported to your operating system!".}
@@ -326,10 +328,7 @@ iterator walkDirRec*(dir: string,
 
 proc rawRemoveDir(dir: string) {.noWeirdTarget.} =
   when defined(windows):
-    when useWinUnicode:
-      wrapUnary(res, removeDirectoryW, dir)
-    else:
-      var res = removeDirectoryA(dir)
+    wrapUnary(res, removeDirectoryW, dir)
     let lastError = osLastError()
     if res == 0'i32 and lastError.int32 != 3'i32 and
         lastError.int32 != 18'i32 and lastError.int32 != 2'i32:
@@ -394,10 +393,7 @@ proc rawCreateDir(dir: string): bool {.noWeirdTarget.} =
       #echo res
       raiseOSError(osLastError(), dir)
   else:
-    when useWinUnicode:
-      wrapUnary(res, createDirectoryW, dir)
-    else:
-      let res = createDirectoryA(dir)
+    wrapUnary(res, createDirectoryW, dir)
 
     if res != 0'i32:
       result = true
@@ -450,13 +446,17 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1",
     else:
       discard existsOrCreateDir(p)
 
-proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
+proc copyDir*(source, dest: string, skipSpecial = false) {.rtl, extern: "nos$1",
   tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect], benign, noWeirdTarget.} =
   ## Copies a directory from `source` to `dest`.
   ##
   ## On non-Windows OSes, symlinks are copied as symlinks. On Windows, symlinks
   ## are skipped.
   ##
+  ## If `skipSpecial` is true, then (besides all directories) only *regular*
+  ## files (**without** special "file" objects like FIFOs, device files,
+  ## etc) will be copied on Unix.
+  ##
   ## If this fails, `OSError` is raised.
   ##
   ## On the Windows platform this proc will copy the attributes from
@@ -476,16 +476,17 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1",
   ## * `createDir proc`_
   ## * `moveDir proc`_
   createDir(dest)
-  for kind, path in walkDir(source):
+  for kind, path in walkDir(source, skipSpecial = skipSpecial):
     var noSource = splitPath(path).tail
     if kind == pcDir:
-      copyDir(path, dest / noSource)
+      copyDir(path, dest / noSource, skipSpecial = skipSpecial)
     else:
       copyFile(path, dest / noSource, {cfSymlinkAsIs})
 
 
 proc copyDirWithPermissions*(source, dest: string,
-                             ignorePermissionErrors = true)
+                             ignorePermissionErrors = true,
+                             skipSpecial = false)
   {.rtl, extern: "nos$1", tags: [ReadDirEffect, WriteIOEffect, ReadIOEffect],
    benign, noWeirdTarget.} =
   ## Copies a directory from `source` to `dest` preserving file permissions.
@@ -493,6 +494,10 @@ proc copyDirWithPermissions*(source, dest: string,
   ## On non-Windows OSes, symlinks are copied as symlinks. On Windows, symlinks
   ## are skipped.
   ##
+  ## If `skipSpecial` is true, then (besides all directories) only *regular*
+  ## files (**without** special "file" objects like FIFOs, device files,
+  ## etc) will be copied on Unix.
+  ##
   ## If this fails, `OSError` is raised. This is a wrapper proc around
   ## `copyDir`_ and `copyFileWithPermissions`_ procs
   ## on non-Windows platforms.
@@ -522,10 +527,10 @@ proc copyDirWithPermissions*(source, dest: string,
     except:
       if not ignorePermissionErrors:
         raise
-  for kind, path in walkDir(source):
+  for kind, path in walkDir(source, skipSpecial = skipSpecial):
     var noSource = splitPath(path).tail
     if kind == pcDir:
-      copyDirWithPermissions(path, dest / noSource, ignorePermissionErrors)
+      copyDirWithPermissions(path, dest / noSource, ignorePermissionErrors, skipSpecial = skipSpecial)
     else:
       copyFileWithPermissions(path, dest / noSource, ignorePermissionErrors, {cfSymlinkAsIs})
 
@@ -559,10 +564,7 @@ proc setCurrentDir*(newDir: string) {.inline, tags: [], noWeirdTarget.} =
   ## * `getTempDir proc`_
   ## * `getCurrentDir proc`_
   when defined(windows):
-    when useWinUnicode:
-      if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
-        raiseOSError(osLastError(), newDir)
-    else:
-      if setCurrentDirectoryA(newDir) == 0'i32: raiseOSError(osLastError(), newDir)
+    if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32:
+      raiseOSError(osLastError(), newDir)
   else:
     if chdir(newDir) != 0'i32: raiseOSError(osLastError(), newDir)
diff --git a/lib/std/private/osfiles.nim b/lib/std/private/osfiles.nim
index 301f14600..37d8eabca 100644
--- a/lib/std/private/osfiles.nim
+++ b/lib/std/private/osfiles.nim
@@ -7,6 +7,7 @@ export fileExists
 
 import ospaths2, ossymlinks
 
+## .. importdoc:: osdirs.nim, os.nim
 
 when defined(nimPreviewSlimSystem):
   import std/[syncio, assertions, widestrs]
@@ -14,9 +15,9 @@ when defined(nimPreviewSlimSystem):
 when weirdTarget:
   discard
 elif defined(windows):
-  import winlean
+  import std/winlean
 elif defined(posix):
-  import posix, times
+  import std/[posix, times]
 
   proc toTime(ts: Timespec): times.Time {.inline.} =
     result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
@@ -83,10 +84,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {.
     if (a.st_mode and S_IWOTH.Mode) != 0.Mode: result.incl(fpOthersWrite)
     if (a.st_mode and S_IXOTH.Mode) != 0.Mode: result.incl(fpOthersExec)
   else:
-    when useWinUnicode:
-      wrapUnary(res, getFileAttributesW, filename)
-    else:
-      var res = getFileAttributesA(filename)
+    wrapUnary(res, getFileAttributesW, filename)
     if res == -1'i32: raiseOSError(osLastError(), filename)
     if (res and FILE_ATTRIBUTE_READONLY) != 0'i32:
       result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead,
@@ -135,19 +133,13 @@ proc setFilePermissions*(filename: string, permissions: set[FilePermission],
       if chmod(filename, cast[Mode](p)) != 0:
         raiseOSError(osLastError(), $(filename, permissions))
   else:
-    when useWinUnicode:
-      wrapUnary(res, getFileAttributesW, filename)
-    else:
-      var res = getFileAttributesA(filename)
+    wrapUnary(res, getFileAttributesW, filename)
     if res == -1'i32: raiseOSError(osLastError(), filename)
     if fpUserWrite in permissions:
       res = res and not FILE_ATTRIBUTE_READONLY
     else:
       res = res or FILE_ATTRIBUTE_READONLY
-    when useWinUnicode:
-      wrapBinary(res2, setFileAttributesW, filename, res)
-    else:
-      var res2 = setFileAttributesA(filename, res)
+    wrapBinary(res2, setFileAttributesW, filename, res)
     if res2 == - 1'i32: raiseOSError(osLastError(), $(filename, permissions))
 
 
@@ -163,10 +155,14 @@ when hasCCopyfile:
   proc copyfile_state_alloc(): copyfile_state_t
   proc copyfile_state_free(state: copyfile_state_t): cint
   proc c_copyfile(src, dst: cstring,  state: copyfile_state_t, flags: copyfile_flags_t): cint {.importc: "copyfile".}
-  # replace with `let` pending bootstrap >= 1.4.0
-  var
-    COPYFILE_DATA {.nodecl.}: copyfile_flags_t
-    COPYFILE_XATTR {.nodecl.}: copyfile_flags_t
+  when (NimMajor, NimMinor) >= (1, 4):
+    let
+      COPYFILE_DATA {.nodecl.}: copyfile_flags_t
+      COPYFILE_XATTR {.nodecl.}: copyfile_flags_t
+  else:
+    var
+      COPYFILE_DATA {.nodecl.}: copyfile_flags_t
+      COPYFILE_XATTR {.nodecl.}: copyfile_flags_t
   {.pop.}
 
 type
@@ -177,7 +173,7 @@ type
 
 const copyFlagSymlink = {cfSymlinkAsIs, cfSymlinkFollow, cfSymlinkIgnore}
 
-proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl,
+proc copyFile*(source, dest: string, options = {cfSymlinkFollow}; bufferSize = 16_384) {.rtl,
   extern: "nos$1", tags: [ReadDirEffect, ReadIOEffect, WriteIOEffect],
   noWeirdTarget.} =
   ## Copies a file from `source` to `dest`, where `dest.parentDir` must exist.
@@ -206,6 +202,8 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl,
   ## On OSX, `copyfile` C api will be used (available since OSX 10.5) unless
   ## `-d:nimLegacyCopyFile` is used.
   ##
+  ## `copyFile` allows to specify `bufferSize` to improve I/O performance.
+  ##
   ## See also:
   ## * `CopyFlag enum`_
   ## * `copyDir proc`_
@@ -214,20 +212,15 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl,
   ## * `removeFile proc`_
   ## * `moveFile proc`_
 
-  doAssert card(copyFlagSymlink * options) == 1, "There should be exactly " &
-                                                 "one cfSymlink* in options"
+  doAssert card(copyFlagSymlink * options) == 1, "There should be exactly one cfSymlink* in options"
   let isSymlink = source.symlinkExists
   if isSymlink and (cfSymlinkIgnore in options or defined(windows)):
     return
   when defined(windows):
-    when useWinUnicode:
-      let s = newWideCString(source)
-      let d = newWideCString(dest)
-      if copyFileW(s, d, 0'i32) == 0'i32:
-        raiseOSError(osLastError(), $(source, dest))
-    else:
-      if copyFileA(source, dest, 0'i32) == 0'i32:
-        raiseOSError(osLastError(), $(source, dest))
+    let s = newWideCString(source)
+    let d = newWideCString(dest)
+    if copyFileW(s, d, 0'i32) == 0'i32:
+      raiseOSError(osLastError(), $(source, dest))
   else:
     if isSymlink and cfSymlinkAsIs in options:
       createSymlink(expandSymlink(source), dest)
@@ -246,15 +239,21 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl,
         if status2 != 0: raiseOSError(osLastError(), $(source, dest))
       else:
         # generic version of copyFile which works for any platform:
-        const bufSize = 8000 # better for memory manager
         var d, s: File
-        if not open(s, source):raiseOSError(osLastError(), source)
+        if not open(s, source): raiseOSError(osLastError(), source)
         if not open(d, dest, fmWrite):
           close(s)
           raiseOSError(osLastError(), dest)
-        var buf = alloc(bufSize)
+
+        # Hints for kernel-level aggressive sequential low-fragmentation read-aheads:
+        # https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_fadvise.html
+        when defined(linux) or defined(osx):
+          discard posix_fadvise(getFileHandle(d), 0.cint, 0.cint, POSIX_FADV_SEQUENTIAL)
+          discard posix_fadvise(getFileHandle(s), 0.cint, 0.cint, POSIX_FADV_SEQUENTIAL)
+
+        var buf = alloc(bufferSize)
         while true:
-          var bytesread = readBuffer(s, buf, bufSize)
+          var bytesread = readBuffer(s, buf, bufferSize)
           if bytesread > 0:
             var byteswritten = writeBuffer(d, buf, bytesread)
             if bytesread != byteswritten:
@@ -262,13 +261,13 @@ proc copyFile*(source, dest: string, options = {cfSymlinkFollow}) {.rtl,
               close(s)
               close(d)
               raiseOSError(osLastError(), dest)
-          if bytesread != bufSize: break
+          if bytesread != bufferSize: break
         dealloc(buf)
         close(s)
         flushFile(d)
         close(d)
 
-proc copyFileToDir*(source, dir: string, options = {cfSymlinkFollow})
+proc copyFileToDir*(source, dir: string, options = {cfSymlinkFollow}; bufferSize = 16_384)
   {.noWeirdTarget, since: (1,3,7).} =
   ## Copies a file `source` into directory `dir`, which must exist.
   ##
@@ -276,12 +275,14 @@ proc copyFileToDir*(source, dir: string, options = {cfSymlinkFollow})
   ## if `source` is a symlink, copies the file symlink points to. `options` is
   ## ignored on Windows: symlinks are skipped.
   ##
+  ## `copyFileToDir` allows to specify `bufferSize` to improve I/O performance.
+  ##
   ## See also:
   ## * `CopyFlag enum`_
   ## * `copyFile proc`_
   if dir.len == 0: # treating "" as "." is error prone
     raise newException(ValueError, "dest is empty")
-  copyFile(source, dir / source.lastPathPart, options)
+  copyFile(source, dir / source.lastPathPart, options, bufferSize)
 
 
 proc copyFileWithPermissions*(source, dest: string,
@@ -333,14 +334,9 @@ when not declared(ENOENT) and not defined(windows):
     var ENOENT {.importc, header: "<errno.h>".}: cint
 
 when defined(windows) and not weirdTarget:
-  when useWinUnicode:
-    template deleteFile(file: untyped): untyped  = deleteFileW(file)
-    template setFileAttributes(file, attrs: untyped): untyped =
-      setFileAttributesW(file, attrs)
-  else:
-    template deleteFile(file: untyped): untyped = deleteFileA(file)
-    template setFileAttributes(file, attrs: untyped): untyped =
-      setFileAttributesA(file, attrs)
+  template deleteFile(file: untyped): untyped  = deleteFileW(file)
+  template setFileAttributes(file, attrs: untyped): untyped =
+    setFileAttributesW(file, attrs)
 
 proc tryRemoveFile*(file: string): bool {.rtl, extern: "nos$1", tags: [WriteDirEffect], noWeirdTarget.} =
   ## Removes the `file`.
@@ -357,10 +353,7 @@ proc tryRemoveFile*(file: string): bool {.rtl, extern: "nos$1", tags: [WriteDirE
   ## * `moveFile proc`_
   result = true
   when defined(windows):
-    when useWinUnicode:
-      let f = newWideCString(file)
-    else:
-      let f = file
+    let f = newWideCString(file)
     if deleteFile(f) == 0:
       result = false
       let err = getLastError()
@@ -412,12 +405,12 @@ proc moveFile*(source, dest: string) {.rtl, extern: "nos$1",
 
   if not tryMoveFSObject(source, dest, isDir = false):
     when defined(windows):
-      doAssert false
+      raiseAssert "unreachable"
     else:
       # Fallback to copy & del
-      copyFile(source, dest, {cfSymlinkAsIs})
+      copyFileWithPermissions(source, dest, options={cfSymlinkAsIs})
       try:
         removeFile(source)
       except:
         discard tryRemoveFile(dest)
-        raise
\ No newline at end of file
+        raise
diff --git a/lib/std/private/ospaths2.nim b/lib/std/private/ospaths2.nim
index 75c34ecf5..bc69ff725 100644
--- a/lib/std/private/ospaths2.nim
+++ b/lib/std/private/ospaths2.nim
@@ -1,7 +1,7 @@
 include system/inclrtl
 import std/private/since
 
-import strutils, pathnorm
+import std/[strutils, pathnorm]
 import std/oserrors
 
 import oscommon
@@ -10,14 +10,16 @@ export ReadDirEffect, WriteDirEffect
 when defined(nimPreviewSlimSystem):
   import std/[syncio, assertions, widestrs]
 
+## .. importdoc:: osappdirs.nim, osdirs.nim, osseps.nim, os.nim
+
 const weirdTarget = defined(nimscript) or defined(js)
 
 when weirdTarget:
   discard
 elif defined(windows):
-  import winlean
+  import std/winlean
 elif defined(posix):
-  import posix, system/ansi_c
+  import std/posix, system/ansi_c
 else:
   {.error: "OS module not ported to your operating system!".}
 
@@ -252,12 +254,12 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1", raise
     result = path[0] != ':'
   elif defined(RISCOS):
     result = path[0] == '$'
-  elif defined(posix) or defined(js):
-    # `or defined(js)` wouldn't be needed pending https://github.com/nim-lang/Nim/issues/13469
-    # This works around the problem for posix, but Windows is still broken with nim js -d:nodejs
+  elif defined(posix):
     result = path[0] == '/'
+  elif defined(nodejs):
+    {.emit: [result," = require(\"path\").isAbsolute(",path.cstring,");"].}
   else:
-    doAssert false # if ever hits here, adapt as needed
+    raiseAssert "unreachable" # if ever hits here, adapt as needed
 
 when FileSystemCaseSensitive:
   template `!=?`(a, b: char): bool = a != b
@@ -569,7 +571,7 @@ proc normExt(ext: string): string =
 
 proc searchExtPos*(path: string): int =
   ## Returns index of the `'.'` char in `path` if it signifies the beginning
-  ## of extension. Returns -1 otherwise.
+  ## of the file extension. Returns -1 otherwise.
   ##
   ## See also:
   ## * `splitFile proc`_
@@ -582,15 +584,28 @@ proc searchExtPos*(path: string): int =
     assert searchExtPos("c.nim") == 1
     assert searchExtPos("a/b/c.nim") == 5
     assert searchExtPos("a.b.c.nim") == 5
+    assert searchExtPos(".nim") == -1
+    assert searchExtPos("..nim") == -1
+    assert searchExtPos("a..nim") == 2
 
-  # BUGFIX: do not search until 0! .DS_Store is no file extension!
+  # Unless there is any char that is not `ExtSep` before last `ExtSep` in the file name,
+  # it is not a file extension.
+  const DirSeps = when doslikeFileSystem: {DirSep, AltSep, ':'} else: {DirSep, AltSep}
   result = -1
-  for i in countdown(len(path)-1, 1):
+  var i = path.high
+  while i >= 1:
     if path[i] == ExtSep:
+      break
+    elif path[i] in DirSeps:
+      return -1 # do not skip over path
+    dec i
+
+  for j in countdown(i - 1, 0):
+    if path[j] in DirSeps:
+      return -1
+    elif path[j] != ExtSep:
       result = i
       break
-    elif path[i] in {DirSep, AltSep}:
-      break # do not skip over path
 
 proc splitFile*(path: string): tuple[dir, name, ext: string] {.
   noSideEffect, rtl, extern: "nos$1".} =
@@ -748,9 +763,9 @@ proc cmpPaths*(pathA, pathB: string): int {.
   ## On a case-sensitive filesystem this is done
   ## case-sensitively otherwise case-insensitively. Returns:
   ##
-  ## | 0 if pathA == pathB
-  ## | < 0 if pathA < pathB
-  ## | > 0 if pathA > pathB
+  ## | `0` if pathA == pathB
+  ## | `< 0` if pathA < pathB
+  ## | `> 0` if pathA > pathB
   runnableExamples:
     when defined(macosx):
       assert cmpPaths("foo", "Foo") == 0
@@ -844,33 +859,20 @@ when not defined(nimscript):
       {.emit: "`ret` = process.cwd();".}
       return $ret
     elif defined(js):
-      doAssert false, "use -d:nodejs to have `getCurrentDir` defined"
+      raiseAssert "use -d:nodejs to have `getCurrentDir` defined"
     elif defined(windows):
       var bufsize = MAX_PATH.int32
-      when useWinUnicode:
-        var res = newWideCString("", bufsize)
-        while true:
-          var L = getCurrentDirectoryW(bufsize, res)
-          if L == 0'i32:
-            raiseOSError(osLastError())
-          elif L > bufsize:
-            res = newWideCString("", L)
-            bufsize = L
-          else:
-            result = res$L
-            break
-      else:
-        result = newString(bufsize)
-        while true:
-          var L = getCurrentDirectoryA(bufsize, result)
-          if L == 0'i32:
-            raiseOSError(osLastError())
-          elif L > bufsize:
-            result = newString(L)
-            bufsize = L
-          else:
-            setLen(result, L)
-            break
+      var res = newWideCString(bufsize)
+      while true:
+        var L = getCurrentDirectoryW(bufsize, res)
+        if L == 0'i32:
+          raiseOSError(osLastError())
+        elif L > bufsize:
+          res = newWideCString(L)
+          bufsize = L
+        else:
+          result = res$L
+          break
     else:
       var bufsize = 1024 # should be enough
       result = newString(bufsize)
diff --git a/lib/std/private/osseps.nim b/lib/std/private/osseps.nim
index 1ea587e3c..f2d49d886 100644
--- a/lib/std/private/osseps.nim
+++ b/lib/std/private/osseps.nim
@@ -3,6 +3,8 @@
 
 # Improved based on info in 'compiler/platform.nim'
 
+## .. importdoc:: ospaths2.nim
+
 const
   doslikeFileSystem* = defined(windows) or defined(OS2) or defined(DOS)
 
diff --git a/lib/std/private/ossymlinks.nim b/lib/std/private/ossymlinks.nim
index cb6287bde..c1760c42e 100644
--- a/lib/std/private/ossymlinks.nim
+++ b/lib/std/private/ossymlinks.nim
@@ -10,9 +10,9 @@ when defined(nimPreviewSlimSystem):
 when weirdTarget:
   discard
 elif defined(windows):
-  import winlean, times
+  import std/[winlean, times]
 elif defined(posix):
-  import posix
+  import std/posix
 else:
   {.error: "OS module not ported to your operating system!".}
 
@@ -31,6 +31,7 @@ elif defined(js):
 else:
   {.pragma: noNimJs.}
 
+## .. importdoc:: os.nim
 
 proc createSymlink*(src, dest: string) {.noWeirdTarget.} =
   ## Create a symbolic link at `dest` which points to the item specified
@@ -47,14 +48,10 @@ proc createSymlink*(src, dest: string) {.noWeirdTarget.} =
     const SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE = 2
     # allows anyone with developer mode on to create a link
     let flag = dirExists(src).int32 or SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE
-    when useWinUnicode:
-      var wSrc = newWideCString(src)
-      var wDst = newWideCString(dest)
-      if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
-        raiseOSError(osLastError(), $(src, dest))
-    else:
-      if createSymbolicLinkA(dest, src, flag) == 0 or getLastError() != 0:
-        raiseOSError(osLastError(), $(src, dest))
+    var wSrc = newWideCString(src)
+    var wDst = newWideCString(dest)
+    if createSymbolicLinkW(wDst, wSrc, flag) == 0 or getLastError() != 0:
+      raiseOSError(osLastError(), $(src, dest))
   else:
     if symlink(src, dest) != 0:
       raiseOSError(osLastError(), $(src, dest))
@@ -66,14 +63,16 @@ proc expandSymlink*(symlinkPath: string): string {.noWeirdTarget.} =
   ##
   ## See also:
   ## * `createSymlink proc`_
-  when defined(windows):
+  when defined(windows) or defined(nintendoswitch):
     result = symlinkPath
   else:
-    result = newString(maxSymlinkLen)
-    var len = readlink(symlinkPath, result.cstring, maxSymlinkLen)
-    if len < 0:
-      raiseOSError(osLastError(), symlinkPath)
-    if len > maxSymlinkLen:
-      result = newString(len+1)
-      len = readlink(symlinkPath, result.cstring, len)
-    setLen(result, len)
+    var bufLen = 1024
+    while true:
+      result = newString(bufLen)
+      let len = readlink(symlinkPath.cstring, result.cstring, bufLen)
+      if len < 0:
+        raiseOSError(osLastError(), symlinkPath)
+      if len < bufLen:
+        result.setLen(len)
+        break
+      bufLen = bufLen shl 1
diff --git a/lib/std/private/schubfach.nim b/lib/std/private/schubfach.nim
index dad8363ba..b8c85d2bc 100644
--- a/lib/std/private/schubfach.nim
+++ b/lib/std/private/schubfach.nim
@@ -39,10 +39,10 @@ const
   exponentMask: BitsType = maxIeeeExponent shl (significandSize - 1)
   signMask: BitsType = not (not BitsType(0) shr 1)
 
-proc constructSingle(bits: BitsType): Single {.constructor.} =
+proc constructSingle(bits: BitsType): Single  =
   result.bits = bits
 
-proc constructSingle(value: ValueType): Single {.constructor.} =
+proc constructSingle(value: ValueType): Single  =
   result.bits = cast[typeof(result.bits)](value)
 
 proc physicalSignificand(this: Single): BitsType {.noSideEffect.} =
@@ -244,12 +244,12 @@ proc toDecimal32(ieeeSignificand: uint32; ieeeExponent: uint32): FloatingDecimal
 ##  ToChars
 ## ==================================================================================================
 
-proc printDecimalDigitsBackwards[T: Ordinal](buf: var openArray[char]; pos: T; output: uint32): int32 {.inline.} =
+proc printDecimalDigitsBackwards[T: Ordinal](buf: var openArray[char]; pos: T; output: uint32): int {.inline.} =
   var output = output
   var pos = pos
-  var tz: int32 = 0
+  var tz = 0
   ##  number of trailing zeros removed.
-  var nd: int32 = 0
+  var nd = 0
   ##  number of decimal digits processed.
   ##  At most 9 digits remaining
   if output >= 10000:
@@ -355,7 +355,7 @@ proc formatDigits[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint3
     ##  dE+123 or d.igitsE+123
     decimalDigitsPosition = 1
   var digitsEnd = pos + decimalDigitsPosition + numDigits
-  let tz: int32 = printDecimalDigitsBackwards(buffer, digitsEnd, digits)
+  let tz = printDecimalDigitsBackwards(buffer, digitsEnd, digits)
   dec(digitsEnd, tz)
   dec(numDigits, tz)
   ##   decimal_exponent += tz; // => decimal_point unchanged.
diff --git a/lib/std/private/since.nim b/lib/std/private/since.nim
index 5b22b6391..720120f11 100644
--- a/lib/std/private/since.nim
+++ b/lib/std/private/since.nim
@@ -1,5 +1,5 @@
 ##[
-`since` is used to emulate older versions of nim stdlib with `--useVersion`,
+`since` is used to emulate older versions of nim stdlib,
 see `tuse_version.nim`.
 
 If a symbol `foo` is added in version `(1,3,5)`, use `{.since: (1.3.5).}`, not
@@ -15,19 +15,19 @@ The emulation cannot be 100% faithful and to avoid adding too much complexity,
 template since*(version: (int, int), body: untyped) {.dirty.} =
   ## Evaluates `body` if the ``(NimMajor, NimMinor)`` is greater than
   ## or equal to `version`. Usage:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   proc fun*() {.since: (1, 3).}
   ##   since (1, 3): fun()
+  ##   ```
   when (NimMajor, NimMinor) >= version:
     body
 
 template since*(version: (int, int, int), body: untyped) {.dirty.} =
   ## Evaluates `body` if ``(NimMajor, NimMinor, NimPatch)`` is greater than 
   ## or equal to `version`. Usage:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   proc fun*() {.since: (1, 3, 1).}
   ##   since (1, 3, 1): fun()
+  ##   ```
   when (NimMajor, NimMinor, NimPatch) >= version:
     body
diff --git a/lib/std/private/strimpl.nim b/lib/std/private/strimpl.nim
index 6a38cbfd2..f8c9236a5 100644
--- a/lib/std/private/strimpl.nim
+++ b/lib/std/private/strimpl.nim
@@ -93,7 +93,7 @@ func find*(s: cstring, sub: char, start: Natural = 0, last = 0): int =
   if L > 0:
     let found = c_memchr(s[start].unsafeAddr, sub, cast[csize_t](L))
     if not found.isNil:
-      return cast[ByteAddress](found) -% cast[ByteAddress](s)
+      return cast[int](found) -% cast[int](s)
   return -1
 
 func find*(s, sub: cstring, start: Natural = 0, last = 0): int =
@@ -108,6 +108,6 @@ func find*(s, sub: cstring, start: Natural = 0, last = 0): int =
   if last == 0 and s.len > start:
     let found = c_strstr(cast[cstring](s[start].unsafeAddr), sub)
     if not found.isNil:
-      result = cast[ByteAddress](found) -% cast[ByteAddress](s)
+      result = cast[int](found) -% cast[int](s)
     else:
       result = -1
diff --git a/lib/std/private/syslocks.nim b/lib/std/private/syslocks.nim
index ca8897dc2..e19ec2c04 100644
--- a/lib/std/private/syslocks.nim
+++ b/lib/std/private/syslocks.nim
@@ -16,7 +16,7 @@ when defined(windows):
     Handle = int
 
     SysLock* {.importc: "CRITICAL_SECTION",
-              header: "<windows.h>", final, pure.} = object # CRITICAL_SECTION in WinApi
+              header: "<windows.h>", final, pure, byref.} = object # CRITICAL_SECTION in WinApi
       DebugInfo: pointer
       LockCount: int32
       RecursionCount: int32
@@ -24,7 +24,7 @@ when defined(windows):
       LockSemaphore: int
       SpinCount: int
 
-    SysCond* {.importc: "RTL_CONDITION_VARIABLE", header: "<windows.h>".} = object
+    SysCond* {.importc: "RTL_CONDITION_VARIABLE", header: "<windows.h>", byref.} = object
       thePtr {.importc: "Ptr".} : Handle
 
   proc initSysLock*(L: var SysLock) {.importc: "InitializeCriticalSection",
@@ -46,7 +46,7 @@ when defined(windows):
                                     header: "<windows.h>".}
     ## Releases the lock `L`.
 
-  proc deinitSys*(L: var SysLock) {.importc: "DeleteCriticalSection",
+  proc deinitSys*(L: SysLock) {.importc: "DeleteCriticalSection",
                                    header: "<windows.h>".}
 
   proc initializeConditionVariable(
@@ -68,7 +68,7 @@ when defined(windows):
 
   proc initSysCond*(cond: var SysCond) {.inline.} =
     initializeConditionVariable(cond)
-  proc deinitSysCond*(cond: var SysCond) {.inline.} =
+  proc deinitSysCond*(cond: SysCond) {.inline.} =
     discard
   proc waitSysCond*(cond: var SysCond, lock: var SysLock) =
     discard sleepConditionVariableCS(cond, lock, -1'i32)
@@ -83,13 +83,13 @@ elif defined(genode):
               header: Header.} = object
 
   proc initSysLock*(L: var SysLock) = discard
-  proc deinitSys*(L: var SysLock) = discard
+  proc deinitSys*(L: SysLock) = discard
   proc acquireSys*(L: var SysLock) {.noSideEffect, importcpp.}
   proc tryAcquireSys*(L: var SysLock): bool {.noSideEffect, importcpp.}
   proc releaseSys*(L: var SysLock) {.noSideEffect, importcpp.}
 
   proc initSysCond*(L: var SysCond) = discard
-  proc deinitSysCond*(L: var SysCond) = discard
+  proc deinitSysCond*(L: SysCond) = discard
   proc waitSysCond*(cond: var SysCond, lock: var SysLock) {.
     noSideEffect, importcpp.}
   proc signalSysCond*(cond: var SysCond) {.
@@ -101,7 +101,7 @@ else:
   type
     SysLockObj {.importc: "pthread_mutex_t", pure, final,
                header: """#include <sys/types.h>
-                          #include <pthread.h>""".} = object
+                          #include <pthread.h>""", byref.} = object
       when defined(linux) and defined(amd64):
         abi: array[40 div sizeof(clong), clong]
 
@@ -113,7 +113,7 @@ else:
 
     SysCondObj {.importc: "pthread_cond_t", pure, final,
                header: """#include <sys/types.h>
-                          #include <pthread.h>""".} = object
+                          #include <pthread.h>""", byref.} = object
       when defined(linux) and defined(amd64):
         abi: array[48 div sizeof(clonglong), clonglong]
 
@@ -127,7 +127,7 @@ else:
 
   proc initSysLockAux(L: var SysLockObj, attr: ptr SysLockAttr) {.
     importc: "pthread_mutex_init", header: "<pthread.h>", noSideEffect.}
-  proc deinitSysAux(L: var SysLockObj) {.noSideEffect,
+  proc deinitSysAux(L: SysLockObj) {.noSideEffect,
     importc: "pthread_mutex_destroy", header: "<pthread.h>".}
 
   proc acquireSysAux(L: var SysLockObj) {.noSideEffect,
@@ -156,7 +156,7 @@ else:
       L = cast[SysLock](c_malloc(csize_t(sizeof(SysLockObj))))
       initSysLockAux(L[], attr)
 
-    proc deinitSys*(L: var SysLock) =
+    proc deinitSys*(L: SysLock) =
       deinitSysAux(L[])
       c_free(L)
 
@@ -173,7 +173,7 @@ else:
 
     template initSysLock*(L: var SysLock, attr: ptr SysLockAttr = nil) =
       initSysLockAux(L, attr)
-    template deinitSys*(L: var SysLock) =
+    template deinitSys*(L: SysLock) =
       deinitSysAux(L)
     template acquireSys*(L: var SysLock) =
       acquireSysAux(L)
@@ -193,7 +193,7 @@ else:
   # locks
   proc initSysCondAux(cond: var SysCondObj, cond_attr: ptr SysCondAttr = nil) {.
     importc: "pthread_cond_init", header: "<pthread.h>", noSideEffect.}
-  proc deinitSysCondAux(cond: var SysCondObj) {.noSideEffect,
+  proc deinitSysCondAux(cond: SysCondObj) {.noSideEffect,
     importc: "pthread_cond_destroy", header: "<pthread.h>".}
 
   proc waitSysCondAux(cond: var SysCondObj, lock: var SysLockObj): cint {.
@@ -208,7 +208,7 @@ else:
       cond = cast[SysCond](c_malloc(csize_t(sizeof(SysCondObj))))
       initSysCondAux(cond[], cond_attr)
 
-    proc deinitSysCond*(cond: var SysCond) =
+    proc deinitSysCond*(cond: SysCond) =
       deinitSysCondAux(cond[])
       c_free(cond)
 
@@ -221,7 +221,7 @@ else:
   else:
     template initSysCond*(cond: var SysCond, cond_attr: ptr SysCondAttr = nil) =
       initSysCondAux(cond, cond_attr)
-    template deinitSysCond*(cond: var SysCond) =
+    template deinitSysCond*(cond: SysCond) =
       deinitSysCondAux(cond)
 
     template waitSysCond*(cond: var SysCond, lock: var SysLock) =
diff --git a/lib/std/private/underscored_calls.nim b/lib/std/private/underscored_calls.nim
index f0bcbcc74..f853572b5 100644
--- a/lib/std/private/underscored_calls.nim
+++ b/lib/std/private/underscored_calls.nim
@@ -10,7 +10,9 @@
 
 ## This is an internal helper module. Do not use.
 
-import macros
+import std/macros
+
+proc underscoredCalls*(result, calls, arg0: NimNode)
 
 proc underscoredCall(n, arg0: NimNode): NimNode =
   proc underscorePos(n: NimNode): int =
@@ -19,13 +21,19 @@ proc underscoredCall(n, arg0: NimNode): NimNode =
     return 0
 
   if n.kind in nnkCallKinds:
-    result = copyNimNode(n)
-    result.add n[0]
+    if n[0].kind in {nnkIdent, nnkSym} and n[0].eqIdent("with"):
+      expectKind n[1], {nnkIdent, nnkSym}
 
-    let u = underscorePos(n)
-    for i in 1..u-1: result.add n[i]
-    result.add arg0
-    for i in u+1..n.len-1: result.add n[i]
+      result = newStmtList()
+      underscoredCalls(result, n[2 .. ^1].newStmtList, newDotExpr(arg0, n[1]))
+    else:
+      result = copyNimNode(n)
+      result.add n[0]
+
+      let u = underscorePos(n)
+      for i in 1..u-1: result.add n[i]
+      result.add arg0
+      for i in u+1..n.len-1: result.add n[i]
   elif n.kind in {nnkAsgn, nnkExprEqExpr}:
     var field = n[0]
     if n[0].kind == nnkDotExpr and n[0][0].eqIdent("_"):
diff --git a/lib/std/private/win_setenv.nim b/lib/std/private/win_setenv.nim
index 303889a40..66e199dfe 100644
--- a/lib/std/private/win_setenv.nim
+++ b/lib/std/private/win_setenv.nim
@@ -33,25 +33,25 @@ else:
     # same as winlean.setEnvironmentVariableA
 
   proc c_getenv(varname: cstring): cstring {.importc: "getenv", header: "<stdlib.h>".}
-  proc c_wputenv(envstring: WideCString): cint {.importc: "_wputenv", header: "<stdlib.h>".}
-  proc c_wgetenv(varname: WideCString): WideCString {.importc: "_wgetenv", header: "<stdlib.h>".}
+  proc c_wputenv(envstring: ptr wchar_t): cint {.importc: "_wputenv", header: "<stdlib.h>".}
+  proc c_wgetenv(varname: ptr wchar_t): ptr wchar_t {.importc: "_wgetenv", header: "<stdlib.h>".}
 
   var errno {.importc, header: "<errno.h>".}: cint
   var genviron {.importc: "_environ".}: ptr ptr char
     # xxx `ptr UncheckedArray[WideCString]` did not work
 
-  proc wcstombs(wcstr: ptr char, mbstr: WideCString, count: csize_t): csize_t {.importc, header: "<stdlib.h>".}
+  proc wcstombs(wcstr: ptr char, mbstr: ptr wchar_t, count: csize_t): csize_t {.importc, header: "<stdlib.h>".}
     # xxx cint vs errno_t?
 
   proc setEnvImpl*(name: string, value: string, overwrite: cint): cint =
     const EINVAL = cint(22)
-    let wideName = newWideCString(name)
-    if overwrite == 0 and c_wgetenv(wideName) != nil:
+    let wideName: WideCString = newWideCString(name)
+    if overwrite == 0 and c_wgetenv(cast[ptr wchar_t](wideName)) != nil:
       return 0
 
     if value != "":
-      let envstring = name & "=" & value
-      let e = c_wputenv(newWideCString(envstring))
+      let envstring: WideCString = newWideCString(name & "=" & value)
+      let e = c_wputenv(cast[ptr wchar_t](envstring))
       if e != 0:
         errno = EINVAL
         return -1
@@ -62,19 +62,19 @@ else:
     SetEnvironmentVariableA doesn't update `_environ`,
     so we have to do these terrible things.
     ]#
-    let envstring = name & "=  "
-    if c_wputenv(newWideCString(envstring)) != 0:
+    let envstring: WideCString = newWideCString(name & "=  ")
+    if c_wputenv(cast[ptr wchar_t](envstring)) != 0:
       errno = EINVAL
       return -1
     # Here lies the documentation we blatently ignore to make this work.
-    var s = c_wgetenv(wideName)
+    var s = cast[WideCString](c_wgetenv(cast[ptr wchar_t](wideName)))
     s[0] = Utf16Char('\0')
     #[
     This would result in a double null termination, which normally signifies the
     end of the environment variable list, so we stick a completely empty
     environment variable into the list instead.
     ]#
-    s = c_wgetenv(wideName)
+    s = cast[WideCString](c_wgetenv(cast[ptr wchar_t](wideName)))
     s[1] = Utf16Char('=')
     #[
     If genviron is null, the MBCS environment has not been initialized
@@ -88,12 +88,12 @@ else:
       # in the current codepage. Skip updating MBCS environment in this case.
       # For some reason, second `wcstombs` can find non-convertible characters
       # that the first `wcstombs` cannot.
-      let requiredSizeS = wcstombs(nil, wideName, 0)
+      let requiredSizeS = wcstombs(nil, cast[ptr wchar_t](wideName), 0)
       if requiredSizeS != high(csize_t):
         let requiredSize = requiredSizeS.int
         var buf = newSeq[char](requiredSize + 1)
         let buf2 = buf[0].addr
-        if wcstombs(buf2, wideName, csize_t(requiredSize + 1)) != high(csize_t):
+        if wcstombs(buf2, cast[ptr wchar_t](wideName), csize_t(requiredSize + 1)) != high(csize_t):
           var ptrToEnv = c_getenv(cast[cstring](buf2))
           ptrToEnv[0] = '\0'
           ptrToEnv = c_getenv(cast[cstring](buf2))
diff --git a/lib/std/setutils.nim b/lib/std/setutils.nim
index 4664d6dcc..8e7bc6a92 100644
--- a/lib/std/setutils.nim
+++ b/lib/std/setutils.nim
@@ -14,7 +14,7 @@
 ## * `std/packedsets <packedsets.html>`_
 ## * `std/sets <sets.html>`_
 
-import typetraits, macros
+import std/[typetraits, macros]
 
 #[
   type SetElement* = char|byte|bool|int16|uint16|enum|uint8|int8
diff --git a/lib/std/sha1.nim b/lib/std/sha1.nim
index 50175024c..213af4229 100644
--- a/lib/std/sha1.nim
+++ b/lib/std/sha1.nim
@@ -26,8 +26,11 @@ runnableExamples("-r:off"):
     b = parseSecureHash("10DFAEBF6BFDBC7939957068E2EFACEC4972933C")
   assert a == b, "files don't match"
 
-import strutils
-from endians import bigEndian32, bigEndian64
+
+{.deprecated: "use command `nimble install checksums` and import `checksums/sha1` instead".}
+
+import std/strutils
+from std/endians import bigEndian32, bigEndian64
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -281,4 +284,4 @@ proc `==`*(a, b: SecureHash): bool =
 
 proc isValidSha1Hash*(s: string): bool =
   ## Checks if a string is a valid sha1 hash sum.
-  s.len == 40 and allCharsInSet(s, HexDigits)
+  s.len == 40 and allCharsInSet(s, HexDigits)
\ No newline at end of file
diff --git a/lib/std/socketstreams.nim b/lib/std/socketstreams.nim
index 5c882858d..45e906795 100644
--- a/lib/std/socketstreams.nim
+++ b/lib/std/socketstreams.nim
@@ -31,39 +31,40 @@
 ## Examples
 ## ========
 ##
-## .. code-block:: Nim
-##  import std/socketstreams
+##   ```Nim
+##   import std/socketstreams
 ##
-##  var
-##    socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
-##    stream = newReadSocketStream(socket)
-##  socket.sendTo("127.0.0.1", Port(12345), "SOME REQUEST")
-##  echo stream.readLine() # Will call `recv`
-##  stream.setPosition(0)
-##  echo stream.readLine() # Will return the read line from the buffer
-##  stream.resetStream() # Buffer is now empty, position is 0
-##  echo stream.readLine() # Will call `recv` again
-##  stream.close() # Closes the socket
+##   var
+##     socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
+##     stream = newReadSocketStream(socket)
+##   socket.sendTo("127.0.0.1", Port(12345), "SOME REQUEST")
+##   echo stream.readLine() # Will call `recv`
+##   stream.setPosition(0)
+##   echo stream.readLine() # Will return the read line from the buffer
+##   stream.resetStream() # Buffer is now empty, position is 0
+##   echo stream.readLine() # Will call `recv` again
+##   stream.close() # Closes the socket
+##   ```
 ##
-## .. code-block:: Nim
+##   ```Nim
+##   import std/socketstreams
 ##
-##  import std/socketstreams
-##
-##  var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
-##  socket.connect("127.0.0.1", Port(12345))
-##  var sendStream = newWriteSocketStream(socket)
-##  sendStream.write "NOM"
-##  sendStream.setPosition(1)
-##  echo sendStream.peekStr(2) # OM
-##  sendStream.write "I"
-##  sendStream.setPosition(0)
-##  echo sendStream.readStr(3) # NIM
-##  echo sendStream.getPosition() # 3
-##  sendStream.flush() # This actually performs the writing to the socket
-##  sendStream.setPosition(1)
-##  sendStream.write "I" # Throws an error as we can't write into an already sent buffer
-
-import net, streams
+##   var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
+##   socket.connect("127.0.0.1", Port(12345))
+##   var sendStream = newWriteSocketStream(socket)
+##   sendStream.write "NOM"
+##   sendStream.setPosition(1)
+##   echo sendStream.peekStr(2) # OM
+##   sendStream.write "I"
+##   sendStream.setPosition(0)
+##   echo sendStream.readStr(3) # NIM
+##   echo sendStream.getPosition() # 3
+##   sendStream.flush() # This actually performs the writing to the socket
+##   sendStream.setPosition(1)
+##   sendStream.write "I" # Throws an error as we can't write into an already sent buffer
+##   ```
+
+import std/[net, streams]
 
 type
   ReadSocketStream* = ref ReadSocketStreamObj
@@ -146,7 +147,7 @@ proc wsFlush(s: Stream) =
   s.lastFlush = s.buf.len
 
 proc rsClose(s: Stream) =
-  {.cast(tags: []).}:
+  {.cast(raises: [IOError, OSError]), cast(tags: []).}: # todo fixme maybe do something?
     var s = ReadSocketStream(s)
     s.data.close()
 
diff --git a/lib/std/staticos.nim b/lib/std/staticos.nim
new file mode 100644
index 000000000..2617c6913
--- /dev/null
+++ b/lib/std/staticos.nim
@@ -0,0 +1,13 @@
+## This module implements path handling like os module but works at only compile-time.
+## This module works even when cross compiling to OS that is not supported by os module.
+
+proc staticFileExists*(filename: string): bool {.compileTime.} =
+  ## Returns true if `filename` exists and is a regular file or symlink.
+  ##
+  ## Directories, device files, named pipes and sockets return false.
+  discard
+
+proc staticDirExists*(dir: string): bool {.compileTime.} =
+  ## Returns true if the directory `dir` exists. If `dir` is a file, false
+  ## is returned. Follows symlinks.
+  discard
diff --git a/lib/std/strbasics.nim b/lib/std/strbasics.nim
index be1dd7a58..b2c36a4be 100644
--- a/lib/std/strbasics.nim
+++ b/lib/std/strbasics.nim
@@ -23,8 +23,8 @@ proc add*(x: var string, y: openArray[char]) =
   # Use `{.noalias.}` ?
   let n = x.len
   x.setLen n + y.len
-    # pending https://github.com/nim-lang/Nim/issues/14655#issuecomment-643671397
-    # use x.setLen(n + y.len, isInit = false)
+    # pending #19727
+    # setLen unnecessarily zeros memory
   var i = 0
   while i < y.len:
     x[n + i] = y[i]
diff --git a/lib/std/symlinks.nim b/lib/std/symlinks.nim
index 9e77bbe2a..dbe908612 100644
--- a/lib/std/symlinks.nim
+++ b/lib/std/symlinks.nim
@@ -1,11 +1,12 @@
 ## This module implements symlink (symbolic link) handling.
 
-from paths import Path, ReadDirEffect
+## .. importdoc:: os.nim
 
-from std/private/ossymlinks import symlinkExists, createSymlink, expandSymlink
+from std/paths import Path, ReadDirEffect
 
+from std/private/ossymlinks import symlinkExists, createSymlink, expandSymlink
 
-proc symlinkExists*(link: Path): bool {.inline, tags: [ReadDirEffect].} =
+proc symlinkExists*(link: Path): bool {.inline, tags: [ReadDirEffect], sideEffect.} =
   ## Returns true if the symlink `link` exists. Will return true
   ## regardless of whether the link points to a directory or file.
   result = symlinkExists(link.string)
diff --git a/lib/std/syncio.nim b/lib/std/syncio.nim
index 2b5ea6a3c..c34a025af 100644
--- a/lib/std/syncio.nim
+++ b/lib/std/syncio.nim
@@ -38,8 +38,8 @@ type
                          ## at the end. If the file does not exist, it
                          ## will be created.
 
-  FileHandle* = cint ## type that represents an OS file handle; this is
-                      ## useful for low-level file access
+  FileHandle* = cint ## The type that represents an OS file handle; this is
+                      ## useful for low-level file access.
 
   FileSeekPos* = enum ## Position relative to which seek should happen.
                       # The values are ordered so that they match with stdio
@@ -151,14 +151,11 @@ proc c_fprintf(f: File, frmt: cstring): cint {.
 proc c_fputc(c: char, f: File): cint {.
   importc: "fputc", header: "<stdio.h>".}
 
-template sysFatal(exc, msg) =
-  raise newException(exc, msg)
-
 proc raiseEIO(msg: string) {.noinline, noreturn.} =
-  sysFatal(IOError, msg)
+  raise newException(IOError, msg)
 
 proc raiseEOF() {.noinline, noreturn.} =
-  sysFatal(EOFError, "EOF reached")
+  raise newException(EOFError, "EOF reached")
 
 proc strerror(errnum: cint): cstring {.importc, header: "<string.h>".}
 
@@ -246,7 +243,7 @@ when defined(windows):
     # machine. We also enable `setConsoleOutputCP(65001)` now by default.
     # But we cannot call printf directly as the string might contain \0.
     # So we have to loop over all the sections separated by potential \0s.
-    var i = c_fprintf(f, "%s", s)
+    var i = int c_fprintf(f, "%s", s)
     while i < s.len:
       if s[i] == '\0':
         let w = c_fputc('\0', f)
@@ -323,7 +320,7 @@ elif defined(windows):
 const
   BufSize = 4000
 
-proc close*(f: File) {.tags: [], gcsafe.} =
+proc close*(f: File) {.tags: [], gcsafe, sideEffect.} =
   ## Closes the file.
   if not f.isNil:
     discard c_fclose(f)
@@ -359,12 +356,12 @@ proc getOsFileHandle*(f: File): FileHandle =
 
 when defined(nimdoc) or (defined(posix) and not defined(nimscript)) or defined(windows):
   proc setInheritable*(f: FileHandle, inheritable: bool): bool =
-    ## control whether a file handle can be inherited by child processes. Returns
+    ## Controls whether a file handle can be inherited by child processes. Returns
     ## `true` on success. This requires the OS file handle, which can be
     ## retrieved via `getOsFileHandle <#getOsFileHandle,File>`_.
     ##
     ## This procedure is not guaranteed to be available for all platforms. Test for
-    ## availability with `declared() <system.html#declared,untyped>`.
+    ## availability with `declared() <system.html#declared,untyped>`_.
     when SupportIoctlInheritCtl:
       result = c_ioctl(f, if inheritable: FIONCLEX else: FIOCLEX) != -1
     elif defined(freertos) or defined(zephyr):
@@ -390,7 +387,7 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
   proc c_memchr(s: pointer, c: cint, n: csize_t): pointer {.
     importc: "memchr", header: "<string.h>".}
 
-  when defined(windows) and not defined(useWinAnsi):
+  when defined(windows):
     proc readConsole(hConsoleInput: FileHandle, lpBuffer: pointer,
                      nNumberOfCharsToRead: int32,
                      lpNumberOfCharsRead: ptr int32,
@@ -422,7 +419,7 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
     if f.isatty:
       const numberOfCharsToRead = 2048
       var numberOfCharsRead = 0'i32
-      var buffer = newWideCString("", numberOfCharsToRead)
+      var buffer = newWideCString(numberOfCharsToRead)
       if readConsole(getOsFileHandle(f), addr(buffer[0]),
         numberOfCharsToRead, addr(numberOfCharsRead), nil) == 0:
         var error = getLastError()
@@ -480,15 +477,16 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
     let m = c_memchr(addr line[pos], '\L'.ord, cast[csize_t](sp))
     if m != nil:
       # \l found: Could be our own or the one by fgets, in any case, we're done
-      var last = cast[ByteAddress](m) - cast[ByteAddress](addr line[0])
+      var last = cast[int](m) - cast[int](addr line[0])
       if last > 0 and line[last-1] == '\c':
         line.setLen(last-1)
         return last > 1 or fgetsSuccess
-        # We have to distinguish between two possible cases:
+      elif last > 0 and line[last-1] == '\0':
+        # We have to distinguish among three possible cases:
         # \0\l\0 => line ending in a null character.
         # \0\l\l => last line without newline, null was put there by fgets.
-      elif last > 0 and line[last-1] == '\0':
-        if last < pos + sp - 1 and line[last+1] != '\0':
+        #   \0\l => last line without newline, null was put there by fgets.
+        if last >= pos + sp - 1 or line[last+1] != '\0': # bug #21273
           dec last
       line.setLen(last)
       return last > 0 or fgetsSuccess
@@ -611,7 +609,7 @@ proc writeLine*[Ty](f: File, x: varargs[Ty, `$`]) {.inline,
 
 # interface to the C procs:
 
-when defined(windows) and not defined(useWinAnsi):
+when defined(windows):
   when defined(cpp):
     proc wfopen(filename, mode: WideCString): pointer {.
       importcpp: "_wfopen((const wchar_t*)#, (const wchar_t*)#)", nodecl.}
@@ -650,6 +648,9 @@ const
         ""
     else:
       ""
+  RawFormatOpen: array[FileMode, cstring] = [
+    # used for open by FileHandle, which calls `fdopen`
+    cstring("rb"), "wb", "w+b", "r+b", "ab"]
   FormatOpen: array[FileMode, cstring] = [
     cstring("rb" & NoInheritFlag), "wb" & NoInheritFlag, "w+b" & NoInheritFlag,
     "r+b" & NoInheritFlag, "ab" & NoInheritFlag
@@ -751,7 +752,7 @@ proc open*(f: var File, filehandle: FileHandle,
         filehandle) else: filehandle
     if not setInheritable(oshandle, false):
       return false
-  f = c_fdopen(filehandle, FormatOpen[mode])
+  f = c_fdopen(filehandle, RawFormatOpen[mode])
   result = f != nil
 
 proc open*(filename: string,
@@ -763,9 +764,9 @@ proc open*(filename: string,
   ##
   ## The file handle associated with the resulting `File` is not inheritable.
   if not open(result, filename, mode, bufSize):
-    sysFatal(IOError, "cannot open: " & filename)
+    raise newException(IOError, "cannot open: " & filename)
 
-proc setFilePos*(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) {.benign.} =
+proc setFilePos*(f: File, pos: int64, relativeTo: FileSeekPos = fspSet) {.benign, sideEffect.} =
   ## Sets the position of the file pointer that is used for read/write
   ## operations. The file's first byte has the index zero.
   if c_fseek(f, pos, cint(relativeTo)) != 0:
@@ -851,7 +852,7 @@ proc readFile*(filename: string): string {.tags: [ReadIOEffect], benign.} =
     finally:
       close(f)
   else:
-    sysFatal(IOError, "cannot open: " & filename)
+    raise newException(IOError, "cannot open: " & filename)
 
 proc writeFile*(filename, content: string) {.tags: [WriteIOEffect], benign.} =
   ## Opens a file named `filename` for writing. Then writes the
@@ -864,7 +865,7 @@ proc writeFile*(filename, content: string) {.tags: [WriteIOEffect], benign.} =
     finally:
       close(f)
   else:
-    sysFatal(IOError, "cannot open: " & filename)
+    raise newException(IOError, "cannot open: " & filename)
 
 proc writeFile*(filename: string, content: openArray[byte]) {.since: (1, 1).} =
   ## Opens a file named `filename` for writing. Then writes the
@@ -873,7 +874,7 @@ proc writeFile*(filename: string, content: openArray[byte]) {.since: (1, 1).} =
   var f: File = nil
   if open(f, filename, fmWrite):
     try:
-      f.writeBuffer(unsafeAddr content[0], content.len)
+      discard f.writeBuffer(unsafeAddr content[0], content.len)
     finally:
       close(f)
   else:
@@ -894,7 +895,7 @@ proc readLines*(filename: string, n: Natural): seq[string] =
     finally:
       close(f)
   else:
-    sysFatal(IOError, "cannot open: " & filename)
+    raise newException(IOError, "cannot open: " & filename)
 
 template readLines*(filename: string): seq[
     string] {.deprecated: "use readLines with two arguments".} =
diff --git a/lib/std/sysatomics.nim b/lib/std/sysatomics.nim
index b7ccb4092..2f203b3eb 100644
--- a/lib/std/sysatomics.nim
+++ b/lib/std/sysatomics.nim
@@ -15,7 +15,7 @@ when defined(nimPreviewSlimSystem):
 
 const
   hasThreadSupport = compileOption("threads") and not defined(nimscript)
-const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang)
+const someGcc = defined(gcc) or defined(llvm_gcc) or defined(clang) or defined(nintendoswitch)
 const someVcc = defined(vcc) or defined(clang_cl)
 
 type
@@ -265,6 +265,7 @@ else:
 
 
 proc atomicInc*(memLoc: var int, x: int = 1): int {.inline, discardable, raises: [], tags: [].} =
+  ## Atomically increments the integer by some `x`. It returns the new value.
   when someGcc and hasThreadSupport:
     result = atomicAddFetch(memLoc.addr, x, ATOMIC_SEQ_CST)
   elif someVcc and hasThreadSupport:
@@ -275,6 +276,7 @@ proc atomicInc*(memLoc: var int, x: int = 1): int {.inline, discardable, raises:
     result = memLoc
 
 proc atomicDec*(memLoc: var int, x: int = 1): int {.inline, discardable, raises: [], tags: [].} =
+  ## Atomically decrements the integer by some `x`. It returns the new value.
   when someGcc and hasThreadSupport:
     when declared(atomicSubFetch):
       result = atomicSubFetch(memLoc.addr, x, ATOMIC_SEQ_CST)
@@ -361,7 +363,7 @@ elif someGcc or defined(tcc):
 elif defined(icl):
   proc cpuRelax* {.importc: "_mm_pause", header: "xmmintrin.h".}
 elif false:
-  from os import sleep
+  from std/os import sleep
 
   proc cpuRelax* {.inline.} = os.sleep(1)
 
diff --git a/lib/std/sysrand.nim b/lib/std/sysrand.nim
index eeaa23d72..6f2c6b0c1 100644
--- a/lib/std/sysrand.nim
+++ b/lib/std/sysrand.nim
@@ -60,7 +60,7 @@ when not defined(js):
   import std/oserrors
 
 when defined(posix):
-  import posix
+  import std/posix
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -168,8 +168,10 @@ elif defined(windows):
     result = randomBytes(addr dest[0], size)
 
 elif defined(linux) and not defined(nimNoGetRandom) and not defined(emscripten):
-  # TODO using let, pending bootstrap >= 1.4.0
-  var SYS_getrandom {.importc: "SYS_getrandom", header: "<sys/syscall.h>".}: clong
+  when (NimMajor, NimMinor) >= (1, 4):
+    let SYS_getrandom {.importc: "SYS_getrandom", header: "<sys/syscall.h>".}: clong
+  else:
+    var SYS_getrandom {.importc: "SYS_getrandom", header: "<sys/syscall.h>".}: clong
   const syscallHeader = """#include <unistd.h>
 #include <sys/syscall.h>"""
 
@@ -190,12 +192,11 @@ elif defined(linux) and not defined(nimNoGetRandom) and not defined(emscripten):
     while result < size:
       let readBytes = syscall(SYS_getrandom, addr dest[result], cint(size - result), 0).int
       if readBytes == 0:
-        doAssert false
+        raiseAssert "unreachable"
       elif readBytes > 0:
         inc(result, readBytes)
       else:
-        if osLastError().int in {EINTR, EAGAIN}:
-          discard
+        if osLastError().cint in [EINTR, EAGAIN]: discard
         else:
           result = -1
           break
diff --git a/lib/std/tasks.nim b/lib/std/tasks.nim
index 055ddf144..7e59747f5 100644
--- a/lib/std/tasks.nim
+++ b/lib/std/tasks.nim
@@ -11,7 +11,6 @@
 ## A `Task` should be only owned by a single Thread, it cannot be shared by threads.
 
 import std/[macros, isolation, typetraits]
-import system/ansi_c
 
 when defined(nimPreviewSlimSystem):
   import std/assertions
@@ -62,24 +61,33 @@ when compileOption("threads"):
 
 type
   Task* = object ## `Task` contains the callback and its arguments.
-    callback: proc (args: pointer) {.nimcall, gcsafe.}
+    callback: proc (args, res: pointer) {.nimcall, gcsafe.}
     args: pointer
     destroy: proc (args: pointer) {.nimcall, gcsafe.}
 
 
 proc `=copy`*(x: var Task, y: Task) {.error.}
 
-proc `=destroy`*(t: var Task) {.inline, gcsafe.} =
-  ## Frees the resources allocated for a `Task`.
-  if t.args != nil:
-    if t.destroy != nil:
-      t.destroy(t.args)
-    c_free(t.args)
-
-proc invoke*(task: Task) {.inline, gcsafe.} =
+const arcLike = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc)
+when defined(nimAllowNonVarDestructor) and arcLike:
+  proc `=destroy`*(t: Task) {.inline, gcsafe.} =
+    ## Frees the resources allocated for a `Task`.
+    if t.args != nil:
+      if t.destroy != nil:
+        t.destroy(t.args)
+      deallocShared(t.args)
+else:
+  proc `=destroy`*(t: var Task) {.inline, gcsafe.} =
+    ## Frees the resources allocated for a `Task`.
+    if t.args != nil:
+      if t.destroy != nil:
+        t.destroy(t.args)
+      deallocShared(t.args)
+
+proc invoke*(task: Task; res: pointer = nil) {.inline, gcsafe.} =
   ## Invokes the `task`.
   assert task.callback != nil
-  task.callback(task.args)
+  task.callback(task.args, res)
 
 template checkIsolate(scratchAssignList: seq[NimNode], procParam, scratchDotExpr: NimNode) =
   # block:
@@ -102,22 +110,38 @@ template addAllNode(assignParam: NimNode, procParam: NimNode) =
   tempAssignList.add newLetStmt(tempNode, newDotExpr(objTemp, formalParams[i][0]))
   scratchRecList.add newIdentDefs(newIdentNode(formalParams[i][0].strVal), assignParam)
 
+proc analyseRootSym(s: NimNode): NimNode =
+  result = s
+  while true:
+    case result.kind
+    of nnkBracketExpr, nnkDerefExpr, nnkHiddenDeref,
+        nnkAddr, nnkHiddenAddr,
+        nnkObjDownConv, nnkObjUpConv:
+      result = result[0]
+    of nnkDotExpr, nnkCheckedFieldExpr, nnkHiddenStdConv, nnkHiddenSubConv:
+      result = result[1]
+    else:
+      break
+
 macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkCallStrLit}): Task =
   ## Converts the call and its arguments to `Task`.
-  runnableExamples("--gc:orc"):
+  runnableExamples:
     proc hello(a: int) = echo a
 
     let b = toTask hello(13)
     assert b is Task
 
-  if getTypeInst(e).typeKind != ntyVoid:
-    error("'toTask' cannot accept a call with a return value", e)
+  let retType = getTypeInst(e)
+  let returnsVoid = retType.typeKind == ntyVoid
+
+  let rootSym = analyseRootSym(e[0])
+  expectKind rootSym, nnkSym
 
   when compileOption("threads"):
-    if not isGcSafe(e[0]):
+    if not isGcSafe(rootSym):
       error("'toTask' takes a GC safe call expression", e)
 
-  if hasClosure(e[0]):
+  if hasClosure(rootSym):
     error("closure call is not allowed", e)
 
   if e.len > 1:
@@ -166,7 +190,7 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC
         # passing by static parameters
         # so we pass them directly instead of passing by scratchObj
         callNode.add nnkExprEqExpr.newTree(formalParams[i][0], e[i])
-      of nnkSym, nnkPtrTy:
+      of nnkSym, nnkPtrTy, nnkProcTy, nnkTupleConstr:
         addAllNode(param, e[i])
       of nnkCharLit..nnkNilLit:
         callNode.add nnkExprEqExpr.newTree(formalParams[i][0], e[i])
@@ -188,40 +212,43 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC
 
 
     let scratchObjPtrType = quote do:
-      cast[ptr `scratchObjType`](c_calloc(csize_t 1, csize_t sizeof(`scratchObjType`)))
-
-    let scratchLetSection = newLetStmt(
-      scratchIdent,
-      scratchObjPtrType
-    )
+      cast[ptr `scratchObjType`](allocShared0(sizeof(`scratchObjType`)))
 
-    let scratchCheck = quote do:
-      if `scratchIdent`.isNil:
-        raise newException(OutOfMemDefect, "Could not allocate memory")
+    let scratchLetSection = newLetStmt(scratchIdent, scratchObjPtrType)
 
     var stmtList = newStmtList()
     stmtList.add(scratchObj)
     stmtList.add(scratchLetSection)
-    stmtList.add(scratchCheck)
     stmtList.add(nnkBlockStmt.newTree(newEmptyNode(), newStmtList(scratchAssignList)))
 
     var functionStmtList = newStmtList()
     let funcCall = newCall(e[0], callNode)
     functionStmtList.add tempAssignList
-    functionStmtList.add funcCall
 
-    let funcName = genSym(nskProc, e[0].strVal)
+    let funcName = genSym(nskProc, rootSym.strVal)
     let destroyName = genSym(nskProc, "destroyScratch")
     let objTemp2 = genSym(ident = "obj")
     let tempNode = quote("@") do:
         `=destroy`(@objTemp2[])
 
+    var funcDecl: NimNode
+    if returnsVoid:
+      funcDecl = quote do:
+        proc `funcName`(args, res: pointer) {.gcsafe, nimcall.} =
+          let `objTemp` = cast[ptr `scratchObjType`](args)
+          `functionStmtList`
+          `funcCall`
+    else:
+      funcDecl = quote do:
+        proc `funcName`(args, res: pointer) {.gcsafe, nimcall.} =
+          let `objTemp` = cast[ptr `scratchObjType`](args)
+          `functionStmtList`
+          cast[ptr `retType`](res)[] = `funcCall`
+
     result = quote do:
       `stmtList`
 
-      proc `funcName`(args: pointer) {.gcsafe, nimcall.} =
-        let `objTemp` = cast[ptr `scratchObjType`](args)
-        `functionStmtList`
+      `funcDecl`
 
       proc `destroyName`(args: pointer) {.gcsafe, nimcall.} =
         let `objTemp2` = cast[ptr `scratchObjType`](args)
@@ -230,18 +257,26 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC
       Task(callback: `funcName`, args: `scratchIdent`, destroy: `destroyName`)
   else:
     let funcCall = newCall(e[0])
-    let funcName = genSym(nskProc, e[0].strVal)
+    let funcName = genSym(nskProc, rootSym.strVal)
 
-    result = quote do:
-      proc `funcName`(args: pointer) {.gcsafe, nimcall.} =
-        `funcCall`
+    if returnsVoid:
+      result = quote do:
+        proc `funcName`(args, res: pointer) {.gcsafe, nimcall.} =
+          `funcCall`
+
+        Task(callback: `funcName`, args: nil)
+    else:
+      result = quote do:
+        proc `funcName`(args, res: pointer) {.gcsafe, nimcall.} =
+          cast[ptr `retType`](res)[] = `funcCall`
+
+        Task(callback: `funcName`, args: nil)
 
-      Task(callback: `funcName`, args: nil)
 
   when defined(nimTasksDebug):
     echo result.repr
 
-runnableExamples("--gc:orc"):
+runnableExamples:
   block:
     var num = 0
     proc hello(a: int) = inc num, a
diff --git a/lib/std/tempfiles.nim b/lib/std/tempfiles.nim
index 1160aaaad..539305bde 100644
--- a/lib/std/tempfiles.nim
+++ b/lib/std/tempfiles.nim
@@ -17,7 +17,7 @@ See also:
 * `mkstemp` (posix), refs https://man7.org/linux/man-pages/man3/mkstemp.3.html
 ]#
 
-import os, random
+import std / [os, random]
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -29,7 +29,7 @@ const
 
 
 when defined(windows):
-  import winlean
+  import std/winlean
   when defined(nimPreviewSlimSystem):
     import std/widestrs
 
@@ -46,7 +46,7 @@ when defined(windows):
   proc close_osfandle(fd: cint): cint {.
     importc: "_close", header: "<io.h>".}
 else:
-  import posix
+  import std/posix
 
   proc c_fdopen(
     filehandle: cint,
diff --git a/lib/std/time_t.nim b/lib/std/time_t.nim
index 7fb6e6d46..de051b135 100644
--- a/lib/std/time_t.nim
+++ b/lib/std/time_t.nim
@@ -14,10 +14,10 @@ when defined(nimdoc):
       ## Wrapper for `time_t`. On posix, this is an alias to `posix.Time`.
 elif defined(windows):
   when defined(i386) and defined(gcc):
-    type Time* {.importc: "time_t", header: "<time.h>".} = distinct int32
+    type Time* {.importc: "time_t", header: "<time.h>".} = distinct clong
   else:
     # newest version of Visual C++ defines time_t to be of 64 bits
     type Time* {.importc: "time_t", header: "<time.h>".} = distinct int64
 elif defined(posix):
-  import posix
+  import std/posix
   export posix.Time
\ No newline at end of file
diff --git a/lib/std/typedthreads.nim b/lib/std/typedthreads.nim
index 53b18d01e..7b0b81968 100644
--- a/lib/std/typedthreads.nim
+++ b/lib/std/typedthreads.nim
@@ -7,38 +7,74 @@
 #    distribution, for details about the copyright.
 #
 
-## Thread support for Nim.
-##
-## Nim's memory model for threads is quite different from other common
-## programming languages (C, Pascal): Each thread has its own
-## (garbage collected) heap and sharing of memory is restricted. This helps
-## to prevent race conditions and improves efficiency. See `the manual for
-## details of this memory model <manual.html#threads>`_.
-##
-## Examples
-## ========
-##
-## .. code-block:: Nim
-##
-##  import std/locks
-##
-##  var
-##    thr: array[0..4, Thread[tuple[a,b: int]]]
-##    L: Lock
-##
-##  proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
-##    for i in interval.a..interval.b:
-##      acquire(L) # lock stdout
-##      echo i
-##      release(L)
-##
-##  initLock(L)
-##
-##  for i in 0..high(thr):
-##    createThread(thr[i], threadFunc, (i*10, i*10+5))
-##  joinThreads(thr)
-##
-##  deinitLock(L)
+##[
+Thread support for Nim. Threads allow multiple functions to execute concurrently.
+ 
+In Nim, threads are a low-level construct and using a library like `malebolgia`, `taskpools` or `weave` is recommended.
+ 
+When creating a thread, you can pass arguments to it. As Nim's garbage collector does not use atomic references, sharing
+`ref` and other variables managed by the garbage collector between threads is not supported.
+Use global variables to do so, or pointers.
+ 
+Memory allocated using [`sharedAlloc`](./system.html#allocShared.t%2CNatural) can be used and shared between threads.
+
+To communicate between threads, consider using [channels](./system.html#Channel)
+
+Examples
+========
+
+```Nim
+import std/locks
+
+var
+  thr: array[0..4, Thread[tuple[a,b: int]]]
+  L: Lock
+
+proc threadFunc(interval: tuple[a,b: int]) {.thread.} =
+  for i in interval.a..interval.b:
+    acquire(L) # lock stdout
+    echo i
+    release(L)
+
+initLock(L)
+
+for i in 0..high(thr):
+  createThread(thr[i], threadFunc, (i*10, i*10+5))
+joinThreads(thr)
+
+deinitLock(L)
+```
+ 
+When using a memory management strategy that supports shared heaps like `arc` or `boehm`,
+you can pass pointer to threads and share memory between them, but the memory must outlive the thread.
+The default memory management strategy, `orc`, supports this.
+The example below is **not valid** for memory management strategies that use local heaps like `refc`!
+
+```Nim
+import locks
+ 
+var l: Lock
+ 
+proc threadFunc(obj: ptr seq[int]) {.thread.} =
+  withLock l:
+    for i in 0..<100:
+      obj[].add(obj[].len * obj[].len)
+ 
+proc threadHandler() =
+  var thr: array[0..4, Thread[ptr seq[int]]]
+  var s = newSeq[int]()
+    
+  for i in 0..high(thr):
+    createThread(thr[i], threadFunc, s.addr)
+  joinThreads(thr)
+  echo s
+ 
+initLock(l)
+threadHandler()
+deinitLock(l)
+```
+]##
+
 
 import std/private/[threadtypes]
 export Thread
@@ -51,8 +87,11 @@ when defined(nimPreviewSlimSystem):
 when defined(genode):
   import genode/env
 
+when hostOS == "any":
+  {.error: "Threads not implemented for os:any. Please compile with --threads:off.".}
 
-when hasAllocStack or defined(zephyr) or defined(freertos) or defined(cpu16) or defined(cpu8):
+when hasAllocStack or defined(zephyr) or defined(freertos) or defined(nuttx) or
+    defined(cpu16) or defined(cpu8):
   const
     nimThreadStackSize {.intdefine.} = 8192
     nimThreadStackGuard {.intdefine.} = 128
diff --git a/lib/std/varints.nim b/lib/std/varints.nim
index 0d18b9069..32fe2fffb 100644
--- a/lib/std/varints.nim
+++ b/lib/std/varints.nim
@@ -82,29 +82,29 @@ proc writeVu64*(z: var openArray[byte], x: uint64): int =
       z[3] = cast[uint8](y)
       return 4
     z[0] = 251
-    varintWrite32(toOpenArray(z, 1, z.high-1), y)
+    varintWrite32(toOpenArray(z, 1, 4), y)
     return 5
   if w <= 255:
     z[0] = 252
     z[1] = cast[uint8](w)
-    varintWrite32(toOpenArray(z, 2, z.high-2), y)
+    varintWrite32(toOpenArray(z, 2, 5), y)
     return 6
   if w <= 65535:
     z[0] = 253
     z[1] = cast[uint8](w shr 8)
     z[2] = cast[uint8](w)
-    varintWrite32(toOpenArray(z, 3, z.high-3), y)
+    varintWrite32(toOpenArray(z, 3, 6), y)
     return 7
   if w <= 16777215:
     z[0] = 254
     z[1] = cast[uint8](w shr 16)
     z[2] = cast[uint8](w shr 8)
     z[3] = cast[uint8](w)
-    varintWrite32(toOpenArray(z, 4, z.high-4), y)
+    varintWrite32(toOpenArray(z, 4, 7), y)
     return 8
   z[0] = 255
-  varintWrite32(toOpenArray(z, 1, z.high-1), w)
-  varintWrite32(toOpenArray(z, 5, z.high-5), y)
+  varintWrite32(toOpenArray(z, 1, 4), w)
+  varintWrite32(toOpenArray(z, 5, 8), y)
   return 9
 
 proc sar(a, b: int64): int64 =
diff --git a/lib/std/widestrs.nim b/lib/std/widestrs.nim
index 8973579e1..2ddf80d14 100644
--- a/lib/std/widestrs.nim
+++ b/lib/std/widestrs.nim
@@ -25,12 +25,21 @@ when not (defined(cpu16) or defined(cpu8)):
         bytes: int
         data: WideCString
 
-    proc `=destroy`(a: var WideCStringObj) =
-      if a.data != nil:
-        when compileOption("threads"):
-          deallocShared(a.data)
-        else:
-          dealloc(a.data)
+    const arcLike = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc)
+    when defined(nimAllowNonVarDestructor) and arcLike:
+      proc `=destroy`(a: WideCStringObj) =
+        if a.data != nil:
+          when compileOption("threads"):
+            deallocShared(a.data)
+          else:
+            dealloc(a.data)
+    else:
+      proc `=destroy`(a: var WideCStringObj) =
+        if a.data != nil:
+          when compileOption("threads"):
+            deallocShared(a.data)
+          else:
+            dealloc(a.data)
 
     proc `=copy`(a: var WideCStringObj; b: WideCStringObj) {.error.}
 
@@ -146,6 +155,7 @@ when not (defined(cpu16) or defined(cpu8)):
     createWide(result, size * 2 + 2)
 
   proc newWideCString*(source: cstring, L: int): WideCStringObj =
+    ## Warning:: `source` needs to be preallocated with the length `L`
     createWide(result, L * 2 + 2)
     var d = 0
     for ch in runes(source, L):
diff --git a/lib/std/with.nim b/lib/std/with.nim
index c7338b4e4..c2eaa4bef 100644
--- a/lib/std/with.nim
+++ b/lib/std/with.nim
@@ -14,7 +14,7 @@
 ##
 ## **Since:** version 1.2.
 
-import macros, private / underscored_calls
+import std/[macros, private / underscored_calls]
 
 macro with*(arg: typed; calls: varargs[untyped]): untyped =
   ## This macro provides `chaining`:idx: of function calls.
@@ -35,5 +35,14 @@ macro with*(arg: typed; calls: varargs[untyped]): untyped =
       -= 5
     doAssert a == 43
 
+    # Nesting works for object types too!
+    var foo = (bar: 1, qux: (baz: 2))
+    with foo:
+      bar = 2
+      with qux:
+        baz = 3
+    doAssert foo.bar == 2
+    doAssert foo.qux.baz == 3
+
   result = newNimNode(nnkStmtList, arg)
   underscoredCalls(result, calls, arg)
diff --git a/lib/std/wordwrap.nim b/lib/std/wordwrap.nim
index 7dcfc7f59..9333f880b 100644
--- a/lib/std/wordwrap.nim
+++ b/lib/std/wordwrap.nim
@@ -9,7 +9,7 @@
 
 ## This module contains an algorithm to wordwrap a Unicode string.
 
-import strutils, unicode
+import std/[strutils, unicode]
 
 proc olen(s: string; start, lastExclusive: int): int =
   var i = start
diff --git a/lib/std/wrapnils.nim b/lib/std/wrapnils.nim
index 235638134..0b75c270e 100644
--- a/lib/std/wrapnils.nim
+++ b/lib/std/wrapnils.nim
@@ -13,7 +13,7 @@ consider handling indexing operations, eg:
 doAssert ?.default(seq[int])[3] == default(int)
 ]#
 
-import macros
+import std/macros
 
 runnableExamples:
   type Foo = ref object
@@ -122,7 +122,7 @@ macro `?.`*(a: typed): auto =
     `lhs`
 
 # the code below is not needed for `?.`
-from options import Option, isSome, get, option, unsafeGet, UnpackDefect
+from std/options import Option, isSome, get, option, unsafeGet, UnpackDefect
 
 macro `??.`*(a: typed): Option =
   ## Same as `?.` but returns an `Option`.
diff --git a/lib/system.nim b/lib/system.nim
index 8faf8f4ce..2f9cdc5f9 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -25,7 +25,11 @@
 include "system/basic_types"
 
 func zeroDefault*[T](_: typedesc[T]): T {.magic: "ZeroDefault".} =
-  ## returns the default value of the type `T`.
+  ## Returns the binary zeros representation of the type `T`. It ignores
+  ## default fields of an object.
+  ##
+  ## See also:
+  ## * `default <#default,typedesc[T]>`_
 
 include "system/compilation"
 
@@ -62,11 +66,11 @@ proc typeof*(x: untyped; mode = typeOfIter): typedesc {.
     doAssert type(myFoo()) is string
     doAssert typeof(myFoo()) is string
     doAssert typeof(myFoo(), typeOfIter) is string
-    doAssert typeof(myFoo3) is "iterator"
+    doAssert typeof(myFoo3) is iterator
 
     doAssert typeof(myFoo(), typeOfProc) is float
     doAssert typeof(0.0, typeOfProc) is float
-    doAssert typeof(myFoo3, typeOfProc) is "iterator"
+    doAssert typeof(myFoo3, typeOfProc) is iterator
     doAssert not compiles(typeof(myFoo2(), typeOfProc))
       # this would give: Error: attempting to call routine: 'myFoo2'
       # since `typeOfProc` expects a typed expression and `myFoo2()` can
@@ -85,17 +89,12 @@ when defined(nimHasIterable):
   type
     iterable*[T] {.magic: IterableType.}  ## Represents an expression that yields `T`
 
-when defined(nimHashOrdinalFixed):
-  type
-    Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer,
-                                   ## bool, character, and enumeration types
-                                   ## as well as their subtypes. See also
-                                   ## `SomeOrdinal`.
-else:
-  # bootstrap < 1.2.0
-  type
-    OrdinalImpl[T] {.magic: Ordinal.}
-    Ordinal* = OrdinalImpl | uint | uint64
+type
+  Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer,
+                                  ## bool, character, and enumeration types
+                                  ## as well as their subtypes. See also
+                                  ## `SomeOrdinal`.
+
 
 proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} =
   ## Builtin `addr` operator for taking the address of a memory location.
@@ -109,7 +108,7 @@ proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} =
   ##
   ## Cannot be overloaded.
   ##
-  ##   ```
+  ##   ```nim
   ##   var
   ##     buf: seq[char] = @['a','b','c']
   ##     p = buf[1].addr
@@ -126,9 +125,6 @@ proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} =
 
 const ThisIsSystem = true
 
-proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.}
-  ## Leaked implementation detail. Do not use.
-
 proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
   magic: "NewFinalize", noSideEffect.}
   ## Creates a new object of type `T` and returns a safe (traced)
@@ -142,15 +138,32 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {.
   ## **Note**: The `finalizer` refers to the type `T`, not to the object!
   ## This means that for each object of type `T` the finalizer will be called!
 
-proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} =
+proc `=wasMoved`*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} =
+  ## Generic `wasMoved`:idx: implementation that can be overridden.
+
+proc wasMoved*[T](obj: var T) {.inline, noSideEffect.} =
   ## Resets an object `obj` to its initial (binary zero) value to signify
   ## it was "moved" and to signify its destructor should do nothing and
   ## ideally be optimized away.
-  discard
+  {.cast(raises: []), cast(tags: []).}:
+    `=wasMoved`(obj)
 
 proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} =
   result = x
-  wasMoved(x)
+  {.cast(raises: []), cast(tags: []).}:
+    `=wasMoved`(x)
+
+when defined(nimHasEnsureMove):
+  proc ensureMove*[T](x: T): T {.magic: "EnsureMove", noSideEffect.} =
+    ## Ensures that `x` is moved to the new location, otherwise it gives
+    ## an error at the compile time.
+    runnableExamples:
+      proc foo =
+        var x = "Hello"
+        let y = ensureMove(x)
+        doAssert y == "Hello"
+      foo()
+    discard "implemented in injectdestructors"
 
 type
   range*[T]{.magic: "Range".}         ## Generic type to construct range types.
@@ -180,7 +193,7 @@ proc high*[T: Ordinal|enum|range](x: T): T {.magic: "High", noSideEffect,
   ## **This proc is deprecated**, use this one instead:
   ## * `high(typedesc) <#high,typedesc[T]>`_
   ##
-  ## ```
+  ## ```nim
   ## high(2) # => 9223372036854775807
   ## ```
 
@@ -188,7 +201,7 @@ proc high*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "High", noSideEffe
   ## Returns the highest possible value of an ordinal or enum type.
   ##
   ## `high(int)` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:.
-  ##   ```
+  ##   ```nim
   ##   high(int) # => 9223372036854775807
   ##   ```
   ##
@@ -197,7 +210,7 @@ proc high*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "High", noSideEffe
 
 proc high*[T](x: openArray[T]): int {.magic: "High", noSideEffect.}
   ## Returns the highest possible index of a sequence `x`.
-  ##   ```
+  ##   ```nim
   ##   var s = @[1, 2, 3, 4, 5, 6, 7]
   ##   high(s) # => 6
   ##   for i in low(s)..high(s):
@@ -211,7 +224,7 @@ proc high*[I, T](x: array[I, T]): I {.magic: "High", noSideEffect.}
   ## Returns the highest possible index of an array `x`.
   ##
   ## For empty arrays, the return type is `int`.
-  ##   ```
+  ##   ```nim
   ##   var arr = [1, 2, 3, 4, 5, 6, 7]
   ##   high(arr) # => 6
   ##   for i in low(arr)..high(arr):
@@ -225,7 +238,7 @@ proc high*[I, T](x: typedesc[array[I, T]]): I {.magic: "High", noSideEffect.}
   ## Returns the highest possible index of an array type.
   ##
   ## For empty arrays, the return type is `int`.
-  ##   ```
+  ##   ```nim
   ##   high(array[7, int]) # => 6
   ##   ```
   ##
@@ -241,7 +254,7 @@ proc high*(x: cstring): int {.magic: "High", noSideEffect.}
 
 proc high*(x: string): int {.magic: "High", noSideEffect.}
   ## Returns the highest possible index of a string `x`.
-  ##   ```
+  ##   ```nim
   ##   var str = "Hello world!"
   ##   high(str) # => 11
   ##   ```
@@ -257,7 +270,7 @@ proc low*[T: Ordinal|enum|range](x: T): T {.magic: "Low", noSideEffect,
   ## **This proc is deprecated**, use this one instead:
   ## * `low(typedesc) <#low,typedesc[T]>`_
   ##
-  ## ```
+  ## ```nim
   ## low(2) # => -9223372036854775808
   ## ```
 
@@ -265,7 +278,7 @@ proc low*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "Low", noSideEffect
   ## Returns the lowest possible value of an ordinal or enum type.
   ##
   ## `low(int)` is Nim's way of writing `INT_MIN`:idx: or `MIN_INT`:idx:.
-  ##   ```
+  ##   ```nim
   ##   low(int) # => -9223372036854775808
   ##   ```
   ##
@@ -274,7 +287,7 @@ proc low*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "Low", noSideEffect
 
 proc low*[T](x: openArray[T]): int {.magic: "Low", noSideEffect.}
   ## Returns the lowest possible index of a sequence `x`.
-  ##   ```
+  ##   ```nim
   ##   var s = @[1, 2, 3, 4, 5, 6, 7]
   ##   low(s) # => 0
   ##   for i in low(s)..high(s):
@@ -288,7 +301,7 @@ proc low*[I, T](x: array[I, T]): I {.magic: "Low", noSideEffect.}
   ## Returns the lowest possible index of an array `x`.
   ##
   ## For empty arrays, the return type is `int`.
-  ##   ```
+  ##   ```nim
   ##   var arr = [1, 2, 3, 4, 5, 6, 7]
   ##   low(arr) # => 0
   ##   for i in low(arr)..high(arr):
@@ -302,7 +315,7 @@ proc low*[I, T](x: typedesc[array[I, T]]): I {.magic: "Low", noSideEffect.}
   ## Returns the lowest possible index of an array type.
   ##
   ## For empty arrays, the return type is `int`.
-  ##   ```
+  ##   ```nim
   ##   low(array[7, int]) # => 0
   ##   ```
   ##
@@ -317,7 +330,7 @@ proc low*(x: cstring): int {.magic: "Low", noSideEffect.}
 
 proc low*(x: string): int {.magic: "Low", noSideEffect.}
   ## Returns the lowest possible index of a string `x`.
-  ##   ```
+  ##   ```nim
   ##   var str = "Hello world!"
   ##   low(str) # => 0
   ##   ```
@@ -325,7 +338,7 @@ proc low*(x: string): int {.magic: "Low", noSideEffect.}
   ## See also:
   ## * `high(string) <#high,string>`_
 
-when not defined(gcArc) and not defined(gcOrc):
+when not defined(gcArc) and not defined(gcOrc) and not defined(gcAtomicArc):
   proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".}
     ## Use this instead of `=` for a `shallow copy`:idx:.
     ##
@@ -349,12 +362,36 @@ proc arrGet[I: Ordinal;T](a: T; i: I): T {.
 proc arrPut[I: Ordinal;T,S](a: T; i: I;
   x: S) {.noSideEffect, magic: "ArrPut".}
 
-proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} =
-  ## Generic `destructor`:idx: implementation that can be overridden.
-  discard
+const arcLikeMem = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc)
+
+
+when defined(nimAllowNonVarDestructor) and arcLikeMem and defined(nimPreviewNonVarDestructor):
+  proc `=destroy`*[T](x: T) {.inline, magic: "Destroy".} =
+    ## Generic `destructor`:idx: implementation that can be overridden.
+    discard
+else:
+  proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} =
+    ## Generic `destructor`:idx: implementation that can be overridden.
+    discard
+
+  when defined(nimAllowNonVarDestructor) and arcLikeMem:
+    proc `=destroy`*(x: string) {.inline, magic: "Destroy", enforceNoRaises.} =
+      discard
+
+    proc `=destroy`*[T](x: seq[T]) {.inline, magic: "Destroy".} =
+      discard
+
+    proc `=destroy`*[T](x: ref T) {.inline, magic: "Destroy".} =
+      discard
+
+when defined(nimHasDup):
+  proc `=dup`*[T](x: T): T {.inline, magic: "Dup".} =
+    ## Generic `dup`:idx: implementation that can be overridden.
+    discard
+
 proc `=sink`*[T](x: var T; y: T) {.inline, nodestroy, magic: "Asgn".} =
   ## Generic `sink`:idx: implementation that can be overridden.
-  when defined(gcArc) or defined(gcOrc):
+  when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
     x = y
   else:
     shallowCopy(x, y)
@@ -376,7 +413,7 @@ proc `..`*[T, U](a: sink T, b: sink U): HSlice[T, U] {.noSideEffect, inline, mag
   ##
   ## Slices can also be used in the set constructor and in ordinal case
   ## statements, but then they are special-cased by the compiler.
-  ##   ```
+  ##   ```nim
   ##   let a = [10, 20, 30, 40, 50]
   ##   echo a[2 .. 3] # @[30, 40]
   ##   ```
@@ -385,7 +422,7 @@ proc `..`*[T, U](a: sink T, b: sink U): HSlice[T, U] {.noSideEffect, inline, mag
 proc `..`*[T](b: sink T): HSlice[int, T]
   {.noSideEffect, inline, magic: "DotDot", deprecated: "replace `..b` with `0..b`".} =
   ## Unary `slice`:idx: operator that constructs an interval `[default(int), b]`.
-  ##   ```
+  ##   ```nim
   ##   let a = [10, 20, 30, 40, 50]
   ##   echo a[.. 2] # @[10, 20, 30]
   ##   ```
@@ -424,10 +461,6 @@ when not defined(js) and not defined(nimSeqsV2):
       data: UncheckedArray[char]
     NimString = ptr NimStringDesc
 
-when notJSnotNims and not defined(nimSeqsV2):
-  template space(s: PGenericSeq): int {.dirty.} =
-    s.reserved and not (seqShallowFlag or strlitFlag)
-
 when notJSnotNims:
   include "system/hti"
 
@@ -451,9 +484,7 @@ type
            ## However, objects that have no ancestor are also allowed.
   RootRef* = ref RootObj ## Reference to `RootObj`.
 
-const NimStackTraceMsgs =
-  when defined(nimHasStacktraceMsgs): compileOption("stacktraceMsgs")
-  else: false
+const NimStackTraceMsgs = compileOption("stacktraceMsgs")
 
 type
   RootEffect* {.compilerproc.} = object of RootObj ## \
@@ -542,7 +573,7 @@ proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.}
   ## sizeof should fallback to the `sizeof` in the C compiler. The
   ## result isn't available for the Nim compiler and therefore can't
   ## be used inside of macros.
-  ##   ```
+  ##   ```nim
   ##   sizeof('A') # => 1
   ##   sizeof(2) # => 8
   ##   ```
@@ -573,7 +604,7 @@ proc newSeq*[T](s: var seq[T], len: Natural) {.magic: "NewSeq", noSideEffect.}
   ## Note that the sequence will be filled with zeroed entries.
   ## After the creation of the sequence you should assign entries to
   ## the sequence instead of adding them. Example:
-  ##   ```
+  ##   ```nim
   ##   var inputStrings: seq[string]
   ##   newSeq(inputStrings, 3)
   ##   assert len(inputStrings) == 3
@@ -589,7 +620,7 @@ proc newSeq*[T](len = 0.Natural): seq[T] =
   ## Note that the sequence will be filled with zeroed entries.
   ## After the creation of the sequence you should assign entries to
   ## the sequence instead of adding them.
-  ##   ```
+  ##   ```nim
   ##   var inputStrings = newSeq[string](3)
   ##   assert len(inputStrings) == 3
   ##   inputStrings[0] = "The fourth"
@@ -600,14 +631,14 @@ proc newSeq*[T](len = 0.Natural): seq[T] =
   ##
   ## See also:
   ## * `newSeqOfCap <#newSeqOfCap,Natural>`_
-  ## * `newSeqUninitialized <#newSeqUninitialized,Natural>`_
+  ## * `newSeqUninit <#newSeqUninit,Natural>`_
   newSeq(result, len)
 
 proc newSeqOfCap*[T](cap: Natural): seq[T] {.
   magic: "NewSeqOfCap", noSideEffect.} =
   ## Creates a new sequence of type `seq[T]` with length zero and capacity
   ## `cap`. Example:
-  ##   ```
+  ##   ```nim
   ##   var x = newSeqOfCap[int](5)
   ##   assert len(x) == 0
   ##   x.add(10)
@@ -615,26 +646,6 @@ proc newSeqOfCap*[T](cap: Natural): seq[T] {.
   ##   ```
   discard
 
-when not defined(js):
-  proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] =
-    ## Creates a new sequence of type `seq[T]` with length `len`.
-    ##
-    ## Only available for numbers types. Note that the sequence will be
-    ## uninitialized. After the creation of the sequence you should assign
-    ## entries to the sequence instead of adding them.
-    ## Example:
-    ##   ```
-    ##   var x = newSeqUninitialized[int](3)
-    ##   assert len(x) == 3
-    ##   x[0] = 10
-    ##   ```
-    result = newSeqOfCap[T](len)
-    when defined(nimSeqsV2):
-      cast[ptr int](addr result)[] = len
-    else:
-      var s = cast[PGenericSeq](result)
-      s.len = len
-
 func len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.magic: "LengthOpenArray".} =
   ## Returns the length of an openArray.
   runnableExamples:
@@ -717,7 +728,7 @@ include "system/setops"
 proc contains*[U, V, W](s: HSlice[U, V], value: W): bool {.noSideEffect, inline.} =
   ## Checks if `value` is within the range of `s`; returns true if
   ## `value >= s.a and value <= s.b`.
-  ##   ```
+  ##   ```nim
   ##   assert((1..3).contains(1) == true)
   ##   assert((1..3).contains(2) == true)
   ##   assert((1..3).contains(4) == false)
@@ -729,13 +740,13 @@ when not defined(nimHasCallsitePragma):
 
 template `in`*(x, y: untyped): untyped {.dirty, callsite.} = contains(y, x)
   ## Sugar for `contains`.
-  ##   ```
+  ##   ```nim
   ##   assert(1 in (1..3) == true)
   ##   assert(5 in (1..3) == false)
   ##   ```
 template `notin`*(x, y: untyped): untyped {.dirty, callsite.} = not contains(y, x)
   ## Sugar for `not contains`.
-  ##   ```
+  ##   ```nim
   ##   assert(1 notin (1..3) == false)
   ##   assert(5 notin (1..3) == true)
   ##   ```
@@ -745,7 +756,7 @@ proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
   ##
   ## For a negated version, use `isnot <#isnot.t,untyped,untyped>`_.
   ##
-  ##   ```
+  ##   ```nim
   ##   assert 42 is int
   ##   assert @[1, 2] is seq
   ##
@@ -760,7 +771,7 @@ proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.}
   ##   ```
 template `isnot`*(x, y: untyped): untyped {.callsite.} = not (x is y)
   ## Negated version of `is <#is,T,S>`_. Equivalent to `not(x is y)`.
-  ##   ```
+  ##   ```nim
   ##   assert 42 isnot float
   ##   assert @[1, 2] isnot enum
   ##   ```
@@ -856,7 +867,7 @@ proc cmp*[T](x, y: T): int =
   ##
   ## This is useful for writing generic algorithms without performance loss.
   ## This generic implementation uses the `==` and `<` operators.
-  ##   ```
+  ##   ```nim
   ##   import std/algorithm
   ##   echo sorted(@[4, 2, 6, 5, 8, 7], cmp[int])
   ##   ```
@@ -877,7 +888,7 @@ proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {.magic: "ArrToSeq", noSideEff
   ## sequences with the array constructor: `@[1, 2, 3]` has the type
   ## `seq[int]`, while `[1, 2, 3]` has the type `array[0..2, int]`.
   ##
-  ##   ```
+  ##   ```nim
   ##   let
   ##     a = [1, 3, 5]
   ##     b = "foo"
@@ -887,35 +898,39 @@ proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {.magic: "ArrToSeq", noSideEff
   ##   ```
 
 proc default*[T](_: typedesc[T]): T {.magic: "Default", noSideEffect.} =
-  ## returns the default value of the type `T`.
-  runnableExamples:
+  ## Returns the default value of the type `T`. Contrary to `zeroDefault`, it takes default fields
+  ## of an object into consideration.
+  ##
+  ## See also:
+  ## * `zeroDefault <#zeroDefault,typedesc[T]>`_
+  ##
+  runnableExamples("-d:nimPreviewRangeDefault"):
     assert (int, float).default == (0, 0.0)
-    # note: `var a = default(T)` is usually the same as `var a: T` and (currently) generates
-    # a value whose binary representation is all 0, regardless of whether this
-    # would violate type constraints such as `range`, `not nil`, etc. This
-    # property is required to implement certain algorithms efficiently which
-    # may require intermediate invalid states.
     type Foo = object
       a: range[2..6]
-    var a1: range[2..6] # currently, this compiles
-    # var a2: Foo # currently, this errors: Error: The Foo type doesn't have a default value.
-    # var a3 = Foo() # ditto
-    var a3 = Foo.default # this works, but generates a `UnsafeDefault` warning.
-  # note: the doc comment also explains why `default` can't be implemented
-  # via: `template default*[T](t: typedesc[T]): T = (var v: T; v)`
+    var x = Foo.default
+    assert x.a == 2
 
 
 proc reset*[T](obj: var T) {.noSideEffect.} =
   ## Resets an object `obj` to its default value.
-  obj = default(typeof(obj))
+  when nimvm:
+    obj = default(typeof(obj))
+  else:
+    when defined(gcDestructors):
+      {.cast(noSideEffect), cast(raises: []), cast(tags: []).}:
+        `=destroy`(obj)
+        `=wasMoved`(obj)
+    else:
+      obj = default(typeof(obj))
 
 proc setLen*[T](s: var seq[T], newlen: Natural) {.
-  magic: "SetLengthSeq", noSideEffect.}
+  magic: "SetLengthSeq", noSideEffect, nodestroy.}
   ## Sets the length of seq `s` to `newlen`. `T` may be any sequence type.
   ##
   ## If the current length is greater than the new length,
   ## `s` will be truncated.
-  ##   ```
+  ##   ```nim
   ##   var x = @[10, 20]
   ##   x.setLen(5)
   ##   x[4] = 50
@@ -930,7 +945,7 @@ proc setLen*(s: var string, newlen: Natural) {.
   ##
   ## If the current length is greater than the new length,
   ## `s` will be truncated.
-  ##   ```
+  ##   ```nim
   ##   var myS = "Nim is great!!"
   ##   myS.setLen(3) # myS <- "Nim"
   ##   echo myS, " is fantastic!!"
@@ -938,8 +953,8 @@ proc setLen*(s: var string, newlen: Natural) {.
 
 proc newString*(len: Natural): string {.
   magic: "NewString", importc: "mnewString", noSideEffect.}
-  ## Returns a new string of length `len` but with uninitialized
-  ## content. One needs to fill the string character after character
+  ## Returns a new string of length `len`.
+  ## One needs to fill the string character after character
   ## with the index operator `s[i]`.
   ##
   ## This procedure exists only for optimization purposes;
@@ -955,25 +970,25 @@ proc newStringOfCap*(cap: Natural): string {.
 proc `&`*(x: string, y: char): string {.
   magic: "ConStrStr", noSideEffect.}
   ## Concatenates `x` with `y`.
-  ##   ```
+  ##   ```nim
   ##   assert("ab" & 'c' == "abc")
   ##   ```
 proc `&`*(x, y: char): string {.
   magic: "ConStrStr", noSideEffect.}
   ## Concatenates characters `x` and `y` into a string.
-  ##   ```
+  ##   ```nim
   ##   assert('a' & 'b' == "ab")
   ##   ```
 proc `&`*(x, y: string): string {.
   magic: "ConStrStr", noSideEffect.}
   ## Concatenates strings `x` and `y`.
-  ##   ```
+  ##   ```nim
   ##   assert("ab" & "cd" == "abcd")
   ##   ```
 proc `&`*(x: char, y: string): string {.
   magic: "ConStrStr", noSideEffect.}
   ## Concatenates `x` with `y`.
-  ##   ```
+  ##   ```nim
   ##   assert('a' & "bc" == "abc")
   ##   ```
 
@@ -982,7 +997,7 @@ proc `&`*(x: char, y: string): string {.
 
 proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.}
   ## Appends `y` to `x` in place.
-  ##   ```
+  ##   ```nim
   ##   var tmp = ""
   ##   tmp.add('a')
   ##   tmp.add('b')
@@ -1022,7 +1037,7 @@ const
     ## Possible values:
     ## `"i386"`, `"alpha"`, `"powerpc"`, `"powerpc64"`, `"powerpc64el"`,
     ## `"sparc"`, `"amd64"`, `"mips"`, `"mipsel"`, `"arm"`, `"arm64"`,
-    ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, '"loongarch64"'.
+    ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, `"loongarch64"`.
 
   seqShallowFlag = low(int)
   strlitFlag = 1 shl (sizeof(int)*8 - 2) # later versions of the codegen \
@@ -1033,6 +1048,10 @@ const
   hasThreadSupport = compileOption("threads") and not defined(nimscript)
   hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own
 
+when notJSnotNims and not defined(nimSeqsV2):
+  template space(s: PGenericSeq): int =
+    s.reserved and not (seqShallowFlag or strlitFlag)
+
 when hasThreadSupport and defined(tcc) and not compileOption("tlsEmulation"):
   # tcc doesn't support TLS
   {.error: "`--tlsEmulation:on` must be used when using threads with tcc backend".}
@@ -1088,31 +1107,9 @@ proc align(address, alignment: int): int =
   else:
     result = (address + (alignment - 1)) and not (alignment - 1)
 
-when defined(nimNoQuit):
-  proc rawQuit(errorcode: int = QuitSuccess) = discard "ignoring quit"
-
-elif defined(genode):
-  import genode/env
-
-  var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr
-
-  type GenodeEnv* = GenodeEnvPtr
-    ## Opaque type representing Genode environment.
-
-  proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn,
-    importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "<base/sleep.h>".}
-
-  proc rawQuit(errorcode: int = QuitSuccess) {.inline, noreturn.} =
-    systemEnv.rawQuit(errorcode)
-
-
-elif defined(js) and defined(nodejs) and not defined(nimscript):
-  proc rawQuit(errorcode: int = QuitSuccess) {.magic: "Exit",
-    importc: "process.exit", noreturn.}
-
-else:
-  proc rawQuit(errorcode: cint) {.
-    magic: "Exit", importc: "exit", header: "<stdlib.h>", noreturn.}
+include system/rawquits
+when defined(genode):
+  export GenodeEnv
 
 template sysAssert(cond: bool, msg: string) =
   when defined(useSysAssert):
@@ -1124,8 +1121,6 @@ template sysAssert(cond: bool, msg: string) =
 
 const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript)
 
-when notJSnotNims and hostOS != "standalone" and hostOS != "any":
-  include "system/cgprocs"
 when notJSnotNims and hasAlloc and not defined(nimSeqsV2):
   proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.}
 
@@ -1137,6 +1132,11 @@ when defined(nimscript) or not defined(nimSeqsV2):
     ## containers should also call their adding proc `add` for consistency.
     ## Generic code becomes much easier to write if the Nim naming scheme is
     ## respected.
+    ##   ```nim
+    ##   var s: seq[string] = @["test2","test2"]
+    ##   s.add("test")
+    ##   assert s == @["test2", "test2", "test"]
+    ##   ```
 
 when false: # defined(gcDestructors):
   proc add*[T](x: var seq[T], y: sink openArray[T]) {.noSideEffect.} =
@@ -1146,7 +1146,7 @@ when false: # defined(gcDestructors):
     ## containers should also call their adding proc `add` for consistency.
     ## Generic code becomes much easier to write if the Nim naming scheme is
     ## respected.
-    ##   ```
+    ##   ```nim
     ##   var s: seq[string] = @["test2","test2"]
     ##   s.add("test") # s <- @[test2, test2, test]
     ##   ```
@@ -1171,13 +1171,17 @@ else:
     ## containers should also call their adding proc `add` for consistency.
     ## Generic code becomes much easier to write if the Nim naming scheme is
     ## respected.
-    ##   ```
-    ##   var s: seq[string] = @["test2","test2"]
-    ##   s.add("test") # s <- @[test2, test2, test]
-    ##   ```
     ##
     ## See also:
     ## * `& proc <#&,seq[T],seq[T]>`_
+    runnableExamples:
+      var a = @["a1", "a2"]
+      a.add(["b1", "b2"])
+      assert a == @["a1", "a2", "b1", "b2"]
+      var c = @["c0", "c1", "c2", "c3"]
+      a.add(c.toOpenArray(1, 2))
+      assert a == @["a1", "a2", "b1", "b2", "c1", "c2"]
+
     {.noSideEffect.}:
       let xl = x.len
       setLen(x, xl + y.len)
@@ -1208,7 +1212,7 @@ proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} =
 
 proc insert*[T](x: var seq[T], item: sink T, i = 0.Natural) {.noSideEffect.} =
   ## Inserts `item` into `x` at position `i`.
-  ##   ```
+  ##   ```nim
   ##   var i = @[1, 3, 5]
   ##   i.insert(99, 0) # i <- @[99, 1, 3, 5]
   ##   ```
@@ -1239,7 +1243,7 @@ when not defined(nimV2):
     ##
     ## It works even for complex data graphs with cycles. This is a great
     ## debugging tool.
-    ##   ```
+    ##   ```nim
     ##   var s: seq[string] = @["test2", "test2"]
     ##   var i = @[1, 2, 3, 4, 5]
     ##   echo repr(s) # => 0x1055eb050[0x1055ec050"test2", 0x1055ec078"test2"]
@@ -1272,7 +1276,7 @@ proc toFloat*(i: int): float {.noSideEffect, inline.} =
   ## If the conversion fails, `ValueError` is raised.
   ## However, on most platforms the conversion cannot fail.
   ##
-  ##   ```
+  ##   ```nim
   ##   let
   ##     a = 2
   ##     b = 3.7
@@ -1295,7 +1299,7 @@ proc toInt*(f: float): int {.noSideEffect.} =
   ##
   ## Note that some floating point numbers (e.g. infinity or even 1e19)
   ## cannot be accurately converted.
-  ##   ```
+  ##   ```nim
   ##   doAssert toInt(0.49) == 0
   ##   doAssert toInt(0.5) == 1
   ##   doAssert toInt(-0.5) == -1 # rounding is symmetrical
@@ -1308,7 +1312,7 @@ proc toBiggestInt*(f: BiggestFloat): BiggestInt {.noSideEffect.} =
 
 proc `/`*(x, y: int): float {.inline, noSideEffect.} =
   ## Division of integers that results in a float.
-  ##   ```
+  ##   ```nim
   ##   echo 7 / 5 # => 1.4
   ##   ```
   ##
@@ -1375,7 +1379,7 @@ proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.}
   ## This is often more efficient than `tmp = a; a = b; b = tmp`.
   ## Particularly useful for sorting algorithms.
   ##
-  ##   ```
+  ##   ```nim
   ##   var
   ##     a = 5
   ##     b = 9
@@ -1414,7 +1418,7 @@ include "system/iterators_1"
 
 proc len*[U: Ordinal; V: Ordinal](x: HSlice[U, V]): int {.noSideEffect, inline.} =
   ## Length of ordinal slice. When x.b < x.a returns zero length.
-  ##   ```
+  ##   ```nim
   ##   assert((0..5).len == 6)
   ##   assert((5..2).len == 0)
   ##   ```
@@ -1425,11 +1429,10 @@ proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
 proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
 proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
 proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}
-proc isNil*[T: proc](x: T): bool {.noSideEffect, magic: "IsNil".}
+proc isNil*[T: proc | iterator {.closure.}](x: T): bool {.noSideEffect, magic: "IsNil".}
   ## Fast check whether `x` is nil. This is sometimes more efficient than
   ## `== nil`.
 
-
 when defined(nimHasTopDownInference):
   # magic used for seq type inference
   proc `@`*[T](a: openArray[T]): seq[T] {.magic: "OpenArrayToSeq".} =
@@ -1455,7 +1458,7 @@ when defined(nimSeqsV2):
     ## Concatenates two sequences.
     ##
     ## Requires copying of the sequences.
-    ##   ```
+    ##   ```nim
     ##   assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6])
     ##   ```
     ##
@@ -1471,7 +1474,7 @@ when defined(nimSeqsV2):
     ## Appends element y to the end of the sequence.
     ##
     ## Requires copying of the sequence.
-    ##   ```
+    ##   ```nim
     ##   assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4])
     ##   ```
     ##
@@ -1486,7 +1489,7 @@ when defined(nimSeqsV2):
     ## Prepends the element x to the beginning of the sequence.
     ##
     ## Requires copying of the sequence.
-    ##   ```
+    ##   ```nim
     ##   assert(1 & @[2, 3, 4] == @[1, 2, 3, 4])
     ##   ```
     newSeq(result, y.len + 1)
@@ -1500,7 +1503,7 @@ else:
     ## Concatenates two sequences.
     ##
     ## Requires copying of the sequences.
-    ##   ```
+    ##   ```nim
     ##   assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6])
     ##   ```
     ##
@@ -1516,7 +1519,7 @@ else:
     ## Appends element y to the end of the sequence.
     ##
     ## Requires copying of the sequence.
-    ##   ```
+    ##   ```nim
     ##   assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4])
     ##   ```
     ##
@@ -1531,7 +1534,7 @@ else:
     ## Prepends the element x to the beginning of the sequence.
     ##
     ## Requires copying of the sequence.
-    ##   ```
+    ##   ```nim
     ##   assert(1 & @[2, 3, 4] == @[1, 2, 3, 4])
     ##   ```
     newSeq(result, y.len + 1)
@@ -1552,7 +1555,7 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[
   ## to retrieve information about the current filename and line number.
   ## Example:
   ##
-  ##   ```
+  ##   ```nim
   ##   import std/strutils
   ##
   ##   template testException(exception, code: untyped): typed =
@@ -1597,17 +1600,97 @@ when not defined(js) and defined(nimV2):
       align: int16
       depth: int16
       display: ptr UncheckedArray[uint32] # classToken
-      when defined(nimTypeNames):
+      when defined(nimTypeNames) or defined(nimArcIds):
         name: cstring
       traceImpl: pointer
       typeInfoV1: pointer # for backwards compat, usually nil
       flags: int
+      when defined(gcDestructors):
+        when defined(cpp):
+          vTable: ptr UncheckedArray[pointer] # vtable for types
+        else:
+          vTable: UncheckedArray[pointer] # vtable for types
     PNimTypeV2 = ptr TNimTypeV2
 
+proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
+
 when notJSnotNims and defined(nimSeqsV2):
   include "system/strs_v2"
   include "system/seqs_v2"
 
+when not defined(js):
+  template newSeqImpl(T, len) =
+    result = newSeqOfCap[T](len)
+    {.cast(noSideEffect).}:
+      when defined(nimSeqsV2):
+        cast[ptr int](addr result)[] = len
+      else:
+        var s = cast[PGenericSeq](result)
+        s.len = len
+
+  proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] {.deprecated: "Use `newSeqUninit` instead".} =
+    ## Creates a new sequence of type `seq[T]` with length `len`.
+    ##
+    ## Only available for numbers types. Note that the sequence will be
+    ## uninitialized. After the creation of the sequence you should assign
+    ## entries to the sequence instead of adding them.
+    ## Example:
+    ##   ```nim
+    ##   var x = newSeqUninitialized[int](3)
+    ##   assert len(x) == 3
+    ##   x[0] = 10
+    ##   ```
+    result = newSeqOfCap[T](len)
+    when defined(nimSeqsV2):
+      cast[ptr int](addr result)[] = len
+    else:
+      var s = cast[PGenericSeq](result)
+      s.len = len
+
+  func newSeqUninit*[T](len: Natural): seq[T] =
+    ## Creates a new sequence of type `seq[T]` with length `len`.
+    ##
+    ## Only available for types, which don't contain
+    ## managed memory or have destructors.
+    ## Note that the sequence will be uninitialized.
+    ## After the creation of the sequence you should assign
+    ## entries to the sequence instead of adding them.
+    runnableExamples:
+      var x = newSeqUninit[int](3)
+      assert len(x) == 3
+      x[0] = 10
+    when supportsCopyMem(T):
+      when nimvm:
+        result = newSeq[T](len)
+      else:
+        newSeqImpl(T, len)
+    else:
+      {.error: "The type T cannot contain managed memory or have destructors".}
+
+  proc newStringUninit*(len: Natural): string =
+    ## Returns a new string of length `len` but with uninitialized
+    ## content. One needs to fill the string character after character
+    ## with the index operator `s[i]`.
+    ##
+    ## This procedure exists only for optimization purposes;
+    ## the same effect can be achieved with the `&` operator or with `add`.
+    when nimvm:
+      result = newString(len)
+    else:
+      result = newStringOfCap(len)
+      when defined(nimSeqsV2):
+        let s = cast[ptr NimStringV2](addr result)
+        if len > 0:
+          s.len = len
+          s.p.data[len] = '\0'
+      else:
+        let s = cast[NimString](result)
+        s.len = len
+        s.data[len] = '\0'
+else:
+  proc newStringUninit*(len: Natural): string {.
+    magic: "NewString", importc: "mnewString", noSideEffect.}
+
 {.pop.}
 
 when not defined(nimscript):
@@ -1619,8 +1702,24 @@ when not defined(nimscript):
 when not declared(sysFatal):
   include "system/fatal"
 
+type
+  PFrame* = ptr TFrame  ## Represents a runtime frame of the call stack;
+                        ## part of the debugger API.
+  # keep in sync with nimbase.h `struct TFrame_`
+  TFrame* {.importc, nodecl, final.} = object ## The frame itself.
+    prev*: PFrame       ## Previous frame; used for chaining the call stack.
+    procname*: cstring  ## Name of the proc that is currently executing.
+    line*: int          ## Line number of the proc that is currently executing.
+    filename*: cstring  ## Filename of the proc that is currently executing.
+    len*: int16         ## Length of the inspectable slots.
+    calldepth*: int16   ## Used for max call depth checking.
+    when NimStackTraceMsgs:
+      frameMsgLen*: int   ## end position in frameMsgBuf for this frame.
 
 when defined(nimV2):
+  var
+    framePtr {.threadvar.}: PFrame
+
   include system/arc
 
 template newException*(exceptn: typedesc, message: string;
@@ -1630,7 +1729,6 @@ template newException*(exceptn: typedesc, message: string;
   (ref exceptn)(msg: message, parent: parentException)
 
 when not defined(nimPreviewSlimSystem):
-  {.deprecated: "assertions is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/assertions`".}
   import std/assertions
   export assertions
 
@@ -1653,7 +1751,7 @@ proc contains*[T](a: openArray[T], item: T): bool {.inline.}=
   ##
   ## This allows the `in` operator: `a.contains(item)` is the same as
   ## `item in a`.
-  ##   ```
+  ##   ```nim
   ##   var a = @[1, 3, 5]
   ##   assert a.contains(5)
   ##   assert 3 in a
@@ -1664,6 +1762,8 @@ proc contains*[T](a: openArray[T], item: T): bool {.inline.}=
 proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} =
   ## Returns the last item of `s` and decreases `s.len` by one. This treats
   ## `s` as a stack and implements the common *pop* operation.
+  ##
+  ## Raises `IndexDefect` if `s` is empty.
   runnableExamples:
     var a = @[1, 3, 5, 7]
     let b = pop(a)
@@ -1745,7 +1845,7 @@ when notJSnotNims:
       ##
       ## `outOfMemHook` can be used to raise an exception in case of OOM like so:
       ##
-      ##   ```
+      ##   ```nim
       ##   var gOutOfMem: ref EOutOfMemory
       ##   new(gOutOfMem) # need to be allocated *before* OOM really happened!
       ##   gOutOfMem.msg = "out of memory"
@@ -1764,20 +1864,6 @@ when notJSnotNims:
       ## writes an error message and terminates the program, except when
       ## using `--os:any`
 
-type
-  PFrame* = ptr TFrame  ## Represents a runtime frame of the call stack;
-                        ## part of the debugger API.
-  # keep in sync with nimbase.h `struct TFrame_`
-  TFrame* {.importc, nodecl, final.} = object ## The frame itself.
-    prev*: PFrame       ## Previous frame; used for chaining the call stack.
-    procname*: cstring  ## Name of the proc that is currently executing.
-    line*: int          ## Line number of the proc that is currently executing.
-    filename*: cstring  ## Filename of the proc that is currently executing.
-    len*: int16         ## Length of the inspectable slots.
-    calldepth*: int16   ## Used for max call depth checking.
-    when NimStackTraceMsgs:
-      frameMsgLen*: int   ## end position in frameMsgBuf for this frame.
-
 when defined(js) or defined(nimdoc):
   proc add*(x: var string, y: cstring) {.asmNoStackFrame.} =
     ## Appends `y` to `x` in place.
@@ -1786,14 +1872,14 @@ when defined(js) or defined(nimdoc):
       tmp.add(cstring("ab"))
       tmp.add(cstring("cd"))
       doAssert tmp == "abcd"
-    asm """
+    {.emit: """
       if (`x` === null) { `x` = []; }
       var off = `x`.length;
       `x`.length += `y`.length;
       for (var i = 0; i < `y`.length; ++i) {
         `x`[off+i] = `y`.charCodeAt(i);
       }
-    """
+    """.}
   proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".} =
     ## Appends `y` to `x` in place.
     ## Only implemented for JS backend.
@@ -1859,7 +1945,7 @@ template likely*(val: bool): bool =
   ## You can use this template to decorate a branch condition. On certain
   ## platforms this can help the processor predict better which branch is
   ## going to be run. Example:
-  ##   ```
+  ##   ```nim
   ##   for value in inputValues:
   ##     if likely(value <= 100):
   ##       process(value)
@@ -1883,7 +1969,7 @@ template unlikely*(val: bool): bool =
   ## You can use this proc to decorate a branch condition. On certain
   ## platforms this can help the processor predict better which branch is
   ## going to be run. Example:
-  ##   ```
+  ##   ```nim
   ##   for value in inputValues:
   ##     if unlikely(value > 100):
   ##       echo "Value too big!"
@@ -1909,15 +1995,11 @@ when defined(nimAuditDelete):
 else:
   {.pragma: auditDelete.}
 
-proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, auditDelete.} =
+proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, systemRaisesDefect, auditDelete.} =
   ## Deletes the item at index `i` by moving all `x[i+1..^1]` items by one position.
   ##
   ## This is an `O(n)` operation.
   ##
-  ## .. note:: With `-d:nimStrictDelete`, an index error is produced when the index passed
-  ##    to it was out of bounds. `-d:nimStrictDelete` will become the default
-  ##    in upcoming versions.
-  ##
   ## See also:
   ## * `del <#del,seq[T],Natural>`_ for O(1) operation
   ##
@@ -1926,7 +2008,7 @@ proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, auditDelete.} =
     s.delete(2)
     doAssert s == @[1, 2, 4, 5]
 
-  when defined(nimStrictDelete):
+  when not defined(nimAuditDelete):
     if i > high(x):
       # xxx this should call `raiseIndexError2(i, high(x))` after some refactoring
       raise (ref IndexDefect)(msg: "index out of bounds: '" & $i & "' < '" & $x.len & "' failed")
@@ -2003,7 +2085,8 @@ when notJSnotNims:
   proc cmpMem(a, b: pointer, size: Natural): int =
     nimCmpMem(a, b, size).int
 
-when not defined(js):
+when not defined(js) or defined(nimscript):
+  # nimscript can be defined if config file for js compilation
   proc cmp(x, y: string): int =
     when nimvm:
       if x < y: result = -1
@@ -2020,12 +2103,14 @@ when not defined(js):
     proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] =
       ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be
       ## of length `len`.
+      if a == nil: return @[]
       newSeq(result, len)
       for i in 0..len-1: result[i] = $a[i]
 
     proc cstringArrayToSeq*(a: cstringArray): seq[string] =
       ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be
       ## terminated by `nil`.
+      if a == nil: return @[]
       var L = 0
       while a[L] != nil: inc(L)
       result = cstringArrayToSeq(a, L)
@@ -2050,7 +2135,7 @@ when not defined(js) and declared(alloc0) and declared(dealloc):
       inc(i)
     dealloc(a)
 
-when notJSnotNims:
+when notJSnotNims and not gotoBasedExceptions:
   type
     PSafePoint = ptr TSafePoint
     TSafePoint {.compilerproc, final.} = object
@@ -2066,7 +2151,6 @@ when not defined(js):
     when hostOS != "standalone":
       include system/threadimpl
       when not defined(nimPreviewSlimSystem):
-        {.deprecated: "threads is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/typedthreads`".}
         import std/typedthreads
         export typedthreads
 
@@ -2080,7 +2164,7 @@ when notJSnotNims:
     ## is pressed. Only one such hook is supported.
     ## Example:
     ##
-    ##   ```
+    ##   ```nim
     ##   proc ctrlc() {.noconv.} =
     ##     echo "Ctrl+C fired!"
     ##     # do clean up stuff
@@ -2113,10 +2197,7 @@ when notJSnotNims:
 
   # we cannot compile this with stack tracing on
   # as it would recurse endlessly!
-  when defined(nimNewIntegerOps):
-    include "system/integerops"
-  else:
-    include "system/arithm"
+  include "system/integerops"
   {.pop.}
 
 
@@ -2129,6 +2210,16 @@ when not defined(js):
 
 when notJSnotNims:
   when hostOS != "standalone" and hostOS != "any":
+    type
+      LibHandle = pointer       # private type
+      ProcAddr = pointer        # library loading and loading of procs:
+
+    proc nimLoadLibrary(path: string): LibHandle {.compilerproc, hcrInline, nonReloadable.}
+    proc nimUnloadLibrary(lib: LibHandle) {.compilerproc, hcrInline, nonReloadable.}
+    proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc, hcrInline, nonReloadable.}
+
+    proc nimLoadLibraryError(path: string) {.compilerproc, hcrInline, nonReloadable.}
+
     include "system/dyncalls"
 
   import system/countbits_impl
@@ -2211,44 +2302,72 @@ when notJSnotNims:
     include "system/profiler"
   {.pop.}
 
-  proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} =
+  proc rawProc*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
     ## Retrieves the raw proc pointer of the closure `x`. This is
-    ## useful for interfacing closures with C/C++, hash compuations, etc.
-    when T is "closure":
-      #[
-      The conversion from function pointer to `void*` is a tricky topic, but this
-      should work at least for c++ >= c++11, e.g. for `dlsym` support.
-      refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869,
-      https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c
-      ]#
-      {.emit: """
-      `result` = (void*)`x`.ClP_0;
-      """.}
-    else:
-      {.error: "Only closure function and iterator are allowed!".}
+    ## useful for interfacing closures with C/C++, hash computations, etc.
+    ## If `rawEnv(x)` returns `nil`, the proc which the result points to
+    ## takes as many parameters as `x`, but with `{.nimcall.}` as its calling
+    ## convention instead of `{.closure.}`, otherwise it takes one more parameter
+    ## which is a `pointer`, and it still has `{.nimcall.}` as its calling convention.
+    ## To invoke the resulted proc, what this returns has to be casted into a `proc`,
+    ## not a `ptr proc`, and, in a case where `rawEnv(x)` returns non-`nil`,
+    ## the last and additional argument has to be the result of `rawEnv(x)`.
+    ## This is not available for the JS target.
+    #[
+    The conversion from function pointer to `void*` is a tricky topic, but this
+    should work at least for c++ >= c++11, e.g. for `dlsym` support.
+    refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869,
+    https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c
+    ]#
+    runnableExamples:
+      proc makeClosure(x: int): (proc(y: int): int) =
+        var n = x
+        result = (
+          proc(y: int): int =
+            n += y
+            return n
+        )
+
+      var
+        c1 = makeClosure(10)
+        e = c1.rawEnv()
+        p = c1.rawProc()
 
-  proc rawEnv*[T: proc](x: T): pointer {.noSideEffect, inline.} =
+      if e.isNil():
+        let c2 = cast[proc(y: int): int {.nimcall.}](p)
+        echo c2(2)
+      else:
+        let c3 = cast[proc(y: int; env: pointer): int {.nimcall.}](p)
+        echo c3(3, e)
+
+    {.emit: """
+    `result` = (void*)`x`.ClP_0;
+    """.}
+
+  proc rawEnv*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} =
     ## Retrieves the raw environment pointer of the closure `x`. See also `rawProc`.
-    when T is "closure":
-      {.emit: """
-      `result` = `x`.ClE_0;
-      """.}
-    else:
-      {.error: "Only closure function and iterator are allowed!".}
-
-  proc finished*[T: proc](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
-    ## It can be used to determine if a first class iterator has finished.
-    when T is "iterator":
-      {.emit: """
-      `result` = ((NI*) `x`.ClE_0)[1] < 0;
-      """.}
-    else:
-      {.error: "Only closure iterator is allowed!".}
+    ## This is not available for the JS target.
+    {.emit: """
+    `result` = `x`.ClE_0;
+    """.}
+
+proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} =
+  ## It can be used to determine if a first class iterator has finished.
+  when defined(js):
+    # TODO: mangle `:state`
+    {.emit: """
+    `result` = (`x`.ClE_0).HEX3Astate < 0;
+    """.}
+  else:
+    {.emit: """
+    `result` = ((NI*) `x`.ClE_0)[1] < 0;
+    """.}
 
 from std/private/digitsutils import addInt
 export addInt
 
-when defined(js):
+when defined(js) and not defined(nimscript):
+  # nimscript can be defined if config file for js compilation
   include "system/jssys"
   include "system/reprjs"
 
@@ -2279,7 +2398,7 @@ elif defined(nimdoc):
     ##    `quit(int(0x100000000))` is equal to `quit(127)` on Linux.
     ##
     ## .. danger:: In almost all cases, in particular in library code, prefer
-    ##   alternatives, e.g. `doAssert false` or raise a `Defect`.
+    ##   alternatives, e.g. `raiseAssert` or raise a `Defect`.
     ##   `quit` bypasses regular control flow in particular `defer`,
     ##   `try`, `catch`, `finally` and `destructors`, and exceptions that may have been
     ##   raised by an `addExitProc` proc, as well as cleanup code in other threads.
@@ -2329,7 +2448,7 @@ include "system/indices"
 
 proc `&=`*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
   ## Appends in place to a string.
-  ##   ```
+  ##   ```nim
   ##   var a = "abc"
   ##   a &= "de" # a <- "abcde"
   ##   ```
@@ -2349,7 +2468,7 @@ when compileOption("rangechecks"):
 else:
   template rangeCheck*(cond) = discard
 
-when not defined(gcArc) and not defined(gcOrc):
+when not defined(gcArc) and not defined(gcOrc) and not defined(gcAtomicArc):
   proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} =
     ## Marks a sequence `s` as `shallow`:idx:. Subsequent assignments will not
     ## perform deep copies of `s`.
@@ -2358,7 +2477,8 @@ when not defined(gcArc) and not defined(gcOrc):
     if s.len == 0: return
     when not defined(js) and not defined(nimscript) and not defined(nimSeqsV2):
       var s = cast[PGenericSeq](s)
-      s.reserved = s.reserved or seqShallowFlag
+      {.noSideEffect.}:
+        s.reserved = s.reserved or seqShallowFlag
 
   proc shallow*(s: var string) {.noSideEffect, inline.} =
     ## Marks a string `s` as `shallow`:idx:. Subsequent assignments will not
@@ -2371,7 +2491,8 @@ when not defined(gcArc) and not defined(gcOrc):
         s = cast[PGenericSeq](newString(0))
       # string literals cannot become 'shallow':
       if (s.reserved and strlitFlag) == 0:
-        s.reserved = s.reserved or seqShallowFlag
+        {.noSideEffect.}:
+          s.reserved = s.reserved or seqShallowFlag
 
 type
   NimNodeObj = object
@@ -2393,18 +2514,30 @@ when defined(nimV2):
   import system/repr_v2
   export repr_v2
 
+proc repr*[T, U](x: HSlice[T, U]): string =
+  ## Generic `repr` operator for slices that is lifted from the components
+  ## of `x`. Example:
+  ##   ```Nim
+  ##   $(1 .. 5) == "1 .. 5"
+  ##   ```
+  result = repr(x.a)
+  result.add(" .. ")
+  result.add(repr(x.b))
+
 when hasAlloc or defined(nimscript):
   proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} =
     ## Inserts `item` into `x` at position `i`.
-    ##   ```
+    ##   ```nim
     ##   var a = "abc"
     ##   a.insert("zz", 0) # a <- "zzabc"
     ##   ```
+    if item.len == 0: # prevents self-assignment
+      return
     var xl = x.len
     setLen(x, xl+item.len)
     var j = xl-1
     while j >= i:
-      when defined(gcArc) or defined(gcOrc):
+      when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc):
         x[j+item.len] = move x[j]
       else:
         shallowCopy(x[j+item.len], x[j])
@@ -2475,7 +2608,7 @@ proc addQuoted*[T](s: var string, x: T) =
   ## Users may overload `addQuoted` for custom (string-like) types if
   ## they want to implement a customized element representation.
   ##
-  ##   ```
+  ##   ```nim
   ##   var tmp = ""
   ##   tmp.addQuoted(1)
   ##   tmp.add(", ")
@@ -2517,7 +2650,7 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} =
   ## the official signature says, the return type is *not* `RootObj` but a
   ## tuple of a structure that depends on the current scope. Example:
   ##
-  ##   ```
+  ##   ```nim
   ##   proc testLocals() =
   ##     var
   ##       a = "something"
@@ -2543,7 +2676,7 @@ when hasAlloc and notJSnotNims:
     ## This is also used by the code generator
     ## for the implementation of `spawn`.
     ##
-    ## For `--gc:arc` or `--gc:orc` deepcopy support has to be enabled
+    ## For `--mm:arc` or `--mm:orc` deepcopy support has to be enabled
     ## via `--deepcopy:on`.
     discard
 
@@ -2556,7 +2689,7 @@ when hasAlloc and notJSnotNims:
 proc procCall*(x: untyped) {.magic: "ProcCall", compileTime.} =
   ## Special magic to prohibit dynamic binding for `method`:idx: calls.
   ## This is similar to `super`:idx: in ordinary OO languages.
-  ##   ```
+  ##   ```nim
   ##   # 'someMethod' will be resolved fully statically:
   ##   procCall someMethod(a, b)
   ##   ```
@@ -2569,7 +2702,7 @@ proc `==`*(x, y: cstring): bool {.magic: "EqCString", noSideEffect,
   proc strcmp(a, b: cstring): cint {.noSideEffect,
     importc, header: "<string.h>".}
   if pointer(x) == pointer(y): result = true
-  elif x.isNil or y.isNil: result = false
+  elif pointer(x) == nil or pointer(y) == nil: result = false
   else: result = strcmp(x, y) == 0
 
 template closureScope*(body: untyped): untyped =
@@ -2581,7 +2714,7 @@ template closureScope*(body: untyped): untyped =
   ##
   ## Example:
   ##
-  ##   ```
+  ##   ```nim
   ##   var myClosure : proc()
   ##   # without closureScope:
   ##   for i in 0 .. 5:
@@ -2601,7 +2734,7 @@ template closureScope*(body: untyped): untyped =
 
 template once*(body: untyped): untyped =
   ## Executes a block of code only once (the first time the block is reached).
-  ##   ```
+  ##   ```nim
   ##   proc draw(t: Triangle) =
   ##     once:
   ##       graphicsInit()
@@ -2658,14 +2791,25 @@ 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*(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".}
+  ## Allows passing the slice of `x` from the element at `first` to the element
+  ## at `last` to `openArray[T]` parameters without copying it.
+  ##
+  ## Example:
+  ##   ```nim
+  ##   proc test(x: openArray[int]) =
+  ##     doAssert x == [1, 2, 3]
+  ##
+  ##   let s = @[0, 1, 2, 3, 4]
+  ##   s.toOpenArray(1, 3).test
+  ##   ```
+
 proc toOpenArray*[T](x: openArray[T]; first, last: int): openArray[T] {.
   magic: "Slice".}
 proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openArray[T] {.
@@ -2680,6 +2824,9 @@ proc toOpenArrayByte*(x: openArray[char]; first, last: int): openArray[byte] {.
 proc toOpenArrayByte*(x: seq[char]; first, last: int): openArray[byte] {.
   magic: "Slice".}
 
+proc toOpenArrayChar*(x: openArray[byte]; first, last: int): openArray[char] {.
+  magic: "Slice".}
+
 when defined(genode):
   var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.}
     ## Hook into the Genode component bootstrap process.
@@ -2719,10 +2866,11 @@ when notJSnotNims:
                     not defined(nintendoswitch) and
                     not defined(freertos) and
                     not defined(zephyr) and
+                    not defined(nuttx) and
                     hostOS != "any"
 
   proc raiseEIO(msg: string) {.noinline, noreturn.} =
-    sysFatal(IOError, msg)
+    raise newException(IOError, msg)
 
   proc echoBinSafe(args: openArray[string]) {.compilerproc.} =
     when defined(androidNDK):
@@ -2752,7 +2900,7 @@ when notJSnotNims:
             # machine. We also enable `setConsoleOutputCP(65001)` now by default.
             # But we cannot call printf directly as the string might contain \0.
             # So we have to loop over all the sections separated by potential \0s.
-            var i = c_fprintf(f, "%s", s)
+            var i = int c_fprintf(f, "%s", s)
             while i < s.len:
               if s[i] == '\0':
                 let w = c_fputc('\0', f)
@@ -2778,7 +2926,6 @@ when notJSnotNims:
         releaseSys echoLock
 
 when not defined(nimPreviewSlimSystem):
-  {.deprecated: "io is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/syncio`".}
   import std/syncio
   export syncio
 
@@ -2790,7 +2937,7 @@ when notJSnotNims and not defined(nimSeqsV2):
     ## String literals (e.g. "abc", etc) in the ARC/ORC mode are "copy on write",
     ## therefore you should call `prepareMutation` before modifying the strings
     ## via `addr`.
-    runnableExamples("--gc:arc"):
+    runnableExamples:
       var x = "abc"
       var y = "defgh"
       prepareMutation(y) # without this, you may get a `SIGBUS` or `SIGSEGV`
@@ -2798,7 +2945,11 @@ when notJSnotNims and not defined(nimSeqsV2):
       assert y == "abcgh"
     discard
 
-proc nimArrayWith[T](y: T, size: static int): array[size, T] {.compilerRtl, raises: [].} =
+proc arrayWith*[T](y: T, size: static int): array[size, T] {.raises: [].} =
   ## Creates a new array filled with `y`.
   for i in 0..size-1:
-    result[i] = y
+    when nimvm:
+      result[i] = y
+    else:
+      # TODO: fixme it should be `=dup`
+      result[i] = y
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 9c8f70c11..3de6d8713 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -20,6 +20,37 @@ template track(op, address, size) =
 
 # We manage *chunks* of memory. Each chunk is a multiple of the page size.
 # Each chunk starts at an address that is divisible by the page size.
+# Small chunks may be divided into smaller cells of reusable pointers to reduce the number of page allocations.
+
+# An allocation of a small pointer looks approximately like this
+#[
+
+  alloc -> rawAlloc -> No free chunk available > Request a new page from tslf -> result = chunk.data -------------+
+              |                                                                                                   |
+              v                                                                                                   |
+    Free chunk available                                                                                          |
+              |                                                                                                   |
+              v                                                                                                   v
+      Fetch shared cells -> No free cells available -> Advance acc -> result = chunk.data + chunk.acc -------> return
+    (may not add new cells)                                                                                       ^
+              |                                                                                                   |
+              v                                                                                                   |
+     Free cells available -> result = chunk.freeList -> Advance chunk.freeList -----------------------------------+
+]#
+# so it is split into 3 paths, where the last path is preferred to prevent unnecessary allocations.
+#
+#
+# A deallocation of a small pointer then looks like this
+#[
+  dealloc -> rawDealloc -> chunk.owner == addr(a) --------------> This thread owns the chunk ------> The current chunk is active    -> Chunk is completely unused -----> Chunk references no foreign cells
+                                      |                                       |                   (Add cell into the current chunk)                 |                  Return the current chunk back to tlsf
+                                      |                                       |                                   |                                 |
+                                      v                                       v                                   v                                 v
+                      A different thread owns this chunk.     The current chunk is not active.          chunk.free was < size      Chunk references foreign cells, noop
+                      Add the cell to a.sharedFreeLists      Add the cell into the active chunk          Activate the chunk                       (end)
+                                    (end)                                    (end)                              (end)
+]#
+# So "true" deallocation is delayed for as long as possible in favor of reusing cells.
 
 const
   nimMinHeapPages {.intdefine.} = 128 # 0.5 MB
@@ -71,6 +102,8 @@ const
 
 type
   FreeCell {.final, pure.} = object
+    # A free cell is a pointer that has been freed, meaning it became available for reuse.
+    # It may become foreign if it is lent to a chunk that did not create it, doing so reduces the amount of needed pages.
     next: ptr FreeCell  # next free cell in chunk (overlaid with refcount)
     when not defined(gcDestructors):
       zeroField: int       # 0 means cell is not used (overlaid with typ field)
@@ -90,22 +123,23 @@ type
 
   SmallChunk = object of BaseChunk
     next, prev: PSmallChunk  # chunks of the same size
-    freeList: ptr FreeCell
-    free: int            # how many bytes remain
-    acc: int             # accumulator for small object allocation
-    when defined(gcDestructors):
-      sharedFreeList: ptr FreeCell # make no attempt at avoiding false sharing for now for this object field
-    when defined(nimAlignPragma):
-      data {.align: MemAlign.}: UncheckedArray[byte]      # start of usable memory
-    else:
-      data: UncheckedArray[byte]
+    freeList: ptr FreeCell   # Singly linked list of cells. They may be from foreign chunks or from the current chunk.
+                             #  Should be `nil` when the chunk isn't active in `a.freeSmallChunks`.
+    free: int32              # Bytes this chunk is able to provide using both the accumulator and free cells.
+                             # When a cell is considered foreign, its source chunk's free field is NOT adjusted until it
+                             #  reaches dealloc while the source chunk is active.
+                             # Instead, the receiving chunk gains the capacity and thus reserves space in the foreign chunk.
+    acc: uint32              # Offset from data, used when there are no free cells available but the chunk is considered free.
+    foreignCells: int        # When a free cell is given to a chunk that is not its origin,
+                             #  both the cell and the source chunk are considered foreign.
+                             # Receiving a foreign cell can happen both when deallocating from another thread or when
+                             #  the active chunk in `a.freeSmallChunks` is not the current chunk.
+                             # Freeing a chunk while `foreignCells > 0` leaks memory as all references to it become lost.
+    data {.align: MemAlign.}: UncheckedArray[byte]      # start of usable memory
 
   BigChunk = object of BaseChunk # not necessarily > PageSize!
     next, prev: PBigChunk    # chunks of the same (or bigger) size
-    when defined(nimAlignPragma):
-      data {.align: MemAlign.}: UncheckedArray[byte]      # start of usable memory
-    else:
-      data: UncheckedArray[byte]
+    data {.align: MemAlign.}: UncheckedArray[byte]      # start of usable memory
 
   HeapLinks = object
     len: int
@@ -115,7 +149,12 @@ type
   MemRegion = object
     when not defined(gcDestructors):
       minLargeObj, maxLargeObj: int
-    freeSmallChunks: array[0..max(1,SmallChunkSize div MemAlign-1), PSmallChunk]
+    freeSmallChunks: array[0..max(1, SmallChunkSize div MemAlign-1), PSmallChunk]
+      # List of available chunks per size class. Only one is expected to be active per class.
+    when defined(gcDestructors):
+      sharedFreeLists: array[0..max(1, SmallChunkSize div MemAlign-1), ptr FreeCell]
+        # When a thread frees a pointer it did not create, it must not adjust the counters.
+        # Instead, the cell is placed here and deferred until the next allocation.
     flBitmap: uint32
     slBitmap: array[RealFli, uint32]
     matrix: array[RealFli, array[MaxSli, PBigChunk]]
@@ -274,6 +313,20 @@ proc getMaxMem(a: var MemRegion): int =
   # maximum of these both values here:
   result = max(a.currMem, a.maxMem)
 
+const nimMaxHeap {.intdefine.} = 0
+
+proc allocPages(a: var MemRegion, size: int): pointer =
+  when nimMaxHeap != 0:
+    if a.occ + size > nimMaxHeap * 1024 * 1024:
+      raiseOutOfMem()
+  osAllocPages(size)
+
+proc tryAllocPages(a: var MemRegion, size: int): pointer =
+  when nimMaxHeap != 0:
+    if a.occ + size > nimMaxHeap * 1024 * 1024:
+      raiseOutOfMem()
+  osTryAllocPages(size)
+
 proc llAlloc(a: var MemRegion, size: int): pointer =
   # *low-level* alloc for the memory managers data structures. Deallocation
   # is done at the end of the allocator's life time.
@@ -283,14 +336,14 @@ proc llAlloc(a: var MemRegion, size: int): pointer =
     # is one page:
     sysAssert roundup(size+sizeof(LLChunk), PageSize) == PageSize, "roundup 6"
     var old = a.llmem # can be nil and is correct with nil
-    a.llmem = cast[PLLChunk](osAllocPages(PageSize))
+    a.llmem = cast[PLLChunk](allocPages(a, PageSize))
     when defined(nimAvlcorruption):
       trackLocation(a.llmem, PageSize)
     incCurrMem(a, PageSize)
     a.llmem.size = PageSize - sizeof(LLChunk)
     a.llmem.acc = sizeof(LLChunk)
     a.llmem.next = old
-  result = cast[pointer](cast[ByteAddress](a.llmem) + a.llmem.acc)
+  result = cast[pointer](cast[int](a.llmem) + a.llmem.acc)
   dec(a.llmem.size, size)
   inc(a.llmem.acc, size)
   zeroMem(result, size)
@@ -326,7 +379,7 @@ when not defined(gcDestructors):
     n.link[0] = a.freeAvlNodes
     a.freeAvlNodes = n
 
-proc addHeapLink(a: var MemRegion; p: PBigChunk, size: int) =
+proc addHeapLink(a: var MemRegion; p: PBigChunk, size: int): ptr HeapLinks =
   var it = addr(a.heapLinks)
   while it != nil and it.len >= it.chunks.len: it = it.next
   if it == nil:
@@ -335,10 +388,12 @@ proc addHeapLink(a: var MemRegion; p: PBigChunk, size: int) =
     a.heapLinks.next = n
     n.chunks[0] = (p, size)
     n.len = 1
+    result = n
   else:
     let L = it.len
     it.chunks[L] = (p, size)
     inc it.len
+    result = it
 
 when not defined(gcDestructors):
   include "system/avltree"
@@ -422,8 +477,8 @@ iterator allObjects(m: var MemRegion): pointer {.inline.} =
           var c = cast[PSmallChunk](c)
 
           let size = c.size
-          var a = cast[ByteAddress](addr(c.data))
-          let limit = a + c.acc
+          var a = cast[int](addr(c.data))
+          let limit = a + c.acc.int
           while a <% limit:
             yield cast[pointer](a)
             a = a +% size
@@ -441,13 +496,13 @@ when not defined(gcDestructors):
 
 # ------------- chunk management ----------------------------------------------
 proc pageIndex(c: PChunk): int {.inline.} =
-  result = cast[ByteAddress](c) shr PageShift
+  result = cast[int](c) shr PageShift
 
 proc pageIndex(p: pointer): int {.inline.} =
-  result = cast[ByteAddress](p) shr PageShift
+  result = cast[int](p) shr PageShift
 
 proc pageAddr(p: pointer): PChunk {.inline.} =
-  result = cast[PChunk](cast[ByteAddress](p) and not PageMask)
+  result = cast[PChunk](cast[int](p) and not PageMask)
   #sysAssert(Contains(allocator.chunkStarts, pageIndex(result)))
 
 when false:
@@ -459,15 +514,10 @@ when false:
                 it, it.next, it.prev, it.size)
       it = it.next
 
-const nimMaxHeap {.intdefine.} = 0
-
 proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
   when not defined(emscripten):
     if not a.blockChunkSizeIncrease:
       let usedMem = a.occ #a.currMem # - a.freeMem
-      when nimMaxHeap != 0:
-        if usedMem > nimMaxHeap * 1024 * 1024:
-          raiseOutOfMem()
       if usedMem < 64 * 1024:
         a.nextChunkSize = PageSize*4
       else:
@@ -476,32 +526,32 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
 
   var size = size
   if size > a.nextChunkSize:
-    result = cast[PBigChunk](osAllocPages(size))
+    result = cast[PBigChunk](allocPages(a, size))
   else:
-    result = cast[PBigChunk](osTryAllocPages(a.nextChunkSize))
+    result = cast[PBigChunk](tryAllocPages(a, a.nextChunkSize))
     if result == nil:
-      result = cast[PBigChunk](osAllocPages(size))
+      result = cast[PBigChunk](allocPages(a, size))
       a.blockChunkSizeIncrease = true
     else:
       size = a.nextChunkSize
 
   incCurrMem(a, size)
   inc(a.freeMem, size)
-  a.addHeapLink(result, size)
+  let heapLink = a.addHeapLink(result, size)
   when defined(debugHeapLinks):
     cprintf("owner: %p; result: %p; next pointer %p; size: %ld\n", addr(a),
-      result, result.heapLink, result.size)
+      result, heapLink, size)
 
   when defined(memtracker):
     trackLocation(addr result.size, sizeof(int))
 
-  sysAssert((cast[ByteAddress](result) and PageMask) == 0, "requestOsChunks 1")
+  sysAssert((cast[int](result) and PageMask) == 0, "requestOsChunks 1")
   #zeroMem(result, size)
   result.next = nil
   result.prev = nil
   result.size = size
   # update next.prevSize:
-  var nxt = cast[ByteAddress](result) +% size
+  var nxt = cast[int](result) +% size
   sysAssert((nxt and PageMask) == 0, "requestOsChunks 2")
   var next = cast[PChunk](nxt)
   if pageIndex(next) in a.chunkStarts:
@@ -509,7 +559,7 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk =
     next.prevSize = size or (next.prevSize and 1)
   # set result.prevSize:
   var lastSize = if a.lastSize != 0: a.lastSize else: PageSize
-  var prv = cast[ByteAddress](result) -% lastSize
+  var prv = cast[int](result) -% lastSize
   sysAssert((nxt and PageMask) == 0, "requestOsChunks 3")
   var prev = cast[PChunk](prv)
   if pageIndex(prev) in a.chunkStarts and prev.size == lastSize:
@@ -555,13 +605,13 @@ proc listRemove[T](head: var T, c: T) {.inline.} =
 
 proc updatePrevSize(a: var MemRegion, c: PBigChunk,
                     prevSize: int) {.inline.} =
-  var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
-  sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "updatePrevSize")
+  var ri = cast[PChunk](cast[int](c) +% c.size)
+  sysAssert((cast[int](ri) and PageMask) == 0, "updatePrevSize")
   if isAccessible(a, ri):
     ri.prevSize = prevSize or (ri.prevSize and 1)
 
 proc splitChunk2(a: var MemRegion, c: PBigChunk, size: int): PBigChunk =
-  result = cast[PBigChunk](cast[ByteAddress](c) +% size)
+  result = cast[PBigChunk](cast[int](c) +% size)
   result.size = c.size - size
   track("result.size", addr result.size, sizeof(int))
   when not defined(nimOptimizedSplitChunk):
@@ -590,8 +640,8 @@ proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
   when coalescLeft:
     let prevSize = c.prevSize
     if prevSize != 0:
-      var le = cast[PChunk](cast[ByteAddress](c) -% prevSize)
-      sysAssert((cast[ByteAddress](le) and PageMask) == 0, "freeBigChunk 4")
+      var le = cast[PChunk](cast[int](c) -% prevSize)
+      sysAssert((cast[int](le) and PageMask) == 0, "freeBigChunk 4")
       if isAccessible(a, le) and chunkUnused(le):
         sysAssert(not isSmallChunk(le), "freeBigChunk 5")
         if not isSmallChunk(le) and le.size < MaxBigChunkSize:
@@ -607,8 +657,8 @@ proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
             addChunkToMatrix(a, c)
             c = rest
   when coalescRight:
-    var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
-    sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "freeBigChunk 2")
+    var ri = cast[PChunk](cast[int](c) +% c.size)
+    sysAssert((cast[int](ri) and PageMask) == 0, "freeBigChunk 2")
     if isAccessible(a, ri) and chunkUnused(ri):
       sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
       if not isSmallChunk(ri) and c.size < MaxBigChunkSize:
@@ -660,7 +710,7 @@ proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
     releaseSys a.lock
 
 proc getHugeChunk(a: var MemRegion; size: int): PBigChunk =
-  result = cast[PBigChunk](osAllocPages(size))
+  result = cast[PBigChunk](allocPages(a, size))
   when RegionHasLock:
     if not a.lockActive:
       a.lockActive = true
@@ -669,7 +719,7 @@ proc getHugeChunk(a: var MemRegion; size: int): PBigChunk =
   incCurrMem(a, size)
   # XXX add this to the heap links. But also remove it from it later.
   when false: a.addHeapLink(result, size)
-  sysAssert((cast[ByteAddress](result) and PageMask) == 0, "getHugeChunk")
+  sysAssert((cast[int](result) and PageMask) == 0, "getHugeChunk")
   result.next = nil
   result.prev = nil
   result.size = size
@@ -772,40 +822,42 @@ when defined(gcDestructors):
     sysAssert c.next == nil, "c.next pointer must be nil"
     atomicPrepend a.sharedFreeListBigChunks, c
 
-  proc addToSharedFreeList(c: PSmallChunk; f: ptr FreeCell) {.inline.} =
-    atomicPrepend c.sharedFreeList, f
+  proc addToSharedFreeList(c: PSmallChunk; f: ptr FreeCell; size: int) {.inline.} =
+    atomicPrepend c.owner.sharedFreeLists[size], f
+
+  const MaxSteps = 20
 
   proc compensateCounters(a: var MemRegion; c: PSmallChunk; size: int) =
     # rawDealloc did NOT do the usual:
     # `inc(c.free, size); dec(a.occ, size)` because it wasn't the owner of these
     # memory locations. We have to compensate here for these for the entire list.
-    # Well, not for the entire list, but for `max` elements of the list because
-    # we split the list in order to achieve bounded response times.
     var it = c.freeList
-    var x = 0
-    var maxIters = 20 # make it time-bounded
+    var total = 0
     while it != nil:
-      if maxIters == 0:
-        let rest = it.next.loada
-        it.next.storea nil
-        addToSharedFreeList(c, rest)
-        break
-      inc x, size
-      it = it.next.loada
-      dec maxIters
-    inc(c.free, x)
-    dec(a.occ, x)
+      inc total, size
+      let chunk = cast[PSmallChunk](pageAddr(it))
+      if c != chunk:
+        # The cell is foreign, potentially even from a foreign thread.
+        # It must block the current chunk from being freed, as doing so would leak memory.
+        inc c.foreignCells
+      it = it.next
+    # By not adjusting the foreign chunk we reserve space in it to prevent deallocation
+    inc(c.free, total)
+    dec(a.occ, total)
 
   proc freeDeferredObjects(a: var MemRegion; root: PBigChunk) =
     var it = root
-    var maxIters = 20 # make it time-bounded
+    var maxIters = MaxSteps # make it time-bounded
     while true:
+      let rest = it.next.loada
+      it.next.storea nil
+      deallocBigChunk(a, cast[PBigChunk](it))
       if maxIters == 0:
-        let rest = it.next.loada
-        it.next.storea nil
-        addToSharedFreeListBigChunks(a, rest)
+        if rest != nil:
+          addToSharedFreeListBigChunks(a, rest)
+          sysAssert a.sharedFreeListBigChunks != nil, "re-enqueing failed"
         break
-      it = it.next.loada
+      it = rest
       dec maxIters
       if it == nil: break
 
@@ -816,61 +868,90 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
   sysAssert(roundup(65, 8) == 72, "rawAlloc: roundup broken")
   var size = roundup(requestedSize, MemAlign)
   sysAssert(size >= sizeof(FreeCell), "rawAlloc: requested size too small")
-
   sysAssert(size >= requestedSize, "insufficient allocated size!")
   #c_fprintf(stdout, "alloc; size: %ld; %ld\n", requestedSize, size)
+
   if size <= SmallChunkSize-smallChunkOverhead():
+    template fetchSharedCells(tc: PSmallChunk) =
+      # Consumes cells from (potentially) foreign threads from `a.sharedFreeLists[s]`
+      when defined(gcDestructors):
+        if tc.freeList == nil:
+          when hasThreadSupport:
+            # Steal the entire list from `sharedFreeList`:
+            tc.freeList = atomicExchangeN(addr a.sharedFreeLists[s], nil, ATOMIC_RELAXED)
+          else:
+            tc.freeList = a.sharedFreeLists[s]
+            a.sharedFreeLists[s] = nil
+          # if `tc.freeList` isn't nil, `tc` will gain capacity.
+          # We must calculate how much it gained and how many foreign cells are included.
+          compensateCounters(a, tc, size)
+
     # allocate a small block: for small chunks, we use only its next pointer
     let s = size div MemAlign
     var c = a.freeSmallChunks[s]
     if c == nil:
+      # There is no free chunk of the requested size available, we need a new one.
       c = getSmallChunk(a)
+      # init all fields in case memory didn't get zeroed
       c.freeList = nil
+      c.foreignCells = 0
       sysAssert c.size == PageSize, "rawAlloc 3"
       c.size = size
-      c.acc = size
-      when defined(gcDestructors):
-        c.sharedFreeList = nil
-      c.free = SmallChunkSize - smallChunkOverhead() - size
+      c.acc = size.uint32
+      c.free = SmallChunkSize - smallChunkOverhead() - size.int32
       sysAssert c.owner == addr(a), "rawAlloc: No owner set!"
       c.next = nil
       c.prev = nil
-      listAdd(a.freeSmallChunks[s], c)
+      # Shared cells are fetched here in case `c.size * 2 >= SmallChunkSize - smallChunkOverhead()`.
+      # For those single cell chunks, we would otherwise have to allocate a new one almost every time.
+      fetchSharedCells(c)
+      if c.free >= size:
+        # Because removals from `a.freeSmallChunks[s]` only happen in the other alloc branch and during dealloc,
+        #  we must not add it to the list if it cannot be used the next time a pointer of `size` bytes is needed.
+        listAdd(a.freeSmallChunks[s], c)
       result = addr(c.data)
-      sysAssert((cast[ByteAddress](result) and (MemAlign-1)) == 0, "rawAlloc 4")
+      sysAssert((cast[int](result) and (MemAlign-1)) == 0, "rawAlloc 4")
     else:
+      # There is a free chunk of the requested size available, use it.
       sysAssert(allocInv(a), "rawAlloc: begin c != nil")
       sysAssert c.next != c, "rawAlloc 5"
       #if c.size != size:
       #  c_fprintf(stdout, "csize: %lld; size %lld\n", c.size, size)
       sysAssert c.size == size, "rawAlloc 6"
-      when defined(gcDestructors):
-        if c.freeList == nil:
-          when hasThreadSupport:
-            c.freeList = atomicExchangeN(addr c.sharedFreeList, nil, ATOMIC_RELAXED)
-          else:
-            c.freeList = c.sharedFreeList
-            c.sharedFreeList = nil
-          compensateCounters(a, c, size)
       if c.freeList == nil:
-        sysAssert(c.acc + smallChunkOverhead() + size <= SmallChunkSize,
+        sysAssert(c.acc.int + smallChunkOverhead() + size <= SmallChunkSize,
                   "rawAlloc 7")
-        result = cast[pointer](cast[ByteAddress](addr(c.data)) +% c.acc)
+        result = cast[pointer](cast[int](addr(c.data)) +% c.acc.int)
         inc(c.acc, size)
       else:
+        # There are free cells available, prefer them over the accumulator
         result = c.freeList
         when not defined(gcDestructors):
           sysAssert(c.freeList.zeroField == 0, "rawAlloc 8")
         c.freeList = c.freeList.next
+        if cast[PSmallChunk](pageAddr(result)) != c:
+          # This cell isn't a blocker for the current chunk's deallocation anymore
+          dec(c.foreignCells)
+        else:
+          sysAssert(c == cast[PSmallChunk](pageAddr(result)), "rawAlloc: Bad cell")
+      # Even if the cell we return is foreign, the local chunk's capacity decreases.
+      # The capacity was previously reserved in the source chunk (when it first got allocated),
+      #  then added into the current chunk during dealloc,
+      #  so the source chunk will not be freed or leak memory because of this.
       dec(c.free, size)
-      sysAssert((cast[ByteAddress](result) and (MemAlign-1)) == 0, "rawAlloc 9")
+      sysAssert((cast[int](result) and (MemAlign-1)) == 0, "rawAlloc 9")
       sysAssert(allocInv(a), "rawAlloc: end c != nil")
-    sysAssert(allocInv(a), "rawAlloc: before c.free < size")
-    if c.free < size:
-      sysAssert(allocInv(a), "rawAlloc: before listRemove test")
-      listRemove(a.freeSmallChunks[s], c)
-      sysAssert(allocInv(a), "rawAlloc: end listRemove test")
-    sysAssert(((cast[ByteAddress](result) and PageMask) - smallChunkOverhead()) %%
+      # We fetch deferred cells *after* advancing `c.freeList`/`acc` to adjust `c.free`.
+      # If after the adjustment it turns out there's free cells available,
+      #  the chunk stays in `a.freeSmallChunks[s]` and the need for a new chunk is delayed.
+      fetchSharedCells(c)
+      sysAssert(allocInv(a), "rawAlloc: before c.free < size")
+      if c.free < size:
+        # Even after fetching shared cells the chunk has no usable memory left. It is no longer the active chunk
+        sysAssert(allocInv(a), "rawAlloc: before listRemove test")
+        listRemove(a.freeSmallChunks[s], c)
+        sysAssert(allocInv(a), "rawAlloc: end listRemove test")
+    sysAssert(((cast[int](result) and PageMask) - smallChunkOverhead()) %%
                size == 0, "rawAlloc 21")
     sysAssert(allocInv(a), "rawAlloc: end small size")
     inc a.occ, size
@@ -892,16 +973,16 @@ proc rawAlloc(a: var MemRegion, requestedSize: int): pointer =
     sysAssert c.prev == nil, "rawAlloc 10"
     sysAssert c.next == nil, "rawAlloc 11"
     result = addr(c.data)
-    sysAssert((cast[ByteAddress](c) and (MemAlign-1)) == 0, "rawAlloc 13")
-    sysAssert((cast[ByteAddress](c) and PageMask) == 0, "rawAlloc: Not aligned on a page boundary")
+    sysAssert((cast[int](c) and (MemAlign-1)) == 0, "rawAlloc 13")
+    sysAssert((cast[int](c) and PageMask) == 0, "rawAlloc: Not aligned on a page boundary")
     when not defined(gcDestructors):
       if a.root == nil: a.root = getBottom(a)
-      add(a, a.root, cast[ByteAddress](result), cast[ByteAddress](result)+%size)
+      add(a, a.root, cast[int](result), cast[int](result)+%size)
     inc a.occ, c.size
     trackSize(c.size)
   sysAssert(isAccessible(a, result), "rawAlloc 14")
   sysAssert(allocInv(a), "rawAlloc: end")
-  when logAlloc: cprintf("var pointer_%p = alloc(%ld)\n", result, requestedSize)
+  when logAlloc: cprintf("var pointer_%p = alloc(%ld) # %p\n", result, requestedSize, addr a)
 
 proc rawAlloc0(a: var MemRegion, requestedSize: int): pointer =
   result = rawAlloc(a, requestedSize)
@@ -917,7 +998,7 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
   if isSmallChunk(c):
     # `p` is within a small chunk:
     var c = cast[PSmallChunk](c)
-    var s = c.size
+    let s = c.size
     #       ^ We might access thread foreign storage here.
     # The other thread cannot possibly free this block as it's still alive.
     var f = cast[ptr FreeCell](p)
@@ -926,37 +1007,54 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
       dec a.occ, s
       untrackSize(s)
       sysAssert a.occ >= 0, "rawDealloc: negative occupied memory (case A)"
-      sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
+      sysAssert(((cast[int](p) and PageMask) - smallChunkOverhead()) %%
                 s == 0, "rawDealloc 3")
       when not defined(gcDestructors):
-        #echo("setting to nil: ", $cast[ByteAddress](addr(f.zeroField)))
+        #echo("setting to nil: ", $cast[int](addr(f.zeroField)))
         sysAssert(f.zeroField != 0, "rawDealloc 1")
         f.zeroField = 0
-      f.next = c.freeList
-      c.freeList = f
       when overwriteFree:
         # set to 0xff to check for usage after free bugs:
         nimSetMem(cast[pointer](cast[int](p) +% sizeof(FreeCell)), -1'i32,
                 s -% sizeof(FreeCell))
-      # check if it is not in the freeSmallChunks[s] list:
-      if c.free < s:
-        # add it to the freeSmallChunks[s] array:
-        listAdd(a.freeSmallChunks[s div MemAlign], c)
-        inc(c.free, s)
+      let activeChunk = a.freeSmallChunks[s div MemAlign]
+      if activeChunk != nil and c != activeChunk:
+        # This pointer is not part of the active chunk, lend it out
+        #  and do not adjust the current chunk (same logic as compensateCounters.)
+        # Put the cell into the active chunk,
+        #  may prevent a queue of available chunks from forming in a.freeSmallChunks[s div MemAlign].
+        #  This queue would otherwise waste memory in the form of free cells until we return to those chunks.
+        f.next = activeChunk.freeList
+        activeChunk.freeList = f # lend the cell
+        inc(activeChunk.free, s) # By not adjusting the current chunk's capacity it is prevented from being freed
+        inc(activeChunk.foreignCells) # The cell is now considered foreign from the perspective of the active chunk
       else:
-        inc(c.free, s)
-        if c.free == SmallChunkSize-smallChunkOverhead():
-          listRemove(a.freeSmallChunks[s div MemAlign], c)
-          c.size = SmallChunkSize
-          freeBigChunk(a, cast[PBigChunk](c))
+        f.next = c.freeList
+        c.freeList = f
+        if c.free < s:
+          # The chunk could not have been active as it didn't have enough space to give
+          listAdd(a.freeSmallChunks[s div MemAlign], c)
+          inc(c.free, s)
+        else:
+          inc(c.free, s)
+          # Free only if the entire chunk is unused and there are no borrowed cells.
+          # If the chunk were to be freed while it references foreign cells,
+          #  the foreign chunks will leak memory and can never be freed.
+          if c.free == SmallChunkSize-smallChunkOverhead() and c.foreignCells == 0:
+            listRemove(a.freeSmallChunks[s div MemAlign], c)
+            c.size = SmallChunkSize
+            freeBigChunk(a, cast[PBigChunk](c))
     else:
+      when logAlloc: cprintf("dealloc(pointer_%p) # SMALL FROM %p CALLER %p\n", p, c.owner, addr(a))
+
       when defined(gcDestructors):
-        addToSharedFreeList(c, f)
-    sysAssert(((cast[ByteAddress](p) and PageMask) - smallChunkOverhead()) %%
+        addToSharedFreeList(c, f, s div MemAlign)
+    sysAssert(((cast[int](p) and PageMask) - smallChunkOverhead()) %%
                s == 0, "rawDealloc 2")
   else:
     # set to 0xff to check for usage after free bugs:
     when overwriteFree: nimSetMem(p, -1'i32, c.size -% bigChunkOverhead())
+    when logAlloc: cprintf("dealloc(pointer_%p) # BIG %p\n", p, c.owner)
     when defined(gcDestructors):
       if c.owner == addr(a):
         deallocBigChunk(a, cast[PBigChunk](c))
@@ -964,8 +1062,9 @@ proc rawDealloc(a: var MemRegion, p: pointer) =
         addToSharedFreeListBigChunks(c.owner[], cast[PBigChunk](c))
     else:
       deallocBigChunk(a, cast[PBigChunk](c))
+
   sysAssert(allocInv(a), "rawDealloc: end")
-  when logAlloc: cprintf("dealloc(pointer_%p)\n", p)
+  #when logAlloc: cprintf("dealloc(pointer_%p)\n", p)
 
 when not defined(gcDestructors):
   proc isAllocatedPtr(a: MemRegion, p: pointer): bool =
@@ -974,9 +1073,9 @@ when not defined(gcDestructors):
       if not chunkUnused(c):
         if isSmallChunk(c):
           var c = cast[PSmallChunk](c)
-          var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
+          var offset = (cast[int](p) and (PageSize-1)) -%
                       smallChunkOverhead()
-          result = (c.acc >% offset) and (offset %% c.size == 0) and
+          result = (c.acc.int >% offset) and (offset %% c.size == 0) and
             (cast[ptr FreeCell](p).zeroField >% 1)
         else:
           var c = cast[PBigChunk](c)
@@ -992,12 +1091,12 @@ when not defined(gcDestructors):
       if not chunkUnused(c):
         if isSmallChunk(c):
           var c = cast[PSmallChunk](c)
-          var offset = (cast[ByteAddress](p) and (PageSize-1)) -%
+          var offset = (cast[int](p) and (PageSize-1)) -%
                       smallChunkOverhead()
-          if c.acc >% offset:
-            sysAssert(cast[ByteAddress](addr(c.data)) +% offset ==
-                      cast[ByteAddress](p), "offset is not what you think it is")
-            var d = cast[ptr FreeCell](cast[ByteAddress](addr(c.data)) +%
+          if c.acc.int >% offset:
+            sysAssert(cast[int](addr(c.data)) +% offset ==
+                      cast[int](p), "offset is not what you think it is")
+            var d = cast[ptr FreeCell](cast[int](addr(c.data)) +%
                       offset -% (offset %% c.size))
             if d.zeroField >% 1:
               result = d
@@ -1024,7 +1123,7 @@ when not defined(gcDestructors):
 
 proc ptrSize(p: pointer): int =
   when not defined(gcDestructors):
-    var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
+    var x = cast[pointer](cast[int](p) -% sizeof(FreeCell))
     var c = pageAddr(p)
     sysAssert(not chunkUnused(c), "ptrSize")
     result = c.size -% sizeof(FreeCell)
@@ -1042,7 +1141,7 @@ proc alloc(allocator: var MemRegion, size: Natural): pointer {.gcsafe.} =
     result = rawAlloc(allocator, size+sizeof(FreeCell))
     cast[ptr FreeCell](result).zeroField = 1 # mark it as used
     sysAssert(not isAllocatedPtr(allocator, result), "alloc")
-    result = cast[pointer](cast[ByteAddress](result) +% sizeof(FreeCell))
+    result = cast[pointer](cast[int](result) +% sizeof(FreeCell))
     track("alloc", result, size)
   else:
     result = rawAlloc(allocator, size)
@@ -1054,7 +1153,7 @@ proc alloc0(allocator: var MemRegion, size: Natural): pointer =
 proc dealloc(allocator: var MemRegion, p: pointer) =
   when not defined(gcDestructors):
     sysAssert(p != nil, "dealloc: p is nil")
-    var x = cast[pointer](cast[ByteAddress](p) -% sizeof(FreeCell))
+    var x = cast[pointer](cast[int](p) -% sizeof(FreeCell))
     sysAssert(x != nil, "dealloc: x is nil")
     sysAssert(isAccessible(allocator, x), "is not accessible")
     sysAssert(cast[ptr FreeCell](x).zeroField == 1, "dealloc: object header corrupted")
@@ -1087,7 +1186,7 @@ proc deallocOsPages(a: var MemRegion) =
       let (p, size) = it.chunks[i]
       when defined(debugHeapLinks):
         cprintf("owner %p; dealloc A: %p size: %ld; next: %p\n", addr(a),
-          it, it.size, next)
+          it, size, next)
       sysAssert size >= PageSize, "origSize too small"
       osDeallocPages(p, size)
     it = next
@@ -1115,7 +1214,7 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
       result = interiorAllocatedPtr(allocator, p)
 
     proc isAllocatedPtr*(p: pointer): bool =
-      let p = cast[pointer](cast[ByteAddress](p)-%ByteAddress(sizeof(Cell)))
+      let p = cast[pointer](cast[int](p)-%ByteAddress(sizeof(Cell)))
       result = isAllocatedPtr(allocator, p)
 
   proc deallocOsPages = deallocOsPages(allocator)
@@ -1135,7 +1234,7 @@ template instantiateForRegion(allocator: untyped) {.dirty.} =
   proc realloc0Impl(p: pointer, oldSize, newSize: Natural): pointer =
     result = realloc(allocator, p, newSize)
     if newSize > oldSize:
-      zeroMem(cast[pointer](cast[int](result) + oldSize), newSize - oldSize)
+      zeroMem(cast[pointer](cast[uint](result) + uint(oldSize)), newSize - oldSize)
 
   when false:
     proc countFreeMem(): int =
diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim
index a8a4bd767..3098e17d6 100644
--- a/lib/system/ansi_c.nim
+++ b/lib/system/ansi_c.nim
@@ -65,7 +65,7 @@ elif defined(macosx) or defined(linux) or defined(freebsd) or
     SIGSEGV* = cint(11)
     SIGTERM* = cint(15)
     SIGPIPE* = cint(13)
-    SIG_DFL* = cast[CSighandlerT](0)
+    SIG_DFL* = CSighandlerT(nil)
 elif defined(haiku):
   const
     SIGABRT* = cint(6)
@@ -75,7 +75,7 @@ elif defined(haiku):
     SIGSEGV* = cint(11)
     SIGTERM* = cint(15)
     SIGPIPE* = cint(7)
-    SIG_DFL* = cast[CSighandlerT](0)
+    SIG_DFL* = CSighandlerT(nil)
 else:
   when defined(nimscript):
     {.error: "SIGABRT not ported to your platform".}
@@ -187,6 +187,9 @@ proc c_sprintf*(buf, frmt: cstring): cint {.
   importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.}
   # we use it only in a way that cannot lead to security issues
 
+proc c_snprintf*(buf: cstring, n: csize_t, frmt: cstring): cint {.
+  importc: "snprintf", header: "<stdio.h>", varargs, noSideEffect.}
+
 when defined(zephyr) and not defined(zephyrUseLibcMalloc):
   proc c_malloc*(size: csize_t): pointer {.
     importc: "k_malloc", header: "<kernel.h>".}
@@ -224,7 +227,7 @@ proc rawWriteString*(f: CFilePtr, s: cstring, length: int) {.compilerproc, nonRe
 
 proc rawWrite*(f: CFilePtr, s: cstring) {.compilerproc, nonReloadable, inline.} =
   # we cannot throw an exception here!
-  discard c_fwrite(s, 1, cast[csize_t](s.len), f)
+  discard c_fwrite(s, 1, c_strlen(s), f)
   discard c_fflush(f)
 
 {.pop.}
diff --git a/lib/system/arc.nim b/lib/system/arc.nim
index d8527e1e4..d001fcaa5 100644
--- a/lib/system/arc.nim
+++ b/lib/system/arc.nim
@@ -26,6 +26,9 @@ else:
     rcMask = 0b111
     rcShift = 3      # shift by rcShift to get the reference counter
 
+const
+  orcLeakDetector = defined(nimOrcLeakDetector)
+
 type
   RefHeader = object
     rc: int # the object header is now a single RC field.
@@ -36,9 +39,21 @@ type
                    # in O(1) without doubly linked lists
     when defined(nimArcDebug) or defined(nimArcIds):
       refId: int
+    when defined(gcOrc) and orcLeakDetector:
+      filename: cstring
+      line: int
 
   Cell = ptr RefHeader
 
+template setFrameInfo(c: Cell) =
+  when orcLeakDetector:
+    if framePtr != nil and framePtr.prev != nil:
+      c.filename = framePtr.prev.filename
+      c.line = framePtr.prev.line
+    else:
+      c.filename = nil
+      c.line = 0
+
 template head(p: pointer): Cell =
   cast[Cell](cast[int](p) -% sizeof(RefHeader))
 
@@ -57,6 +72,21 @@ elif defined(nimArcIds):
 
   const traceId = -1
 
+when defined(gcAtomicArc) and hasThreadSupport:
+  template decrement(cell: Cell): untyped =
+    discard atomicDec(cell.rc, rcIncrement)
+  template increment(cell: Cell): untyped =
+    discard atomicInc(cell.rc, rcIncrement)
+  template count(x: Cell): untyped =
+    atomicLoadN(x.rc.addr, ATOMIC_ACQUIRE) shr rcShift
+else:
+  template decrement(cell: Cell): untyped =
+    dec(cell.rc, rcIncrement)
+  template increment(cell: Cell): untyped =
+    inc(cell.rc, rcIncrement)
+  template count(x: Cell): untyped =
+    x.rc shr rcShift
+
 proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} =
   let hdrSize = align(sizeof(RefHeader), alignment)
   let s = size + hdrSize
@@ -69,9 +99,10 @@ proc nimNewObj(size, alignment: int): pointer {.compilerRtl.} =
     atomicInc gRefId
     if head(result).refId == traceId:
       writeStackTrace()
-      cfprintf(cstderr, "[nimNewObj] %p %ld\n", result, head(result).rc shr rcShift)
+      cfprintf(cstderr, "[nimNewObj] %p %ld\n", result, head(result).count)
   when traceCollector:
     cprintf("[Allocated] %p result: %p\n", result -! sizeof(RefHeader), result)
+  setFrameInfo head(result)
 
 proc nimNewObjUninit(size, alignment: int): pointer {.compilerRtl.} =
   # Same as 'newNewObj' but do not initialize the memory to zero.
@@ -90,21 +121,34 @@ proc nimNewObjUninit(size, alignment: int): pointer {.compilerRtl.} =
     atomicInc gRefId
     if head(result).refId == traceId:
       writeStackTrace()
-      cfprintf(cstderr, "[nimNewObjUninit] %p %ld\n", result, head(result).rc shr rcShift)
+      cfprintf(cstderr, "[nimNewObjUninit] %p %ld\n", result, head(result).count)
 
   when traceCollector:
     cprintf("[Allocated] %p result: %p\n", result -! sizeof(RefHeader), result)
+  setFrameInfo head(result)
 
 proc nimDecWeakRef(p: pointer) {.compilerRtl, inl.} =
-  dec head(p).rc, rcIncrement
+  decrement head(p)
+
+proc isUniqueRef*[T](x: ref T): bool {.inline.} =
+  ## Returns true if the object `x` points to is uniquely referenced. Such
+  ## an object can potentially be passed over to a different thread safely,
+  ## if great care is taken. This queries the internal reference count of
+  ## the object which is subject to lots of optimizations! In other words
+  ## the value of `isUniqueRef` can depend on the used compiler version and
+  ## optimizer setting.
+  ## Nevertheless it can be used as a very valuable debugging tool and can
+  ## be used to specify the constraints of a threading related API
+  ## via `assert isUniqueRef(x)`.
+  head(cast[pointer](x)).rc == 0
 
 proc nimIncRef(p: pointer) {.compilerRtl, inl.} =
   when defined(nimArcDebug):
     if head(p).refId == traceId:
       writeStackTrace()
-      cfprintf(cstderr, "[IncRef] %p %ld\n", p, head(p).rc shr rcShift)
+      cfprintf(cstderr, "[IncRef] %p %ld\n", p, head(p).count)
 
-  inc head(p).rc, rcIncrement
+  increment head(p)
   when traceCollector:
     cprintf("[INCREF] %p\n", head(p))
 
@@ -173,17 +217,24 @@ proc nimDecRefIsLast(p: pointer): bool {.compilerRtl, inl.} =
     when defined(nimArcDebug):
       if cell.refId == traceId:
         writeStackTrace()
-        cfprintf(cstderr, "[DecRef] %p %ld\n", p, cell.rc shr rcShift)
-
-    if (cell.rc and not rcMask) == 0:
-      result = true
-      when traceCollector:
-        cprintf("[ABOUT TO DESTROY] %p\n", cell)
+        cfprintf(cstderr, "[DecRef] %p %ld\n", p, cell.count)
+
+    when defined(gcAtomicArc) and hasThreadSupport:
+      # `atomicDec` returns the new value
+      if atomicDec(cell.rc, rcIncrement) == -rcIncrement:
+        result = true
+        when traceCollector:
+          cprintf("[ABOUT TO DESTROY] %p\n", cell)
     else:
-      dec cell.rc, rcIncrement
-      # According to Lins it's correct to do nothing else here.
-      when traceCollector:
-        cprintf("[DeCREF] %p\n", cell)
+      if cell.count == 0:
+        result = true
+        when traceCollector:
+          cprintf("[ABOUT TO DESTROY] %p\n", cell)
+      else:
+        decrement cell
+        # According to Lins it's correct to do nothing else here.
+        when traceCollector:
+          cprintf("[DECREF] %p\n", cell)
 
 proc GC_unref*[T](x: ref T) =
   ## New runtime only supports this operation for 'ref T'.
@@ -196,16 +247,21 @@ proc GC_ref*[T](x: ref T) =
 
 when not defined(gcOrc):
   template GC_fullCollect* =
-    ## Forces a full garbage collection pass. With `--gc:arc` a nop.
+    ## Forces a full garbage collection pass. With `--mm:arc` a nop.
     discard
 
 template setupForeignThreadGc* =
-  ## With `--gc:arc` a nop.
+  ## With `--mm:arc` a nop.
   discard
 
 template tearDownForeignThreadGc* =
-  ## With `--gc:arc` a nop.
+  ## With `--mm:arc` a nop.
   discard
 
-proc isObjDisplayCheck(source: PNimTypeV2, targetDepth: int16, token: uint32): bool {.compilerRtl, inline.} =
+proc isObjDisplayCheck(source: PNimTypeV2, targetDepth: int16, token: uint32): bool {.compilerRtl, inl.} =
   result = targetDepth <= source.depth and source.display[targetDepth] == token
+
+when defined(gcDestructors):
+  proc nimGetVTable(p: pointer, index: int): pointer
+        {.compilerRtl, inline, raises: [].} =
+    result = cast[ptr PNimTypeV2](p).vTable[index]
diff --git a/lib/system/arithm.nim b/lib/system/arithm.nim
deleted file mode 100644
index 158f40177..000000000
--- a/lib/system/arithm.nim
+++ /dev/null
@@ -1,425 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-
-# simple integer arithmetic with overflow checking
-
-proc raiseOverflow {.compilerproc, noinline.} =
-  # a single proc to reduce code size to a minimum
-  sysFatal(OverflowDefect, "over- or underflow")
-
-proc raiseDivByZero {.compilerproc, noinline.} =
-  sysFatal(DivByZeroDefect, "division by zero")
-
-when defined(builtinOverflow):
-  # Builtin compiler functions for improved performance
-  when sizeof(clong) == 8:
-    proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
-      importc: "__builtin_saddl_overflow", nodecl, nosideeffect.}
-
-    proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
-      importc: "__builtin_ssubl_overflow", nodecl, nosideeffect.}
-
-    proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
-      importc: "__builtin_smull_overflow", nodecl, nosideeffect.}
-
-  elif sizeof(clonglong) == 8:
-    proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
-      importc: "__builtin_saddll_overflow", nodecl, nosideeffect.}
-
-    proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
-      importc: "__builtin_ssubll_overflow", nodecl, nosideeffect.}
-
-    proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
-      importc: "__builtin_smulll_overflow", nodecl, nosideeffect.}
-
-  when sizeof(int) == 8:
-    proc addIntOverflow(a, b: int, c: var int): bool {.inline.} =
-      addInt64Overflow(a, b, c)
-
-    proc subIntOverflow(a, b: int, c: var int): bool {.inline.} =
-      subInt64Overflow(a, b, c)
-
-    proc mulIntOverflow(a, b: int, c: var int): bool {.inline.} =
-      mulInt64Overflow(a, b, c)
-
-  elif sizeof(int) == 4 and sizeof(cint) == 4:
-    proc addIntOverflow(a, b: int, c: var int): bool {.
-      importc: "__builtin_sadd_overflow", nodecl, nosideeffect.}
-
-    proc subIntOverflow(a, b: int, c: var int): bool {.
-      importc: "__builtin_ssub_overflow", nodecl, nosideeffect.}
-
-    proc mulIntOverflow(a, b: int, c: var int): bool {.
-      importc: "__builtin_smul_overflow", nodecl, nosideeffect.}
-
-  proc addInt64(a, b: int64): int64 {.compilerproc, inline.} =
-    if addInt64Overflow(a, b, result):
-      raiseOverflow()
-
-  proc subInt64(a, b: int64): int64 {.compilerproc, inline.} =
-    if subInt64Overflow(a, b, result):
-      raiseOverflow()
-
-  proc mulInt64(a, b: int64): int64 {.compilerproc, inline.} =
-    if mulInt64Overflow(a, b, result):
-      raiseOverflow()
-else:
-  proc addInt64(a, b: int64): int64 {.compilerproc, inline.} =
-    result = a +% b
-    if (result xor a) >= int64(0) or (result xor b) >= int64(0):
-      return result
-    raiseOverflow()
-
-  proc subInt64(a, b: int64): int64 {.compilerproc, inline.} =
-    result = a -% b
-    if (result xor a) >= int64(0) or (result xor not b) >= int64(0):
-      return result
-    raiseOverflow()
-
-  #
-  # This code has been inspired by Python's source code.
-  # The native int product x*y is either exactly right or *way* off, being
-  # just the last n bits of the true product, where n is the number of bits
-  # in an int (the delivered product is the true product plus i*2**n for
-  # some integer i).
-  #
-  # The native float64 product x*y is subject to three
-  # rounding errors: on a sizeof(int)==8 box, each cast to double can lose
-  # info, and even on a sizeof(int)==4 box, the multiplication can lose info.
-  # But, unlike the native int product, it's not in *range* trouble:  even
-  # if sizeof(int)==32 (256-bit ints), the product easily fits in the
-  # dynamic range of a float64. So the leading 50 (or so) bits of the float64
-  # product are correct.
-  #
-  # We check these two ways against each other, and declare victory if they're
-  # approximately the same. Else, because the native int product is the only
-  # one that can lose catastrophic amounts of information, it's the native int
-  # product that must have overflowed.
-  #
-  proc mulInt64(a, b: int64): int64 {.compilerproc.} =
-    var
-      resAsFloat, floatProd: float64
-    result = a *% b
-    floatProd = toBiggestFloat(a) # conversion
-    floatProd = floatProd * toBiggestFloat(b)
-    resAsFloat = toBiggestFloat(result)
-
-    # Fast path for normal case: small multiplicands, and no info
-    # is lost in either method.
-    if resAsFloat == floatProd: return result
-
-    # Somebody somewhere lost info. Close enough, or way off? Note
-    # that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
-    # The difference either is or isn't significant compared to the
-    # true value (of which floatProd is a good approximation).
-
-    # abs(diff)/abs(prod) <= 1/32 iff
-    #   32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
-    if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
-      return result
-    raiseOverflow()
-
-proc negInt64(a: int64): int64 {.compilerproc, inline.} =
-  if a != low(int64): return -a
-  raiseOverflow()
-
-proc absInt64(a: int64): int64 {.compilerproc, inline.} =
-  if a != low(int64):
-    if a >= 0: return a
-    else: return -a
-  raiseOverflow()
-
-proc divInt64(a, b: int64): int64 {.compilerproc, inline.} =
-  if b == int64(0):
-    raiseDivByZero()
-  if a == low(int64) and b == int64(-1):
-    raiseOverflow()
-  return a div b
-
-proc modInt64(a, b: int64): int64 {.compilerproc, inline.} =
-  if b == int64(0):
-    raiseDivByZero()
-  return a mod b
-
-proc absInt(a: int): int {.compilerproc, inline.} =
-  if a != low(int):
-    if a >= 0: return a
-    else: return -a
-  raiseOverflow()
-
-const
-  asmVersion = defined(i386) and (defined(vcc) or defined(wcc) or
-               defined(dmc) or defined(gcc) or defined(llvm_gcc))
-    # my Version of Borland C++Builder does not have
-    # tasm32, which is needed for assembler blocks
-    # this is why Borland is not included in the 'when'
-
-when asmVersion and not defined(gcc) and not defined(llvm_gcc):
-  # assembler optimized versions for compilers that
-  # have an intel syntax assembler:
-  proc addInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-    # a in eax, and b in edx
-    asm """
-        mov eax, ecx
-        add eax, edx
-        jno theEnd
-        call `raiseOverflow`
-      theEnd:
-        ret
-    """
-
-  proc subInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-    asm """
-        mov eax, ecx
-        sub eax, edx
-        jno theEnd
-        call `raiseOverflow`
-      theEnd:
-        ret
-    """
-
-  proc negInt(a: int): int {.compilerproc, asmNoStackFrame.} =
-    asm """
-        mov eax, ecx
-        neg eax
-        jno theEnd
-        call `raiseOverflow`
-      theEnd:
-        ret
-    """
-
-  proc divInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-    asm """
-        test  edx, edx
-        jne   L_NOT_ZERO
-        call  `raiseDivByZero`
-      L_NOT_ZERO:
-        cmp   ecx, 0x80000000
-        jne   L_DO_DIV
-        cmp   edx, -1
-        jne   L_DO_DIV
-        call  `raiseOverflow`
-      L_DO_DIV:
-        mov   eax, ecx
-        mov   ecx, edx
-        cdq
-        idiv  ecx
-        ret
-    """
-
-  proc modInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-    asm """
-        test  edx, edx
-        jne   L_NOT_ZERO
-        call  `raiseDivByZero`
-      L_NOT_ZERO:
-        cmp   ecx, 0x80000000
-        jne   L_DO_DIV
-        cmp   edx, -1
-        jne   L_DO_DIV
-        call  `raiseOverflow`
-      L_DO_DIV:
-        mov   eax, ecx
-        mov   ecx, edx
-        cdq
-        idiv  ecx
-        mov   eax, edx
-        ret
-    """
-
-  proc mulInt(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-    asm """
-        mov eax, ecx
-        mov ecx, edx
-        xor edx, edx
-        imul ecx
-        jno theEnd
-        call `raiseOverflow`
-      theEnd:
-        ret
-    """
-
-elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
-  proc addInt(a, b: int): int {.compilerproc, inline.} =
-    # don't use a pure proc here!
-    asm """
-      "addl %%ecx, %%eax\n"
-      "jno 1\n"
-      "call _raiseOverflow\n"
-      "1: \n"
-      :"=a"(`result`)
-      :"a"(`a`), "c"(`b`)
-    """
-    #".intel_syntax noprefix"
-    #/* Intel syntax here */
-    #".att_syntax"
-
-  proc subInt(a, b: int): int {.compilerproc, inline.} =
-    asm """ "subl %%ecx,%%eax\n"
-            "jno 1\n"
-            "call _raiseOverflow\n"
-            "1: \n"
-           :"=a"(`result`)
-           :"a"(`a`), "c"(`b`)
-    """
-
-  proc mulInt(a, b: int): int {.compilerproc, inline.} =
-    asm """  "xorl %%edx, %%edx\n"
-             "imull %%ecx\n"
-             "jno 1\n"
-             "call _raiseOverflow\n"
-             "1: \n"
-            :"=a"(`result`)
-            :"a"(`a`), "c"(`b`)
-            :"%edx"
-    """
-
-  proc negInt(a: int): int {.compilerproc, inline.} =
-    asm """ "negl %%eax\n"
-            "jno 1\n"
-            "call _raiseOverflow\n"
-            "1: \n"
-           :"=a"(`result`)
-           :"a"(`a`)
-    """
-
-  proc divInt(a, b: int): int {.compilerproc, inline.} =
-    asm """  "xorl %%edx, %%edx\n"
-             "idivl %%ecx\n"
-             "jno 1\n"
-             "call _raiseOverflow\n"
-             "1: \n"
-            :"=a"(`result`)
-            :"a"(`a`), "c"(`b`)
-            :"%edx"
-    """
-
-  proc modInt(a, b: int): int {.compilerproc, inline.} =
-    asm """  "xorl %%edx, %%edx\n"
-             "idivl %%ecx\n"
-             "jno 1\n"
-             "call _raiseOverflow\n"
-             "1: \n"
-             "movl %%edx, %%eax"
-            :"=a"(`result`)
-            :"a"(`a`), "c"(`b`)
-            :"%edx"
-    """
-
-when not declared(addInt) and defined(builtinOverflow):
-  proc addInt(a, b: int): int {.compilerproc, inline.} =
-    if addIntOverflow(a, b, result):
-      raiseOverflow()
-
-when not declared(subInt) and defined(builtinOverflow):
-  proc subInt(a, b: int): int {.compilerproc, inline.} =
-    if subIntOverflow(a, b, result):
-      raiseOverflow()
-
-when not declared(mulInt) and defined(builtinOverflow):
-  proc mulInt(a, b: int): int {.compilerproc, inline.} =
-    if mulIntOverflow(a, b, result):
-      raiseOverflow()
-
-# Platform independent versions of the above (slower!)
-when not declared(addInt):
-  proc addInt(a, b: int): int {.compilerproc, inline.} =
-    result = a +% b
-    if (result xor a) >= 0 or (result xor b) >= 0:
-      return result
-    raiseOverflow()
-
-when not declared(subInt):
-  proc subInt(a, b: int): int {.compilerproc, inline.} =
-    result = a -% b
-    if (result xor a) >= 0 or (result xor not b) >= 0:
-      return result
-    raiseOverflow()
-
-when not declared(negInt):
-  proc negInt(a: int): int {.compilerproc, inline.} =
-    if a != low(int): return -a
-    raiseOverflow()
-
-when not declared(divInt):
-  proc divInt(a, b: int): int {.compilerproc, inline.} =
-    if b == 0:
-      raiseDivByZero()
-    if a == low(int) and b == -1:
-      raiseOverflow()
-    return a div b
-
-when not declared(modInt):
-  proc modInt(a, b: int): int {.compilerproc, inline.} =
-    if b == 0:
-      raiseDivByZero()
-    return a mod b
-
-when not declared(mulInt):
-  #
-  # This code has been inspired by Python's source code.
-  # The native int product x*y is either exactly right or *way* off, being
-  # just the last n bits of the true product, where n is the number of bits
-  # in an int (the delivered product is the true product plus i*2**n for
-  # some integer i).
-  #
-  # The native float64 product x*y is subject to three
-  # rounding errors: on a sizeof(int)==8 box, each cast to double can lose
-  # info, and even on a sizeof(int)==4 box, the multiplication can lose info.
-  # But, unlike the native int product, it's not in *range* trouble:  even
-  # if sizeof(int)==32 (256-bit ints), the product easily fits in the
-  # dynamic range of a float64. So the leading 50 (or so) bits of the float64
-  # product are correct.
-  #
-  # We check these two ways against each other, and declare victory if
-  # they're approximately the same. Else, because the native int product is
-  # the only one that can lose catastrophic amounts of information, it's the
-  # native int product that must have overflowed.
-  #
-  proc mulInt(a, b: int): int {.compilerproc.} =
-    var
-      resAsFloat, floatProd: float
-
-    result = a *% b
-    floatProd = toFloat(a) * toFloat(b)
-    resAsFloat = toFloat(result)
-
-    # Fast path for normal case: small multiplicands, and no info
-    # is lost in either method.
-    if resAsFloat == floatProd: return result
-
-    # Somebody somewhere lost info. Close enough, or way off? Note
-    # that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
-    # The difference either is or isn't significant compared to the
-    # true value (of which floatProd is a good approximation).
-
-    # abs(diff)/abs(prod) <= 1/32 iff
-    #   32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
-    if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd):
-      return result
-    raiseOverflow()
-
-# We avoid setting the FPU control word here for compatibility with libraries
-# written in other languages.
-
-proc raiseFloatInvalidOp {.compilerproc, noinline.} =
-  sysFatal(FloatInvalidOpDefect, "FPU operation caused a NaN result")
-
-proc nanCheck(x: float64) {.compilerproc, inline.} =
-  if x != x: raiseFloatInvalidOp()
-
-proc raiseFloatOverflow(x: float64) {.compilerproc, noinline.} =
-  if x > 0.0:
-    sysFatal(FloatOverflowDefect, "FPU operation caused an overflow")
-  else:
-    sysFatal(FloatUnderflowDefect, "FPU operations caused an underflow")
-
-proc infCheck(x: float64) {.compilerproc, inline.} =
-  if x != 0.0 and x*0.5 == x: raiseFloatOverflow(x)
diff --git a/lib/system/arithmetics.nim b/lib/system/arithmetics.nim
index d05aaaa5b..e229a0f4b 100644
--- a/lib/system/arithmetics.nim
+++ b/lib/system/arithmetics.nim
@@ -93,7 +93,7 @@ proc `*`*(x, y: int16): int16 {.magic: "MulI", noSideEffect.}
 proc `*`*(x, y: int32): int32 {.magic: "MulI", noSideEffect.}
 proc `*`*(x, y: int64): int64 {.magic: "MulI", noSideEffect.}
 
-proc `div`*(x, y: int): int {.magic: "DivI", noSideEffect.} = 
+proc `div`*(x, y: int): int {.magic: "DivI", noSideEffect.} =
   ## Computes the integer division.
   ##
   ## This is roughly the same as `math.trunc(x/y).int`.
@@ -403,107 +403,3 @@ proc `%%`*(x, y: int8): int8 {.inline.}   = cast[int8](cast[uint8](x) mod cast[u
 proc `%%`*(x, y: int16): int16 {.inline.} = cast[int16](cast[uint16](x) mod cast[uint16](y))
 proc `%%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) mod cast[uint32](y))
 proc `%%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) mod cast[uint64](y))
-
-when not defined(nimPreviewSlimSystem):
-  when defined(nimNoZeroExtendMagic):
-    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 {.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 {.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 {.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 {.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 {.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 {.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 {.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 {.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.
-      cast[int32](x)
-
-  elif not defined(js):
-    proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect, deprecated.}
-      ## zero extends a smaller integer type to `int`. This treats `x` as
-      ## unsigned.
-      ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
-
-    proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect, deprecated.}
-      ## zero extends a smaller integer type to `int`. This treats `x` as
-      ## unsigned.
-      ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
-
-    proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect, deprecated.}
-      ## zero extends a smaller integer type to `int64`. This treats `x` as
-      ## unsigned.
-      ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
-
-    proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect, deprecated.}
-      ## zero extends a smaller integer type to `int64`. This treats `x` as
-      ## unsigned.
-      ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
-
-    proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect, deprecated.}
-      ## zero extends a smaller integer type to `int64`. This treats `x` as
-      ## unsigned.
-      ## **Deprecated since version 0.19.9**: Use unsigned integers instead.
-
-    proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect, 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.
-
-    proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect, 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.
-
-    proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect, 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.
-
-    proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect, 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.
diff --git a/lib/system/assign.nim b/lib/system/assign.nim
index 20b854107..9f4cbc0fe 100644
--- a/lib/system/assign.nim
+++ b/lib/system/assign.nim
@@ -15,8 +15,8 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) {.benign.
 proc genericAssignAux(dest, src: pointer, n: ptr TNimNode,
                       shallow: bool) {.benign.} =
   var
-    d = cast[ByteAddress](dest)
-    s = cast[ByteAddress](src)
+    d = cast[int](dest)
+    s = cast[int](src)
   case n.kind
   of nkSlot:
     genericAssignAux(cast[pointer](d +% n.offset),
@@ -56,8 +56,8 @@ template deepSeqAssignImpl(operation, additionalArg) {.dirty.} =
 
 proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
   var
-    d = cast[ByteAddress](dest)
-    s = cast[ByteAddress](src)
+    d = cast[int](dest)
+    s = cast[int](src)
   sysAssert(mt != nil, "genericAssignAux 2")
   case mt.kind
   of tyString:
@@ -89,17 +89,17 @@ proc genericAssignAux(dest, src: pointer, mt: PNimType, shallow: bool) =
         var ss = nimNewSeqOfCap(mt, seq.len)
         cast[PGenericSeq](ss).len = seq.len
         unsureAsgnRef(x, ss)
-        var dst = cast[ByteAddress](cast[PPointer](dest)[])
+        var dst = cast[int](cast[PPointer](dest)[])
         copyMem(cast[pointer](dst +% align(GenericSeqSize, mt.base.align)),
-                cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align)),
+                cast[pointer](cast[int](s2) +% align(GenericSeqSize, mt.base.align)),
                 seq.len *% mt.base.size)
       else:
         unsureAsgnRef(x, newSeq(mt, seq.len))
-        var dst = cast[ByteAddress](cast[PPointer](dest)[])
+        var dst = cast[int](cast[PPointer](dest)[])
         for i in 0..seq.len-1:
           genericAssignAux(
             cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
-            cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
+            cast[pointer](cast[int](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size ),
             mt.base, shallow)
   of tyObject:
     var it = mt.base
@@ -181,15 +181,15 @@ proc genericSeqAssign(dest, src: pointer, mt: PNimType) {.compilerproc.} =
 proc genericAssignOpenArray(dest, src: pointer, len: int,
                             mt: PNimType) {.compilerproc.} =
   var
-    d = cast[ByteAddress](dest)
-    s = cast[ByteAddress](src)
+    d = cast[int](dest)
+    s = cast[int](src)
   for i in 0..len-1:
     genericAssign(cast[pointer](d +% i *% mt.base.size),
                   cast[pointer](s +% i *% mt.base.size), mt.base)
 
 proc objectInit(dest: pointer, typ: PNimType) {.compilerproc, benign.}
 proc objectInitAux(dest: pointer, n: ptr TNimNode) {.benign.} =
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   case n.kind
   of nkNone: sysAssert(false, "objectInitAux")
   of nkSlot: objectInit(cast[pointer](d +% n.offset), n.typ)
@@ -203,7 +203,7 @@ proc objectInitAux(dest: pointer, n: ptr TNimNode) {.benign.} =
 proc objectInit(dest: pointer, typ: PNimType) =
   # the generic init proc that takes care of initialization of complex
   # objects on the stack or heap
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   case typ.kind
   of tyObject:
     # iterate over any structural type
@@ -226,7 +226,7 @@ proc objectInit(dest: pointer, typ: PNimType) =
 
 proc genericReset(dest: pointer, mt: PNimType) {.compilerproc, benign.}
 proc genericResetAux(dest: pointer, n: ptr TNimNode) =
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   case n.kind
   of nkNone: sysAssert(false, "genericResetAux")
   of nkSlot: genericReset(cast[pointer](d +% n.offset), n.typ)
@@ -238,7 +238,7 @@ proc genericResetAux(dest: pointer, n: ptr TNimNode) =
     zeroMem(cast[pointer](d +% n.offset), n.typ.size)
 
 proc genericReset(dest: pointer, mt: PNimType) =
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   sysAssert(mt != nil, "genericReset 2")
   case mt.kind
   of tyRef:
@@ -275,10 +275,12 @@ proc genericReset(dest: pointer, mt: PNimType) =
 
 proc selectBranch(discVal, L: int,
                   a: ptr array[0x7fff, ptr TNimNode]): ptr TNimNode =
-  result = a[L] # a[L] contains the ``else`` part (but may be nil)
   if discVal <% L:
-    let x = a[discVal]
-    if x != nil: result = x
+    result = a[discVal]
+    if result == nil:
+      result = a[L]
+  else:
+    result = a[L] # a[L] contains the ``else`` part (but may be nil)
 
 proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int,
                             a: ptr array[0x7fff, ptr TNimNode],
diff --git a/lib/system/cellseqs_v1.nim b/lib/system/cellseqs_v1.nim
index 1952491b3..1a305aa42 100644
--- a/lib/system/cellseqs_v1.nim
+++ b/lib/system/cellseqs_v1.nim
@@ -16,18 +16,21 @@ type
     d: PCellArray
 
 proc contains(s: CellSeq, c: PCell): bool {.inline.} =
-  for i in 0 .. s.len-1:
-    if s.d[i] == c: return true
+  for i in 0 ..< s.len:
+    if s.d[i] == c:
+      return true
   return false
 
+proc resize(s: var CellSeq) =
+  s.cap = s.cap * 3 div 2
+  let d = cast[PCellArray](alloc(s.cap * sizeof(PCell)))
+  copyMem(d, s.d, s.len * sizeof(PCell))
+  dealloc(s.d)
+  s.d = d
+
 proc add(s: var CellSeq, c: PCell) {.inline.} =
   if s.len >= s.cap:
-    s.cap = s.cap * 3 div 2
-    var d = cast[PCellArray](alloc(s.cap * sizeof(PCell)))
-    copyMem(d, s.d, s.len * sizeof(PCell))
-    dealloc(s.d)
-    s.d = d
-    # XXX: realloc?
+    resize(s)
   s.d[s.len] = c
   inc(s.len)
 
diff --git a/lib/system/cellseqs_v2.nim b/lib/system/cellseqs_v2.nim
index 27be48d78..c6c7b1a8e 100644
--- a/lib/system/cellseqs_v2.nim
+++ b/lib/system/cellseqs_v2.nim
@@ -16,20 +16,17 @@ type
     len, cap: int
     d: CellArray[T]
 
-proc add[T](s: var CellSeq[T], c: T; t: PNimTypeV2) {.inline.} =
+proc resize[T](s: var CellSeq[T]) =
+  s.cap = s.cap * 3 div 2
+  var newSize = s.cap * sizeof(CellTuple[T])
+  when compileOption("threads"):
+    s.d = cast[CellArray[T]](reallocShared(s.d, newSize))
+  else:
+    s.d = cast[CellArray[T]](realloc(s.d, newSize))
+
+proc add[T](s: var CellSeq[T], c: T, t: PNimTypeV2) {.inline.} =
   if s.len >= s.cap:
-    s.cap = s.cap * 3 div 2
-    when compileOption("threads"):
-      var d = cast[CellArray[T]](allocShared(uint(s.cap * sizeof(CellTuple[T]))))
-    else:
-      var d = cast[CellArray[T]](alloc(s.cap * sizeof(CellTuple[T])))
-    copyMem(d, s.d, s.len * sizeof(CellTuple[T]))
-    when compileOption("threads"):
-      deallocShared(s.d)
-    else:
-      dealloc(s.d)
-    s.d = d
-    # XXX: realloc?
+    s.resize()
   s.d[s.len] = (c, t)
   inc(s.len)
 
diff --git a/lib/system/cellsets.nim b/lib/system/cellsets.nim
index a0f1fabf9..92036c226 100644
--- a/lib/system/cellsets.nim
+++ b/lib/system/cellsets.nim
@@ -42,7 +42,7 @@ Complete traversal is done in this way::
 
 ]#
 
-when defined(gcOrc) or defined(gcArc):
+when defined(gcOrc) or defined(gcArc) or defined(gcAtomicArc):
   type
     PCell = Cell
 
@@ -78,7 +78,7 @@ type
     head: PPageDesc
     data: PPageDescArray
 
-when defined(gcOrc) or defined(gcArc):
+when defined(gcOrc) or defined(gcArc) or defined(gcAtomicArc):
   discard
 else:
   include cellseqs_v1
diff --git a/lib/system/cgprocs.nim b/lib/system/cgprocs.nim
index 9d0d248c3..9a7645f9b 100644
--- a/lib/system/cgprocs.nim
+++ b/lib/system/cgprocs.nim
@@ -8,13 +8,3 @@
 #
 
 # Headers for procs that the code generator depends on ("compilerprocs")
-
-type
-  LibHandle = pointer       # private type
-  ProcAddr = pointer        # library loading and loading of procs:
-
-proc nimLoadLibrary(path: string): LibHandle {.compilerproc, hcrInline, nonReloadable.}
-proc nimUnloadLibrary(lib: LibHandle) {.compilerproc, hcrInline, nonReloadable.}
-proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc, hcrInline, nonReloadable.}
-
-proc nimLoadLibraryError(path: string) {.compilerproc, hcrInline, nonReloadable.}
diff --git a/lib/system/channels_builtin.nim b/lib/system/channels_builtin.nim
index fbe3f0e98..02b4d8cbf 100644
--- a/lib/system/channels_builtin.nim
+++ b/lib/system/channels_builtin.nim
@@ -26,7 +26,7 @@
 ## The following is a simple example of two different ways to use channels:
 ## blocking and non-blocking.
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   # Be sure to compile with --threads:on.
 ##   # The channels and threads modules are part of system and should not be
 ##   # imported.
@@ -87,6 +87,7 @@
 ##
 ##   # Clean up the channel.
 ##   chan.close()
+##   ```
 ##
 ## Sample output
 ## -------------
@@ -113,7 +114,7 @@
 ## using e.g. `system.allocShared0` and pass these pointers through thread
 ## arguments:
 ##
-## .. code-block:: Nim
+##   ```Nim
 ##   proc worker(channel: ptr Channel[string]) =
 ##     let greeting = channel[].recv()
 ##     echo greeting
@@ -135,6 +136,7 @@
 ##     deallocShared(channel)
 ##
 ##   localChannelExample() # "Hello from the main thread!"
+##   ```
 
 when not declared(ThisIsSystem):
   {.error: "You must not import this module explicitly".}
@@ -185,8 +187,8 @@ when not usesDestructors:
   proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel,
                 mode: LoadStoreMode) {.benign.} =
     var
-      d = cast[ByteAddress](dest)
-      s = cast[ByteAddress](src)
+      d = cast[int](dest)
+      s = cast[int](src)
     case n.kind
     of nkSlot: storeAux(cast[pointer](d +% n.offset),
                         cast[pointer](s +% n.offset), n.typ, t, mode)
@@ -205,8 +207,8 @@ when not usesDestructors:
       cast[pointer](cast[int](p) +% x)
 
     var
-      d = cast[ByteAddress](dest)
-      s = cast[ByteAddress](src)
+      d = cast[int](dest)
+      s = cast[int](src)
     sysAssert(mt != nil, "mt == nil")
     case mt.kind
     of tyString:
@@ -245,14 +247,14 @@ when not usesDestructors:
           x[] = alloc0(t.region, align(GenericSeqSize, mt.base.align) +% seq.len *% mt.base.size)
         else:
           unsureAsgnRef(x, newSeq(mt, seq.len))
-        var dst = cast[ByteAddress](cast[PPointer](dest)[])
+        var dst = cast[int](cast[PPointer](dest)[])
         var dstseq = cast[PGenericSeq](dst)
         dstseq.len = seq.len
         dstseq.reserved = seq.len
         for i in 0..seq.len-1:
           storeAux(
             cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
-            cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +%
+            cast[pointer](cast[int](s2) +% align(GenericSeqSize, mt.base.align) +%
                           i *% mt.base.size),
             mt.base, t, mode)
         if mode != mStore: dealloc(t.region, s2)
@@ -392,7 +394,7 @@ proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) =
   q.ready = false
   if typ != q.elemType:
     releaseSys(q.lock)
-    sysFatal(ValueError, "cannot receive message of wrong type")
+    raise newException(ValueError, "cannot receive message of wrong type")
   rawRecv(q, res, typ)
   if q.maxItems > 0 and q.count == q.maxItems - 1:
     # Parent thread is awaiting in send. Wake it up.
diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index dd26d140d..b48855964 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -38,6 +38,10 @@ when defined(nimV2):
   proc raiseFieldError2(f: string, discVal: int) {.compilerproc, noinline.} =
     ## raised when field is inaccessible given runtime value of discriminant
     sysFatal(FieldDefect, f & $discVal & "'")
+
+  proc raiseFieldErrorStr(f: string, discVal: string) {.compilerproc, noinline.} =
+    ## raised when field is inaccessible given runtime value of discriminant
+    sysFatal(FieldDefect, formatFieldDefect(f, discVal))
 else:
   proc raiseFieldError2(f: string, discVal: string) {.compilerproc, noinline.} =
     ## raised when field is inaccessible given runtime value of discriminant
diff --git a/lib/system/comparisons.nim b/lib/system/comparisons.nim
index 36d4d06a8..a8d78bb93 100644
--- a/lib/system/comparisons.nim
+++ b/lib/system/comparisons.nim
@@ -35,7 +35,7 @@ proc `==`*[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
   ## Checks that two `ref` variables refer to the same item.
 proc `==`*[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
   ## Checks that two `ptr` variables refer to the same item.
-proc `==`*[T: proc](x, y: T): bool {.magic: "EqProc", noSideEffect.}
+proc `==`*[T: proc | iterator](x, y: T): bool {.magic: "EqProc", noSideEffect.}
   ## Checks that two `proc` variables refer to the same procedure.
 
 proc `<=`*[Enum: enum](x, y: Enum): bool {.magic: "LeEnum", noSideEffect.}
@@ -324,7 +324,7 @@ proc `==`*[T](x, y: seq[T]): bool {.noSideEffect.} =
         return true
     else:
       var sameObject = false
-      asm """`sameObject` = `x` === `y`"""
+      {.emit: """`sameObject` = `x` === `y`;""".}
       if sameObject: return true
 
   if x.len != y.len:
diff --git a/lib/system/compilation.nim b/lib/system/compilation.nim
index 6109e9874..cdb976ed5 100644
--- a/lib/system/compilation.nim
+++ b/lib/system/compilation.nim
@@ -1,16 +1,16 @@
 const
-  NimMajor* {.intdefine.}: int = 1
+  NimMajor* {.intdefine.}: int = 2
     ## is the major number of Nim's version. Example:
-    ##   ```
+    ##   ```nim
     ##   when (NimMajor, NimMinor, NimPatch) >= (1, 3, 1): discard
     ##   ```
     # see also std/private/since
 
-  NimMinor* {.intdefine.}: int = 7
+  NimMinor* {.intdefine.}: int = 2
     ## is the minor number of Nim's version.
     ## Odd for devel, even for releases.
 
-  NimPatch* {.intdefine.}: int = 3
+  NimPatch* {.intdefine.}: int = 1
     ## is the patch number of Nim's version.
     ## Odd for devel, even for releases.
 
@@ -40,7 +40,7 @@ proc defined*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
   ## `x` is an external symbol introduced through the compiler's
   ## `-d:x switch <nimc.html#compiler-usage-compileminustime-symbols>`_ to enable
   ## build time conditionals:
-  ##   ```
+  ##   ```nim
   ##   when not defined(release):
   ##     # Do here programmer friendly expensive sanity checks.
   ##   # Put here the normal code
@@ -51,36 +51,30 @@ proc defined*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
   ## * `compileOption <#compileOption,string,string>`_ for enum options
   ## * `define pragmas <manual.html#implementation-specific-pragmas-compileminustime-define-pragmas>`_
 
-when defined(nimHasDeclaredMagic):
-  proc declared*(x: untyped): bool {.magic: "Declared", noSideEffect, compileTime.}
-    ## Special compile-time procedure that checks whether `x` is
-    ## declared. `x` has to be an identifier or a qualified identifier.
-    ##
-    ## This can be used to check whether a library provides a certain
-    ## feature or not:
-    ##   ```
-    ##   when not declared(strutils.toUpper):
-    ##     # provide our own toUpper proc here, because strutils is
-    ##     # missing it.
-    ##   ```
-    ##
-    ## See also:
-    ## * `declaredInScope <#declaredInScope,untyped>`_
-else:
-  proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
-
-when defined(nimHasDeclaredMagic):
-  proc declaredInScope*(x: untyped): bool {.magic: "DeclaredInScope", noSideEffect, compileTime.}
-    ## Special compile-time procedure that checks whether `x` is
-    ## declared in the current scope. `x` has to be an identifier.
-else:
-  proc declaredInScope*(x: untyped): bool {.magic: "DefinedInScope", noSideEffect, compileTime.}
+proc declared*(x: untyped): bool {.magic: "Declared", noSideEffect, compileTime.}
+  ## Special compile-time procedure that checks whether `x` is
+  ## declared. `x` has to be an identifier or a qualified identifier.
+  ##
+  ## This can be used to check whether a library provides a certain
+  ## feature or not:
+  ##   ```nim
+  ##   when not declared(strutils.toUpper):
+  ##     # provide our own toUpper proc here, because strutils is
+  ##     # missing it.
+  ##   ```
+  ##
+  ## See also:
+  ## * `declaredInScope <#declaredInScope,untyped>`_
+
+proc declaredInScope*(x: untyped): bool {.magic: "DeclaredInScope", noSideEffect, compileTime.}
+  ## Special compile-time procedure that checks whether `x` is
+  ## declared in the current scope. `x` has to be an identifier.
 
 proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime.} =
   ## Special compile-time procedure that checks whether `x` can be compiled
   ## without any semantic error.
   ## This can be used to check whether a type supports some operation:
-  ##   ```
+  ##   ```nim
   ##   when compiles(3 + 4):
   ##     echo "'+' for integers is available"
   ##   ```
@@ -150,16 +144,17 @@ template currentSourcePath*: string = instantiationInfo(-1, true).filename
   ## Returns the full file-system path of the current source.
   ##
   ## To get the directory containing the current source, use it with
-  ## `os.parentDir() <os.html#parentDir%2Cstring>`_ as `currentSourcePath.parentDir()`.
+  ## `ospaths2.parentDir() <ospaths2.html#parentDir%2Cstring>`_ as
+  ## `currentSourcePath.parentDir()`.
   ##
   ## The path returned by this template is set at compile time.
   ##
   ## See the docstring of `macros.getProjectPath() <macros.html#getProjectPath>`_
-  ## for an example to see the distinction between the `currentSourcePath`
-  ## and `getProjectPath`.
+  ## for an example to see the distinction between the `currentSourcePath()`
+  ## and `getProjectPath()`.
   ##
   ## See also:
-  ## * `getCurrentDir proc <os.html#getCurrentDir>`_
+  ## * `ospaths2.getCurrentDir() proc <ospaths2.html#getCurrentDir>`_
 
 proc slurp*(filename: string): string {.magic: "Slurp".}
   ## This is an alias for `staticRead <#staticRead,string>`_.
@@ -170,7 +165,7 @@ proc staticRead*(filename: string): string {.magic: "Slurp".}
   ##
   ## The maximum file size limit that `staticRead` and `slurp` can read is
   ## near or equal to the *free* memory of the device you are using to compile.
-  ##   ```
+  ##   ```nim
   ##   const myResource = staticRead"mydatafile.bin"
   ##   ```
   ##
@@ -187,7 +182,7 @@ proc staticExec*(command: string, input = "", cache = ""): string {.
   ##
   ## If `input` is not an empty string, it will be passed as a standard input
   ## to the executed program.
-  ##   ```
+  ##   ```nim
   ##   const buildInfo = "Revision " & staticExec("git rev-parse HEAD") &
   ##                     "\nCompiled on " & staticExec("uname -v")
   ##   ```
@@ -203,7 +198,7 @@ proc staticExec*(command: string, input = "", cache = ""): string {.
   ## behaviour then. `command & input & cache` (the concatenated string) is
   ## used to determine whether the entry in the cache is still valid. You can
   ## use versioning information for `cache`:
-  ##   ```
+  ##   ```nim
   ##   const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0")
   ##   ```
 
diff --git a/lib/system/ctypes.nim b/lib/system/ctypes.nim
index 6ba28ed49..b788274bd 100644
--- a/lib/system/ctypes.nim
+++ b/lib/system/ctypes.nim
@@ -12,16 +12,10 @@ type
     ## compiler supports. Currently this is `float64`, but it is
     ## platform-dependent in general.
 
-when defined(js):
-  type BiggestUInt* = uint32
+  BiggestUInt* = uint64
     ## is an alias for the biggest unsigned integer type the Nim compiler
-    ## supports. Currently this is `uint32` for JS and `uint64` for other
-    ## targets.
-else:
-  type BiggestUInt* = uint64
-    ## is an alias for the biggest unsigned integer type the Nim compiler
-    ## supports. Currently this is `uint32` for JS and `uint64` for other
-    ## targets.
+    ## supports. Currently this is `uint64`, but it is platform-dependent
+    ## in general.
 
 when defined(windows):
   type
@@ -67,7 +61,7 @@ type # these work for most platforms:
     ## This is the same as the type `unsigned long long` in *C*.
 
 type
-  ByteAddress* = int
+  ByteAddress* {.deprecated: "use `uint`".} = int
     ## is the signed integer type that should be used for converting
     ## pointers to integer addresses for readability.
 
diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim
index 1f30b8427..72d35f518 100644
--- a/lib/system/deepcopy.nim
+++ b/lib/system/deepcopy.nim
@@ -61,8 +61,8 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType;
 proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode;
                         tab: var PtrTable) {.benign.} =
   var
-    d = cast[ByteAddress](dest)
-    s = cast[ByteAddress](src)
+    d = cast[int](dest)
+    s = cast[int](src)
   case n.kind
   of nkSlot:
     genericDeepCopyAux(cast[pointer](d +% n.offset),
@@ -85,8 +85,8 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode;
 
 proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
   var
-    d = cast[ByteAddress](dest)
-    s = cast[ByteAddress](src)
+    d = cast[int](dest)
+    s = cast[int](src)
   sysAssert(mt != nil, "genericDeepCopyAux 2")
   case mt.kind
   of tyString:
@@ -113,11 +113,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) =
         return
       sysAssert(dest != nil, "genericDeepCopyAux 3")
       unsureAsgnRef(x, newSeq(mt, seq.len))
-      var dst = cast[ByteAddress](cast[PPointer](dest)[])
+      var dst = cast[int](cast[PPointer](dest)[])
       for i in 0..seq.len-1:
         genericDeepCopyAux(
           cast[pointer](dst +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
-          cast[pointer](cast[ByteAddress](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
+          cast[pointer](cast[int](s2) +% align(GenericSeqSize, mt.base.align) +% i *% mt.base.size),
           mt.base, tab)
   of tyObject:
     # we need to copy m_type field for tyObject, as it could be empty for
@@ -199,8 +199,8 @@ proc genericSeqDeepCopy(dest, src: pointer, mt: PNimType) {.compilerproc.} =
 proc genericDeepCopyOpenArray(dest, src: pointer, len: int,
                             mt: PNimType) {.compilerproc.} =
   var
-    d = cast[ByteAddress](dest)
-    s = cast[ByteAddress](src)
+    d = cast[int](dest)
+    s = cast[int](src)
   for i in 0..len-1:
     genericDeepCopy(cast[pointer](d +% i *% mt.base.size),
                     cast[pointer](s +% i *% mt.base.size), mt.base)
diff --git a/lib/system/dollars.nim b/lib/system/dollars.nim
index 4ff3d0ae6..89a739d5a 100644
--- a/lib/system/dollars.nim
+++ b/lib/system/dollars.nim
@@ -41,9 +41,9 @@ proc `$`*(x: bool): string {.magic: "BoolToStr", noSideEffect.}
 proc `$`*(x: char): string {.magic: "CharToStr", noSideEffect.}
   ## The stringify operator for a character argument. Returns `x`
   ## converted to a string.
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   assert $'c' == "c"
+  ##   ```
 
 proc `$`*(x: cstring): string {.magic: "CStrToStr", noSideEffect.}
   ## The stringify operator for a CString argument. Returns `x`
@@ -67,19 +67,20 @@ proc `$`*(t: typedesc): string {.magic: "TypeTrait".}
   ## For more procedures dealing with `typedesc`, see
   ## `typetraits module <typetraits.html>`_.
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   doAssert $(typeof(42)) == "int"
   ##   doAssert $(typeof("Foo")) == "string"
   ##   static: doAssert $(typeof(@['A', 'B'])) == "seq[char]"
+  ##   ```
 
 proc `$`*[T: tuple](x: T): string =
   ## Generic `$` operator for tuples that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   $(23, 45) == "(23, 45)"
   ##   $(a: 23, b: 45) == "(a: 23, b: 45)"
   ##   $() == "()"
+  ##   ```
   tupleObjectDollar(result, x)
 
 when not defined(nimPreviewSlimSystem):
@@ -108,25 +109,25 @@ proc collectionToString[T](x: T, prefix, separator, suffix: string): string =
 proc `$`*[T](x: set[T]): string =
   ## Generic `$` operator for sets that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   ${23, 45} == "{23, 45}"
+  ##   ```
   collectionToString(x, "{", ", ", "}")
 
 proc `$`*[T](x: seq[T]): string =
   ## Generic `$` operator for seqs that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   $(@[23, 45]) == "@[23, 45]"
+  ##   ```
   collectionToString(x, "@[", ", ", "]")
 
 proc `$`*[T, U](x: HSlice[T, U]): string =
   ## Generic `$` operator for slices that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##  $(1 .. 5) == "1 .. 5"
+  ##  ```
   result = $x.a
   result.add(" .. ")
   result.add($x.b)
@@ -140,7 +141,7 @@ when not defined(nimNoArrayToString):
 proc `$`*[T](x: openArray[T]): string =
   ## Generic `$` operator for openarrays that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   $(@[23, 45].toOpenArray(0, 1)) == "[23, 45]"
+  ##   ```
   collectionToString(x, "[", ", ", "]")
diff --git a/lib/system/dyncalls.nim b/lib/system/dyncalls.nim
index de22f7cbb..2162b234f 100644
--- a/lib/system/dyncalls.nim
+++ b/lib/system/dyncalls.nim
@@ -176,7 +176,7 @@ elif defined(genode):
   proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr =
     raiseAssert("nimGetProcAddr not implemented")
 
-elif defined(nintendoswitch) or defined(freertos) or defined(zephyr):
+elif defined(nintendoswitch) or defined(freertos) or defined(zephyr) or defined(nuttx):
   proc nimUnloadLibrary(lib: LibHandle) =
     cstderr.rawWrite("nimUnLoadLibrary not implemented")
     cstderr.rawWrite("\n")
diff --git a/lib/system/embedded.nim b/lib/system/embedded.nim
index e0b053c7b..ea6776f58 100644
--- a/lib/system/embedded.nim
+++ b/lib/system/embedded.nim
@@ -19,8 +19,9 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} = discard
 proc popFrame {.compilerRtl, inl.} = discard
 
 proc setFrame(s: PFrame) {.compilerRtl, inl.} = discard
-proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = discard
-proc popSafePoint {.compilerRtl, inl.} = discard
+when not gotoBasedExceptions:
+  proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} = discard
+  proc popSafePoint {.compilerRtl, inl.} = discard
 proc pushCurrentException(e: ref Exception) {.compilerRtl, inl.} = discard
 proc popCurrentException {.compilerRtl, inl.} = discard
 
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index 86cfff9cd..dae5c4a4a 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -73,26 +73,45 @@ type
 
 when NimStackTraceMsgs:
   var frameMsgBuf* {.threadvar.}: string
+
+when not defined(nimV2):
+  var
+    framePtr {.threadvar.}: PFrame
+
 var
-  framePtr {.threadvar.}: PFrame
-  excHandler {.threadvar.}: PSafePoint
-    # list of exception handlers
-    # a global variable for the root of all try blocks
   currException {.threadvar.}: ref Exception
-  gcFramePtr {.threadvar.}: GcFrame
 
-type
-  FrameState = tuple[gcFramePtr: GcFrame, framePtr: PFrame,
-                     excHandler: PSafePoint, currException: ref Exception]
+when not gotoBasedExceptions:
+  var
+    excHandler {.threadvar.}: PSafePoint
+      # list of exception handlers
+      # a global variable for the root of all try blocks
+    gcFramePtr {.threadvar.}: GcFrame
+
+when gotoBasedExceptions:
+  type
+    FrameState = tuple[framePtr: PFrame,
+                      currException: ref Exception]
+else:
+  type
+    FrameState = tuple[gcFramePtr: GcFrame, framePtr: PFrame,
+                      excHandler: PSafePoint, currException: ref Exception]
 
 proc getFrameState*(): FrameState {.compilerRtl, inl.} =
-  return (gcFramePtr, framePtr, excHandler, currException)
+  when gotoBasedExceptions:
+    return (framePtr, currException)
+  else:
+    return (gcFramePtr, framePtr, excHandler, currException)
 
 proc setFrameState*(state: FrameState) {.compilerRtl, inl.} =
-  gcFramePtr = state.gcFramePtr
-  framePtr = state.framePtr
-  excHandler = state.excHandler
-  currException = state.currException
+  when gotoBasedExceptions:
+    framePtr = state.framePtr
+    currException = state.currException
+  else:
+    gcFramePtr = state.gcFramePtr
+    framePtr = state.framePtr
+    excHandler = state.excHandler
+    currException = state.currException
 
 proc getFrame*(): PFrame {.compilerRtl, inl.} = framePtr
 
@@ -114,20 +133,21 @@ when false:
 proc setFrame*(s: PFrame) {.compilerRtl, inl.} =
   framePtr = s
 
-proc getGcFrame*(): GcFrame {.compilerRtl, inl.} = gcFramePtr
-proc popGcFrame*() {.compilerRtl, inl.} = gcFramePtr = gcFramePtr.prev
-proc setGcFrame*(s: GcFrame) {.compilerRtl, inl.} = gcFramePtr = s
-proc pushGcFrame*(s: GcFrame) {.compilerRtl, inl.} =
-  s.prev = gcFramePtr
-  zeroMem(cast[pointer](cast[int](s)+%sizeof(GcFrameHeader)), s.len*sizeof(pointer))
-  gcFramePtr = s
+when not gotoBasedExceptions:
+  proc getGcFrame*(): GcFrame {.compilerRtl, inl.} = gcFramePtr
+  proc popGcFrame*() {.compilerRtl, inl.} = gcFramePtr = gcFramePtr.prev
+  proc setGcFrame*(s: GcFrame) {.compilerRtl, inl.} = gcFramePtr = s
+  proc pushGcFrame*(s: GcFrame) {.compilerRtl, inl.} =
+    s.prev = gcFramePtr
+    zeroMem(cast[pointer](cast[int](s)+%sizeof(GcFrameHeader)), s.len*sizeof(pointer))
+    gcFramePtr = s
 
-proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
-  s.prev = excHandler
-  excHandler = s
+  proc pushSafePoint(s: PSafePoint) {.compilerRtl, inl.} =
+    s.prev = excHandler
+    excHandler = s
 
-proc popSafePoint {.compilerRtl, inl.} =
-  excHandler = excHandler.prev
+  proc popSafePoint {.compilerRtl, inl.} =
+    excHandler = excHandler.prev
 
 proc pushCurrentException(e: sink(ref Exception)) {.compilerRtl, inl.} =
   e.up = currException
@@ -407,15 +427,16 @@ proc reportUnhandledError(e: ref Exception) {.nodestroy, gcsafe.} =
   when hostOS != "any":
     reportUnhandledErrorAux(e)
 
-proc nimLeaveFinally() {.compilerRtl.} =
-  when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions:
-    {.emit: "throw;".}
-  else:
-    if excHandler != nil:
-      c_longjmp(excHandler.context, 1)
+when not gotoBasedExceptions:
+  proc nimLeaveFinally() {.compilerRtl.} =
+    when defined(cpp) and not defined(noCppExceptions) and not gotoBasedExceptions:
+      {.emit: "throw;".}
     else:
-      reportUnhandledError(currException)
-      rawQuit(1)
+      if excHandler != nil:
+        c_longjmp(excHandler.context, 1)
+      else:
+        reportUnhandledError(currException)
+        rawQuit(1)
 
 when gotoBasedExceptions:
   var nimInErrorMode {.threadvar.}: bool
@@ -448,7 +469,7 @@ proc raiseExceptionAux(e: sink(ref Exception)) {.nodestroy.} =
     else:
       pushCurrentException(e)
       {.emit: "throw `e`;".}
-  elif defined(nimQuirky) or gotoBasedExceptions:
+  elif quirkyExceptions or gotoBasedExceptions:
     pushCurrentException(e)
     when gotoBasedExceptions:
       inc nimInErrorMode
@@ -560,7 +581,7 @@ proc nimFrame(s: PFrame) {.compilerRtl, inl, raises: [].} =
 when defined(cpp) and appType != "lib" and not gotoBasedExceptions and
     not defined(js) and not defined(nimscript) and
     hostOS != "standalone" and hostOS != "any" and not defined(noCppExceptions) and
-    not defined(nimQuirky):
+    not quirkyExceptions:
 
   type
     StdException {.importcpp: "std::exception", header: "<exception>".} = object
diff --git a/lib/system/fatal.nim b/lib/system/fatal.nim
index a55af2dc3..25c05e52d 100644
--- a/lib/system/fatal.nim
+++ b/lib/system/fatal.nim
@@ -9,27 +9,26 @@
 
 {.push profiler: off.}
 
-when defined(nimHasExceptionsQuery):
-  const gotoBasedExceptions = compileOption("exceptions", "goto")
-else:
-  const gotoBasedExceptions = false
+const
+  gotoBasedExceptions = compileOption("exceptions", "goto")
+  quirkyExceptions = compileOption("exceptions", "quirky")
 
 when hostOS == "standalone":
   include "$projectpath/panicoverride"
 
-  func sysFatal(exceptn: typedesc, message: string) {.inline.} =
+  func sysFatal(exceptn: typedesc[Defect], message: string) {.inline.} =
     panic(message)
 
-  func sysFatal(exceptn: typedesc, message, arg: string) {.inline.} =
+  func sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline.} =
     rawoutput(message)
     panic(arg)
 
-elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript):
+elif quirkyExceptions and not defined(nimscript):
   import ansi_c
 
   func name(t: typedesc): string {.magic: "TypeTrait".}
 
-  func sysFatal(exceptn: typedesc, message, arg: string) {.inline, noreturn.} =
+  func sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline, noreturn.} =
     when nimvm:
       # TODO when doAssertRaises works in CT, add a test for it
       raise (ref exceptn)(msg: message & arg)
@@ -46,14 +45,14 @@ elif (defined(nimQuirky) or defined(nimPanics)) and not defined(nimscript):
         cstderr.rawWrite buf
       rawQuit 1
 
-  func sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} =
+  func sysFatal(exceptn: typedesc[Defect], message: string) {.inline, noreturn.} =
     sysFatal(exceptn, message, "")
 
 else:
-  func sysFatal(exceptn: typedesc, message: string) {.inline, noreturn.} =
+  func sysFatal(exceptn: typedesc[Defect], message: string) {.inline, noreturn.} =
     raise (ref exceptn)(msg: message)
 
-  func sysFatal(exceptn: typedesc, message, arg: string) {.inline, noreturn.} =
+  func sysFatal(exceptn: typedesc[Defect], message, arg: string) {.inline, noreturn.} =
     raise (ref exceptn)(msg: message & arg)
 
 {.pop.}
diff --git a/lib/system/gc.nim b/lib/system/gc.nim
index b36822aad..9289c7f55 100644
--- a/lib/system/gc.nim
+++ b/lib/system/gc.nim
@@ -31,7 +31,7 @@ In Nim the compiler cannot always know if a reference
 is stored on the stack or not. This is caused by var parameters.
 Consider this example:
 
-.. code-block:: Nim
+  ```Nim
   proc setRef(r: var ref TNode) =
     new(r)
 
@@ -41,11 +41,12 @@ Consider this example:
     setRef(r) # here we should not update the reference counts, because
               # r is on the stack
     setRef(r.left) # here we should update the refcounts!
+  ```
 
 We have to decide at runtime whether the reference is on the stack or not.
 The generated code looks roughly like this:
 
-.. code-block:: C
+  ```C
   void setref(TNode** ref) {
     unsureAsgnRef(ref, newObj(TNode_TI, sizeof(TNode)))
   }
@@ -53,6 +54,7 @@ The generated code looks roughly like this:
     setRef(&r)
     setRef(&r->left)
   }
+  ```
 
 Note that for systems with a continuous stack (which most systems have)
 the check whether the ref is on the stack is very cheap (only two
@@ -76,7 +78,7 @@ when defined(memProfiler):
   proc nimProfile(requestedSize: int) {.benign.}
 
 when hasThreadSupport:
-  import sharedlist
+  import std/sharedlist
 
 const
   rcIncrement = 0b1000 # so that lowest 3 bits are not touched
@@ -170,11 +172,11 @@ proc addZCT(s: var CellSeq, c: PCell) {.noinline.} =
 
 proc cellToUsr(cell: PCell): pointer {.inline.} =
   # convert object (=pointer to refcount) to pointer to userdata
-  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(Cell)))
+  result = cast[pointer](cast[int](cell)+%ByteAddress(sizeof(Cell)))
 
 proc usrToCell(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
-  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(Cell)))
+  result = cast[PCell](cast[int](usr)-%ByteAddress(sizeof(Cell)))
 
 proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
   # used for code generation concerning debugging
@@ -336,7 +338,7 @@ proc cellsetReset(s: var CellSet) =
 {.push stacktrace:off.}
 
 proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   case n.kind
   of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
   of nkList:
@@ -356,7 +358,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
   of nkNone: sysAssert(false, "forAllSlotsAux")
 
 proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) =
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   if dest == nil: return # nothing to do
   if ntfNoRefs notin mt.flags:
     case mt.kind
@@ -382,7 +384,7 @@ proc forAllChildren(cell: PCell, op: WalkOp) =
     of tyRef: # common case
       forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
     of tySequence:
-      var d = cast[ByteAddress](cellToUsr(cell))
+      var d = cast[int](cellToUsr(cell))
       var s = cast[PGenericSeq](d)
       if s != nil:
         for i in 0..s.len-1:
@@ -457,7 +459,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
   collectCT(gch)
   var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
   #gcAssert typ.kind in {tyString, tySequence} or size >= typ.base.size, "size too small"
-  gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
+  gcAssert((cast[int](res) and (MemAlign-1)) == 0, "newObj: 2")
   # now it is buffered in the ZCT
   res.typ = typ
   setFrameInfo(res)
@@ -507,7 +509,7 @@ proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl, noinline.} =
 
   var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
   sysAssert(allocInv(gch.region), "newObjRC1 after rawAlloc")
-  sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
+  sysAssert((cast[int](res) and (MemAlign-1)) == 0, "newObj: 2")
   # now it is buffered in the ZCT
   res.typ = typ
   setFrameInfo(res)
@@ -549,9 +551,9 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
 
   var oldsize = align(GenericSeqSize, elemAlign) + cast[PGenericSeq](old).len * elemSize
   copyMem(res, ol, oldsize + sizeof(Cell))
-  zeroMem(cast[pointer](cast[ByteAddress](res) +% oldsize +% sizeof(Cell)),
+  zeroMem(cast[pointer](cast[int](res) +% oldsize +% sizeof(Cell)),
           newsize-oldsize)
-  sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
+  sysAssert((cast[int](res) and (MemAlign-1)) == 0, "growObj: 3")
   # This can be wrong for intermediate temps that are nevertheless on the
   # heap because of lambda lifting:
   #gcAssert(res.refcount shr rcShift <=% 1, "growObj: 4")
@@ -683,7 +685,7 @@ proc collectCycles(gch: var GcHeap) {.raises: [].} =
 proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells:
   sysAssert(allocInv(gch.region), "gcMark begin")
-  var c = cast[ByteAddress](p)
+  var c = cast[int](p)
   if c >% PageSize:
     # fast check: does it look like a cell?
     var objStart = cast[PCell](interiorAllocatedPtr(gch.region, p))
@@ -848,10 +850,10 @@ when withRealTime:
         stack.bottomSaved = stack.bottom
         when stackIncreases:
           stack.bottom = cast[pointer](
-            cast[ByteAddress](stack.pos) - sizeof(pointer) * 6 - stackSize)
+            cast[int](stack.pos) - sizeof(pointer) * 6 - stackSize)
         else:
           stack.bottom = cast[pointer](
-            cast[ByteAddress](stack.pos) + sizeof(pointer) * 6 + stackSize)
+            cast[int](stack.pos) + sizeof(pointer) * 6 + stackSize)
 
     GC_step(gch, us, strongAdvice)
 
diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim
deleted file mode 100644
index 0593b396e..000000000
--- a/lib/system/gc2.nim
+++ /dev/null
@@ -1,749 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2017 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# xxx deadcode, consider removing unless something could be reused.
-
-
-#            Garbage Collector
-#
-# The basic algorithm is an incremental mark
-# and sweep GC to free cycles. It is hard realtime in that if you play
-# according to its rules, no deadline will ever be missed.
-# Since this kind of collector is very bad at recycling dead objects
-# early, Nim's codegen emits ``nimEscape`` calls at strategic
-# places. For this to work even 'unsureAsgnRef' needs to mark things
-# so that only return values need to be considered in ``nimEscape``.
-
-{.push profiler:off.}
-
-const
-  CycleIncrease = 2 # is a multiplicative increase
-  InitialCycleThreshold = 512*1024 # start collecting after 500KB
-  ZctThreshold = 500  # we collect garbage if the ZCT's size
-                      # reaches this threshold
-                      # this seems to be a good value
-  withRealTime = defined(useRealtimeGC)
-
-when withRealTime and not declared(getTicks):
-  include "system/timers"
-when defined(memProfiler):
-  proc nimProfile(requestedSize: int) {.benign.}
-
-when hasThreadSupport:
-  include sharedlist
-
-type
-  ObjectSpaceIter = object
-    state: range[-1..0]
-
-iterToProc(allObjects, ptr ObjectSpaceIter, allObjectsAsProc)
-
-const
-  escapedBit = 0b1000 # so that lowest 3 bits are not touched
-  rcBlackOrig = 0b000
-  rcWhiteOrig = 0b001
-  rcGrey = 0b010   # traditional color for incremental mark&sweep
-  rcUnused = 0b011
-  colorMask = 0b011
-type
-  WalkOp = enum
-    waMarkGlobal,    # part of the backup mark&sweep
-    waMarkGrey,
-    waZctDecRef,
-    waDebug
-
-  Phase {.pure.} = enum
-    None, Marking, Sweeping
-  Finalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
-    # A ref type can have a finalizer that is called before the object's
-    # storage is freed.
-
-  GcStat = object
-    stackScans: int          # number of performed stack scans (for statistics)
-    completedCollections: int    # number of performed full collections
-    maxThreshold: int        # max threshold that has been set
-    maxStackSize: int        # max stack size
-    maxStackCells: int       # max stack cells in ``decStack``
-    cycleTableSize: int      # max entries in cycle table
-    maxPause: int64          # max measured GC pause in nanoseconds
-
-  GcStack {.final, pure.} = object
-    when nimCoroutines:
-      prev: ptr GcStack
-      next: ptr GcStack
-      maxStackSize: int      # Used to track statistics because we can not use
-                             # GcStat.maxStackSize when multiple stacks exist.
-    bottom: pointer
-
-    when withRealTime or nimCoroutines:
-      pos: pointer           # Used with `withRealTime` only for code clarity, see GC_Step().
-    when withRealTime:
-      bottomSaved: pointer
-
-  GcHeap = object # this contains the zero count and
-                  # non-zero count table
-    black, red: int # either 0 or 1.
-    stack: GcStack
-    when nimCoroutines:
-      activeStack: ptr GcStack    # current executing coroutine stack.
-    phase: Phase
-    cycleThreshold: int
-    when useCellIds:
-      idGenerator: int
-    greyStack: CellSeq
-    recGcLock: int           # prevent recursion via finalizers; no thread lock
-    when withRealTime:
-      maxPause: Nanos        # max allowed pause in nanoseconds; active if > 0
-    region: MemRegion        # garbage collected region
-    stat: GcStat
-    additionalRoots: CellSeq # explicit roots for GC_ref/unref
-    spaceIter: ObjectSpaceIter
-    pDumpHeapFile: pointer # File that is used for GC_dumpHeap
-    when hasThreadSupport:
-      toDispose: SharedList[pointer]
-    gcThreadId: int
-
-var
-  gch {.rtlThreadVar.}: GcHeap
-
-when not defined(useNimRtl):
-  instantiateForRegion(gch.region)
-
-# Which color to use for new objects is tricky: When we're marking,
-# they have to be *white* so that everything is marked that is only
-# reachable from them. However, when we are sweeping, they have to
-# be black, so that we don't free them prematuredly. In order to save
-# a comparison gch.phase == Phase.Marking, we use the pseudo-color
-# 'red' for new objects.
-template allocColor(): untyped = gch.red
-
-template gcAssert(cond: bool, msg: string) =
-  when defined(useGcAssert):
-    if not cond:
-      echo "[GCASSERT] ", msg
-      GC_disable()
-      writeStackTrace()
-      rawQuit 1
-
-proc cellToUsr(cell: PCell): pointer {.inline.} =
-  # convert object (=pointer to refcount) to pointer to userdata
-  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(Cell)))
-
-proc usrToCell(usr: pointer): PCell {.inline.} =
-  # convert pointer to userdata to object (=pointer to refcount)
-  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(Cell)))
-
-proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
-  # used for code generation concerning debugging
-  result = usrToCell(c).typ
-
-proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
-  result = 0
-
-# this that has to equals zero, otherwise we have to round up UnitsPerPage:
-when BitsPerPage mod (sizeof(int)*8) != 0:
-  {.error: "(BitsPerPage mod BitsPerUnit) should be zero!".}
-
-template color(c): untyped = c.refCount and colorMask
-template setColor(c, col) =
-  c.refcount = c.refcount and not colorMask or col
-
-template markAsEscaped(c: PCell) =
-  c.refcount = c.refcount or escapedBit
-
-template didEscape(c: PCell): bool =
-  (c.refCount and escapedBit) != 0
-
-proc writeCell(file: File; msg: cstring, c: PCell) =
-  var kind = -1
-  if c.typ != nil: kind = ord(c.typ.kind)
-  let col = if c.color == rcGrey: 'g'
-            elif c.color == gch.black: 'b'
-            else: 'w'
-  when useCellIds:
-    let id = c.id
-  else:
-    let id = c
-  when defined(nimTypeNames):
-    c_fprintf(file, "%s %p %d escaped=%ld color=%c of type %s\n",
-              msg, id, kind, didEscape(c), col, c.typ.name)
-  elif leakDetector:
-    c_fprintf(file, "%s %p %d escaped=%ld color=%c from %s(%ld)\n",
-              msg, id, kind, didEscape(c), col, c.filename, c.line)
-  else:
-    c_fprintf(file, "%s %p %d escaped=%ld color=%c\n",
-              msg, id, kind, didEscape(c), col)
-
-proc writeCell(msg: cstring, c: PCell) =
-  stdout.writeCell(msg, c)
-
-proc myastToStr[T](x: T): string {.magic: "AstToStr", noSideEffect.}
-
-template gcTrace(cell, state: untyped) =
-  when traceGC: writeCell(myastToStr(state), cell)
-
-# forward declarations:
-proc collectCT(gch: var GcHeap) {.benign.}
-proc isOnStack(p: pointer): bool {.noinline, benign.}
-proc forAllChildren(cell: PCell, op: WalkOp) {.benign.}
-proc doOperation(p: pointer, op: WalkOp) {.benign.}
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) {.benign.}
-# we need the prototype here for debugging purposes
-
-proc nimGCref(p: pointer) {.compilerproc.} =
-  let cell = usrToCell(p)
-  markAsEscaped(cell)
-  add(gch.additionalRoots, cell)
-
-proc nimGCunref(p: pointer) {.compilerproc.} =
-  let cell = usrToCell(p)
-  var L = gch.additionalRoots.len-1
-  var i = L
-  let d = gch.additionalRoots.d
-  while i >= 0:
-    if d[i] == cell:
-      d[i] = d[L]
-      dec gch.additionalRoots.len
-      break
-    dec(i)
-
-proc nimGCunrefNoCycle(p: pointer) {.compilerproc, inline.} =
-  discard "can we do some freeing here?"
-
-proc nimGCunrefRC1(p: pointer) {.compilerproc, inline.} =
-  discard "can we do some freeing here?"
-
-template markGrey(x: PCell) =
-  if x.color != 1-gch.black and gch.phase == Phase.Marking:
-    if not isAllocatedPtr(gch.region, x):
-      c_fprintf(stdout, "[GC] markGrey proc: %p\n", x)
-      #GC_dumpHeap()
-      sysAssert(false, "wtf")
-    x.setColor(rcGrey)
-    add(gch.greyStack, x)
-
-proc asgnRef(dest: PPointer, src: pointer) {.compilerproc, inline.} =
-  # the code generator calls this proc!
-  gcAssert(not isOnStack(dest), "asgnRef")
-  # BUGFIX: first incRef then decRef!
-  if src != nil:
-    let s = usrToCell(src)
-    markAsEscaped(s)
-    markGrey(s)
-  dest[] = src
-
-proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerproc, inline,
-  deprecated: "old compiler compat".} = asgnRef(dest, src)
-
-proc unsureAsgnRef(dest: PPointer, src: pointer) {.compilerproc.} =
-  # unsureAsgnRef marks 'src' as grey only if dest is not on the
-  # stack. It is used by the code generator if it cannot decide whether a
-  # reference is in the stack or not (this can happen for var parameters).
-  if src != nil:
-    let s = usrToCell(src)
-    markAsEscaped(s)
-    if not isOnStack(dest): markGrey(s)
-  dest[] = src
-
-proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
-  var d = cast[ByteAddress](dest)
-  case n.kind
-  of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
-  of nkList:
-    for i in 0..n.len-1:
-      forAllSlotsAux(dest, n.sons[i], op)
-  of nkCase:
-    var m = selectBranch(dest, n)
-    if m != nil: forAllSlotsAux(dest, m, op)
-  of nkNone: sysAssert(false, "forAllSlotsAux")
-
-proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) =
-  var d = cast[ByteAddress](dest)
-  if dest == nil: return # nothing to do
-  if ntfNoRefs notin mt.flags:
-    case mt.kind
-    of tyRef, tyString, tySequence: # leaf:
-      doOperation(cast[PPointer](d)[], op)
-    of tyObject, tyTuple:
-      forAllSlotsAux(dest, mt.node, op)
-    of tyArray, tyArrayConstr, tyOpenArray:
-      for i in 0..(mt.size div mt.base.size)-1:
-        forAllChildrenAux(cast[pointer](d +% i *% mt.base.size), mt.base, op)
-    else: discard
-
-proc forAllChildren(cell: PCell, op: WalkOp) =
-  gcAssert(cell != nil, "forAllChildren: 1")
-  gcAssert(isAllocatedPtr(gch.region, cell), "forAllChildren: 2")
-  gcAssert(cell.typ != nil, "forAllChildren: 3")
-  gcAssert cell.typ.kind in {tyRef, tySequence, tyString}, "forAllChildren: 4"
-  let marker = cell.typ.marker
-  if marker != nil:
-    marker(cellToUsr(cell), op.int)
-  else:
-    case cell.typ.kind
-    of tyRef: # common case
-      forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
-    of tySequence:
-      var d = cast[ByteAddress](cellToUsr(cell))
-      var s = cast[PGenericSeq](d)
-      if s != nil:
-        for i in 0..s.len-1:
-          forAllChildrenAux(cast[pointer](d +% align(GenericSeqSize, cell.typ.base.align) +% i *% cell.typ.base.size), cell.typ.base, op)
-    else: discard
-
-{.push stackTrace: off, profiler:off.}
-proc gcInvariant*() =
-  sysAssert(allocInv(gch.region), "injected")
-  when declared(markForDebug):
-    markForDebug(gch)
-{.pop.}
-
-include gc_common
-
-proc initGC() =
-  when not defined(useNimRtl):
-    gch.red = (1-gch.black)
-    gch.cycleThreshold = InitialCycleThreshold
-    gch.stat.stackScans = 0
-    gch.stat.completedCollections = 0
-    gch.stat.maxThreshold = 0
-    gch.stat.maxStackSize = 0
-    gch.stat.maxStackCells = 0
-    gch.stat.cycleTableSize = 0
-    # init the rt
-    init(gch.additionalRoots)
-    init(gch.greyStack)
-    when hasThreadSupport:
-      init(gch.toDispose)
-    gch.gcThreadId = atomicInc(gHeapidGenerator) - 1
-    gcAssert(gch.gcThreadId >= 0, "invalid computed thread ID")
-
-proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
-  # generates a new object and sets its reference counter to 0
-  sysAssert(allocInv(gch.region), "rawNewObj begin")
-  gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
-  collectCT(gch)
-  var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
-  gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
-  # now it is buffered in the ZCT
-  res.typ = typ
-  when leakDetector and not hasThreadSupport:
-    if framePtr != nil and framePtr.prev != nil:
-      res.filename = framePtr.prev.filename
-      res.line = framePtr.prev.line
-  # refcount is zero, color is black, but mark it to be in the ZCT
-  res.refcount = allocColor()
-  sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3")
-  when logGC: writeCell("new cell", res)
-  gcTrace(res, csAllocated)
-  when useCellIds:
-    inc gch.idGenerator
-    res.id = gch.idGenerator
-  result = cellToUsr(res)
-  sysAssert(allocInv(gch.region), "rawNewObj end")
-
-{.pop.}
-
-proc newObjNoInit(typ: PNimType, size: int): pointer {.compilerRtl.} =
-  result = rawNewObj(typ, size, gch)
-  when defined(memProfiler): nimProfile(size)
-
-proc newObj(typ: PNimType, size: int): pointer {.compilerRtl.} =
-  result = rawNewObj(typ, size, gch)
-  zeroMem(result, size)
-  when defined(memProfiler): nimProfile(size)
-
-proc newSeq(typ: PNimType, len: int): pointer {.compilerRtl.} =
-  # `newObj` already uses locks, so no need for them here.
-  let size = addInt(align(GenericSeqSize, typ.base.align), mulInt(len, typ.base.size))
-  result = newObj(typ, size)
-  cast[PGenericSeq](result).len = len
-  cast[PGenericSeq](result).reserved = len
-  when defined(memProfiler): nimProfile(size)
-
-proc newObjRC1(typ: PNimType, size: int): pointer {.compilerRtl.} =
-  result = newObj(typ, size)
-
-proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
-  result = newSeq(typ, len)
-
-proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer =
-  collectCT(gch)
-  var ol = usrToCell(old)
-  sysAssert(ol.typ != nil, "growObj: 1")
-  gcAssert(ol.typ.kind in {tyString, tySequence}, "growObj: 2")
-
-  var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell)))
-  var elemSize, elemAlign = 1
-  if ol.typ.kind != tyString:
-    elemSize = ol.typ.base.size
-    elemAlign = ol.typ.base.align
-  incTypeSize ol.typ, newsize
-
-  var oldsize = align(GenericSeqSize, elemAlign) + cast[PGenericSeq](old).len*elemSize
-  copyMem(res, ol, oldsize + sizeof(Cell))
-  zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
-          newsize-oldsize)
-  sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
-  when false:
-    # this is wrong since seqs can be shared via 'shallow':
-    when reallyDealloc: rawDealloc(gch.region, ol)
-    else:
-      zeroMem(ol, sizeof(Cell))
-  when useCellIds:
-    inc gch.idGenerator
-    res.id = gch.idGenerator
-  result = cellToUsr(res)
-  when defined(memProfiler): nimProfile(newsize-oldsize)
-
-proc growObj(old: pointer, newsize: int): pointer {.rtl.} =
-  result = growObj(old, newsize, gch)
-
-{.push profiler:off.}
-
-
-template takeStartTime(workPackageSize) {.dirty.} =
-  const workPackage = workPackageSize
-  var debugticker = 1000
-  when withRealTime:
-    var steps = workPackage
-    var t0: Ticks
-    if gch.maxPause > 0: t0 = getticks()
-
-template takeTime {.dirty.} =
-  when withRealTime: dec steps
-  dec debugticker
-
-template checkTime {.dirty.} =
-  if debugticker <= 0:
-    #echo "in loop"
-    debugticker = 1000
-  when withRealTime:
-    if steps == 0:
-      steps = workPackage
-      if gch.maxPause > 0:
-        let duration = getticks() - t0
-        # the GC's measuring is not accurate and needs some cleanup actions
-        # (stack unmarking), so subtract some short amount of time in
-        # order to miss deadlines less often:
-        if duration >= gch.maxPause - 50_000:
-          return false
-
-# ---------------- dump heap ----------------
-
-template dumpHeapFile(gch: var GcHeap): File =
-  cast[File](gch.pDumpHeapFile)
-
-proc debugGraph(s: PCell) =
-  c_fprintf(gch.dumpHeapFile, "child %p\n", s)
-
-proc dumpRoot(gch: var GcHeap; s: PCell) =
-  if isAllocatedPtr(gch.region, s):
-    c_fprintf(gch.dumpHeapFile, "global_root %p\n", s)
-  else:
-    c_fprintf(gch.dumpHeapFile, "global_root_invalid %p\n", s)
-
-proc GC_dumpHeap*(file: File) =
-  ## Dumps the GCed heap's content to a file. Can be useful for
-  ## debugging. Produces an undocumented text file format that
-  ## can be translated into "dot" syntax via the "heapdump2dot" tool.
-  gch.pDumpHeapFile = file
-  var spaceIter: ObjectSpaceIter
-  when false:
-    var d = gch.decStack.d
-    for i in 0 .. gch.decStack.len-1:
-      if isAllocatedPtr(gch.region, d[i]):
-        c_fprintf(file, "onstack %p\n", d[i])
-      else:
-        c_fprintf(file, "onstack_invalid %p\n", d[i])
-  if gch.gcThreadId == 0:
-    for i in 0 .. globalMarkersLen-1: globalMarkers[i]()
-  for i in 0 .. threadLocalMarkersLen-1: threadLocalMarkers[i]()
-  while true:
-    let x = allObjectsAsProc(gch.region, addr spaceIter)
-    if spaceIter.state < 0: break
-    if isCell(x):
-      # cast to PCell is correct here:
-      var c = cast[PCell](x)
-      writeCell(file, "cell ", c)
-      forAllChildren(c, waDebug)
-      c_fprintf(file, "end\n")
-  gch.pDumpHeapFile = nil
-
-proc GC_dumpHeap() =
-  var f: File
-  if open(f, "heap.txt", fmWrite):
-    GC_dumpHeap(f)
-    f.close()
-  else:
-    c_fprintf(stdout, "cannot write heap.txt")
-
-# ---------------- cycle collector -------------------------------------------
-
-proc freeCyclicCell(gch: var GcHeap, c: PCell) =
-  gcAssert(isAllocatedPtr(gch.region, c), "freeCyclicCell: freed pointer?")
-  prepareDealloc(c)
-  gcTrace(c, csCycFreed)
-  when logGC: writeCell("cycle collector dealloc cell", c)
-  when reallyDealloc:
-    sysAssert(allocInv(gch.region), "free cyclic cell")
-    rawDealloc(gch.region, c)
-  else:
-    gcAssert(c.typ != nil, "freeCyclicCell")
-    zeroMem(c, sizeof(Cell))
-
-proc sweep(gch: var GcHeap): bool =
-  takeStartTime(100)
-  #echo "loop start"
-  let white = 1-gch.black
-  #c_fprintf(stdout, "black is %d\n", black)
-  while true:
-    let x = allObjectsAsProc(gch.region, addr gch.spaceIter)
-    if gch.spaceIter.state < 0: break
-    takeTime()
-    if isCell(x):
-      # cast to PCell is correct here:
-      var c = cast[PCell](x)
-      gcAssert c.color != rcGrey, "cell is still grey?"
-      if c.color == white: freeCyclicCell(gch, c)
-      # Since this is incremental, we MUST not set the object to 'white' here.
-      # We could set all the remaining objects to white after the 'sweep'
-      # completed but instead we flip the meaning of black/white to save one
-      # traversal over the heap!
-    checkTime()
-  # prepare for next iteration:
-  #echo "loop end"
-  gch.spaceIter = ObjectSpaceIter()
-  result = true
-
-proc markRoot(gch: var GcHeap, c: PCell) {.inline.} =
-  if c.color == 1-gch.black:
-    c.setColor(rcGrey)
-    add(gch.greyStack, c)
-
-proc markIncremental(gch: var GcHeap): bool =
-  var L = addr(gch.greyStack.len)
-  takeStartTime(100)
-  while L[] > 0:
-    var c = gch.greyStack.d[0]
-    if not isAllocatedPtr(gch.region, c):
-      c_fprintf(stdout, "[GC] not allocated anymore: %p\n", c)
-      #GC_dumpHeap()
-      sysAssert(false, "wtf")
-
-    #sysAssert(isAllocatedPtr(gch.region, c), "markIncremental: isAllocatedPtr")
-    gch.greyStack.d[0] = gch.greyStack.d[L[] - 1]
-    dec(L[])
-    takeTime()
-    if c.color == rcGrey:
-      c.setColor(gch.black)
-      forAllChildren(c, waMarkGrey)
-    elif c.color == (1-gch.black):
-      gcAssert false, "wtf why are there white objects in the greystack?"
-    checkTime()
-  gcAssert gch.greyStack.len == 0, "markIncremental: greystack not empty "
-  result = true
-
-proc markGlobals(gch: var GcHeap) =
-  if gch.gcThreadId == 0:
-    for i in 0 .. globalMarkersLen-1: globalMarkers[i]()
-  for i in 0 .. threadLocalMarkersLen-1: threadLocalMarkers[i]()
-
-proc doOperation(p: pointer, op: WalkOp) =
-  if p == nil: return
-  var c: PCell = usrToCell(p)
-  gcAssert(c != nil, "doOperation: 1")
-  # the 'case' should be faster than function pointers because of easy
-  # prediction:
-  case op
-  of waZctDecRef:
-    #if not isAllocatedPtr(gch.region, c):
-    #  c_fprintf(stdout, "[GC] decref bug: %p", c)
-    gcAssert(isAllocatedPtr(gch.region, c), "decRef: waZctDecRef")
-    discard "use me for nimEscape?"
-  of waMarkGlobal:
-    template handleRoot =
-      if gch.dumpHeapFile.isNil:
-        markRoot(gch, c)
-      else:
-        dumpRoot(gch, c)
-    handleRoot()
-    discard allocInv(gch.region)
-  of waMarkGrey:
-    when false:
-      if not isAllocatedPtr(gch.region, c):
-        c_fprintf(stdout, "[GC] not allocated anymore: MarkGrey %p\n", c)
-        #GC_dumpHeap()
-        sysAssert(false, "wtf")
-    if c.color == 1-gch.black:
-      c.setColor(rcGrey)
-      add(gch.greyStack, c)
-  of waDebug: debugGraph(c)
-
-proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
-  doOperation(d, WalkOp(op))
-
-proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
-  # the addresses are not as cells on the stack, so turn them to cells:
-  sysAssert(allocInv(gch.region), "gcMark begin")
-  var cell = usrToCell(p)
-  var c = cast[ByteAddress](cell)
-  if c >% PageSize:
-    # fast check: does it look like a cell?
-    var objStart = cast[PCell](interiorAllocatedPtr(gch.region, cell))
-    if objStart != nil:
-      # mark the cell:
-      markRoot(gch, objStart)
-  sysAssert(allocInv(gch.region), "gcMark end")
-
-proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} =
-  forEachStackSlot(gch, gcMark)
-
-proc collectALittle(gch: var GcHeap): bool =
-  case gch.phase
-  of Phase.None:
-    if getOccupiedMem(gch.region) >= gch.cycleThreshold:
-      gch.phase = Phase.Marking
-      markGlobals(gch)
-      result = collectALittle(gch)
-      #when false: c_fprintf(stdout, "collectALittle: introduced bug E %ld\n", gch.phase)
-      #discard allocInv(gch.region)
-  of Phase.Marking:
-    when hasThreadSupport:
-      for c in gch.toDispose:
-        nimGCunref(c)
-    prepareForInteriorPointerChecking(gch.region)
-    markStackAndRegisters(gch)
-    inc(gch.stat.stackScans)
-    if markIncremental(gch):
-      gch.phase = Phase.Sweeping
-      gch.red = 1 - gch.red
-  of Phase.Sweeping:
-    gcAssert gch.greyStack.len == 0, "greystack not empty"
-    when hasThreadSupport:
-      for c in gch.toDispose:
-        nimGCunref(c)
-    if sweep(gch):
-      gch.phase = Phase.None
-      # flip black/white meanings:
-      gch.black = 1 - gch.black
-      gcAssert gch.red == 1 - gch.black, "red color is wrong"
-      inc(gch.stat.completedCollections)
-      result = true
-
-proc collectCTBody(gch: var GcHeap) =
-  when withRealTime:
-    let t0 = getticks()
-  sysAssert(allocInv(gch.region), "collectCT: begin")
-
-  when not nimCoroutines:
-    gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize())
-  #gch.stat.maxStackCells = max(gch.stat.maxStackCells, gch.decStack.len)
-  if collectALittle(gch):
-    gch.cycleThreshold = max(InitialCycleThreshold, getOccupiedMem() *
-                              CycleIncrease)
-    gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold)
-  sysAssert(allocInv(gch.region), "collectCT: end")
-  when withRealTime:
-    let duration = getticks() - t0
-    gch.stat.maxPause = max(gch.stat.maxPause, duration)
-    when defined(reportMissedDeadlines):
-      if gch.maxPause > 0 and duration > gch.maxPause:
-        c_fprintf(stdout, "[GC] missed deadline: %ld\n", duration)
-
-when nimCoroutines:
-  proc currentStackSizes(): int =
-    for stack in items(gch.stack):
-      result = result + stack.stackSize()
-
-proc collectCT(gch: var GcHeap) =
-  # stackMarkCosts prevents some pathological behaviour: Stack marking
-  # becomes more expensive with large stacks and large stacks mean that
-  # cells with RC=0 are more likely to be kept alive by the stack.
-  when nimCoroutines:
-    let stackMarkCosts = max(currentStackSizes() div (16*sizeof(int)), ZctThreshold)
-  else:
-    let stackMarkCosts = max(stackSize() div (16*sizeof(int)), ZctThreshold)
-  if (gch.greyStack.len >= stackMarkCosts or (cycleGC and
-      getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and
-      gch.recGcLock == 0:
-    collectCTBody(gch)
-
-when withRealTime:
-  proc toNano(x: int): Nanos {.inline.} =
-    result = x * 1000
-
-  proc GC_setMaxPause*(MaxPauseInUs: int) =
-    gch.maxPause = MaxPauseInUs.toNano
-
-  proc GC_step(gch: var GcHeap, us: int, strongAdvice: bool) =
-    gch.maxPause = us.toNano
-    #if (getOccupiedMem(gch.region)>=gch.cycleThreshold) or
-    #    alwaysGC or strongAdvice:
-    collectCTBody(gch)
-
-  proc GC_step*(us: int, strongAdvice = false, stackSize = -1) {.noinline.} =
-    if stackSize >= 0:
-      var stackTop {.volatile.}: pointer
-      gch.getActiveStack().pos = addr(stackTop)
-
-      for stack in gch.stack.items():
-        stack.bottomSaved = stack.bottom
-        when stackIncreases:
-          stack.bottom = cast[pointer](
-            cast[ByteAddress](stack.pos) - sizeof(pointer) * 6 - stackSize)
-        else:
-          stack.bottom = cast[pointer](
-            cast[ByteAddress](stack.pos) + sizeof(pointer) * 6 + stackSize)
-
-    GC_step(gch, us, strongAdvice)
-
-    if stackSize >= 0:
-      for stack in gch.stack.items():
-        stack.bottom = stack.bottomSaved
-
-when not defined(useNimRtl):
-  proc GC_disable() =
-    inc(gch.recGcLock)
-  proc GC_enable() =
-    if gch.recGcLock > 0:
-      dec(gch.recGcLock)
-
-  proc GC_setStrategy(strategy: GC_Strategy) =
-    discard
-
-  proc GC_enableMarkAndSweep() = discard
-  proc GC_disableMarkAndSweep() = discard
-
-  proc GC_fullCollect() =
-    var oldThreshold = gch.cycleThreshold
-    gch.cycleThreshold = 0 # forces cycle collection
-    collectCT(gch)
-    gch.cycleThreshold = oldThreshold
-
-  proc GC_getStatistics(): string =
-    GC_disable()
-    result = "[GC] total memory: " & $(getTotalMem()) & "\n" &
-             "[GC] occupied memory: " & $(getOccupiedMem()) & "\n" &
-             "[GC] stack scans: " & $gch.stat.stackScans & "\n" &
-             "[GC] stack cells: " & $gch.stat.maxStackCells & "\n" &
-             "[GC] completed collections: " & $gch.stat.completedCollections & "\n" &
-             "[GC] max threshold: " & $gch.stat.maxThreshold & "\n" &
-             "[GC] grey stack capacity: " & $gch.greyStack.cap & "\n" &
-             "[GC] max cycle table size: " & $gch.stat.cycleTableSize & "\n" &
-             "[GC] max pause time [ms]: " & $(gch.stat.maxPause div 1000_000) & "\n"
-    when nimCoroutines:
-      result.add "[GC] number of stacks: " & $gch.stack.len & "\n"
-      for stack in items(gch.stack):
-        result.add "[GC]   stack " & stack.bottom.repr & "[GC]     max stack size " & $stack.maxStackSize & "\n"
-    else:
-      result.add "[GC] max stack size: " & $gch.stat.maxStackSize & "\n"
-    GC_enable()
-
-{.pop.}
diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim
index f5f4f164f..eb0884560 100644
--- a/lib/system/gc_common.nim
+++ b/lib/system/gc_common.nim
@@ -222,9 +222,9 @@ proc stackSize(stack: ptr GcStack): int {.noinline.} =
 
   if pos != nil:
     when stackIncreases:
-      result = cast[ByteAddress](pos) -% cast[ByteAddress](stack.bottom)
+      result = cast[int](pos) -% cast[int](stack.bottom)
     else:
-      result = cast[ByteAddress](stack.bottom) -% cast[ByteAddress](pos)
+      result = cast[int](stack.bottom) -% cast[int](pos)
   else:
     result = 0
 
@@ -295,8 +295,8 @@ when not defined(useNimRtl):
       # the first init must be the one that defines the stack bottom:
       gch.stack.bottom = theStackBottom
     elif theStackBottom != gch.stack.bottom:
-      var a = cast[ByteAddress](theStackBottom) # and not PageMask - PageSize*2
-      var b = cast[ByteAddress](gch.stack.bottom)
+      var a = cast[int](theStackBottom) # and not PageMask - PageSize*2
+      var b = cast[int](gch.stack.bottom)
       #c_fprintf(stdout, "old: %p new: %p;\n",gch.stack.bottom,theStackBottom)
       when stackIncreases:
         gch.stack.bottom = cast[pointer](min(a, b))
@@ -312,11 +312,11 @@ when not defined(useNimRtl):
 proc isOnStack(p: pointer): bool =
   var stackTop {.volatile, noinit.}: pointer
   stackTop = addr(stackTop)
-  var a = cast[ByteAddress](gch.getActiveStack().bottom)
-  var b = cast[ByteAddress](stackTop)
+  var a = cast[int](gch.getActiveStack().bottom)
+  var b = cast[int](stackTop)
   when not stackIncreases:
     swap(a, b)
-  var x = cast[ByteAddress](p)
+  var x = cast[int](p)
   result = a <=% x and x <=% b
 
 when defined(sparc): # For SPARC architecture.
@@ -337,7 +337,7 @@ when defined(sparc): # For SPARC architecture.
     # Addresses decrease as the stack grows.
     while sp <= max:
       gcMark(gch, sp[])
-      sp = cast[PPointer](cast[ByteAddress](sp) +% sizeof(pointer))
+      sp = cast[PPointer](cast[int](sp) +% sizeof(pointer))
 
 elif defined(ELATE):
   {.error: "stack marking code is to be written for this architecture".}
@@ -354,8 +354,8 @@ elif stackIncreases:
 
   template forEachStackSlotAux(gch, gcMark: untyped) {.dirty.} =
     for stack in gch.stack.items():
-      var max = cast[ByteAddress](gch.stack.bottom)
-      var sp = cast[ByteAddress](addr(registers)) -% sizeof(pointer)
+      var max = cast[int](gch.stack.bottom)
+      var sp = cast[int](addr(registers)) -% sizeof(pointer)
       while sp >=% max:
         gcMark(gch, cast[PPointer](sp)[])
         sp = sp -% sizeof(pointer)
@@ -383,15 +383,14 @@ else:
     gch.getActiveStack().setPosition(addr(registers))
     if c_setjmp(registers) == 0'i32: # To fill the C stack with registers.
       for stack in gch.stack.items():
-        var max = cast[ByteAddress](stack.bottom)
-        var sp = cast[ByteAddress](addr(registers))
+        var max = cast[int](stack.bottom)
+        var sp = cast[int](addr(registers))
         when defined(amd64):
           if stack.isActiveStack():
             # words within the jmp_buf structure may not be properly aligned.
             let regEnd = sp +% sizeof(registers)
             while sp <% regEnd:
               gcMark(gch, cast[PPointer](sp)[])
-              gcMark(gch, cast[PPointer](sp +% sizeof(pointer) div 2)[])
               sp = sp +% sizeof(pointer)
         # Make sure sp is word-aligned
         sp = sp and not (sizeof(pointer) - 1)
diff --git a/lib/system/gc_ms.nim b/lib/system/gc_ms.nim
index f91b37b94..c885a6893 100644
--- a/lib/system/gc_ms.nim
+++ b/lib/system/gc_ms.nim
@@ -27,7 +27,7 @@ when defined(memProfiler):
   proc nimProfile(requestedSize: int)
 
 when hasThreadSupport:
-  import sharedlist
+  import std/sharedlist
 
 type
   WalkOp = enum
@@ -94,11 +94,11 @@ template gcAssert(cond: bool, msg: string) =
 
 proc cellToUsr(cell: PCell): pointer {.inline.} =
   # convert object (=pointer to refcount) to pointer to userdata
-  result = cast[pointer](cast[ByteAddress](cell)+%ByteAddress(sizeof(Cell)))
+  result = cast[pointer](cast[int](cell)+%ByteAddress(sizeof(Cell)))
 
 proc usrToCell(usr: pointer): PCell {.inline.} =
   # convert pointer to userdata to object (=pointer to refcount)
-  result = cast[PCell](cast[ByteAddress](usr)-%ByteAddress(sizeof(Cell)))
+  result = cast[PCell](cast[int](usr)-%ByteAddress(sizeof(Cell)))
 
 proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
   # used for code generation concerning debugging
@@ -217,7 +217,7 @@ proc initGC() =
     gcAssert(gch.gcThreadId >= 0, "invalid computed thread ID")
 
 proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   case n.kind
   of nkSlot: forAllChildrenAux(cast[pointer](d +% n.offset), n.typ, op)
   of nkList:
@@ -229,7 +229,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) {.benign.} =
   of nkNone: sysAssert(false, "forAllSlotsAux")
 
 proc forAllChildrenAux(dest: pointer, mt: PNimType, op: WalkOp) =
-  var d = cast[ByteAddress](dest)
+  var d = cast[int](dest)
   if dest == nil: return # nothing to do
   if ntfNoRefs notin mt.flags:
     case mt.kind
@@ -255,7 +255,7 @@ proc forAllChildren(cell: PCell, op: WalkOp) =
       forAllChildrenAux(cellToUsr(cell), cell.typ.base, op)
     of tySequence:
       when not defined(nimSeqsV2):
-        var d = cast[ByteAddress](cellToUsr(cell))
+        var d = cast[int](cellToUsr(cell))
         var s = cast[PGenericSeq](d)
         if s != nil:
           for i in 0..s.len-1:
@@ -268,7 +268,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap): pointer =
   gcAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1")
   collectCT(gch, size + sizeof(Cell))
   var res = cast[PCell](rawAlloc(gch.region, size + sizeof(Cell)))
-  gcAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2")
+  gcAssert((cast[int](res) and (MemAlign-1)) == 0, "newObj: 2")
   # now it is buffered in the ZCT
   res.typ = typ
   when leakDetector and not hasThreadSupport:
@@ -336,9 +336,9 @@ when not defined(nimSeqsV2):
 
     var oldsize = align(GenericSeqSize, elemAlign) + cast[PGenericSeq](old).len*elemSize
     copyMem(res, ol, oldsize + sizeof(Cell))
-    zeroMem(cast[pointer](cast[ByteAddress](res)+% oldsize +% sizeof(Cell)),
+    zeroMem(cast[pointer](cast[int](res)+% oldsize +% sizeof(Cell)),
             newsize-oldsize)
-    sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3")
+    sysAssert((cast[int](res) and (MemAlign-1)) == 0, "growObj: 3")
     when withBitvectors: incl(gch.allocated, res)
     when useCellIds:
       inc gch.idGenerator
@@ -446,7 +446,7 @@ proc markGlobals(gch: var GcHeap) =
 
 proc gcMark(gch: var GcHeap, p: pointer) {.inline.} =
   # the addresses are not as cells on the stack, so turn them to cells:
-  var c = cast[ByteAddress](p)
+  var c = cast[int](p)
   if c >% PageSize:
     # fast check: does it look like a cell?
     var objStart = cast[PCell](interiorAllocatedPtr(gch.region, p))
diff --git a/lib/system/hti.nim b/lib/system/hti.nim
index 9acaae88b..a26aff982 100644
--- a/lib/system/hti.nim
+++ b/lib/system/hti.nim
@@ -59,7 +59,7 @@ type
     tyOwned, tyUnused1, tyUnused2,
     tyVarargsHidden,
     tyUncheckedArray,
-    tyProxyHidden,
+    tyErrorHidden,
     tyBuiltInTypeClassHidden,
     tyUserTypeClassHidden,
     tyUserTypeClassInstHidden,
diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim
index 42c85ad26..3bf0b9893 100644
--- a/lib/system/inclrtl.nim
+++ b/lib/system/inclrtl.nim
@@ -47,5 +47,4 @@ else:
 
 {.pragma: benign, gcsafe.}
 
-when defined(nimHasSinkInference):
-  {.push sinkInference: on.}
+{.push sinkInference: on.}
diff --git a/lib/system/indices.nim b/lib/system/indices.nim
index fd6770e23..f2bad2528 100644
--- a/lib/system/indices.nim
+++ b/lib/system/indices.nim
@@ -10,7 +10,7 @@ template `^`*(x: int): BackwardsIndex = BackwardsIndex(x)
   ## Builtin `roof`:idx: operator that can be used for convenient array access.
   ## `a[^x]` is a shortcut for `a[a.len-x]`.
   ##
-  ##   ```
+  ##   ```nim
   ##   let
   ##     a = [1, 3, 5, 7, 9]
   ##     b = "abcdefgh"
@@ -46,7 +46,7 @@ template `..^`*(a, b: untyped): untyped =
 
 template `..<`*(a, b: untyped): untyped =
   ## A shortcut for `a .. pred(b)`.
-  ##   ```
+  ##   ```nim
   ##   for i in 5 ..< 9:
   ##     echo i # => 5; 6; 7; 8
   ##   ```
@@ -76,7 +76,7 @@ template spliceImpl(s, a, L, b: typed): untyped =
 proc `[]`*[T, U: Ordinal](s: string, x: HSlice[T, U]): string {.inline, systemRaisesDefect.} =
   ## Slice operation for strings.
   ## Returns the inclusive range `[s[x.a], s[x.b]]`:
-  ##   ```
+  ##   ```nim
   ##   var s = "abcdef"
   ##   assert s[1..3] == "bcd"
   ##   ```
@@ -106,10 +106,13 @@ proc `[]=`*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) {.systemRa
 proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] {.systemRaisesDefect.} =
   ## Slice operation for arrays.
   ## Returns the inclusive range `[a[x.a], a[x.b]]`:
-  ##   ```
+  ##   ```nim
   ##   var a = [1, 2, 3, 4]
   ##   assert a[0..2] == @[1, 2, 3]
   ##   ```
+  ##
+  ## See also:
+  ## * `toOpenArray(array[I, T];I,I) <#toOpenArray,array[I,T],I,I>`_
   let xa = a ^^ x.a
   let L = (a ^^ x.b) - xa + 1
   result = newSeq[T](L)
@@ -117,7 +120,7 @@ proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] {.s
 
 proc `[]=`*[Idx, T; U, V: Ordinal](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) {.systemRaisesDefect.} =
   ## Slice assignment for arrays.
-  ##   ```
+  ##   ```nim
   ##   var a = [10, 20, 30, 40, 50]
   ##   a[1..2] = @[99, 88]
   ##   assert a == [10, 99, 88, 40, 50]
@@ -132,10 +135,13 @@ proc `[]=`*[Idx, T; U, V: Ordinal](a: var array[Idx, T], x: HSlice[U, V], b: ope
 proc `[]`*[T; U, V: Ordinal](s: openArray[T], x: HSlice[U, V]): seq[T] {.systemRaisesDefect.} =
   ## Slice operation for sequences.
   ## Returns the inclusive range `[s[x.a], s[x.b]]`:
-  ##   ```
+  ##   ```nim
   ##   var s = @[1, 2, 3, 4]
   ##   assert s[0..2] == @[1, 2, 3]
   ##   ```
+  ##
+  ## See also:
+  ## * `toOpenArray(openArray[T];int,int) <#toOpenArray,openArray[T],int,int>`_
   let a = s ^^ x.a
   let L = (s ^^ x.b) - a + 1
   newSeq(result, L)
diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim
index b16a605b7..125bee98f 100644
--- a/lib/system/iterators.nim
+++ b/lib/system/iterators.nim
@@ -3,17 +3,22 @@
 when defined(nimPreviewSlimSystem):
   import std/assertions
 
-when defined(nimHasLentIterators) and not defined(nimNoLentIterators):
+when not defined(nimNoLentIterators):
   template lent2(T): untyped = lent T
 else:
   template lent2(T): untyped = T
 
+template unCheckedInc(x) =
+  {.push overflowChecks: off.}
+  inc(x)
+  {.pop.}
+
 iterator items*[T: not char](a: openArray[T]): lent2 T {.inline.} =
   ## Iterates over each item of `a`.
   var i = 0
   while i < len(a):
     yield a[i]
-    inc(i)
+    unCheckedInc(i)
 
 iterator items*[T: char](a: openArray[T]): T {.inline.} =
   ## Iterates over each item of `a`.
@@ -23,14 +28,14 @@ iterator items*[T: char](a: openArray[T]): T {.inline.} =
   var i = 0
   while i < len(a):
     yield a[i]
-    inc(i)
+    unCheckedInc(i)
 
 iterator mitems*[T](a: var openArray[T]): var T {.inline.} =
   ## Iterates over each item of `a` so that you can modify the yielded value.
   var i = 0
   while i < len(a):
     yield a[i]
-    inc(i)
+    unCheckedInc(i)
 
 iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
   ## Iterates over each item of `a`.
@@ -39,7 +44,7 @@ iterator items*[IX, T](a: array[IX, T]): T {.inline.} =
     while true:
       yield a[i]
       if i >= high(IX): break
-      inc(i)
+      unCheckedInc(i)
 
 iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} =
   ## Iterates over each item of `a` so that you can modify the yielded value.
@@ -48,7 +53,7 @@ iterator mitems*[IX, T](a: var array[IX, T]): var T {.inline.} =
     while true:
       yield a[i]
       if i >= high(IX): break
-      inc(i)
+      unCheckedInc(i)
 
 iterator items*[T](a: set[T]): T {.inline.} =
   ## Iterates over each element of `a`. `items` iterates only over the
@@ -56,8 +61,11 @@ iterator items*[T](a: set[T]): T {.inline.} =
   ## able to hold).
   var i = low(T).int
   while i <= high(T).int:
-    if T(i) in a: yield T(i)
-    inc(i)
+    when T is enum and not defined(js):
+      if cast[T](i) in a: yield cast[T](i)
+    else:
+      if T(i) in a: yield T(i)
+    unCheckedInc(i)
 
 iterator items*(a: cstring): char {.inline.} =
   ## Iterates over each item of `a`.
@@ -76,7 +84,7 @@ iterator items*(a: cstring): char {.inline.} =
     let n = len(a)
     while i < n:
       yield a[i]
-      inc(i)
+      unCheckedInc(i)
   when defined(js): impl()
   else:
     when nimvm:
@@ -86,7 +94,7 @@ iterator items*(a: cstring): char {.inline.} =
       var i = 0
       while a[i] != '\0':
         yield a[i]
-        inc(i)
+        unCheckedInc(i)
 
 iterator mitems*(a: var cstring): var char {.inline.} =
   ## Iterates over each item of `a` so that you can modify the yielded value.
@@ -109,7 +117,7 @@ iterator mitems*(a: var cstring): var char {.inline.} =
     let n = len(a)
     while i < n:
       yield a[i]
-      inc(i)
+      unCheckedInc(i)
   when defined(js): impl()
   else:
     when nimvm: impl()
@@ -117,7 +125,7 @@ iterator mitems*(a: var cstring): var char {.inline.} =
       var i = 0
       while a[i] != '\0':
         yield a[i]
-        inc(i)
+        unCheckedInc(i)
 
 iterator items*[T: enum and Ordinal](E: typedesc[T]): T =
   ## Iterates over the values of `E`.
@@ -140,7 +148,7 @@ iterator pairs*[T](a: openArray[T]): tuple[key: int, val: T] {.inline.} =
   var i = 0
   while i < len(a):
     yield (i, a[i])
-    inc(i)
+    unCheckedInc(i)
 
 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.
@@ -148,7 +156,7 @@ iterator mpairs*[T](a: var openArray[T]): tuple[key: int, val: var T]{.inline.}
   var i = 0
   while i < len(a):
     yield (i, a[i])
-    inc(i)
+    unCheckedInc(i)
 
 iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
   ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -157,7 +165,7 @@ iterator pairs*[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.} =
     while true:
       yield (i, a[i])
       if i >= high(IX): break
-      inc(i)
+      unCheckedInc(i)
 
 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.
@@ -167,7 +175,7 @@ iterator mpairs*[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inlin
     while true:
       yield (i, a[i])
       if i >= high(IX): break
-      inc(i)
+      unCheckedInc(i)
 
 iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} =
   ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -175,7 +183,7 @@ iterator pairs*[T](a: seq[T]): tuple[key: int, val: T] {.inline.} =
   let L = len(a)
   while i < L:
     yield (i, a[i])
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the seq changed while iterating over it")
 
 iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} =
@@ -185,7 +193,7 @@ iterator mpairs*[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.} =
   let L = len(a)
   while i < L:
     yield (i, a[i])
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the seq changed while iterating over it")
 
 iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} =
@@ -194,7 +202,7 @@ iterator pairs*(a: string): tuple[key: int, val: char] {.inline.} =
   let L = len(a)
   while i < L:
     yield (i, a[i])
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the string changed while iterating over it")
 
 iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} =
@@ -204,7 +212,7 @@ iterator mpairs*(a: var string): tuple[key: int, val: var char] {.inline.} =
   let L = len(a)
   while i < L:
     yield (i, a[i])
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the string changed while iterating over it")
 
 iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} =
@@ -214,12 +222,12 @@ iterator pairs*(a: cstring): tuple[key: int, val: char] {.inline.} =
     var L = len(a)
     while i < L:
       yield (i, a[i])
-      inc(i)
+      unCheckedInc(i)
   else:
     var i = 0
     while a[i] != '\0':
       yield (i, a[i])
-      inc(i)
+      unCheckedInc(i)
 
 iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
   ## Iterates over each item of `a`. Yields `(index, a[index])` pairs.
@@ -229,12 +237,12 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
     var L = len(a)
     while i < L:
       yield (i, a[i])
-      inc(i)
+      unCheckedInc(i)
   else:
     var i = 0
     while a[i] != '\0':
       yield (i, a[i])
-      inc(i)
+      unCheckedInc(i)
 
 iterator items*[T](a: seq[T]): lent2 T {.inline.} =
   ## Iterates over each item of `a`.
@@ -242,7 +250,7 @@ iterator items*[T](a: seq[T]): lent2 T {.inline.} =
   let L = len(a)
   while i < L:
     yield a[i]
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the seq changed while iterating over it")
 
 iterator mitems*[T](a: var seq[T]): var T {.inline.} =
@@ -251,7 +259,7 @@ iterator mitems*[T](a: var seq[T]): var T {.inline.} =
   let L = len(a)
   while i < L:
     yield a[i]
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the seq changed while iterating over it")
 
 iterator items*(a: string): char {.inline.} =
@@ -260,7 +268,7 @@ iterator items*(a: string): char {.inline.} =
   let L = len(a)
   while i < L:
     yield a[i]
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the string changed while iterating over it")
 
 iterator mitems*(a: var string): var char {.inline.} =
@@ -269,7 +277,7 @@ iterator mitems*(a: var string): var char {.inline.} =
   let L = len(a)
   while i < L:
     yield a[i]
-    inc(i)
+    unCheckedInc(i)
     assert(len(a) == L, "the length of the string changed while iterating over it")
 
 
diff --git a/lib/system/iterators_1.nim b/lib/system/iterators_1.nim
index be61fd62c..d00e3f823 100644
--- a/lib/system/iterators_1.nim
+++ b/lib/system/iterators_1.nim
@@ -16,7 +16,7 @@ iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} =
     let x = collect(newSeq):
       for i in countdown(7, 3):
         i
-    
+
     assert x == @[7, 6, 5, 4, 3]
 
     let y = collect(newseq):
@@ -32,7 +32,10 @@ iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} =
   elif T is IntLikeForCount and T is Ordinal:
     var res = int(a)
     while res >= int(b):
-      yield T(res)
+      when defined(nimHasCastExtendedVm):
+        yield cast[T](res)
+      else:
+        yield T(res)
       dec(res, step)
   else:
     var res = a
@@ -64,7 +67,10 @@ iterator countup*[T](a, b: T, step: Positive = 1): T {.inline.} =
   when T is IntLikeForCount and T is Ordinal:
     var res = int(a)
     while res <= int(b):
-      yield T(res)
+      when defined(nimHasCastExtendedVm):
+        yield cast[T](res)
+      else:
+        yield T(res)
       inc(res, step)
   else:
     var res = a
@@ -89,7 +95,10 @@ iterator `..`*[T](a, b: T): T {.inline.} =
   when T is IntLikeForCount and T is Ordinal:
     var res = int(a)
     while res <= int(b):
-      yield T(res)
+      when defined(nimHasCastExtendedVm):
+        yield cast[T](res)
+      else:
+        yield T(res)
       inc(res)
   else:
     var res = a
diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim
index 9dfa80877..5599240fd 100644
--- a/lib/system/jssys.nim
+++ b/lib/system/jssys.nim
@@ -49,7 +49,7 @@ proc nimCharToStr(x: char): string {.compilerproc.} =
   result[0] = x
 
 proc isNimException(): bool {.asmNoStackFrame.} =
-  asm "return `lastJSError` && `lastJSError`.m_type;"
+  {.emit: "return `lastJSError` && `lastJSError`.m_type;".}
 
 proc getCurrentException*(): ref Exception {.compilerRtl, benign.} =
   if isNimException(): result = cast[ref Exception](lastJSError)
@@ -72,6 +72,10 @@ proc getCurrentExceptionMsg*(): string =
 proc setCurrentException*(exc: ref Exception) =
   lastJSError = cast[PJSError](exc)
 
+proc closureIterSetupExc(e: ref Exception) {.compilerproc, inline.} =
+  ## Used to set up exception handling for closure iterators
+  setCurrentException(e)
+
 proc auxWriteStackTrace(f: PCallFrame): string =
   type
     TempFrame = tuple[procname: cstring, line: int, filename: cstring]
@@ -148,7 +152,7 @@ proc raiseException(e: ref Exception, ename: cstring) {.
     unhandledException(e)
   when NimStackTrace:
     e.trace = rawWriteStackTrace()
-  asm "throw `e`;"
+  {.emit: "throw `e`;".}
 
 proc reraiseException() {.compilerproc, asmNoStackFrame.} =
   if lastJSError == nil:
@@ -158,7 +162,7 @@ proc reraiseException() {.compilerproc, asmNoStackFrame.} =
       if isNimException():
         unhandledException(cast[ref Exception](lastJSError))
 
-    asm "throw lastJSError;"
+    {.emit: "throw lastJSError;".}
 
 proc raiseOverflow {.exportc: "raiseOverflow", noreturn, compilerproc.} =
   raise newException(OverflowDefect, "over- or underflow")
@@ -176,7 +180,7 @@ proc raiseFieldError2(f: string, discVal: string) {.compilerproc, noreturn.} =
   raise newException(FieldDefect, formatFieldDefect(f, discVal))
 
 proc setConstr() {.varargs, asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     var result = {};
     for (var i = 0; i < arguments.length; ++i) {
       var x = arguments[i];
@@ -189,7 +193,7 @@ proc setConstr() {.varargs, asmNoStackFrame, compilerproc.} =
       }
     }
     return result;
-  """
+  """.}
 
 proc makeNimstrLit(c: cstring): string {.asmNoStackFrame, compilerproc.} =
   {.emit: """
@@ -277,62 +281,64 @@ proc toJSStr(s: string): cstring {.compilerproc.} =
   result = join(res)
 
 proc mnewString(len: int): string {.asmNoStackFrame, compilerproc.} =
-  asm """
-    return new Array(`len`);
-  """
+  {.emit: """
+    var result = new Array(`len`);
+    for (var i = 0; i < `len`; i++) {result[i] = 0;}
+    return result;
+  """.}
 
 proc SetCard(a: int): int {.compilerproc, asmNoStackFrame.} =
   # argument type is a fake
-  asm """
+  {.emit: """
     var result = 0;
     for (var elem in `a`) { ++result; }
     return result;
-  """
+  """.}
 
 proc SetEq(a, b: int): bool {.compilerproc, asmNoStackFrame.} =
-  asm """
+  {.emit: """
     for (var elem in `a`) { if (!`b`[elem]) return false; }
     for (var elem in `b`) { if (!`a`[elem]) return false; }
     return true;
-  """
+  """.}
 
 proc SetLe(a, b: int): bool {.compilerproc, asmNoStackFrame.} =
-  asm """
+  {.emit: """
     for (var elem in `a`) { if (!`b`[elem]) return false; }
     return true;
-  """
+  """.}
 
 proc SetLt(a, b: int): bool {.compilerproc.} =
   result = SetLe(a, b) and not SetEq(a, b)
 
 proc SetMul(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-  asm """
+  {.emit: """
     var result = {};
     for (var elem in `a`) {
       if (`b`[elem]) { result[elem] = true; }
     }
     return result;
-  """
+  """.}
 
 proc SetPlus(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-  asm """
+  {.emit: """
     var result = {};
     for (var elem in `a`) { result[elem] = true; }
     for (var elem in `b`) { result[elem] = true; }
     return result;
-  """
+  """.}
 
 proc SetMinus(a, b: int): int {.compilerproc, asmNoStackFrame.} =
-  asm """
+  {.emit: """
     var result = {};
     for (var elem in `a`) {
       if (!`b`[elem]) { result[elem] = true; }
     }
     return result;
-  """
+  """.}
 
 proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     if (`a` == `b`) return 0;
     if (!`a`) return -1;
     if (!`b`) return 1;
@@ -341,7 +347,7 @@ proc cmpStrings(a, b: string): int {.asmNoStackFrame, compilerproc.} =
       if (result != 0) return result;
     }
     return `a`.length - `b`.length;
-  """
+  """.}
 
 proc cmp(x, y: string): int =
   when nimvm:
@@ -352,7 +358,7 @@ proc cmp(x, y: string): int =
     result = cmpStrings(x, y)
 
 proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     if (`a` == `b`) return true;
     if (`a` === null && `b`.length == 0) return true;
     if (`b` === null && `a`.length == 0) return true;
@@ -362,29 +368,29 @@ proc eqStrings(a, b: string): bool {.asmNoStackFrame, compilerproc.} =
     for (var i = 0; i < alen; ++i)
       if (`a`[i] != `b`[i]) return false;
     return true;
-  """
+  """.}
 
 when defined(kwin):
   proc rawEcho {.compilerproc, asmNoStackFrame.} =
-    asm """
+    {.emit: """
       var buf = "";
       for (var i = 0; i < arguments.length; ++i) {
         buf += `toJSStr`(arguments[i]);
       }
       print(buf);
-    """
+    """.}
 
 elif not defined(nimOldEcho):
   proc ewriteln(x: cstring) = log(x)
 
   proc rawEcho {.compilerproc, asmNoStackFrame.} =
-    asm """
+    {.emit: """
       var buf = "";
       for (var i = 0; i < arguments.length; ++i) {
         buf += `toJSStr`(arguments[i]);
       }
       console.log(buf);
-    """
+    """.}
 
 else:
   proc ewriteln(x: cstring) =
@@ -412,84 +418,84 @@ else:
 
 # Arithmetic:
 proc checkOverflowInt(a: int) {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     if (`a` > 2147483647 || `a` < -2147483648) `raiseOverflow`();
-  """
+  """.}
 
 proc addInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     var result = `a` + `b`;
     `checkOverflowInt`(result);
     return result;
-  """
+  """.}
 
 proc subInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     var result = `a` - `b`;
     `checkOverflowInt`(result);
     return result;
-  """
+  """.}
 
 proc mulInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     var result = `a` * `b`;
     `checkOverflowInt`(result);
     return result;
-  """
+  """.}
 
 proc divInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     if (`b` == 0) `raiseDivByZero`();
     if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
     return Math.trunc(`a` / `b`);
-  """
+  """.}
 
 proc modInt(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+  {.emit: """
     if (`b` == 0) `raiseDivByZero`();
     if (`b` == -1 && `a` == 2147483647) `raiseOverflow`();
     return Math.trunc(`a` % `b`);
-  """
+  """.}
 
-proc checkOverflowInt64(a: int) {.asmNoStackFrame, compilerproc.} =
-  asm """
-    if (`a` > 9223372036854775807 || `a` < -9223372036854775808) `raiseOverflow`();
-  """
+proc checkOverflowInt64(a: int64) {.asmNoStackFrame, compilerproc.} =
+  {.emit: """
+    if (`a` > 9223372036854775807n || `a` < -9223372036854775808n) `raiseOverflow`();
+  """.}
 
-proc addInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+proc addInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
+  {.emit: """
     var result = `a` + `b`;
     `checkOverflowInt64`(result);
     return result;
-  """
+  """.}
 
-proc subInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+proc subInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
+  {.emit: """
     var result = `a` - `b`;
     `checkOverflowInt64`(result);
     return result;
-  """
+  """.}
 
-proc mulInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
+proc mulInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
+  {.emit: """
     var result = `a` * `b`;
     `checkOverflowInt64`(result);
     return result;
-  """
+  """.}
 
-proc divInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    if (`b` == 0) `raiseDivByZero`();
-    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
-    return Math.trunc(`a` / `b`);
-  """
+proc divInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
+  {.emit: """
+    if (`b` == 0n) `raiseDivByZero`();
+    if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`();
+    return `a` / `b`;
+  """.}
 
-proc modInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} =
-  asm """
-    if (`b` == 0) `raiseDivByZero`();
-    if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`();
-    return Math.trunc(`a` % `b`);
-  """
+proc modInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} =
+  {.emit: """
+    if (`b` == 0n) `raiseDivByZero`();
+    if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`();
+    return `a` % `b`;
+  """.}
 
 proc negInt(a: int): int {.compilerproc.} =
   result = a*(-1)
@@ -503,32 +509,10 @@ proc absInt(a: int): int {.compilerproc.} =
 proc absInt64(a: int64): int64 {.compilerproc.} =
   result = if a < 0: a*(-1) else: a
 
-when not defined(nimNoZeroExtendMagic):
-  proc ze*(a: int): int {.compilerproc.} =
-    result = a
-
-  proc ze64*(a: int64): int64 {.compilerproc.} =
-    result = a
-
-  proc toU8*(a: int): int8 {.asmNoStackFrame, compilerproc.} =
-    asm """
-      return `a`;
-    """
-
-  proc toU16*(a: int): int16 {.asmNoStackFrame, compilerproc.} =
-    asm """
-      return `a`;
-    """
-
-  proc toU32*(a: int64): int32 {.asmNoStackFrame, compilerproc.} =
-    asm """
-      return `a`;
-    """
-
 proc nimMin(a, b: int): int {.compilerproc.} = return if a <= b: a else: b
 proc nimMax(a, b: int): int {.compilerproc.} = return if a >= b: a else: b
 
-proc chckNilDisp(p: pointer) {.compilerproc.} =
+proc chckNilDisp(p: JSRef) {.compilerproc.} =
   if p == nil:
     sysFatal(NilAccessDefect, "cannot dispatch; dispatcher is nil")
 
@@ -546,22 +530,22 @@ proc nimCopyAux(dest, src: JSRef, n: ptr TNimNode) {.compilerproc.} =
   case n.kind
   of nkNone: sysAssert(false, "nimCopyAux")
   of nkSlot:
-    asm """
+    {.emit: """
       `dest`[`n`.offset] = nimCopy(`dest`[`n`.offset], `src`[`n`.offset], `n`.typ);
-    """
+    """.}
   of nkList:
-    asm """
+    {.emit: """
     for (var i = 0; i < `n`.sons.length; i++) {
       nimCopyAux(`dest`, `src`, `n`.sons[i]);
     }
-    """
+    """.}
   of nkCase:
-    asm """
+    {.emit: """
       `dest`[`n`.offset] = nimCopy(`dest`[`n`.offset], `src`[`n`.offset], `n`.typ);
       for (var i = 0; i < `n`.sons.length; ++i) {
         nimCopyAux(`dest`, `src`, `n`.sons[i][1]);
       }
-    """
+    """.}
 
 proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef =
   case ti.kind
@@ -569,9 +553,9 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef =
     if not isFatPointer(ti):
       result = src
     else:
-      asm "`result` = [`src`[0], `src`[1]];"
+      {.emit: "`result` = [`src`[0], `src`[1]];".}
   of tySet:
-    asm """
+    {.emit: """
       if (`dest` === null || `dest` === undefined) {
         `dest` = {};
       }
@@ -580,18 +564,18 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef =
       }
       for (var key in `src`) { `dest`[key] = `src`[key]; }
       `result` = `dest`;
-    """
+    """.}
   of tyTuple, tyObject:
     if ti.base != nil: result = nimCopy(dest, src, ti.base)
     elif ti.kind == tyObject:
-      asm "`result` = (`dest` === null || `dest` === undefined) ? {m_type: `ti`} : `dest`;"
+      {.emit: "`result` = (`dest` === null || `dest` === undefined) ? {m_type: `ti`} : `dest`;".}
     else:
-      asm "`result` = (`dest` === null || `dest` === undefined) ? {} : `dest`;"
+      {.emit: "`result` = (`dest` === null || `dest` === undefined) ? {} : `dest`;".}
     nimCopyAux(result, src, ti.node)
   of tyArrayConstr, tyArray:
     # In order to prevent a type change (TypedArray -> Array) and to have better copying performance,
     # arrays constructors are considered separately
-    asm """
+    {.emit: """
       if(ArrayBuffer.isView(`src`)) { 
         if(`dest` === null || `dest` === undefined || `dest`.length != `src`.length) {
           `dest` = new `src`.constructor(`src`);
@@ -613,9 +597,9 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef =
           }
         }
       }
-    """
+    """.}
   of tySequence, tyOpenArray:
-    asm """
+    {.emit: """
       if (`src` === null) {
         `result` = null;
       }
@@ -628,55 +612,24 @@ proc nimCopy(dest, src: JSRef, ti: PNimType): JSRef =
           `result`[i] = nimCopy(`result`[i], `src`[i], `ti`.base);
         }
       }
-    """
+    """.}
   of tyString:
-    asm """
+    {.emit: """
       if (`src` !== null) {
         `result` = `src`.slice(0);
       }
-    """
+    """.}
   else:
     result = src
 
-proc genericReset(x: JSRef, ti: PNimType): JSRef {.compilerproc.} =
-  asm "`result` = null;"
-  case ti.kind
-  of tyPtr, tyRef, tyVar, tyNil:
-    if isFatPointer(ti):
-      asm """
-        `result` = [null, 0];
-      """
-  of tySet:
-    asm """
-      `result` = {};
-    """
-  of tyTuple, tyObject:
-    if ti.kind == tyObject:
-      asm "`result` = {m_type: `ti`};"
-    else:
-      asm "`result` = {};"
-  of tySequence, tyOpenArray, tyString:
-    asm """
-      `result` = [];
-    """
-  of tyArrayConstr, tyArray:
-    asm """
-      `result` = new Array(`x`.length);
-      for (var i = 0; i < `x`.length; ++i) {
-        `result`[i] = genericReset(`x`[i], `ti`.base);
-      }
-    """
-  else:
-    discard
-
 proc arrayConstr(len: int, value: JSRef, typ: PNimType): JSRef {.
                 asmNoStackFrame, compilerproc.} =
   # types are fake
-  asm """
+  {.emit: """
     var result = new Array(`len`);
     for (var i = 0; i < `len`; ++i) result[i] = nimCopy(null, `value`, `typ`);
     return result;
-  """
+  """.}
 
 proc chckIndx(i, a, b: int): int {.compilerproc.} =
   if i >= a and i <= b: return i
@@ -705,7 +658,7 @@ proc isObj(obj, subclass: PNimType): bool {.compilerproc.} =
   return true
 
 proc addChar(x: string, c: char) {.compilerproc, asmNoStackFrame.} =
-  asm "`x`.push(`c`);"
+  {.emit: "`x`.push(`c`);".}
 
 {.pop.}
 
@@ -732,9 +685,9 @@ proc parseFloatNative(a: openarray[char]): float =
 
   let cstr = cstring str
 
-  asm """
+  {.emit: """
   `result` = Number(`cstr`);
-  """
+  """.}
 
 proc nimParseBiggestFloat(s: openarray[char], number: var BiggestFloat): int {.compilerproc.} =
   var sign: bool
@@ -801,3 +754,15 @@ if (!Math.trunc) {
   };
 }
 """.}
+
+proc cmpClosures(a, b: JSRef): bool {.compilerproc, asmNoStackFrame.} =
+  # Both `a` and `b` need to be a closure
+  {.emit: """
+    if (`a` !== null && `a`.ClP_0 !== undefined &&
+        `b` !== null && `b`.ClP_0 !== undefined) {
+      return `a`.ClP_0 == `b`.ClP_0 && `a`.ClE_0 == `b`.ClE_0;
+    } else {
+      return `a` == `b`;
+    }
+  """
+  .}
diff --git a/lib/system/memory.nim b/lib/system/memory.nim
index ebda60d8d..156773c48 100644
--- a/lib/system/memory.nim
+++ b/lib/system/memory.nim
@@ -43,6 +43,7 @@ proc nimCmpMem*(a, b: pointer, size: Natural): cint {.compilerproc, nonReloadabl
       inc i
 
 proc nimCStrLen*(a: cstring): int {.compilerproc, nonReloadable, inline.} =
+  if a.isNil: return 0
   when useLibC:
     cast[int](c_strlen(a))
   else:
diff --git a/lib/system/mm/go.nim b/lib/system/mm/go.nim
index 9ec25fb65..8f3aeb964 100644
--- a/lib/system/mm/go.nim
+++ b/lib/system/mm/go.nim
@@ -109,7 +109,7 @@ proc newSeqRC1(typ: PNimType, len: int): pointer {.compilerRtl.} =
   writebarrierptr(addr(result), newSeq(typ, len))
 
 proc nimNewSeqOfCap(typ: PNimType, cap: int): pointer {.compilerproc.} =
-  result = newObj(typ, align(GenericSeqSize, typ.base.align) + cap * typ.base.size)
+  result = newObjNoInit(typ, align(GenericSeqSize, typ.base.align) + cap * typ.base.size)
   cast[PGenericSeq](result).len = 0
   cast[PGenericSeq](result).reserved = cap
   cast[PGenericSeq](result).elemSize = typ.base.size
diff --git a/lib/system/mm/malloc.nim b/lib/system/mm/malloc.nim
index d41dce705..47f1a95ae 100644
--- a/lib/system/mm/malloc.nim
+++ b/lib/system/mm/malloc.nim
@@ -22,7 +22,7 @@ proc reallocImpl(p: pointer, newSize: Natural): pointer =
 proc realloc0Impl(p: pointer, oldsize, newSize: Natural): pointer =
   result = realloc(p, newSize.csize_t)
   if newSize > oldSize:
-    zeroMem(cast[pointer](cast[int](result) + oldSize), newSize - oldSize)
+    zeroMem(cast[pointer](cast[uint](result) + uint(oldSize)), newSize - oldSize)
 
 proc deallocImpl(p: pointer) =
   c_free(p)
@@ -88,7 +88,7 @@ type
 
 proc alloc(r: var MemRegion, size: int): pointer =
   result = alloc(size)
-proc alloc0Impl(r: var MemRegion, size: int): pointer =
+proc alloc0(r: var MemRegion, size: int): pointer =
   result = alloc0Impl(size)
 proc dealloc(r: var MemRegion, p: pointer) = dealloc(p)
 proc deallocOsPages(r: var MemRegion) = discard
diff --git a/lib/system/nimscript.nim b/lib/system/nimscript.nim
index 0b49ea2e7..cf81f6d86 100644
--- a/lib/system/nimscript.nim
+++ b/lib/system/nimscript.nim
@@ -86,12 +86,12 @@ proc patchFile*(package, filename, replacement: string) =
   ## is interpreted to be local to the Nimscript file that contains
   ## the call to `patchFile`, Nim's `--path` is not used at all
   ## to resolve the filename!
+  ## The compiler also performs `path substitution <nimc.html#compiler-usage-commandminusline-switches>`_ on `replacement`.
   ##
   ## Example:
-  ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   patchFile("stdlib", "asyncdispatch", "patches/replacement")
+  ##   ```
   discard
 
 proc getCommand*(): string =
@@ -158,20 +158,19 @@ proc strip(s: string): string =
 template `--`*(key, val: untyped) =
   ## A shortcut for `switch <#switch,string,string>`_
   ## Example:
-  ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   --path:somePath # same as switch("path", "somePath")
   ##   --path:"someOtherPath" # same as switch("path", "someOtherPath")
+  ##   --hint:"[Conf]:off" # same as switch("hint", "[Conf]:off")
+  ##   ```
   switch(strip(astToStr(key)), strip(astToStr(val)))
 
 template `--`*(key: untyped) =
   ## A shortcut for `switch <#switch,string,string>`_
   ## Example:
-  ##
-  ## .. code-block:: nim
-  ##
+  ##   ```nim
   ##   --listCmd # same as switch("listCmd")
+  ##   ```
   switch(strip(astToStr(key)))
 
 type
@@ -254,11 +253,12 @@ proc cpDir*(`from`, to: string) {.raises: [OSError].} =
 proc exec*(command: string) {.
   raises: [OSError], tags: [ExecIOEffect, WriteIOEffect].} =
   ## Executes an external process. If the external process terminates with
-  ## a non-zero exit code, an OSError exception is raised.
+  ## a non-zero exit code, an OSError exception is raised. The command is
+  ## executed relative to the current source path.
   ##
-  ## **Note:** If you need a version of `exec` that returns the exit code
-  ## and text output of the command, you can use `system.gorgeEx
-  ## <system.html#gorgeEx,string,string,string>`_.
+  ## .. note:: If you need a version of `exec` that returns the exit code
+  ##   and text output of the command, you can use `system.gorgeEx
+  ##   <system.html#gorgeEx,string,string,string>`_.
   log "exec: " & command:
     if rawExec(command) != 0:
       raise newException(OSError, "FAILED: " & command)
@@ -268,11 +268,17 @@ proc exec*(command: string, input: string, cache = "") {.
   raises: [OSError], tags: [ExecIOEffect, WriteIOEffect].} =
   ## Executes an external process. If the external process terminates with
   ## a non-zero exit code, an OSError exception is raised.
+  ##
+  ## .. warning:: This version of `exec` is executed relative to the nimscript
+  ##   module path, which affects how the command resolves relative paths. Thus
+  ##   it is generally better to use `gorgeEx` directly when you need more
+  ##   control over the execution environment or when working with commands
+  ##   that deal with relative paths.
   log "exec: " & command:
     let (output, exitCode) = gorgeEx(command, input, cache)
+    echo output
     if exitCode != 0:
       raise newException(OSError, "FAILED: " & command)
-    echo output
 
 proc selfExec*(command: string) {.
   raises: [OSError], tags: [ExecIOEffect, WriteIOEffect].} =
@@ -340,12 +346,12 @@ template withDir*(dir: string; body: untyped): untyped =
   ##
   ## If you need a permanent change, use the `cd() <#cd,string>`_ proc.
   ## Usage example:
-  ##
-  ## .. code-block:: nim
+  ##   ```nim
   ##   # inside /some/path/
   ##   withDir "foo":
   ##     # move to /some/path/foo/
   ##   # back in /some/path/
+  ##   ```
   let curDir = getCurrentDir()
   try:
     cd(dir)
@@ -390,10 +396,10 @@ when not defined(nimble):
     ## Defines a task. Hidden tasks are supported via an empty description.
     ##
     ## Example:
-    ##
-    ## .. code-block:: nim
-    ##  task build, "default build is via the C backend":
-    ##    setCommand "c"
+    ##   ```nim
+    ##   task build, "default build is via the C backend":
+    ##     setCommand "c"
+    ##   ```
     ##
     ## For a task named `foo`, this template generates a `proc` named
     ## `fooTask`.  This is useful if you need to call one task in
@@ -401,13 +407,14 @@ when not defined(nimble):
     ##
     ## Example:
     ##
-    ## .. code-block:: nim
-    ##  task foo, "foo":        # > nim foo
-    ##    echo "Running foo"    # Running foo
+    ##   ```nim
+    ##   task foo, "foo":        # > nim foo
+    ##     echo "Running foo"    # Running foo
     ##
-    ##  task bar, "bar":        # > nim bar
-    ##    echo "Running bar"    # Running bar
-    ##    fooTask()             # Running foo
+    ##   task bar, "bar":        # > nim bar
+    ##     echo "Running bar"    # Running bar
+    ##     fooTask()             # Running foo
+    ##   ```
     proc `name Task`*() =
       setCommand "nop"
       body
diff --git a/lib/system/orc.nim b/lib/system/orc.nim
index 83b983ee1..c02a24989 100644
--- a/lib/system/orc.nim
+++ b/lib/system/orc.nim
@@ -81,10 +81,14 @@ proc trace(s: Cell; desc: PNimTypeV2; j: var GcEnv) {.inline.} =
 
 include threadids
 
-when logOrc:
+when logOrc or orcLeakDetector:
   proc writeCell(msg: cstring; s: Cell; desc: PNimTypeV2) =
-    cfprintf(cstderr, "%s %s %ld root index: %ld; RC: %ld; color: %ld; thread: %ld\n",
-      msg, desc.name, s.refId, s.rootIdx, s.rc shr rcShift, s.color, getThreadId())
+    when orcLeakDetector:
+      cfprintf(cstderr, "%s %s file: %s:%ld; color: %ld; thread: %ld\n",
+        msg, desc.name, s.filename, s.line, s.color, getThreadId())
+    else:
+      cfprintf(cstderr, "%s %s %ld root index: %ld; RC: %ld; color: %ld; thread: %ld\n",
+        msg, desc.name, s.refId, s.rootIdx, s.rc shr rcShift, s.color, getThreadId())
 
 proc free(s: Cell; desc: PNimTypeV2) {.inline.} =
   when traceCollector:
@@ -142,7 +146,7 @@ proc unregisterCycle(s: Cell) =
   let idx = s.rootIdx-1
   when false:
     if idx >= roots.len or idx < 0:
-      cprintf("[Bug!] %ld\n", idx)
+      cprintf("[Bug!] %ld %ld\n", idx, roots.len)
       rawQuit 1
   roots.d[idx] = roots.d[roots.len-1]
   roots.d[idx][0].rootIdx = idx+1
@@ -299,6 +303,14 @@ proc collectColor(s: Cell; desc: PNimTypeV2; col: int; j: var GcEnv) =
         t.setColor(colBlack)
         trace(t, desc, j)
 
+const
+  defaultThreshold = when defined(nimFixedOrc): 10_000 else: 128
+
+when defined(nimStressOrc):
+  const rootsThreshold = 10 # broken with -d:nimStressOrc: 10 and for havlak iterations 1..8
+else:
+  var rootsThreshold {.threadvar.}: int
+
 proc collectCyclesBacon(j: var GcEnv; lowMark: int) =
   # pretty direct translation from
   # https://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf
@@ -337,20 +349,28 @@ proc collectCyclesBacon(j: var GcEnv; lowMark: int) =
     s.rootIdx = 0
     collectColor(s, roots.d[i][1], colToCollect, j)
 
+  # Bug #22927: `free` calls destructors which can append to `roots`.
+  # We protect against this here by setting `roots.len` to 0 and also
+  # setting the threshold so high that no cycle collection can be triggered
+  # until we are out of this critical section:
+  when not defined(nimStressOrc):
+    let oldThreshold = rootsThreshold
+    rootsThreshold = high(int)
+  roots.len = 0
+
   for i in 0 ..< j.toFree.len:
+    when orcLeakDetector:
+      writeCell("CYCLIC OBJECT FREED", j.toFree.d[i][0], j.toFree.d[i][1])
     free(j.toFree.d[i][0], j.toFree.d[i][1])
 
+  when not defined(nimStressOrc):
+    rootsThreshold = oldThreshold
+
   inc j.freed, j.toFree.len
   deinit j.toFree
-  #roots.len = 0
-
-const
-  defaultThreshold = when defined(nimFixedOrc): 10_000 else: 128
 
-when defined(nimStressOrc):
-  const rootsThreshold = 10 # broken with -d:nimStressOrc: 10 and for havlak iterations 1..8
-else:
-  var rootsThreshold = defaultThreshold
+when defined(nimOrcStats):
+  var freedCyclicObjects {.threadvar.}: int
 
 proc partialCollect(lowMark: int) =
   when false:
@@ -365,6 +385,8 @@ proc partialCollect(lowMark: int) =
       roots.len - lowMark)
   roots.len = lowMark
   deinit j.traceStack
+  when defined(nimOrcStats):
+    inc freedCyclicObjects, j.freed
 
 proc collectCycles() =
   ## Collect cycles.
@@ -385,33 +407,44 @@ proc collectCycles() =
     collectCyclesBacon(j, 0)
 
   deinit j.traceStack
-  deinit roots
+  if roots.len == 0:
+    deinit roots
 
   when not defined(nimStressOrc):
     # compute the threshold based on the previous history
     # of the cycle collector's effectiveness:
     # we're effective when we collected 50% or more of the nodes
     # we touched. If we're effective, we can reset the threshold:
-    if j.keepThreshold and rootsThreshold <= defaultThreshold:
+    if j.keepThreshold:
       discard
     elif j.freed * 2 >= j.touched:
       when not defined(nimFixedOrc):
         rootsThreshold = max(rootsThreshold div 3 * 2, 16)
       else:
-        rootsThreshold = defaultThreshold
+        rootsThreshold = 0
       #cfprintf(cstderr, "[collectCycles] freed %ld, touched %ld new threshold %ld\n", j.freed, j.touched, rootsThreshold)
     elif rootsThreshold < high(int) div 4:
-      rootsThreshold = rootsThreshold * 3 div 2
+      rootsThreshold = (if rootsThreshold <= 0: defaultThreshold else: rootsThreshold) * 3 div 2
   when logOrc:
     cfprintf(cstderr, "[collectCycles] end; freed %ld new threshold %ld touched: %ld mem: %ld rcSum: %ld edges: %ld\n", j.freed, rootsThreshold, j.touched,
       getOccupiedMem(), j.rcSum, j.edges)
+  when defined(nimOrcStats):
+    inc freedCyclicObjects, j.freed
+
+when defined(nimOrcStats):
+  type
+    OrcStats* = object ## Statistics of the cycle collector subsystem.
+      freedCyclicObjects*: int ## Number of freed cyclic objects.
+  proc GC_orcStats*(): OrcStats =
+    ## Returns the statistics of the cycle collector subsystem.
+    result = OrcStats(freedCyclicObjects: freedCyclicObjects)
 
 proc registerCycle(s: Cell; desc: PNimTypeV2) =
   s.rootIdx = roots.len+1
   if roots.d == nil: init(roots)
   add(roots, s, desc)
 
-  if roots.len >= rootsThreshold:
+  if roots.len - defaultThreshold >= rootsThreshold:
     collectCycles()
   when logOrc:
     writeCell("[added root]", s, desc)
@@ -424,13 +457,13 @@ proc GC_runOrc* =
   orcAssert roots.len == 0, "roots not empty!"
 
 proc GC_enableOrc*() =
-  ## Enables the cycle collector subsystem of `--gc:orc`. This is a `--gc:orc`
+  ## Enables the cycle collector subsystem of `--mm:orc`. This is a `--mm:orc`
   ## specific API. Check with `when defined(gcOrc)` for its existence.
   when not defined(nimStressOrc):
-    rootsThreshold = defaultThreshold
+    rootsThreshold = 0
 
 proc GC_disableOrc*() =
-  ## Disables the cycle collector subsystem of `--gc:orc`. This is a `--gc:orc`
+  ## Disables the cycle collector subsystem of `--mm:orc`. This is a `--mm:orc`
   ## specific API. Check with `when defined(gcOrc)` for its existence.
   when not defined(nimStressOrc):
     rootsThreshold = high(int)
@@ -441,16 +474,16 @@ proc GC_partialCollect*(limit: int) =
   partialCollect(limit)
 
 proc GC_fullCollect* =
-  ## Forces a full garbage collection pass. With `--gc:orc` triggers the cycle
+  ## Forces a full garbage collection pass. With `--mm:orc` triggers the cycle
   ## collector. This is an alias for `GC_runOrc`.
   collectCycles()
 
 proc GC_enableMarkAndSweep*() =
-  ## For `--gc:orc` an alias for `GC_enableOrc`.
+  ## For `--mm:orc` an alias for `GC_enableOrc`.
   GC_enableOrc()
 
 proc GC_disableMarkAndSweep*() =
-  ## For `--gc:orc` an alias for `GC_disableOrc`.
+  ## For `--mm:orc` an alias for `GC_disableOrc`.
   GC_disableOrc()
 
 const
@@ -485,6 +518,19 @@ proc nimDecRefIsLastCyclicDyn(p: pointer): bool {.compilerRtl, inl.} =
     #if cell.color == colPurple:
     rememberCycle(result, cell, cast[ptr PNimTypeV2](p)[])
 
+proc nimDecRefIsLastDyn(p: pointer): bool {.compilerRtl, inl.} =
+  if p != nil:
+    var cell = head(p)
+    if (cell.rc and not rcMask) == 0:
+      result = true
+      #cprintf("[DESTROY] %p\n", p)
+    else:
+      dec cell.rc, rcIncrement
+    #if cell.color == colPurple:
+    if result:
+      if cell.rootIdx > 0:
+        unregisterCycle(cell)
+
 proc nimDecRefIsLastCyclicStatic(p: pointer; desc: PNimTypeV2): bool {.compilerRtl, inl.} =
   if p != nil:
     var cell = head(p)
diff --git a/lib/system/osalloc.nim b/lib/system/osalloc.nim
index 4817059be..5509d0070 100644
--- a/lib/system/osalloc.nim
+++ b/lib/system/osalloc.nim
@@ -29,8 +29,8 @@ const doNotUnmap = not (defined(amd64) or defined(i386)) or
 
 
 when defined(nimAllocPagesViaMalloc):
-  when not defined(gcArc) and not defined(gcOrc):
-    {.error: "-d:nimAllocPagesViaMalloc is only supported with --gc:arc or --gc:orc".}
+  when not defined(gcArc) and not defined(gcOrc) and not defined(gcAtomicArc):
+    {.error: "-d:nimAllocPagesViaMalloc is only supported with --mm:arc or --mm:atomicArc or --mm:orc".}
 
   proc osTryAllocPages(size: int): pointer {.inline.} =
     let base = c_malloc(csize_t size + PageSize - 1 + sizeof(uint32))
@@ -80,12 +80,12 @@ elif defined(emscripten) and not defined(StandaloneHeapSize):
     let pos = cast[int](result)
 
     # Convert pointer to PageSize correct one.
-    var new_pos = cast[ByteAddress](pos) +% (PageSize - (pos %% PageSize))
+    var new_pos = cast[int](pos) +% (PageSize - (pos %% PageSize))
     if (new_pos-pos) < sizeof(EmscriptenMMapBlock):
       new_pos = new_pos +% PageSize
     result = cast[pointer](new_pos)
 
-    var mmapDescrPos = cast[ByteAddress](result) -% sizeof(EmscriptenMMapBlock)
+    var mmapDescrPos = cast[int](result) -% sizeof(EmscriptenMMapBlock)
 
     var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
     mmapDescr.realSize = realSize
@@ -96,7 +96,7 @@ elif defined(emscripten) and not defined(StandaloneHeapSize):
   proc osTryAllocPages(size: int): pointer = osAllocPages(size)
 
   proc osDeallocPages(p: pointer, size: int) {.inline.} =
-    var mmapDescrPos = cast[ByteAddress](p) -% sizeof(EmscriptenMMapBlock)
+    var mmapDescrPos = cast[int](p) -% sizeof(EmscriptenMMapBlock)
     var mmapDescr = cast[EmscriptenMMapBlock](mmapDescrPos)
     munmap(mmapDescr.realPointer, mmapDescr.realSize)
 
diff --git a/lib/system/rawquits.nim b/lib/system/rawquits.nim
new file mode 100644
index 000000000..f0ead10c6
--- /dev/null
+++ b/lib/system/rawquits.nim
@@ -0,0 +1,27 @@
+import system/ctypes
+
+when defined(nimNoQuit):
+  proc rawQuit(errorcode: int = QuitSuccess) = discard "ignoring quit"
+
+elif defined(genode):
+  import genode/env
+
+  var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr
+
+  type GenodeEnv = GenodeEnvPtr
+    ## Opaque type representing Genode environment.
+
+  proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn,
+    importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "<base/sleep.h>".}
+
+  proc rawQuit(errorcode: int = QuitSuccess) {.inline, noreturn.} =
+    systemEnv.rawQuit(errorcode)
+
+
+elif defined(js) and defined(nodejs) and not defined(nimscript):
+  proc rawQuit(errorcode: int = QuitSuccess) {.magic: "Exit",
+    importc: "process.exit", noreturn.}
+
+else:
+  proc rawQuit(errorcode: cint) {.
+    magic: "Exit", importc: "exit", header: "<stdlib.h>", noreturn.}
\ No newline at end of file
diff --git a/lib/system/repr.nim b/lib/system/repr.nim
index e47220656..13118e40b 100644
--- a/lib/system/repr.nim
+++ b/lib/system/repr.nim
@@ -17,7 +17,7 @@ proc reprFloat(x: float): string {.compilerproc.} = return $x
 
 proc reprPointer(x: pointer): string {.compilerproc.} =
   result = newString(60)
-  let n = c_sprintf(cast[cstring](addr result[0]), "%p", x)
+  let n = c_snprintf(cast[cstring](addr result[0]), csize_t(60), "%p", x)
   setLen(result, n)
 
 proc reprStrAux(result: var string, s: cstring; len: int) =
@@ -155,7 +155,7 @@ when not defined(useNimRtl):
     var bs = typ.base.size
     for i in 0..typ.size div bs - 1:
       if i > 0: add result, ", "
-      reprAux(result, cast[pointer](cast[ByteAddress](p) + i*bs), typ.base, cl)
+      reprAux(result, cast[pointer](cast[int](p) + i*bs), typ.base, cl)
     add result, "]"
 
   when defined(nimSeqsV2):
@@ -183,7 +183,7 @@ when not defined(useNimRtl):
     var bs = typ.base.size
     for i in 0..cast[PGenericSeq](p).len-1:
       if i > 0: add result, ", "
-      reprAux(result, cast[pointer](cast[ByteAddress](payloadPtr(p)) + align(payloadOffset, typ.align) + i*bs),
+      reprAux(result, cast[pointer](cast[int](payloadPtr(p)) + align(payloadOffset, typ.align) + i*bs),
               typ.base, cl)
     add result, "]"
 
@@ -194,14 +194,14 @@ when not defined(useNimRtl):
     of nkSlot:
       add result, $n.name
       add result, " = "
-      reprAux(result, cast[pointer](cast[ByteAddress](p) + n.offset), n.typ, cl)
+      reprAux(result, cast[pointer](cast[int](p) + n.offset), n.typ, cl)
     of nkList:
       for i in 0..n.len-1:
         if i > 0: add result, ",\n"
         reprRecordAux(result, p, n.sons[i], cl)
     of nkCase:
       var m = selectBranch(p, n)
-      reprAux(result, cast[pointer](cast[ByteAddress](p) + n.offset), n.typ, cl)
+      reprAux(result, cast[pointer](cast[int](p) + n.offset), n.typ, cl)
       if m != nil: reprRecordAux(result, p, m, cl)
 
   proc reprRecord(result: var string, p: pointer, typ: PNimType,
@@ -307,7 +307,7 @@ when not defined(useNimRtl):
     var bs = elemtyp.size
     for i in 0..length - 1:
       if i > 0: add result, ", "
-      reprAux(result, cast[pointer](cast[ByteAddress](p) + i*bs), elemtyp, cl)
+      reprAux(result, cast[pointer](cast[int](p) + i*bs), elemtyp, cl)
     add result, "]"
     deinitReprClosure(cl)
 
diff --git a/lib/system/repr_v2.nim b/lib/system/repr_v2.nim
index f6c720e2c..d2aef536c 100644
--- a/lib/system/repr_v2.nim
+++ b/lib/system/repr_v2.nim
@@ -9,6 +9,9 @@ proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
 proc distinctBase(T: typedesc, recursive: static bool = true): typedesc {.magic: "TypeTrait".}
   ## imported from typetraits
 
+proc rangeBase(T: typedesc): typedesc {.magic: "TypeTrait".}
+  # skip one level of range; return the base type of a range type
+
 proc repr*(x: NimNode): string {.magic: "Repr", noSideEffect.}
 
 proc repr*(x: int): string =
@@ -35,9 +38,10 @@ proc repr*(x: char): string {.noSideEffect, raises: [].} =
   ## repr for a character argument. Returns `x`
   ## converted to an escaped string.
   ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   assert repr('c') == "'c'"
-  result.add '\''
+  ##   ```
+  result = "'"
   # Elides string creations if not needed
   if x in {'\\', '\0'..'\31', '\127'..'\255'}:
     result.add '\\'
@@ -50,7 +54,7 @@ proc repr*(x: char): string {.noSideEffect, raises: [].} =
 proc repr*(x: string | cstring): string {.noSideEffect, raises: [].} =
   ## repr for a string argument. Returns `x`
   ## converted to a quoted and escaped string.
-  result.add '\"'
+  result = "\""
   for i in 0..<x.len:
     if x[i] in {'"', '\\', '\0'..'\31', '\127'..'\255'}:
       result.add '\\'
@@ -91,12 +95,17 @@ proc repr*(p: pointer): string =
         result[j] = HexChars[n and 0xF]
         n = n shr 4
 
-proc repr*(p: proc): string =
+proc repr*(p: proc | iterator {.closure.}): string =
   ## repr of a proc as its address
   repr(cast[ptr pointer](unsafeAddr p)[])
 
-template repr*(x: distinct): string =
-  repr(distinctBase(typeof(x))(x))
+template repr*[T: distinct|(range and not enum)](x: T): string =
+  when T is range: # add a branch to handle range
+    repr(rangeBase(typeof(x))(x))
+  elif T is distinct:
+    repr(distinctBase(typeof(x))(x))
+  else:
+    {.error: "cannot happen".}
 
 template repr*(t: typedesc): string = $t
 
@@ -124,11 +133,11 @@ proc reprObject[T: tuple|object](res: var string, x: T) {.noSideEffect, raises:
 proc repr*[T: tuple|object](x: T): string {.noSideEffect, raises: [].} =
   ## Generic `repr` operator for tuples that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   $(23, 45) == "(23, 45)"
   ##   $(a: 23, b: 45) == "(a: 23, b: 45)"
   ##   $() == "()"
+  ##   ```
   when T is object:
     result = $typeof(x)
   reprObject(result, x)
@@ -156,29 +165,19 @@ proc collectionToRepr[T](x: T, prefix, separator, suffix: string): string {.noSi
 proc repr*[T](x: set[T]): string =
   ## Generic `repr` operator for sets that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   ${23, 45} == "{23, 45}"
+  ##   ```
   collectionToRepr(x, "{", ", ", "}")
 
 proc repr*[T](x: seq[T]): string =
   ## Generic `repr` operator for seqs that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   $(@[23, 45]) == "@[23, 45]"
+  ##   ```
   collectionToRepr(x, "@[", ", ", "]")
 
-proc repr*[T, U](x: HSlice[T, U]): string =
-  ## Generic `repr` operator for slices that is lifted from the components
-  ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
-  ##  $(1 .. 5) == "1 .. 5"
-  result = repr(x.a)
-  result.add(" .. ")
-  result.add(repr(x.b))
-
 proc repr*[T, IDX](x: array[IDX, T]): string =
   ## Generic `repr` operator for arrays that is lifted from the components.
   collectionToRepr(x, "[", ", ", "]")
@@ -186,9 +185,9 @@ proc repr*[T, IDX](x: array[IDX, T]): string =
 proc repr*[T](x: openArray[T]): string =
   ## Generic `repr` operator for openarrays that is lifted from the components
   ## of `x`. Example:
-  ##
-  ## .. code-block:: Nim
+  ##   ```Nim
   ##   $(@[23, 45].toOpenArray(0, 1)) == "[23, 45]"
+  ##   ```
   collectionToRepr(x, "[", ", ", "]")
 
 proc repr*[T](x: UncheckedArray[T]): string =
diff --git a/lib/system/reprjs.nim b/lib/system/reprjs.nim
index 0818f9cc9..761d66aec 100644
--- a/lib/system/reprjs.nim
+++ b/lib/system/reprjs.nim
@@ -12,6 +12,8 @@ when defined(nimPreviewSlimSystem):
   import std/formatfloat
 
 proc reprInt(x: int64): string {.compilerproc.} = $x
+proc reprInt(x: uint64): string {.compilerproc.} = $x
+proc reprInt(x: int): string {.compilerproc.} = $x
 proc reprFloat(x: float): string {.compilerproc.} = $x
 
 proc reprPointer(p: pointer): string {.compilerproc.} =
@@ -27,7 +29,7 @@ proc reprBool(x: bool): string {.compilerRtl.} =
 proc reprEnum(e: int, typ: PNimType): string {.compilerRtl.} =
   var tmp: bool
   let item = typ.node.sons[e]
-  {.emit: "`tmp` = `item` !== undefined".}
+  {.emit: "`tmp` = `item` !== undefined;".}
   if tmp:
     result = makeNimstrLit(item.name)
   else:
@@ -134,7 +136,7 @@ proc reprArray(a: pointer, typ: PNimType,
   add(result, "]")
 
 proc isPointedToNil(p: pointer): bool =
-  {. emit: "if (`p` === null) {`result` = true};\n" .}
+  {. emit: "if (`p` === null) {`result` = true;}\n" .}
 
 proc reprRef(result: var string, p: pointer, typ: PNimType,
           cl: var ReprClosure) =
@@ -192,8 +194,12 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
     return
   dec(cl.recDepth)
   case typ.kind
-  of tyInt..tyInt64, tyUInt..tyUInt64:
+  of tyInt..tyInt32, tyUInt..tyUInt32:
     add(result, reprInt(cast[int](p)))
+  of tyInt64:
+    add(result, reprInt(cast[int64](p)))
+  of tyUInt64:
+    add(result, reprInt(cast[uint64](p)))
   of tyChar:
     add(result, reprChar(cast[char](p)))
   of tyBool:
diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim
index 40fd50b48..572e77408 100644
--- a/lib/system/seqs_v2.nim
+++ b/lib/system/seqs_v2.nim
@@ -8,10 +8,13 @@
 #
 
 
-# import typetraits
+# import std/typetraits
 # strs already imported allocateds for us.
 
-proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".}
+
+# Some optimizations here may be not to empty-seq-initialize some symbols, then StrictNotNil complains.
+{.push warning[StrictNotNil]: off.}  # See https://github.com/nim-lang/Nim/issues/21401
+
 
 ## Default seq implementation used by Nim's core.
 type
@@ -27,6 +30,10 @@ type
     len: int
     p: ptr NimSeqPayload[T]
 
+  NimRawSeq = object
+    len: int
+    p: pointer
+
 const nimSeqVersion {.core.} = 2
 
 # XXX make code memory safe for overflows in '*'
@@ -41,6 +48,15 @@ proc newSeqPayload(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises
   else:
     result = nil
 
+proc newSeqPayloadUninit(cap, elemSize, elemAlign: int): pointer {.compilerRtl, raises: [].} =
+  # Used in `newSeqOfCap()`.
+  if cap > 0:
+    var p = cast[ptr NimSeqPayloadBase](alignedAlloc(align(sizeof(NimSeqPayloadBase), elemAlign) + cap * elemSize, elemAlign))
+    p.cap = cap
+    result = p
+  else:
+    result = nil
+
 template `+!`(p: pointer, s: int): pointer =
   cast[pointer](cast[int](p) +% s)
 
@@ -48,7 +64,7 @@ template `-!`(p: pointer, s: int): pointer =
   cast[pointer](cast[int](p) -% s)
 
 proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
-    noSideEffect, raises: [], compilerRtl.} =
+    noSideEffect, tags: [], raises: [], compilerRtl.} =
   {.noSideEffect.}:
     let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
     if addlen <= 0:
@@ -61,15 +77,48 @@ proc prepareSeqAdd(len: int; p: pointer; addlen, elemSize, elemAlign: int): poin
       var p = cast[ptr NimSeqPayloadBase](p)
       let oldCap = p.cap and not strlitFlag
       let newCap = max(resize(oldCap), len+addlen)
+      var q: ptr NimSeqPayloadBase
+      if (p.cap and strlitFlag) == strlitFlag:
+        q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign))
+        copyMem(q +! headerSize, p +! headerSize, len * elemSize)
+      else:
+        let oldSize = headerSize + elemSize * oldCap
+        let newSize = headerSize + elemSize * newCap
+        q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign))
+
+      zeroMem(q +! headerSize +! len * elemSize, addlen * elemSize)
+      q.cap = newCap
+      result = q
+
+proc zeroNewElements(len: int; q: pointer; addlen, elemSize, elemAlign: int) {.
+    noSideEffect, tags: [], raises: [], compilerRtl.} =
+  {.noSideEffect.}:
+    let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
+    zeroMem(q +! headerSize +! len * elemSize, addlen * elemSize)
+
+proc prepareSeqAddUninit(len: int; p: pointer; addlen, elemSize, elemAlign: int): pointer {.
+    noSideEffect, tags: [], raises: [], compilerRtl.} =
+  {.noSideEffect.}:
+    let headerSize = align(sizeof(NimSeqPayloadBase), elemAlign)
+    if addlen <= 0:
+      result = p
+    elif p == nil:
+      result = newSeqPayloadUninit(len+addlen, elemSize, elemAlign)
+    else:
+      # Note: this means we cannot support things that have internal pointers as
+      # they get reallocated here. This needs to be documented clearly.
+      var p = cast[ptr NimSeqPayloadBase](p)
+      let oldCap = p.cap and not strlitFlag
+      let newCap = max(resize(oldCap), len+addlen)
       if (p.cap and strlitFlag) == strlitFlag:
-        var q = cast[ptr NimSeqPayloadBase](alignedAlloc0(headerSize + elemSize * newCap, elemAlign))
+        var q = cast[ptr NimSeqPayloadBase](alignedAlloc(headerSize + elemSize * newCap, elemAlign))
         copyMem(q +! headerSize, p +! headerSize, len * elemSize)
         q.cap = newCap
         result = q
       else:
         let oldSize = headerSize + elemSize * oldCap
         let newSize = headerSize + elemSize * newCap
-        var q = cast[ptr NimSeqPayloadBase](alignedRealloc0(p, oldSize, newSize, elemAlign))
+        var q = cast[ptr NimSeqPayloadBase](alignedRealloc(p, oldSize, newSize, elemAlign))
         q.cap = newCap
         result = q
 
@@ -83,38 +132,41 @@ proc shrink*[T](x: var seq[T]; newLen: Natural) {.tags: [], raises: [].} =
       for i in countdown(x.len - 1, newLen):
         reset x[i]
     # XXX This is wrong for const seqs that were moved into 'x'!
-    cast[ptr NimSeqV2[T]](addr x).len = newLen
+    {.noSideEffect.}:
+      cast[ptr NimSeqV2[T]](addr x).len = newLen
 
-proc grow*[T](x: var seq[T]; newLen: Natural; value: T) =
+proc grow*[T](x: var seq[T]; newLen: Natural; value: T) {.nodestroy.} =
   let oldLen = x.len
   #sysAssert newLen >= x.len, "invalid newLen parameter for 'grow'"
   if newLen <= oldLen: return
   var xu = cast[ptr NimSeqV2[T]](addr x)
-  if xu.p == nil or xu.p.cap < newLen:
-    xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T)))
+  if xu.p == nil or (xu.p.cap and not strlitFlag) < newLen:
+    xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newLen - oldLen, sizeof(T), alignof(T)))
   xu.len = newLen
   for i in oldLen .. newLen-1:
-    xu.p.data[i] = value
+    wasMoved(xu.p.data[i])
+    `=copy`(xu.p.data[i], value)
 
-proc add*[T](x: var seq[T]; value: sink T) {.magic: "AppendSeqElem", noSideEffect, nodestroy.} =
+proc add*[T](x: var seq[T]; y: sink T) {.magic: "AppendSeqElem", noSideEffect, nodestroy.} =
   ## Generic proc for adding a data item `y` to a container `x`.
   ##
   ## For containers that have an order, `add` means *append*. New generic
   ## containers should also call their adding proc `add` for consistency.
   ## Generic code becomes much easier to write if the Nim naming scheme is
   ## respected.
-  let oldLen = x.len
-  var xu = cast[ptr NimSeqV2[T]](addr x)
-  if xu.p == nil or xu.p.cap < oldLen+1:
-    xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, 1, sizeof(T), alignof(T)))
-  xu.len = oldLen+1
-  # .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
-  # copyMem(). This is fine as know by construction that
-  # in `xu.p.data[oldLen]` there is nothing to destroy.
-  # We also save the `wasMoved + destroy` pair for the sink parameter.
-  xu.p.data[oldLen] = value
-
-proc setLen[T](s: var seq[T], newlen: Natural) =
+  {.cast(noSideEffect).}:
+    let oldLen = x.len
+    var xu = cast[ptr NimSeqV2[T]](addr x)
+    if xu.p == nil or (xu.p.cap and not strlitFlag) < oldLen+1:
+      xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, 1, sizeof(T), alignof(T)))
+    xu.len = oldLen+1
+    # .nodestroy means `xu.p.data[oldLen] = value` is compiled into a
+    # copyMem(). This is fine as know by construction that
+    # in `xu.p.data[oldLen]` there is nothing to destroy.
+    # We also save the `wasMoved + destroy` pair for the sink parameter.
+    xu.p.data[oldLen] = y
+
+proc setLen[T](s: var seq[T], newlen: Natural) {.nodestroy.} =
   {.noSideEffect.}:
     if newlen < s.len:
       shrink(s, newlen)
@@ -122,8 +174,8 @@ proc setLen[T](s: var seq[T], newlen: Natural) =
       let oldLen = s.len
       if newlen <= oldLen: return
       var xu = cast[ptr NimSeqV2[T]](addr s)
-      if xu.p == nil or xu.p.cap < newlen:
-        xu.p = cast[typeof(xu.p)](prepareSeqAdd(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
+      if xu.p == nil or (xu.p.cap and not strlitFlag) < newlen:
+        xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
       xu.len = newlen
       for i in oldLen..<newlen:
         xu.p.data[i] = default(T)
@@ -132,9 +184,9 @@ proc newSeq[T](s: var seq[T], len: Natural) =
   shrink(s, 0)
   setLen(s, len)
 
+proc sameSeqPayload(x: pointer, y: pointer): bool {.compilerRtl, inl.} =
+  result = cast[ptr NimRawSeq](x)[].p == cast[ptr NimRawSeq](y)[].p
 
-template capacityImpl(sek: NimSeqV2): int =
-  if sek.p != nil: sek.p.cap else: 0
 
 func capacity*[T](self: seq[T]): int {.inline.} =
   ## Returns the current capacity of the seq.
@@ -144,6 +196,32 @@ func capacity*[T](self: seq[T]): int {.inline.} =
     lst.add "Nim"
     assert lst.capacity == 42
 
-  {.cast(noSideEffect).}:
-    let sek = unsafeAddr self
-    result = capacityImpl(cast[ptr NimSeqV2](sek)[])
+  let sek = cast[ptr NimSeqV2[T]](unsafeAddr self)
+  result = if sek.p != nil: sek.p.cap and not strlitFlag else: 0
+
+func setLenUninit*[T](s: var seq[T], newlen: Natural) {.nodestroy.} =
+  ## Sets the length of seq `s` to `newlen`. `T` may be any sequence type.
+  ## New slots will not be initialized.
+  ##
+  ## If the current length is greater than the new length,
+  ## `s` will be truncated.
+  ##   ```nim
+  ##   var x = @[10, 20]
+  ##   x.setLenUninit(5)
+  ##   x[4] = 50
+  ##   assert x[4] == 50
+  ##   x.setLenUninit(1)
+  ##   assert x == @[10]
+  ##   ```
+  {.noSideEffect.}:
+    if newlen < s.len:
+      shrink(s, newlen)
+    else:
+      let oldLen = s.len
+      if newlen <= oldLen: return
+      var xu = cast[ptr NimSeqV2[T]](addr s)
+      if xu.p == nil or (xu.p.cap and not strlitFlag) < newlen:
+        xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
+      xu.len = newlen
+
+{.pop.}  # See https://github.com/nim-lang/Nim/issues/21401
diff --git a/lib/system/setops.nim b/lib/system/setops.nim
index b42c8b4a8..67aa3097a 100644
--- a/lib/system/setops.nim
+++ b/lib/system/setops.nim
@@ -26,9 +26,9 @@ func excl*[T](x: var set[T], y: T) {.magic: "Excl".} =
   ##
   ## This is the same as `x = x - {y}`, but it might be more efficient.
   runnableExamples:
-    var b = {2, 3, 5, 6, 12, 545}
+    var b = {2, 3, 5, 6, 12, 54}
     b.excl(5)
-    assert b == {2, 3, 6, 12, 545}
+    assert b == {2, 3, 6, 12, 54}
 
 template excl*[T](x: var set[T], y: set[T]) {.callsite.} =
   ## Excludes the set `y` from the set `x`.
diff --git a/lib/system/sets.nim b/lib/system/sets.nim
index 103c8d343..97431c296 100644
--- a/lib/system/sets.nim
+++ b/lib/system/sets.nim
@@ -9,18 +9,20 @@
 
 # set handling
 
-type
-  NimSet = array[0..4*2048-1, uint8]
 
-
-proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} =
+proc cardSetImpl(s: ptr UncheckedArray[uint8], len: int): int {.inline.} =
   var i = 0
   result = 0
+  var num = 0'u64
   when defined(x86) or defined(amd64):
     while i < len - 8:
-      inc(result, countBits64((cast[ptr uint64](s[i].unsafeAddr))[]))
+      copyMem(addr num, addr s[i], 8)
+      inc(result, countBits64(num))
       inc(i, 8)
 
   while i < len:
     inc(result, countBits32(uint32(s[i])))
     inc(i, 1)
+
+proc cardSet(s: ptr UncheckedArray[uint8], len: int): int {.compilerproc, inline.} =
+  result = cardSetImpl(s, len)
diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim
index 0b2578280..89046253b 100644
--- a/lib/system/strmantle.nim
+++ b/lib/system/strmantle.nim
@@ -23,6 +23,14 @@ proc cmpStrings(a, b: string): int {.inline, compilerproc.} =
   else:
     result = alen - blen
 
+proc leStrings(a, b: string): bool {.inline, compilerproc.} =
+  # required by upcoming backends (NIR).
+  cmpStrings(a, b) <= 0
+
+proc ltStrings(a, b: string): bool {.inline, compilerproc.} =
+  # required by upcoming backends (NIR).
+  cmpStrings(a, b) < 0
+
 proc eqStrings(a, b: string): bool {.inline, compilerproc.} =
   let alen = a.len
   let blen = b.len
@@ -33,7 +41,7 @@ proc eqStrings(a, b: string): bool {.inline, compilerproc.} =
 proc hashString(s: string): int {.compilerproc.} =
   # the compiler needs exactly the same hash function!
   # this used to be used for efficient generation of string case statements
-  var h : uint = 0
+  var h = 0'u
   for i in 0..len(s)-1:
     h = h + uint(s[i])
     h = h + h shl 10
@@ -75,8 +83,8 @@ const
               1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
               1e20, 1e21, 1e22]
 
-when defined(nimHasInvariant):
-  {.push staticBoundChecks: off.}
+
+{.push staticBoundChecks: off.}
 
 proc nimParseBiggestFloat(s: openArray[char], number: var BiggestFloat,
                          ): int {.compilerproc.} =
@@ -178,7 +186,9 @@ proc nimParseBiggestFloat(s: openArray[char], number: var BiggestFloat,
 
   # if exponent greater than can be represented: +/- zero or infinity
   if absExponent > 999:
-    if expNegative:
+    if integer == 0:
+      number = 0.0
+    elif expNegative:
       number = 0.0*sign
     else:
       number = Inf*sign
@@ -234,8 +244,7 @@ proc nimParseBiggestFloat(s: openArray[char], number: var BiggestFloat,
   t[ti-3] = ('0'.ord + absExponent mod 10).char
   number = c_strtod(cast[cstring](addr t), nil)
 
-when defined(nimHasInvariant):
-  {.pop.} # staticBoundChecks
+{.pop.} # staticBoundChecks
 
 proc nimBoolToStr(x: bool): string {.compilerRtl.} =
   return if x: "true" else: "false"
diff --git a/lib/system/strs_v2.nim b/lib/system/strs_v2.nim
index 429724dab..404b4f78d 100644
--- a/lib/system/strs_v2.nim
+++ b/lib/system/strs_v2.nim
@@ -34,53 +34,72 @@ template frees(s) =
     else:
       dealloc(s.p)
 
+template allocPayload(newLen: int): ptr NimStrPayload =
+  when compileOption("threads"):
+    cast[ptr NimStrPayload](allocShared(contentSize(newLen)))
+  else:
+    cast[ptr NimStrPayload](alloc(contentSize(newLen)))
+
+template allocPayload0(newLen: int): ptr NimStrPayload =
+  when compileOption("threads"):
+    cast[ptr NimStrPayload](allocShared0(contentSize(newLen)))
+  else:
+    cast[ptr NimStrPayload](alloc0(contentSize(newLen)))
+
+template reallocPayload(p: pointer, newLen: int): ptr NimStrPayload =
+  when compileOption("threads"):
+    cast[ptr NimStrPayload](reallocShared(p, contentSize(newLen)))
+  else:
+    cast[ptr NimStrPayload](realloc(p, contentSize(newLen)))
+
+template reallocPayload0(p: pointer; oldLen, newLen: int): ptr NimStrPayload =
+  when compileOption("threads"):
+    cast[ptr NimStrPayload](reallocShared0(p, contentSize(oldLen), contentSize(newLen)))
+  else:
+    cast[ptr NimStrPayload](realloc0(p, contentSize(oldLen), contentSize(newLen)))
+
 proc resize(old: int): int {.inline.} =
   if old <= 0: result = 4
   elif old <= high(int16): result = old * 2
   else: result = old * 3 div 2 # for large arrays * 3/2 is better
 
-proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} =
-  let newLen = s.len + addlen
+proc prepareAdd(s: var NimStringV2; addLen: int) {.compilerRtl.} =
+  let newLen = s.len + addLen
   if isLiteral(s):
     let oldP = s.p
     # can't mutate a literal, so we need a fresh copy here:
-    when compileOption("threads"):
-      s.p = cast[ptr NimStrPayload](allocShared0(contentSize(newLen)))
-    else:
-      s.p = cast[ptr NimStrPayload](alloc0(contentSize(newLen)))
+    s.p = allocPayload(newLen)
     s.p.cap = newLen
     if s.len > 0:
       # we are about to append, so there is no need to copy the \0 terminator:
       copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], min(s.len, newLen))
+    elif oldP == nil:
+      # In the case of `newString(0) & ""`, since `src.len == 0`, `appendString`
+      # will not set the `\0` terminator, so we set it here.
+      s.p.data[0] = '\0'
   else:
     let oldCap = s.p.cap and not strlitFlag
     if newLen > oldCap:
       let newCap = max(newLen, resize(oldCap))
-      when compileOption("threads"):
-        s.p = cast[ptr NimStrPayload](reallocShared0(s.p, contentSize(oldCap), contentSize(newCap)))
-      else:
-        s.p = cast[ptr NimStrPayload](realloc0(s.p, contentSize(oldCap), contentSize(newCap)))
+      s.p = reallocPayload(s.p, newCap)
       s.p.cap = newCap
+      if newLen < newCap:
+        zeroMem(cast[pointer](addr s.p.data[newLen+1]), newCap - newLen)
 
-proc nimAddCharV1(s: var NimStringV2; c: char) {.compilerRtl, inline.} =
+proc nimAddCharV1(s: var NimStringV2; c: char) {.compilerRtl, inl.} =
   #if (s.p == nil) or (s.len+1 > s.p.cap and not strlitFlag):
   prepareAdd(s, 1)
   s.p.data[s.len] = c
-  s.p.data[s.len+1] = '\0'
   inc s.len
+  s.p.data[s.len] = '\0'
 
 proc toNimStr(str: cstring, len: int): NimStringV2 {.compilerproc.} =
   if len <= 0:
     result = NimStringV2(len: 0, p: nil)
   else:
-    when compileOption("threads"):
-      var p = cast[ptr NimStrPayload](allocShared0(contentSize(len)))
-    else:
-      var p = cast[ptr NimStrPayload](alloc0(contentSize(len)))
+    var p = allocPayload(len)
     p.cap = len
-    if len > 0:
-      # we are about to append, so there is no need to copy the \0 terminator:
-      copyMem(unsafeAddr p.data[0], str, len)
+    copyMem(unsafeAddr p.data[0], str, len+1)
     result = NimStringV2(len: len, p: p)
 
 proc cstrToNimstr(str: cstring): NimStringV2 {.compilerRtl.} =
@@ -99,29 +118,24 @@ proc appendString(dest: var NimStringV2; src: NimStringV2) {.compilerproc, inlin
 
 proc appendChar(dest: var NimStringV2; c: char) {.compilerproc, inline.} =
   dest.p.data[dest.len] = c
-  dest.p.data[dest.len+1] = '\0'
   inc dest.len
+  dest.p.data[dest.len] = '\0'
 
 proc rawNewString(space: int): NimStringV2 {.compilerproc.} =
   # this is also 'system.newStringOfCap'.
   if space <= 0:
     result = NimStringV2(len: 0, p: nil)
   else:
-    when compileOption("threads"):
-      var p = cast[ptr NimStrPayload](allocShared0(contentSize(space)))
-    else:
-      var p = cast[ptr NimStrPayload](alloc0(contentSize(space)))
+    var p = allocPayload(space)
     p.cap = space
+    p.data[0] = '\0'
     result = NimStringV2(len: 0, p: p)
 
 proc mnewString(len: int): NimStringV2 {.compilerproc.} =
   if len <= 0:
     result = NimStringV2(len: 0, p: nil)
   else:
-    when compileOption("threads"):
-      var p = cast[ptr NimStrPayload](allocShared0(contentSize(len)))
-    else:
-      var p = cast[ptr NimStrPayload](alloc0(contentSize(len)))
+    var p = allocPayload0(len)
     p.cap = len
     result = NimStringV2(len: len, p: p)
 
@@ -129,13 +143,30 @@ proc setLengthStrV2(s: var NimStringV2, newLen: int) {.compilerRtl.} =
   if newLen == 0:
     discard "do not free the buffer here, pattern 's.setLen 0' is common for avoiding allocations"
   else:
-    if newLen > s.len or isLiteral(s):
-      prepareAdd(s, newLen - s.len)
+    if isLiteral(s):
+      let oldP = s.p
+      s.p = allocPayload(newLen)
+      s.p.cap = newLen
+      if s.len > 0:
+        copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], min(s.len, newLen))
+        if newLen > s.len:
+          zeroMem(cast[pointer](addr s.p.data[s.len]), newLen - s.len + 1)
+        else:
+          s.p.data[newLen] = '\0'
+      else:
+        zeroMem(cast[pointer](addr s.p.data[0]), newLen + 1)
+    elif newLen > s.len:
+      let oldCap = s.p.cap and not strlitFlag
+      if newLen > oldCap:
+        let newCap = max(newLen, resize(oldCap))
+        s.p = reallocPayload0(s.p, oldCap, newCap)
+        s.p.cap = newCap
+
     s.p.data[newLen] = '\0'
   s.len = newLen
 
 proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
-  if a.p == b.p: return
+  if a.p == b.p and a.len == b.len: return
   if isLiteral(b):
     # we can shallow copy literals:
     frees(a)
@@ -147,10 +178,7 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
       # 'let y = newStringOfCap(); var x = y'
       # on the other hand... These get turned into moves now.
       frees(a)
-      when compileOption("threads"):
-        a.p = cast[ptr NimStrPayload](allocShared0(contentSize(b.len)))
-      else:
-        a.p = cast[ptr NimStrPayload](alloc0(contentSize(b.len)))
+      a.p = allocPayload(b.len)
       a.p.cap = b.len
     a.len = b.len
     copyMem(unsafeAddr a.p.data[0], unsafeAddr b.p.data[0], b.len+1)
@@ -158,14 +186,11 @@ proc nimAsgnStrV2(a: var NimStringV2, b: NimStringV2) {.compilerRtl.} =
 proc nimPrepareStrMutationImpl(s: var NimStringV2) =
   let oldP = s.p
   # can't mutate a literal, so we need a fresh copy here:
-  when compileOption("threads"):
-    s.p = cast[ptr NimStrPayload](allocShared0(contentSize(s.len)))
-  else:
-    s.p = cast[ptr NimStrPayload](alloc0(contentSize(s.len)))
+  s.p = allocPayload(s.len)
   s.p.cap = s.len
   copyMem(unsafeAddr s.p.data[0], unsafeAddr oldP.data[0], s.len+1)
 
-proc nimPrepareStrMutationV2(s: var NimStringV2) {.compilerRtl, inline.} =
+proc nimPrepareStrMutationV2(s: var NimStringV2) {.compilerRtl, inl.} =
   if s.p != nil and (s.p.cap and strlitFlag) == strlitFlag:
     nimPrepareStrMutationImpl(s)
 
@@ -176,9 +201,16 @@ proc prepareMutation*(s: var string) {.inline.} =
     let s = unsafeAddr s
     nimPrepareStrMutationV2(cast[ptr NimStringV2](s)[])
 
+proc nimAddStrV1(s: var NimStringV2; src: NimStringV2) {.compilerRtl, inl.} =
+  #if (s.p == nil) or (s.len+1 > s.p.cap and not strlitFlag):
+  prepareAdd(s, src.len)
+  appendString s, src
+
+proc nimDestroyStrV1(s: NimStringV2) {.compilerRtl, inl.} =
+  frees(s)
 
-template capacityImpl(str: NimStringV2): int =
-  if str.p != nil: str.p.cap else: 0
+proc nimStrAtLe(s: string; idx: int; ch: char): bool {.compilerRtl, inl.} =
+  result = idx < s.len and s[idx] <= ch
 
 func capacity*(self: string): int {.inline.} =
   ## Returns the current capacity of the string.
@@ -188,6 +220,5 @@ func capacity*(self: string): int {.inline.} =
     str.add "Nim"
     assert str.capacity == 42
 
-  {.cast(noSideEffect).}:
-    let str = unsafeAddr self
-    result = capacityImpl(cast[ptr NimStringV2](str)[])
+  let str = cast[ptr NimStringV2](unsafeAddr self)
+  result = if str.p != nil: str.p.cap and not strlitFlag else: 0
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index be32652d8..3621c4960 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -17,10 +17,10 @@
 
 
 proc dataPointer(a: PGenericSeq, elemAlign: int): pointer =
-  cast[pointer](cast[ByteAddress](a) +% align(GenericSeqSize, elemAlign))
+  cast[pointer](cast[int](a) +% align(GenericSeqSize, elemAlign))
 
 proc dataPointer(a: PGenericSeq, elemAlign, elemSize, index: int): pointer =
-  cast[pointer](cast[ByteAddress](a) +% align(GenericSeqSize, elemAlign) +% (index*%elemSize))
+  cast[pointer](cast[int](a) +% align(GenericSeqSize, elemAlign) +% (index*%elemSize))
 
 proc resize(old: int): int {.inline.} =
   if old <= 0: result = 4
@@ -47,27 +47,22 @@ else:
   template allocStrNoInit(size: untyped): untyped =
     cast[NimString](newObjNoInit(addr(strDesc), size))
 
-proc rawNewStringNoInit(space: int): NimString {.compilerproc.} =
-  var s = space
-  if s < 7: s = 7
+proc rawNewStringNoInit(space: int): NimString =
+  let s = max(space, 7)
   result = allocStrNoInit(sizeof(TGenericSeq) + s + 1)
   result.reserved = s
-  result.len = 0
   when defined(gogc):
     result.elemSize = 1
 
 proc rawNewString(space: int): NimString {.compilerproc.} =
-  var s = space
-  if s < 7: s = 7
-  result = allocStr(sizeof(TGenericSeq) + s + 1)
-  result.reserved = s
+  result = rawNewStringNoInit(space)
   result.len = 0
-  when defined(gogc):
-    result.elemSize = 1
+  result.data[0] = '\0'
 
 proc mnewString(len: int): NimString {.compilerproc.} =
-  result = rawNewString(len)
+  result = rawNewStringNoInit(len)
   result.len = len
+  zeroMem(addr result.data[0], len + 1)
 
 proc copyStrLast(s: NimString, start, last: int): NimString {.compilerproc.} =
   # This is not used by most recent versions of the compiler anymore, but
@@ -75,13 +70,10 @@ proc copyStrLast(s: NimString, start, last: int): NimString {.compilerproc.} =
   let start = max(start, 0)
   if s == nil: return nil
   let len = min(last, s.len-1) - start + 1
-  if len > 0:
-    result = rawNewStringNoInit(len)
-    result.len = len
-    copyMem(addr(result.data), addr(s.data[start]), len)
-    result.data[len] = '\0'
-  else:
-    result = rawNewString(len)
+  result = rawNewStringNoInit(len)
+  result.len = len
+  copyMem(addr(result.data), addr(s.data[start]), len)
+  result.data[len] = '\0'
 
 proc copyStr(s: NimString, start: int): NimString {.compilerproc.} =
   # This is not used by most recent versions of the compiler anymore, but
@@ -96,7 +88,8 @@ proc nimToCStringConv(s: NimString): cstring {.compilerproc, nonReloadable, inli
 proc toNimStr(str: cstring, len: int): NimString {.compilerproc.} =
   result = rawNewStringNoInit(len)
   result.len = len
-  copyMem(addr(result.data), str, len + 1)
+  copyMem(addr(result.data), str, len)
+  result.data[len] = '\0'
 
 proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
   if str == nil: NimString(nil)
@@ -201,7 +194,7 @@ proc addChar(s: NimString, c: char): NimString =
 
 proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
   if dest == nil:
-    result = rawNewStringNoInit(addlen)
+    result = rawNewString(addlen)
   elif dest.len + addlen <= dest.space:
     result = dest
   else: # slow path:
@@ -227,15 +220,18 @@ proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
 proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
   let n = max(newLen, 0)
   if s == nil:
-    result = mnewString(newLen)
+    if n == 0:
+      return s
+    else:
+      result = mnewString(n)
   elif n <= s.space:
     result = s
   else:
-    let sp = max(resize(s.space), newLen)
+    let sp = max(resize(s.space), n)
     result = rawNewStringNoInit(sp)
     result.len = s.len
-    copyMem(addr result.data[0], unsafeAddr(s.data[0]), s.len+1)
-    zeroMem(addr result.data[s.len], newLen - s.len)
+    copyMem(addr result.data[0], unsafeAddr(s.data[0]), s.len)
+    zeroMem(addr result.data[s.len], n - s.len)
     result.reserved = sp
   result.len = n
   result.data[n] = '\0'
@@ -308,7 +304,10 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
     compilerRtl.} =
   sysAssert typ.kind == tySequence, "setLengthSeqV2: type is not a seq"
   if s == nil:
-    result = cast[PGenericSeq](newSeq(typ, newLen))
+    if newLen == 0:
+      result = s
+    else:
+      result = cast[PGenericSeq](newSeq(typ, newLen))
   else:
     let elemSize = typ.base.size
     let elemAlign = typ.base.align
@@ -340,3 +339,25 @@ proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
       result = s
       zeroMem(dataPointer(result, elemAlign, elemSize, result.len), (newLen-%result.len) *% elemSize)
     result.len = newLen
+
+func capacity*(self: string): int {.inline.} =
+  ## Returns the current capacity of the string.
+  # See https://github.com/nim-lang/RFCs/issues/460
+  runnableExamples:
+    var str = newStringOfCap(cap = 42)
+    str.add "Nim"
+    assert str.capacity == 42
+
+  let str = cast[NimString](self)
+  result = if str != nil: str.space else: 0
+
+func capacity*[T](self: seq[T]): int {.inline.} =
+  ## Returns the current capacity of the seq.
+  # See https://github.com/nim-lang/RFCs/issues/460
+  runnableExamples:
+    var lst = newSeqOfCap[string](cap = 42)
+    lst.add "Nim"
+    assert lst.capacity == 42
+
+  let sek = cast[PGenericSeq](self)
+  result = if sek != nil: sek.space else: 0
diff --git a/lib/system/threadimpl.nim b/lib/system/threadimpl.nim
index 94db23336..285b8f5e7 100644
--- a/lib/system/threadimpl.nim
+++ b/lib/system/threadimpl.nim
@@ -20,13 +20,8 @@ when not defined(useNimRtl):
       threadType = ThreadType.NimThread
 
 when defined(gcDestructors):
-  proc allocThreadStorage(size: int): pointer =
-    result = c_malloc(csize_t size)
-    zeroMem(result, size)
-
   proc deallocThreadStorage(p: pointer) = c_free(p)
 else:
-  template allocThreadStorage(size: untyped): untyped = allocShared0(size)
   template deallocThreadStorage(p: pointer) = deallocShared(p)
 
 template afterThreadRuns() =
diff --git a/lib/system_overview.rst b/lib/system_overview.rst
index b338845d6..cc0643bf1 100644
--- a/lib/system_overview.rst
+++ b/lib/system_overview.rst
@@ -99,6 +99,7 @@ Proc                                Usage
 ===============================     ======================================
 
 **See also:**
+* `setutils module <setutils.html>`_ for bit set convenience functions
 * `sets module <sets.html>`_ for hash sets
 * `intsets module <intsets.html>`_ for efficient int sets
 
diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim
index 93ab3dd2e..79681376b 100644
--- a/lib/windows/winlean.nim
+++ b/lib/windows/winlean.nim
@@ -10,7 +10,7 @@
 ## This module implements a small wrapper for some needed Win API procedures,
 ## so that the Nim compiler does not depend on the huge Windows module.
 
-import dynlib
+import std/dynlib
 
 when defined(nimHasStyleChecks):
   {.push styleChecks: off.}
@@ -21,13 +21,7 @@ when defined(nimPreviewSlimSystem):
   from std/syncio import FileHandle
   import std/widestrs
 
-const
-  useWinUnicode* = not defined(useWinAnsi)
-
-when useWinUnicode:
-  type WinChar* = Utf16Char
-else:
-  type WinChar* = char
+type WinChar* = Utf16Char
 
 # See https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types
 type
@@ -48,12 +42,12 @@ type
   HGLRC* = Handle
   BYTE* = uint8
 
-  SECURITY_ATTRIBUTES* {.final, pure.} = object
+  SECURITY_ATTRIBUTES* = object
     nLength*: int32
     lpSecurityDescriptor*: pointer
     bInheritHandle*: WINBOOL
 
-  STARTUPINFO* {.final, pure.} = object
+  STARTUPINFO* = object
     cb*: int32
     lpReserved*: cstring
     lpDesktop*: cstring
@@ -73,17 +67,17 @@ type
     hStdOutput*: Handle
     hStdError*: Handle
 
-  PROCESS_INFORMATION* {.final, pure.} = object
+  PROCESS_INFORMATION* = object
     hProcess*: Handle
     hThread*: Handle
     dwProcessId*: int32
     dwThreadId*: int32
 
-  FILETIME* {.final, pure.} = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
+  FILETIME* = object ## CANNOT BE int64 BECAUSE OF ALIGNMENT
     dwLowDateTime*: DWORD
     dwHighDateTime*: DWORD
 
-  BY_HANDLE_FILE_INFORMATION* {.final, pure.} = object
+  BY_HANDLE_FILE_INFORMATION* = object
     dwFileAttributes*: DWORD
     ftCreationTime*: FILETIME
     ftLastAccessTime*: FILETIME
@@ -95,7 +89,7 @@ type
     nFileIndexHigh*: DWORD
     nFileIndexLow*: DWORD
 
-  OSVERSIONINFO* {.final, pure.} = object
+  OSVERSIONINFO* = object
     dwOSVersionInfoSize*: DWORD
     dwMajorVersion*: DWORD
     dwMinorVersion*: DWORD
@@ -184,26 +178,14 @@ proc peekNamedPipe*(hNamedPipe: Handle, lpBuffer: pointer=nil,
                     lpBytesLeftThisMessage: ptr int32 = nil): bool {.
     stdcall, dynlib: "kernel32", importc: "PeekNamedPipe".}
 
-when useWinUnicode:
-  proc createProcessW*(lpApplicationName, lpCommandLine: WideCString,
-                     lpProcessAttributes: ptr SECURITY_ATTRIBUTES,
-                     lpThreadAttributes: ptr SECURITY_ATTRIBUTES,
-                     bInheritHandles: WINBOOL, dwCreationFlags: int32,
-                     lpEnvironment, lpCurrentDirectory: WideCString,
-                     lpStartupInfo: var STARTUPINFO,
-                     lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{.
-    stdcall, dynlib: "kernel32", importc: "CreateProcessW", sideEffect.}
-
-else:
-  proc createProcessA*(lpApplicationName, lpCommandLine: cstring,
-                       lpProcessAttributes: ptr SECURITY_ATTRIBUTES,
-                       lpThreadAttributes: ptr SECURITY_ATTRIBUTES,
-                       bInheritHandles: WINBOOL, dwCreationFlags: int32,
-                       lpEnvironment: pointer, lpCurrentDirectory: cstring,
-                       lpStartupInfo: var STARTUPINFO,
-                       lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{.
-      stdcall, dynlib: "kernel32", importc: "CreateProcessA", sideEffect.}
-
+proc createProcessW*(lpApplicationName, lpCommandLine: WideCString,
+                   lpProcessAttributes: ptr SECURITY_ATTRIBUTES,
+                   lpThreadAttributes: ptr SECURITY_ATTRIBUTES,
+                   bInheritHandles: WINBOOL, dwCreationFlags: int32,
+                   lpEnvironment, lpCurrentDirectory: WideCString,
+                   lpStartupInfo: var STARTUPINFO,
+                   lpProcessInformation: var PROCESS_INFORMATION): WINBOOL{.
+  stdcall, dynlib: "kernel32", importc: "CreateProcessW", sideEffect.}
 
 proc suspendThread*(hThread: Handle): int32 {.stdcall, dynlib: "kernel32",
     importc: "SuspendThread", sideEffect.}
@@ -232,67 +214,37 @@ proc getLastError*(): int32 {.importc: "GetLastError",
 proc setLastError*(error: int32) {.importc: "SetLastError",
     stdcall, dynlib: "kernel32", sideEffect.}
 
-when useWinUnicode:
-  proc formatMessageW*(dwFlags: int32, lpSource: pointer,
-                      dwMessageId, dwLanguageId: int32,
-                      lpBuffer: pointer, nSize: int32,
-                      arguments: pointer): int32 {.
-                      importc: "FormatMessageW", stdcall, dynlib: "kernel32".}
-else:
-  proc formatMessageA*(dwFlags: int32, lpSource: pointer,
+proc formatMessageW*(dwFlags: int32, lpSource: pointer,
                     dwMessageId, dwLanguageId: int32,
                     lpBuffer: pointer, nSize: int32,
                     arguments: pointer): int32 {.
-                    importc: "FormatMessageA", stdcall, dynlib: "kernel32".}
+                    importc: "FormatMessageW", stdcall, dynlib: "kernel32".}
 
 proc localFree*(p: pointer) {.
   importc: "LocalFree", stdcall, dynlib: "kernel32".}
 
-when useWinUnicode:
-  proc getCurrentDirectoryW*(nBufferLength: int32,
-                             lpBuffer: WideCString): int32 {.
-    importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
-  proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {.
-    importc: "SetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
-  proc createDirectoryW*(pathName: WideCString, security: pointer=nil): int32 {.
-    importc: "CreateDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
-  proc removeDirectoryW*(lpPathName: WideCString): int32 {.
-    importc: "RemoveDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
-  proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {.
-    stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW", sideEffect.}
-
-  proc getModuleFileNameW*(handle: Handle, buf: WideCString,
-                           size: int32): int32 {.importc: "GetModuleFileNameW",
-    dynlib: "kernel32", stdcall.}
-else:
-  proc getCurrentDirectoryA*(nBufferLength: int32, lpBuffer: cstring): int32 {.
-    importc: "GetCurrentDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
-  proc setCurrentDirectoryA*(lpPathName: cstring): int32 {.
-    importc: "SetCurrentDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
-  proc createDirectoryA*(pathName: cstring, security: pointer=nil): int32 {.
-    importc: "CreateDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
-  proc removeDirectoryA*(lpPathName: cstring): int32 {.
-    importc: "RemoveDirectoryA", dynlib: "kernel32", stdcall, sideEffect.}
-  proc setEnvironmentVariableA*(lpName, lpValue: cstring): int32 {.
-    stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableA", sideEffect.}
-
-  proc getModuleFileNameA*(handle: Handle, buf: cstring, size: int32): int32 {.
-    importc: "GetModuleFileNameA", dynlib: "kernel32", stdcall.}
-
-when useWinUnicode:
-  proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString,
-                         flags: DWORD): int32 {.
-    importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall, sideEffect.}
-  proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString,
-                         security: pointer=nil): int32 {.
-    importc:"CreateHardLinkW", dynlib: "kernel32", stdcall, sideEffect.}
-else:
-  proc createSymbolicLinkA*(lpSymlinkFileName, lpTargetFileName: cstring,
-                           flags: DWORD): int32 {.
-    importc:"CreateSymbolicLinkA", dynlib: "kernel32", stdcall, sideEffect.}
-  proc createHardLinkA*(lpFileName, lpExistingFileName: cstring,
-                           security: pointer=nil): int32 {.
-    importc:"CreateHardLinkA", dynlib: "kernel32", stdcall, sideEffect.}
+proc getCurrentDirectoryW*(nBufferLength: int32,
+                           lpBuffer: WideCString): int32 {.
+  importc: "GetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
+proc setCurrentDirectoryW*(lpPathName: WideCString): int32 {.
+  importc: "SetCurrentDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
+proc createDirectoryW*(pathName: WideCString, security: pointer=nil): int32 {.
+  importc: "CreateDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
+proc removeDirectoryW*(lpPathName: WideCString): int32 {.
+  importc: "RemoveDirectoryW", dynlib: "kernel32", stdcall, sideEffect.}
+proc setEnvironmentVariableW*(lpName, lpValue: WideCString): int32 {.
+  stdcall, dynlib: "kernel32", importc: "SetEnvironmentVariableW", sideEffect.}
+
+proc getModuleFileNameW*(handle: Handle, buf: WideCString,
+                         size: int32): int32 {.importc: "GetModuleFileNameW",
+  dynlib: "kernel32", stdcall.}
+
+proc createSymbolicLinkW*(lpSymlinkFileName, lpTargetFileName: WideCString,
+                       flags: DWORD): int32 {.
+  importc:"CreateSymbolicLinkW", dynlib: "kernel32", stdcall, sideEffect.}
+proc createHardLinkW*(lpFileName, lpExistingFileName: WideCString,
+                       security: pointer=nil): int32 {.
+  importc:"CreateHardLinkW", dynlib: "kernel32", stdcall, sideEffect.}
 
 const
   FILE_ATTRIBUTE_READONLY* = 0x00000001'i32
@@ -343,84 +295,45 @@ type
     cFileName*: array[0..(MAX_PATH) - 1, WinChar]
     cAlternateFileName*: array[0..13, WinChar]
 
-when useWinUnicode:
-  proc findFirstFileW*(lpFileName: WideCString,
-                      lpFindFileData: var WIN32_FIND_DATA): Handle {.
-      stdcall, dynlib: "kernel32", importc: "FindFirstFileW", sideEffect.}
-  proc findNextFileW*(hFindFile: Handle,
-                     lpFindFileData: var WIN32_FIND_DATA): int32 {.
-      stdcall, dynlib: "kernel32", importc: "FindNextFileW", sideEffect.}
-else:
-  proc findFirstFileA*(lpFileName: cstring,
-                      lpFindFileData: var WIN32_FIND_DATA): Handle {.
-      stdcall, dynlib: "kernel32", importc: "FindFirstFileA", sideEffect.}
-  proc findNextFileA*(hFindFile: Handle,
-                     lpFindFileData: var WIN32_FIND_DATA): int32 {.
-      stdcall, dynlib: "kernel32", importc: "FindNextFileA", sideEffect.}
+proc findFirstFileW*(lpFileName: WideCString,
+                    lpFindFileData: var WIN32_FIND_DATA): Handle {.
+    stdcall, dynlib: "kernel32", importc: "FindFirstFileW", sideEffect.}
+proc findNextFileW*(hFindFile: Handle,
+                   lpFindFileData: var WIN32_FIND_DATA): int32 {.
+    stdcall, dynlib: "kernel32", importc: "FindNextFileW", sideEffect.}
 
 proc findClose*(hFindFile: Handle) {.stdcall, dynlib: "kernel32",
   importc: "FindClose".}
 
-when useWinUnicode:
-  proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32,
-                        lpBuffer: WideCString,
-                        lpFilePart: var WideCString): int32 {.
+proc getFullPathNameW*(lpFileName: WideCString, nBufferLength: int32,
+                      lpBuffer: WideCString,
+                      lpFilePart: var WideCString): int32 {.
+                      stdcall, dynlib: "kernel32",
+                      importc: "GetFullPathNameW", sideEffect.}
+proc getFileAttributesW*(lpFileName: WideCString): int32 {.
                         stdcall, dynlib: "kernel32",
-                        importc: "GetFullPathNameW", sideEffect.}
-  proc getFileAttributesW*(lpFileName: WideCString): int32 {.
-                          stdcall, dynlib: "kernel32",
-                          importc: "GetFileAttributesW", sideEffect.}
-  proc setFileAttributesW*(lpFileName: WideCString,
-                           dwFileAttributes: int32): WINBOOL {.
-      stdcall, dynlib: "kernel32", importc: "SetFileAttributesW", sideEffect.}
-
-  proc copyFileW*(lpExistingFileName, lpNewFileName: WideCString,
-                 bFailIfExists: WINBOOL): WINBOOL {.
-    importc: "CopyFileW", stdcall, dynlib: "kernel32", sideEffect.}
-
-  proc moveFileW*(lpExistingFileName, lpNewFileName: WideCString): WINBOOL {.
-    importc: "MoveFileW", stdcall, dynlib: "kernel32", sideEffect.}
-  proc moveFileExW*(lpExistingFileName, lpNewFileName: WideCString,
-                    flags: DWORD): WINBOOL {.
-    importc: "MoveFileExW", stdcall, dynlib: "kernel32", sideEffect.}
-
-  proc getEnvironmentStringsW*(): WideCString {.
-    stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW", sideEffect.}
-  proc freeEnvironmentStringsW*(para1: WideCString): int32 {.
-    stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsW", sideEffect.}
-
-  proc getCommandLineW*(): WideCString {.importc: "GetCommandLineW",
-    stdcall, dynlib: "kernel32", sideEffect.}
+                        importc: "GetFileAttributesW", sideEffect.}
+proc setFileAttributesW*(lpFileName: WideCString,
+                         dwFileAttributes: int32): WINBOOL {.
+    stdcall, dynlib: "kernel32", importc: "SetFileAttributesW", sideEffect.}
 
-else:
-  proc getFullPathNameA*(lpFileName: cstring, nBufferLength: int32,
-                        lpBuffer: cstring, lpFilePart: var cstring): int32 {.
-                        stdcall, dynlib: "kernel32",
-                        importc: "GetFullPathNameA", sideEffect.}
-  proc getFileAttributesA*(lpFileName: cstring): int32 {.
-                          stdcall, dynlib: "kernel32",
-                          importc: "GetFileAttributesA", sideEffect.}
-  proc setFileAttributesA*(lpFileName: cstring,
-                           dwFileAttributes: int32): WINBOOL {.
-      stdcall, dynlib: "kernel32", importc: "SetFileAttributesA", sideEffect.}
-
-  proc copyFileA*(lpExistingFileName, lpNewFileName: cstring,
-                 bFailIfExists: cint): cint {.
-    importc: "CopyFileA", stdcall, dynlib: "kernel32", sideEffect.}
-
-  proc moveFileA*(lpExistingFileName, lpNewFileName: cstring): WINBOOL {.
-    importc: "MoveFileA", stdcall, dynlib: "kernel32", sideEffect.}
-  proc moveFileExA*(lpExistingFileName, lpNewFileName: cstring,
-                    flags: DWORD): WINBOOL {.
-    importc: "MoveFileExA", stdcall, dynlib: "kernel32", sideEffect.}
-
-  proc getEnvironmentStringsA*(): cstring {.
-    stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsA", sideEffect.}
-  proc freeEnvironmentStringsA*(para1: cstring): int32 {.
-    stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsA", sideEffect.}
-
-  proc getCommandLineA*(): cstring {.
-    importc: "GetCommandLineA", stdcall, dynlib: "kernel32", sideEffect.}
+proc copyFileW*(lpExistingFileName, lpNewFileName: WideCString,
+               bFailIfExists: WINBOOL): WINBOOL {.
+  importc: "CopyFileW", stdcall, dynlib: "kernel32", sideEffect.}
+
+proc moveFileW*(lpExistingFileName, lpNewFileName: WideCString): WINBOOL {.
+  importc: "MoveFileW", stdcall, dynlib: "kernel32", sideEffect.}
+proc moveFileExW*(lpExistingFileName, lpNewFileName: WideCString,
+                  flags: DWORD): WINBOOL {.
+  importc: "MoveFileExW", stdcall, dynlib: "kernel32", sideEffect.}
+
+proc getEnvironmentStringsW*(): WideCString {.
+  stdcall, dynlib: "kernel32", importc: "GetEnvironmentStringsW", sideEffect.}
+proc freeEnvironmentStringsW*(para1: WideCString): int32 {.
+  stdcall, dynlib: "kernel32", importc: "FreeEnvironmentStringsW", sideEffect.}
+
+proc getCommandLineW*(): WideCString {.importc: "GetCommandLineW",
+  stdcall, dynlib: "kernel32", sideEffect.}
 
 proc rdFileTime*(f: FILETIME): int64 =
   result = int64(cast[uint32](f.dwLowDateTime)) or (int64(cast[uint32](f.dwHighDateTime)) shl 32)
@@ -434,17 +347,10 @@ proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var FILETIME) {.
 proc sleep*(dwMilliseconds: int32){.stdcall, dynlib: "kernel32",
                                     importc: "Sleep", sideEffect.}
 
-when useWinUnicode:
-  proc shellExecuteW*(hwnd: Handle, lpOperation, lpFile,
-                     lpParameters, lpDirectory: WideCString,
-                     nShowCmd: int32): Handle{.
-      stdcall, dynlib: "shell32.dll", importc: "ShellExecuteW", sideEffect.}
-
-else:
-  proc shellExecuteA*(hwnd: Handle, lpOperation, lpFile,
-                     lpParameters, lpDirectory: cstring,
-                     nShowCmd: int32): Handle{.
-      stdcall, dynlib: "shell32.dll", importc: "ShellExecuteA", sideEffect.}
+proc shellExecuteW*(hwnd: Handle, lpOperation, lpFile,
+                   lpParameters, lpDirectory: WideCString,
+                   nShowCmd: int32): Handle{.
+    stdcall, dynlib: "shell32.dll", importc: "ShellExecuteW", sideEffect.}
 
 proc getFileInformationByHandle*(hFile: Handle,
   lpFileInformation: ptr BY_HANDLE_FILE_INFORMATION): WINBOOL{.
@@ -794,13 +700,6 @@ proc createFileMappingW*(hFile: Handle,
                        lpName: pointer): Handle {.
   stdcall, dynlib: "kernel32", importc: "CreateFileMappingW".}
 
-when not useWinUnicode:
-  proc createFileMappingA*(hFile: Handle,
-                           lpFileMappingAttributes: pointer,
-                           flProtect, dwMaximumSizeHigh: DWORD,
-                           dwMaximumSizeLow: DWORD, lpName: cstring): Handle {.
-      stdcall, dynlib: "kernel32", importc: "CreateFileMappingA".}
-
 proc unmapViewOfFile*(lpBaseAddress: pointer): WINBOOL {.stdcall,
     dynlib: "kernel32", importc: "UnmapViewOfFile".}
 
@@ -820,7 +719,7 @@ type
   POVERLAPPED_COMPLETION_ROUTINE* = proc (para1: DWORD, para2: DWORD,
       para3: POVERLAPPED){.stdcall.}
 
-  GUID* {.final, pure.} = object
+  GUID* = object
     D1*: int32
     D2*: int16
     D3*: int16
@@ -976,7 +875,7 @@ proc inet_ntop*(family: cint, paddr: pointer, pStringBuffer: cstring,
                   stringBufSize: int32): cstring {.stdcall.} =
   var ver: OSVERSIONINFO
   ver.dwOSVersionInfoSize = sizeof(ver).DWORD
-  let res = when useWinUnicode: getVersionExW(ver.addr) else: getVersionExA(ver.addr)
+  let res = getVersionExW(ver.addr)
   if res == 0:
     result = nil
   elif ver.dwMajorVersion >= 6:
@@ -1060,16 +959,10 @@ proc openProcess*(dwDesiredAccess: DWORD, bInheritHandle: WINBOOL,
                     dwProcessId: DWORD): Handle
      {.stdcall, dynlib: "kernel32", importc: "OpenProcess".}
 
-when defined(useWinAnsi):
-  proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES,
-                    bManualReset: DWORD, bInitialState: DWORD,
-                    lpName: cstring): Handle
-       {.stdcall, dynlib: "kernel32", importc: "CreateEventA".}
-else:
-  proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES,
-                    bManualReset: DWORD, bInitialState: DWORD,
-                    lpName: ptr Utf16Char): Handle
-       {.stdcall, dynlib: "kernel32", importc: "CreateEventW".}
+proc createEvent*(lpEventAttributes: ptr SECURITY_ATTRIBUTES,
+                  bManualReset: DWORD, bInitialState: DWORD,
+                  lpName: ptr Utf16Char): Handle
+     {.stdcall, dynlib: "kernel32", importc: "CreateEventW".}
 
 proc setEvent*(hEvent: Handle): cint
      {.stdcall, dynlib: "kernel32", importc: "SetEvent".}
@@ -1101,7 +994,7 @@ proc wsaResetEvent*(hEvent: Handle): bool
      {.stdcall, importc: "WSAResetEvent", dynlib: "ws2_32.dll".}
 
 type
-  KEY_EVENT_RECORD* {.final, pure.} = object
+  KEY_EVENT_RECORD* = object
     eventType*: int16
     bKeyDown*: WINBOOL
     wRepeatCount*: int16
@@ -1110,14 +1003,9 @@ type
     uChar*: int16
     dwControlKeyState*: DWORD
 
-when defined(useWinAnsi):
-  proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
-                        lpNumberOfEventsRead: ptr cint): cint
-       {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputA".}
-else:
-  proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
-                        lpNumberOfEventsRead: ptr cint): cint
-       {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
+proc readConsoleInput*(hConsoleInput: Handle, lpBuffer: pointer, nLength: cint,
+                      lpNumberOfEventsRead: ptr cint): cint
+     {.stdcall, dynlib: "kernel32", importc: "ReadConsoleInputW".}
 
 type
   LPFIBER_START_ROUTINE* = proc (param: pointer) {.stdcall.}
diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim
deleted file mode 100644
index 2fefe4a8b..000000000
--- a/lib/wrappers/mysql.nim
+++ /dev/null
@@ -1,1115 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2010 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-{.push, callconv: cdecl.}
-when defined(nimHasStyleChecks):
-  {.push styleChecks: off.}
-
-when defined(unix):
-  when defined(macosx):
-    const
-      lib = "(libmysqlclient|libmariadbclient)(|.20|.19|.18|.17|.16|.15).dylib"
-  else:
-    const
-      lib = "(libmysqlclient|libmariadbclient).so(|.20|.19|.18|.17|.16|.15)"
-when defined(windows):
-  const
-    lib = "(libmysql.dll|libmariadb.dll)"
-type
-  my_bool* = bool
-  Pmy_bool* = ptr my_bool
-  PVIO* = pointer
-  Pgptr* = ptr gptr
-  gptr* = cstring
-  Pmy_socket* = ptr my_socket
-  my_socket* = cint
-  PPByte* = pointer
-  cuint* = cint
-
-#  ------------ Start of declaration in "mysql_com.h"   ---------------------
-#
-#  ** Common definition between mysql server & client
-#
-# Field/table name length
-
-const
-  NAME_LEN* = 64
-  HOSTNAME_LENGTH* = 60
-  USERNAME_LENGTH* = 16
-  SERVER_VERSION_LENGTH* = 60
-  SQLSTATE_LENGTH* = 5
-  LOCAL_HOST* = "localhost"
-  LOCAL_HOST_NAMEDPIPE* = '.'
-
-const
-  NAMEDPIPE* = "MySQL"
-  SERVICENAME* = "MySQL"
-
-type
-  Enum_server_command* = enum
-    COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST, COM_CREATE_DB,
-    COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS, COM_PROCESS_INFO,
-    COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING, COM_TIME,
-    COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, COM_TABLE_DUMP,
-    COM_CONNECT_OUT, COM_REGISTER_SLAVE, COM_STMT_PREPARE, COM_STMT_EXECUTE,
-    COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE, COM_STMT_RESET, COM_SET_OPTION,
-    COM_STMT_FETCH, COM_END
-{.deprecated: [Tenum_server_command: Enum_server_command].}
-
-const
-  SCRAMBLE_LENGTH* = 20 # Length of random string sent by server on handshake;
-                        # this is also length of obfuscated password,
-                        # received from client
-  SCRAMBLE_LENGTH_323* = 8    # length of password stored in the db:
-                              # new passwords are preceded with '*'
-  SCRAMBLED_PASSWORD_CHAR_LENGTH* = SCRAMBLE_LENGTH * 2 + 1
-  SCRAMBLED_PASSWORD_CHAR_LENGTH_323* = SCRAMBLE_LENGTH_323 * 2
-  NOT_NULL_FLAG* = 1          #  Field can't be NULL
-  PRI_KEY_FLAG* = 2           #  Field is part of a primary key
-  UNIQUE_KEY_FLAG* = 4        #  Field is part of a unique key
-  MULTIPLE_KEY_FLAG* = 8      #  Field is part of a key
-  BLOB_FLAG* = 16             #  Field is a blob
-  UNSIGNED_FLAG* = 32         #  Field is unsigned
-  ZEROFILL_FLAG* = 64         #  Field is zerofill
-  BINARY_FLAG* = 128          #  Field is binary
-                              # The following are only sent to new clients
-  ENUM_FLAG* = 256            # field is an enum
-  AUTO_INCREMENT_FLAG* = 512  # field is a autoincrement field
-  TIMESTAMP_FLAG* = 1024      # Field is a timestamp
-  SET_FLAG* = 2048            # field is a set
-  NO_DEFAULT_VALUE_FLAG* = 4096 # Field doesn't have default value
-  NUM_FLAG* = 32768           # Field is num (for clients)
-  PART_KEY_FLAG* = 16384      # Intern; Part of some key
-  GROUP_FLAG* = 32768         # Intern: Group field
-  UNIQUE_FLAG* = 65536        # Intern: Used by sql_yacc
-  BINCMP_FLAG* = 131072       # Intern: Used by sql_yacc
-  REFRESH_GRANT* = 1          # Refresh grant tables
-  REFRESH_LOG* = 2            # Start on new log file
-  REFRESH_TABLES* = 4         # close all tables
-  REFRESH_HOSTS* = 8          # Flush host cache
-  REFRESH_STATUS* = 16        # Flush status variables
-  REFRESH_THREADS* = 32       # Flush thread cache
-  REFRESH_SLAVE* = 64         # Reset master info and restart slave thread
-  REFRESH_MASTER* = 128 # Remove all bin logs in the index and truncate the index
-                        # The following can't be set with mysql_refresh()
-  REFRESH_READ_LOCK* = 16384  # Lock tables for read
-  REFRESH_FAST* = 32768       # Intern flag
-  REFRESH_QUERY_CACHE* = 65536 # RESET (remove all queries) from query cache
-  REFRESH_QUERY_CACHE_FREE* = 0x00020000 # pack query cache
-  REFRESH_DES_KEY_FILE* = 0x00040000
-  REFRESH_USER_RESOURCES* = 0x00080000
-  CLIENT_LONG_PASSWORD* = 1   # new more secure passwords
-  CLIENT_FOUND_ROWS* = 2      # Found instead of affected rows
-  CLIENT_LONG_FLAG* = 4       # Get all column flags
-  CLIENT_CONNECT_WITH_DB* = 8 # One can specify db on connect
-  CLIENT_NO_SCHEMA* = 16      # Don't allow database.table.column
-  CLIENT_COMPRESS* = 32       # Can use compression protocol
-  CLIENT_ODBC* = 64           # Odbc client
-  CLIENT_LOCAL_FILES* = 128   # Can use LOAD DATA LOCAL
-  CLIENT_IGNORE_SPACE* = 256  # Ignore spaces before '('
-  CLIENT_PROTOCOL_41* = 512   # New 4.1 protocol
-  CLIENT_INTERACTIVE* = 1024  # This is an interactive client
-  CLIENT_SSL* = 2048          # Switch to SSL after handshake
-  CLIENT_IGNORE_SIGPIPE* = 4096 # IGNORE sigpipes
-  CLIENT_TRANSACTIONS* = 8192 # Client knows about transactions
-  CLIENT_RESERVED* = 16384    # Old flag for 4.1 protocol
-  CLIENT_SECURE_CONNECTION* = 32768 # New 4.1 authentication
-  CLIENT_MULTI_STATEMENTS* = 65536 # Enable/disable multi-stmt support
-  CLIENT_MULTI_RESULTS* = 131072 # Enable/disable multi-results
-  CLIENT_REMEMBER_OPTIONS*: int = 1 shl 31
-  SERVER_STATUS_IN_TRANS* = 1 # Transaction has started
-  SERVER_STATUS_AUTOCOMMIT* = 2 # Server in auto_commit mode
-  SERVER_STATUS_MORE_RESULTS* = 4 # More results on server
-  SERVER_MORE_RESULTS_EXISTS* = 8 # Multi query - next query exists
-  SERVER_QUERY_NO_GOOD_INDEX_USED* = 16
-  SERVER_QUERY_NO_INDEX_USED* = 32 # The server was able to fulfill the clients request and opened a
-                                   #      read-only non-scrollable cursor for a query. This flag comes
-                                   #      in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands.
-  SERVER_STATUS_CURSOR_EXISTS* = 64 # This flag is sent when a read-only cursor is exhausted, in reply to
-                                    #      COM_STMT_FETCH command.
-  SERVER_STATUS_LAST_ROW_SENT* = 128
-  SERVER_STATUS_DB_DROPPED* = 256 # A database was dropped
-  SERVER_STATUS_NO_BACKSLASH_ESCAPES* = 512
-  ERRMSG_SIZE* = 200
-  NET_READ_TIMEOUT* = 30      # Timeout on read
-  NET_WRITE_TIMEOUT* = 60     # Timeout on write
-  NET_WAIT_TIMEOUT* = 8 * 60 * 60 # Wait for new query
-  ONLY_KILL_QUERY* = 1
-
-const
-  MAX_TINYINT_WIDTH* = 3      # Max width for a TINY w.o. sign
-  MAX_SMALLINT_WIDTH* = 5     # Max width for a SHORT w.o. sign
-  MAX_MEDIUMINT_WIDTH* = 8    # Max width for a INT24 w.o. sign
-  MAX_INT_WIDTH* = 10         # Max width for a LONG w.o. sign
-  MAX_BIGINT_WIDTH* = 20      # Max width for a LONGLONG
-  MAX_CHAR_WIDTH* = 255       # Max length for a CHAR column
-  MAX_BLOB_WIDTH* = 8192      # Default width for blob
-
-type
-  Pst_net* = ptr St_net
-  St_net*{.final.} = object
-    vio*: PVIO
-    buff*: cstring
-    buff_end*: cstring
-    write_pos*: cstring
-    read_pos*: cstring
-    fd*: my_socket            # For Perl DBI/dbd
-    max_packet*: int
-    max_packet_size*: int
-    pkt_nr*: cuint
-    compress_pkt_nr*: cuint
-    write_timeout*: cuint
-    read_timeout*: cuint
-    retry_count*: cuint
-    fcntl*: cint
-    compress*: my_bool #   The following variable is set if we are doing several queries in one
-                       #        command ( as in LOAD TABLE ... FROM MASTER ),
-                       #        and do not want to confuse the client with OK at the wrong time
-    remain_in_buf*: int
-    len*: int
-    buf_length*: int
-    where_b*: int
-    return_status*: ptr cint
-    reading_or_writing*: char
-    save_char*: cchar
-    no_send_ok*: my_bool      # For SPs and other things that do multiple stmts
-    no_send_eof*: my_bool     # For SPs' first version read-only cursors
-    no_send_error*: my_bool # Set if OK packet is already sent, and
-                            # we do not need to send error messages
-                            #   Pointer to query object in query cache, do not equal NULL (0) for
-                            #        queries in cache that have not stored its results yet
-                            # $endif
-    last_error*: array[0..(ERRMSG_SIZE) - 1, char]
-    sqlstate*: array[0..(SQLSTATE_LENGTH + 1) - 1, char]
-    last_errno*: cuint
-    error*: char
-    query_cache_query*: gptr
-    report_error*: my_bool    # We should report error (we have unreported error)
-    return_errno*: my_bool
-
-  NET* = St_net
-  PNET* = ptr NET
-{.deprecated: [Tst_net: St_net, TNET: NET].}
-
-const
-  packet_error* = - 1
-
-type
-  Enum_field_types* = enum    # For backward compatibility
-    TYPE_DECIMAL, TYPE_TINY, TYPE_SHORT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE,
-    TYPE_NULL, TYPE_TIMESTAMP, TYPE_LONGLONG, TYPE_INT24, TYPE_DATE, TYPE_TIME,
-    TYPE_DATETIME, TYPE_YEAR, TYPE_NEWDATE, TYPE_VARCHAR, TYPE_BIT,
-    TYPE_NEWDECIMAL = 246, TYPE_ENUM = 247, TYPE_SET = 248,
-    TYPE_TINY_BLOB = 249, TYPE_MEDIUM_BLOB = 250, TYPE_LONG_BLOB = 251,
-    TYPE_BLOB = 252, TYPE_VAR_STRING = 253, TYPE_STRING = 254,
-    TYPE_GEOMETRY = 255
-{.deprecated: [Tenum_field_types: Enum_field_types].}
-
-const
-  CLIENT_MULTI_QUERIES* = CLIENT_MULTI_STATEMENTS
-  FIELD_TYPE_DECIMAL* = TYPE_DECIMAL
-  FIELD_TYPE_NEWDECIMAL* = TYPE_NEWDECIMAL
-  FIELD_TYPE_TINY* = TYPE_TINY
-  FIELD_TYPE_SHORT* = TYPE_SHORT
-  FIELD_TYPE_LONG* = TYPE_LONG
-  FIELD_TYPE_FLOAT* = TYPE_FLOAT
-  FIELD_TYPE_DOUBLE* = TYPE_DOUBLE
-  FIELD_TYPE_NULL* = TYPE_NULL
-  FIELD_TYPE_TIMESTAMP* = TYPE_TIMESTAMP
-  FIELD_TYPE_LONGLONG* = TYPE_LONGLONG
-  FIELD_TYPE_INT24* = TYPE_INT24
-  FIELD_TYPE_DATE* = TYPE_DATE
-  FIELD_TYPE_TIME* = TYPE_TIME
-  FIELD_TYPE_DATETIME* = TYPE_DATETIME
-  FIELD_TYPE_YEAR* = TYPE_YEAR
-  FIELD_TYPE_NEWDATE* = TYPE_NEWDATE
-  FIELD_TYPE_ENUM* = TYPE_ENUM
-  FIELD_TYPE_SET* = TYPE_SET
-  FIELD_TYPE_TINY_BLOB* = TYPE_TINY_BLOB
-  FIELD_TYPE_MEDIUM_BLOB* = TYPE_MEDIUM_BLOB
-  FIELD_TYPE_LONG_BLOB* = TYPE_LONG_BLOB
-  FIELD_TYPE_BLOB* = TYPE_BLOB
-  FIELD_TYPE_VAR_STRING* = TYPE_VAR_STRING
-  FIELD_TYPE_STRING* = TYPE_STRING
-  FIELD_TYPE_CHAR* = TYPE_TINY
-  FIELD_TYPE_INTERVAL* = TYPE_ENUM
-  FIELD_TYPE_GEOMETRY* = TYPE_GEOMETRY
-  FIELD_TYPE_BIT* = TYPE_BIT  # Shutdown/kill enums and constants
-                              # Bits for THD::killable.
-  SHUTDOWN_KILLABLE_CONNECT* = chr(1 shl 0)
-  SHUTDOWN_KILLABLE_TRANS* = chr(1 shl 1)
-  SHUTDOWN_KILLABLE_LOCK_TABLE* = chr(1 shl 2)
-  SHUTDOWN_KILLABLE_UPDATE* = chr(1 shl 3)
-
-type
-  Enum_shutdown_level* = enum
-    SHUTDOWN_DEFAULT = 0, SHUTDOWN_WAIT_CONNECTIONS = 1,
-    SHUTDOWN_WAIT_TRANSACTIONS = 2, SHUTDOWN_WAIT_UPDATES = 8,
-    SHUTDOWN_WAIT_ALL_BUFFERS = 16, SHUTDOWN_WAIT_CRITICAL_BUFFERS = 17,
-    KILL_QUERY = 254, KILL_CONNECTION = 255
-  Enum_cursor_type* = enum    # options for mysql_set_option
-    CURSOR_TYPE_NO_CURSOR = 0, CURSOR_TYPE_READ_ONLY = 1,
-    CURSOR_TYPE_FOR_UPDATE = 2, CURSOR_TYPE_SCROLLABLE = 4
-  Enum_mysql_set_option* = enum
-    OPTION_MULTI_STATEMENTS_ON, OPTION_MULTI_STATEMENTS_OFF
-{.deprecated: [Tenum_shutdown_level: Enum_shutdown_level,
-              Tenum_cursor_type: Enum_cursor_type,
-              Tenum_mysql_set_option: Enum_mysql_set_option].}
-
-proc my_net_init*(net: PNET, vio: PVIO): my_bool{.cdecl, dynlib: lib,
-    importc: "my_net_init".}
-proc my_net_local_init*(net: PNET){.cdecl, dynlib: lib,
-                                    importc: "my_net_local_init".}
-proc net_end*(net: PNET){.cdecl, dynlib: lib, importc: "net_end".}
-proc net_clear*(net: PNET){.cdecl, dynlib: lib, importc: "net_clear".}
-proc net_realloc*(net: PNET, len: int): my_bool{.cdecl, dynlib: lib,
-    importc: "net_realloc".}
-proc net_flush*(net: PNET): my_bool{.cdecl, dynlib: lib, importc: "net_flush".}
-proc my_net_write*(net: PNET, packet: cstring, length: int): my_bool{.cdecl,
-    dynlib: lib, importc: "my_net_write".}
-proc net_write_command*(net: PNET, command: char, header: cstring,
-                        head_len: int, packet: cstring, length: int): my_bool{.
-    cdecl, dynlib: lib, importc: "net_write_command".}
-proc net_real_write*(net: PNET, packet: cstring, length: int): cint{.cdecl,
-    dynlib: lib, importc: "net_real_write".}
-proc my_net_read*(net: PNET): int{.cdecl, dynlib: lib, importc: "my_net_read".}
-  # The following function is not meant for normal usage
-  #      Currently it's used internally by manager.c
-type
-  Psockaddr* = ptr Sockaddr
-  Sockaddr*{.final.} = object  # undefined structure
-{.deprecated: [Tsockaddr: Sockaddr].}
-
-proc my_connect*(s: my_socket, name: Psockaddr, namelen: cuint, timeout: cuint): cint{.
-    cdecl, dynlib: lib, importc: "my_connect".}
-type
-  Prand_struct* = ptr Rand_struct
-  Rand_struct*{.final.} = object # The following is for user defined functions
-    seed1*: int
-    seed2*: int
-    max_value*: int
-    max_value_dbl*: cdouble
-
-  Item_result* = enum
-    STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT
-  PItem_result* = ptr Item_result
-  Pst_udf_args* = ptr St_udf_args
-  St_udf_args*{.final.} = object
-    arg_count*: cuint         # Number of arguments
-    arg_type*: PItem_result   # Pointer to item_results
-    args*: cstringArray       # Pointer to item_results
-    lengths*: ptr int         # Length of string arguments
-    maybe_null*: cstring      # Length of string arguments
-    attributes*: cstringArray # Pointer to attribute name
-    attribute_lengths*: ptr int # Length of attribute arguments
-
-  UDF_ARGS* = St_udf_args
-  PUDF_ARGS* = ptr UDF_ARGS   # This holds information about the result
-  Pst_udf_init* = ptr St_udf_init
-  St_udf_init*{.final.} = object
-    maybe_null*: my_bool      # 1 if function can return NULL
-    decimals*: cuint          # for real functions
-    max_length*: int          # For string functions
-    theptr*: cstring          # free pointer for function data
-    const_item*: my_bool      # free pointer for function data
-
-  UDF_INIT* = St_udf_init
-  PUDF_INIT* = ptr UDF_INIT   # Constants when using compression
-{.deprecated: [Trand_stuct: Rand_struct, TItem_result: Item_result,
-              Tst_udf_args: St_udf_args, TUDF_ARGS: UDF_ARGS,
-              Tst_udf_init: St_udf_init, TUDF_INIT: UDF_INIT].}
-
-const
-  NET_HEADER_SIZE* = 4        # standard header size
-  COMP_HEADER_SIZE* = 3 # compression header extra size
-                        # Prototypes to password functions
-                        # These functions are used for authentication by client and server and
-                        #      implemented in sql/password.c
-
-proc randominit*(para1: Prand_struct, seed1: int, seed2: int){.cdecl,
-    dynlib: lib, importc: "randominit".}
-proc my_rnd*(para1: Prand_struct): cdouble{.cdecl, dynlib: lib,
-    importc: "my_rnd".}
-proc create_random_string*(fto: cstring, len: cuint, rand_st: Prand_struct){.
-    cdecl, dynlib: lib, importc: "create_random_string".}
-proc hash_password*(fto: int, password: cstring, password_len: cuint){.cdecl,
-    dynlib: lib, importc: "hash_password".}
-proc make_scrambled_password_323*(fto: cstring, password: cstring){.cdecl,
-    dynlib: lib, importc: "make_scrambled_password_323".}
-proc scramble_323*(fto: cstring, message: cstring, password: cstring){.cdecl,
-    dynlib: lib, importc: "scramble_323".}
-proc check_scramble_323*(para1: cstring, message: cstring, salt: int): my_bool{.
-    cdecl, dynlib: lib, importc: "check_scramble_323".}
-proc get_salt_from_password_323*(res: ptr int, password: cstring){.cdecl,
-    dynlib: lib, importc: "get_salt_from_password_323".}
-proc make_password_from_salt_323*(fto: cstring, salt: ptr int){.cdecl,
-    dynlib: lib, importc: "make_password_from_salt_323".}
-proc octet2hex*(fto: cstring, str: cstring, length: cuint): cstring{.cdecl,
-    dynlib: lib, importc: "octet2hex".}
-proc make_scrambled_password*(fto: cstring, password: cstring){.cdecl,
-    dynlib: lib, importc: "make_scrambled_password".}
-proc scramble*(fto: cstring, message: cstring, password: cstring){.cdecl,
-    dynlib: lib, importc: "scramble".}
-proc check_scramble*(reply: cstring, message: cstring, hash_stage2: pointer): my_bool{.
-    cdecl, dynlib: lib, importc: "check_scramble".}
-proc get_salt_from_password*(res: pointer, password: cstring){.cdecl,
-    dynlib: lib, importc: "get_salt_from_password".}
-proc make_password_from_salt*(fto: cstring, hash_stage2: pointer){.cdecl,
-    dynlib: lib, importc: "make_password_from_salt".}
-  # end of password.c
-proc get_tty_password*(opt_message: cstring): cstring{.cdecl, dynlib: lib,
-    importc: "get_tty_password".}
-proc errno_to_sqlstate*(errno: cuint): cstring{.cdecl, dynlib: lib,
-    importc: "mysql_errno_to_sqlstate".}
-  # Some other useful functions
-proc modify_defaults_file*(file_location: cstring, option: cstring,
-                           option_value: cstring, section_name: cstring,
-                           remove_option: cint): cint{.cdecl, dynlib: lib,
-    importc: "load_defaults".}
-proc load_defaults*(conf_file: cstring, groups: cstringArray, argc: ptr cint,
-                    argv: ptr cstringArray): cint{.cdecl, dynlib: lib,
-    importc: "load_defaults".}
-proc my_init*(): my_bool{.cdecl, dynlib: lib, importc: "my_init".}
-proc my_thread_init*(): my_bool{.cdecl, dynlib: lib, importc: "my_thread_init".}
-proc my_thread_end*(){.cdecl, dynlib: lib, importc: "my_thread_end".}
-const
-  NULL_LENGTH*: int = int(not (0)) # For net_store_length
-
-const
-  STMT_HEADER* = 4
-  LONG_DATA_HEADER* = 6 #  ------------ Stop of declaration in "mysql_com.h"   -----------------------
-                        # $include "mysql_time.h"
-                        # $include "mysql_version.h"
-                        # $include "typelib.h"
-                        # $include "my_list.h" /* for LISTs used in 'MYSQL' and 'MYSQL_STMT' */
-                        #      var
-                        #         mysql_port : cuint;cvar;external;
-                        #         mysql_unix_port : Pchar;cvar;external;
-
-const
-  CLIENT_NET_READ_TIMEOUT* = 365 * 24 * 3600 # Timeout on read
-  CLIENT_NET_WRITE_TIMEOUT* = 365 * 24 * 3600 # Timeout on write
-
-type
-  Pst_mysql_field* = ptr St_mysql_field
-  St_mysql_field*{.final.} = object
-    name*: cstring            # Name of column
-    org_name*: cstring        # Original column name, if an alias
-    table*: cstring           # Table of column if column was a field
-    org_table*: cstring       # Org table name, if table was an alias
-    db*: cstring              # Database for table
-    catalog*: cstring         # Catalog for table
-    def*: cstring             # Default value (set by mysql_list_fields)
-    len*: int                 # Width of column (create length)
-    max_length*: int          # Max width for selected set
-    name_length*: cuint
-    org_name_length*: cuint
-    table_length*: cuint
-    org_table_length*: cuint
-    db_length*: cuint
-    catalog_length*: cuint
-    def_length*: cuint
-    flags*: cuint             # Div flags
-    decimals*: cuint          # Number of decimals in field
-    charsetnr*: cuint         # Character set
-    ftype*: Enum_field_types  # Type of field. See mysql_com.h for types
-    extension*: pointer
-
-  FIELD* = St_mysql_field
-  PFIELD* = ptr FIELD
-  PROW* = ptr ROW             # return data as array of strings
-  ROW* = cstringArray
-  PFIELD_OFFSET* = ptr FIELD_OFFSET # offset to current field
-  FIELD_OFFSET* = cuint
-{.deprecated: [Tst_mysql_field: St_mysql_field, TFIELD: FIELD, TROW: ROW,
-              TFIELD_OFFSET: FIELD_OFFSET].}
-
-proc IS_PRI_KEY*(n: int32): bool
-proc IS_NOT_NULL*(n: int32): bool
-proc IS_BLOB*(n: int32): bool
-proc IS_NUM*(t: Enum_field_types): bool
-proc INTERNAL_NUM_FIELD*(f: Pst_mysql_field): bool
-proc IS_NUM_FIELD*(f: Pst_mysql_field): bool
-type
-  my_ulonglong* = int64
-  Pmy_ulonglong* = ptr my_ulonglong
-
-const
-  COUNT_ERROR* = not (my_ulonglong(0))
-
-type
-  Pst_mysql_rows* = ptr St_mysql_rows
-  St_mysql_rows*{.final.} = object
-    next*: Pst_mysql_rows     # list of rows
-    data*: ROW
-    len*: int
-
-  ROWS* = St_mysql_rows
-  PROWS* = ptr ROWS
-  PROW_OFFSET* = ptr ROW_OFFSET # offset to current row
-  ROW_OFFSET* = ROWS
-{.deprecated: [Tst_mysql_rows: St_mysql_rows, TROWS: ROWS,
-              TROW_OFFSET: ROW_OFFSET].}
-
-const
-  ALLOC_MAX_BLOCK_TO_DROP* = 4096
-  ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP* = 10 # struct for once_alloc (block)
-
-type
-  Pst_used_mem* = ptr St_used_mem
-  St_used_mem*{.final.} = object
-    next*: Pst_used_mem       # Next block in use
-    left*: cuint              # memory left in block
-    size*: cuint              # size of block
-
-  USED_MEM* = St_used_mem
-  PUSED_MEM* = ptr USED_MEM
-  Pst_mem_root* = ptr St_mem_root
-  St_mem_root*{.final.} = object
-    free*: PUSED_MEM          # blocks with free memory in it
-    used*: PUSED_MEM          # blocks almost without free memory
-    pre_alloc*: PUSED_MEM     # preallocated block
-    min_malloc*: cuint        # if block have less memory it will be put in 'used' list
-    block_size*: cuint        # initial block size
-    block_num*: cuint # allocated blocks counter
-                      #    first free block in queue test counter (if it exceed
-                      #       MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list)
-    first_block_usage*: cuint
-    error_handler*: proc (){.cdecl.}
-
-  MEM_ROOT* = St_mem_root
-  PMEM_ROOT* = ptr MEM_ROOT   #  ------------ Stop of declaration in "my_alloc.h"    ----------------------
-{.deprecated: [Tst_used_mem: St_used_mem, TUSED_MEM: USED_MEM,
-              Tst_mem_root: St_mem_root, TMEM_ROOT: MEM_ROOT].}
-
-type
-  Pst_mysql_data* = ptr St_mysql_data
-  St_mysql_data*{.final.} = object
-    rows*: my_ulonglong
-    fields*: cuint
-    data*: PROWS
-    alloc*: MEM_ROOT
-    prev_ptr*: ptr PROWS
-
-  DATA* = St_mysql_data
-  PDATA* = ptr DATA
-  Option* = enum
-    OPT_CONNECT_TIMEOUT, OPT_COMPRESS, OPT_NAMED_PIPE, INIT_COMMAND,
-    READ_DEFAULT_FILE, READ_DEFAULT_GROUP, SET_CHARSET_DIR, SET_CHARSET_NAME,
-    OPT_LOCAL_INFILE, OPT_PROTOCOL, SHARED_MEMORY_BASE_NAME, OPT_READ_TIMEOUT,
-    OPT_WRITE_TIMEOUT, OPT_USE_RESULT, OPT_USE_REMOTE_CONNECTION,
-    OPT_USE_EMBEDDED_CONNECTION, OPT_GUESS_CONNECTION, SET_CLIENT_IP,
-    SECURE_AUTH, REPORT_DATA_TRUNCATION, OPT_RECONNECT
-{.deprecated: [Tst_mysql_data: St_mysql_data, TDATA: DATA, Toption: Option].}
-
-const
-  MAX_MYSQL_MANAGER_ERR* = 256
-  MAX_MYSQL_MANAGER_MSG* = 256
-  MANAGER_OK* = 200
-  MANAGER_INFO* = 250
-  MANAGER_ACCESS* = 401
-  MANAGER_CLIENT_ERR* = 450
-  MANAGER_INTERNAL_ERR* = 500
-
-type
-  St_dynamic_array*{.final.} = object
-    buffer*: cstring
-    elements*: cuint
-    max_element*: cuint
-    alloc_increment*: cuint
-    size_of_element*: cuint
-
-  DYNAMIC_ARRAY* = St_dynamic_array
-  Pst_dynamic_array* = ptr St_dynamic_array
-  Pst_mysql_options* = ptr St_mysql_options
-  St_mysql_options*{.final.} = object
-    connect_timeout*: cuint
-    read_timeout*: cuint
-    write_timeout*: cuint
-    port*: cuint
-    protocol*: cuint
-    client_flag*: int
-    host*: cstring
-    user*: cstring
-    password*: cstring
-    unix_socket*: cstring
-    db*: cstring
-    init_commands*: Pst_dynamic_array
-    my_cnf_file*: cstring
-    my_cnf_group*: cstring
-    charset_dir*: cstring
-    charset_name*: cstring
-    ssl_key*: cstring         # PEM key file
-    ssl_cert*: cstring        # PEM cert file
-    ssl_ca*: cstring          # PEM CA file
-    ssl_capath*: cstring      # PEM directory of CA-s?
-    ssl_cipher*: cstring      # cipher to use
-    shared_memory_base_name*: cstring
-    max_allowed_packet*: int
-    use_ssl*: my_bool         # if to use SSL or not
-    compress*: my_bool
-    named_pipe*: my_bool #  On connect, find out the replication role of the server, and
-                         #       establish connections to all the peers
-    rpl_probe*: my_bool #  Each call to mysql_real_query() will parse it to tell if it is a read
-                        #       or a write, and direct it to the slave or the master
-    rpl_parse*: my_bool #  If set, never read from a master, only from slave, when doing
-                        #       a read that is replication-aware
-    no_master_reads*: my_bool
-    separate_thread*: my_bool
-    methods_to_use*: Option
-    client_ip*: cstring
-    secure_auth*: my_bool     # Refuse client connecting to server if it uses old (pre-4.1.1) protocol
-    report_data_truncation*: my_bool # 0 - never report, 1 - always report (default)
-                                     # function pointers for local infile support
-    local_infile_init*: proc (para1: var pointer, para2: cstring, para3: pointer): cint{.
-        cdecl.}
-    local_infile_read*: proc (para1: pointer, para2: cstring, para3: cuint): cint
-    local_infile_end*: proc (para1: pointer)
-    local_infile_error*: proc (para1: pointer, para2: cstring, para3: cuint): cint
-    local_infile_userdata*: pointer
-
-  Status* = enum
-    STATUS_READY, STATUS_GET_RESULT, STATUS_USE_RESULT
-  Protocol_type* = enum  # There are three types of queries - the ones that have to go to
-                          # the master, the ones that go to a slave, and the administrative
-                          # type which must happen on the pivot connection
-    PROTOCOL_DEFAULT, PROTOCOL_TCP, PROTOCOL_SOCKET, PROTOCOL_PIPE,
-    PROTOCOL_MEMORY
-  Rpl_type* = enum
-    RPL_MASTER, RPL_SLAVE, RPL_ADMIN
-  Charset_info_st*{.final.} = object
-    number*: cuint
-    primary_number*: cuint
-    binary_number*: cuint
-    state*: cuint
-    csname*: cstring
-    name*: cstring
-    comment*: cstring
-    tailoring*: cstring
-    ftype*: cstring
-    to_lower*: cstring
-    to_upper*: cstring
-    sort_order*: cstring
-    contractions*: ptr int16
-    sort_order_big*: ptr ptr int16
-    tab_to_uni*: ptr int16
-    tab_from_uni*: pointer    # was ^MY_UNI_IDX
-    state_map*: cstring
-    ident_map*: cstring
-    strxfrm_multiply*: cuint
-    mbminlen*: cuint
-    mbmaxlen*: cuint
-    min_sort_char*: int16
-    max_sort_char*: int16
-    escape_with_backslash_is_dangerous*: my_bool
-    cset*: pointer            # was ^MY_CHARSET_HANDLER
-    coll*: pointer            # was ^MY_COLLATION_HANDLER;
-
-  CHARSET_INFO* = Charset_info_st
-  Pcharset_info_st* = ptr Charset_info_st
-  Pcharacter_set* = ptr Character_set
-  Character_set*{.final.} = object
-    number*: cuint
-    state*: cuint
-    csname*: cstring
-    name*: cstring
-    comment*: cstring
-    dir*: cstring
-    mbminlen*: cuint
-    mbmaxlen*: cuint
-
-  MY_CHARSET_INFO* = Character_set
-  PMY_CHARSET_INFO* = ptr MY_CHARSET_INFO
-  Pst_mysql_methods* = ptr St_mysql_methods
-  Pst_mysql* = ptr St_mysql
-  St_mysql*{.final.} = object
-    net*: NET                 # Communication parameters
-    connector_fd*: gptr       # ConnectorFd for SSL
-    host*: cstring
-    user*: cstring
-    passwd*: cstring
-    unix_socket*: cstring
-    server_version*: cstring
-    host_info*: cstring
-    info*: cstring
-    db*: cstring
-    charset*: Pcharset_info_st
-    fields*: PFIELD
-    field_alloc*: MEM_ROOT
-    affected_rows*: my_ulonglong
-    insert_id*: my_ulonglong  # id if insert on table with NEXTNR
-    extra_info*: my_ulonglong # Used by mysqlshow, not used by mysql 5.0 and up
-    thread_id*: int           # Id for connection in server
-    packet_length*: int
-    port*: cuint
-    client_flag*: int
-    server_capabilities*: int
-    protocol_version*: cuint
-    field_count*: cuint
-    server_status*: cuint
-    server_language*: cuint
-    warning_count*: cuint
-    options*: St_mysql_options
-    status*: Status
-    free_me*: my_bool         # If free in mysql_close
-    reconnect*: my_bool       # set to 1 if automatic reconnect
-    scramble*: array[0..(SCRAMBLE_LENGTH + 1) - 1, char] # session-wide random string
-                                                         #  Set if this is the original connection, not a master or a slave we have
-                                                         #       added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave()
-    rpl_pivot*: my_bool #   Pointers to the master, and the next slave connections, points to
-                        #        itself if lone connection.
-    master*: Pst_mysql
-    next_slave*: Pst_mysql
-    last_used_slave*: Pst_mysql # needed for round-robin slave pick
-    last_used_con*: Pst_mysql # needed for send/read/store/use result to work correctly with replication
-    stmts*: pointer           # was PList, list of all statements
-    methods*: Pst_mysql_methods
-    thd*: pointer #   Points to boolean flag in MYSQL_RES  or MYSQL_STMT. We set this flag
-                  #        from mysql_stmt_close if close had to cancel result set of this object.
-    unbuffered_fetch_owner*: Pmy_bool
-
-  MySQL* = St_mysql
-  PMySQL* = ptr MySQL
-  Pst_mysql_res* = ptr St_mysql_res
-  St_mysql_res*{.final.} = object
-    row_count*: my_ulonglong
-    fields*: PFIELD
-    data*: PDATA
-    data_cursor*: PROWS
-    lengths*: ptr int         # column lengths of current row
-    handle*: PMySQL                # for unbuffered reads
-    field_alloc*: MEM_ROOT
-    field_count*: cuint
-    current_field*: cuint
-    row*: ROW                 # If unbuffered read
-    current_row*: ROW         # buffer to current row
-    eof*: my_bool             # Used by mysql_fetch_row
-    unbuffered_fetch_cancelled*: my_bool # mysql_stmt_close() had to cancel this result
-    methods*: Pst_mysql_methods
-
-  RES* = St_mysql_res
-  PRES* = ptr RES
-  Pst_mysql_stmt* = ptr St_mysql_stmt
-  PSTMT* = ptr STMT
-  St_mysql_methods*{.final.} = object
-    read_query_result*: proc (MySQL:  PMySQL): my_bool{.cdecl.}
-    advanced_command*: proc (MySQL: PMySQL, command: Enum_server_command, header: cstring,
-                             header_length: int, arg: cstring, arg_length: int,
-                             skip_check: my_bool): my_bool
-    read_rows*: proc (MySQL: PMySQL, fields: PFIELD, fields_count: cuint): PDATA
-    use_result*: proc (MySQL: PMySQL): PRES
-    fetch_lengths*: proc (fto: ptr int, column: ROW, field_count: cuint)
-    flush_use_result*: proc (MySQL: PMySQL)
-    list_fields*: proc (MySQL: PMySQL): PFIELD
-    read_prepare_result*: proc (MySQL: PMySQL, stmt: PSTMT): my_bool
-    stmt_execute*: proc (stmt: PSTMT): cint
-    read_binary_rows*: proc (stmt: PSTMT): cint
-    unbuffered_fetch*: proc (MySQL: PMySQL, row: cstringArray): cint
-    free_embedded_thd*: proc (MySQL: PMySQL)
-    read_statistics*: proc (MySQL: PMySQL): cstring
-    next_result*: proc (MySQL: PMySQL): my_bool
-    read_change_user_result*: proc (MySQL: PMySQL, buff: cstring, passwd: cstring): cint
-    read_rowsfrom_cursor*: proc (stmt: PSTMT): cint
-
-  METHODS* = St_mysql_methods
-  PMETHODS* = ptr METHODS
-  Pst_mysql_manager* = ptr St_mysql_manager
-  St_mysql_manager*{.final.} = object
-    net*: NET
-    host*: cstring
-    user*: cstring
-    passwd*: cstring
-    port*: cuint
-    free_me*: my_bool
-    eof*: my_bool
-    cmd_status*: cint
-    last_errno*: cint
-    net_buf*: cstring
-    net_buf_pos*: cstring
-    net_data_end*: cstring
-    net_buf_size*: cint
-    last_error*: array[0..(MAX_MYSQL_MANAGER_ERR) - 1, char]
-
-  MANAGER* = St_mysql_manager
-  PMANAGER* = ptr MANAGER
-  Pst_mysql_parameters* = ptr St_mysql_parameters
-  St_mysql_parameters*{.final.} = object
-    p_max_allowed_packet*: ptr int
-    p_net_buffer_length*: ptr int
-
-  PARAMETERS* = St_mysql_parameters
-  PPARAMETERS* = ptr PARAMETERS
-  Enum_mysql_stmt_state* = enum
-    STMT_INIT_DONE = 1, STMT_PREPARE_DONE, STMT_EXECUTE_DONE, STMT_FETCH_DONE
-  Pst_mysql_bind* = ptr St_mysql_bind
-  St_mysql_bind*{.final.} = object
-    len*: int                 # output length pointer
-    is_null*: Pmy_bool        # Pointer to null indicator
-    buffer*: pointer          # buffer to get/put data
-    error*: Pmy_bool          # set this if you want to track data truncations happened during fetch
-    buffer_type*: Enum_field_types # buffer type
-    buffer_length*: int       # buffer length, must be set for str/binary
-                              # Following are for internal use. Set by mysql_stmt_bind_param
-    row_ptr*: ptr byte        # for the current data position
-    offset*: int              # offset position for char/binary fetch
-    length_value*: int        #  Used if length is 0
-    param_number*: cuint      # For null count and error messages
-    pack_length*: cuint       # Internal length for packed data
-    error_value*: my_bool     # used if error is 0
-    is_unsigned*: my_bool     # set if integer type is unsigned
-    long_data_used*: my_bool  # If used with mysql_send_long_data
-    is_null_value*: my_bool   # Used if is_null is 0
-    store_param_func*: proc (net: PNET, param: Pst_mysql_bind){.cdecl.}
-    fetch_result*: proc (para1: Pst_mysql_bind, para2: PFIELD, row: PPByte)
-    skip_result*: proc (para1: Pst_mysql_bind, para2: PFIELD, row: PPByte)
-
-  BIND* = St_mysql_bind
-  PBIND* = ptr BIND           # statement handler
-  St_mysql_stmt*{.final.} = object
-    mem_root*: MEM_ROOT       # root allocations
-    mysql*: PMySQL                      # connection handle
-    params*: PBIND            # input parameters
-    `bind`*: PBIND            # input parameters
-    fields*: PFIELD           # result set metadata
-    result*: DATA             # cached result set
-    data_cursor*: PROWS       # current row in cached result
-    affected_rows*: my_ulonglong # copy of mysql->affected_rows after statement execution
-    insert_id*: my_ulonglong
-    read_row_func*: proc (stmt: Pst_mysql_stmt, row: PPByte): cint{.cdecl.}
-    stmt_id*: int             # Id for prepared statement
-    flags*: int               # i.e. type of cursor to open
-    prefetch_rows*: int       # number of rows per one COM_FETCH
-    server_status*: cuint # Copied from mysql->server_status after execute/fetch to know
-                          # server-side cursor status for this statement.
-    last_errno*: cuint        # error code
-    param_count*: cuint       # input parameter count
-    field_count*: cuint       # number of columns in result set
-    state*: Enum_mysql_stmt_state # statement state
-    last_error*: array[0..(ERRMSG_SIZE) - 1, char] # error message
-    sqlstate*: array[0..(SQLSTATE_LENGTH + 1) - 1, char]
-    send_types_to_server*: my_bool # Types of input parameters should be sent to server
-    bind_param_done*: my_bool # input buffers were supplied
-    bind_result_done*: char   # output buffers were supplied
-    unbuffered_fetch_cancelled*: my_bool
-    update_max_length*: my_bool
-
-  STMT* = St_mysql_stmt
-
-  Enum_stmt_attr_type* = enum
-    STMT_ATTR_UPDATE_MAX_LENGTH, STMT_ATTR_CURSOR_TYPE, STMT_ATTR_PREFETCH_ROWS
-{.deprecated: [Tst_dynamic_array: St_dynamic_array, Tst_mysql_options: St_mysql_options,
-              TDYNAMIC_ARRAY: DYNAMIC_ARRAY, Tprotocol_type: Protocol_type,
-              Trpl_type: Rpl_type, Tcharset_info_st: Charset_info_st,
-              TCHARSET_INFO: CHARSET_INFO, Tcharacter_set: Character_set,
-              TMY_CHARSET_INFO: MY_CHARSET_INFO, Tst_mysql: St_mysql,
-              Tst_mysql_methods: St_mysql_methods, TMySql: MySql,
-              Tst_mysql_res: St_mysql_res, TMETHODS: METHODS, TRES: RES,
-              Tst_mysql_manager: St_mysql_manager, TMANAGER: MANAGER,
-              Tst_mysql_parameters: St_mysql_parameters, TPARAMETERS: PARAMETERS,
-              Tenum_mysql_stmt_state: Enum_mysql_stmt_state,
-              Tst_mysql_bind: St_mysql_bind, TBIND: BIND, Tst_mysql_stmt: St_mysql_stmt,
-              TSTMT: STMT, Tenum_stmt_attr_type: Enum_stmt_attr_type,
-              Tstatus: Status].}
-
-proc server_init*(argc: cint, argv: cstringArray, groups: cstringArray): cint{.
-    cdecl, dynlib: lib, importc: "mysql_server_init".}
-proc server_end*(){.cdecl, dynlib: lib, importc: "mysql_server_end".}
-  # mysql_server_init/end need to be called when using libmysqld or
-  #      libmysqlclient (exactly, mysql_server_init() is called by mysql_init() so
-  #      you don't need to call it explicitly; but you need to call
-  #      mysql_server_end() to free memory). The names are a bit misleading
-  #      (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general
-  #      names which suit well whether you're using libmysqld or libmysqlclient. We
-  #      intend to promote these aliases over the mysql_server* ones.
-proc library_init*(argc: cint, argv: cstringArray, groups: cstringArray): cint{.
-    cdecl, dynlib: lib, importc: "mysql_server_init".}
-proc library_end*(){.cdecl, dynlib: lib, importc: "mysql_server_end".}
-proc get_parameters*(): PPARAMETERS{.stdcall, dynlib: lib,
-                                     importc: "mysql_get_parameters".}
-  # Set up and bring down a thread; these function should be called
-  #      for each thread in an application which opens at least one MySQL
-  #      connection.  All uses of the connection(s) should be between these
-  #      function calls.
-proc thread_init*(): my_bool{.stdcall, dynlib: lib, importc: "mysql_thread_init".}
-proc thread_end*(){.stdcall, dynlib: lib, importc: "mysql_thread_end".}
-  # Functions to get information from the MYSQL and MYSQL_RES structures
-  #      Should definitely be used if one uses shared libraries.
-proc num_rows*(res: PRES): my_ulonglong{.stdcall, dynlib: lib,
-    importc: "mysql_num_rows".}
-proc num_fields*(res: PRES): cuint{.stdcall, dynlib: lib,
-                                    importc: "mysql_num_fields".}
-proc eof*(res: PRES): my_bool{.stdcall, dynlib: lib, importc: "mysql_eof".}
-proc fetch_field_direct*(res: PRES, fieldnr: cuint): PFIELD{.stdcall,
-    dynlib: lib, importc: "mysql_fetch_field_direct".}
-proc fetch_fields*(res: PRES): PFIELD{.stdcall, dynlib: lib,
-                                       importc: "mysql_fetch_fields".}
-proc row_tell*(res: PRES): ROW_OFFSET{.stdcall, dynlib: lib,
-                                       importc: "mysql_row_tell".}
-proc field_tell*(res: PRES): FIELD_OFFSET{.stdcall, dynlib: lib,
-    importc: "mysql_field_tell".}
-proc field_count*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib,
-                               importc: "mysql_field_count".}
-proc affected_rows*(MySQL: PMySQL): my_ulonglong{.stdcall, dynlib: lib,
-                                        importc: "mysql_affected_rows".}
-proc insert_id*(MySQL: PMySQL): my_ulonglong{.stdcall, dynlib: lib,
-                                    importc: "mysql_insert_id".}
-proc errno*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, importc: "mysql_errno".}
-proc error*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_error".}
-proc sqlstate*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_sqlstate".}
-proc warning_count*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib,
-                                 importc: "mysql_warning_count".}
-proc info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_info".}
-proc thread_id*(MySQL: PMySQL): int{.stdcall, dynlib: lib, importc: "mysql_thread_id".}
-proc character_set_name*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib,
-                                        importc: "mysql_character_set_name".}
-proc set_character_set*(MySQL: PMySQL, csname: cstring): int32{.stdcall, dynlib: lib,
-    importc: "mysql_set_character_set".}
-proc init*(MySQL: PMySQL): PMySQL{.stdcall, dynlib: lib, importc: "mysql_init".}
-proc ssl_set*(MySQL: PMySQL, key: cstring, cert: cstring, ca: cstring, capath: cstring,
-              cipher: cstring): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_ssl_set".}
-proc change_user*(MySQL: PMySQL, user: cstring, passwd: cstring, db: cstring): my_bool{.
-    stdcall, dynlib: lib, importc: "mysql_change_user".}
-proc real_connect*(MySQL: PMySQL, host: cstring, user: cstring, passwd: cstring,
-                   db: cstring, port: cuint, unix_socket: cstring,
-                   clientflag: int): PMySQL{.stdcall, dynlib: lib,
-                                        importc: "mysql_real_connect".}
-proc select_db*(MySQL: PMySQL, db: cstring): cint{.stdcall, dynlib: lib,
-    importc: "mysql_select_db".}
-proc query*(MySQL: PMySQL, q: cstring): cint{.stdcall, dynlib: lib, importc: "mysql_query".}
-proc send_query*(MySQL: PMySQL, q: cstring, len: int): cint{.stdcall, dynlib: lib,
-    importc: "mysql_send_query".}
-proc real_query*(MySQL: PMySQL, q: cstring, len: int): cint{.stdcall, dynlib: lib,
-    importc: "mysql_real_query".}
-proc store_result*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib,
-                               importc: "mysql_store_result".}
-proc use_result*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib, importc: "mysql_use_result".}
-  # perform query on master
-proc master_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_master_query".}
-proc master_send_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall,
-    dynlib: lib, importc: "mysql_master_send_query".}
-  # perform query on slave
-proc slave_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_slave_query".}
-proc slave_send_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall,
-    dynlib: lib, importc: "mysql_slave_send_query".}
-proc get_character_set_info*(MySQL: PMySQL, charset: PMY_CHARSET_INFO){.stdcall,
-    dynlib: lib, importc: "mysql_get_character_set_info".}
-  # local infile support
-const
-  LOCAL_INFILE_ERROR_LEN* = 512
-
-# procedure mysql_set_local_infile_handler(mysql:PMYSQL; local_infile_init:function (para1:Ppointer; para2:Pchar; para3:pointer):longint; local_infile_read:function (para1:pointer; para2:Pchar; para3:dword):longint; local_infile_end:procedure (_pa
-# para6:pointer);cdecl;external mysqllib name 'mysql_set_local_infile_handler';
-
-proc set_local_infile_default*(MySQL: PMySQL){.cdecl, dynlib: lib,
-                                     importc: "mysql_set_local_infile_default".}
-  # enable/disable parsing of all queries to decide if they go on master or
-  #      slave
-proc enable_rpl_parse*(MySQL: PMySQL){.stdcall, dynlib: lib,
-                             importc: "mysql_enable_rpl_parse".}
-proc disable_rpl_parse*(MySQL: PMySQL){.stdcall, dynlib: lib,
-                              importc: "mysql_disable_rpl_parse".}
-  # get the value of the parse flag
-proc rpl_parse_enabled*(MySQL: PMySQL): cint{.stdcall, dynlib: lib,
-                                    importc: "mysql_rpl_parse_enabled".}
-  #  enable/disable reads from master
-proc enable_reads_from_master*(MySQL: PMySQL){.stdcall, dynlib: lib,
-                                     importc: "mysql_enable_reads_from_master".}
-proc disable_reads_from_master*(MySQL: PMySQL){.stdcall, dynlib: lib, importc: "mysql_disable_reads_from_master".}
-  # get the value of the master read flag
-proc reads_from_master_enabled*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_reads_from_master_enabled".}
-proc rpl_query_type*(q: cstring, length: cint): Rpl_type{.stdcall, dynlib: lib,
-    importc: "mysql_rpl_query_type".}
-  # discover the master and its slaves
-proc rpl_probe*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_rpl_probe".}
-  # set the master, close/free the old one, if it is not a pivot
-proc set_master*(MySQL: PMySQL, host: cstring, port: cuint, user: cstring, passwd: cstring): cint{.
-    stdcall, dynlib: lib, importc: "mysql_set_master".}
-proc add_slave*(MySQL: PMySQL, host: cstring, port: cuint, user: cstring, passwd: cstring): cint{.
-    stdcall, dynlib: lib, importc: "mysql_add_slave".}
-proc shutdown*(MySQL: PMySQL, shutdown_level: Enum_shutdown_level): cint{.stdcall,
-    dynlib: lib, importc: "mysql_shutdown".}
-proc dump_debug_info*(MySQL: PMySQL): cint{.stdcall, dynlib: lib,
-                                  importc: "mysql_dump_debug_info".}
-proc refresh*(sql: PMySQL, refresh_options: cuint): cint{.stdcall, dynlib: lib,
-    importc: "mysql_refresh".}
-proc kill*(MySQL: PMySQL, pid: int): cint{.stdcall, dynlib: lib, importc: "mysql_kill".}
-proc set_server_option*(MySQL: PMySQL, option: Enum_mysql_set_option): cint{.stdcall,
-    dynlib: lib, importc: "mysql_set_server_option".}
-proc ping*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, importc: "mysql_ping".}
-proc stat*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_stat".}
-proc get_server_info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib,
-                                     importc: "mysql_get_server_info".}
-proc get_client_info*(): cstring{.stdcall, dynlib: lib,
-                                  importc: "mysql_get_client_info".}
-proc get_client_version*(): int{.stdcall, dynlib: lib,
-                                 importc: "mysql_get_client_version".}
-proc get_host_info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib,
-                                   importc: "mysql_get_host_info".}
-proc get_server_version*(MySQL: PMySQL): int{.stdcall, dynlib: lib,
-                                    importc: "mysql_get_server_version".}
-proc get_proto_info*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib,
-                                  importc: "mysql_get_proto_info".}
-proc list_dbs*(MySQL: PMySQL, wild: cstring): PRES{.stdcall, dynlib: lib,
-    importc: "mysql_list_dbs".}
-proc list_tables*(MySQL: PMySQL, wild: cstring): PRES{.stdcall, dynlib: lib,
-    importc: "mysql_list_tables".}
-proc list_processes*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib,
-                                 importc: "mysql_list_processes".}
-proc options*(MySQL: PMySQL, option: Option, arg: cstring): cint{.stdcall, dynlib: lib,
-    importc: "mysql_options".}
-proc free_result*(result: PRES){.stdcall, dynlib: lib,
-                                 importc: "mysql_free_result".}
-proc data_seek*(result: PRES, offset: my_ulonglong){.stdcall, dynlib: lib,
-    importc: "mysql_data_seek".}
-proc row_seek*(result: PRES, offset: ROW_OFFSET): ROW_OFFSET{.stdcall,
-    dynlib: lib, importc: "mysql_row_seek".}
-proc field_seek*(result: PRES, offset: FIELD_OFFSET): FIELD_OFFSET{.stdcall,
-    dynlib: lib, importc: "mysql_field_seek".}
-proc fetch_row*(result: PRES): ROW{.stdcall, dynlib: lib,
-                                    importc: "mysql_fetch_row".}
-proc fetch_lengths*(result: PRES): ptr int{.stdcall, dynlib: lib,
-    importc: "mysql_fetch_lengths".}
-proc fetch_field*(result: PRES): PFIELD{.stdcall, dynlib: lib,
-    importc: "mysql_fetch_field".}
-proc list_fields*(MySQL: PMySQL, table: cstring, wild: cstring): PRES{.stdcall,
-    dynlib: lib, importc: "mysql_list_fields".}
-proc escape_string*(fto: cstring, `from`: cstring, from_length: int): int{.
-    stdcall, dynlib: lib, importc: "mysql_escape_string".}
-proc hex_string*(fto: cstring, `from`: cstring, from_length: int): int{.stdcall,
-    dynlib: lib, importc: "mysql_hex_string".}
-proc real_escape_string*(MySQL: PMySQL, fto: cstring, `from`: cstring, len: int): int{.
-    stdcall, dynlib: lib, importc: "mysql_real_escape_string".}
-proc debug*(debug: cstring){.stdcall, dynlib: lib, importc: "mysql_debug".}
-  #    function mysql_odbc_escape_string(mysql:PMYSQL; fto:Pchar; to_length:dword; from:Pchar; from_length:dword;
-  #               param:pointer; extend_buffer:function (para1:pointer; to:Pchar; length:Pdword):Pchar):Pchar;stdcall;external mysqllib name 'mysql_odbc_escape_string';
-proc myodbc_remove_escape*(MySQL: PMySQL, name: cstring){.stdcall, dynlib: lib,
-    importc: "myodbc_remove_escape".}
-proc thread_safe*(): cuint{.stdcall, dynlib: lib, importc: "mysql_thread_safe".}
-proc embedded*(): my_bool{.stdcall, dynlib: lib, importc: "mysql_embedded".}
-proc manager_init*(con: PMANAGER): PMANAGER{.stdcall, dynlib: lib,
-    importc: "mysql_manager_init".}
-proc manager_connect*(con: PMANAGER, host: cstring, user: cstring,
-                      passwd: cstring, port: cuint): PMANAGER{.stdcall,
-    dynlib: lib, importc: "mysql_manager_connect".}
-proc manager_close*(con: PMANAGER){.stdcall, dynlib: lib,
-                                    importc: "mysql_manager_close".}
-proc manager_command*(con: PMANAGER, cmd: cstring, cmd_len: cint): cint{.
-    stdcall, dynlib: lib, importc: "mysql_manager_command".}
-proc manager_fetch_line*(con: PMANAGER, res_buf: cstring, res_buf_size: cint): cint{.
-    stdcall, dynlib: lib, importc: "mysql_manager_fetch_line".}
-proc read_query_result*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib,
-                                       importc: "mysql_read_query_result".}
-proc stmt_init*(MySQL: PMySQL): PSTMT{.stdcall, dynlib: lib, importc: "mysql_stmt_init".}
-proc stmt_prepare*(stmt: PSTMT, query: cstring, len: int): cint{.stdcall,
-    dynlib: lib, importc: "mysql_stmt_prepare".}
-proc stmt_execute*(stmt: PSTMT): cint{.stdcall, dynlib: lib,
-                                       importc: "mysql_stmt_execute".}
-proc stmt_fetch*(stmt: PSTMT): cint{.stdcall, dynlib: lib,
-                                     importc: "mysql_stmt_fetch".}
-proc stmt_fetch_column*(stmt: PSTMT, `bind`: PBIND, column: cuint, offset: int): cint{.
-    stdcall, dynlib: lib, importc: "mysql_stmt_fetch_column".}
-proc stmt_store_result*(stmt: PSTMT): cint{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_store_result".}
-proc stmt_param_count*(stmt: PSTMT): int{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_param_count".}
-proc stmt_attr_set*(stmt: PSTMT, attr_type: Enum_stmt_attr_type, attr: pointer): my_bool{.
-    stdcall, dynlib: lib, importc: "mysql_stmt_attr_set".}
-proc stmt_attr_get*(stmt: PSTMT, attr_type: Enum_stmt_attr_type, attr: pointer): my_bool{.
-    stdcall, dynlib: lib, importc: "mysql_stmt_attr_get".}
-proc stmt_bind_param*(stmt: PSTMT, bnd: PBIND): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_bind_param".}
-proc stmt_bind_result*(stmt: PSTMT, bnd: PBIND): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_bind_result".}
-proc stmt_close*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib,
-                                        importc: "mysql_stmt_close".}
-proc stmt_reset*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib,
-                                        importc: "mysql_stmt_reset".}
-proc stmt_free_result*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_free_result".}
-proc stmt_send_long_data*(stmt: PSTMT, param_number: cuint, data: cstring,
-                          len: int): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_send_long_data".}
-proc stmt_result_metadata*(stmt: PSTMT): PRES{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_result_metadata".}
-proc stmt_param_metadata*(stmt: PSTMT): PRES{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_param_metadata".}
-proc stmt_errno*(stmt: PSTMT): cuint{.stdcall, dynlib: lib,
-                                      importc: "mysql_stmt_errno".}
-proc stmt_error*(stmt: PSTMT): cstring{.stdcall, dynlib: lib,
-                                        importc: "mysql_stmt_error".}
-proc stmt_sqlstate*(stmt: PSTMT): cstring{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_sqlstate".}
-proc stmt_row_seek*(stmt: PSTMT, offset: ROW_OFFSET): ROW_OFFSET{.stdcall,
-    dynlib: lib, importc: "mysql_stmt_row_seek".}
-proc stmt_row_tell*(stmt: PSTMT): ROW_OFFSET{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_row_tell".}
-proc stmt_data_seek*(stmt: PSTMT, offset: my_ulonglong){.stdcall, dynlib: lib,
-    importc: "mysql_stmt_data_seek".}
-proc stmt_num_rows*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_num_rows".}
-proc stmt_affected_rows*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_affected_rows".}
-proc stmt_insert_id*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_insert_id".}
-proc stmt_field_count*(stmt: PSTMT): cuint{.stdcall, dynlib: lib,
-    importc: "mysql_stmt_field_count".}
-proc commit*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_commit".}
-proc rollback*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_rollback".}
-proc autocommit*(MySQL: PMySQL, auto_mode: my_bool): my_bool{.stdcall, dynlib: lib,
-    importc: "mysql_autocommit".}
-proc more_results*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib,
-                                  importc: "mysql_more_results".}
-proc next_result*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, importc: "mysql_next_result".}
-proc close*(sock: PMySQL){.stdcall, dynlib: lib, importc: "mysql_close".}
-  # status return codes
-const
-  NO_DATA* = 100
-  DATA_TRUNCATED* = 101
-
-proc reload*(x: PMySQL): cint
-when defined(USE_OLD_FUNCTIONS):
-  proc connect*(MySQL: PMySQL, host: cstring, user: cstring, passwd: cstring): PMySQL{.stdcall,
-      dynlib: lib, importc: "mysql_connect".}
-  proc create_db*(MySQL: PMySQL, DB: cstring): cint{.stdcall, dynlib: lib,
-      importc: "mysql_create_db".}
-  proc drop_db*(MySQL: PMySQL, DB: cstring): cint{.stdcall, dynlib: lib,
-      importc: "mysql_drop_db".}
-proc net_safe_read*(MySQL: PMySQL): cuint{.cdecl, dynlib: lib, importc: "net_safe_read".}
-
-proc IS_PRI_KEY(n: int32): bool =
-  result = (n and PRI_KEY_FLAG) != 0
-
-proc IS_NOT_NULL(n: int32): bool =
-  result = (n and NOT_NULL_FLAG) != 0
-
-proc IS_BLOB(n: int32): bool =
-  result = (n and BLOB_FLAG) != 0
-
-proc IS_NUM_FIELD(f: Pst_mysql_field): bool =
-  result = (f.flags and NUM_FLAG) != 0
-
-proc IS_NUM(t: Enum_field_types): bool =
-  result = (t <= FIELD_TYPE_INT24) or (t == FIELD_TYPE_YEAR) or
-      (t == FIELD_TYPE_NEWDECIMAL)
-
-proc INTERNAL_NUM_FIELD(f: Pst_mysql_field): bool =
-  result = (f.ftype <= FIELD_TYPE_INT24) and
-      ((f.ftype != FIELD_TYPE_TIMESTAMP) or (f.len == 14) or (f.len == 8)) or
-      (f.ftype == FIELD_TYPE_YEAR)
-
-proc reload(x: PMySQL): cint =
-  result = refresh(x, REFRESH_GRANT)
-
-{.pop.}
-when defined(nimHasStyleChecks):
-  {.pop.}
diff --git a/lib/wrappers/odbcsql.nim b/lib/wrappers/odbcsql.nim
deleted file mode 100644
index 6b300c5ff..000000000
--- a/lib/wrappers/odbcsql.nim
+++ /dev/null
@@ -1,844 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-when defined(nimPreviewSlimSystem):
-  import std/widestrs
-
-when not defined(ODBCVER):
-  const
-    ODBCVER = 0x0351 ## define ODBC version 3.51 by default
-
-when defined(windows):
-  {.push callconv: stdcall.}
-  const odbclib = "odbc32.dll"
-else:
-  {.push callconv: cdecl.}
-  const odbclib = "libodbc.so"
-
-when defined(nimHasStyleChecks):
-  {.push styleChecks: off.}
-
-# DATA TYPES CORRESPONDENCE
-#   BDE fields  ODBC types
-#   ----------  ------------------
-#   ftBlob      SQL_BINARY
-#   ftBoolean   SQL_BIT
-#   ftDate      SQL_TYPE_DATE
-#   ftTime      SQL_TYPE_TIME
-#   ftDateTime  SQL_TYPE_TIMESTAMP
-#   ftInteger   SQL_INTEGER
-#   ftSmallint  SQL_SMALLINT
-#   ftFloat     SQL_DOUBLE
-#   ftString    SQL_CHAR
-#   ftMemo      SQL_BINARY // SQL_VARCHAR
-#
-
-type
-  TSqlChar* = char
-  TSqlSmallInt* = int16
-  SqlUSmallInt* = int16
-  SqlHandle* = pointer
-  SqlHEnv* = SqlHandle
-  SqlHDBC* = SqlHandle
-  SqlHStmt* = SqlHandle
-  SqlHDesc* = SqlHandle
-  TSqlInteger* = int32
-  SqlUInteger* = int32
-  TSqlLen* = int
-  TSqlULen* = uint
-  SqlPointer* = pointer
-  TSqlReal* = cfloat
-  TSqlDouble* = cdouble
-  TSqlFloat* = cdouble
-  SqlHWND* = pointer
-  PSQLCHAR* = cstring
-  PSQLINTEGER* = ptr TSqlInteger
-  PSQLUINTEGER* = ptr SqlUInteger
-  PSQLSMALLINT* = ptr TSqlSmallInt
-  PSQLUSMALLINT* = ptr SqlUSmallInt
-  PSQLREAL* = ptr TSqlReal
-  PSQLDOUBLE* = ptr TSqlDouble
-  PSQLFLOAT* = ptr TSqlFloat
-  PSQLHANDLE* = ptr SqlHandle
-
-const                         # SQL data type codes
-  SQL_UNKNOWN_TYPE* = 0
-  SQL_LONGVARCHAR* = (- 1)
-  SQL_BINARY* = (- 2)
-  SQL_VARBINARY* = (- 3)
-  SQL_LONGVARBINARY* = (- 4)
-  SQL_BIGINT* = (- 5)
-  SQL_TINYINT* = (- 6)
-  SQL_BIT* = (- 7)
-  SQL_WCHAR* = (- 8)
-  SQL_WVARCHAR* = (- 9)
-  SQL_WLONGVARCHAR* = (- 10)
-  SQL_CHAR* = 1
-  SQL_NUMERIC* = 2
-  SQL_DECIMAL* = 3
-  SQL_INTEGER* = 4
-  SQL_SMALLINT* = 5
-  SQL_FLOAT* = 6
-  SQL_REAL* = 7
-  SQL_DOUBLE* = 8
-  SQL_DATETIME* = 9
-  SQL_VARCHAR* = 12
-  SQL_TYPE_DATE* = 91
-  SQL_TYPE_TIME* = 92
-  SQL_TYPE_TIMESTAMP* = 93
-  SQL_DATE* = 9
-  SQL_TIME* = 10
-  SQL_TIMESTAMP* = 11
-  SQL_INTERVAL* = 10
-  SQL_GUID* = - 11            # interval codes
-
-when ODBCVER >= 0x0300:
-  const
-    SQL_CODE_YEAR* = 1
-    SQL_CODE_MONTH* = 2
-    SQL_CODE_DAY* = 3
-    SQL_CODE_HOUR* = 4
-    SQL_CODE_MINUTE* = 5
-    SQL_CODE_SECOND* = 6
-    SQL_CODE_YEAR_TO_MONTH* = 7
-    SQL_CODE_DAY_TO_HOUR* = 8
-    SQL_CODE_DAY_TO_MINUTE* = 9
-    SQL_CODE_DAY_TO_SECOND* = 10
-    SQL_CODE_HOUR_TO_MINUTE* = 11
-    SQL_CODE_HOUR_TO_SECOND* = 12
-    SQL_CODE_MINUTE_TO_SECOND* = 13
-    SQL_INTERVAL_YEAR* = 100 + SQL_CODE_YEAR
-    SQL_INTERVAL_MONTH* = 100 + SQL_CODE_MONTH
-    SQL_INTERVAL_DAY* = 100 + SQL_CODE_DAY
-    SQL_INTERVAL_HOUR* = 100 + SQL_CODE_HOUR
-    SQL_INTERVAL_MINUTE* = 100 + SQL_CODE_MINUTE
-    SQL_INTERVAL_SECOND* = 100 + SQL_CODE_SECOND
-    SQL_INTERVAL_YEAR_TO_MONTH* = 100 + SQL_CODE_YEAR_TO_MONTH
-    SQL_INTERVAL_DAY_TO_HOUR* = 100 + SQL_CODE_DAY_TO_HOUR
-    SQL_INTERVAL_DAY_TO_MINUTE* = 100 + SQL_CODE_DAY_TO_MINUTE
-    SQL_INTERVAL_DAY_TO_SECOND* = 100 + SQL_CODE_DAY_TO_SECOND
-    SQL_INTERVAL_HOUR_TO_MINUTE* = 100 + SQL_CODE_HOUR_TO_MINUTE
-    SQL_INTERVAL_HOUR_TO_SECOND* = 100 + SQL_CODE_HOUR_TO_SECOND
-    SQL_INTERVAL_MINUTE_TO_SECOND* = 100 + SQL_CODE_MINUTE_TO_SECOND
-else:
-  const
-    SQL_INTERVAL_YEAR* = - 80
-    SQL_INTERVAL_MONTH* = - 81
-    SQL_INTERVAL_YEAR_TO_MONTH* = - 82
-    SQL_INTERVAL_DAY* = - 83
-    SQL_INTERVAL_HOUR* = - 84
-    SQL_INTERVAL_MINUTE* = - 85
-    SQL_INTERVAL_SECOND* = - 86
-    SQL_INTERVAL_DAY_TO_HOUR* = - 87
-    SQL_INTERVAL_DAY_TO_MINUTE* = - 88
-    SQL_INTERVAL_DAY_TO_SECOND* = - 89
-    SQL_INTERVAL_HOUR_TO_MINUTE* = - 90
-    SQL_INTERVAL_HOUR_TO_SECOND* = - 91
-    SQL_INTERVAL_MINUTE_TO_SECOND* = - 92
-
-
-when ODBCVER < 0x0300:
-  const
-    SQL_UNICODE* = - 95
-    SQL_UNICODE_VARCHAR* = - 96
-    SQL_UNICODE_LONGVARCHAR* = - 97
-    SQL_UNICODE_CHAR* = SQL_UNICODE
-else:
-  # The previous definitions for SQL_UNICODE_ are historical and obsolete
-  const
-    SQL_UNICODE* = SQL_WCHAR
-    SQL_UNICODE_VARCHAR* = SQL_WVARCHAR
-    SQL_UNICODE_LONGVARCHAR* = SQL_WLONGVARCHAR
-    SQL_UNICODE_CHAR* = SQL_WCHAR
-const                         # C datatype to SQL datatype mapping
-  SQL_C_CHAR* = SQL_CHAR
-  SQL_C_LONG* = SQL_INTEGER
-  SQL_C_SHORT* = SQL_SMALLINT
-  SQL_C_FLOAT* = SQL_REAL
-  SQL_C_DOUBLE* = SQL_DOUBLE
-  SQL_C_NUMERIC* = SQL_NUMERIC
-  SQL_C_DEFAULT* = 99
-  SQL_SIGNED_OFFSET* = - 20
-  SQL_UNSIGNED_OFFSET* = - 22
-  SQL_C_DATE* = SQL_DATE
-  SQL_C_TIME* = SQL_TIME
-  SQL_C_TIMESTAMP* = SQL_TIMESTAMP
-  SQL_C_TYPE_DATE* = SQL_TYPE_DATE
-  SQL_C_TYPE_TIME* = SQL_TYPE_TIME
-  SQL_C_TYPE_TIMESTAMP* = SQL_TYPE_TIMESTAMP
-  SQL_C_INTERVAL_YEAR* = SQL_INTERVAL_YEAR
-  SQL_C_INTERVAL_MONTH* = SQL_INTERVAL_MONTH
-  SQL_C_INTERVAL_DAY* = SQL_INTERVAL_DAY
-  SQL_C_INTERVAL_HOUR* = SQL_INTERVAL_HOUR
-  SQL_C_INTERVAL_MINUTE* = SQL_INTERVAL_MINUTE
-  SQL_C_INTERVAL_SECOND* = SQL_INTERVAL_SECOND
-  SQL_C_INTERVAL_YEAR_TO_MONTH* = SQL_INTERVAL_YEAR_TO_MONTH
-  SQL_C_INTERVAL_DAY_TO_HOUR* = SQL_INTERVAL_DAY_TO_HOUR
-  SQL_C_INTERVAL_DAY_TO_MINUTE* = SQL_INTERVAL_DAY_TO_MINUTE
-  SQL_C_INTERVAL_DAY_TO_SECOND* = SQL_INTERVAL_DAY_TO_SECOND
-  SQL_C_INTERVAL_HOUR_TO_MINUTE* = SQL_INTERVAL_HOUR_TO_MINUTE
-  SQL_C_INTERVAL_HOUR_TO_SECOND* = SQL_INTERVAL_HOUR_TO_SECOND
-  SQL_C_INTERVAL_MINUTE_TO_SECOND* = SQL_INTERVAL_MINUTE_TO_SECOND
-  SQL_C_BINARY* = SQL_BINARY
-  SQL_C_BIT* = SQL_BIT
-  SQL_C_SBIGINT* = SQL_BIGINT + SQL_SIGNED_OFFSET # SIGNED BIGINT
-  SQL_C_UBIGINT* = SQL_BIGINT + SQL_UNSIGNED_OFFSET # UNSIGNED BIGINT
-  SQL_C_TINYINT* = SQL_TINYINT
-  SQL_C_SLONG* = SQL_C_LONG + SQL_SIGNED_OFFSET # SIGNED INTEGER
-  SQL_C_SSHORT* = SQL_C_SHORT + SQL_SIGNED_OFFSET # SIGNED SMALLINT
-  SQL_C_STINYINT* = SQL_TINYINT + SQL_SIGNED_OFFSET # SIGNED TINYINT
-  SQL_C_ULONG* = SQL_C_LONG + SQL_UNSIGNED_OFFSET # UNSIGNED INTEGER
-  SQL_C_USHORT* = SQL_C_SHORT + SQL_UNSIGNED_OFFSET # UNSIGNED SMALLINT
-  SQL_C_UTINYINT* = SQL_TINYINT + SQL_UNSIGNED_OFFSET # UNSIGNED TINYINT
-  SQL_C_BOOKMARK* = SQL_C_ULONG # BOOKMARK
-  SQL_C_GUID* = SQL_GUID
-  SQL_TYPE_NULL* = 0
-
-when ODBCVER < 0x0300:
-  const
-    SQL_TYPE_MIN* = SQL_BIT
-    SQL_TYPE_MAX* = SQL_VARCHAR
-
-const
-  SQL_C_VARBOOKMARK* = SQL_C_BINARY
-  SQL_API_SQLDESCRIBEPARAM* = 58
-  SQL_NO_TOTAL* = - 4
-
-type
-  SQL_DATE_STRUCT* {.final, pure.} = object
-    Year*: TSqlSmallInt
-    Month*: SqlUSmallInt
-    Day*: SqlUSmallInt
-
-  PSQL_DATE_STRUCT* = ptr SQL_DATE_STRUCT
-  SQL_TIME_STRUCT* {.final, pure.} = object
-    Hour*: SqlUSmallInt
-    Minute*: SqlUSmallInt
-    Second*: SqlUSmallInt
-
-  PSQL_TIME_STRUCT* = ptr SQL_TIME_STRUCT
-  SQL_TIMESTAMP_STRUCT* {.final, pure.} = object
-    Year*: SqlUSmallInt
-    Month*: SqlUSmallInt
-    Day*: SqlUSmallInt
-    Hour*: SqlUSmallInt
-    Minute*: SqlUSmallInt
-    Second*: SqlUSmallInt
-    Fraction*: SqlUInteger
-
-  PSQL_TIMESTAMP_STRUCT* = ptr SQL_TIMESTAMP_STRUCT
-
-const
-  SQL_NAME_LEN* = 128
-  SQL_OV_ODBC3* = 3
-  SQL_OV_ODBC2* = 2
-  SQL_ATTR_ODBC_VERSION* = 200 # Options for SQLDriverConnect
-  SQL_DRIVER_NOPROMPT* = 0
-  SQL_DRIVER_COMPLETE* = 1
-  SQL_DRIVER_PROMPT* = 2
-  SQL_DRIVER_COMPLETE_REQUIRED* = 3
-  SQL_IS_POINTER* = (- 4)  # whether an attribute is a pointer or not
-  SQL_IS_UINTEGER* = (- 5)
-  SQL_IS_INTEGER* = (- 6)
-  SQL_IS_USMALLINT* = (- 7)
-  SQL_IS_SMALLINT* = (- 8)    # SQLExtendedFetch "fFetchType" values
-  SQL_FETCH_BOOKMARK* = 8
-  SQL_SCROLL_OPTIONS* = 44    # SQL_USE_BOOKMARKS options
-  SQL_UB_OFF* = 0
-  SQL_UB_ON* = 1
-  SQL_UB_DEFAULT* = SQL_UB_OFF
-  SQL_UB_FIXED* = SQL_UB_ON
-  SQL_UB_VARIABLE* = 2        # SQL_SCROLL_OPTIONS masks
-  SQL_SO_FORWARD_ONLY* = 0x00000001
-  SQL_SO_KEYSET_DRIVEN* = 0x00000002
-  SQL_SO_DYNAMIC* = 0x00000004
-  SQL_SO_MIXED* = 0x00000008
-  SQL_SO_STATIC* = 0x00000010
-  SQL_BOOKMARK_PERSISTENCE* = 82
-  SQL_STATIC_SENSITIVITY* = 83 # SQL_BOOKMARK_PERSISTENCE values
-  SQL_BP_CLOSE* = 0x00000001
-  SQL_BP_DELETE* = 0x00000002
-  SQL_BP_DROP* = 0x00000004
-  SQL_BP_TRANSACTION* = 0x00000008
-  SQL_BP_UPDATE* = 0x00000010
-  SQL_BP_OTHER_HSTMT* = 0x00000020
-  SQL_BP_SCROLL* = 0x00000040
-  SQL_DYNAMIC_CURSOR_ATTRIBUTES1* = 144
-  SQL_DYNAMIC_CURSOR_ATTRIBUTES2* = 145
-  SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1* = 146
-  SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES2* = 147
-  SQL_INDEX_KEYWORDS* = 148
-  SQL_INFO_SCHEMA_VIEWS* = 149
-  SQL_KEYSET_CURSOR_ATTRIBUTES1* = 150
-  SQL_KEYSET_CURSOR_ATTRIBUTES2* = 151
-  SQL_STATIC_CURSOR_ATTRIBUTES1* = 167
-  SQL_STATIC_CURSOR_ATTRIBUTES2* = 168 # supported SQLFetchScroll FetchOrientation's
-  SQL_CA1_NEXT* = 1
-  SQL_CA1_ABSOLUTE* = 2
-  SQL_CA1_RELATIVE* = 4
-  SQL_CA1_BOOKMARK* = 8       # supported SQLSetPos LockType's
-  SQL_CA1_LOCK_NO_CHANGE* = 0x00000040
-  SQL_CA1_LOCK_EXCLUSIVE* = 0x00000080
-  SQL_CA1_LOCK_UNLOCK* = 0x00000100 # supported SQLSetPos Operations
-  SQL_CA1_POS_POSITION* = 0x00000200
-  SQL_CA1_POS_UPDATE* = 0x00000400
-  SQL_CA1_POS_DELETE* = 0x00000800
-  SQL_CA1_POS_REFRESH* = 0x00001000 # positioned updates and deletes
-  SQL_CA1_POSITIONED_UPDATE* = 0x00002000
-  SQL_CA1_POSITIONED_DELETE* = 0x00004000
-  SQL_CA1_SELECT_FOR_UPDATE* = 0x00008000 # supported SQLBulkOperations operations
-  SQL_CA1_BULK_ADD* = 0x00010000
-  SQL_CA1_BULK_UPDATE_BY_BOOKMARK* = 0x00020000
-  SQL_CA1_BULK_DELETE_BY_BOOKMARK* = 0x00040000
-  SQL_CA1_BULK_FETCH_BY_BOOKMARK* = 0x00080000 # supported values for SQL_ATTR_SCROLL_CONCURRENCY
-  SQL_CA2_READ_ONLY_CONCURRENCY* = 1
-  SQL_CA2_LOCK_CONCURRENCY* = 2
-  SQL_CA2_OPT_ROWVER_CONCURRENCY* = 4
-  SQL_CA2_OPT_VALUES_CONCURRENCY* = 8 # sensitivity of the cursor to its own inserts, deletes, and updates
-  SQL_CA2_SENSITIVITY_ADDITIONS* = 0x00000010
-  SQL_CA2_SENSITIVITY_DELETIONS* = 0x00000020
-  SQL_CA2_SENSITIVITY_UPDATES* = 0x00000040 #  semantics of SQL_ATTR_MAX_ROWS
-  SQL_CA2_MAX_ROWS_SELECT* = 0x00000080
-  SQL_CA2_MAX_ROWS_INSERT* = 0x00000100
-  SQL_CA2_MAX_ROWS_DELETE* = 0x00000200
-  SQL_CA2_MAX_ROWS_UPDATE* = 0x00000400
-  SQL_CA2_MAX_ROWS_CATALOG* = 0x00000800
-  SQL_CA2_MAX_ROWS_AFFECTS_ALL* = (SQL_CA2_MAX_ROWS_SELECT or
-      SQL_CA2_MAX_ROWS_INSERT or SQL_CA2_MAX_ROWS_DELETE or
-      SQL_CA2_MAX_ROWS_UPDATE or SQL_CA2_MAX_ROWS_CATALOG) # semantics of
-                                                           # SQL_DIAG_CURSOR_ROW_COUNT
-  SQL_CA2_CRC_EXACT* = 0x00001000
-  SQL_CA2_CRC_APPROXIMATE* = 0x00002000 #  the kinds of positioned statements that can be simulated
-  SQL_CA2_SIMULATE_NON_UNIQUE* = 0x00004000
-  SQL_CA2_SIMULATE_TRY_UNIQUE* = 0x00008000
-  SQL_CA2_SIMULATE_UNIQUE* = 0x00010000 #  Operations in SQLBulkOperations
-  SQL_ADD* = 4
-  SQL_SETPOS_MAX_OPTION_VALUE* = SQL_ADD
-  SQL_UPDATE_BY_BOOKMARK* = 5
-  SQL_DELETE_BY_BOOKMARK* = 6
-  SQL_FETCH_BY_BOOKMARK* = 7  # Operations in SQLSetPos
-  SQL_POSITION* = 0
-  SQL_REFRESH* = 1
-  SQL_UPDATE* = 2
-  SQL_DELETE* = 3             # Lock options in SQLSetPos
-  SQL_LOCK_NO_CHANGE* = 0
-  SQL_LOCK_EXCLUSIVE* = 1
-  SQL_LOCK_UNLOCK* = 2        # SQLExtendedFetch "rgfRowStatus" element values
-  SQL_ROW_SUCCESS* = 0
-  SQL_ROW_DELETED* = 1
-  SQL_ROW_UPDATED* = 2
-  SQL_ROW_NOROW* = 3
-  SQL_ROW_ADDED* = 4
-  SQL_ROW_ERROR* = 5
-  SQL_ROW_SUCCESS_WITH_INFO* = 6
-  SQL_ROW_PROCEED* = 0
-  SQL_ROW_IGNORE* = 1
-  SQL_MAX_DSN_LENGTH* = 32    # maximum data source name size
-  SQL_MAX_OPTION_STRING_LENGTH* = 256
-  SQL_ODBC_CURSORS* = 110
-  SQL_ATTR_ODBC_CURSORS* = SQL_ODBC_CURSORS # SQL_ODBC_CURSORS options
-  SQL_CUR_USE_IF_NEEDED* = 0
-  SQL_CUR_USE_ODBC* = 1
-  SQL_CUR_USE_DRIVER* = 2
-  SQL_CUR_DEFAULT* = SQL_CUR_USE_DRIVER
-  SQL_PARAM_TYPE_UNKNOWN* = 0
-  SQL_PARAM_INPUT* = 1
-  SQL_PARAM_INPUT_OUTPUT* = 2
-  SQL_RESULT_COL* = 3
-  SQL_PARAM_OUTPUT* = 4
-  SQL_RETURN_VALUE* = 5       # special length/indicator values
-  SQL_NULL_DATA* = (- 1)
-  SQL_DATA_AT_EXEC* = (- 2)
-  SQL_SUCCESS* = 0
-  SQL_SUCCESS_WITH_INFO* = 1
-  SQL_NO_DATA* = 100
-  SQL_ERROR* = (- 1)
-  SQL_INVALID_HANDLE* = (- 2)
-  SQL_STILL_EXECUTING* = 2
-  SQL_NEED_DATA* = 99         # flags for null-terminated string
-  SQL_NTS* = (- 3)            # maximum message length
-  SQL_MAX_MESSAGE_LENGTH* = 512 # date/time length constants
-  SQL_DATE_LEN* = 10
-  SQL_TIME_LEN* = 8           # add P+1 if precision is nonzero
-  SQL_TIMESTAMP_LEN* = 19     # add P+1 if precision is nonzero
-                              # handle type identifiers
-  SQL_HANDLE_ENV* = 1
-  SQL_HANDLE_DBC* = 2
-  SQL_HANDLE_STMT* = 3
-  SQL_HANDLE_DESC* = 4        # environment attribute
-  SQL_ATTR_OUTPUT_NTS* = 10001 # connection attributes
-  SQL_ATTR_AUTO_IPD* = 10001
-  SQL_ATTR_METADATA_ID* = 10014 # statement attributes
-  SQL_ATTR_APP_ROW_DESC* = 10010
-  SQL_ATTR_APP_PARAM_DESC* = 10011
-  SQL_ATTR_IMP_ROW_DESC* = 10012
-  SQL_ATTR_IMP_PARAM_DESC* = 10013
-  SQL_ATTR_CURSOR_SCROLLABLE* = (- 1)
-  SQL_ATTR_CURSOR_SENSITIVITY* = (- 2)
-  SQL_QUERY_TIMEOUT* = 0
-  SQL_MAX_ROWS* = 1
-  SQL_NOSCAN* = 2
-  SQL_MAX_LENGTH* = 3
-  SQL_ASYNC_ENABLE* = 4       # same as SQL_ATTR_ASYNC_ENABLE */
-  SQL_BIND_TYPE* = 5
-  SQL_CURSOR_TYPE* = 6
-  SQL_CONCURRENCY* = 7
-  SQL_KEYSET_SIZE* = 8
-  SQL_ROWSET_SIZE* = 9
-  SQL_SIMULATE_CURSOR* = 10
-  SQL_RETRIEVE_DATA* = 11
-  SQL_USE_BOOKMARKS* = 12
-  SQL_GET_BOOKMARK* = 13      #      GetStmtOption Only */
-  SQL_ROW_NUMBER* = 14        #      GetStmtOption Only */
-  SQL_ATTR_CURSOR_TYPE* = SQL_CURSOR_TYPE
-  SQL_ATTR_CONCURRENCY* = SQL_CONCURRENCY
-  SQL_ATTR_FETCH_BOOKMARK_PTR* = 16
-  SQL_ATTR_ROW_STATUS_PTR* = 25
-  SQL_ATTR_ROWS_FETCHED_PTR* = 26
-  SQL_AUTOCOMMIT* = 102
-  SQL_ATTR_AUTOCOMMIT* = SQL_AUTOCOMMIT
-  SQL_ATTR_ROW_NUMBER* = SQL_ROW_NUMBER
-  SQL_TXN_ISOLATION* = 108
-  SQL_ATTR_TXN_ISOLATION* = SQL_TXN_ISOLATION
-  SQL_ATTR_MAX_ROWS* = SQL_MAX_ROWS
-  SQL_ATTR_USE_BOOKMARKS* = SQL_USE_BOOKMARKS #* connection attributes */
-  SQL_ACCESS_MODE* = 101      #  SQL_AUTOCOMMIT              =102;
-  SQL_LOGIN_TIMEOUT* = 103
-  SQL_OPT_TRACE* = 104
-  SQL_OPT_TRACEFILE* = 105
-  SQL_TRANSLATE_DLL* = 106
-  SQL_TRANSLATE_OPTION* = 107 #  SQL_TXN_ISOLATION           =108;
-  SQL_CURRENT_QUALIFIER* = 109 #  SQL_ODBC_CURSORS            =110;
-  SQL_QUIET_MODE* = 111
-  SQL_PACKET_SIZE* = 112      #* connection attributes with new names */
-  SQL_ATTR_ACCESS_MODE* = SQL_ACCESS_MODE #  SQL_ATTR_AUTOCOMMIT                       =SQL_AUTOCOMMIT;
-  SQL_ATTR_CONNECTION_DEAD* = 1209 #* GetConnectAttr only */
-  SQL_ATTR_CONNECTION_TIMEOUT* = 113
-  SQL_ATTR_CURRENT_CATALOG* = SQL_CURRENT_QUALIFIER
-  SQL_ATTR_DISCONNECT_BEHAVIOR* = 114
-  SQL_ATTR_ENLIST_IN_DTC* = 1207
-  SQL_ATTR_ENLIST_IN_XA* = 1208
-  SQL_ATTR_LOGIN_TIMEOUT* = SQL_LOGIN_TIMEOUT #  SQL_ATTR_ODBC_CURSORS             =SQL_ODBC_CURSORS;
-  SQL_ATTR_PACKET_SIZE* = SQL_PACKET_SIZE
-  SQL_ATTR_QUIET_MODE* = SQL_QUIET_MODE
-  SQL_ATTR_TRACE* = SQL_OPT_TRACE
-  SQL_ATTR_TRACEFILE* = SQL_OPT_TRACEFILE
-  SQL_ATTR_TRANSLATE_LIB* = SQL_TRANSLATE_DLL
-  SQL_ATTR_TRANSLATE_OPTION* = SQL_TRANSLATE_OPTION #  SQL_ATTR_TXN_ISOLATION                  =SQL_TXN_ISOLATION;
-                                                    #* SQL_ACCESS_MODE options */
-  SQL_MODE_READ_WRITE* = 0
-  SQL_MODE_READ_ONLY* = 1
-  SQL_MODE_DEFAULT* = SQL_MODE_READ_WRITE #* SQL_AUTOCOMMIT options */
-  SQL_AUTOCOMMIT_OFF* = 0
-  SQL_AUTOCOMMIT_ON* = 1
-  SQL_AUTOCOMMIT_DEFAULT* = SQL_AUTOCOMMIT_ON # SQL_ATTR_CURSOR_SCROLLABLE values
-  SQL_NONSCROLLABLE* = 0
-  SQL_SCROLLABLE* = 1         # SQL_CURSOR_TYPE options
-  SQL_CURSOR_FORWARD_ONLY* = 0
-  SQL_CURSOR_KEYSET_DRIVEN* = 1
-  SQL_CURSOR_DYNAMIC* = 2
-  SQL_CURSOR_STATIC* = 3
-  SQL_CURSOR_TYPE_DEFAULT* = SQL_CURSOR_FORWARD_ONLY # Default value
-                                                     # SQL_CONCURRENCY options
-  SQL_CONCUR_READ_ONLY* = 1
-  SQL_CONCUR_LOCK* = 2
-  SQL_CONCUR_ROWVER* = 3
-  SQL_CONCUR_VALUES* = 4
-  SQL_CONCUR_DEFAULT* = SQL_CONCUR_READ_ONLY # Default value
-                                             # identifiers of fields in the SQL descriptor
-  SQL_DESC_COUNT* = 1001
-  SQL_DESC_TYPE* = 1002
-  SQL_DESC_LENGTH* = 1003
-  SQL_DESC_OCTET_LENGTH_PTR* = 1004
-  SQL_DESC_PRECISION* = 1005
-  SQL_DESC_SCALE* = 1006
-  SQL_DESC_DATETIME_INTERVAL_CODE* = 1007
-  SQL_DESC_NULLABLE* = 1008
-  SQL_DESC_INDICATOR_PTR* = 1009
-  SQL_DESC_DATA_PTR* = 1010
-  SQL_DESC_NAME* = 1011
-  SQL_DESC_UNNAMED* = 1012
-  SQL_DESC_OCTET_LENGTH* = 1013
-  SQL_DESC_ALLOC_TYPE* = 1099 # identifiers of fields in the diagnostics area
-  SQL_DIAG_RETURNCODE* = 1
-  SQL_DIAG_NUMBER* = 2
-  SQL_DIAG_ROW_COUNT* = 3
-  SQL_DIAG_SQLSTATE* = 4
-  SQL_DIAG_NATIVE* = 5
-  SQL_DIAG_MESSAGE_TEXT* = 6
-  SQL_DIAG_DYNAMIC_FUNCTION* = 7
-  SQL_DIAG_CLASS_ORIGIN* = 8
-  SQL_DIAG_SUBCLASS_ORIGIN* = 9
-  SQL_DIAG_CONNECTION_NAME* = 10
-  SQL_DIAG_SERVER_NAME* = 11
-  SQL_DIAG_DYNAMIC_FUNCTION_CODE* = 12 # dynamic function codes
-  SQL_DIAG_ALTER_TABLE* = 4
-  SQL_DIAG_CREATE_INDEX* = (- 1)
-  SQL_DIAG_CREATE_TABLE* = 77
-  SQL_DIAG_CREATE_VIEW* = 84
-  SQL_DIAG_DELETE_WHERE* = 19
-  SQL_DIAG_DROP_INDEX* = (- 2)
-  SQL_DIAG_DROP_TABLE* = 32
-  SQL_DIAG_DROP_VIEW* = 36
-  SQL_DIAG_DYNAMIC_DELETE_CURSOR* = 38
-  SQL_DIAG_DYNAMIC_UPDATE_CURSOR* = 81
-  SQL_DIAG_GRANT* = 48
-  SQL_DIAG_INSERT* = 50
-  SQL_DIAG_REVOKE* = 59
-  SQL_DIAG_SELECT_CURSOR* = 85
-  SQL_DIAG_UNKNOWN_STATEMENT* = 0
-  SQL_DIAG_UPDATE_WHERE* = 82 # Statement attribute values for cursor sensitivity
-  SQL_UNSPECIFIED* = 0
-  SQL_INSENSITIVE* = 1
-  SQL_SENSITIVE* = 2          # GetTypeInfo() request for all data types
-  SQL_ALL_TYPES* = 0          # Default conversion code for SQLBindCol(), SQLBindParam() and SQLGetData()
-  SQL_DEFAULT* = 99 # SQLGetData() code indicating that the application row descriptor
-                    #    specifies the data type
-  SQL_ARD_TYPE* = (- 99)      # SQL date/time type subcodes
-  SQL_CODE_DATE* = 1
-  SQL_CODE_TIME* = 2
-  SQL_CODE_TIMESTAMP* = 3     # CLI option values
-  SQL_FALSE* = 0
-  SQL_TRUE* = 1               # values of NULLABLE field in descriptor
-  SQL_NO_NULLS* = 0
-  SQL_NULLABLE* = 1 # Value returned by SQLGetTypeInfo() to denote that it is
-                    # not known whether or not a data type supports null values.
-  SQL_NULLABLE_UNKNOWN* = 2
-  SQL_CLOSE* = 0
-  SQL_DROP* = 1
-  SQL_UNBIND* = 2
-  SQL_RESET_PARAMS* = 3 # Codes used for FetchOrientation in SQLFetchScroll(),
-                        #   and in SQLDataSources()
-  SQL_FETCH_NEXT* = 1
-  SQL_FETCH_FIRST* = 2
-  SQL_FETCH_FIRST_USER* = 31
-  SQL_FETCH_FIRST_SYSTEM* = 32 # Other codes used for FetchOrientation in SQLFetchScroll()
-  SQL_FETCH_LAST* = 3
-  SQL_FETCH_PRIOR* = 4
-  SQL_FETCH_ABSOLUTE* = 5
-  SQL_FETCH_RELATIVE* = 6
-  SQL_NULL_HENV* = SqlHEnv(nil)
-  SQL_NULL_HDBC* = SqlHDBC(nil)
-  SQL_NULL_HSTMT* = SqlHStmt(nil)
-  SQL_NULL_HDESC* = SqlHDesc(nil) #* null handle used in place of parent handle when allocating HENV */
-  SQL_NULL_HANDLE* = SqlHandle(nil) #* Values that may appear in the result set of SQLSpecialColumns() */
-  SQL_SCOPE_CURROW* = 0
-  SQL_SCOPE_TRANSACTION* = 1
-  SQL_SCOPE_SESSION* = 2      #* Column types and scopes in SQLSpecialColumns.  */
-  SQL_BEST_ROWID* = 1
-  SQL_ROWVER* = 2
-  SQL_ROW_IDENTIFIER* = 1     #* Reserved values for UNIQUE argument of SQLStatistics() */
-  SQL_INDEX_UNIQUE* = 0
-  SQL_INDEX_ALL* = 1          #* Reserved values for RESERVED argument of SQLStatistics() */
-  SQL_QUICK* = 0
-  SQL_ENSURE* = 1             #* Values that may appear in the result set of SQLStatistics() */
-  SQL_TABLE_STAT* = 0
-  SQL_INDEX_CLUSTERED* = 1
-  SQL_INDEX_HASHED* = 2
-  SQL_INDEX_OTHER* = 3
-  SQL_SCROLL_CONCURRENCY* = 43
-  SQL_TXN_CAPABLE* = 46
-  SQL_TRANSACTION_CAPABLE* = SQL_TXN_CAPABLE
-  SQL_USER_NAME* = 47
-  SQL_TXN_ISOLATION_OPTION* = 72
-  SQL_TRANSACTION_ISOLATION_OPTION* = SQL_TXN_ISOLATION_OPTION
-  SQL_OJ_CAPABILITIES* = 115
-  SQL_OUTER_JOIN_CAPABILITIES* = SQL_OJ_CAPABILITIES
-  SQL_XOPEN_CLI_YEAR* = 10000
-  SQL_CURSOR_SENSITIVITY* = 10001
-  SQL_DESCRIBE_PARAMETER* = 10002
-  SQL_CATALOG_NAME* = 10003
-  SQL_COLLATION_SEQ* = 10004
-  SQL_MAX_IDENTIFIER_LEN* = 10005
-  SQL_MAXIMUM_IDENTIFIER_LENGTH* = SQL_MAX_IDENTIFIER_LEN
-  SQL_SCCO_READ_ONLY* = 1
-  SQL_SCCO_LOCK* = 2
-  SQL_SCCO_OPT_ROWVER* = 4
-  SQL_SCCO_OPT_VALUES* = 8    #* SQL_TXN_CAPABLE values */
-  SQL_TC_NONE* = 0
-  SQL_TC_DML* = 1
-  SQL_TC_ALL* = 2
-  SQL_TC_DDL_COMMIT* = 3
-  SQL_TC_DDL_IGNORE* = 4      #* SQL_TXN_ISOLATION_OPTION bitmasks */
-  SQL_TXN_READ_UNCOMMITTED* = 1
-  SQL_TRANSACTION_READ_UNCOMMITTED* = SQL_TXN_READ_UNCOMMITTED
-  SQL_TXN_READ_COMMITTED* = 2
-  SQL_TRANSACTION_READ_COMMITTED* = SQL_TXN_READ_COMMITTED
-  SQL_TXN_REPEATABLE_READ* = 4
-  SQL_TRANSACTION_REPEATABLE_READ* = SQL_TXN_REPEATABLE_READ
-  SQL_TXN_SERIALIZABLE* = 8
-  SQL_TRANSACTION_SERIALIZABLE* = SQL_TXN_SERIALIZABLE
-  SQL_SS_ADDITIONS* = 1
-  SQL_SS_DELETIONS* = 2
-  SQL_SS_UPDATES* = 4         # SQLColAttributes defines
-  SQL_COLUMN_COUNT* = 0
-  SQL_COLUMN_NAME* = 1
-  SQL_COLUMN_TYPE* = 2
-  SQL_COLUMN_LENGTH* = 3
-  SQL_COLUMN_PRECISION* = 4
-  SQL_COLUMN_SCALE* = 5
-  SQL_COLUMN_DISPLAY_SIZE* = 6
-  SQL_COLUMN_NULLABLE* = 7
-  SQL_COLUMN_UNSIGNED* = 8
-  SQL_COLUMN_MONEY* = 9
-  SQL_COLUMN_UPDATABLE* = 10
-  SQL_COLUMN_AUTO_INCREMENT* = 11
-  SQL_COLUMN_CASE_SENSITIVE* = 12
-  SQL_COLUMN_SEARCHABLE* = 13
-  SQL_COLUMN_TYPE_NAME* = 14
-  SQL_COLUMN_TABLE_NAME* = 15
-  SQL_COLUMN_OWNER_NAME* = 16
-  SQL_COLUMN_QUALIFIER_NAME* = 17
-  SQL_COLUMN_LABEL* = 18
-  SQL_COLATT_OPT_MAX* = SQL_COLUMN_LABEL
-  SQL_COLUMN_DRIVER_START* = 1000
-  SQL_DESC_ARRAY_SIZE* = 20
-  SQL_DESC_ARRAY_STATUS_PTR* = 21
-  SQL_DESC_AUTO_UNIQUE_VALUE* = SQL_COLUMN_AUTO_INCREMENT
-  SQL_DESC_BASE_COLUMN_NAME* = 22
-  SQL_DESC_BASE_TABLE_NAME* = 23
-  SQL_DESC_BIND_OFFSET_PTR* = 24
-  SQL_DESC_BIND_TYPE* = 25
-  SQL_DESC_CASE_SENSITIVE* = SQL_COLUMN_CASE_SENSITIVE
-  SQL_DESC_CATALOG_NAME* = SQL_COLUMN_QUALIFIER_NAME
-  SQL_DESC_CONCISE_TYPE* = SQL_COLUMN_TYPE
-  SQL_DESC_DATETIME_INTERVAL_PRECISION* = 26
-  SQL_DESC_DISPLAY_SIZE* = SQL_COLUMN_DISPLAY_SIZE
-  SQL_DESC_FIXED_PREC_SCALE* = SQL_COLUMN_MONEY
-  SQL_DESC_LABEL* = SQL_COLUMN_LABEL
-  SQL_DESC_LITERAL_PREFIX* = 27
-  SQL_DESC_LITERAL_SUFFIX* = 28
-  SQL_DESC_LOCAL_TYPE_NAME* = 29
-  SQL_DESC_MAXIMUM_SCALE* = 30
-  SQL_DESC_MINIMUM_SCALE* = 31
-  SQL_DESC_NUM_PREC_RADIX* = 32
-  SQL_DESC_PARAMETER_TYPE* = 33
-  SQL_DESC_ROWS_PROCESSED_PTR* = 34
-  SQL_DESC_SCHEMA_NAME* = SQL_COLUMN_OWNER_NAME
-  SQL_DESC_SEARCHABLE* = SQL_COLUMN_SEARCHABLE
-  SQL_DESC_TYPE_NAME* = SQL_COLUMN_TYPE_NAME
-  SQL_DESC_TABLE_NAME* = SQL_COLUMN_TABLE_NAME
-  SQL_DESC_UNSIGNED* = SQL_COLUMN_UNSIGNED
-  SQL_DESC_UPDATABLE* = SQL_COLUMN_UPDATABLE #* SQLEndTran() options */
-  SQL_COMMIT* = 0
-  SQL_ROLLBACK* = 1
-  SQL_ATTR_ROW_ARRAY_SIZE* = 27 #* SQLConfigDataSource() options */
-  ODBC_ADD_DSN* = 1
-  ODBC_CONFIG_DSN* = 2
-  ODBC_REMOVE_DSN* = 3
-  ODBC_ADD_SYS_DSN* = 4
-  ODBC_CONFIG_SYS_DSN* = 5
-  ODBC_REMOVE_SYS_DSN* = 6
-
-  SQL_ACTIVE_CONNECTIONS* = 0   # SQLGetInfo
-  SQL_DATA_SOURCE_NAME* = 2
-  SQL_DATA_SOURCE_READ_ONLY* = 25
-  SQL_DATABASE_NAME* = 2
-  SQL_DBMS_NAME* = 17
-  SQL_DBMS_VERSION* = 18
-  SQL_DRIVER_HDBC* = 3
-  SQL_DRIVER_HENV* = 4
-  SQL_DRIVER_HSTMT* = 5
-  SQL_DRIVER_NAME* = 6
-  SQL_DRIVER_VER* = 7
-  SQL_FETCH_DIRECTION* = 8
-  SQL_ODBC_VER* = 10
-  SQL_DRIVER_ODBC_VER* = 77
-  SQL_SERVER_NAME* = 13
-  SQL_ACTIVE_ENVIRONMENTS* = 116
-  SQL_ACTIVE_STATEMENTS* = 1
-  SQL_SQL_CONFORMANCE* = 118
-  SQL_DATETIME_LITERALS* = 119
-  SQL_ASYNC_MODE* = 10021
-  SQL_BATCH_ROW_COUNT* = 120
-  SQL_BATCH_SUPPORT* = 121
-  SQL_CATALOG_LOCATION* = 114
-  #SQL_CATALOG_NAME* = 10003
-  SQL_CATALOG_NAME_SEPARATOR* = 41
-  SQL_CATALOG_TERM* = 42
-  SQL_CATALOG_USAGE* = 92
-  #SQL_COLLATION_SEQ* = 10004
-  SQL_COLUMN_ALIAS* = 87
-  #SQL_USER_NAME* = 47
-
-proc SQLAllocHandle*(HandleType: TSqlSmallInt, InputHandle: SqlHandle,
-                     OutputHandlePtr: var SqlHandle): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLSetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
-                    Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLGetEnvAttr*(EnvironmentHandle: SqlHEnv, Attribute: TSqlInteger,
-                    Value: SqlPointer, BufferLength: TSqlInteger,
-                    StringLength: PSQLINTEGER): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLFreeHandle*(HandleType: TSqlSmallInt, Handle: SqlHandle): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLGetDiagRec*(HandleType: TSqlSmallInt, Handle: SqlHandle,
-                    RecNumber: TSqlSmallInt, Sqlstate: PSQLCHAR,
-                    NativeError: var TSqlInteger, MessageText: PSQLCHAR,
-                    BufferLength: TSqlSmallInt, TextLength: var TSqlSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLGetDiagField*(HandleType: TSqlSmallInt, Handle: SqlHandle,
-                      RecNumber: TSqlSmallInt, DiagIdentifier: TSqlSmallInt,
-                      DiagInfoPtr: SqlPointer, BufferLength: TSqlSmallInt,
-                      StringLengthPtr: var TSqlSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLConnect*(ConnectionHandle: SqlHDBC, ServerName: PSQLCHAR,
-                 NameLength1: TSqlSmallInt, UserName: PSQLCHAR,
-                 NameLength2: TSqlSmallInt, Authentication: PSQLCHAR,
-                 NameLength3: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLDisconnect*(ConnectionHandle: SqlHDBC): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLDriverConnect*(hdbc: SqlHDBC, hwnd: SqlHWND, szCsin: cstring,
-                       szCLen: TSqlSmallInt, szCsout: cstring,
-                       cbCSMax: TSqlSmallInt, cbCsOut: var TSqlSmallInt,
-                       f: SqlUSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLBrowseConnect*(hdbc: SqlHDBC, szConnStrIn: PSQLCHAR,
-                       cbConnStrIn: TSqlSmallInt, szConnStrOut: PSQLCHAR,
-                       cbConnStrOutMax: TSqlSmallInt,
-                       cbConnStrOut: var TSqlSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLExecDirect*(StatementHandle: SqlHStmt, StatementText: PSQLCHAR,
-                    TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLExecDirectW*(StatementHandle: SqlHStmt, StatementText: WideCString,
-                    TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLPrepare*(StatementHandle: SqlHStmt, StatementText: PSQLCHAR,
-                 TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLPrepareW*(StatementHandle: SqlHStmt, StatementText: WideCString,
-                 TextLength: TSqlInteger): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLCloseCursor*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLExecute*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLFetch*(StatementHandle: SqlHStmt): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLNumResultCols*(StatementHandle: SqlHStmt, ColumnCount: var TSqlSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLDescribeCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
-                     ColumnName: PSQLCHAR, BufferLength: TSqlSmallInt,
-                     NameLength: var TSqlSmallInt, DataType: var TSqlSmallInt,
-                     ColumnSize: var TSqlULen,
-                     DecimalDigits: var TSqlSmallInt, Nullable: var TSqlSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLFetchScroll*(StatementHandle: SqlHStmt, FetchOrientation: TSqlSmallInt,
-                     FetchOffset: TSqlLen): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLExtendedFetch*(hstmt: SqlHStmt, fFetchType: SqlUSmallInt,
-                       irow: TSqlLen, pcrow: var TSqlULen,
-                       rgfRowStatus: PSQLUSMALLINT): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLGetData*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
-                 TargetType: TSqlSmallInt, TargetValue: SqlPointer,
-                 BufferLength: TSqlLen, StrLen_or_Ind: ptr TSqlLen): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLSetStmtAttr*(StatementHandle: SqlHStmt, Attribute: TSqlInteger,
-                     Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLGetStmtAttr*(StatementHandle: SqlHStmt, Attribute: TSqlInteger,
-                     Value: SqlPointer, BufferLength: TSqlInteger,
-                     StringLength: PSQLINTEGER): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLGetInfo*(ConnectionHandle: SqlHDBC, InfoType: SqlUSmallInt,
-                 InfoValue: SqlPointer, BufferLength: TSqlSmallInt,
-                 StringLength: PSQLSMALLINT): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLBulkOperations*(StatementHandle: SqlHStmt, Operation: SqlUSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLPutData*(StatementHandle: SqlHStmt, Data: SqlPointer,
-                 StrLen_or_Ind: TSQLLEN): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLBindCol*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
-                 TargetType: TSqlSmallInt, TargetValue: SqlPointer,
-                 BufferLength: TSqlLEN, StrLen_or_Ind: PSQLINTEGER): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLSetPos*(hstmt: SqlHStmt, irow: SqlUSmallInt, fOption: SqlUSmallInt,
-                fLock: SqlUSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLDataSources*(EnvironmentHandle: SqlHEnv, Direction: SqlUSmallInt,
-                     ServerName: PSQLCHAR, BufferLength1: TSqlSmallInt,
-                     NameLength1: PSQLSMALLINT, Description: PSQLCHAR,
-                     BufferLength2: TSqlSmallInt, NameLength2: PSQLSMALLINT): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLDrivers*(EnvironmentHandle: SqlHEnv, Direction: SqlUSmallInt,
-                 DriverDescription: PSQLCHAR, BufferLength1: TSqlSmallInt,
-                 DescriptionLength1: PSQLSMALLINT, DriverAttributes: PSQLCHAR,
-                 BufferLength2: TSqlSmallInt, AttributesLength2: PSQLSMALLINT): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLSetConnectAttr*(ConnectionHandle: SqlHDBC, Attribute: TSqlInteger,
-                        Value: SqlPointer, StringLength: TSqlInteger): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLGetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
-                       BufferLength: TSqlSmallInt, NameLength: PSQLSMALLINT): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLSetCursorName*(StatementHandle: SqlHStmt, CursorName: PSQLCHAR,
-                       NameLength: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLRowCount*(StatementHandle: SqlHStmt, RowCount: var TSQLLEN): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLBindParameter*(hstmt: SqlHStmt, ipar: SqlUSmallInt,
-                       fParamType: TSqlSmallInt, fCType: TSqlSmallInt,
-                       fSqlType: TSqlSmallInt, cbColDef: TSQLULEN,
-                       ibScale: TSqlSmallInt, rgbValue: SqlPointer,
-                       cbValueMax: TSQLLEN, pcbValue: var TSQLLEN): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLFreeStmt*(StatementHandle: SqlHStmt, Option: SqlUSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLColAttribute*(StatementHandle: SqlHStmt, ColumnNumber: SqlUSmallInt,
-                      FieldIdentifier: SqlUSmallInt,
-                      CharacterAttribute: PSQLCHAR, BufferLength: TSqlSmallInt,
-                      StringLength: PSQLSMALLINT,
-                      NumericAttribute: TSQLLEN): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLEndTran*(HandleType: TSqlSmallInt, Handle: SqlHandle,
-                 CompletionType: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLTables*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
-                cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
-                cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
-                cbTableName: TSqlSmallInt, szTableType: PSQLCHAR,
-                cbTableType: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLColumns*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
-                 cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
-                 cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
-                 cbTableName: TSqlSmallInt, szColumnName: PSQLCHAR,
-                 cbColumnName: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib, importc.}
-proc SQLSpecialColumns*(StatementHandle: SqlHStmt, IdentifierType: SqlUSmallInt,
-                        CatalogName: PSQLCHAR, NameLength1: TSqlSmallInt,
-                        SchemaName: PSQLCHAR, NameLength2: TSqlSmallInt,
-                        TableName: PSQLCHAR, NameLength3: TSqlSmallInt,
-                        Scope: SqlUSmallInt,
-                        Nullable: SqlUSmallInt): TSqlSmallInt{.
-    dynlib: odbclib, importc.}
-proc SQLProcedures*(hstmt: SqlHStmt, szTableQualifier: PSQLCHAR,
-                    cbTableQualifier: TSqlSmallInt, szTableOwner: PSQLCHAR,
-                    cbTableOwner: TSqlSmallInt, szTableName: PSQLCHAR,
-                    cbTableName: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLPrimaryKeys*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
-                     NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
-                     NameLength2: TSqlSmallInt, TableName: PSQLCHAR,
-                     NameLength3: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLProcedureColumns*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
-                          NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
-                          NameLength2: TSqlSmallInt, ProcName: PSQLCHAR,
-                          NameLength3: TSqlSmallInt, ColumnName: PSQLCHAR,
-                          NameLength4: TSqlSmallInt): TSqlSmallInt{.dynlib: odbclib,
-    importc.}
-proc SQLStatistics*(hstmt: SqlHStmt, CatalogName: PSQLCHAR,
-                    NameLength1: TSqlSmallInt, SchemaName: PSQLCHAR,
-                    NameLength2: TSqlSmallInt, TableName: PSQLCHAR,
-                    NameLength3: TSqlSmallInt, Unique: SqlUSmallInt,
-                    Reserved: SqlUSmallInt): TSqlSmallInt {.
-                    dynlib: odbclib, importc.}
-proc SQLErr*(henv: SqlHEnv, hdbc: SqlHDBC, hstmt: SqlHStmt,
-              szSqlState, pfNativeError, szErrorMsg: PSQLCHAR,
-              cbErrorMsgMax: TSqlSmallInt,
-              pcbErrorMsg: PSQLSMALLINT): TSqlSmallInt {.
-                    dynlib: odbclib, importc: "SQLError".}
-
-{.pop.}
-when defined(nimHasStyleChecks):
-  {.pop.}
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index b3fe8a608..9921b7ffd 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -10,24 +10,25 @@
 ## OpenSSL wrapper. Supports OpenSSL >= 1.1.0 dynamically (as default) or statically linked
 ## using `--dynlibOverride:ssl`.
 ##
-## `-d:sslVersion=1.2.3` can be used to force an SSL version. 
+## `-d:sslVersion=1.2.3` can be used to force an SSL version.
 ## This version must be included in the library name.
 ## `-d:useOpenssl3` may be set for OpenSSL 3 instead.
-## 
+##
 ## There is also limited support for OpenSSL 1.0.x which may require `-d:openssl10`.
 ##
 ## Build and test examples:
 ##
-## .. code-block::
+##   ```cmd
 ##   ./bin/nim c -d:ssl -p:. -r tests/stdlib/tssl.nim
 ##   ./bin/nim c -d:ssl --threads:on -p:. -r tests/stdlib/thttpclient_ssl.nim
 ##   ./bin/nim c -d:ssl -p:. -r tests/untestable/tssl.nim
 ##   ./bin/nim c -d:ssl -p:. --dynlibOverride:ssl --passl:-lcrypto --passl:-lssl -r tests/untestable/tssl.nim
 ##   ./bin/nim r --putenv:NIM_TESTAMENT_REMOTE_NETWORKING:1 -d:ssl -p:testament/lib --threads:on tests/untestable/thttpclient_ssl_remotenetwork.nim
+##   ```
 
 # https://www.feistyduck.com/library/openssl-cookbook/online/ch-testing-with-openssl.html
 #
-from strutils import startsWith
+from std/strutils import startsWith
 
 when defined(nimPreviewSlimSystem):
   import std/syncio
@@ -50,17 +51,17 @@ when sslVersion != "":
     const
       DLLSSLName* = "libssl." & sslVersion & ".dylib"
       DLLUtilName* = "libcrypto." & sslVersion & ".dylib"
-    from posix import SocketHandle
+    from std/posix import SocketHandle
   elif defined(windows):
     const
       DLLSSLName* = "libssl-" & sslVersion & ".dll"
       DLLUtilName* =  "libcrypto-" & sslVersion & ".dll"
-    from winlean import SocketHandle
+    from std/winlean import SocketHandle
   else:
     const
       DLLSSLName* = "libssl.so." & sslVersion
       DLLUtilName* = "libcrypto.so." & sslVersion
-    from posix import SocketHandle
+    from std/posix import SocketHandle
 
 elif useWinVersion:
   when defined(openssl10) or defined(nimOldDlls):
@@ -81,7 +82,7 @@ elif useWinVersion:
       DLLSSLName* = "(libssl-1_1|ssleay32|libssl32).dll"
       DLLUtilName* = "(libcrypto-1_1|libeay32).dll"
 
-  from winlean import SocketHandle
+  from std/winlean import SocketHandle
 else:
   # same list of versions but ordered differently?
   when defined(osx):
@@ -101,9 +102,9 @@ else:
     const
       DLLSSLName* = "libssl.so" & versions
       DLLUtilName* = "libcrypto.so" & versions
-  from posix import SocketHandle
+  from std/posix import SocketHandle
 
-import dynlib
+import std/dynlib
 
 {.pragma: lcrypto, cdecl, dynlib: DLLUtilName, importc.}
 {.pragma: lssl, cdecl, dynlib: DLLSSLName, importc.}
@@ -467,10 +468,10 @@ else:
       raiseInvalidLibrary MainProc
 
   proc SSL_CTX_set_ciphersuites*(ctx: SslCtx, str: cstring): cint =
-    var theProc {.global.}: proc(ctx: SslCtx, str: cstring) {.cdecl, gcsafe.}
+    var theProc {.global.}: proc(ctx: SslCtx, str: cstring): cint {.cdecl, gcsafe.}
     if theProc.isNil:
       theProc = cast[typeof(theProc)](sslSymThrows("SSL_CTX_set_ciphersuites"))
-    theProc(ctx, str)
+    result = theProc(ctx, str)
 
 proc SSL_new*(context: SslCtx): SslPtr{.cdecl, dynlib: DLLSSLName, importc.}
 proc SSL_free*(ssl: SslPtr){.cdecl, dynlib: DLLSSLName, importc.}
@@ -529,11 +530,8 @@ proc BIO_do_handshake*(bio: BIO): int =
 proc BIO_do_connect*(bio: BIO): int =
   return BIO_do_handshake(bio)
 
-when not defined(nimfix):
-  proc BIO_read*(b: BIO, data: cstring, length: cint): cint{.cdecl,
-      dynlib: DLLUtilName, importc.}
-  proc BIO_write*(b: BIO, data: cstring, length: cint): cint{.cdecl,
-      dynlib: DLLUtilName, importc.}
+proc BIO_read*(b: BIO, data: cstring, length: cint): cint{.cdecl, dynlib: DLLUtilName, importc.}
+proc BIO_write*(b: BIO, data: cstring, length: cint): cint{.cdecl, dynlib: DLLUtilName, importc.}
 
 proc BIO_free*(b: BIO): cint{.cdecl, dynlib: DLLUtilName, importc.}
 
@@ -589,7 +587,7 @@ when not useWinVersion and not defined(macosx) and not defined(android) and useN
     if p != nil: deallocShared(p)
 
   proc CRYPTO_malloc_init*() =
-    CRYPTO_set_mem_functions(allocWrapper, reallocWrapper, deallocWrapper)
+    CRYPTO_set_mem_functions(cast[pointer](allocWrapper), cast[pointer](reallocWrapper), cast[pointer](deallocWrapper))
 else:
   proc CRYPTO_malloc_init*() =
     discard
@@ -781,7 +779,7 @@ proc md5*(d: ptr uint8; n: csize_t; md: ptr uint8): ptr uint8{.importc: "MD5".}
 proc md5_Transform*(c: var MD5_CTX; b: ptr uint8){.importc: "MD5_Transform".}
 {.pop.}
 
-from strutils import toHex, toLowerAscii
+from std/strutils import toHex, toLowerAscii
 
 proc hexStr(buf: cstring): string =
   # turn md5s output into a nice hex str
diff --git a/lib/wrappers/postgres.nim b/lib/wrappers/postgres.nim
deleted file mode 100644
index 6962291f1..000000000
--- a/lib/wrappers/postgres.nim
+++ /dev/null
@@ -1,378 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2015 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-# This module contains the definitions for structures and externs for
-# functions used by frontend postgres applications. It is based on
-# Postgresql's libpq-fe.h.
-#
-# It is for postgreSQL version 7.4 and higher with support for the v3.0
-# connection-protocol.
-#
-
-when defined(nimHasStyleChecks):
-  {.push styleChecks: off.}
-
-when defined(windows):
-  const
-    dllName = "libpq.dll"
-elif defined(macosx):
-  const
-    dllName = "libpq.dylib"
-else:
-  const
-    dllName = "libpq.so(.5|)"
-    
-when defined(nimPreviewSlimSystem):
-  import std/syncio
-
-type
-  POid* = ptr Oid
-  Oid* = int32
-
-const
-  ERROR_MSG_LENGTH* = 4096
-  CMDSTATUS_LEN* = 40
-
-type
-  SockAddr* = array[1..112, int8]
-  PGresAttDesc*{.pure, final.} = object
-    name*: cstring
-    adtid*: Oid
-    adtsize*: int
-
-  PPGresAttDesc* = ptr PGresAttDesc
-  PPPGresAttDesc* = ptr PPGresAttDesc
-  PGresAttValue*{.pure, final.} = object
-    length*: int32
-    value*: cstring
-
-  PPGresAttValue* = ptr PGresAttValue
-  PPPGresAttValue* = ptr PPGresAttValue
-  PExecStatusType* = ptr ExecStatusType
-  ExecStatusType* = enum
-    PGRES_EMPTY_QUERY = 0, PGRES_COMMAND_OK, PGRES_TUPLES_OK, PGRES_COPY_OUT,
-    PGRES_COPY_IN, PGRES_BAD_RESPONSE, PGRES_NONFATAL_ERROR, PGRES_FATAL_ERROR,
-    PGRES_COPY_BOTH, PGRES_SINGLE_TUPLE
-  PGlobjfuncs*{.pure, final.} = object
-    fn_lo_open*: Oid
-    fn_lo_close*: Oid
-    fn_lo_creat*: Oid
-    fn_lo_unlink*: Oid
-    fn_lo_lseek*: Oid
-    fn_lo_tell*: Oid
-    fn_lo_read*: Oid
-    fn_lo_write*: Oid
-
-  PPGlobjfuncs* = ptr PGlobjfuncs
-  PConnStatusType* = ptr ConnStatusType
-  ConnStatusType* = enum
-    CONNECTION_OK, CONNECTION_BAD, CONNECTION_STARTED, CONNECTION_MADE,
-    CONNECTION_AWAITING_RESPONSE, CONNECTION_AUTH_OK, CONNECTION_SETENV,
-    CONNECTION_SSL_STARTUP, CONNECTION_NEEDED, CONNECTION_CHECK_WRITABLE,
-    CONNECTION_CONSUME, CONNECTION_GSS_STARTUP, CONNECTION_CHECK_TARGET
-  PGconn*{.pure, final.} = object
-    pghost*: cstring
-    pgtty*: cstring
-    pgport*: cstring
-    pgoptions*: cstring
-    dbName*: cstring
-    status*: ConnStatusType
-    errorMessage*: array[0..(ERROR_MSG_LENGTH) - 1, char]
-    Pfin*: File
-    Pfout*: File
-    Pfdebug*: File
-    sock*: int32
-    laddr*: SockAddr
-    raddr*: SockAddr
-    salt*: array[0..(2) - 1, char]
-    asyncNotifyWaiting*: int32
-    notifyList*: pointer
-    pguser*: cstring
-    pgpass*: cstring
-    lobjfuncs*: PPGlobjfuncs
-
-  PPGconn* = ptr PGconn
-  PGresult*{.pure, final.} = object
-    ntups*: int32
-    numAttributes*: int32
-    attDescs*: PPGresAttDesc
-    tuples*: PPPGresAttValue
-    tupArrSize*: int32
-    resultStatus*: ExecStatusType
-    cmdStatus*: array[0..(CMDSTATUS_LEN) - 1, char]
-    binary*: int32
-    conn*: PPGconn
-
-  PPGresult* = ptr PGresult
-  PPostgresPollingStatusType* = ptr PostgresPollingStatusType
-  PostgresPollingStatusType* = enum
-    PGRES_POLLING_FAILED = 0, PGRES_POLLING_READING, PGRES_POLLING_WRITING,
-    PGRES_POLLING_OK, PGRES_POLLING_ACTIVE
-  PPGTransactionStatusType* = ptr PGTransactionStatusType
-  PGTransactionStatusType* = enum
-    PQTRANS_IDLE, PQTRANS_ACTIVE, PQTRANS_INTRANS, PQTRANS_INERROR,
-    PQTRANS_UNKNOWN
-  PPGVerbosity* = ptr PGVerbosity
-  PGVerbosity* = enum
-    PQERRORS_TERSE, PQERRORS_DEFAULT, PQERRORS_VERBOSE, PQERRORS_SQLSTATE
-  PPGNotify* = ptr pgNotify
-  pgNotify*{.pure, final.} = object
-    relname*: cstring
-    be_pid*: int32
-    extra*: cstring
-
-  PQnoticeReceiver* = proc (arg: pointer, res: PPGresult){.cdecl.}
-  PQnoticeProcessor* = proc (arg: pointer, message: cstring){.cdecl.}
-  Ppqbool* = ptr pqbool
-  pqbool* = char
-  PPQprintOpt* = ptr PQprintOpt
-  PQprintOpt*{.pure, final.} = object
-    header*: pqbool
-    align*: pqbool
-    standard*: pqbool
-    html3*: pqbool
-    expanded*: pqbool
-    pager*: pqbool
-    fieldSep*: cstring
-    tableOpt*: cstring
-    caption*: cstring
-    fieldName*: ptr cstring
-
-  PPQconninfoOption* = ptr PQconninfoOption
-  PQconninfoOption*{.pure, final.} = object
-    keyword*: cstring
-    envvar*: cstring
-    compiled*: cstring
-    val*: cstring
-    label*: cstring
-    dispchar*: cstring
-    dispsize*: int32
-
-  PPQArgBlock* = ptr PQArgBlock
-  PQArgBlock*{.pure, final.} = object
-    length*: int32
-    isint*: int32
-    p*: pointer
-
-proc pqinitOpenSSL*(do_ssl: int32, do_crypto: int32) {.cdecl, dynlib: dllName,
-    importc: "PQinitOpenSSL".}
-proc pqconnectStart*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName,
-    importc: "PQconnectStart".}
-proc pqconnectPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl,
-    dynlib: dllName, importc: "PQconnectPoll".}
-proc pqconnectdb*(conninfo: cstring): PPGconn{.cdecl, dynlib: dllName,
-    importc: "PQconnectdb".}
-proc pqsetdbLogin*(pghost: cstring, pgport: cstring, pgoptions: cstring,
-                   pgtty: cstring, dbName: cstring, login: cstring, pwd: cstring): PPGconn{.
-    cdecl, dynlib: dllName, importc: "PQsetdbLogin".}
-proc pqsetdb*(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): PPGconn
-proc pqfinish*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQfinish".}
-proc pqconndefaults*(): PPQconninfoOption{.cdecl, dynlib: dllName,
-    importc: "PQconndefaults".}
-proc pqconninfoFree*(connOptions: PPQconninfoOption){.cdecl, dynlib: dllName,
-    importc: "PQconninfoFree".}
-proc pqresetStart*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQresetStart".}
-proc pqresetPoll*(conn: PPGconn): PostgresPollingStatusType{.cdecl,
-    dynlib: dllName, importc: "PQresetPoll".}
-proc pqreset*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQreset".}
-proc pqrequestCancel*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQrequestCancel".}
-proc pqdb*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQdb".}
-proc pquser*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQuser".}
-proc pqpass*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQpass".}
-proc pqhost*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQhost".}
-proc pqport*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQport".}
-proc pqtty*(conn: PPGconn): cstring{.cdecl, dynlib: dllName, importc: "PQtty".}
-proc pqoptions*(conn: PPGconn): cstring{.cdecl, dynlib: dllName,
-    importc: "PQoptions".}
-proc pqstatus*(conn: PPGconn): ConnStatusType{.cdecl, dynlib: dllName,
-    importc: "PQstatus".}
-proc pqtransactionStatus*(conn: PPGconn): PGTransactionStatusType{.cdecl,
-    dynlib: dllName, importc: "PQtransactionStatus".}
-proc pqparameterStatus*(conn: PPGconn, paramName: cstring): cstring{.cdecl,
-    dynlib: dllName, importc: "PQparameterStatus".}
-proc pqserverVersion*(conn: PPGconn): int32{.cdecl,
-    dynlib: dllName, importc: "PQserverVersion".}
-proc pqprotocolVersion*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQprotocolVersion".}
-proc pqerrorMessage*(conn: PPGconn): cstring{.cdecl, dynlib: dllName,
-    importc: "PQerrorMessage".}
-proc pqsocket*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-                                      importc: "PQsocket".}
-proc pqbackendPID*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQbackendPID".}
-proc pqconnectionNeedsPassword*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQconnectionNeedsPassword".}
-proc pqconnectionUsedPassword*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQconnectionUsedPassword".}
-proc pqclientEncoding*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQclientEncoding".}
-proc pqsetClientEncoding*(conn: PPGconn, encoding: cstring): int32{.cdecl,
-    dynlib: dllName, importc: "PQsetClientEncoding".}
-proc pqsetErrorVerbosity*(conn: PPGconn, verbosity: PGVerbosity): PGVerbosity{.
-    cdecl, dynlib: dllName, importc: "PQsetErrorVerbosity".}
-proc pqtrace*(conn: PPGconn, debug_port: File){.cdecl, dynlib: dllName,
-    importc: "PQtrace".}
-proc pquntrace*(conn: PPGconn){.cdecl, dynlib: dllName, importc: "PQuntrace".}
-proc pqsetNoticeReceiver*(conn: PPGconn, theProc: PQnoticeReceiver, arg: pointer): PQnoticeReceiver{.
-    cdecl, dynlib: dllName, importc: "PQsetNoticeReceiver".}
-proc pqsetNoticeProcessor*(conn: PPGconn, theProc: PQnoticeProcessor,
-                           arg: pointer): PQnoticeProcessor{.cdecl,
-    dynlib: dllName, importc: "PQsetNoticeProcessor".}
-proc pqexec*(conn: PPGconn, query: cstring): PPGresult{.cdecl, dynlib: dllName,
-    importc: "PQexec".}
-proc pqexecParams*(conn: PPGconn, command: cstring, nParams: int32,
-                   paramTypes: POid, paramValues: cstringArray,
-                   paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQexecParams".}
-proc pqprepare*(conn: PPGconn, stmtName, query: cstring, nParams: int32,
-    paramTypes: POid): PPGresult{.cdecl, dynlib: dllName, importc: "PQprepare".}
-proc pqexecPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
-                     paramValues: cstringArray,
-                     paramLengths, paramFormats: ptr int32, resultFormat: int32): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQexecPrepared".}
-proc pqsendQuery*(conn: PPGconn, query: cstring): int32{.cdecl, dynlib: dllName,
-    importc: "PQsendQuery".}
-  ## See also https://www.postgresql.org/docs/current/libpq-async.html
-proc pqsendQueryParams*(conn: PPGconn, command: cstring, nParams: int32,
-                        paramTypes: POid, paramValues: cstringArray,
-                        paramLengths, paramFormats: ptr int32,
-                        resultFormat: int32): int32{.cdecl, dynlib: dllName,
-    importc: "PQsendQueryParams".}
-proc pqsendQueryPrepared*(conn: PPGconn, stmtName: cstring, nParams: int32,
-                          paramValues: cstringArray,
-                          paramLengths, paramFormats: ptr int32,
-                          resultFormat: int32): int32{.cdecl, dynlib: dllName,
-    importc: "PQsendQueryPrepared".}
-proc pqSetSingleRowMode*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQsetSingleRowMode".}
-  ## See also https://www.postgresql.org/docs/current/libpq-single-row-mode.html
-proc pqgetResult*(conn: PPGconn): PPGresult{.cdecl, dynlib: dllName,
-    importc: "PQgetResult".}
-proc pqisBusy*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-                                      importc: "PQisBusy".}
-proc pqconsumeInput*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQconsumeInput".}
-proc pqnotifies*(conn: PPGconn): PPGNotify{.cdecl, dynlib: dllName,
-    importc: "PQnotifies".}
-proc pqputCopyData*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQputCopyData".}
-proc pqputCopyEnd*(conn: PPGconn, errormsg: cstring): int32{.cdecl,
-    dynlib: dllName, importc: "PQputCopyEnd".}
-proc pqgetCopyData*(conn: PPGconn, buffer: cstringArray, async: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetCopyData".}
-proc pqgetline*(conn: PPGconn, str: cstring, len: int32): int32{.cdecl,
-    dynlib: dllName, importc: "PQgetline".}
-proc pqputline*(conn: PPGconn, str: cstring): int32{.cdecl, dynlib: dllName,
-    importc: "PQputline".}
-proc pqgetlineAsync*(conn: PPGconn, buffer: cstring, bufsize: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetlineAsync".}
-proc pqputnbytes*(conn: PPGconn, buffer: cstring, nbytes: int32): int32{.cdecl,
-    dynlib: dllName, importc: "PQputnbytes".}
-proc pqendcopy*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-                                       importc: "PQendcopy".}
-proc pqsetnonblocking*(conn: PPGconn, arg: int32): int32{.cdecl,
-    dynlib: dllName, importc: "PQsetnonblocking".}
-proc pqisnonblocking*(conn: PPGconn): int32{.cdecl, dynlib: dllName,
-    importc: "PQisnonblocking".}
-proc pqflush*(conn: PPGconn): int32{.cdecl, dynlib: dllName, importc: "PQflush".}
-proc pqfn*(conn: PPGconn, fnid: int32, result_buf, result_len: ptr int32,
-           result_is_int: int32, args: PPQArgBlock, nargs: int32): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQfn".}
-proc pqresultStatus*(res: PPGresult): ExecStatusType{.cdecl, dynlib: dllName,
-    importc: "PQresultStatus".}
-proc pqresStatus*(status: ExecStatusType): cstring{.cdecl, dynlib: dllName,
-    importc: "PQresStatus".}
-proc pqresultErrorMessage*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
-    importc: "PQresultErrorMessage".}
-proc pqresultErrorField*(res: PPGresult, fieldcode: int32): cstring{.cdecl,
-    dynlib: dllName, importc: "PQresultErrorField".}
-proc pqntuples*(res: PPGresult): int32{.cdecl, dynlib: dllName,
-                                        importc: "PQntuples".}
-proc pqnfields*(res: PPGresult): int32{.cdecl, dynlib: dllName,
-                                        importc: "PQnfields".}
-proc pqbinaryTuples*(res: PPGresult): int32{.cdecl, dynlib: dllName,
-    importc: "PQbinaryTuples".}
-proc pqfname*(res: PPGresult, field_num: int32): cstring{.cdecl,
-    dynlib: dllName, importc: "PQfname".}
-proc pqfnumber*(res: PPGresult, field_name: cstring): int32{.cdecl,
-    dynlib: dllName, importc: "PQfnumber".}
-proc pqftable*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName,
-    importc: "PQftable".}
-proc pqftablecol*(res: PPGresult, field_num: int32): int32{.cdecl,
-    dynlib: dllName, importc: "PQftablecol".}
-proc pqfformat*(res: PPGresult, field_num: int32): int32{.cdecl,
-    dynlib: dllName, importc: "PQfformat".}
-proc pqftype*(res: PPGresult, field_num: int32): Oid{.cdecl, dynlib: dllName,
-    importc: "PQftype".}
-proc pqfsize*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName,
-    importc: "PQfsize".}
-proc pqfmod*(res: PPGresult, field_num: int32): int32{.cdecl, dynlib: dllName,
-    importc: "PQfmod".}
-proc pqcmdStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
-    importc: "PQcmdStatus".}
-proc pqoidStatus*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
-    importc: "PQoidStatus".}
-proc pqoidValue*(res: PPGresult): Oid{.cdecl, dynlib: dllName,
-                                       importc: "PQoidValue".}
-proc pqcmdTuples*(res: PPGresult): cstring{.cdecl, dynlib: dllName,
-    importc: "PQcmdTuples".}
-proc pqgetvalue*(res: PPGresult, tup_num: int32, field_num: int32): cstring{.
-    cdecl, dynlib: dllName, importc: "PQgetvalue".}
-proc pqgetlength*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetlength".}
-proc pqgetisnull*(res: PPGresult, tup_num: int32, field_num: int32): int32{.
-    cdecl, dynlib: dllName, importc: "PQgetisnull".}
-proc pqclear*(res: PPGresult){.cdecl, dynlib: dllName, importc: "PQclear".}
-proc pqfreemem*(p: pointer){.cdecl, dynlib: dllName, importc: "PQfreemem".}
-proc pqmakeEmptyPGresult*(conn: PPGconn, status: ExecStatusType): PPGresult{.
-    cdecl, dynlib: dllName, importc: "PQmakeEmptyPGresult".}
-proc pqescapeString*(till, `from`: cstring, len: int): int{.cdecl,
-    dynlib: dllName, importc: "PQescapeString".}
-proc pqescapeBytea*(bintext: cstring, binlen: int, bytealen: var int): cstring{.
-    cdecl, dynlib: dllName, importc: "PQescapeBytea".}
-proc pqunescapeBytea*(strtext: cstring, retbuflen: var int): cstring{.cdecl,
-    dynlib: dllName, importc: "PQunescapeBytea".}
-proc pqprint*(fout: File, res: PPGresult, ps: PPQprintOpt){.cdecl,
-    dynlib: dllName, importc: "PQprint".}
-proc pqdisplayTuples*(res: PPGresult, fp: File, fillAlign: int32,
-                      fieldSep: cstring, printHeader: int32, quiet: int32){.
-    cdecl, dynlib: dllName, importc: "PQdisplayTuples".}
-proc pqprintTuples*(res: PPGresult, fout: File, printAttName: int32,
-                    terseOutput: int32, width: int32){.cdecl, dynlib: dllName,
-    importc: "PQprintTuples".}
-proc lo_open*(conn: PPGconn, lobjId: Oid, mode: int32): int32{.cdecl,
-    dynlib: dllName, importc: "lo_open".}
-proc lo_close*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName,
-    importc: "lo_close".}
-proc lo_read*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
-    cdecl, dynlib: dllName, importc: "lo_read".}
-proc lo_write*(conn: PPGconn, fd: int32, buf: cstring, length: int): int32{.
-    cdecl, dynlib: dllName, importc: "lo_write".}
-proc lo_lseek*(conn: PPGconn, fd: int32, offset: int32, whence: int32): int32{.
-    cdecl, dynlib: dllName, importc: "lo_lseek".}
-proc lo_creat*(conn: PPGconn, mode: int32): Oid{.cdecl, dynlib: dllName,
-    importc: "lo_creat".}
-proc lo_tell*(conn: PPGconn, fd: int32): int32{.cdecl, dynlib: dllName,
-    importc: "lo_tell".}
-proc lo_unlink*(conn: PPGconn, lobjId: Oid): int32{.cdecl, dynlib: dllName,
-    importc: "lo_unlink".}
-proc lo_import*(conn: PPGconn, filename: cstring): Oid{.cdecl, dynlib: dllName,
-    importc: "lo_import".}
-proc lo_export*(conn: PPGconn, lobjId: Oid, filename: cstring): int32{.cdecl,
-    dynlib: dllName, importc: "lo_export".}
-proc pqmblen*(s: cstring, encoding: int32): int32{.cdecl, dynlib: dllName,
-    importc: "PQmblen".}
-proc pqenv2encoding*(): int32{.cdecl, dynlib: dllName, importc: "PQenv2encoding".}
-proc pqsetdb(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME: cstring): PPGconn =
-  result = pqsetdbLogin(M_PGHOST, M_PGPORT, M_PGOPT, M_PGTTY, M_DBNAME, "", "")
-
-when defined(nimHasStyleChecks):
-  {.pop.}
diff --git a/lib/wrappers/sqlite3.nim b/lib/wrappers/sqlite3.nim
deleted file mode 100644
index 96c37e09c..000000000
--- a/lib/wrappers/sqlite3.nim
+++ /dev/null
@@ -1,392 +0,0 @@
-#
-#
-#            Nim's Runtime Library
-#        (c) Copyright 2012 Andreas Rumpf
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-when defined(nimHasStyleChecks):
-  {.push styleChecks: off.}
-
-when defined(windows):
-  when defined(nimOldDlls):
-    const Lib = "sqlite3.dll"
-  elif defined(cpu64):
-    const Lib = "sqlite3_64.dll"
-  else:
-    const Lib = "sqlite3_32.dll"
-elif defined(macosx):
-  const
-    Lib = "libsqlite3(|.0).dylib"
-else:
-  const
-    Lib = "libsqlite3.so(|.0)"
-
-when defined(staticSqlite):
-  {.pragma: mylib.}
-  {.compile("sqlite3.c", "-O3").}
-else:
-  {.pragma: mylib, dynlib: Lib.}
-
-const
-  SQLITE_INTEGER* = 1
-  SQLITE_FLOAT* = 2
-  SQLITE_BLOB* = 4
-  SQLITE_NULL* = 5
-  SQLITE_TEXT* = 3
-  SQLITE_UTF8* = 1
-  SQLITE_UTF16LE* = 2
-  SQLITE_UTF16BE* = 3         # Use native byte order
-  SQLITE_UTF16* = 4           # sqlite3_create_function only
-  SQLITE_ANY* = 5             #sqlite_exec return values
-  SQLITE_OK* = 0
-  SQLITE_ERROR* = 1           # SQL error or missing database
-  SQLITE_INTERNAL* = 2        # An internal logic error in SQLite
-  SQLITE_PERM* = 3            # Access permission denied
-  SQLITE_ABORT* = 4           # Callback routine requested an abort
-  SQLITE_BUSY* = 5            # The database file is locked
-  SQLITE_LOCKED* = 6          # A table in the database is locked
-  SQLITE_NOMEM* = 7           # A malloc() failed
-  SQLITE_READONLY* = 8        # Attempt to write a readonly database
-  SQLITE_INTERRUPT* = 9       # Operation terminated by sqlite3_interrupt()
-  SQLITE_IOERR* = 10          # Some kind of disk I/O error occurred
-  SQLITE_CORRUPT* = 11        # The database disk image is malformed
-  SQLITE_NOTFOUND* = 12       # (Internal Only) Table or record not found
-  SQLITE_FULL* = 13           # Insertion failed because database is full
-  SQLITE_CANTOPEN* = 14       # Unable to open the database file
-  SQLITE_PROTOCOL* = 15       # Database lock protocol error
-  SQLITE_EMPTY* = 16          # Database is empty
-  SQLITE_SCHEMA* = 17         # The database schema changed
-  SQLITE_TOOBIG* = 18         # Too much data for one row of a table
-  SQLITE_CONSTRAINT* = 19     # Abort due to constraint violation
-  SQLITE_MISMATCH* = 20       # Data type mismatch
-  SQLITE_MISUSE* = 21         # Library used incorrectly
-  SQLITE_NOLFS* = 22          # Uses OS features not supported on host
-  SQLITE_AUTH* = 23           # Authorization denied
-  SQLITE_FORMAT* = 24         # Auxiliary database format error
-  SQLITE_RANGE* = 25          # 2nd parameter to sqlite3_bind out of range
-  SQLITE_NOTADB* = 26         # File opened that is not a database file
-  SQLITE_ROW* = 100           # sqlite3_step() has another row ready
-  SQLITE_DONE* = 101          # sqlite3_step() has finished executing
-  SQLITE_COPY* = 0
-  SQLITE_CREATE_INDEX* = 1
-  SQLITE_CREATE_TABLE* = 2
-  SQLITE_CREATE_TEMP_INDEX* = 3
-  SQLITE_CREATE_TEMP_TABLE* = 4
-  SQLITE_CREATE_TEMP_TRIGGER* = 5
-  SQLITE_CREATE_TEMP_VIEW* = 6
-  SQLITE_CREATE_TRIGGER* = 7
-  SQLITE_CREATE_VIEW* = 8
-  SQLITE_DELETE* = 9
-  SQLITE_DROP_INDEX* = 10
-  SQLITE_DROP_TABLE* = 11
-  SQLITE_DROP_TEMP_INDEX* = 12
-  SQLITE_DROP_TEMP_TABLE* = 13
-  SQLITE_DROP_TEMP_TRIGGER* = 14
-  SQLITE_DROP_TEMP_VIEW* = 15
-  SQLITE_DROP_TRIGGER* = 16
-  SQLITE_DROP_VIEW* = 17
-  SQLITE_INSERT* = 18
-  SQLITE_PRAGMA* = 19
-  SQLITE_READ* = 20
-  SQLITE_SELECT* = 21
-  SQLITE_TRANSACTION* = 22
-  SQLITE_UPDATE* = 23
-  SQLITE_ATTACH* = 24
-  SQLITE_DETACH* = 25
-  SQLITE_ALTER_TABLE* = 26
-  SQLITE_REINDEX* = 27
-  SQLITE_DENY* = 1
-  SQLITE_IGNORE* = 2          # Original from sqlite3.h:
-                              #define SQLITE_STATIC      ((void(*)(void *))0)
-                              #define SQLITE_TRANSIENT   ((void(*)(void *))-1)
-  SQLITE_DETERMINISTIC* = 0x800
-
-type
-  Sqlite3 {.pure, final.} = object
-  PSqlite3* = ptr Sqlite3
-  PPSqlite3* = ptr PSqlite3
-  Sqlite3_Backup {.pure, final.} = object
-  PSqlite3_Backup* = ptr Sqlite3_Backup
-  PPSqlite3_Backup* = ptr PSqlite3_Backup
-  Context{.pure, final.} = object
-  Pcontext* = ptr Context
-  TStmt{.pure, final.} = object
-  PStmt* = ptr TStmt
-  Value{.pure, final.} = object
-  PValue* = ptr Value
-  PValueArg* = array[0..127, PValue]
-
-  Callback* = proc (para1: pointer, para2: int32, para3,
-                     para4: cstringArray): int32{.cdecl.}
-  Tbind_destructor_func* = proc (para1: pointer){.cdecl, tags: [], gcsafe.}
-  Create_function_step_func* = proc (para1: Pcontext, para2: int32,
-                                      para3: PValueArg){.cdecl.}
-  Create_function_func_func* = proc (para1: Pcontext, para2: int32,
-                                      para3: PValueArg){.cdecl.}
-  Create_function_final_func* = proc (para1: Pcontext){.cdecl.}
-  Result_func* = proc (para1: pointer){.cdecl.}
-  Create_collation_func* = proc (para1: pointer, para2: int32, para3: pointer,
-                                  para4: int32, para5: pointer): int32{.cdecl.}
-  Collation_needed_func* = proc (para1: pointer, para2: PSqlite3, eTextRep: int32,
-                                  para4: cstring){.cdecl.}
-
-const
-  SQLITE_STATIC* = nil
-  SQLITE_TRANSIENT* = cast[Tbind_destructor_func](-1)
-
-proc close*(para1: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_close".}
-proc exec*(para1: PSqlite3, sql: cstring, para3: Callback, para4: pointer,
-           errmsg: var cstring): int32{.cdecl, mylib,
-                                        importc: "sqlite3_exec".}
-proc last_insert_rowid*(para1: PSqlite3): int64{.cdecl, mylib,
-    importc: "sqlite3_last_insert_rowid".}
-proc changes*(para1: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_changes".}
-proc total_changes*(para1: PSqlite3): int32{.cdecl, mylib,
-                                      importc: "sqlite3_total_changes".}
-proc interrupt*(para1: PSqlite3){.cdecl, mylib, importc: "sqlite3_interrupt".}
-proc complete*(sql: cstring): int32{.cdecl, mylib,
-                                     importc: "sqlite3_complete".}
-proc complete16*(sql: pointer): int32{.cdecl, mylib,
-                                       importc: "sqlite3_complete16".}
-proc busy_handler*(para1: PSqlite3,
-                   para2: proc (para1: pointer, para2: int32): int32{.cdecl.},
-                   para3: pointer): int32{.cdecl, mylib,
-    importc: "sqlite3_busy_handler".}
-proc busy_timeout*(para1: PSqlite3, ms: int32): int32{.cdecl, mylib,
-    importc: "sqlite3_busy_timeout".}
-proc get_table*(para1: PSqlite3, sql: cstring, resultp: var cstringArray,
-                nrow, ncolumn: var cint, errmsg: ptr cstring): int32{.cdecl,
-    mylib, importc: "sqlite3_get_table".}
-proc free_table*(result: cstringArray){.cdecl, mylib,
-                                        importc: "sqlite3_free_table".}
-  # Todo: see how translate sqlite3_mprintf, sqlite3_vmprintf, sqlite3_snprintf
-  # function sqlite3_mprintf(_para1:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_mprintf';
-proc mprintf*(para1: cstring): cstring{.cdecl, varargs, mylib,
-                                        importc: "sqlite3_mprintf".}
-  #function sqlite3_vmprintf(_para1:Pchar; _para2:va_list):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_vmprintf';
-proc free*(z: cstring){.cdecl, mylib, importc: "sqlite3_free".}
-  #function sqlite3_snprintf(_para1:longint; _para2:Pchar; _para3:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_snprintf';
-proc snprintf*(para1: int32, para2: cstring, para3: cstring): cstring{.cdecl,
-    mylib, varargs, importc: "sqlite3_snprintf".}
-proc set_authorizer*(para1: PSqlite3, xAuth: proc (para1: pointer, para2: int32,
-    para3: cstring, para4: cstring, para5: cstring, para6: cstring): int32{.
-    cdecl.}, pUserData: pointer): int32{.cdecl, mylib,
-    importc: "sqlite3_set_authorizer".}
-proc trace*(para1: PSqlite3, xTrace: proc (para1: pointer, para2: cstring){.cdecl.},
-            para3: pointer): pointer{.cdecl, mylib,
-                                      importc: "sqlite3_trace".}
-proc progress_handler*(para1: PSqlite3, para2: int32,
-                       para3: proc (para1: pointer): int32{.cdecl.},
-                       para4: pointer){.cdecl, mylib,
-                                        importc: "sqlite3_progress_handler".}
-proc commit_hook*(para1: PSqlite3, para2: proc (para1: pointer): int32{.cdecl.},
-                  para3: pointer): pointer{.cdecl, mylib,
-    importc: "sqlite3_commit_hook".}
-proc open*(filename: cstring, ppDb: var PSqlite3): int32{.cdecl, mylib,
-    importc: "sqlite3_open".}
-proc open16*(filename: pointer, ppDb: var PSqlite3): int32{.cdecl, mylib,
-    importc: "sqlite3_open16".}
-proc errcode*(db: PSqlite3): int32{.cdecl, mylib, importc: "sqlite3_errcode".}
-proc errmsg*(para1: PSqlite3): cstring{.cdecl, mylib, importc: "sqlite3_errmsg".}
-proc errmsg16*(para1: PSqlite3): pointer{.cdecl, mylib,
-                                   importc: "sqlite3_errmsg16".}
-proc prepare*(db: PSqlite3, zSql: cstring, nBytes: int32, ppStmt: var PStmt,
-              pzTail: ptr cstring): int32{.cdecl, mylib,
-    importc: "sqlite3_prepare".}
-
-proc prepare_v2*(db: PSqlite3, zSql: cstring, nByte: cint, ppStmt: var PStmt,
-                pzTail: ptr cstring): cint {.
-                importc: "sqlite3_prepare_v2", cdecl, mylib.}
-
-proc prepare16*(db: PSqlite3, zSql: pointer, nBytes: int32, ppStmt: var PStmt,
-                pzTail: var pointer): int32{.cdecl, mylib,
-    importc: "sqlite3_prepare16".}
-proc bind_blob*(para1: PStmt, para2: int32, para3: pointer, n: int32,
-                para5: Tbind_destructor_func): int32{.cdecl, mylib,
-    importc: "sqlite3_bind_blob".}
-proc bind_double*(para1: PStmt, para2: int32, para3: float64): int32{.cdecl,
-    mylib, importc: "sqlite3_bind_double".}
-proc bind_int*(para1: PStmt, para2: int32, para3: int32): int32{.cdecl,
-    mylib, importc: "sqlite3_bind_int".}
-proc bind_int64*(para1: PStmt, para2: int32, para3: int64): int32{.cdecl,
-    mylib, importc: "sqlite3_bind_int64".}
-proc bind_null*(para1: PStmt, para2: int32): int32{.cdecl, mylib,
-    importc: "sqlite3_bind_null".}
-proc bind_text*(para1: PStmt, para2: int32, para3: cstring, n: int32,
-                para5: Tbind_destructor_func): int32{.cdecl, mylib,
-    importc: "sqlite3_bind_text".}
-proc bind_text16*(para1: PStmt, para2: int32, para3: pointer, para4: int32,
-                  para5: Tbind_destructor_func): int32{.cdecl, mylib,
-    importc: "sqlite3_bind_text16".}
-  #function sqlite3_bind_value(_para1:Psqlite3_stmt; _para2:longint; _para3:Psqlite3_value):longint;cdecl; external Sqlite3Lib name 'sqlite3_bind_value';
-  #These overloaded functions were introduced to allow the use of SQLITE_STATIC and SQLITE_TRANSIENT
-  #It's the c world man ;-)
-proc bind_blob*(para1: PStmt, para2: int32, para3: pointer, n: int32,
-                para5: int32): int32{.cdecl, mylib,
-                                      importc: "sqlite3_bind_blob".}
-proc bind_text*(para1: PStmt, para2: int32, para3: cstring, n: int32,
-                para5: int32): int32{.cdecl, mylib,
-                                      importc: "sqlite3_bind_text".}
-proc bind_text16*(para1: PStmt, para2: int32, para3: pointer, para4: int32,
-                  para5: int32): int32{.cdecl, mylib,
-                                        importc: "sqlite3_bind_text16".}
-proc bind_parameter_count*(para1: PStmt): int32{.cdecl, mylib,
-    importc: "sqlite3_bind_parameter_count".}
-proc bind_parameter_name*(para1: PStmt, para2: int32): cstring{.cdecl,
-    mylib, importc: "sqlite3_bind_parameter_name".}
-proc bind_parameter_index*(para1: PStmt, zName: cstring): int32{.cdecl,
-    mylib, importc: "sqlite3_bind_parameter_index".}
-proc clear_bindings*(para1: PStmt): int32 {.cdecl,
-    mylib, importc: "sqlite3_clear_bindings".}
-proc column_count*(PStmt: PStmt): int32{.cdecl, mylib,
-    importc: "sqlite3_column_count".}
-proc column_name*(para1: PStmt, para2: int32): cstring{.cdecl, mylib,
-    importc: "sqlite3_column_name".}
-proc column_table_name*(para1: PStmt; para2: int32): cstring{.cdecl, mylib,
-    importc: "sqlite3_column_table_name".}
-proc column_name16*(para1: PStmt, para2: int32): pointer{.cdecl, mylib,
-    importc: "sqlite3_column_name16".}
-proc column_decltype*(para1: PStmt, i: int32): cstring{.cdecl, mylib,
-    importc: "sqlite3_column_decltype".}
-proc column_decltype16*(para1: PStmt, para2: int32): pointer{.cdecl,
-    mylib, importc: "sqlite3_column_decltype16".}
-proc step*(para1: PStmt): int32{.cdecl, mylib, importc: "sqlite3_step".}
-proc data_count*(PStmt: PStmt): int32{.cdecl, mylib,
-                                       importc: "sqlite3_data_count".}
-proc column_blob*(para1: PStmt, iCol: int32): pointer{.cdecl, mylib,
-    importc: "sqlite3_column_blob".}
-proc column_bytes*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
-    importc: "sqlite3_column_bytes".}
-proc column_bytes16*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
-    importc: "sqlite3_column_bytes16".}
-proc column_double*(para1: PStmt, iCol: int32): float64{.cdecl, mylib,
-    importc: "sqlite3_column_double".}
-proc column_int*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
-    importc: "sqlite3_column_int".}
-proc column_int64*(para1: PStmt, iCol: int32): int64{.cdecl, mylib,
-    importc: "sqlite3_column_int64".}
-proc column_text*(para1: PStmt, iCol: int32): cstring{.cdecl, mylib,
-    importc: "sqlite3_column_text".}
-proc column_text16*(para1: PStmt, iCol: int32): pointer{.cdecl, mylib,
-    importc: "sqlite3_column_text16".}
-proc column_type*(para1: PStmt, iCol: int32): int32{.cdecl, mylib,
-    importc: "sqlite3_column_type".}
-proc finalize*(PStmt: PStmt): int32{.cdecl, mylib,
-                                     importc: "sqlite3_finalize".}
-proc reset*(PStmt: PStmt): int32{.cdecl, mylib, importc: "sqlite3_reset".}
-proc create_function*(para1: PSqlite3, zFunctionName: cstring, nArg: int32,
-                      eTextRep: int32, para5: pointer,
-                      xFunc: Create_function_func_func,
-                      xStep: Create_function_step_func,
-                      xFinal: Create_function_final_func): int32{.cdecl,
-    mylib, importc: "sqlite3_create_function".}
-proc create_function16*(para1: PSqlite3, zFunctionName: pointer, nArg: int32,
-                        eTextRep: int32, para5: pointer,
-                        xFunc: Create_function_func_func,
-                        xStep: Create_function_step_func,
-                        xFinal: Create_function_final_func): int32{.cdecl,
-    mylib, importc: "sqlite3_create_function16".}
-proc aggregate_count*(para1: Pcontext): int32{.cdecl, mylib,
-    importc: "sqlite3_aggregate_count".}
-proc value_blob*(para1: PValue): pointer{.cdecl, mylib,
-    importc: "sqlite3_value_blob".}
-proc value_bytes*(para1: PValue): int32{.cdecl, mylib,
-    importc: "sqlite3_value_bytes".}
-proc value_bytes16*(para1: PValue): int32{.cdecl, mylib,
-    importc: "sqlite3_value_bytes16".}
-proc value_double*(para1: PValue): float64{.cdecl, mylib,
-    importc: "sqlite3_value_double".}
-proc value_int*(para1: PValue): int32{.cdecl, mylib,
-                                       importc: "sqlite3_value_int".}
-proc value_int64*(para1: PValue): int64{.cdecl, mylib,
-    importc: "sqlite3_value_int64".}
-proc value_text*(para1: PValue): cstring{.cdecl, mylib,
-    importc: "sqlite3_value_text".}
-proc value_text16*(para1: PValue): pointer{.cdecl, mylib,
-    importc: "sqlite3_value_text16".}
-proc value_text16le*(para1: PValue): pointer{.cdecl, mylib,
-    importc: "sqlite3_value_text16le".}
-proc value_text16be*(para1: PValue): pointer{.cdecl, mylib,
-    importc: "sqlite3_value_text16be".}
-proc value_type*(para1: PValue): int32{.cdecl, mylib,
-                                        importc: "sqlite3_value_type".}
-proc aggregate_context*(para1: Pcontext, nBytes: int32): pointer{.cdecl,
-    mylib, importc: "sqlite3_aggregate_context".}
-proc user_data*(para1: Pcontext): pointer{.cdecl, mylib,
-    importc: "sqlite3_user_data".}
-proc get_auxdata*(para1: Pcontext, para2: int32): pointer{.cdecl, mylib,
-    importc: "sqlite3_get_auxdata".}
-proc set_auxdata*(para1: Pcontext, para2: int32, para3: pointer,
-                  para4: proc (para1: pointer){.cdecl.}){.cdecl, mylib,
-    importc: "sqlite3_set_auxdata".}
-proc result_blob*(para1: Pcontext, para2: pointer, para3: int32,
-                  para4: Result_func){.cdecl, mylib,
-                                        importc: "sqlite3_result_blob".}
-proc result_double*(para1: Pcontext, para2: float64){.cdecl, mylib,
-    importc: "sqlite3_result_double".}
-proc result_error*(para1: Pcontext, para2: cstring, para3: int32){.cdecl,
-    mylib, importc: "sqlite3_result_error".}
-proc result_error16*(para1: Pcontext, para2: pointer, para3: int32){.cdecl,
-    mylib, importc: "sqlite3_result_error16".}
-proc result_int*(para1: Pcontext, para2: int32){.cdecl, mylib,
-    importc: "sqlite3_result_int".}
-proc result_int64*(para1: Pcontext, para2: int64){.cdecl, mylib,
-    importc: "sqlite3_result_int64".}
-proc result_null*(para1: Pcontext){.cdecl, mylib,
-                                    importc: "sqlite3_result_null".}
-proc result_text*(para1: Pcontext, para2: cstring, para3: int32,
-                  para4: Result_func){.cdecl, mylib,
-                                        importc: "sqlite3_result_text".}
-proc result_text16*(para1: Pcontext, para2: pointer, para3: int32,
-                    para4: Result_func){.cdecl, mylib,
-    importc: "sqlite3_result_text16".}
-proc result_text16le*(para1: Pcontext, para2: pointer, para3: int32,
-                      para4: Result_func){.cdecl, mylib,
-    importc: "sqlite3_result_text16le".}
-proc result_text16be*(para1: Pcontext, para2: pointer, para3: int32,
-                      para4: Result_func){.cdecl, mylib,
-    importc: "sqlite3_result_text16be".}
-proc result_value*(para1: Pcontext, para2: PValue){.cdecl, mylib,
-    importc: "sqlite3_result_value".}
-proc create_collation*(para1: PSqlite3, zName: cstring, eTextRep: int32,
-                       para4: pointer, xCompare: Create_collation_func): int32{.
-    cdecl, mylib, importc: "sqlite3_create_collation".}
-proc create_collation16*(para1: PSqlite3, zName: cstring, eTextRep: int32,
-                         para4: pointer, xCompare: Create_collation_func): int32{.
-    cdecl, mylib, importc: "sqlite3_create_collation16".}
-proc collation_needed*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{.
-    cdecl, mylib, importc: "sqlite3_collation_needed".}
-proc collation_needed16*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{.
-    cdecl, mylib, importc: "sqlite3_collation_needed16".}
-proc libversion*(): cstring{.cdecl, mylib, importc: "sqlite3_libversion".}
-  #Alias for allowing better code portability (win32 is not working with external variables)
-proc version*(): cstring{.cdecl, mylib, importc: "sqlite3_libversion".}
-  # Not published functions
-proc libversion_number*(): int32{.cdecl, mylib,
-                                  importc: "sqlite3_libversion_number".}
-
-proc backup_init*(pDest: PSqlite3, zDestName: cstring, pSource: PSqlite3, zSourceName: cstring): PSqlite3_Backup {.
-    cdecl, mylib, importc: "sqlite3_backup_init".}
-
-proc backup_step*(pBackup: PSqlite3_Backup, nPage: int32): int32 {.cdecl, mylib, importc: "sqlite3_backup_step".}
-
-proc backup_finish*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_finish".}
-
-proc backup_pagecount*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_pagecount".}
-
-proc backup_remaining*(pBackup: PSqlite3_Backup): int32 {.cdecl, mylib, importc: "sqlite3_backup_remaining".}
-
-proc sqlite3_sleep*(t: int64): int64 {.cdecl, mylib, importc: "sqlite3_sleep".}
-
-  #function sqlite3_key(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_key';
-  #function sqlite3_rekey(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_rekey';
-  #function sqlite3_sleep(_para1:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_sleep';
-  #function sqlite3_expired(_para1:Psqlite3_stmt):longint;cdecl; external Sqlite3Lib name 'sqlite3_expired';
-  #function sqlite3_global_recover:longint;cdecl; external Sqlite3Lib name 'sqlite3_global_recover';
-# implementation
-
-when defined(nimHasStyleChecks):
-  {.pop.}