summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim6
-rw-r--r--compiler/ccgexprs.nim2
-rw-r--r--compiler/ccgstmts.nim4
-rw-r--r--compiler/ccgutils.nim2
-rw-r--r--compiler/cgen.nim28
-rw-r--r--compiler/cgendata.nim10
-rw-r--r--compiler/commands.nim14
-rw-r--r--compiler/extccomp.nim37
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/lambdalifting.nim2
-rw-r--r--compiler/lists.nim117
-rw-r--r--compiler/main.nim8
-rw-r--r--compiler/nimblecmd.nim8
-rw-r--r--compiler/nimeval.nim4
-rw-r--r--compiler/nimfix/nimfix.nim6
-rw-r--r--compiler/options.nim28
-rw-r--r--compiler/passes.nim2
-rw-r--r--compiler/pragmas.nim35
-rw-r--r--compiler/renderer.nim2
-rw-r--r--compiler/scriptconfig.nim4
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semdata.nim18
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--compiler/semfold.nim2
-rw-r--r--compiler/semgnrc.nim6
-rw-r--r--compiler/semstmts.nim1
-rw-r--r--compiler/semtempl.nim12
-rw-r--r--compiler/transf.nim2
-rw-r--r--lib/core/macros.nim2
-rw-r--r--tests/template/mgensym_generic_cross_module.nim14
-rw-r--r--tests/template/tgensym_generic_cross_module.nim14
-rw-r--r--tests/template/tgensym_label.nim18
-rw-r--r--tools/nimsuggest/nimsuggest.nim16
33 files changed, 190 insertions, 240 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 4ea68dc99..66fbe577c 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -10,7 +10,7 @@
 # abstract syntax tree + symbol table
 
 import
-  msgs, hashes, nversion, options, strutils, securehash, ropes, idents, lists,
+  msgs, hashes, nversion, options, strutils, securehash, ropes, idents,
   intsets, idgen
 
 type
@@ -736,13 +736,15 @@ type
 
   TLibKind* = enum
     libHeader, libDynamic
-  TLib* = object of lists.TListEntry # also misused for headers!
+    
+  TLib* = object              # also misused for headers!
     kind*: TLibKind
     generated*: bool          # needed for the backends:
     isOverriden*: bool
     name*: Rope
     path*: PNode              # can be a string literal!
 
+    
   CompilesId* = int ## id that is used for the caching logic within
                     ## ``system.compiles``. See the seminst module.
   TInstantiation* = object
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 6f7e83c18..e9c78b48b 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -944,7 +944,7 @@ proc genEcho(p: BProc, n: PNode) =
   # this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
   # is threadsafe.
   internalAssert n.kind == nkBracket
-  discard lists.includeStr(p.module.headerFiles, "<stdio.h>")
+  p.module.includeHeader("<stdio.h>")
   var args: Rope = nil
   var a: TLoc
   for i in countup(0, n.len-1):
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 02119d63e..3a861ebd4 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -540,7 +540,7 @@ proc genBreakStmt(p: BProc, t: PNode) =
     # named break?
     assert(t.sons[0].kind == nkSym)
     var sym = t.sons[0].sym
-    assert(sym.loc.k == locOther)
+    doAssert(sym.loc.k == locOther)
     idx = sym.position-1
   else:
     # an unnamed 'break' can only break a loop after 'transf' pass:
@@ -884,7 +884,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   #
   if not isEmptyType(t.typ) and d.k == locNone:
     getTemp(p, t.typ, d)
-  discard lists.includeStr(p.module.headerFiles, "<setjmp.h>")
+  p.module.includeHeader("<setjmp.h>")
   genLineDir(p, t)
   var safePoint = getTempName(p.module)
   if getCompilerProc("Exception") != nil:
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index d42f0438f..a00ce3505 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, lists, hashes, strutils, types, msgs, wordrecg,
+  ast, astalgo, ropes, hashes, strutils, types, msgs, wordrecg,
   platform, trees
 
 proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 9db6b7774..7fef34a27 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -11,7 +11,7 @@
 
 import
   ast, astalgo, hashes, trees, platform, magicsys, extccomp, options, intsets,
-  nversion, nimsets, msgs, securehash, bitsets, idents, lists, types,
+  nversion, nimsets, msgs, securehash, bitsets, idents, types,
   ccgutils, os, ropes, math, passes, rodread, wordrecg, treetab, cgmeth,
   condsyms, rodutils, renderer, idgen, cgendata, ccgmerge, semfold, aliases,
   lowerings, semparallel, tables, sets, ndi
@@ -75,12 +75,13 @@ proc isSimpleConst(typ: PType): bool =
 proc useStringh(m: BModule) =
   if includesStringh notin m.flags:
     incl m.flags, includesStringh
-    discard lists.includeStr(m.headerFiles, "<string.h>")
+    m.includeHeader("<string.h>")
 
 proc useHeader(m: BModule, sym: PSym) =
   if lfHeader in sym.loc.flags:
     assert(sym.annex != nil)
-    discard lists.includeStr(m.headerFiles, getStr(sym.annex.path))
+    let str = getStr(sym.annex.path)
+    m.includeHeader(str)
 
 proc cgsym(m: BModule, name: string): Rope
 
@@ -594,15 +595,14 @@ proc cgsym(m: BModule, name: string): Rope =
 
 proc generateHeaders(m: BModule) =
   add(m.s[cfsHeaders], tnl & "#include \"nimbase.h\"" & tnl)
