summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/ast.nim3
-rw-r--r--compiler/ccgmerge.nim4
-rw-r--r--compiler/ccgutils.nim2
-rw-r--r--compiler/cgen.nim4
-rw-r--r--compiler/cgendata.nim2
-rw-r--r--compiler/cgmeth.nim2
-rw-r--r--compiler/closureiters.nim4
-rw-r--r--compiler/commands.nim2
-rw-r--r--compiler/condsyms.nim2
-rw-r--r--compiler/depends.nim3
-rw-r--r--compiler/dfa.nim2
-rw-r--r--compiler/docgen.nim2
-rw-r--r--compiler/docgen2.nim3
-rw-r--r--compiler/evaltempl.nim3
-rw-r--r--compiler/filter_tmpl.nim4
-rw-r--r--compiler/filters.nim2
-rw-r--r--compiler/gorgeimpl.nim2
-rw-r--r--compiler/idents.nim2
-rw-r--r--compiler/idgen.nim2
-rw-r--r--compiler/importer.nim4
-rw-r--r--compiler/incremental.nim4
-rw-r--r--compiler/injectdestructors.nim2
-rw-r--r--compiler/jsgen.nim8
-rw-r--r--compiler/lambdalifting.nim2
-rw-r--r--compiler/liftdestructors.nim2
-rw-r--r--compiler/liftlocals.nim2
-rw-r--r--compiler/linter.nim6
-rw-r--r--compiler/llstream.nim2
-rw-r--r--compiler/lookups.nim2
-rw-r--r--compiler/lowerings.nim1
-rw-r--r--compiler/macrocacheimpl.nim2
-rw-r--r--compiler/magicsys.nim2
-rw-r--r--compiler/main.nim10
-rw-r--r--compiler/modulepaths.nim2
-rw-r--r--compiler/modules.nim4
-rw-r--r--compiler/msgs.nim2
-rw-r--r--compiler/nim.nim6
-rw-r--r--compiler/nimconf.nim2
-rw-r--r--compiler/nimfix/prettybase.nim2
-rw-r--r--compiler/nimsets.nim3
-rw-r--r--compiler/options.nim2
-rw-r--r--compiler/parampatterns.nim2
-rw-r--r--compiler/parser.nim2
-rw-r--r--compiler/passaux.nim2
-rw-r--r--compiler/passes.nim6
-rw-r--r--compiler/pathutils.nim2
-rw-r--r--compiler/patterns.nim3
-rw-r--r--compiler/plugins/itersgen.nim4
-rw-r--r--compiler/plugins/locals.nim2
-rw-r--r--compiler/reorder.nim4
-rw-r--r--compiler/rod.nim2
-rw-r--r--compiler/scriptconfig.nim7
-rw-r--r--compiler/sem.nim8
-rw-r--r--compiler/semdata.nim7
-rw-r--r--compiler/semfold.nim4
-rw-r--r--compiler/semmacrosanity.nim2
-rw-r--r--compiler/sempass2.nim2
-rw-r--r--compiler/sighashes.nim2
-rw-r--r--compiler/sigmatch.nim2
-rw-r--r--compiler/spawn.nim856
-rw-r--r--compiler/suggest.nim4
-rw-r--r--compiler/syntaxes.nim2
-rw-r--r--compiler/transf.nim4
-rw-r--r--compiler/trees.nim2
-rw-r--r--compiler/typesrenderer.nim2
-rw-r--r--compiler/vm.nim2
-rw-r--r--compiler/vmdef.nim3
-rw-r--r--compiler/vmdeps.nim2
-rw-r--r--compiler/vmgen.nim6
-rw-r--r--compiler/writetracking.nim3
70 files changed, 525 insertions, 546 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index c8ce0dccb..8d52f12ff 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -10,8 +10,7 @@
 # abstract syntax tree + symbol table
 
 import
-  lineinfos, hashes, nversion, options, strutils, std / sha1, ropes, idents,
-  intsets, idgen
+  lineinfos, hashes, options, ropes, idents, idgen
 
 type
   TCallingConvention* = enum
diff --git a/compiler/ccgmerge.nim b/compiler/ccgmerge.nim
index a0aa1b05d..cdb43f20f 100644
--- a/compiler/ccgmerge.nim
+++ b/compiler/ccgmerge.nim
@@ -11,8 +11,8 @@
 ## is needed for incremental compilation.
 
 import
-  ast, astalgo, ropes, options, strutils, nimlexbase, msgs, cgendata, rodutils,
-  intsets, platform, llstream, tables, sighashes, modulegraphs, pathutils
+  ast, ropes, options, strutils, nimlexbase, cgendata, rodutils,
+  intsets, llstream, tables, modulegraphs, pathutils
 
 # Careful! Section marks need to contain a tabulator so that they cannot
 # be part of C string literals.
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 455012e60..3c7b0510e 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -10,7 +10,7 @@
 # This module declares some helpers for the C code generator.
 
 import
-  ast, astalgo, ropes, hashes, strutils, types, msgs, wordrecg,
+  ast, hashes, strutils, msgs, wordrecg,
   platform, trees, options
 
 proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 4f136d9e3..d2ddd4a39 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -11,9 +11,9 @@
 
 import
   ast, astalgo, hashes, trees, platform, magicsys, extccomp, options, intsets,
-  nversion, nimsets, msgs, std / sha1, bitsets, idents, types,
+  nversion, nimsets, msgs, bitsets, idents, types,
   ccgutils, os, ropes, math, passes, wordrecg, treetab, cgmeth,
-  condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
+  condsyms, rodutils, renderer, cgendata, ccgmerge, aliases,
   lowerings, tables, sets, ndi, lineinfos, pathutils, transf, enumtostr
 
 when not defined(leanCompiler):
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 76c64782c..77445639e 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -10,7 +10,7 @@
 ## This module contains the data structures for the C code generation phase.
 
 import
-  ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
+  ast, ropes, passes, options, intsets,
   tables, ndi, lineinfos, pathutils, modulegraphs
 
 type
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index ab406bc4b..d83ca3c55 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -10,7 +10,7 @@
 ## This module implements code generation for multi methods.
 
 import
-  intsets, options, ast, astalgo, msgs, idents, renderer, types, magicsys,
+  intsets, options, ast, msgs, idents, renderer, types, magicsys,
   sempass2, strutils, modulegraphs, lineinfos
 
 proc genConv(n: PNode, d: PType, downcast: bool; conf: ConfigRef): PNode =
diff --git a/compiler/closureiters.nim b/compiler/closureiters.nim
index d1f2a6cd6..22595b772 100644
--- a/compiler/closureiters.nim
+++ b/compiler/closureiters.nim
@@ -131,8 +131,8 @@
 #   break :stateLoop
 
 import
-  intsets, strutils, options, ast, astalgo, trees, treetab, msgs, idents,
-  renderer, types, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
+  ast, msgs, idents,
+  renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos
 
 type
   Ctx = object
diff --git a/compiler/commands.nim b/compiler/commands.nim
index ff76fff71..ed0320a7c 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -27,7 +27,7 @@ bootSwitch(usedNoGC, defined(nogc), "--gc:none")
 
 import
   os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
-  wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils, lineinfos,
+  wordrecg, parseutils, nimblecmd, parseopt, sequtils, lineinfos,
   pathutils, strtabs
 
 # but some have deps to imported modules. Yay.
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index ed95c8183..ce295c8b9 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -10,7 +10,7 @@
 # This module handles the conditional symbols.
 
 import
-  strtabs, platform, strutils, idents
+  strtabs
 
 from options import Feature
 from lineinfos import HintsToStr, WarningsToStr
diff --git a/compiler/depends.nim b/compiler/depends.nim
index 300ab3b54..603f67e77 100644
--- a/compiler/depends.nim
+++ b/compiler/depends.nim
@@ -10,8 +10,7 @@
 # This module implements a dependency file generator.
 
 import
-  os, options, ast, astalgo, msgs, ropes, idents, passes, modulepaths,
-  pathutils
+  options, ast, ropes, idents, passes, modulepaths, pathutils
 
 from modulegraphs import ModuleGraph, PPassContext
 
diff --git a/compiler/dfa.nim b/compiler/dfa.nim
index f97d8f298..7315e74bc 100644
--- a/compiler/dfa.nim
+++ b/compiler/dfa.nim
@@ -29,7 +29,7 @@
 ## "A Graph–Free Approach to Data–Flow Analysis" by Markus Mohnen.
 ## https://link.springer.com/content/pdf/10.1007/3-540-45937-5_6.pdf
 
-import ast, astalgo, types, intsets, tables, msgs, options, lineinfos, renderer
+import ast, types, intsets, lineinfos, renderer
 
 from patterns import sameTrees
 
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index a98360c07..2e03c0d4d 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -16,7 +16,7 @@ import
   wordrecg, syntaxes, renderer, lexer, packages/docutils/rstast,
   packages/docutils/rst, packages/docutils/rstgen,
   packages/docutils/highlite, json, xmltree, cgi, trees, types,
-  typesrenderer, astalgo, modulepaths, lineinfos, sequtils, intsets,
+  typesrenderer, astalgo, modulepaths, lineinfos, intsets,
   pathutils, trees
 
 const
diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim
index 048860423..e19b3a989 100644
--- a/compiler/docgen2.nim
+++ b/compiler/docgen2.nim
@@ -11,8 +11,7 @@
 # semantic checking.
 
 import
-  os, options, ast, astalgo, msgs, ropes, idents, passes, docgen, lineinfos,
-  pathutils
+  options, ast, msgs, idents, passes, docgen, lineinfos, pathutils
 
 from modulegraphs import ModuleGraph, PPassContext
 
diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim
index 8acb85907..d3d3e5f77 100644
--- a/compiler/evaltempl.nim
+++ b/compiler/evaltempl.nim
@@ -10,8 +10,7 @@
 ## Template evaluation engine. Now hygienic.
 
 import
-  strutils, options, ast, astalgo, msgs, os, idents, wordrecg, renderer,
-  lineinfos
+  strutils, options, ast, astalgo, msgs, renderer, lineinfos
 
 type
   TemplCtx = object
diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim
index b884b1ec3..490c184cf 100644
--- a/compiler/filter_tmpl.nim
+++ b/compiler/filter_tmpl.nim
@@ -10,8 +10,8 @@
 # This module implements Nim's standard template filter.
 
 import
-  llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
-  renderer, filters, lineinfos, pathutils
+  llstream, strutils, ast, msgs, options,
+  filters, lineinfos, pathutils
 
 type
   TParseState = enum
diff --git a/compiler/filters.nim b/compiler/filters.nim
index c04d61320..a2f7b6bbb 100644
--- a/compiler/filters.nim
+++ b/compiler/filters.nim
@@ -10,7 +10,7 @@
 # This module implements Nim's simple filters and helpers for filters.
 
 import
-  llstream, os, wordrecg, idents, strutils, ast, astalgo, msgs, options,
+  llstream, idents, strutils, ast, msgs, options,
   renderer, pathutils
 
 proc invalidPragma(conf: ConfigRef; n: PNode) =
diff --git a/compiler/gorgeimpl.nim b/compiler/gorgeimpl.nim
index d61dcdac3..c9f82b505 100644
--- a/compiler/gorgeimpl.nim
+++ b/compiler/gorgeimpl.nim
@@ -9,7 +9,7 @@
 
 ## Module that implements ``gorge`` for the compiler.
 
-import msgs, std / sha1, os, osproc, streams, strutils, options,
+import msgs, std / sha1, os, osproc, streams, options,
   lineinfos, pathutils
 
 proc readOutput(p: Process): (string, int) =
diff --git a/compiler/idents.nim b/compiler/idents.nim
index f82ff5db5..3153745d5 100644
--- a/compiler/idents.nim
+++ b/compiler/idents.nim
@@ -12,7 +12,7 @@
 # id. This module is essential for the compiler's performance.
 
 import
-  hashes, strutils, wordrecg
+  hashes, wordrecg
 
 type
   TIdObj* = object of RootObj
diff --git a/compiler/idgen.nim b/compiler/idgen.nim
index 239df0c57..7d49e33e3 100644
--- a/compiler/idgen.nim
+++ b/compiler/idgen.nim
@@ -9,7 +9,7 @@
 
 ## This module contains a simple persistent id generator.
 
-import idents, strutils, os, options, pathutils
+import idents, strutils, options, pathutils
 
 var gFrontEndId*: int
 
diff --git a/compiler/importer.nim b/compiler/importer.nim
index ec065a1ec..2a5a1ac7c 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -10,8 +10,8 @@
 ## This module implements the symbol importing mechanism.
 
 import
-  intsets, strutils, os, ast, astalgo, msgs, options, idents, lookups,
-  semdata, passes, renderer, modulepaths, sigmatch, lineinfos
+  intsets, ast, astalgo, msgs, options, idents, lookups,
+  semdata, modulepaths, sigmatch, lineinfos
 
 proc readExceptSet*(c: PContext, n: PNode): IntSet =
   assert n.kind in {nkImportExceptStmt, nkExportExceptStmt}
diff --git a/compiler/incremental.nim b/compiler/incremental.nim
index f66a75efd..29528bbd3 100644
--- a/compiler/incremental.nim
+++ b/compiler/incremental.nim
@@ -12,10 +12,10 @@
 
 const nimIncremental* = defined(nimIncremental)
 
-import options, lineinfos, pathutils
+import options, lineinfos
 
 when nimIncremental:
-  import ast, msgs, intsets, btrees, db_sqlite, std / sha1
+  import ast, msgs, intsets, btrees, db_sqlite, std / sha1, pathutils
   from strutils import parseInt
 
   type
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index a8a2cf97f..6f1da37fb 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -134,7 +134,7 @@ to do it.
 ]#
 
 import
-  intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
+  intsets, ast, msgs, renderer, magicsys, types, idents,
   strutils, options, dfa, lowerings, tables, modulegraphs, msgs,
   lineinfos, parampatterns, sighashes
 
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 0c04b339c..788e3e75b 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -29,11 +29,11 @@ implements the required case distinction.
 
 
 import
-  ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options,
-  nversion, nimsets, msgs, std / sha1, bitsets, idents, types, os, tables,
-  times, ropes, math, passes, ccgutils, wordrecg, renderer,
+  ast, strutils, trees, magicsys, options,
+  nversion, msgs, idents, types, tables,
+  ropes, math, passes, ccgutils, wordrecg, renderer,
   intsets, cgmeth, lowerings, sighashes, modulegraphs, lineinfos, rodutils,
-  pathutils, transf
+  transf
 
 
 from modulegraphs import ModuleGraph, PPassContext
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 6d87444ec..679391224 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -10,7 +10,7 @@
 # This file implements lambda lifting for the transformator.
 
 import
-  intsets, strutils, options, ast, astalgo, trees, treetab, msgs,
+  intsets, strutils, options, ast, astalgo, msgs,
   idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos,
   transf, liftdestructors
 
diff --git a/compiler/liftdestructors.nim b/compiler/liftdestructors.nim
index 97c2636ac..5619350ef 100644
--- a/compiler/liftdestructors.nim
+++ b/compiler/liftdestructors.nim
@@ -13,7 +13,7 @@
 # Todo:
 # - use openArray instead of array to avoid over-specializations
 
-import modulegraphs, lineinfos, idents, ast, astalgo, renderer, semdata,
+import modulegraphs, lineinfos, idents, ast, renderer, semdata,
   sighashes, lowerings, options, types, msgs, magicsys, tables
 
 type
diff --git a/compiler/liftlocals.nim b/compiler/liftlocals.nim
index ae789cd88..eed0560ab 100644
--- a/compiler/liftlocals.nim
+++ b/compiler/liftlocals.nim
@@ -10,7 +10,7 @@
 ## This module implements the '.liftLocals' pragma.
 
 import
-  intsets, strutils, options, ast, astalgo, msgs,
+  strutils, options, ast, msgs,
   idents, renderer, types, lowerings, lineinfos
 
 from pragmas import getPragmaVal
diff --git a/compiler/linter.nim b/compiler/linter.nim
index abefe9bec..d3c461b66 100644
--- a/compiler/linter.nim
+++ b/compiler/linter.nim
@@ -9,11 +9,9 @@
 
 ## This module implements the style checker.
 
-import
-  strutils, os, intsets, strtabs
+import strutils
 
-import options, ast, astalgo, msgs, semdata, ropes, idents,
-  lineinfos, pathutils, wordrecg
+import options, ast, msgs, idents, lineinfos, wordrecg
 
 const
   Letters* = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '_'}
diff --git a/compiler/llstream.nim b/compiler/llstream.nim
index 9cbca4c4b..ab4e1645c 100644
--- a/compiler/llstream.nim
+++ b/compiler/llstream.nim
@@ -10,7 +10,7 @@
 ## Low-level streams for high performance.
 
 import
-  strutils, pathutils
+  pathutils
 
 # support '-d:useGnuReadline' for backwards compatibility:
 when not defined(windows) and (defined(useGnuReadline) or defined(useLinenoise)):
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 7c37817fd..4de1fc371 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -11,7 +11,7 @@
 
 import
   intsets, ast, astalgo, idents, semdata, types, msgs, options,
-  renderer, wordrecg, idgen, nimfix/prettybase, lineinfos, strutils
+  renderer, nimfix/prettybase, lineinfos, strutils
 
 proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope)
 
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 0030f1a49..727b88760 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -14,7 +14,6 @@ const
 
 import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs,
   lineinfos
-from trees import getMagic
 
 proc newDeref*(n: PNode): PNode {.inline.} =
   result = newNodeIT(nkHiddenDeref, n.info, n.typ.sons[0])
diff --git a/compiler/macrocacheimpl.nim b/compiler/macrocacheimpl.nim
index d23040763..365497e31 100644
--- a/compiler/macrocacheimpl.nim
+++ b/compiler/macrocacheimpl.nim
@@ -9,7 +9,7 @@
 
 ## This module implements helpers for the macro cache.
 
-import lineinfos, ast, modulegraphs, vmdef, magicsys
+import lineinfos, ast, modulegraphs, vmdef
 
 proc recordInc*(c: PCtx; info: TLineInfo; key: string; by: BiggestInt) =
   var recorded = newNodeI(nkCommentStmt, info)
diff --git a/compiler/magicsys.nim b/compiler/magicsys.nim
index aeeb489c0..38240061f 100644
--- a/compiler/magicsys.nim
+++ b/compiler/magicsys.nim
@@ -10,7 +10,7 @@
 # Built-in types and compilerprocs are registered here.
 
 import
-  ast, astalgo, hashes, msgs, platform, nversion, times, idents,
+  ast, astalgo, msgs, platform, idents,
   modulegraphs, lineinfos
 
 export createMagic
diff --git a/compiler/main.nim b/compiler/main.nim
index 460fd90c7..ce80af36d 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -13,12 +13,12 @@ when not defined(nimcore):
   {.error: "nimcore MUST be defined for Nim's core tooling".}
 
 import
