summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2018-12-12 16:29:46 +0100
committerGitHub <noreply@github.com>2018-12-12 16:29:46 +0100
commita1bf9fd2b6525e613899c5dc0380fb80021ee3e7 (patch)
treed2bdb332c973d2f6d43391369229cc732642c74d
parenta38f35359738534ba856d02f3564d5fbc2dfc822 (diff)
parent070bcf4cea28a3238089379f5884787b2084b2de (diff)
downloadNim-a1bf9fd2b6525e613899c5dc0380fb80021ee3e7.tar.gz
Merge branch 'devel' into sorted_deduplicate
-rw-r--r--.gitignore3
-rw-r--r--.gitlab-ci.yml3
-rw-r--r--.travis.yml2
-rw-r--r--appveyor.yml4
-rw-r--r--changelog.md26
-rw-r--r--compiler/ast.nim9
-rw-r--r--compiler/astalgo.nim6
-rw-r--r--compiler/ccgcalls.nim20
-rw-r--r--compiler/ccgexprs.nim16
-rw-r--r--compiler/ccgstmts.nim3
-rw-r--r--compiler/cgen.nim2
-rw-r--r--compiler/cgmeth.nim6
-rw-r--r--compiler/commands.nim10
-rw-r--r--compiler/destroyer.nim177
-rw-r--r--compiler/dfa.nim2
-rw-r--r--compiler/evaltempl.nim14
-rw-r--r--compiler/extccomp.nim34
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/lambdalifting.nim5
-rw-r--r--compiler/lookups.nim2
-rw-r--r--compiler/main.nim16
-rw-r--r--compiler/modulegraphs.nim2
-rw-r--r--compiler/nim.nim8
-rw-r--r--compiler/pragmas.nim6
-rw-r--r--compiler/sem.nim11
-rw-r--r--compiler/semasgn.nim14
-rw-r--r--compiler/semdata.nim6
-rw-r--r--compiler/semexprs.nim4
-rw-r--r--compiler/semfold.nim16
-rw-r--r--compiler/seminst.nim2
-rw-r--r--compiler/semmagic.nim2
-rw-r--r--compiler/semstmts.nim59
-rw-r--r--compiler/semtypes.nim10
-rw-r--r--compiler/vm.nim18
-rw-r--r--doc/advopt.txt4
-rw-r--r--doc/contributing.rst11
-rw-r--r--doc/lib.rst4
-rw-r--r--koch.nim6
-rw-r--r--lib/impure/nre.nim131
-rw-r--r--lib/impure/nre/private/util.nim16
-rw-r--r--lib/pure/asyncdispatch.nim213
-rw-r--r--lib/pure/collections/lists.nim15
-rw-r--r--lib/pure/collections/sharedstrings.nim6
-rw-r--r--lib/pure/includes/asynccommon.nim211
-rw-r--r--lib/pure/includes/oserr.nim3
-rw-r--r--lib/pure/memfiles.nim38
-rw-r--r--lib/pure/options.nim34
-rw-r--r--lib/pure/subexes.nim4
-rw-r--r--lib/std/diff.nim387
-rw-r--r--lib/system/chcks.nim9
-rw-r--r--lib/system/excpt.nim11
-rw-r--r--lib/system/helpers2.nim5
-rw-r--r--testament/backend.nim16
-rw-r--r--testament/categories.nim267
-rw-r--r--testament/specs.nim257
-rw-r--r--testament/tester.nim205
-rw-r--r--testament/tests/shouldfail/tcolumn.nim2
-rw-r--r--testament/tests/shouldfail/terrormsg.nim2
-rw-r--r--testament/tests/shouldfail/tfile.nim2
-rw-r--r--testament/tests/shouldfail/tline.nim2
-rw-r--r--tests/ambsym/tambsym.nim4
-rw-r--r--tests/ambsym/tambsym2.nim3
-rw-r--r--tests/ambsym/tambsym3.nim4
-rw-r--r--tests/ambsym/tambsys.nim3
-rw-r--r--tests/array/tarray.nim7
-rw-r--r--tests/array/tarraycons.nim5
-rw-r--r--tests/array/tarraycons_ptr_generic2.nim2
-rw-r--r--tests/assert/tassert.nim3
-rw-r--r--tests/assign/tassign.nim1
-rw-r--r--tests/assign/tvariantasgn.nim4
-rw-r--r--tests/async/t7192.nim2
-rw-r--r--tests/async/t7758.nim6
-rw-r--r--tests/async/tasyncRecvLine.nim3
-rw-r--r--tests/async/tasync_gcunsafe.nim2
-rw-r--r--tests/async/tasyncall.nim1
-rw-r--r--tests/async/tasyncawait.nim1
-rw-r--r--tests/async/tasyncconnect.nim3
-rw-r--r--tests/async/tasyncdial.nim1
-rw-r--r--tests/async/tasyncexceptions.nim5
-rw-r--r--tests/async/tasyncfile.nim8
-rw-r--r--tests/async/tasyncrecursion.nim5
-rw-r--r--tests/async/tasyncsend4757.nim3
-rw-r--r--tests/async/tasyncssl.nim1
-rw-r--r--tests/async/tasynctry.nim4
-rw-r--r--tests/async/tawaitsemantics.nim4
-rw-r--r--tests/async/tfuturestream.nim6
-rw-r--r--tests/async/tioselectors.nim1
-rw-r--r--tests/async/tnewasyncudp.nim1
-rw-r--r--tests/async/tpendingcheck.nim3
-rw-r--r--tests/async/twinasyncrw.nim1
-rw-r--r--tests/benchmark.nim47
-rw-r--r--tests/benchmarks/fannkuch.nim69
-rw-r--r--tests/benchmarks/quicksort.nim54
-rw-r--r--tests/bind/tbind.nim4
-rw-r--r--tests/bind/tbind2.nim5
-rw-r--r--tests/bind/tdatabind.nim2
-rw-r--r--tests/bind/tinvalidbindtypedesc.nim3
-rw-r--r--tests/bind/tnicerrorforsymchoice.nim2
-rw-r--r--tests/borrow/tinvalidborrow.nim3
-rw-r--r--tests/caas/absurd_nesting.nim29
-rw-r--r--tests/caas/absurd_nesting.txt29
-rw-r--r--tests/caas/basic-recompile.txt10
-rw-r--r--tests/caas/compile-suggest.txt7
-rw-r--r--tests/caas/compile-then-def.txt11
-rw-r--r--tests/caas/completion_dot_syntax.txt9
-rw-r--r--tests/caas/completion_dot_syntax_dirty.nim25
-rw-r--r--tests/caas/completion_dot_syntax_main.nim24
-rw-r--r--tests/caas/def-def-compile.txt12
-rw-r--r--tests/caas/def-then-compile.txt8
-rw-r--r--tests/caas/forward_declarations.nim15
-rw-r--r--tests/caas/forward_declarations.txt9
-rw-r--r--tests/caas/forward_usages.txt17
-rw-r--r--tests/caas/idetools_api.nim84
-rw-r--r--tests/caas/idetools_api.txt59
-rw-r--r--tests/caas/imported.nim3
-rw-r--r--tests/caas/issue_416_template_shift.nim17
-rw-r--r--tests/caas/issue_416_template_shift.txt14
-rw-r--r--tests/caas/issue_452_export_shift.nim8
-rw-r--r--tests/caas/issue_452_export_shift.txt11
-rw-r--r--tests/caas/issue_477_dynamic_dispatch.nim19
-rw-r--r--tests/caas/issue_477_dynamic_dispatch.txt5
-rw-r--r--tests/caas/its_full_of_procs.nim29
-rw-r--r--tests/caas/its_full_of_procs.txt20
-rw-r--r--tests/caas/main.nim7
-rw-r--r--tests/caas/main_dirty.nim14
-rw-r--r--tests/caas/suggest-compile.txt13
-rw-r--r--tests/caas/suggest-invalid-source.txt26
-rw-r--r--tests/casestmt/t7699.nim2
-rw-r--r--tests/casestmt/tcaseexpr1.nim13
-rw-r--r--tests/casestmt/tcaseoverlaprange.nim2
-rw-r--r--tests/casestmt/tcaseoverlaprange2.nim2
-rw-r--r--tests/casestmt/tcasestmt.nim5
-rw-r--r--tests/ccgbugs/t8616.nim2
-rw-r--r--tests/ccgbugs/t8781.nim2
-rw-r--r--tests/ccgbugs/tcgbug.nim8
-rw-r--r--tests/ccgbugs/tconstobj.nim16
-rw-r--r--tests/ccgbugs/tgeneric_closure.nim2
-rw-r--r--tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim5
-rw-r--r--tests/ccgbugs/tmarkerproc_regression.nim4
-rw-r--r--tests/ccgbugs/tmissingbracket.nim7
-rw-r--r--tests/ccgbugs/tmissinginit.nim2
-rw-r--r--tests/ccgbugs/tobjconstr_bad_aliasing.nim3
-rw-r--r--tests/clearmsg/tconsttypemismatch.nim3
-rw-r--r--tests/clearmsg/tmacroerrorproc.nim2
-rw-r--r--tests/closure/tclosure.nim1
-rw-r--r--tests/closure/tinvalidclosure.nim2
-rw-r--r--tests/closure/tinvalidclosure2.nim2
-rw-r--r--tests/closure/tinvalidclosure3.nim4
-rw-r--r--tests/closure/tnested.nim3
-rw-r--r--tests/cnstseq/tcnstseq.nim3
-rw-r--r--tests/collections/tcollections.nim4
-rw-r--r--tests/collections/thashsets.nim (renamed from tests/collections/tsets.nim)0
-rw-r--r--tests/collections/ttables.nim12
-rw-r--r--tests/compilerapi/tcompilerapi.nim3
-rw-r--r--tests/concepts/tconcepts.nim29
-rw-r--r--tests/concepts/texplain.nim3
-rw-r--r--tests/concepts/trandomvars.nim4
-rw-r--r--tests/concepts/trandomvars2.nim (renamed from tests/concepts/trandom_vars.nim)0
-rw-r--r--tests/constr/tconstr1.nim4
-rw-r--r--tests/constr/tconstr2.nim6
-rw-r--r--tests/constraints/tconstraints.nim4
-rw-r--r--tests/constructors/t5965_1.nim2
-rw-r--r--tests/constructors/t5965_2.nim2
-rw-r--r--tests/controlflow/tblock1.nim4
-rw-r--r--tests/controlflow/tcontrolflow.nim10
-rw-r--r--tests/controlflow/tstatret.nim5
-rw-r--r--tests/converter/tconverter_unique_ptr.nim7
-rw-r--r--tests/converter/tconverter_with_constraint.nim8
-rw-r--r--tests/deprecated/tnoannot.nim2
-rw-r--r--tests/deps/jester-#head/jester/patterns.nim2
-rw-r--r--tests/deps/jester-#head/jester/private/utils.nim2
-rw-r--r--tests/deps/zip-0.2.1/zip/zipfiles.nim2
-rw-r--r--tests/destructor/tmatrix.nim22
-rw-r--r--tests/destructor/tmove_objconstr.nim49
-rw-r--r--tests/destructor/turn_destroy_into_finalizer.nim8
-rw-r--r--tests/discard/tdiscardable.nim3
-rw-r--r--tests/discard/tillegaldiscard.nim2
-rw-r--r--tests/discard/tneedsdiscard.nim2
-rw-r--r--tests/discard/tneedsdiscard_in_for.nim2
-rw-r--r--tests/distinct/tdistinct.nim6
-rw-r--r--tests/distinct/tnil.nim4
-rw-r--r--tests/effects/teffects1.nim3
-rw-r--r--tests/effects/teffects2.nim3
-rw-r--r--tests/effects/teffects3.nim3
-rw-r--r--tests/effects/teffects4.nim3
-rw-r--r--tests/effects/tgcsafe.nim2
-rw-r--r--tests/effects/tsidee1.nim5
-rw-r--r--tests/effects/tsidee2.nim4
-rw-r--r--tests/effects/tsidee3.nim4
-rw-r--r--tests/effects/tsidee4.nim4
-rw-r--r--tests/enum/tenumitems.nim4
-rw-r--r--tests/errmsgs/t6483.nim2
-rw-r--r--tests/errmsgs/t8339.nim2
-rw-r--r--tests/errmsgs/t9908_01.nim10
-rw-r--r--tests/errmsgs/t9908_02.nim10
-rw-r--r--tests/errmsgs/tproper_stacktrace.nim2
-rw-r--r--tests/errmsgs/treportunused.nim2
-rw-r--r--tests/exception/tcontinuexc.nim4
-rw-r--r--tests/exception/texceptionbreak.nim1
-rw-r--r--tests/exception/texcsub.nim4
-rw-r--r--tests/exception/tfinally.nim6
-rw-r--r--tests/exception/tfinally2.nim12
-rw-r--r--tests/exception/tfinally3.nim7
-rw-r--r--tests/exception/tfinally4.nim1
-rw-r--r--tests/exception/tnestedreturn.nim1
-rw-r--r--tests/exception/tnestedreturn2.nim1
-rw-r--r--tests/exception/treraise.nim4
-rw-r--r--tests/exception/tunhandledexc.nim3
-rw-r--r--tests/exception/twrongexc.nim5
-rw-r--r--tests/exprs/texprstmt.nim2
-rw-r--r--tests/exprs/tstmtexp.nim3
-rw-r--r--tests/flags/tgenscript.nim1
-rw-r--r--tests/float/tfloat1.nim3
-rw-r--r--tests/float/tfloat2.nim3
-rw-r--r--tests/float/tfloat3.nim15
-rw-r--r--tests/float/tfloat4.nim3
-rw-r--r--tests/float/tfloat5.nim7
-rw-r--r--tests/float/tfloat6.nim7
-rw-r--r--tests/float/tfloat7.nim7
-rw-r--r--tests/float/tfloatnan.nim4
-rw-r--r--tests/float/tissue5821.nim8
-rw-r--r--tests/generics/t6137.nim3
-rw-r--r--tests/generics/t7141.nim3
-rw-r--r--tests/generics/t8270.nim2
-rw-r--r--tests/generics/tbintre2.nim31
-rw-r--r--tests/generics/tbintree.nim19
-rw-r--r--tests/generics/texplicitgeneric1.nim4
-rw-r--r--tests/generics/texplicitgeneric2.nim1
-rw-r--r--tests/generics/tgeneric0.nim5
-rw-r--r--tests/generics/tgeneric3.nim95
-rw-r--r--tests/generics/tgenericprocvar.nim1
-rw-r--r--tests/generics/tgenerics_issues.nim3
-rw-r--r--tests/generics/tgenerics_various.nim3
-rw-r--r--tests/generics/tgenericvariant.nim4
-rw-r--r--tests/generics/toverloading_typedesc.nim2
-rw-r--r--tests/generics/tparser_generator.nim32
-rw-r--r--tests/generics/trtree.nim133
-rw-r--r--tests/generics/tthread_generic.nim2
-rw-r--r--tests/generics/twrong_floatlit_type.nim2
-rw-r--r--tests/global/t5958.nim2
-rw-r--r--tests/implicit/timplicit.nim5
-rw-r--r--tests/iter/tcountup.nim11
-rw-r--r--tests/iter/titer10.nim2
-rw-r--r--tests/iter/titer11.nim4
-rw-r--r--tests/iter/titer3.nim1
-rw-r--r--tests/iter/titer4.nim4
-rw-r--r--tests/iter/titer5.nim5
-rw-r--r--tests/iter/titer6.nim4
-rw-r--r--tests/iter/titer7.nim4
-rw-r--r--tests/iter/titerconcat.nim (renamed from tests/iter/tconcat.nim)0
-rw-r--r--tests/iter/titervaropenarray.nim3
-rw-r--r--tests/iter/treciter.nim4
-rw-r--r--tests/iter/twrongiter.nim2
-rw-r--r--tests/js/t7224.nim3
-rw-r--r--tests/js/tvarargs.nim2
-rw-r--r--tests/let/tlet.nim3
-rw-r--r--tests/let/tlet2.nim3
-rw-r--r--tests/lexer/tind1.nim2
-rw-r--r--tests/lexer/tinvalidintegerliteral1.nim2
-rw-r--r--tests/lexer/tinvalidintegerliteral2.nim2
-rw-r--r--tests/lexer/tinvalidintegerliteral3.nim2
-rw-r--r--tests/lexer/tmissingnl.nim3
-rw-r--r--tests/lexer/tstrlits.nim7
-rw-r--r--tests/lexer/tunderscores.nim5
-rw-r--r--tests/macros/tmacro4.nim2
-rw-r--r--tests/macros/tmacrogenerics.nim1
-rw-r--r--tests/macros/tmacrogensym.nim (renamed from tests/macros/tgensym.nim)0
-rw-r--r--tests/macros/tquotewords.nim1
-rw-r--r--tests/macros/trecmacro.nim2
-rw-r--r--tests/macros/tsametype.nim1
-rw-r--r--tests/macros/tstringinterp.nim2
-rw-r--r--tests/magics/tmagics.nim7
-rw-r--r--tests/manyloc/argument_parser/argument_parser.nim2
-rw-r--r--tests/manyloc/argument_parser/ex_wget.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim2
-rw-r--r--tests/manyloc/keineschweine/dependencies/nake/nake.nim2
-rw-r--r--tests/manyloc/keineschweine/enet_server/enet_server.nim2
-rw-r--r--tests/manyloc/keineschweine/keineschweine.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/estreams.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/map_filter.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/sg_packets.nim2
-rw-r--r--tests/manyloc/keineschweine/lib/zlib_helpers.nim2
-rw-r--r--tests/manyloc/keineschweine/server/old_dirserver.nim2
-rw-r--r--tests/manyloc/keineschweine/server/old_sg_server.nim2
-rw-r--r--tests/manyloc/nake/nake.nim2
-rw-r--r--tests/metatype/tmatrix1.nim4
-rw-r--r--tests/metatype/tmeta_typeclasses.nim (renamed from tests/metatype/ttypeclasses.nim)0
-rw-r--r--tests/metatype/tmetatypematrix.nim (renamed from tests/metatype/tmatrix.nim)4
-rw-r--r--tests/metatype/tstaticparams.nim4
-rw-r--r--tests/method/tmethod.nim2
-rw-r--r--tests/method/tmultim.nim10
-rw-r--r--tests/misc/t99bott.nim8
-rw-r--r--tests/misc/tack.nim4
-rw-r--r--tests/misc/tbug511622.nim4
-rw-r--r--tests/misc/tcmdline.nim1
-rw-r--r--tests/misc/temit.nim5
-rw-r--r--tests/misc/tevents.nim8
-rw-r--r--tests/misc/tgenconstraints.nim3
-rw-r--r--tests/misc/thallo.nim4
-rw-r--r--tests/misc/thintoff.nim12
-rw-r--r--tests/misc/tinc.nim6
-rw-r--r--tests/misc/tinit.nim3
-rw-r--r--tests/misc/tinout.nim4
-rw-r--r--tests/misc/tinvalidarrayaccess.nim25
-rw-r--r--tests/misc/tinvalidarrayaccess2.nim16
-rw-r--r--tests/misc/tinvalidnewseq.nim5
-rw-r--r--tests/misc/tissue710.nim2
-rw-r--r--tests/misc/tnew.nim1
-rw-r--r--tests/misc/tnoinst.nim3
-rw-r--r--tests/misc/tnolen.nim3
-rw-r--r--tests/misc/tnot.nim2
-rw-r--r--tests/misc/tparseopt.nim1
-rw-r--r--tests/misc/tpos.nim4
-rw-r--r--tests/misc/tradix.nim103
-rw-r--r--tests/misc/trawstr.nim4
-rw-r--r--tests/misc/tshadow_magic_type.nim7
-rw-r--r--tests/misc/tsimtych.nim4
-rw-r--r--tests/misc/tsizeof2.nim2
-rw-r--r--tests/misc/tslices.nim5
-rw-r--r--tests/misc/tsortdev.nim5
-rw-r--r--tests/misc/tstrange.nim8
-rw-r--r--tests/misc/tvarious1.nim4
-rw-r--r--tests/misc/tvarnums.nim3
-rw-r--r--tests/modules/m9627/a.nim1
-rw-r--r--tests/modules/m9627/b.nim1
-rw-r--r--tests/modules/t9627.nim7
-rw-r--r--tests/modules/timportexcept.nim3
-rw-r--r--tests/modules/tmismatchedvisibility.nim2
-rw-r--r--tests/modules/tnamspc.nim4
-rw-r--r--tests/modules/tnotuniquename.nim2
-rw-r--r--tests/modules/tnotuniquename2.nim2
-rw-r--r--tests/modules/topaque.nim4
-rw-r--r--tests/modules/trecinca.nim4
-rw-r--r--tests/modules/trecincb.nim4
-rw-r--r--tests/modules/trecmod.nim2
-rw-r--r--tests/modules/tselfimport.nim3
-rw-r--r--tests/namedparams/tnamedparams.nim5
-rw-r--r--tests/niminaction/Chapter2/explicit_discard.nim4
-rw-r--r--tests/niminaction/Chapter2/no_def_eq.nim4
-rw-r--r--tests/niminaction/Chapter2/no_iterator.nim4
-rw-r--r--tests/niminaction/Chapter2/no_seq_type.nim4
-rw-r--r--tests/niminaction/Chapter2/resultreject.nim8
-rw-r--r--tests/niminaction/Chapter3/ChatApp/src/protocol.nim2
-rw-r--r--tests/niminaction/Chapter3/ChatApp/src/server.nim2
-rw-r--r--tests/niminaction/Chapter6/WikipediaStats/concurrency.nim2
-rw-r--r--tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim2
-rw-r--r--tests/niminaction/Chapter6/WikipediaStats/naive.nim2
-rw-r--r--tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim2
-rw-r--r--tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim2
-rw-r--r--tests/niminaction/Chapter7/Tweeter/src/views/user.nim2
-rw-r--r--tests/niminaction/Chapter7/Tweeter/tests/database_test.nim2
-rw-r--r--tests/notnil/tnotnil.nim2
-rw-r--r--tests/objects/tobjconstr.nim31
-rw-r--r--tests/objects/tobjpragma.nim9
-rw-r--r--tests/objects/toop1.nim1
-rw-r--r--tests/objvariant/tadrdisc.nim2
-rw-r--r--tests/objvariant/temptycaseobj.nim4
-rw-r--r--tests/objvariant/tvariantstack.nim3
-rw-r--r--tests/openarray/t8259.nim2
-rw-r--r--tests/openarray/topena1.nim5
-rw-r--r--tests/openarray/topenarrayrepr.nim4
-rw-r--r--tests/openarray/topenlen.nim3
-rw-r--r--tests/openarray/tptrarrayderef.nim9
-rw-r--r--tests/osproc/ta_out.nim6
-rw-r--r--tests/osproc/texecps.nim8
-rw-r--r--tests/osproc/texitcode.nim1
-rw-r--r--tests/osproc/tstderr.nim7
-rw-r--r--tests/osproc/tstdin.nim1
-rw-r--r--tests/osproc/tstdout.nim2
-rw-r--r--tests/osproc/tworkingdir.nim1
-rw-r--r--tests/overflw/toverflw.nim2
-rw-r--r--tests/overflw/toverflw2.nim3
-rw-r--r--tests/overflw/tovfint.nim3
-rw-r--r--tests/overload/toverl.nim4
-rw-r--r--tests/overload/toverload_issues.nim34
-rw-r--r--tests/parallel/tarray_of_channels.nim2
-rw-r--r--tests/parallel/tgc_unsafe.nim2
-rw-r--r--tests/parallel/tgc_unsafe2.nim4
-rw-r--r--tests/parallel/tmissing_deepcopy.nim2
-rw-r--r--tests/parallel/tsimple_array_checks.nim2
-rw-r--r--tests/parallel/tsysspawnbadarg.nim2
-rw-r--r--tests/parallel/twrong_refcounts.nim2
-rw-r--r--tests/parser/tdomulttest.nim4
-rw-r--r--tests/parser/tinvcolonlocation1.nim2
-rw-r--r--tests/parser/tinvcolonlocation2.nim2
-rw-r--r--tests/parser/tinvcolonlocation3.nim2
-rw-r--r--tests/parser/tinvwhen.nim4
-rw-r--r--tests/parser/toprprec.nim1
-rw-r--r--tests/parser/ttupleunpack.nim6
-rw-r--r--tests/pragmas/t6448.nim4
-rw-r--r--tests/pragmas/t8741.nim2
-rw-r--r--tests/pragmas/tcustom_pragma.nim22
-rw-r--r--tests/pragmas/tused.nim10
-rw-r--r--tests/pragmas/tuserpragma2.nim2
-rw-r--r--tests/proc/tprocredef.nim3
-rw-r--r--tests/range/tsubrange.nim3
-rw-r--r--tests/range/tsubrange2.nim2
-rw-r--r--tests/range/tsubrange3.nim1
-rw-r--r--tests/rational/trat_float.nim2
-rw-r--r--tests/realtimeGC/shared.nim3
-rw-r--r--tests/seq/tseq.nim1
-rw-r--r--tests/sets/t2669.nim2
-rw-r--r--tests/sets/tsets.nim7
-rw-r--r--tests/statictypes/t9255.nim2
-rw-r--r--tests/stdlib/nre/captures.nim31
-rw-r--r--tests/stdlib/nre/match.nim6
-rw-r--r--tests/stdlib/nre/replace.nim6
-rw-r--r--tests/stdlib/t8925.nim2
-rw-r--r--tests/stdlib/tbitops.nim1
-rw-r--r--tests/stdlib/tbitops2.nim1
-rw-r--r--tests/stdlib/tcgi.nim6
-rw-r--r--tests/stdlib/tjsonmacro.nim3
-rw-r--r--tests/stdlib/tjsonmacro_reject.nim4
-rw-r--r--tests/stdlib/tjsonmacro_reject2.nim4
-rw-r--r--tests/stdlib/tlists.nim3
-rw-r--r--tests/stdlib/tmemfiles1.nim4
-rw-r--r--tests/stdlib/tmemmapstreams.nim4
-rw-r--r--tests/stdlib/tnativesockets.nim11
-rw-r--r--tests/stdlib/tospaths.nim1
-rw-r--r--tests/stdlib/tosproc.nim1
-rw-r--r--tests/stdlib/tparsesql.nim4
-rw-r--r--tests/stdlib/tquit.nim1
-rw-r--r--tests/stdlib/tregex.nim3
-rw-r--r--tests/stdlib/trepr.nim2
-rw-r--r--tests/stdlib/tsqlparser.nim2
-rw-r--r--tests/stdlib/tstdlib_various.nim2
-rw-r--r--tests/stdlib/tstreams2.nim1
-rw-r--r--tests/stdlib/tstreams3.nim1
-rw-r--r--tests/stdlib/tstring.nim1
-rw-r--r--tests/stdlib/tstrutil.nim1
-rw-r--r--tests/stdlib/tsugar.nim1
-rw-r--r--tests/stdlib/ttimes.nim11
-rw-r--r--tests/system/helpers/readall_echo.nim2
-rw-r--r--tests/system/t7894.nim1
-rw-r--r--tests/system/talloc2.nim1
-rw-r--r--tests/system/tostring.nim5
-rw-r--r--tests/system/tparams.nim5
-rw-r--r--tests/system/trealloc.nim1
-rw-r--r--tests/template/t_otemplates.nim2
-rw-r--r--tests/template/template_issues.nim2
-rw-r--r--tests/template/tgensymregression.nim2
-rw-r--r--tests/template/thygienictempl.nim2
-rw-r--r--tests/template/tparams_gensymed.nim40
-rw-r--r--tests/template/ttempl2.nim3
-rw-r--r--tests/template/twrongopensymchoice.nim2
-rw-r--r--tests/testament/tshouldfail.nim16
-rw-r--r--tests/threads/t8535.nim2
-rw-r--r--tests/threads/tthreadanalysis2.nim3
-rw-r--r--tests/threads/tthreadheapviolation1.nim4
-rw-r--r--tests/trmacros/tdisallowif.nim2
-rw-r--r--tests/tuples/ttuples_various.nim2
-rw-r--r--tests/tuples/twrongtupleaccess.nim3
-rw-r--r--tests/typerel/t2plus.nim2
-rw-r--r--tests/typerel/t8172.nim2
-rw-r--r--tests/typerel/temptynode.nim2
-rw-r--r--tests/typerel/texplicitcmp.nim11
-rw-r--r--tests/typerel/tno_int_in_bool_context.nim3
-rw-r--r--tests/typerel/tnocontains.nim2
-rw-r--r--tests/typerel/trefs.nim5
-rw-r--r--tests/typerel/tregionptrs.nim2
-rw-r--r--tests/typerel/ttypedesc_as_genericparam1.nim2
-rw-r--r--tests/typerel/ttypedesc_as_genericparam2.nim2
-rw-r--r--tests/typerel/ttypenoval.nim4
-rw-r--r--tests/typerel/typredef.nim3
-rw-r--r--tests/types/t6456.nim2
-rw-r--r--tests/types/tassignemptytuple.nim2
-rw-r--r--tests/types/tillegaltyperecursion.nim2
-rw-r--r--tests/types/tillrec.nim3
-rw-r--r--tests/types/tissues_types.nim (renamed from tests/types/tissues.nim)3
-rw-r--r--tests/types/tparameterizedparent0.nim2
-rw-r--r--tests/types/tparameterizedparent1.nim2
-rw-r--r--tests/types/tparameterizedparent3.nim2
-rw-r--r--tests/types/tparameterizedparent4.nim2
-rw-r--r--tests/untestable/tssl.nim2
-rw-r--r--tests/usingstmt/tusingstatement.nim3
-rw-r--r--tests/varres/tnewseq_on_result_vart.nim2
-rw-r--r--tests/varres/tprevent_forloopvar_mutations.nim2
-rw-r--r--tests/varres/tvarres1.nim3
-rw-r--r--tests/varres/tvarres2.nim3
-rw-r--r--tests/varres/tvarres_via_forwarding.nim2
-rw-r--r--tests/varres/tvartup.nim3
-rw-r--r--tests/varres/twrong_parameter.nim2
-rw-r--r--tests/varstmt/tvardecl.nim5
-rw-r--r--tests/vm/t2574.nim2
-rw-r--r--tests/vm/tcastint.nim5
-rw-r--r--tests/vm/tconstobj.nim22
-rw-r--r--tests/vm/tforwardproc.nim2
-rw-r--r--tests/vm/tmitems_vm.nim (renamed from tests/vm/tmitems.nim)0
-rw-r--r--tests/vm/tsetlen.nim30
-rw-r--r--tests/vm/tvmmisc.nim4
-rw-r--r--tools/kochdocs.nim1
494 files changed, 2507 insertions, 2655 deletions
diff --git a/.gitignore b/.gitignore
index 8cd092639..d736cdf8d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -66,3 +66,6 @@ testresults/
 test.txt
 /test.ini
 
+tweeter.db
+tweeter_test.db
+megatest.nim
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 70ff59136..9f536e6c9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -53,9 +53,8 @@ test-windows:
   <<: *win_set_path_def
   script:
     - call ci\deps.bat
-    - nim c --taintMode:on testament\tester
+    - nim c testament\tester
     - testament\tester.exe --pedantic all
   tags:
     - windows
     - fast
-
diff --git a/.travis.yml b/.travis.yml
index 4c3c687e2..abd115701 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -51,7 +51,7 @@ script:
   #- nimble install sdl1
   #- nimble install jester@#head -y
   #- nimble install niminst
-  - nim c --taintMode:on -d:nimCoroutines testament/tester
+  - nim c -d:nimCoroutines testament/tester
   - testament/tester --pedantic all -d:nimCoroutines
   - nim c -o:bin/nimpretty nimpretty/nimpretty.nim
   - nim c -r nimpretty/tester.nim
diff --git a/appveyor.yml b/appveyor.yml
index a60831f9d..9c8525d72 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -53,8 +53,8 @@ build_script:
 #  - nimble install opengl -y
 #  - nimble install sdl1 -y
 #  - nimble install jester@#head -y
-  - nim c --taintMode:on -d:nimCoroutines --os:genode -d:posix --compileOnly testament/tester
-  - nim c --taintMode:on -d:nimCoroutines testament/tester
+  - nim c -d:nimCoroutines --os:genode -d:posix --compileOnly testament/tester
+  - nim c -d:nimCoroutines testament/tester
 
 test_script:
   - testament\tester --pedantic all -d:nimCoroutines
diff --git a/changelog.md b/changelog.md
index f60c038a4..1772652d6 100644
--- a/changelog.md
+++ b/changelog.md
@@ -29,6 +29,27 @@
 
 - `osproc.execProcess` now also takes a `workingDir` parameter.
 
+- `options.UnpackError` is no longer a ref type and inherits from `System.Defect` instead of `System.ValueError`.
+
+- nre's `RegexMatch.{captureBounds,captures}[]`  no longer return `Option` or
+  `nil`/`""`, respectivly. Use the newly added `n in p.captures` method to
+  check if a group is captured, otherwise you'll recieve an exception.
+
+- nre's `RegexMatch.{captureBounds,captures}.toTable` no longer accept a
+  default parameter. Instead uncaptured entries are left empty. Use
+  `Table.getOrDefault()` if you need defaults.
+
+- nre's `RegexMatch.captures.{items,toSeq}` now returns an `Option[string]`
+  instead of a `string`. With the removal of `nil` strings, this is the only
+  way to indicate a missing match. Inside your loops, instead of `capture ==
+  ""` or `capture == nil`, use `capture.isSome` to check if a capture is
+  present, and `capture.get` to get its value.
+
+- nre's `replace()` no longer throws `ValueError` when the replacement string
+  has missing captures. It instead throws `KeyError` for named captures, and
+  `IndexError` for un-named captures. This is consistant with
+  `RegexMatch.{captureBounds,captures}[]`.
+
 #### Breaking changes in the compiler
 
 - The compiler now implements the "generic symbol prepass" for `when` statements
@@ -66,6 +87,8 @@ proc enumToString*(enums: openArray[enum]): string =
   is instantiation of generic proc symbol.
 
 - Added the parameter ``isSorted`` for the ``sequtils.deduplicate`` proc.
+- There is a new stdlib mdoule `std/diff` to compute the famous "diff"
+  of two texts by line.
 
 ### Library changes
 
@@ -93,6 +116,9 @@ proc enumToString*(enums: openArray[enum]): string =
 - There is a new pragma block `noSideEffect` that works like
   the `gcsafe` pragma block.
 - added os.getCurrentProcessId()
+- User defined pragmas are now allowed in the pragma blocks
+- Pragma blocks are now longer eliminated from the typed AST tree to preserve
+  pragmas for further analysis by macros
 
 ### Language changes
 
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 40a05e6bf..5f5f296cb 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -723,10 +723,9 @@ type
       sons*: TNodeSeq
     comment*: string
 
-  TSymSeq* = seq[PSym]
   TStrTable* = object         # a table[PIdent] of PSym
     counter*: int
-    data*: TSymSeq
+    data*: seq[PSym]
 
   # -------------- backend information -------------------------------
   TLocKind* = enum
@@ -1087,9 +1086,6 @@ proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
   result.id = getID()
   when debugIds:
     registerId(result)
-  #if result.id == 77131:
-  #  writeStacktrace()
-  #  echo name.s
 
 proc isMetaType*(t: PType): bool =
   return t.kind in tyMetaTypes or
@@ -1261,6 +1257,9 @@ proc `$`*(x: TLockLevel): string =
   elif x.ord == UnknownLockLevel.ord: result = "<unknown>"
   else: result = $int16(x)
 
+proc `$`*(s: PSym): string =
+  result = s.name.s & "@" & $s.id
+
 proc newType*(kind: TTypeKind, owner: PSym): PType =
   new(result)
   result.kind = kind
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index b2671d81e..60eecbdc5 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -507,7 +507,7 @@ proc strTableContains*(t: TStrTable, n: PSym): bool =
     h = nextTry(h, high(t.data))
   result = false
 
-proc strTableRawInsert(data: var TSymSeq, n: PSym) =
+proc strTableRawInsert(data: var seq[PSym], n: PSym) =
   var h: Hash = n.name.h and high(data)
   if sfImmediate notin n.flags:
     # fast path:
@@ -535,7 +535,7 @@ proc strTableRawInsert(data: var TSymSeq, n: PSym) =
     data[h] = n
     if favPos >= 0: swap data[h], data[favPos]
 
-proc symTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) =
+proc symTabReplaceRaw(data: var seq[PSym], prevSym: PSym, newSym: PSym) =
   assert prevSym.name.h == newSym.name.h
   var h: Hash = prevSym.name.h and high(data)
   while data[h] != nil:
@@ -549,7 +549,7 @@ proc symTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) =
   symTabReplaceRaw(t.data, prevSym, newSym)
 
 proc strTableEnlarge(t: var TStrTable) =
-  var n: TSymSeq
+  var n: seq[PSym]
   newSeq(n, len(t.data) * GrowthFactor)
   for i in countup(0, high(t.data)):
     if t.data[i] != nil: strTableRawInsert(n, t.data[i])
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index b23cd598e..d177e1f88 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -63,26 +63,6 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
     add(pl, ~");$n")
     line(p, cpsStmts, pl)
 
-proc isInCurrentFrame(p: BProc, n: PNode): bool =
-  # checks if `n` is an expression that refers to the current frame;
-  # this does not work reliably because of forwarding + inlining can break it
-  case n.kind
-  of nkSym:
-    if n.sym.kind in {skVar, skResult, skTemp, skLet} and p.prc != nil:
-      result = p.prc.id == n.sym.owner.id
-  of nkDotExpr, nkBracketExpr:
-    if skipTypes(n.sons[0].typ, abstractInst).kind notin {tyVar,tyLent,tyPtr,tyRef}:
-      result = isInCurrentFrame(p, n.sons[0])
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv:
-    result = isInCurrentFrame(p, n.sons[1])
-  of nkHiddenDeref, nkDerefExpr:
-    # what about: var x = addr(y); callAsOpenArray(x[])?
-    # *shrug* ``addr`` is unsafe anyway.
-    result = false
-  of nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
-    result = isInCurrentFrame(p, n.sons[0])
-  else: discard
-
 proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
 
 proc openArrayLoc(p: BProc, n: PNode): Rope =
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 59ef05f9c..d00371dd8 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -850,7 +850,6 @@ proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
   initLocExpr(p, x, a)
   initLocExpr(p, y, b)
-  var ty = skipTypes(a.t, abstractVarRange + abstractPtrs + tyUserTypeClasses)
   d.inheritLocation(a)
   putIntoDest(p, d, n, ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)),
               a.storage)
@@ -867,15 +866,15 @@ proc genArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
       # semantic pass has already checked for const index expressions
       if firstOrd(p.config, ty) == 0:
         if (firstOrd(p.config, b.t) < firstOrd(p.config, ty)) or (lastOrd(p.config, b.t) > lastOrd(p.config, ty)):
-          linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError();$n",
+          linefmt(p, cpsStmts, "if ((NU)($1) > (NU)($2)) #raiseIndexError2($1, $2);$n",
                   rdCharLoc(b), intLiteral(lastOrd(p.config, ty)))
       else:
-        linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
+        linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError3($1, $2, $3);$n",
                 rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty)))
     else:
       let idx = getOrdValue(y)
       if idx < firstOrd(p.config, ty) or idx > lastOrd(p.config, ty):
-        localError(p.config, x.info, "index out of bounds")
+        localError(p.config, x.info, formatErrorIndexBound(idx, firstOrd(p.config, ty), lastOrd(p.config, ty)))
   d.inheritLocation(a)
   putIntoDest(p, d, n,
               ropecg(p.module, "$1[($2)- $3]", rdLoc(a), rdCharLoc(b), first), a.storage)
@@ -884,7 +883,6 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
   initLocExpr(p, x, a)
   initLocExpr(p, y, b)
-  var ty = skipTypes(a.t, abstractVarRange)
   inheritLocation(d, a)
   putIntoDest(p, d, n,
               ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
@@ -915,7 +913,7 @@ proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   initLocExpr(p, x, a)
   initLocExpr(p, y, b) # emit range check:
   if optBoundsCheck in p.options:
-    linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n",
+    linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError2($1,$2Len_0-1);$n",
             rdLoc(b), rdLoc(a)) # BUGFIX: ``>=`` and not ``>``!
   inheritLocation(d, a)
   putIntoDest(p, d, n,
@@ -931,11 +929,11 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   if optBoundsCheck in p.options:
     if ty.kind == tyString and (not defined(nimNoZeroTerminator) or optLaxStrings in p.options):
       linefmt(p, cpsStmts,
-              "if ((NU)($1) > (NU)$2) #raiseIndexError();$n",
+              "if ((NU)($1) > (NU)$2) #raiseIndexError2($1,$2);$n",
               rdLoc(b), lenExpr(p, a))
     else:
       linefmt(p, cpsStmts,
-              "if ((NU)($1) >= (NU)$2) #raiseIndexError();$n",
+              "if ((NU)($1) >= (NU)$2) #raiseIndexError2($1,$2-1);$n",
               rdLoc(b), lenExpr(p, a))
   if d.k == locNone: d.storage = OnHeap
   if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
@@ -1402,7 +1400,6 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
   else:
     var i: TLoc
     getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i)
-    let oldCode = p.s(cpsStmts)
     linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",  i.r, L.rope)
     initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
     elem.r = ropecg(p.module, "$1$3[$2]", rdLoc(d), rdLoc(i), dataField(p))
@@ -2576,7 +2573,6 @@ proc genConstObjConstr(p: BProc; n: PNode): Rope =
 proc genConstSimpleList(p: BProc, n: PNode): Rope =
   var length = sonsLen(n)
   result = rope("{")
-  let t = n.typ.skipTypes(abstractInst)
   for i in countup(0, length - 2):
     addf(result, "$1,$n", [genNamedConstExpr(p, n.sons[i])])
   if length > 0:
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index e83b80b7c..6c33b302d 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -559,7 +559,8 @@ proc genParForStmt(p: BProc, t: PNode) =
     initLocExpr(p, call.sons[1], rangeA)
     initLocExpr(p, call.sons[2], rangeB)
 
-    lineF(p, cpsStmts, "#pragma omp $4$n" &
+    # $n at the beginning because of #9710
+    lineF(p, cpsStmts, "$n#pragma omp $4$n" &
                         "for ($1 = $2; $1 <= $3; ++$1)",
                         [forLoopVar.loc.rdLoc,
                         rangeA.rdLoc, rangeB.rdLoc,
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 3545edc88..457a6e176 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -16,6 +16,8 @@ import
   condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
   lowerings, tables, sets, ndi, lineinfos, pathutils, transf
 
+import system/helpers2
+
 when not defined(leanCompiler):
   import semparallel
 
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index cba07446f..f5014fa8c 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -188,7 +188,7 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
   elif sfBase notin s.flags:
     message(g.config, s.info, warnUseBase)
 
-proc relevantCol(methods: TSymSeq, col: int): bool =
+proc relevantCol(methods: seq[PSym], col: int): bool =
   # returns true iff the position is relevant
   var t = methods[0].typ.sons[col].skipTypes(skipPtrs)
   if t.kind == tyObject:
@@ -206,7 +206,7 @@ proc cmpSignatures(a, b: PSym, relevantCols: IntSet): int =
       if (d != high(int)) and d != 0:
         return d
 
-proc sortBucket(a: var TSymSeq, relevantCols: IntSet) =
+proc sortBucket(a: var seq[PSym], relevantCols: IntSet) =
   # we use shellsort here; fast and simple
   var n = len(a)
   var h = 1
@@ -225,7 +225,7 @@ proc sortBucket(a: var TSymSeq, relevantCols: IntSet) =
       a[j] = v
     if h == 1: break
 
-proc genDispatcher(g: ModuleGraph; methods: TSymSeq, relevantCols: IntSet): PSym =
+proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PSym =
   var base = lastSon(methods[0].ast).sym
   result = base
   var paramLen = sonsLen(base.typ)
diff --git a/compiler/commands.nim b/compiler/commands.nim
index fa17e9851..b090a09a5 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -480,7 +480,7 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
     of "native", "gdb":
       incl(conf.globalOptions, optCDebug)
       conf.options = conf.options + {optLineDir} - {optEndb}
-      defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
+      #defineSymbol(conf.symbols, "nimTypeNames") # type names are used in gdb pretty printing
       undefSymbol(conf.symbols, "endb")
     else:
       localError(conf, info, "expected endb|gdb but found " & arg)
@@ -617,6 +617,14 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
   of "run", "r":
     expectNoArg(conf, switch, arg, pass, info)
     incl(conf.globalOptions, optRun)
+  of "errormax":
+    expectArg(conf, switch, arg, pass, info)
+    # Note: `nim check` (etc) can overwrite this.
+    # `0` is meaningless, give it a useful meaning as in clang's -ferror-limit
+    # If user doesn't set this flag and the code doesn't either, it'd
+    # have the same effect as errorMax = 1
+    let ret = parseInt(arg)
+    conf.errorMax = if ret == 0: high(int) else: ret
   of "verbosity":
     expectArg(conf, switch, arg, pass, info)
     let verbosity = parseInt(arg)
diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim
index 51ad26f2c..40af11e70 100644
--- a/compiler/destroyer.nim
+++ b/compiler/destroyer.nim
@@ -116,7 +116,7 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently
 
 import
   intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
-  strutils, options, dfa, lowerings, tables, modulegraphs,
+  strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
   lineinfos, parampatterns
 
 const
@@ -127,20 +127,11 @@ type
     owner: PSym
     g: ControlFlowGraph
     jumpTargets: IntSet
-    tmpObj: PType
-    tmp: PSym
     destroys, topLevelVars: PNode
-    toDropBit: Table[int, PSym]
     graph: ModuleGraph
     emptyNode: PNode
     otherRead: PNode
 
-proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
-  # XXX why are temps fields in an object here?
-  let f = newSym(skField, getIdent(c.graph.cache, ":d" & $c.tmpObj.n.len), c.owner, info)
-  f.typ = typ
-  rawAddField c.tmpObj, f
-  result = rawDirectAccess(c.tmp, f)
 
 proc isHarmlessVar*(s: PSym; c: Con): bool =
   # 's' is harmless if it used only once and its
@@ -329,22 +320,11 @@ proc genDestroy(c: Con; t: PType; dest: PNode): PNode =
 proc addTopVar(c: var Con; v: PNode) =
   c.topLevelVars.add newTree(nkIdentDefs, v, c.emptyNode, c.emptyNode)
 
-proc dropBit(c: var Con; s: PSym): PSym =
-  result = c.toDropBit.getOrDefault(s.id)
-  assert result != nil
-
-proc registerDropBit(c: var Con; s: PSym) =
-  let result = newSym(skTemp, getIdent(c.graph.cache, s.name.s & "_AliveBit"), c.owner, s.info)
-  result.typ = getSysType(c.graph, s.info, tyBool)
-  let trueVal = newIntTypeNode(nkIntLit, 1, result.typ)
-  c.topLevelVars.add newTree(nkIdentDefs, newSymNode result, c.emptyNode, trueVal)
-  c.toDropBit[s.id] = result
-  # generate:
-  #  if not sinkParam_AliveBit: `=destroy`(sinkParam)
-  let t = s.typ.skipTypes({tyGenericInst, tyAlias, tySink})
-  if t.destructor != nil:
-    c.destroys.add newTree(nkIfStmt,
-      newTree(nkElifBranch, newSymNode result, genDestroy(c, t, newSymNode s)))
+proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
+  let sym = newSym(skTemp, getIdent(c.graph.cache, ":tmpD"), c.owner, info)
+  sym.typ = typ
+  result = newSymNode(sym)
+  c.addTopVar(result)
 
 proc p(n: PNode; c: var Con): PNode
 
@@ -355,16 +335,6 @@ template recurse(n, dest) =
 proc isSinkParam(s: PSym): bool {.inline.} =
   result = s.kind == skParam and s.typ.kind == tySink
 
-proc destructiveMoveSink(n: PNode; c: var Con): PNode =
-  # generate:  (chckMove(sinkParam_AliveBit); sinkParam_AliveBit = false; sinkParam)
-  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
-  let bit = newSymNode dropBit(c, n.sym)
-  if optMoveCheck in c.owner.options:
-    result.add callCodegenProc(c.graph, "chckMove", bit.info, bit)
-  result.add newTree(nkAsgn, bit,
-    newIntTypeNode(nkIntLit, 0, getSysType(c.graph, n.info, tyBool)))
-  result.add n
-
 proc genMagicCall(n: PNode; c: var Con; magicname: string; m: TMagic): PNode =
   result = newNodeI(nkCall, n.info)
   result.add(newSymNode(createMagic(c.graph, magicname, m)))
@@ -395,6 +365,12 @@ proc destructiveMoveVar(n: PNode; c: var Con): PNode =
   result.add genWasMoved(n, c)
   result.add tempAsNode
 
+proc sinkParamIsLastReadCheck(c: var Con, s: PNode) = 
+  assert s.kind == nkSym and s.sym.kind == skParam
+  if not isLastRead(s, c):
+     localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s &
+         "` is already consumed at " & toFileLineCol(c. graph.config, s.info))
+
 proc passCopyToSink(n: PNode; c: var Con): PNode =
   result = newNodeIT(nkStmtListExpr, n.info, n.typ)
   let tmp = getTemp(c, n.typ, n.info)
@@ -411,6 +387,11 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
   result.add tmp
 
 proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
+  template pArgIfTyped(arg_part: PNode): PNode =
+    # typ is nil if we are in if/case expr branch with noreturn
+    if arg_part.typ == nil: p(arg_part, c)
+    else: pArg(arg_part, c, isSink)
+
   if isSink:
     if arg.kind in nkCallKinds:
       # recurse but skip the call expression in order to prevent
@@ -421,17 +402,53 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
       result.add arg[0]
       for i in 1..<arg.len:
         result.add pArg(arg[i], c, i < L and parameters[i].kind == tySink)
-    elif arg.kind in {nkObjConstr, nkCharLit..nkFloat128Lit}:
+    elif arg.kind in {nkBracket, nkObjConstr, nkTupleConstr, nkBracket, nkCharLit..nkFloat128Lit}:
       discard "object construction to sink parameter: nothing to do"
       result = arg
+    elif arg.kind == nkSym and isSinkParam(arg.sym):
+      # Sinked params can be consumed only once. We need to reset the memory
+      # to disable the destructor which we have not elided
+      sinkParamIsLastReadCheck(c, arg)
+      result = destructiveMoveVar(arg, c)
     elif arg.kind == nkSym and arg.sym.kind in InterestingSyms and isLastRead(arg, c):
-      # if x is a variable and it its last read we eliminate its
-      # destructor invokation, but don't. We need to reset its memory
-      # to disable its destructor which we have not elided:
+      # it is the last read, can be sinked. We need to reset the memory
+      # to disable the destructor which we have not elided
       result = destructiveMoveVar(arg, c)
-    elif arg.kind == nkSym and isSinkParam(arg.sym):
-      # mark the sink parameter as used:
-      result = destructiveMoveSink(arg, c)
+    elif arg.kind in {nkBlockExpr, nkBlockStmt}:
+      result = copyNode(arg)
+      result.add arg[0]
+      result.add pArg(arg[1], c, isSink)
+    elif arg.kind == nkStmtListExpr:
+      result = copyNode(arg)
+      for i in 0..arg.len-2:
+        result.add p(arg[i], c)
+      result.add pArg(arg[^1], c, isSink)
+    elif arg.kind in {nkIfExpr, nkIfStmt}:
+      result = copyNode(arg)
+      for i in 0..<arg.len:
+        var branch = copyNode(arg[i])
+        if arg[i].kind in {nkElifBranch, nkElifExpr}:   
+          branch.add p(arg[i][0], c)
+          branch.add pArgIfTyped(arg[i][1])
+        else:
+          branch.add pArgIfTyped(arg[i][0])
+        result.add branch
+    elif arg.kind == nkCaseStmt:
+      result = copyNode(arg)
+      result.add p(arg[0], c)
+      for i in 1..<arg.len:
+        var branch: PNode
+        if arg[i].kind == nkOfbranch:
+          branch = arg[i] # of branch conditions are constants
+          branch[^1] = pArgIfTyped(arg[i][^1])
+        elif arg[i].kind in {nkElifBranch, nkElifExpr}:
+          branch = copyNode(arg[i])   
+          branch.add p(arg[i][0], c)
+          branch.add pArgIfTyped(arg[i][1])
+        else:
+          branch = copyNode(arg[i]) 
+          branch.add pArgIfTyped(arg[i][0])
+        result.add branch     
     else:
       # an object that is not temporary but passed to a 'sink' parameter
       # results in a copy.
@@ -440,6 +457,11 @@ proc pArg(arg: PNode; c: var Con; isSink: bool): PNode =
     result = p(arg, c)
 
 proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
+  template moveOrCopyIfTyped(ri_part: PNode): PNode =
+    # typ is nil if we are in if/case expr branch with noreturn
+    if ri_part.typ == nil: p(ri_part, c)
+    else: moveOrCopy(dest, ri_part, c)
+
   case ri.kind
   of nkCallKinds:
     result = genSink(c, dest.typ, dest, ri)
@@ -454,7 +476,7 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
     result.add ri2
   of nkBracketExpr:
     if ri[0].kind == nkSym and isUnpackedTuple(ri[0].sym):
-      # unpacking of tuple: move out the elements
+      # unpacking of tuple: move out the elements 
       result = genSink(c, dest.typ, dest, ri)
     else:
       result = genCopy(c, dest.typ, dest, ri)
@@ -464,6 +486,45 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
     for i in 0..ri.len-2:
       result.add p(ri[i], c)
     result.add moveOrCopy(dest, ri[^1], c)
+  of nkBlockExpr, nkBlockStmt:
+    result = newNodeI(nkBlockStmt, ri.info)
+    result.add ri[0] ## add label
+    result.add moveOrCopy(dest, ri[1], c)
+  of nkIfExpr, nkIfStmt:
+    result = newNodeI(nkIfStmt, ri.info)
+    for i in 0..<ri.len:
+      var branch = copyNode(ri[i])
+      if ri[i].kind in {nkElifBranch, nkElifExpr}:
+        branch.add p(ri[i][0], c)
+        branch.add moveOrCopyIfTyped(ri[i][1])
+      else:
+        branch.add moveOrCopyIfTyped(ri[i][0])
+      result.add branch
+  of nkCaseStmt:
+    result = newNodeI(nkCaseStmt, ri.info)
+    result.add p(ri[0], c)
+    for i in 1..<ri.len:
+      var branch: PNode
+      if ri[i].kind == nkOfbranch:
+        branch = ri[i] # of branch conditions are constants
+        branch[^1] = moveOrCopyIfTyped(ri[i][^1])
+      elif ri[i].kind in {nkElifBranch, nkElifExpr}:
+        branch = copyNode(ri[i])   
+        branch.add p(ri[i][0], c)
+        branch.add moveOrCopyIfTyped(ri[i][1])
+      else:
+        branch = copyNode(ri[i]) 
+        branch.add moveOrCopyIfTyped(ri[i][0])
+      result.add branch
+  of nkBracket:
+    # array constructor
+    result = genSink(c, dest.typ, dest, ri)
+    let ri2 = copyTree(ri)
+    for i in 0..<ri.len:
+      # everything that is passed to an array constructor is consumed,
+      # so these all act like 'sink' parameters:
+      ri2[i] = pArg(ri[i], c, isSink = true)
+    result.add ri2
   of nkObjConstr:
     result = genSink(c, dest.typ, dest, ri)
     let ri2 = copyTree(ri)
@@ -484,14 +545,17 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
         ri2[i] = pArg(ri[i], c, isSink = true)
     result.add ri2
   of nkSym:
-    if ri.sym.kind != skParam and isLastRead(ri, c):
+    if isSinkParam(ri.sym):
       # Rule 3: `=sink`(x, z); wasMoved(z)
+      sinkParamIsLastReadCheck(c, ri)
       var snk = genSink(c, dest.typ, dest, ri)
-      snk.add p(ri, c)
+      snk.add ri
+      result = newTree(nkStmtList, snk, genMagicCall(ri, c, "wasMoved", mWasMoved))   
+    elif ri.sym.kind != skParam and isLastRead(ri, c):
+      # Rule 3: `=sink`(x, z); wasMoved(z)
+      var snk = genSink(c, dest.typ, dest, ri)
+      snk.add ri
       result = newTree(nkStmtList, snk, genMagicCall(ri, c, "wasMoved", mWasMoved))
-    elif isSinkParam(ri.sym):
-      result = genSink(c, dest.typ, dest, ri)
-      result.add destructiveMoveSink(ri, c)
     else:
       result = genCopy(c, dest.typ, dest, ri)
       result.add p(ri, c)
@@ -512,14 +576,15 @@ proc p(n: PNode; c: var Con): PNode =
       if it.kind == nkVarTuple and hasDestructor(ri.typ):
         let x = lowerTupleUnpacking(c.graph, it, c.owner)
         result.add p(x, c)
-      elif it.kind == nkIdentDefs and hasDestructor(it[0].typ) and not isUnpackedTuple(it[0].sym):
+      elif it.kind == nkIdentDefs and hasDestructor(it[0].typ):
         for j in 0..L-2:
           let v = it[j]
           doAssert v.kind == nkSym
           # move the variable declaration to the top of the frame:
           c.addTopVar v
           # make sure it's destroyed at the end of the proc:
-          c.destroys.add genDestroy(c, v.typ, v)
+          if not isUnpackedTuple(it[0].sym):
+            c.destroys.add genDestroy(c, v.typ, v)
           if ri.kind != nkEmpty:
             let r = moveOrCopy(v, ri, c)
             result.add r
@@ -566,12 +631,8 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
     echo "injecting into ", n
   var c: Con
   c.owner = owner
-  c.tmp = newSym(skTemp, getIdent(g.cache, ":d"), owner, n.info)
-  c.tmpObj = createObj(g, owner, n.info)
-  c.tmp.typ = c.tmpObj
   c.destroys = newNodeI(nkStmtList, n.info)
   c.topLevelVars = newNodeI(nkVarSection, n.info)
-  c.toDropBit = initTable[int, PSym]()
   c.graph = g
   c.emptyNode = newNodeI(nkEmpty, n.info)
   let cfg = constructCfg(owner, n)
@@ -586,10 +647,10 @@ proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
     let params = owner.typ.n
     for i in 1 ..< params.len:
       let param = params[i].sym
-      if param.typ.kind == tySink: registerDropBit(c, param)
+      if param.typ.kind == tySink and hasDestructor(param.typ): 
+        c.destroys.add genDestroy(c, param.typ.skipTypes({tyGenericInst, tyAlias, tySink}), params[i])
+
   let body = p(n, c)
-  if c.tmp.typ.n.len > 0:
-    c.addTopVar(newSymNode c.tmp)
   result = newNodeI(nkStmtList, n.info)
   if c.topLevelVars.len > 0:
     result.add c.topLevelVars
diff --git a/compiler/dfa.nim b/compiler/dfa.nim
index 415cc4ab3..cd32d95d5 100644
--- a/compiler/dfa.nim
+++ b/compiler/dfa.nim
@@ -272,7 +272,7 @@ proc genReturn(c: var Con; n: PNode) =
   c.code.add Instr(n: n, kind: goto, dest: high(int) - c.code.len)
 
 const
-  InterestingSyms = {skVar, skResult, skLet}
+  InterestingSyms = {skVar, skResult, skLet, skParam}
 
 proc genUse(c: var Con; n: PNode) =
   var n = n
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 09a1cd436..0f9220102 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -37,18 +37,21 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
   case templ.kind
   of nkSym:
     var s = templ.sym
-    if s.owner.id == c.owner.id:
+    if s.owner == nil or s.owner.id == c.owner.id:
       if s.kind == skParam and sfGenSym notin s.flags:
         handleParam actual.sons[s.position]
-      elif s.kind == skGenericParam or
-           s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam:
+      elif (s.owner != nil) and (s.kind == skGenericParam or
+           s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
         handleParam actual.sons[s.owner.typ.len + s.position - 1]
       else:
         internalAssert c.config, sfGenSym in s.flags or s.kind == skType
         var x = PSym(idTableGet(c.mapping, s))
         if x == nil:
           x = copySym(s)
-          x.owner = c.genSymOwner
+          # sem'check needs to set the owner properly later, see bug #9476
+          x.owner = nil # c.genSymOwner
+          #if x.kind == skParam and x.owner.kind == skModule:
+          #  internalAssert c.config, false
           idTablePut(c.mapping, s, x)
         result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
     else:
@@ -173,6 +176,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
   initIdTable(ctx.mapping)
 
   let body = tmpl.getBody
+  #echo "instantion of ", renderTree(body, {renderIds})
   if isAtom(body):
     result = newNodeI(nkPar, body.info)
     evalTemplateAux(body, args, ctx, result)
@@ -189,5 +193,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym;
       evalTemplateAux(body.sons[i], args, ctx, result)
   result.flags.incl nfFromTemplate
   result = wrapInComesFrom(n.info, tmpl, result)
+  #if ctx.debugActive:
+  #  echo "instantion of ", renderTree(result, {renderIds})
   dec(conf.evalTemplateCounter)
 
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index f3f74ece8..2fe151a1c 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -763,6 +763,32 @@ proc execCmdsInParallel(conf: ConfigRef; cmds: seq[string]; prettyCb: proc (idx:
       rawMessage(conf, errGenerated, "execution of an external program failed: '$1'" %
         cmds.join())
 
+proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
+  # Extracting the linker.exe here is a bit hacky but the best solution
+  # given ``buildLib``'s design.
+  var i = 0
+  var last = 0
+  if cmd.len > 0 and cmd[0] == '"':
+    inc i
+    while i < cmd.len and cmd[i] != '"': inc i
+    last = i
+    inc i
+  else:
+    while i < cmd.len and cmd[i] != ' ': inc i
+    last = i
+  while i < cmd.len and cmd[i] == ' ': inc i
+  let linkerArgs = conf.projectName & "_" & "linkerArgs.txt"
+  let args = cmd.substr(i)
+  # GCC's response files don't support backslashes. Junk.
+  if conf.cCompiler == ccGcc:
+    writeFile(linkerArgs, args.replace('\\', '/'))
+  else:
+    writeFile(linkerArgs, args)
+  try:
+    execLinkCmd(conf, cmd.substr(0, last) & " @" & linkerArgs)
+  finally:
+    removeFile(linkerArgs)
+
 proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) =
   var
     linkCmd: string
@@ -795,7 +821,13 @@ proc callCCompiler*(conf: ConfigRef; projectfile: AbsoluteFile) =
 
     linkCmd = getLinkCmd(conf, projectfile, objfiles)
     if optCompileOnly notin conf.globalOptions:
-      execLinkCmd(conf, linkCmd)
+      if defined(windows) and linkCmd.len > 8_000:
+        # Windows's command line limit is about 8K (don't laugh...) so C compilers on
+        # Windows support a feature where the command line can be passed via ``@linkcmd``
+        # to them.
+        linkViaResponseFile(conf, linkCmd)
+      else:
+        execLinkCmd(conf, linkCmd)
   else:
     linkCmd = ""
   if optGenScript in conf.globalOptions:
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index a9813f5c5..4d22c4224 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -945,7 +945,7 @@ proc needsNoCopy(p: PProc; y: PNode): bool =
   else:
     return (mapType(y.typ) != etyBaseIndex and
             (skipTypes(y.typ, abstractInst).kind in
-             {tyRef, tyPtr, tyLent, tyVar, tyCString} + IntegralTypes))
+             {tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc} + IntegralTypes))
   return true
 
 proc genAsgnAux(p: PProc, x, y: PNode, noCopyNeeded: bool) =
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 874cb4bd0..ddde1be31 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -407,11 +407,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
               obj.n[0].sym.id = -s.id
             else:
               addField(obj, s, c.graph.cache)
-      # but always return because the rest of the proc is only relevant when
-      # ow != owner:
-      return
     # direct or indirect dependency:
-    if (innerProc and s.typ.callConv == ccClosure) or interestingVar(s):
+    elif (innerProc and s.typ.callConv == ccClosure) or interestingVar(s):
       discard """
         proc outer() =
           var x: int
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 2fb4e5241..db03ac2e0 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -169,7 +169,7 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) =
             getSymRepr(c.config, s))
       inc missingImpls
     elif {sfUsed, sfExported} * s.flags == {}:
-      if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam}:
+      if s.kind notin {skForVar, skParam, skMethod, skUnknown, skGenericParam, skEnumField}:
         # XXX: implicit type params are currently skTypes
         # maybe they can be made skGenericParam as well.
         if s.typ != nil and tfImplicitTypeParam notin s.typ.flags and
diff --git a/compiler/main.nim b/compiler/main.nim
index 6afe57d87..4e28ed483 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -266,11 +266,23 @@ proc mainCommand*(graph: ModuleGraph) =
       var libpaths = newJArray()
       for dir in conf.searchPaths: libpaths.elems.add(%dir.string)
 
-      var dumpdata = % [
+      var hints = newJObject() # consider factoring with `listHints`
+      for a in hintMin..hintMax:
+        let key = lineinfos.HintsToStr[ord(a) - ord(hintMin)]
+        hints[key] = %(a in conf.notes)
+      var warnings = newJObject()
+      for a in warnMin..warnMax:
+        let key = lineinfos.WarningsToStr[ord(a) - ord(warnMin)]
+        warnings[key] = %(a in conf.notes)
+
+      var dumpdata = %[
         (key: "version", val: %VersionAsString),
         (key: "project_path", val: %conf.projectFull.string),
         (key: "defined_symbols", val: definedSymbols),
-        (key: "lib_paths", val: libpaths)
+        (key: "lib_paths", val: %libpaths),
+        (key: "out", val: %conf.outFile.string),
+        (key: "hints", val: hints),
+        (key: "warnings", val: warnings),
       ]
 
       msgWriteln(conf, $dumpdata, {msgStdout, msgSkipHook})
diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim
index d05b301ae..63fa597ff 100644
--- a/compiler/modulegraphs.nim
+++ b/compiler/modulegraphs.nim
@@ -47,7 +47,7 @@ type
     doStopCompile*: proc(): bool {.closure.}
     usageSym*: PSym # for nimsuggest
     owners*: seq[PSym]
-    methods*: seq[tuple[methods: TSymSeq, dispatcher: PSym]] # needs serialization!
+    methods*: seq[tuple[methods: seq[PSym], dispatcher: PSym]] # needs serialization!
     systemModule*: PSym
     sysTypes*: array[TTypeKind, PType]
     compilerprocs*: TStrTable
diff --git a/compiler/nim.nim b/compiler/nim.nim
index 1c4dbd3be..cbd9d6f39 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -9,14 +9,14 @@
 
 when defined(gcc) and defined(windows):
   when defined(x86):
-    {.link: "icons/nim.res".}
+    {.link: "../icons/nim.res".}
   else:
-    {.link: "icons/nim_icon.o".}
+    {.link: "../icons/nim_icon.o".}
 
 when defined(amd64) and defined(windows) and defined(vcc):
-  {.link: "icons/nim-amd64-windows-vcc.res".}
+  {.link: "../icons/nim-amd64-windows-vcc.res".}
 when defined(i386) and defined(windows) and defined(vcc):
-  {.link: "icons/nim-i386-windows-vcc.res".}
+  {.link: "../icons/nim-i386-windows-vcc.res".}
 
 import
   commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 3d8e5645b..f67e74f11 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -1111,8 +1111,8 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
         else: sym.flags.incl sfUsed
       of wLiftLocals: discard
       else: invalidPragma(c, it)
-    elif sym != nil and sym.kind in {skVar, skLet, skParam, skField, skProc,
-                                     skFunc, skConverter, skMethod, skType}:
+    elif sym == nil or (sym != nil and sym.kind in {skVar, skLet, skParam, 
+                      skField, skProc, skFunc, skConverter, skMethod, skType}):
       n.sons[i] = semCustomPragma(c, it)
     elif sym != nil:
       illegalCustomPragma(c, it, sym)
@@ -1138,7 +1138,7 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
             internalError(c.config, n.info, "implicitPragmas")
           inc i
         popInfoContext(c.config)
-        if sym.kind in routineKinds: mergePragmas(sym.ast, o)
+        if sym.kind in routineKinds and sym.ast != nil: mergePragmas(sym.ast, o)
 
     if lfExportLib in sym.loc.flags and sfExportc notin sym.flags:
       localError(c.config, n.info, ".dynlib requires .exportc")
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 924e53b66..8332af346 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -207,11 +207,12 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
     if result.kind notin {kind, skTemp}:
       localError(c.config, n.info, "cannot use symbol of kind '" &
                  $result.kind & "' as a '" & $kind & "'")
-    if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
-      # declarative context, so produce a fresh gensym:
-      result = copySym(result)
-      result.ast = n.sym.ast
-      put(c.p, n.sym, result)
+    when false:
+      if sfGenSym in result.flags and result.kind notin {skTemplate, skMacro, skParam}:
+        # declarative context, so produce a fresh gensym:
+        result = copySym(result)
+        result.ast = n.sym.ast
+        put(c.p, n.sym, result)
     # when there is a nested proc inside a template, semtmpl
     # will assign a wrong owner during the first pass over the
     # template; we must fix it here: see #909
diff --git a/compiler/semasgn.nim b/compiler/semasgn.nim
index 3947e4f6c..5d676dc76 100644
--- a/compiler/semasgn.nim
+++ b/compiler/semasgn.nim
@@ -309,11 +309,15 @@ proc liftBody(c: PContext; typ: PType; kind: TTypeAttachedOp;
   liftBodyAux(a, typ, body, newSymNode(dest).newDeref, newSymNode(src))
   # recursion is handled explicitly, do not register the type based operation
   # before 'liftBodyAux':
-  case kind
-  of attachedAsgn: typ.assignment = result
-  of attachedSink: typ.sink = result
-  of attachedDeepCopy: typ.deepCopy = result
-  of attachedDestructor: typ.destructor = result
+  if c.config.selectedGC == gcDestructors and
+      typ.kind in {tySequence, tyString} and body.len == 0:
+    discard "do not cache it yet"
+  else:
+    case kind
+    of attachedAsgn: typ.assignment = result
+    of attachedSink: typ.sink = result
+    of attachedDeepCopy: typ.deepCopy = result
+    of attachedDestructor: typ.destructor = result
 
   var n = newNodeI(nkProcDef, info, bodyPos+1)
   for i in 0 ..< n.len: n.sons[i] = newNodeI(nkEmpty, info)
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index bec4a59a4..735c6f6b1 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -100,8 +100,8 @@ type
     compilesContextId*: int    # > 0 if we are in a ``compiles`` magic
     compilesContextIdGenerator*: int
     inGenericInst*: int        # > 0 if we are instantiating a generic
-    converters*: TSymSeq       # sequence of converters
-    patterns*: TSymSeq         # sequence of pattern matchers
+    converters*: seq[PSym]
+    patterns*: seq[PSym]       # sequence of pattern matchers
     optionStack*: seq[POptionEntry]
     symMapping*: TIdTable      # every gensym'ed symbol needs to be mapped
                                # to some new symbol in a generic instantiation
@@ -239,7 +239,7 @@ proc newContext*(graph: ModuleGraph; module: PSym): PContext =
   result.typesWithOps = @[]
   result.features = graph.config.features
 
-proc inclSym(sq: var TSymSeq, s: PSym) =
+proc inclSym(sq: var seq[PSym], s: PSym) =
   var L = len(sq)
   for i in countup(0, L - 1):
     if sq[i].id == s.id: return
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 08917cb29..ddec457a1 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1083,6 +1083,8 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode =
       # XXX see the hack in sigmatch.nim ...
       return s.typ.n
     elif sfGenSym in s.flags:
+      # the owner should have been set by now by addParamOrResult
+      internalAssert c.config, s.owner != nil
       if c.p.wasForwarded:
         # gensym'ed parameters that nevertheless have been forward declared
         # need a special fixup:
@@ -2289,6 +2291,8 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode =
     var labl = newSymG(skLabel, n.sons[0], c)
     if sfGenSym notin labl.flags:
       addDecl(c, labl)
+    elif labl.owner == nil:
+      labl.owner = c.p.owner
     n.sons[0] = newSymNode(labl, n.sons[0].info)
     suggestSym(c.config, n.sons[0].info, labl, c.graph.usageSym)
     styleCheckDef(c.config, labl)
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 5ec702257..9e7ed5cee 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -15,6 +15,8 @@ import
   nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
   commands, magicsys, modulegraphs, strtabs, lineinfos
 
+import system/helpers2
+
 proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
   case skipTypes(n.typ, abstractVarRange).kind
   of tyInt:
@@ -489,11 +491,11 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
       result = x.sons[int(idx)]
       if result.kind == nkExprColonExpr: result = result.sons[1]
     else:
-      localError(g.config, n.info, "index out of bounds: " & $n)
+      localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)+1) & $n)
   of nkBracket:
     idx = idx - firstOrd(g.config, x.typ)
     if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
-    else: localError(g.config, n.info, "index out of bounds: " & $n)
+    else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len+1) & $n)
   of nkStrLit..nkTripleStrLit:
     result = newNodeIT(nkCharLit, x.info, n.typ)
     if idx >= 0 and idx < len(x.strVal):
@@ -501,7 +503,7 @@ proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
     elif idx == len(x.strVal) and optLaxStrings in g.config.options:
       discard
     else:
-      localError(g.config, n.info, "index out of bounds: " & $n)
+      localError(g.config, n.info, formatErrorIndexBound(idx, len(x.strVal)-1) & $n)
   else: discard
 
 proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
@@ -626,6 +628,14 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
         # It doesn't matter if the argument is const or not for mLengthArray.
         # This fixes bug #544.
         result = newIntNodeT(lengthOrd(g.config, n.sons[1].typ), n, g)
+      of mSizeOf:
+        let size = getSize(g.config, n[1].typ)
+        if size >= 0:
+          result = newIntNode(nkIntLit, size)
+          result.info = n.info
+          result.typ = getSysType(g, n.info, tyInt)
+        else:
+          result = nil
       of mAstToStr:
         result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g)
       of mConStrStr:
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 17f61c7dd..09991048e 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -116,7 +116,7 @@ proc freshGenSyms(n: PNode, owner, orig: PSym, symMap: var TIdTable) =
     var x = PSym(idTableGet(symMap, s))
     if x != nil:
       n.sym = x
-    elif s.owner.kind == skPackage:
+    elif s.owner == nil or s.owner.kind == skPackage:
       #echo "copied this ", s.name.s
       x = copySym(s)
       x.owner = owner
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index df2c084a1..7e61854b8 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -321,8 +321,6 @@ proc semOf(c: PContext, n: PNode): PNode =
 proc magicsAfterOverloadResolution(c: PContext, n: PNode,
                                    flags: TExprFlags): PNode =
   ## This is the preferred code point to implement magics.
-  ## This function basically works like a macro, with the difference
-  ## that it is implemented in the compiler and not on the nimvm.
   ## ``c`` the current module, a symbol table to a very good approximation
   ## ``n`` the ast like it would be passed to a real macro
   ## ``flags`` Some flags for more contextual information on how the
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 48aa75528..aec03b492 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -497,8 +497,10 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
       var v = semIdentDef(c, a.sons[j], symkind)
       styleCheckDef(c.config, v)
       onDef(a[j].info, v)
-      if sfGenSym notin v.flags and not isDiscardUnderscore(v):
-        addInterfaceDecl(c, v)
+      if sfGenSym notin v.flags:
+        if not isDiscardUnderscore(v): addInterfaceDecl(c, v)
+      else:
+        if v.owner == nil: v.owner = c.p.owner
       when oKeepVariableNames:
         if c.inUnrolledContext > 0: v.flags.incl(sfShadowed)
         else:
@@ -573,6 +575,7 @@ proc semConst(c: PContext, n: PNode): PNode =
     setVarType(c, v, typ)
     v.ast = def               # no need to copy
     if sfGenSym notin v.flags: addInterfaceDecl(c, v)
+    elif v.owner == nil: v.owner = getCurrOwner(c)
     var b = newNodeI(nkConstDef, a.info)
     if importantComments(c.config): b.comment = a.comment
     addSon(b, newSymNode(v))
@@ -616,6 +619,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
       v.typ = iterBase
       n.sons[0] = newSymNode(v)
       if sfGenSym notin v.flags: addForVarDecl(c, v)
+      elif v.owner == nil: v.owner = getCurrOwner(c)
     else:
       localError(c.config, n.info, errWrongNumberOfVariables)
   elif length-2 != sonsLen(iter):
@@ -626,8 +630,9 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
       if getCurrOwner(c).kind == skModule: incl(v.flags, sfGlobal)
       v.typ = iter.sons[i]
       n.sons[i] = newSymNode(v)
-      if sfGenSym notin v.flags and not isDiscardUnderscore(v):
-        addForVarDecl(c, v)
+      if sfGenSym notin v.flags:
+        if not isDiscardUnderscore(v): addForVarDecl(c, v)
+      elif v.owner == nil: v.owner = getCurrOwner(c)
   inc(c.p.nestedLoopCounter)
   openScope(c)
   n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags)
@@ -922,6 +927,7 @@ proc typeSectionLeftSidePass(c: PContext, n: PNode) =
             s = typsym
       # add it here, so that recursive types are possible:
       if sfGenSym notin s.flags: addInterfaceDecl(c, s)
+      elif s.owner == nil: s.owner = getCurrOwner(c)
 
     if name.kind == nkPragmaExpr:
       a.sons[0].sons[0] = newSymNode(s)
@@ -1620,7 +1626,8 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
     else:
       s.typ.callConv = lastOptionEntry(c).defaultCC
     # add it here, so that recursive procs are possible:
-    if sfGenSym in s.flags: discard
+    if sfGenSym in s.flags:
+      if s.owner == nil: s.owner = getCurrOwner(c)
     elif kind in OverloadableSyms:
       if not typeIsDetermined:
         addInterfaceOverloadableSymAt(c, oldScope, s)
@@ -1836,35 +1843,49 @@ proc semMacroDef(c: PContext, n: PNode): PNode =
   if n.sons[bodyPos].kind == nkEmpty:
     localError(c.config, n.info, errImplOfXexpected % s.name.s)
 
+proc incMod(c: PContext, n: PNode, it: PNode, includeStmtResult: PNode) =
+  var f = checkModuleName(c.config, it)
+  if f != InvalidFileIDX:
+    if containsOrIncl(c.includedFiles, f.int):
+      localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f))
+    else:
+      addSon(includeStmtResult, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {}))
+      excl(c.includedFiles, f.int)
+
 proc evalInclude(c: PContext, n: PNode): PNode =
   result = newNodeI(nkStmtList, n.info)
   addSon(result, n)
   for i in countup(0, sonsLen(n) - 1):
-    var f = checkModuleName(c.config, n.sons[i])
-    if f != InvalidFileIDX:
-      if containsOrIncl(c.includedFiles, f.int):
-        localError(c.config, n.info, errRecursiveDependencyX % toFilename(c.config, f))
-      else:
-        addSon(result, semStmt(c, c.graph.includeFileCallback(c.graph, c.module, f), {}))
-        excl(c.includedFiles, f.int)
+    var imp: PNode
+    let it = n.sons[i]
+    if it.kind == nkInfix and it.len == 3 and it[2].kind == nkBracket:
+      let sep = it[0]
+      let dir = it[1]
+      imp = newNodeI(nkInfix, it.info)
+      imp.add sep
+      imp.add dir
+      imp.add sep # dummy entry, replaced in the loop
+      for x in it[2]:
+        imp.sons[2] = x
+        incMod(c, n, imp, result)
+    else:
+      incMod(c, n, it, result)
 
 proc setLine(n: PNode, info: TLineInfo) =
   for i in 0 ..< safeLen(n): setLine(n.sons[i], info)
   n.info = info
 
 proc semPragmaBlock(c: PContext, n: PNode): PNode =
+  checkSonsLen(n, 2, c.config)
   let pragmaList = n.sons[0]
   pragma(c, nil, pragmaList, exprPragmas)
-  result = semExpr(c, n.sons[1])
-  n.sons[1] = result
+  n[1] = semExpr(c, n[1])
+  result = n
+  result.typ = n[1].typ
   for i in 0 ..< pragmaList.len:
     case whichPragma(pragmaList.sons[i])
     of wLine: setLine(result, pragmaList.sons[i].info)
-    of wLocks, wGcSafe, wNosideeffect:
-      result = n
-      result.typ = n.sons[1].typ
-    of wNoRewrite:
-      incl(result.flags, nfNoRewrite)
+    of wNoRewrite: incl(result.flags, nfNoRewrite)
     else: discard
 
 proc semStaticStmt(c: PContext, n: PNode): PNode =
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index a011a8fc8..f4ff97ba4 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -90,6 +90,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
         if sonsLen(v) == 2:
           strVal = v.sons[1] # second tuple part is the string value
           if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
+            if not isOrdinalType(v.sons[0].typ):
+              localError(c.config, v.sons[0].info, errOrdinalTypeExpected)
             x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
           else:
             localError(c.config, strVal.info, errStringLiteralExpected)
@@ -99,6 +101,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
         strVal = v
         x = counter
       else:
+        if not isOrdinalType(v.typ):
+          localError(c.config, v.info, errOrdinalTypeExpected)
         x = getOrdValue(v)
       if i != 1:
         if x != counter: incl(result.flags, tfEnumHasHoles)
@@ -821,7 +825,11 @@ proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
       a.typ = nn.typ
       addDecl(c, a)
   else:
-    if sfGenSym notin param.flags: addDecl(c, param)
+    if sfGenSym in param.flags:
+      # bug #XXX, fix the gensym'ed parameters owner:
+      if param.owner == nil:
+        param.owner = getCurrOwner(c)
+    else: addDecl(c, param)
 
 template shouldHaveMeta(t) =
   internalAssert c.config, tfHasMeta in t.flags
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 7e7ec8903..c8784c3e7 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -413,26 +413,12 @@ proc recSetFlagIsRef(arg: PNode) =
     arg.sons[i].recSetFlagIsRef
 
 proc setLenSeq(c: PCtx; node: PNode; newLen: int; info: TLineInfo) =
-  # FIXME: this doesn't attempt to solve incomplete
-  # support of tyPtr, tyRef in VM.
   let typ = node.typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
-  let typeEntry = typ.sons[0].skipTypes(abstractInst+{tyRange}-{tyTypeDesc})
-  let typeKind = case typeEntry.kind
-                 of tyUInt..tyUInt64: nkUIntLit
-                 of tyRange, tyEnum, tyBool, tyChar, tyInt..tyInt64: nkIntLit
-                 of tyFloat..tyFloat128: nkFloatLit
-                 of tyString: nkStrLit
-                 of tyObject: nkObjConstr
-                 of tySequence: nkNilLit
-                 of tyProc, tyTuple: nkTupleConstr
-                 else: nkEmpty
-
   let oldLen = node.len
   setLen(node.sons, newLen)
   if oldLen < newLen:
-    # TODO: This is still not correct for tyPtr, tyRef default value
     for i in oldLen ..< newLen:
-      node.sons[i] = newNodeI(typeKind, info)
+      node.sons[i] = getNullValue(typ.sons[0], info, c.config)
 
 const
   errIndexOutOfBounds = "index out of bounds"
@@ -458,7 +444,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     #if c.traceActive:
     when traceCode:
       echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra, " rb ", instr.regB, " rc ", instr.regC
-    #  message(c.config, c.debug[pc], warnUser, "Trace")
+      # message(c.config, c.debug[pc], warnUser, "Trace")
 
     case instr.opcode
     of opcEof: return regs[ra]
diff --git a/doc/advopt.txt b/doc/advopt.txt
index 7cd72f6c3..60cae7fd0 100644
--- a/doc/advopt.txt
+++ b/doc/advopt.txt
@@ -11,8 +11,9 @@ Advanced commands:
   //buildIndex              build an index for the whole documentation
   //run                     run the project (with Tiny C backend; buggy!)
   //genDepend               generate a DOT file containing the
-                            module dependency graph
+                          module dependency graph
   //dump                    dump all defined conditionals and search paths
+                            see also: --dump.format:json (useful with: ` | jq`)
   //check                   checks the project for syntax and semantic
 
 Advanced options:
@@ -103,6 +104,7 @@ Advanced options:
                             value = number of processors (0 for auto-detect)
   --incremental:on|off      only recompile the changed modules (experimental!)
   --verbosity:0|1|2|3       set Nim's verbosity level (1 is default)
+  --errorMax:N              stop compilation after N errors; 0 means unlimited
   --experimental:$1
                             enable experimental language feature
   -v, --version             show detailed version information
diff --git a/doc/contributing.rst b/doc/contributing.rst
index a2c95db74..e3ab697d3 100644
--- a/doc/contributing.rst
+++ b/doc/contributing.rst
@@ -263,17 +263,8 @@ Take advantage of no implicit bool conversion
   doAssert isValid() == true
   doAssert isValid() # preferred
 
-.. _immediately_invoked_lambdas:
-Immediately invoked lambdas (https://en.wikipedia.org/wiki/Immediately-invoked_function_expression)
-
-.. code-block:: nim
-
-  let a = (proc (): auto = getFoo())()
-  let a = block:  # preferred
-    getFoo()
-
 .. _design_for_mcs:
-Design with method call syntax (UFCS in other languages) chaining in mind
+Design with method call syntax chaining in mind
 
 .. code-block:: nim
 
diff --git a/doc/lib.rst b/doc/lib.rst
index 46e1f9d19..c0119d36d 100644
--- a/doc/lib.rst
+++ b/doc/lib.rst
@@ -154,6 +154,10 @@ String handling
 * `std/wordwrap <wordwrap.html>`_
   This module contains an algorithm to wordwrap a Unicode string.
 
+* `std/diff <diff.html>`_
+  This module contains an algorithm to compute the famous "diff"
+  of two texts by line.
+
 
 Generic Operating System Services
 ---------------------------------
diff --git a/koch.nim b/koch.nim
index 9a8d38a79..3f528a1b2 100644
--- a/koch.nim
+++ b/koch.nim
@@ -79,6 +79,7 @@ template withDir(dir, body) =
   finally:
     setCurrentdir(old)
 
+let origDir = getCurrentDir()
 setCurrentDir(getAppDir())
 
 proc tryExec(cmd: string): bool =
@@ -378,9 +379,7 @@ proc winRelease*() =
 template `|`(a, b): string = (if a.len > 0: a else: b)
 
 proc tests(args: string) =
-  # we compile the tester with taintMode:on to have a basic
-  # taint mode test :-)
-  nimexec "cc --taintMode:on --opt:speed testament/tester"
+  nimexec "cc --opt:speed testament/tester"
   # Since tests take a long time (on my machine), and we want to defy Murhpys
   # law - lets make sure the compiler really is freshly compiled!
   nimexec "c --lib:lib -d:release --opt:speed compiler/nim.nim"
@@ -415,6 +414,7 @@ proc temp(args: string) =
   let nimexec = findNim()
   exec(nimexec & " c -d:debug --debugger:native " & bootArgs & " " & (d / "compiler" / "nim"), 125)
   copyExe(output, finalDest)
+  setCurrentDir(origDir)
   if programArgs.len > 0: exec(finalDest & " " & programArgs)
 
 proc xtemp(cmd: string) =
diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim
index 58594f054..94dd89db5 100644
--- a/lib/impure/nre.nim
+++ b/lib/impure/nre.nim
@@ -65,7 +65,7 @@ runnableExamples:
   let hasVowel = firstVowel.isSome()
   if hasVowel:
     let matchBounds = firstVowel.get().captureBounds[-1]
-    doAssert matchBounds.get().a == 1
+    doAssert matchBounds.a == 1
 
 
 # Type definitions {{{
@@ -167,14 +167,15 @@ type
     ##     -  ``"abc".match(re"(?<letter>\w)").get.captures["letter"] == "a"``
     ##     -  ``"abc".match(re"(\w)\w").get.captures[-1] == "ab"``
     ##
-    ## ``captureBounds[]: Option[HSlice[int, int]]``
+    ## ``captureBounds[]: HSlice[int, int]``
     ##     gets the bounds of the given capture according to the same rules as
     ##     the above. If the capture is not filled, then ``None`` is returned.
     ##     The bounds are both inclusive.
     ##
-    ##     -  ``"abc".match(re"(\w)").get.captureBounds[0].get == 0 .. 0``
-    ##     -  ``"abc".match(re"").get.captureBounds[-1].get == 0 .. -1``
-    ##     -  ``"abc".match(re"abc").get.captureBounds[-1].get == 0 .. 2``
+    ##     -  ``"abc".match(re"(\w)").get.captureBounds[0] == 0 .. 0``
+    ##     -  ``0 in "abc".match(re"(\w)").get.captureBounds == true``
+    ##     -  ``"abc".match(re"").get.captureBounds[-1] == 0 .. -1``
+    ##     -  ``"abc".match(re"abc").get.captureBounds[-1] == 0 .. 2``
     ##
     ## ``match: string``
     ##     the full text of the match.
@@ -227,9 +228,10 @@ runnableExamples:
     doAssert "abc".match(re"(?<letter>\w)").get.captures["letter"] == "a"
     doAssert "abc".match(re"(\w)\w").get.captures[-1] == "ab"
 
-    doAssert "abc".match(re"(\w)").get.captureBounds[0].get == 0 .. 0
-    doAssert "abc".match(re"").get.captureBounds[-1].get == 0 .. -1
-    doAssert "abc".match(re"abc").get.captureBounds[-1].get == 0 .. 2
+    doAssert "abc".match(re"(\w)").get.captureBounds[0] == 0 .. 0
+    doAssert 0 in "abc".match(re"(\w)").get.captureBounds == true
+    doAssert "abc".match(re"").get.captureBounds[-1] == 0 .. -1
+    doAssert "abc".match(re"abc").get.captureBounds[-1] == 0 .. 2
 # }}}
 
 proc getinfo[T](pattern: Regex, opt: cint): T =
@@ -269,78 +271,99 @@ proc matchesCrLf(pattern: Regex): bool =
 # }}}
 
 # Capture accessors {{{
-proc captureBounds*(pattern: RegexMatch): CaptureBounds = return CaptureBounds(pattern)
+func captureBounds*(pattern: RegexMatch): CaptureBounds = return CaptureBounds(pattern)
 
-proc captures*(pattern: RegexMatch): Captures = return Captures(pattern)
+func captures*(pattern: RegexMatch): Captures = return Captures(pattern)
 
-proc `[]`*(pattern: CaptureBounds, i: int): Option[HSlice[int, int]] =
+func contains*(pattern: CaptureBounds, i: int): bool =
   let pattern = RegexMatch(pattern)
-  if pattern.pcreMatchBounds[i + 1].a != -1:
-    let bounds = pattern.pcreMatchBounds[i + 1]
-    return some(int(bounds.a) .. int(bounds.b-1))
-  else:
-    return none(HSlice[int, int])
+  pattern.pcreMatchBounds[i + 1].a != -1
+
+func contains*(pattern: Captures, i: int): bool =
+  i in CaptureBounds(pattern)
 
-proc `[]`*(pattern: Captures, i: int): string =
+func `[]`*(pattern: CaptureBounds, i: int): HSlice[int, int] =
+  let pattern = RegexMatch(pattern)
+  if not (i in pattern.captureBounds):
+    raise newException(IndexError, "Group '" & $i & "' was not captured")
+
+  let bounds = pattern.pcreMatchBounds[i + 1]
+  int(bounds.a)..int(bounds.b-1)
+
+func `[]`*(pattern: Captures, i: int): string =
   let pattern = RegexMatch(pattern)
   let bounds = pattern.captureBounds[i]
 
-  if bounds.isSome:
-    let bounds = bounds.get
-    return pattern.str.substr(bounds.a, bounds.b)
-  else:
-    return ""
+  pattern.str.substr(bounds.a, bounds.b)
 
-proc match*(pattern: RegexMatch): string =
+func match*(pattern: RegexMatch): string =
   return pattern.captures[-1]
 
-proc matchBounds*(pattern: RegexMatch): HSlice[int, int] =
-  return pattern.captureBounds[-1].get
+func matchBounds*(pattern: RegexMatch): HSlice[int, int] =
+  return pattern.captureBounds[-1]
+
+func contains*(pattern: CaptureBounds, name: string): bool =
+  let pattern = RegexMatch(pattern)
+  let nameToId = pattern.pattern.captureNameToId
+  if not (name in nameToId):
+      return false
+  nameToId[name] in pattern.captureBounds
+
+func contains*(pattern: Captures, name: string): bool =
+  name in CaptureBounds(pattern)
 
-proc `[]`*(pattern: CaptureBounds, name: string): Option[HSlice[int, int]] =
+func checkNamedCaptured(pattern: RegexMatch, name: string): void =
+  if not (name in pattern.captureBounds):
+    raise newException(KeyError, "Group '" & name & "' was not captured")
+
+func `[]`*(pattern: CaptureBounds, name: string): HSlice[int, int] =
   let pattern = RegexMatch(pattern)
-  return pattern.captureBounds[pattern.pattern.captureNameToId.fget(name)]
+  checkNamedCaptured(pattern, name)
+  pattern.captureBounds[pattern.pattern.captureNameToId[name]]
 
-proc `[]`*(pattern: Captures, name: string): string =
+func `[]`*(pattern: Captures, name: string): string =
   let pattern = RegexMatch(pattern)
-  return pattern.captures[pattern.pattern.captureNameToId.fget(name)]
+  checkNamedCaptured(pattern, name)
+  return pattern.captures[pattern.pattern.captureNameToId[name]]
 
-template toTableImpl(cond: untyped) {.dirty.} =
+template toTableImpl() {.dirty.} =
   for key in RegexMatch(pattern).pattern.captureNameId.keys:
-    let nextVal = pattern[key]
-    if cond:
-      result[key] = default
-    else:
-      result[key] = nextVal
+    if key in pattern:
+        result[key] = pattern[key]
 
-proc toTable*(pattern: Captures, default: string = ""): Table[string, string] =
+func toTable*(pattern: Captures): Table[string, string] =
   result = initTable[string, string]()
-  toTableImpl(nextVal.len == 0)
+  toTableImpl()
 
-proc toTable*(pattern: CaptureBounds, default = none(HSlice[int, int])):
-    Table[string, Option[HSlice[int, int]]] =
-  result = initTable[string, Option[HSlice[int, int]]]()
-  toTableImpl(nextVal.isNone)
+func toTable*(pattern: CaptureBounds): Table[string, HSlice[int, int]] =
+  result = initTable[string, HSlice[int, int]]()
+  toTableImpl()
 
-template itemsImpl(cond: untyped) {.dirty.} =
+template itemsImpl() {.dirty.} =
   for i in 0 ..< RegexMatch(pattern).pattern.captureCount:
-    let nextVal = pattern[i]
     # done in this roundabout way to avoid multiple yields (potential code
     # bloat)
-    let nextYieldVal = if cond: default else: nextVal
-    yield nextYieldVal
+    let nextYieldVal = if i in pattern:
+      some(pattern[i])
+    else:
+      default
 
+    yield nextYieldVal
 
-iterator items*(pattern: CaptureBounds, default = none(HSlice[int, int])): Option[HSlice[int, int]] =
-  itemsImpl(nextVal.isNone)
+iterator items*(pattern: CaptureBounds,
+                default = none(HSlice[int, int])): Option[HSlice[int, int]] =
+  itemsImpl()
 
-iterator items*(pattern: Captures, default: string = ""): string =
-  itemsImpl(nextVal.len == 0)
+iterator items*(pattern: Captures,
+                default: Option[string] = none(string)): Option[string] =
+  itemsImpl()
 
-proc toSeq*(pattern: CaptureBounds, default = none(HSlice[int, int])): seq[Option[HSlice[int, int]]] =
+proc toSeq*(pattern: CaptureBounds,
+            default = none(HSlice[int, int])): seq[Option[HSlice[int, int]]] =
   accumulateResult(pattern.items(default))
 
-proc toSeq*(pattern: Captures, default: string = ""): seq[string] =
+proc toSeq*(pattern: Captures,
+            default: Option[string] = none(string)): seq[Option[string]] =
   accumulateResult(pattern.items(default))
 
 proc `$`*(pattern: RegexMatch): string =
@@ -652,7 +675,8 @@ proc split*(str: string, pattern: Regex, maxSplit = -1, start = 0): seq[string]
 
     for cap in match.captures:
       # if there are captures, include them in the result
-      result.add(cap)
+      if cap.isSome:
+        result.add(cap.get)
 
     if splits == maxSplit - 1:
       break
@@ -706,7 +730,8 @@ proc replace*(str: string, pattern: Regex,
   ## -  ``$#`` - first capture
   ## -  ``$0`` - full match
   ##
-  ## If a given capture is missing, a ``ValueError`` exception is thrown.
+  ## If a given capture is missing, ``IndexError`` thrown for un-named captures
+  ## and ``KeyError`` for named captures.
   replaceImpl(str, pattern, subproc(match))
 
 proc replace*(str: string, pattern: Regex,
diff --git a/lib/impure/nre/private/util.nim b/lib/impure/nre/private/util.nim
index a3ae84007..f7d8b1d60 100644
--- a/lib/impure/nre/private/util.nim
+++ b/lib/impure/nre/private/util.nim
@@ -1,17 +1,9 @@
 ## INTERNAL FILE FOR USE ONLY BY nre.nim.
 import tables
 
-proc fget*[K, V](self: Table[K, V], key: K): V =
-  if self.hasKey(key):
-    return self[key]
-  else:
-    raise newException(KeyError, "Key does not exist in table: " & $key)
-
 const Ident = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'}
 const StartIdent = Ident - {'0'..'9'}
 
-template checkNil(arg: string): string = arg
-
 template formatStr*(howExpr, namegetter, idgetter): untyped =
   let how = howExpr
   var val = newStringOfCap(how.len)
@@ -28,7 +20,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped =
         i += 2
       elif how[i + 1] == '#':
         var id {.inject.} = lastNum
-        val.add(checkNil(idgetter))
+        val.add(idgetter)
         lastNum += 1
         i += 2
       elif how[i + 1] in {'0'..'9'}:
@@ -37,7 +29,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped =
         while i < how.len and how[i] in {'0'..'9'}:
           id += (id * 10) + (ord(how[i]) - ord('0'))
           i += 1
-        val.add(checkNil(idgetter))
+        val.add(idgetter)
         lastNum = id + 1
       elif how[i + 1] in StartIdent:
         i += 1
@@ -45,7 +37,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped =
         while i < how.len and how[i] in Ident:
           name.add(how[i])
           i += 1
-        val.add(checkNil(namegetter))
+        val.add(namegetter)
       elif how[i + 1] == '{':
         i += 2
         var name {.inject.} = ""
@@ -53,7 +45,7 @@ template formatStr*(howExpr, namegetter, idgetter): untyped =
           name.add(how[i])
           i += 1
         i += 1
-        val.add(checkNil(namegetter))
+        val.add(namegetter)
       else:
         raise newException(Exception, "Syntax error in format string at " & $i)
   val
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index aef4f1ce6..36319a317 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -1513,8 +1513,217 @@ proc poll*(timeout = 500) =
   ## `epoll`:idx: or `kqueue`:idx: primitive only once.
   discard runOnce(timeout)
 
-# Common procedures between current and upcoming asyncdispatch
-include includes/asynccommon
+template createAsyncNativeSocketImpl(domain, sockType, protocol) =
+  let handle = newNativeSocket(domain, sockType, protocol)
+  if handle == osInvalidSocket:
+    return osInvalidSocket.AsyncFD
+  handle.setBlocking(false)
+  when defined(macosx) and not defined(nimdoc):
+    handle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
+  result = handle.AsyncFD
+  register(result)
+
+proc createAsyncNativeSocket*(domain: cint, sockType: cint,
+                           protocol: cint): AsyncFD =
+  createAsyncNativeSocketImpl(domain, sockType, protocol)
+
+proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
+                           sockType: SockType = SOCK_STREAM,
+                           protocol: Protocol = IPPROTO_TCP): AsyncFD =
+  createAsyncNativeSocketImpl(domain, sockType, protocol)
+
+proc newAsyncNativeSocket*(domain: cint, sockType: cint,
+                           protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} =
+  createAsyncNativeSocketImpl(domain, sockType, protocol)
+
+proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
+                           sockType: SockType = SOCK_STREAM,
+                           protocol: Protocol = IPPROTO_TCP): AsyncFD
+                           {.deprecated: "use createAsyncNativeSocket instead".} =
+  createAsyncNativeSocketImpl(domain, sockType, protocol)
+
+when defined(windows) or defined(nimdoc):
+  proc bindToDomain(handle: SocketHandle, domain: Domain) =
+    # Extracted into a separate proc, because connect() on Windows requires
+    # the socket to be initially bound.
+    template doBind(saddr) =
+      if bindAddr(handle, cast[ptr SockAddr](addr(saddr)),
+                  sizeof(saddr).SockLen) < 0'i32:
+        raiseOSError(osLastError())
+
+    if domain == Domain.AF_INET6:
+      var saddr: Sockaddr_in6
+      saddr.sin6_family = uint16(toInt(domain))
+      doBind(saddr)
+    else:
+      var saddr: Sockaddr_in
+      saddr.sin_family = uint16(toInt(domain))
+      doBind(saddr)
+
+  proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] =
+    let retFuture = newFuture[void]("doConnect")
+    result = retFuture
+
+    var ol = PCustomOverlapped()
+    GC_ref(ol)
+    ol.data = CompletionData(fd: socket, cb:
+      proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
+        if not retFuture.finished:
+          if errcode == OSErrorCode(-1):
+            retFuture.complete()
+          else:
+            retFuture.fail(newException(OSError, osErrorMsg(errcode)))
+    )
+
+    let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr,
+                        cint(addrInfo.ai_addrlen), nil, 0, nil,
+                        cast[POVERLAPPED](ol))
+    if ret:
+      # Request to connect completed immediately.
+      retFuture.complete()
+      # We don't deallocate ``ol`` here because even though this completed
+      # immediately poll will still be notified about its completion and it
+      # will free ``ol``.
+    else:
+      let lastError = osLastError()
+      if lastError.int32 != ERROR_IO_PENDING:
+        # With ERROR_IO_PENDING ``ol`` will be deallocated in ``poll``,
+        # and the future will be completed/failed there, too.
+        GC_unref(ol)
+        retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+else:
+  proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] =
+    let retFuture = newFuture[void]("doConnect")
+    result = retFuture
+
+    proc cb(fd: AsyncFD): bool =
+      let ret = SocketHandle(fd).getSockOptInt(
+        cint(SOL_SOCKET), cint(SO_ERROR))
+      if ret == 0:
+        # We have connected.
+        retFuture.complete()
+        return true
+      elif ret == EINTR:
+        # interrupted, keep waiting
+        return false
+      else:
+        retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret))))
+        return true
+
+    let ret = connect(socket.SocketHandle,
+                      addrInfo.ai_addr,
+                      addrInfo.ai_addrlen.Socklen)
+    if ret == 0:
+      # Request to connect completed immediately.
+      retFuture.complete()
+    else:
+      let lastError = osLastError()
+      if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
+        addWrite(socket, cb)
+      else:
+        retFuture.fail(newException(OSError, osErrorMsg(lastError)))
+
+template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped,
+                           protocol: Protocol = IPPROTO_RAW) =
+  ## Iterates through the AddrInfo linked list asynchronously
+  ## until the connection can be established.
+  const shouldCreateFd = not declared(fd)
+
+  when shouldCreateFd:
+    let sockType = protocol.toSockType()
+
+    var fdPerDomain: array[low(Domain).ord..high(Domain).ord, AsyncFD]
+    for i in low(fdPerDomain)..high(fdPerDomain):
+      fdPerDomain[i] = osInvalidSocket.AsyncFD
+    template closeUnusedFds(domainToKeep = -1) {.dirty.} =
+      for i, fd in fdPerDomain:
+        if fd != osInvalidSocket.AsyncFD and i != domainToKeep:
+          fd.closeSocket()
+
+  var lastException: ref Exception
+  var curAddrInfo = addrInfo
+  var domain: Domain
+  when shouldCreateFd:
+    var curFd: AsyncFD
+  else:
+    var curFd = fd
+  proc tryNextAddrInfo(fut: Future[void]) {.gcsafe.} =
+    if fut == nil or fut.failed:
+      if fut != nil:
+        lastException = fut.readError()
+
+      while curAddrInfo != nil:
+        let domainOpt = curAddrInfo.ai_family.toKnownDomain()
+        if domainOpt.isSome:
+          domain = domainOpt.unsafeGet()
+          break
+        curAddrInfo = curAddrInfo.ai_next
+
+      if curAddrInfo == nil:
+        freeAddrInfo(addrInfo)
+        when shouldCreateFd:
+          closeUnusedFds()
+        if lastException != nil:
+          retFuture.fail(lastException)
+        else:
+          retFuture.fail(newException(
+            IOError, "Couldn't resolve address: " & address))
+        return
+
+      when shouldCreateFd:
+        curFd = fdPerDomain[ord(domain)]
+        if curFd == osInvalidSocket.AsyncFD:
+          try:
+            curFd = newAsyncNativeSocket(domain, sockType, protocol)
+          except:
+            freeAddrInfo(addrInfo)
+            closeUnusedFds()
+            raise getCurrentException()
+          when defined(windows):
+            curFd.SocketHandle.bindToDomain(domain)
+          fdPerDomain[ord(domain)] = curFd
+
+      doConnect(curFd, curAddrInfo).callback = tryNextAddrInfo
+      curAddrInfo = curAddrInfo.ai_next
+    else:
+      freeAddrInfo(addrInfo)
+      when shouldCreateFd:
+        closeUnusedFds(ord(domain))
+        retFuture.complete(curFd)
+      else:
+        retFuture.complete()
+
+  tryNextAddrInfo(nil)
+
+proc dial*(address: string, port: Port,
+           protocol: Protocol = IPPROTO_TCP): Future[AsyncFD] =
+  ## Establishes connection to the specified ``address``:``port`` pair via the
+  ## specified protocol. The procedure iterates through possible
+  ## resolutions of the ``address`` until it succeeds, meaning that it
+  ## seamlessly works with both IPv4 and IPv6.
+  ## Returns the async file descriptor, registered in the dispatcher of
+  ## the current thread, ready to send or receive data.
+  let retFuture = newFuture[AsyncFD]("dial")
+  result = retFuture
+  let sockType = protocol.toSockType()
+
+  let aiList = getAddrInfo(address, port, Domain.AF_UNSPEC, sockType, protocol)
+  asyncAddrInfoLoop(aiList, noFD, protocol)
+
+proc connect*(socket: AsyncFD, address: string, port: Port,
+              domain = Domain.AF_INET): Future[void] =
+  let retFuture = newFuture[void]("connect")
+  result = retFuture
+
+  when defined(windows):
+    verifyPresence(socket)
+  else:
+    assert getSockDomain(socket.SocketHandle) == domain
+
+  let aiList = getAddrInfo(address, port, domain)
+  when defined(windows):
+    socket.SocketHandle.bindToDomain(domain)
+  asyncAddrInfoLoop(aiList, socket)
 
 proc sleepAsync*(ms: int | float): Future[void] =
   ## Suspends the execution of the current async procedure for the next
diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim
index 0b3708a7c..15ce5d074 100644
--- a/lib/pure/collections/lists.nim
+++ b/lib/pure/collections/lists.nim
@@ -140,11 +140,26 @@ proc contains*[T](L: SomeLinkedCollection[T], value: T): bool {.inline.} =
   ## exist, true otherwise.
   result = find(L, value) != nil
 
+proc append*[T](L: var SinglyLinkedList[T],
+                n: SinglyLinkedNode[T]) {.inline.} =
+  ## appends a node `n` to `L`. Efficiency: O(1).
+  n.next = nil
+  if L.tail != nil:
+    assert(L.tail.next == nil)
+    L.tail.next = n
+  L.tail = n
+  if L.head == nil: L.head = n
+
+proc append*[T](L: var SinglyLinkedList[T], value: T) {.inline.} =
+  ## appends a value to `L`. Efficiency: O(1).
+  append(L, newSinglyLinkedNode(value))
+
 proc prepend*[T](L: var SinglyLinkedList[T],
                  n: SinglyLinkedNode[T]) {.inline.} =
   ## prepends a node to `L`. Efficiency: O(1).
   n.next = L.head
   L.head = n
+  if L.tail == nil: L.tail = n
 
 proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} =
   ## prepends a node to `L`. Efficiency: O(1).
diff --git a/lib/pure/collections/sharedstrings.nim b/lib/pure/collections/sharedstrings.nim
index 7e9de4b73..b283cd4b1 100644
--- a/lib/pure/collections/sharedstrings.nim
+++ b/lib/pure/collections/sharedstrings.nim
@@ -12,6 +12,8 @@
 type
   UncheckedCharArray = UncheckedArray[char]
 
+import system/helpers2
+
 type
   Buffer = ptr object
     refcount: int
@@ -49,11 +51,11 @@ proc len*(s: SharedString): int = s.len
 
 proc `[]`*(s: SharedString; i: Natural): char =
   if i < s.len: result = s.buffer.data[i+s.first]
-  else: raise newException(IndexError, "index out of bounds")
+  else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1))
 
 proc `[]=`*(s: var SharedString; i: Natural; value: char) =
   if i < s.len: s.buffer.data[i+s.first] = value
-  else: raise newException(IndexError, "index out of bounds")
+  else: raise newException(IndexError, formatErrorIndexBound(i, s.len-1))
 
 proc `[]`*(s: SharedString; ab: HSlice[int, int]): SharedString =
   #incRef(src.buffer)
diff --git a/lib/pure/includes/asynccommon.nim b/lib/pure/includes/asynccommon.nim
deleted file mode 100644
index 13887acc9..000000000
--- a/lib/pure/includes/asynccommon.nim
+++ /dev/null
@@ -1,211 +0,0 @@
-template createAsyncNativeSocketImpl(domain, sockType, protocol) =
-  let handle = newNativeSocket(domain, sockType, protocol)
-  if handle == osInvalidSocket:
-    return osInvalidSocket.AsyncFD
-  handle.setBlocking(false)
-  when defined(macosx) and not defined(nimdoc):
-    handle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
-  result = handle.AsyncFD
-  register(result)
-
-proc createAsyncNativeSocket*(domain: cint, sockType: cint,
-                           protocol: cint): AsyncFD =
-  createAsyncNativeSocketImpl(domain, sockType, protocol)
-
-proc createAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
-                           sockType: SockType = SOCK_STREAM,
-                           protocol: Protocol = IPPROTO_TCP): AsyncFD =
-  createAsyncNativeSocketImpl(domain, sockType, protocol)
-
-proc newAsyncNativeSocket*(domain: cint, sockType: cint,
-                           protocol: cint): AsyncFD {.deprecated: "use createAsyncNativeSocket instead".} =
-  createAsyncNativeSocketImpl(domain, sockType, protocol)
-
-proc newAsyncNativeSocket*(domain: Domain = Domain.AF_INET,
-                           sockType: SockType = SOCK_STREAM,
-                           protocol: Protocol = IPPROTO_TCP): AsyncFD
-                           {.deprecated: "use createAsyncNativeSocket instead".} =
-  createAsyncNativeSocketImpl(domain, sockType, protocol)
-
-when defined(windows) or defined(nimdoc):
-  proc bindToDomain(handle: SocketHandle, domain: Domain) =
-    # Extracted into a separate proc, because connect() on Windows requires
-    # the socket to be initially bound.
-    template doBind(saddr) =
-      if bindAddr(handle, cast[ptr SockAddr](addr(saddr)),
-                  sizeof(saddr).SockLen) < 0'i32:
-        raiseOSError(osLastError())
-
-    if domain == Domain.AF_INET6:
-      var saddr: Sockaddr_in6
-      saddr.sin6_family = uint16(toInt(domain))
-      doBind(saddr)
-    else:
-      var saddr: Sockaddr_in
-      saddr.sin_family = uint16(toInt(domain))
-      doBind(saddr)
-
-  proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] =
-    let retFuture = newFuture[void]("doConnect")
-    result = retFuture
-
-    var ol = PCustomOverlapped()
-    GC_ref(ol)
-    ol.data = CompletionData(fd: socket, cb:
-      proc (fd: AsyncFD, bytesCount: Dword, errcode: OSErrorCode) =
-        if not retFuture.finished:
-          if errcode == OSErrorCode(-1):
-            retFuture.complete()
-          else:
-            retFuture.fail(newException(OSError, osErrorMsg(errcode)))
-    )
-
-    let ret = connectEx(socket.SocketHandle, addrInfo.ai_addr,
-                        cint(addrInfo.ai_addrlen), nil, 0, nil,
-                        cast[POVERLAPPED](ol))
-    if ret:
-      # Request to connect completed immediately.
-      retFuture.complete()
-      # We don't deallocate ``ol`` here because even though this completed
-      # immediately poll will still be notified about its completion and it
-      # will free ``ol``.
-    else:
-      let lastError = osLastError()
-      if lastError.int32 != ERROR_IO_PENDING:
-        # With ERROR_IO_PENDING ``ol`` will be deallocated in ``poll``,
-        # and the future will be completed/failed there, too.
-        GC_unref(ol)
-        retFuture.fail(newException(OSError, osErrorMsg(lastError)))
-else:
-  proc doConnect(socket: AsyncFD, addrInfo: ptr AddrInfo): Future[void] =
-    let retFuture = newFuture[void]("doConnect")
-    result = retFuture
-
-    proc cb(fd: AsyncFD): bool =
-      let ret = SocketHandle(fd).getSockOptInt(
-        cint(SOL_SOCKET), cint(SO_ERROR))
-      if ret == 0:
-        # We have connected.
-        retFuture.complete()
-        return true
-      elif ret == EINTR:
-        # interrupted, keep waiting
-        return false
-      else:
-        retFuture.fail(newException(OSError, osErrorMsg(OSErrorCode(ret))))
-        return true
-
-    let ret = connect(socket.SocketHandle,
-                      addrInfo.ai_addr,
-                      addrInfo.ai_addrlen.Socklen)
-    if ret == 0:
-      # Request to connect completed immediately.
-      retFuture.complete()
-    else:
-      let lastError = osLastError()
-      if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS:
-        addWrite(socket, cb)
-      else:
-        retFuture.fail(newException(OSError, osErrorMsg(lastError)))
-
-template asyncAddrInfoLoop(addrInfo: ptr AddrInfo, fd: untyped,
-                           protocol: Protocol = IPPROTO_RAW) =
-  ## Iterates through the AddrInfo linked list asynchronously
-  ## until the connection can be established.
-  const shouldCreateFd = not declared(fd)
-
-  when shouldCreateFd:
-    let sockType = protocol.toSockType()
-
-    var fdPerDomain: array[low(Domain).ord..high(Domain).ord, AsyncFD]
-    for i in low(fdPerDomain)..high(fdPerDomain):
-      fdPerDomain[i] = osInvalidSocket.AsyncFD
-    template closeUnusedFds(domainToKeep = -1) {.dirty.} =
-      for i, fd in fdPerDomain:
-        if fd != osInvalidSocket.AsyncFD and i != domainToKeep:
-          fd.closeSocket()
-
-  var lastException: ref Exception
-  var curAddrInfo = addrInfo
-  var domain: Domain
-  when shouldCreateFd:
-    var curFd: AsyncFD
-  else:
-    var curFd = fd
-  proc tryNextAddrInfo(fut: Future[void]) {.gcsafe.} =
-    if fut == nil or fut.failed:
-      if fut != nil:
-        lastException = fut.readError()
-
-      while curAddrInfo != nil:
-        let domainOpt = curAddrInfo.ai_family.toKnownDomain()
-        if domainOpt.isSome:
-          domain = domainOpt.unsafeGet()
-          break
-        curAddrInfo = curAddrInfo.ai_next
-
-      if curAddrInfo == nil:
-        freeAddrInfo(addrInfo)
-        when shouldCreateFd:
-          closeUnusedFds()
-        if lastException != nil:
-          retFuture.fail(lastException)
-        else:
-          retFuture.fail(newException(
-            IOError, "Couldn't resolve address: " & address))
-        return
-
-      when shouldCreateFd:
-        curFd = fdPerDomain[ord(domain)]
-        if curFd == osInvalidSocket.AsyncFD:
-          try:
-            curFd = newAsyncNativeSocket(domain, sockType, protocol)
-          except:
-            freeAddrInfo(addrInfo)
-            closeUnusedFds()
-            raise getCurrentException()
-          when defined(windows):
-            curFd.SocketHandle.bindToDomain(domain)
-          fdPerDomain[ord(domain)] = curFd
-
-      doConnect(curFd, curAddrInfo).callback = tryNextAddrInfo
-      curAddrInfo = curAddrInfo.ai_next
-    else:
-      freeAddrInfo(addrInfo)
-      when shouldCreateFd:
-        closeUnusedFds(ord(domain))
-        retFuture.complete(curFd)
-      else:
-        retFuture.complete()
-
-  tryNextAddrInfo(nil)
-
-proc dial*(address: string, port: Port,
-           protocol: Protocol = IPPROTO_TCP): Future[AsyncFD] =
-  ## Establishes connection to the specified ``address``:``port`` pair via the
-  ## specified protocol. The procedure iterates through possible
-  ## resolutions of the ``address`` until it succeeds, meaning that it
-  ## seamlessly works with both IPv4 and IPv6.
-  ## Returns the async file descriptor, registered in the dispatcher of
-  ## the current thread, ready to send or receive data.
-  let retFuture = newFuture[AsyncFD]("dial")
-  result = retFuture
-  let sockType = protocol.toSockType()
-
-  let aiList = getAddrInfo(address, port, Domain.AF_UNSPEC, sockType, protocol)
-  asyncAddrInfoLoop(aiList, noFD, protocol)
-
-proc connect*(socket: AsyncFD, address: string, port: Port,
-              domain = Domain.AF_INET): Future[void] =
-  let retFuture = newFuture[void]("connect")
-  result = retFuture
-
-  when defined(windows):
-    verifyPresence(socket)
-  else:
-    assert getSockDomain(socket.SocketHandle) == domain
-
-  let aiList = getAddrInfo(address, port, domain)
-  when defined(windows):
-    socket.SocketHandle.bindToDomain(domain)
-  asyncAddrInfoLoop(aiList, socket)
diff --git a/lib/pure/includes/oserr.nim b/lib/pure/includes/oserr.nim
index 72c3f4f49..abd0bf501 100644
--- a/lib/pure/includes/oserr.nim
+++ b/lib/pure/includes/oserr.nim
@@ -59,7 +59,8 @@ proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} =
   e.errorCode = errorCode.int32
   e.msg = osErrorMsg(errorCode)
   if additionalInfo.len > 0:
-    e.msg.add  "; Additional info: "
+    if e.msg[^1] != '\n': e.msg.add '\n'
+    e.msg.add  "Additional info: "
     e.msg.addQuoted additionalInfo
   if e.msg == "":
     e.msg = "unknown OS error"
diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim
index e5345e645..810223d72 100644
--- a/lib/pure/memfiles.nim
+++ b/lib/pure/memfiles.nim
@@ -36,11 +36,12 @@ type
     size*: int       ## size of the memory mapped file
 
     when defined(windows):
-      fHandle: Handle
-      mapHandle: Handle
-      wasOpened: bool   ## only close if wasOpened
+      fHandle*: Handle     ## **Caution**: Windows specific public field to allow
+                           ## even more low level trickery.
+      mapHandle*: Handle   ## **Caution**: Windows specific public field.
+      wasOpened*: bool     ## **Caution**: Windows specific public field.
     else:
-      handle: cint
+      handle*: cint        ## **Caution**: Posix specific public field.
 
 proc mapMem*(m: var MemFile, mode: FileMode = fmRead,
              mappedSize = -1, offset = 0): pointer =
@@ -281,6 +282,35 @@ proc flush*(f: var MemFile; attempts: Natural = 3) =
       if lastErr != EBUSY.OSErrorCode:
         raiseOSError(lastErr, "error flushing mapping")
 
+when defined(posix) or defined(nimdoc):
+  proc resize*(f: var MemFile, newFileSize: int) {.raises: [IOError, OSError].} =
+    ## resize and re-map the file underlying an ``allowRemap MemFile``.
+    ## **Note**: this assumes the entire file is mapped read-write at offset zero.
+    ## Also, the value of ``.mem`` will probably change.
+    ## **Note**: This is not (yet) avaiable on Windows.
+    when defined(posix):
+      if f.handle == -1:
+        raise newException(IOError,
+                            "Cannot resize MemFile opened with allowRemap=false")
+      if ftruncate(f.handle, newFileSize) == -1:
+        raiseOSError(osLastError())
+      when defined(linux):                          #Maybe NetBSD, too?
+        #On Linux this can be over 100 times faster than a munmap,mmap cycle.
+        proc mremap(old: pointer; oldSize,newSize: csize; flags: cint): pointer {.
+          importc: "mremap", header: "<sys/mman.h>" .}
+        let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1))
+        if newAddr == cast[pointer](MAP_FAILED):
+          raiseOSError(osLastError())
+      else:
+        if munmap(f.mem, f.size) != 0:
+          raiseOSError(osLastError())
+        let newAddr = mmap(nil, newFileSize, PROT_READ or PROT_WRITE,
+                            MAP_SHARED or MAP_POPULATE, f.handle, 0)
+        if newAddr == cast[pointer](MAP_FAILED):
+          raiseOSError(osLastError())
+      f.mem = newAddr
+      f.size = newFileSize
+
 proc close*(f: var MemFile) =
   ## closes the memory mapped file `f`. All changes are written back to the
   ## file system, if `f` was opened with write access.
diff --git a/lib/pure/options.nim b/lib/pure/options.nim
index 12e38d8b5..b827e1aa3 100644
--- a/lib/pure/options.nim
+++ b/lib/pure/options.nim
@@ -39,17 +39,18 @@
 ##
 ## .. code-block:: nim
 ##
-##   try:
-##     assert("abc".find('c').get() == 2)  # Immediately extract the value
-##   except UnpackError:  # If there is no value
-##     assert false  # This will not be reached, because the value is present
-##
+##    let found = "abc".find('c')
+##    assert found.isSome and found.get() == 2
+##   
 ## The ``get`` operation demonstrated above returns the underlying value, or
-## raises ``UnpackError`` if there is no value. There is another option for
-## obtaining the value: ``unsafeGet``, but you must only use it when you are
-## absolutely sure the value is present (e.g. after checking ``isSome``). If
-## you do not care about the tiny overhead that ``get`` causes, you should
-## simply never use ``unsafeGet``.
+## raises ``UnpackError`` if there is no value. Note that ``UnpackError`` inherits
+## from ``system.Defect``, and should therefore never be catched. Instead, rely on
+## checking if the option contains a value with ``isSome`` and ``isNone``.
+##
+## There is another option for obtaining the value: ``unsafeGet``, but you must
+## only use it when you are absolutely sure the value is present (e.g. after
+## checking ``isSome``). If you do not care about the tiny overhead that ``get``
+## causes, you should simply never use ``unsafeGet``.
 ##
 ## How to deal with an absence of a value:
 ##
@@ -61,12 +62,7 @@
 ##   assert(result == none(int))
 ##   # It has no value:
 ##   assert(result.isNone)
-##
-##   try:
-##     echo result.get()
-##     assert(false)  # This will not be reached
-##   except UnpackError:  # Because an exception is raised
-##     discard
+
 import typetraits
 
 type
@@ -81,7 +77,7 @@ type
       val: T
       has: bool
 
-  UnpackError* = ref object of ValueError
+  UnpackError* = object of Defect
 
 proc some*[T](val: T): Option[T] =
   ## Returns a ``Option`` that has this value.
@@ -129,7 +125,7 @@ proc get*[T](self: Option[T]): T =
   ## Returns contents of the Option. If it is none, then an exception is
   ## thrown.
   if self.isNone:
-    raise UnpackError(msg: "Can't obtain a value from a `none`")
+    raise newException(UnpackError, "Can't obtain a value from a `none`")
   self.val
 
 proc get*[T](self: Option[T], otherwise: T): T =
@@ -143,7 +139,7 @@ proc get*[T](self: var Option[T]): var T =
   ## Returns contents of the Option. If it is none, then an exception is
   ## thrown.
   if self.isNone:
-    raise UnpackError(msg: "Can't obtain a value from a `none`")
+    raise newException(UnpackError, "Can't obtain a value from a `none`")
   return self.val
 
 proc map*[T](self: Option[T], callback: proc (input: T)) =
diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim
index d103af710..638e71f04 100644
--- a/lib/pure/subexes.nim
+++ b/lib/pure/subexes.nim
@@ -17,7 +17,7 @@
 
 from strutils import parseInt, cmpIgnoreStyle, Digits
 include "system/inclrtl"
-
+import system/helpers2
 
 proc findNormalized(x: string, inArray: openarray[string]): int =
   var i = 0
@@ -85,7 +85,7 @@ proc getFormatArg(p: var FormatParser, a: openArray[string]): int =
     result = parseInt(a[result])-1
   else:
     raiseInvalidFormat("'#', '$', number or identifier expected")
-  if result >=% a.len: raiseInvalidFormat("index out of bounds: " & $result)
+  if result >=% a.len: raiseInvalidFormat(formatErrorIndexBound(result, a.len))
   p.i = i
 
 proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) {.
diff --git a/lib/std/diff.nim b/lib/std/diff.nim
new file mode 100644
index 000000000..bffce2803
--- /dev/null
+++ b/lib/std/diff.nim
@@ -0,0 +1,387 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2018 Nim contributors
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements an algorithm to compute the
+## `diff`:idx: between two sequences of lines.
+
+# code owner: Arne Döring
+#
+# This is based on C# code written by Matthias Hertel, http://www.mathertel.de
+#
+# This Class implements the Difference Algorithm published in
+# "An O(ND) Difference Algorithm and its Variations" by Eugene Myers
+# Algorithmica Vol. 1 No. 2, 1986, p 251.
+
+import tables, strutils
+
+type
+  Item* = object    ## An Item in the list of differences.
+    startA*: int    ## Start Line number in Data A.
+    startB*: int    ## Start Line number in Data B.
+    deletedA*: int  ## Number of changes in Data A.
+    insertedB*: int ## Number of changes in Data B.
+
+  DiffData = object ## Data on one input file being compared.
+    data: seq[int] ## Buffer of numbers that will be compared.
+    modified: seq[bool] ## Array of booleans that flag for modified
+                        ## data. This is the result of the diff.
+                        ## This means deletedA in the first Data or
+                        ## inserted in the second Data.
+
+  Smsrd = object
+    x, y: int
+
+# template to avoid a seq copy. Required until ``sink`` parameters are ready.
+template newDiffData(initData: seq[int]; L: int): DiffData =
+  DiffData(
+    data: initData,
+    modified: newSeq[bool](L + 2)
+  )
+
+proc len(d: DiffData): int {.inline.} = d.data.len
+
+proc diffCodes(aText: string; h: var Table[string, int]): DiffData =
+  ## This function converts all textlines of the text into unique numbers for every unique textline
+  ## so further work can work only with simple numbers.
+  ## ``aText`` the input text
+  ## ``h`` This extern initialized hashtable is used for storing all ever used textlines.
+  ## ``trimSpace`` ignore leading and trailing space characters
+  ## Returns a array of integers.
+  var lastUsedCode = h.len
+  result.data = newSeq[int]()
+  for s in aText.splitLines:
+    if h.contains s:
+      result.data.add h[s]
+    else:
+      inc lastUsedCode
+      h[s] = lastUsedCode
+      result.data.add lastUsedCode
+  result.modified = newSeq[bool](result.data.len + 2)
+
+proc optimize(data: var DiffData) =
+  ## If a sequence of modified lines starts with a line that contains the same content
+  ## as the line that appends the changes, the difference sequence is modified so that the
+  ## appended line and not the starting line is marked as modified.
+  ## This leads to more readable diff sequences when comparing text files.
+  var startPos = 0
+  while startPos < data.len:
+    while startPos < data.len and not data.modified[startPos]:
+      inc startPos
+    var endPos = startPos
+    while endPos < data.len and data.modified[endPos]:
+      inc endPos
+
+    if endPos < data.len and data.data[startPos] == data.data[endPos]:
+      data.modified[startPos] = false
+      data.modified[endPos] = true
+    else:
+      startPos = endPos
+
+proc sms(dataA: var DiffData; lowerA, upperA: int; dataB: DiffData; lowerB, upperB: int;
+         downVector, upVector: var openArray[int]): Smsrd =
+  ## This is the algorithm to find the Shortest Middle Snake (sms).
+  ## ``dataA`` sequence A
+  ## ``lowerA`` lower bound of the actual range in dataA
+  ## ``upperA`` upper bound of the actual range in dataA (exclusive)
+  ## ``dataB`` sequence B
+  ## ``lowerB`` lower bound of the actual range in dataB
+  ## ``upperB`` upper bound of the actual range in dataB (exclusive)
+  ## ``downVector`` a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons.
+  ## ``upVector`` a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons.
+  ## Returns a MiddleSnakeData record containing x,y and u,v.
+
+  let max = dataA.len + dataB.len + 1
+
+  let downK = lowerA - lowerB # the k-line to start the forward search
+  let upK = upperA - upperB # the k-line to start the reverse search
+
+  let delta = (upperA - lowerA) - (upperB - lowerB)
+  let oddDelta = (delta and 1) != 0
+
+  # The vectors in the publication accepts negative indexes. the vectors implemented here are 0-based
+  # and are access using a specific offset: upOffset upVector and downOffset for downVector
+  let downOffset = max - downK
+  let upOffset = max - upK
+
+  let maxD = ((upperA - lowerA + upperB - lowerB) div 2) + 1
+
+  downVector[downOffset + downK + 1] = lowerA
+  upVector[upOffset + upK - 1] = upperA
+
+  for D in 0 .. maxD:
+    # Extend the forward path.
+    for k in countUp(downK - D, downK + D, 2):
+      # find the only or better starting point
+      var x: int
+      if k == downK - D:
+        x = downVector[downOffset + k + 1] # down
+      else:
+        x = downVector[downOffset + k - 1] + 1 # a step to the right
+        if k < downK + D and downVector[downOffset + k + 1] >= x:
+          x = downVector[downOffset + k + 1] # down
+
+      var y = x - k
+
+      # find the end of the furthest reaching forward D-path in diagonal k.
+      while x < upperA and y < upperB and dataA.data[x] == dataB.data[y]:
+        inc x
+        inc y
+
+      downVector[downOffset + k] = x
+
+      # overlap ?
+      if oddDelta and upK - D < k and k < upK + D:
+        if upVector[upOffset + k] <= downVector[downOffset + k]:
+          return Smsrd(x: downVector[downOffset + k],
+                       y: downVector[downOffset + k] - k)
+
+    # Extend the reverse path.
+    for k in countUp(upK - D, upK + D, 2):
+      # find the only or better starting point
+      var x: int
+      if k == upK + D:
+        x = upVector[upOffset + k - 1] # up
+      else:
+        x = upVector[upOffset + k + 1] - 1 # left
+        if k > upK - D and upVector[upOffset + k - 1] < x:
+          x = upVector[upOffset + k - 1] # up
+
+      var y = x - k
+      while x > lowerA and y > lowerB and dataA.data[x - 1] == dataB.data[y - 1]:
+        dec x
+        dec y
+
+      upVector[upOffset + k] = x
+
+      # overlap ?
+      if not oddDelta and downK-D <= k and k <= downK+D:
+        if upVector[upOffset + k] <= downVector[downOffset + k]:
+          return Smsrd(x: downVector[downOffset + k],
+                       y: downVector[downOffset + k] - k)
+
+  assert false, "the algorithm should never come here."
+
+proc lcs(dataA: var DiffData; lowerA, upperA: int; dataB: var DiffData; lowerB, upperB: int;
+         downVector, upVector: var openArray[int]) =
+  ## This is the divide-and-conquer implementation of the longes common-subsequence (lcs)
+  ## algorithm.
+  ## The published algorithm passes recursively parts of the A and B sequences.
+  ## To avoid copying these arrays the lower and upper bounds are passed while the sequences stay constant.
+  ## ``dataA`` sequence A
+  ## ``lowerA`` lower bound of the actual range in dataA
+  ## ``upperA`` upper bound of the actual range in dataA (exclusive)
+  ## ``dataB`` sequence B
+  ## ``lowerB`` lower bound of the actual range in dataB
+  ## ``upperB`` upper bound of the actual range in dataB (exclusive)
+  ## ``downVector`` a vector for the (0,0) to (x,y) search. Passed as a parameter for speed reasons.
+  ## ``upVector`` a vector for the (u,v) to (N,M) search. Passed as a parameter for speed reasons.
+
+  # make mutable copy:
+  var lowerA = lowerA
+  var lowerB = lowerB
+  var upperA = upperA
+  var upperB = upperB
+
+  # Fast walkthrough equal lines at the start
+  while lowerA < upperA and lowerB < upperB and dataA.data[lowerA] == dataB.data[lowerB]:
+    inc lowerA
+    inc lowerB
+
+  # Fast walkthrough equal lines at the end
+  while lowerA < upperA and lowerB < upperB and dataA.data[upperA - 1] == dataB.data[upperB - 1]:
+    dec upperA
+    dec upperB
+
+  if lowerA == upperA:
+    # mark as inserted lines.
+    while lowerB < upperB:
+      dataB.modified[lowerB] = true
+      inc lowerB
+
+  elif lowerB == upperB:
+    # mark as deleted lines.
+    while lowerA < upperA:
+      dataA.modified[lowerA] = true
+      inc lowerA
+
+  else:
+    # Find the middle snakea and length of an optimal path for A and B
+    let smsrd = sms(dataA, lowerA, upperA, dataB, lowerB, upperB, downVector, upVector)
+    # Debug.Write(2, "MiddleSnakeData", String.Format("{0},{1}", smsrd.x, smsrd.y))
+
+    # The path is from LowerX to (x,y) and (x,y) to UpperX
+    lcs(dataA, lowerA, smsrd.x, dataB, lowerB, smsrd.y, downVector, upVector)
+    lcs(dataA, smsrd.x, upperA, dataB, smsrd.y, upperB, downVector, upVector)  # 2002.09.20: no need for 2 points
+
+proc createDiffs(dataA, dataB: DiffData): seq[Item] =
+  ## Scan the tables of which lines are inserted and deleted,
+  ## producing an edit script in forward order.
+  var startA = 0
+  var startB = 0
+  var lineA = 0
+  var lineB = 0
+  while lineA < dataA.len or lineB < dataB.len:
+    if lineA < dataA.len and not dataA.modified[lineA] and
+       lineB < dataB.len and not dataB.modified[lineB]:
+      # equal lines
+      inc lineA
+      inc lineB
+    else:
+      # maybe deleted and/or inserted lines
+      startA = lineA
+      startB = lineB
+
+      while lineA < dataA.len and (lineB >= dataB.len or dataA.modified[lineA]):
+        inc lineA
+
+      while lineB < dataB.len and (lineA >= dataA.len or dataB.modified[lineB]):
+        inc lineB
+
+      if (startA < lineA) or (startB < lineB):
+        result.add Item(startA: startA,
+                        startB: startB,
+                        deletedA: lineA - startA,
+                        insertedB: lineB - startB)
+
+
+proc diffInt*(arrayA, arrayB: openArray[int]): seq[Item] =
+  ## Find the difference in 2 arrays of integers.
+  ## ``arrayA`` A-version of the numbers (usualy the old one)
+  ## ``arrayB`` B-version of the numbers (usualy the new one)
+  ## Returns a array of Items that describe the differences.
+
+  # The A-Version of the data (original data) to be compared.
+  var dataA = newDiffData(@arrayA, arrayA.len)
+
+  # The B-Version of the data (modified data) to be compared.
+  var dataB = newDiffData(@arrayB, arrayB.len)
+
+  let max = dataA.len + dataB.len + 1
+  ## vector for the (0,0) to (x,y) search
+  var downVector = newSeq[int](2 * max + 2)
+  ## vector for the (u,v) to (N,M) search
+  var upVector = newSeq[int](2 * max + 2)
+
+  lcs(dataA, 0, dataA.len, dataB, 0, dataB.len, downVector, upVector)
+  result = createDiffs(dataA, dataB)
+
+proc diffText*(textA, textB: string): seq[Item] =
+  ## Find the difference in 2 text documents, comparing by textlines.
+  ## The algorithm itself is comparing 2 arrays of numbers so when comparing 2 text documents
+  ## each line is converted into a (hash) number. This hash-value is computed by storing all
+  ## textlines into a common hashtable so i can find dublicates in there, and generating a
+  ## new number each time a new textline is inserted.
+  ## ``TextA`` A-version of the text (usualy the old one)
+  ## ``TextB`` B-version of the text (usualy the new one)
+  ## ``trimSpace`` When set to true, all leading and trailing whitespace characters are stripped out before the comparation is done.
+  ## ``ignoreSpace`` When set to true, all whitespace characters are converted to a single space character before the comparation is done.
+  ## ``ignoreCase`` When set to true, all characters are converted to their lowercase equivivalence before the comparation is done.
+  ## Returns a seq of Items that describe the differences.
+
+  # prepare the input-text and convert to comparable numbers.
+  var h = initTable[string, int]()  # TextA.len + TextB.len  <- probably wrong initial size
+  # The A-Version of the data (original data) to be compared.
+  var dataA = diffCodes(textA, h)
+
+  # The B-Version of the data (modified data) to be compared.
+  var dataB = diffCodes(textB, h)
+
+  h.clear # free up hashtable memory (maybe)
+
+  let max = dataA.len + dataB.len + 1
+  ## vector for the (0,0) to (x,y) search
+  var downVector = newSeq[int](2 * max + 2)
+  ## vector for the (u,v) to (N,M) search
+  var upVector = newSeq[int](2 * max + 2)
+
+  lcs(dataA, 0, dataA.len, dataB, 0, dataB.len, downVector, upVector)
+
+  optimize(dataA)
+  optimize(dataB)
+  result = createDiffs(dataA, dataB)
+
+when isMainModule:
+
+  proc testHelper(f: seq[Item]): string =
+    for it in f:
+      result.add(
+        $it.deletedA & "." & $it.insertedB & "." & $it.startA & "." & $it.startB & "*"
+      )
+
+  proc main() =
+    var a, b: string
+
+    stdout.writeLine("Diff Self Test...")
+
+    # test all changes
+    a = "a,b,c,d,e,f,g,h,i,j,k,l".replace(',', '\n')
+    b = "0,1,2,3,4,5,6,7,8,9".replace(',', '\n')
+    assert(testHelper(diffText(a, b)) ==
+      "12.10.0.0*",
+      "all-changes test failed.")
+    stdout.writeLine("all-changes test passed.")
+    # test all same
+    a = "a,b,c,d,e,f,g,h,i,j,k,l".replace(',', '\n')
+    b = a
+    assert(testHelper(diffText(a, b)) ==
+      "",
+      "all-same test failed.")
+    stdout.writeLine("all-same test passed.")
+
+    # test snake
+    a = "a,b,c,d,e,f".replace(',', '\n')
+    b = "b,c,d,e,f,x".replace(',', '\n')
+    assert(testHelper(diffText(a, b)) ==
+      "1.0.0.0*0.1.6.5*",
+      "snake test failed.")
+    stdout.writeLine("snake test passed.")
+
+    # 2002.09.20 - repro
+    a = "c1,a,c2,b,c,d,e,g,h,i,j,c3,k,l".replace(',', '\n')
+    b = "C1,a,C2,b,c,d,e,I1,e,g,h,i,j,C3,k,I2,l".replace(',', '\n')
+    assert(testHelper(diffText(a, b)) ==
+      "1.1.0.0*1.1.2.2*0.2.7.7*1.1.11.13*0.1.13.15*",
+      "repro20020920 test failed.")
+    stdout.writeLine("repro20020920 test passed.")
+
+    # 2003.02.07 - repro
+    a = "F".replace(',', '\n')
+    b = "0,F,1,2,3,4,5,6,7".replace(',', '\n')
+    assert(testHelper(diffText(a, b)) ==
+      "0.1.0.0*0.7.1.2*",
+      "repro20030207 test failed.")
+    stdout.writeLine("repro20030207 test passed.")
+
+    # Muegel - repro
+    a = "HELLO\nWORLD"
+    b = "\n\nhello\n\n\n\nworld\n"
+    assert(testHelper(diffText(a, b)) ==
+      "2.8.0.0*",
+      "repro20030409 test failed.")
+    stdout.writeLine("repro20030409 test passed.")
+
+    # test some differences
+    a = "a,b,-,c,d,e,f,f".replace(',', '\n')
+    b = "a,b,x,c,e,f".replace(',', '\n')
+    assert(testHelper(diffText(a, b)) ==
+      "1.1.2.2*1.0.4.4*1.0.7.6*",
+      "some-changes test failed.")
+    stdout.writeLine("some-changes test passed.")
+
+    # test one change within long chain of repeats
+    a = "a,a,a,a,a,a,a,a,a,a".replace(',', '\n')
+    b = "a,a,a,a,-,a,a,a,a,a".replace(',', '\n')
+    assert(testHelper(diffText(a, b)) ==
+      "0.1.4.4*1.0.9.10*",
+      "long chain of repeats test failed.")
+
+    stdout.writeLine("End.")
+    stdout.flushFile
+
+  main()
diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index d3651f659..6f4e8ce37 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -8,6 +8,7 @@
 #
 
 # Implementation of some runtime checks.
+import system/helpers2
 
 proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
   when hostOS == "standalone":
@@ -15,6 +16,12 @@ proc raiseRangeError(val: BiggestInt) {.compilerproc, noinline.} =
   else:
     sysFatal(RangeError, "value out of range: ", $val)
 
+proc raiseIndexError3(i, a, b: int) {.compilerproc, noinline.} =
+  sysFatal(IndexError, formatErrorIndexBound(i, a, b))
+
+proc raiseIndexError2(i, n: int) {.compilerproc, noinline.} =
+  sysFatal(IndexError, formatErrorIndexBound(i, n))
+
 proc raiseIndexError() {.compilerproc, noinline.} =
   sysFatal(IndexError, "index out of bounds")
 
@@ -25,7 +32,7 @@ proc chckIndx(i, a, b: int): int =
   if i >= a and i <= b:
     return i
   else:
-    raiseIndexError()
+    raiseIndexError3(i, a, b)
 
 proc chckRange(i, a, b: int): int =
   if i >= a and i <= b:
diff --git a/lib/system/excpt.nim b/lib/system/excpt.nim
index a6da8f5a3..84a1da343 100644
--- a/lib/system/excpt.nim
+++ b/lib/system/excpt.nim
@@ -454,16 +454,21 @@ when not defined(gcDestructors):
     shallowCopy(result, e.trace)
 
 when defined(nimRequiresNimFrame):
-  proc stackOverflow() {.noinline.} =
+  const nimCallDepthLimit {.intdefine.} = 2000
+
+  proc callDepthLimitReached() {.noinline.} =
     writeStackTrace()
-    showErrorMessage("Stack overflow\n")
+    showErrorMessage("Error: call depth limit reached in a debug build (" &
+        $nimCallDepthLimit & " function calls). You can change it with " &
+        "-d:nimCallDepthLimit=<int> but really try to avoid deep " &
+        "recursions instead.\n")
     quitOrDebug()
 
   proc nimFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
     s.calldepth = if framePtr == nil: 0 else: framePtr.calldepth+1
     s.prev = framePtr
     framePtr = s
-    if s.calldepth == 2000: stackOverflow()
+    if s.calldepth == nimCallDepthLimit: callDepthLimitReached()
 else:
   proc pushFrame(s: PFrame) {.compilerRtl, inl, exportc: "nimFrame".} =
     # XXX only for backwards compatibility
diff --git a/lib/system/helpers2.nim b/lib/system/helpers2.nim
new file mode 100644
index 000000000..1c9e7c068
--- /dev/null
+++ b/lib/system/helpers2.nim
@@ -0,0 +1,5 @@
+template formatErrorIndexBound*[T](i, a, b: T): string =
+  "index out of bounds: (a:" & $a & ") <= (i:" & $i & ") <= (b:" & $b & ") "
+
+template formatErrorIndexBound*[T](i, n: T): string =
+  "index out of bounds: (i:" & $i & ") <= (n:" & $n & ") "
diff --git a/testament/backend.nim b/testament/backend.nim
index 385f1171c..c2658d6a0 100644
--- a/testament/backend.nim
+++ b/testament/backend.nim
@@ -20,14 +20,11 @@ var
   thisCommit: CommitId
   thisBranch: string
 
-{.experimental.}
-proc `()`(cmd: string{lit}): string = cmd.execProcess.string.strip
-
 proc getMachine*(): MachineId =
-  var name = "hostname"()
+  var name = execProcess("hostname").string.strip
   if name.len == 0:
-    name = when defined(posix): getenv"HOSTNAME".string
-           else: getenv"COMPUTERNAME".string
+    name = when defined(posix): getenv("HOSTNAME").string
+           else: getenv("COMPUTERNAME").string
   if name.len == 0:
     quit "cannot determine the machine name"
 
@@ -35,8 +32,8 @@ proc getMachine*(): MachineId =
 
 proc getCommit(): CommitId =
   const commLen = "commit ".len
-  let hash = "git log -n 1"()[commLen..commLen+10]
-  thisBranch = "git symbolic-ref --short HEAD"()
+  let hash = execProcess("git log -n 1").string.strip[commLen..commLen+10]
+  thisBranch = execProcess("git symbolic-ref --short HEAD").string.strip
   if hash.len == 0 or thisBranch.len == 0: quit "cannot determine git HEAD"
   result = CommitId(hash)
 
@@ -45,8 +42,7 @@ var
   currentCategory: string
   entries: int
 
-proc writeTestResult*(name, category, target,
-                      action, result, expected, given: string) =
+proc writeTestResult*(name, category, target, action, result, expected, given: string) =
   createDir("testresults")
   if currentCategory != category:
     if currentCategory.len > 0:
diff --git a/testament/categories.nim b/testament/categories.nim
index e1f173c26..a72602217 100644
--- a/testament/categories.nim
+++ b/testament/categories.nim
@@ -10,6 +10,36 @@
 ## Include for the tester that contains test suites that test special features
 ## of the compiler.
 
+const
+  specialCategories = [
+    "assert",
+    "async",
+    "debugger",
+    "dll",
+    "examples",
+    "flags",
+    "gc",
+    "io",
+    "js",
+    "lib",
+    "longgc",
+    "manyloc",
+    "nimble-all",
+    "nimble-core",
+    "nimble-extra",
+    "niminaction",
+    "rodfiles",
+    "threads",
+    "untestable",
+    "stdlib",
+    "testdata",
+    "nimcache",
+    "coroutines",
+    "osproc",
+    "shouldfail",
+    "dir with space"
+  ]
+
 # included from tester.nim
 # ---------------- ROD file tests ---------------------------------------------
 
@@ -27,7 +57,7 @@ proc delNimCache(filename, options: string) =
 proc runRodFiles(r: var TResults, cat: Category, options: string) =
   template test(filename: string, clearCacheFirst=false) =
     if clearCacheFirst: delNimCache(filename, options)
-    testSpec r, makeTest(rodfilesDir / filename, options, cat, actionRun)
+    testSpec r, makeTest(rodfilesDir / filename, options, cat)
 
 
   # test basic recompilation scheme:
@@ -97,10 +127,12 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) =
     else:
       ""
 
-  testNoSpec c, makeTest("lib/nimrtl.nim",
-    options & " --app:lib -d:createNimRtl --threads:on", cat, actionCompile)
-  testNoSpec c, makeTest("tests/dll/server.nim",
-    options & " --app:lib -d:useNimRtl --threads:on" & rpath, cat, actionCompile)
+  var test1 = makeTest("lib/nimrtl.nim", options & " --app:lib -d:createNimRtl --threads:on", cat)
+  test1.spec.action = actionCompile
+  testSpec c, test1
+  var test2 = makeTest("tests/dll/server.nim", options & " --app:lib -d:useNimRtl --threads:on" & rpath, cat)
+  test2.spec.action = actionCompile
+  testSpec c, test2
 
   when defined(Windows):
     # windows looks in the dir of the exe (yay!):
@@ -120,7 +152,7 @@ proc runBasicDLLTest(c, r: var TResults, cat: Category, options: string) =
     safeCopyFile("lib" / nimrtlDll, "tests/dll" / nimrtlDll)
 
   testSpec r, makeTest("tests/dll/client.nim", options & " -d:useNimRtl --threads:on" & rpath,
-                       cat, actionRun)
+                       cat)
 
 proc dllTests(r: var TResults, cat: Category, options: string) =
   # dummy compile result:
@@ -138,32 +170,32 @@ proc dllTests(r: var TResults, cat: Category, options: string) =
 proc gcTests(r: var TResults, cat: Category, options: string) =
   template testWithNone(filename: untyped) =
     testSpec r, makeTest("tests/gc" / filename, options &
-                  " --gc:none", cat, actionRun)
+                  " --gc:none", cat)
     testSpec r, makeTest("tests/gc" / filename, options &
-                  " -d:release --gc:none", cat, actionRun)
+                  " -d:release --gc:none", cat)
 
   template testWithoutMs(filename: untyped) =
-    testSpec r, makeTest("tests/gc" / filename, options, cat, actionRun)
+    testSpec r, makeTest("tests/gc" / filename, options, cat)
     testSpec r, makeTest("tests/gc" / filename, options &
-                  " -d:release", cat, actionRun)
+                  " -d:release", cat)
     testSpec r, makeTest("tests/gc" / filename, options &
-                  " -d:release -d:useRealtimeGC", cat, actionRun)
+                  " -d:release -d:useRealtimeGC", cat)
 
   template testWithoutBoehm(filename: untyped) =
     testWithoutMs filename
     testSpec r, makeTest("tests/gc" / filename, options &
-                  " --gc:markAndSweep", cat, actionRun)
+                  " --gc:markAndSweep", cat)
     testSpec r, makeTest("tests/gc" / filename, options &
-                  " -d:release --gc:markAndSweep", cat, actionRun)
+                  " -d:release --gc:markAndSweep", cat)
   template test(filename: untyped) =
     testWithoutBoehm filename
     when not defined(windows) and not defined(android):
       # AR: cannot find any boehm.dll on the net, right now, so disabled
       # for windows:
       testSpec r, makeTest("tests/gc" / filename, options &
-                    " --gc:boehm", cat, actionRun)
+                    " --gc:boehm", cat)
       testSpec r, makeTest("tests/gc" / filename, options &
-                    " -d:release --gc:boehm", cat, actionRun)
+                    " -d:release --gc:boehm", cat)
 
   testWithoutBoehm "foreign_thr"
   test "gcemscripten"
@@ -196,17 +228,18 @@ proc longGCTests(r: var TResults, cat: Category, options: string) =
 
   var c = initResults()
   # According to ioTests, this should compile the file
-  testNoSpec c, makeTest("tests/realtimeGC/shared", options, cat, actionCompile)
-  testC r, makeTest("tests/realtimeGC/cmain", cOptions, cat, actionRun)
-  testSpec r, makeTest("tests/realtimeGC/nmain", options & "--threads: on", cat, actionRun)
+  testSpec c, makeTest("tests/realtimeGC/shared", options, cat)
+  #        ^- why is this not appended to r? Should this be discarded?
+  testC r, makeTest("tests/realtimeGC/cmain", cOptions, cat), actionRun
+  testSpec r, makeTest("tests/realtimeGC/nmain", options & "--threads: on", cat)
 
 # ------------------------- threading tests -----------------------------------
 
 proc threadTests(r: var TResults, cat: Category, options: string) =
   template test(filename: untyped) =
-    testSpec r, makeTest(filename, options, cat, actionRun)
-    testSpec r, makeTest(filename, options & " -d:release", cat, actionRun)
-    testSpec r, makeTest(filename, options & " --tlsEmulation:on", cat, actionRun)
+    testSpec r, makeTest(filename, options, cat)
+    testSpec r, makeTest(filename, options & " -d:release", cat)
+    testSpec r, makeTest(filename, options & " --tlsEmulation:on", cat)
   for t in os.walkFiles("tests/threads/t*.nim"):
     test(t)
 
@@ -229,16 +262,16 @@ proc asyncTests(r: var TResults, cat: Category, options: string) =
 # ------------------------- debugger tests ------------------------------------
 
 proc debuggerTests(r: var TResults, cat: Category, options: string) =
-  testNoSpec r, makeTest("tools/nimgrep", options & " --debugger:on", cat)
+  var t = makeTest("tools/nimgrep", options & " --debugger:on", cat)
+  t.spec.action = actionCompile
+  testSpec r, t
 
 # ------------------------- JS tests ------------------------------------------
 
 proc jsTests(r: var TResults, cat: Category, options: string) =
   template test(filename: untyped) =
-    testSpec r, makeTest(filename, options & " -d:nodejs", cat,
-                         actionRun), targetJS
-    testSpec r, makeTest(filename, options & " -d:nodejs -d:release", cat,
-                         actionRun), targetJS
+    testSpec r, makeTest(filename, options & " -d:nodejs", cat), {targetJS}
+    testSpec r, makeTest(filename, options & " -d:nodejs -d:release", cat), {targetJS}
 
   for t in os.walkFiles("tests/js/t*.nim"):
     test(t)
@@ -259,14 +292,14 @@ proc jsTests(r: var TResults, cat: Category, options: string) =
 proc testNimInAction(r: var TResults, cat: Category, options: string) =
   let options = options & " --nilseqs:on"
 
-  template test(filename: untyped, action: untyped) =
-    testSpec r, makeTest(filename, options, cat, action)
+  template test(filename: untyped) =
+    testSpec r, makeTest(filename, options, cat)
 
   template testJS(filename: untyped) =
-    testSpec r, makeTest(filename, options, cat, actionCompile), targetJS
+    testSpec r, makeTest(filename, options, cat), {targetJS}
 
   template testCPP(filename: untyped) =
-    testSpec r, makeTest(filename, options, cat, actionCompile), targetCPP
+    testSpec r, makeTest(filename, options, cat), {targetCPP}
 
   let tests = [
     "niminaction/Chapter1/various1",
@@ -298,39 +331,43 @@ proc testNimInAction(r: var TResults, cat: Category, options: string) =
   # edit when making a conscious breaking change, also please try to make your
   # commit message clear and notify me so I can easily compile an errata later.
   const refHashes = @[
-    "51afdfa84b3ca3d810809d6c4e5037ba", "30f07e4cd5eaec981f67868d4e91cfcf",
-    "d14e7c032de36d219c9548066a97e846", "2e40bfd5daadb268268727da91bb4e81",
-    "c5d3853ed0aba04bf6d35ba28a98dca0", "058603145ff92d46c009006b06e5b228",
-    "7b94a029b94ddb7efafddd546c965ff6", "586d74514394e49f2370dfc01dd9e830",
-    "13febc363ed82585f2a60de40ddfefda", "c11a013db35e798f44077bc0763cc86d",
-    "3e32e2c5e9a24bd13375e1cd0467079c", "0b9fe7ba159623d49ae60db18a15037c",
-    "b2dd5293d7f784824bbf9792c6fb51ad", "4c19d8d9026bfe151b31d7007fa3c237",
-    "9415c6a568cfceed08da8378e95b5cd5", "da520038c153f4054cb8cc5faa617714",
-    "e6c6e061b6f77b2475db6fec7abfb7f4", "9a8fe78c588d08018843b64b57409a02",
-    "8b5d28e985c0542163927d253a3e4fc9", "783299b98179cc725f9c46b5e3b5381f",
-    "bc523f9a9921299090bac1af6c958e73", "80f9c3e594a798225046e8a42e990daf"
+    "51afdfa84b3ca3d810809d6c4e5037ba",
+    "30f07e4cd5eaec981f67868d4e91cfcf",
+    "d14e7c032de36d219c9548066a97e846",
+    "b335635562ff26ec0301bdd86356ac0c",
+    "6c4add749fbf50860e2f523f548e6b0e",
+    "76de5833a7cc46f96b006ce51179aeb1",
+    "705eff79844e219b47366bd431658961",
+    "a1e87b881c5eb161553d119be8b52f64",
+    "2d706a6ec68d2973ec7e733e6d5dce50",
+    "c11a013db35e798f44077bc0763cc86d",
+    "3e32e2c5e9a24bd13375e1cd0467079c",
+    "a5452722b2841f0c1db030cf17708955",
+    "dc6c45eb59f8814aaaf7aabdb8962294",
+    "69d208d281a2e7bffd3eaf4bab2309b1",
+    "ec05666cfb60211bedc5e81d4c1caf3d",
+    "da520038c153f4054cb8cc5faa617714",
+    "59906c8cd819cae67476baa90a36b8c1",
+    "9a8fe78c588d08018843b64b57409a02",
+    "8b5d28e985c0542163927d253a3e4fc9",
+    "783299b98179cc725f9c46b5e3b5381f",
+    "1a2b3fba1187c68d6a9bfa66854f3318",
+    "80f9c3e594a798225046e8a42e990daf"
   ]
 
   for i, test in tests:
     let filename = "tests" / test.addFileExt("nim")
     let testHash = getMD5(readFile(filename).string)
     doAssert testHash == refHashes[i], "Nim in Action test " & filename & " was changed."
-
   # Run the tests.
   for testfile in tests:
-    test "tests/" & testfile & ".nim", actionCompile
-
+    test "tests/" & testfile & ".nim"
   let jsFile = "tests/niminaction/Chapter8/canvas/canvas_test.nim"
   testJS jsFile
-
   let cppFile = "tests/niminaction/Chapter8/sfml/sfml_test.nim"
   testCPP cppFile
 
-
 # ------------------------- manyloc -------------------------------------------
-#proc runSpecialTests(r: var TResults, options: string) =
-#  for t in ["lib/packages/docutils/highlite"]:
-#    testSpec(r, t, options)
 
 proc findMainFile(dir: string): string =
   # finds the file belonging to ".nim.cfg"; if there is no such file
@@ -354,27 +391,32 @@ proc manyLoc(r: var TResults, cat: Category, options: string) =
       if dir.endsWith"named_argument_bug": continue
       let mainfile = findMainFile(dir)
       if mainfile != "":
-        testNoSpec r, makeTest(mainfile, options, cat)
+        var test = makeTest(mainfile, options, cat)
+        test.spec.action = actionCompile
+        testSpec r, test
 
 proc compileExample(r: var TResults, pattern, options: string, cat: Category) =
   for test in os.walkFiles(pattern):
-    testNoSpec r, makeTest(test, options, cat)
+    var test = makeTest(test, options, cat)
+    test.spec.action = actionCompile
+    testSpec r, test
 
 proc testStdlib(r: var TResults, pattern, options: string, cat: Category) =
-  for test in os.walkFiles(pattern):
-    let name = extractFilename(test)
+  for testFile in os.walkFiles(pattern):
+    let name = extractFilename(testFile)
     if name notin disabledFiles:
-      let contents = readFile(test).string
-      if contents.contains("when isMainModule"):
-        testSpec r, makeTest(test, options, cat, actionRunNoSpec)
-      else:
-        testNoSpec r, makeTest(test, options, cat, actionCompile)
+      let contents = readFile(testFile).string
+      var testObj = makeTest(testFile, options, cat)
+      if "when isMainModule" notin contents:
+        testObj.spec.action = actionCompile
+      testSpec r, testObj
 
 # ----------------------------- nimble ----------------------------------------
-type PackageFilter = enum
-  pfCoreOnly
-  pfExtraOnly
-  pfAll
+type
+  PackageFilter = enum
+    pfCoreOnly
+    pfExtraOnly
+    pfAll
 
 var nimbleDir = getEnv("NIMBLE_DIR").string
 if nimbleDir.len == 0: nimbleDir = getHomeDir() / ".nimble"
@@ -404,7 +446,6 @@ proc getPackageDir(package: string): string =
 
 iterator listPackages(filter: PackageFilter): tuple[name, url: string] =
   let packageList = parseFile(packageIndex)
-
   for package in packageList.items():
     let
       name = package["name"].str
@@ -458,24 +499,99 @@ proc testNimblePackages(r: var TResults, cat: Category, filter: PackageFilter) =
 
 # ----------------------------------------------------------------------------
 
-const AdditionalCategories = ["debugger", "examples", "lib"]
+const AdditionalCategories = ["debugger", "examples", "lib", "megatest"]
 
 proc `&.?`(a, b: string): string =
   # candidate for the stdlib?
   result = if b.startswith(a): b else: a & b
 
-#proc `&?.`(a, b: string): string = # not used
-  # candidate for the stdlib?
-  #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
   let target = if cat.string.normalize == "js": targetJS else: targetC
+  if existsFile(test):
+    testSpec r, makeTest(test, options, cat), {target}
+  else:
+    echo "[Warning] - ", test, " test does not exist"
+
+proc isJoinableSpec(spec: TSpec): bool =
+  result = not spec.sortoutput and
+    spec.action == actionRun and
+    not fileExists(spec.file.changeFileExt("cfg")) and
+    not fileExists(parentDir(spec.file) / "nim.cfg") and
+    spec.cmd.len == 0 and
+    spec.err != reDisabled and
+    not spec.unjoinable and
+    spec.exitCode == 0 and
+    spec.input.len == 0 and
+    spec.nimout.len == 0 and
+    spec.outputCheck != ocSubstr and
+    spec.ccodeCheck.len == 0 and
+    (spec.targets == {} or spec.targets == {targetC})
+
+proc norm(s: var string) =
+  while true:
+    let tmp = s.replace("\n\n", "\n")
+    if tmp == s: break
+    s = tmp
+  s = s.strip
+
+proc runJoinedTest(r: var TResults, cat: Category, testsDir: string) =
+  ## returs a list of tests that have problems
+  var specs: seq[TSpec] = @[]
+
+  for kind, dir in walkDir(testsDir):
+    assert testsDir.startsWith(testsDir)
+    let cat = dir[testsDir.len .. ^1]
+    if kind == pcDir and cat notin specialCategories:
+      for file in os.walkFiles(testsDir / cat / "t*.nim"):
+        let spec = parseSpec(file)
+        if isJoinableSpec(spec):
+          specs.add spec
+
+  echo "joinable specs: ", specs.len
+
+  var megatest: string
+  for runSpec in specs:
+    megatest.add "import r\""
+    megatest.add runSpec.file
+    megatest.add "\"\n"
+
+  writeFile("megatest.nim", megatest)
+
+  const args = ["c", "-d:testing", "--listCmd", "megatest.nim"]
+  var (buf, exitCode) = execCmdEx2(command = "nim", args = args, options = {poStdErrToStdOut, poUsePath}, input = "")
+  if exitCode != 0:
+    echo buf
+    quit("megatest compilation failed")
+
+  (buf, exitCode) = execCmdEx("./megatest")
+  if exitCode != 0:
+    echo buf
+    quit("megatest execution failed")
+
+  norm buf
+  writeFile("outputGotten.txt", buf)
+  var outputExpected = ""
+  for i, runSpec in specs:
+    outputExpected.add runSpec.output.strip
+    outputExpected.add '\n'
+  norm outputExpected
+
+  if buf != outputExpected:
+    writeFile("outputExpected.txt", outputExpected)
+    discard execShellCmd("diff -uNdr outputExpected.txt outputGotten.txt")
+    echo "output different!"
+    quit 1
+  else:
+    echo "output OK"
+    removeFile("outputGotten.txt")
+    removeFile("megatest.nim")
+  #testSpec r, makeTest("megatest", options, cat)
 
-  if existsFile(test): testSpec r, makeTest(test, options, cat), target
-  else: echo "[Warning] - ", test, " test does not exist"
+# ---------------------------------------------------------------------------
 
-proc processCategory(r: var TResults, cat: Category, options: string) =
+proc processCategory(r: var TResults, cat: Category, options, testsDir: string,
+                     runJoinableTests: bool) =
   case cat.string.normalize
   of "rodfiles":
     when false:
@@ -524,10 +640,17 @@ proc processCategory(r: var TResults, cat: Category, options: string) =
   of "untestable":
     # We can't test it because it depends on a third party.
     discard # TODO: Move untestable tests to someplace else, i.e. nimble repo.
+  of "megatest":
+    runJoinedTest(r, cat, testsDir)
   else:
     var testsRun = 0
     for name in os.walkFiles("tests" & DirSep &.? cat.string / "t*.nim"):
-      testSpec r, makeTest(name, options, cat)
+      var test = makeTest(name, options, cat)
+      if runJoinableTests or not isJoinableSpec(test.spec) or cat.string in specialCategories:
+        discard "run the test"
+      else:
+        test.spec.err = reJoined
+      testSpec r, test
       inc testsRun
     if testsRun == 0:
       echo "[Warning] - Invalid category specified \"", cat.string, "\", no tests were run"
diff --git a/testament/specs.nim b/testament/specs.nim
index 86fc8bed4..df12db543 100644
--- a/testament/specs.nim
+++ b/testament/specs.nim
@@ -9,21 +9,21 @@
 
 import parseutils, strutils, os, osproc, streams, parsecfg
 
-
 var compilerPrefix* = "compiler" / "nim"
 
 let isTravis* = existsEnv("TRAVIS")
 let isAppVeyor* = existsEnv("APPVEYOR")
 
-proc cmdTemplate*(): string =
-  compilerPrefix & " $target --hints:on -d:testing --nimblePath:tests/deps $options $file"
-
 type
   TTestAction* = enum
     actionRun = "run"
     actionCompile = "compile"
     actionReject = "reject"
-    actionRunNoSpec = "runNoSpec"
+
+  TOutputCheck* = enum
+    ocIgnore = "ignore"
+    ocEqual  = "equal"
+    ocSubstr = "substr"
 
   TResultEnum* = enum
     reNimcCrash,     # nim compiler seems to have crashed
@@ -38,8 +38,10 @@ type
     reExeNotFound,
     reInstallFailed     # package installation failed
     reBuildFailed       # package building failed
-    reIgnored,          # test is ignored
+    reDisabled,         # test is disabled
+    reJoined,           # test is disabled because it was joined into the megatest
     reSuccess           # test was successful
+    reInvalidSpec       # test had problems to parse the spec
 
   TTarget* = enum
     targetC = "C"
@@ -51,7 +53,9 @@ type
     action*: TTestAction
     file*, cmd*: string
     input*: string
-    outp*: string
+    outputCheck*: TOutputCheck
+    sortoutput*: bool
+    output*: string
     line*, column*: int
     tfile*: string
     tline*, tcolumn*: int
@@ -60,9 +64,16 @@ type
     ccodeCheck*: string
     maxCodeSize*: int
     err*: TResultEnum
-    substr*, sortoutput*: bool
     targets*: set[TTarget]
     nimout*: string
+    parseErrors*: string # when the spec definition is invalid, this is not empty.
+    unjoinable*: bool
+
+proc getCmd*(s: TSpec): string =
+  if s.cmd.len == 0:
+    result = compilerPrefix & " $target --hints:on -d:testing --nimblePath:tests/deps $options $file"
+  else:
+    result = s.cmd
 
 const
   targetToExt*: array[TTarget, string] = ["c", "cpp", "m", "js"]
@@ -91,33 +102,6 @@ proc extractSpec(filename: string): string =
 when not defined(nimhygiene):
   {.pragma: inject.}
 
-template parseSpecAux(fillResult: untyped) =
-  var ss = newStringStream(extractSpec(filename))
-  var p {.inject.}: CfgParser
-  open(p, ss, filename, 1)
-  while true:
-    var e {.inject.} = next(p)
-    case e.kind
-    of cfgEof: break
-    of cfgSectionStart, cfgOption, cfgError:
-      echo ignoreMsg(p, e)
-    of cfgKeyValuePair:
-      fillResult
-  close(p)
-
-proc specDefaults*(result: var TSpec) =
-  result.msg = ""
-  result.outp = ""
-  result.nimout = ""
-  result.ccodeCheck = ""
-  result.cmd = cmdTemplate()
-  result.line = 0
-  result.column = 0
-  result.tfile = ""
-  result.tline = 0
-  result.tcolumn = 0
-  result.maxCodeSize = 0
-
 proc parseTargets*(value: string): set[TTarget] =
   for v in value.normalize.splitWhitespace:
     case v
@@ -127,81 +111,134 @@ proc parseTargets*(value: string): set[TTarget] =
     of "js": result.incl(targetJS)
     else: echo "target ignored: " & v
 
+proc addLine*(self: var string; a: string) =
+  self.add a
+  self.add "\n"
+
+proc addLine*(self: var string; a,b: string) =
+  self.add a
+  self.add b
+  self.add "\n"
+
 proc parseSpec*(filename: string): TSpec =
-  specDefaults(result)
   result.file = filename
-  parseSpecAux:
-    case normalize(e.key)
-    of "action":
-      case e.value.normalize
-      of "compile": result.action = actionCompile
-      of "run": result.action = actionRun
-      of "reject": result.action = actionReject
-      else: echo ignoreMsg(p, e)
-    of "file": result.file = e.value
-    of "line": discard parseInt(e.value, result.line)
-    of "column": discard parseInt(e.value, result.column)
-    of "tfile": result.tfile = e.value
-    of "tline": discard parseInt(e.value, result.tline)
-    of "tcolumn": discard parseInt(e.value, result.tcolumn)
-    of "output":
-      result.action = actionRun
-      result.outp = e.value
-    of "input":
-      result.input = e.value
-    of "outputsub":
-      result.action = actionRun
-      result.outp = e.value
-      result.substr = true
-    of "sortoutput":
-      result.sortoutput = parseCfgBool(e.value)
-    of "exitcode":
-      discard parseInt(e.value, result.exitCode)
-      result.action = actionRun
-    of "msg":
-      result.msg = e.value
-      if result.action != actionRun:
-        result.action = actionCompile
-    of "errormsg", "errmsg":
-      result.msg = e.value
-      result.action = actionReject
-    of "nimout":
-      result.nimout = e.value
-    of "disabled":
-      case e.value.normalize
-      of "y", "yes", "true", "1", "on": result.err = reIgnored
-      of "n", "no", "false", "0", "off": discard
-      of "win", "windows":
-        when defined(windows): result.err = reIgnored
-      of "linux":
-        when defined(linux): result.err = reIgnored
-      of "bsd":
-        when defined(bsd): result.err = reIgnored
-      of "macosx":
-        when defined(macosx): result.err = reIgnored
-      of "unix":
-        when defined(unix): result.err = reIgnored
-      of "posix":
-        when defined(posix): result.err = reIgnored
-      of "travis":
-        if isTravis: result.err = reIgnored
-      of "appveyor":
-        if isAppVeyor: result.err = reIgnored
-      else:
-        raise newException(ValueError, "cannot interpret as a bool: " & e.value)
-    of "cmd":
-      if e.value.startsWith("nim "):
-        result.cmd = compilerPrefix & e.value[3..^1]
+  let specStr = extractSpec(filename)
+  var ss = newStringStream(specStr)
+  var p: CfgParser
+  open(p, ss, filename, 1)
+  while true:
+    var e = next(p)
+    case e.kind
+    of cfgKeyValuePair:
+      case normalize(e.key)
+      of "action":
+        case e.value.normalize
+        of "compile":
+          result.action = actionCompile
+        of "run":
+          result.action = actionRun
+        of "reject":
+          result.action = actionReject
+        else:
+          result.parseErrors.addLine "cannot interpret as action: ", e.value
+      of "file":
+        if result.msg.len == 0 and result.nimout.len == 0:
+          result.parseErrors.addLine "errormsg or msg needs to be specified before file"
+        result.file = e.value
+      of "line":
+        if result.msg.len == 0 and result.nimout.len == 0:
+          result.parseErrors.addLine "errormsg, msg or nimout needs to be specified before line"
+        discard parseInt(e.value, result.line)
+      of "column":
+        if result.msg.len == 0 and result.nimout.len == 0:
+          result.parseErrors.addLine "errormsg or msg needs to be specified before column"
+        discard parseInt(e.value, result.column)
+      of "tfile":
+        result.tfile = e.value
+      of "tline":
+        discard parseInt(e.value, result.tline)
+      of "tcolumn":
+        discard parseInt(e.value, result.tcolumn)
+      of "output":
+        result.outputCheck = ocEqual
+        result.output = strip(e.value)
+      of "input":
+        result.input = e.value
+      of "outputsub":
+        result.outputCheck = ocSubstr
+        result.output = strip(e.value)
+      of "sortoutput":
+        try:
+          result.sortoutput  = parseCfgBool(e.value)
+        except:
+          result.parseErrors.addLine getCurrentExceptionMsg()
+      of "exitcode":
+        discard parseInt(e.value, result.exitCode)
+        result.action = actionRun
+      of "msg":
+        result.msg = e.value
+        if result.action != actionRun:
+          result.action = actionCompile
+      of "errormsg", "errmsg":
+        result.msg = e.value
+        result.action = actionReject
+      of "nimout":
+        result.nimout = e.value
+      of "joinable":
+        result.unjoinable = not parseCfgBool(e.value)
+      of "disabled":
+        case e.value.normalize
+        of "y", "yes", "true", "1", "on": result.err = reDisabled
+        of "n", "no", "false", "0", "off": discard
+        of "win", "windows":
+          when defined(windows): result.err = reDisabled
+        of "linux":
+          when defined(linux): result.err = reDisabled
+        of "bsd":
+          when defined(bsd): result.err = reDisabled
+        of "macosx":
+          when defined(macosx): result.err = reDisabled
+        of "unix":
+          when defined(unix): result.err = reDisabled
+        of "posix":
+          when defined(posix): result.err = reDisabled
+        of "travis":
+          if isTravis: result.err = reDisabled
+        of "appveyor":
+          if isAppVeyor: result.err = reDisabled
+        else:
+          result.parseErrors.addLine "cannot interpret as a bool: ", e.value
+      of "cmd":
+        if e.value.startsWith("nim "):
+          result.cmd = compilerPrefix & e.value[3..^1]
+        else:
+          result.cmd = e.value
+      of "ccodecheck":
+        result.ccodeCheck = e.value
+      of "maxcodesize":
+        discard parseInt(e.value, result.maxCodeSize)
+      of "target", "targets":
+        for v in e.value.normalize.splitWhitespace:
+          case v
+          of "c":
+            result.targets.incl(targetC)
+          of "cpp", "c++":
+            result.targets.incl(targetCpp)
+          of "objc":
+            result.targets.incl(targetObjC)
+          of "js":
+            result.targets.incl(targetJS)
+          else:
+            result.parseErrors.addLine "cannot interpret as a target: ", e.value
       else:
-        result.cmd = e.value
-    of "ccodecheck": result.ccodeCheck = e.value
-    of "maxcodesize": discard parseInt(e.value, result.maxCodeSize)
-    of "target", "targets":
-      for v in e.value.normalize.splitWhitespace:
-        case v
-        of "c": result.targets.incl(targetC)
-        of "cpp", "c++": result.targets.incl(targetCpp)
-        of "objc": result.targets.incl(targetObjC)
-        of "js": result.targets.incl(targetJS)
-        else: echo ignoreMsg(p, e)
-    else: echo ignoreMsg(p, e)
+        result.parseErrors.addLine "invalid key for test spec: ", e.key
+
+    of cfgSectionStart:
+      result.parseErrors.addLine "section ignored: ", e.section
+    of cfgOption:
+      result.parseErrors.addLine "command ignored: ", e.key & ": " & e.value
+    of cfgError:
+      result.parseErrors.addLine e.msg
+    of cfgEof:
+      break
+  close(p)
diff --git a/testament/tester.nim b/testament/tester.nim
index 59c0171b4..6d9e05aa9 100644
--- a/testament/tester.nim
+++ b/testament/tester.nim
@@ -15,6 +15,7 @@ import
   algorithm, compiler/nodejs, times, sets, md5
 
 var useColors = true
+var backendLogging = true
 
 const
   resultsFile = "testresults.html"
@@ -27,6 +28,7 @@ Command:
   c|cat|category <category>   run all the tests of a certain category
   r|run <test>                run single test file
   html                        generate $1 from the database
+  stats                       generate statistics about test cases
 Arguments:
   arguments are passed to the compiler
 Options:
@@ -35,7 +37,8 @@ Options:
   --targets:"c c++ js objc" run tests for specified targets (default: all)
   --nim:path                use a particular nim executable (default: compiler/nim)
   --directory:dir           Change to directory dir before reading the tests or doing anything else.
-  --colors:on|off           turn messagescoloring on|off
+  --colors:on|off           Turn messagescoloring on|off.
+  --backendLogging:on|off   Disable or enable backend logging. By default turned on.
 """ % resultsFile
 
 type
@@ -48,7 +51,7 @@ type
     name: string
     cat: Category
     options: string
-    action: TTestAction
+    spec: TSpec
     startTime: float
 
 # ----------------------------------------------------------------------------
@@ -113,7 +116,7 @@ proc nimcacheDir(filename, options: string, target: TTarget): string =
 proc callCompiler(cmdTemplate, filename, options: string,
                   target: TTarget, extraOptions=""): TSpec =
   let nimcache = nimcacheDir(filename, options, target)
-  let options = options & " " & ("--nimCache:" & nimcache).quoteShell & extraOptions
+  let options = options & " " & quoteShell("--nimCache:" & nimcache) & extraOptions
   let c = parseCmdLine(cmdTemplate % ["target", targetToCmd[target],
                        "options", options, "file", filename.quoteShell,
                        "filedir", filename.getFileDir()])
@@ -138,7 +141,7 @@ proc callCompiler(cmdTemplate, filename, options: string,
   close(p)
   result.msg = ""
   result.file = ""
-  result.outp = ""
+  result.output = ""
   result.line = 0
   result.column = 0
   result.tfile = ""
@@ -170,7 +173,7 @@ proc callCCompiler(cmdTemplate, filename, options: string,
   result.nimout = ""
   result.msg = ""
   result.file = ""
-  result.outp = ""
+  result.output = ""
   result.line = -1
   while outp.readLine(x.TaintedString) or running(p):
     result.nimout.add(x & "\n")
@@ -219,18 +222,21 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
   let name = test.name.extractFilename & " " & $target & test.options
   let duration = epochTime() - test.startTime
   let durationStr = duration.formatFloat(ffDecimal, precision = 8).align(11)
-  backend.writeTestResult(name = name,
-                          category = test.cat.string,
-                          target = $target,
-                          action = $test.action,
-                          result = $success,
-                          expected = expected,
-                          given = given)
+  if backendLogging:
+    backend.writeTestResult(name = name,
+                            category = test.cat.string,
+                            target = $target,
+                            action = $test.spec.action,
+                            result = $success,
+                            expected = expected,
+                            given = given)
   r.data.addf("$#\t$#\t$#\t$#", name, expected, given, $success)
   if success == reSuccess:
     maybeStyledEcho fgGreen, "PASS: ", fgCyan, alignLeft(name, 60), fgBlue, " (", durationStr, " secs)"
-  elif success == reIgnored:
+  elif success == reDisabled:
     maybeStyledEcho styleDim, fgYellow, "SKIP: ", styleBright, fgCyan, name
+  elif success == reJoined:
+    maybeStyledEcho styleDim, fgYellow, "JOINED: ", styleBright, fgCyan, name
   else:
     maybeStyledEcho styleBright, fgRed, "FAIL: ", fgCyan, name
     maybeStyledEcho styleBright, fgCyan, "Test \"", test.name, "\"", " in category \"", test.cat.string, "\""
@@ -240,11 +246,11 @@ proc addResult(r: var TResults, test: TTest, target: TTarget,
     maybeStyledEcho fgYellow, "Gotten:"
     maybeStyledEcho styleBright, given, "\n"
 
-  if existsEnv("APPVEYOR"):
+  if backendLogging and existsEnv("APPVEYOR"):
     let (outcome, msg) =
       if success == reSuccess:
         ("Passed", "")
-      elif success == reIgnored:
+      elif success in {reDisabled, reJoined}:
         ("Skipped", "")
       else:
         ("Failed", "Failure: " & $success & "\nExpected:\n" & expected & "\n\n" & "Gotten:\n" & given)
@@ -328,11 +334,6 @@ proc nimoutCheck(test: TTest; expectedNimout: string; given: var TSpec) =
       given.err = reMsgsDiffer
       return
 
-proc makeDeterministic(s: string): string =
-  var x = splitLines(s)
-  sort(x, system.cmp)
-  result = join(x, "\n")
-
 proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec,
                          expected: TSpec; r: var TResults) =
   var expectedmsg: string = ""
@@ -350,75 +351,58 @@ proc compilerOutputTests(test: TTest, target: TTarget, given: var TSpec,
   if given.err == reSuccess: inc(r.passed)
   r.addResult(test, target, expectedmsg, givenmsg, given.err)
 
-proc testSpec(r: var TResults, test: TTest, target = targetC) =
-  let tname = test.name.addFileExt(".nim")
-  var expected: TSpec
-  if test.action != actionRunNoSpec:
-    expected = parseSpec(tname)
-    if test.action == actionRun and expected.action == actionCompile:
-      expected.action = actionRun
-  else:
-    specDefaults expected
-    expected.action = actionRunNoSpec
-
-  if expected.err == reIgnored:
-    r.addResult(test, target, "", "", reIgnored)
+proc testSpec(r: var TResults, test: TTest, targets: set[TTarget] = {}) =
+  var expected = test.spec
+  if expected.parseErrors.len > 0:
+    # targetC is a lie, but parameter is required
+    r.addResult(test, targetC, "", expected.parseErrors, reInvalidSpec)
+    inc(r.total)
+    return
+  if expected.err in {reDisabled, reJoined}:
+    # targetC is a lie, but parameter is required
+    r.addResult(test, targetC, "", "", expected.err)
     inc(r.skipped)
     inc(r.total)
     return
-
-  if getEnv("NIM_COMPILE_TO_CPP", "false").string == "true" and target == targetC and expected.targets == {}:
-    expected.targets.incl(targetCpp)
-  elif expected.targets == {}:
-    expected.targets.incl(target)
-
+  expected.targets.incl targets
+  # still no target specified at all
+  if expected.targets == {}:
+    if getEnv("NIM_COMPILE_TO_CPP", "false").string == "true":
+      expected.targets = {targetCpp}
+    else:
+      expected.targets = {targetC}
   for target in expected.targets:
     inc(r.total)
-    if target notin targets:
-      r.addResult(test, target, "", "", reIgnored)
-      inc(r.skipped)
-      continue
-
     case expected.action
     of actionCompile:
-      var given = callCompiler(expected.cmd, test.name, test.options, target,
+      var given = callCompiler(expected.getCmd, test.name, test.options, target,
         extraOptions=" --stdout --hint[Path]:off --hint[Processing]:off")
       compilerOutputTests(test, target, given, expected, r)
-    of actionRun, actionRunNoSpec:
+    of actionRun:
       # In this branch of code "early return" pattern is clearer than deep
       # nested conditionals - the empty rows in between to clarify the "danger"
-      var given = callCompiler(expected.cmd, test.name, test.options,
+      var given = callCompiler(expected.getCmd, test.name, test.options,
                                target)
-
-      # echo "expected.cmd: ", expected.cmd
-      # echo "nimout: ", given.nimout
-      # echo "outp:   ", given.outp
-      # echo "msg:    ", given.msg
-      # echo "err:    ", given.err
-
       if given.err != reSuccess:
         r.addResult(test, target, "", given.msg, given.err)
         continue
-
       let isJsTarget = target == targetJS
       var exeFile: string
       if isJsTarget:
-        let (_, file, _) = splitFile(tname)
-        exeFile = nimcacheDir(test.name, test.options, target) / file & ".js"
+        let file = test.name.lastPathPart.changeFileExt("js")
+        exeFile = nimcacheDir(test.name, test.options, target) / file
       else:
-        exeFile = changeFileExt(tname, ExeExt)
+        exeFile = changeFileExt(test.name, ExeExt)
 
       if not existsFile(exeFile):
-        r.addResult(test, target, expected.outp, "executable not found", reExeNotFound)
+        r.addResult(test, target, expected.output, "executable not found", reExeNotFound)
         continue
 
       let nodejs = if isJsTarget: findNodeJs() else: ""
       if isJsTarget and nodejs == "":
-        r.addResult(test, target, expected.outp, "nodejs binary not in PATH",
+        r.addResult(test, target, expected.output, "nodejs binary not in PATH",
                     reExeNotFound)
         continue
-
-
       var exeCmd: string
       var args: seq[string]
       if isJsTarget:
@@ -426,55 +410,44 @@ proc testSpec(r: var TResults, test: TTest, target = targetC) =
         args.add exeFile
       else:
         exeCmd = exeFile
-
       var (buf, exitCode) = execCmdEx2(exeCmd, args, options = {poStdErrToStdOut}, input = expected.input)
-
       # Treat all failure codes from nodejs as 1. Older versions of nodejs used
       # to return other codes, but for us it is sufficient to know that it's not 0.
       if exitCode != 0: exitCode = 1
-
-      let bufB = if expected.sortoutput: makeDeterministic(strip(buf.string))
-                 else: strip(buf.string)
-      let expectedOut = strip(expected.outp)
-
+      let bufB =
+        if expected.sortoutput:
+          var x = splitLines(strip(buf.string))
+          sort(x, system.cmp)
+          join(x, "\n")
+        else:
+          strip(buf.string)
       if exitCode != expected.exitCode:
         r.addResult(test, target, "exitcode: " & $expected.exitCode,
                           "exitcode: " & $exitCode & "\n\nOutput:\n" &
                           bufB, reExitCodesDiffer)
         continue
-
-      if bufB != expectedOut and expected.action != actionRunNoSpec:
-        if not (expected.substr and expectedOut in bufB):
-          given.err = reOutputsDiffer
-          r.addResult(test, target, expected.outp, bufB, reOutputsDiffer)
-          continue
-
+      if (expected.outputCheck == ocEqual and expected.output != bufB) or
+         (expected.outputCheck == ocSubstr and expected.output notin bufB):
+        given.err = reOutputsDiffer
+        r.addResult(test, target, expected.output, bufB, reOutputsDiffer)
+        continue
       compilerOutputTests(test, target, given, expected, r)
       continue
-
     of actionReject:
-      var given = callCompiler(expected.cmd, test.name, test.options,
+      var given = callCompiler(expected.getCmd, test.name, test.options,
                                target)
       cmpMsgs(r, expected, given, test, target)
       continue
 
-proc testNoSpec(r: var TResults, test: TTest, target = targetC) =
-  # does not extract the spec because the file is not supposed to have any
-  #let tname = test.name.addFileExt(".nim")
-  inc(r.total)
-  let given = callCompiler(cmdTemplate(), test.name, test.options, target)
-  r.addResult(test, target, "", given.msg, given.err)
-  if given.err == reSuccess: inc(r.passed)
-
-proc testC(r: var TResults, test: TTest) =
+proc testC(r: var TResults, test: TTest, action: TTestAction) =
   # runs C code. Doesn't support any specs, just goes by exit code.
   let tname = test.name.addFileExt(".c")
   inc(r.total)
   maybeStyledEcho "Processing ", fgCyan, extractFilename(tname)
-  var given = callCCompiler(cmdTemplate(), test.name & ".c", test.options, targetC)
+  var given = callCCompiler(getCmd(TSpec()), test.name & ".c", test.options, targetC)
   if given.err != reSuccess:
     r.addResult(test, targetC, "", given.msg, given.err)
-  elif test.action == actionRun:
+  elif action == actionRun:
     let exeFile = changeFileExt(test.name, ExeExt)
     var (_, exitCode) = execCmdEx(exeFile, options = {poStdErrToStdOut, poUsePath})
     if exitCode != 0: given.err = reExitCodesDiffer
@@ -485,7 +458,6 @@ proc testExec(r: var TResults, test: TTest) =
   inc(r.total)
   let (outp, errC) = execCmdEx(test.options.strip())
   var given: TSpec
-  specDefaults(given)
   if errC == 0:
     given.err = reSuccess
   else:
@@ -495,11 +467,12 @@ proc testExec(r: var TResults, test: TTest) =
   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:
-  result = TTest(cat: cat, name: test, options: options,
-                 action: action, startTime: epochTime())
+proc makeTest(test, options: string, cat: Category): TTest =
+  result.cat = cat
+  result.name = test
+  result.options = options
+  result.spec = parseSpec(addFileExt(test, ".nim"))
+  result.startTime = epochTime()
 
 when defined(windows):
   const
@@ -512,10 +485,7 @@ else:
 
 include categories
 
-# proc runCaasTests(r: var TResults) =
-#   for test, output, status, mode in caasTestsRunner():
-#     r.addResult(test, "", output & "-> " & $mode,
-#                 if status: reSuccess else: reOutputsDiffer)
+const testsDir = "tests" & DirSep
 
 proc main() =
   os.putenv "NIMTEST_COLOR", "never"
@@ -524,10 +494,8 @@ proc main() =
   backend.open()
   var optPrintResults = false
   var optFailing = false
-
   var targetsStr = ""
 
-
   var p = initOptParser()
   p.next()
   while p.kind == cmdLongoption:
@@ -538,26 +506,38 @@ proc main() =
     of "targets":
       targetsStr = p.val.string
       targets = parseTargets(targetsStr)
-    of "nim": compilerPrefix = p.val.string
+    of "nim":
+      compilerPrefix = addFileExt(p.val.string, ExeExt)
     of "directory":
       setCurrentDir(p.val.string)
     of "colors":
-      if p.val.string == "on":
+      case p.val.string:
+      of "on":
         useColors = true
-      elif p.val.string == "off":
+      of "off":
         useColors = false
       else:
         quit Usage
+    of "backendlogging":
+      case p.val.string:
+      of "on":
+        backendLogging = true
+      of "off":
+        backendLogging = false
+      else:
+        quit Usage
     else:
       quit Usage
     p.next()
-  if p.kind != cmdArgument: quit Usage
+  if p.kind != cmdArgument:
+    quit Usage
   var action = p.key.string.normalize
   p.next()
   var r = initResults()
   case action
   of "all":
-    let testsDir = "tests" & DirSep
+    #processCategory(r, Category"megatest", p.cmdLineRest.string, testsDir, runJoinableTests = false)
+
     var myself = quoteShell(findExe("testament" / "tester"))
     if targetsStr.len > 0:
       myself &= " " & quoteShell("--targets:" & targetsStr)
@@ -570,14 +550,21 @@ proc main() =
       assert testsDir.startsWith(testsDir)
       let cat = dir[testsDir.len .. ^1]
       if kind == pcDir and cat notin ["testdata", "nimcache"]:
-        cmds.add(myself & " cat " & quoteShell(cat) & rest)
+        cmds.add(myself & " pcat " & quoteShell(cat) & rest)
     for cat in AdditionalCategories:
-      cmds.add(myself & " cat " & quoteShell(cat) & rest)
+      cmds.add(myself & " pcat " & quoteShell(cat) & rest)
     quit osproc.execProcesses(cmds, {poEchoCmd, poStdErrToStdOut, poUsePath, poParentStreams})
   of "c", "cat", "category":
     var cat = Category(p.key)
     p.next
-    processCategory(r, cat, p.cmdLineRest.string)
+    processCategory(r, cat, p.cmdLineRest.string, testsDir, runJoinableTests = true)
+  of "pcat":
+    # 'pcat' is used for running a category in parallel. Currently the only
+    # difference is that we don't want to run joinable tests here as they
+    # are covered by the 'megatest' category.
+    var cat = Category(p.key)
+    p.next
+    processCategory(r, cat, p.cmdLineRest.string, testsDir, runJoinableTests = false)
   of "r", "run":
     let (dir, file) = splitPath(p.key.string)
     let (_, subdir) = splitPath(dir)
diff --git a/testament/tests/shouldfail/tcolumn.nim b/testament/tests/shouldfail/tcolumn.nim
index f4046d58d..89482e673 100644
--- a/testament/tests/shouldfail/tcolumn.nim
+++ b/testament/tests/shouldfail/tcolumn.nim
@@ -1,7 +1,7 @@
 discard """
+errormsg: "undeclared identifier: 'undeclared'"
 line: 8
 column: 7
-errormsg: "undeclared identifier: 'undeclared'"
 """
 
 # test should fail because the line directive is wrong
diff --git a/testament/tests/shouldfail/terrormsg.nim b/testament/tests/shouldfail/terrormsg.nim
index 61c08d93d..dbbdf5021 100644
--- a/testament/tests/shouldfail/terrormsg.nim
+++ b/testament/tests/shouldfail/terrormsg.nim
@@ -1,7 +1,7 @@
 discard """
+errormsg: "wrong error message"
 line: 8
 column: 6
-errormsg: "wrong error message"
 """
 
 # test should fail because the line directive is wrong
diff --git a/testament/tests/shouldfail/tfile.nim b/testament/tests/shouldfail/tfile.nim
index 07a526c68..a6c2ad359 100644
--- a/testament/tests/shouldfail/tfile.nim
+++ b/testament/tests/shouldfail/tfile.nim
@@ -1,6 +1,6 @@
 discard """
-file: "notthisfile.nim"
 errmsg: "undeclared identifier: 'undefined'"
+file: "notthisfile.nim"
 """
 
 echo undefined
diff --git a/testament/tests/shouldfail/tline.nim b/testament/tests/shouldfail/tline.nim
index 963e44fc7..f7a09875c 100644
--- a/testament/tests/shouldfail/tline.nim
+++ b/testament/tests/shouldfail/tline.nim
@@ -1,7 +1,7 @@
 discard """
+errormsg: "undeclared identifier: 'undeclared'"
 line: 9
 column: 6
-errormsg: "undeclared identifier: 'undeclared'"
 """
 
 # test should fail because the line directive is wrong
diff --git a/tests/ambsym/tambsym.nim b/tests/ambsym/tambsym.nim
index d9115e16d..bd0f41717 100644
--- a/tests/ambsym/tambsym.nim
+++ b/tests/ambsym/tambsym.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "ambiguous identifier"
   file: "tambsym.nim"
   line: 11
-  errormsg: "ambiguous identifier"
 """
 # Test ambiguous symbols
 
@@ -11,5 +11,3 @@ var
   v: TExport #ERROR_MSG ambiguous identifier
 
 v = y
-
-
diff --git a/tests/ambsym/tambsym2.nim b/tests/ambsym/tambsym2.nim
index 8e288e73a..747f1a086 100644
--- a/tests/ambsym/tambsym2.nim
+++ b/tests/ambsym/tambsym2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tambsym2.nim"
   output: "7"
 """
 # Test overloading of procs with locals
@@ -20,5 +19,3 @@ m.len = 7
 m.data = "1234"
 
 x(m, 5) #OUT 7
-
-
diff --git a/tests/ambsym/tambsym3.nim b/tests/ambsym/tambsym3.nim
index b25dadfd6..0558517bd 100644
--- a/tests/ambsym/tambsym3.nim
+++ b/tests/ambsym/tambsym3.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "ambiguous identifier"
   file: "tambsym3.nim"
   line: 11
-  errormsg: "ambiguous identifier"
 """
 # Test ambiguous symbols
 
@@ -11,5 +11,3 @@ var
   v = mDec #ERROR_MSG ambiguous identifier
 
 writeLine(stdout, ord(v))
-
-
diff --git a/tests/ambsym/tambsys.nim b/tests/ambsym/tambsys.nim
index 67522d7c9..aa740c38f 100644
--- a/tests/ambsym/tambsys.nim
+++ b/tests/ambsym/tambsys.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tambsys.nim"
   output: ""
 """
 # Test ambiguous symbols
@@ -9,5 +8,3 @@ import mambsys1, mambsys2
 var
   v: mambsys1.TExport
 mambsys2.foo(3) #OUT
-
-
diff --git a/tests/array/tarray.nim b/tests/array/tarray.nim
index 8551d324c..2a371b788 100644
--- a/tests/array/tarray.nim
+++ b/tests/array/tarray.nim
@@ -1,7 +1,5 @@
 discard """
-  file: "tarray.nim"
-  output:
-'''
+output: '''
 [4, 5, 6]
 
 [16, 25, 36]
@@ -30,6 +28,7 @@ dflfdjkl__abcdefgasfsgdfgsgdfggsdfasdfsafewfkljdsfajsdf
 kgdchlfniambejop
 fjpmholcibdgeakn
 '''
+joinable: false
 """
 
 block tarray:
@@ -358,7 +357,7 @@ block troofregression:
   echo testStr[testStr.len - 8 .. testStr.len - 1] & "__" & testStr[0 .. testStr.len - pred(rot)]
 
   var
-    instructions = readFile(getAppDir() / "troofregression2.txt").split(',')
+    instructions = readFile(parentDir(currentSourcePath) / "troofregression2.txt").split(',')
     programs = "abcdefghijklmnop"
 
   proc dance(dancers: string): string =
diff --git a/tests/array/tarraycons.nim b/tests/array/tarraycons.nim
index 9f09fd405..b6ebe55c8 100644
--- a/tests/array/tarraycons.nim
+++ b/tests/array/tarraycons.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "invalid order in array constructor"
   file: "tarraycons.nim"
   line: 14
-  errormsg: "invalid order in array constructor"
 """
 
 type
@@ -19,6 +19,3 @@ const
   ]
 
 echo myMapping[eC][1]
-
-
-
diff --git a/tests/array/tarraycons_ptr_generic2.nim b/tests/array/tarraycons_ptr_generic2.nim
index fce7af669..f6ed32b58 100644
--- a/tests/array/tarraycons_ptr_generic2.nim
+++ b/tests/array/tarraycons_ptr_generic2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch: got <ptr Hard[system.string]> but expected 'Book[system.string]'"
   file: "tarraycons_ptr_generic2.nim"
   line: 17
-  errormsg: "type mismatch: got <ptr Hard[system.string]> but expected 'Book[system.string]'"
 """
 
 type
diff --git a/tests/assert/tassert.nim b/tests/assert/tassert.nim
index b5f2fb715..99929f080 100644
--- a/tests/assert/tassert.nim
+++ b/tests/assert/tassert.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tassert.nim"
   outputsub: "assertion failure!this shall be always written"
   exitcode: "1"
 """
@@ -19,5 +18,3 @@ finally:
   system.write(stdout, "this shall be always written")
 
 assert(false) #OUT assertion failure!this shall be always written
-
-
diff --git a/tests/assign/tassign.nim b/tests/assign/tassign.nim
index cb03b5004..b421802ae 100644
--- a/tests/assign/tassign.nim
+++ b/tests/assign/tassign.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tassign.nim"
   output:
 '''
 TEMP=C:\Programs\xyz\bin
diff --git a/tests/assign/tvariantasgn.nim b/tests/assign/tvariantasgn.nim
index 46cc23dd1..2278957ac 100644
--- a/tests/assign/tvariantasgn.nim
+++ b/tests/assign/tvariantasgn.nim
@@ -1,7 +1,7 @@
 discard """
-  file: "tvariantasgn.nim"
   output: "came here"
 """
+
 #BUG
 type
   TAnyKind = enum
@@ -26,5 +26,3 @@ nr.intVal = 78
 # s = nr # works
 nr = s # fails!
 echo "came here"
-
-
diff --git a/tests/async/t7192.nim b/tests/async/t7192.nim
index c380f93e1..9ac0e07c0 100644
--- a/tests/async/t7192.nim
+++ b/tests/async/t7192.nim
@@ -9,6 +9,6 @@ import asyncdispatch
 proc testCallback() =
   echo "testCallback()"
 
-when isMainModule:
+when true:
   callSoon(testCallback)
   poll()
diff --git a/tests/async/t7758.nim b/tests/async/t7758.nim
index 102a4ce4c..ce4df1fc9 100644
--- a/tests/async/t7758.nim
+++ b/tests/async/t7758.nim
@@ -1,7 +1,3 @@
-discard """
-  file: "t7758.nim"
-  exitcode: 0
-"""
 import asyncdispatch
 
 proc task() {.async.} =
@@ -16,4 +12,4 @@ proc main() =
 
   doAssert counter <= 4
 
-for i in 0 .. 10: main()
\ No newline at end of file
+for i in 0 .. 10: main()
diff --git a/tests/async/tasyncRecvLine.nim b/tests/async/tasyncRecvLine.nim
index 679831b27..a13a171c3 100644
--- a/tests/async/tasyncRecvLine.nim
+++ b/tests/async/tasyncRecvLine.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tasyncRecvLine.nim"
-  output: '''
+output: '''
 Hello World
 Hello World
 '''
diff --git a/tests/async/tasync_gcunsafe.nim b/tests/async/tasync_gcunsafe.nim
index f4e2cdcf2..55b66aaef 100644
--- a/tests/async/tasync_gcunsafe.nim
+++ b/tests/async/tasync_gcunsafe.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "'anotherGCSafeAsyncProcIter' is not GC-safe as it calls 'asyncGCUnsafeProc'"
   cmd: "nim c --threads:on $file"
   file: "asyncmacro.nim"
-  errormsg: "'anotherGCSafeAsyncProcIter' is not GC-safe as it calls 'asyncGCUnsafeProc'"
 """
 
 assert compileOption("threads"), "this test will not do anything useful without --threads:on"
diff --git a/tests/async/tasyncall.nim b/tests/async/tasyncall.nim
index 3e30e8ba8..3c318dbf7 100644
--- a/tests/async/tasyncall.nim
+++ b/tests/async/tasyncall.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tasyncall.nim"
   exitcode: 0
 """
 import times, sequtils
diff --git a/tests/async/tasyncawait.nim b/tests/async/tasyncawait.nim
index e7a2ec1d9..fcb48a1f5 100644
--- a/tests/async/tasyncawait.nim
+++ b/tests/async/tasyncawait.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tasyncawait.nim"
   output: "5000"
 """
 import asyncdispatch, nativesockets, net, strutils, os
diff --git a/tests/async/tasyncconnect.nim b/tests/async/tasyncconnect.nim
index 3dac379b2..f63a87990 100644
--- a/tests/async/tasyncconnect.nim
+++ b/tests/async/tasyncconnect.nim
@@ -1,7 +1,6 @@
 discard """
-  file: "tasyncconnect.nim"
-  exitcode: 1
   outputsub: "Error: unhandled exception: Connection refused"
+  exitcode: 1
 """
 
 import
diff --git a/tests/async/tasyncdial.nim b/tests/async/tasyncdial.nim
index fa81235fe..815520294 100644
--- a/tests/async/tasyncdial.nim
+++ b/tests/async/tasyncdial.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tasyncdial.nim"
   output: '''
 OK AF_INET
 OK AF_INET6
diff --git a/tests/async/tasyncexceptions.nim b/tests/async/tasyncexceptions.nim
index 7aa1d7fb0..de61c099d 100644
--- a/tests/async/tasyncexceptions.nim
+++ b/tests/async/tasyncexceptions.nim
@@ -1,7 +1,6 @@
 discard """
-  file: "tasyncexceptions.nim"
-  exitcode: 1
   outputsub: "Error: unhandled exception: foobar"
+  exitcode: 1
 """
 import asyncdispatch
 
@@ -28,7 +27,7 @@ proc serve() {.async.} =
     var fut = await accept()
     await processClient(fut)
 
-when isMainModule:
+when true:
   proc main =
     var fut = serve()
     fut.callback =
diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim
index c7b71a2f7..d95850c31 100644
--- a/tests/async/tasyncfile.nim
+++ b/tests/async/tasyncfile.nim
@@ -1,10 +1,9 @@
 discard """
-  output: '''13
+output: '''
+13
 hello humans!
 13
 '''
-  file: "tasyncfile.nim"
-  exitcode: 0
 """
 import asyncfile, asyncdispatch, os
 
@@ -54,8 +53,7 @@ proc main() {.async.} =
 
   # Issue #7347
   block:
-    let appDir = getAppDir()
-    var file = openAsync(appDir & DirSep & "hello.txt")
+    var file = openAsync( parentDir(currentSourcePath) / "hello.txt")
     echo file.getFileSize()
     echo await file.readAll()
     echo file.getFilePos()
diff --git a/tests/async/tasyncrecursion.nim b/tests/async/tasyncrecursion.nim
index 1aeebe9b4..7c12dbb0e 100644
--- a/tests/async/tasyncrecursion.nim
+++ b/tests/async/tasyncrecursion.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tasyncrecursion.nim"
-  output: "50005000"
+output: "50005000"
 """
 import asyncdispatch
 
@@ -16,7 +15,7 @@ proc asyncRecursionTest*(): Future[int] {.async.} =
     inc(result, await asyncRecursionCycle(i))
     inc(i)
 
-when isMainModule:
+when true:
   setGlobalDispatcher(newDispatcher())
   var i = waitFor asyncRecursionTest()
   echo i
diff --git a/tests/async/tasyncsend4757.nim b/tests/async/tasyncsend4757.nim
index 752bb3e75..a87c5df95 100644
--- a/tests/async/tasyncsend4757.nim
+++ b/tests/async/tasyncsend4757.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tasyncsend4754.nim"
-  output: "Finished"
+output: "Finished"
 """
 
 import asyncdispatch, asyncnet
diff --git a/tests/async/tasyncssl.nim b/tests/async/tasyncssl.nim
index 212260922..88a5eb32e 100644
--- a/tests/async/tasyncssl.nim
+++ b/tests/async/tasyncssl.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tasyncssl.nim"
   cmd: "nim $target --hints:on --define:ssl $options $file"
   output: "500"
   disabled: "windows"
diff --git a/tests/async/tasynctry.nim b/tests/async/tasynctry.nim
index 0fe9efdc1..b13c57951 100644
--- a/tests/async/tasynctry.nim
+++ b/tests/async/tasynctry.nim
@@ -1,7 +1,5 @@
 discard """
-  file: "tasynctry.nim"
-  exitcode: 0
-  output: '''
+output: '''
 Generic except: Test
 Specific except
 Multiple idents in except
diff --git a/tests/async/tawaitsemantics.nim b/tests/async/tawaitsemantics.nim
index 98fb5dfd5..67903cc5e 100644
--- a/tests/async/tawaitsemantics.nim
+++ b/tests/async/tawaitsemantics.nim
@@ -1,7 +1,5 @@
 discard """
-  file: "tawaitsemantics.nim"
-  exitcode: 0
-  output: '''
+output: '''
 Error can be caught using yield
 Infix `or` raises
 Infix `and` raises
diff --git a/tests/async/tfuturestream.nim b/tests/async/tfuturestream.nim
index 69ad80f47..b5772d5ac 100644
--- a/tests/async/tfuturestream.nim
+++ b/tests/async/tfuturestream.nim
@@ -1,7 +1,5 @@
 discard """
-  file: "tfuturestream.nim"
-  exitcode: 0
-  output: '''
+output: '''
 0
 1
 2
@@ -70,4 +68,4 @@ waitFor testCompletion()
 
 #   echo("Finished")
 
-# waitFor omega()
\ No newline at end of file
+# waitFor omega()
diff --git a/tests/async/tioselectors.nim b/tests/async/tioselectors.nim
index 7a8986644..be6d3a167 100644
--- a/tests/async/tioselectors.nim
+++ b/tests/async/tioselectors.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tioselectors.nim"
   output: "All tests passed!"
 """
 import selectors
diff --git a/tests/async/tnewasyncudp.nim b/tests/async/tnewasyncudp.nim
index b442c0524..7dbd5a3d0 100644
--- a/tests/async/tnewasyncudp.nim
+++ b/tests/async/tnewasyncudp.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tnewasyncudp.nim"
   output: "5000"
 """
 import asyncdispatch, nativesockets, net, strutils, os
diff --git a/tests/async/tpendingcheck.nim b/tests/async/tpendingcheck.nim
index 825acb613..a5537d8cb 100644
--- a/tests/async/tpendingcheck.nim
+++ b/tests/async/tpendingcheck.nim
@@ -1,6 +1,4 @@
 discard """
-  file: "tpendingcheck.nim"
-  exitcode: 0
   output: ""
 """
 
@@ -18,4 +16,3 @@ while not f.finished:
 f.read
 
 doAssert(not hasPendingOperations())
-
diff --git a/tests/async/twinasyncrw.nim b/tests/async/twinasyncrw.nim
index 94193e921..64c5d6c26 100644
--- a/tests/async/twinasyncrw.nim
+++ b/tests/async/twinasyncrw.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "twinasyncrw.nim"
   output: "5000"
 """
 when defined(windows):
diff --git a/tests/benchmark.nim b/tests/benchmark.nim
deleted file mode 100644
index 69c9a3927..000000000
--- a/tests/benchmark.nim
+++ /dev/null
@@ -1,47 +0,0 @@
-#
-#
-#            Nim Benchmark tool
-#        (c) Copyright 2012 Dominik Picheta
-#
-#    See the file "copying.txt", included in this
-#    distribution, for details about the copyright.
-#
-
-## This program runs benchmarks
-import osproc, os, times, json
-
-type
-  TBenchResult = tuple[file: string, success: bool, time: float]
-
-proc compileBench(file: string) =
-  ## Compiles ``file``.
-  doAssert(execCmdEx("nim c -d:release " & file).exitCode == QuitSuccess)
-
-proc runBench(file: string): TBenchResult =
-  ## Runs ``file`` and returns info on how long it took to run.
-  var start = epochTime()
-  if execCmdEx(file.addFileExt(ExeExt)).exitCode == QuitSuccess:
-    var t = epochTime() - start
-    result = (file, true, t)
-  else: result = (file, false, -1.0)
-
-proc genOutput(benches: seq[TBenchResult]): PJsonNode =
-  result = newJObject()
-  for i in benches:
-    if i.success:
-      result[i.file.extractFilename] = newJFloat(i.time)
-    else:
-      result[i.file.extractFilename] = newJNull()
-
-proc doBench(): seq[TBenchResult] =
-  result = @[]
-  for i in walkFiles("tests/benchmarks/*.nim"):
-    echo(i.extractFilename)
-    compileBench(i)
-    result.add(runBench(i))
-
-when isMainModule:
-  var b = doBench()
-  var output = genOutput(b)
-  writeFile("benchmarkResults.json", pretty(output))
-
diff --git a/tests/benchmarks/fannkuch.nim b/tests/benchmarks/fannkuch.nim
deleted file mode 100644
index c87295092..000000000
--- a/tests/benchmarks/fannkuch.nim
+++ /dev/null
@@ -1,69 +0,0 @@
-import os
-import strutils
-
-proc fannkuch(n: int): int =
-    var
-        count: seq[int]
-        maxFlips = 0
-        m = n-1
-        r = n
-        check = 0
-        perm1: seq[int]
-        perm: seq[int]
-
-    newSeq(count, n+1)
-    newSeq(perm1, n)
-    newSeq(perm, n)
-    for i in 0 .. n-1:
-        count[i] = i+1
-        perm1[i] = i
-        perm[i]  = i
-    count[n] = n+1
-
-    while true:
-        if check < 30:
-            for i in items(perm1):
-                write(stdout, $(i+1))
-            echo("")
-            inc(check)
-
-        while r != 1:
-            count[r-1] = r
-            dec (r)
-
-        if perm1[0] != 0 and perm1[m] != m:
-            # perm = perm1
-            # The above line is between 3 and 4 times slower than the loop below!
-            for i in 0 .. n-1:
-                perm[i] = perm1[i]
-            var flipsCount = 0
-            var k = perm[0]
-            while k != 0:
-                for i in 0 .. (k div 2):
-                    swap(perm[i], perm[k-i])
-                inc(flipsCount)
-                k = perm[0]
-
-            if flipsCount > maxFlips:
-                maxFlips = flipsCount
-
-        block makePerm:
-            while r != n:
-                var tmp = perm1[0]
-                # # perm1.delete (0)
-                # # perm1.insert (tmp, r)
-                # # The above is about twice as slow as the following:
-                # moveMem (addr (perm1[0]), addr (perm1[1]), r * sizeof (int))
-                # The call to moveMem is about 50% slower than the loop below!
-                for i in 0 .. r-1:
-                    perm1[i] = perm1[i+1]
-                perm1[r] = tmp
-
-                dec(count[r])
-                if count[r] > 0:
-                    break makePerm
-                inc(r)
-            return maxFlips
-
-var n = 10
-echo("Pfannkuchen(" & $n & ") = " & $fannkuch(n))
diff --git a/tests/benchmarks/quicksort.nim b/tests/benchmarks/quicksort.nim
deleted file mode 100644
index 114321492..000000000
--- a/tests/benchmarks/quicksort.nim
+++ /dev/null
@@ -1,54 +0,0 @@
-import os
-import strutils
-
-# Generate some pseudo-random data
-var seed: tuple[s1, s2, s3: int32] = (2'i32, 8'i32, 16'i32)
-
-proc random(): int32 =
-    seed = (((((((seed[0] and 0x0007_FFFF'i32) shl 13'i32) xor seed[0]) shr
-               19'i32) and 0x0000_1FFF'i32) xor
-             ((seed[0] and 0x000F_FFFE'i32) shl 12'i32)),
-
-            ((((((seed[1] and 0x3FFF_FFFF'i32) shl  2'i32) xor seed[1]) shr
-               25'i32) and 0x0000_007F'i32) xor
-             ((seed[1] and 0x0FFF_FFF8'i32) shl  4'i32)),
-
-            ((((((seed[2] and 0x1FFF_FFFF'i32) shl  3'i32) xor seed[2]) shr
-               11'i32) and 0x001F_FFFF'i32) xor
-             ((seed[2] and 0x0000_7FF0'i32) shl 17'i32)))
-    return seed[0] xor seed[1] xor seed[2]
-
-var n = 9999999
-
-var data: seq[int32]
-newSeq(data, n)
-for i in 0 .. data.high():
-    data[i] = random()
-
-
-proc `$`(d: seq[int32]): string =
-    result = "[ "
-    for i in items(d):
-        result.addSep(", ", 2)
-        result.add($(i and 0xFFFF_FFFF'i64))
-    result.add(" ]")
-
-# Sort the data
-proc sort(start, stop: int) =
-    if stop <= start+1:
-        return
-
-    var j = start
-    for i in start..stop-2:
-        if data[i] <% data[stop-1]:
-            swap(data[i], data[j])
-            inc(j)
-    swap(data[j], data[stop-1])
-
-    sort(start, j)
-    sort(j+1, stop)
-
-sort(0, data.len)
-echo(data[n div 2 - 1] and 0xFFFF_FFFF'i64, ", ",
-     data[n div 2] and 0xFFFF_FFFF'i64, ", ",
-     data[n div 2 + 1] and 0xFFFF_FFFF'i64)
diff --git a/tests/bind/tbind.nim b/tests/bind/tbind.nim
index 6fcf95433..49c37ae2e 100644
--- a/tests/bind/tbind.nim
+++ b/tests/bind/tbind.nim
@@ -1,7 +1,5 @@
 discard """
-  file: "tbind.nim"
-  output:
-'''
+output: '''
 3
 1
 1
diff --git a/tests/bind/tbind2.nim b/tests/bind/tbind2.nim
index 799b14381..fc2eeda1a 100644
--- a/tests/bind/tbind2.nim
+++ b/tests/bind/tbind2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "ambiguous call"
   file: "tbind2.nim"
   line: 12
-  errormsg: "ambiguous call"
 """
 # Test the new ``bind`` keyword for templates
 
@@ -12,6 +12,3 @@ template tempBind(x, y): untyped =
   (bind p1(x, y))  #ERROR_MSG ambiguous call
 
 echo tempBind(1'i8, 2'i8)
-
-
-
diff --git a/tests/bind/tdatabind.nim b/tests/bind/tdatabind.nim
index 124faee6f..f6455749c 100644
--- a/tests/bind/tdatabind.nim
+++ b/tests/bind/tdatabind.nim
@@ -74,7 +74,7 @@ proc propertyBind*[T](p1: var TProperty[T], p2: var TProperty[T]) =
 proc `->`[T](p1: var TProperty[T], p2: var TProperty[T]) =
   propertyBind(p2,p1)
 
-when isMainModule:
+when true:
   # Initial value testing
   var myProp = newProperty(5)
 
diff --git a/tests/bind/tinvalidbindtypedesc.nim b/tests/bind/tinvalidbindtypedesc.nim
index ecdd12603..4bcd4e39d 100644
--- a/tests/bind/tinvalidbindtypedesc.nim
+++ b/tests/bind/tinvalidbindtypedesc.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 10
   errormsg: "type mismatch: got <type float, string>"
+  line: 10
 """
 
 proc foo(T: typedesc; some: T) =
@@ -8,4 +8,3 @@ proc foo(T: typedesc; some: T) =
 
 foo int, 4
 foo float, "bad"
-
diff --git a/tests/bind/tnicerrorforsymchoice.nim b/tests/bind/tnicerrorforsymchoice.nim
index 8c3a99c97..f16b323de 100644
--- a/tests/bind/tnicerrorforsymchoice.nim
+++ b/tests/bind/tnicerrorforsymchoice.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 18
   errormsg: "type mismatch: got <proc (s: TScgi: ScgiState or AsyncScgiState) | proc (client: AsyncSocket, headers: StringTableRef, input: string){.noSideEffect, gcsafe, locks: 0.}>"
+  line: 18
 """
 
 #bug #442
diff --git a/tests/borrow/tinvalidborrow.nim b/tests/borrow/tinvalidborrow.nim
index 9ab9e8d64..89aa4e2e8 100644
--- a/tests/borrow/tinvalidborrow.nim
+++ b/tests/borrow/tinvalidborrow.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 11
   errormsg: "no symbol to borrow from found"
+  line: 11
 """
 
 # bug #516
@@ -14,4 +14,3 @@ var
   d, e: TAtom
 
 echo( $(d == e) )
-
diff --git a/tests/caas/absurd_nesting.nim b/tests/caas/absurd_nesting.nim
deleted file mode 100644
index 136d65cc7..000000000
--- a/tests/caas/absurd_nesting.nim
+++ /dev/null
@@ -1,29 +0,0 @@
-# Tries to test the full ownership path generated by idetools.
-
-proc lev1(t1: string) =
-  var temp = t1
-  for i in 0..len(temp)-1:
-    temp[i] = chr(int(temp[i]) + 1)
-
-  proc lev2(t2: string) =
-    var temp = t2
-    for i in 0..len(temp)-1:
-      temp[i] = chr(int(temp[i]) + 1)
-
-    proc lev3(t3: string) =
-      var temp = t3
-      for i in 0..len(temp)-1:
-        temp[i] = chr(int(temp[i]) + 1)
-
-      proc lev4(t4: string) =
-        var temp = t4
-        for i in 0..len(temp)-1:
-          temp[i] = chr(int(temp[i]) + 1)
-
-        echo temp & "(lev4)"
-      lev4(temp & "(lev3)")
-    lev3(temp & "(lev2)")
-  lev2(temp & "(lev1)")
-
-when isMainModule:
-  lev1("abcd")
diff --git a/tests/caas/absurd_nesting.txt b/tests/caas/absurd_nesting.txt
deleted file mode 100644
index 986e34836..000000000
--- a/tests/caas/absurd_nesting.txt
+++ /dev/null
@@ -1,29 +0,0 @@
-absurd_nesting.nim
-
-> c --verbosity:0 --hints:on
-SuccessX
-
-> idetools --track:$TESTNIM,6,6 --def $SILENT
-skVar\tabsurd_nesting.lev1.temp\tstring
-
-> idetools --track:$TESTNIM,21,13 --def $SILENT
-skVar\tabsurd_nesting.lev1.lev2.lev3.lev4.temp\tstring
-
-> idetools --track:$TESTNIM,6,27 --def $SILENT
-skForVar\tabsurd_nesting.lev1.i\tint
-
-> idetools --track:$TESTNIM,21,33 --def $SILENT
-skForVar\tabsurd_nesting.lev1.lev1.lev3.lev4.i\tint
-
-> idetools --track:$TESTNIM,24,8 --def $SILENT
-skProc\tabsurd_nesting.lev1.lev1.lev3.lev4\tproc \(string\)
-
-> idetools --track:$TESTNIM,4,13 --def $SILENT
-skParam\tabsurd_nesting.lev1.t1\tstring
-
-> idetools --track:$TESTNIM,4,13 --def $SILENT
-skParam\tabsurd_nesting.lev1.t1\tstring
-
-> idetools --track:$TESTNIM,19,19 --def $SILENT
-skParam\tabsurd_nesting.lev1.lev2.lev3.lev4.t4\tstring
-
diff --git a/tests/caas/basic-recompile.txt b/tests/caas/basic-recompile.txt
deleted file mode 100644
index 620e0c059..000000000
--- a/tests/caas/basic-recompile.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-main.nim
-> c --verbosity:0 --hints:on
-SuccessX
-# The "Processing" string will be found always in proc mode since each
-# compilation command will generate it. We need to test it only in Caas mode to
-# verify the server is not recompiling again the file.
-CaasRun > c --verbosity:0 --hints:on
-CaasRun ! Processing
-CaasRun SuccessX
-
diff --git a/tests/caas/compile-suggest.txt b/tests/caas/compile-suggest.txt
deleted file mode 100644
index 378320014..000000000
--- a/tests/caas/compile-suggest.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-main.nim
-> c --verbosity:0 --hints:on
-SuccessX
-> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT
-skField\tx
-skField\ty
-
diff --git a/tests/caas/compile-then-def.txt b/tests/caas/compile-then-def.txt
deleted file mode 100644
index 72ba46b04..000000000
--- a/tests/caas/compile-then-def.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-main.nim
-> c --verbosity:0 --hints:on
-SuccessX
-
-> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
-strutils.toUpper
-! SuccessX
-
-> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
-strutils.toUpper
-! SuccessX
diff --git a/tests/caas/completion_dot_syntax.txt b/tests/caas/completion_dot_syntax.txt
deleted file mode 100644
index 4a975e5df..000000000
--- a/tests/caas/completion_dot_syntax.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-completion_dot_syntax_main.nim
-> idetools --track:$TESTNIM,24,15 --def
-def\tskProc\t$MODULE.echoRemainingDollars
-> idetools --trackDirty:completion_dot_syntax_dirty.nim,$TESTNIM,25,12 --suggest
-sug\tskProc\techoRemainingDollars
-# The suggestion should not mention the other echoRemaining* variants.
-!echoRemainingEuros
-!echoRemainingBugs
-
diff --git a/tests/caas/completion_dot_syntax_dirty.nim b/tests/caas/completion_dot_syntax_dirty.nim
deleted file mode 100644
index 6237c4e79..000000000
--- a/tests/caas/completion_dot_syntax_dirty.nim
+++ /dev/null
@@ -1,25 +0,0 @@
-import strutils
-
-# Verifies if the --suggestion switch differentiates types for dot notation.
-
-type
-  TDollar = distinct int
-  TEuro = distinct int
-
-proc echoRemainingDollars(amount: TDollar) =
-  echo "You have $1 dollars" % [$int(amount)]
-
-proc echoRemainingEuros(amount: TEuro) =
-  echo "You have $1 euros" % [$int(amount)]
-
-proc echoRemainingBugs() =
-  echo "You still have bugs"
-
-proc main =
-  var
-    d: TDollar
-    e: TEuro
-  d = TDollar(23)
-  e = TEuro(32)
-  d.echoRemainingDollars()
-  e.echoRemai
diff --git a/tests/caas/completion_dot_syntax_main.nim b/tests/caas/completion_dot_syntax_main.nim
deleted file mode 100644
index 0be8c7f4f..000000000
--- a/tests/caas/completion_dot_syntax_main.nim
+++ /dev/null
@@ -1,24 +0,0 @@
-import strutils
-
-# Verifies if the --suggestion switch differentiates types for dot notation.
-
-type
-  TDollar = distinct int
-  TEuro = distinct int
-
-proc echoRemainingDollars(amount: TDollar) =
-  echo "You have $1 dollars" % [$int(amount)]
-
-proc echoRemainingEuros(amount: TEuro) =
-  echo "You have $1 euros" % [$int(amount)]
-
-proc echoRemainingBugs() =
-  echo "You still have bugs"
-
-proc main =
-  var
-    d: TDollar
-    e: TEuro
-  d = TDollar(23)
-  e = TEuro(32)
-  d.echoRemainingDollars()
diff --git a/tests/caas/def-def-compile.txt b/tests/caas/def-def-compile.txt
deleted file mode 100644
index 21d5ea962..000000000
--- a/tests/caas/def-def-compile.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-main.nim
-> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
-strutils.toUpper
-! SuccessX
-
-> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
-strutils.toUpper
-! SuccessX
-
-> c --verbosity:0 --hints:on
-SuccessX
-
diff --git a/tests/caas/def-then-compile.txt b/tests/caas/def-then-compile.txt
deleted file mode 100644
index 2214bf02c..000000000
--- a/tests/caas/def-then-compile.txt
+++ /dev/null
@@ -1,8 +0,0 @@
-main.nim
-> idetools --track:$TESTNIM,5,18 --def --verbosity:0 --hints:on
-strutils.toUpper
-! SuccessX
-
-> c --verbosity:0 --hints:on
-SuccessX
-
diff --git a/tests/caas/forward_declarations.nim b/tests/caas/forward_declarations.nim
deleted file mode 100644
index 177d82f20..000000000
--- a/tests/caas/forward_declarations.nim
+++ /dev/null
@@ -1,15 +0,0 @@
-# This example shows that idetools returns an empty signature for a forward
-# declared proc in proc/symproc runs, but correctly returns the full signature
-# in caas mode.
-
-proc echoHello(text: string)
-
-proc testForward() =
-  echo "T"
-  echoHello("T")
-
-proc echoHello(text: string) =
-  echo "Hello Mr." & text
-
-when isMainModule:
-  testForward()
diff --git a/tests/caas/forward_declarations.txt b/tests/caas/forward_declarations.txt
deleted file mode 100644
index b1695b9c7..000000000
--- a/tests/caas/forward_declarations.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-forward_declarations.nim
-
-> idetools --track:$TESTNIM,9,5 --def $SILENT
-skProc
-proc \(string\)
-
-> idetools --track:$TESTNIM,5,9 --def $SILENT
-skProc
-proc \(string\)
diff --git a/tests/caas/forward_usages.txt b/tests/caas/forward_usages.txt
deleted file mode 100644
index 05ef517dc..000000000
--- a/tests/caas/forward_usages.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-forward_declarations.nim
-
-> c --verbosity:0 --hints:on
-SuccessX
-
-# None of the following return three instances of the echoHello proc, the first
-# being the forward declaration, the second being the usage inside testForward,
-# and the third being the actual implementation.
-
-> idetools --track:$TESTNIM,5,5 --usages $SILENT
-skProc.*\n.*skProc.*\n.*skProc
-
-> idetools --track:$TESTNIM,9,5 --usages $SILENT
-skProc.*\n.*skProc.*\n.*skProc
-
-> idetools --track:$TESTNIM,11,5 --usages $SILENT
-skProc.*\n.*skProc.*\n.*skProc
diff --git a/tests/caas/idetools_api.nim b/tests/caas/idetools_api.nim
deleted file mode 100644
index 281e562d7..000000000
--- a/tests/caas/idetools_api.nim
+++ /dev/null
@@ -1,84 +0,0 @@
-import unicode, sequtils, macros, re
-
-proc test_enums() =
-  var o: Tfile
-  if o.open("files " & "test.txt", fmWrite):
-    o.write("test")
-    o.close()
-
-proc test_iterators(filename = "tests.nim") =
-  let
-    input = readFile(filename)
-    letters = toSeq(runes(string(input)))
-  for letter in letters: echo int(letter)
-
-const SOME_SEQUENCE = @[1, 2]
-type
-  bad_string = distinct string
-  TPerson = object of TObject
-    name*: bad_string
-    age: int
-
-proc adder(a, b: int): int =
-  result = a + b
-
-type
-  PExpr = ref object of TObject ## abstract base class for an expression
-  PLiteral = ref object of PExpr
-    x: int
-  PPlusExpr = ref object of PExpr
-    a, b: PExpr
-
-# watch out: 'eval' relies on dynamic binding
-method eval(e: PExpr): int =
-  # override this base method
-  quit "to override!"
-
-method eval(e: PLiteral): int = e.x
-method eval(e: PPlusExpr): int = eval(e.a) + eval(e.b)
-
-proc newLit(x: int): PLiteral = PLiteral(x: x)
-proc newPlus(a, b: PExpr): PPlusExpr = PPlusExpr(a: a, b: b)
-
-echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
-
-proc findVowelPosition(text: string) =
-  var found = -1
-  block loops:
-    for i, letter in pairs(text):
-      for j in ['a', 'e', 'i', 'o', 'u']:
-        if letter == j:
-          found = i
-          break loops # leave both for-loops
-  echo found
-
-findVowelPosition("Zerg") # should output 1, position of vowel.
-
-macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} =
-  ## Expect docstrings
-  let exp = callsite()
-  template expectBody(errorTypes, lineInfoLit: expr,
-                      body: stmt): NimNode {.dirty.} =
-    try:
-      body
-      assert false
-    except errorTypes:
-      nil
-
-  var body = exp[exp.len - 1]
-
-  var errorTypes = newNimNode(nnkBracket)
-  for i in countup(1, exp.len - 2):
-    errorTypes.add(exp[i])
-
-  result = getAst(expectBody(errorTypes, exp.lineinfo, body))
-
-proc err =
-  raise newException(EArithmetic, "some exception")
-
-proc testMacro() =
-  expect(EArithmetic):
-    err()
-
-testMacro()
-let notAModule = re"(\w+)=(.*)"
diff --git a/tests/caas/idetools_api.txt b/tests/caas/idetools_api.txt
deleted file mode 100644
index 035590dc3..000000000
--- a/tests/caas/idetools_api.txt
+++ /dev/null
@@ -1,59 +0,0 @@
-idetools_api.nim
-> c --verbosity:0 --hints:on
-SuccessX
-> idetools --track:$TESTNIM,4,11 --def $SILENT
-def\tskType\tsystem.TFile\tTFile
-> idetools --track:$TESTNIM,5,7 --def $SILENT
-def\tskProc\tsystem.Open\tproc \(var TFile, string, TFileMode, int\): bool
-> idetools --track:$TESTNIM,5,21 --def $SILENT
-def\tskProc\tsystem.\&\tproc \(string, string\): string\{.noSideEffect.\}
-> idetools --track:$TESTNIM,5,38 --def $SILENT
-def\tskEnumField\tsystem.TFileMode.fmWrite\tTFileMode
-> idetools --track:$TESTNIM,7,6 --def $SILENT
-def\tskProc\tsystem.Close\tproc \(TFile\)
-> idetools --track:$TESTNIM,12,23 --def $SILENT
-def\tskIterator\tunicode.runes\titerator \(string\): TRune
-> idetools --track:$TESTNIM,12,15 --def $SILENT
-def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr
-> idetools --track:$TESTNIM,15,7 --def $SILENT
-
-# ProcRun mode will fail the next line, because the type is returned empty.
-def\tskConst\t$MODULE.SOME_SEQUENCE\tseq\[int\]\t
-> idetools --track:$TESTNIM,15,23 --def $SILENT
-def\tskProc\tsystem.@\tproc \(array\[IDX, T\]\): seq\[T\]\{.noSideEffect.\}
-> idetools --track:$TESTNIM,17,3 --def $SILENT
-
-# ProcRun mode will fail the next line, because the type is returned empty.
-def\tskType\t$MODULE.bad_string\tbad_string\t
-> idetools --track:$TESTNIM,11,24 --def $SILENT
-def\tskParam\t$MODULE.test_iterators.filename\tstring
-> idetools --track:$TESTNIM,6,5 --def $SILENT
-def\tskVar\t$MODULE.test_enums.o\tTFile
-> idetools --track:$TESTNIM,12,34 --def $SILENT
-def\tskLet\t$MODULE.test_iterators.input\tTaintedString
-> idetools --track:$TESTNIM,13,35 --def $SILENT
-def\tskForVar\t$MODULE.test_iterators.letter\tTRune
-> idetools --track:$TESTNIM,23,3 --def $SILENT
-def\tskResult\t$MODULE.adder.result\tint
-> idetools --track:$TESTNIM,19,6 --def $SILENT
-
-# ProcRun mode will fail the next line, because the type is returned empty.
-def\tskField\t$MODULE.TPerson.name\tbad_string\t
-
-> idetools --track:$TESTNIM,43,7 --def $SILENT
-def\tskMethod\t$MODULE.eval\tproc \(PPlusExpr\): int\t
-
-> idetools --track:$TESTNIM,47,8 --def $SILENT
-def\tskLabel\t$MODULE.findVowelPosition.loops\t\t
-# For some reason the use of the label with break displaces its position.
-> idetools --track:$TESTNIM,52,16 --def $SILENT
-def\tskLabel\t$MODULE.findVowelPosition.loops\t\t
-
-# Displaced macro usage by one character.
-> idetools --track:$TESTNIM,80,2 --def $SILENT
-def\tskMacro\t$MODULE.expect\tproc \(varargs\[expr\], stmt\): stmt\t
-
-# The syntax for extended raw string literals should not be returned as module
-# but as the proc re() inside the re module.
-> idetools --track:$TESTNIM,84,17 --def $SILENT
-!def\tskModule
diff --git a/tests/caas/imported.nim b/tests/caas/imported.nim
deleted file mode 100644
index a4bc5c0e6..000000000
--- a/tests/caas/imported.nim
+++ /dev/null
@@ -1,3 +0,0 @@
-proc `+++`*(a,b: string): string =
-  return a & "  " & b
-
diff --git a/tests/caas/issue_416_template_shift.nim b/tests/caas/issue_416_template_shift.nim
deleted file mode 100644
index d52f611d6..000000000
--- a/tests/caas/issue_416_template_shift.nim
+++ /dev/null
@@ -1,17 +0,0 @@
-import unicode, sequtils
-
-proc test() =
-  let input = readFile("weird.nim")
-  for letter in runes(string(input)):
-    echo int(letter)
-
-when 1 > 0:
-  proc failtest() =
-    let
-      input = readFile("weird.nim")
-      letters = toSeq(runes(string(input)))
-    for letter in letters:
-      echo int(letter)
-
-when isMainModule:
-  test()
diff --git a/tests/caas/issue_416_template_shift.txt b/tests/caas/issue_416_template_shift.txt
deleted file mode 100644
index e911c1360..000000000
--- a/tests/caas/issue_416_template_shift.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-issue_416_template_shift.nim
-> c --verbosity:0 --hints:on
-SuccessX
-> idetools --track:$TESTNIM,12,28 --def $SILENT
-def\tskType\tsystem.string\tstring
-> idetools --track:$TESTNIM,12,35 --def $SILENT
-def\tskLet\t$MODULE.failtest.input\tTaintedString
-
-# The following fail because they seem shifted one column to the right.
-> idetools --track:$TESTNIM,12,16 --def $SILENT
-def\tskTemplate\tsequtils.toSeq\tproc \(expr\): expr
-> idetools --track:$TESTNIM,12,22 --def $SILENT
-def\tskIterator\tunicode.runes\titerator \(string\): TRune
-
diff --git a/tests/caas/issue_452_export_shift.nim b/tests/caas/issue_452_export_shift.nim
deleted file mode 100644
index 46cff6241..000000000
--- a/tests/caas/issue_452_export_shift.nim
+++ /dev/null
@@ -1,8 +0,0 @@
-const
-  VERSION_STR1* = "0.5.0" ## Idetools shifts this one column.
-  VERSION_STR2 = "0.5.0" ## This one is ok.
-  VERSION_STR3* = "0.5.0" ## Bad.
-  VERSION_STR4 = "0.5.0" ## Ok.
-
-proc forward1*(): string = result = ""
-proc forward2(): string = result = ""
diff --git a/tests/caas/issue_452_export_shift.txt b/tests/caas/issue_452_export_shift.txt
deleted file mode 100644
index 4676ed71e..000000000
--- a/tests/caas/issue_452_export_shift.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-issue_452_export_shift.nim
-> c --verbosity:0 --hints:on
-SuccessX
-> idetools --track:$TESTNIM,2,2 --def $SILENT
-def\tskConst\t$MODULE.VERSION_STR1\tstring
-> idetools --track:$TESTNIM,3,2 --def $SILENT
-def\tskConst\t$MODULE.VERSION_STR2\tstring
-> idetools --track:$TESTNIM,7,5 --def $SILENT
-def\tskProc\t$MODULE.forward1\tproc \(\): string\t
-> idetools --track:$TESTNIM,8,5 --def $SILENT
-def\tskProc\t$MODULE.forward2\tproc \(\): string\t
diff --git a/tests/caas/issue_477_dynamic_dispatch.nim b/tests/caas/issue_477_dynamic_dispatch.nim
deleted file mode 100644
index 6e6b21ef0..000000000
--- a/tests/caas/issue_477_dynamic_dispatch.nim
+++ /dev/null
@@ -1,19 +0,0 @@
-type
-  TThing = object of TObject
-  TUnit = object of TThing
-    x: int
-
-method collide(a, b: TThing) {.inline.} =
-  quit "to override!"
-
-method collide(a: TThing, b: TUnit) {.inline.} =
-  echo "collide1"
-
-method collide(a: TUnit, b: TThing) {.inline.} =
-  echo "collide2"
-
-var
-  a, b: TUnit
-
-when isMainModule:
-  collide(a, b) # output: 2
diff --git a/tests/caas/issue_477_dynamic_dispatch.txt b/tests/caas/issue_477_dynamic_dispatch.txt
deleted file mode 100644
index 12fd750de..000000000
--- a/tests/caas/issue_477_dynamic_dispatch.txt
+++ /dev/null
@@ -1,5 +0,0 @@
-issue_477_dynamic_dispatch.nim
-> c --run
-SuccessX
-> idetools --track:issue_477_dynamic_dispatch.nim,19,5 --def $SILENT
-def\tskMethod\tissue_477_dynamic_dispatch.collide\tproc \(TUnit, TThing\)\{.inline.\}
diff --git a/tests/caas/its_full_of_procs.nim b/tests/caas/its_full_of_procs.nim
deleted file mode 100644
index 8f8b66764..000000000
--- a/tests/caas/its_full_of_procs.nim
+++ /dev/null
@@ -1,29 +0,0 @@
-import unicode, sequtils
-
-# This example shows that idetools returns proc as signature for everything
-# which can be called. While a clever person would use the second column to
-# differentiate between procs, methods and others, why does the output contain
-# incorrect information?
-
-type
-  TThing = object of TObject
-  TUnit = object of TThing
-    x: int
-
-method collide(a, b: TThing) {.inline.} =
-  quit "to override!"
-
-method collide(a: TThing, b: TUnit) {.inline.} =
-  echo "1"
-
-method collide(a: TUnit, b: TThing) {.inline.} =
-  echo "2"
-
-var
-  a, b: TUnit
-
-let
-  input = readFile("its_full_of_procs.nim")
-  letters = toSeq(runes(string(input)))
-
-collide(a, b) # output: 2
diff --git a/tests/caas/its_full_of_procs.txt b/tests/caas/its_full_of_procs.txt
deleted file mode 100644
index 31a2d3baa..000000000
--- a/tests/caas/its_full_of_procs.txt
+++ /dev/null
@@ -1,20 +0,0 @@
-its_full_of_procs.nim
-
-> idetools --track:$TESTNIM,26,15 --def $SILENT
-skProc
-proc \(
-
-> idetools --track:$TESTNIM,27,21 --def $SILENT
-skIterator
-iterator \(
-!proc \(
-
-> idetools --track:$TESTNIM,29,0 --def $SILENT
-skMethod
-method \(
-!proc \(
-
-> idetools --track:$TESTNIM,27,15 --def $SILENT
-skTemplate
-template \(
-!proc \(
diff --git a/tests/caas/main.nim b/tests/caas/main.nim
deleted file mode 100644
index fafeff93b..000000000
--- a/tests/caas/main.nim
+++ /dev/null
@@ -1,7 +0,0 @@
-import imported, strutils
-
-proc main =
-  var t1 = "text"
-  var t2 = t1.toUpper
-  echo(t1 +++ t2)
-
diff --git a/tests/caas/main_dirty.nim b/tests/caas/main_dirty.nim
deleted file mode 100644
index 95fb6c624..000000000
--- a/tests/caas/main_dirty.nim
+++ /dev/null
@@ -1,14 +0,0 @@
-import imported, strutils
-
-type
-  TFoo = object
-    x: int
-    y: string
-
-proc main =
-  var t1 = "text"
-  var t2 = t1.toUpper
-  var foo = TFoo(x: 10, y: "test")
-  foo.
-  echo(t1 +++ t2)
-
diff --git a/tests/caas/suggest-compile.txt b/tests/caas/suggest-compile.txt
deleted file mode 100644
index a322908ac..000000000
--- a/tests/caas/suggest-compile.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-main.nim
-# This example shows how the suggest feature can be used on a partial file
-# using the --trackDirty switch.
-> idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT
-skField\tx
-skField\ty
-# Repeating the query in caas should work always and retrieve same output.
-CaasRun > idetools --trackDirty:main_dirty.nim,$TESTNIM,12,7 --suggest $SILENT
-CaasRun skField\tx
-CaasRun skField\ty
-> c --verbosity:0 --hints:on
-SuccessX
-
diff --git a/tests/caas/suggest-invalid-source.txt b/tests/caas/suggest-invalid-source.txt
deleted file mode 100644
index 7f8f1213d..000000000
--- a/tests/caas/suggest-invalid-source.txt
+++ /dev/null
@@ -1,26 +0,0 @@
-main_dirty.nim
-# A variant of the suggest-compile.txt, instead of using a "base" correct
-# source, this one uses the "broken" main_dirty.nim which won't compile. The
-# test tries to stress idetools to still provide a valid answer if possible,
-# and at least provide the same output with repeated queries rather than dying
-# after the first compilation error.
-
-# The first query should work and provide valid suggestions.
-> idetools --track:$TESTNIM,12,6 --suggest $SILENT
-skField\tx
-skField\ty
-
-# Repeating the query should work too.
-> idetools --track:$TESTNIM,12,6 --suggest $SILENT
-skField\tx
-skField\ty
-
-# Expect now a compilation failure.
-> c
-!SuccessX
-invalid indentation
-
-# Repeating suggestions *after broken compilation* should work too.
-> idetools --track:$TESTNIM,12,6 --suggest $SILENT
-skField\tx
-skField\ty
diff --git a/tests/casestmt/t7699.nim b/tests/casestmt/t7699.nim
index ea08388eb..1354551c1 100644
--- a/tests/casestmt/t7699.nim
+++ b/tests/casestmt/t7699.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 13
   errormsg: "case statement cannot work on enums with holes for computed goto"
+  line: 13
 """
 
 type
diff --git a/tests/casestmt/tcaseexpr1.nim b/tests/casestmt/tcaseexpr1.nim
index 24543f1b8..4fdac8191 100644
--- a/tests/casestmt/tcaseexpr1.nim
+++ b/tests/casestmt/tcaseexpr1.nim
@@ -1,13 +1,17 @@
 discard """
-  file: "tcaseexpr1.nim"
-
-  line: 29
   errormsg: "type mismatch: got <string> but expected 'int'"
+  line: 33
+  file: "tcaseexpr1.nim"
 
-  line: 23
   errormsg: "not all cases are covered"
+  line: 27
+  file: "tcaseexpr1.nim"
 """
 
+# NOTE: This spec is wrong. Spec doesn't support multiple error
+# messages. The first one is simply overridden by the second one.
+# This just has never been noticed.
+
 type
   E = enum A, B, C
 
@@ -27,4 +31,3 @@ var t1 = case x:
 var t2 = case x:
   of A: 10
   of B, C: "23"
-
diff --git a/tests/casestmt/tcaseoverlaprange.nim b/tests/casestmt/tcaseoverlaprange.nim
index 3527c9385..e9651c69f 100644
--- a/tests/casestmt/tcaseoverlaprange.nim
+++ b/tests/casestmt/tcaseoverlaprange.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 13
   errormsg: "duplicate case label"
+  line: 13
 """
 
 type
diff --git a/tests/casestmt/tcaseoverlaprange2.nim b/tests/casestmt/tcaseoverlaprange2.nim
index 4a9479a5f..4a1cb3ea6 100644
--- a/tests/casestmt/tcaseoverlaprange2.nim
+++ b/tests/casestmt/tcaseoverlaprange2.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 13
   errormsg: "duplicate case label"
+  line: 13
 """
 
 
diff --git a/tests/casestmt/tcasestmt.nim b/tests/casestmt/tcasestmt.nim
index 333700197..465080e84 100644
--- a/tests/casestmt/tcasestmt.nim
+++ b/tests/casestmt/tcasestmt.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tcasestmt.nim"
-  output:
+output:
 '''
 Not found!
 Found!
@@ -226,4 +225,4 @@ block tcasestm:
         "invalid Y".quit(3)
         true
       else: raise newException(ValueError, "Invalid")
-  ))
\ No newline at end of file
+  ))
diff --git a/tests/ccgbugs/t8616.nim b/tests/ccgbugs/t8616.nim
index 54068652a..5fd940d3b 100644
--- a/tests/ccgbugs/t8616.nim
+++ b/tests/ccgbugs/t8616.nim
@@ -1,4 +1,4 @@
 import pkg8616 / scheduler
 
-when isMainModule:
+when true:
   init()
diff --git a/tests/ccgbugs/t8781.nim b/tests/ccgbugs/t8781.nim
index 1fa8ec8a5..884c6962a 100644
--- a/tests/ccgbugs/t8781.nim
+++ b/tests/ccgbugs/t8781.nim
@@ -18,7 +18,7 @@ type
     of false:
         region: float
 
-when isMainModule:
+when true:
   let r = 1.5
   let a = TypeOne(animatedU: true,
                   animated: false,
diff --git a/tests/ccgbugs/tcgbug.nim b/tests/ccgbugs/tcgbug.nim
index ffaa91ff3..eda475d4f 100644
--- a/tests/ccgbugs/tcgbug.nim
+++ b/tests/ccgbugs/tcgbug.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tcgbug.nim"
-  output: '''success
+output: '''
+success
 M1 M2
 '''
 """
@@ -74,5 +74,5 @@ proc newMyObjectRef(kind: MyKind, val: string): MyObjectRef =
     of M2: result.b = parseFloat(val)
     of M3: result.c = val
 
- 
-echo newMyObject(M1, "2").kind, " ", newMyObjectRef(M2, "3").kind
\ No newline at end of file
+
+echo newMyObject(M1, "2").kind, " ", newMyObjectRef(M2, "3").kind
diff --git a/tests/ccgbugs/tconstobj.nim b/tests/ccgbugs/tconstobj.nim
deleted file mode 100644
index 51cf661ee..000000000
--- a/tests/ccgbugs/tconstobj.nim
+++ /dev/null
@@ -1,16 +0,0 @@
-discard """
-  output: '''(FirstName: "James", LastName: "Franco")'''
-"""
-
-# bug #1547
-import tables
-
-type Person* = object
-    FirstName*: string
-    LastName*: string
-
-let people = {
-    "001": Person(FirstName: "James", LastName: "Franco")
-}.toTable()
-
-echo people["001"]
diff --git a/tests/ccgbugs/tgeneric_closure.nim b/tests/ccgbugs/tgeneric_closure.nim
index bb3b924b9..9f3c5b446 100644
--- a/tests/ccgbugs/tgeneric_closure.nim
+++ b/tests/ccgbugs/tgeneric_closure.nim
@@ -15,7 +15,7 @@ type
 proc mult(x:int, y:var int) =
   y = 2 * x
 
-when isMainModule:
+when true:
 
   var input = 1
   var output = 0
diff --git a/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim
index 919dc3fc1..3788b9985 100644
--- a/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim
+++ b/tests/ccgbugs/tgeneric_smallobj_asgn_opt.nim
@@ -1,5 +1,5 @@
 discard """
-  output: '''false'''
+  output: "done generic smallobj asgn opt"
 """
 
 # bug #5402
@@ -23,4 +23,5 @@ proc newListOfContainers[T](): ListOfContainers[T] =
   result.list = initDoublyLinkedList[Container[T]]()
 
 let q = newListOfContainers[int64]()
-echo q.contains(123)
+if not q.contains(123):
+  echo "done generic smallobj asgn opt"
diff --git a/tests/ccgbugs/tmarkerproc_regression.nim b/tests/ccgbugs/tmarkerproc_regression.nim
index 99b38e3ec..3b606b834 100644
--- a/tests/ccgbugs/tmarkerproc_regression.nim
+++ b/tests/ccgbugs/tmarkerproc_regression.nim
@@ -1,5 +1,5 @@
 discard """
-  output: "done"
+  output: "done markerproc regression"
 """
 
 type
@@ -42,6 +42,6 @@ proc main =
     let expected = $i & "some longer text here " & $i
     if a[i].ver.string != expected:
       quit "bug!"
-  echo "done"
+  echo "done markerproc regression"
 
 main()
diff --git a/tests/ccgbugs/tmissingbracket.nim b/tests/ccgbugs/tmissingbracket.nim
index d54983860..468e13366 100644
--- a/tests/ccgbugs/tmissingbracket.nim
+++ b/tests/ccgbugs/tmissingbracket.nim
@@ -1,6 +1,8 @@
 discard """
-  output: '''Subobject test called
-5'''
+output: '''
+Subobject test called
+5
+'''
 """
 
 type
@@ -49,4 +51,3 @@ var a: SubObject
 
 a.test()
 echo a.t
-
diff --git a/tests/ccgbugs/tmissinginit.nim b/tests/ccgbugs/tmissinginit.nim
index b4087008a..8806a2f21 100644
--- a/tests/ccgbugs/tmissinginit.nim
+++ b/tests/ccgbugs/tmissinginit.nim
@@ -27,4 +27,4 @@ echo bug()[0]
 echo bug()[0]
 echo bug()[0]
 
-when isMainModule: test()
+test()
diff --git a/tests/ccgbugs/tobjconstr_bad_aliasing.nim b/tests/ccgbugs/tobjconstr_bad_aliasing.nim
index ea51ecacb..9f6045364 100644
--- a/tests/ccgbugs/tobjconstr_bad_aliasing.nim
+++ b/tests/ccgbugs/tobjconstr_bad_aliasing.nim
@@ -22,5 +22,4 @@ proc dosomething(): seq[TThing] =
 
   result = @[TThing(data: 10, children: result)]
 
-when isMainModule:
-  echo($dosomething()[0])
+echo($dosomething()[0])
diff --git a/tests/clearmsg/tconsttypemismatch.nim b/tests/clearmsg/tconsttypemismatch.nim
index edf480348..727bfbffb 100644
--- a/tests/clearmsg/tconsttypemismatch.nim
+++ b/tests/clearmsg/tconsttypemismatch.nim
@@ -1,8 +1,7 @@
 discard """
+  errormsg: "type mismatch"
   file: "tconsttypemismatch.nim"
   line: 7
-  errormsg: "type mismatch"
 """
 # bug #2252
 const foo: int = 1000 / 30
-
diff --git a/tests/clearmsg/tmacroerrorproc.nim b/tests/clearmsg/tmacroerrorproc.nim
index cd9b15e25..86726af72 100644
--- a/tests/clearmsg/tmacroerrorproc.nim
+++ b/tests/clearmsg/tmacroerrorproc.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "Expected a node of kind nnkCharLit, got nnkCommand"
   file: "tmacroerrorproc.nim"
   line: 13
-  errormsg: "Expected a node of kind nnkCharLit, got nnkCommand"
 """
 # issue #4915
 import macros
diff --git a/tests/closure/tclosure.nim b/tests/closure/tclosure.nim
index c213d6a4b..cfef4193a 100644
--- a/tests/closure/tclosure.nim
+++ b/tests/closure/tclosure.nim
@@ -33,6 +33,7 @@ foo88
 11
 @[1, 10, 45, 120, 210, 252, 210, 120, 45, 10, 1]
 '''
+joinable: false
 """
 
 
diff --git a/tests/closure/tinvalidclosure.nim b/tests/closure/tinvalidclosure.nim
index 4e5f61f06..b2d8bd28d 100644
--- a/tests/closure/tinvalidclosure.nim
+++ b/tests/closure/tinvalidclosure.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 12
   errormsg: "type mismatch: got <proc (x: int){.gcsafe, locks: 0.}>"
+  line: 12
 """
 
 proc ugh[T](x: T) {.nimcall.} =
diff --git a/tests/closure/tinvalidclosure2.nim b/tests/closure/tinvalidclosure2.nim
index 845559309..2d58f0215 100644
--- a/tests/closure/tinvalidclosure2.nim
+++ b/tests/closure/tinvalidclosure2.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 10
   errormsg: "illegal capture 'A'"
+  line: 10
 """
 
 proc outer() =
diff --git a/tests/closure/tinvalidclosure3.nim b/tests/closure/tinvalidclosure3.nim
index 31c4976f8..0cbdaf39e 100644
--- a/tests/closure/tinvalidclosure3.nim
+++ b/tests/closure/tinvalidclosure3.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 9
   errormsg: "illegal capture 'x'"
+  line: 9
 """
 
 proc outer(arg: string) =
@@ -9,4 +9,4 @@ proc outer(arg: string) =
     echo "inner", x
   inner()
 
-outer("abc")
\ No newline at end of file
+outer("abc")
diff --git a/tests/closure/tnested.nim b/tests/closure/tnested.nim
index f8d69011a..dbbe9ba58 100644
--- a/tests/closure/tnested.nim
+++ b/tests/closure/tnested.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tnested.nim"
-  output: '''
+output: '''
 foo88
 23 24foo 88
 foo88
diff --git a/tests/cnstseq/tcnstseq.nim b/tests/cnstseq/tcnstseq.nim
index e044b9f3f..5679a6e37 100644
--- a/tests/cnstseq/tcnstseq.nim
+++ b/tests/cnstseq/tcnstseq.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tcnstseq.nim"
-  output: '''
+output: '''
 AngelikaAnneAnnaAnkaAnja
 AngelikaAnneAnnaAnkaAnja
 AngelikaAnneAnnaAnkaAnja
diff --git a/tests/collections/tcollections.nim b/tests/collections/tcollections.nim
index ff6673bba..2f8cfece7 100644
--- a/tests/collections/tcollections.nim
+++ b/tests/collections/tcollections.nim
@@ -1,7 +1,5 @@
 discard """
-  file: "tcollections.nim"
-  output: '''
-'''
+  output: ""
 """
 
 import deques, sequtils
diff --git a/tests/collections/tsets.nim b/tests/collections/thashsets.nim
index cd4401511..cd4401511 100644
--- a/tests/collections/tsets.nim
+++ b/tests/collections/thashsets.nim
diff --git a/tests/collections/ttables.nim b/tests/collections/ttables.nim
index 4d11f56f2..6798e5731 100644
--- a/tests/collections/ttables.nim
+++ b/tests/collections/ttables.nim
@@ -1,16 +1,16 @@
 discard """
-  file: "ttables.nim"
-  output: '''
-done
+output: '''
+done tableadds
 And we get here
 1
 2
 3
 '''
+joinable: false
 """
 import hashes, sequtils, tables
 
-
+# test should not be joined because it takes too long.
 block tableadds:
   proc main =
     var tab = newTable[string, string]()
@@ -18,7 +18,7 @@ block tableadds:
       tab.add "key", "value " & $i
 
   main()
-  echo "done"
+  echo "done tableadds"
 
 
 block tcounttable:
@@ -142,7 +142,7 @@ block tindexby:
   tbl2.add("bar", elem1)
   tbl2.add("baz", elem2)
   doAssert indexBy(@[elem1,elem2], proc(x: TElem): string = x.bar) == tbl2, "element table"
-  
+
 
 block tableconstr:
   # Test if the new table constructor syntax works:
diff --git a/tests/compilerapi/tcompilerapi.nim b/tests/compilerapi/tcompilerapi.nim
index 30007eff0..2a7db04eb 100644
--- a/tests/compilerapi/tcompilerapi.nim
+++ b/tests/compilerapi/tcompilerapi.nim
@@ -15,7 +15,7 @@ import std / [os]
 
 proc main() =
   let std = findNimStdLibCompileTime()
-  var intr = createInterpreter("myscript.nim", [std, getAppDir()])
+  var intr = createInterpreter("myscript.nim",[std, parentDir(currentSourcePath)])
   intr.implementRoutine("*", "exposed", "addFloats", proc (a: VmArgs) =
     setResult(a, getFloat(a, 0) + getFloat(a, 1) + getFloat(a, 2))
   )
@@ -51,4 +51,3 @@ block issue9180:
 
   evalString("echo 10+1")
   evalString("echo 10+2")
-
diff --git a/tests/concepts/tconcepts.nim b/tests/concepts/tconcepts.nim
index dec1dafe0..d0bc76c20 100644
--- a/tests/concepts/tconcepts.nim
+++ b/tests/concepts/tconcepts.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tconcepts.nim"
-  output: '''
+output: '''
 10
 20
 int
@@ -378,53 +377,53 @@ block tvectorspace:
 block tstack:
   template reject(e) =
     static: assert(not compiles(e))
-  
+
   type
     ArrayStack = object
       data: seq[int]
-  
+
   proc push(s: var ArrayStack, item: int) =
     s.data.add item
-  
+
   proc pop(s: var ArrayStack): int =
     return s.data.pop()
-  
+
   type
     Stack[T] = concept var s
       s.push(T)
       s.pop() is T
-  
+
       type ValueType = T
       const ValueTypeName = T.name.toUpperAscii
-  
+
   proc genericAlgorithm[T](s: var Stack[T], y: T) =
     static:
       echo "INFERRED ", T.name
       echo "VALUE TYPE ", s.ValueType.name
       echo "VALUE TYPE NAME ", s.ValueTypeName
-  
+
     s.push(y)
     echo s.pop
-  
+
   proc implicitGeneric(s: var Stack): auto =
     static:
       echo "IMPLICIT INFERRED ", s.T.name, " ", Stack.T.name
       echo "IMPLICIT VALUE TYPE ", s.ValueType.name, " ", Stack.ValueType.name
       echo "IMPLICIT VALUE TYPE NAME ", s.ValueTypeName, " ", Stack.ValueTypeName
-  
+
     return s.pop()
-  
+
   var s = ArrayStack(data: @[])
-  
+
   s.push 10
   s.genericAlgorithm 20
   echo s.implicitGeneric
-  
+
   reject s.genericAlgorithm "x"
   reject s.genericAlgorithm 1.0
   reject "str".implicitGeneric
   reject implicitGeneric(10)
-  
+
 
 
 import libs/[trie_database, trie]
diff --git a/tests/concepts/texplain.nim b/tests/concepts/texplain.nim
index 5c8e02440..ac0c972f5 100644
--- a/tests/concepts/texplain.nim
+++ b/tests/concepts/texplain.nim
@@ -63,8 +63,8 @@ texplain.nim(92, 5) NestedConcept: concept predicate failed
 
 expression: f(y)
 '''
-  line: 138
   errormsg: "type mismatch: got <MatchingType>"
+  line: 138
 """
 
 
@@ -136,4 +136,3 @@ static:
 # finally, provide multiple nested explanations for failed matching
 # of regular concepts, even when the explain pragma is not used
 f(y)
-
diff --git a/tests/concepts/trandomvars.nim b/tests/concepts/trandomvars.nim
index db41aa901..1f04b9ecf 100644
--- a/tests/concepts/trandomvars.nim
+++ b/tests/concepts/trandomvars.nim
@@ -41,7 +41,8 @@ proc lift1[A, B](f: proc(a: A): B, r: RandomVar[A]): ClosureVar[B] =
 
   return inner
 
-when isMainModule:
+
+proc main() =
   proc sq(x: float): float = x * x
 
   let
@@ -59,3 +60,4 @@ when isMainModule:
   echo rng.sample(u)
   echo rng.sample(t)
 
+main()
diff --git a/tests/concepts/trandom_vars.nim b/tests/concepts/trandomvars2.nim
index 861e876a7..861e876a7 100644
--- a/tests/concepts/trandom_vars.nim
+++ b/tests/concepts/trandomvars2.nim
diff --git a/tests/constr/tconstr1.nim b/tests/constr/tconstr1.nim
index b9cf5d00b..a169bf453 100644
--- a/tests/constr/tconstr1.nim
+++ b/tests/constr/tconstr1.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch"
   file: "tconstr1.nim"
   line: 25
-  errormsg: "type mismatch"
 """
 # Test array, record constructors
 
@@ -26,5 +26,3 @@ const
   otherThings = [  # the same
     (s: "hi", x: 69, y: 45, z: 0.0, chars: {'a', 'b', 'c'}),
     (s: "hi", x: 69, y: 45, z: 1.0, chars: {'a'})]
-
-
diff --git a/tests/constr/tconstr2.nim b/tests/constr/tconstr2.nim
index b16be6c50..2557d7db9 100644
--- a/tests/constr/tconstr2.nim
+++ b/tests/constr/tconstr2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tconstr2.nim"
   output: "69"
 """
 # Test array, record constructors
@@ -19,8 +18,5 @@ const
     (s: "hi", x: 69, y: 45, z: 0.0, chars: {'a', 'b', 'c'}),
     (s: "hi", x: 69, y: 45, z: 1.0, chars: {'a'})]
 
-write(stdout, things[0].x)
+writeLine(stdout, things[0].x)
 #OUT 69
-
-
-
diff --git a/tests/constraints/tconstraints.nim b/tests/constraints/tconstraints.nim
index 3c9fdc354..3ca01cfd5 100644
--- a/tests/constraints/tconstraints.nim
+++ b/tests/constraints/tconstraints.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 16
   errormsg: "type mismatch: got <int literal(232)>"
+  line: 16
 """
 
 proc myGenericProc[T: object|tuple|ptr|ref|distinct](x: T): string =
@@ -14,5 +14,3 @@ var
 
 assert myGenericProc(x) == "(x: 0, y: 0)"
 assert myGenericProc(232) == "232"
-
-
diff --git a/tests/constructors/t5965_1.nim b/tests/constructors/t5965_1.nim
index 9f947f859..abf07b21c 100644
--- a/tests/constructors/t5965_1.nim
+++ b/tests/constructors/t5965_1.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "incorrect object construction syntax"
   file: "t5965_1.nim"
   line: 10
-  errormsg: "incorrect object construction syntax"
 """
 
 type Foo = object
diff --git a/tests/constructors/t5965_2.nim b/tests/constructors/t5965_2.nim
index a3f7174c9..e04f1b715 100644
--- a/tests/constructors/t5965_2.nim
+++ b/tests/constructors/t5965_2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "incorrect object construction syntax"
   file: "t5965_2.nim"
   line: 10
-  errormsg: "incorrect object construction syntax"
 """
 
 type Foo = object
diff --git a/tests/controlflow/tblock1.nim b/tests/controlflow/tblock1.nim
index e3a780dfe..70c844513 100644
--- a/tests/controlflow/tblock1.nim
+++ b/tests/controlflow/tblock1.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "undeclared identifier: \'ha\'"
   file: "tblock1.nim"
   line: 14
-  errormsg: "undeclared identifier: \'ha\'"
 """
 # check for forward label and
 # for failure when label is not declared
@@ -14,5 +14,3 @@ proc main =
   break ha #ERROR
 
 main()
-
-
diff --git a/tests/controlflow/tcontrolflow.nim b/tests/controlflow/tcontrolflow.nim
index 9019e55b2..258f3f50d 100644
--- a/tests/controlflow/tcontrolflow.nim
+++ b/tests/controlflow/tcontrolflow.nim
@@ -85,13 +85,13 @@ block tnestif:
   if x == 0:
       write(stdout, "i == 0")
       if y == 0:
-          write(stdout, x)
+          writeLine(stdout, x)
       else:
-          write(stdout, y)
+          writeLine(stdout, y)
   elif x == 1:
-      write(stdout, "i == 1")
+      writeLine(stdout, "i == 1")
   elif x == 2:
-      write(stdout, "i == 2")
+      writeLine(stdout, "i == 2")
   else:
-      write(stdout, "looks like Python")
+      writeLine(stdout, "looks like Python")
   #OUT i == 2
diff --git a/tests/controlflow/tstatret.nim b/tests/controlflow/tstatret.nim
index 8f43c5d8f..e0f816c7d 100644
--- a/tests/controlflow/tstatret.nim
+++ b/tests/controlflow/tstatret.nim
@@ -1,12 +1,9 @@
 discard """
+  errormsg: "unreachable statement after 'return' statement or '{.noReturn.}' proc"
   file: "tstatret.nim"
   line: 9
-  errormsg: "unreachable statement after 'return' statement or '{.noReturn.}' proc"
 """
 # no statement after return
 proc main() =
   return
   echo("huch?") #ERROR_MSG statement not allowed after
-
-
-
diff --git a/tests/converter/tconverter_unique_ptr.nim b/tests/converter/tconverter_unique_ptr.nim
index 25b001d52..23c1a3d96 100644
--- a/tests/converter/tconverter_unique_ptr.nim
+++ b/tests/converter/tconverter_unique_ptr.nim
@@ -1,6 +1,5 @@
 
 discard """
-  file: "tconverter_unique_ptr.nim"
   targets: "c cpp"
   output: ""
 """
@@ -34,7 +33,7 @@ proc `=`*(m: var MySeq, m2: MySeq) =
     `=destroy`(m)
 
   m.len = m2.len
-  let bytes = m.len.int * sizeof(float) 
+  let bytes = m.len.int * sizeof(float)
   if bytes > 0:
     m.data = cast[ptr UncheckedArray[float]](allocShared(bytes))
     copyMem(m.data, m2.data, bytes)
@@ -59,7 +58,7 @@ proc `[]`*(m: var MySeq; i: MyLen): var float {.inline.} =
 proc `[]=`*(m: var MySeq; i: MyLen, val: float) {.inline.} =
   m.data[i.int] = val
 
-proc setTo(s: var MySeq, val: float) = 
+proc setTo(s: var MySeq, val: float) =
   for i in 0..<s.len.int:
     s.data[i] = val
 
@@ -112,7 +111,7 @@ doAssert pu[0] == 2.0
 doAssert: pu2[0] == 2.0
 
 ##-----------------------------------------------------------------------------------------
-## Bugs #9735 and #9736 
+## Bugs #9735 and #9736
 type
   ConstPtr*[T] = object
     ## This pointer makes it impossible to change underlying value
diff --git a/tests/converter/tconverter_with_constraint.nim b/tests/converter/tconverter_with_constraint.nim
index 793264434..ce5135586 100644
--- a/tests/converter/tconverter_with_constraint.nim
+++ b/tests/converter/tconverter_with_constraint.nim
@@ -1,8 +1,8 @@
 
 discard """
+  errormsg: "type mismatch: got <int>"
   file: "tconverter_with_constraint.nim"
   line: 20
-  errormsg: "type mismatch: got <int>"
 """
 
 type
@@ -10,11 +10,11 @@ type
 
 converter to_mytype(m: int{lit}): MyType =
   m.MyType
- 
+
 proc myproc(m: MyType) =
   echo m.int, ".MyType"
 
-myproc(1) # call by literal is ok 
+myproc(1) # call by literal is ok
 
 var x: int = 12
-myproc(x) # should fail
\ No newline at end of file
+myproc(x) # should fail
diff --git a/tests/deprecated/tnoannot.nim b/tests/deprecated/tnoannot.nim
index 9cc5c7e06..ac168952e 100644
--- a/tests/deprecated/tnoannot.nim
+++ b/tests/deprecated/tnoannot.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 7
   errormsg: "annotation to deprecated not supported here"
+  line: 7
 """
 
 var foo* {.deprecated.} = 42
diff --git a/tests/deps/jester-#head/jester/patterns.nim b/tests/deps/jester-#head/jester/patterns.nim
index 52b0d3a15..c827fbc7f 100644
--- a/tests/deps/jester-#head/jester/patterns.nim
+++ b/tests/deps/jester-#head/jester/patterns.nim
@@ -120,7 +120,7 @@ proc match*(pattern: Pattern, s: string):
   if s.len != i:
     result.matched = false
 
-when isMainModule:
+when true:
   let f = parsePattern("/show/@id/test/@show?/?")
   doAssert match(f, "/show/12/test/hallo/").matched
   doAssert match(f, "/show/2131726/test/jjjuuwąąss").matched
diff --git a/tests/deps/jester-#head/jester/private/utils.nim b/tests/deps/jester-#head/jester/private/utils.nim
index 66f0b37a6..16dce61fe 100644
--- a/tests/deps/jester-#head/jester/private/utils.nim
+++ b/tests/deps/jester-#head/jester/private/utils.nim
@@ -188,7 +188,7 @@ when not declared(normalizePath) and not declared(normalizedPath):
     result = path
     normalizePath(result)
 
-when isMainModule:
+when false:
   var r = {:}.newStringTable
   parseUrlQuery("FirstName=Mickey", r)
   echo r
diff --git a/tests/deps/zip-0.2.1/zip/zipfiles.nim b/tests/deps/zip-0.2.1/zip/zipfiles.nim
index ca1979488..274587df9 100644
--- a/tests/deps/zip-0.2.1/zip/zipfiles.nim
+++ b/tests/deps/zip-0.2.1/zip/zipfiles.nim
@@ -186,7 +186,7 @@ proc extractAll*(z: var ZipArchive, dest: string) =
       createDir(dest / file[0..file.rfind("/")])
     extractFile(z, file, dest / file)
 
-when not defined(testing) and isMainModule:
+when not defined(testing) and true:
   var zip: ZipArchive
   if not zip.open("nim-0.11.0.zip"):
     raise newException(IOError, "opening zip failed")
diff --git a/tests/destructor/tmatrix.nim b/tests/destructor/tmatrix.nim
index a16bfa37b..b89b41a4c 100644
--- a/tests/destructor/tmatrix.nim
+++ b/tests/destructor/tmatrix.nim
@@ -52,6 +52,8 @@ proc matrix*(m, n: int, s: float): Matrix =
   for i in 0 ..< m * n:
     result.data[i] = s
 
+proc len(m: Matrix): int = m.n * m.m
+
 proc `[]`*(m: Matrix, i, j: int): float {.inline.} =
   ## Get a single element.
   m.data[i * m.n + j]
@@ -67,24 +69,26 @@ proc `[]=`*(m: var Matrix, i, j: int, s: float) =
 proc `-`*(m: sink Matrix): Matrix =
   ## Unary minus
   result = m
-  for i in 0 ..< m.m:
-    for j in 0 ..< m.n:
-      result[i, j] = -m[i, j]
+  for i in 0 ..< result.m:
+    for j in 0 ..< result.n:
+      result[i, j] = -result[i, j]
 
 proc `+`*(a: sink Matrix; b: Matrix): Matrix =
   ## ``C = A + B``
-  assert(b.m == a.m and b.n == a.n, "Matrix dimensions must agree.")
+  doAssert(b.m == a.m and b.n == a.n, "Matrix dimensions must agree.")
+  doAssert(a.len == b.len) # non destructive use before sink is ok
   result = a
-  for i in 0 ..< a.m:
-    for j in 0 ..< a.n:
-      result[i, j] = a[i, j] + b[i, j]
+  for i in 0 ..< result.m:
+    for j in 0 ..< result.n:
+      result[i, j] = result[i, j] + b[i, j]
 
 proc `-`*(a: sink Matrix; b: Matrix): Matrix =
   ## ``C = A - B``
   assert(b.m == a.m and b.n == a.n, "Matrix dimensions must agree.")
+  doAssert(a.len == b.len) # non destructive use before sink is ok
   result = a
-  for i in 0 ..< a.m:
-     for j in 0 ..< a.n:
+  for i in 0 ..< result.m:
+     for j in 0 ..< result.n:
         result[i, j] = a[i, j] - b[i, j]
 
 proc info =
diff --git a/tests/destructor/tmove_objconstr.nim b/tests/destructor/tmove_objconstr.nim
index 26cc682b5..875f78283 100644
--- a/tests/destructor/tmove_objconstr.nim
+++ b/tests/destructor/tmove_objconstr.nim
@@ -36,7 +36,7 @@ proc pointlessWrapper(s: string): Data =
 proc main =
   var x = pointlessWrapper"test"
 
-when isMainModule:
+when true:
   main()
 
 # bug #985
@@ -109,7 +109,19 @@ proc myfunc(x, y: int): (MySeqNonCopyable, MySeqNonCopyable) =
 
 proc myfunc2(x, y: int): tuple[a: MySeqNonCopyable, b:int, c:MySeqNonCopyable] =
   var cc = newMySeq(y, 5.0)
-  (a: newMySeq(x, 1.0), b:0, c: cc)
+  (a: case x:
+    of 1: 
+      let (z1, z2) = myfunc(x,y)
+      z2
+    elif x > 5: raise newException(ValueError, "new error")
+    else: newMySeq(x, 1.0), 
+   b: 0, 
+   c: block:
+        var tmp = if y > 0: move(cc) else: newMySeq(1, 3.0)
+        tmp[0] = 5
+        tmp 
+  )
+   
 
 let (seq1, seq2) = myfunc(2, 3)
 doAssert seq1.len == 2
@@ -122,4 +134,35 @@ doAssert seq3.len == 2
 doAssert seq3[0] == 1.0
 
 var seq4, seq5: MySeqNonCopyable
-(seq4, i, seq5) = myfunc2(2, 3)
\ No newline at end of file
+(seq4, i, seq5) = myfunc2(2, 3)
+
+seq4 = block:
+  var tmp = newMySeq(4, 1.0)
+  tmp[0] = 3.0
+  tmp
+
+doAssert seq4[0] == 3.0 
+
+import macros
+
+seq4 = 
+  if i > 0: newMySeq(2, 5.0) 
+  elif i < -100: raise newException(ValueError, "Parse Error")
+  else: newMySeq(2, 3.0)
+
+seq4 = 
+  case (char) i:
+    of 'A', {'W'..'Z'}: newMySeq(2, 5.0) 
+    of 'B': quit(-1)
+    else: 
+      let (x1, x2, x3) = myfunc2(2, 3)
+      x3
+
+
+#------------------------------------------------------------
+#-- Move into array constructor
+#------------------------------------------------------------
+
+var ii = 1
+let arr2 = [newMySeq(2, 5.0), if i > 1: newMySeq(3, 1.0) else: newMySeq(0, 0.0)]
+var seqOfSeq2 = @[newMySeq(2, 5.0), newMySeq(3, 1.0)]
diff --git a/tests/destructor/turn_destroy_into_finalizer.nim b/tests/destructor/turn_destroy_into_finalizer.nim
index f5b705593..1409c1c57 100644
--- a/tests/destructor/turn_destroy_into_finalizer.nim
+++ b/tests/destructor/turn_destroy_into_finalizer.nim
@@ -1,5 +1,6 @@
 discard """
-  output: '''true'''
+  output: "turn_destroy_into_finalizer works"
+  joinable: false
 """
 
 type
@@ -17,6 +18,9 @@ proc main =
   for i in 1..50_000:
     new(r)
     r.id = i
-  echo destroyed > 30_000
+  if destroyed > 30_000:
+    echo "turn_destroy_into_finalizer works"
+  else:
+    echo "turn_destroy_into_finalizer failed: ", destroyed
 
 main()
diff --git a/tests/discard/tdiscardable.nim b/tests/discard/tdiscardable.nim
index a3dd966a0..81e17866a 100644
--- a/tests/discard/tdiscardable.nim
+++ b/tests/discard/tdiscardable.nim
@@ -1,10 +1,13 @@
 discard """
 output: '''
+tdiscardable
 1
 1
 '''
 """
 
+echo "tdiscardable"
+
 # Test the discardable pragma
 
 proc p(x, y: int): int {.discardable.} =
diff --git a/tests/discard/tillegaldiscard.nim b/tests/discard/tillegaldiscard.nim
index 5e1a3f03e..757f4e727 100644
--- a/tests/discard/tillegaldiscard.nim
+++ b/tests/discard/tillegaldiscard.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 9
   errormsg: "illegal discard"
+  line: 9
 """
 
 proc pop[T](arg: T): T =
diff --git a/tests/discard/tneedsdiscard.nim b/tests/discard/tneedsdiscard.nim
index 8d59e7fec..7d2997b3f 100644
--- a/tests/discard/tneedsdiscard.nim
+++ b/tests/discard/tneedsdiscard.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 10
   errormsg: '''expression 'open(f, "arg.txt", fmRead, -1)' is of type 'bool' and has to be discarded; start of expression here: tneedsdiscard.nim(7, 2)'''
+  line: 10
 """
 
 proc p =
diff --git a/tests/discard/tneedsdiscard_in_for.nim b/tests/discard/tneedsdiscard_in_for.nim
index 5658f4ba2..499b06009 100644
--- a/tests/discard/tneedsdiscard_in_for.nim
+++ b/tests/discard/tneedsdiscard_in_for.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 22
   errormsg: '''expression 'premultiply(app.gradient[i])' is of type 'Rgba8' and has to be discarded'''
+  line: 22
 """
 
 # bug #9076
diff --git a/tests/distinct/tdistinct.nim b/tests/distinct/tdistinct.nim
index 52728fc2b..70e586ded 100644
--- a/tests/distinct/tdistinct.nim
+++ b/tests/distinct/tdistinct.nim
@@ -1,9 +1,11 @@
 discard """
   output: '''
+tdistinct
 25
 '''
 """
 
+echo "tdistinct"
 
 block tborrowdot:
   type
@@ -18,8 +20,6 @@ block tborrowdot:
   bb.a = 90
   bb.s = "abc"
 
-
-
 block tcurrncy:
   template Additive(typ: untyped) =
     proc `+`(x, y: typ): typ {.borrow.}
@@ -53,8 +53,6 @@ block tcurrncy:
   DefineCurrency(TEuro, int)
   echo($( 12.TDollar + 13.TDollar )) #OUT 25
 
-
-
 block tconsts:
   # bug #2641
 
diff --git a/tests/distinct/tnil.nim b/tests/distinct/tnil.nim
index 16de38f60..5bdb97f37 100644
--- a/tests/distinct/tnil.nim
+++ b/tests/distinct/tnil.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tnil.nim"
-  output: '''1
+output: '''
+1
 0
 0
 '''
diff --git a/tests/effects/teffects1.nim b/tests/effects/teffects1.nim
index ef76c9130..767845cb4 100644
--- a/tests/effects/teffects1.nim
+++ b/tests/effects/teffects1.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "system.nim"
   errormsg: "can raise an unlisted exception: ref IOError"
+  file: "system.nim"
 """
 
 type
@@ -17,4 +17,3 @@ proc lier(): int {.raises: [IO2Error].} =
 
 proc forw: int =
   raise newException(IOError, "arg")
-
diff --git a/tests/effects/teffects2.nim b/tests/effects/teffects2.nim
index 0fa789869..e4b50aba5 100644
--- a/tests/effects/teffects2.nim
+++ b/tests/effects/teffects2.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 19
   errormsg: "can raise an unlisted exception: ref IOError"
+  line: 19
 """
 
 type
@@ -17,4 +17,3 @@ proc lier(): int {.raises: [IOError].} =
 
 proc forw: int =
   raise newException(IOError, "arg")
-
diff --git a/tests/effects/teffects3.nim b/tests/effects/teffects3.nim
index cbd11f722..ee5470c47 100644
--- a/tests/effects/teffects3.nim
+++ b/tests/effects/teffects3.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 18
   errormsg: "type mismatch"
+  line: 18
 """
 
 type
@@ -16,4 +16,3 @@ proc raiser(): int {.tags: [TObj, WriteIoEffect].} =
 
 var o: TObjB
 o.fn = raiser
-
diff --git a/tests/effects/teffects4.nim b/tests/effects/teffects4.nim
index 0025c10c5..88cc0efa9 100644
--- a/tests/effects/teffects4.nim
+++ b/tests/effects/teffects4.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 23
   errormsg: "type mismatch"
+  line: 23
 """
 
 type
@@ -21,4 +21,3 @@ proc raiser(): int =
 
 var o: TObjB
 o.fn = raiser
-
diff --git a/tests/effects/tgcsafe.nim b/tests/effects/tgcsafe.nim
index d146794b6..ff207df59 100644
--- a/tests/effects/tgcsafe.nim
+++ b/tests/effects/tgcsafe.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 17
   errormsg: "'mainUnsafe' is not GC-safe"
+  line: 17
   cmd: "nim $target --hints:on --threads:on $options $file"
 """
 
diff --git a/tests/effects/tsidee1.nim b/tests/effects/tsidee1.nim
index e486d32e7..ca6816561 100644
--- a/tests/effects/tsidee1.nim
+++ b/tests/effects/tsidee1.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "\'SideEffectLyer\' can have side effects"
   file: "tsidee1.nim"
   line: 12
-  errormsg: "\'SideEffectLyer\' can have side effects"
 """
 
 var
@@ -13,6 +13,3 @@ proc SideEffectLyer(x, y: int): int {.noSideEffect.} = #ERROR_MSG 'SideEffectLye
   return x + y + dontcare(x)
 
 echo SideEffectLyer(1, 3)
-
-
-
diff --git a/tests/effects/tsidee2.nim b/tests/effects/tsidee2.nim
index 5ed541300..b2e5f3379 100644
--- a/tests/effects/tsidee2.nim
+++ b/tests/effects/tsidee2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tsidee2.nim"
   output: "5"
 """
 
@@ -12,6 +11,3 @@ proc SideEffectLyer(x, y: int): int {.noSideEffect.} =
   return x + y + dontcare(x)
 
 echo SideEffectLyer(1, 3) #OUT 5
-
-
-
diff --git a/tests/effects/tsidee3.nim b/tests/effects/tsidee3.nim
index e15fbc3d1..c3801ba28 100644
--- a/tests/effects/tsidee3.nim
+++ b/tests/effects/tsidee3.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tsidee3.nim"
   output: "5"
 """
 
@@ -12,6 +11,3 @@ proc noSideEffect(x, y: int, p: proc (a: int): int {.noSideEffect.}): int {.noSi
   return x + y + dontcare(x)
 
 echo noSideEffect(1, 3, dontcare) #OUT 5
-
-
-
diff --git a/tests/effects/tsidee4.nim b/tests/effects/tsidee4.nim
index ecc79580c..d6c192cbf 100644
--- a/tests/effects/tsidee4.nim
+++ b/tests/effects/tsidee4.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "'noSideEffect' can have side effects"
   file: "tsidee4.nim"
   line: 12
-  errormsg: "'noSideEffect' can have side effects"
 """
 
 var
@@ -13,5 +13,3 @@ proc noSideEffect(x, y: int, p: proc (a: int): int {.noSideEffect.}): int {.noSi
   return x + y + dontcare(x)
 
 echo noSideEffect(1, 3, dontcare) #ERROR_MSG type mismatch
-
-
diff --git a/tests/enum/tenumitems.nim b/tests/enum/tenumitems.nim
index 6d13dd162..76f368f8a 100644
--- a/tests/enum/tenumitems.nim
+++ b/tests/enum/tenumitems.nim
@@ -1,9 +1,7 @@
 discard """
-  line: 7
   errormsg: "attempting to call routine: 'items'"
+  line: 7
 """
 
 type a = enum b,c,d
 a.items()
-
-
diff --git a/tests/errmsgs/t6483.nim b/tests/errmsgs/t6483.nim
index 59ea6d7e2..0e977b36d 100644
--- a/tests/errmsgs/t6483.nim
+++ b/tests/errmsgs/t6483.nim
@@ -16,7 +16,7 @@ type
     variables: seq[VarItem]
     children: seq[VarScope]
 
-when isMainModule:
+when true:
   var scope1 = VarScope(
     variables: newSeq[VarItem](),
     children: newSeq[VarScope]()
diff --git a/tests/errmsgs/t8339.nim b/tests/errmsgs/t8339.nim
index f0a97658a..720e080c0 100644
--- a/tests/errmsgs/t8339.nim
+++ b/tests/errmsgs/t8339.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 8
   errormsg: "type mismatch: got <seq[int]> but expected 'seq[float]'"
+  line: 8
 """
 
 import sequtils
diff --git a/tests/errmsgs/t9908_01.nim b/tests/errmsgs/t9908_01.nim
new file mode 100644
index 000000000..b9d37b67b
--- /dev/null
+++ b/tests/errmsgs/t9908_01.nim
@@ -0,0 +1,10 @@
+discard """
+errormsg: "ordinal type expected"
+line: 10
+"""
+
+# https://github.com/nim-lang/Nim/issues/9908
+
+type
+  X = enum
+    a = ("a", "b")
diff --git a/tests/errmsgs/t9908_02.nim b/tests/errmsgs/t9908_02.nim
new file mode 100644
index 000000000..7ff3d1ff7
--- /dev/null
+++ b/tests/errmsgs/t9908_02.nim
@@ -0,0 +1,10 @@
+discard """
+errormsg: "ordinal type expected"
+line: 10
+"""
+
+# https://github.com/nim-lang/Nim/pull/9909#issuecomment-445519287
+
+type
+  E = enum
+    myVal = 80.9
diff --git a/tests/errmsgs/tproper_stacktrace.nim b/tests/errmsgs/tproper_stacktrace.nim
index 134946651..c0090a595 100644
--- a/tests/errmsgs/tproper_stacktrace.nim
+++ b/tests/errmsgs/tproper_stacktrace.nim
@@ -66,7 +66,7 @@ template verifyStackTrace*(expectedStackTrace: string, body: untyped) =
 
 
 
-when isMainModule:
+when true:
 # <-- Align with line 70 in the text editor
   block:
     proc bar() =
diff --git a/tests/errmsgs/treportunused.nim b/tests/errmsgs/treportunused.nim
index 929da8843..c74fea46f 100644
--- a/tests/errmsgs/treportunused.nim
+++ b/tests/errmsgs/treportunused.nim
@@ -12,10 +12,10 @@ treportunused.nim(27, 5) Hint: 's9' is declared but not used [XDeclaredButNotUse
 treportunused.nim(21, 10) Hint: 's3' is declared but not used [XDeclaredButNotUsed]
 treportunused.nim(28, 6) Hint: 's10' is declared but not used [XDeclaredButNotUsed]
 '''
+action: compile
 """
 
 # bug #9764
-
 iterator s1(a:string): int = discard
 iterator s2(): int = discard
 template s3(): untyped = 123
diff --git a/tests/exception/tcontinuexc.nim b/tests/exception/tcontinuexc.nim
index 2a05da9c0..b7560a605 100644
--- a/tests/exception/tcontinuexc.nim
+++ b/tests/exception/tcontinuexc.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tcontinuexc.nim"
   outputsub: "ECcaught"
   exitcode: "1"
 """
@@ -25,6 +24,3 @@ finally:
   echo "caught"
 
 #OUT ECcaught
-
-
-
diff --git a/tests/exception/texceptionbreak.nim b/tests/exception/texceptionbreak.nim
index 00dd8ed9f..6548192c6 100644
--- a/tests/exception/texceptionbreak.nim
+++ b/tests/exception/texceptionbreak.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tnestedbreak.nim"
   output: "1\n2\n3\n4"
 """
 
diff --git a/tests/exception/texcsub.nim b/tests/exception/texcsub.nim
index 02125d2c0..463e95613 100644
--- a/tests/exception/texcsub.nim
+++ b/tests/exception/texcsub.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "texcsub.nim"
   output: "caught!"
 """
 # Test inheritance for exception matching:
@@ -12,6 +11,3 @@ except:
   echo "wtf!?"
 
 #OUT caught!
-
-
-
diff --git a/tests/exception/tfinally.nim b/tests/exception/tfinally.nim
index 7a218b444..c5b1dd841 100644
--- a/tests/exception/tfinally.nim
+++ b/tests/exception/tfinally.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tfinally.nim"
-  output: '''came
+  output: '''
+came
 here
 3
 msg1
@@ -59,4 +59,4 @@ try:
 except:
   echo "except2"
 finally:
-  echo "finally2"
\ No newline at end of file
+  echo "finally2"
diff --git a/tests/exception/tfinally2.nim b/tests/exception/tfinally2.nim
index f1acf2774..dae1a468a 100644
--- a/tests/exception/tfinally2.nim
+++ b/tests/exception/tfinally2.nim
@@ -1,9 +1,10 @@
 discard """
-  file: "tfinally2.nim"
-  output: '''A
+output: '''
+A
 B
 C
-D'''
+D
+'''
 """
 # Test break in try statement:
 
@@ -24,7 +25,4 @@ proc main: int =
   finally:
     echo("D")
 
-discard main() #OUT ABCD
-
-
-
+discard main()
diff --git a/tests/exception/tfinally3.nim b/tests/exception/tfinally3.nim
index 6098672a2..9053d397d 100644
--- a/tests/exception/tfinally3.nim
+++ b/tests/exception/tfinally3.nim
@@ -1,7 +1,8 @@
 discard """
-  file: "tfinally3.nim"
-  outputsub: '''false
-Within finally->try'''
+  outputsub: '''
+false
+Within finally->try
+'''
   exitCode: 1
 """
 # Test break in try statement:
diff --git a/tests/exception/tfinally4.nim b/tests/exception/tfinally4.nim
index 3aa707ff6..feaf1bc96 100644
--- a/tests/exception/tfinally4.nim
+++ b/tests/exception/tfinally4.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tfinally4.nim"
   output: "B1\nA1\n1\nB1\nB2\ncatch\nA1\n1\nB1\nA1\nA2\n2\nB1\nB2\ncatch\nA1\nA2\n0\nB1\nA1\n1\nB1\nB2\nA1\n1\nB1\nA1\nA2\n2\nB1\nB2\nA1\nA2\n3"
 """
 
diff --git a/tests/exception/tnestedreturn.nim b/tests/exception/tnestedreturn.nim
index bf26f4903..acb83d2c8 100644
--- a/tests/exception/tnestedreturn.nim
+++ b/tests/exception/tnestedreturn.nim
@@ -1,6 +1,5 @@
 discard """
   targets: "c cpp"
-  file: "tnestedreturn.nim"
   output: "A\nB\nC\n"
 """
 
diff --git a/tests/exception/tnestedreturn2.nim b/tests/exception/tnestedreturn2.nim
index 79523a883..167d09b96 100644
--- a/tests/exception/tnestedreturn2.nim
+++ b/tests/exception/tnestedreturn2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tnestedreturn2.nim"
   outputsub: "Error: unhandled exception: Problem [OSError]"
   exitcode: "1"
 """
diff --git a/tests/exception/treraise.nim b/tests/exception/treraise.nim
index b2a11d34f..17a38aa53 100644
--- a/tests/exception/treraise.nim
+++ b/tests/exception/treraise.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "treraise.nim"
   outputsub: "Error: unhandled exception: bla [ESomeOtherErr]"
   exitcode: "1"
 """
@@ -19,6 +18,3 @@ except ESomething:
   echo("Error happened")
 except:
   raise
-
-
-
diff --git a/tests/exception/tunhandledexc.nim b/tests/exception/tunhandledexc.nim
index f0fa2bf27..6ca311d38 100644
--- a/tests/exception/tunhandledexc.nim
+++ b/tests/exception/tunhandledexc.nim
@@ -1,7 +1,6 @@
 discard """
-  file: "tunhandledexc.nim"
   cmd: "nim $target -d:release $options $file"
-  outputsub: '''tunhandledexc.nim(16)    genErrors
+  outputsub: '''tunhandledexc.nim(15)    genErrors
 Error: unhandled exception: bla [ESomeOtherErr]'''
   exitcode: "1"
 """
diff --git a/tests/exception/twrongexc.nim b/tests/exception/twrongexc.nim
index b224d4c83..9c656f3d9 100644
--- a/tests/exception/twrongexc.nim
+++ b/tests/exception/twrongexc.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "twrongexc.nim"
   outputsub: "Error: unhandled exception:  [ValueError]"
   exitcode: "1"
 """
@@ -7,7 +6,3 @@ try:
   raise newException(ValueError, "")
 except OverflowError:
   echo("Error caught")
-
-
-
-
diff --git a/tests/exprs/texprstmt.nim b/tests/exprs/texprstmt.nim
index 6c9759cf5..742670cc1 100644
--- a/tests/exprs/texprstmt.nim
+++ b/tests/exprs/texprstmt.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 10
   errormsg: "expression 'result[1 .. BackwardsIndex(1)]' is of type 'string' and has to be discarded"
+  line: 10
 """
 
 # bug #578
diff --git a/tests/exprs/tstmtexp.nim b/tests/exprs/tstmtexp.nim
index 0fb835bc6..75d8dd081 100644
--- a/tests/exprs/tstmtexp.nim
+++ b/tests/exprs/tstmtexp.nim
@@ -1,9 +1,8 @@
 discard """
+  errormsg: "expression '5' is of type 'int literal(5)' and has to be discarded"
   file: "tstmtexp.nim"
   line: 8
-  errormsg: "expression '5' is of type 'int literal(5)' and has to be discarded"
 """
 # Test 3
 
 1+4
-
diff --git a/tests/flags/tgenscript.nim b/tests/flags/tgenscript.nim
index 989ca8bcb..bf83ab972 100644
--- a/tests/flags/tgenscript.nim
+++ b/tests/flags/tgenscript.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tgenscript.nim"
   target: "c"
   action: compile
 """
diff --git a/tests/float/tfloat1.nim b/tests/float/tfloat1.nim
index ed99260ea..54d49a7c1 100644
--- a/tests/float/tfloat1.nim
+++ b/tests/float/tfloat1.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tfloat1.nim"
   outputsub: "Error: unhandled exception: FPU operation caused an overflow [FloatOverflowError]"
   exitcode: "1"
 """
@@ -11,5 +10,3 @@ var x = 0.8
 var y = 0.0
 
 echo x / y #OUT Error: unhandled exception: FPU operation caused an overflow
-
-
diff --git a/tests/float/tfloat2.nim b/tests/float/tfloat2.nim
index b84120fba..130c71087 100644
--- a/tests/float/tfloat2.nim
+++ b/tests/float/tfloat2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tfloat2.nim"
   outputsub: "Error: unhandled exception: FPU operation caused a NaN result [FloatInvalidOpError]"
   exitcode: "1"
 """
@@ -11,5 +10,3 @@ var x = 0.0
 var y = 0.0
 
 echo x / y #OUT Error: unhandled exception: FPU operation caused a NaN result
-
-
diff --git a/tests/float/tfloat3.nim b/tests/float/tfloat3.nim
index a14c6c396..215470cfc 100644
--- a/tests/float/tfloat3.nim
+++ b/tests/float/tfloat3.nim
@@ -1,15 +1,15 @@
 discard """
-  file: "tfloat3.nim"
-  output: "Nim    3.4368930843, 0.3299290698 C double: 3.4368930843, 0.3299290698"
+  output: '''
+Nim 3.4368930843, 0.3299290698
+C double: 3.4368930843, 0.3299290698'''
 """
 
 import math, strutils
 
 {.emit: """
 void printFloats(void) {
-    double y = 1.234567890123456789;
-
-    printf("C double: %.10f, %.10f ", exp(y), cos(y));
+  double y = 1.234567890123456789;
+  printf("C double: %.10f, %.10f\n", exp(y), cos(y));
 }
 """.}
 
@@ -17,8 +17,5 @@ proc c_printf(frmt: cstring) {.importc: "printf", header: "<stdio.h>", varargs.}
 proc printFloats {.importc, nodecl.}
 
 var x: float = 1.234567890123456789
-c_printf("Nim    %.10f, %.10f ", exp(x), cos(x))
+c_printf("Nim %.10f, %.10f\n", exp(x), cos(x))
 printFloats()
-
-
-
diff --git a/tests/float/tfloat4.nim b/tests/float/tfloat4.nim
index 68df56be8..56280111c 100644
--- a/tests/float/tfloat4.nim
+++ b/tests/float/tfloat4.nim
@@ -1,8 +1,7 @@
 discard """
-  file: "tfloat4.nim"
   output: "passed all tests."
-  exitcode: 0
 """
+
 import math, strutils
 
 proc c_sprintf(buf, fmt: cstring) {.importc:"sprintf", header: "<stdio.h>", varargs.}
diff --git a/tests/float/tfloat5.nim b/tests/float/tfloat5.nim
index aa7dc6c53..0708838fc 100644
--- a/tests/float/tfloat5.nim
+++ b/tests/float/tfloat5.nim
@@ -1,9 +1,10 @@
 discard """
-  file: "tfloat5.nim"
-  output: '''0 : 0.0
+output: '''
 0 : 0.0
 0 : 0.0
-0 : 0.0'''
+0 : 0.0
+0 : 0.0
+'''
 """
 
 import parseutils
diff --git a/tests/float/tfloat6.nim b/tests/float/tfloat6.nim
index 8e043a658..c4cd6e932 100644
--- a/tests/float/tfloat6.nim
+++ b/tests/float/tfloat6.nim
@@ -1,12 +1,13 @@
 discard """
-  file: "tfloat6.nim"
-  output: '''1e-06 : 1e-06
+  output: '''
+1e-06 : 1e-06
 1e-06 : 1e-06
 0.001 : 0.001
 1e-06 : 1e-06
 1e-06 : 1e-06
 10.000001 : 10.000001
-100.000001 : 100.000001'''
+100.000001 : 100.000001
+'''
   disabled: "windows"
 """
 
diff --git a/tests/float/tfloat7.nim b/tests/float/tfloat7.nim
index 5fd0d43d9..a6d7af10b 100644
--- a/tests/float/tfloat7.nim
+++ b/tests/float/tfloat7.nim
@@ -1,12 +1,13 @@
 discard """
-  file: "tfloat6.nim"
-  output: '''passed.
+output: '''
 passed.
 passed.
 passed.
 passed.
 passed.
-passed.'''
+passed.
+passed.
+'''
 """
 
 import strutils
diff --git a/tests/float/tfloatnan.nim b/tests/float/tfloatnan.nim
index aa288d342..29937a862 100644
--- a/tests/float/tfloatnan.nim
+++ b/tests/float/tfloatnan.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tfloatnan.nim"
-  output: '''Nim: nan
+output: '''
+Nim: nan
 Nim: nan (float)
 Nim: nan (double)
 '''
diff --git a/tests/float/tissue5821.nim b/tests/float/tissue5821.nim
index e8aa4a1d9..c4f561f09 100644
--- a/tests/float/tissue5821.nim
+++ b/tests/float/tissue5821.nim
@@ -1,7 +1,7 @@
 discard """
-  file: "tissue5821.nim"
-  output: ''''''
+output: "ok"
 """
+
 proc main(): void =
   let a: float32 = 47.11'f32
   doAssert a == 47.11'f32
@@ -10,4 +10,6 @@ proc main(): void =
   doAssert b != 10.123402823e+38'f64
   doAssert b == 10.234402823e+38'f64
 
-main()
\ No newline at end of file
+  echo "ok"
+
+main()
diff --git a/tests/generics/t6137.nim b/tests/generics/t6137.nim
index 639675f35..abf02a756 100644
--- a/tests/generics/t6137.nim
+++ b/tests/generics/t6137.nim
@@ -1,7 +1,6 @@
 discard """
-  action: "reject"
-  line: 29
   errormsg: "\'vectFunc\' doesn't have a concrete type, due to unspecified generic parameters."
+  line: 28
 """
 
 type
diff --git a/tests/generics/t7141.nim b/tests/generics/t7141.nim
index 8a128d828..b1e9cbf43 100644
--- a/tests/generics/t7141.nim
+++ b/tests/generics/t7141.nim
@@ -1,7 +1,6 @@
 discard """
-  action: "reject"
-  line: 7
   errormsg: "cannot instantiate: \'T\'"
+  line: 6
 """
 
 proc foo[T](x: T) =
diff --git a/tests/generics/t8270.nim b/tests/generics/t8270.nim
index 707e981fa..1e731d1d4 100644
--- a/tests/generics/t8270.nim
+++ b/tests/generics/t8270.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 6
   errormsg: "cannot instantiate: \'T\'"
+  line: 6
 """
 
 proc m[T](x: T): int = discard
diff --git a/tests/generics/tbintre2.nim b/tests/generics/tbintre2.nim
deleted file mode 100644
index eb46b5157..000000000
--- a/tests/generics/tbintre2.nim
+++ /dev/null
@@ -1,31 +0,0 @@
-discard """
-  file: "tbintre2.nim"
-  output: "helloworld99110223"
-"""
-# Same test, but check module boundaries
-
-import tbintree
-
-var
-  root: PBinaryTree[string]
-  x = newNode("hello")
-add(root, x)
-add(root, "world")
-if find(root, "world"):
-  for str in items(root):
-    stdout.write(str)
-else:
-  stdout.writeLine("BUG")
-
-var
-  r2: PBinaryTree[int]
-add(r2, newNode(110))
-add(r2, 223)
-add(r2, 99)
-for y in items(r2):
-  stdout.write(y)
-
-#OUT helloworld99110223
-
-
-
diff --git a/tests/generics/tbintree.nim b/tests/generics/tbintree.nim
index 13163f764..a1a13c7b5 100644
--- a/tests/generics/tbintree.nim
+++ b/tests/generics/tbintree.nim
@@ -1,6 +1,9 @@
 discard """
-  file: "tbintree.nim"
-  output: "helloworld99110223"
+  output: '''hello
+world
+99
+110
+223'''
 """
 type
   TBinaryTree[T] = object      # TBinaryTree is a generic type with
@@ -82,7 +85,7 @@ proc debug[T](a: PBinaryTree[T]) =
     echo a.data
     debug(a.ri)
 
-when isMainModule:
+when true:
   var
     root: PBinaryTree[string]
     x = newNode("hello")
@@ -90,9 +93,9 @@ when isMainModule:
   add(root, "world")
   if find(root, "world"):
     for str in items(root):
-      stdout.write(str)
+      echo(str)
   else:
-    stdout.writeLine("BUG")
+    echo("BUG")
 
   var
     r2: PBinaryTree[int]
@@ -100,8 +103,4 @@ when isMainModule:
   add(r2, 223)
   add(r2, 99)
   for y in items(r2):
-    stdout.write(y)
-
-#OUT helloworld99110223
-
-
+    echo(y)
diff --git a/tests/generics/texplicitgeneric1.nim b/tests/generics/texplicitgeneric1.nim
index ac0197c1a..16f4f7330 100644
--- a/tests/generics/texplicitgeneric1.nim
+++ b/tests/generics/texplicitgeneric1.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "texplicitgeneric1.nim"
   output: "Key: 12 value: 12Key: 13 value: 13 Key: A value: 12 Key: B value: 13"
 """
 # test explicit type instantiation
@@ -34,5 +33,4 @@ c.add('B', "13")
 for k, v in items(c):
   stdout.write(" Key: ", $k, " value: ", v)
 
-
-
+stdout.write "\n"
diff --git a/tests/generics/texplicitgeneric2.nim b/tests/generics/texplicitgeneric2.nim
index c4af17b7b..573b10ae8 100644
--- a/tests/generics/texplicitgeneric2.nim
+++ b/tests/generics/texplicitgeneric2.nim
@@ -33,3 +33,4 @@ c.add('B', "13")
 for k, v in items(c):
   stdout.write(" Key: ", $k, " value: ", v)
 
+stdout.write "\n"
diff --git a/tests/generics/tgeneric0.nim b/tests/generics/tgeneric0.nim
index 6698ecec0..3a35ebaba 100644
--- a/tests/generics/tgeneric0.nim
+++ b/tests/generics/tgeneric0.nim
@@ -1,6 +1,7 @@
 discard """
   output: '''
-100 0
+100
+0
 '''
 """
 
@@ -72,7 +73,7 @@ block tgeneric1:
 
   proc print[T](heap: PBinHeap[T]) =
     for i in countup(0, heap.last):
-      stdout.write($heap.heap[i].data, " ")
+      stdout.write($heap.heap[i].data, "\n")
 
   var heap: PBinHeap[int]
 
diff --git a/tests/generics/tgeneric3.nim b/tests/generics/tgeneric3.nim
index 34b415446..4cb12f91b 100644
--- a/tests/generics/tgeneric3.nim
+++ b/tests/generics/tgeneric3.nim
@@ -430,55 +430,50 @@ iterator keys* [T,D] (n: PNode[T,D]): T =
         i = Path[level].Xi
         inc(i)
 
-
-when isMainModule:
-
-  proc test() =
-    var oldvalue: int
-    var root = internalPut[int, int](nil, 312, 312, oldvalue)
-    var someOtherRoot = internalPut[string, int](nil, "312", 312, oldvalue)
-    var it1 = internalFind(root, 312)
-    echo it1.value
-
-    for i in 1..1_000_000:
-      root = internalPut(root, i, i, oldvalue)
-
-    var cnt = 0
-    oldvalue = -1
-    when true : # code compiles, when this or the other when is switched to false
-      for k in root.keys :
-        if k <= oldvalue :
-          echo k
-        oldvalue = k
-        inc(cnt)
-      echo cnt
+proc test() =
+  var oldvalue: int
+  var root = internalPut[int, int](nil, 312, 312, oldvalue)
+  var someOtherRoot = internalPut[string, int](nil, "312", 312, oldvalue)
+  var it1 = internalFind(root, 312)
+  echo it1.value
+
+  for i in 1..1_000_000:
+    root = internalPut(root, i, i, oldvalue)
+
+  var cnt = 0
+  oldvalue = -1
+  when true : # code compiles, when this or the other when is switched to false
+    for k in root.keys :
+      if k <= oldvalue :
+        echo k
+      oldvalue = k
+      inc(cnt)
+    echo cnt
+  when true :
+    cnt = 0
+    VisitAll(root, proc(key, val: int) = inc(cnt))
+    echo cnt
     when true :
-      cnt = 0
-      VisitAll(root, proc(key, val: int) = inc(cnt))
-      echo cnt
-      when true :
-        root = VisitAll(root, proc(key: int, value: var int): bool =
-          return key mod 2 == 0 )
-      cnt = 0
-      oldvalue = -1
-      VisitAll(root, proc(key: int, value: int) {.closure.} =
-        if key <= oldvalue :
-          echo key
-        oldvalue = key
-        inc(cnt) )
-      echo cnt
       root = VisitAll(root, proc(key: int, value: var int): bool =
-        return key mod 2 != 0 )
-      cnt = 0
-      oldvalue = -1
-      VisitAll(root, proc(key: int, value: int) {.closure.} =
-        if key <= oldvalue :
-          echo "error ", key
-        oldvalue = key
-        inc(cnt) )
-      echo cnt
-      #traceTree(root)
-
-
-
-  test()
+        return key mod 2 == 0 )
+    cnt = 0
+    oldvalue = -1
+    VisitAll(root, proc(key: int, value: int) {.closure.} =
+      if key <= oldvalue :
+        echo key
+      oldvalue = key
+      inc(cnt) )
+    echo cnt
+    root = VisitAll(root, proc(key: int, value: var int): bool =
+      return key mod 2 != 0 )
+    cnt = 0
+    oldvalue = -1
+    VisitAll(root, proc(key: int, value: int) {.closure.} =
+      if key <= oldvalue :
+        echo "error ", key
+      oldvalue = key
+      inc(cnt) )
+    echo cnt
+    #traceTree(root)
+
+test()
diff --git a/tests/generics/tgenericprocvar.nim b/tests/generics/tgenericprocvar.nim
index dca9c8538..7935d90c2 100644
--- a/tests/generics/tgenericprocvar.nim
+++ b/tests/generics/tgenericprocvar.nim
@@ -34,3 +34,4 @@ proc test(data: seq[int], value: int): seq[int] =
 for x in items(test(@[1,2,3], 2)):
   stdout.write(x)
 
+stdout.write "\n"
diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim
index c215ea2c2..a1d464b97 100644
--- a/tests/generics/tgenerics_issues.nim
+++ b/tests/generics/tgenerics_issues.nim
@@ -24,12 +24,11 @@ G:0,1:0.1
 G:0,1:0.1
 H:1:0.1
 '''
+joinable: false
 """
 
-
 import macros, sequtils, sets, sugar, tables, typetraits
 
-
 block t88:
   type
     BaseClass[V] = object of RootObj
diff --git a/tests/generics/tgenerics_various.nim b/tests/generics/tgenerics_various.nim
index 5e18995f5..9e6186534 100644
--- a/tests/generics/tgenerics_various.nim
+++ b/tests/generics/tgenerics_various.nim
@@ -5,12 +5,11 @@ direct
 generic
 generic
 '''
+joinable: false
 """
 
-
 import algorithm, sugar, sequtils, typetraits, asyncdispatch
 
-
 block tconfusing_arrow:
   type Deck = object
     value: int
diff --git a/tests/generics/tgenericvariant.nim b/tests/generics/tgenericvariant.nim
index 73c8af825..5ba3a2e7c 100644
--- a/tests/generics/tgenericvariant.nim
+++ b/tests/generics/tgenericvariant.nim
@@ -26,9 +26,11 @@ proc safeReadLine(): TMaybe[string] =
   if r == "": return Nothing[string]()
   else: return Just(r)
 
-when isMainModule:
+proc main() =
   var Test = Just("Test")
   echo(Test.value)
   var mSomething = safeReadLine()
   echo(mSomething.value)
   mSomething = safeReadLine()
+
+main()
diff --git a/tests/generics/toverloading_typedesc.nim b/tests/generics/toverloading_typedesc.nim
index 94f4d860d..5ab700828 100644
--- a/tests/generics/toverloading_typedesc.nim
+++ b/tests/generics/toverloading_typedesc.nim
@@ -10,7 +10,7 @@ type
   LBar = object
 
 
-when isMainModule:
+when true:
   doAssert FBar.new() == 3
 
   proc new(_: typedesc[LFoo]): int = 0
diff --git a/tests/generics/tparser_generator.nim b/tests/generics/tparser_generator.nim
index 01ddd29b8..8f8fea382 100644
--- a/tests/generics/tparser_generator.nim
+++ b/tests/generics/tparser_generator.nim
@@ -1,6 +1,7 @@
 discard """
   output: '''Match failed: spam
 Match failed: ham'''
+joinable: false
 """
 
 # bug #6220
@@ -397,19 +398,18 @@ template grammar*[K](Kind, Text, Symbol: typedesc; default: K, code: untyped): t
 template grammar*[K](Kind: typedesc; default: K, code: untyped): typed {.hint[XDeclaredButNotUsed]: off.} =
   grammar(Kind, string, char, default, code)
 
-when isMainModule:
-  block:
-    type DummyKind = enum dkDefault
-    grammar(DummyKind, string, char, dkDefault):
-      let rule = token("h[a]+m") + ignore(token(r"\s+")) + (literal("eggs") / literal("beans"))
-      var text = "ham beans"
-      discard rule.parse(text)
-
-      var recursive = newRule()
-      recursive -> (literal("(") + recursive + literal(")")) / token(r"\d+")
-      for test in ["spam", "57", "(25)", "((25))"]:
-        discard recursive.parse(test)
-
-      let repeated = +literal("spam") + ?literal("ham") + *literal("salami")
-      for test in ["ham", "spam", "spamspamspam" , "spamham", "spamsalami", "spamsalamisalami"]:
-        discard  repeated.parse(test)
+block:
+  type DummyKind = enum dkDefault
+  grammar(DummyKind, string, char, dkDefault):
+    let rule = token("h[a]+m") + ignore(token(r"\s+")) + (literal("eggs") / literal("beans"))
+    var text = "ham beans"
+    discard rule.parse(text)
+
+    var recursive = newRule()
+    recursive -> (literal("(") + recursive + literal(")")) / token(r"\d+")
+    for test in ["spam", "57", "(25)", "((25))"]:
+      discard recursive.parse(test)
+
+    let repeated = +literal("spam") + ?literal("ham") + *literal("salami")
+    for test in ["ham", "spam", "spamspamspam" , "spamham", "spamsalami", "spamsalamisalami"]:
+      discard  repeated.parse(test)
diff --git a/tests/generics/trtree.nim b/tests/generics/trtree.nim
index 321b31df6..6ec1c8f6f 100644
--- a/tests/generics/trtree.nim
+++ b/tests/generics/trtree.nim
@@ -2,8 +2,11 @@ discard """
   output: '''1 [2, 3, 4, 7]
 [0, 0]'''
   target: "c"
+  joinable: false
 """
 
+# don't join because the code is too messy.
+
 # Nim RTree and R*Tree implementation
 # S. Salewski, 06-JAN-2018
 
@@ -589,70 +592,68 @@ proc delete*[M, D: Dim; RT, LT](t: RTree[M, D, RT, LT]; leaf: L[D, RT, LT]): boo
       t.root.parent = nil
     return true
 
-when isMainModule:
-
-  var t = [4, 1, 3, 2]
-  var xt = 7
-  sortPlus(t, xt, system.cmp, SortOrder.Ascending)
-  echo xt, " ", t
-
-  type
-    RSE = L[2, int, int]
-    RSeq = seq[RSE]
-
-  proc rseq_search(rs: RSeq; rse: RSE): seq[int] =
-    result = newSeq[int]()
-    for i in rs:
-      if intersect(i.b, rse.b):
-        result.add(i.l)
-
-  proc rseq_delete(rs: var RSeq; rse: RSE): bool =
-    for i in 0 .. rs.high:
-      if rs[i] == rse:
-        #rs.delete(i)
-        rs[i] = rs[rs.high]
-        rs.setLen(rs.len - 1)
-        return true
-
-  import random, algorithm
-
-  proc test(n: int) =
-    var b: Box[2, int]
-    echo center(b)
-    var x1, x2, y1, y2: int
-    var t = newRStarTree[8, 2, int, int]()
-    #var t = newRTree[8, 2, int, int]()
-    var rs = newSeq[RSE]()
-    for i in 0 .. 5:
-      for i in 0 .. n - 1:
-        x1 = rand(1000)
-        y1 = rand(1000)
-        x2 = x1 + rand(25)
-        y2 = y1 + rand(25)
-        b = [(x1, x2), (y1, y2)]
-        let el: L[2, int, int] = (b, i + 7)
-        t.insert(el)
-        rs.add(el)
-
-      for i in 0 .. (n div 4):
-        let j = rand(rs.high)
-        var el = rs[j]
-        assert t.delete(el)
-        assert rs.rseq_delete(el)
-
-      for i in 0 .. n - 1:
-        x1 = rand(1000)
-        y1 = rand(1000)
-        x2 = x1 + rand(100)
-        y2 = y1 + rand(100)
-        b = [(x1, x2), (y1, y2)]
-        let el: L[2, int, int] = (b, i)
-        let r = search(t, b)
-        let r2 = rseq_search(rs, el)
-        assert r.len == r2.len
-        assert r.sorted(system.cmp) == r2.sorted(system.cmp)
-
-  test(1500)
-
-  # 651 lines
 
+var t = [4, 1, 3, 2]
+var xt = 7
+sortPlus(t, xt, system.cmp, SortOrder.Ascending)
+echo xt, " ", t
+
+type
+  RSE = L[2, int, int]
+  RSeq = seq[RSE]
+
+proc rseq_search(rs: RSeq; rse: RSE): seq[int] =
+  result = newSeq[int]()
+  for i in rs:
+    if intersect(i.b, rse.b):
+      result.add(i.l)
+
+proc rseq_delete(rs: var RSeq; rse: RSE): bool =
+  for i in 0 .. rs.high:
+    if rs[i] == rse:
+      #rs.delete(i)
+      rs[i] = rs[rs.high]
+      rs.setLen(rs.len - 1)
+      return true
+
+import random, algorithm
+
+proc test(n: int) =
+  var b: Box[2, int]
+  echo center(b)
+  var x1, x2, y1, y2: int
+  var t = newRStarTree[8, 2, int, int]()
+  #var t = newRTree[8, 2, int, int]()
+  var rs = newSeq[RSE]()
+  for i in 0 .. 5:
+    for i in 0 .. n - 1:
+      x1 = rand(1000)
+      y1 = rand(1000)
+      x2 = x1 + rand(25)
+      y2 = y1 + rand(25)
+      b = [(x1, x2), (y1, y2)]
+      let el: L[2, int, int] = (b, i + 7)
+      t.insert(el)
+      rs.add(el)
+
+    for i in 0 .. (n div 4):
+      let j = rand(rs.high)
+      var el = rs[j]
+      assert t.delete(el)
+      assert rs.rseq_delete(el)
+
+    for i in 0 .. n - 1:
+      x1 = rand(1000)
+      y1 = rand(1000)
+      x2 = x1 + rand(100)
+      y2 = y1 + rand(100)
+      b = [(x1, x2), (y1, y2)]
+      let el: L[2, int, int] = (b, i)
+      let r = search(t, b)
+      let r2 = rseq_search(rs, el)
+      assert r.len == r2.len
+      assert r.sorted(system.cmp) == r2.sorted(system.cmp)
+
+test(1500)
+
+# 651 lines
diff --git a/tests/generics/tthread_generic.nim b/tests/generics/tthread_generic.nim
index f2e9cafa9..2af5a7615 100644
--- a/tests/generics/tthread_generic.nim
+++ b/tests/generics/tthread_generic.nim
@@ -26,7 +26,7 @@ proc `@||->`*[T](fn: proc(): T {.thread.},
 proc `||->`*[T](fn: proc(): T{.thread.}, callback: proc(val: T){.thread.}) =
   discard fn @||-> callback
 
-when isMainModule:
+when true:
   import os
   proc testFunc(): int {.thread.} =
     return 1
diff --git a/tests/generics/twrong_floatlit_type.nim b/tests/generics/twrong_floatlit_type.nim
index c1830cd5a..04bacc0d9 100644
--- a/tests/generics/twrong_floatlit_type.nim
+++ b/tests/generics/twrong_floatlit_type.nim
@@ -108,7 +108,7 @@ proc `/`*[S](a, b: Vector2D[S]): Vector2D[S] =
 proc vec[S](x, y: S): Vector2D[S] =
   Vector2D[S](x: x, y: y)
 
-if isMainModule:
+if true:
   # Comment out this let, and the program will fail to
   # compile with a type mismatch, as expected.
 
diff --git a/tests/global/t5958.nim b/tests/global/t5958.nim
index 5abcad4a9..9b7642363 100644
--- a/tests/global/t5958.nim
+++ b/tests/global/t5958.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 9
   errormsg: "undeclared identifier: 'a'"
+  line: 9
 """
 
 static:
diff --git a/tests/implicit/timplicit.nim b/tests/implicit/timplicit.nim
index 70f14db53..bb701249c 100644
--- a/tests/implicit/timplicit.nim
+++ b/tests/implicit/timplicit.nim
@@ -6,6 +6,7 @@ discard """
 4
 2
 88
+timplicit done
 '''
 """
 
@@ -43,4 +44,6 @@ block:
   var indirect = p
   x.indirect(44)
 
-  echo x[]
\ No newline at end of file
+  echo x[]
+
+  echo "timplicit done"
diff --git a/tests/iter/tcountup.nim b/tests/iter/tcountup.nim
index 1559041aa..f93f1536e 100644
--- a/tests/iter/tcountup.nim
+++ b/tests/iter/tcountup.nim
@@ -1,14 +1,9 @@
 discard """
-  file: "tcountup.nim"
   output: "0123456789"
 """
 
-# Test new countup and unary <
+# Test new countup
 
-for i in 0 .. < 10'i64:
+for i in 0 ..< 10'i64:
   stdout.write(i)
-
-#OUT 0123456789
-
-
-
+echo "\n"
diff --git a/tests/iter/titer10.nim b/tests/iter/titer10.nim
index 6a6afc780..9c76b62e1 100644
--- a/tests/iter/titer10.nim
+++ b/tests/iter/titer10.nim
@@ -23,7 +23,7 @@ when true:
       for val in sortable:
           yield val
 
-  when isMainModule:
+  when true:
     proc main =
       for val in byDistance([2, 3, 5, 1], 3):
           echo val
diff --git a/tests/iter/titer11.nim b/tests/iter/titer11.nim
index 6c410e945..c4c7d4a16 100644
--- a/tests/iter/titer11.nim
+++ b/tests/iter/titer11.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "titer11.nim"
-  output: '''[
+output: '''
+[
 1
 2
 3
diff --git a/tests/iter/titer3.nim b/tests/iter/titer3.nim
index cc603fd85..9dcfd7be5 100644
--- a/tests/iter/titer3.nim
+++ b/tests/iter/titer3.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "titer3.nim"
   output: '''1231
 4
 6
diff --git a/tests/iter/titer4.nim b/tests/iter/titer4.nim
index 9b52f8055..912883a63 100644
--- a/tests/iter/titer4.nim
+++ b/tests/iter/titer4.nim
@@ -1,10 +1,8 @@
 discard """
+  errormsg: "iterator within for loop context expected"
   file: "titer4.nim"
   line: 7
-  errormsg: "iterator within for loop context expected"
 """
 # implicit items/pairs, but not if we have 3 for loop vars:
 for x, y, z in {'a'..'z'}: #ERROR_MSG iterator within for loop context expected
   nil
-
-
diff --git a/tests/iter/titer5.nim b/tests/iter/titer5.nim
index bbd50fcb1..cb691ffdb 100644
--- a/tests/iter/titer5.nim
+++ b/tests/iter/titer5.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "titer5.nim"
   output: "abcxyz"
 """
 # Test method call syntax for iterators:
@@ -11,6 +10,4 @@ for x in lines.split():
   stdout.write(x)
 
 #OUT abcxyz
-
-
-
+stdout.write "\n"
diff --git a/tests/iter/titer6.nim b/tests/iter/titer6.nim
index b7c8fee80..69a10d868 100644
--- a/tests/iter/titer6.nim
+++ b/tests/iter/titer6.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "titer6.nim"
   output: "000"
 """
 # Test iterator with more than 1 yield statement
@@ -33,5 +32,4 @@ proc wordWrap2(s: string, maxLineWidth = 80,
   for word, isSep in tokenize2(s, seps):
     var w = 0
 
-
-
+stdout.write "\n"
diff --git a/tests/iter/titer7.nim b/tests/iter/titer7.nim
index c2bd9b9cb..9cba3038d 100644
--- a/tests/iter/titer7.nim
+++ b/tests/iter/titer7.nim
@@ -45,9 +45,9 @@ proc square(x:int): int =
 let list = @[1,2,3,4,5,6,7,8,9]
 
 echo ("--- evens")
-for item in list / isEven : echo(item)
+for item in list / isEven: echo(item)
 echo ("--- squares")
-for item in list >> square : echo(item)
+for item in list >> square: echo(item)
 #echo ("--- squares of evens, only")
 # next line doesn't compile. Generic types are not inferred
 #for item in list />> (isEven, square) : echo(item)
diff --git a/tests/iter/tconcat.nim b/tests/iter/titerconcat.nim
index 477ac5e26..477ac5e26 100644
--- a/tests/iter/tconcat.nim
+++ b/tests/iter/titerconcat.nim
diff --git a/tests/iter/titervaropenarray.nim b/tests/iter/titervaropenarray.nim
index 9eea085e3..701f652df 100644
--- a/tests/iter/titervaropenarray.nim
+++ b/tests/iter/titervaropenarray.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "titer2.nim"
   output: "123"
 """
 # Try to break the transformation pass:
@@ -11,3 +10,5 @@ iterator iterAndZero(a: var openArray[int]): int =
 var x = [[1, 2, 3], [4, 5, 6]]
 for y in iterAndZero(x[0]): write(stdout, $y)
 #OUT 123
+
+write stdout, "\n"
diff --git a/tests/iter/treciter.nim b/tests/iter/treciter.nim
index dacdbdfd7..7b61326f4 100644
--- a/tests/iter/treciter.nim
+++ b/tests/iter/treciter.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "recursive dependency: \'myrec\'"
   file: "treciter.nim"
   line: 9
-  errormsg: "recursive dependency: \'myrec\'"
 """
 # Test that an error message occurs for a recursive iterator
 
@@ -10,5 +10,3 @@ iterator myrec(n: int): int =
     yield x
 
 for x in myrec(10): echo x
-
-
diff --git a/tests/iter/twrongiter.nim b/tests/iter/twrongiter.nim
index 33394219b..577b8c4f1 100644
--- a/tests/iter/twrongiter.nim
+++ b/tests/iter/twrongiter.nim
@@ -1,6 +1,6 @@
 discard """
-line: 12
 errormsg: "type mismatch"
+line: 12
 """
 
 proc first(it: iterator(): int): seq[int] =
diff --git a/tests/js/t7224.nim b/tests/js/t7224.nim
index 2d7ee1336..be9d0ae9c 100644
--- a/tests/js/t7224.nim
+++ b/tests/js/t7224.nim
@@ -7,7 +7,7 @@ t7224.ccc, line: 15
 t7224.ddd, line: 12
 '''
 """
-  
+
 proc ddd() =
   raise newException(IOError, "didn't do stuff")
 
@@ -22,5 +22,6 @@ proc aaa() =
 
 try:
   aaa()
+
 except IOError as e:
   echo getStackTrace(e)
diff --git a/tests/js/tvarargs.nim b/tests/js/tvarargs.nim
index b8c532767..8d57af58d 100644
--- a/tests/js/tvarargs.nim
+++ b/tests/js/tvarargs.nim
@@ -11,5 +11,5 @@ type
 
 var console* {.importc.}: Console
 
-when isMainModule:
+when true:
   console.log "Hello, world"
diff --git a/tests/let/tlet.nim b/tests/let/tlet.nim
index 6703ba254..25d7b9bf7 100644
--- a/tests/let/tlet.nim
+++ b/tests/let/tlet.nim
@@ -1,6 +1,6 @@
 discard """
-  line: "10"
   errormsg: "'name' cannot be assigned to"
+  line: "10"
 """
 
 echo("What's your name? ")
@@ -8,4 +8,3 @@ let name = readLine(stdin)
 while name == "":
   echo("Please tell me your name: ")
   name = readLine(stdin)
-
diff --git a/tests/let/tlet2.nim b/tests/let/tlet2.nim
index 2df15fa5c..63e7d6128 100644
--- a/tests/let/tlet2.nim
+++ b/tests/let/tlet2.nim
@@ -1,6 +1,6 @@
 discard """
-  line: "13"
   errormsg: "type mismatch: got <int literal(8), int literal(5), int, int>"
+  line: "13"
 """
 
 proc divmod(a, b: int, res, remainder: var int) =
@@ -13,4 +13,3 @@ let
 divmod(8, 5, x, y) # modifies x and y
 echo(x)
 echo(y)
-
diff --git a/tests/lexer/tind1.nim b/tests/lexer/tind1.nim
index ffbde48fd..2185c3074 100644
--- a/tests/lexer/tind1.nim
+++ b/tests/lexer/tind1.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 24
   errormsg: "invalid indentation"
+  line: 24
 """
 
 import macros
diff --git a/tests/lexer/tinvalidintegerliteral1.nim b/tests/lexer/tinvalidintegerliteral1.nim
index 08ab82a22..6bf7624f3 100644
--- a/tests/lexer/tinvalidintegerliteral1.nim
+++ b/tests/lexer/tinvalidintegerliteral1.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "invalid number"
   file: "tinvalidintegerliteral1.nim"
   line: 7
-  errormsg: "invalid number"
 """
 
 echo 0b
diff --git a/tests/lexer/tinvalidintegerliteral2.nim b/tests/lexer/tinvalidintegerliteral2.nim
index bc8793e4e..eb6efc131 100644
--- a/tests/lexer/tinvalidintegerliteral2.nim
+++ b/tests/lexer/tinvalidintegerliteral2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "invalid number"
   file: "tinvalidintegerliteral2.nim"
   line: 7
-  errormsg: "invalid number"
 """
 
 echo 0x
diff --git a/tests/lexer/tinvalidintegerliteral3.nim b/tests/lexer/tinvalidintegerliteral3.nim
index 9c2fe69df..e09cda54a 100644
--- a/tests/lexer/tinvalidintegerliteral3.nim
+++ b/tests/lexer/tinvalidintegerliteral3.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "0O5 is an invalid int literal; For octal literals use the '0o' prefix."
   file: "tinvalidintegerliteral3.nim"
   line: 7
-  errormsg: "0O5 is an invalid int literal; For octal literals use the '0o' prefix."
 """
 
 echo 0O5
diff --git a/tests/lexer/tmissingnl.nim b/tests/lexer/tmissingnl.nim
index 095d9570e..dc939bcd2 100644
--- a/tests/lexer/tmissingnl.nim
+++ b/tests/lexer/tmissingnl.nim
@@ -1,10 +1,9 @@
 discard """
+  errormsg: "invalid indentation"
   file: "tmissingnl.nim"
   line: 7
-  errormsg: "invalid indentation"
 """
 
 import strutils let s: seq[int] = @[0, 1, 2, 3, 4, 5, 6]
 
 #s[1..3] = @[]
-
diff --git a/tests/lexer/tstrlits.nim b/tests/lexer/tstrlits.nim
index d13baf7ff..8e8250a5b 100644
--- a/tests/lexer/tstrlits.nim
+++ b/tests/lexer/tstrlits.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstrlits.nim"
   output: "a\"\"long string\"\"\"\"\"abc\"def_'2'●𝌆𝌆A"
 """
 # Test the new different string literals
@@ -17,8 +16,4 @@ const
 stdout.write(rawQuote)
 stdout.write(tripleEmpty)
 stdout.write(raw)
-stdout.write(escaped)
-#OUT a""long string"""""abc"def_'2'●𝌆𝌆A
-
-
-
+stdout.writeLine(escaped)
diff --git a/tests/lexer/tunderscores.nim b/tests/lexer/tunderscores.nim
index f64f36977..1896a2898 100644
--- a/tests/lexer/tunderscores.nim
+++ b/tests/lexer/tunderscores.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "invalid token: trailing underscore"
   file: "tunderscores.nim"
   line: 8
-  errormsg: "invalid token: trailing underscore"
 """
 # Bug #502670
 
@@ -9,6 +9,3 @@ var ef_ = 3  #ERROR_MSG invalid token: _
 var a__b = 1
 var c___d = 2
 echo(ab, cd, ef_)
-
-
-
diff --git a/tests/macros/tmacro4.nim b/tests/macros/tmacro4.nim
index 164afaeb7..7c2839aba 100644
--- a/tests/macros/tmacro4.nim
+++ b/tests/macros/tmacro4.nim
@@ -11,7 +11,7 @@ macro test_macro*(s: string, n: untyped): untyped =
   add(ass, newIdentNode("str"))
   add(ass, newStrLitNode("after"))
   add(result, ass)
-when isMainModule:
+when true:
   var str: string = "before"
   test_macro(str):
     var i : integer = 123
diff --git a/tests/macros/tmacrogenerics.nim b/tests/macros/tmacrogenerics.nim
index e4acdc321..bb562cacb 100644
--- a/tests/macros/tmacrogenerics.nim
+++ b/tests/macros/tmacrogenerics.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tmacrogenerics.nim"
   nimout: '''
 instantiation 1 with None and None
 instantiation 2 with None and None
diff --git a/tests/macros/tgensym.nim b/tests/macros/tmacrogensym.nim
index 1237b8bf7..1237b8bf7 100644
--- a/tests/macros/tgensym.nim
+++ b/tests/macros/tmacrogensym.nim
diff --git a/tests/macros/tquotewords.nim b/tests/macros/tquotewords.nim
index fa00ba9de..e718d25f9 100644
--- a/tests/macros/tquotewords.nim
+++ b/tests/macros/tquotewords.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tquotewords.nim"
   output: "thisanexample"
 """
 # Test an idea I recently had:
diff --git a/tests/macros/trecmacro.nim b/tests/macros/trecmacro.nim
index 69ebe3da3..d804178bc 100644
--- a/tests/macros/trecmacro.nim
+++ b/tests/macros/trecmacro.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "recursive dependency: 'dump'"
   file: "trecmacro.nim"
   line: 8
-  errormsg: "recursive dependency: 'dump'"
 """
 
 macro dump(n: untyped): untyped =
diff --git a/tests/macros/tsametype.nim b/tests/macros/tsametype.nim
index 865fb4cb8..5219a3767 100644
--- a/tests/macros/tsametype.nim
+++ b/tests/macros/tsametype.nim
@@ -9,6 +9,7 @@ true
 false
 true
 false'''
+joinable: false
 """
 
 import macros
diff --git a/tests/macros/tstringinterp.nim b/tests/macros/tstringinterp.nim
index 305f40ac5..74c73599b 100644
--- a/tests/macros/tstringinterp.nim
+++ b/tests/macros/tstringinterp.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstringinterp.nim"
   output: "Hello Alice, 64 | Hello Bob, 10$"
 """
 
@@ -71,3 +70,4 @@ var
   s2 = formatStyleInterpolation"Hello ${bob}, ${sum(alice.len, bob.len, 2)}$$"
 
 write(stdout, s1 & " | " & s2)
+write(stdout, "\n")
diff --git a/tests/magics/tmagics.nim b/tests/magics/tmagics.nim
index 841de56a5..fa138320c 100644
--- a/tests/magics/tmagics.nim
+++ b/tests/magics/tmagics.nim
@@ -8,20 +8,21 @@ true
 false
 true
 '''
+joinable: false
 """
 
 block tlowhigh:
   type myEnum = enum e1, e2, e3, e4, e5
   var a: array[myEnum, int]
-  
+
   for i in low(a) .. high(a):
     a[i] = 0
-  
+
   proc sum(a: openarray[int]): int =
     result = 0
     for i in low(a)..high(a):
       inc(result, a[i])
-  
+
   doAssert sum([1, 2, 3, 4]) == 10
 
 
diff --git a/tests/manyloc/argument_parser/argument_parser.nim b/tests/manyloc/argument_parser/argument_parser.nim
index d42842f93..9a37ef8c9 100644
--- a/tests/manyloc/argument_parser/argument_parser.nim
+++ b/tests/manyloc/argument_parser/argument_parser.nim
@@ -486,7 +486,7 @@ proc echo_help*(expected: seq[Tparameter_specification] = @[],
     echo line
 
 
-when isMainModule:
+when true:
   # Simply tests code embedded in docs.
   let
     parsed_param1 = new_parsed_parameter(PK_FLOAT, 3.41)
diff --git a/tests/manyloc/argument_parser/ex_wget.nim b/tests/manyloc/argument_parser/ex_wget.nim
index 625a6f595..ebbf1933f 100644
--- a/tests/manyloc/argument_parser/ex_wget.nim
+++ b/tests/manyloc/argument_parser/ex_wget.nim
@@ -81,7 +81,7 @@ proc process_commandline(): Tcommandline_results =
     echo "Will use progress type $1" % [result.options[PARAM_PROGRESS[0]].str_val]
 
 
-when isMainModule:
+when true:
   let args = process_commandline()
   for param in args.positional_parameters:
     echo "Downloading $1" % param.str_val
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim
index 3026cc4b9..fe9909750 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket.nim
@@ -252,7 +252,7 @@ template forwardPacketT*(typeName: expr): stmt {.dirty, immediate.} =
   proc `pack typeName`*(p: var typeName; s: PStream) =
     writeData(s, addr p, sizeof(p))
 
-when isMainModule:
+when true:
   type
     SomeEnum = enum
       A = 0'i8,
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
index dccbe61ba..b36b49823 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/genpacket_enet.nim
@@ -244,7 +244,7 @@ template forwardPacketT*(typeName: untyped; underlyingType: untyped) {.dirty.} =
     #writeData(s, addr p, sizeof(p))
     buffer.write(underlyingType(ord))
 
-when isMainModule:
+when false:
   type
     SomeEnum = enum
       A = 0'i8,
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
index 33d2a7177..3341f42c2 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/macro_dsl.nim
@@ -50,7 +50,7 @@ macro `?`(a: untyped): untyped =
   result = ($a[1].ident)[0].lit
 ## echo(?F,?a,?t,?t,?y)
 
-when isMainModule:
+when false:
   macro foo(x: untyped) =
     result = newNimNode(nnkStmtList)
     result.add(newNimNode(nnkCall).und(!!"echo", "Hello thar".lit))
diff --git a/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim b/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim
index 5a1dffc93..ad0d20f1c 100644
--- a/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim
+++ b/tests/manyloc/keineschweine/dependencies/genpacket/streams_enh.nim
@@ -24,7 +24,7 @@ proc writeLEStr*(s: PStream, str: string) =
   s.write(str.len.int16)
   s.write(str)
 
-when isMainModule:
+when true:
   var testStream = newStringStream()
 
   testStream.writeLEStr("Hello")
diff --git a/tests/manyloc/keineschweine/dependencies/nake/nake.nim b/tests/manyloc/keineschweine/dependencies/nake/nake.nim
index 5341c1079..83569e30e 100644
--- a/tests/manyloc/keineschweine/dependencies/nake/nake.nim
+++ b/tests/manyloc/keineschweine/dependencies/nake/nake.nim
@@ -50,7 +50,7 @@ template withDir*(dir: string; body: stmt): stmt =
   body
   cd(curDir)
 
-when isMainModule:
+when true:
   if not existsFile("nakefile.nim"):
     echo "No nakefile.nim found. Current working dir is ", getCurrentDir()
     quit 1
diff --git a/tests/manyloc/keineschweine/enet_server/enet_server.nim b/tests/manyloc/keineschweine/enet_server/enet_server.nim
index eae7c034e..3bb259386 100644
--- a/tests/manyloc/keineschweine/enet_server/enet_server.nim
+++ b/tests/manyloc/keineschweine/enet_server/enet_server.nim
@@ -102,7 +102,7 @@ handlers[HZoneJoinReq] = proc(client: PClient; buffer: PBuffer) =
 
 
 
-when isMainModule:
+when true:
   import parseopt, matchers, os, json
 
 
diff --git a/tests/manyloc/keineschweine/keineschweine.nim b/tests/manyloc/keineschweine/keineschweine.nim
index 04fec2788..b6fd3cc19 100644
--- a/tests/manyloc/keineschweine/keineschweine.nim
+++ b/tests/manyloc/keineschweine/keineschweine.nim
@@ -663,7 +663,7 @@ proc mainRender() =
 proc readyMainState() =
   specInputClient.setActive()
 
-when isMainModule:
+when true:
   import parseopt
 
   localPlayer = newPlayer()
diff --git a/tests/manyloc/keineschweine/lib/estreams.nim b/tests/manyloc/keineschweine/lib/estreams.nim
index 00a55c626..99cbb63d1 100644
--- a/tests/manyloc/keineschweine/lib/estreams.nim
+++ b/tests/manyloc/keineschweine/lib/estreams.nim
@@ -106,7 +106,7 @@ proc readChar*(buffer: PBuffer): char {.inline.} = return readInt8(buffer).char
 proc readBool*(buffer: PBuffer): bool {.inline.} = return readInt8(buffer).bool
 
 
-when isMainModule:
+when false:
   var b = newBuffer(100)
   var str = "hello there"
   b.write str
diff --git a/tests/manyloc/keineschweine/lib/map_filter.nim b/tests/manyloc/keineschweine/lib/map_filter.nim
index f3f1df190..acb58c60e 100644
--- a/tests/manyloc/keineschweine/lib/map_filter.nim
+++ b/tests/manyloc/keineschweine/lib/map_filter.nim
@@ -17,7 +17,7 @@ template unless*(condition: untyped; body: untyped) {.dirty.} =
   if not condition:
     body
 
-when isMainModule:
+when false:
   proc dumpSeq[T](x: seq[T]) =
     for index, item in x.pairs:
       echo index, " ", item
diff --git a/tests/manyloc/keineschweine/lib/sg_packets.nim b/tests/manyloc/keineschweine/lib/sg_packets.nim
index f3a0e8925..9a5aa5496 100644
--- a/tests/manyloc/keineschweine/lib/sg_packets.nim
+++ b/tests/manyloc/keineschweine/lib/sg_packets.nim
@@ -92,7 +92,7 @@ defPacket(DsMsg, tuple[msg: string])
 let HVerifyClient* = 'v'
 defPacket(SdVerifyClient, tuple[session: ScLogin])
 
-when isMainModule:
+when true:
 
   var buf = newBuffer(100)
   var m = toMd5("hello there")
diff --git a/tests/manyloc/keineschweine/lib/zlib_helpers.nim b/tests/manyloc/keineschweine/lib/zlib_helpers.nim
index 076475964..895f41759 100644
--- a/tests/manyloc/keineschweine/lib/zlib_helpers.nim
+++ b/tests/manyloc/keineschweine/lib/zlib_helpers.nim
@@ -20,7 +20,7 @@ proc uncompress*(source: string, destLen: var int): string =
     echo "Error occurred: ", res
 
 
-when isMainModule:
+when true:
   import strutils
   var r = compress("Hello")
   echo repr(r)
diff --git a/tests/manyloc/keineschweine/server/old_dirserver.nim b/tests/manyloc/keineschweine/server/old_dirserver.nim
index 202dc6fe7..cfb0b0377 100644
--- a/tests/manyloc/keineschweine/server/old_dirserver.nim
+++ b/tests/manyloc/keineschweine/server/old_dirserver.nim
@@ -156,7 +156,7 @@ proc poll*(timeout: int = 250) =
       echo("Write ", c, " result: ", res, " data: ", repr(c.outputBuf.data))
       c.outputBuf.flush()
 
-when isMainModule:
+when true:
   import parseopt, matchers, strutils
   var cfgFile = "dirserver_settings.json"
   for kind, key, val in getOpt():
diff --git a/tests/manyloc/keineschweine/server/old_sg_server.nim b/tests/manyloc/keineschweine/server/old_sg_server.nim
index bddc74c6d..d046df9dd 100644
--- a/tests/manyloc/keineschweine/server/old_sg_server.nim
+++ b/tests/manyloc/keineschweine/server/old_sg_server.nim
@@ -141,7 +141,7 @@ proc poll*(timeout: int = 250) =
       echo("Write ", c, " result: ", res, " data: ", c.outputBuf.data)
       c.outputBuf.flush()
 
-when isMainModule:
+when true:
   import parseopt, matchers, strutils
   var zoneCfgFile = "./server_settings.json"
   for kind, key, val in getOpt():
diff --git a/tests/manyloc/nake/nake.nim b/tests/manyloc/nake/nake.nim
index ff3c10a17..ebcf21d19 100644
--- a/tests/manyloc/nake/nake.nim
+++ b/tests/manyloc/nake/nake.nim
@@ -50,7 +50,7 @@ template withDir*(dir: string; body: untyped) =
   body
   cd(curDir)
 
-when isMainModule:
+when true:
   if not existsFile("nakefile.nim"):
     echo "No nakefile.nim found. Current working dir is ", getCurrentDir()
     quit 1
diff --git a/tests/metatype/tmatrix1.nim b/tests/metatype/tmatrix1.nim
index 0f325a17b..15913499f 100644
--- a/tests/metatype/tmatrix1.nim
+++ b/tests/metatype/tmatrix1.nim
@@ -8,10 +8,10 @@ type
   TMatrix2x2*[T] = TMatrixNM[range[0..1], range[0..1], T]
   TMatrix3x3*[T] = TMatrixNM[range[0..2], range[0..2], T]
 
-proc test*[T] (matrix: TMatrix2x2[T]) =
+proc test*[T](matrix: TMatrix2x2[T]) =
   echo "wrong proc called"
 
-proc test*[T] (matrix: TMatrix3x3[T]) =
+proc test*[T](matrix: TMatrix3x3[T]) =
   echo "right proc called"
 
 var matrix: TMatrix3x3[float]
diff --git a/tests/metatype/ttypeclasses.nim b/tests/metatype/tmeta_typeclasses.nim
index 720527088..720527088 100644
--- a/tests/metatype/ttypeclasses.nim
+++ b/tests/metatype/tmeta_typeclasses.nim
diff --git a/tests/metatype/tmatrix.nim b/tests/metatype/tmetatypematrix.nim
index 4fd32a932..4cd0aa49f 100644
--- a/tests/metatype/tmatrix.nim
+++ b/tests/metatype/tmetatypematrix.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tmatrix.nim"
   output: "111"
 """
 # Test overloading of [] with multiple indices
@@ -44,5 +43,4 @@ for i in 0..w-1:
 
 for i in 0..w-1:
   stdout.write(m[i,i]) #OUT 111
-
-
+stdout.write "\n"
diff --git a/tests/metatype/tstaticparams.nim b/tests/metatype/tstaticparams.nim
index ad6aa6589..09d505f94 100644
--- a/tests/metatype/tstaticparams.nim
+++ b/tests/metatype/tstaticparams.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstaticparams.nim"
   output: "abracadabra\ntest\n3\n15\n4\n2\nfloat\n3\nfloat\nyin\nyang\n2\n4\n4\n2\n3"
 """
 
@@ -140,7 +139,7 @@ dontBind1 bb_2
 dontBind2 bb_1
 dontBind2 bb_2
 
-# https://github.com/nim-lang/Nim/issues/4524 
+# https://github.com/nim-lang/Nim/issues/4524
 const
   size* = 2
 
@@ -172,4 +171,3 @@ echo inSize([
   [1, 2, 3],
   [4, 5, 6]
 ])
-
diff --git a/tests/method/tmethod.nim b/tests/method/tmethod.nim
index 0cfe24c70..005294d64 100644
--- a/tests/method/tmethod.nim
+++ b/tests/method/tmethod.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "\'method\' needs a parameter that has an object type"
   file: "tmethod.nim"
   line: 7
-  errormsg: "\'method\' needs a parameter that has an object type"
 """
 
 method m(i: int): int =
diff --git a/tests/method/tmultim.nim b/tests/method/tmultim.nim
index 310502c56..7023e18bf 100644
--- a/tests/method/tmultim.nim
+++ b/tests/method/tmultim.nim
@@ -4,9 +4,12 @@ collide: unit, thing
 collide: unit, thing
 collide: thing, unit
 collide: thing, thing
-collide: unit, thing | collide: unit, thing | collide: thing, unit | 
+collide: unit, thing |
+collide: unit, thing |
+collide: thing, unit |
 do nothing
 '''
+  joinable: false
 """
 
 
@@ -55,10 +58,10 @@ method collide(a, b: Thing) {.base, inline.} =
   quit "to override!"
 
 method collide[T](a: Thing, b: Unit[T]) {.inline.} =
-  write stdout, "collide: thing, unit | "
+  echo "collide: thing, unit |"
 
 method collide[T](a: Unit[T], b: Thing) {.inline.} =
-  write stdout, "collide: unit, thing | "
+  echo "collide: unit, thing |"
 
 proc test(a, b: Thing) {.inline.} =
   collide(a, b)
@@ -69,7 +72,6 @@ var
 collide(bbb, Thing(ccc))
 test(bbb, ccc)
 collide(aaa, bbb)
-echo ""
 
 
 
diff --git a/tests/misc/t99bott.nim b/tests/misc/t99bott.nim
index 62ccfbe16..f60023818 100644
--- a/tests/misc/t99bott.nim
+++ b/tests/misc/t99bott.nim
@@ -1,9 +1,9 @@
 discard """
+  errormsg: "cannot evaluate at compile time: bn"
   file: "t99bott.nim"
   line: 26
-  errormsg: "cannot evaluate at compile time: bn"
-  disabled: false
 """
+
 ## 99 Bottles of Beer
 ## http://www.99-bottles-of-beer.net/
 ## Nim version
@@ -30,7 +30,3 @@ for bn in countdown(99, 1):
 
 echo "No more bottles of beer on the wall, no more bottles of beer."
 echo "Go to the store and buy some more, 99 bottles of beer on the wall."
-
-
-
-
diff --git a/tests/misc/tack.nim b/tests/misc/tack.nim
index a0afab9e8..458395ef6 100644
--- a/tests/misc/tack.nim
+++ b/tests/misc/tack.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tack.nim"
   output: "125"
 """
 # the Ackermann function
@@ -17,5 +16,4 @@ proc ack(x, y: int): int =
 
 # echo(ack(0, 0))
 write(stdout, ack(3, 4)) #OUT 125
-
-
+write stdout, "\n"
diff --git a/tests/misc/tbug511622.nim b/tests/misc/tbug511622.nim
index a5360423d..4b30e96e6 100644
--- a/tests/misc/tbug511622.nim
+++ b/tests/misc/tbug511622.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tbug511622.nim"
   output: "3"
 """
 import StrUtils, Math
@@ -11,6 +10,3 @@ proc FibonacciA(n: int): int64 =
   return int64((pow(p, fn) + pow(q, fn)) / sqrt(5.0))
 
 echo FibonacciA(4) #OUT 3
-
-
-
diff --git a/tests/misc/tcmdline.nim b/tests/misc/tcmdline.nim
index 2c4768716..71e1301ca 100644
--- a/tests/misc/tcmdline.nim
+++ b/tests/misc/tcmdline.nim
@@ -1,5 +1,6 @@
 discard """
 outputsub: "Number of parameters: 0"
+joinable: false
 """
 # Test the command line
 
diff --git a/tests/misc/temit.nim b/tests/misc/temit.nim
index c83235659..ee7455d4c 100644
--- a/tests/misc/temit.nim
+++ b/tests/misc/temit.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "temit.nim"
   output: "509"
 """
 # Test the new ``emit`` pragma:
@@ -14,7 +13,3 @@ proc embedsC() =
   {.emit: """printf("%d\n", cvariable + (int)`nimVar`);""".}
 
 embedsC()
-
-
-
-
diff --git a/tests/misc/tevents.nim b/tests/misc/tevents.nim
index caf674084..045c9fc5b 100644
--- a/tests/misc/tevents.nim
+++ b/tests/misc/tevents.nim
@@ -1,8 +1,9 @@
 discard """
-file: "tevents.nim"
-output: '''HandlePrintEvent: Output -> Handled print event
+output: '''
+HandlePrintEvent: Output -> Handled print event
 HandlePrintEvent2: Output -> printing for ME
-HandlePrintEvent2: Output -> printing for ME'''
+HandlePrintEvent2: Output -> printing for ME
+'''
 """
 
 import events
@@ -45,4 +46,3 @@ ee.emit(obj.printEvent, eventargs)
 obj.printEvent.removeHandler(handleprintevent2)
 
 ee.emit(obj.printEvent, eventargs)
-
diff --git a/tests/misc/tgenconstraints.nim b/tests/misc/tgenconstraints.nim
index 6e8fdc738..829da5173 100644
--- a/tests/misc/tgenconstraints.nim
+++ b/tests/misc/tgenconstraints.nim
@@ -1,8 +1,8 @@
 discard """
+  errormsg: "cannot instantiate T2"
   file: "tgenconstraints.nim"
   line: 25
   disabled: true
-  errormsg: "cannot instantiate T2"
 """
 
 type
@@ -29,4 +29,3 @@ proc bar(x: int|TNumber): T1[type(x)] {.discardable.} =
 bar "test"
 bar 100
 bar 1.1
-
diff --git a/tests/misc/thallo.nim b/tests/misc/thallo.nim
index 6f9d49121..7172a6b46 100644
--- a/tests/misc/thallo.nim
+++ b/tests/misc/thallo.nim
@@ -11,7 +11,7 @@ type
   TMyEnum = enum
     meA, meB, meC, meD
 
-when isMainModule:
+when true:
   {.hint: "this is the main file".}
 
 proc fac[T](x: T): T =
@@ -84,5 +84,5 @@ for i in 2..6:
   for j in countdown(i+4, 2):
     echo(fac(i * j))
 
-when isMainModule:
+when true:
   {.hint: "this is the main file".}
diff --git a/tests/misc/thintoff.nim b/tests/misc/thintoff.nim
deleted file mode 100644
index 95318ce9b..000000000
--- a/tests/misc/thintoff.nim
+++ /dev/null
@@ -1,12 +0,0 @@
-discard """
-  file: "thintoff.nim"
-  output: "0"
-"""
-
-{.hint[XDeclaredButNotUsed]: off.}
-var
-  x: int
-
-echo x #OUT 0
-
-
diff --git a/tests/misc/tinc.nim b/tests/misc/tinc.nim
index 7819775e3..91f6223e2 100644
--- a/tests/misc/tinc.nim
+++ b/tests/misc/tinc.nim
@@ -1,12 +1,8 @@
 discard """
+  errormsg: "type mismatch: got <int>"
   file: "tinc.nim"
   line: 8
-  errormsg: "type mismatch: got <int>"
 """
 var x = 0
 
 inc(x+1)
-
-
-
-
diff --git a/tests/misc/tinit.nim b/tests/misc/tinit.nim
index 02607909b..207cb17e8 100644
--- a/tests/misc/tinit.nim
+++ b/tests/misc/tinit.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tinit.nim"
   output: "Hello from module! Hello from main module!"
 """
 # Test the new init section in modules
@@ -8,5 +7,3 @@ import minit
 
 write(stdout, "Hello from main module!\n")
 #OUT Hello from module! Hello from main module!
-
-
diff --git a/tests/misc/tinout.nim b/tests/misc/tinout.nim
index 46af2f5de..bae0fb185 100644
--- a/tests/misc/tinout.nim
+++ b/tests/misc/tinout.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch: got <int literal(3)>"
   file: "tinout.nim"
   line: 12
-  errormsg: "type mismatch: got <int literal(3)>"
 """
 # Test in out checking for parameters
 
@@ -12,5 +12,3 @@ proc b() =
     abc(3) #ERROR
 
 b()
-
-
diff --git a/tests/misc/tinvalidarrayaccess.nim b/tests/misc/tinvalidarrayaccess.nim
index 03105b41b..57ad38b85 100644
--- a/tests/misc/tinvalidarrayaccess.nim
+++ b/tests/misc/tinvalidarrayaccess.nim
@@ -1,14 +1,21 @@
 discard """
-  errormsg: "index out of bounds"
-  line: 11
+  errormsg: "index out of bounds: (a:0) <= (i:2) <= (b:1) "
+  line: 18
 """
 
+block:
+  try:
+    let a = @[1,2]
+    echo a[3]
+  except Exception as e:
+    doAssert e.msg == "index out of bounds: (i:3) <= (n:1) "
 
-type TTestArr = array[0..1, int16]
-var f: TTestArr
-f[0] = 30
-f[1] = 40
-f[2] = 50
-f[3] = 60
+block:
+  type TTestArr = array[0..1, int16]
+  var f: TTestArr
+  f[0] = 30
+  f[1] = 40
+  f[2] = 50
+  f[3] = 60
 
-echo(repr(f))
+  echo(repr(f))
diff --git a/tests/misc/tinvalidarrayaccess2.nim b/tests/misc/tinvalidarrayaccess2.nim
new file mode 100644
index 000000000..86d349457
--- /dev/null
+++ b/tests/misc/tinvalidarrayaccess2.nim
@@ -0,0 +1,16 @@
+discard """
+  errormsg: "index out of bounds: (a:0) <= (i:3) <= (b:1) "
+  line: 9
+"""
+
+# Note: merge in tinvalidarrayaccess.nim pending https://github.com/nim-lang/Nim/issues/9906
+
+let a = [1,2]
+echo a[3]
+
+when false:
+  # TOOD: this case is not yet handled, giving: "index out of bounds"
+  proc fun()=
+    let a = @[1,2]
+    echo a[3]
+  static: fun()
diff --git a/tests/misc/tinvalidnewseq.nim b/tests/misc/tinvalidnewseq.nim
index 66e9388ef..dec00fd4a 100644
--- a/tests/misc/tinvalidnewseq.nim
+++ b/tests/misc/tinvalidnewseq.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch: got <array[0..6, string], int literal(7)>"
   file: "tinvalidnewseq.nim"
   line: 15
-  errormsg: "type mismatch: got <array[0..6, string], int literal(7)>"
 """
 import re, strutils
 
@@ -22,6 +22,3 @@ var r: TUrl
 
 r = parseUrl(r"http://google.com/search?var=bleahdhsad")
 echo(r.domain)
-
-
-
diff --git a/tests/misc/tissue710.nim b/tests/misc/tissue710.nim
index e2cca0024..ec125b840 100644
--- a/tests/misc/tissue710.nim
+++ b/tests/misc/tissue710.nim
@@ -1,7 +1,7 @@
 discard """
+  errorMsg: "attempting to call routine: '||'"
   file: "tissue710.nim"
   line: 8
-  errorMsg: "attempting to call routine: '||'"
 """
 var sum = 0
 for x in 3..1000:
diff --git a/tests/misc/tnew.nim b/tests/misc/tnew.nim
index 02282dd4a..2d9a64461 100644
--- a/tests/misc/tnew.nim
+++ b/tests/misc/tnew.nim
@@ -3,6 +3,7 @@ outputsub: '''
 Simple tree node allocation worked!
 Simple cycle allocation worked!
 '''
+joinable: false
 """
 
 # Test the implementation of the new operator
diff --git a/tests/misc/tnoinst.nim b/tests/misc/tnoinst.nim
index 25ebe8dfc..85db1e8e7 100644
--- a/tests/misc/tnoinst.nim
+++ b/tests/misc/tnoinst.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 12
   errormsg: "instantiate 'notConcrete' explicitly"
+  line: 12
   disabled: "true"
 """
 
@@ -14,4 +14,3 @@ proc wrap[T]() =
 
 
 wrap[int]()
-
diff --git a/tests/misc/tnolen.nim b/tests/misc/tnolen.nim
index 2831e5048..e0e8025d4 100644
--- a/tests/misc/tnolen.nim
+++ b/tests/misc/tnolen.nim
@@ -1,9 +1,8 @@
 discard """
-  line: 8
   errormsg: "type mismatch: got <int literal(3)>"
+  line: 8
 """
 
 # please finally disallow Len(3)
 
 echo len(3)
-
diff --git a/tests/misc/tnot.nim b/tests/misc/tnot.nim
index 5c268981e..a3669705b 100644
--- a/tests/misc/tnot.nim
+++ b/tests/misc/tnot.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch"
   file: "tnot.nim"
   line: 14
-  errormsg: "type mismatch"
 """
 # BUG: following compiles, but should not:
 
diff --git a/tests/misc/tparseopt.nim b/tests/misc/tparseopt.nim
index 651689398..cbed5d476 100644
--- a/tests/misc/tparseopt.nim
+++ b/tests/misc/tparseopt.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tparseopt.nim"
   output: '''
 parseopt
 first round
diff --git a/tests/misc/tpos.nim b/tests/misc/tpos.nim
index bedb62e62..f7607d643 100644
--- a/tests/misc/tpos.nim
+++ b/tests/misc/tpos.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tpos.nim"
   output: "6"
 """
 # test this particular function
@@ -30,6 +29,5 @@ proc mypos(sub, s: string, start: int = 0): int =
 var sub = "hello"
 var s = "world hello"
 write(stdout, mypos(sub, s))
+write stdout, "\n"
 #OUT 6
-
-
diff --git a/tests/misc/tradix.nim b/tests/misc/tradix.nim
index 5009dfcfb..5be89530f 100644
--- a/tests/misc/tradix.nim
+++ b/tests/misc/tradix.nim
@@ -1,5 +1,6 @@
 discard """
 output: '''
+start tradix.nim
 false
 false
 false
@@ -29,6 +30,8 @@ false
 ## We use a radix tree with node compression.
 ## There are two node kinds:
 
+echo "start tradix.nim"
+
 const BitsPerUnit = 8*sizeof(int)
 
 type
@@ -126,7 +129,7 @@ proc excl*(r: PRadixNode, a: ByteAddress): bool =
 proc addLeaf(r: var PRadixNode, a: int): bool =
   if r == nil:
     # a linear node:
-    var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear)))
+    var x = cast[ptr TRadixNodeLinear](alloc0(sizeof(TRadixNodeLinear)))
     x.kind = rnLeafLinear
     x.len = 1'i8
     x.keys[0] = toU8(a)
@@ -162,7 +165,7 @@ proc addInner(r: var PRadixNode, a: int, d: int): bool =
   var k = a shr d and 0xff
   if r == nil:
     # a linear node:
-    var x = cast[ptr TRadixNodeLinear](alloc(sizeof(TRadixNodeLinear)))
+    var x = cast[ptr TRadixNodeLinear](alloc0(sizeof(TRadixNodeLinear)))
     x.kind = rnLinear
     x.len = 1'i8
     x.keys[0] = toU8(k)
@@ -246,99 +249,3 @@ proc main() =
   for x in elements(r): echo(x)
 
 main()
-
-
-when false:
-  proc traverse(r: PRadixNode, prefix: int, d: int) =
-    if r == nil: return
-    case r.kind
-    of rnLeafBits:
-      assert(d == 0)
-      var x = cast[ptr TRadixNodeLeafBits](r)
-      # iterate over any bit:
-      for i in 0..high(x.b):
-        if x.b[i] != 0: # test all bits for zero
-          for j in 0..BitsPerUnit-1:
-            if testBit(x.b[i], j):
-              visit(prefix or i*BitsPerUnit+j)
-    of rnLeafLinear:
-      assert(d == 0)
-      var x = cast[ptr TRadixNodeLeafLinear](r)
-      for i in 0..ze(x.len)-1:
-        visit(prefix or ze(x.keys[i]))
-    of rnFull:
-      var x = cast[ptr TRadixNodeFull](r)
-      for i in 0..high(r.b):
-        if r.b[i] != nil:
-          traverse(r.b[i], prefix or (i shl d), d-8)
-    of rnLinear:
-      var x = cast[ptr TRadixNodeLinear](r)
-      for i in 0..ze(x.len)-1:
-        traverse(x.vals[i], prefix or (ze(x.keys[i]) shl d), d-8)
-
-  type
-    TRadixIter {.final.} = object
-      r: PRadixNode
-      p: int
-      x: int
-
-  proc init(i: var TRadixIter, r: PRadixNode) =
-    i.r = r
-    i.x = 0
-    i.p = 0
-
-  proc nextr(i: var TRadixIter): PRadixNode =
-    if i.r == nil: return nil
-    case i.r.kind
-    of rnFull:
-      var r = cast[ptr TRadixNodeFull](i.r)
-      while i.x <= high(r.b):
-        if r.b[i.x] != nil:
-          i.p = i.x
-          return r.b[i.x]
-        inc(i.x)
-    of rnLinear:
-      var r = cast[ptr TRadixNodeLinear](i.r)
-      if i.x < ze(r.len):
-        i.p = ze(r.keys[i.x])
-        result = r.vals[i.x]
-        inc(i.x)
-    else: assert(false)
-
-  proc nexti(i: var TRadixIter): int =
-    result = -1
-    case i.r.kind
-    of rnLeafBits:
-      var r = cast[ptr TRadixNodeLeafBits](i.r)
-      # iterate over any bit:
-      for i in 0..high(r.b):
-        if x.b[i] != 0: # test all bits for zero
-          for j in 0..BitsPerUnit-1:
-            if testBit(x.b[i], j):
-              visit(prefix or i*BitsPerUnit+j)
-    of rnLeafLinear:
-      var r = cast[ptr TRadixNodeLeafLinear](i.r)
-      if i.x < ze(r.len):
-        result = ze(r.keys[i.x])
-        inc(i.x)
-
-  iterator elements(r: PRadixNode): ByteAddress {.inline.} =
-    var
-      a, b, c, d: TRadixIter
-    init(a, r)
-    while true:
-      var x = nextr(a)
-      if x != nil:
-        init(b, x)
-        while true:
-          var y = nextr(b)
-          if y != nil:
-            init(c, y)
-            while true:
-              var z = nextr(c)
-              if z != nil:
-                init(d, z)
-                while true:
-                  var q = nexti(d)
-                  if q != -1:
-                    yield a.p shl 24 or b.p shl 16 or c.p shl 8 or q
diff --git a/tests/misc/trawstr.nim b/tests/misc/trawstr.nim
index 55e508acc..aa41071d5 100644
--- a/tests/misc/trawstr.nim
+++ b/tests/misc/trawstr.nim
@@ -1,12 +1,10 @@
 discard """
+  errormsg: "closing \" expected"
   file: "trawstr.nim"
   line: 10
-  errormsg: "closing \" expected"
 """
 # Test the new raw strings:
 
 const
   xxx = r"This is a raw string!"
   yyy = "This not\" #ERROR
-
-
diff --git a/tests/misc/tshadow_magic_type.nim b/tests/misc/tshadow_magic_type.nim
index 6f9716bb9..3176a4596 100644
--- a/tests/misc/tshadow_magic_type.nim
+++ b/tests/misc/tshadow_magic_type.nim
@@ -26,7 +26,6 @@ proc lrange*(key: string): TRedisList =
   foo.str = key
   result = @[foo]
 
-when isMainModule:
-  var p = lrange("mylist")
-  for i in items(p):
-    echo(i.str)
+var p = lrange("mylist")
+for i in items(p):
+  echo(i.str)
diff --git a/tests/misc/tsimtych.nim b/tests/misc/tsimtych.nim
index 037172bd5..74a6ad4c0 100644
--- a/tests/misc/tsimtych.nim
+++ b/tests/misc/tsimtych.nim
@@ -1,12 +1,10 @@
 discard """
+  errormsg: "type mismatch: got <bool> but expected \'string\'"
   file: "tsimtych.nim"
   line: 10
-  errormsg: "type mismatch: got <bool> but expected \'string\'"
 """
 # Test 2
 # Simple type checking
 
 var a: string
 a = false #ERROR
-
-
diff --git a/tests/misc/tsizeof2.nim b/tests/misc/tsizeof2.nim
index 4252142d7..130f28e21 100644
--- a/tests/misc/tsizeof2.nim
+++ b/tests/misc/tsizeof2.nim
@@ -13,3 +13,5 @@ echo i
 # bug #9868
 proc foo(a: SomeInteger): array[sizeof(a), byte] =
   discard
+
+discard foo(1)
diff --git a/tests/misc/tslices.nim b/tests/misc/tslices.nim
index 388a46509..d063c5ebf 100644
--- a/tests/misc/tslices.nim
+++ b/tests/misc/tslices.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tslices.nim"
-  output: '''456456
+output: '''
+456456
 456456
 456456
 Zugr5nd
@@ -56,4 +56,3 @@ echo mystr
 var s = "abcdef"
 s[1 .. ^2] = "xyz"
 assert s == "axyzf"
-
diff --git a/tests/misc/tsortdev.nim b/tests/misc/tsortdev.nim
index f360d9646..0b2a4f3e8 100644
--- a/tests/misc/tsortdev.nim
+++ b/tests/misc/tsortdev.nim
@@ -1,5 +1,5 @@
 discard """
-  output: "done"
+  output: "done tsortdev"
 """
 
 import algorithm, strutils
@@ -55,5 +55,4 @@ proc main() =
 for i in 0..1_000:
   main()
 
-echo "done"
-
+echo "done tsortdev"
diff --git a/tests/misc/tstrange.nim b/tests/misc/tstrange.nim
index fee0f44e4..82a82d267 100644
--- a/tests/misc/tstrange.nim
+++ b/tests/misc/tstrange.nim
@@ -1,8 +1,9 @@
 discard """
-  file: "tstrange.nim"
-  output: '''hallo40
+output: '''
+hallo40
 1
-2'''
+2
+'''
 """
 # test for extremely strange bug
 
@@ -25,4 +26,3 @@ write(stdout, ack(5, 4))
 let h=3
 for x in 0.. <h.int:
   echo x
-
diff --git a/tests/misc/tvarious1.nim b/tests/misc/tvarious1.nim
index 595c77919..9c0b541db 100644
--- a/tests/misc/tvarious1.nim
+++ b/tests/misc/tvarious1.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tlenopenarray.nim"
-  output: '''1
+output: '''
+1
 0
 Whopie
 12
diff --git a/tests/misc/tvarnums.nim b/tests/misc/tvarnums.nim
index 5daa2c4b8..39269b4c0 100644
--- a/tests/misc/tvarnums.nim
+++ b/tests/misc/tvarnums.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tvarnums.nim"
   output: "Success!"
 """
 # Test variable length binary integers
@@ -138,5 +137,3 @@ tm(low(int32))
 tm(high(int32))
 
 writeLine(stdout, "Success!") #OUT Success!
-
-
diff --git a/tests/modules/m9627/a.nim b/tests/modules/m9627/a.nim
new file mode 100644
index 000000000..0dd32430e
--- /dev/null
+++ b/tests/modules/m9627/a.nim
@@ -0,0 +1 @@
+var a = 10
diff --git a/tests/modules/m9627/b.nim b/tests/modules/m9627/b.nim
new file mode 100644
index 000000000..2806a78ed
--- /dev/null
+++ b/tests/modules/m9627/b.nim
@@ -0,0 +1 @@
+var b = 9
diff --git a/tests/modules/t9627.nim b/tests/modules/t9627.nim
new file mode 100644
index 000000000..daba46374
--- /dev/null
+++ b/tests/modules/t9627.nim
@@ -0,0 +1,7 @@
+discard """
+  output: "109"
+"""
+
+include m9627 / [a, b]
+
+echo a, b
diff --git a/tests/modules/timportexcept.nim b/tests/modules/timportexcept.nim
index 93a7fd642..40b748088 100644
--- a/tests/modules/timportexcept.nim
+++ b/tests/modules/timportexcept.nim
@@ -1,10 +1,9 @@
 discard """
-  line: 9
   errormsg: "undeclared identifier: '%'"
+  line: 9
 """
 
 import strutils except `%`
 
 # doesn't work
 echo "$1" % "abc"
-
diff --git a/tests/modules/tmismatchedvisibility.nim b/tests/modules/tmismatchedvisibility.nim
index 2e8636d1e..4bf244807 100644
--- a/tests/modules/tmismatchedvisibility.nim
+++ b/tests/modules/tmismatchedvisibility.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 8
   errormsg: "public implementation 'tmismatchedvisibility.foo(a: int)[declared in tmismatchedvisibility.nim(6, 5)]' has non-public forward declaration in "
+  line: 8
 """
 
 proc foo(a: int): int
diff --git a/tests/modules/tnamspc.nim b/tests/modules/tnamspc.nim
index 2f488644c..93ce71568 100644
--- a/tests/modules/tnamspc.nim
+++ b/tests/modules/tnamspc.nim
@@ -1,12 +1,10 @@
 discard """
+  errormsg: "undeclared identifier: \'global\'"
   file: "tnamspc.nim"
   line: 10
-  errormsg: "undeclared identifier: \'global\'"
 """
 # Test17 - test correct handling of namespaces
 
 import mnamspc1
 
 global = 9 #ERROR
-
-
diff --git a/tests/modules/tnotuniquename.nim b/tests/modules/tnotuniquename.nim
index 2d8ce4869..403c8a47e 100644
--- a/tests/modules/tnotuniquename.nim
+++ b/tests/modules/tnotuniquename.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tnotuniquename/mnotuniquename.nim"
   errormsg: "module names need to be unique per Nimble package"
+  file: "tnotuniquename/mnotuniquename.nim"
 """
 
 import mnotuniquename
diff --git a/tests/modules/tnotuniquename2.nim b/tests/modules/tnotuniquename2.nim
index 8e486d19f..7aa4de515 100644
--- a/tests/modules/tnotuniquename2.nim
+++ b/tests/modules/tnotuniquename2.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tnotuniquename/mnotuniquename.nim"
   errormsg: "module names need to be unique per Nimble package"
+  file: "tnotuniquename/mnotuniquename.nim"
 """
 
 import mnotuniquename
diff --git a/tests/modules/topaque.nim b/tests/modules/topaque.nim
index 84e2388bc..94ff8ff25 100644
--- a/tests/modules/topaque.nim
+++ b/tests/modules/topaque.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "undeclared field: \'buffer\'"
   file: "topaque.nim"
   line: 16
-  errormsg: "undeclared field: \'buffer\'"
 """
 # Test the new opaque types
 
@@ -14,5 +14,3 @@ var
 L.filename = "ha"
 L.line = 34
 L.buffer[0] = '\0' #ERROR_MSG undeclared field: 'buffer'
-
-
diff --git a/tests/modules/trecinca.nim b/tests/modules/trecinca.nim
index 7a74d7a46..56798dedd 100644
--- a/tests/modules/trecinca.nim
+++ b/tests/modules/trecinca.nim
@@ -1,12 +1,10 @@
 discard """
+  errormsg: "recursive dependency: 'trecincb.nim'"
   file: "trecincb.nim"
   line: 9
-  errormsg: "recursive dependency: 'trecincb.nim'"
 """
 # Test recursive includes
 
 include trecincb
 
 echo "trecina"
-
-
diff --git a/tests/modules/trecincb.nim b/tests/modules/trecincb.nim
index 1d3eb5503..30a5d7800 100644
--- a/tests/modules/trecincb.nim
+++ b/tests/modules/trecincb.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "recursive dependency: 'trecincb.nim'"
   file: "trecincb.nim"
   line: 9
-  errormsg: "recursive dependency: 'trecincb.nim'"
 """
 # Test recursive includes
 
@@ -9,5 +9,3 @@ discard """
 include trecincb
 
 echo "trecinb"
-
-
diff --git a/tests/modules/trecmod.nim b/tests/modules/trecmod.nim
index 5f053bcae..43e510e87 100644
--- a/tests/modules/trecmod.nim
+++ b/tests/modules/trecmod.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "recursive module dependency detected"
   file: "mrecmod.nim"
   line: 1
-  errormsg: "recursive module dependency detected"
   disabled: true
 """
 # recursive module
diff --git a/tests/modules/tselfimport.nim b/tests/modules/tselfimport.nim
index ddb3a5b09..7e50bef7c 100644
--- a/tests/modules/tselfimport.nim
+++ b/tests/modules/tselfimport.nim
@@ -1,9 +1,8 @@
 discard """
+  errormsg: "A module cannot import itself"
   file: "tselfimport.nim"
   line: 7
-  errormsg: "A module cannot import itself"
 """
 import strutils as su # guard against regression
 import tselfimport #ERROR
 echo("Hello World")
-
diff --git a/tests/namedparams/tnamedparams.nim b/tests/namedparams/tnamedparams.nim
index 8799e8a15..d0774f0d8 100644
--- a/tests/namedparams/tnamedparams.nim
+++ b/tests/namedparams/tnamedparams.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch: got <input: string, filename: string, line: int literal(1), col: int literal(23)>"
   file: "tnamedparams.nim"
   line: 8
-  errormsg: "type mismatch: got <input: string, filename: string, line: int literal(1), col: int literal(23)>"
 """
 import pegs
 
@@ -10,6 +10,3 @@ discard parsePeg(
       filename = "filename",
       line = 1,
       col = 23)
-
-
-
diff --git a/tests/niminaction/Chapter2/explicit_discard.nim b/tests/niminaction/Chapter2/explicit_discard.nim
index 3e94c335b..9a3b4407e 100644
--- a/tests/niminaction/Chapter2/explicit_discard.nim
+++ b/tests/niminaction/Chapter2/explicit_discard.nim
@@ -1,7 +1,7 @@
 discard """
-  line: 7
   errormsg: "has to be discarded"
+  line: 7
 """
 
 proc myProc(name: string): string = "Hello " & name
-myProc("Dominik")
\ No newline at end of file
+myProc("Dominik")
diff --git a/tests/niminaction/Chapter2/no_def_eq.nim b/tests/niminaction/Chapter2/no_def_eq.nim
index 77f0a7dd8..b9d62e036 100644
--- a/tests/niminaction/Chapter2/no_def_eq.nim
+++ b/tests/niminaction/Chapter2/no_def_eq.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 16
   errormsg: "type mismatch"
+  line: 16
 """
 
 type
@@ -13,4 +13,4 @@ type
 let dog: Dog = Dog(name: "Fluffy")
 let cat: Cat = Cat(name: "Fluffy")
 
-echo(dog == cat)
\ No newline at end of file
+echo(dog == cat)
diff --git a/tests/niminaction/Chapter2/no_iterator.nim b/tests/niminaction/Chapter2/no_iterator.nim
index 331d69480..555fac21a 100644
--- a/tests/niminaction/Chapter2/no_iterator.nim
+++ b/tests/niminaction/Chapter2/no_iterator.nim
@@ -1,7 +1,7 @@
 discard """
-  line: 6
   errormsg: "type mismatch"
+  line: 6
 """
 
 for i in 5:
-  echo i
\ No newline at end of file
+  echo i
diff --git a/tests/niminaction/Chapter2/no_seq_type.nim b/tests/niminaction/Chapter2/no_seq_type.nim
index 493be270a..f1494124b 100644
--- a/tests/niminaction/Chapter2/no_seq_type.nim
+++ b/tests/niminaction/Chapter2/no_seq_type.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 6
   errormsg: "cannot infer the type of the sequence"
+  line: 6
 """
 
-var list = @[]
\ No newline at end of file
+var list = @[]
diff --git a/tests/niminaction/Chapter2/resultreject.nim b/tests/niminaction/Chapter2/resultreject.nim
index de59af7d9..87c84bf0a 100644
--- a/tests/niminaction/Chapter2/resultreject.nim
+++ b/tests/niminaction/Chapter2/resultreject.nim
@@ -1,13 +1,13 @@
 discard """
-  line: 27
   errormsg: "has to be discarded"
+  line: 27
 """
 
 # Page 35.
 
 proc implicit: string =
   "I will be returned"
-  
+
 proc discarded: string =
   discard "I will not be returned"
 
@@ -16,7 +16,7 @@ proc explicit: string =
 
 proc resultVar: string =
   result = "I will be returned"
-  
+
 proc resultVar2: string =
   result = ""
   result.add("I will be ")
@@ -30,4 +30,4 @@ doAssert implicit() == "I will be returned"
 doAssert discarded() == nil
 doAssert explicit() == "I will be returned"
 doAssert resultVar() == "I will be returned"
-doAssert resultVar2() == "I will be returned"
\ No newline at end of file
+doAssert resultVar2() == "I will be returned"
diff --git a/tests/niminaction/Chapter3/ChatApp/src/protocol.nim b/tests/niminaction/Chapter3/ChatApp/src/protocol.nim
index af515861c..4c122d4cc 100644
--- a/tests/niminaction/Chapter3/ChatApp/src/protocol.nim
+++ b/tests/niminaction/Chapter3/ChatApp/src/protocol.nim
@@ -37,7 +37,7 @@ proc createMessage*(username, message: string): string =
     "message": %message
   }) & "\c\l"
 
-when isMainModule:
+when true:
   block:
     let data = """{"username": "dom", "message": "hello"}"""
     let parsed = parseMessage(data)
diff --git a/tests/niminaction/Chapter3/ChatApp/src/server.nim b/tests/niminaction/Chapter3/ChatApp/src/server.nim
index 31da74d16..fbf0e5110 100644
--- a/tests/niminaction/Chapter3/ChatApp/src/server.nim
+++ b/tests/niminaction/Chapter3/ChatApp/src/server.nim
@@ -79,7 +79,7 @@ proc loop(server: Server, port = 7687) {.async.} =
 
 # Check whether this module has been imported as a dependency to another
 # module, or whether this module is the main module.
-when isMainModule:
+when true:
   # Initialise a new server.
   var server = newServer()
   echo("Server initialised!")
diff --git a/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim b/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim
index f20e21f4d..766f07fa5 100644
--- a/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim
+++ b/tests/niminaction/Chapter6/WikipediaStats/concurrency.nim
@@ -79,5 +79,5 @@ proc readChunks(filename: string, chunksize = 1000000): Stats =
   file.close()
 
 
-when isMainModule:
+when true:
   echo readChunks(filename)
diff --git a/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim b/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim
index dbd635634..19b157926 100644
--- a/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim
+++ b/tests/niminaction/Chapter6/WikipediaStats/concurrency_regex.nim
@@ -64,5 +64,5 @@ proc readChunks(filename: string, chunksize = 1000000): Stats =
   file.close()
 
 
-when isMainModule:
+when true:
   echo readChunks(filename)
diff --git a/tests/niminaction/Chapter6/WikipediaStats/naive.nim b/tests/niminaction/Chapter6/WikipediaStats/naive.nim
index ce995efaf..687177f74 100644
--- a/tests/niminaction/Chapter6/WikipediaStats/naive.nim
+++ b/tests/niminaction/Chapter6/WikipediaStats/naive.nim
@@ -29,5 +29,5 @@ proc parse(filename: string): tuple[projectName, pageTitle: string,
 
   file.close()
 
-when isMainModule:
+when true:
   echo parse(filename)
diff --git a/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim b/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim
index 74857367a..2c4a59d83 100644
--- a/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim
+++ b/tests/niminaction/Chapter6/WikipediaStats/parallel_counts.nim
@@ -70,7 +70,7 @@ proc readPageCounts(filename: string, chunkSize = 1_000_000) =
 
   echo("Most popular is: ", mostPopular)
 
-when isMainModule:
+when true:
   const file = "pagecounts-20160101-050000"
   let filename = getCurrentDir() / file
   readPageCounts(filename)
diff --git a/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim b/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim
index 102dd15d3..f4bae3df5 100644
--- a/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim
+++ b/tests/niminaction/Chapter6/WikipediaStats/sequential_counts.nim
@@ -32,7 +32,7 @@ proc readPageCounts(filename: string) =
 
   echo("Most popular is: ", mostPopular)
 
-when isMainModule:
+when true:
   const file = "pagecounts-20160101-050000"
   let filename = getCurrentDir() / file
   readPageCounts(filename)
diff --git a/tests/niminaction/Chapter7/Tweeter/src/views/user.nim b/tests/niminaction/Chapter7/Tweeter/src/views/user.nim
index f3791b493..18f3713b3 100644
--- a/tests/niminaction/Chapter7/Tweeter/src/views/user.nim
+++ b/tests/niminaction/Chapter7/Tweeter/src/views/user.nim
@@ -40,7 +40,7 @@
 </div>
 #end proc
 #
-#when isMainModule:
+#when true:
 #  echo renderUser(User(username: "d0m96<>", following: @[]))
 #  echo renderMessages(@[
 #    Message(username: "d0m96", time: getTime(), msg: "Hello World!"),
diff --git a/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim b/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim
index da69a004c..a3cab4cba 100644
--- a/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim
+++ b/tests/niminaction/Chapter7/Tweeter/tests/database_test.nim
@@ -4,7 +4,7 @@ outputsub: "All tests finished successfully!"
 
 import database, os, times
 
-when isMainModule:
+when true:
   removeFile("tweeter_test.db")
   var db = newDatabase("tweeter_test.db")
   db.setup()
diff --git a/tests/notnil/tnotnil.nim b/tests/notnil/tnotnil.nim
index aff3f8959..c33b6fcac 100644
--- a/tests/notnil/tnotnil.nim
+++ b/tests/notnil/tnotnil.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 13
   errormsg: "type mismatch"
+  line: 13
 """
 {.experimental: "notnil".}
 type
diff --git a/tests/objects/tobjconstr.nim b/tests/objects/tobjconstr.nim
index 7238d10c7..1e4d89d68 100644
--- a/tests/objects/tobjconstr.nim
+++ b/tests/objects/tobjconstr.nim
@@ -1,14 +1,15 @@
 discard """
-  output: '''(k: kindA, a: (x: "abc", z: [1, 1, 3]), method: ())
-(k: kindA, a: (x: "abc", z: [1, 2, 3]), method: ())
-(k: kindA, a: (x: "abc", z: [1, 3, 3]), method: ())
-(k: kindA, a: (x: "abc", z: [1, 4, 3]), method: ())
-(k: kindA, a: (x: "abc", z: [1, 5, 3]), method: ())
-(k: kindA, a: (x: "abc", z: [1, 6, 3]), method: ())
-(k: kindA, a: (x: "abc", z: [1, 7, 3]), method: ())
-(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: ())
+  output: '''
+(k: kindA, a: (x: "abc", z: @[1, 1, 3]), method: ())
+(k: kindA, a: (x: "abc", z: @[1, 2, 3]), method: ())
+(k: kindA, a: (x: "abc", z: @[1, 3, 3]), method: ())
+(k: kindA, a: (x: "abc", z: @[1, 4, 3]), method: ())
+(k: kindA, a: (x: "abc", z: @[1, 5, 3]), method: ())
+(k: kindA, a: (x: "abc", z: @[1, 6, 3]), method: ())
+(k: kindA, a: (x: "abc", z: @[1, 7, 3]), method: ())
+(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: ())
 (y: 0, x: 123)
 (y: 678, x: 123)
 (z: 89, y: 0, x: 128)
@@ -16,7 +17,8 @@ discard """
 (y: 678, x: 123)
 (y: 0, x: 123)
 (y: 678, x: 123)
-(y: 123, x: 678)'''
+(y: 123, x: 678)
+'''
 """
 
 type
@@ -32,13 +34,6 @@ type
       a: TArg
       `method`: TEmpty # bug #1791
 
-proc `$`[T](s: seq[T]): string =
-  result = "["
-  for i, x in s:
-    if i > 0: result.add(", ")
-    result.add($x)
-  result.add("]")
-
 proc main() =
   for i in 1..10:
     let d = TDummy(k: kindA, a: TArg(x: "abc", z: @[1,i,3]), `method`: TEmpty())
diff --git a/tests/objects/tobjpragma.nim b/tests/objects/tobjpragma.nim
index 0a6cc893b..789b3ec4e 100644
--- a/tests/objects/tobjpragma.nim
+++ b/tests/objects/tobjpragma.nim
@@ -1,13 +1,14 @@
 discard """
-  file: "tobjpragma.nim"
-  output: '''2
+  output: '''
+2
 3
 9
 257
 1
 2
-3'''
-  disabled: "true"
+3
+'''
+disabled: "true"
 """
 
 # Disabled since some versions of GCC ignore the 'packed' attribute
diff --git a/tests/objects/toop1.nim b/tests/objects/toop1.nim
index f4880e3c6..f22ddaf62 100644
--- a/tests/objects/toop1.nim
+++ b/tests/objects/toop1.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "toop1.nim"
   output: "34[]o 5"
 """
 # Test the stuff in the tutorial
diff --git a/tests/objvariant/tadrdisc.nim b/tests/objvariant/tadrdisc.nim
index 258fb42f3..a68dddf66 100644
--- a/tests/objvariant/tadrdisc.nim
+++ b/tests/objvariant/tadrdisc.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch: got <TKind>"
   file: "tadrdisc.nim"
   line: 20
-  errormsg: "type mismatch: got <TKind>"
 """
 # Test that the address of a dicriminants cannot be taken
 
diff --git a/tests/objvariant/temptycaseobj.nim b/tests/objvariant/temptycaseobj.nim
index 53171e054..2b2c40514 100644
--- a/tests/objvariant/temptycaseobj.nim
+++ b/tests/objvariant/temptycaseobj.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 11
   errormsg: "identifier expected, but got 'keyword of'"
+  line: 11
 """
 
 type
@@ -10,5 +10,3 @@ type
     of enA:
     of enU: x, y: int
     of enO: a, b: string
-
-
diff --git a/tests/objvariant/tvariantstack.nim b/tests/objvariant/tvariantstack.nim
index 0cdde5a20..31a0d8b82 100644
--- a/tests/objvariant/tvariantstack.nim
+++ b/tests/objvariant/tvariantstack.nim
@@ -1,6 +1,5 @@
 discard """
-  file: "tvariantstack.nim"
-  output: "came here"
+output: "came here"
 """
 #BUG
 type
diff --git a/tests/openarray/t8259.nim b/tests/openarray/t8259.nim
index 40ff2b2f1..c07576997 100644
--- a/tests/openarray/t8259.nim
+++ b/tests/openarray/t8259.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 6
   errormsg: "invalid type: 'openarray[int]' for result"
+  line: 6
 """
 
 proc foo(a: openArray[int]):auto = a
diff --git a/tests/openarray/topena1.nim b/tests/openarray/topena1.nim
index 0dbc5506a..ed3a0cedb 100644
--- a/tests/openarray/topena1.nim
+++ b/tests/openarray/topena1.nim
@@ -1,12 +1,9 @@
 discard """
+  errormsg: "invalid type"
   file: "topena1.nim"
   line: 9
-  errormsg: "invalid type"
 """
 # Tests a special bug
 
 var
   x: ref openarray[string] #ERROR_MSG invalid type
-
-
-
diff --git a/tests/openarray/topenarrayrepr.nim b/tests/openarray/topenarrayrepr.nim
index d276756bc..3784d4bbb 100644
--- a/tests/openarray/topenarrayrepr.nim
+++ b/tests/openarray/topenarrayrepr.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "topenarrayrepr.nim"
   output: "5 - [1]"
 """
 type
@@ -12,6 +11,3 @@ proc Bar(n: int, m: openarray[int64]) =
   echo($n & " - " & repr(m))
 
 Foo(5, Bar) #OUT 5 - [1]
-
-
-
diff --git a/tests/openarray/topenlen.nim b/tests/openarray/topenlen.nim
index fec8e87b7..83d58ac5c 100644
--- a/tests/openarray/topenlen.nim
+++ b/tests/openarray/topenlen.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "topenlen.nim"
   output: "7"
 """
 # Tests a special bug
@@ -14,5 +13,3 @@ proc p(a, b: openarray[string]): int =
 
 discard choose(["sh", "-c", $p([""], ["a"])])
 echo($p(["", "ha", "abc"], ["xyz"])) #OUT 7
-
-
diff --git a/tests/openarray/tptrarrayderef.nim b/tests/openarray/tptrarrayderef.nim
index 1e73be108..5c63f6f98 100644
--- a/tests/openarray/tptrarrayderef.nim
+++ b/tests/openarray/tptrarrayderef.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tptrarrayderef.nim"
   output: "OK"
 """
 
@@ -15,7 +14,7 @@ var
 proc mutate[T](arr:openarray[T], brr: openArray[T]) =
   for i in 0..arr.len-1:
     doAssert(arr[i] == brr[i])
-    
+
 mutate(arr, arr)
 
 #bug #2240
@@ -46,9 +45,9 @@ proc getFilledBuffer(sz: int): ref seq[char] =
   s[] = newSeq[char](sz)
   fillBuffer(s[])
   return s
-  
+
 let aa = getFilledBuffer(3)
 for i in 0..aa[].len-1:
   doAssert(aa[i] == chr(i))
-  
-echo "OK"
\ No newline at end of file
+
+echo "OK"
diff --git a/tests/osproc/ta_out.nim b/tests/osproc/ta_out.nim
index 318a27d59..01b78eb11 100644
--- a/tests/osproc/ta_out.nim
+++ b/tests/osproc/ta_out.nim
@@ -1,14 +1,18 @@
 discard """
 output: '''
+start ta_out
 to stdout
 to stdout
 to stderr
 to stderr
 to stdout
 to stdout
+end ta_out
 '''
 """
 
+echo "start ta_out"
+
 # This file is prefixed with an "a", because other tests
 # depend on it and it must be compiled first.
 stdout.writeLine("to stdout")
@@ -25,3 +29,5 @@ stdout.writeLine("to stdout")
 stdout.flushFile()
 stdout.writeLine("to stdout")
 stdout.flushFile()
+
+echo "end ta_out"
diff --git a/tests/osproc/texecps.nim b/tests/osproc/texecps.nim
index 887d79bfb..10715fa0f 100644
--- a/tests/osproc/texecps.nim
+++ b/tests/osproc/texecps.nim
@@ -1,8 +1,3 @@
-discard """
-  file: "texecps.nim"
-  output: ""
-"""
-
 import osproc, streams, strutils, os
 
 const NumberOfProcesses = 13
@@ -14,8 +9,7 @@ proc execCb(idx: int, p: Process) =
   if exitCode < len(gResults):
     gResults[exitCode] = p.outputStream.readAll.strip
 
-when isMainModule:
-
+when true:
   if paramCount() == 0:
     gResults = newSeq[string](NumberOfProcesses)
     var checks = newSeq[string](NumberOfProcesses)
diff --git a/tests/osproc/texitcode.nim b/tests/osproc/texitcode.nim
index 6dc5508b5..558017716 100644
--- a/tests/osproc/texitcode.nim
+++ b/tests/osproc/texitcode.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "texitcode.nim"
   output: ""
 """
 
diff --git a/tests/osproc/tstderr.nim b/tests/osproc/tstderr.nim
index 7a39522a3..55b11eba5 100644
--- a/tests/osproc/tstderr.nim
+++ b/tests/osproc/tstderr.nim
@@ -1,10 +1,15 @@
 discard """
-  output: '''--------------------------------------
+  output: '''
+start tstderr
+--------------------------------------
 to stderr
 to stderr
 --------------------------------------
 '''
 """
+
+echo "start tstderr"
+
 import osproc, os, streams
 
 const filename = "ta_out".addFileExt(ExeExt)
diff --git a/tests/osproc/tstdin.nim b/tests/osproc/tstdin.nim
index 9b49ed786..8579680ab 100644
--- a/tests/osproc/tstdin.nim
+++ b/tests/osproc/tstdin.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstdin.nim"
   output: "10"
 """
 import osproc, os, streams
diff --git a/tests/osproc/tstdout.nim b/tests/osproc/tstdout.nim
index 0cb5bd9c0..e3ed3986a 100644
--- a/tests/osproc/tstdout.nim
+++ b/tests/osproc/tstdout.nim
@@ -1,11 +1,13 @@
 discard """
   output: '''--------------------------------------
+start ta_out
 to stdout
 to stdout
 to stderr
 to stderr
 to stdout
 to stdout
+end ta_out
 --------------------------------------
 '''
 """
diff --git a/tests/osproc/tworkingdir.nim b/tests/osproc/tworkingdir.nim
index 7d58d5ae6..3a3c1b6ab 100644
--- a/tests/osproc/tworkingdir.nim
+++ b/tests/osproc/tworkingdir.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tworkingdir.nim"
   output: ""
 """
 
diff --git a/tests/overflw/toverflw.nim b/tests/overflw/toverflw.nim
index 20bc56a53..aef597e6c 100644
--- a/tests/overflw/toverflw.nim
+++ b/tests/overflw/toverflw.nim
@@ -1,8 +1,6 @@
 discard """
-  file: "toverflw.nim"
   output: "ok"
   cmd: "nim $target -d:release $options $file"
-
 """
 # Tests nim's ability to detect overflows
 
diff --git a/tests/overflw/toverflw2.nim b/tests/overflw/toverflw2.nim
index 75bd4cdf5..91b900ca4 100644
--- a/tests/overflw/toverflw2.nim
+++ b/tests/overflw/toverflw2.nim
@@ -1,10 +1,7 @@
 discard """
-  file: "toverflw2.nim"
   outputsub: "Error: unhandled exception: over- or underflow [OverflowError]"
   exitcode: "1"
 """
 var a : int32 = 2147483647
 var b : int32 = 2147483647
 var c = a + b
-
-
diff --git a/tests/overflw/tovfint.nim b/tests/overflw/tovfint.nim
index f775d2e1c..5c440a540 100644
--- a/tests/overflw/tovfint.nim
+++ b/tests/overflw/tovfint.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tovfint.nim"
   output: "works!"
 """
 # this tests the new overflow literals
@@ -19,5 +18,3 @@ else:
     write(stdout, "broken!\n")
 
 #OUT works!
-
-
diff --git a/tests/overload/toverl.nim b/tests/overload/toverl.nim
index 807b643a4..64257be77 100644
--- a/tests/overload/toverl.nim
+++ b/tests/overload/toverl.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "redefinition of \'TNone\'"
   file: "toverl.nim"
   line: 11
-  errormsg: "redefinition of \'TNone\'"
 """
 # Test for overloading
 
@@ -9,5 +9,3 @@ type
   TNone {.exportc: "_NONE", final.} = object
 
 proc TNone(a, b: int) = nil #ERROR_MSG attempt to redefine 'TNone'
-
-
diff --git a/tests/overload/toverload_issues.nim b/tests/overload/toverload_issues.nim
index 7980f51a9..fe1603a44 100644
--- a/tests/overload/toverload_issues.nim
+++ b/tests/overload/toverload_issues.nim
@@ -119,28 +119,24 @@ template test(loopCount: int, testBody: untyped): typed =
     test(loopCount, 0, testBody)
     echo "done extraI passed 0"
 
-when isMainModule:
-  var
-    loops = 0
-
-  test 0, 0:
-    loops += 1
-  echo "test 0 complete, loops=", loops
-
-  test 1, 1.0:
-    loops += 1
-  echo "test 1.0 complete, loops=", loops
-
-  when true:
-    # when true we get the following compile time error:
-    #   b.nim(35, 6) Error: expression 'loops += 1' has no type (or is ambiguous)
-    loops = 0
-    test 2:
-      loops += 1
-    echo "test no extra complete, loops=", loops
+var
+  loops = 0
 
+test 0, 0:
+  loops += 1
+echo "test 0 complete, loops=", loops
 
+test 1, 1.0:
+  loops += 1
+echo "test 1.0 complete, loops=", loops
 
+when true:
+  # when true we get the following compile time error:
+  #   b.nim(35, 6) Error: expression 'loops += 1' has no type (or is ambiguous)
+  loops = 0
+  test 2:
+    loops += 1
+  echo "test no extra complete, loops=", loops
 
 # bug #2229
 type
diff --git a/tests/parallel/tarray_of_channels.nim b/tests/parallel/tarray_of_channels.nim
index e2a682bd5..5139920ea 100644
--- a/tests/parallel/tarray_of_channels.nim
+++ b/tests/parallel/tarray_of_channels.nim
@@ -34,5 +34,5 @@ proc main =
   sync()
   for ix in 1..3: channels[ix].close()
 
-when isMainModule:
+when true:
   main()
diff --git a/tests/parallel/tgc_unsafe.nim b/tests/parallel/tgc_unsafe.nim
index a4d96cd73..baf0dc24a 100644
--- a/tests/parallel/tgc_unsafe.nim
+++ b/tests/parallel/tgc_unsafe.nim
@@ -28,5 +28,5 @@ proc main =
   sync()
   for ix in 1..3: channels[ix].close()
 
-when isMainModule:
+when true:
   main()
diff --git a/tests/parallel/tgc_unsafe2.nim b/tests/parallel/tgc_unsafe2.nim
index 40bfbdadb..40af728fb 100644
--- a/tests/parallel/tgc_unsafe2.nim
+++ b/tests/parallel/tgc_unsafe2.nim
@@ -1,10 +1,10 @@
 discard """
+  errormsg: "'consumer' is not GC-safe as it calls 'track'"
   line: 28
   nimout: '''tgc_unsafe2.nim(22, 6) Warning: 'trick' is not GC-safe as it accesses 'global' which is a global using GC'ed memory [GcUnsafe2]
 tgc_unsafe2.nim(26, 6) Warning: 'track' is not GC-safe as it calls 'trick' [GcUnsafe2]
 tgc_unsafe2.nim(28, 6) Error: 'consumer' is not GC-safe as it calls 'track'
 '''
-  errormsg: "'consumer' is not GC-safe as it calls 'track'"
 """
 
 import threadpool
@@ -35,5 +35,5 @@ proc main =
   sync()
   for ix in 1..3: channels[ix].close()
 
-when isMainModule:
+when true:
   main()
diff --git a/tests/parallel/tmissing_deepcopy.nim b/tests/parallel/tmissing_deepcopy.nim
index 45fdf0f8f..694eb77db 100644
--- a/tests/parallel/tmissing_deepcopy.nim
+++ b/tests/parallel/tmissing_deepcopy.nim
@@ -36,6 +36,6 @@ proc update =
     for i in 0 .. people.high:
       spawn people[i].greet()
 
-when isMainModule:
+when true:
   setup()
   update()
diff --git a/tests/parallel/tsimple_array_checks.nim b/tests/parallel/tsimple_array_checks.nim
index ee9508074..5d6e87efe 100644
--- a/tests/parallel/tsimple_array_checks.nim
+++ b/tests/parallel/tsimple_array_checks.nim
@@ -59,5 +59,5 @@ proc maino =
 
 maino() # Doesn't work outside a proc
 
-when isMainModule:
+when true:
   main()
diff --git a/tests/parallel/tsysspawnbadarg.nim b/tests/parallel/tsysspawnbadarg.nim
index 2d3ffd241..a8f1ed401 100644
--- a/tests/parallel/tsysspawnbadarg.nim
+++ b/tests/parallel/tsysspawnbadarg.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 9
   errormsg: "'spawn' takes a call expression"
+  line: 9
   cmd: "nim $target --threads:on $options $file"
 """
 
diff --git a/tests/parallel/twrong_refcounts.nim b/tests/parallel/twrong_refcounts.nim
index 57e0588a0..ac428762d 100644
--- a/tests/parallel/twrong_refcounts.nim
+++ b/tests/parallel/twrong_refcounts.nim
@@ -48,6 +48,6 @@ proc update =
 
 # ---
 
-when isMainModule:
+when true:
   setup()
   update()
diff --git a/tests/parser/tdomulttest.nim b/tests/parser/tdomulttest.nim
index 418192ac8..9e1afd034 100644
--- a/tests/parser/tdomulttest.nim
+++ b/tests/parser/tdomulttest.nim
@@ -1,14 +1,14 @@
 discard """
-  file: "tdomulttest.nim"
   output: "555\ntest\nmulti lines\n99999999\nend"
-  disabled: true
 """
+
 proc foo(bar, baz: proc (x: int): int) =
   echo bar(555)
   echo baz(99999999)
 
 foo do (x: int) -> int:
   return x
+
 do (x: int) -> int:
   echo("test")
   echo("multi lines")
diff --git a/tests/parser/tinvcolonlocation1.nim b/tests/parser/tinvcolonlocation1.nim
index 2fddab2f8..7fca5deb7 100644
--- a/tests/parser/tinvcolonlocation1.nim
+++ b/tests/parser/tinvcolonlocation1.nim
@@ -1,8 +1,8 @@
 discard """
+  errormsg: "expected: ':', but got: 'echo'"
   file: "tinvcolonlocation1.nim"
   line: 8
   column: 7
-  errormsg: "expected: ':', but got: 'echo'"
 """
 try #<- missing ':'
   echo "try"
diff --git a/tests/parser/tinvcolonlocation2.nim b/tests/parser/tinvcolonlocation2.nim
index 4251598b9..e3de393b8 100644
--- a/tests/parser/tinvcolonlocation2.nim
+++ b/tests/parser/tinvcolonlocation2.nim
@@ -1,8 +1,8 @@
 discard """
+  errormsg: "expected: ':', but got: 'keyword finally'"
   file: "tinvcolonlocation2.nim"
   line: 11
   column: 8
-  errormsg: "expected: ':', but got: 'keyword finally'"
 """
 try:
   echo "try"
diff --git a/tests/parser/tinvcolonlocation3.nim b/tests/parser/tinvcolonlocation3.nim
index a8db658eb..46252f24e 100644
--- a/tests/parser/tinvcolonlocation3.nim
+++ b/tests/parser/tinvcolonlocation3.nim
@@ -1,8 +1,8 @@
 discard """
+  errormsg: "expected: ':', but got: 'echo'"
   file: "tinvcolonlocation3.nim"
   line: 12
   column: 7
-  errormsg: "expected: ':', but got: 'echo'"
 """
 try:
   echo "try"
diff --git a/tests/parser/tinvwhen.nim b/tests/parser/tinvwhen.nim
index 99701bdf5..7a47f69a4 100644
--- a/tests/parser/tinvwhen.nim
+++ b/tests/parser/tinvwhen.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "invalid indentation"
   file: "tinvwhen.nim"
   line: 11
-  errormsg: "invalid indentation"
 """
 # This was parsed even though it should not!
 
@@ -11,5 +11,3 @@ proc getcwd(buf: cstring, buflen: cint): cstring
     when defined(unix): {.importc: "getcwd", header: "<unistd.h>".} #ERROR_MSG invalid indentation
     elif defined(windows): {.importc: "getcwd", header: "<direct.h>"}
     else: {.error: "os library not ported to your OS. Please help!".}
-
-
diff --git a/tests/parser/toprprec.nim b/tests/parser/toprprec.nim
index 1acd381e7..363ad1c18 100644
--- a/tests/parser/toprprec.nim
+++ b/tests/parser/toprprec.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "toprprec.nim"
   output: "done"
 """
 # Test operator precedence:
diff --git a/tests/parser/ttupleunpack.nim b/tests/parser/ttupleunpack.nim
index aaa06f9f4..c7ab9ea15 100644
--- a/tests/parser/ttupleunpack.nim
+++ b/tests/parser/ttupleunpack.nim
@@ -1,9 +1,3 @@
-discard """
-  file: "ttupleunpack.nim"
-  output: ""
-  exitcode: 0
-"""
-
 proc returnsTuple(): (int, int, int) = (4, 2, 3)
 
 proc main2 =
diff --git a/tests/pragmas/t6448.nim b/tests/pragmas/t6448.nim
index 61e4a35d9..a1bd747a0 100644
--- a/tests/pragmas/t6448.nim
+++ b/tests/pragmas/t6448.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 9
   errormsg: '''ambiguous call; both foobar.async'''
+  line: 9
 """
 
 import foobar
@@ -9,7 +9,7 @@ import asyncdispatch, macros
 proc bar() {.async.} =
   echo 42
 
-proc foo() {.async.} = 
+proc foo() {.async.} =
   await bar()
 
 asyncCheck foo()
diff --git a/tests/pragmas/t8741.nim b/tests/pragmas/t8741.nim
index 41f2f9e8a..c132c3543 100644
--- a/tests/pragmas/t8741.nim
+++ b/tests/pragmas/t8741.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 9
   errormsg: "cannot attach a custom pragma to 'a'"
+  line: 9
 """
 
 for a {.gensym, inject.} in @[1,2,3]:
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim
index ae0f39631..0bc4d2f18 100644
--- a/tests/pragmas/tcustom_pragma.nim
+++ b/tests/pragmas/tcustom_pragma.nim
@@ -174,3 +174,25 @@ type
 var foo: Something
 foo.cardinal = north
 doAssert foo.b.hasCustomPragma(thingy) == true
+
+
+proc myproc(s: string): int = 
+  {.thingy.}:
+    s.len
+
+doAssert myproc("123") == 3
+
+let xx = compiles:
+  proc myproc_bad(s: string): int = 
+    {.not_exist.}:
+      s.len
+doAssert: xx == false
+
+
+macro checkSym(s: typed{nkSym}): untyped = 
+  let body = s.getImpl.body
+  doAssert body[1].kind == nnkPragmaBlock
+  doAssert body[1][0].kind == nnkPragma
+  doAssert body[1][0][0] == bindSym"thingy"
+
+checkSym(myproc)
\ No newline at end of file
diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim
index 83c62b7bb..7616c1215 100644
--- a/tests/pragmas/tused.nim
+++ b/tests/pragmas/tused.nim
@@ -1,11 +1,13 @@
 discard """
   nimout: '''
 compile start
-tused.nim(15, 8) Hint: 'tused.echoSub(a: int, b: int)[declared in tused.nim(15, 7)]' is declared but not used [XDeclaredButNotUsed]
+tused.nim(17, 8) Hint: 'tused.echoSub(a: int, b: int)[declared in tused.nim(17, 7)]' is declared but not used [XDeclaredButNotUsed]
 compile end'''
   output: "8\n8"
+  joinable: false
 """
 
+# not joinable because paths in nimout differ when imported
 static:
   echo "compile start"
 
@@ -31,5 +33,11 @@ block:
   implementArithOpsNew(int)
   echoAdd 3, 5
 
+# issue #9896
+type
+  MyEnum {.used.} = enum
+    Val1, Val2, Val3
+
+
 static:
   echo "compile end"
diff --git a/tests/pragmas/tuserpragma2.nim b/tests/pragmas/tuserpragma2.nim
index bf8844e66..ce16c4649 100644
--- a/tests/pragmas/tuserpragma2.nim
+++ b/tests/pragmas/tuserpragma2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "can raise an unlisted exception: ref Exception"
   file: "tuserpragma2.nim"
   line: 11
-  errormsg: "can raise an unlisted exception: ref Exception"
 """
 
 # bug #7216
diff --git a/tests/proc/tprocredef.nim b/tests/proc/tprocredef.nim
index 4ec771510..0cd6ec770 100644
--- a/tests/proc/tprocredef.nim
+++ b/tests/proc/tprocredef.nim
@@ -1,9 +1,8 @@
 discard """
+  errormsg: "redefinition of \'foo\'"
   file: "tprocredef.nim"
   line: 8
-  errormsg: "redefinition of \'foo\'"
 """
 
 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 914e7c6e7..f778c55eb 100644
--- a/tests/range/tsubrange.nim
+++ b/tests/range/tsubrange.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 20
   errormsg: "cannot convert 60 to TRange"
+  line: 20
 """
 
 type
@@ -18,4 +18,3 @@ p y
 
 const
   myConst: TRange = 60
-
diff --git a/tests/range/tsubrange2.nim b/tests/range/tsubrange2.nim
index 7097faed2..e0fb71c5f 100644
--- a/tests/range/tsubrange2.nim
+++ b/tests/range/tsubrange2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tsubrange2.nim"
   outputsub: "value out of range: 50 [RangeError]"
   exitcode: "1"
 """
@@ -14,4 +13,3 @@ var
   r: TRange
   y = 50
 p y
-
diff --git a/tests/range/tsubrange3.nim b/tests/range/tsubrange3.nim
index f5bb2f161..d3aae87df 100644
--- a/tests/range/tsubrange3.nim
+++ b/tests/range/tsubrange3.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tsubrange.nim"
   outputsub: "value out of range: 50 [RangeError]"
   exitcode: "1"
 """
diff --git a/tests/rational/trat_float.nim b/tests/rational/trat_float.nim
index 24797c4a0..663973bf9 100644
--- a/tests/rational/trat_float.nim
+++ b/tests/rational/trat_float.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: '''type mismatch: got'''
   file: "trat_float.nim"
   line: "9,19"
-  errormsg: '''type mismatch: got'''
 """
 import rationals
 var
diff --git a/tests/realtimeGC/shared.nim b/tests/realtimeGC/shared.nim
index 2d1dd6c3c..1abe42089 100644
--- a/tests/realtimeGC/shared.nim
+++ b/tests/realtimeGC/shared.nim
@@ -1,5 +1,6 @@
 discard """
-  cmd: "nim $target --debuginfo --hints:on --app:lib $options $file"
+cmd: "nim $target --debuginfo --hints:on --app:lib $options $file"
+action: compile
 """
 
 import strutils
diff --git a/tests/seq/tseq.nim b/tests/seq/tseq.nim
index 1cb94b308..6a28bc8e6 100644
--- a/tests/seq/tseq.nim
+++ b/tests/seq/tseq.nim
@@ -203,3 +203,4 @@ block ttoseq:
     stdout.write(x)
   var y: type("a b c".split)
   y = "xzy"
+  stdout.write("\n")
diff --git a/tests/sets/t2669.nim b/tests/sets/t2669.nim
index 6b8eb0f54..0a92818fa 100644
--- a/tests/sets/t2669.nim
+++ b/tests/sets/t2669.nim
@@ -1,6 +1,6 @@
 discard """
-line: 6
 errormsg: "cannot convert 6 to range 1..5(int8)"
+line: 6
 """
 
 var c: set[range[1i8..5i8]] = {1i8, 2i8, 6i8}
diff --git a/tests/sets/tsets.nim b/tests/sets/tsets.nim
index 13a5f54e6..bde25cf81 100644
--- a/tests/sets/tsets.nim
+++ b/tests/sets/tsets.nim
@@ -1,7 +1,8 @@
 discard """
-  file: "tsets.nim"
-  output: '''Ha ein F ist in s!
-false'''
+output: '''
+Ha ein F ist in s!
+false
+'''
 """
 # Test the handling of sets
 
diff --git a/tests/statictypes/t9255.nim b/tests/statictypes/t9255.nim
index bc8df6656..86bc8c7f1 100644
--- a/tests/statictypes/t9255.nim
+++ b/tests/statictypes/t9255.nim
@@ -8,6 +8,6 @@ type mismatch: got <static[proc (a0: int): string{.noSideEffect, gcsafe, locks:
 macro fun(a: static float): untyped =
   discard
 
-when isMainModule:
+when true:
   proc bar(a0: int): string = discard
   fun(bar)
diff --git a/tests/stdlib/nre/captures.nim b/tests/stdlib/nre/captures.nim
index 31de71154..bd5e83ecc 100644
--- a/tests/stdlib/nre/captures.nim
+++ b/tests/stdlib/nre/captures.nim
@@ -9,16 +9,16 @@ suite "captures":
   test "capture bounds are correct":
     let ex1 = re("([0-9])")
     check("1 23".find(ex1).matchBounds == 0 .. 0)
-    check("1 23".find(ex1).captureBounds[0].get == 0 .. 0)
+    check("1 23".find(ex1).captureBounds[0] == 0 .. 0)
     check("1 23".find(ex1, 1).matchBounds == 2 .. 2)
     check("1 23".find(ex1, 3).matchBounds == 3 .. 3)
 
     let ex2 = re("()()()()()()()()()()([0-9])")
-    check("824".find(ex2).captureBounds[0].get == 0 .. -1)
-    check("824".find(ex2).captureBounds[10].get == 0 .. 0)
+    check("824".find(ex2).captureBounds[0] == 0 .. -1)
+    check("824".find(ex2).captureBounds[10] == 0 .. 0)
 
     let ex3 = re("([0-9]+)")
-    check("824".find(ex3).captureBounds[0].get == 0 .. 2)
+    check("824".find(ex3).captureBounds[0] == 0 .. 2)
 
   test "named captures":
     let ex1 = "foobar".find(re("(?<foo>foo)(?<bar>bar)"))
@@ -26,13 +26,19 @@ suite "captures":
     check(ex1.captures["bar"] == "bar")
 
     let ex2 = "foo".find(re("(?<foo>foo)(?<bar>bar)?"))
+    check("foo" in ex2.captureBounds)
     check(ex2.captures["foo"] == "foo")
-    check(ex2.captures["bar"] == "")
+    check(not ("bar" in ex2.captures))
+    expect KeyError:
+        discard ex2.captures["bar"]
 
   test "named capture bounds":
     let ex1 = "foo".find(re("(?<foo>foo)(?<bar>bar)?"))
-    check(ex1.captureBounds["foo"] == some(0..2))
-    check(ex1.captureBounds["bar"] == none(Slice[int]))
+    check("foo" in ex1.captureBounds)
+    check(ex1.captureBounds["foo"] == 0..2)
+    check(not ("bar" in ex1.captures))
+    expect KeyError:
+        discard ex1.captures["bar"]
 
   test "capture count":
     let ex1 = re("(?<foo>foo)(?<bar>bar)?")
@@ -41,19 +47,18 @@ suite "captures":
 
   test "named capture table":
     let ex1 = "foo".find(re("(?<foo>foo)(?<bar>bar)?"))
-    check(ex1.captures.toTable == {"foo" : "foo", "bar" : ""}.toTable())
-    check(ex1.captureBounds.toTable == {"foo" : some(0..2), "bar" : none(Slice[int])}.toTable())
-    check(ex1.captures.toTable("") == {"foo" : "foo", "bar" : ""}.toTable())
+    check(ex1.captures.toTable == {"foo" : "foo"}.toTable())
+    check(ex1.captureBounds.toTable == {"foo" : 0..2}.toTable())
 
     let ex2 = "foobar".find(re("(?<foo>foo)(?<bar>bar)?"))
     check(ex2.captures.toTable == {"foo" : "foo", "bar" : "bar"}.toTable())
 
   test "capture sequence":
     let ex1 = "foo".find(re("(?<foo>foo)(?<bar>bar)?"))
-    check(ex1.captures.toSeq == @["foo", ""])
+    check(ex1.captures.toSeq == @[some("foo"), none(string)])
     check(ex1.captureBounds.toSeq == @[some(0..2), none(Slice[int])])
-    check(ex1.captures.toSeq("") == @["foo", ""])
+    check(ex1.captures.toSeq(some("")) == @[some("foo"), some("")])
 
     let ex2 = "foobar".find(re("(?<foo>foo)(?<bar>bar)?"))
-    check(ex2.captures.toSeq == @["foo", "bar"])
+    check(ex2.captures.toSeq == @[some("foo"), some("bar")])
 
diff --git a/tests/stdlib/nre/match.nim b/tests/stdlib/nre/match.nim
index 38ee5214b..06b69fd04 100644
--- a/tests/stdlib/nre/match.nim
+++ b/tests/stdlib/nre/match.nim
@@ -10,9 +10,9 @@ suite "match":
     check("abc".match(re"(\w)").captures[0] == "a")
     check("abc".match(re"(?<letter>\w)").captures["letter"] == "a")
     check("abc".match(re"(\w)\w").captures[-1] == "ab")
-    check("abc".match(re"(\w)").captureBounds[0].get == 0 .. 0)
-    check("abc".match(re"").captureBounds[-1].get == 0 .. -1)
-    check("abc".match(re"abc").captureBounds[-1].get == 0 .. 2)
+    check("abc".match(re"(\w)").captureBounds[0] == 0 .. 0)
+    check("abc".match(re"").captureBounds[-1] == 0 .. -1)
+    check("abc".match(re"abc").captureBounds[-1] == 0 .. 2)
 
   test "match test cases":
     check("123".match(re"").matchBounds == 0 .. -1)
diff --git a/tests/stdlib/nre/replace.nim b/tests/stdlib/nre/replace.nim
index b762271a2..812a7f384 100644
--- a/tests/stdlib/nre/replace.nim
+++ b/tests/stdlib/nre/replace.nim
@@ -16,5 +16,7 @@ suite "replace":
     check("123".replace(re"(?<foo>\d)(\d)", "${foo}$#$#") == "1123")
 
   test "replacing missing captures should throw instead of segfaulting":
-    discard "ab".replace(re"(a)|(b)", "$1$2")
-    discard "b".replace(re"(a)?(b)", "$1$2")
+    expect IndexError: discard "ab".replace(re"(a)|(b)", "$1$2")
+    expect IndexError: discard "b".replace(re"(a)?(b)", "$1$2")
+    expect KeyError: discard "b".replace(re"(a)?", "${foo}")
+    expect KeyError: discard "b".replace(re"(?<foo>a)?", "${foo}")
diff --git a/tests/stdlib/t8925.nim b/tests/stdlib/t8925.nim
index d3dc1ea86..dbf55fd88 100644
--- a/tests/stdlib/t8925.nim
+++ b/tests/stdlib/t8925.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "strscans.nim"
   errormsg: "type mismatch between pattern '$i' (position: 1) and HourRange var 'hour'"
+  file: "strscans.nim"
 """
 
 import strscans
diff --git a/tests/stdlib/tbitops.nim b/tests/stdlib/tbitops.nim
index 8301256c4..d8c6da1d4 100644
--- a/tests/stdlib/tbitops.nim
+++ b/tests/stdlib/tbitops.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tbitops.nim"
   output: "OK"
 """
 import bitops
diff --git a/tests/stdlib/tbitops2.nim b/tests/stdlib/tbitops2.nim
index 31952316c..e8c7318be 100644
--- a/tests/stdlib/tbitops2.nim
+++ b/tests/stdlib/tbitops2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tbitops.nim"
   output: "OK"
 """
 import bitops
diff --git a/tests/stdlib/tcgi.nim b/tests/stdlib/tcgi.nim
index 23b8b82ca..bc177125e 100644
--- a/tests/stdlib/tcgi.nim
+++ b/tests/stdlib/tcgi.nim
@@ -1,9 +1,3 @@
-discard """

-  action: run

-  file: tcgi.nim

-  output: "[Suite] Test cgi module"

-"""

-

 import unittest

 import cgi, strtabs

 

diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim
index bf0bb3ea7..33332447b 100644
--- a/tests/stdlib/tjsonmacro.nim
+++ b/tests/stdlib/tjsonmacro.nim
@@ -1,10 +1,9 @@
 discard """
-  file: "tjsonmacro.nim"
   output: ""
 """
 import json, strutils, options, tables
 
-when isMainModule:
+when true:
   # Tests inspired by own use case (with some additional tests).
   # This should succeed.
   type
diff --git a/tests/stdlib/tjsonmacro_reject.nim b/tests/stdlib/tjsonmacro_reject.nim
index 00506449f..ada365d7d 100644
--- a/tests/stdlib/tjsonmacro_reject.nim
+++ b/tests/stdlib/tjsonmacro_reject.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "Use a named tuple instead of: (string, float)"
   file: "tjsonmacro_reject.nim"
   line: 11
-  errormsg: "Use a named tuple instead of: (string, float)"
 """
 
 import json
@@ -15,4 +15,4 @@ let j = """
   {"engine": {"name": "V8", "capacity": 5.5}, model: "Skyline"}
 """
 let parsed = parseJson(j)
-echo(to(parsed, Car))
\ No newline at end of file
+echo(to(parsed, Car))
diff --git a/tests/stdlib/tjsonmacro_reject2.nim b/tests/stdlib/tjsonmacro_reject2.nim
index b01153553..e13dad307 100644
--- a/tests/stdlib/tjsonmacro_reject2.nim
+++ b/tests/stdlib/tjsonmacro_reject2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "The `to` macro does not support ref objects with cycles."
   file: "tjsonmacro_reject2.nim"
   line: 10
-  errormsg: "The `to` macro does not support ref objects with cycles."
 """
 import json
 
@@ -18,4 +18,4 @@ let data = """
 """
 
 let dataParsed = parseJson(data)
-let dataDeser = to(dataParsed, Cycle)
\ No newline at end of file
+let dataDeser = to(dataParsed, Cycle)
diff --git a/tests/stdlib/tlists.nim b/tests/stdlib/tlists.nim
index b7c7f9f5a..a288af781 100644
--- a/tests/stdlib/tlists.nim
+++ b/tests/stdlib/tlists.nim
@@ -10,7 +10,8 @@ const
 block SinglyLinkedListTest1:
   var L: SinglyLinkedList[int]
   for d in items(data): L.prepend(d)
-  assert($L == "[6, 5, 4, 3, 2, 1]")
+  for d in items(data): L.append(d)
+  assert($L == "[6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6]")
 
   assert(4 in L)
 
diff --git a/tests/stdlib/tmemfiles1.nim b/tests/stdlib/tmemfiles1.nim
index a18fba083..21a65369f 100644
--- a/tests/stdlib/tmemfiles1.nim
+++ b/tests/stdlib/tmemfiles1.nim
@@ -1,7 +1,3 @@
-discard """
-  file: "tmemfiles1.nim"
-  outputsub: ""
-"""
 import memfiles, os
 var
   mm: MemFile
diff --git a/tests/stdlib/tmemmapstreams.nim b/tests/stdlib/tmemmapstreams.nim
index 243574f1a..dd011d777 100644
--- a/tests/stdlib/tmemmapstreams.nim
+++ b/tests/stdlib/tmemmapstreams.nim
@@ -1,6 +1,6 @@
 discard """
-  file: "tmemmapstreams.nim"
-  output: '''Created size: 10
+output: '''
+Created size: 10
 Position after writing: 5
 Position after writing one char: 6
 Peeked data: Hello
diff --git a/tests/stdlib/tnativesockets.nim b/tests/stdlib/tnativesockets.nim
deleted file mode 100644
index c2738b8a5..000000000
--- a/tests/stdlib/tnativesockets.nim
+++ /dev/null
@@ -1,11 +0,0 @@
-discard """
-outputsub: ""
-"""
-
-import nativesockets, unittest
-
-suite "nativesockets":
-  test "getHostname":
-    let hostname = getHostname()
-    check hostname.len > 0
-    check hostname.len < 64
diff --git a/tests/stdlib/tospaths.nim b/tests/stdlib/tospaths.nim
index 9e2a5605c..bee9bab76 100644
--- a/tests/stdlib/tospaths.nim
+++ b/tests/stdlib/tospaths.nim
@@ -1,5 +1,4 @@
 discard """

-  file: "tospaths.nim"

   output: ""

 """

 # test the ospaths module

diff --git a/tests/stdlib/tosproc.nim b/tests/stdlib/tosproc.nim
index ac129e709..9d57d4574 100644
--- a/tests/stdlib/tosproc.nim
+++ b/tests/stdlib/tosproc.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tospaths.nim"
   output: ""
 """
 # test the osproc module
diff --git a/tests/stdlib/tparsesql.nim b/tests/stdlib/tparsesql.nim
index 126020ed6..8cf8fa848 100644
--- a/tests/stdlib/tparsesql.nim
+++ b/tests/stdlib/tparsesql.nim
@@ -1,7 +1,3 @@
-discard """
-  file: "tparsesql.nim"
-"""
-
 import parsesql
 
 doAssert $parseSQL("SELECT foo FROM table;") == "select foo from table;"
diff --git a/tests/stdlib/tquit.nim b/tests/stdlib/tquit.nim
index 4f8d5fb20..1f9283ec4 100644
--- a/tests/stdlib/tquit.nim
+++ b/tests/stdlib/tquit.nim
@@ -2,6 +2,7 @@ discard """
 output: '''
 just exiting...
 '''
+joinable: false
 """
 
 # Test the new beforeQuit variable:
diff --git a/tests/stdlib/tregex.nim b/tests/stdlib/tregex.nim
index ae6714de1..21f4e6743 100644
--- a/tests/stdlib/tregex.nim
+++ b/tests/stdlib/tregex.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tregex.nim"
   output: "key: keyAYes!"
 """
 # Test the new regular expression module
@@ -27,5 +26,3 @@ else:
     echo("Bug!")
 
   #OUT key: keyAYes!
-
-
diff --git a/tests/stdlib/trepr.nim b/tests/stdlib/trepr.nim
index 18fe7e054..33cb581ef 100644
--- a/tests/stdlib/trepr.nim
+++ b/tests/stdlib/trepr.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "trepr.nim"
   output: "{a, b}{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}"
 """
 
@@ -26,4 +25,3 @@ when false:
 #  "a", "b", "c", "d", "e"
 #]
 #echo(repr(testseq))
-
diff --git a/tests/stdlib/tsqlparser.nim b/tests/stdlib/tsqlparser.nim
index 4a7b2f7d7..11ee22e2b 100644
--- a/tests/stdlib/tsqlparser.nim
+++ b/tests/stdlib/tsqlparser.nim
@@ -6,7 +6,7 @@ discard """
 
 import parsesql, streams, os
 
-var tree = parseSql(newFileStream(getAppDir() / "somesql.sql"), "somesql")
+var tree = parseSql(newFileStream(parentDir(currentSourcePath) / "somesql.sql"), "somesql")
 discard renderSql(tree)
 
 echo "true"
diff --git a/tests/stdlib/tstdlib_various.nim b/tests/stdlib/tstdlib_various.nim
index 7abc9a391..d1723df78 100644
--- a/tests/stdlib/tstdlib_various.nim
+++ b/tests/stdlib/tstdlib_various.nim
@@ -219,7 +219,7 @@ block tsplit2:
 
 block tsqlparser:
   # Just check that we can parse 'somesql' and render it without crashes.
-  var tree = parseSql(newFileStream(getAppDir() / "somesql.sql"), "somesql")
+  var tree = parseSql(newFileStream( parentDir(currentSourcePath) / "somesql.sql"), "somesql")
   discard renderSql(tree)
 
 
diff --git a/tests/stdlib/tstreams2.nim b/tests/stdlib/tstreams2.nim
index 90102d8e3..70f0bac32 100644
--- a/tests/stdlib/tstreams2.nim
+++ b/tests/stdlib/tstreams2.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstreams2.nim"
   output: '''fs is: nil'''
 """
 import streams
diff --git a/tests/stdlib/tstreams3.nim b/tests/stdlib/tstreams3.nim
index b2c9170e3..e3b395e05 100644
--- a/tests/stdlib/tstreams3.nim
+++ b/tests/stdlib/tstreams3.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstreams3.nim"
   output: "threw exception"
 """
 import streams
diff --git a/tests/stdlib/tstring.nim b/tests/stdlib/tstring.nim
index 660746150..852ff4fb7 100644
--- a/tests/stdlib/tstring.nim
+++ b/tests/stdlib/tstring.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstring.nim"
   output: "OK"
 """
 const characters = "abcdefghijklmnopqrstuvwxyz"
diff --git a/tests/stdlib/tstrutil.nim b/tests/stdlib/tstrutil.nim
index 64b8f8ecc..fffa85bd1 100644
--- a/tests/stdlib/tstrutil.nim
+++ b/tests/stdlib/tstrutil.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tstrutil.nim"
   output: "ha/home/a1xyz/usr/bin"
 """
 # test the new strutils module
diff --git a/tests/stdlib/tsugar.nim b/tests/stdlib/tsugar.nim
index a870bf6fe..111ca96a4 100644
--- a/tests/stdlib/tsugar.nim
+++ b/tests/stdlib/tsugar.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tsugar.nim"
   output: ""
 """
 import sugar
diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim
index 7ebbe61d9..ed87b15ac 100644
--- a/tests/stdlib/ttimes.nim
+++ b/tests/stdlib/ttimes.nim
@@ -1,8 +1,5 @@
 discard """
-  file: "ttimes.nim"
   target: "c js"
-  output: '''[Suite] ttimes
-'''
 """
 
 import times, strutils, unittest
@@ -125,7 +122,7 @@ suite "ttimes":
   when defined(linux) or defined(macosx):
     let tz_dir = getEnv("TZDIR", "/usr/share/zoneinfo")
     const f = "yyyy-MM-dd HH:mm zzz"
-    
+
     let orig_tz = getEnv("TZ")
     var tz_cnt = 0
     for tz_fn in walkFiles(tz_dir & "/**/*"):
@@ -152,7 +149,7 @@ suite "ttimes":
       check initDateTime(29, mOct, 2017, 01, 00, 00).isDst
       check initDateTime(29, mOct, 2017, 03, 01, 00).format(f) == "2017-10-29 03:01 +01:00"
       check (not initDateTime(29, mOct, 2017, 03, 01, 00).isDst)
-      
+
       check initDateTime(21, mOct, 2017, 01, 00, 00).format(f) == "2017-10-21 01:00 +02:00"
 
     test "issue #6520":
@@ -170,10 +167,10 @@ suite "ttimes":
       check diff == initDuration(seconds = 2208986872)
 
     test "issue #6465":
-      putEnv("TZ", "Europe/Stockholm")      
+      putEnv("TZ", "Europe/Stockholm")
       let dt = parse("2017-03-25 12:00", "yyyy-MM-dd hh:mm")
       check $(dt + initTimeInterval(days = 1)) == "2017-03-26T12:00:00+02:00"
-      check $(dt + initDuration(days = 1)) == "2017-03-26T13:00:00+02:00"      
+      check $(dt + initDuration(days = 1)) == "2017-03-26T13:00:00+02:00"
 
     test "datetime before epoch":
       check $fromUnix(-2147483648).utc == "1901-12-13T20:45:52Z"
diff --git a/tests/system/helpers/readall_echo.nim b/tests/system/helpers/readall_echo.nim
index 79937bf6f..2891ef3ae 100644
--- a/tests/system/helpers/readall_echo.nim
+++ b/tests/system/helpers/readall_echo.nim
@@ -1,2 +1,2 @@
-when isMainModule:
+when true:
   echo(stdin.readAll)
diff --git a/tests/system/t7894.nim b/tests/system/t7894.nim
index 27ee3f220..b7ca1eec8 100644
--- a/tests/system/t7894.nim
+++ b/tests/system/t7894.nim
@@ -1,6 +1,7 @@
 discard """
 disabled: "travis"
 disabled: "appveyor"
+joinable: false
 """
 
 # CI integration servers are out of memory for this test
diff --git a/tests/system/talloc2.nim b/tests/system/talloc2.nim
index e40c3f93c..7e0dec9d3 100644
--- a/tests/system/talloc2.nim
+++ b/tests/system/talloc2.nim
@@ -1,5 +1,6 @@
 discard """
 disabled: "windows"
+joinable: false
 """
 
 # appveyor is "out of memory"
diff --git a/tests/system/tostring.nim b/tests/system/tostring.nim
index 04b37f133..ea4a44417 100644
--- a/tests/system/tostring.nim
+++ b/tests/system/tostring.nim
@@ -1,5 +1,5 @@
 discard """
-  output: ""
+  output: "DONE: tostring.nim"
 """
 
 doAssert "@[23, 45]" == $(@[23, 45])
@@ -115,3 +115,6 @@ block:
   var s: string
   s.addQuoted a2
   doAssert s == "\"fo\\\"o2\""
+
+
+echo "DONE: tostring.nim"
diff --git a/tests/system/tparams.nim b/tests/system/tparams.nim
index 015530043..dcd620b20 100644
--- a/tests/system/tparams.nim
+++ b/tests/system/tparams.nim
@@ -1,3 +1,8 @@
+discard """
+joinable: false
+"""
+
+# not joinable because it executes itself with parameters
 import os
 import osproc
 import parseopt2
diff --git a/tests/system/trealloc.nim b/tests/system/trealloc.nim
index dc5f712d6..7180b8eda 100644
--- a/tests/system/trealloc.nim
+++ b/tests/system/trealloc.nim
@@ -1,5 +1,6 @@
 discard """
   output: '''success'''
+  joinable: false
 """
 
 # bug #4818
diff --git a/tests/template/t_otemplates.nim b/tests/template/t_otemplates.nim
index 6597bd37a..8d2ac38a6 100644
--- a/tests/template/t_otemplates.nim
+++ b/tests/template/t_otemplates.nim
@@ -340,6 +340,6 @@ macro tmpl*(body: untyped): untyped =
 
 
 # Run tests
-when isMainModule:
+when true:
     include otests
     echo "Success"
diff --git a/tests/template/template_issues.nim b/tests/template/template_issues.nim
index 8599b161a..15d6ab2b1 100644
--- a/tests/template/template_issues.nim
+++ b/tests/template/template_issues.nim
@@ -43,7 +43,7 @@ block t2629:
 
   let rst_files = concat(glob_rst(), glob_rst("docs"))
 
-  when isMainModule: echo rst_files
+  when true: echo rst_files
 
 
 block t5417:
diff --git a/tests/template/tgensymregression.nim b/tests/template/tgensymregression.nim
index 4cc64a831..4194e3e88 100644
--- a/tests/template/tgensymregression.nim
+++ b/tests/template/tgensymregression.nim
@@ -15,7 +15,7 @@ template mathPerComponent(op: untyped): untyped =
 mathPerComponent(`***`)
 # bug #5285
 when true:
-  if isMainModule:
+  if true:
     var v1: array[3, float64]
     var v2: array[3, float64]
     echo repr(v1 *** v2)
diff --git a/tests/template/thygienictempl.nim b/tests/template/thygienictempl.nim
index 506f57148..9020c3e28 100644
--- a/tests/template/thygienictempl.nim
+++ b/tests/template/thygienictempl.nim
@@ -18,5 +18,5 @@ template test_in(a, b, c: untyped): bool {.dirty.} =
   var result {.gensym.}: bool = false
   false
 
-when isMainModule:
+when true:
   assert test_in(ret2, "test", str_val)
diff --git a/tests/template/tparams_gensymed.nim b/tests/template/tparams_gensymed.nim
index da86d63dc..91fa26596 100644
--- a/tests/template/tparams_gensymed.nim
+++ b/tests/template/tparams_gensymed.nim
@@ -70,3 +70,43 @@ proc genericProc(x: any) =
 
 concreteProc(7) # This works
 genericProc(7)  # This doesn't compile
+
+import tables
+
+# bug #9476
+proc getTypeInfo*(T: typedesc): pointer =
+  var dummy: T
+  getTypeInfo(dummy)
+
+
+macro implementUnary(op: untyped): untyped =
+  result = newStmtList()
+
+  template defineTable(tableSymbol) =
+    var tableSymbol = initTable[pointer, pointer]()
+  let tableSymbol = genSym(nskVar, "registeredProcs")
+  result.add(getAst(defineTable(tableSymbol)))
+
+  template defineRegisterInstantiation(tableSym, regTemplSym, instSym, op) =
+    template regTemplSym*(T: typedesc) =
+      let ti = getTypeInfo(T)
+
+      proc instSym(xOrig: int): int {.gensym, cdecl.} =
+        let x {.inject.} = xOrig
+        op
+
+      tableSym[ti] = cast[pointer](instSym)
+
+  let regTemplSymbol = ident("registerInstantiation")
+  let instSymbol = ident("instantiation")
+  result.add(getAst(defineRegisterInstantiation(
+    tableSymbol, regTemplSymbol, instSymbol, op
+  )))
+
+  echo result.repr
+
+
+implementUnary(): x*x
+
+registerInstantiation(int)
+registerInstantiation(float)
diff --git a/tests/template/ttempl2.nim b/tests/template/ttempl2.nim
index aaa2f1344..eb67bea0c 100644
--- a/tests/template/ttempl2.nim
+++ b/tests/template/ttempl2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "undeclared identifier: \'b\'"
   file: "ttempl2.nim"
   line: 18
-  errormsg: "undeclared identifier: \'b\'"
 """
 template declareInScope(x: untyped, t: typeDesc): untyped {.immediate.} =
   var x: t
@@ -16,4 +16,3 @@ a = 42  # works, `a` is known here
 
 declareInNewScope(b, int)
 b = 42  #ERROR_MSG undeclared identifier: 'b'
-
diff --git a/tests/template/twrongopensymchoice.nim b/tests/template/twrongopensymchoice.nim
index 360c92037..7a2bb48d3 100644
--- a/tests/template/twrongopensymchoice.nim
+++ b/tests/template/twrongopensymchoice.nim
@@ -20,5 +20,5 @@ proc main =
   var f = Foo.new()
   echo f.b
 
-when isMainModule:
+when true:
   main()
diff --git a/tests/testament/tshouldfail.nim b/tests/testament/tshouldfail.nim
index 02e4bfd80..d35dd99ac 100644
--- a/tests/testament/tshouldfail.nim
+++ b/tests/testament/tshouldfail.nim
@@ -1,17 +1,31 @@
 discard """
-cmd: "testament/tester --directory:testament --colors:off --nim:../compiler/nim category shouldfail"
+cmd: "testament/tester --directory:testament --colors:off --backendLogging:off --nim:../compiler/nim category shouldfail"
 action: compile
 nimout: '''
 FAIL: tccodecheck.nim C
+Failure: reCodegenFailure
+Expected:
+baz
 FAIL: tcolumn.nim C
+Failure: reLinesDiffer
 FAIL: terrormsg.nim C
+Failure: reMsgsDiffer
 FAIL: texitcode1.nim C
+Failure: reExitcodesDiffer
 FAIL: tfile.nim C
+Failure: reFilesDiffer
 FAIL: tline.nim C
+Failure: reLinesDiffer
 FAIL: tmaxcodesize.nim C
+Failure: reCodegenFailure
+max allowed size: 1
 FAIL: tnimout.nim C
+Failure: reMsgsDiffer
 FAIL: toutput.nim C
+Failure: reOutputsDiffer
 FAIL: toutputsub.nim C
+Failure: reOutputsDiffer
 FAIL: tsortoutput.nim C
+Failure: reOutputsDiffer
 '''
 """
diff --git a/tests/threads/t8535.nim b/tests/threads/t8535.nim
index a8d69657b..e1b5a1369 100644
--- a/tests/threads/t8535.nim
+++ b/tests/threads/t8535.nim
@@ -12,5 +12,5 @@ type
 
 var foo {.threadvar.}: CircAlloc[1,Job]
 
-when isMainModule:
+when true:
   echo foo.index
diff --git a/tests/threads/tthreadanalysis2.nim b/tests/threads/tthreadanalysis2.nim
index c1ec3ae39..067e186a8 100644
--- a/tests/threads/tthreadanalysis2.nim
+++ b/tests/threads/tthreadanalysis2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "'threadFunc' is not GC-safe"
   file: "tthreadanalysis2.nim"
   line: 37
-  errormsg: "'threadFunc' is not GC-safe"
   cmd: "nim $target --hints:on --threads:on $options $file"
 """
 
@@ -49,4 +49,3 @@ proc main =
   joinThreads(thr)
 
 main()
-
diff --git a/tests/threads/tthreadheapviolation1.nim b/tests/threads/tthreadheapviolation1.nim
index 59ecb742c..379bd55e6 100644
--- a/tests/threads/tthreadheapviolation1.nim
+++ b/tests/threads/tthreadheapviolation1.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 11
   errormsg: "'horrible' is not GC-safe"
+  line: 11
   cmd: "nim $target --hints:on --threads:on $options $file"
 """
 
@@ -16,5 +16,3 @@ proc horrible() {.thread.} =
 
 createThread[void](t, horrible)
 joinThread(t)
-
-
diff --git a/tests/trmacros/tdisallowif.nim b/tests/trmacros/tdisallowif.nim
index 18dfd1c82..36f60800e 100644
--- a/tests/trmacros/tdisallowif.nim
+++ b/tests/trmacros/tdisallowif.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 24
   errormsg: "usage of 'disallowIf' is a user-defined error"
+  line: 24
   disabled: true
 """
 
diff --git a/tests/tuples/ttuples_various.nim b/tests/tuples/ttuples_various.nim
index 36171d5d7..010893ced 100644
--- a/tests/tuples/ttuples_various.nim
+++ b/tests/tuples/ttuples_various.nim
@@ -121,7 +121,7 @@ block tuple_with_seq:
   proc g(t: tuple[n:int, xs:seq[int]]) =
     discard
 
-  when isMainModule:
+  when true:
     f(@[]) # OK
     g((1,@[1])) # OK
     g((0,@[])) # NG
diff --git a/tests/tuples/twrongtupleaccess.nim b/tests/tuples/twrongtupleaccess.nim
index b1684b097..591716a2e 100644
--- a/tests/tuples/twrongtupleaccess.nim
+++ b/tests/tuples/twrongtupleaccess.nim
@@ -1,10 +1,9 @@
 discard """
+  errormsg: "attempting to call undeclared routine: \'setBLAH\'"
   file: "twrongtupleaccess.nim"
   line: 9
-  errormsg: "attempting to call undeclared routine: \'setBLAH\'"
 """
 # Bugfix
 
 var v = (5.0, 10.0)
 v.setBLAH(10)
-
diff --git a/tests/typerel/t2plus.nim b/tests/typerel/t2plus.nim
index d099eeeb0..4b18b6221 100644
--- a/tests/typerel/t2plus.nim
+++ b/tests/typerel/t2plus.nim
@@ -16,7 +16,7 @@ proc foldRight[T,U](lst: seq[T], v: U, f: (T, U) -> U): U =
 proc mean[T: SomeNumber](xs: seq[T]): T =
   xs.foldRight(0.T, (xBAZ: auto, yBAZ: auto) => xBAZ + yBAZ) / T(xs.len)
 
-when isMainModule:
+when true:
   let x = mean(@[1.float, 2, 3])
   echo x
 
diff --git a/tests/typerel/t8172.nim b/tests/typerel/t8172.nim
index 8e0b32932..57b788250 100644
--- a/tests/typerel/t8172.nim
+++ b/tests/typerel/t8172.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 11
   errormsg: "cannot convert array[0..0, string] to varargs[string]"
+  line: 11
 """
 
 proc f(v: varargs[string]) =
diff --git a/tests/typerel/temptynode.nim b/tests/typerel/temptynode.nim
index df308fbc2..8c71a6092 100644
--- a/tests/typerel/temptynode.nim
+++ b/tests/typerel/temptynode.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 16
   errormsg: "type mismatch: got <void>"
+  line: 16
 """
 
 # bug #950
diff --git a/tests/typerel/texplicitcmp.nim b/tests/typerel/texplicitcmp.nim
index e91ac2ffe..b11aa2f4e 100644
--- a/tests/typerel/texplicitcmp.nim
+++ b/tests/typerel/texplicitcmp.nim
@@ -24,9 +24,8 @@ proc weird(json_params: Table) =
   sort(f, system.cmp[int])
   outp(f)
 
-when isMainModule:
-  var t = @[3, 2, 1]
-  sort(t, system.cmp[int])
-  outp(t)
-  works()
-  weird(initTable[string, JsonNode]())
+var t = @[3, 2, 1]
+sort(t, system.cmp[int])
+outp(t)
+works()
+weird(initTable[string, JsonNode]())
diff --git a/tests/typerel/tno_int_in_bool_context.nim b/tests/typerel/tno_int_in_bool_context.nim
index a4b4237d2..66e9da58a 100644
--- a/tests/typerel/tno_int_in_bool_context.nim
+++ b/tests/typerel/tno_int_in_bool_context.nim
@@ -1,8 +1,7 @@
 discard """
-  line: 6
   errormsg: "type mismatch: got <int literal(1)> but expected 'bool'"
+  line: 6
 """
 
 if 1:
   echo "wtf?"
-
diff --git a/tests/typerel/tnocontains.nim b/tests/typerel/tnocontains.nim
index a93db2fc3..8bea8aa56 100644
--- a/tests/typerel/tnocontains.nim
+++ b/tests/typerel/tnocontains.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch: got <string, string>"
   file: "tnocontains.nim"
   line: 10
-  errormsg: "type mismatch: got <string, string>"
 """
 
 # shouldn't compile since it doesn't do what you think it does without
diff --git a/tests/typerel/trefs.nim b/tests/typerel/trefs.nim
index d4383c562..e9862bd0f 100644
--- a/tests/typerel/trefs.nim
+++ b/tests/typerel/trefs.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch"
   file: "trefs.nim"
   line: 20
-  errormsg: "type mismatch"
 """
 # test for ref types (including refs to procs)
 
@@ -18,6 +18,3 @@ var p: TProc
 p = foo
 write(stdout, "success!")
 p = wrongfoo  #ERROR_MSG type mismatch
-
-
-
diff --git a/tests/typerel/tregionptrs.nim b/tests/typerel/tregionptrs.nim
index 9eeded18b..504ec1011 100644
--- a/tests/typerel/tregionptrs.nim
+++ b/tests/typerel/tregionptrs.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 16
   errormsg: "type mismatch: got <BPtr> but expected 'APtr = ptr[RegionA, int]'"
+  line: 16
 """
 
 type
diff --git a/tests/typerel/ttypedesc_as_genericparam1.nim b/tests/typerel/ttypedesc_as_genericparam1.nim
index 9ae464842..b7c3e727d 100644
--- a/tests/typerel/ttypedesc_as_genericparam1.nim
+++ b/tests/typerel/ttypedesc_as_genericparam1.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 6
   errormsg: "type mismatch: got <type int>"
+  line: 6
 """
 # bug #3079, #1146
 echo repr(int)
diff --git a/tests/typerel/ttypedesc_as_genericparam2.nim b/tests/typerel/ttypedesc_as_genericparam2.nim
index 0b4281269..ea06606f9 100644
--- a/tests/typerel/ttypedesc_as_genericparam2.nim
+++ b/tests/typerel/ttypedesc_as_genericparam2.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 9
   errormsg: "'repr' doesn't support 'void' type"
+  line: 9
 """
 
 # bug #2879
diff --git a/tests/typerel/ttypenoval.nim b/tests/typerel/ttypenoval.nim
index 720e5d662..c7829f9dd 100644
--- a/tests/typerel/ttypenoval.nim
+++ b/tests/typerel/ttypenoval.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "type mismatch: got <type int> but expected 'int'"
   file: "ttypenoval.nim"
   line: 38
-  errormsg: "type mismatch: got <type int> but expected 'int'"
 """
 
 # A min-heap.
@@ -51,5 +51,3 @@ var
 newBinHeap(heap, 256)
 add(heap, 1, 100)
 print(heap)
-
-
diff --git a/tests/typerel/typredef.nim b/tests/typerel/typredef.nim
index 0b6aed875..c502a834c 100644
--- a/tests/typerel/typredef.nim
+++ b/tests/typerel/typredef.nim
@@ -1,8 +1,7 @@
 discard """
+  errormsg: "illegal recursion in type \'Uint8\'"
   file: "typredef.nim"
   line: 7
-  errormsg: "illegal recursion in type \'Uint8\'"
 """
 type
   Uint8 = Uint8 #ERROR_MSG illegal recursion in type 'Uint8'
-
diff --git a/tests/types/t6456.nim b/tests/types/t6456.nim
index 2d2aad370..19bbc2c02 100644
--- a/tests/types/t6456.nim
+++ b/tests/types/t6456.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 6
   errormsg: "type \'ptr void\' is not allowed"
+  line: 6
 """
 
 proc foo(x: ptr void) =
diff --git a/tests/types/tassignemptytuple.nim b/tests/types/tassignemptytuple.nim
index bdfc653a5..9d5a311ba 100644
--- a/tests/types/tassignemptytuple.nim
+++ b/tests/types/tassignemptytuple.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "cannot infer the type of the tuple"
   file: "tassignemptytuple.nim"
   line: 11
-  errormsg: "cannot infer the type of the tuple"
 """
 
 var
diff --git a/tests/types/tillegaltyperecursion.nim b/tests/types/tillegaltyperecursion.nim
index 6ead902b7..d8021c06f 100644
--- a/tests/types/tillegaltyperecursion.nim
+++ b/tests/types/tillegaltyperecursion.nim
@@ -59,7 +59,7 @@ proc Connect*(irc: var TIRC, nick: string, host: string, port: int = 6667) =
 
 
 
-when isMainModule:
+when true:
     var irc = initIRC()
     irc.Connect("AmryBot[Nim]","irc.freenode.net",6667)
     irc.sendRaw("JOIN #nim")
diff --git a/tests/types/tillrec.nim b/tests/types/tillrec.nim
index 18757140a..7584282b6 100644
--- a/tests/types/tillrec.nim
+++ b/tests/types/tillrec.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "illegal recursion in type \'TIllegal\'"
   file: "tillrec.nim"
   line: 13
-  errormsg: "illegal recursion in type \'TIllegal\'"
 """
 # test illegal recursive types
 
@@ -13,4 +13,3 @@ type
   TIllegal {.final.} = object  #ERROR_MSG illegal recursion in type 'TIllegal'
     y: int
     x: array[0..3, TIllegal]
-
diff --git a/tests/types/tissues.nim b/tests/types/tissues_types.nim
index 97c796302..d3643842e 100644
--- a/tests/types/tissues.nim
+++ b/tests/types/tissues_types.nim
@@ -9,8 +9,9 @@ ptr Foo
 (member: "hello world", x: ...)
 (member: 123.456, x: ...)
 '''
+joinable: false
 """
-
+# not joinable because it causes out of memory with --gc:boehm
 import typetraits
 
 block t1252:
diff --git a/tests/types/tparameterizedparent0.nim b/tests/types/tparameterizedparent0.nim
index 1b72a4e21..90e7a9c0c 100644
--- a/tests/types/tparameterizedparent0.nim
+++ b/tests/types/tparameterizedparent0.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "inheritance only works with non-final objects"
   file: "tparameterizedparent0.nim"
   line: 14
-  errormsg: "inheritance only works with non-final objects"
 """
 # bug #5264
 type
diff --git a/tests/types/tparameterizedparent1.nim b/tests/types/tparameterizedparent1.nim
index 24fb9a565..5da8189f4 100644
--- a/tests/types/tparameterizedparent1.nim
+++ b/tests/types/tparameterizedparent1.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "inheritance only works with non-final objects"
   file: "tparameterizedparent1.nim"
   line: 14
-  errormsg: "inheritance only works with non-final objects"
 """
 # bug #5264
 type
diff --git a/tests/types/tparameterizedparent3.nim b/tests/types/tparameterizedparent3.nim
index 58aaf80ea..fcca6453e 100644
--- a/tests/types/tparameterizedparent3.nim
+++ b/tests/types/tparameterizedparent3.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "attempt to redefine: 'color'"
   file: "tparameterizedparent3.nim"
   line: 13
-  errormsg: "attempt to redefine: 'color'"
 """
 # bug #5264
 type
diff --git a/tests/types/tparameterizedparent4.nim b/tests/types/tparameterizedparent4.nim
index a37461bb4..4759d9d9b 100644
--- a/tests/types/tparameterizedparent4.nim
+++ b/tests/types/tparameterizedparent4.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "attempt to redefine: 'grain'"
   file: "tparameterizedparent4.nim"
   line: 23
-  errormsg: "attempt to redefine: 'grain'"
 """
 # bug #5264
 type
diff --git a/tests/untestable/tssl.nim b/tests/untestable/tssl.nim
index 664ad805c..fca6385f8 100644
--- a/tests/untestable/tssl.nim
+++ b/tests/untestable/tssl.nim
@@ -20,7 +20,7 @@ from strutils import contains, toHex
 
 from openssl import getOpenSSLVersion
 
-when isMainModule:
+when true:
   echo "version: 0x" & $getOpenSSLVersion().toHex()
 
   let client = newHttpClient()
diff --git a/tests/usingstmt/tusingstatement.nim b/tests/usingstmt/tusingstatement.nim
index 8585bcc9e..6e4998892 100644
--- a/tests/usingstmt/tusingstatement.nim
+++ b/tests/usingstmt/tusingstatement.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tusingstatement.nim"
   output: "Using test.Closing test."
 """
 
@@ -85,3 +84,5 @@ proc use(r: var TResource) =
 
 autoClose(r = openResource("test")):
   use r
+
+write stdout, "\n"
diff --git a/tests/varres/tnewseq_on_result_vart.nim b/tests/varres/tnewseq_on_result_vart.nim
index 18935a1d1..4a700468f 100644
--- a/tests/varres/tnewseq_on_result_vart.nim
+++ b/tests/varres/tnewseq_on_result_vart.nim
@@ -1,7 +1,7 @@
 
 discard """
-  line: 9
   errormsg: "address of 'result' may not escape its stack frame"
+  line: 9
 """
 # bug #5113
 
diff --git a/tests/varres/tprevent_forloopvar_mutations.nim b/tests/varres/tprevent_forloopvar_mutations.nim
index 15938bb77..43cc04f30 100644
--- a/tests/varres/tprevent_forloopvar_mutations.nim
+++ b/tests/varres/tprevent_forloopvar_mutations.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 15
   errmsg: "type mismatch: got <int>"
+  line: 15
   nimout: '''type mismatch: got <int>
 but expected one of:
 proc inc[T: Ordinal | uint | uint64](x: var T; y = 1)
diff --git a/tests/varres/tvarres1.nim b/tests/varres/tvarres1.nim
index 5a5247142..e58d7f083 100644
--- a/tests/varres/tvarres1.nim
+++ b/tests/varres/tvarres1.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "'bla' escapes its stack frame; context: 'bla'"
   file: "tvarres1.nim"
   line: 12
-  errormsg: "'bla' escapes its stack frame; context: 'bla'"
 """
 
 var
@@ -14,4 +14,3 @@ proc p(): var int =
 p() = 45
 
 echo g
-
diff --git a/tests/varres/tvarres2.nim b/tests/varres/tvarres2.nim
index 53a57d882..4ec0bb05b 100644
--- a/tests/varres/tvarres2.nim
+++ b/tests/varres/tvarres2.nim
@@ -1,7 +1,7 @@
 discard """
+  errormsg: "expression has no address"
   file: "tvarres2.nim"
   line: 11
-  errormsg: "expression has no address"
 """
 
 var
@@ -13,4 +13,3 @@ proc p(): var int =
 p() = 45
 
 echo g
-
diff --git a/tests/varres/tvarres_via_forwarding.nim b/tests/varres/tvarres_via_forwarding.nim
index 8fd3dfcfd..fb7201ad2 100644
--- a/tests/varres/tvarres_via_forwarding.nim
+++ b/tests/varres/tvarres_via_forwarding.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 10
   errormsg: "'y' escapes its stack frame; context: 'forward(y)'"
+  line: 10
 """
 
 proc forward(x: var int): var int = result = x
diff --git a/tests/varres/tvartup.nim b/tests/varres/tvartup.nim
index 1957a3e35..a8f15b232 100644
--- a/tests/varres/tvartup.nim
+++ b/tests/varres/tvartup.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tvartup.nim"
   output: "2 3"
 """
 # Test the new tuple unpacking
@@ -9,5 +8,3 @@ proc divmod(a, b: int): tuple[di, mo: int] =
 
 var (x, y) = divmod(15, 6)
 echo x, " ", y
-
-#OUT 2 3
diff --git a/tests/varres/twrong_parameter.nim b/tests/varres/twrong_parameter.nim
index 8a363dd19..58d01fd7e 100644
--- a/tests/varres/twrong_parameter.nim
+++ b/tests/varres/twrong_parameter.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 10
   errormsg: "'x' is not the first parameter; context: 'x.field[0]'"
+  line: 10
 """
 
 type
diff --git a/tests/varstmt/tvardecl.nim b/tests/varstmt/tvardecl.nim
index a6b508295..37bc4bad7 100644
--- a/tests/varstmt/tvardecl.nim
+++ b/tests/varstmt/tvardecl.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tvardecl.nim"
   output: "44"
 """
 # Test the new variable declaration syntax
@@ -10,6 +9,4 @@ var
   a, b: int = 4
 
 write(stdout, a)
-write(stdout, b) #OUT 44
-
-
+writeLine(stdout, b) #OUT 44
diff --git a/tests/vm/t2574.nim b/tests/vm/t2574.nim
index 86602aeaf..4332667b4 100644
--- a/tests/vm/t2574.nim
+++ b/tests/vm/t2574.nim
@@ -1,6 +1,6 @@
 discard """
-  line: 14
   errormsg: "cannot call method eval at compile time"
+  line: 14
 """
 
 type
diff --git a/tests/vm/tcastint.nim b/tests/vm/tcastint.nim
index f9d42fc54..437342a74 100644
--- a/tests/vm/tcastint.nim
+++ b/tests/vm/tcastint.nim
@@ -1,5 +1,4 @@
 discard """
-  file: "tcastint.nim"
   output: "OK"
 """
 
@@ -130,7 +129,7 @@ proc test_float_cast =
   doAssert(mantissa == 0, $mantissa)
 
   # construct 2^N float, where N is integer
-  let x = -2'i64 
+  let x = -2'i64
   let xx = (x + exp_bias) shl exp_shift
   let xf = cast[float](xx)
   doAssert(xf == 0.25, $xf)
@@ -151,7 +150,7 @@ proc test_float32_cast =
   doAssert(mantissa == 0, $mantissa)
 
   # construct 2^N float32 where N is integer
-  let x = 4'i32  
+  let x = 4'i32
   let xx = (x + exp_bias) shl exp_shift
   let xf = cast[float32](xx)
   doAssert(xf == 16.0'f32, $xf)
diff --git a/tests/vm/tconstobj.nim b/tests/vm/tconstobj.nim
index 38fcdd844..021fcb728 100644
--- a/tests/vm/tconstobj.nim
+++ b/tests/vm/tconstobj.nim
@@ -1,10 +1,12 @@
 discard """
-  output: '''(name: "hello")
-(-1, 0)'''
+  output: '''
+(name: "hello")
+(-1, 0)
+(FirstName: "James", LastName: "Franco")
+'''
 """
 
 # bug #2774, bug #3195
-
 type Foo = object
   name: string
 
@@ -14,7 +16,6 @@ const fooArray = [
 
 echo fooArray[0]
 
-
 type
     Position = object
         x, y: int
@@ -34,3 +35,16 @@ const
      ]
 
 echo offset[1]
+
+# bug #1547
+import tables
+
+type Person* = object
+    FirstName*: string
+    LastName*: string
+
+let people = {
+    "001": Person(FirstName: "James", LastName: "Franco")
+}.toTable()
+
+echo people["001"]
diff --git a/tests/vm/tforwardproc.nim b/tests/vm/tforwardproc.nim
index 727ac6641..bcd929f0e 100644
--- a/tests/vm/tforwardproc.nim
+++ b/tests/vm/tforwardproc.nim
@@ -14,4 +14,4 @@ proc initArray(): array[10, int] =
   for f in 0..<10:
     result[f] = 3
 
-when isMainModule: echo repr(someTable)
+when true: echo repr(someTable)
diff --git a/tests/vm/tmitems.nim b/tests/vm/tmitems_vm.nim
index 87835d1cd..87835d1cd 100644
--- a/tests/vm/tmitems.nim
+++ b/tests/vm/tmitems_vm.nim
diff --git a/tests/vm/tsetlen.nim b/tests/vm/tsetlen.nim
new file mode 100644
index 000000000..9fd30f331
--- /dev/null
+++ b/tests/vm/tsetlen.nim
@@ -0,0 +1,30 @@
+type Foo = object
+  index: int
+
+block:
+  proc fun[T]() =
+    var foo: T
+    var n = 10
+
+    var foos: seq[T]
+    foos.setLen n
+
+    n.inc
+    foos.setLen n
+
+    for i in 0 ..< n:
+      let temp = foos[i]
+      when T is object:
+        doAssert temp.index == 0
+      when T is ref object:
+        doAssert temp == nil
+      doAssert temp == foo
+
+  static:
+    fun[Foo]()
+    fun[int]()
+    fun[float]()
+    fun[string]()
+    fun[(int, string)]()
+    fun[ref Foo]()
+    fun[seq[int]]()
diff --git a/tests/vm/tvmmisc.nim b/tests/vm/tvmmisc.nim
index 85de26e39..bd3aa2fcd 100644
--- a/tests/vm/tvmmisc.nim
+++ b/tests/vm/tvmmisc.nim
@@ -70,7 +70,9 @@ block:
 # Tests for VM ops
 block:
   static:
-    assert "vm" in getProjectPath()
+    # for joint test, the project path is different, so I disabled it:
+    when false:
+      assert "vm" in getProjectPath()
 
     let b = getEnv("UNSETENVVAR")
     assert b == ""
diff --git a/tools/kochdocs.nim b/tools/kochdocs.nim
index 7cd13b2ac..03a694449 100644
--- a/tools/kochdocs.nim
+++ b/tools/kochdocs.nim
@@ -129,6 +129,7 @@ lib/pure/math.nim
 lib/pure/matchers.nim
 lib/std/editdistance.nim
 lib/std/wordwrap.nim
+lib/std/diff.nim
 lib/pure/algorithm.nim
 lib/pure/stats.nim
 lib/windows/winlean.nim