summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorNeelesh Chandola <neelesh.chandola@outlook.com>2018-12-14 09:34:46 +0530
committerNeelesh Chandola <neelesh.chandola@outlook.com>2018-12-14 09:34:46 +0530
commitf233b2fe8b0659674f10def4365a1c13f9bdebb8 (patch)
tree2267489131177677c9502c66a19da9501638be8d /compiler
parent31cff752e0687b663d15ebfa71a57d5723c5b876 (diff)
parent5b39c7aca91c1d20eb81425cf8f3854876aed475 (diff)
downloadNim-f233b2fe8b0659674f10def4365a1c13f9bdebb8.tar.gz
Merge remote-tracking branch 'upstream/devel' into better-error-message
Diffstat (limited to 'compiler')
-rw-r--r--compiler/cmdlinehelper.nim12
-rw-r--r--compiler/extccomp.nim2
-rw-r--r--compiler/pathutils.nim171
-rw-r--r--compiler/semstmts.nim4
-rw-r--r--compiler/semtypes.nim4
-rw-r--r--compiler/transf.nim5
6 files changed, 33 insertions, 165 deletions
diff --git a/compiler/cmdlinehelper.nim b/compiler/cmdlinehelper.nim
index 8bd073314..9fbf4a0b0 100644
--- a/compiler/cmdlinehelper.nim
+++ b/compiler/cmdlinehelper.nim
@@ -48,6 +48,15 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
   if self.suggestMode:
     conf.command = "nimsuggest"
 
+  # These defines/options should not be enabled while processing nimscript
+  # bug #4446, #9420, #8991, #9589, #9153
+  undefSymbol(conf.symbols, "profiler")
+  undefSymbol(conf.symbols, "memProfiler")
+  undefSymbol(conf.symbols, "nodejs")
+
+  # bug #9120
+  conf.globalOptions.excl(optTaintMode)
+
   proc runNimScriptIfExists(path: AbsoluteFile)=
     if fileExists(path):
       runNimScript(cache, path, freshDefines = false, conf)
