summary refs log tree commit diff stats
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/array/tarraycons_ptr_generic.nim51
-rw-r--r--tests/array/tarraycons_ptr_generic2.nim17
-rw-r--r--tests/assign/toverload_asgn1.nim1
-rw-r--r--tests/assign/toverload_asgn2.nim1
-rw-r--r--tests/async/tasyncawait.nim12
-rw-r--r--tests/async/tlambda.nim4
-rw-r--r--tests/collections/tcollections_to_string.nim10
-rw-r--r--tests/collections/thashes.nim4
-rw-r--r--tests/collections/tsets.nim52
-rw-r--r--tests/compiles/trecursive_generic_in_compiles.nim4
-rw-r--r--tests/concepts/tstackconcept.nim2
-rw-r--r--tests/constructors/tinvalid_construction.nim4
-rw-r--r--tests/controlflow/tstatret.nim2
-rw-r--r--tests/converter/tconvert.nim2
-rw-r--r--tests/cpp/tcovariancerules.nim16
-rw-r--r--tests/distinct/tnil.nim15
-rw-r--r--tests/effects/teffects4.nim2
-rw-r--r--tests/enum/toptions.nim2
-rw-r--r--tests/errmsgs/t1154.nim11
-rw-r--r--tests/errmsgs/tcant_overload_by_return_type.nim9
-rw-r--r--tests/errmsgs/tinvalidinout.nim8
-rw-r--r--tests/errmsgs/tproper_stacktrace2.nim4
-rw-r--r--tests/exprs/tstmtexprs.nim2
-rw-r--r--tests/flags/tgenscript.nim5
-rw-r--r--tests/generics/module_with_generics.nim14
-rw-r--r--tests/generics/t5602_inheritence.nim8
-rw-r--r--tests/iter/tobj_iter.nim2
-rw-r--r--tests/lexer/tunderscores.nim2
-rw-r--r--tests/macros/tmacro1.nim17
-rw-r--r--tests/macros/tstructuredlogging.nim154
-rw-r--r--tests/macros/ttemplatesymbols.nim173
-rw-r--r--tests/manyloc/argument_parser/argument_parser.nim12
-rw-r--r--tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim27
-rw-r--r--tests/manyloc/keineschweine/dependencies/enet/enet.nim23
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim14
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim10
-rw-r--r--tests/manyloc/keineschweine/dependencies/nake/nakefile.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/sfml/sfml.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim1
-rw-r--r--tests/manyloc/keineschweine/keineschweine.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/estreams.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/input_helpers.nim6
-rw-r--r--tests/manyloc/keineschweine/lib/sg_assets.nim90
-rw-r--r--tests/manyloc/keineschweine/lib/sg_gui.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/sg_packets.nim6
-rw-r--r--tests/manyloc/keineschweine/server/nim.cfg1
-rw-r--r--tests/manyloc/nake/nake.nim2
-rw-r--r--tests/manyloc/nake/nakefile.nim6
-rw-r--r--tests/manyloc/standalone/barebone.nim.cfg1
-rw-r--r--tests/metatype/tbindtypedesc.nim8
-rw-r--r--tests/method/tsimmeth.nim2
-rw-r--r--tests/misc/tmemoization.nim2
-rw-r--r--tests/misc/tsemfold.nim23
-rw-r--r--tests/misc/tsimplesort.nim10
-rw-r--r--tests/misc/tunsignedmisc.nim2
-rw-r--r--tests/modules/definitions.nim4
-rw-r--r--tests/modules/proxy_module.nim3
-rw-r--r--tests/notnil/tmust_compile.nim1
-rw-r--r--tests/notnil/tnotnil.nim6
-rw-r--r--tests/notnil/tnotnil1.nim6
-rw-r--r--tests/notnil/tnotnil2.nim4
-rw-r--r--tests/notnil/tnotnil3.nim2
-rw-r--r--tests/notnil/tnotnil4.nim2
-rw-r--r--tests/notnil/tnotnil_in_generic.nim1
-rw-r--r--tests/notnil/tnotnil_in_objconstr.nim2
-rw-r--r--tests/objects/tinherentedvalues.nim16
-rw-r--r--tests/objects/tobj_asgn_dont_slice.nim24
-rw-r--r--tests/objects/tobjconstr.nim7
-rw-r--r--tests/objvariant/tcheckedfield1.nim2
-rw-r--r--tests/objvariant/temptycaseobj.nim2
-rw-r--r--tests/osproc/tclose.nim24
-rw-r--r--tests/overload/tissue966.nim2
-rw-r--r--tests/overload/toverprc.nim2
-rw-r--r--tests/overload/tparam_forwarding.nim16
-rw-r--r--tests/parallel/tparfind.nim2
-rw-r--r--tests/parallel/twaitany.nim35
-rw-r--r--tests/parser/tbraces.nim432
-rw-r--r--tests/parser/tcommand_as_expr.nim13
-rw-r--r--tests/parser/tinvcolonlocation1.nim4
-rw-r--r--tests/parser/tinvcolonlocation2.nim4
-rw-r--r--tests/parser/tinvcolonlocation3.nim4
-rw-r--r--tests/parser/twhen_in_enum.nim2
-rw-r--r--tests/parser/twrongcmdsyntax.nim2
-rw-r--r--tests/pragmas/tcustom_pragma.nim10
-rw-r--r--tests/pragmas/tnoreturn.nim7
-rw-r--r--tests/proc/tprocredef.nim4
-rw-r--r--tests/range/tsubrange.nim2
-rw-r--r--tests/rodfiles/deadg.nim3
-rw-r--r--tests/stdlib/tpegs.nim1770
-rw-r--r--tests/stdlib/ttimes.nim19
-rw-r--r--tests/stdlib/twchartoutf8.nim1
-rw-r--r--tests/system/tnilconcats.nim25
-rw-r--r--tests/system/toString.nim56
-rw-r--r--tests/template/i2416.nim1
-rw-r--r--tests/template/t2416.nim2
-rw-r--r--tests/testament/backend.nim2
-rw-r--r--tests/testament/categories.nim28
-rw-r--r--tests/testament/htmlgen.nim2
-rw-r--r--tests/testament/tester.nim33
-rw-r--r--tests/threads/tthreadvars.nim78
-rw-r--r--tests/trmacros/thoist.nim2
-rw-r--r--tests/typerel/t7600_1.nim18
-rw-r--r--tests/typerel/t7600_2.nim17
-rw-r--r--tests/typerel/texplicitcmp.nim4
-rw-r--r--tests/typerel/ttypelessemptyset.nim2
-rw-r--r--tests/types/tparameterizedparent3.nim2
-rw-r--r--tests/types/tparameterizedparent4.nim2
-rw-r--r--tests/varres/tnewseq_on_result_vart.nim9
-rw-r--r--tests/vm/tref.nim12
110 files changed, 1157 insertions, 2446 deletions
diff --git a/tests/array/tarraycons_ptr_generic.nim b/tests/array/tarraycons_ptr_generic.nim
new file mode 100644
index 000000000..eb89a196f
--- /dev/null
+++ b/tests/array/tarraycons_ptr_generic.nim
@@ -0,0 +1,51 @@
+discard """
+  output: '''apple
+banana
+Fruit
+2
+4
+3
+none
+skin
+paper
+'''
+"""
+type
+  Fruit = object of RootObj
+    name: string
+  Apple = object of Fruit
+  Banana = object of Fruit
+
+var
+  ir = Fruit(name: "Fruit")
+  ia = Apple(name: "apple")
+  ib = Banana(name: "banana")
+
+let x = [ia.addr, ib.addr, ir.addr]
+for c in x: echo c.name
+
+type
+  Vehicle[T] = object of RootObj
+    tire: T
+  Car[T] = object of Vehicle[T]
+  Bike[T] = object of Vehicle[T]
+
+var v = Vehicle[int](tire: 3)
+var c = Car[int](tire: 4)
+var b = Bike[int](tire: 2)
+
+let y = [b.addr, c.addr, v.addr]
+for c in y: echo c.tire
+
+type
+  Book[T] = ref object of RootObj
+    cover: T
+  Hard[T] = ref object of Book[T]
+  Soft[T] = ref object of Book[T]
+
+var bn = Book[string](cover: "none")
+var hs = Hard[string](cover: "skin")
+var bp = Soft[string](cover: "paper")
+
+let z = [bn, hs, bp]
+for c in z: echo c.cover
diff --git a/tests/array/tarraycons_ptr_generic2.nim b/tests/array/tarraycons_ptr_generic2.nim
new file mode 100644
index 000000000..fce7af669
--- /dev/null
+++ b/tests/array/tarraycons_ptr_generic2.nim
@@ -0,0 +1,17 @@
+discard """
+  file: "tarraycons_ptr_generic2.nim"
+  line: 17
+  errormsg: "type mismatch: got <ptr Hard[system.string]> but expected 'Book[system.string]'"
+"""
+
+type
+  Book[T] = ref object of RootObj
+    cover: T
+  Hard[T] = ref object of Book[T]
+  Soft[T] = ref object of Book[T]
+
+var bn = Book[string](cover: "none")
+var hs = Hard[string](cover: "skin")
+var bp = Soft[string](cover: "paper")
+
+let z = [bn, hs.addr, bp]
diff --git a/tests/assign/toverload_asgn1.nim b/tests/assign/toverload_asgn1.nim
index dbc3a71c4..01e7e7aa7 100644
--- a/tests/assign/toverload_asgn1.nim
+++ b/tests/assign/toverload_asgn1.nim
@@ -14,6 +14,7 @@ GenericT[T] '=' bool
 GenericT[T] '=' bool
 GenericT[T] '=' bool
 GenericT[T] '=' bool'''
+  disabled: "true"
 """
 
 import typetraits
diff --git a/tests/assign/toverload_asgn2.nim b/tests/assign/toverload_asgn2.nim
index 243c90494..1104be92b 100644
--- a/tests/assign/toverload_asgn2.nim
+++ b/tests/assign/toverload_asgn2.nim
@@ -1,6 +1,7 @@
 discard """
   output: '''i value 88
 2aa'''
+  disabled: "true"
 """
 
 import moverload_asgn2
diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim
index 9fe9507ad..74933f063 100644
--- a/tests/async/tasyncawait.nim
+++ b/tests/async/tasyncawait.nim
@@ -12,11 +12,11 @@ const
 
 var clientCount = 0
 
-proc sendMessages(client: TAsyncFD) {.async.} =
+proc sendMessages(client: AsyncFD) {.async.} =
   for i in 0 .. <messagesToSend:
     await send(client, "Message " & $i & "\c\L")
 
-proc launchSwarm(port: TPort) {.async.} =
+proc launchSwarm(port: Port) {.async.} =
   for i in 0 .. <swarmSize:
     var sock = newAsyncNativeSocket()
 
@@ -24,7 +24,7 @@ proc launchSwarm(port: TPort) {.async.} =
     await sendMessages(sock)
     closeSocket(sock)
 
-proc readMessages(client: TAsyncFD) {.async.} =
+proc readMessages(client: AsyncFD) {.async.} =
   while true:
     var line = await recvLine(client)
     if line == "":
@@ -37,7 +37,7 @@ proc readMessages(client: TAsyncFD) {.async.} =
       else:
         doAssert false
 
-proc createServer(port: TPort) {.async.} =
+proc createServer(port: Port) {.async.} =
   var server = newAsyncNativeSocket()
   block:
     var name: Sockaddr_in
@@ -55,8 +55,8 @@ proc createServer(port: TPort) {.async.} =
   while true:
     asyncCheck readMessages(await accept(server))
 
-asyncCheck createServer(TPort(10335))
-asyncCheck launchSwarm(TPort(10335))
+asyncCheck createServer(Port(10335))
+asyncCheck launchSwarm(Port(10335))
 while true:
   poll()
   if clientCount == swarmSize: break
diff --git a/tests/async/tlambda.nim b/tests/async/tlambda.nim
index d187c0d50..8f570689b 100644
--- a/tests/async/tlambda.nim
+++ b/tests/async/tlambda.nim
@@ -1,7 +1,7 @@
 
 # bug 2007
 
-import asyncdispatch, asyncnet, logging, json, uri, strutils, future
+import asyncdispatch, asyncnet, logging, json, uri, strutils, sugar
 
 type
   Builder = ref object
@@ -27,7 +27,7 @@ proc newBuild*(onProgress: ProgressCB): Build =
   result.onProgress = onProgress
 
 proc start(build: Build, repo, hash: string) {.async.} =
-  let path = repo.parseUri().path.toLower()
+  let path = repo.parseUri().path.toLowerAscii()
 
 proc onProgress(builder: Builder, message: string) {.async.} =
   debug($message)
diff --git a/tests/collections/tcollections_to_string.nim b/tests/collections/tcollections_to_string.nim
index 6cc8a84ff..48b06a6aa 100644
--- a/tests/collections/tcollections_to_string.nim
+++ b/tests/collections/tcollections_to_string.nim
@@ -85,14 +85,20 @@ block:
   s.addQuoted('\0')
   s.addQuoted('\31')
   s.addQuoted('\127')
-  s.addQuoted('\255')
-  doAssert s == "'\\x00''\\x1F''\\x7F''\\xFF'"
+  doAssert s == "'\\x00''\\x1F''\\x7F'"
 block:
   var s = ""
   s.addQuoted('\\')
   s.addQuoted('\'')
   s.addQuoted('\"')
   doAssert s == """'\\''\'''\"'"""
+block:
+  var s = ""
+  s.addQuoted("å")
+  s.addQuoted("ä")
+  s.addQuoted("ö")
+  s.addEscapedChar('\xFF')
+  doAssert s == """"å""ä""ö"\xFF"""
 
 # Test customized element representation
 type CustomString = object
diff --git a/tests/collections/thashes.nim b/tests/collections/thashes.nim
index 76b99313c..5cc3cc8bb 100644
--- a/tests/collections/thashes.nim
+++ b/tests/collections/thashes.nim
@@ -3,7 +3,7 @@ discard """
 """
 
 import tables
-from hashes import THash
+from hashes import Hash
 
 # Test with int
 block:
@@ -66,7 +66,7 @@ block:
 # The same test with a custom hash(s: string) does
 # work though.
 block:
-  proc hash(x: int): THash {.inline.} =
+  proc hash(x: int): Hash {.inline.} =
     echo "overloaded hash"
     result = x
   var t = initTable[int, int]()
diff --git a/tests/collections/tsets.nim b/tests/collections/tsets.nim
index 6139560bd..61e14260a 100644
--- a/tests/collections/tsets.nim
+++ b/tests/collections/tsets.nim
@@ -1,4 +1,6 @@
 import sets
+import hashes
+import algorithm
 
 block setEquality:
   var
@@ -35,7 +37,7 @@ block setWithSequences:
   doAssert( not s.contains(@[4, 5, 6]) )
 
 block setClearWorked:
-  var s = initSet[char]() 
+  var s = initSet[char]()
 
   for c in "this is a test":
     s.incl(c)
@@ -68,12 +70,54 @@ block orderedSetClearWorked:
   for c in "eat at joes":
     s.incl(c)
 
-  r = "" 
+  r = ""
   for c in items(s):
     add(r, c)
 
   doAssert r == "zeat jos"
 
+block hashForHashedSet:
+  let
+    seq1 = "This is the test."
+    seq2 = "the test is This."
+    s1 = seq1.toSet()
+    s2 = seq2.toSet()
+  var hashSeq: seq[Hash] = @[]
+  doAssert s1 == s2
+  doAssert hash(s1) == hash(s2)
+
+block hashForOrderdSet:
+  let
+    str = "This is the test."
+    rstr = str.reversed
 
-
-
+  var
+    s1 = initOrderedSet[char]()
+    s2 = initOrderedSet[char]()
+    r = initOrderedSet[char]()
+    expected: Hash
+    added: seq[char] = @[]
+    reversed: Hash
+    radded: seq[char] = @[]
+
+  expected = 0
+  for c in str:
+    if (not (c in added)):
+      expected = expected !& hash(c)
+      added.add(c)
+    s1.incl(c)
+    s2.incl(c)
+  expected = !$expected
+  doAssert hash(s1) == expected
+  doAssert hash(s1) == hash(s2)
+  doAssert hash(s1) != hash(r)
+
+  reversed = 0
+  for c in rstr:
+    if (not (c in radded)):
+      reversed = reversed !& hash(c)
+      radded.add(c)
+    r.incl(c)
+  reversed = !$reversed
+  doAssert hash(r) == reversed
+  doAssert hash(s1) != reversed
diff --git a/tests/compiles/trecursive_generic_in_compiles.nim b/tests/compiles/trecursive_generic_in_compiles.nim
index 77bf0bb02..9c7fd10b3 100644
--- a/tests/compiles/trecursive_generic_in_compiles.nim
+++ b/tests/compiles/trecursive_generic_in_compiles.nim
@@ -1,6 +1,6 @@
 # bug #3313
-import unittest, future
-
+import unittest, sugar
+{.experimental: "notnil".}
 type
   ListNodeKind = enum
     lnkNil, lnkCons
diff --git a/tests/concepts/tstackconcept.nim b/tests/concepts/tstackconcept.nim
index 2238dacb6..cb8db566d 100644
--- a/tests/concepts/tstackconcept.nim
+++ b/tests/concepts/tstackconcept.nim
@@ -31,7 +31,7 @@ type
     s.pop() is T
 
     type ValueType = T
-    const ValueTypeName = T.name.toUpper
+    const ValueTypeName = T.name.toUpperAscii
 
 proc genericAlgorithm[T](s: var Stack[T], y: T) =
   static:
diff --git a/tests/constructors/tinvalid_construction.nim b/tests/constructors/tinvalid_construction.nim
index bb3b1bebb..b3e56eec6 100644
--- a/tests/constructors/tinvalid_construction.nim
+++ b/tests/constructors/tinvalid_construction.nim
@@ -3,12 +3,12 @@ template accept(x) =
 
 template reject(x) =
   static: assert(not compiles(x))
-
+{.experimental: "notnil".}
 type
   TRefObj = ref object
     x: int
 
-  THasNotNils = object of TObject
+  THasNotNils = object of RootObj
     a: TRefObj not nil
     b: TRefObj not nil
     c: TRefObj
diff --git a/tests/controlflow/tstatret.nim b/tests/controlflow/tstatret.nim
index d655f5595..04cac9966 100644
--- a/tests/controlflow/tstatret.nim
+++ b/tests/controlflow/tstatret.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tstatret.nim"
   line: 9
-  errormsg: "statement not allowed after"
+  errormsg: "unreachable statement after 'return'"
 """
 # no statement after return
 proc main() =
diff --git a/tests/converter/tconvert.nim b/tests/converter/tconvert.nim
index a37140234..48367a85b 100644
--- a/tests/converter/tconvert.nim
+++ b/tests/converter/tconvert.nim
@@ -15,6 +15,6 @@ type TFoo = object
 converter toPtr*(some: var TFoo): ptr TFoo = (addr some)
 
 
-proc zoot(x: ptr TFoo) = nil
+proc zoot(x: ptr TFoo) = discard
 var x: Tfoo
 zoot(x)
diff --git a/tests/cpp/tcovariancerules.nim b/tests/cpp/tcovariancerules.nim
index f81d67a50..acde1b288 100644
--- a/tests/cpp/tcovariancerules.nim
+++ b/tests/cpp/tcovariancerules.nim
@@ -13,14 +13,8 @@ cat
 cat
 dog
 dog
-dog value
-cat value
-dog value
-cat value
 dog
 dog
-dog value
-cat value
 dog 1
 dog 2
 '''
@@ -243,11 +237,12 @@ reject modifiesCovariantArray(dogRefsArray.addr)
 
 var dogValues = @[vdog, vdog]
 var dogValuesArray = [vdog, vdog]
-var animalValues = @[Animal(vdog), Animal(vcat)]
-var animalValuesArray = [Animal(vdog), Animal(vcat)]
+when false:
+  var animalValues = @[Animal(vdog), Animal(vcat)]
+  var animalValuesArray = [Animal(vdog), Animal(vcat)]
 
-wantsNonCovariantSeq animalValues
-wantsNonCovariantArray animalValuesArray
+  wantsNonCovariantSeq animalValues
+  wantsNonCovariantArray animalValuesArray
 
 reject wantsNonCovariantSeq(dogRefs)
 reject modifiesCovariantOperArray(dogRefs)
@@ -260,7 +255,6 @@ modifiesDerivedOperArray dogRefs
 reject modifiesDerivedOperArray(dogValues)
 reject modifiesDerivedOperArray(animalRefs)
 
-wantsNonCovariantOperArray animalValues
 reject wantsNonCovariantOperArray(animalRefs)
 reject wantsNonCovariantOperArray(dogRefs)
 reject wantsNonCovariantOperArray(dogValues)
diff --git a/tests/distinct/tnil.nim b/tests/distinct/tnil.nim
index e60437a1f..759a14657 100644
--- a/tests/distinct/tnil.nim
+++ b/tests/distinct/tnil.nim
@@ -1,15 +1,11 @@
 discard """
   file: "tnil.nim"
-  output: '''0x1
-
-nil
-
-nil
-
+  output: '''1
+0
+0
 '''
-  disabled: "windows"
 """
-
+{.experimental: "notnil".}
 type
   MyPointer = distinct pointer
   MyString = distinct string
@@ -17,7 +13,8 @@ type
   MyInt = distinct int
 
 proc foo(a: MyPointer) =
-  echo a.repr
+  # workaround a Windows 'repr' difference:
+  echo cast[int](a)
 
 foo(cast[MyPointer](1))
 foo(cast[MyPointer](nil))
diff --git a/tests/effects/teffects4.nim b/tests/effects/teffects4.nim
index fd5dd49e2..d0960126f 100644
--- a/tests/effects/teffects4.nim
+++ b/tests/effects/teffects4.nim
@@ -12,7 +12,7 @@ type
   EIO2 = ref object of EIO
 
 proc q() {.tags: [FIO].} =
-  nil
+  discard
 
 proc raiser(): int =
   writeLine stdout, "arg"
diff --git a/tests/enum/toptions.nim b/tests/enum/toptions.nim
index e53acb2b3..da66f0067 100644
--- a/tests/enum/toptions.nim
+++ b/tests/enum/toptions.nim
@@ -4,7 +4,7 @@ type
   TOption = enum
     optNone, optForceFullMake, optBoehmGC, optRefcGC, optRangeCheck,
     optBoundsCheck, optOverflowCheck, optNilCheck, optAssert, optLineDir,
-    optWarns, optHints, optDeadCodeElim, optListCmd, optCompileOnly,
+    optWarns, optHints, optListCmd, optCompileOnly,
     optSafeCode,             # only allow safe code
     optStyleCheck, optOptimizeSpeed, optOptimizeSize, optGenDynLib,
     optGenGuiApp, optStackTrace
diff --git a/tests/errmsgs/t1154.nim b/tests/errmsgs/t1154.nim
new file mode 100644
index 000000000..7fcbf8a27
--- /dev/null
+++ b/tests/errmsgs/t1154.nim
@@ -0,0 +1,11 @@
+discard """
+errormsg: "invalid type: 'expr' in this context: 'proc (a: varargs[expr])' for proc"
+line: 8
+"""
+
+import typetraits
+
+proc foo(a:varargs[expr]) =
+  echo a[0].type.name
+
+foo(1)
diff --git a/tests/errmsgs/tcant_overload_by_return_type.nim b/tests/errmsgs/tcant_overload_by_return_type.nim
new file mode 100644
index 000000000..613a896b4
--- /dev/null
+++ b/tests/errmsgs/tcant_overload_by_return_type.nim
@@ -0,0 +1,9 @@
+discard """
+errormsg: "overloaded 'x' leads to ambiguous calls"
+line: 9
+"""
+
+# bug #6393
+
+proc x(): int = 7
+proc x(): string = "strange"
diff --git a/tests/errmsgs/tinvalidinout.nim b/tests/errmsgs/tinvalidinout.nim
index ce7eb6022..1fa3805ee 100644
--- a/tests/errmsgs/tinvalidinout.nim
+++ b/tests/errmsgs/tinvalidinout.nim
@@ -1,10 +1,10 @@
 discard """
 cmd: "nim check $file"
-errormsg: "The `in` modifier can be used only with imported types"
+errormsg: "the 'in' modifier can be used only with imported types"
 nimout: '''
-tinvalidinout.nim(14, 7) Error: The `out` modifier can be used only with imported types
-tinvalidinout.nim(17, 9) Error: The `in` modifier can be used only with imported types
-tinvalidinout.nim(18, 9) Error: The `in` modifier can be used only with imported types
+tinvalidinout.nim(14, 7) Error: the 'out' modifier can be used only with imported types
+tinvalidinout.nim(17, 9) Error: the 'in' modifier can be used only with imported types
+tinvalidinout.nim(18, 9) Error: the 'in' modifier can be used only with imported types
 '''
 """
 
diff --git a/tests/errmsgs/tproper_stacktrace2.nim b/tests/errmsgs/tproper_stacktrace2.nim
index 5f312b870..44b208c87 100644
--- a/tests/errmsgs/tproper_stacktrace2.nim
+++ b/tests/errmsgs/tproper_stacktrace2.nim
@@ -3,7 +3,7 @@ discard """
   exitcode: 1
 """
 
-proc returnsNil(): string = return nil
+proc returnsNil(): ref int = return nil
 
 iterator fields*(a, b: int): int =
   if a == b:
@@ -17,6 +17,6 @@ proc main(): string =
   result = ""
   for i in fields(0, 1):
     let x = returnsNil()
-    result &= "string literal " & $x
+    result &= "string literal " & $x[]
 
 echo main()
diff --git a/tests/exprs/tstmtexprs.nim b/tests/exprs/tstmtexprs.nim
index 2a0ec2821..577f314ec 100644
--- a/tests/exprs/tstmtexprs.nim
+++ b/tests/exprs/tstmtexprs.nim
@@ -81,7 +81,7 @@ semiProblem()
 # bug #844
 
 import json
-proc parseResponse(): PJsonNode =
+proc parseResponse(): JsonNode =
   result = % { "key1": % { "key2": % "value" } }
   for key, val in result["key1"]:
     var excMsg = key & "("
diff --git a/tests/flags/tgenscript.nim b/tests/flags/tgenscript.nim
new file mode 100644
index 000000000..6a037b5d8
--- /dev/null
+++ b/tests/flags/tgenscript.nim
@@ -0,0 +1,5 @@
+discard """
+  file: "tgenscript.nim"
+"""
+
+echo "--genscript"
diff --git a/tests/generics/module_with_generics.nim b/tests/generics/module_with_generics.nim
new file mode 100644
index 000000000..e801a4790
--- /dev/null
+++ b/tests/generics/module_with_generics.nim
@@ -0,0 +1,14 @@
+type
+  Base[T] = ref object {.inheritable.}
+    value*: T
+
+  Derived[T] = ref object of Base[T]
+    derivedValue*: T
+
+proc makeDerived*[T](v: T): Derived[T] =
+  new result
+  result.value = v
+
+proc setBaseValue*[T](a: Base[T], value: T) =
+  a.value = value
+
diff --git a/tests/generics/t5602_inheritence.nim b/tests/generics/t5602_inheritence.nim
index 6d48c796e..ee5ba89d5 100644
--- a/tests/generics/t5602_inheritence.nim
+++ b/tests/generics/t5602_inheritence.nim
@@ -1,10 +1,11 @@
 discard """
   output: "seq[float]\n0"
+  targets: "c cpp"
 """
 
 # https://github.com/nim-lang/Nim/issues/5602
 
-import typetraits
+import typetraits, module_with_generics
 
 type
   Foo[T] = object of RootObj
@@ -16,3 +17,8 @@ proc p[T](f: Foo[T]): T =
 var s: Bar[float]
 echo p(s).len # the bug was: p(s) should return seq[float], but returns float instead
 
+# Test overloading and code generation when
+# downcasting is required for generic types:
+var d = makeDerived(10)
+setBaseValue(d, 20)
+
diff --git a/tests/iter/tobj_iter.nim b/tests/iter/tobj_iter.nim
index eb0e37b23..a894755d7 100644
--- a/tests/iter/tobj_iter.nim
+++ b/tests/iter/tobj_iter.nim
@@ -4,8 +4,6 @@ discard """
 
 # bug #2023
 
-{.deadCodeElim:on.}
-
 type
     Obj = object
         iter: iterator (): int8 {.closure.}
diff --git a/tests/lexer/tunderscores.nim b/tests/lexer/tunderscores.nim
index e718fb40a..f64f36977 100644
--- a/tests/lexer/tunderscores.nim
+++ b/tests/lexer/tunderscores.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tunderscores.nim"
   line: 8
-  errormsg: "invalid token: _"
+  errormsg: "invalid token: trailing underscore"
 """
 # Bug #502670
 
diff --git a/tests/macros/tmacro1.nim b/tests/macros/tmacro1.nim
index 0b83345a1..ac2bf9094 100644
--- a/tests/macros/tmacro1.nim
+++ b/tests/macros/tmacro1.nim
@@ -27,11 +27,19 @@ import strutils
 template assertNot(arg: untyped): untyped =
   assert(not(arg))
 
+
+proc foo(arg: int): void =
+  discard
+
+proc foo(arg: float): void =
+  discard
+
 static:
   ## test eqIdent
   let a = "abc_def"
   let b = "abcDef"
   let c = "AbcDef"
+  let d = nnkBracketExpr.newTree() # not an identifier at all
 
   assert eqIdent(             a ,              b )
   assert eqIdent(newIdentNode(a),              b )
@@ -62,3 +70,12 @@ static:
   assertNot eqIdent(genSym(nskLet, c), newIdentNode(  b))
   assertNot eqIdent(newIdentNode(  c), genSym(nskLet, b))
   assertNot eqIdent(genSym(nskLet, c), genSym(nskLet, b))
+
+  # eqIdent on non identifier at all
+  assertNot eqIdent(a,d)
+
+  # eqIdent on sym choice
+  let fooSym = bindSym"foo"
+  assert fooSym.kind in {nnkOpenSymChoice, nnkClosedSymChoice}
+  assert    fooSym.eqIdent("fOO")
+  assertNot fooSym.eqIdent("bar")
diff --git a/tests/macros/tstructuredlogging.nim b/tests/macros/tstructuredlogging.nim
new file mode 100644
index 000000000..05bb52a40
--- /dev/null
+++ b/tests/macros/tstructuredlogging.nim
@@ -0,0 +1,154 @@
+discard """
+output: '''
+main started: a=10, b=inner-b, c=10, d=some-d, x=16, z=20
+exiting: a=12, b=overriden-b, c=100, msg=bye bye, x=16
+'''
+"""
+
+import macros, tables
+
+template scopeHolder =
+  0 # scope revision number
+
+type
+  BindingsSet = Table[string, NimNode]
+
+proc actualBody(n: NimNode): NimNode =
+  # skip over the double StmtList node introduced in `mergeScopes`
+  result = n.body
+  if result.kind == nnkStmtList and result[0].kind == nnkStmtList:
+    result = result[0]
+
+iterator bindings(n: NimNode, skip = 0): (string, NimNode) =
+  for i in skip ..< n.len:
+    let child = n[i]
+    if child.kind in {nnkAsgn, nnkExprEqExpr}:
+      let name = $child[0]
+      let value = child[1]
+      yield (name, value)
+
+proc scopeRevision(scopeHolder: NimNode): int =
+  # get the revision number from a scopeHolder sym
+  assert scopeHolder.kind == nnkSym
+  var revisionNode = scopeHolder.getImpl.actualBody[0]
+  result = int(revisionNode.intVal)
+
+proc lastScopeHolder(scopeHolders: NimNode): NimNode =
+  # get the most recent scopeHolder from a symChoice node
+  if scopeHolders.kind in {nnkClosedSymChoice, nnkOpenSymChoice}:
+    var bestScopeRev = 0
+    assert scopeHolders.len > 0
+    for scope in scopeHolders:
+      let rev = scope.scopeRevision
+      if result == nil or rev > bestScopeRev:
+        result = scope
+        bestScopeRev = rev
+  else:
+    result = scopeHolders
+
+  assert result.kind == nnkSym
+
+macro mergeScopes(scopeHolders: typed, newBindings: untyped): untyped =
+  var
+    bestScope = scopeHolders.lastScopeHolder
+    bestScopeRev = bestScope.scopeRevision
+
+  var finalBindings = initTable[string, NimNode]()
+  for k, v in bindings(bestScope.getImpl.actualBody, skip = 1):
+    finalBindings[k] = v
+
+  for k, v in bindings(newBindings):
+    finalBindings[k] = v
+
+  var newScopeDefinition = newStmtList(newLit(bestScopeRev + 1))
+
+  for k, v in finalBindings:
+    newScopeDefinition.add newAssignment(newIdentNode(k), v)
+
+  result = quote:
+    template scopeHolder = `newScopeDefinition`
+
+template scope(newBindings: untyped) {.dirty.} =
+  mergeScopes(bindSym"scopeHolder", newBindings)
+
+type
+  TextLogRecord = object
+    line: string
+
+  StdoutLogRecord = object
+
+template setProperty(r: var TextLogRecord, key: string, val: string, isFirst: bool) =
+  if not first: r.line.add ", "
+  r.line.add key
+  r.line.add "="
+  r.line.add val
+
+template setEventName(r: var StdoutLogRecord, name: string) =
+  stdout.write(name & ": ")
+
+template setProperty(r: var StdoutLogRecord, key: string, val: auto, isFirst: bool) =
+  when not isFirst: stdout.write ", "
+  stdout.write key
+  stdout.write "="
+  stdout.write $val
+
+template flushRecord(r: var StdoutLogRecord) =
+  stdout.write "\n"
+  stdout.flushFile
+
+macro logImpl(scopeHolders: typed,
+              logStmtProps: varargs[untyped]): untyped =
+  let lexicalScope = scopeHolders.lastScopeHolder.getImpl.actualBody
+  var finalBindings = initOrderedTable[string, NimNode]()
+
+  for k, v in bindings(lexicalScope, skip = 1):
+    finalBindings[k] = v
+
+  for k, v in bindings(logStmtProps, skip = 1):
+    finalBindings[k] = v
+
+  finalBindings.sort(system.cmp)
+
+  let eventName = logStmtProps[0]
+  assert eventName.kind in {nnkStrLit}
+  let record = genSym(nskVar, "record")
+
+  result = quote:
+    var `record`: StdoutLogRecord
+    setEventName(`record`, `eventName`)
+
+  var isFirst = true
+  for k, v in finalBindings:
+    result.add newCall(newIdentNode"setProperty",
+                       record, newLit(k), v, newLit(isFirst))
+    isFirst = false
+
+  result.add newCall(newIdentNode"flushRecord", record)
+
+template log(props: varargs[untyped]) {.dirty.} =
+  logImpl(bindSym"scopeHolder", props)
+
+scope:
+  a = 12
+  b = "original-b"
+
+scope:
+  x = 16
+  b = "overriden-b"
+
+scope:
+  c = 100
+
+proc main =
+  scope:
+    c = 10
+
+  scope:
+    z = 20
+
+  log("main started", a = 10, b = "inner-b", d = "some-d")
+
+main()
+
+log("exiting", msg = "bye bye")
+
diff --git a/tests/macros/ttemplatesymbols.nim b/tests/macros/ttemplatesymbols.nim
new file mode 100644
index 000000000..8d9c9ec02
--- /dev/null
+++ b/tests/macros/ttemplatesymbols.nim
@@ -0,0 +1,173 @@
+import
+  macros, algorithm, strutils
+
+proc normalProc(x: int) =
+  echo x
+
+template templateWithtouParams =
+  echo 10
+
+proc overloadedProc(x: int) =
+  echo x
+
+proc overloadedProc(x: string) =
+  echo x
+
+proc overloadedProc[T](x: T) =
+  echo x
+
+template normalTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: string) =
+  echo x
+
+macro normalMacro(x: int): untyped =
+  discard
+
+macro macroWithoutParams: untyped =
+  discard
+
+macro inspectSymbol(sym: typed, expected: static[string]): untyped =
+  if sym.kind == nnkSym:
+    echo "Symbol node:"
+    let res = sym.getImpl.repr & "\n"
+    echo res
+    # echo "|", res, "|"
+    # echo "|", expected, "|"
+    if expected.len > 0: assert res == expected
+  elif sym.kind in {nnkClosedSymChoice, nnkOpenSymChoice}:
+    echo "Begin sym choice:"
+    var results = newSeq[string](0)
+    for innerSym in sym:
+      results.add innerSym.getImpl.repr
+    sort(results, cmp[string])
+    let res = results.join("\n") & "\n"
+    echo res
+    if expected.len > 0: assert res == expected
+    echo "End symchoice."
+  else:
+    echo "Non-symbol node: ", sym.kind
+    if expected.len > 0: assert $sym.kind == expected
+
+macro inspectUntyped(sym: untyped, expected: static[string]): untyped =
+  let res = sym.repr
+  echo "Untyped node: ", res
+  assert res == expected
+
+inspectSymbol templateWithtouParams, "nnkCommand"
+  # this template is expanded, because bindSym was not used
+  # the end result is the template body (nnkCommand)
+
+inspectSymbol bindSym("templateWithtouParams"), """
+template templateWithtouParams() =
+  echo 10
+
+"""
+
+inspectSymbol macroWithoutParams, "nnkEmpty"
+  # Just like the template above, the macro was expanded
+
+inspectSymbol bindSym("macroWithoutParams"), """
+macro macroWithoutParams(): untyped =
+  discard
+
+"""
+
+inspectSymbol normalMacro, """
+macro normalMacro(x: int): untyped =
+  discard
+
+"""
+  # Since the normalMacro has params, it's automatically
+  # treated as a symbol here (no need for `bindSym`)
+
+inspectSymbol bindSym("normalMacro"), """
+macro normalMacro(x: int): untyped =
+  discard
+
+"""
+
+inspectSymbol normalTemplate, """
+template normalTemplate(x: int) =
+  echo x
+
+"""
+
+inspectSymbol bindSym("normalTemplate"), """
+template normalTemplate(x: int) =
+  echo x
+
+"""
+
+inspectSymbol overloadedTemplate, """
+template overloadedTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: string) =
+  echo x
+
+"""
+
+inspectSymbol bindSym("overloadedTemplate"), """
+template overloadedTemplate(x: int) =
+  echo x
+
+template overloadedTemplate(x: string) =
+  echo x
+
+"""
+
+inspectUntyped bindSym("overloadedTemplate"), """bindSym("overloadedTemplate")"""
+  # binSym is active only in the presense of `typed` params.
+  # `untyped` params still get the raw AST
+
+inspectSymbol normalProc, """
+proc normalProc(x: int) =
+  echo [x]
+
+"""
+
+inspectSymbol bindSym("normalProc"), """
+proc normalProc(x: int) =
+  echo [x]
+
+"""
+
+inspectSymbol overloadedProc, """
+proc overloadedProc(x: int) =
+  echo [x]
+
+proc overloadedProc(x: string) =
+  echo [x]
+
+proc overloadedProc[T](x: T) =
+  echo x
+
+"""
+  # XXX: There seems to be a repr rendering problem above.
+  # Notice that `echo [x]`
+
+inspectSymbol overloadedProc[float], """
+proc overloadedProc(x: T) =
+  echo [x]
+
+"""
+  # As expected, when we select a specific generic, the
+  # AST is no longer a symChoice
+
+inspectSymbol bindSym("overloadedProc"), """
+proc overloadedProc(x: int) =
+  echo [x]
+
+proc overloadedProc(x: string) =
+  echo [x]
+
+proc overloadedProc[T](x: T) =
+  echo x
+
+"""
+
diff --git a/tests/manyloc/argument_parser/argument_parser.nim b/tests/manyloc/argument_parser/argument_parser.nim
index 14352066d..1095a893e 100644
--- a/tests/manyloc/argument_parser/argument_parser.nim
+++ b/tests/manyloc/argument_parser/argument_parser.nim
@@ -209,7 +209,7 @@ proc `$`*(data: Tcommandline_results): string =
 
 # - Parse code
 
-template raise_or_quit(exception, message: expr): stmt {.immediate.} =
+template raise_or_quit(exception, message: untyped) =
   ## Avoids repeating if check based on the default quit_on_failure variable.
   ##
   ## As a special case, if message has a zero length the call to quit won't
@@ -230,15 +230,15 @@ template run_custom_proc(parsed_parameter: Tparsed_parameter,
   ##
   ## Pass in the string of the parameter triggering the call. If the
   if not custom_validator.isNil:
+    try:
+      let message = custom_validator(parameter, parsed_parameter)
+      if not message.isNil and message.len > 0:
+        raise_or_quit(ValueError, ("Failed to validate value for " &
+          "parameter $1:\n$2" % [escape(parameter), message]))
     except:
       raise_or_quit(ValueError, ("Couldn't run custom proc for " &
         "parameter $1:\n$2" % [escape(parameter),
         getCurrentExceptionMsg()]))
-    let message = custom_validator(parameter, parsed_parameter)
-    if not message.isNil and message.len > 0:
-      raise_or_quit(ValueError, ("Failed to validate value for " &
-        "parameter $1:\n$2" % [escape(parameter), message]))
-
 
 proc parse_parameter(quit_on_failure: bool, param, value: string,
     param_kind: Tparam_kind): Tparsed_parameter =
diff --git a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
index 56d3edec4..ac425c7a0 100644
--- a/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
+++ b/tests/manyloc/keineschweine/dependencies/chipmunk/chipmunk.nim
@@ -23,7 +23,6 @@ const Lib = "libchipmunk.so.6.1.1"
 
 when defined(MoreNim):
   {.hint: "MoreNim defined; some Chipmunk functions replaced in Nim".}
-{.deadCodeElim: on.}
 from math import sqrt, sin, cos, arctan2
 when defined(CpUseFloat):
   {.hint: "CpUseFloat defined; using float32 as float".}
@@ -389,13 +388,13 @@ type
     cdecl.}
 
 ##cp property emulators
-template defGetter(otype: typedesc, memberType: typedesc, memberName: expr, procName: expr): stmt {.immediate.} =
+template defGetter(otype: typedesc, memberType: typedesc, memberName, procName: untyped) =
   proc `get procName`*(obj: otype): memberType {.cdecl.} =
     return obj.memberName
-template defSetter(otype: typedesc, memberType: typedesc, memberName: expr, procName: expr): stmt {.immediate.} =
+template defSetter(otype: typedesc, memberType: typedesc, memberName, procName: untyped) =
   proc `set procName`*(obj: otype, value: memberType) {.cdecl.} =
     obj.memberName = value
-template defProp(otype: typedesc, memberType: typedesc, memberName: expr, procName: expr): stmt {.immediate.} =
+template defProp(otype: typedesc, memberType: typedesc, memberName, procName: untyped) =
   defGetter(otype, memberType, memberName, procName)
   defSetter(otype, memberType, memberName, procName)
 
@@ -909,7 +908,7 @@ proc getShapes*(arb: PArbiter, a, b: var PShape) {.inline.} =
 
 #/ A macro shortcut for defining and retrieving the shapes from an arbiter.
 #define CP_ARBITER_GET_SHAPES(arb, a, b) cpShape *a, *b; cpArbiterGetShapes(arb, &a, &b);
-template getShapes*(arb: PArbiter, name1, name2: expr): stmt {.immediate.} =
+template getShapes*(arb: PArbiter, name1, name2: untyped) =
   var name1, name2: PShape
   getShapes(arb, name1, name2)
 
@@ -924,7 +923,7 @@ template getShapes*(arb: PArbiter, name1, name2: expr): stmt {.immediate.} =
 
 #/ A macro shortcut for defining and retrieving the bodies from an arbiter.
 #define CP_ARBITER_GET_BODIES(arb, a, b) cpBody *a, *b; cpArbiterGetBodies(arb, &a, &b);
-template getBodies*(arb: PArbiter, name1, name2: expr): stmt {.immediate.} =
+template getBodies*(arb: PArbiter, name1, name2: untyped) =
   var name1, name2: PBOdy
   getBodies(arb, name1, name2)
 
@@ -948,11 +947,11 @@ proc getDepth*(arb: PArbiter; i: cint): CpFloat {.
   cdecl, importc: "cpArbiterGetDepth", dynlib: Lib.}
 
 ##Shapes
-template defShapeSetter(memberType: typedesc, memberName: expr, procName: expr, activates: bool): stmt {.immediate.} =
+template defShapeSetter(memberType: typedesc, memberName: untyped, procName: untyped, activates: bool) =
   proc `set procName`*(obj: PShape, value: memberType) {.cdecl.} =
     if activates and obj.body != nil: obj.body.activate()
     obj.memberName = value
-template defShapeProp(memberType: typedesc, memberName: expr, procName: expr, activates: bool): stmt {.immediate.} =
+template defShapeProp(memberType: typedesc, memberName: untyped, procName: untyped, activates: bool) =
   defGetter(PShape, memberType, memberName, procName)
   defShapeSetter(memberType, memberName, procName, activates)
 
@@ -1273,11 +1272,11 @@ proc activateBodies(constraint: PConstraint) {.inline.} =
 # 	cpConstraintActivateBodies(constraint); \
 # 	constraint->member = value; \
 # }
-template defConstraintSetter(memberType: typedesc, member: expr, name: expr): stmt {.immediate.} =
+template defConstraintSetter(memberType: typedesc, member, name: untyped) =
   proc `set name`*(constraint: PConstraint, value: memberType) {.cdecl.} =
     activateBodies(constraint)
     constraint.member = value
-template defConstraintProp(memberType: typedesc, member: expr, name: expr): stmt {.immediate.} =
+template defConstraintProp(memberType: typedesc, member, name: untyped) =
   defGetter(PConstraint, memberType, member, name)
   defConstraintSetter(memberType, member, name)
 # CP_DefineConstraintStructGetter(cpSpace*, CP_PRIVATE(space), Space)
@@ -1307,18 +1306,18 @@ proc getImpulse*(constraint: PConstraint): CpFloat {.inline.} =
 # 	cpConstraintActivateBodies(constraint); \
 # 	((struct *)constraint)->member = value; \
 # }
-template constraintCheckCast(constraint: PConstraint, ctype: expr): stmt {.immediate.} =
+template constraintCheckCast(constraint: PConstraint, ctype: untyped) =
   assert(constraint.klass == `ctype getClass`(), "Constraint is the wrong class")
-template defCGetter(ctype: expr, memberType: typedesc, member: expr, name: expr): stmt {.immediate.} =
+template defCGetter(ctype: untyped, memberType: typedesc, member, name: untyped) =
   proc `get ctype name`*(constraint: PConstraint): memberType {.cdecl.} =
     constraintCheckCast(constraint, ctype)
     result = cast[`P ctype`](constraint).member
-template defCSetter(ctype: expr, memberType: typedesc, member: expr, name: expr): stmt {.immediate.} =
+template defCSetter(ctype: untyped, memberType: typedesc, member, name: untyped) =
   proc `set ctype name`*(constraint: PConstraint, value: memberType) {.cdecl.} =
     constraintCheckCast(constraint, ctype)
     activateBodies(constraint)
     cast[`P ctype`](constraint).member = value
-template defCProp(ctype: expr, memberType: typedesc, member: expr, name: expr): stmt {.immediate.} =
+template defCProp(ctype: untyped, memberType: typedesc, member, name: untyped) =
   defCGetter(ctype, memberType, member, name)
   defCSetter(ctype, memberType, member, name)
 
diff --git a/tests/manyloc/keineschweine/dependencies/enet/enet.nim b/tests/manyloc/keineschweine/dependencies/enet/enet.nim
index 3c4ce2017..07079f2ea 100644
--- a/tests/manyloc/keineschweine/dependencies/enet/enet.nim
+++ b/tests/manyloc/keineschweine/dependencies/enet/enet.nim
@@ -20,12 +20,11 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 const Lib = "libenet.so.1(|.0.3)"
 
-{.deadCodeElim: on.}
 const
   ENET_VERSION_MAJOR* = 1
   ENET_VERSION_MINOR* = 3
   ENET_VERSION_PATCH* = 3
-template ENET_VERSION_CREATE(major, minor, patch: expr): expr =
+template ENET_VERSION_CREATE(major, minor, patch: untyped): untyped =
   (((major) shl 16) or ((minor) shl 8) or (patch))
 
 const
@@ -278,22 +277,22 @@ when defined(Linux) or true:
       dataLength*: csize
     TENetSocketSet* = Tfd_set
   ## see if these are different on win32, if not then get rid of these
-  template ENET_HOST_TO_NET_16*(value: expr): expr =
+  template ENET_HOST_TO_NET_16*(value: untyped): untyped =
     (htons(value))
-  template ENET_HOST_TO_NET_32*(value: expr): expr =
+  template ENET_HOST_TO_NET_32*(value: untyped): untyped =
     (htonl(value))
-  template ENET_NET_TO_HOST_16*(value: expr): expr =
+  template ENET_NET_TO_HOST_16*(value: untyped): untyped =
     (ntohs(value))
-  template ENET_NET_TO_HOST_32*(value: expr): expr =
+  template ENET_NET_TO_HOST_32*(value: untyped): untyped =
     (ntohl(value))
 
-  template ENET_SOCKETSET_EMPTY*(sockset: expr): expr =
+  template ENET_SOCKETSET_EMPTY*(sockset: untyped): untyped =
     FD_ZERO(addr((sockset)))
-  template ENET_SOCKETSET_ADD*(sockset, socket: expr): expr =
+  template ENET_SOCKETSET_ADD*(sockset, socket: untyped): untyped =
     FD_SET(socket, addr((sockset)))
-  template ENET_SOCKETSET_REMOVE*(sockset, socket: expr): expr =
+  template ENET_SOCKETSET_REMOVE*(sockset, socket: untyped): untyped =
     FD_CLEAR(socket, addr((sockset)))
-  template ENET_SOCKETSET_CHECK*(sockset, socket: expr): expr =
+  template ENET_SOCKETSET_CHECK*(sockset, socket: untyped): untyped =
     FD_ISSET(socket, addr((sockset)))
 
 when defined(Windows):