-  var it = PStrEntry(m.headerFiles.head)
-  while it != nil:
-    if it.data[0] == '#':
-      add(m.s[cfsHeaders], rope(it.data.replace('`', '"') & tnl))
-    elif it.data[0] notin {'\"', '<'}:
-      addf(m.s[cfsHeaders], "#include \"$1\"$N", [rope(it.data)])
+  
+  for it in m.headerFiles:
+    if it[0] == '#':
+      add(m.s[cfsHeaders], rope(it.replace('`', '"') & tnl))
+    elif it[0] notin {'\"', '<'}:
+      addf(m.s[cfsHeaders], "#include \"$1\"$N", [rope(it)])
     else:
-      addf(m.s[cfsHeaders], "#include $1$N", [rope(it.data)])
-    it = PStrEntry(it.next)
+      addf(m.s[cfsHeaders], "#include $1$N", [rope(it)])
   add(m.s[cfsHeaders], "#undef linux" & tnl)
 
 proc initFrame(p: BProc, procname, filename: Rope): Rope =
@@ -974,7 +974,7 @@ proc genMainProc(m: BModule) =
     else:
       nimMain = WinNimDllMain
       otherMain = WinCDllMain
-    discard lists.includeStr(m.headerFiles, "<windows.h>")
+    m.includeHeader("<windows.h>")
   elif optGenDynLib in gGlobalOptions:
     nimMain = PosixNimDllMain
     otherMain = PosixCDllMain
@@ -1129,7 +1129,7 @@ proc initProcOptions(m: BModule): TOptions =
 proc rawNewModule(g: BModuleList; module: PSym, filename: string): BModule =
   new(result)
   result.tmpBase = rope("TM" & $hashOwner(module) & "_")
-  initLinkedList(result.headerFiles)
+  result.headerFiles = @[]
   result.declaredThings = initIntSet()
   result.declaredProtos = initIntSet()
   result.cfilename = filename
@@ -1166,7 +1166,7 @@ proc nullify[T](arr: var T) =
 proc resetModule*(m: BModule) =
   # between two compilations in CAAS mode, we can throw
   # away all the data that was written to disk
-  initLinkedList(m.headerFiles)
+  m.headerFiles = @[]
   m.declaredProtos = initIntSet()
   m.forwTypeCache = initTable[SigHash, Rope]()
   m.initProc = newProc(nil, m)
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 565399ead..be087095f 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, lists, platform, sighashes,
+  ast, astalgo, ropes, passes, options, intsets, platform, sighashes,
   tables, ndi
 
 from msgs import TLineInfo
@@ -130,7 +130,7 @@ type
     forwTypeCache*: TypeCache # cache for forward declarations of types
     declaredThings*: IntSet   # things we have declared in this .c file
     declaredProtos*: IntSet   # prototypes we have declared in this .c file
-    headerFiles*: TLinkedList # needed headers to include
+    headerFiles*: seq[string] # needed headers to include
     typeInfoMarker*: TypeCache # needed for generating type information
     initProc*: BProc          # code for init procedure
     postInitProc*: BProc      # code to be executed after the init proc
@@ -148,9 +148,13 @@ type
     g*: BModuleList
     ndi*: NdiFile
 
+proc includeHeader*(this: BModule; header: string) =
+  if not this.headerFiles.contains header:
+    this.headerFiles.add header
+
 proc s*(p: BProc, s: TCProcSection): var Rope {.inline.} =
   # section in the current block
-  result = p.blocks[p.blocks.len - 1].sections[s]
+  result = p.blocks[^1].sections[s]
 
 proc procSec*(p: BProc, s: TCProcSection): var Rope {.inline.} =
   # top level proc sections
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 74503a414..b75e953de 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -26,8 +26,8 @@ bootSwitch(usedGoGC, defined(gogc), "--gc:go")
 bootSwitch(usedNoGC, defined(nogc), "--gc:none")
 
 import
-  os, msgs, options, nversion, condsyms, strutils, extccomp, platform, lists,
-  wordrecg, parseutils, nimblecmd, idents, parseopt
+  os, msgs, options, nversion, condsyms, strutils, extccomp, platform,
+  wordrecg, parseutils, nimblecmd, idents, parseopt, sequtils
 
 # but some have deps to imported modules. Yay.
 bootSwitch(usedTinyC, hasTinyCBackend, "-d:tinyc")
@@ -335,12 +335,14 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
   of "excludepath":
     expectArg(switch, arg, pass, info)
     let path = processPath(arg, info)
-    lists.excludePath(options.searchPaths, path)
-    lists.excludePath(options.lazyPaths, path)
+    
+    options.searchPaths.keepItIf( cmpPaths(it, path) != 0 )
+    options.lazyPaths.keepItIf( cmpPaths(it, path) != 0 )
+    
     if (len(path) > 0) and (path[len(path) - 1] == DirSep):
       let strippedPath = path[0 .. (len(path) - 2)]
-      lists.excludePath(options.searchPaths, strippedPath)
-      lists.excludePath(options.lazyPaths, strippedPath)
+      options.searchPaths.keepItIf( cmpPaths(it, strippedPath) != 0 )
+      options.lazyPaths.keepItIf( cmpPaths(it, strippedPath) != 0 )
   of "nimcache":
     expectArg(switch, arg, pass, info)
     options.nimcacheDir = processPath(arg, info, true)
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 1b068385a..dab643d50 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -13,7 +13,7 @@
 # nim files.
 
 import
-  lists, ropes, os, strutils, osproc, platform, condsyms, options, msgs,
+  ropes, os, strutils, osproc, platform, condsyms, options, msgs,
   securehash, streams
 
 #from debuginfo import writeDebugInfo
@@ -390,8 +390,8 @@ type
   CfileList = seq[Cfile]
 
 var
