summary refs log tree commit diff stats
path: root/compiler/options.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/options.nim')
-rw-r--r--compiler/options.nim188
1 files changed, 98 insertions, 90 deletions
diff --git a/compiler/options.nim b/compiler/options.nim
index c9334991a..a95d9930a 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -9,7 +9,7 @@
 
 import
   os, strutils, strtabs, osproc, sets, lineinfos, platform,
-  prefixmatches
+  prefixmatches, pathutils
 
 from terminal import isatty
 from times import utc, fromUnix, local, getTime, format, DateTime
@@ -121,7 +121,8 @@ type
     notnil,
     dynamicBindSym,
     forLoopMacros,
-    caseStmtMacros
+    caseStmtMacros,
+    codeReordering,
 
   SymbolFilesOption* = enum
     disabledSf, writeOnlySf, readOnlySf, v2Sf
@@ -135,7 +136,7 @@ type
     External   ## file was introduced via .compile pragma
 
   Cfile* = object
-    cname*, obj*: string
+    cname*, obj*: AbsoluteFile
     flags*: set[CFileFlag]
   CfileList* = seq[Cfile]
 
@@ -203,13 +204,14 @@ type
                              ## symbols are always guaranteed to be style
                              ## insensitive. Otherwise hell would break lose.
     packageCache*: StringTableRef
-    searchPaths*: seq[string]
-    lazyPaths*: seq[string]
-    outFile*, prefixDir*, libpath*, nimcacheDir*: string
+    searchPaths*: seq[AbsoluteDir]
+    lazyPaths*: seq[AbsoluteDir]
+    outFile*: AbsoluteFile
+    prefixDir*, libpath*, nimcacheDir*: AbsoluteDir
     dllOverrides, moduleOverrides*: StringTableRef
     projectName*: string # holds a name like 'nim'
-    projectPath*: string # holds a path like /home/alice/projects/nim/compiler/
-    projectFull*: string # projectPath/projectName
+    projectPath*: AbsoluteDir # holds a path like /home/alice/projects/nim/compiler/
+    projectFull*: AbsoluteFile # projectPath/projectName
     projectIsStdin*: bool # whether we're compiling from stdin
     projectMainIdx*: FileIndex # the canonical path id of the main module
     command*: string # the main command (e.g. cc, check, scan, etc)
@@ -221,9 +223,9 @@ type
     # The string uses the formatting variables `path` and `line`.
 
      # the used compiler
-    cIncludes*: seq[string]  # directories to search for included files
-    cLibs*: seq[string]      # directories to search for lib files
-    cLinkedLibs*: seq[string]  # libraries to link
+    cIncludes*: seq[AbsoluteDir]  # directories to search for included files
+    cLibs*: seq[AbsoluteDir]      # directories to search for lib files
+    cLinkedLibs*: seq[string]     # libraries to link
 
     externalToLink*: seq[string]  # files to link in addition to the file
                                   # we compiled (*)
@@ -302,12 +304,13 @@ proc newConfigRef*(): ConfigRef =
     packageCache: newPackageCache(),
     searchPaths: @[],
     lazyPaths: @[],
-    outFile: "", prefixDir: "", libpath: "", nimcacheDir: "",
+    outFile: AbsoluteFile"", prefixDir: AbsoluteDir"",
+    libpath: AbsoluteDir"", nimcacheDir: AbsoluteDir"",
     dllOverrides: newStringTable(modeCaseInsensitive),
     moduleOverrides: newStringTable(modeStyleInsensitive),
     projectName: "", # holds a name like 'nim'