-  llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
-  os, condsyms, times,
-  wordrecg, sem, semdata, idents, passes, extccomp,
+  llstream, strutils, ast, lexer, syntaxes, options, msgs,
+  condsyms, times,
+  sem, idents, passes, extccomp,
   cgen, json, nversion,
-  platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
-  parser, modules, ccgutils, sigmatch, ropes,
+  platform, nimconf, passaux, depends, vm, idgen,
+  parser, modules,
   modulegraphs, tables, rod, lineinfos, pathutils
 
 when not defined(leanCompiler):
diff --git a/compiler/modulepaths.nim b/compiler/modulepaths.nim
index 6130c3032..eedb22084 100644
--- a/compiler/modulepaths.nim
+++ b/compiler/modulepaths.nim
@@ -8,7 +8,7 @@
 #
 
 import ast, renderer, strutils, msgs, options, idents, os, lineinfos,
-  pathutils, nimblecmd
+  pathutils
 
 when false:
   const
diff --git a/compiler/modules.nim b/compiler/modules.nim
index 3dbc1b2c1..40d9a904c 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -10,8 +10,8 @@
 ## Implements the module handling, including the caching of modules.
 
 import
-  ast, astalgo, magicsys, std / sha1, msgs, cgendata, sigmatch, options,
-  idents, os, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod,
+  ast, astalgo, magicsys, msgs, options,
+  idents, lexer, idgen, passes, syntaxes, llstream, modulegraphs, rod,
   lineinfos, pathutils, tables
 
 proc resetSystemArtifacts*(g: ModuleGraph) =
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 03b6213fa..1264133a9 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -8,7 +8,7 @@
 #
 
 import
-  options, strutils, os, tables, ropes, platform, terminal, macros,
+  options, strutils, os, tables, ropes, terminal, macros,
   lineinfos, pathutils
 
 proc toCChar*(c: char; result: var string) =
diff --git a/compiler/nim.nim b/compiler/nim.nim
index 5fcf043b5..ec7e8b8dc 100644
--- a/compiler/nim.nim
+++ b/compiler/nim.nim
@@ -19,9 +19,9 @@ when defined(i386) and defined(windows) and defined(vcc):
   {.link: "../icons/nim-i386-windows-vcc.res".}
 
 import
-  commands, lexer, condsyms, options, msgs, nversion, nimconf, ropes,
-  extccomp, strutils, os, osproc, platform, main, parseopt,
-  scriptconfig, idents, modulegraphs, lineinfos, cmdlinehelper,
+  commands, options, msgs,
+  extccomp, strutils, os, main, parseopt,
+  idents, lineinfos, cmdlinehelper,
   pathutils
 
 include nodejs
diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim
index f518b3abf..a470179bd 100644
--- a/compiler/nimconf.nim
+++ b/compiler/nimconf.nim
@@ -10,7 +10,7 @@
 # This module handles the reading of the config file.
 
 import
-  llstream, nversion, commands, os, strutils, msgs, platform, condsyms, lexer,
+  llstream, commands, os, strutils, msgs, lexer,
   options, idents, wordrecg, strtabs, lineinfos, pathutils
 
 # ---------------- configuration file parser -----------------------------
diff --git a/compiler/nimfix/prettybase.nim b/compiler/nimfix/prettybase.nim
index c3e16e5ba..fbc2e3bd1 100644
--- a/compiler/nimfix/prettybase.nim
+++ b/compiler/nimfix/prettybase.nim
@@ -8,9 +8,7 @@
 #
 
 import strutils except Letters
-import lexbase, streams
 import ".." / [ast, msgs, lineinfos, idents, options, linter]
-from os import splitFile
 
 proc replaceDeprecated*(conf: ConfigRef; info: TLineInfo; oldSym, newSym: PIdent) =
   let line = sourceLine(conf, info)
diff --git a/compiler/nimsets.nim b/compiler/nimsets.nim
index c2436dff0..f4ef0cc39 100644
--- a/compiler/nimsets.nim
+++ b/compiler/nimsets.nim
@@ -10,8 +10,7 @@
 # this unit handles Nim sets; it implements symbolic sets
 
 import
-  ast, astalgo, trees, nversion, lineinfos, platform, bitsets, types, renderer,
-  options
+  ast, astalgo, lineinfos, bitsets, types, options
 
 proc inSet*(s: PNode, elem: PNode): bool =
   assert s.kind == nkCurly
diff --git a/compiler/options.nim b/compiler/options.nim
index 985955d98..6303224a2 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -8,7 +8,7 @@
 #
 
 import
-  os, strutils, strtabs, osproc, sets, lineinfos, platform,
+  os, strutils, strtabs, sets, lineinfos, platform,
   prefixmatches, pathutils
 
 from terminal import isatty
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index b4409fcec..1bd703fe8 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -10,7 +10,7 @@
 ## This module implements the pattern matching features for term rewriting
 ## macro support.
 
-import strutils, ast, astalgo, types, msgs, idents, renderer, wordrecg, trees,
+import strutils, ast, types, msgs, idents, renderer, wordrecg, trees,
   options
 
 # we precompile the pattern here for efficiency into some internal
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 12036f20b..74d633814 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -27,7 +27,7 @@ when isMainModule:
   outp.close
 
 import
-  llstream, lexer, idents, strutils, ast, astalgo, msgs, options, lineinfos,
+  llstream, lexer, idents, strutils, ast, msgs, options, lineinfos,
   pathutils
 
 when defined(nimpretty):
diff --git a/compiler/passaux.nim b/compiler/passaux.nim
index 17c4c506a..2ac89c24e 100644
--- a/compiler/passaux.nim
+++ b/compiler/passaux.nim
@@ -10,7 +10,7 @@
 ## implements some little helper passes
 
 import
-  strutils, ast, astalgo, passes, idents, msgs, options, idgen, lineinfos
+  ast, passes, idents, msgs, options, idgen, lineinfos
 
 from modulegraphs import ModuleGraph, PPassContext
 
diff --git a/compiler/passes.nim b/compiler/passes.nim
index 72140d9de..7effcfeb5 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -11,9 +11,9 @@
 ## `TPass` interface.
 
 import
-  strutils, options, ast, astalgo, llstream, msgs, platform, os,
-  condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
-  nimsets, syntaxes, times, idgen, modulegraphs, reorder, rod,
+  options, ast, llstream, msgs,
+  idents,
+  syntaxes, idgen, modulegraphs, reorder, rod,
   lineinfos, pathutils
 
 type
diff --git a/compiler/pathutils.nim b/compiler/pathutils.nim
index cd6fb2a53..b73942a21 100644
--- a/compiler/pathutils.nim
+++ b/compiler/pathutils.nim
@@ -10,7 +10,7 @@
 ## Path handling utilities for Nim. Strictly typed code in order
 ## to avoid the never ending time sink in getting path handling right.
 
-import os, strutils, pathnorm
+import os, pathnorm
 
 type
   AbsoluteFile* = distinct string
diff --git a/compiler/patterns.nim b/compiler/patterns.nim
index d9a6e7d1d..e20c42b66 100644
--- a/compiler/patterns.nim
+++ b/compiler/patterns.nim
@@ -11,8 +11,7 @@
 ## macro support.
 
 import
-  ast, astalgo, types, semdata, sigmatch, msgs, idents, aliases, parampatterns,
-  trees
+  ast, types, semdata, sigmatch, idents, aliases, parampatterns, trees
 
 type
   TPatternContext = object
diff --git a/compiler/plugins/itersgen.nim b/compiler/plugins/itersgen.nim
index 440d2e081..e4b3a5029 100644
--- a/compiler/plugins/itersgen.nim
+++ b/compiler/plugins/itersgen.nim
@@ -9,9 +9,7 @@
 
 ## Plugin to transform an inline iterator into a data structure.
 
-import ".." / [ast, astalgo,
-  magicsys, lookups, semdata,
-  lambdalifting, msgs]
+import ".." / [ast, lookups, semdata, lambdalifting, msgs]
 
 proc iterToProcImpl*(c: PContext, n: PNode): PNode =
   result = newNodeI(nkStmtList, n.info)
diff --git a/compiler/plugins/locals.nim b/compiler/plugins/locals.nim
index eb3324b36..08d836f7d 100644
--- a/compiler/plugins/locals.nim
+++ b/compiler/plugins/locals.nim
@@ -9,7 +9,7 @@
 
 ## The builtin 'system.locals' implemented as a plugin.
 