-  externalToLink: TLinkedList # files to link in addition to the file
-                              # we compiled
+  externalToLink: seq[string] = @[] # files to link in addition to the file
+                                    # we compiled
   linkOptionsCmd: string = ""
   compileOptionsCmd: seq[string] = @[]
   linkOptions: string = ""
@@ -486,11 +486,10 @@ proc resetCompilationLists* =
   # when the module is loaded/unloaded it adds/removes its items
   # That's because we still need to hash check the external files
   # Maybe we can do that in checkDep on the other hand?
-  initLinkedList(externalToLink)
+  externalToLink.setLen 0
 
 proc addExternalFileToLink*(filename: string) =
-  prependStr(externalToLink, filename)
-  # BUGFIX: was ``appendStr``
+  externalToLink.insert(filename, 0)
 
 proc execWithEcho(cmd: string, msg = hintExecuting): int =
   rawMessage(msg, cmd)
@@ -527,9 +526,6 @@ proc noAbsolutePaths: bool {.inline.} =
   # `optGenMapping` is included here for niminst.
   result = gGlobalOptions * {optGenScript, optGenMapping} != {}
 
-proc add(s: var string, many: openArray[string]) =
-  s.add many.join
-
 proc cFileSpecificOptions(cfilename: string): string =
   result = compileOptions
   for option in compileOptionsCmd:
@@ -560,7 +556,7 @@ proc getLinkOptions: string =
   for linkedLib in items(cLinkedLibs):
     result.add(CC[cCompiler].linkLibCmd % linkedLib.quoteShell)
   for libDir in items(cLibs):
-    result.add([CC[cCompiler].linkDirCmd, libDir.quoteShell])
+    result.add(join([CC[cCompiler].linkDirCmd, libDir.quoteShell]))
 
 proc needsExeExt(): bool {.inline.} =
   result = (optGenScript in gGlobalOptions and targetOS == osWindows) or
@@ -611,7 +607,7 @@ proc getCompileCFileCmd*(cfile: Cfile): string =
     includeCmd = CC[c].includeCmd & quoteShell(libpath)
 
     for includeDir in items(cIncludes):
-      includeCmd.add([CC[c].includeCmd, includeDir.quoteShell])
+      includeCmd.add(join([CC[c].includeCmd, includeDir.quoteShell]))
 
     compilePattern = joinPath(ccompilerpath, exe)
   else:
@@ -786,14 +782,12 @@ proc callCCompiler*(projectfile: string) =
         rawMessage(errExecutionOfProgramFailed, cmds.join())
   if optNoLinking notin gGlobalOptions:
     # call the linker:
-    var it = PStrEntry(externalToLink.head)
     var objfiles = ""
-    while it != nil:
-      let objFile = if noAbsolutePaths(): it.data.extractFilename else: it.data
+    for it in externalToLink:
+      let objFile = if noAbsolutePaths(): it.extractFilename else: it
       add(objfiles, ' ')
       add(objfiles, quoteShell(
           addFileExt(objFile, CC[cCompiler].objExt)))
-      it = PStrEntry(it.next)
     for x in toCompile:
       add(objfiles, ' ')
       add(objfiles, quoteShell(x.obj))
@@ -836,15 +830,14 @@ proc writeJsonBuildInstructions*(projectfile: string) =
       else:
         lit "],\L"
 
-  proc linkfiles(f: File; buf, objfiles: var string; toLink: TLinkedList) =
-    var it = PStrEntry(toLink.head)
-    while it != nil:
-      let objfile = addFileExt(it.data, CC[cCompiler].objExt)
-      str objfile
+  proc linkfiles(f: File; buf, objfiles: var string; toLink: seq[string]) =
+    for i, it in toLink:
+      let objfile = addFileExt(it, CC[cCompiler].objExt)
+      str(objfile)
       add(objfiles, ' ')
       add(objfiles, quoteShell(objfile))
-      it = PStrEntry(it.next)
-      if it == nil:
+      
+      if i == toLink.high:
         lit "\L"
       else:
         lit ",\L"
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index b2d291d70..8f819686d 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -31,7 +31,7 @@ implements the required case distinction.
 
 import
   ast, astalgo, strutils, hashes, trees, platform, magicsys, extccomp, options,
-  nversion, nimsets, msgs, securehash, bitsets, idents, lists, types, os,
+  nversion, nimsets, msgs, securehash, bitsets, idents, types, os,
   times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils,
   intsets, cgmeth, lowerings
 
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 8d4badb4e..cd2ccfe53 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -10,7 +10,7 @@
 # This include file implements lambda lifting for the transformator.
 
 import