@@ -79,6 +88,9 @@ proc loadConfigsAndRunMainCommand*(self: NimProg, cache: IdentCache; conf: Confi
         # 'nimsuggest foo.nims' means to just auto-complete the NimScript file
         discard
 
+  # Reload configuration from .cfg file
+  loadConfigs(DefaultConfig, cache, conf)
+
   # now process command line arguments again, because some options in the
   # command line can overwite the config file's settings
   extccomp.initVars(conf)
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 4b9e1c6fe..23f723e29 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -780,7 +780,7 @@ proc linkViaResponseFile(conf: ConfigRef; cmd: string) =
   let linkerArgs = conf.projectName & "_" & "linkerArgs.txt"
   let args = cmd.substr(i)
   # GCC's response files don't support backslashes. Junk.
-  if conf.cCompiler == ccGcc:
+  if conf.cCompiler == ccGcc or conf.cCompiler == ccCLang:
     writeFile(linkerArgs, args.replace('\\', '/'))
   else:
     writeFile(linkerArgs, args)
diff --git a/compiler/pathutils.nim b/compiler/pathutils.nim
index 703467bc4..80c479898 100644
--- a/compiler/pathutils.nim
+++ b/compiler/pathutils.nim
@@ -9,9 +9,8 @@
 
 ## Path handling utilities for Nim. Strictly typed code in order
 ## to avoid the never ending time sink in getting path handling right.
-## Might be a candidate for the stdlib later.
 
-import os, strutils
+import os, strutils, pathnorm
 
 type
   AbsoluteFile* = distinct string
@@ -45,130 +44,9 @@ proc cmpPaths*(x, y: AbsoluteDir): int {.borrow.}
 
 proc createDir*(x: AbsoluteDir) {.borrow.}
 
-type
-  PathIter = object
-    i, prev: int
-    notFirst: bool
-
-proc hasNext(it: PathIter; x: string): bool =
-  it.i < x.len
-
-proc next(it: var PathIter; x: string): (int, int) =
-  it.prev = it.i
-  if not it.notFirst and x[it.i] in {DirSep, AltSep}:
-    # absolute path:
-    inc it.i
-  else:
-    while it.i < x.len and x[it.i] notin {DirSep, AltSep}: inc it.i
-  if it.i > it.prev:
-    result = (it.prev, it.i-1)
-  elif hasNext(it, x):
-    result = next(it, x)
-
-  # skip all separators:
-  while it.i < x.len and x[it.i] in {DirSep, AltSep}: inc it.i
-  it.notFirst = true
-
-iterator dirs(x: string): (int, int) =
-  var it: PathIter
-  while hasNext(it, x): yield next(it, x)
-
-proc isDot(x: string; bounds: (int, int)): bool =
-  bounds[1] == bounds[0] and x[bounds[0]] == '.'
-
-proc isDotDot(x: string; bounds: (int, int)): bool =
-  bounds[1] == bounds[0] + 1 and x[bounds[0]] == '.' and x[bounds[0]+1] == '.'
-
-proc isSlash(x: string; bounds: (int, int)): bool =
-  bounds[1] == bounds[0] and x[bounds[0]] in {DirSep, AltSep}
-
-const canonDirSep = when isMainModule: '/' else: DirSep
-
-proc canon(x: string; result: var string; state: var int) =
-  # state: 0th bit set if isAbsolute path. Other bits count
-  # the number of path components.
-  for b in dirs(x):
-    if (state shr 1 == 0) and isSlash(x, b):
-      result.add canonDirSep
-      state = state or 1
-    elif result.len > (state and 1) and isDotDot(x, b):
-      var d = result.len
-      # f/..
-      while (d-1) > (state and 1) and result[d-1] notin {DirSep, AltSep}:
-        dec d
-      if d > 0: setLen(result, d-1)
-    elif isDot(x, b):
-      discard "discard the dot"
-    elif b[1] >= b[0]:
-      if result.len > 0 and result[^1] notin {DirSep, AltSep}:
-        result.add canonDirSep
-      result.add substr(x, b[0], b[1])
-    inc state, 2
-
-proc canon(x: string): string =
-  # - Turn multiple slashes into single slashes.
-  # - Resolve '/foo/../bar' to '/bar'.
-  # - Remove './' from the path.
-  result = newStringOfCap(x.len)
-  var state = 0
-  canon(x, result, state)
-
-when FileSystemCaseSensitive:
-  template `!=?`(a, b: char): bool = toLowerAscii(a) != toLowerAscii(b)
-else:
-  template `!=?`(a, b: char): bool = a != b
-
-proc relativeTo(full, base: string; sep = canonDirSep): string =
-  if full.len == 0: return ""
-  var f, b: PathIter
-  var ff = (0, -1)
-  var bb = (0, -1) # (int, int)
-  result = newStringOfCap(full.len)
-  # skip the common prefix:
-  while f.hasNext(full) and b.hasNext(base):
-    ff = next(f, full)
-    bb = next(b, base)
-    let diff = ff[1] - ff[0]
-    if diff != bb[1] - bb[0]: break
-    var same = true
-    for i in 0..diff:
-      if full[i + ff[0]] !=? base[i + bb[0]]:
-        same = false
-        break
-    if not same: break
-    ff = (0, -1)
-    bb = (0, -1)
-  #  for i in 0..diff:
-  #    result.add base[i + bb[0]]
-
-  # /foo/bar/xxx/ -- base
-  # /foo/bar/baz  -- full path
-  #   ../baz
-  # every directory that is in 'base', needs to add '..'
-  while true:
-    if bb[1] >= bb[0]:
-      if result.len > 0 and result[^1] != sep:
-        result.add sep
-      result.add ".."
-    if not b.hasNext(base): break
-    bb = b.next(base)
-
-  # add the rest of 'full':
-  while true:
-    if ff[1] >= ff[0]:
-      if result.len > 0 and result[^1] != sep:
-        result.add sep
-      for i in 0..ff[1] - ff[0]:
-        result.add full[i + ff[0]]
-    if not f.hasNext(full): break
-    ff = f.next(full)
-
 when true:
-  proc eqImpl(x, y: string): bool =
-    when FileSystemCaseSensitive:
-      result = cmpIgnoreCase(canon x, canon y) == 0
-    else:
-      result = canon(x) == canon(y)
+  proc eqImpl(x, y: string): bool {.inline.} =
+    result = cmpPaths(x, y) == 0
 
   proc `==`*(x, y: AbsoluteFile): bool = eqImpl(x.string, y.string)
   proc `==`*(x, y: AbsoluteDir): bool = eqImpl(x.string, y.string)
@@ -180,20 +58,20 @@ when true:
     assert(not isAbsolute(f.string))
     result = AbsoluteFile newStringOfCap(base.string.len + f.string.len)
     var state = 0
-    canon(base.string, result.string, state)
-    canon(f.string, result.string, state)
+    addNormalizePath(base.string, result.string, state)
+    addNormalizePath(f.string, result.string, state)
 
   proc `/`*(base: AbsoluteDir; f: RelativeDir): AbsoluteDir =
     #assert isAbsolute(base.string)
     assert(not isAbsolute(f.string))
     result = AbsoluteDir newStringOfCap(base.string.len + f.string.len)
     var state = 0
-    canon(base.string, result.string, state)
-    canon(f.string, result.string, state)
+    addNormalizePath(base.string, result.string, state)
+    addNormalizePath(f.string, result.string, state)
 
   proc relativeTo*(fullPath: AbsoluteFile, baseFilename: AbsoluteDir;
-                   sep = canonDirSep): RelativeFile =
-    RelativeFile(relativeTo(fullPath.string, baseFilename.string, sep))
+                   sep = DirSep): RelativeFile =
+    RelativeFile(relativePath(fullPath.string, baseFilename.string, sep))
 
   proc toAbsolute*(file: string; base: AbsoluteDir): AbsoluteFile =
     if isAbsolute(file): result = AbsoluteFile(file)