-import ".." / [pluginsupport, ast, astalgo,
+import ".." / [ast, astalgo,
   magicsys, lookups, semdata, lowerings]
 
 proc semLocals*(c: PContext, n: PNode): PNode =
diff --git a/compiler/reorder.nim b/compiler/reorder.nim
index e341885ee..960929811 100644
--- a/compiler/reorder.nim
+++ b/compiler/reorder.nim
@@ -1,7 +1,7 @@
 
 import
-  intsets, ast, idents, algorithm, renderer, parser, os, strutils,
-  sequtils, msgs, modulegraphs, syntaxes, options, modulepaths, tables,
+  intsets, ast, idents, algorithm, renderer, os, strutils,
+  msgs, modulegraphs, syntaxes, options, modulepaths,
   lineinfos
 
 type
diff --git a/compiler/rod.nim b/compiler/rod.nim
index bbd2f0c6c..e3e568a0e 100644
--- a/compiler/rod.nim
+++ b/compiler/rod.nim
@@ -9,7 +9,7 @@
 
 ## This module implements the canonalization for the various caching mechanisms.
 
-import ast, idgen, lineinfos, msgs, incremental, modulegraphs, pathutils
+import ast, idgen, lineinfos, incremental, modulegraphs, pathutils
 
 when not nimIncremental:
   template setupModuleCache*(g: ModuleGraph) = discard
diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim
index 6c3d0a122..9878cf597 100644
--- a/compiler/scriptconfig.nim
+++ b/compiler/scriptconfig.nim
@@ -11,9 +11,10 @@
 ## language.
 
 import
-  ast, modules, idents, passes, passaux, condsyms,
-  options, nimconf, sem, semdata, llstream, vm, vmdef, commands, msgs,
-  os, times, osproc, wordrecg, strtabs, modulegraphs, lineinfos, pathutils
+  ast, modules, idents, passes, condsyms,
+  options, sem, llstream, vm, vmdef, commands, msgs,
+  os, times, osproc, wordrecg, strtabs, modulegraphs,
+  lineinfos, pathutils
 
 # we support 'cmpIgnoreStyle' natively for efficiency:
 from strutils import cmpIgnoreStyle, contains
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 95c22e549..fa0f742f7 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -10,13 +10,13 @@
 # This module implements the semantic checking pass.
 
 import
-  ast, strutils, hashes, options, lexer, astalgo, trees, treetab,
-  wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
-  magicsys, parser, nversion, nimsets, semfold, modulepaths, importer,
+  ast, strutils, options, astalgo, trees,
+  wordrecg, ropes, msgs, idents, renderer, types, platform, math,
+  magicsys, nversion, nimsets, semfold, modulepaths, importer,
   procfind, lookups, pragmas, passes, semdata, semtypinst, sigmatch,
   intsets, transf, vmdef, vm, idgen, aliases, cgmeth, lambdalifting,
   evaltempl, patterns, parampatterns, sempass2, linter, semmacrosanity,
-  lowerings, pluginsupport, plugins/active, rod, lineinfos, strtabs, int128
+  lowerings, plugins/active, rod, lineinfos, strtabs, int128
 
 from modulegraphs import ModuleGraph, PPassContext, onUse, onDef, onDefResolveForward
 
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index e411633c2..6c7dd02ed 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -10,11 +10,8 @@
 ## This module contains the data structures for the semantic checking phase.
 
 import
-  strutils, intsets, options, lexer, ast, astalgo, trees, treetab,
-  wordrecg,
-  ropes, msgs, platform, os, condsyms, idents, renderer, types, extccomp, math,
-  magicsys, nversion, nimsets, parser, times, passes, vmdef,
-  modulegraphs, lineinfos
+  intsets, options, ast, astalgo, msgs, idents, renderer,
+  magicsys, passes, vmdef, modulegraphs, lineinfos
 
 type
   TOptionEntry* = object      # entries to put on a stack for pragma parsing
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 2f07940c8..c7efa1a87 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -11,8 +11,8 @@
 # and evaluation phase
 
 import
-  strutils, options, ast, astalgo, trees, treetab, nimsets,
-  nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
+  strutils, options, ast, trees, nimsets,
+  platform, math, msgs, idents, renderer, types,
   commands, magicsys, modulegraphs, strtabs, lineinfos
 
 proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
diff --git a/compiler/semmacrosanity.nim b/compiler/semmacrosanity.nim
index faf3e3868..af740e518 100644
--- a/compiler/semmacrosanity.nim
+++ b/compiler/semmacrosanity.nim
@@ -10,7 +10,7 @@
 ## Implements type sanity checking for ASTs resulting from macros. Lots of
 ## room for improvement here.
 
-import ast, astalgo, msgs, types, options
+import ast, msgs, types, options
 
 proc ithField(n: PNode, field: var int): PSym =
   result = nil
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 0e1c9cb07..8252a7857 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -10,7 +10,7 @@
 import
   intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
   wordrecg, strutils, options, guards, lineinfos, semfold, semdata,
-  modulegraphs, lowerings, sigmatch, tables
+  modulegraphs
 
 when not defined(leanCompiler):
   import writetracking
diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim
index c69797391..a9d911e27 100644
--- a/compiler/sighashes.nim
+++ b/compiler/sighashes.nim
@@ -11,9 +11,7 @@
 
 import ast, tables, ropes, md5, modulegraphs
 from hashes import Hash
-from astalgo import debug
 import types
-from strutils import startsWith, contains
 
 proc `&=`(c: var MD5Context, s: string) = md5Update(c, s, s.len)
 proc `&=`(c: var MD5Context, ch: char) = md5Update(c, unsafeAddr ch, 1)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 9f24dd3c2..b331b6f1f 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -12,7 +12,7 @@
 
 import
   intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
-  magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees,
+  magicsys, idents, lexer, options, parampatterns, strutils, trees,
   linter, lineinfos, lowerings, modulegraphs
 
 when (defined(booting) or defined(nimsuggest)) and not defined(leanCompiler):
diff --git a/compiler/spawn.nim b/compiler/spawn.nim
index b8477567b..733ce7732 100644
--- a/compiler/spawn.nim
+++ b/compiler/spawn.nim
@@ -1,428 +1,428 @@
-#

-#

-#           The Nim Compiler

-#        (c) Copyright 2015 Andreas Rumpf

-#

-#    See the file "copying.txt", included in this

-#    distribution, for details about the copyright.

-#

-

-## This module implements threadpool's ``spawn``.

-

-import ast, astalgo, types, idents, magicsys, msgs, options, modulegraphs,

-  lineinfos, lowerings

-from trees import getMagic

-

-proc callProc(a: PNode): PNode =

-  result = newNodeI(nkCall, a.info)

-  result.add a

-  result.typ = a.typ.sons[0]

-

-# we have 4 cases to consider:

-# - a void proc --> nothing to do

-# - a proc returning GC'ed memory --> requires a flowVar

-# - a proc returning non GC'ed memory --> pass as hidden 'var' parameter

-# - not in a parallel environment --> requires a flowVar for memory safety

-type

-  TSpawnResult* = enum

-    srVoid, srFlowVar, srByVar

-  TFlowVarKind = enum

-    fvInvalid # invalid type T for 'FlowVar[T]'

-    fvGC      # FlowVar of a GC'ed type

-    fvBlob    # FlowVar of a blob type

-

-proc spawnResult*(t: PType; inParallel: bool): TSpawnResult =

-  if t.isEmptyType: srVoid

-  elif inParallel and not containsGarbageCollectedRef(t): srByVar

-  else: srFlowVar

-

-proc flowVarKind(t: PType): TFlowVarKind =

-  if t.skipTypes(abstractInst).kind in {tyRef, tyString, tySequence}: fvGC

-  elif containsGarbageCollectedRef(t): fvInvalid

-  else: fvBlob

-

-proc typeNeedsNoDeepCopy(t: PType): bool =

-  var t = t.skipTypes(abstractInst)

-  # for the tconvexhull example (and others) we're a bit lax here and pretend

-  # seqs and strings are *by value* only and 'shallow' doesn't exist!

-  if t.kind == tyString: return true

-  # note that seq[T] is fine, but 'var seq[T]' is not, so we need to skip 'var'

-  # for the stricter check and likewise we can skip 'seq' for a less

-  # strict check:

-  if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon

-  result = not containsGarbageCollectedRef(t)

-

-proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType;

-                 v: PNode; useShallowCopy=false): PSym =

-  result = newSym(skTemp, getIdent(g.cache, genPrefix), owner, varSection.info,

-                  owner.options)

-  result.typ = typ

-  incl(result.flags, sfFromGeneric)

-

-  var vpart = newNodeI(nkIdentDefs, varSection.info, 3)

-  vpart.sons[0] = newSymNode(result)

-  vpart.sons[1] = newNodeI(nkEmpty, varSection.info)

-  vpart.sons[2] = if varInit.isNil: v else: vpart[1]

-  varSection.add vpart

-  if varInit != nil:

-    if useShallowCopy and typeNeedsNoDeepCopy(typ):

-      varInit.add newFastAsgnStmt(newSymNode(result), v)

-    else:

-      let deepCopyCall = newNodeI(nkCall, varInit.info, 3)

-      deepCopyCall.sons[0] = newSymNode(getSysMagic(g, varSection.info, "deepCopy", mDeepCopy))

-      deepCopyCall.sons[1] = newSymNode(result)

-      deepCopyCall.sons[2] = v

-      varInit.add deepCopyCall

-

-discard """

-We generate roughly this:

-

-proc f_wrapper(thread, args) =

-  barrierEnter(args.barrier)  # for parallel statement

-  var a = args.a # thread transfer; deepCopy or shallowCopy or no copy

-                 # depending on whether we're in a 'parallel' statement

-  var b = args.b

-  var fv = args.fv

-

-  fv.owner = thread # optional

-  nimArgsPassingDone() # signal parent that the work is done

-  #

-  args.fv.blob = f(a, b, ...)

-  nimFlowVarSignal(args.fv)

-

-  # - or -

-  f(a, b, ...)

-  barrierLeave(args.barrier)  # for parallel statement

-

-stmtList:

-  var scratchObj

-  scratchObj.a = a

-  scratchObj.b = b

-

-  nimSpawn(f_wrapper, addr scratchObj)

-  scratchObj.fv # optional

-

-"""

-

-proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;

-                       varSection, varInit, call, barrier, fv: PNode;

-                       spawnKind: TSpawnResult): PSym =

-  var body = newNodeI(nkStmtList, f.info)

-  body.flags.incl nfTransf # do not transform further

-

-  var threadLocalBarrier: PSym

-  if barrier != nil:

-    var varSection2 = newNodeI(nkVarSection, barrier.info)