-  intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
+  intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
   idents, renderer, types, magicsys, rodread, lowerings, tables
 
 discard """
diff --git a/compiler/lists.nim b/compiler/lists.nim
index 27e373342..bfd052204 100644
--- a/compiler/lists.nim
+++ b/compiler/lists.nim
@@ -7,113 +7,22 @@
 #    distribution, for details about the copyright.
 #
 
-# This module implements a generic doubled linked list.
-# TODO Remove this and replace it with something sensible
-import os
-type
-  PListEntry* = ref TListEntry
-  TListEntry* = object of RootObj
-    prev*, next*: PListEntry
-
-  TStrEntry* = object of TListEntry
-    data*: string
-
-  PStrEntry* = ref TStrEntry
-  TLinkedList* = object       # for the "find" operation:
-    head*, tail*: PListEntry
-    counter*: int
-
-  TCompareProc* = proc (entry: PListEntry, closure: pointer): bool {.nimcall.}
-
-proc initLinkedList*(list: var TLinkedList) =
-  list.counter = 0
-  list.head = nil
-  list.tail = nil
-
-proc append*(list: var TLinkedList, entry: PListEntry) =
-  inc(list.counter)
-  entry.next = nil
-  entry.prev = list.tail
-  if list.tail != nil:
-    assert(list.tail.next == nil)
-    list.tail.next = entry
-  list.tail = entry
-  if list.head == nil: list.head = entry
-
-proc contains*(list: TLinkedList, data: string): bool =
-  var it = list.head
-  while it != nil:
-    if PStrEntry(it).data == data:
-      return true
-    it = it.next
+# This module is deprecated, don't use it.
+# TODO Remove this
 
-proc newStrEntry(data: string): PStrEntry =
-  new(result)
-  result.data = data
-
-proc appendStr*(list: var TLinkedList, data: string) =
-  append(list, newStrEntry(data))
-
-proc includeStr*(list: var TLinkedList, data: string): bool =
-  if contains(list, data): return true
-  appendStr(list, data)       # else: add to list
-
-proc prepend*(list: var TLinkedList, entry: PListEntry) =
-  inc(list.counter)
-  entry.prev = nil
-  entry.next = list.head
-  if list.head != nil:
-    assert(list.head.prev == nil)
-    list.head.prev = entry
-  list.head = entry
-  if list.tail == nil: list.tail = entry
-
-proc prependStr*(list: var TLinkedList, data: string) =
-  prepend(list, newStrEntry(data))
+import os
 
-proc insertBefore*(list: var TLinkedList, pos, entry: PListEntry) =
-  assert(pos != nil)
-  if pos == list.head:
-    prepend(list, entry)
-  else:
-    inc(list.counter)
-    entry.next = pos
-    entry.prev = pos.prev
-    if pos.prev != nil: pos.prev.next = entry
-    pos.prev = entry
+static:
+  echo "WARNING: imported deprecated module compiler/lists.nim, use seq ore lists from the standard library"
 
-proc remove*(list: var TLinkedList, entry: PListEntry) =
-  dec(list.counter)
-  if entry == list.tail:
-    list.tail = entry.prev
-  if entry == list.head:
-    list.head = entry.next
-  if entry.next != nil: entry.next.prev = entry.prev
-  if entry.prev != nil: entry.prev.next = entry.next
+proc appendStr*(list: var seq[string]; data: string) {.deprecated.} =
+  # just use system.add
+  list.add(data)
 
-proc bringToFront*(list: var TLinkedList, entry: PListEntry) =
-  when true:
-    list.remove entry
-    list.prepend entry
+proc includeStr(list: var seq[string]; data: string): bool {.deprecated.} =
+  if list.contains(data):
+    result = true
   else:
-    if entry == list.head: return
-    if entry == list.tail: list.tail = entry.prev
-    if entry.next != nil: entry.next.prev = entry.prev
-    if entry.prev != nil: entry.prev.next = entry.next
-    entry.prev = nil
-    entry.next = list.head
-    list.head = entry
-
-proc excludePath*(list: var TLinkedList, data: string) =
-  var it = list.head
-  while it != nil:
-    let nxt = it.next
-    if cmpPaths(PStrEntry(it).data, data) == 0:
-      remove(list, it)
-    it = nxt
+    result = false
+    list.add data
 
-proc find*(list: TLinkedList, fn: TCompareProc, closure: pointer): PListEntry =
-  result = list.head
-  while result != nil:
-    if fn(result, closure): return
-    result = result.next
diff --git a/compiler/main.nim b/compiler/main.nim
index 2acb7620c..5f86e6188 100644
--- a/compiler/main.nim
+++ b/compiler/main.nim
@@ -15,7 +15,7 @@ import
   wordrecg, sem, semdata, idents, passes, docgen, extccomp,
   cgen, jsgen, json, nversion,
   platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
-  docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists,
+  docgen2, service, parser, modules, ccgutils, sigmatch, ropes,
   modulegraphs
 
 from magicsys import systemModule, resetSysTypes
@@ -151,7 +151,7 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
   # In "nim serve" scenario, each command must reset the registered passes
   clearPasses()
   gLastCmdTime = epochTime()
-  appendStr(searchPaths, options.libpath)
+  searchPaths.add(options.libpath)
   when false: # gProjectFull.len != 0:
     # current path is always looked first for modules
     prependStr(searchPaths, gProjectPath)
@@ -229,7 +229,7 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
       for s in definedSymbolNames(): definedSymbols.elems.add(%s)
 
       var libpaths = newJArray()
-      for dir in iterSearchPath(searchPaths): libpaths.elems.add(%dir)
+      for dir in searchPaths: libpaths.elems.add(%dir)
 
       var dumpdata = % [
         (key: "version", val: %VersionAsString),
@@ -245,7 +245,7 @@ proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
       for s in definedSymbolNames(): msgWriteln(s, {msgStdout, msgSkipHook})
       msgWriteln("-- end of list --", {msgStdout, msgSkipHook})
 
-      for it in iterSearchPath(searchPaths): msgWriteln(it)
+      for it in searchPaths: msgWriteln(it)
   of "check":
     gCmd = cmdCheck
     commandCheck(graph, cache)
diff --git a/compiler/nimblecmd.nim b/compiler/nimblecmd.nim
index 9c5c17287..e6466fc24 100644
--- a/compiler/nimblecmd.nim
+++ b/compiler/nimblecmd.nim
@@ -9,11 +9,11 @@
 
 ## Implements some helper procs for Nimble (Nim's package manager) support.
 
-import parseutils, strutils, strtabs, os, options, msgs, lists
+import parseutils, strutils, strtabs, os, options, msgs
 
 proc addPath*(path: string, info: TLineInfo) =
-  if not contains(options.searchPaths, path):
-    lists.prependStr(options.searchPaths, path)
+  if not options.searchPaths.contains(path):
+    options.searchPaths.insert(path, 0)
 
 proc versionSplitPos(s: string): int =
   result = s.len-2
@@ -61,7 +61,7 @@ iterator chosen(packages: StringTableRef): string =
 proc addNimblePath(p: string, info: TLineInfo) =
   if not contains(options.searchPaths, p):
     message(info, hintPath, p)
-    lists.prependStr(options.lazyPaths, p)
+    options.lazyPaths.insert(p, 0)
 
 proc addPathRec(dir: string, info: TLineInfo) =
   var packages = newStringTable(modeStyleInsensitive)
diff --git a/compiler/nimeval.nim b/compiler/nimeval.nim
index 2872bdade..aca03fc16 100644
--- a/compiler/nimeval.nim
+++ b/compiler/nimeval.nim
@@ -10,7 +10,7 @@
 ## exposes the Nim VM to clients.
 import
   ast, modules, passes, passaux, condsyms,
-  options, nimconf, lists, sem, semdata, llstream, vm, modulegraphs, idents
+  options, nimconf, sem, semdata, llstream, vm, modulegraphs, idents
 
 proc execute*(program: string) =
   passes.gIncludeFile = includeModule
@@ -25,7 +25,7 @@ proc execute*(program: string) =
   registerPass(semPass)
   registerPass(evalPass)
 
-  appendStr(searchPaths, options.libpath)
+  searchPaths.add options.libpath
   var graph = newModuleGraph()
   var cache = newIdentCache()
   var m = makeStdinModule(graph)
diff --git a/compiler/nimfix/nimfix.nim b/compiler/nimfix/nimfix.nim
index 4afb16912..a97d88078 100644
--- a/compiler/nimfix/nimfix.nim
+++ b/compiler/nimfix/nimfix.nim
@@ -13,7 +13,7 @@ import strutils, os, parseopt
 import compiler/[options, commands, modules, sem,
   passes, passaux, nimfix/pretty,
   msgs, nimconf,
-  extccomp, condsyms, lists,
+  extccomp, condsyms,
   modulegraphs, idents]
 
 const Usage = """