@@ -607,7 +606,7 @@ proc protocolCommandSize*(commandNumber: cuchar): csize{.
 
 {.pop.}
 
-from hashes import `!$`, `!&`, THash, hash
-proc hash*(x: TAddress): THash {.nimcall, noSideEffect.} =
+from hashes import `!$`, `!&`, Hash, hash
+proc hash*(x: TAddress): Hash {.nimcall, noSideEffect.} =
   result = !$(hash(x.host.int32) !& hash(x.port.int16))
 
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
index 142b190ab..3fb4dc7d9 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
@@ -1,15 +1,15 @@
 import macros, macro_dsl, estreams
 from strutils import format
 
-template newLenName(): stmt {.immediate.} =
+template newLenName() =
   let lenName {.inject.} = ^("len"& $lenNames)
   inc(lenNames)
 
-template defPacketImports*(): stmt {.immediate, dirty.} =
+template defPacketImports*() {.dirty.} =
   import macros, macro_dsl, estreams
   from strutils import format
 
-macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} =
+macro defPacket*(typeNameN: untyped, typeFields: untyped): untyped =
   result = newNimNode(nnkStmtList)
   let
     typeName = quoted2ident(typeNameN)
@@ -60,7 +60,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} =
     let
       name = typeFields[i][0]
       dotName = packetID.dot(name)
-      resName = newIdentNode(!"result").dot(name)
+      resName = newIdentNode("result").dot(name)
     case typeFields[i][1].kind
     of nnkBracketExpr: #ex: paddedstring[32, '\0'], array[range, type]
       case $typeFields[i][1][0].ident
@@ -141,7 +141,7 @@ macro defPacket*(typeNameN: expr, typeFields: expr): stmt {.immediate.} =
 
   const emptyFields = {nnkEmpty, nnkNilLit}
   var objFields = newNimNode(nnkRecList)