@@ -208,37 +86,8 @@ when true:
   proc writeFile*(x: AbsoluteFile; content: string) {.borrow.}
 
 when isMainModule:
-  doAssert canon"/foo/../bar" == "/bar"
-  doAssert canon"foo/../bar" == "bar"
-
-  doAssert canon"/f/../bar///" == "/bar"
-  doAssert canon"f/..////bar" == "bar"
-
-  doAssert canon"../bar" == "../bar"
-  doAssert canon"/../bar" == "/../bar"
-
-  doAssert canon("foo/../../bar/") == "../bar"
-  doAssert canon("./bla/blob/") == "bla/blob"
-  doAssert canon(".hiddenFile") == ".hiddenFile"
-  doAssert canon("./bla/../../blob/./zoo.nim") == "../blob/zoo.nim"
-
-  doAssert canon("C:/file/to/this/long") == "C:/file/to/this/long"
-  doAssert canon("") == ""
-  doAssert canon("foobar") == "foobar"
-  doAssert canon("f/////////") == "f"
-
-  doAssert relativeTo("/foo/bar//baz.nim", "/foo") == "bar/baz.nim"
-
-  doAssert relativeTo("/Users/me/bar/z.nim", "/Users/other/bad") == "../../me/bar/z.nim"
-
-  doAssert relativeTo("/Users/me/bar/z.nim", "/Users/other") == "../me/bar/z.nim"
-  doAssert relativeTo("/Users///me/bar//z.nim", "//Users/") == "me/bar/z.nim"
-  doAssert relativeTo("/Users/me/bar/z.nim", "/Users/me") == "bar/z.nim"
-  doAssert relativeTo("", "/users/moo") == ""
-  doAssert relativeTo("foo", "") == "foo"
-
   doAssert AbsoluteDir"/Users/me///" / RelativeFile"z.nim" == AbsoluteFile"/Users/me/z.nim"
-  doAssert relativeTo("/foo/bar.nim", "/foo/") == "bar.nim"
+  doAssert relativePath("/foo/bar.nim", "/foo/", '/') == "bar.nim"
 
 when isMainModule and defined(windows):
   let nasty = string(AbsoluteDir(r"C:\Users\rumpf\projects\nim\tests\nimble\nimbleDir\linkedPkgs\pkgB-#head\../../simplePkgs/pkgB-#head/") / RelativeFile"pkgA/module.nim")
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index aec03b492..5be57f614 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -807,11 +807,13 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode =
       typ = commonType(typ, x.sons[1])
       closeScope(c)
     of nkElse:
-      chckCovered = false
       checkSonsLen(x, 1, c.config)
       x.sons[0] = semExprBranchScope(c, x.sons[0])
       typ = commonType(typ, x.sons[0])
       hasElse = true
+      if chckCovered and covered == toCover(c, n.sons[0].typ):
+        localError(c.config, x.info, "invalid else, all cases are already covered")
+      chckCovered = false
     else:
       illFormedAst(x, c.config)
   if chckCovered:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 97ee062d1..2ca10ada2 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -90,7 +90,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
         if sonsLen(v) == 2:
           strVal = v.sons[1] # second tuple part is the string value
           if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCString}:
-            if not isOrdinalType(v.sons[0].typ):
+            if not isOrdinalType(v.sons[0].typ, allowEnumWithHoles=true):
               localError(c.config, v.sons[0].info, errOrdinalTypeExpected & "; given: " & typeToString(v.sons[0].typ, preferDesc))
             x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
           else:
@@ -101,7 +101,7 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
         strVal = v
         x = counter
       else:
-        if not isOrdinalType(v.typ):
+        if not isOrdinalType(v.typ, allowEnumWithHoles=true):
           localError(c.config, v.info, errOrdinalTypeExpected & "; given: " & typeToString(v.typ, preferDesc))
         x = getOrdValue(v)
       if i != 1:
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 7b2979dea..82be4158f 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -368,6 +368,11 @@ proc transformYield(c: PTransf, n: PNode): PTransNode =
   else:
     # we need to introduce new local variables:
     add(result, introduceNewLocalVars(c, c.transCon.forLoopBody.PNode))
+  if result.len > 0:
+    var changeNode = PNode(result[0])
+    changeNode.info = c.transCon.forStmt.info
+    for i, child in changeNode:
+      child.info = changeNode.info
 
 proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
   result = transformSons(c, n)