-    threadLocalBarrier = addLocalVar(g, varSection2, nil, argsParam.owner,

-                                     barrier.typ, barrier)

-    body.add varSection2

-    body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info,

-      threadLocalBarrier.newSymNode)

-  var threadLocalProm: PSym

-  if spawnKind == srByVar:

-    threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)

-  elif fv != nil:

-    internalAssert g.config, fv.typ.kind == tyGenericInst

-    threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)

-  body.add varSection

-  body.add varInit

-  if fv != nil and spawnKind != srByVar:

-    # generate:

-    #   fv.owner = threadParam

-    body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,

-      "owner", fv.info, g.cache), threadParam.newSymNode)

-

-  body.add callCodegenProc(g, "nimArgsPassingDone", threadParam.info,

-    threadParam.newSymNode)

-  if spawnKind == srByVar:

-    body.add newAsgnStmt(genDeref(threadLocalProm.newSymNode), call)

-  elif fv != nil:

-    let fk = fv.typ.sons[1].flowVarKind

-    if fk == fvInvalid:

-      localError(g.config, f.info, "cannot create a flowVar of type: " &

-        typeToString(fv.typ.sons[1]))

-    body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,

-      if fk == fvGC: "data" else: "blob", fv.info, g.cache), call)

-    if fk == fvGC:

-      let incRefCall = newNodeI(nkCall, fv.info, 2)

-      incRefCall.sons[0] = newSymNode(getSysMagic(g, fv.info, "GCref", mGCref))

-      incRefCall.sons[1] = indirectAccess(threadLocalProm.newSymNode,

-                                          "data", fv.info, g.cache)

-      body.add incRefCall

-    if barrier == nil:

-      # by now 'fv' is shared and thus might have beeen overwritten! we need

-      # to use the thread-local view instead:

-      body.add callCodegenProc(g, "nimFlowVarSignal", threadLocalProm.info,

-        threadLocalProm.newSymNode)

-  else:

-    body.add call

-  if barrier != nil:

-    body.add callCodegenProc(g, "barrierLeave", threadLocalBarrier.info,

-      threadLocalBarrier.newSymNode)

-

-  var params = newNodeI(nkFormalParams, f.info)

-  params.add newNodeI(nkEmpty, f.info)

-  params.add threadParam.newSymNode

-  params.add argsParam.newSymNode

-

-  var t = newType(tyProc, threadParam.owner)

-  t.rawAddSon nil

-  t.rawAddSon threadParam.typ

-  t.rawAddSon argsParam.typ

-  t.n = newNodeI(nkFormalParams, f.info)

-  t.n.add newNodeI(nkEffectList, f.info)

-  t.n.add threadParam.newSymNode

-  t.n.add argsParam.newSymNode

-

-  let name = (if f.kind == nkSym: f.sym.name.s else: genPrefix) & "Wrapper"

-  result = newSym(skProc, getIdent(g.cache, name), argsParam.owner, f.info,

-                  argsParam.options)

-  let emptyNode = newNodeI(nkEmpty, f.info)

-  result.ast = newProcNode(nkProcDef, f.info, body = body,

-      params = params, name = newSymNode(result), pattern = emptyNode,

-      genericParams = emptyNode, pragmas = emptyNode,

-      exceptions = emptyNode)

-  result.typ = t

-

-proc createCastExpr(argsParam: PSym; objType: PType): PNode =

-  result = newNodeI(nkCast, argsParam.info)

-  result.add newNodeI(nkEmpty, argsParam.info)

-  result.add newSymNode(argsParam)

-  result.typ = newType(tyPtr, objType.owner)

-  result.typ.rawAddSon(objType)

-

-proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym,

-                             castExpr, call,

-                             varSection, varInit, result: PNode) =

-  let formals = n[0].typ.n

-  let tmpName = getIdent(g.cache, genPrefix)

-  for i in 1 ..< n.len:

-    # we pick n's type here, which hopefully is 'tyArray' and not

-    # 'tyOpenArray':

-    var argType = n[i].typ.skipTypes(abstractInst)

-    if i < formals.len and formals[i].typ.kind in {tyVar, tyLent}:

-      localError(g.config, n[i].info, "'spawn'ed function cannot have a 'var' parameter")

-    #elif containsTyRef(argType):

-    #  localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")

-

-    let fieldname = if i < formals.len: formals[i].sym.name else: tmpName

-    var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)

-    field.typ = argType

-    objType.addField(field, g.cache)

-    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])

-

-    let temp = addLocalVar(g, varSection, varInit, objType.owner, argType,

-                           indirectAccess(castExpr, field, n.info))

-    call.add(newSymNode(temp))

-

-proc getRoot*(n: PNode): PSym =

-  ## ``getRoot`` takes a *path* ``n``. A path is an lvalue expression

-  ## like ``obj.x[i].y``. The *root* of a path is the symbol that can be

-  ## determined as the owner; ``obj`` in the example.

-  case n.kind

-  of nkSym:

-    if n.sym.kind in {skVar, skResult, skTemp, skLet, skForVar}:

-      result = n.sym

-  of nkDotExpr, nkBracketExpr, nkHiddenDeref, nkDerefExpr,

-      nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:

-    result = getRoot(n.sons[0])

-  of nkHiddenStdConv, nkHiddenSubConv, nkConv:

-    result = getRoot(n.sons[1])

-  of nkCallKinds:

-    if getMagic(n) == mSlice: result = getRoot(n.sons[1])

-  else: discard

-

-proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym;

-                             castExpr, call,

-                             varSection, varInit, result: PNode) =

-  let formals = n[0].typ.n

-  let tmpName = getIdent(g.cache, genPrefix)

-  # we need to copy the foreign scratch object fields into local variables

-  # for correctness: These are called 'threadLocal' here.

-  for i in 1 ..< n.len:

-    let n = n[i]

-    let argType = skipTypes(if i < formals.len: formals[i].typ else: n.typ,

-                            abstractInst)

-    #if containsTyRef(argType):

-    #  localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")

-

-    let fieldname = if i < formals.len: formals[i].sym.name else: tmpName

-    var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)

-

-    if argType.kind in {tyVarargs, tyOpenArray}:

-      # important special case: we always create a zero-copy slice:

-      let slice = newNodeI(nkCall, n.info, 4)

-      slice.typ = n.typ

-      slice.sons[0] = newSymNode(createMagic(g, "slice", mSlice))

-      slice.sons[0].typ = getSysType(g, n.info, tyInt) # fake type

-      var fieldB = newSym(skField, tmpName, objType.owner, n.info, g.config.options)

-      fieldB.typ = getSysType(g, n.info, tyInt)

-      objType.addField(fieldB, g.cache)

-

-      if getMagic(n) == mSlice:

-        let a = genAddrOf(n[1])

-        field.typ = a.typ

-        objType.addField(field, g.cache)

-        result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)

-

-        var fieldA = newSym(skField, tmpName, objType.owner, n.info, g.config.options)

-        fieldA.typ = getSysType(g, n.info, tyInt)

-        objType.addField(fieldA, g.cache)

-        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])

-        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3])

-

-        let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldA.typ,

-                                      indirectAccess(castExpr, fieldA, n.info),

-                                      useShallowCopy=true)

-        slice.sons[2] = threadLocal.newSymNode

-      else:

-        let a = genAddrOf(n)

-        field.typ = a.typ

-        objType.addField(field, g.cache)

-        result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)

-        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(g, n))

-

-        slice.sons[2] = newIntLit(g, n.info, 0)

-      # the array itself does not need to go through a thread local variable:

-      slice.sons[1] = genDeref(indirectAccess(castExpr, field, n.info))

-

-      let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldB.typ,

-                                    indirectAccess(castExpr, fieldB, n.info),

-                                    useShallowCopy=true)

-      slice.sons[3] = threadLocal.newSymNode

-      call.add slice

-    elif (let size = computeSize(g.config, argType); size < 0 or size > 16) and

-        n.getRoot != nil:

-      # it is more efficient to pass a pointer instead:

-      let a = genAddrOf(n)

-      field.typ = a.typ

-      objType.addField(field, g.cache)

-      result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)

-      let threadLocal = addLocalVar(g, varSection,nil, objType.owner, field.typ,

-                                    indirectAccess(castExpr, field, n.info),

-                                    useShallowCopy=true)

-      call.add(genDeref(threadLocal.newSymNode))

-    else:

-      # boring case

-      field.typ = argType

-      objType.addField(field, g.cache)

-      result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n)

-      let threadLocal = addLocalVar(g, varSection, varInit,

-                                    objType.owner, field.typ,

-                                    indirectAccess(castExpr, field, n.info),

-                                    useShallowCopy=true)

-      call.add(threadLocal.newSymNode)

-

-proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: PType;

-                       barrier, dest: PNode = nil): PNode =

-  # if 'barrier' != nil, then it is in a 'parallel' section and we

-  # generate quite different code

-  let n = spawnExpr[^2]

-  let spawnKind = spawnResult(retType, barrier!=nil)

-  case spawnKind

-  of srVoid:

-    internalAssert g.config, dest == nil

-    result = newNodeI(nkStmtList, n.info)

-  of srFlowVar:

-    internalAssert g.config, dest == nil

-    result = newNodeIT(nkStmtListExpr, n.info, retType)

-  of srByVar:

-    if dest == nil: localError(g.config, n.info, "'spawn' must not be discarded")

-    result = newNodeI(nkStmtList, n.info)

-

-  if n.kind notin nkCallKinds:

-    localError(g.config, n.info, "'spawn' takes a call expression")