@@ -39,10 +39,10 @@ proc mainCommand =
   registerPass verbosePass
   registerPass semPass
   gCmd = cmdPretty
-  appendStr(searchPaths, options.libpath)
+  searchPaths.add options.libpath
   if gProjectFull.len != 0:
     # current path is always looked first for modules
-    prependStr(searchPaths, gProjectPath)
+    searchPaths.insert(gProjectPath, 0)
 
   compileProject(newModuleGraph(), newIdentCache())
   pretty.overwriteFiles()
diff --git a/compiler/options.nim b/compiler/options.nim
index 97e142569..6281980ff 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -8,7 +8,7 @@
 #
 
 import
-  os, lists, strutils, strtabs, osproc, sets
+  os, strutils, strtabs, osproc, sets
 
 const
   hasTinyCBackend* = defined(tinyc)
@@ -129,7 +129,8 @@ var
   gExitcode*: int8
   gCmd*: TCommands = cmdNone  # the command
   gSelectedGC* = gcRefc       # the selected GC
-  searchPaths*, lazyPaths*: TLinkedList
+  searchPaths*: seq[string] = @[]
+  lazyPaths*: seq[string]   = @[]
   outFile*: string = ""
   docSeeSrcUrl*: string = ""  # if empty, no seeSrc will be generated. \
   # The string uses the formatting variables `path` and `line`.
@@ -267,9 +268,7 @@ proc removeTrailingDirSep*(path: string): string =
 
 proc disableNimblePath*() =
   gNoNimblePath = true
-  lazyPaths.head = nil
-  lazyPaths.tail = nil
-  lazyPaths.counter = 0
+  lazyPaths.setLen(0)
 
 include packagehandling
 
@@ -336,27 +335,22 @@ proc completeGeneratedFilePath*(f: string, createSubDir: bool = true): string =
   result = joinPath(subdir, tail)
   #echo "completeGeneratedFilePath(", f, ") = ", result
 
-iterator iterSearchPath*(searchPaths: TLinkedList): string =
-  var it = PStrEntry(searchPaths.head)
-  while it != nil:
-    yield it.data
-    it = PStrEntry(it.next)
-
 proc rawFindFile(f: string): string =
-  for it in iterSearchPath(searchPaths):
+  for it in searchPaths:
     result = joinPath(it, f)
     if existsFile(result):
       return result.canonicalizePath
   result = ""
 
 proc rawFindFile2(f: string): string =
-  var it = PStrEntry(lazyPaths.head)
-  while it != nil:
-    result = joinPath(it.data, f)
+  for i, it in lazyPaths:
+    result = joinPath(it, f)
     if existsFile(result):
-      bringToFront(lazyPaths, it)
+      # bring to front
+      for j in countDown(i,1):
+        swap(lazyPaths[j], lazyPaths[j-1])
+      
       return result.canonicalizePath
-    it = PStrEntry(it.next)
   result = ""
 
 template patchModule() {.dirty.} =
diff --git a/compiler/passes.nim b/compiler/passes.nim
index abab599b6..7966ee88d 100644
--- a/compiler/passes.nim
+++ b/compiler/passes.nim
@@ -11,7 +11,7 @@
 # `TPass` interface.
 
 import
-  strutils, lists, options, ast, astalgo, llstream, msgs, platform, os,
+  strutils, options, ast, astalgo, llstream, msgs, platform, os,
   condsyms, idents, renderer, types, extccomp, math, magicsys, nversion,
   nimsets, syntaxes, times, rodread, idgen, modulegraphs
 
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index bcb0461f2..4476dab72 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -11,7 +11,7 @@
 
 import
   os, platform, condsyms, ast, astalgo, idents, semdata, msgs, renderer,
