diff options
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) |