-    return

-  if optThreadAnalysis in g.config.globalOptions:

-    if {tfThread, tfNoSideEffect} * n[0].typ.flags == {}:

-      localError(g.config, n.info, "'spawn' takes a GC safe call expression")

-  var

-    threadParam = newSym(skParam, getIdent(g.cache, "thread"), owner, n.info, g.config.options)

-    argsParam = newSym(skParam, getIdent(g.cache, "args"), owner, n.info, g.config.options)

-  block:

-    let ptrType = getSysType(g, n.info, tyPointer)

-    threadParam.typ = ptrType

-    argsParam.typ = ptrType

-    argsParam.position = 1

-

-  var objType = createObj(g, owner, n.info)

-  incl(objType.flags, tfFinal)

-  let castExpr = createCastExpr(argsParam, objType)

-

-  var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), owner, n.info, g.config.options)

-  block:

-    scratchObj.typ = objType

-    incl(scratchObj.flags, sfFromGeneric)

-    var varSectionB = newNodeI(nkVarSection, n.info)

-    varSectionB.addVar(scratchObj.newSymNode)

-    result.add varSectionB

-

-  var call = newNodeIT(nkCall, n.info, n.typ)

-  var fn = n.sons[0]

-  # templates and macros are in fact valid here due to the nature of

-  # the transformation:

-  if fn.kind == nkClosure or (fn.typ != nil and fn.typ.callConv == ccClosure):

-    localError(g.config, n.info, "closure in spawn environment is not allowed")

-  if not (fn.kind == nkSym and fn.sym.kind in {skProc, skTemplate, skMacro,

-                                               skFunc, skMethod, skConverter}):

-    # for indirect calls we pass the function pointer in the scratchObj

-    var argType = n[0].typ.skipTypes(abstractInst)

-    var field = newSym(skField, getIdent(g.cache, "fn"), owner, n.info, g.config.options)

-    field.typ = argType

-    objType.addField(field, g.cache)

-    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])

-    fn = indirectAccess(castExpr, field, n.info)

-  elif fn.kind == nkSym and fn.sym.kind == skIterator:

-    localError(g.config, n.info, "iterator in spawn environment is not allowed")

-  elif fn.typ.callConv == ccClosure:

-    localError(g.config, n.info, "closure in spawn environment is not allowed")

-

-  call.add(fn)

-  var varSection = newNodeI(nkVarSection, n.info)

-  var varInit = newNodeI(nkStmtList, n.info)

-  if barrier.isNil:

-    setupArgsForConcurrency(g, n, objType, scratchObj, castExpr, call,

-                            varSection, varInit, result)

-  else:

-    setupArgsForParallelism(g, n, objType, scratchObj, castExpr, call,

-                            varSection, varInit, result)

-

-  var barrierAsExpr: PNode = nil

-  if barrier != nil:

-    let typ = newType(tyPtr, owner)

-    typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ)

-    var field = newSym(skField, getIdent(g.cache, "barrier"), owner, n.info, g.config.options)

-    field.typ = typ

-    objType.addField(field, g.cache)

-    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier)

-    barrierAsExpr = indirectAccess(castExpr, field, n.info)

-

-  var fvField, fvAsExpr: PNode = nil

-  if spawnKind == srFlowVar:

-    var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)

-    field.typ = retType

-    objType.addField(field, g.cache)

-    fvField = newDotExpr(scratchObj, field)

-    fvAsExpr = indirectAccess(castExpr, field, n.info)

-    # create flowVar:

-    result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1]))

-    if barrier == nil:

-      result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info,

-        fvField)

-

-  elif spawnKind == srByVar:

-    var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)

-    field.typ = newType(tyPtr, objType.owner)

-    field.typ.rawAddSon(retType)

-    objType.addField(field, g.cache)

-    fvAsExpr = indirectAccess(castExpr, field, n.info)

-    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest))

-

-  let wrapper = createWrapperProc(g, fn, threadParam, argsParam,

-                                  varSection, varInit, call,

-                                  barrierAsExpr, fvAsExpr, spawnKind)

-  result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapper.info,

-    wrapper.newSymNode, genAddrOf(scratchObj.newSymNode), nil, spawnExpr)

-

-  if spawnKind == srFlowVar: result.add fvField

-