-  wordrecg, ropes, options, strutils, lists, extccomp, math, magicsys, trees,
+  wordrecg, ropes, options, strutils, extccomp, math, magicsys, trees,
   rodread, types, lookups
 
 const
@@ -218,20 +218,19 @@ proc processCallConv(c: PContext, n: PNode) =
     var sw = whichKeyword(n.sons[1].ident)
     case sw
     of FirstCallConv..LastCallConv:
-      POptionEntry(c.optionStack.tail).defaultCC = wordToCallConv(sw)
+      c.optionStack[^1].defaultCC = wordToCallConv(sw)
     else: localError(n.info, errCallConvExpected)
   else:
     localError(n.info, errCallConvExpected)
 
 proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
-  var it = PLib(c.libs.head)
-  while it != nil:
-    if it.kind == kind:
-      if trees.exprStructuralEquivalent(it.path, path): return it
-    it = PLib(it.next)
+  for it in c.libs:
+    if it.kind == kind and trees.exprStructuralEquivalent(it.path, path):
+      return it
+      
   result = newLib(kind)
   result.path = path
-  append(c.libs, result)
+  c.libs.add result
   if path.kind in {nkStrLit..nkTripleStrLit}:
     result.isOverriden = options.isDynlibOverride(path.strVal)
 
@@ -254,7 +253,7 @@ proc processDynLib(c: PContext, n: PNode, sym: PSym) =
   if (sym == nil) or (sym.kind == skModule):
     let lib = getLib(c, libDynamic, expectDynlibNode(c, n))
     if not lib.isOverriden:
-      POptionEntry(c.optionStack.tail).dynlib = lib
+      c.optionStack[^1].dynlib = lib
   else:
     if n.kind == nkExprColonExpr:
       var lib = getLib(c, libDynamic, expectDynlibNode(c, n))
@@ -350,12 +349,12 @@ proc processPush(c: PContext, n: PNode, start: int) =
   if n.sons[start-1].kind == nkExprColonExpr:
     localError(n.info, errGenerated, "':' after 'push' not supported")
   var x = newOptionEntry()
-  var y = POptionEntry(c.optionStack.tail)
+  var y = c.optionStack[^1]
   x.options = gOptions
   x.defaultCC = y.defaultCC
   x.dynlib = y.dynlib
   x.notes = gNotes
-  append(c.optionStack, x)
+  c.optionStack.add(x)
   for i in countup(start, sonsLen(n) - 1):
     if processOption(c, n.sons[i]):
       # simply store it somewhere:
@@ -365,12 +364,12 @@ proc processPush(c: PContext, n: PNode, start: int) =
     #localError(n.info, errOptionExpected)
 
 proc processPop(c: PContext, n: PNode) =
-  if c.optionStack.counter <= 1:
+  if c.optionStack.len <= 1:
     localError(n.info, errAtPopWithoutPush)
   else:
-    gOptions = POptionEntry(c.optionStack.tail).options
-    gNotes = POptionEntry(c.optionStack.tail).notes
-    remove(c.optionStack, c.optionStack.tail)
+    gOptions = c.optionStack[^1].options
+    gNotes = c.optionStack[^1].notes
+    c.optionStack.setLen(c.optionStack.len - 1)
 
 proc processDefine(c: PContext, n: PNode) =
   if (n.kind == nkExprColonExpr) and (n.sons[1].kind == nkIdent):
@@ -977,8 +976,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: int,
 proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
                       validPragmas: TSpecialWords) =
   if sym != nil and sym.kind != skModule:
-    var it = POptionEntry(c.optionStack.head)
-    while it != nil:
+    for it in c.optionStack:
       let o = it.otherPragmas
       if not o.isNil:
         pushInfoContext(n.info)