-  for i in 0.. < len(typeFields):
+  for i in 0 ..< len(typeFields):
     let fname = typeFields[i][0]
     constructorParams.add(newNimNode(nnkIdentDefs).und(
       fname,
@@ -200,7 +200,7 @@ proc iddefs*(a: string; b: NimNode): NimNode {.compileTime.} =
 proc varTy*(a: NimNode): NimNode {.compileTime.} =
   result = newNimNode(nnkVarTy).und(a)
 
-macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} =
+macro forwardPacket*(typeName: untyped, underlyingType: untyped): untyped =
   var
     packetID = ^"p"
     streamID = ^"s"
@@ -234,7 +234,7 @@ macro forwardPacket*(typeName: expr, underlyingType: expr): stmt {.immediate.} =
     echo "unknown type:", repr(underlyingtype)
   echo(repr(result))
 
-template forwardPacketT*(typeName: expr; underlyingType: expr): stmt {.dirty, immediate.} =
+template forwardPacketT*(typeName: untyped; underlyingType: untyped) {.dirty.} =
   proc `read typeName`*(buffer: PBuffer): typeName =
     #discard readData(s, addr result, sizeof(result))
     var res: underlyingType
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
index d3a0c701d..33d2a7177 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
@@ -1,5 +1,5 @@
 import macros
-{.deadCodeElim: on.}
+
 #Inline macro.add() to allow for easier nesting
 proc und*(a: NimNode; b: NimNode): NimNode {.compileTime.} =
   a.add(b)
@@ -10,7 +10,7 @@ proc und*(a: NimNode; b: varargs[NimNode]): NimNode {.compileTime.} =
 
 proc `^`*(a: string): NimNode {.compileTime.} =
   ## new ident node
-  result = newIdentNode(!a)
+  result = newIdentNode(a)
 proc `[]`*(a, b: NimNode): NimNode {.compileTime.} =
   ## new bracket expression: node[node] not to be confused with node[indx]
   result = newNimNode(nnkBracketExpr).und(a, b)
@@ -34,7 +34,7 @@ proc emptyNode*(): NimNode {.compileTime.} =
 proc dot*(left, right: NimNode): NimNode {.compileTime.} =
   result = newNimNode(nnkDotExpr).und(left, right)
 proc prefix*(a: string, b: NimNode): NimNode {.compileTime.} =
-  result = newNimNode(nnkPrefix).und(newIdentNode(!a), b)
+  result = newNimNode(nnkPrefix).und(newIdentNode(a), b)
 
 proc quoted2ident*(a: NimNode): NimNode {.compileTime.} =
   if a.kind != nnkAccQuoted:
@@ -45,13 +45,13 @@ proc quoted2ident*(a: NimNode): NimNode {.compileTime.} =
   result = ^pname
 
 
-macro `?`(a: expr): expr =
+macro `?`(a: untyped): untyped =
   ## Character literal ?A #=> 'A'
   result = ($a[1].ident)[0].lit
 ## echo(?F,?a,?t,?t,?y)
 
 when isMainModule:
-  macro foo(x: stmt): stmt =
+  macro foo(x: untyped) =
     result = newNimNode(nnkStmtList)
     result.add(newNimNode(nnkCall).und(!!"echo", "Hello thar".lit))
     result.add(newCall("echo", lit("3 * 45 = "), (3.lit.infix("*", 45.lit))))
diff --git a/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim b/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim
index bdf2139c9..5490211de 100644
--- a/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim
+++ b/tests/manyloc/keineschweine/dependencies/nake/nakefile.nim
@@ -7,7 +7,7 @@ task "install", "compile and install nake binary":
     for index, dir in pairs(path):
       echo "  ", index, ". ", dir
     echo "Where to install nake binary? (quit with ^C or quit or exit)"
-    let ans = stdin.readLine().toLower
+    let ans = stdin.readLine().toLowerAscii
     var index = 0
     case ans
     of "q", "quit", "x", "exit":
diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
index 1524f0eb4..0060bf12b 100644
--- a/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
+++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml.nim
@@ -12,7 +12,7 @@ else:
     LibS = "libcsfml-system.so.2.0"
     LibW = "libcsfml-window.so.2.0"
   #{.error: "Platform unsupported".}
-{.deadCodeElim: on.}
+
 {.pragma: pf, pure, final.}
 type
   PClock* = ptr TClock
diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim
index 95a760e1f..b4eb1b8f0 100644
--- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim
+++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_colors.nim
@@ -1,5 +1,5 @@
 import sfml
-{.deadCodeElim: on.}
+
 let
   Black*: TColor = color(0, 0, 0)
   White*: TColor = color(255, 255, 255)
diff --git a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim
index 474d249aa..94c5308a9 100644
--- a/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim
+++ b/tests/manyloc/keineschweine/dependencies/sfml/sfml_vector.nim
@@ -1,2 +1 @@
 import sfml, math, strutils
-{.deadCodeElim: on.}
diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim
index c0f1bc031..59347ee46 100644
--- a/tests/manyloc/keineschweine/keineschweine.nim
+++ b/tests/manyloc/keineschweine/keineschweine.nim
@@ -5,7 +5,7 @@ import
   sg_gui, sg_assets, sound_buffer, enet_client
 when defined(profiler):
   import nimprof
-{.deadCodeElim: on.}
+
 type
   PPlayer* = ref TPlayer
   TPlayer* = object
diff --git a/tests/manyloc/keineschweine/lib/estreams.nim b/tests/manyloc/keineschweine/lib/estreams.nim
index bdf9b2bf0..00a55c626 100644
--- a/tests/manyloc/keineschweine/lib/estreams.nim
+++ b/tests/manyloc/keineschweine/lib/estreams.nim
@@ -78,7 +78,7 @@ proc write*(buffer: PBuffer; val: var string) =
   setLen buffer.data, buffer.pos + length.int
   copyMem(addr buffer.data[buffer.pos], addr val[0], length.int)
   inc buffer.pos, length.int
-proc write*[T: TNumber|bool|char|byte](buffer: PBuffer; val: T) =
+proc write*[T: SomeNumber|bool|char|byte](buffer: PBuffer; val: T) =
   var v: T
   shallowCopy v, val
   writeBE buffer, v
diff --git a/tests/manyloc/keineschweine/lib/input_helpers.nim b/tests/manyloc/keineschweine/lib/input_helpers.nim
index 1953cb58c..ff1286c8d 100644
--- a/tests/manyloc/keineschweine/lib/input_helpers.nim
+++ b/tests/manyloc/keineschweine/lib/input_helpers.nim
@@ -5,8 +5,8 @@ type
   TInputFinishedProc* = proc()
   TKeyCallback = proc()
   PKeyClient* = ref object
-    onKeyDown: TTable[int32, TKeyCallback]
-    onKeyUp: TTable[int32, TKeyCallback]
+    onKeyDown: Table[int32, TKeyCallback]
+    onKeyUp: Table[int32, TKeyCallback]
     name: string
   PTextInput* = ref object
     text*: string
@@ -134,5 +134,5 @@ iterator pollEvents*(window: PRenderWindow): PEvent =
     of EvtMouseButtonReleased: addButtonEvent(event.mouseButton.button, up)
     of EvtTextEntered: recordText(activeInput, event.text)
     of EvtMouseMoved: setMousePos(event.mouseMove.x, event.mouseMove.y)
-    else: nil
+    else: discard
     yield(addr event)
diff --git a/tests/manyloc/keineschweine/lib/sg_assets.nim b/tests/manyloc/keineschweine/lib/sg_assets.nim
index fbc3c9ab8..1e8a99c83 100644
--- a/tests/manyloc/keineschweine/lib/sg_assets.nim
+++ b/tests/manyloc/keineschweine/lib/sg_assets.nim
@@ -59,7 +59,7 @@ type
     of Projectile:
       bullet*: PBulletRecord
     else:
-      nil
+      discard
   PBulletRecord* = ref TBulletRecord
   TBulletRecord* = object
     id*: int16
@@ -115,10 +115,10 @@ var
   cfg: PZoneSettings
   SpriteSheets* = initTable[string, PSpriteSheet](64)
   SoundCache  * = initTable[string, PSoundRecord](64)
-  nameToVehID*: TTable[string, int]
-  nameToItemID*: TTable[string, int]
-  nameToObjID*: TTable[string, int]
-  nameToBulletID*: TTable[string, int]
+  nameToVehID*: Table[string, int]
+  nameToItemID*: Table[string, int]
+  nameToObjID*: Table[string, int]
+  nameToBulletID*: Table[string, int]
   activeState = Lobby
 
 proc newSprite*(filename: string; errors: var seq[string]): PSpriteSheet
@@ -126,7 +126,7 @@ proc load*(ss: PSpriteSheet): bool {.discardable.}
 proc newSound*(filename: string; errors: var seq[string]): PSoundRecord
 proc load*(s: PSoundRecord): bool {.discardable.}
 
-proc validateSettings*(settings: PJsonNode; errors: var seq[string]): bool
+proc validateSettings*(settings: JsonNode; errors: var seq[string]): bool
 proc loadSettings*(rawJson: string, errors: var seq[string]): bool
 proc loadSettingsFromFile*(filename: string, errors: var seq[string]): bool
 
@@ -135,17 +135,17 @@ proc fetchItm*(itm: string): PItemRecord
 proc fetchObj*(name: string): PObjectRecord
 proc fetchBullet(name: string): PBulletRecord
 
-proc importLevel(data: PJsonNode; errors: var seq[string]): PLevelSettings
-proc importVeh(data: PJsonNode; errors: var seq[string]): PVehicleRecord
-proc importObject(data: PJsonNode; errors: var seq[string]): PObjectRecord
-proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord
-proc importPhys(data: PJsonNode): TPhysicsRecord
-proc importAnim(data: PJsonNode; errors: var seq[string]): PAnimationRecord
-proc importHandling(data: PJsonNode): THandlingRecord
-proc importBullet(data: PJsonNode; errors: var seq[string]): PBulletRecord
-proc importSoul(data: PJsonNode): TSoulRecord
-proc importExplosion(data: PJsonNode; errors: var seq[string]): TExplosionRecord
-proc importSound*(data: PJsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord
+proc importLevel(data: JsonNode; errors: var seq[string]): PLevelSettings
+proc importVeh(data: JsonNode; errors: var seq[string]): PVehicleRecord
+proc importObject(data: JsonNode; errors: var seq[string]): PObjectRecord
+proc importItem(data: JsonNode; errors: var seq[string]): PItemRecord
+proc importPhys(data: JsonNode): TPhysicsRecord
+proc importAnim(data: JsonNode; errors: var seq[string]): PAnimationRecord
+proc importHandling(data: JsonNode): THandlingRecord
+proc importBullet(data: JsonNode; errors: var seq[string]): PBulletRecord
+proc importSoul(data: JsonNode): TSoulRecord
+proc importExplosion(data: JsonNode; errors: var seq[string]): TExplosionRecord
+proc importSound*(data: JsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord
 
 ## this is the only pipe between lobby and main.nim
 proc getActiveState*(): TGameState =
@@ -203,7 +203,7 @@ iterator playableVehicles*(): PVehicleRecord =
     if v.playable:
       yield v
 
-template allAssets*(body: stmt) {.dirty.}=
+template allAssets*(body: untyped) {.dirty.}=
   block:
     var assetType = FGraphics
     for file, asset in pairs(SpriteSheets):
@@ -212,7 +212,7 @@ template allAssets*(body: stmt) {.dirty.}=
     for file, asset in pairs(SoundCache):
       body
 
-template cacheImpl(procName, cacheName, resultType: expr; body: stmt) {.dirty, immediate.} =
+template cacheImpl(procName, cacheName, resultType, body: untyped) {.dirty.} =
   proc procName*(filename: string; errors: var seq[string]): resulttype =
     if hasKey(cacheName, filename):
       return cacheName[filename]
@@ -220,7 +220,7 @@ template cacheImpl(procName, cacheName, resultType: expr; body: stmt) {.dirty, i
     body
     cacheName[filename] = result
 
-template checkFile(path: expr): stmt {.dirty, immediate.} =
+template checkFile(path: untyped) {.dirty.} =
   if not existsFile(path):
     errors.add("File missing: "& path)
 
@@ -243,7 +243,7 @@ proc expandPath*(assetType: TAssetType; fileName: string): string =
   case assetType
   of FGraphics: result.add "gfx/"
   of FSound:    result.add "sfx/"
-  else: nil
+  else: discard
   result.add fileName
 proc expandPath*(fc: ScFileChallenge): string {.inline.} =
   result = expandPath(fc.assetType, fc.file)
@@ -280,10 +280,10 @@ else:
     if not s.soundBuf.isNil:
       result = true
 
-template addError(e: expr): stmt {.immediate.} =
+template addError(e: untyped) =
   errors.add(e)
   result = false
-proc validateSettings*(settings: PJsonNode, errors: var seq[string]): bool =
+proc validateSettings*(settings: JsonNode, errors: var seq[string]): bool =
   result = true
   if settings.kind != JObject:
     addError("Settings root must be an object")
@@ -328,10 +328,10 @@ proc loadSettingsFromFile*(filename: string, errors: var seq[string]): bool =
     result = loadSettings(readFile(filename), errors)
 
 proc loadSettings*(rawJson: string, errors: var seq[string]): bool =
-  var settings: PJsonNode
+  var settings: JsonNode
   try:
     settings = parseJson(rawJson)
-  except EJsonParsingError:
+  except JsonParsingError:
     errors.add("JSON parsing error: "& getCurrentExceptionMsg())
     return
   except:
@@ -407,21 +407,21 @@ proc fetchObj*(name: string): PObjectRecord =
 proc fetchBullet(name: string): PBulletRecord =
   return cfg.bullets[nameToBulletID[name]]
 
-proc getField(node: PJsonNode, field: string, target: var float) =
+proc getField(node: JsonNode, field: string, target: var float) =
   if not node.hasKey(field):
     return
   if node[field].kind == JFloat:
     target = node[field].fnum
   elif node[field].kind == JInt:
     target = node[field].num.float
-proc getField(node: PJsonNode, field: string, target: var int) =
+proc getField(node: JsonNode, field: string, target: var int) =
   if not node.hasKey(field):
     return
   if node[field].kind == JInt:
     target = node[field].num.int
   elif node[field].kind == JFloat:
     target = node[field].fnum.int
-proc getField(node: PJsonNode; field: string; target: var bool) =
+proc getField(node: JsonNode; field: string; target: var bool) =
   if not node.hasKey(field):
     return
   case node[field].kind
@@ -431,19 +431,19 @@ proc getField(node: PJsonNode; field: string; target: var bool) =
     target = (node[field].num != 0)
   of JFloat:
     target = (node[field].fnum != 0.0)
-  else: nil
+  else: discard
 
-template checkKey(node: expr; key: string): stmt =
+template checkKey(node: untyped; key: string) =
   if not hasKey(node, key):
     return
 
-proc importTrail(data: PJsonNode; errors: var seq[string]): TTrailRecord =
+proc importTrail(data: JsonNode; errors: var seq[string]): TTrailRecord =
   checkKey(data, "trail")
   result.anim = importAnim(data["trail"], errors)
   result.timer = 1000.0
   getField(data["trail"], "timer", result.timer)
   result.timer /= 1000.0
-proc importLevel(data: PJsonNode; errors: var seq[string]): PLevelSettings =
+proc importLevel(data: JsonNode; errors: var seq[string]): PLevelSettings =
   new(result)
   result.size = vec2i(5000, 5000)
   result.starfield = @[]
@@ -456,7 +456,7 @@ proc importLevel(data: PJsonNode; errors: var seq[string]): PLevelSettings =
   if level.hasKey("starfield"):
     for star in level["starfield"].items:
       result.starfield.add(newSprite(star.str, errors))
-proc importPhys(data: PJsonNode): TPhysicsRecord =
+proc importPhys(data: JsonNode): TPhysicsRecord =
   result.radius = 20.0
   result.mass = 10.0
 
@@ -466,7 +466,7 @@ proc importPhys(data: PJsonNode): TPhysicsRecord =
     phys.getField("mass", result.mass)
   when not defined(NoChipmunk):
     result.moment = momentForCircle(result.mass, 0.0, result.radius, VectorZero) * MomentMult
-proc importHandling(data: PJsonNode): THandlingRecord =
+proc importHandling(data: JsonNode): THandlingRecord =
   result.thrust = 45.0
   result.topSpeed = 100.0 #unused
   result.reverse = 30.0
@@ -483,7 +483,7 @@ proc importHandling(data: PJsonNode): THandlingRecord =
   hand.getField("reverse", result.reverse)
   hand.getField("strafe", result.strafe)
   hand.getField("rotation", result.rotation)
-proc importAnim(data: PJsonNode, errors: var seq[string]): PAnimationRecord =
+proc importAnim(data: JsonNode, errors: var seq[string]): PAnimationRecord =
   new(result)
   result.angle = 0.0
   result.delay = 1000.0
@@ -502,26 +502,26 @@ proc importAnim(data: PJsonNode, errors: var seq[string]): PAnimationRecord =
 
   result.angle = radians(result.angle) ## comes in as degrees
   result.delay /= 1000 ## delay comes in as milliseconds
-proc importSoul(data: PJsonNode): TSoulRecord =
+proc importSoul(data: JsonNode): TSoulRecord =
   result.energy = 10000
   result.health = 1
   checkKey(data, "soul")
   let soul = data["soul"]
   soul.getField("energy", result.energy)
   soul.getField("health", result.health)
-proc importExplosion(data: PJsonNode; errors: var seq[string]): TExplosionRecord =
+proc importExplosion(data: JsonNode; errors: var seq[string]): TExplosionRecord =
   checkKey(data, "explode")
   let expl = data["explode"]
   result.anim = importAnim(expl, errors)
   result.sound = importSound(expl, errors, "sound")
-proc importSound*(data: PJsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord =
+proc importSound*(data: JsonNode; errors: var seq[string]; fieldName: string = nil): PSoundRecord =
   if data.kind == JObject:
     checkKey(data, fieldName)
     result = newSound(data[fieldName].str, errors)
   elif data.kind == JString:
     result = newSound(data.str, errors)
 
-proc importVeh(data: PJsonNode; errors: var seq[string]): PVehicleRecord =
+proc importVeh(data: JsonNode; errors: var seq[string]): PVehicleRecord =
   new(result)
   result.playable = false
   if data.kind != JArray or data.len != 2 or
@@ -538,7 +538,7 @@ proc importVeh(data: PJsonNode; errors: var seq[string]): PVehicleRecord =
   vehdata.getField("playable", result.playable)
   if result.anim.spriteSheet.isNil and result.playable:
     result.playable = false
-proc importObject(data: PJsonNode; errors: var seq[string]): PObjectRecord =
+proc importObject(data: JsonNode; errors: var seq[string]): PObjectRecord =
   new(result)
   if data.kind != JArray or data.len != 2:
     result.name = "(broken)"
@@ -546,7 +546,7 @@ proc importObject(data: PJsonNode; errors: var seq[string]): PObjectRecord =
   result.name = data[0].str
   result.anim = importAnim(data[1], errors)
   result.physics = importPhys(data[1])
-proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord =
+proc importItem(data: JsonNode; errors: var seq[string]): PItemRecord =
   new(result)
   if data.kind != JArray or data.len != 3:
     result.name = "(broken)"
@@ -562,7 +562,7 @@ proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord =
 
   result.useSound = importSound(data[2], errors, "useSound")
 
-  case data[1].str.toLower
+  case data[1].str.toLowerAscii
   of "projectile":
     result.kind = Projectile
     if data[2]["bullet"].kind == JString:
@@ -576,15 +576,15 @@ proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord =
   of "ammo":
     result.kind = Ammo
   of "utility":
-    nil
+    discard
   else:
     errors.add "Invalid item type \""&data[1].str&"\" for item "&result.name
 
-proc importBullet(data: PJsonNode; errors: var seq[string]): PBulletRecord =
+proc importBullet(data: JsonNode; errors: var seq[string]): PBulletRecord =
   new(result)
   result.id = -1
 
-  var bdata: PJsonNode
+  var bdata: JsonNode
   if data.kind == JArray:
     result.name = data[0].str
     bdata = data[1]
diff --git a/tests/manyloc/keineschweine/lib/sg_gui.nim b/tests/manyloc/keineschweine/lib/sg_gui.nim
index ffc4e8215..b7448d9df 100644
--- a/tests/manyloc/keineschweine/lib/sg_gui.nim
+++ b/tests/manyloc/keineschweine/lib/sg_gui.nim
@@ -2,7 +2,7 @@ import
   sfml, sfml_colors,
   input_helpers, sg_packets
 from strutils import countlines
-{.deadCodeElim: on.}
+
 type
   PGuiContainer* = ref TGuiContainer
   TGuiContainer* = object of TObject
diff --git a/tests/manyloc/keineschweine/lib/sg_packets.nim b/tests/manyloc/keineschweine/lib/sg_packets.nim
index d84bf72fc..f3a0e8925 100644
--- a/tests/manyloc/keineschweine/lib/sg_packets.nim
+++ b/tests/manyloc/keineschweine/lib/sg_packets.nim
@@ -4,14 +4,14 @@ defPacketImports()
 type
   PacketID* = char
 
-template idpacket(pktName, id, s2c, c2s: expr): stmt {.immediate, dirty.} =
+template idpacket(pktName, id, s2c, c2s: untyped) {.dirty.} =
   let `H pktName`* {.inject.} = id
   defPacket(`Sc pktName`, s2c)
   defPacket(`Cs pktName`, c2s)
 
 forwardPacketT(uint8, int8)
 forwardPacketT(uint16, int16)
-forwardPacketT(TPort, int16)
+forwardPacketT(Port, int16)
 
 idPacket(Login, 'a',
   tuple[id: int32; alias: string; sessionKey: string],
@@ -22,7 +22,7 @@ defPacket(CsZoneJoinReq, tuple[session: ScLogin])
 
 defPacket(ScZoneRecord, tuple[
   name: string = "", desc: string = "",
-  ip: string = "", port: TPort = 0.Tport])
+  ip: string = "", port: Port = 0.Port])
 idPacket(ZoneList, 'z',
   tuple[network: string = "", zones: seq[ScZoneRecord]],
   tuple[time: string])
diff --git a/tests/manyloc/keineschweine/server/nim.cfg b/tests/manyloc/keineschweine/server/nim.cfg
index fdc45a8e1..211ad3003 100644
--- a/tests/manyloc/keineschweine/server/nim.cfg
+++ b/tests/manyloc/keineschweine/server/nim.cfg
@@ -1,5 +1,4 @@
 debugger = off
-deadCodeElim = on
 path = ".."
 path = "../genpacket"
 path = "../helpers"
diff --git a/tests/manyloc/nake/nake.nim b/tests/manyloc/nake/nake.nim
index 1e88fa73b..728619e47 100644
--- a/tests/manyloc/nake/nake.nim
+++ b/tests/manyloc/nake/nake.nim
@@ -67,7 +67,7 @@ else:
     for kind, key, val in getOpt():
       case kind
       of cmdLongOption, cmdShortOption:
-        case key.tolower
+        case key.tolowerAscii
         of "tasks", "t":
           printTaskList = true
         else:
diff --git a/tests/manyloc/nake/nakefile.nim b/tests/manyloc/nake/nakefile.nim
index 2055d7834..3e8609169 100644
--- a/tests/manyloc/nake/nakefile.nim
+++ b/tests/manyloc/nake/nakefile.nim
@@ -10,7 +10,7 @@ const
   ExeName = "keineschweine"
   ServerDefines = "-d:NoSFML -d:NoChipmunk"
   TestBuildDefines = "-d:escapeMenuTest -d:debugWeps -d:showFPS -d:moreNim -d:debugKeys -d:foo -d:recordMode --forceBuild"
-  ReleaseDefines = "-d:release --deadCodeElim:on"
+  ReleaseDefines = "-d:release"
   ReleaseTestDefines = "-d:debugWeps -d:debugKeys --forceBuild"
 
 task "testprofile", "..":
@@ -88,7 +88,7 @@ task "download", "download game assets":
   if existsFile(path):
     echo "The file already exists\n",
       "[R]emove  [M]ove  [Q]uit  [S]kip    Source: ", GameAssets
-    case stdin.readLine.toLower
+    case stdin.readLine.toLowerAscii
     of "r":
       removeFile path
     of "m":
@@ -120,7 +120,7 @@ task "download", "download game assets":
 
   echo "Download binary libs? Only libs for linux are available currently, enjoy the irony.\n",
     "[Y]es [N]o   Source: ", BinLibs
-  case stdin.readline.toLower
+  case stdin.readline.toLowerAscii
   of "y", "yes":
     discard ## o_O
   else:
diff --git a/tests/manyloc/standalone/barebone.nim.cfg b/tests/manyloc/standalone/barebone.nim.cfg
index bb350ff55..b956bef8e 100644
--- a/tests/manyloc/standalone/barebone.nim.cfg
+++ b/tests/manyloc/standalone/barebone.nim.cfg
@@ -1,3 +1,2 @@
 --os:standalone
---deadCodeElim:on
 --gc:none
diff --git a/tests/metatype/tbindtypedesc.nim b/tests/metatype/tbindtypedesc.nim
index b287aad01..039acfbe9 100644
--- a/tests/metatype/tbindtypedesc.nim
+++ b/tests/metatype/tbindtypedesc.nim
@@ -46,7 +46,7 @@ type
   type1 = typedesc
   type2 = typedesc
 
-proc typePairs(A, B: type1; C, D: type2) = nil
+proc typePairs(A, B: type1; C, D: type2) = discard
 
 accept typePairs(int, int, TFoo, TFOO)
 accept typePairs(TBAR, TBar, TBAR, TBAR)
@@ -55,7 +55,7 @@ accept typePairs(int, int, string, string)
 reject typePairs(TBAR, TBar, TBar, TFoo)
 reject typePairs(string, int, TBAR, TBAR)
 
-proc typePairs2[T: typedesc, U: typedesc](A, B: T; C, D: U) = nil
+proc typePairs2[T: typedesc, U: typedesc](A, B: T; C, D: U) = discard
 
 accept typePairs2(int, int, TFoo, TFOO)
 accept typePairs2(TBAR, TBar, TBAR, TBAR)
@@ -71,12 +71,12 @@ proc dontBind(a: typedesc, b: typedesc) =
 accept dontBind(int, float)
 accept dontBind(TFoo, TFoo)
 
-proc dontBind2(a, b: typedesc) = nil
+proc dontBind2(a, b: typedesc) = discard
 
 accept dontBind2(int, float)
 accept dontBind2(TBar, int)
 
-proc bindArg(T: typedesc, U: typedesc, a, b: T, c, d: U) = nil
+proc bindArg(T: typedesc, U: typedesc, a, b: T, c, d: U) = discard
 
 accept bindArg(int, string, 10, 20, "test", "nest")
 accept bindArg(int, int, 10, 20, 30, 40)
diff --git a/tests/method/tsimmeth.nim b/tests/method/tsimmeth.nim
index 11ff2674f..a057c35b7 100644
--- a/tests/method/tsimmeth.nim
+++ b/tests/method/tsimmeth.nim
@@ -6,7 +6,7 @@ discard """
 
 import strutils
 
-var x = "hello world!".toLower.toUpper
+var x = "hello world!".toLowerAscii.toUpperAscii
 x.echo()
 #OUT HELLO WORLD!
 
diff --git a/tests/misc/tmemoization.nim b/tests/misc/tmemoization.nim
index 180acd89b..840eb3b0d 100644
--- a/tests/misc/tmemoization.nim
+++ b/tests/misc/tmemoization.nim
@@ -8,7 +8,7 @@ import strutils
 proc foo(s: static[string]): string =
   static: echo s
 
-  const R = s.toUpper
+  const R = s.toUpperAscii
   return R
 
 echo foo("test 1")
diff --git a/tests/misc/tsemfold.nim b/tests/misc/tsemfold.nim
new file mode 100644
index 000000000..18c282d9e
--- /dev/null
+++ b/tests/misc/tsemfold.nim
@@ -0,0 +1,23 @@
+discard """
+  action: run
+"""
+
+doAssertRaises(OverflowError): discard low(int8) - 1'i8
+doAssertRaises(OverflowError): discard high(int8) + 1'i8
+doAssertRaises(OverflowError): discard abs(low(int8))
+doAssertRaises(DivByZeroError): discard 1 mod 0
+doAssertRaises(DivByZeroError): discard 1 div 0
+doAssertRaises(OverflowError): discard low(int8) div -1'i8
+
+doAssertRaises(OverflowError): discard low(int64) - 1'i64
+doAssertRaises(OverflowError): discard high(int64) + 1'i64
+
+type E = enum eA, eB
+doAssertRaises(OverflowError): discard eA.pred
+doAssertRaises(OverflowError): discard eB.succ
+
+doAssertRaises(OverflowError): discard low(int8) * -1
+doAssertRaises(OverflowError): discard low(int64) * -1
+doAssertRaises(OverflowError): discard high(int8) * 2
+doAssertRaises(OverflowError): discard high(int64) * 2
+
diff --git a/tests/misc/tsimplesort.nim b/tests/misc/tsimplesort.nim
index 3115863d5..e4a8e0b37 100644
--- a/tests/misc/tsimplesort.nim
+++ b/tests/misc/tsimplesort.nim
@@ -40,11 +40,11 @@ proc mustRehash(length, counter: int): bool {.inline.} =
   assert(length > counter)
   result = (length * 2 < counter * 3) or (length - counter < 4)
 
-proc nextTry(h, maxHash: THash): THash {.inline.} =
+proc nextTry(h, maxHash: Hash): Hash {.inline.} =
   result = ((5 * h) + 1) and maxHash
 
 template rawGetImpl() =
-  var h: THash = hash(key) and high(t.data) # start with real hash value
+  var h: Hash = hash(key) and high(t.data) # start with real hash value
   while t.data[h].slot != seEmpty:
     if t.data[h].key == key and t.data[h].slot == seFilled:
       return h
@@ -52,7 +52,7 @@ template rawGetImpl() =
   result = -1
 
 template rawInsertImpl() =
-  var h: THash = hash(key) and high(data)
+  var h: Hash = hash(key) and high(data)
   while data[h].slot == seFilled:
     h = nextTry(h, high(data))
   data[h].key = key
@@ -162,7 +162,7 @@ iterator values*[A](t: TCountTable[A]): int =
     if t.data[h].val != 0: yield t.data[h].val
 
 proc RawGet[A](t: TCountTable[A], key: A): int =
-  var h: THash = hash(key) and high(t.data) # start with real hash value
+  var h: Hash = hash(key) and high(t.data) # start with real hash value
   while t.data[h].val != 0:
     if t.data[h].key == key: return h
     h = nextTry(h, high(t.data))
@@ -181,7 +181,7 @@ proc hasKey*[A](t: TCountTable[A], key: A): bool =
 
 proc rawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]],
                   key: A, val: int) =
-  var h: THash = hash(key) and high(data)
+  var h: Hash = hash(key) and high(data)
   while data[h].val != 0: h = nextTry(h, high(data))
   data[h].key = key
   data[h].val = val
diff --git a/tests/misc/tunsignedmisc.nim b/tests/misc/tunsignedmisc.nim
index 4b8157ddd..fc02eee19 100644
--- a/tests/misc/tunsignedmisc.nim
+++ b/tests/misc/tunsignedmisc.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "number 0x123'u8 out of valid range"
+  errormsg: "number out of range: '0x123'u8'"
 """
 
 # Bug #1179
diff --git a/tests/modules/definitions.nim b/tests/modules/definitions.nim
new file mode 100644
index 000000000..edc6eaa6d
--- /dev/null
+++ b/tests/modules/definitions.nim
@@ -0,0 +1,4 @@
+var v*: int
+proc p* = echo "proc p called"
+template t* = echo "template t expanded"
+
diff --git a/tests/modules/proxy_module.nim b/tests/modules/proxy_module.nim
new file mode 100644
index 000000000..c244688cd
--- /dev/null
+++ b/tests/modules/proxy_module.nim
@@ -0,0 +1,3 @@
+import definitions
+export definitions except p
+
diff --git a/tests/notnil/tmust_compile.nim b/tests/notnil/tmust_compile.nim
index 10da154f0..a32c6c7ec 100644
--- a/tests/notnil/tmust_compile.nim
+++ b/tests/notnil/tmust_compile.nim
@@ -3,6 +3,7 @@ discard """
 """
 
 # bug #6682
+{.experimental: "notnil".}
 
 type
     Fields = enum
diff --git a/tests/notnil/tnotnil.nim b/tests/notnil/tnotnil.nim
index f65634ed6..e392b155c 100644
--- a/tests/notnil/tnotnil.nim
+++ b/tests/notnil/tnotnil.nim
@@ -2,7 +2,7 @@ discard """
   line: 22
   errormsg: "type mismatch"
 """
-
+{.experimental: "notnil".}
 type
   PObj = ref TObj not nil
   TObj = object
@@ -15,8 +15,8 @@ type
 proc p(x: string not nil): int =
   result = 45
 
-proc q(x: MyString) = nil
-proc q2(x: string) = nil
+proc q(x: MyString) = discard
+proc q2(x: string) = discard
 
 q2(nil)
 q(nil)
diff --git a/tests/notnil/tnotnil1.nim b/tests/notnil/tnotnil1.nim
index 73472752c..7f9d02295 100644
--- a/tests/notnil/tnotnil1.nim
+++ b/tests/notnil/tnotnil1.nim
@@ -4,7 +4,7 @@ discard """
 """
 
 import strutils
-
+{.experimental: "notnil".}
 
 type
   TObj = object
@@ -18,13 +18,13 @@ proc q(s: superstring) =
   echo s
 
 proc p2() =
-  var  a: string = "I am not nil"
+  var a: string = "I am not nil"
   q(a) # but this should and does not
 
 p2()
 
 proc q(x: pointer not nil) =
-  nil
+  discard
 
 proc p() =
   var x: pointer
diff --git a/tests/notnil/tnotnil2.nim b/tests/notnil/tnotnil2.nim
index bd6b8b675..6cd08de73 100644
--- a/tests/notnil/tnotnil2.nim
+++ b/tests/notnil/tnotnil2.nim
@@ -4,14 +4,14 @@ discard """
 """
 
 import strutils
-
+{.experimental: "notnil".}
 
 type
   TObj = object
     x, y: int
 
 proc q(x: pointer not nil) =
-  nil
+  discard
 
 proc p() =
   var x: pointer
diff --git a/tests/notnil/tnotnil3.nim b/tests/notnil/tnotnil3.nim
index b7c7a811d..31a4efef7 100644
--- a/tests/notnil/tnotnil3.nim
+++ b/tests/notnil/tnotnil3.nim
@@ -5,7 +5,7 @@ discard """
 
 # bug #584
 # Testprogram for 'not nil' check
-
+{.experimental: "notnil".}
 const testWithResult = true
 
 type
diff --git a/tests/notnil/tnotnil4.nim b/tests/notnil/tnotnil4.nim
index 2fa888357..4fd169827 100644
--- a/tests/notnil/tnotnil4.nim
+++ b/tests/notnil/tnotnil4.nim
@@ -2,6 +2,8 @@ discard ""
 type
    TObj = ref object
 
+{.experimental: "notnil".}
+
 proc check(a: TObj not nil) =
   echo repr(a)
 
diff --git a/tests/notnil/tnotnil_in_generic.nim b/tests/notnil/tnotnil_in_generic.nim
index 357ab2c7c..89d20f182 100644
--- a/tests/notnil/tnotnil_in_generic.nim
+++ b/tests/notnil/tnotnil_in_generic.nim
@@ -3,6 +3,7 @@ discard """
 """
 
 # bug #2216
+{.experimental: "notnil".}
 
 type
     A[T] = ref object
diff --git a/tests/notnil/tnotnil_in_objconstr.nim b/tests/notnil/tnotnil_in_objconstr.nim
index 7dce98c29..d33709906 100644
--- a/tests/notnil/tnotnil_in_objconstr.nim
+++ b/tests/notnil/tnotnil_in_objconstr.nim
@@ -2,7 +2,7 @@ discard """
   errormsg: "fields not initialized: bar"
   line: "13"
 """
-
+{.experimental: "notnil".}
 # bug #2355
 type
   Foo = object
diff --git a/tests/objects/tinherentedvalues.nim b/tests/objects/tinherentedvalues.nim
index c96a0fd6d..ad7b5f326 100644
--- a/tests/objects/tinherentedvalues.nim
+++ b/tests/objects/tinherentedvalues.nim
@@ -1,9 +1,7 @@
 discard """
-  output: '''tbObj of TC false
-false
+  output: '''tbObj of TC true
 true
-5
-false'''
+5'''
 """
 
 # bug #1053
@@ -20,10 +18,10 @@ type
 proc test(p: TA) =
   #echo "p of TB ", p of TB
   if p of TB:
-    var tbObj = TB(p)
+    #var tbObj = TB(p)
 
     # tbObj is actually no longer compatible with TC:
-    echo "tbObj of TC ", tbObj of TC
+    echo "tbObj of TC ", p of TC
 
 var v = TC()
 v.a = 1
@@ -48,8 +46,8 @@ proc isMyObject(obj: TObject) =
 
 asd.x = 5
 
-var asdCopy = TObject(asd)
-echo asdCopy of MyObject
+#var asdCopy = TObject(asd)
+#echo asdCopy of MyObject
 
 isMyObject(asd)
-isMyObject(asdCopy)
+#isMyObject(asdCopy)
diff --git a/tests/objects/tobj_asgn_dont_slice.nim b/tests/objects/tobj_asgn_dont_slice.nim
new file mode 100644
index 000000000..866b5aecc
--- /dev/null
+++ b/tests/objects/tobj_asgn_dont_slice.nim
@@ -0,0 +1,24 @@
+discard """
+  outputsub: '''ObjectAssignmentError'''
+  exitcode: "1"
+"""
+
+# bug #7637
+type
+  Fruit = object of RootObj
+    name*: string
+  Apple = object of Fruit
+  Pear = object of Fruit
+
+method eat(f: Fruit) {.base.} =
+  raise newException(Exception, "PURE VIRTUAL CALL")
+
+method eat(f: Apple) =
+  echo "fruity"
+
+method eat(f: Pear) =
+  echo "juicy"
+
+let basket = [Apple(name:"a"), Pear(name:"b")]
+
+eat(basket[0])
diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim
index d1f3c8bdb..7238d10c7 100644
--- a/tests/objects/tobjconstr.nim
+++ b/tests/objects/tobjconstr.nim
@@ -9,8 +9,8 @@ discard """
 (k: kindA, a: (x: "abc", z: [1, 8, 3]), method: ())
 (k: kindA, a: (x: "abc", z: [1, 9, 3]), method: ())
 (k: kindA, a: (x: "abc", z: [1, 10, 3]), method: ())
-(x: 123)
-(x: 123)
+(y: 0, x: 123)
+(y: 678, x: 123)
 (z: 89, y: 0, x: 128)
 (y: 678, x: 123)
 (y: 678, x: 123)
@@ -33,7 +33,6 @@ type
       `method`: TEmpty # bug #1791
 
 proc `$`[T](s: seq[T]): string =
-  # XXX why is that not in the stdlib?
   result = "["
   for i, x in s:
     if i > 0: result.add(", ")
@@ -59,7 +58,7 @@ type
 # inherited fields are ignored, so no fields are set
 when true:
   var
-    o: A
+    o: B
   o = B(x: 123)
   echo o
   o = B(y: 678, x: 123)
diff --git a/tests/objvariant/tcheckedfield1.nim b/tests/objvariant/tcheckedfield1.nim
index 56d784a2b..a7f232c5b 100644
--- a/tests/objvariant/tcheckedfield1.nim
+++ b/tests/objvariant/tcheckedfield1.nim
@@ -6,7 +6,7 @@ discard """
 import strutils
 
 {.warning[ProveField]: on.}
-
+{.experimental: "notnil".}
 type
   TNodeKind = enum
     nkBinary, nkTernary, nkStr
diff --git a/tests/objvariant/temptycaseobj.nim b/tests/objvariant/temptycaseobj.nim
index 5c012746e..53171e054 100644
--- a/tests/objvariant/temptycaseobj.nim
+++ b/tests/objvariant/temptycaseobj.nim
@@ -1,6 +1,6 @@
 discard """
   line: 11
-  errormsg: "identifier expected, but found 'keyword of'"
+  errormsg: "identifier expected, but got 'keyword of'"
 """
 
 type
diff --git a/tests/osproc/tclose.nim b/tests/osproc/tclose.nim
new file mode 100644
index 000000000..d466b466a
--- /dev/null
+++ b/tests/osproc/tclose.nim
@@ -0,0 +1,24 @@
+discard """
+  exitcode: 0
+"""
+
+when defined(linux):
+  import osproc, os
+
+  proc countFds(): int =
+    result = 0
+    for i in walkDir("/proc/self/fd"):
+      result += 1
+
+  let initCount = countFds()
+
+  let p = osproc.startProcess("echo", options={poUsePath})
+  assert countFds() == initCount + 3
+  p.close
+  assert countFds() == initCount
+
+  let p1 = osproc.startProcess("echo", options={poUsePath})
+  discard p1.inputStream
+  assert countFds() == initCount + 3
+  p.close
+  assert countFds() == initCount
diff --git a/tests/overload/tissue966.nim b/tests/overload/tissue966.nim
index c5b28e217..d0a723875 100644
--- a/tests/overload/tissue966.nim
+++ b/tests/overload/tissue966.nim
@@ -5,7 +5,7 @@ discard """
 type
   PTest = ref object
 
-proc test(x: PTest, y: int) = nil
+proc test(x: PTest, y: int) = discard
 
 var buf: PTest
 buf.test()
diff --git a/tests/overload/toverprc.nim b/tests/overload/toverprc.nim
index 112eae096..9be2203f6 100644
--- a/tests/overload/toverprc.nim
+++ b/tests/overload/toverprc.nim
@@ -11,7 +11,7 @@ proc parseInt(x: float): int {.noSideEffect.} = discard
 proc parseInt(x: bool): int {.noSideEffect.} = discard
 proc parseInt(x: float32): int {.noSideEffect.} = discard
 proc parseInt(x: int8): int {.noSideEffect.} = discard
-proc parseInt(x: TFile): int {.noSideEffect.} = discard
+proc parseInt(x: File): int {.noSideEffect.} = discard
 proc parseInt(x: char): int {.noSideEffect.} = discard
 proc parseInt(x: int16): int {.noSideEffect.} = discard
 
diff --git a/tests/overload/tparam_forwarding.nim b/tests/overload/tparam_forwarding.nim
index c1b276bfc..b0eea42c7 100644
--- a/tests/overload/tparam_forwarding.nim
+++ b/tests/overload/tparam_forwarding.nim
@@ -6,6 +6,10 @@ output: '''baz
 a
 b
 c
+x: 1, y: test 1
+x: 2, y: test 2
+x: 10, y: test 3
+x: 4, y: test 4
 '''
 """
 
@@ -35,3 +39,15 @@ templateForwarding fooVarargs, "test".len > 3, Foo(x: 10), Foo(x: 100), Foo(x: 1
 
 procForwarding "a", "b", "c"
 
+proc hasKeywordArgs(x = 10, y = "y") =
+  echo "x: ", x, ", y: ", y
+
+proc hasRegularArgs(x: int, y: string) =
+  echo "x: ", x, ", y: ", y
+
+templateForwarding(hasRegularArgs, true, 1, "test 1")
+templateForwarding hasKeywordArgs, true, 2, "test 2"
+
+templateForwarding(hasKeywordArgs, true, y = "test 3")
+templateForwarding hasKeywordArgs, true, y = "test 4", x = 4
+
diff --git a/tests/parallel/tparfind.nim b/tests/parallel/tparfind.nim
index 9de5012f5..4b3610c67 100644
--- a/tests/parallel/tparfind.nim
+++ b/tests/parallel/tparfind.nim
@@ -4,7 +4,7 @@ discard """
 
 import threadpool, sequtils
 
-{.experimental.}
+{.experimental: "parallel".}
 
 proc linearFind(a: openArray[int]; x, offset: int): int =
   for i, y in a:
diff --git a/tests/parallel/twaitany.nim b/tests/parallel/twaitany.nim
new file mode 100644
index 000000000..69136a3b6
--- /dev/null
+++ b/tests/parallel/twaitany.nim
@@ -0,0 +1,35 @@
+discard """
+  output: '''true'''
+"""
+
+# bug #7638
+import threadpool, os, strformat
+
+proc timer(d: int): int =
+  #echo fmt"sleeping {d}"
+  sleep(d)
+  #echo fmt"done {d}"
+  return d
+
+var durations = [1000, 2000, 3000, 4000, 5000]
+var tasks: seq[FlowVarBase] = @[]
+var results: seq[int] = @[]
+
+for i in 0 .. durations.high:
+  tasks.add spawn timer(durations[i])
+
+var index = awaitAny(tasks)
+while index != -1:
+  results.add ^cast[FlowVar[int]](tasks[index])
+  tasks.del(index)
+  #echo repr results
+  index = awaitAny(tasks)
+
+doAssert results.len == 5
+doAssert 1000 in results
+doAssert 2000 in results
+doAssert 3000 in results
+doAssert 4000 in results
+doAssert 5000 in results
+sync()
+echo "true"
diff --git a/tests/parser/tbraces.nim b/tests/parser/tbraces.nim
deleted file mode 100644
index 86c854546..000000000
--- a/tests/parser/tbraces.nim
+++ /dev/null
@@ -1,432 +0,0 @@
-#? braces
-
-#
-#
-#            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 implements some common generic algorithms.
-
-type
-  SortOrder* = enum {  ## sort order
-    Descending, Ascending
-  }
-
-
-type(
-  DummyAlias = int
-  OtherAlias = distinct char
-
-  SomeObject = object of RootObj { ## declaration here
-    fieldA, fieldB: int
-    case order: SortOrder {
-      of Descending {a: string}
-      of Ascending {b: seq[char]}
-    }
-  }
-
-  MyConcept = concept x {
-     x is int
-  }
-)
-
-{.deprecated: [TSortOrder: SortOrder].}
-
-
-proc `*`*(x: int, order: SortOrder): int @inline {
-  ## flips `x` if ``order == Descending``;
-  ## if ``order == Ascending`` then `x` is returned.
-  ## `x` is supposed to be the result of a comparator, ie ``< 0`` for
-  ## *less than*, ``== 0`` for *equal*, ``> 0`` for *greater than*.
-  var y = order.ord - 1
-  result = (x xor y) - y
-}
-
-proc fill*[T](a: var openArray[T], first, last: Natural, value: T) {
-  ## fills the array ``a[first..last]`` with `value`.
-  var x = first
-  while x <= last {
-    a[x] = value
-    inc(x)
-  }
-}
-
-proc fill*[T](a: var openArray[T], value: T) {
-  ## fills the array `a` with `value`.
-  fill(a, 0, a.high, value)
-}
-
-proc reverse*[T](a: var openArray[T], first, last: Natural) {
-  ## reverses the array ``a[first..last]``.
-  var x = first
-  var y = last
-  while x < y {
-    swap(a[x], a[y])
-    dec(y)
-    inc(x)
-  }
-}
-
-proc reverse*[T](a: var openArray[T]) {
-  ## reverses the array `a`.
-  reverse(a, 0, a.high)
-}
-
-proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] {
-  ## returns the reverse of the array `a[first..last]`.
-  assert last >= first-1
-  var i = last - first
-  var x = first.int
-  result = newSeq[T](i + 1)
-  while i >= 0 {
-    result[i] = a[x]
-    dec(i)
-    inc(x)
-  }
-}
-
-proc reversed*[T](a: openArray[T]): seq[T] {
-  ## returns the reverse of the array `a`.
-  reversed(a, 0, a.high)
-}
-
-proc binarySearch*[T](a: openArray[T], key: T): int {
-  ## binary search for `key` in `a`. Returns -1 if not found.
-  var b = len(a)
-  while result < b {
-    var mid = (result + b) div 2
-    if a[mid] < key { result = mid + 1 } else { b = mid }
-  }
-  if result >= len(a) or a[result] != key { result = -1 }
-}
-
-proc smartBinarySearch*[T](a: openArray[T], key: T): int {
-  ## ``a.len`` must be a power of 2 for this to work.
-  var step = a.len div 2
-  while step > 0 {
-    if a[result or step] <= key { result = result or step }
-    step = step shr 1
-  }
-  if a[result] != key { result = -1 }
-}
-
-const (
-  onlySafeCode = true
-)
-
-proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int @closure): int {
-  ## same as binarySearch except that if key is not in `a` then this
-  ## returns the location where `key` would be if it were. In other
-  ## words if you have a sorted sequence and you call
-  ## insert(thing, elm, lowerBound(thing, elm))
-  ## the sequence will still be sorted.
-  ##
-  ## `cmp` is the comparator function to use, the expected return values are
-  ## the same as that of system.cmp.
-  ##
-  ## example::
-  ##
-  ##   var arr = @[1,2,3,5,6,7,8,9]
-  ##   arr.insert(4, arr.lowerBound(4))
-  ##   # after running the above arr is `[1,2,3,4,5,6,7,8,9]`
-  result = a.low
-  var count = a.high - a.low + 1
-  var step, pos: int
-  while count != 0 {
-    step = count div 2
-    pos = result + step
-    if cmp(a[pos], key) < 0 {
-      result = pos + 1
-      count -= step + 1
-    } else {
-      count = step
-    }
-  }
-}
-
-proc lowerBound*[T](a: openArray[T], key: T): int { lowerBound(a, key, cmp[T]) }
-proc merge[T](a, b: var openArray[T], lo, m, hi: int,
-              cmp: proc (x, y: T): int @closure, order: SortOrder) {
-  template `<-` (a, b) {
-    when false {
-      a = b
-    } elif onlySafeCode {
-      shallowCopy(a, b)
-    } else {
-      copyMem(addr(a), addr(b), sizeof(T))
-    }
-  }
-  # optimization: If max(left) <= min(right) there is nothing to do!
-  # 1 2 3 4  ## 5 6 7 8
-  # -> O(n) for sorted arrays.
-  # On random data this safes up to 40% of merge calls
-  if cmp(a[m], a[m+1]) * order <= 0 { return }
-  var j = lo
-  # copy a[j..m] into b:
-  assert j <= m
-  when onlySafeCode {
-    var bb = 0
-    while j <= m {
-      b[bb] <- a[j]
-      inc(bb)
-      inc(j)
-    }
-  } else {
-    copyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1))
-    j = m+1
-  }
-  var i = 0
-  var k = lo
-  # copy proper element back:
-  while k < j and j <= hi {
-    if cmp(b[i], a[j]) * order <= 0 {
-      a[k] <- b[i]
-      inc(i)
-    } else {
-      a[k] <- a[j]
-      inc(j)
-    }
-    inc(k)
-  }
-  # copy rest of b:
-  when onlySafeCode {
-    while k < j {
-      a[k] <- b[i]
-      inc(k)
-      inc(i)
-    }
-  } else {
-    if k < j { copyMem(addr(a[k]), addr(b[i]), sizeof(T)*(j-k)) }
-  }
-}
-
-proc sort*[T](a: var openArray[T],
-              cmp: proc (x, y: T): int @closure,
-              order = SortOrder.Ascending) {
-  ## Default Nim sort (an implementation of merge sort). The sorting
-  ## is guaranteed to be stable and the worst case is guaranteed to
-  ## be O(n log n).
-  ## The current implementation uses an iterative
-  ## mergesort to achieve this. It uses a temporary sequence of
-  ## length ``a.len div 2``. Currently Nim does not support a
-  ## sensible default argument for ``cmp``, so you have to provide one
-  ## of your own. However, the ``system.cmp`` procs can be used:
-  ##
-  ## .. code-block:: nim
-  ##
-  ##    sort(myIntArray, system.cmp[int])
-  ##
-  ##    # do not use cmp[string] here as we want to use the specialized
-  ##    # overload:
-  ##    sort(myStrArray, system.cmp)
-  ##
-  ## You can inline adhoc comparison procs with the `do notation
-  ## <manual.html#procedures-do-notation>`_. Example:
-  ##
-  ## .. code-block:: nim
-  ##
-  ##   people.sort do (x, y: Person) -> int:
-  ##     result = cmp(x.surname, y.surname)
-  ##     if result == 0:
-  ##       result = cmp(x.name, y.name)
-  var n = a.len
-  var b: seq[T]
-  newSeq(b, n div 2)
-  var s = 1
-  while s < n {
-    var m = n-1-s
-    while m >= 0 {
-      merge(a, b, max(m-s+1, 0), m, m+s, cmp, order)
-      dec(m, s*2)
-    }
-    s = s*2
-  }
-}
-
-proc sorted*[T](a: openArray[T], cmp: proc(x, y: T): int {.closure.},
-                order = SortOrder.Ascending): seq[T] {
-  ## returns `a` sorted by `cmp` in the specified `order`.
-  result = newSeq[T](a.len)
-  for i in 0 .. a.high { result[i] = a[i] }
-  sort(result, cmp, order)
-}
-
-template sortedByIt*(seq1, op: untyped): untyped {
-  ## Convenience template around the ``sorted`` proc to reduce typing.
-  ##
-  ## The template injects the ``it`` variable which you can use directly in an
-  ## expression. Example:
-  ##
-  ## .. code-block:: nim
-  ##
-  ##   type Person = tuple[name: string, age: int]
-  ##   var
-  ##     p1: Person = (name: "p1", age: 60)
-  ##     p2: Person = (name: "p2", age: 20)
-  ##     p3: Person = (name: "p3", age: 30)
-  ##     p4: Person = (name: "p4", age: 30)
-  ##     people = @[p1,p2,p4,p3]
-  ##
-  ##   echo people.sortedByIt(it.name)
-  ##
-  ## Because the underlying ``cmp()`` is defined for tuples you can do
-  ## a nested sort like in the following example:
-  ##
-  ## .. code-block:: nim
-  ##
-  ##   echo people.sortedByIt((it.age, it.name))
-  ##
-  var result = sorted(seq1, proc(x, y: type[seq1[0]]): int {
-    var it {.inject.} = x
-    let a = op
-    it = y
-    let b = op
-    result = cmp(a, b)
-  })
-  result
-}
-
-proc isSorted*[T](a: openarray[T],
-                 cmp: proc(x, y: T): int {.closure.},
-                 order = SortOrder.Ascending): bool {
-  ## Checks to see whether `a` is already sorted in `order`
-  ## using `cmp` for the comparison. Parameters identical
-  ## to `sort`
-  result = true
-  for i in 0..<len(a)-1 {
-    case cmp(a[i],a[i+1]) * order > 0 {
-      of true { return false }
-      of false {}
-    }
-  }
-}
-
-proc product*[T](x: openArray[seq[T]]): seq[seq[T]] {
-  ## produces the Cartesian product of the array. Warning: complexity
-  ## may explode.
-  result = newSeq[seq[T]]()
-  if x.len == 0 { return }
-  if x.len == 1 {
-    result = @x
-    return
-  }
-  var (
-    indexes = newSeq[int](x.len)
-    initial = newSeq[int](x.len)
-    index = 0
-  )
-  var next = newSeq[T]()
-  next.setLen(x.len)
-  for i in 0..(x.len-1) {
-    if len(x[i]) == 0 { return }
-    initial[i] = len(x[i])-1
-  }
-  indexes = initial
-  while true {
-    while indexes[index] == -1 {
-      indexes[index] = initial[index]
-      index += 1
-      if index == x.len { return }
-      indexes[index] -= 1
-    }
-    for ni, i in indexes {
-      next[ni] = x[ni][i]
-    }
-    var res: seq[T]
-    shallowCopy(res, next)
-    result.add(res)
-    index = 0
-    indexes[index] -= 1
-  }
-}
-
-proc nextPermutation*[T](x: var openarray[T]): bool {.discardable.} {
-  ## Calculates the next lexicographic permutation, directly modifying ``x``.
-  ## The result is whether a permutation happened, otherwise we have reached
-  ## the last-ordered permutation.
-  ##
-  ## .. code-block:: nim
-  ##
-  ##     var v = @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-  ##     v.nextPermutation()
-  ##     echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
-  if x.len < 2 {
-    return false }
-
-  var i = x.high
-  while i > 0 and x[i-1] >= x[i] { dec i }
-  if i == 0 { return false }
-
-  var j = x.high
-  while j >= i and x[j] <= x[i-1] { dec j }
-
-  swap x[j], x[i-1]
-  x.reverse(i, x.high)
-
-  result = true
-}
-
-proc prevPermutation*[T](x: var openarray[T]): bool @discardable {
-  ## Calculates the previous lexicographic permutation, directly modifying
-  ## ``x``.  The result is whether a permutation happened, otherwise we have
-  ## reached the first-ordered permutation.
-  ##
-  ## .. code-block:: nim
-  ##
-  ##     var v = @[0, 1, 2, 3, 4, 5, 6, 7, 9, 8]
-  ##     v.prevPermutation()
-  ##     echo v # @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-  if x.len < 2 { return false }
-
-  var i = x.high
-  while i > 0 and x[i-1] <= x[i] {
-    dec i
-  }
-  if i == 0 { return false }
-
-  x.reverse(i, x.high)
-
-  var j = x.high
-  while j >= i and x[j-1] < x[i-1] {
-    dec j
-  }
-  swap x[i-1], x[j]
-
-  result = true
-}
-
-when isMainModule {
-  # Tests for lowerBound
-  var arr = @[1,2,3,5,6,7,8,9]
-  assert arr.lowerBound(0) == 0
-  assert arr.lowerBound(4) == 3
-  assert arr.lowerBound(5) == 3
-  assert arr.lowerBound(10) == 8
-  arr = @[1,5,10]
-  try {
-    assert arr.lowerBound(4) == 1
-    assert arr.lowerBound(5) == 1
-    assert arr.lowerBound(6) == 2
-  } except ValueError {}
-  # Tests for isSorted
-  var srt1 = [1,2,3,4,4,4,4,5]
-  var srt2 = ["iello","hello"]
-  var srt3 = [1.0,1.0,1.0]
-  var srt4: seq[int] = @[]
-  assert srt1.isSorted(cmp) == true
-  assert srt2.isSorted(cmp) == false
-  assert srt3.isSorted(cmp) == true
-  var srtseq = newSeq[int]()
-  assert srtseq.isSorted(cmp) == true
-  # Tests for reversed
-  var arr1 = @[0,1,2,3,4]
-  assert arr1.reversed() == @[4,3,2,1,0]
-  for i in 0 .. high(arr1) {
-    assert arr1.reversed(0, i) == arr1.reversed()[high(arr1) - i .. high(arr1)]
-    assert arr1.reversed(i, high(arr1)) == arr1.reversed()[0 .. high(arr1) - i]
-  }
-}
diff --git a/tests/parser/tcommand_as_expr.nim b/tests/parser/tcommand_as_expr.nim
index a244c8767..b25ec4bd8 100644
--- a/tests/parser/tcommand_as_expr.nim
+++ b/tests/parser/tcommand_as_expr.nim
@@ -2,7 +2,10 @@ discard """
   output: '''140
 5-120-120
 359
-77'''
+77
+-4
+-1
+-1'''
 """
 #import math
 import sequtils