+#
+#
+#           The Nim Compiler
+#        (c) Copyright 2015 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements threadpool's ``spawn``.
+
+import ast, types, idents, magicsys, msgs, options, modulegraphs,
+  lowerings
+from trees import getMagic
+
+proc callProc(a: PNode): PNode =
+  result = newNodeI(nkCall, a.info)
+  result.add a
+  result.typ = a.typ.sons[0]
+
+# we have 4 cases to consider:
+# - a void proc --> nothing to do
+# - a proc returning GC'ed memory --> requires a flowVar
+# - a proc returning non GC'ed memory --> pass as hidden 'var' parameter
+# - not in a parallel environment --> requires a flowVar for memory safety
+type
+  TSpawnResult* = enum
+    srVoid, srFlowVar, srByVar
+  TFlowVarKind = enum
+    fvInvalid # invalid type T for 'FlowVar[T]'
+    fvGC      # FlowVar of a GC'ed type
+    fvBlob    # FlowVar of a blob type
+
+proc spawnResult*(t: PType; inParallel: bool): TSpawnResult =
+  if t.isEmptyType: srVoid
+  elif inParallel and not containsGarbageCollectedRef(t): srByVar
+  else: srFlowVar
+
+proc flowVarKind(t: PType): TFlowVarKind =
+  if t.skipTypes(abstractInst).kind in {tyRef, tyString, tySequence}: fvGC
+  elif containsGarbageCollectedRef(t): fvInvalid
+  else: fvBlob
+
+proc typeNeedsNoDeepCopy(t: PType): bool =
+  var t = t.skipTypes(abstractInst)
+  # for the tconvexhull example (and others) we're a bit lax here and pretend
+  # seqs and strings are *by value* only and 'shallow' doesn't exist!
+  if t.kind == tyString: return true
+  # note that seq[T] is fine, but 'var seq[T]' is not, so we need to skip 'var'
+  # for the stricter check and likewise we can skip 'seq' for a less
+  # strict check:
+  if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon
+  result = not containsGarbageCollectedRef(t)
+
+proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType;
+                 v: PNode; useShallowCopy=false): PSym =
+  result = newSym(skTemp, getIdent(g.cache, genPrefix), owner, varSection.info,
+                  owner.options)
+  result.typ = typ
+  incl(result.flags, sfFromGeneric)
+
+  var vpart = newNodeI(nkIdentDefs, varSection.info, 3)
+  vpart.sons[0] = newSymNode(result)
+  vpart.sons[1] = newNodeI(nkEmpty, varSection.info)
+  vpart.sons[2] = if varInit.isNil: v else: vpart[1]
+  varSection.add vpart
+  if varInit != nil:
+    if useShallowCopy and typeNeedsNoDeepCopy(typ):
+      varInit.add newFastAsgnStmt(newSymNode(result), v)
+    else:
+      let deepCopyCall = newNodeI(nkCall, varInit.info, 3)
+      deepCopyCall.sons[0] = newSymNode(getSysMagic(g, varSection.info, "deepCopy", mDeepCopy))
+      deepCopyCall.sons[1] = newSymNode(result)
+      deepCopyCall.sons[2] = v
+      varInit.add deepCopyCall
+
+discard """
+We generate roughly this:
+
+proc f_wrapper(thread, args) =
+  barrierEnter(args.barrier)  # for parallel statement
+  var a = args.a # thread transfer; deepCopy or shallowCopy or no copy
+                 # depending on whether we're in a 'parallel' statement
+  var b = args.b
+  var fv = args.fv
+
+  fv.owner = thread # optional
+  nimArgsPassingDone() # signal parent that the work is done
+  #
+  args.fv.blob = f(a, b, ...)
+  nimFlowVarSignal(args.fv)
+
+  # - or -
+  f(a, b, ...)
+  barrierLeave(args.barrier)  # for parallel statement
+
+stmtList:
+  var scratchObj
+  scratchObj.a = a
+  scratchObj.b = b
+
+  nimSpawn(f_wrapper, addr scratchObj)
+  scratchObj.fv # optional
+
+"""
+
+proc createWrapperProc(g: ModuleGraph; f: PNode; threadParam, argsParam: PSym;
+                       varSection, varInit, call, barrier, fv: PNode;
+                       spawnKind: TSpawnResult): PSym =
+  var body = newNodeI(nkStmtList, f.info)
+  body.flags.incl nfTransf # do not transform further
+
+  var threadLocalBarrier: PSym
+  if barrier != nil:
+    var varSection2 = newNodeI(nkVarSection, barrier.info)
+    threadLocalBarrier = addLocalVar(g, varSection2, nil, argsParam.owner,
+                                     barrier.typ, barrier)
+    body.add varSection2
+    body.add callCodegenProc(g, "barrierEnter", threadLocalBarrier.info,
+      threadLocalBarrier.newSymNode)
+  var threadLocalProm: PSym
+  if spawnKind == srByVar:
+    threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)
+  elif fv != nil:
+    internalAssert g.config, fv.typ.kind == tyGenericInst
+    threadLocalProm = addLocalVar(g, varSection, nil, argsParam.owner, fv.typ, fv)
+  body.add varSection
+  body.add varInit
+  if fv != nil and spawnKind != srByVar:
+    # generate:
+    #   fv.owner = threadParam
+    body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
+      "owner", fv.info, g.cache), threadParam.newSymNode)
+
+  body.add callCodegenProc(g, "nimArgsPassingDone", threadParam.info,
+    threadParam.newSymNode)
+  if spawnKind == srByVar:
+    body.add newAsgnStmt(genDeref(threadLocalProm.newSymNode), call)
+  elif fv != nil:
+    let fk = fv.typ.sons[1].flowVarKind
+    if fk == fvInvalid:
+      localError(g.config, f.info, "cannot create a flowVar of type: " &
+        typeToString(fv.typ.sons[1]))
+    body.add newAsgnStmt(indirectAccess(threadLocalProm.newSymNode,
+      if fk == fvGC: "data" else: "blob", fv.info, g.cache), call)
+    if fk == fvGC:
+      let incRefCall = newNodeI(nkCall, fv.info, 2)
+      incRefCall.sons[0] = newSymNode(getSysMagic(g, fv.info, "GCref", mGCref))
+      incRefCall.sons[1] = indirectAccess(threadLocalProm.newSymNode,
+                                          "data", fv.info, g.cache)
+      body.add incRefCall
+    if barrier == nil:
+      # by now 'fv' is shared and thus might have beeen overwritten! we need
+      # to use the thread-local view instead:
+      body.add callCodegenProc(g, "nimFlowVarSignal", threadLocalProm.info,
+        threadLocalProm.newSymNode)
+  else:
+    body.add call
+  if barrier != nil:
+    body.add callCodegenProc(g, "barrierLeave", threadLocalBarrier.info,
+      threadLocalBarrier.newSymNode)
+
+  var params = newNodeI(nkFormalParams, f.info)
+  params.add newNodeI(nkEmpty, f.info)
+  params.add threadParam.newSymNode
+  params.add argsParam.newSymNode
+
+  var t = newType(tyProc, threadParam.owner)
+  t.rawAddSon nil
+  t.rawAddSon threadParam.typ
+  t.rawAddSon argsParam.typ
+  t.n = newNodeI(nkFormalParams, f.info)
+  t.n.add newNodeI(nkEffectList, f.info)
+  t.n.add threadParam.newSymNode
+  t.n.add argsParam.newSymNode
+
+  let name = (if f.kind == nkSym: f.sym.name.s else: genPrefix) & "Wrapper"
+  result = newSym(skProc, getIdent(g.cache, name), argsParam.owner, f.info,
+                  argsParam.options)
+  let emptyNode = newNodeI(nkEmpty, f.info)
+  result.ast = newProcNode(nkProcDef, f.info, body = body,
+      params = params, name = newSymNode(result), pattern = emptyNode,
+      genericParams = emptyNode, pragmas = emptyNode,
+      exceptions = emptyNode)
+  result.typ = t
+
+proc createCastExpr(argsParam: PSym; objType: PType): PNode =
+  result = newNodeI(nkCast, argsParam.info)
+  result.add newNodeI(nkEmpty, argsParam.info)
+  result.add newSymNode(argsParam)
+  result.typ = newType(tyPtr, objType.owner)
+  result.typ.rawAddSon(objType)
+
+proc setupArgsForConcurrency(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym,
+                             castExpr, call,
+                             varSection, varInit, result: PNode) =
+  let formals = n[0].typ.n
+  let tmpName = getIdent(g.cache, genPrefix)
+  for i in 1 ..< n.len:
+    # we pick n's type here, which hopefully is 'tyArray' and not
+    # 'tyOpenArray':
+    var argType = n[i].typ.skipTypes(abstractInst)
+    if i < formals.len and formals[i].typ.kind in {tyVar, tyLent}:
+      localError(g.config, n[i].info, "'spawn'ed function cannot have a 'var' parameter")
+    #elif containsTyRef(argType):
+    #  localError(n[i].info, "'spawn'ed function cannot refer to 'ref'/closure")
+
+    let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
+    var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
+    field.typ = argType
+    objType.addField(field, g.cache)
+    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[i])
+
+    let temp = addLocalVar(g, varSection, varInit, objType.owner, argType,
+                           indirectAccess(castExpr, field, n.info))
+    call.add(newSymNode(temp))
+
+proc getRoot*(n: PNode): PSym =
+  ## ``getRoot`` takes a *path* ``n``. A path is an lvalue expression
+  ## like ``obj.x[i].y``. The *root* of a path is the symbol that can be
+  ## determined as the owner; ``obj`` in the example.
+  case n.kind
+  of nkSym:
+    if n.sym.kind in {skVar, skResult, skTemp, skLet, skForVar}:
+      result = n.sym
+  of nkDotExpr, nkBracketExpr, nkHiddenDeref, nkDerefExpr,
+      nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
+    result = getRoot(n.sons[0])
+  of nkHiddenStdConv, nkHiddenSubConv, nkConv:
+    result = getRoot(n.sons[1])
+  of nkCallKinds:
+    if getMagic(n) == mSlice: result = getRoot(n.sons[1])
+  else: discard
+
+proc setupArgsForParallelism(g: ModuleGraph; n: PNode; objType: PType; scratchObj: PSym;
+                             castExpr, call,
+                             varSection, varInit, result: PNode) =
+  let formals = n[0].typ.n
+  let tmpName = getIdent(g.cache, genPrefix)
+  # we need to copy the foreign scratch object fields into local variables
+  # for correctness: These are called 'threadLocal' here.
+  for i in 1 ..< n.len:
+    let n = n[i]
+    let argType = skipTypes(if i < formals.len: formals[i].typ else: n.typ,
+                            abstractInst)
+    #if containsTyRef(argType):
+    #  localError(n.info, "'spawn'ed function cannot refer to 'ref'/closure")
+
+    let fieldname = if i < formals.len: formals[i].sym.name else: tmpName
+    var field = newSym(skField, fieldname, objType.owner, n.info, g.config.options)
+
+    if argType.kind in {tyVarargs, tyOpenArray}:
+      # important special case: we always create a zero-copy slice:
+      let slice = newNodeI(nkCall, n.info, 4)
+      slice.typ = n.typ
+      slice.sons[0] = newSymNode(createMagic(g, "slice", mSlice))
+      slice.sons[0].typ = getSysType(g, n.info, tyInt) # fake type
+      var fieldB = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
+      fieldB.typ = getSysType(g, n.info, tyInt)
+      objType.addField(fieldB, g.cache)
+
+      if getMagic(n) == mSlice:
+        let a = genAddrOf(n[1])
+        field.typ = a.typ
+        objType.addField(field, g.cache)
+        result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
+
+        var fieldA = newSym(skField, tmpName, objType.owner, n.info, g.config.options)
+        fieldA.typ = getSysType(g, n.info, tyInt)
+        objType.addField(fieldA, g.cache)
+        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldA), n[2])
+        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), n[3])
+
+        let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldA.typ,
+                                      indirectAccess(castExpr, fieldA, n.info),
+                                      useShallowCopy=true)
+        slice.sons[2] = threadLocal.newSymNode
+      else:
+        let a = genAddrOf(n)
+        field.typ = a.typ
+        objType.addField(field, g.cache)
+        result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
+        result.add newFastAsgnStmt(newDotExpr(scratchObj, fieldB), genHigh(g, n))
+
+        slice.sons[2] = newIntLit(g, n.info, 0)
+      # the array itself does not need to go through a thread local variable:
+      slice.sons[1] = genDeref(indirectAccess(castExpr, field, n.info))
+
+      let threadLocal = addLocalVar(g, varSection,nil, objType.owner, fieldB.typ,
+                                    indirectAccess(castExpr, fieldB, n.info),
+                                    useShallowCopy=true)
+      slice.sons[3] = threadLocal.newSymNode
+      call.add slice
+    elif (let size = computeSize(g.config, argType); size < 0 or size > 16) and
+        n.getRoot != nil:
+      # it is more efficient to pass a pointer instead:
+      let a = genAddrOf(n)
+      field.typ = a.typ
+      objType.addField(field, g.cache)
+      result.add newFastAsgnStmt(newDotExpr(scratchObj, field), a)
+      let threadLocal = addLocalVar(g, varSection,nil, objType.owner, field.typ,
+                                    indirectAccess(castExpr, field, n.info),
+                                    useShallowCopy=true)
+      call.add(genDeref(threadLocal.newSymNode))
+    else:
+      # boring case
+      field.typ = argType
+      objType.addField(field, g.cache)
+      result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n)
+      let threadLocal = addLocalVar(g, varSection, varInit,
+                                    objType.owner, field.typ,
+                                    indirectAccess(castExpr, field, n.info),
+                                    useShallowCopy=true)
+      call.add(threadLocal.newSymNode)
+
+proc wrapProcForSpawn*(g: ModuleGraph; owner: PSym; spawnExpr: PNode; retType: PType;
+                       barrier, dest: PNode = nil): PNode =
+  # if 'barrier' != nil, then it is in a 'parallel' section and we
+  # generate quite different code
+  let n = spawnExpr[^2]
+  let spawnKind = spawnResult(retType, barrier!=nil)
+  case spawnKind
+  of srVoid:
+    internalAssert g.config, dest == nil
+    result = newNodeI(nkStmtList, n.info)
+  of srFlowVar:
+    internalAssert g.config, dest == nil
+    result = newNodeIT(nkStmtListExpr, n.info, retType)
+  of srByVar:
+    if dest == nil: localError(g.config, n.info, "'spawn' must not be discarded")
+    result = newNodeI(nkStmtList, n.info)
+
+  if n.kind notin nkCallKinds:
+    localError(g.config, n.info, "'spawn' takes a call expression")
+    return
+  if optThreadAnalysis in g.config.globalOptions:
+    if {tfThread, tfNoSideEffect} * n[0].typ.flags == {}:
+      localError(g.config, n.info, "'spawn' takes a GC safe call expression")
+  var
+    threadParam = newSym(skParam, getIdent(g.cache, "thread"), owner, n.info, g.config.options)
+    argsParam = newSym(skParam, getIdent(g.cache, "args"), owner, n.info, g.config.options)
+  block:
+    let ptrType = getSysType(g, n.info, tyPointer)
+    threadParam.typ = ptrType
+    argsParam.typ = ptrType
+    argsParam.position = 1
+
+  var objType = createObj(g, owner, n.info)
+  incl(objType.flags, tfFinal)
+  let castExpr = createCastExpr(argsParam, objType)
+
+  var scratchObj = newSym(skVar, getIdent(g.cache, "scratch"), owner, n.info, g.config.options)
+  block:
+    scratchObj.typ = objType
+    incl(scratchObj.flags, sfFromGeneric)
+    var varSectionB = newNodeI(nkVarSection, n.info)
+    varSectionB.addVar(scratchObj.newSymNode)
+    result.add varSectionB
+
+  var call = newNodeIT(nkCall, n.info, n.typ)
+  var fn = n.sons[0]
+  # templates and macros are in fact valid here due to the nature of
+  # the transformation:
+  if fn.kind == nkClosure or (fn.typ != nil and fn.typ.callConv == ccClosure):
+    localError(g.config, n.info, "closure in spawn environment is not allowed")
+  if not (fn.kind == nkSym and fn.sym.kind in {skProc, skTemplate, skMacro,
+                                               skFunc, skMethod, skConverter}):
+    # for indirect calls we pass the function pointer in the scratchObj
+    var argType = n[0].typ.skipTypes(abstractInst)
+    var field = newSym(skField, getIdent(g.cache, "fn"), owner, n.info, g.config.options)
+    field.typ = argType
+    objType.addField(field, g.cache)
+    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), n[0])
+    fn = indirectAccess(castExpr, field, n.info)
+  elif fn.kind == nkSym and fn.sym.kind == skIterator:
+    localError(g.config, n.info, "iterator in spawn environment is not allowed")
+  elif fn.typ.callConv == ccClosure:
+    localError(g.config, n.info, "closure in spawn environment is not allowed")
+
+  call.add(fn)
+  var varSection = newNodeI(nkVarSection, n.info)
+  var varInit = newNodeI(nkStmtList, n.info)
+  if barrier.isNil:
+    setupArgsForConcurrency(g, n, objType, scratchObj, castExpr, call,
+                            varSection, varInit, result)
+  else:
+    setupArgsForParallelism(g, n, objType, scratchObj, castExpr, call,
+                            varSection, varInit, result)
+
+  var barrierAsExpr: PNode = nil
+  if barrier != nil:
+    let typ = newType(tyPtr, owner)
+    typ.rawAddSon(magicsys.getCompilerProc(g, "Barrier").typ)
+    var field = newSym(skField, getIdent(g.cache, "barrier"), owner, n.info, g.config.options)
+    field.typ = typ
+    objType.addField(field, g.cache)
+    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), barrier)
+    barrierAsExpr = indirectAccess(castExpr, field, n.info)
+
+  var fvField, fvAsExpr: PNode = nil
+  if spawnKind == srFlowVar:
+    var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)
+    field.typ = retType
+    objType.addField(field, g.cache)
+    fvField = newDotExpr(scratchObj, field)
+    fvAsExpr = indirectAccess(castExpr, field, n.info)
+    # create flowVar:
+    result.add newFastAsgnStmt(fvField, callProc(spawnExpr[^1]))
+    if barrier == nil:
+      result.add callCodegenProc(g, "nimFlowVarCreateSemaphore", fvField.info,
+        fvField)
+
+  elif spawnKind == srByVar:
+    var field = newSym(skField, getIdent(g.cache, "fv"), owner, n.info, g.config.options)
+    field.typ = newType(tyPtr, objType.owner)
+    field.typ.rawAddSon(retType)
+    objType.addField(field, g.cache)
+    fvAsExpr = indirectAccess(castExpr, field, n.info)
+    result.add newFastAsgnStmt(newDotExpr(scratchObj, field), genAddrOf(dest))
+
+  let wrapper = createWrapperProc(g, fn, threadParam, argsParam,
+                                  varSection, varInit, call,
+                                  barrierAsExpr, fvAsExpr, spawnKind)
+  result.add callCodegenProc(g, "nimSpawn" & $spawnExpr.len, wrapper.info,
+    wrapper.newSymNode, genAddrOf(scratchObj.newSymNode), nil, spawnExpr)
+
+  if spawnKind == srFlowVar: result.add fvField
+
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 9e738e8a6..2f92825c0 100644
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -32,11 +32,11 @@
 
 # included from sigmatch.nim
 