-    projectPath: "", # holds a path like /home/alice/projects/nim/compiler/
-    projectFull: "", # projectPath/projectName
+    projectPath: AbsoluteDir"", # holds a path like /home/alice/projects/nim/compiler/
+    projectFull: AbsoluteFile"", # projectPath/projectName
     projectIsStdin: false, # whether we're compiling from stdin
     projectMainIdx: FileIndex(0'i32), # the canonical path id of the main module
     command: "", # the main command (e.g. cc, check, scan, etc)
@@ -401,7 +404,7 @@ template optPreserveOrigSource*(conf: ConfigRef): untyped =
   optEmbedOrigSrc in conf.globalOptions
 
 const
-  genSubDir* = "nimcache"
+  genSubDir* = RelativeDir"nimcache"
   NimExt* = "nim"
   RodExt* = "rod"
   HtmlExt* = "html"
@@ -409,10 +412,10 @@ const
   TagsExt* = "tags"
   TexExt* = "tex"
   IniExt* = "ini"
-  DefaultConfig* = "nim.cfg"
-  DefaultConfigNims* = "config.nims"
-  DocConfig* = "nimdoc.cfg"
-  DocTexConfig* = "nimdoc.tex.cfg"
+  DefaultConfig* = RelativeFile"nim.cfg"
+  DefaultConfigNims* = RelativeFile"config.nims"
+  DocConfig* = RelativeFile"nimdoc.cfg"
+  DocTexConfig* = RelativeFile"nimdoc.tex.cfg"
 
 const oKeepVariableNames* = true
 
@@ -437,56 +440,61 @@ proc getConfigVar*(conf: ConfigRef; key: string, default = ""): string =
 proc setConfigVar*(conf: ConfigRef; key, val: string) =
   conf.configVars[key] = val
 
-proc getOutFile*(conf: ConfigRef; filename, ext: string): string =
-  if conf.outFile != "": result = conf.outFile
-  else: result = changeFileExt(filename, ext)
+proc getOutFile*(conf: ConfigRef; filename: RelativeFile, ext: string): AbsoluteFile =
+  if not conf.outFile.isEmpty: result = conf.outFile
+  else: result = conf.projectPath / changeFileExt(filename, ext)
 
-proc getPrefixDir*(conf: ConfigRef): string =
+proc getPrefixDir*(conf: ConfigRef): AbsoluteDir =
   ## Gets the prefix dir, usually the parent directory where the binary resides.
   ##
   ## This is overridden by some tools (namely nimsuggest) via the ``conf.prefixDir``
-  ## global.
-  if conf.prefixDir != "": result = conf.prefixDir
-  else: result = splitPath(getAppDir()).head
+  ## field.
+  if not conf.prefixDir.isEmpty: result = conf.prefixDir
+  else: result = AbsoluteDir splitPath(getAppDir()).head
 
 proc setDefaultLibpath*(conf: ConfigRef) =
   # set default value (can be overwritten):
-  if conf.libpath == "":
+  if conf.libpath.isEmpty:
     # choose default libpath:
     var prefix = getPrefixDir(conf)
     when defined(posix):
-      if prefix == "/usr": conf.libpath = "/usr/lib/nim"
-      elif prefix == "/usr/local": conf.libpath = "/usr/local/lib/nim"
-      else: conf.libpath = joinPath(prefix, "lib")
-    else: conf.libpath = joinPath(prefix, "lib")
+      if prefix == AbsoluteDir"/usr":
+        conf.libpath = AbsoluteDir"/usr/lib/nim"
+      elif prefix == AbsoluteDir"/usr/local":
+        conf.libpath = AbsoluteDir"/usr/local/lib/nim"
+      else:
+        conf.libpath = prefix / RelativeDir"lib"
+    else:
+      conf.libpath = prefix / RelativeDir"lib"
 
     # Special rule to support other tools (nimble) which import the compiler
     # modules and make use of them.
     let realNimPath = findExe("nim")
     # Find out if $nim/../../lib/system.nim exists.
     let parentNimLibPath = realNimPath.parentDir.parentDir / "lib"
-    if not fileExists(conf.libpath / "system.nim") and
+    if not fileExists(conf.libpath.string / "system.nim") and
         fileExists(parentNimlibPath / "system.nim"):
-      conf.libpath = parentNimLibPath
+      conf.libpath = AbsoluteDir parentNimLibPath
 
-proc canonicalizePath*(conf: ConfigRef; path: string): string =
+proc canonicalizePath*(conf: ConfigRef; path: AbsoluteFile): AbsoluteFile =
   # on Windows, 'expandFilename' calls getFullPathName which doesn't do
   # case corrections, so we have to use this convoluted way of retrieving
   # the true filename (see tests/modules and Nimble uses 'import Uri' instead
   # of 'import uri'):
   when defined(windows):
-    result = path.expandFilename
-    for x in walkFiles(result):
-      return x
+    result = AbsoluteFile path.string.expandFilename
+    for x in walkFiles(result.string):
+      return AbsoluteFile x
   else:
-    result = path.expandFilename
+    result = AbsoluteFile path.string.expandFilename
 
-proc shortenDir*(conf: ConfigRef; dir: string): string =
+proc shortenDir*(conf: ConfigRef; dir: string): string {.
+    deprecated: "use 'relativeTo' instead".} =
   ## returns the interesting part of a dir
-  var prefix = conf.projectPath & DirSep
+  var prefix = conf.projectPath.string & DirSep
   if startsWith(dir, prefix):
     return substr(dir, len(prefix))
-  prefix = getPrefixDir(conf) & DirSep
+  prefix = getPrefixDir(conf).string & DirSep
   if startsWith(dir, prefix):
     return substr(dir, len(prefix))
   result = dir
@@ -507,89 +515,89 @@ proc getOsCacheDir(): string =
   when defined(posix):
     result = getEnv("XDG_CACHE_HOME", getHomeDir() / ".cache") / "nim"
   else:
-    result = getHomeDir() / genSubDir
+    result = getHomeDir() / genSubDir.string
 
-proc getNimcacheDir*(conf: ConfigRef): string =
+proc getNimcacheDir*(conf: ConfigRef): AbsoluteDir =
   # XXX projectName should always be without a file extension!
-  result = if conf.nimcacheDir.len > 0:
+  result = if not conf.nimcacheDir.isEmpty:
              conf.nimcacheDir
            elif conf.cmd == cmdCompileToJS:
-             shortenDir(conf, conf.projectPath) / genSubDir
-           else: getOsCacheDir() / splitFile(conf.projectName).name &
-             (if isDefined(conf, "release"): "_r" else: "_d")
+             conf.projectPath / genSubDir
+           else:
+            AbsoluteDir(getOsCacheDir() / splitFile(conf.projectName).name &
+               (if isDefined(conf, "release"): "_r" else: "_d"))
 
 proc pathSubs*(conf: ConfigRef; p, config: string): string =
   let home = removeTrailingDirSep(os.getHomeDir())
   result = unixToNativePath(p % [
-    "nim", getPrefixDir(conf),
-    "lib", conf.libpath,
+    "nim", getPrefixDir(conf).string,
+    "lib", conf.libpath.string,
     "home", home,
     "config", config,
     "projectname", conf.projectName,
-    "projectpath", conf.projectPath,
-    "projectdir", conf.projectPath,
-    "nimcache", getNimcacheDir(conf)])
+    "projectpath", conf.projectPath.string,
+    "projectdir", conf.projectPath.string,
+    "nimcache", getNimcacheDir(conf).string])
   if "~/" in result:
     result = result.replace("~/", home & '/')
 