@@ -25,3 +28,11 @@ let a = [2,4,8].map do (d:int) -> int: d + 1
 echo a[0], a[1], a[2]
 
 echo(foo 8, foo 8)
+
+# bug #7582
+proc f(x: int): int = x
+
+echo f -4
+
+echo int -1 # doesn't compile
+echo int `-` 1 # compiles
diff --git a/tests/parser/tinvcolonlocation1.nim b/tests/parser/tinvcolonlocation1.nim
index cacde48bd..2fddab2f8 100644
--- a/tests/parser/tinvcolonlocation1.nim
+++ b/tests/parser/tinvcolonlocation1.nim
@@ -1,8 +1,8 @@
 discard """
   file: "tinvcolonlocation1.nim"
   line: 8
-  column: 3
-  errormsg: "':' expected"
+  column: 7
+  errormsg: "expected: ':', but got: 'echo'"
 """
 try #<- missing ':'
   echo "try"
diff --git a/tests/parser/tinvcolonlocation2.nim b/tests/parser/tinvcolonlocation2.nim
index 2b6a92b9d..4251598b9 100644
--- a/tests/parser/tinvcolonlocation2.nim
+++ b/tests/parser/tinvcolonlocation2.nim
@@ -1,8 +1,8 @@
 discard """
   file: "tinvcolonlocation2.nim"
   line: 11
-  column: 1
-  errormsg: "':' expected"
+  column: 8
+  errormsg: "expected: ':', but got: 'keyword finally'"
 """
 try:
   echo "try"
diff --git a/tests/parser/tinvcolonlocation3.nim b/tests/parser/tinvcolonlocation3.nim
index 2b30b1dbe..a8db658eb 100644
--- a/tests/parser/tinvcolonlocation3.nim
+++ b/tests/parser/tinvcolonlocation3.nim
@@ -1,8 +1,8 @@
 discard """
   file: "tinvcolonlocation3.nim"
   line: 12
-  column: 3
-  errormsg: "':' expected"
+  column: 7
+  errormsg: "expected: ':', but got: 'echo'"
 """
 try:
   echo "try"
diff --git a/tests/parser/twhen_in_enum.nim b/tests/parser/twhen_in_enum.nim
index d4a3ea56a..3890b686e 100644
--- a/tests/parser/twhen_in_enum.nim
+++ b/tests/parser/twhen_in_enum.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "identifier expected, but found 'keyword when'"
+  errormsg: "identifier expected, but got 'keyword when'"
 """
 
 # bug #2123
diff --git a/tests/parser/twrongcmdsyntax.nim b/tests/parser/twrongcmdsyntax.nim
index affe72c34..c2962bed4 100644
--- a/tests/parser/twrongcmdsyntax.nim
+++ b/tests/parser/twrongcmdsyntax.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: '''identifier expected, but found 'echo 4'''
+  errormsg: '''in expression '4 2': identifier expected, but found '4'''
   line: 6
 """
 
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim
index 28a8713ce..33a4a7e65 100644
--- a/tests/pragmas/tcustom_pragma.nim
+++ b/tests/pragmas/tcustom_pragma.nim
@@ -51,6 +51,9 @@ block: # A bit more advanced case
 
   static: assert(hasCustomPragma(myproc, alternativeKey))
 
+  const hasFieldCustomPragma = s.field.hasCustomPragma(defaultValue)
+  static: assert(hasFieldCustomPragma == false)
+
   # pragma on an object
   static:
     assert Subfield.hasCustomPragma(defaultValue)
@@ -71,6 +74,8 @@ block: # ref types
     MyFile {.defaultValue: "closed".} = ref object
       path {.defaultValue: "invalid".}: string
 
+    TypeWithoutPragma = object
+
   var s = NodeRef()
 
   const
@@ -91,7 +96,7 @@ block: # ref types
 
   var ptrS = NodePtr(nil)
   const
-    ptrRightSerKey = getCustomPragmaVal(s.right, serializationKey)
+    ptrRightSerKey = getCustomPragmaVal(ptrS.right, serializationKey)
   static:
     assert ptrRightSerKey == "r"
 
@@ -103,6 +108,9 @@ block: # ref types
     assert fileDefVal == "closed"
     assert filePathDefVal == "invalid"
 
+  static:
+    assert TypeWithoutPragma.hasCustomPragma(defaultValue) == false
+
 block:
   type
     VariantKind = enum
diff --git a/tests/pragmas/tnoreturn.nim b/tests/pragmas/tnoreturn.nim
index 4d00c6034..bb59b1c71 100644
--- a/tests/pragmas/tnoreturn.nim
+++ b/tests/pragmas/tnoreturn.nim
@@ -2,13 +2,16 @@ discard """
 ccodeCheck: "\\i @'__attribute__((noreturn))' .*"
 """
 
-proc noret1*(i: int) {.noreturn.} = 
+proc noret1*(i: int) {.noreturn.} =
   echo i
 
 
-proc noret2*(i: int): void {.noreturn.} = 
+proc noret2*(i: int): void {.noreturn.} =
   echo i
 
