summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorAndreas Rumpf <rumpf_a@web.de>2020-06-23 10:53:57 +0200
committerGitHub <noreply@github.com>2020-06-23 10:53:57 +0200
commitda29222f86f7689227ffe12605842d18c9bf0fc1 (patch)
tree312152d96e2313a81170c772ff7b51475299f344 /lib/pure
parenta9eee6db65e72e0e11cbf5faf0794b1b6ac8bd0c (diff)
downloadNim-da29222f86f7689227ffe12605842d18c9bf0fc1.tar.gz
init checks and 'out' parameters (#14521)
* I don't care about observable stores
* enforce explicit initializations
* cleaner code for the stdlib
* stdlib: use explicit initializations
* make tests green
* algorithm.nim: set result explicitly
* remove out parameters and bring the PR into a mergable state
* updated the changelog
Diffstat (limited to 'lib/pure')
-rw-r--r--lib/pure/algorithm.nim1
-rw-r--r--lib/pure/bitops.nim2
-rw-r--r--lib/pure/os.nim6
-rw-r--r--lib/pure/parseutils.nim16
-rw-r--r--lib/pure/pathnorm.nim2
-rw-r--r--lib/pure/strutils.nim22
-rw-r--r--lib/pure/times.nim18
-rw-r--r--lib/pure/typetraits.nim2
-rw-r--r--lib/pure/unicode.nim1
9 files changed, 48 insertions, 22 deletions
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 4a6c2510a..a277d1429 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -187,6 +187,7 @@ proc binarySearch*[T, K](a: openArray[T], key: K,
     else:
       return -1
 
+  result = 0
   if (len and (len - 1)) == 0:
     # when `len` is a power of 2, a faster shr can be used.
     var step = len shr 1
diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim
index 7dd171a38..4f22388f3 100644
--- a/lib/pure/bitops.nim
+++ b/lib/pure/bitops.nim
@@ -395,6 +395,8 @@ proc firstSetBitNim(x: uint64): int {.inline, noSideEffect.} =
   if k == 0:
     k = uint32(v shr 32'u32) and 0xFFFFFFFF'u32
     result = 32
+  else:
+    result = 0
   result += firstSetBitNim(k)
 
 proc fastlog2Nim(x: uint32): int {.inline, noSideEffect.} =
diff --git a/lib/pure/os.nim b/lib/pure/os.nim
index bb09c966f..dcb63458b 100644
--- a/lib/pure/os.nim
+++ b/lib/pure/os.nim
@@ -417,7 +417,8 @@ proc relativePath*(path, base: string, sep = DirSep): string {.
       if not sameRoot(path, base):
         return path
 
-  var f, b: PathIter
+  var f = default PathIter
+  var b = default PathIter
   var ff = (0, -1)
   var bb = (0, -1) # (int, int)
   result = newStringOfCap(path.len)
@@ -1053,6 +1054,7 @@ when defined(windows) or defined(posix) or defined(nintendoswitch):
         assert quoteShellCommand(["aaa", "", "c d"]) == "aaa \"\" \"c d\""
 
     # can't use `map` pending https://github.com/nim-lang/Nim/issues/8303
+    result = ""
     for i in 0..<args.len:
       if i > 0: result.add " "
       result.add quoteShell(args[i])
@@ -2981,7 +2983,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect], noW
           setLen(result, L)
           break
   elif defined(macosx):
-    var size: cuint32
+    var size = cuint32(0)
     getExecPath1(nil, size)
     result = newString(int(size))
     if getExecPath2(result, size):
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index c358005f1..baf238843 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -249,6 +249,7 @@ proc skipWhitespace*(s: string, start = 0): int {.inline.} =
     doAssert skipWhitespace(" Hello World", 0) == 1
     doAssert skipWhitespace("Hello World", 5) == 1
     doAssert skipWhitespace("Hello  World", 5) == 2
+  result = 0
   while start+result < s.len and s[start+result] in Whitespace: inc(result)
 
 proc skip*(s, token: string, start = 0): int {.inline.} =
@@ -260,6 +261,7 @@ proc skip*(s, token: string, start = 0): int {.inline.} =
     doAssert skip("2019-01-22", "19", 2) == 2
     doAssert skip("CAPlow", "CAP", 0) == 3
     doAssert skip("CAPlow", "cap", 0) == 0
+  result = 0
   while start+result < s.len and result < token.len and
       s[result+start] == token[result]:
     inc(result)
@@ -270,6 +272,7 @@ proc skipIgnoreCase*(s, token: string, start = 0): int =
   runnableExamples:
     doAssert skipIgnoreCase("CAPlow", "CAP", 0) == 3
     doAssert skipIgnoreCase("CAPlow", "cap", 0) == 3
+  result = 0
   while start+result < s.len and result < token.len and
       toLower(s[result+start]) == toLower(token[result]): inc(result)
   if result != token.len: result = 0
@@ -282,6 +285,7 @@ proc skipUntil*(s: string, until: set[char], start = 0): int {.inline.} =
     doAssert skipUntil("Hello World", {'W', 'e'}, 0) == 1
     doAssert skipUntil("Hello World", {'W'}, 0) == 6
     doAssert skipUntil("Hello World", {'W', 'd'}, 0) == 6
+  result = 0
   while start+result < s.len and s[result+start] notin until: inc(result)
 
 proc skipUntil*(s: string, until: char, start = 0): int {.inline.} =
@@ -293,6 +297,7 @@ proc skipUntil*(s: string, until: char, start = 0): int {.inline.} =
     doAssert skipUntil("Hello World", 'o', 4) == 0
     doAssert skipUntil("Hello World", 'W', 0) == 6
     doAssert skipUntil("Hello World", 'w', 0) == 11
+  result = 0
   while start+result < s.len and s[result+start] != until: inc(result)
 
 proc skipWhile*(s: string, toSkip: set[char], start = 0): int {.inline.} =
@@ -302,6 +307,7 @@ proc skipWhile*(s: string, toSkip: set[char], start = 0): int {.inline.} =
     doAssert skipWhile("Hello World", {'H', 'e'}) == 2
     doAssert skipWhile("Hello World", {'e'}) == 0
     doAssert skipWhile("Hello World", {'W', 'o', 'r'}, 6) == 3
+  result = 0
   while start+result < s.len and s[result+start] in toSkip: inc(result)
 
 proc parseUntil*(s: string, token: var string, until: set[char],
@@ -437,7 +443,7 @@ proc parseBiggestInt*(s: string, number: var BiggestInt, start = 0): int {.
     var res: BiggestInt
     doAssert parseBiggestInt("9223372036854775807", res, 0) == 19
     doAssert res == 9223372036854775807
-  var res: BiggestInt
+  var res = BiggestInt(0)
   # use 'res' for exception safety (don't write to 'number' in case of an
   # overflow exception):
   result = rawParseInt(s, res, start)
@@ -455,7 +461,7 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
     doAssert res == 2019
     doAssert parseInt("2019", res, 2) == 2
     doAssert res == 19
-  var res: BiggestInt
+  var res = BiggestInt(0)
   result = parseBiggestInt(s, res, start)
   when sizeof(int) <= 4:
     if res < low(int) or res > high(int):
@@ -518,7 +524,7 @@ proc parseBiggestUInt*(s: string, number: var BiggestUInt, start = 0): int {.
     doAssert res == 12
     doAssert parseBiggestUInt("1111111111111111111", res, 0) == 19
     doAssert res == 1111111111111111111'u64
-  var res: BiggestUInt
+  var res = BiggestUInt(0)
   # use 'res' for exception safety (don't write to 'number' in case of an
   # overflow exception):
   result = rawParseUInt(s, res, start)
@@ -536,7 +542,7 @@ proc parseUInt*(s: string, number: var uint, start = 0): int {.
     doAssert res == 3450
     doAssert parseUInt("3450", res, 2) == 2
     doAssert res == 50
-  var res: BiggestUInt
+  var res = BiggestUInt(0)
   result = parseBiggestUInt(s, res, start)
   when sizeof(BiggestUInt) > sizeof(uint) and sizeof(uint) <= 4:
     if res > 0xFFFF_FFFF'u64:
@@ -563,7 +569,7 @@ proc parseFloat*(s: string, number: var float, start = 0): int {.
     doAssert res == 32.57
     doAssert parseFloat("32.57", res, 3) == 2
     doAssert res == 57.00
-  var bf: BiggestFloat
+  var bf = BiggestFloat(0.0)
   result = parseBiggestFloat(s, bf, start)
   if result != 0:
     number = bf
diff --git a/lib/pure/pathnorm.nim b/lib/pure/pathnorm.nim
index 8763ba878..03a65bd60 100644
--- a/lib/pure/pathnorm.nim
+++ b/lib/pure/pathnorm.nim
@@ -44,7 +44,7 @@ proc next*(it: var PathIter; x: string): (int, int) =
   it.notFirst = true
 
 iterator dirs(x: string): (int, int) =
-  var it: PathIter
+  var it = default PathIter
   while hasNext(it, x): yield next(it, x)
 
 proc isDot(x: string; bounds: (int, int)): bool =
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 7c00de2d2..1ffc8bf22 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -1103,6 +1103,7 @@ proc parseInt*(s: string): int {.noSideEffect,
   ## If `s` is not a valid integer, `ValueError` is raised.
   runnableExamples:
     doAssert parseInt("-0042") == -42
+  result = 0
   let L = parseutils.parseInt(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid integer: " & s)
@@ -1112,6 +1113,7 @@ proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect,
   ## Parses a decimal integer value contained in `s`.
   ##
   ## If `s` is not a valid integer, `ValueError` is raised.
+  result = BiggestInt(0)
   let L = parseutils.parseBiggestInt(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid integer: " & s)
@@ -1121,6 +1123,7 @@ proc parseUInt*(s: string): uint {.noSideEffect,
   ## Parses a decimal unsigned integer value contained in `s`.
   ##
   ## If `s` is not a valid integer, `ValueError` is raised.
+  result = uint(0)
   let L = parseutils.parseUInt(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid unsigned integer: " & s)
@@ -1130,6 +1133,7 @@ proc parseBiggestUInt*(s: string): BiggestUInt {.noSideEffect,
   ## Parses a decimal unsigned integer value contained in `s`.
   ##
   ## If `s` is not a valid integer, `ValueError` is raised.
+  result = BiggestUInt(0)
   let L = parseutils.parseBiggestUInt(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid unsigned integer: " & s)
@@ -1143,6 +1147,7 @@ proc parseFloat*(s: string): float {.noSideEffect,
   runnableExamples:
     doAssert parseFloat("3.14") == 3.14
     doAssert parseFloat("inf") == 1.0/0
+  result = 0.0
   let L = parseutils.parseFloat(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid float: " & s)
@@ -1161,6 +1166,7 @@ proc parseBinInt*(s: string): int {.noSideEffect,
     doAssert a.parseBinInt() == 53
     doAssert b.parseBinInt() == 7
 
+  result = 0
   let L = parseutils.parseBin(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid binary integer: " & s)
@@ -1172,6 +1178,7 @@ proc parseOctInt*(s: string): int {.noSideEffect,
   ## If `s` is not a valid oct integer, `ValueError` is raised. `s` can have one
   ## of the following optional prefixes: ``0o``, ``0O``.  Underscores within
   ## `s` are ignored.
+  result = 0
   let L = parseutils.parseOct(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid oct integer: " & s)
@@ -1183,6 +1190,7 @@ proc parseHexInt*(s: string): int {.noSideEffect,
   ## If `s` is not a valid hex integer, `ValueError` is raised. `s` can have one
   ## of the following optional prefixes: ``0x``, ``0X``, ``#``.  Underscores
   ## within `s` are ignored.
+  result = 0
   let L = parseutils.parseHex(s, result, 0)
   if L != s.len or L == 0:
     raise newException(ValueError, "invalid hex integer: " & s)
@@ -1270,9 +1278,9 @@ macro genEnumStmt(typ: typedesc, argSym: typed, default: typed): untyped =
   result = nnkCaseStmt.newTree(nnkDotExpr.newTree(argSym,
                                                   bindSym"nimIdentNormalize"))
   # stores all processed field strings to give error msg for ambiguous enums
-  var foundFields: seq[string]
-  var fStr: string # string of current field
-  var fNum: BiggestInt # int value of current field
+  var foundFields: seq[string] = @[]
+  var fStr = "" # string of current field
+  var fNum = BiggestInt(0) # int value of current field
   for f in impl:
     case f.kind
     of nnkEmpty: continue # skip first node of `enumTy`
@@ -2028,6 +2036,7 @@ proc rfind*(s, sub: string, start: Natural = 0, last = -1): int {.noSideEffect,
   if sub.len == 0:
     return -1
   let last = if last == -1: s.high else: last
+  result = 0
   for i in countdown(last - sub.len + 1, start):
     for j in 0..sub.len-1:
       result = i
@@ -2044,6 +2053,7 @@ proc count*(s: string, sub: char): int {.noSideEffect,
   ##
   ## See also:
   ## * `countLines proc<#countLines,string>`_
+  result = 0
   for c in s:
     if c == sub: inc result
 
@@ -2054,6 +2064,7 @@ proc count*(s: string, subs: set[char]): int {.noSideEffect,
   ## See also:
   ## * `countLines proc<#countLines,string>`_
   doAssert card(subs) > 0
+  result = 0
   for c in s:
     if c in subs: inc result
 
@@ -2066,6 +2077,7 @@ proc count*(s: string, sub: string, overlapping: bool = false): int {.
   ## See also:
   ## * `countLines proc<#countLines,string>`_
   doAssert sub.len > 0
+  result = 0
   var i = 0
   while true:
     i = s.find(sub, i)
@@ -2313,7 +2325,7 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
       case s[i+1]:
       of 'x':
         inc i, 2
-        var c: int
+        var c = 0
         i += parseutils.parseHex(s, c, i, maxLen = 2)
         result.add(chr(c))
         dec i, 2
@@ -2514,7 +2526,7 @@ proc formatSize*(bytes: int64,
     xb: int64 = bytes
     fbytes: float
     lastXb: int64 = bytes
-    matchedIndex: int
+    matchedIndex = 0
     prefixes: array[9, string]
   if prefix == bpColloquial:
     prefixes = collPrefixes
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 7d82733e1..fb2f5e430 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -895,16 +895,16 @@ proc getTime*(): Time {.tags: [TimeEffect], benign.} =
       millis mod convert(Seconds, Milliseconds, 1).int)
     result = initTime(seconds, nanos)
   elif defined(macosx):
-    var a: Timeval
+    var a {.noinit.}: Timeval
     gettimeofday(a)
     result = initTime(a.tv_sec.int64,
                       convert(Microseconds, Nanoseconds, a.tv_usec.int))
   elif defined(posix):
-    var ts: Timespec
+    var ts {.noinit.}: Timespec
     discard clock_gettime(CLOCK_REALTIME, ts)
     result = initTime(ts.tv_sec.int64, ts.tv_nsec.int)
   elif defined(windows):
-    var f: FILETIME
+    var f {.noinit.}: FILETIME
     getSystemTimeAsFileTime(f)
     result = fromWinTime(rdFileTime(f))
 
@@ -1756,7 +1756,7 @@ proc formatPattern(dt: DateTime, pattern: FormatPattern, result: var string,
 proc parsePattern(input: string, pattern: FormatPattern, i: var int,
                   parsed: var ParsedTime, loc: DateTimeLocale): bool =
   template takeInt(allowedWidth: Slice[int], allowSign = false): int =
-    var sv: int
+    var sv = 0
     var pd = parseInt(input, sv, i, allowedWidth.b, allowSign)
     if pd < allowedWidth.a:
       return false
@@ -1987,6 +1987,7 @@ proc format*(dt: DateTime, f: TimeFormat,
     let dt = initDateTime(01, mJan, 2000, 00, 00, 00, utc())
     doAssert "2000-01-01" == dt.format(f)
   assertDateTimeInitialized dt
+  result = ""
   var idx = 0
   while idx <= f.patterns.high:
     case f.patterns[idx].FormatPattern
@@ -2284,7 +2285,7 @@ proc between*(startDt, endDt: DateTime): TimeInterval =
       endDate.monthday.dec
 
   # Years
-  result.years.inc endDate.year - startDate.year - 1
+  result.years = endDate.year - startDate.year - 1
   if (startDate.month, startDate.monthday) <= (endDate.month, endDate.monthday):
     result.years.inc
   startDate.year.inc result.years
@@ -2441,6 +2442,7 @@ proc evaluateInterval(dt: DateTime, interval: TimeInterval):
   var months = interval.years * 12 + interval.months
   var curYear = dt.year
   var curMonth = dt.month
+  result = default(tuple[adjDur, absDur: Duration])
   # Subtracting
   if months < 0:
     for mth in countdown(-1 * months, 1):
@@ -2562,17 +2564,17 @@ proc epochTime*(): float {.tags: [TimeEffect].} =
   ##
   ## ``getTime`` should generally be preferred over this proc.
   when defined(macosx):
-    var a: Timeval
+    var a {.noinit.}: Timeval
     gettimeofday(a)
     result = toBiggestFloat(a.tv_sec.int64) + toBiggestFloat(
         a.tv_usec)*0.00_0001
   elif defined(posix):
-    var ts: Timespec
+    var ts {.noinit.}: Timespec
     discard clock_gettime(CLOCK_REALTIME, ts)
     result = toBiggestFloat(ts.tv_sec.int64) +
       toBiggestFloat(ts.tv_nsec.int64) / 1_000_000_000
   elif defined(windows):
-    var f: winlean.FILETIME
+    var f {.noinit.}: winlean.FILETIME
     getSystemTimeAsFileTime(f)
     var i64 = rdFileTime(f) - epochDiff
     var secs = i64 div rateDiff
diff --git a/lib/pure/typetraits.nim b/lib/pure/typetraits.nim
index 9a215a353..317376405 100644
--- a/lib/pure/typetraits.nim
+++ b/lib/pure/typetraits.nim
@@ -112,7 +112,7 @@ macro genericParamsImpl(T: typedesc): untyped =
       of nnkBracketExpr:
         for i in 1..<impl.len:
           let ai = impl[i]
-          var ret: NimNode
+          var ret: NimNode = nil
           case ai.typeKind
           of ntyTypeDesc:
             ret = ai
diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim
index b550b0eac..8839a7767 100644
--- a/lib/pure/unicode.nim
+++ b/lib/pure/unicode.nim
@@ -39,6 +39,7 @@ proc runeLen*(s: string): int {.rtl, extern: "nuc$1".} =
     doAssert a.runeLen == 6
     ## note: a.len == 8
 
+  result = 0
   var i = 0
   while i < len(s):
     if uint(s[i]) <= 127: inc(i)