-proc toGeneratedFile*(conf: ConfigRef; path, ext: string): string =
+proc toGeneratedFile*(conf: ConfigRef; path: AbsoluteFile,
+                      ext: string): AbsoluteFile =
   ## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod"
-  var (head, tail) = splitPath(path)
-  #if len(head) > 0: head = shortenDir(head & dirSep)
-  result = joinPath([getNimcacheDir(conf), changeFileExt(tail, ext)])
-  #echo "toGeneratedFile(", path, ", ", ext, ") = ", result
-
-proc completeGeneratedFilePath*(conf: ConfigRef; f: string, createSubDir: bool = true): string =
-  var (head, tail) = splitPath(f)
-  #if len(head) > 0: head = removeTrailingDirSep(shortenDir(head & dirSep))
-  var subdir = getNimcacheDir(conf) # / head
+  let (head, tail) = splitPath(path.string)
+  result = getNimcacheDir(conf) / RelativeFile changeFileExt(tail, ext)
+
+proc completeGeneratedFilePath*(conf: ConfigRef; f: AbsoluteFile,
+                                createSubDir: bool = true): AbsoluteFile =
+  let (head, tail) = splitPath(f.string)
+  let subdir = getNimcacheDir(conf)
   if createSubDir:
     try:
-      createDir(subdir)
+      createDir(subdir.string)
     except OSError:
-      writeLine(stdout, "cannot create directory: " & subdir)
+      writeLine(stdout, "cannot create directory: " & subdir.string)
       quit(1)
-  result = joinPath(subdir, tail)
+  result = subdir / RelativeFile tail
   #echo "completeGeneratedFilePath(", f, ") = ", result
 
-proc rawFindFile(conf: ConfigRef; f: string; suppressStdlib: bool): string =
+proc rawFindFile(conf: ConfigRef; f: RelativeFile; suppressStdlib: bool): AbsoluteFile =
   for it in conf.searchPaths:
-    if suppressStdlib and it.startsWith(conf.libpath):
+    if suppressStdlib and it.string.startsWith(conf.libpath.string):
       continue
-    result = joinPath(it, f)
-    if existsFile(result):
+    result = it / f
+    if fileExists(result):
       return canonicalizePath(conf, result)
-  result = ""
+  result = AbsoluteFile""
 
-proc rawFindFile2(conf: ConfigRef; f: string): string =
+proc rawFindFile2(conf: ConfigRef; f: RelativeFile): AbsoluteFile =
   for i, it in conf.lazyPaths:
-    result = joinPath(it, f)
-    if existsFile(result):
+    result = it / f
+    if fileExists(result):
       # bring to front
       for j in countDown(i,1):
         swap(conf.lazyPaths[j], conf.lazyPaths[j-1])
 
       return canonicalizePath(conf, result)
-  result = ""
+  result = AbsoluteFile""
 
 template patchModule(conf: ConfigRef) {.dirty.} =
-  if result.len > 0 and conf.moduleOverrides.len > 0:
-    let key = getPackageName(conf, result) & "_" & splitFile(result).name
+  if not result.isEmpty and conf.moduleOverrides.len > 0:
+    let key = getPackageName(conf, result.string) & "_" & splitFile(result).name
     if conf.moduleOverrides.hasKey(key):
       let ov = conf.moduleOverrides[key]
-      if ov.len > 0: result = ov
+      if ov.len > 0: result = AbsoluteFile(ov)
 
-proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): string {.procvar.} =
+proc findFile*(conf: ConfigRef; f: string; suppressStdlib = false): AbsoluteFile {.procvar.} =
   if f.isAbsolute:
-    result = if f.existsFile: f else: ""
+    result = if f.existsFile: AbsoluteFile(f) else: AbsoluteFile""
   else:
-    result = rawFindFile(conf, f, suppressStdlib)
-    if result.len == 0:
-      result = rawFindFile(conf, f.toLowerAscii, suppressStdlib)
-      if result.len == 0:
-        result = rawFindFile2(conf, f)
-        if result.len == 0:
-          result = rawFindFile2(conf, f.toLowerAscii)
+    result = rawFindFile(conf, RelativeFile f, suppressStdlib)
+    if result.isEmpty:
+      result = rawFindFile(conf, RelativeFile f.toLowerAscii, suppressStdlib)
+      if result.isEmpty:
+        result = rawFindFile2(conf, RelativeFile f)
+        if result.isEmpty:
+          result = rawFindFile2(conf, RelativeFile f.toLowerAscii)
   patchModule(conf)
 
 const stdlibDirs = [
@@ -599,7 +607,7 @@ const stdlibDirs = [
   "wrappers", "wrappers/linenoise",
   "windows", "posix", "js"]
 
-proc findModule*(conf: ConfigRef; modulename, currentModule: string): string =
+proc findModule*(conf: ConfigRef; modulename, currentModule: string): AbsoluteFile =
   # returns path to module
   const pkgPrefix = "pkg/"
   const stdPrefix = "std/"
@@ -610,13 +618,13 @@ proc findModule*(conf: ConfigRef; modulename, currentModule: string): string =
     if m.startsWith(stdPrefix):
       let stripped = m.substr(stdPrefix.len)
       for candidate in stdlibDirs:
-        let path = (conf.libpath / candidate / stripped)
+        let path = (conf.libpath.string / candidate / stripped)
         if fileExists(path):
           m = path
           break
     let currentPath = currentModule.splitFile.dir
-    result = currentPath / m
-    if not existsFile(result):
+    result = AbsoluteFile currentPath / m
+    if not fileExists(result):
       result = findFile(conf, m)
   patchModule(conf)