+noret1(1)
+noret2(2)
+
 var p {.used.}: proc(i: int): int
 doAssert(not compiles(
   p = proc(i: int): int {.noreturn.} = i # noreturn lambda returns int
diff --git a/tests/proc/tprocredef.nim b/tests/proc/tprocredef.nim
index 86ed92b62..4ec771510 100644
--- a/tests/proc/tprocredef.nim
+++ b/tests/proc/tprocredef.nim
@@ -4,6 +4,6 @@ discard """
   errormsg: "redefinition of \'foo\'"
 """
 
-proc foo(a: int, b: string) = nil
-proc foo(a: int, b: string) = nil
+proc foo(a: int, b: string) = discard
+proc foo(a: int, b: string) = discard
 
diff --git a/tests/range/tsubrange.nim b/tests/range/tsubrange.nim
index 6f88c5a22..914e7c6e7 100644
--- a/tests/range/tsubrange.nim
+++ b/tests/range/tsubrange.nim
@@ -7,7 +7,7 @@ type
   TRange = range[0..40]
 
 proc p(r: TRange) =
-  nil
+  discard
 
 var
   r: TRange
diff --git a/tests/rodfiles/deadg.nim b/tests/rodfiles/deadg.nim
index 587608e14..0aee59bb8 100644
--- a/tests/rodfiles/deadg.nim
+++ b/tests/rodfiles/deadg.nim
@@ -1,6 +1,3 @@
-
-{.deadCodeElim: on.}
-
 proc p1*(x, y: int): int =
   result = x + y
 
diff --git a/tests/stdlib/tpegs.nim b/tests/stdlib/tpegs.nim
deleted file mode 100644
index e2a5a1715..000000000
--- a/tests/stdlib/tpegs.nim
+++ /dev/null
@@ -1,1770 +0,0 @@
-discard """
-  output: '''this
-is
-an
-example
-d
-e
-f
-('keyvalue' 'key'*)'''
-"""
-# PEGs module turned out to be a good test to detect memory management bugs.
-
-include "system/inclrtl"
-
-const
-  useUnicode = true ## change this to deactivate proper UTF-8 support
-
-import
-  strutils
-
-when useUnicode:
-  import unicode
-
-const
-  InlineThreshold = 5  ## number of leaves; -1 to disable inlining
-  MaxSubpatterns* = 10 ## defines the maximum number of subpatterns that
-                       ## can be captured. More subpatterns cannot be captured!
-
-type
-  TPegKind = enum
-    pkEmpty,
-    pkAny,              ## any character (.)
-    pkAnyRune,          ## any Unicode character (_)
-    pkNewLine,          ## CR-LF, LF, CR
-    pkLetter,           ## Unicode letter
-    pkLower,            ## Unicode lower case letter
-    pkUpper,            ## Unicode upper case letter
-    pkTitle,            ## Unicode title character
-    pkWhitespace,       ## Unicode whitespace character
-    pkTerminal,
-    pkTerminalIgnoreCase,
-    pkTerminalIgnoreStyle,
-    pkChar,             ## single character to match
-    pkCharChoice,
-    pkNonTerminal,
-    pkSequence,         ## a b c ... --> Internal DSL: peg(a, b, c)
-    pkOrderedChoice,    ## a / b / ... --> Internal DSL: a / b or /[a, b, c]
-    pkGreedyRep,        ## a*     --> Internal DSL: *a
-                        ## a+     --> (a a*)
-    pkGreedyRepChar,    ## x* where x is a single character (superop)
-    pkGreedyRepSet,     ## [set]* (superop)
-    pkGreedyAny,        ## .* or _* (superop)
-    pkOption,           ## a?     --> Internal DSL: ?a
-    pkAndPredicate,     ## &a     --> Internal DSL: &a
-    pkNotPredicate,     ## !a     --> Internal DSL: !a
-    pkCapture,          ## {a}    --> Internal DSL: capture(a)
-    pkBackRef,          ## $i     --> Internal DSL: backref(i)
-    pkBackRefIgnoreCase,
-    pkBackRefIgnoreStyle,
-    pkSearch,           ## @a     --> Internal DSL: !*a
-    pkCapturedSearch,   ## {@} a  --> Internal DSL: !*\a
-    pkRule,             ## a <- b
-    pkList,             ## a, b
-    pkStartAnchor       ## ^      --> Internal DSL: startAnchor()
-  TNonTerminalFlag = enum
-    ntDeclared, ntUsed
-  TNonTerminal {.final.} = object ## represents a non terminal symbol
-    name: string                  ## the name of the symbol
-    line: int                     ## line the symbol has been declared/used in
-    col: int                      ## column the symbol has been declared/used in
-    flags: set[TNonTerminalFlag]  ## the nonterminal's flags
-    rule: TNode                   ## the rule that the symbol refers to
-  TNode {.final, shallow.} = object
-    case kind: TPegKind
-    of pkEmpty..pkWhitespace: nil
-    of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle: term: string
-    of pkChar, pkGreedyRepChar: ch: char
-    of pkCharChoice, pkGreedyRepSet: charChoice: ref set[char]
-    of pkNonTerminal: nt: PNonTerminal
-    of pkBackRef..pkBackRefIgnoreStyle: index: range[0..MaxSubpatterns]
-    else: sons: seq[TNode]
-  PNonTerminal* = ref TNonTerminal
-
-  TPeg* = TNode ## type that represents a PEG
-
-proc term*(t: string): TPeg {.rtl, extern: "npegs$1Str".} =
-  ## constructs a PEG from a terminal string
-  if t.len != 1:
-    result.kind = pkTerminal
-    result.term = t
-  else:
-    result.kind = pkChar
-    result.ch = t[0]
-
-proc termIgnoreCase*(t: string): TPeg {.
-  rtl, extern: "npegs$1".} =
-  ## constructs a PEG from a terminal string; ignore case for matching
-  result.kind = pkTerminalIgnoreCase
-  result.term = t
-
-proc termIgnoreStyle*(t: string): TPeg {.
-  rtl, extern: "npegs$1".} =
-  ## constructs a PEG from a terminal string; ignore style for matching
-  result.kind = pkTerminalIgnoreStyle
-  result.term = t
-
-proc term*(t: char): TPeg {.rtl, extern: "npegs$1Char".} =
-  ## constructs a PEG from a terminal char
-  assert t != '\0'
-  result.kind = pkChar
-  result.ch = t
-
-proc charSet*(s: set[char]): TPeg {.rtl, extern: "npegs$1".} =
-  ## constructs a PEG from a character set `s`
-  assert '\0' notin s
-  result.kind = pkCharChoice
-  new(result.charChoice)
-  result.charChoice[] = s
-
-proc len(a: TPeg): int {.inline.} = return a.sons.len
-proc add(d: var TPeg, s: TPeg) {.inline.} = add(d.sons, s)
-
-proc copyPeg(a: TPeg): TPeg =
-  result.kind = a.kind
-  case a.kind
-  of pkEmpty..pkWhitespace: discard
-  of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle:
-    result.term = a.term
-  of pkChar, pkGreedyRepChar:
-    result.ch = a.ch
-  of pkCharChoice, pkGreedyRepSet:
-    new(result.charChoice)
-    result.charChoice[] = a.charChoice[]
-  of pkNonTerminal: result.nt = a.nt
-  of pkBackRef..pkBackRefIgnoreStyle:
-    result.index = a.index
-  else:
-    result.sons = a.sons
-
-proc addChoice(dest: var TPeg, elem: TPeg) =
-  var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkCharChoice:
-    # caution! Do not introduce false aliasing here!
-    case elem.kind
-    of pkCharChoice:
-      dest.sons[L] = charSet(dest.sons[L].charChoice[] + elem.charChoice[])
-    of pkChar:
-      dest.sons[L] = charSet(dest.sons[L].charChoice[] + {elem.ch})
-    else: add(dest, elem)
-  else: add(dest, elem)
-
-template multipleOp(k: TPegKind, localOpt) =
-  result.kind = k
-  result.sons = @[]
-  for x in items(a):
-    if x.kind == k:
-      for y in items(x.sons):
-        localOpt(result, y)
-    else:
-      localOpt(result, x)
-  if result.len == 1:
-    result = result.sons[0]
-
-proc `/`*(a: varargs[TPeg]): TPeg {.
-  rtl, extern: "npegsOrderedChoice".} =
-  ## constructs an ordered choice with the PEGs in `a`
-  multipleOp(pkOrderedChoice, addChoice)
-
-proc addSequence(dest: var TPeg, elem: TPeg) =
-  var L = dest.len-1
-  if L >= 0 and dest.sons[L].kind == pkTerminal:
-    # caution! Do not introduce false aliasing here!
-    case elem.kind
-    of pkTerminal:
-      dest.sons[L] = term(dest.sons[L].term & elem.term)
-    of pkChar:
-      dest.sons[L] = term(dest.sons[L].term & elem.ch)
-    else: add(dest, elem)
-  else: add(dest, elem)
-
-proc sequence*(a: varargs[TPeg]): TPeg {.
-  rtl, extern: "npegs$1".} =
-  ## constructs a sequence with all the PEGs from `a`
-  multipleOp(pkSequence, addSequence)
-
-proc `?`*(a: TPeg): TPeg {.rtl, extern: "npegsOptional".} =
-  ## constructs an optional for the PEG `a`
-  if a.kind in {pkOption, pkGreedyRep, pkGreedyAny, pkGreedyRepChar,
-                pkGreedyRepSet}:
-    # a* ?  --> a*
-    # a? ?  --> a?
-    result = a
-  else:
-    result.kind = pkOption
-    result.sons = @[a]
-
-proc `*`*(a: TPeg): TPeg {.rtl, extern: "npegsGreedyRep".} =
-  ## constructs a "greedy repetition" for the PEG `a`
-  case a.kind
-  of pkGreedyRep, pkGreedyRepChar, pkGreedyRepSet, pkGreedyAny, pkOption:
-    assert false
-    # produces endless loop!
-  of pkChar:
-    result.kind = pkGreedyRepChar
-    result.ch = a.ch
-  of pkCharChoice:
-    result.kind = pkGreedyRepSet
-    result.charChoice = a.charChoice # copying a reference suffices!
-  of pkAny, pkAnyRune:
-    result.kind = pkGreedyAny
-  else:
-    result.kind = pkGreedyRep
-    result.sons = @[a]
-
-proc `!*`*(a: TPeg): TPeg {.rtl, extern: "npegsSearch".} =
-  ## constructs a "search" for the PEG `a`
-  result.kind = pkSearch
-  result.sons = @[a]
-
-proc `!*\`*(a: TPeg): TPeg {.rtl,
-                             extern: "npgegsCapturedSearch".} =
-  ## constructs a "captured search" for the PEG `a`
-  result.kind = pkCapturedSearch
-  result.sons = @[a]
-
-when false:
-  proc contains(a: TPeg, k: TPegKind): bool =
-    if a.kind == k: return true
-    case a.kind
-    of pkEmpty, pkAny, pkAnyRune, pkGreedyAny, pkNewLine, pkTerminal,
-       pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, pkGreedyRepChar,
-       pkCharChoice, pkGreedyRepSet: discard
-    of pkNonTerminal: return true
-    else:
-      for i in 0..a.sons.len-1:
-        if contains(a.sons[i], k): return true
-
-proc `+`*(a: TPeg): TPeg {.rtl, extern: "npegsGreedyPosRep".} =
-  ## constructs a "greedy positive repetition" with the PEG `a`
-  return sequence(a, *a)
-
-proc `&`*(a: TPeg): TPeg {.rtl, extern: "npegsAndPredicate".} =
-  ## constructs an "and predicate" with the PEG `a`
-  result.kind = pkAndPredicate
-  result.sons = @[a]
-
-proc `!`*(a: TPeg): TPeg {.rtl, extern: "npegsNotPredicate".} =
-  ## constructs a "not predicate" with the PEG `a`
-  result.kind = pkNotPredicate
-  result.sons = @[a]
-
-proc any*: TPeg {.inline.} =
-  ## constructs the PEG `any character`:idx: (``.``)
-  result.kind = pkAny
-
-proc anyRune*: TPeg {.inline.} =
-  ## constructs the PEG `any rune`:idx: (``_``)
-  result.kind = pkAnyRune
-
-proc newLine*: TPeg {.inline.} =
-  ## constructs the PEG `newline`:idx: (``\n``)
-  result.kind = pkNewline
-
-proc UnicodeLetter*: TPeg {.inline.} =
-  ## constructs the PEG ``\letter`` which matches any Unicode letter.
-  result.kind = pkLetter
-
-proc UnicodeLower*: TPeg {.inline.} =
-  ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter.
-  result.kind = pkLower
-
-proc UnicodeUpper*: TPeg {.inline.} =
-  ## constructs the PEG ``\upper`` which matches any Unicode lowercase letter.
-  result.kind = pkUpper
-
-proc UnicodeTitle*: TPeg {.inline.} =
-  ## constructs the PEG ``\title`` which matches any Unicode title letter.
-  result.kind = pkTitle
-
-proc UnicodeWhitespace*: TPeg {.inline.} =
-  ## constructs the PEG ``\white`` which matches any Unicode
-  ## whitespace character.
-  result.kind = pkWhitespace
-
-proc startAnchor*: TPeg {.inline.} =
-  ## constructs the PEG ``^`` which matches the start of the input.
-  result.kind = pkStartAnchor
-
-proc endAnchor*: TPeg {.inline.} =
-  ## constructs the PEG ``$`` which matches the end of the input.
-  result = !any()
-
-proc capture*(a: TPeg): TPeg {.rtl, extern: "npegsCapture".} =
-  ## constructs a capture with the PEG `a`
-  result.kind = pkCapture
-  result.sons = @[a]
-
-proc backref*(index: range[1..MaxSubPatterns]): TPeg {.
-  rtl, extern: "npegs$1".} =
-  ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1.
-  result.kind = pkBackRef
-  result.index = index-1
-
-proc backrefIgnoreCase*(index: range[1..MaxSubPatterns]): TPeg {.
-  rtl, extern: "npegs$1".} =
-  ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1. Ignores case for matching.
-  result.kind = pkBackRefIgnoreCase
-  result.index = index-1
-
-proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {.
-  rtl, extern: "npegs$1".}=
-  ## constructs a back reference of the given `index`. `index` starts counting
-  ## from 1. Ignores style for matching.
-  result.kind = pkBackRefIgnoreStyle
-  result.index = index-1
-
-proc spaceCost(n: TPeg): int =
-  case n.kind
-  of pkEmpty: discard
-  of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar,
-     pkGreedyRepChar, pkCharChoice, pkGreedyRepSet,
-     pkAny..pkWhitespace, pkGreedyAny:
-    result = 1
-  of pkNonTerminal:
-    # we cannot inline a rule with a non-terminal
-    result = InlineThreshold+1
-  else:
-    for i in 0..n.len-1:
-      inc(result, spaceCost(n.sons[i]))
-      if result >= InlineThreshold: break
-
-proc nonterminal*(n: PNonTerminal): TPeg {.
-  rtl, extern: "npegs$1".} =
-  ## constructs a PEG that consists of the nonterminal symbol
-  assert n != nil
-  if ntDeclared in n.flags and spaceCost(n.rule) < InlineThreshold:
-    when false: echo "inlining symbol: ", n.name
-    result = n.rule # inlining of rule enables better optimizations
-  else:
-    result.kind = pkNonTerminal
-    result.nt = n
-
-proc newNonTerminal*(name: string, line, column: int): PNonTerminal {.
-  rtl, extern: "npegs$1".} =
-  ## constructs a nonterminal symbol
-  new(result)
-  result.name = name
-  result.line = line
-  result.col = column
-
-template letters*: TPeg =
-  ## expands to ``charset({'A'..'Z', 'a'..'z'})``
-  charset({'A'..'Z', 'a'..'z'})
-
-template digits*: TPeg =
-  ## expands to ``charset({'0'..'9'})``
-  charset({'0'..'9'})
-
-template whitespace*: TPeg =
-  ## expands to ``charset({' ', '\9'..'\13'})``
-  charset({' ', '\9'..'\13'})
-
-template identChars*: TPeg =
-  ## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})``
-  charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})
-
-template identStartChars*: TPeg =
-  ## expands to ``charset({'A'..'Z', 'a'..'z', '_'})``
-  charset({'a'..'z', 'A'..'Z', '_'})
-
-template ident*: TPeg =
-  ## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier
-  sequence(charset({'a'..'z', 'A'..'Z', '_'}),
-           *charset({'a'..'z', 'A'..'Z', '0'..'9', '_'}))
-
-template natural*: TPeg =
-  ## same as ``\d+``
-  +digits
-
-# ------------------------- debugging -----------------------------------------
-
-proc esc(c: char, reserved = {'\0'..'\255'}): string =
-  case c
-  of '\b': result = "\\b"
-  of '\t': result = "\\t"
-  of '\c': result = "\\c"
-  of '\L': result = "\\l"
-  of '\v': result = "\\v"
-  of '\f': result = "\\f"
-  of '\e': result = "\\e"
-  of '\a': result = "\\a"
-  of '\\': result = "\\\\"
-  of 'a'..'z', 'A'..'Z', '0'..'9', '_': result = $c
-  elif c < ' ' or c >= '\128': result = '\\' & $ord(c)
-  elif c in reserved: result = '\\' & c
-  else: result = $c
-
-proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'"
-
-proc singleQuoteEsc(str: string): string =
-  result = "'"
-  for c in items(str): add result, esc(c, {'\''})
-  add result, '\''
-
-proc charSetEscAux(cc: set[char]): string =
-  const reserved = {'^', '-', ']'}
-  result = ""
-  var c1 = 0
-  while c1 <= 0xff:
-    if chr(c1) in cc:
-      var c2 = c1
-      while c2 < 0xff and chr(succ(c2)) in cc: inc(c2)
-      if c1 == c2:
-        add result, esc(chr(c1), reserved)
-      elif c2 == succ(c1):
-        add result, esc(chr(c1), reserved) & esc(chr(c2), reserved)
-      else:
-        add result, esc(chr(c1), reserved) & '-' & esc(chr(c2), reserved)
-      c1 = c2
-    inc(c1)
-
-proc charSetEsc(cc: set[char]): string =
-  if card(cc) >= 128+64:
-    result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']'
-  else:
-    result = '[' & charSetEscAux(cc) & ']'
-
-proc toStrAux(r: TPeg, res: var string) =
-  case r.kind
-  of pkEmpty: add(res, "()")
-  of pkAny: add(res, '.')
-  of pkAnyRune: add(res, '_')
-  of pkLetter: add(res, "\\letter")
-  of pkLower: add(res, "\\lower")
-  of pkUpper: add(res, "\\upper")
-  of pkTitle: add(res, "\\title")
-  of pkWhitespace: add(res, "\\white")
-
-  of pkNewline: add(res, "\\n")
-  of pkTerminal: add(res, singleQuoteEsc(r.term))
-  of pkTerminalIgnoreCase:
-    add(res, 'i')
-    add(res, singleQuoteEsc(r.term))
-  of pkTerminalIgnoreStyle:
-    add(res, 'y')
-    add(res, singleQuoteEsc(r.term))
-  of pkChar: add(res, singleQuoteEsc(r.ch))
-  of pkCharChoice: add(res, charSetEsc(r.charChoice[]))
-  of pkNonTerminal: add(res, r.nt.name)
-  of pkSequence:
-    add(res, '(')
-    toStrAux(r.sons[0], res)
-    for i in 1 .. high(r.sons):
-      add(res, ' ')
-      toStrAux(r.sons[i], res)
-    add(res, ')')
-  of pkOrderedChoice:
-    add(res, '(')
-    toStrAux(r.sons[0], res)
-    for i in 1 .. high(r.sons):
-      add(res, " / ")
-      toStrAux(r.sons[i], res)
-    add(res, ')')
-  of pkGreedyRep:
-    toStrAux(r.sons[0], res)
-    add(res, '*')
-  of pkGreedyRepChar:
-    add(res, singleQuoteEsc(r.ch))
-    add(res, '*')
-  of pkGreedyRepSet:
-    add(res, charSetEsc(r.charChoice[]))
-    add(res, '*')
-  of pkGreedyAny:
-    add(res, ".*")
-  of pkOption:
-    toStrAux(r.sons[0], res)
-    add(res, '?')
-  of pkAndPredicate:
-    add(res, '&')
-    toStrAux(r.sons[0], res)
-  of pkNotPredicate:
-    add(res, '!')
-    toStrAux(r.sons[0], res)
-  of pkSearch:
-    add(res, '@')
-    toStrAux(r.sons[0], res)
-  of pkCapturedSearch:
-    add(res, "{@}")
-    toStrAux(r.sons[0], res)
-  of pkCapture:
-    add(res, '{')
-    toStrAux(r.sons[0], res)
-    add(res, '}')
-  of pkBackRef:
-    add(res, '$')
-    add(res, $r.index)
-  of pkBackRefIgnoreCase:
-    add(res, "i$")
-    add(res, $r.index)
-  of pkBackRefIgnoreStyle:
-    add(res, "y$")
-    add(res, $r.index)
-  of pkRule:
-    toStrAux(r.sons[0], res)
-    add(res, " <- ")
-    toStrAux(r.sons[1], res)
-  of pkList:
-    for i in 0 .. high(r.sons):
-      toStrAux(r.sons[i], res)
-      add(res, "\n")
-  of pkStartAnchor:
-    add(res, '^')
-
-proc `$` *(r: TPeg): string {.rtl, extern: "npegsToString".} =
-  ## converts a PEG to its string representation
-  result = ""
-  toStrAux(r, result)
-
-# --------------------- core engine -------------------------------------------
-
-type
-  TCaptures* {.final.} = object ## contains the captured substrings.
-    matches: array[0..MaxSubpatterns-1, tuple[first, last: int]]
-    ml: int
-    origStart: int
-
-proc bounds*(c: TCaptures,
-             i: range[0..MaxSubpatterns-1]): tuple[first, last: int] =
-  ## returns the bounds ``[first..last]`` of the `i`'th capture.
-  result = c.matches[i]
-
-when not useUnicode:
-  type
-    Rune = char
-  template fastRuneAt(s, i, ch) =
-    ch = s[i]
-    inc(i)
-  template runeLenAt(s, i): untyped = 1
-
-  proc isAlpha(a: char): bool {.inline.} = return a in {'a'..'z','A'..'Z'}
-  proc isUpper(a: char): bool {.inline.} = return a in {'A'..'Z'}
-  proc isLower(a: char): bool {.inline.} = return a in {'a'..'z'}
-  proc isTitle(a: char): bool {.inline.} = return false
-  proc isWhiteSpace(a: char): bool {.inline.} = return a in {' ', '\9'..'\13'}
-
-proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {.
-               rtl, extern: "npegs$1".} =
-  ## low-level matching proc that implements the PEG interpreter. Use this
-  ## for maximum efficiency (every other PEG operation ends up calling this
-  ## proc).
-  ## Returns -1 if it does not match, else the length of the match
-  case p.kind
-  of pkEmpty: result = 0 # match of length 0
-  of pkAny:
-    if s[start] != '\0': result = 1
-    else: result = -1
-  of pkAnyRune:
-    if s[start] != '\0':
-      result = runeLenAt(s, start)
-    else:
-      result = -1
-  of pkLetter:
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isAlpha(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkLower:
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isLower(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkUpper:
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isUpper(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkTitle:
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isTitle(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkWhitespace:
-    if s[start] != '\0':
-      var a: Rune
-      result = start
-      fastRuneAt(s, result, a)
-      if isWhitespace(a): dec(result, start)
-      else: result = -1
-    else:
-      result = -1
-  of pkGreedyAny:
-    result = len(s) - start
-  of pkNewLine:
-    if s[start] == '\L': result = 1
-    elif s[start] == '\C':
-      if s[start+1] == '\L': result = 2
-      else: result = 1
-    else: result = -1
-  of pkTerminal:
-    result = len(p.term)
-    for i in 0..result-1:
-      if p.term[i] != s[start+i]:
-        result = -1
-        break
-  of pkTerminalIgnoreCase:
-    var
-      i = 0
-      a, b: Rune
-    result = start
-    while i < len(p.term):
-      fastRuneAt(p.term, i, a)
-      fastRuneAt(s, result, b)
-      if toLower(a) != toLower(b):
-        result = -1
-        break
-    dec(result, start)
-  of pkTerminalIgnoreStyle:
-    var
-      i = 0
-      a, b: Rune
-    result = start
-    while i < len(p.term):
-      while true:
-        fastRuneAt(p.term, i, a)
-        if a != Rune('_'): break
-      while true:
-        fastRuneAt(s, result, b)
-        if b != Rune('_'): break
-      if toLower(a) != toLower(b):
-        result = -1
-        break
-    dec(result, start)
-  of pkChar:
-    if p.ch == s[start]: result = 1
-    else: result = -1
-  of pkCharChoice:
-    if contains(p.charChoice[], s[start]): result = 1
-    else: result = -1
-  of pkNonTerminal:
-    var oldMl = c.ml
-    when false: echo "enter: ", p.nt.name
-    result = rawMatch(s, p.nt.rule, start, c)
-    when false: echo "leave: ", p.nt.name
-    if result < 0: c.ml = oldMl
-  of pkSequence:
-    var oldMl = c.ml
-    result = 0
-    assert(not isNil(p.sons))
-    for i in 0..high(p.sons):
-      var x = rawMatch(s, p.sons[i], start+result, c)
-      if x < 0:
-        c.ml = oldMl
-        result = -1
-        break
-      else: inc(result, x)
-  of pkOrderedChoice:
-    var oldMl = c.ml
-    for i in 0..high(p.sons):
-      result = rawMatch(s, p.sons[i], start, c)
-      if result >= 0: break
-      c.ml = oldMl
-  of pkSearch:
-    var oldMl = c.ml
-    result = 0
-    while start+result < s.len:
-      var x = rawMatch(s, p.sons[0], start+result, c)
-      if x >= 0:
-        inc(result, x)
-        return
-      inc(result)
-    result = -1
-    c.ml = oldMl
-  of pkCapturedSearch:
-    var idx = c.ml # reserve a slot for the subpattern
-    inc(c.ml)
-    result = 0
-    while start+result < s.len:
-      var x = rawMatch(s, p.sons[0], start+result, c)
-      if x >= 0:
-        if idx < MaxSubpatterns:
-          c.matches[idx] = (start, start+result-1)
-        #else: silently ignore the capture
-        inc(result, x)
-        return
-      inc(result)
-    result = -1
-    c.ml = idx
-  of pkGreedyRep:
-    result = 0
-    while true:
-      var x = rawMatch(s, p.sons[0], start+result, c)
-      # if x == 0, we have an endless loop; so the correct behaviour would be
-      # not to break. But endless loops can be easily introduced:
-      # ``(comment / \w*)*`` is such an example. Breaking for x == 0 does the
-      # expected thing in this case.
-      if x <= 0: break
-      inc(result, x)
-  of pkGreedyRepChar:
-    result = 0
-    var ch = p.ch
-    while ch == s[start+result]: inc(result)
-  of pkGreedyRepSet:
-    result = 0
-    while contains(p.charChoice[], s[start+result]): inc(result)
-  of pkOption:
-    result = max(0, rawMatch(s, p.sons[0], start, c))
-  of pkAndPredicate:
-    var oldMl = c.ml
-    result = rawMatch(s, p.sons[0], start, c)
-    if result >= 0: result = 0 # do not consume anything
-    else: c.ml = oldMl
-  of pkNotPredicate:
-    var oldMl = c.ml
-    result = rawMatch(s, p.sons[0], start, c)
-    if result < 0: result = 0
-    else:
-      c.ml = oldMl
-      result = -1
-  of pkCapture:
-    var idx = c.ml # reserve a slot for the subpattern
-    inc(c.ml)
-    result = rawMatch(s, p.sons[0], start, c)
-    if result >= 0:
-      if idx < MaxSubpatterns:
-        c.matches[idx] = (start, start+result-1)
-      #else: silently ignore the capture
-    else:
-      c.ml = idx
-  of pkBackRef..pkBackRefIgnoreStyle:
-    if p.index >= c.ml: return -1
-    var (a, b) = c.matches[p.index]
-    var n: TPeg
-    n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef))
-    n.term = s.substr(a, b)
-    result = rawMatch(s, n, start, c)
-  of pkStartAnchor:
-    if c.origStart == start: result = 0
-    else: result = -1
-  of pkRule, pkList: assert false
-
-proc match*(s: string, pattern: TPeg, matches: var openarray[string],
-            start = 0): bool {.rtl, extern: "npegs$1Capture".} =
-  ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and
-  ## the captured substrings in the array ``matches``. If it does not
-  ## match, nothing is written into ``matches`` and ``false`` is
-  ## returned.
-  var c: TCaptures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c) == len(s)-start
-  if result:
-    for i in 0..c.ml-1:
-      matches[i] = substr(s, c.matches[i][0], c.matches[i][1])
-
-proc match*(s: string, pattern: TPeg,
-            start = 0): bool {.rtl, extern: "npegs$1".} =
-  ## returns ``true`` if ``s`` matches the ``pattern`` beginning from ``start``.
-  var c: TCaptures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c) == len(s)-start
-
-proc matchLen*(s: string, pattern: TPeg, matches: var openarray[string],
-               start = 0): int {.rtl, extern: "npegs$1Capture".} =
-  ## the same as ``match``, but it returns the length of the match,
-  ## if there is no match, -1 is returned. Note that a match length
-  ## of zero can happen. It's possible that a suffix of `s` remains
-  ## that does not belong to the match.
-  var c: TCaptures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c)
-  if result >= 0:
-    for i in 0..c.ml-1:
-      matches[i] = substr(s, c.matches[i][0], c.matches[i][1])
-
-proc matchLen*(s: string, pattern: TPeg,
-               start = 0): int {.rtl, extern: "npegs$1".} =
-  ## the same as ``match``, but it returns the length of the match,
-  ## if there is no match, -1 is returned. Note that a match length
-  ## of zero can happen. It's possible that a suffix of `s` remains
-  ## that does not belong to the match.
-  var c: TCaptures
-  c.origStart = start
-  result = rawMatch(s, pattern, start, c)
-
-proc find*(s: string, pattern: TPeg, matches: var openarray[string],
-           start = 0): int {.rtl, extern: "npegs$1Capture".} =
-  ## returns the starting position of ``pattern`` in ``s`` and the captured
-  ## substrings in the array ``matches``. If it does not match, nothing
-  ## is written into ``matches`` and -1 is returned.
-  for i in start .. s.len-1:
-    if matchLen(s, pattern, matches, i) >= 0: return i
-  return -1
-  # could also use the pattern here: (!P .)* P
-
-proc findBounds*(s: string, pattern: TPeg, matches: var openarray[string],
-                 start = 0): tuple[first, last: int] {.
-                 rtl, extern: "npegs$1Capture".} =
-  ## returns the starting position and end position of ``pattern`` in ``s``
-  ## and the captured
-  ## substrings in the array ``matches``. If it does not match, nothing
-  ## is written into ``matches`` and (-1,0) is returned.
-  for i in start .. s.len-1:
-    var L = matchLen(s, pattern, matches, i)
-    if L >= 0: return (i, i+L-1)
-  return (-1, 0)
-
-proc find*(s: string, pattern: TPeg,
-           start = 0): int {.rtl, extern: "npegs$1".} =
-  ## returns the starting position of ``pattern`` in ``s``. If it does not
-  ## match, -1 is returned.
-  for i in start .. s.len-1:
-    if matchLen(s, pattern, i) >= 0: return i
-  return -1
-
-iterator findAll*(s: string, pattern: TPeg, start = 0): string =
-  ## yields all matching captures of pattern in `s`.
-  var matches: array[0..MaxSubpatterns-1, string]
-  var i = start
-  while i < s.len:
-    var L = matchLen(s, pattern, matches, i)
-    if L < 0: break
-    for k in 0..MaxSubPatterns-1:
-      if isNil(matches[k]): break
-      yield matches[k]
-    inc(i, L)
-
-proc findAll*(s: string, pattern: TPeg, start = 0): seq[string] {.
-  rtl, extern: "npegs$1".} =
-  ## returns all matching captures of pattern in `s`.
-  ## If it does not match, @[] is returned.
-  accumulateResult(findAll(s, pattern, start))
-
-template `=~`*(s: string, pattern: TPeg): untyped =
-  ## This calls ``match`` with an implicit declared ``matches`` array that
-  ## can be used in the scope of the ``=~`` call:
-  ##
-  ## .. code-block:: nim
-  ##
-  ##   if line =~ peg"\s* {\w+} \s* '=' \s* {\w+}":
-  ##     # matches a key=value pair:
-  ##     echo("Key: ", matches[0])
-  ##     echo("Value: ", matches[1])
-  ##   elif line =~ peg"\s*{'#'.*}":
-  ##     # matches a comment
-  ##     # note that the implicit ``matches`` array is different from the
-  ##     # ``matches`` array of the first branch
-  ##     echo("comment: ", matches[0])
-  ##   else:
-  ##     echo("syntax error")
-  ##
-  when not declaredInScope(matches):
-    var matches {.inject.}: array[0..MaxSubpatterns-1, string]
-  match(s, pattern, matches)
-
-# ------------------------- more string handling ------------------------------
-
-proc contains*(s: string, pattern: TPeg, start = 0): bool {.
-  rtl, extern: "npegs$1".} =
-  ## same as ``find(s, pattern, start) >= 0``
-  return find(s, pattern, start) >= 0
-
-proc contains*(s: string, pattern: TPeg, matches: var openArray[string],
-              start = 0): bool {.rtl, extern: "npegs$1Capture".} =
-  ## same as ``find(s, pattern, matches, start) >= 0``
-  return find(s, pattern, matches, start) >= 0
-
-proc startsWith*(s: string, prefix: TPeg, start = 0): bool {.
-  rtl, extern: "npegs$1".} =
-  ## returns true if `s` starts with the pattern `prefix`
-  result = matchLen(s, prefix, start) >= 0
-
-proc endsWith*(s: string, suffix: TPeg, start = 0): bool {.
-  rtl, extern: "npegs$1".} =
-  ## returns true if `s` ends with the pattern `prefix`
-  for i in start .. s.len-1:
-    if matchLen(s, suffix, i) == s.len - i: return true
-
-proc replacef*(s: string, sub: TPeg, by: string): string {.
-  rtl, extern: "npegs$1".} =
-  ## 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
-  ##   "var1=key; var2=key2".replace(peg"{\ident}'='{\ident}", "$1<-$2$2")
-  ##
-  ## Results in:
-  ##
-  ## .. code-block:: nim
-  ##
-  ##   "var1<-keykey; val2<-key2key2"
-  result = ""
-  var i = 0
-  var caps: array[0..MaxSubpatterns-1, string]
-  while i < s.len:
-    var x = matchLen(s, sub, caps, i)
-    if x <= 0:
-      add(result, s[i])
-      inc(i)
-    else:
-      addf(result, by, caps)
-      inc(i, x)
-  add(result, substr(s, i))
-
-proc replace*(s: string, sub: TPeg, by = ""): string {.
-  rtl, extern: "npegs$1".} =
-  ## Replaces `sub` in `s` by the string `by`. Captures cannot be accessed
-  ## in `by`.
-  result = ""
-  var i = 0
-  var caps: array[0..MaxSubpatterns-1, string]
-  while i < s.len:
-    var x = matchLen(s, sub, caps, i)
-    if x <= 0:
-      add(result, s[i])
-      inc(i)
-    else:
-      addf(result, by, caps)
-      inc(i, x)
-  add(result, substr(s, i))
-
-proc parallelReplace*(s: string, subs: varargs[
-                      tuple[pattern: TPeg, repl: string]]): string {.
-                      rtl, extern: "npegs$1".} =
-  ## Returns a modified copy of `s` with the substitutions in `subs`
-  ## applied in parallel.
-  result = ""
-  var i = 0
-  var caps: array[0..MaxSubpatterns-1, string]
-  while i < s.len:
-    block searchSubs:
-      for j in 0..high(subs):
-        var x = matchLen(s, subs[j][0], caps, i)
-        if x > 0:
-          addf(result, subs[j][1], caps)
-          inc(i, x)
-          break searchSubs
-      add(result, s[i])
-      inc(i)
-  # copy the rest:
-  add(result, substr(s, i))
-
-proc transformFile*(infile, outfile: string,
-                    subs: varargs[tuple[pattern: TPeg, repl: string]]) {.
-                    rtl, extern: "npegs$1".} =
-  ## reads in the file `infile`, performs a parallel replacement (calls
-  ## `parallelReplace`) and writes back to `outfile`. Calls ``quit`` if an
-  ## error occurs. This is supposed to be used for quick scripting.
-  var x = readFile(infile)
-  if not isNil(x):
-    var f: File
-    if open(f, outfile, fmWrite):
-      write(f, x.parallelReplace(subs))
-      close(f)
-    else:
-      quit("cannot open for writing: " & outfile)
-  else:
-    quit("cannot open for reading: " & infile)
-
-iterator split*(s: string, sep: TPeg): string =
-  ## Splits the string `s` into substrings.
-  ##
-  ## Substrings are separated by the PEG `sep`.
-  ## Examples:
-  ##
-  ## .. code-block:: nim
-  ##   for word in split("00232this02939is39an22example111", peg"\d+"):
-  ##     writeLine(stdout, word)
-  ##
-  ## Results in:
-  ##
-  ## .. code-block:: nim
-  ##   "this"
-  ##   "is"
-  ##   "an"
-  ##   "example"
-  ##
-  var
-    first = 0
-    last = 0
-  while last < len(s):
-    var x = matchLen(s, sep, last)
-    if x > 0: inc(last, x)
-    first = last
-    while last < len(s):
-      inc(last)
-      x = matchLen(s, sep, last)
-      if x > 0: break
-    if first < last:
-      yield substr(s, first, last-1)
-
-proc split*(s: string, sep: TPeg): seq[string] {.
-  rtl, extern: "npegs$1".} =
-  ## Splits the string `s` into substrings.
-  accumulateResult(split(s, sep))
-
-# ------------------- scanner -------------------------------------------------
-
-type
-  TModifier = enum
-    modNone,
-    modVerbatim,
-    modIgnoreCase,
-    modIgnoreStyle
-  TTokKind = enum       ## enumeration of all tokens
-    tkInvalid,          ## invalid token
-    tkEof,              ## end of file reached
-    tkAny,              ## .
-    tkAnyRune,          ## _
-    tkIdentifier,       ## abc
-    tkStringLit,        ## "abc" or 'abc'
-    tkCharSet,          ## [^A-Z]
-    tkParLe,            ## '('
-    tkParRi,            ## ')'
-    tkCurlyLe,          ## '{'
-    tkCurlyRi,          ## '}'
-    tkCurlyAt,          ## '{@}'
-    tkArrow,            ## '<-'
-    tkBar,              ## '/'
-    tkStar,             ## '*'
-    tkPlus,             ## '+'
-    tkAmp,              ## '&'
-    tkNot,              ## '!'
-    tkOption,           ## '?'
-    tkAt,               ## '@'
-    tkBuiltin,          ## \identifier
-    tkEscaped,          ## \\
-    tkBackref,          ## '$'
-    tkDollar,           ## '$'
-    tkHat               ## '^'
-
-  TToken {.final.} = object  ## a token
-    kind: TTokKind           ## the type of the token
-    modifier: TModifier
-    literal: string          ## the parsed (string) literal
-    charset: set[char]       ## if kind == tkCharSet
-    index: int               ## if kind == tkBackref
-
-  TPegLexer {.inheritable.} = object          ## the lexer object.
-    bufpos: int               ## the current position within the buffer
-    buf: cstring              ## the buffer itself
-    lineNumber: int           ## the current line number
-    lineStart: int            ## index of last line start in buffer
-    colOffset: int            ## column to add
-    filename: string
-
-const
-  tokKindToStr: array[TTokKind, string] = [
-    "invalid", "[EOF]", ".", "_", "identifier", "string literal",
-    "character set", "(", ")", "{", "}", "{@}",
-    "<-", "/", "*", "+", "&", "!", "?",
-    "@", "built-in", "escaped", "$", "$", "^"
-  ]
-
-proc HandleCR(L: var TPegLexer, pos: int): int =
-  assert(L.buf[pos] == '\c')
-  inc(L.linenumber)
-  result = pos+1
-  if L.buf[result] == '\L': inc(result)
-  L.lineStart = result
-
-proc HandleLF(L: var TPegLexer, pos: int): int =
-  assert(L.buf[pos] == '\L')
-  inc(L.linenumber)
-  result = pos+1
-  L.lineStart = result
-
-proc init(L: var TPegLexer, input, filename: string, line = 1, col = 0) =
-  L.buf = input
-  L.bufpos = 0
-  L.lineNumber = line
-  L.colOffset = col
-  L.lineStart = 0
-  L.filename = filename
-
-proc getColumn(L: TPegLexer): int {.inline.} =
-  result = abs(L.bufpos - L.lineStart) + L.colOffset
-
-proc getLine(L: TPegLexer): int {.inline.} =
-  result = L.linenumber
-
-proc errorStr(L: TPegLexer, msg: string, line = -1, col = -1): string =
-  var line = if line < 0: getLine(L) else: line
-  var col = if col < 0: getColumn(L) else: col
-  result = "$1($2, $3) Error: $4" % [L.filename, $line, $col, msg]
-
-proc handleHexChar(c: var TPegLexer, xi: var int) =
-  case c.buf[c.bufpos]
-  of '0'..'9':
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0'))
-    inc(c.bufpos)
-  of 'a'..'f':
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10)
-    inc(c.bufpos)
-  of 'A'..'F':
-    xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10)
-    inc(c.bufpos)
-  else: discard
-
-proc getEscapedChar(c: var TPegLexer, tok: var TToken) =
-  inc(c.bufpos)
-  case c.buf[c.bufpos]
-  of 'r', 'R', 'c', 'C':
-    add(tok.literal, '\c')
-    inc(c.bufpos)
-  of 'l', 'L':
-    add(tok.literal, '\L')
-    inc(c.bufpos)
-  of 'f', 'F':
-    add(tok.literal, '\f')
-    inc(c.bufpos)
-  of 'e', 'E':
-    add(tok.literal, '\e')
-    inc(c.bufpos)
-  of 'a', 'A':
-    add(tok.literal, '\a')
-    inc(c.bufpos)
-  of 'b', 'B':
-    add(tok.literal, '\b')
-    inc(c.bufpos)
-  of 'v', 'V':
-    add(tok.literal, '\v')
-    inc(c.bufpos)
-  of 't', 'T':
-    add(tok.literal, '\t')
-    inc(c.bufpos)
-  of 'x', 'X':
-    inc(c.bufpos)
-    var xi = 0
-    handleHexChar(c, xi)
-    handleHexChar(c, xi)
-    if xi == 0: tok.kind = tkInvalid
-    else: add(tok.literal, chr(xi))
-  of '0'..'9':
-    var val = ord(c.buf[c.bufpos]) - ord('0')
-    inc(c.bufpos)
-    var i = 1
-    while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}):
-      val = val * 10 + ord(c.buf[c.bufpos]) - ord('0')
-      inc(c.bufpos)
-      inc(i)
-    if val > 0 and val <= 255: add(tok.literal, chr(val))
-    else: tok.kind = tkInvalid
-  of '\0'..'\31':
-    tok.kind = tkInvalid
-  elif c.buf[c.bufpos] in strutils.Letters:
-    tok.kind = tkInvalid
-  else:
-    add(tok.literal, c.buf[c.bufpos])
-    inc(c.bufpos)
-
-proc skip(c: var TPegLexer) =
-  var pos = c.bufpos
-  var buf = c.buf
-  while true:
-    case buf[pos]
-    of ' ', '\t':
-      inc(pos)
-    of '#':
-      while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos)
-    of '\c':
-      pos = HandleCR(c, pos)
-      buf = c.buf
-    of '\L':
-      pos = HandleLF(c, pos)
-      buf = c.buf
-    else:
-      break                   # EndOfFile also leaves the loop
-  c.bufpos = pos
-
-proc getString(c: var TPegLexer, tok: var TToken) =
-  tok.kind = tkStringLit
-  var pos = c.bufPos + 1
-  var buf = c.buf
-  var quote = buf[pos-1]
-  while true:
-    case buf[pos]
-    of '\\':
-      c.bufpos = pos
-      getEscapedChar(c, tok)
-      pos = c.bufpos
-    of '\c', '\L', '\0':
-      tok.kind = tkInvalid
-      break
-    elif buf[pos] == quote:
-      inc(pos)
-      break
-    else:
-      add(tok.literal, buf[pos])
-      inc(pos)
-  c.bufpos = pos
-
-proc getDollar(c: var TPegLexer, tok: var TToken) =
-  var pos = c.bufPos + 1
-  var buf = c.buf
-  if buf[pos] in {'0'..'9'}:
-    tok.kind = tkBackref
-    tok.index = 0
-    while buf[pos] in {'0'..'9'}:
-      tok.index = tok.index * 10 + ord(buf[pos]) - ord('0')
-      inc(pos)
-  else:
-    tok.kind = tkDollar
-  c.bufpos = pos
-
-proc getCharSet(c: var TPegLexer, tok: var TToken) =
-  tok.kind = tkCharSet
-  tok.charset = {}
-  var pos = c.bufPos + 1
-  var buf = c.buf
-  var caret = false
-  if buf[pos] == '^':
-    inc(pos)
-    caret = true
-  while true:
-    var ch: char
-    case buf[pos]
-    of ']':
-      inc(pos)
-      break
-    of '\\':
-      c.bufpos = pos
-      getEscapedChar(c, tok)
-      pos = c.bufpos
-      ch = tok.literal[tok.literal.len-1]
-    of '\C', '\L', '\0':
-      tok.kind = tkInvalid
-      break
-    else:
-      ch = buf[pos]
-      inc(pos)
-    incl(tok.charset, ch)
-    if buf[pos] == '-':
-      if buf[pos+1] == ']':
-        incl(tok.charset, '-')
-        inc(pos)
-      else:
-        inc(pos)
-        var ch2: char
-        case buf[pos]
-        of '\\':
-          c.bufpos = pos
-          getEscapedChar(c, tok)
-          pos = c.bufpos
-          ch2 = tok.literal[tok.literal.len-1]
-        of '\C', '\L', '\0':
-          tok.kind = tkInvalid
-          break
-        else:
-          ch2 = buf[pos]
-          inc(pos)
-        for i in ord(ch)+1 .. ord(ch2):
-          incl(tok.charset, chr(i))
-  c.bufpos = pos
-  if caret: tok.charset = {'\1'..'\xFF'} - tok.charset
-
-proc getSymbol(c: var TPegLexer, tok: var TToken) =
-  var pos = c.bufpos
-  var buf = c.buf
-  while true:
-    add(tok.literal, buf[pos])
-    inc(pos)
-    if buf[pos] notin strutils.IdentChars: break
-  c.bufpos = pos
-  tok.kind = tkIdentifier
-
-proc getBuiltin(c: var TPegLexer, tok: var TToken) =
-  if c.buf[c.bufpos+1] in strutils.Letters:
-    inc(c.bufpos)
-    getSymbol(c, tok)
-    tok.kind = tkBuiltin
-  else:
-    tok.kind = tkEscaped
-    getEscapedChar(c, tok) # may set tok.kind to tkInvalid
-
-proc getTok(c: var TPegLexer, tok: var TToken) =
-  tok.kind = tkInvalid
-  tok.modifier = modNone
-  setlen(tok.literal, 0)
-  skip(c)
-  case c.buf[c.bufpos]
-  of '{':
-    inc(c.bufpos)
-    if c.buf[c.bufpos] == '@' and c.buf[c.bufpos+1] == '}':
-      tok.kind = tkCurlyAt
-      inc(c.bufpos, 2)
-      add(tok.literal, "{@}")
-    else:
-      tok.kind = tkCurlyLe
-      add(tok.literal, '{')
-  of '}':
-    tok.kind = tkCurlyRi
-    inc(c.bufpos)
-    add(tok.literal, '}')
-  of '[':
-    getCharset(c, tok)
-  of '(':
-    tok.kind = tkParLe
-    inc(c.bufpos)
-    add(tok.literal, '(')
-  of ')':
-    tok.kind = tkParRi
-    inc(c.bufpos)
-    add(tok.literal, ')')
-  of '.':
-    tok.kind = tkAny
-    inc(c.bufpos)
-    add(tok.literal, '.')
-  of '_':
-    tok.kind = tkAnyRune
-    inc(c.bufpos)
-    add(tok.literal, '_')
-  of '\\':
-    getBuiltin(c, tok)
-  of '\'', '"': getString(c, tok)
-  of '$': getDollar(c, tok)
-  of '\0':
-    tok.kind = tkEof
-    tok.literal = "[EOF]"
-  of 'a'..'z', 'A'..'Z', '\128'..'\255':
-    getSymbol(c, tok)
-    if c.buf[c.bufpos] in {'\'', '"'} or
-        c.buf[c.bufpos] == '$' and c.buf[c.bufpos+1] in {'0'..'9'}:
-      case tok.literal
-      of "i": tok.modifier = modIgnoreCase
-      of "y": tok.modifier = modIgnoreStyle
-      of "v": tok.modifier = modVerbatim
-      else: discard
-      setLen(tok.literal, 0)
-      if c.buf[c.bufpos] == '$':
-        getDollar(c, tok)
-      else:
-        getString(c, tok)
-      if tok.modifier == modNone: tok.kind = tkInvalid
-  of '+':
-    tok.kind = tkPlus
-    inc(c.bufpos)
-    add(tok.literal, '+')
-  of '*':
-    tok.kind = tkStar
-    inc(c.bufpos)
-    add(tok.literal, '+')
-  of '<':
-    if c.buf[c.bufpos+1] == '-':
-      inc(c.bufpos, 2)
-      tok.kind = tkArrow
-      add(tok.literal, "<-")
-    else:
-      add(tok.literal, '<')
-  of '/':
-    tok.kind = tkBar
-    inc(c.bufpos)
-    add(tok.literal, '/')
-  of '?':
-    tok.kind = tkOption
-    inc(c.bufpos)
-    add(tok.literal, '?')
-  of '!':
-    tok.kind = tkNot
-    inc(c.bufpos)
-    add(tok.literal, '!')
-  of '&':
-    tok.kind = tkAmp
-    inc(c.bufpos)
-    add(tok.literal, '!')
-  of '@':
-    tok.kind = tkAt
-    inc(c.bufpos)
-    add(tok.literal, '@')
-    if c.buf[c.bufpos] == '@':
-      tok.kind = tkCurlyAt
-      inc(c.bufpos)
-      add(tok.literal, '@')
-  of '^':
-    tok.kind = tkHat
-    inc(c.bufpos)
-    add(tok.literal, '^')
-  else:
-    add(tok.literal, c.buf[c.bufpos])
-    inc(c.bufpos)
-
-proc arrowIsNextTok(c: TPegLexer): bool =
-  # the only look ahead we need
-  var pos = c.bufpos
-  while c.buf[pos] in {'\t', ' '}: inc(pos)
-  result = c.buf[pos] == '<' and c.buf[pos+1] == '-'
-
-# ----------------------------- parser ----------------------------------------
-
-type
-  EInvalidPeg* = object of ValueError ## raised if an invalid
-                                      ## PEG has been detected
-  TPegParser = object of TPegLexer ## the PEG parser object
-    tok: TToken
-    nonterms: seq[PNonTerminal]
-    modifier: TModifier
-    captures: int
-    identIsVerbatim: bool
-    skip: TPeg
-
-proc pegError(p: TPegParser, msg: string, line = -1, col = -1) =
-  var e: ref EInvalidPeg
-  new(e)
-  e.msg = errorStr(p, msg, line, col)
-  raise e
-
-proc getTok(p: var TPegParser) =
-  getTok(p, p.tok)
-  if p.tok.kind == tkInvalid: pegError(p, "invalid token")
-
-proc eat(p: var TPegParser, kind: TTokKind) =
-  if p.tok.kind == kind: getTok(p)
-  else: pegError(p, tokKindToStr[kind] & " expected")
-
-proc parseExpr(p: var TPegParser): TPeg
-
-proc getNonTerminal(p: var TPegParser, name: string): PNonTerminal =
-  for i in 0..high(p.nonterms):
-    result = p.nonterms[i]
-    if cmpIgnoreStyle(result.name, name) == 0: return
-  # forward reference:
-  result = newNonTerminal(name, getLine(p), getColumn(p))
-  add(p.nonterms, result)
-
-proc modifiedTerm(s: string, m: TModifier): TPeg =
-  case m
-  of modNone, modVerbatim: result = term(s)
-  of modIgnoreCase: result = termIgnoreCase(s)
-  of modIgnoreStyle: result = termIgnoreStyle(s)
-
-proc modifiedBackref(s: int, m: TModifier): TPeg =
-  case m
-  of modNone, modVerbatim: result = backRef(s)
-  of modIgnoreCase: result = backRefIgnoreCase(s)
-  of modIgnoreStyle: result = backRefIgnoreStyle(s)
-
-proc builtin(p: var TPegParser): TPeg =
-  # do not use "y", "skip" or "i" as these would be ambiguous
-  case p.tok.literal
-  of "n": result = newLine()
-  of "d": result = charset({'0'..'9'})
-  of "D": result = charset({'\1'..'\xff'} - {'0'..'9'})
-  of "s": result = charset({' ', '\9'..'\13'})
-  of "S": result = charset({'\1'..'\xff'} - {' ', '\9'..'\13'})
-  of "w": result = charset({'a'..'z', 'A'..'Z', '_', '0'..'9'})
-  of "W": result = charset({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'})
-  of "a": result = charset({'a'..'z', 'A'..'Z'})
-  of "A": result = charset({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'})
-  of "ident": result = tpegs.ident
-  of "letter": result = UnicodeLetter()
-  of "upper": result = UnicodeUpper()
-  of "lower": result = UnicodeLower()
-  of "title": result = UnicodeTitle()
-  of "white": result = UnicodeWhitespace()
-  else: pegError(p, "unknown built-in: " & p.tok.literal)
-
-proc token(terminal: TPeg, p: TPegParser): TPeg =
-  if p.skip.kind == pkEmpty: result = terminal
-  else: result = sequence(p.skip, terminal)
-
-proc primary(p: var TPegParser): TPeg =
-  case p.tok.kind
-  of tkAmp:
-    getTok(p)
-    return &primary(p)
-  of tkNot:
-    getTok(p)
-    return !primary(p)
-  of tkAt:
-    getTok(p)
-    return !*primary(p)
-  of tkCurlyAt:
-    getTok(p)
-    return !*\primary(p).token(p)
-  else: discard
-  case p.tok.kind
-  of tkIdentifier:
-    if p.identIsVerbatim:
-      var m = p.tok.modifier
-      if m == modNone: m = p.modifier
-      result = modifiedTerm(p.tok.literal, m).token(p)
-      getTok(p)
-    elif not arrowIsNextTok(p):
-      var nt = getNonTerminal(p, p.tok.literal)
-      incl(nt.flags, ntUsed)
-      result = nonTerminal(nt).token(p)
-      getTok(p)
-    else:
-      pegError(p, "expression expected, but found: " & p.tok.literal)
-  of tkStringLit:
-    var m = p.tok.modifier
-    if m == modNone: m = p.modifier
-    result = modifiedTerm(p.tok.literal, m).token(p)
-    getTok(p)
-  of tkCharSet:
-    if '\0' in p.tok.charset:
-      pegError(p, "binary zero ('\\0') not allowed in character class")
-    result = charset(p.tok.charset).token(p)
-    getTok(p)
-  of tkParLe:
-    getTok(p)
-    result = parseExpr(p)
-    eat(p, tkParRi)
-  of tkCurlyLe:
-    getTok(p)
-    result = capture(parseExpr(p)).token(p)
-    eat(p, tkCurlyRi)
-    inc(p.captures)
-  of tkAny:
-    result = any().token(p)
-    getTok(p)
-  of tkAnyRune:
-    result = anyRune().token(p)
-    getTok(p)
-  of tkBuiltin:
-    result = builtin(p).token(p)
-    getTok(p)
-  of tkEscaped:
-    result = term(p.tok.literal[0]).token(p)
-    getTok(p)
-  of tkDollar:
-    result = endAnchor()
-    getTok(p)
-  of tkHat:
-    result = startAnchor()
-    getTok(p)
-  of tkBackref:
-    var m = p.tok.modifier
-    if m == modNone: m = p.modifier
-    result = modifiedBackRef(p.tok.index, m).token(p)
-    if p.tok.index < 0 or p.tok.index > p.captures:
-      pegError(p, "invalid back reference index: " & $p.tok.index)
-    getTok(p)
-  else:
-    pegError(p, "expression expected, but found: " & p.tok.literal)
-    getTok(p) # we must consume a token here to prevent endless loops!
-  while true:
-    case p.tok.kind
-    of tkOption:
-      result = ?result
-      getTok(p)
-    of tkStar:
-      result = *result
-      getTok(p)
-    of tkPlus:
-      result = +result
-      getTok(p)
-    else: break
-
-proc seqExpr(p: var TPegParser): TPeg =
-  result = primary(p)
-  while true:
-    case p.tok.kind
-    of tkAmp, tkNot, tkAt, tkStringLit, tkCharset, tkParLe, tkCurlyLe,
-       tkAny, tkAnyRune, tkBuiltin, tkEscaped, tkDollar, tkBackref,
-       tkHat, tkCurlyAt:
-      result = sequence(result, primary(p))
-    of tkIdentifier:
-      if not arrowIsNextTok(p):
-        result = sequence(result, primary(p))
-      else: break
-    else: break
-
-proc parseExpr(p: var TPegParser): TPeg =
-  result = seqExpr(p)
-  while p.tok.kind == tkBar:
-    getTok(p)
-    result = result / seqExpr(p)
-
-proc parseRule(p: var TPegParser): PNonTerminal =
-  if p.tok.kind == tkIdentifier and arrowIsNextTok(p):
-    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)
-    getTok(p)
-    eat(p, tkArrow)
-    result.rule = parseExpr(p)
-    incl(result.flags, ntDeclared) # NOW inlining may be attempted
-  else:
-    pegError(p, "rule expected, but found: " & p.tok.literal)
-
-proc rawParse(p: var TPegParser): TPeg =
-  ## parses a rule or a PEG expression
-  while p.tok.kind == tkBuiltin:
-    case p.tok.literal
-    of "i":
-      p.modifier = modIgnoreCase
-      getTok(p)
-    of "y":
-      p.modifier = modIgnoreStyle
-      getTok(p)
-    of "skip":
-      getTok(p)
-      p.skip = ?primary(p)
-    else: break
-  if p.tok.kind == tkIdentifier and arrowIsNextTok(p):
-    result = parseRule(p).rule
-    while p.tok.kind != tkEof:
-      discard parseRule(p)
-  else:
-    p.identIsVerbatim = true
-    result = parseExpr(p)
-  if p.tok.kind != tkEof:
-    pegError(p, "EOF expected, but found: " & p.tok.literal)
-  for i in 0..high(p.nonterms):
-    var nt = p.nonterms[i]
-    if ntDeclared notin nt.flags:
-      pegError(p, "undeclared identifier: " & nt.name, nt.line, nt.col)
-    elif ntUsed notin nt.flags and i > 0:
-      pegError(p, "unused rule: " & nt.name, nt.line, nt.col)
-
-proc parsePeg*(pattern: string, filename = "pattern", line = 1, col = 0): TPeg =
-  ## constructs a TPeg object from `pattern`. `filename`, `line`, `col` are
-  ## used for error messages, but they only provide start offsets. `parsePeg`
-  ## keeps track of line and column numbers within `pattern`.
-  var p: TPegParser
-  init(TPegLexer(p), pattern, filename, line, col)
-  p.tok.kind = tkInvalid
-  p.tok.modifier = modNone
-  p.tok.literal = ""
-  p.tok.charset = {}
-  p.nonterms = @[]
-  p.identIsVerbatim = false
-  getTok(p)
-  result = rawParse(p)
-
-proc peg*(pattern: string): TPeg =
-  ## constructs a TPeg object from the `pattern`. The short name has been
-  ## chosen to encourage its use as a raw string modifier::
-  ##
-  ##   peg"{\ident} \s* '=' \s* {.*}"
-  result = parsePeg(pattern, "pattern")
-
-proc escapePeg*(s: string): string =
-  ## escapes `s` so that it is matched verbatim when used as a peg.
-  result = ""
-  var inQuote = false
-  for c in items(s):
-    case c
-    of '\0'..'\31', '\'', '"', '\\':
-      if inQuote:
-        result.add('\'')
-        inQuote = false
-      result.add("\\x")
-      result.add(toHex(ord(c), 2))
-    else:
-      if not inQuote:
-        result.add('\'')
-        inQuote = true
-      result.add(c)
-  if inQuote: result.add('\'')
-
-when isMainModule:
-  doAssert escapePeg("abc''def'") == r"'abc'\x27\x27'def'\x27"
-  #doAssert match("(a b c)", peg"'(' @ ')'")
-  doAssert match("W_HI_Le", peg"\y 'while'")
-  doAssert(not match("W_HI_L", peg"\y 'while'"))
-  doAssert(not match("W_HI_Le", peg"\y v'while'"))
-  doAssert match("W_HI_Le", peg"y'while'")
-
-  doAssert($ +digits == $peg"\d+")
-  doAssert "0158787".match(peg"\d+")
-  doAssert "ABC 0232".match(peg"\w+\s+\d+")
-  doAssert "ABC".match(peg"\d+ / \w+")
-
-  for word in split("00232this02939is39an22example111", peg"\d+"):
-    writeLine(stdout, word)
-
-  doAssert matchLen("key", ident) == 3
-
-  var pattern = sequence(ident, *whitespace, term('='), *whitespace, ident)
-  doAssert matchLen("key1=  cal9", pattern) == 11
-
-  var ws = newNonTerminal("ws", 1, 1)
-  ws.rule = *whitespace
-
-  var expr = newNonTerminal("expr", 1, 1)
-  expr.rule = sequence(capture(ident), *sequence(
-                nonterminal(ws), term('+'), nonterminal(ws), nonterminal(expr)))
-
-  var c: TCaptures
-  var s = "a+b +  c +d+e+f"
-  doAssert rawMatch(s, expr.rule, 0, c) == len(s)
-  var a = ""
-  for i in 0..c.ml-1:
-    a.add(substr(s, c.matches[i][0], c.matches[i][1]))
-  doAssert a == "abcdef"
-  #echo expr.rule
-
-  #const filename = "lib/devel/peg/grammar.txt"
-  #var grammar = parsePeg(newFileStream(filename, fmRead), filename)
-  #echo "a <- [abc]*?".match(grammar)
-  doAssert find("_____abc_______", term("abc"), 2) == 5
-  doAssert match("_______ana", peg"A <- 'ana' / . A")
-  doAssert match("abcs%%%", peg"A <- ..A / .A / '%'")
-
-  if "abc" =~ peg"{'a'}'bc' 'xyz' / {\ident}":
-    doAssert matches[0] == "abc"
-  else:
-    doAssert false
-
-  var g2 = peg"""S <- A B / C D
-                 A <- 'a'+
-                 B <- 'b'+
-                 C <- 'c'+
-                 D <- 'd'+
-              """
-  doAssert($g2 == "((A B) / (C D))")
-  doAssert match("cccccdddddd", g2)
-  doAssert("var1=key; var2=key2".replacef(peg"{\ident}'='{\ident}", "$1<-$2$2") ==
-         "var1<-keykey; var2<-key2key2")
-  doAssert "var1=key; var2=key2".endsWith(peg"{\ident}'='{\ident}")
-
-  if "aaaaaa" =~ peg"'aa' !. / ({'a'})+":
-    doAssert matches[0] == "a"
-  else:
-    doAssert false
-
-  block:
-    var matches: array[0..2, string]
-    if match("abcdefg", peg"c {d} ef {g}", matches, 2):
-      doAssert matches[0] == "d"
-      doAssert matches[1] == "g"
-    else:
-      doAssert false
-
-  for x in findAll("abcdef", peg"{.}", 3):
-    echo x
-
-  if "f(a, b)" =~ peg"{[0-9]+} / ({\ident} '(' {@} ')')":
-    doAssert matches[0] == "f"
-    doAssert matches[1] == "a, b"
-  else:
-    doAssert false
-
-  doAssert match("eine übersicht und außerdem", peg"(\letter \white*)+")
-  # ß is not a lower cased letter?!
-  doAssert match("eine übersicht und auerdem", peg"(\lower \white*)+")
-  doAssert match("EINE ÜBERSICHT UND AUSSERDEM", peg"(\upper \white*)+")
-  doAssert(not match("456678", peg"(\letter)+"))
-
-  doAssert("var1 = key; var2 = key2".replacef(
-    peg"\skip(\s*) {\ident}'='{\ident}", "$1<-$2$2") ==
-         "var1<-keykey;var2<-key2key2")
-
-  doAssert match("prefix/start", peg"^start$", 7)
-
-  # tricky test to check for false aliasing:
-  block:
-    var a = term"key"
-    echo($sequence(sequence(a, term"value"), *a))
-
diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim
index f35965286..4ab3ba581 100644
--- a/tests/stdlib/ttimes.nim
+++ b/tests/stdlib/ttimes.nim
@@ -28,6 +28,12 @@ t.checkFormat("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &
 
 t.checkFormat("yyyyMMddhhmmss", "20380119031407")
 
+# issue 7620
+let t7620_am = parse("4/15/2017 12:01:02 AM +0", "M/d/yyyy' 'h:mm:ss' 'tt' 'z", utc())
+t7620_am.checkFormat("M/d/yyyy' 'h:mm:ss' 'tt' 'z", "4/15/2017 12:01:02 AM +0")
+let t7620_pm = parse("4/15/2017 12:01:02 PM +0", "M/d/yyyy' 'h:mm:ss' 'tt' 'z", utc())
+t7620_pm.checkFormat("M/d/yyyy' 'h:mm:ss' 'tt' 'z", "4/15/2017 12:01:02 PM +0")
+
 let t2 = fromUnix(160070789).utc # Mon 27 Jan 16:06:29 GMT 1975
 t2.checkFormat("d dd ddd dddd h hh H HH m mm M MM MMM MMMM s" &
   " ss t tt y yy yyy yyyy yyyyy z zz zzz",
@@ -367,6 +373,10 @@ suite "ttimes":
     check d(seconds = 0) - d(milliseconds = 1500) == d(milliseconds = -1500)
     check d(milliseconds = -1500) == d(seconds = -1, milliseconds = -500)
     check d(seconds = -1, milliseconds = 500) == d(milliseconds = -500)
+    check initDuration(seconds = 1, nanoseconds = 2) <=
+      initDuration(seconds = 1, nanoseconds = 3)
+    check (initDuration(seconds = 1, nanoseconds = 3) <=
+      initDuration(seconds = 1, nanoseconds = 1)).not
 
   test "large/small dates":
     discard initDateTime(1, mJan, -35_000, 12, 00, 00, utc())
@@ -409,4 +419,11 @@ suite "ttimes":
     # Bug with adding a day to a Time
     let day = 24.hours
     let tomorrow = now + day
-    check tomorrow - now == initDuration(days = 1)
\ No newline at end of file
+    check tomorrow - now == initDuration(days = 1)
+  
+  test "fromWinTime/toWinTime":
+    check 0.fromUnix.toWinTime.fromWinTime.toUnix == 0
+    check (-1).fromWinTime.nanosecond == convert(Seconds, Nanoseconds, 1) - 100
+    check -1.fromWinTime.toWinTime == -1
+    # One nanosecond is discarded due to differences in time resolution
+    check initTime(0, 101).toWinTime.fromWinTime.nanosecond == 100 
\ No newline at end of file
diff --git a/tests/stdlib/twchartoutf8.nim b/tests/stdlib/twchartoutf8.nim
index b2f68ee32..a6602e3e3 100644
--- a/tests/stdlib/twchartoutf8.nim
+++ b/tests/stdlib/twchartoutf8.nim
@@ -30,7 +30,6 @@ else:
     result = newString(size)
     let res = WideCharToMultiByte(CP_UTF8, 0'i32, cast[LPWCSTR](addr(wc[0])), wclen,
       cstring(result), size, cstring(nil), LPBOOL(nil))
-    result[size] = chr(0)
     doAssert size == res
 
   proc testCP(wc: WideCString, lo, hi: int) =
diff --git a/tests/system/tnilconcats.nim b/tests/system/tnilconcats.nim
new file mode 100644
index 000000000..ce059b7b0
--- /dev/null
+++ b/tests/system/tnilconcats.nim
@@ -0,0 +1,25 @@
+discard """
+  output: '''@[nil, nil, nil, nil, nil, nil, nil, "meh"]'''
+  exitcode: "0"
+"""
+
+when true:
+  var ab: string
+  ab &= "more"
+
+  doAssert ab == "more"
+
+  var x: seq[string]
+
+  setLen(x, 7)
+
+  x.add "meh"
+
+  var s: string
+  var z = "abc"
+  var zz: string
+  s &= "foo" & z & zz
+
+  doAssert s == "fooabc"
+
+  echo x
diff --git a/tests/system/toString.nim b/tests/system/toString.nim
index ea9d6b05b..37c678a74 100644
--- a/tests/system/toString.nim
+++ b/tests/system/toString.nim
@@ -51,3 +51,59 @@ import strutils
 let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0']
 doAssert $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\\x00']"
 doAssert $cstring(unsafeAddr arr) == "Hello World!"
+
+proc takes(c: cstring) =
+  doAssert c == ""
+
+proc testm() =
+  var x: string
+  # nil is mapped to "":
+  takes(x)
+
+testm()
+
+# nil tests
+var xx: seq[string]
+var yy: string
+doAssert xx == @[]
+doAssert yy == ""
+
+proc bar(arg: cstring): void =
+  doAssert arg[0] == '\0'
+
+proc baz(arg: openarray[char]): void =
+  doAssert arg.len == 0
+
+proc stringCompare(): void =
+  var a,b,c,d,e,f,g: string
+  a.add 'a'
+  doAssert a == "a"
+  b.add "bee"
+  doAssert b == "bee"
+  b.add g
+  doAssert b == "bee"
+  c.add 123.456
+  doAssert c == "123.456"
+  d.add 123456
+  doAssert d == "123456"
+
+  doAssert e == ""
+  doAssert "" == e
+  doAssert nil == e
+  doAssert e == nil
+  doAssert f == g
+  doAssert "" == ""
+  doAssert "" == nil
+  doAssert nil == ""
+
+  g.setLen(10)
+  doAssert g == "\0\0\0\0\0\0\0\0\0\0"
+  doAssert "" != "\0\0\0\0\0\0\0\0\0\0"
+
+  var nilstring: string
+  bar(nilstring)
+  baz(nilstring)
+
+stringCompare()
+static:
+  stringCompare()
\ No newline at end of file
diff --git a/tests/template/i2416.nim b/tests/template/i2416.nim
new file mode 100644
index 000000000..4b53cd0ca
--- /dev/null
+++ b/tests/template/i2416.nim
@@ -0,0 +1 @@
+template i2416*() = echo "i2416"
diff --git a/tests/template/t2416.nim b/tests/template/t2416.nim
new file mode 100644
index 000000000..f73880718
--- /dev/null
+++ b/tests/template/t2416.nim
@@ -0,0 +1,2 @@
+import i2416
+i2416()
diff --git a/tests/testament/backend.nim b/tests/testament/backend.nim
index 4acef9ca4..385f1171c 100644
--- a/tests/testament/backend.nim
+++ b/tests/testament/backend.nim
@@ -13,7 +13,7 @@ type
   CommitId = distinct string
 
 proc `$`*(id: MachineId): string {.borrow.}
-proc `$`(id: CommitId): string {.borrow.}
+#proc `$`(id: CommitId): string {.borrow.} # not used
 
 var
   thisMachine: MachineId
diff --git a/tests/testament/categories.nim b/tests/testament/categories.nim
index 2f9198759..84e536636 100644
--- a/tests/testament/categories.nim
+++ b/tests/testament/categories.nim
@@ -63,6 +63,26 @@ proc compileRodFiles(r: var TResults, cat: Category, options: string) =
   test "gtkex1", true
   test "gtkex2"
 
+# --------------------- flags tests -------------------------------------------
+
+proc flagTests(r: var TResults, cat: Category, options: string) =
+  # --genscript
+  const filename = "tests"/"flags"/"tgenscript"
+  const genopts = " --genscript"
+  let nimcache = nimcacheDir(filename, genopts, targetC)
+  testSpec r, makeTest(filename, genopts, cat)
+
+  when defined(windows):
+    testExec r, makeTest(filename, " cmd /c cd " & nimcache &
+                         " && compile_tgenscript.bat", cat)
+
+  when defined(linux):
+    testExec r, makeTest(filename, " sh -c \"cd " & nimcache &
+                         " && sh compile_tgenscript.sh\"", cat)
+
+  # Run
+  testExec r, makeTest(filename, " " & nimcache / "tgenscript", cat)
+
 # --------------------- DLL generation tests ----------------------------------
 
 proc safeCopyFile(src, dest: string) =
@@ -323,7 +343,7 @@ var nimbleDir = getEnv("NIMBLE_DIR").string
 if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
 let
   nimbleExe = findExe("nimble")
-  packageDir = nimbleDir / "pkgs"
+  #packageDir = nimbleDir / "pkgs" # not used
   packageIndex = nimbleDir / "packages.json"
 
 proc waitForExitEx(p: Process): int =
@@ -407,9 +427,9 @@ proc `&.?`(a, b: string): string =
   # candidate for the stdlib?
   result = if b.startswith(a): b else: a & b
 
-proc `&?.`(a, b: string): string =
+#proc `&?.`(a, b: string): string = # not used
   # candidate for the stdlib?
-  result = if a.endswith(b): a else: a & b
+  #result = if a.endswith(b): a else: a & b
 
 proc processSingleTest(r: var TResults, cat: Category, options, test: string) =
   let test = "tests" & DirSep &.? cat.string / test
@@ -429,6 +449,8 @@ proc processCategory(r: var TResults, cat: Category, options: string) =
     jsTests(r, cat, options)
   of "dll":
     dllTests(r, cat, options)
+  of "flags":
+    flagTests(r, cat, options)
   of "gc":
     gcTests(r, cat, options)
   of "longgc":
diff --git a/tests/testament/htmlgen.nim b/tests/testament/htmlgen.nim
index bf26a956d..4a888427e 100644
--- a/tests/testament/htmlgen.nim
+++ b/tests/testament/htmlgen.nim
@@ -121,7 +121,7 @@ proc generateAllTestsContent(outfile: File, allResults: AllTests,
 
 proc generateHtml*(filename: string, onlyFailing: bool) =
   let
-    currentTime = getTime().getLocalTime()
+    currentTime = getTime().local()
     timestring = htmlQuote format(currentTime, "yyyy-MM-dd HH:mm:ss 'UTC'zzz")
   var outfile = open(filename, fmWrite)
 
diff --git a/tests/testament/tester.nim b/tests/testament/tester.nim
index 856f95f3b..0c6f376d3 100644
--- a/tests/testament/tester.nim
+++ b/tests/testament/tester.nim
@@ -16,7 +16,7 @@ import
 
 const
   resultsFile = "testresults.html"
-  jsonFile = "testresults.json"
+  #jsonFile = "testresults.json" # not used
   Usage = """Usage:
   tester [options] command [arguments]
 
@@ -150,11 +150,11 @@ proc initResults: TResults =
   result.skipped = 0
   result.data = ""
 
-proc readResults(filename: string): TResults =
-  result = marshal.to[TResults](readFile(filename).string)
+#proc readResults(filename: string): TResults = # not used
+#  result = marshal.to[TResults](readFile(filename).string)
 
-proc writeResults(filename: string, r: TResults) =
-  writeFile(filename, $$r)
+#proc writeResults(filename: string, r: TResults) = # not used
+#  writeFile(filename, $$r)
 
 proc `$`(x: TResults): string =
   result = ("Tests passed: $1 / $3 <br />\n" &
@@ -212,18 +212,18 @@ proc cmpMsgs(r: var TResults, expected, given: TSpec, test: TTest, target: TTarg
   elif expected.tfile == "" and extractFilename(expected.file) != extractFilename(given.file) and
       "internal error:" notin expected.msg:
     r.addResult(test, target, expected.file, given.file, reFilesDiffer)
-  elif expected.line   != given.line   and expected.line   != 0 or
+  elif expected.line != given.line and expected.line != 0 or
        expected.column != given.column and expected.column != 0:
     r.addResult(test, target, $expected.line & ':' & $expected.column,
-                      $given.line    & ':' & $given.column,
+                      $given.line & ':' & $given.column,
                       reLinesDiffer)
   elif expected.tfile != "" and extractFilename(expected.tfile) != extractFilename(given.tfile) and
       "internal error:" notin expected.msg:
     r.addResult(test, target, expected.tfile, given.tfile, reFilesDiffer)
-  elif expected.tline   != given.tline   and expected.tline   != 0 or
+  elif expected.tline != given.tline and expected.tline != 0 or
        expected.tcolumn != given.tcolumn and expected.tcolumn != 0:
     r.addResult(test, target, $expected.tline & ':' & $expected.tcolumn,
-                      $given.tline    & ':' & $given.tcolumn,
+                      $given.tline & ':' & $given.tcolumn,
                       reLinesDiffer)
   else:
     r.addResult(test, target, expected.msg, given.msg, reSuccess)
@@ -404,6 +404,21 @@ proc testC(r: var TResults, test: TTest) =
     if exitCode != 0: given.err = reExitCodesDiffer
   if given.err == reSuccess: inc(r.passed)
 
+proc testExec(r: var TResults, test: TTest) =
+  # runs executable or script, just goes by exit code
+  inc(r.total)
+  let (outp, errC) = execCmdEx(test.options.strip())
+  var given: TSpec
+  specDefaults(given)
+  if errC == 0:
+    given.err = reSuccess
+  else:
+    given.err = reExitCodesDiffer
+    given.msg = outp.string
+
+  if given.err == reSuccess: inc(r.passed)
+  r.addResult(test, targetC, "", given.msg, given.err)
+
 proc makeTest(test, options: string, cat: Category, action = actionCompile,
               env: string = ""): TTest =
   # start with 'actionCompile', will be overwritten in the spec:
diff --git a/tests/threads/tthreadvars.nim b/tests/threads/tthreadvars.nim
new file mode 100644
index 000000000..81aa2e5ec
--- /dev/null
+++ b/tests/threads/tthreadvars.nim
@@ -0,0 +1,78 @@
+discard """
+output: '''
+10
+1111
+1222
+3030303
+3060606
+6060606
+6121212
+3030903
+3061206
+3031503
+3061806
+5050505
+5101010
+'''
+"""
+
+import typetraits
+
+var tls1 {.threadvar.}: int
+var g0: int
+var g1 {.global.}: int
+
+proc customInc(x: var int, delta: int) =
+  x += delta
+
+customInc(tls1, 10)
+echo tls1
+
+proc nonGenericProc: int =
+  var local: int
+  var nonGenericTls {.threadvar.}: int
+  var nonGenericGlobal {.global.}: int
+  var nonGenericMixedPragmas {.global, threadvar.}: int
+
+  customInc local, 1000
+  customInc nonGenericTls, 1
+  customInc nonGenericGlobal, 10
+  customInc nonGenericMixedPragmas, 100
+
+  return local + nonGenericTls + nonGenericGlobal + nonGenericMixedPragmas
+
+proc genericProc(T: typedesc): int =
+  var local: int
+  var genericTls {.threadvar.}: int
+  var genericGlobal {.global.}: int
+  var genericMixedPragmas {.global, threadvar.}: int
+
+  customInc local, T.name.len * 1000000
+  customInc genericTls, T.name.len * 1
+  customInc genericGlobal, T.name.len * 100
+  customInc genericMixedPragmas, T.name.len * 10000
+
+  return local + genericTls + genericGlobal + genericMixedPragmas
+
+echo nonGenericProc()
+echo nonGenericProc()
+
+echo genericProc(int)
+echo genericProc(int)
+
+echo genericProc(string)
+echo genericProc(string)
+
+proc echoInThread[T]() {.thread.} =
+  echo genericProc(T)
+  echo genericProc(T)
+
+proc newEchoThread(T: typedesc) =
+  var t: Thread[void]
+  createThread(t, echoInThread[T])
+  joinThreads(t)
+
+newEchoThread int
+newEchoThread int
+newEchoThread float
+
diff --git a/tests/trmacros/thoist.nim b/tests/trmacros/thoist.nim
index 7d14c0abf..657f210a1 100644
--- a/tests/trmacros/thoist.nim
+++ b/tests/trmacros/thoist.nim
@@ -5,7 +5,7 @@ true'''
 
 import pegs
 
-template optPeg{peg(pattern)}(pattern: string{lit}): TPeg =
+template optPeg{peg(pattern)}(pattern: string{lit}): Peg =
   var gl {.global, gensym.} = peg(pattern)
   gl
 
diff --git a/tests/typerel/t7600_1.nim b/tests/typerel/t7600_1.nim
new file mode 100644
index 000000000..e3a5fefa2
--- /dev/null
+++ b/tests/typerel/t7600_1.nim
@@ -0,0 +1,18 @@
+discard """
+errormsg: "type mismatch: got <Thin[system.int]>"
+nimout: '''t7600_1.nim(18, 6) Error: type mismatch: got <Thin[system.int]>
+but expected one of:
+proc test[T](x: Paper[T])
+
+expression: test tn'''
+"""
+
+type
+  Paper[T] = ref object of RootObj
+    thickness: T
+  Thin[T]  = object of Paper[T]
+
+proc test[T](x: Paper[T]) = discard
+
+var tn = Thin[int]()
+test tn
diff --git a/tests/typerel/t7600_2.nim b/tests/typerel/t7600_2.nim
new file mode 100644
index 000000000..7badb69cf
--- /dev/null
+++ b/tests/typerel/t7600_2.nim
@@ -0,0 +1,17 @@
+discard """
+errormsg: "type mismatch: got <Thin>"
+nimout: '''t7600_2.nim(17, 6) Error: type mismatch: got <Thin>
+but expected one of:
+proc test(x: Paper)
+
+expression: test tn'''
+"""
+
+type
+  Paper = ref object of RootObj
+  Thin  = object of Paper
+
+proc test(x: Paper) = discard
+
+var tn = Thin()
+test tn
diff --git a/tests/typerel/texplicitcmp.nim b/tests/typerel/texplicitcmp.nim
index 8aec9885a..e91ac2ffe 100644
--- a/tests/typerel/texplicitcmp.nim
+++ b/tests/typerel/texplicitcmp.nim
@@ -18,7 +18,7 @@ proc works() =
   sort(f, system.cmp[int])
   outp(f)
 
-proc weird(json_params: TTable) =
+proc weird(json_params: Table) =
   var f = @[3, 2, 1]
   # The following line doesn't compile: type mismatch. Why?
   sort(f, system.cmp[int])
@@ -29,4 +29,4 @@ when isMainModule:
   sort(t, system.cmp[int])
   outp(t)
   works()
-  weird(initTable[string, TJsonNode]())
+  weird(initTable[string, JsonNode]())
diff --git a/tests/typerel/ttypelessemptyset.nim b/tests/typerel/ttypelessemptyset.nim
index 3e171387b..5f49c33fd 100644
--- a/tests/typerel/ttypelessemptyset.nim
+++ b/tests/typerel/ttypelessemptyset.nim
@@ -1,5 +1,5 @@
 discard """
-  errormsg: "internal error: invalid kind for last(tyEmpty)"
+  errormsg: "internal error: invalid kind for lastOrd(tyEmpty)"
 """
 var q = false
 discard (if q: {} else: {})
diff --git a/tests/types/tparameterizedparent3.nim b/tests/types/tparameterizedparent3.nim
index 3fc83cb4d..58aaf80ea 100644
--- a/tests/types/tparameterizedparent3.nim
+++ b/tests/types/tparameterizedparent3.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tparameterizedparent3.nim"
   line: 13
-  errormsg: "redefinition of 'color'"
+  errormsg: "attempt to redefine: 'color'"
 """
 # bug #5264
 type
diff --git a/tests/types/tparameterizedparent4.nim b/tests/types/tparameterizedparent4.nim
index fa8b525c1..a37461bb4 100644
--- a/tests/types/tparameterizedparent4.nim
+++ b/tests/types/tparameterizedparent4.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tparameterizedparent4.nim"
   line: 23
-  errormsg: "redefinition of 'grain'"
+  errormsg: "attempt to redefine: 'grain'"
 """
 # bug #5264
 type
diff --git a/tests/varres/tnewseq_on_result_vart.nim b/tests/varres/tnewseq_on_result_vart.nim
new file mode 100644
index 000000000..18935a1d1
--- /dev/null
+++ b/tests/varres/tnewseq_on_result_vart.nim
@@ -0,0 +1,9 @@
+
+discard """
+  line: 9
+  errormsg: "address of 'result' may not escape its stack frame"
+"""
+# bug #5113
+
+proc makeSeqVar(size: Natural): var seq[int] =
+  newSeq(result, size)
diff --git a/tests/vm/tref.nim b/tests/vm/tref.nim
new file mode 100644
index 000000000..517a67fb0
--- /dev/null
+++ b/tests/vm/tref.nim
@@ -0,0 +1,12 @@
+static:
+  var
+    a: ref string
+    b: ref string
+  new a
+
+  a[] = "Hello world"
+  b = a
+
+  b[5] = 'c'
+  doAssert a[] == "Hellocworld"
+  doAssert b[] == "Hellocworld"
\ No newline at end of file