-import algorithm, prefixmatches, lineinfos, pathutils, parseutils, linter
+import algorithm, prefixmatches, lineinfos, parseutils, linter
 from wordrecg import wDeprecated, wError, wAddr, wYield, specialWords
 
 when defined(nimsuggest):
-  import passes, tables # importer
+  import passes, tables, pathutils # importer
 
 const
   sep = '\t'
diff --git a/compiler/syntaxes.nim b/compiler/syntaxes.nim
index 3e4f65c0b..3b67b3263 100644
--- a/compiler/syntaxes.nim
+++ b/compiler/syntaxes.nim
@@ -10,7 +10,7 @@
 ## Implements the dispatcher for the different parsers.
 
 import
-  strutils, llstream, ast, astalgo, idents, lexer, options, msgs, parser,
+  strutils, llstream, ast, idents, lexer, options, msgs, parser,
   filters, filter_tmpl, renderer, lineinfos, pathutils
 
 type
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 4dd348742..60a7ce224 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -19,9 +19,9 @@
 # * transforms 'defer' into a 'try finally' statement
 
 import
-  intsets, strutils, options, ast, astalgo, trees, treetab, msgs, lookups,
+  options, ast, astalgo, trees, msgs,
   idents, renderer, types, passes, semfold, magicsys, cgmeth,
-  sempass2, lowerings, injectdestructors, liftlocals,
+  lowerings, injectdestructors, liftlocals,
   modulegraphs, lineinfos
 
 proc transformBody*(g: ModuleGraph, prc: PSym, cache = true;
diff --git a/compiler/trees.nim b/compiler/trees.nim
index c878eb1bf..87ab7c00e 100644
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -10,7 +10,7 @@
 # tree helper routines
 
 import
-  ast, astalgo, lexer, msgs, strutils, wordrecg, idents
+  ast, wordrecg, idents
 
 proc cyclicTreeAux(n: PNode, visited: var seq[PNode]): bool =
   if n == nil: return
diff --git a/compiler/typesrenderer.nim b/compiler/typesrenderer.nim
index 0c4fe01e1..7084349e5 100644
--- a/compiler/typesrenderer.nim
+++ b/compiler/typesrenderer.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-import renderer, strutils, ast, msgs, types, astalgo
+import renderer, strutils, ast, types
 
 const defaultParamSeparator* = ","
 
diff --git a/compiler/vm.nim b/compiler/vm.nim
index bb8c6bbf2..34caec83f 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -13,7 +13,7 @@
 import ast except getstr
 
 import
-  strutils, astalgo, msgs, vmdef, vmgen, nimsets, types, passes,
+  strutils, msgs, vmdef, vmgen, nimsets, types, passes,
   parser, vmdeps, idents, trees, renderer, options, transf, parseutils,
   vmmarshal, gorgeimpl, lineinfos, tables, btrees, macrocacheimpl,
   modulegraphs, sighashes
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 723863ca7..425f728e7 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -10,8 +10,7 @@
 ## This module contains the type definitions for the new evaluation engine.
 ## An instruction is 1-3 int32s in memory, it is a register based VM.
 
-import ast, passes, msgs, idents, intsets, options, modulegraphs, lineinfos,
-  tables, btrees
+import ast, passes, idents, intsets, options, modulegraphs, lineinfos
 
 const
   byteExcess* = 128 # we use excess-K for immediates
diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim
index 5130f30c9..1b2538c79 100644
--- a/compiler/vmdeps.nim
+++ b/compiler/vmdeps.nim
@@ -7,7 +7,7 @@
 #    distribution, for details about the copyright.
 #
 
-import ast, types, msgs, os, streams, options, idents, lineinfos
+import ast, types, msgs, os, options, idents, lineinfos
 
 proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): string =
   try:
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index 37706f1ea..a27cd62c6 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -28,10 +28,8 @@
 # this copy depends on the involved types.
 
 import
-  strutils, ast, astalgo, types, msgs, renderer, vmdef,
-  trees, intsets, magicsys, options, lowerings, lineinfos, transf
-import platform
-from os import splitFile
+  strutils, ast, types, msgs, renderer, vmdef,
+  intsets, magicsys, options, lowerings, lineinfos, transf
 
 const
   debugEchoCode* = defined(nimVMDebug)
diff --git a/compiler/writetracking.nim b/compiler/writetracking.nim
index 04d3b7a16..b310701ca 100644
--- a/compiler/writetracking.nim
+++ b/compiler/writetracking.nim
@@ -15,8 +15,7 @@
 ##   * Computing an aliasing relation based on the assignments. This relation
 ##     is then used to compute the 'writes' and 'escapes' effects.
 
-import intsets, idents, ast, astalgo, trees, renderer, msgs, types, options,
-  lineinfos
+import intsets, idents, ast, trees, msgs, types, options, lineinfos
 
 const
   debug = false