@@ -986,11 +984,10 @@ proc implicitPragmas*(c: PContext, sym: PSym, n: PNode,
           if singlePragma(c, sym, o, i, validPragmas):
             internalError(n.info, "implicitPragmas")
         popInfoContext()
-      it = it.next.POptionEntry
 
     if lfExportLib in sym.loc.flags and sfExportc notin sym.flags:
       localError(n.info, errDynlibRequiresExportc)
-    var lib = POptionEntry(c.optionStack.tail).dynlib
+    var lib = c.optionStack[^1].dynlib
     if {lfDynamicLib, lfHeader} * sym.loc.flags == {} and
         sfImportc in sym.flags and lib != nil:
       incl(sym.loc.flags, lfDynamicLib)
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 1602988dd..5ce8414d6 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -10,7 +10,7 @@
 # This module implements the renderer of the standard Nim representation.
 
 import
-  lexer, options, idents, strutils, ast, msgs, lists
+  lexer, options, idents, strutils, ast, msgs
 
 type
   TRenderFlag* = enum
diff --git a/compiler/scriptconfig.nim b/compiler/scriptconfig.nim
index 9e94f1c19..0c31eadbe 100644
--- a/compiler/scriptconfig.nim
+++ b/compiler/scriptconfig.nim
@@ -12,7 +12,7 @@
 
 import
   ast, modules, idents, passes, passaux, condsyms,
-  options, nimconf, lists, sem, semdata, llstream, vm, vmdef, commands, msgs,
+  options, nimconf, sem, semdata, llstream, vm, vmdef, commands, msgs,
   os, times, osproc, wordrecg, strtabs, modulegraphs
 
 # we support 'cmpIgnoreStyle' natively for efficiency:
@@ -153,7 +153,7 @@ proc runNimScript*(cache: IdentCache; scriptName: string;
   registerPass(semPass)
   registerPass(evalPass)
 
-  appendStr(searchPaths, options.libpath)
+  searchPaths.add(options.libpath)
 
   var m = graph.makeModule(scriptName)
   incl(m.flags, sfMainModule)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index d73826965..682e9d0ca 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -10,7 +10,7 @@
 # This module implements the semantic checking pass.
 
 import
-  ast, strutils, hashes, lists, options, lexer, astalgo, trees, treetab,
+  ast, strutils, hashes, options, lexer, astalgo, trees, treetab,
   wordrecg, ropes, msgs, os, condsyms, idents, renderer, types, platform, math,
   magicsys, parser, nversion, nimsets, semfold, importer,
   procfind, lookups, rodread, pragmas, passes, semdata, semtypinst, sigmatch,
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 93599f49f..77d461007 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -10,15 +10,14 @@
 ## This module contains the data structures for the semantic checking phase.
 
 import
-  strutils, lists, intsets, options, lexer, ast, astalgo, trees, treetab,
+  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, rodread, vmdef,
   modulegraphs
 
 type
-  TOptionEntry* = object of lists.TListEntry # entries to put on a
-                                             # stack for pragma parsing
+  TOptionEntry* = object      # entries to put on a stack for pragma parsing
     options*: TOptions
     defaultCC*: TCallingConvention
     dynlib*: PLib
@@ -79,10 +78,10 @@ type
     inGenericInst*: int        # > 0 if we are instantiating a generic
     converters*: TSymSeq       # sequence of converters
     patterns*: TSymSeq         # sequence of pattern matchers
-    optionStack*: TLinkedList
+    optionStack*: seq[POptionEntry]
     symMapping*: TIdTable      # every gensym'ed symbol needs to be mapped
                                # to some new symbol in a generic instantiation
-    libs*: TLinkedList         # all libs used by this module
+    libs*: seq[PLib]           # all libs used by this module
     semConstExpr*: proc (c: PContext, n: PNode): PNode {.nimcall.} # for the pragmas
     semExpr*: proc (c: PContext, n: PNode, flags: TExprFlags = {}): PNode {.nimcall.}
     semTryExpr*: proc (c: PContext, n: PNode,flags: TExprFlags = {}): PNode {.nimcall.}
@@ -130,7 +129,6 @@ proc getCurrOwner*(c: PContext): PSym =
   # owner field of syms)
   # the documentation comment always gets
   # assigned to the current owner
-  # BUGFIX: global array is needed!
   result = c.graph.owners[^1]
 
 proc pushOwner*(c: PContext; owner: PSym) =
@@ -142,7 +140,7 @@ proc popOwner*(c: PContext) =
   else: internalError("popOwner")
 
 proc lastOptionEntry*(c: PContext): POptionEntry =
-  result = POptionEntry(c.optionStack.tail)
+  result = c.optionStack[^1]
 
 proc popProcCon*(c: PContext) {.inline.} = c.p = c.p.next
 
@@ -185,9 +183,9 @@ proc newOptionEntry*(): POptionEntry =
 proc newContext*(graph: ModuleGraph; module: PSym; cache: IdentCache): PContext =
   new(result)
   result.ambiguousSymbols = initIntSet()
-  initLinkedList(result.optionStack)
-  initLinkedList(result.libs)
-  append(result.optionStack, newOptionEntry())
+  result.optionStack = @[]
+  result.libs = @[]
+  result.optionStack.add(newOptionEntry())
   result.module = module
   result.friendModules = @[module]
   result.converters = @[]
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 64787b82c..6db7724f9 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -2106,7 +2106,7 @@ proc semBlock(c: PContext, n: PNode): PNode =
     var labl = newSymG(skLabel, n.sons[0], c)
     if sfGenSym notin labl.flags:
       addDecl(c, labl)
-      n.sons[0] = newSymNode(labl, n.sons[0].info)
+    n.sons[0] = newSymNode(labl, n.sons[0].info)
     suggestSym(n.sons[0].info, labl, c.graph.usageSym)
     styleCheckDef(labl)
   n.sons[1] = semExpr(c, n.sons[1])
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 749deded1..58239d23e 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -11,7 +11,7 @@
 # and evaluation phase
 
 import
-  strutils, lists, options, ast, astalgo, trees, treetab, nimsets, times,
+  strutils, options, ast, astalgo, trees, treetab, nimsets, times,
   nversion, platform, math, msgs, os, condsyms, idents, renderer, types,
   commands, magicsys, saturate
 
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index bc80c41ad..9c05ab2f9 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -174,7 +174,11 @@ proc semGenericStmt(c: PContext, n: PNode,
     # XXX for example: ``result.add`` -- ``add`` needs to be looked up here...
     var dummy: bool
     result = fuzzyLookup(c, n, flags, ctx, dummy)
-  of nkEmpty, nkSym..nkNilLit:
+  of nkSym:
+    let a = n.sym
+    let b = getGenSym(c, a)
+    if b != a: n.sym = b
+  of nkEmpty, succ(nkSym)..nkNilLit:
     # see tests/compile/tgensymgeneric.nim:
     # We need to open the gensym'ed symbol again so that the instantiation
     # creates a fresh copy; but this is wrong the very first reason for gensym
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 0dfcdc0db..5ecba3ab0 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -30,6 +30,7 @@ proc semBreakOrContinue(c: PContext, n: PNode): PNode =
       of nkIdent: s = lookUp(c, n.sons[0])
       of nkSym: s = n.sons[0].sym
       else: illFormedAst(n)
+      s = getGenSym(c, s)
       if s.kind == skLabel and s.owner.id == c.p.owner.id:
         var x = newSymNode(s)
         x.info = n.info
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 843bef1a8..d7134402f 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -384,11 +384,13 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
     checkSonsLen(n, 2)
     openScope(c)
     if n.sons[0].kind != nkEmpty:
-      # labels are always 'gensym'ed:
-      let s = newGenSym(skLabel, n.sons[0], c)
-      addPrelimDecl(c.c, s)
-      styleCheckDef(s)
-      n.sons[0] = newSymNode(s, n.sons[0].info)
+      addLocalDecl(c, n.sons[0], skLabel)
+      when false:
+        # labels are always 'gensym'ed:
+        let s = newGenSym(skLabel, n.sons[0], c)
+        addPrelimDecl(c.c, s)
+        styleCheckDef(s)
+        n.sons[0] = newSymNode(s, n.sons[0].info)
     n.sons[1] = semTemplBody(c, n.sons[1])
     closeScope(c)
   of nkTryStmt:
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 98e221b56..0c53c0cbf 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -19,7 +19,7 @@
 # * transforms 'defer' into a 'try finally' statement
 
 import
-  intsets, strutils, lists, options, ast, astalgo, trees, treetab, msgs, os,
+  intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
   idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
   lambdalifting, sempass2, lowerings, lookups
 
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index 3adf4670d..83776f16b 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -742,6 +742,8 @@ proc `$`*(node: NimNode): string {.compileTime.} =
     result = $node.symbol
   of nnkOpenSymChoice, nnkClosedSymChoice:
     result = $node[0]
+  of nnkAccQuoted:
+    result = $node[0]
   else:
     badNodeKind node.kind, "$"
 
diff --git a/tests/template/mgensym_generic_cross_module.nim b/tests/template/mgensym_generic_cross_module.nim
new file mode 100644
index 000000000..80b681db4
--- /dev/null
+++ b/tests/template/mgensym_generic_cross_module.nim
@@ -0,0 +1,14 @@
+
+template makeDomElement(x: untyped, name: string = nil) =
+  const tag {.gensym.} = if name == nil: astToStr(x) else: name
+
+  proc x*(p: int|float) =
+    echo tag, p
+
+  proc x*(p: string|cstring) =
+    echo tag, p
+
+#proc wrappedUp[T](x: T) =
+#  mixin foo, bar
+makeDomElement(foo, "foo")
+makeDomElement(bar)
diff --git a/tests/template/tgensym_generic_cross_module.nim b/tests/template/tgensym_generic_cross_module.nim
new file mode 100644
index 000000000..856ab676d
--- /dev/null
+++ b/tests/template/tgensym_generic_cross_module.nim
@@ -0,0 +1,14 @@
+discard """
+  output: '''foo55
+foo8.0
+fooaha
+bar7'''
+"""
+# bug #5419
+import mgensym_generic_cross_module
+
+foo(55)
+foo 8.0
+foo "aha"
+bar 7
+
diff --git a/tests/template/tgensym_label.nim b/tests/template/tgensym_label.nim
new file mode 100644
index 000000000..fd3b0a1ee
--- /dev/null
+++ b/tests/template/tgensym_label.nim
@@ -0,0 +1,18 @@
+
+# bug #5417
+import macros
+
+macro genBody: untyped =
+  let sbx = genSym(nskLabel, "test")
+  when true:
+    result = quote do:
+      block `sbx`:
+        break `sbx`
+  else:
+    template foo(s1, s2) =
+      block s1:
+        break s2
+    result = getAst foo(sbx, sbx)
+
+proc test() =
+  genBody()
diff --git a/tools/nimsuggest/nimsuggest.nim b/tools/nimsuggest/nimsuggest.nim
index f4d72b67e..57d343ae4 100644
--- a/tools/nimsuggest/nimsuggest.nim
+++ b/tools/nimsuggest/nimsuggest.nim
@@ -15,7 +15,7 @@ import strutils, os, parseopt, parseutils, sequtils, net, rdstdin, sexp
 # So we import that one instead.
 import compiler / [options, commands, modules, sem,
   passes, passaux, msgs, nimconf,
-  extccomp, condsyms, lists,
+  extccomp, condsyms,
   sigmatch, ast, scriptconfig,
   idents, modulegraphs, compilerlog, vm]
 
@@ -427,10 +427,8 @@ proc recompileFullProject(graph: ModuleGraph; cache: IdentCache) =
 
 proc mainThread(graph: ModuleGraph; cache: IdentCache) =
   if gLogging:
-    var it = searchPaths.head
-    while it != nil:
-      logStr(PStrEntry(it).data)
-      it = it.next
+    for it in searchPaths:
+      logStr(it)
 
   proc wrHook(line: string) {.closure.} =
     if gMode == mepc:
@@ -503,10 +501,8 @@ proc serveEpc(server: Socket; graph: ModuleGraph; cache: IdentCache) {.deprecate
   # Wait for connection
   accept(server, client)
   if gLogging:
-    var it = searchPaths.head
-    while it != nil:
-      logStr(PStrEntry(it).data)
-      it = it.next
+    for it in searchPaths:
+      logStr(it)
     msgs.writelnHook = proc (line: string) = logStr(line)
 
   while true:
@@ -559,7 +555,7 @@ proc mainCommand(graph: ModuleGraph; cache: IdentCache) =
   incl gGlobalOptions, optCaasEnabled
   isServing = true
   wantMainModule()
-  appendStr(searchPaths, options.libpath)
+  add(searchPaths, options.libpath)
   #if gProjectFull.len != 0:
     # current path is always looked first for modules
   #  prependStr(searchPaths, gProjectPath)