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
This commit is contained in:
Andreas Rumpf 2020-06-23 10:53:57 +02:00 • committed by GitHub
commit da29222f86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 355 additions and 257 deletions

View file

@ -535,9 +535,7 @@ proc copyLineInfo*(arg: NimNode, info: NimNode) {.magic: "NLineInfo", noSideEffe
proc lineInfoObj*(n: NimNode): LineInfo {.compileTime.} =
## Returns ``LineInfo`` of ``n``, using absolute path for ``filename``.
result.filename = n.getFile
result.line = n.getLine
result.column = n.getColumn
result = LineInfo(filename: n.getFile, line: n.getLine, column: n.getColumn)
proc lineInfo*(arg: NimNode): string {.compileTime.} =
## Return line info in the form `filepath(line, column)`.
@ -878,12 +876,14 @@ proc treeRepr*(n: NimNode): string {.compileTime, benign.} =
## Convert the AST `n` to a human-readable tree-like string.
##
## See also `repr`, `lispRepr`, and `astGenRepr`.
result = ""
n.treeTraverse(result, isLisp = false, indented = true)
proc lispRepr*(n: NimNode; indented = false): string {.compileTime, benign.} =
## Convert the AST ``n`` to a human-readable lisp-like string.
##
## See also ``repr``, ``treeRepr``, and ``astGenRepr``.
result = ""
n.treeTraverse(result, isLisp = true, indented = indented)
proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
@ -1611,6 +1611,7 @@ macro getCustomPragmaVal*(n: typed, cp: typed{nkSym}): untyped =
## assert(o.myField.getCustomPragmaVal(serializationKey) == "mf")
## assert(o.getCustomPragmaVal(serializationKey) == "mo")
## assert(MyObj.getCustomPragmaVal(serializationKey) == "mo")
result = nil
let pragmaNode = customPragmaNode(n)
for p in pragmaNode:
if p.kind in nnkPragmaCallKinds and p.len > 0 and p[0].kind == nnkSym and p[0] == cp:

View file

@ -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

View file

@ -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.} =

View file

@ -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):

View file

@ -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

View file

@ -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 =

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -4,7 +4,7 @@ const NimStackTraceMsgs = compileOption("stacktraceMsgs")
template procName*(): string =
## returns current C/C++ function name
when defined(c) or defined(cpp):
var name {.inject.}: cstring
var name {.inject, noinit.}: cstring
{.emit: "`name` = __func__;".}
$name
@ -12,7 +12,7 @@ template getPFrame*(): PFrame =
## avoids a function call (unlike `getFrame()`)
block:
when NimStackTrace:
var framePtr {.inject.}: PFrame
var framePtr {.inject, noinit.}: PFrame
{.emit: "`framePtr` = &FR_;".}
framePtr
@ -21,7 +21,7 @@ template setFrameMsg*(msg: string, prefix = " ") =
## in a given PFrame. Noop unless passing --stacktraceMsgs and --stacktrace
when NimStackTrace and NimStackTraceMsgs:
block:
var fr {.inject.}: PFrame
var fr {.inject, noinit.}: PFrame
{.emit: "`fr` = &FR_;".}
# consider setting a custom upper limit on size (analog to stack overflow)
frameMsgBuf.setLen fr.frameMsgLen

View file

@ -1767,6 +1767,7 @@ export iterators
proc find*[T, S](a: T, item: S): int {.inline.}=
## Returns the first index of `item` in `a` or -1 if not found. This requires
## appropriate `items` and `==` operations to work.
result = 0
for i in items(a):
if i == item: return
inc(result)
@ -2105,7 +2106,7 @@ when not defined(js):
# Linux 64bit system. -- That's because the stack direction is the other
# way around.
when declared(nimGC_setStackBottom):
var locals {.volatile.}: pointer
var locals {.volatile, noinit.}: pointer
locals = addr(locals)
nimGC_setStackBottom(locals)
@ -2274,7 +2275,9 @@ when notJSnotNims:
of 2: d = uint(cast[ptr uint16](a + uint(n.offset))[])
of 4: d = uint(cast[ptr uint32](a + uint(n.offset))[])
of 8: d = uint(cast[ptr uint64](a + uint(n.offset))[])
else: sysAssert(false, "getDiscriminant: invalid n.typ.size")
else:
d = 0'u
sysAssert(false, "getDiscriminant: invalid n.typ.size")
return d
proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode =

View file

@ -586,7 +586,8 @@ proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
sysAssert(size > 0, "getBigChunk 2")
var size = size # roundup(size, PageSize)
var fl, sl: int
var fl = 0
var sl = 0
mappingSearch(size, fl, sl)
sysAssert((size and PageMask) == 0, "getBigChunk: unaligned chunk")
result = findSuitableBlock(a, fl, sl)

View file

@ -11,6 +11,7 @@ proc `$`(x: int): string {.magic: "IntToStr", noSideEffect.}
proc `$`(info: InstantiationInfo): string =
# The +1 is needed here
# instead of overriding `$` (and changing its meaning), consider explicit name.
result = ""
result.toLocation(info.filename, info.line, info.column+1)
# ---------------------------------------------------------------------------

View file

@ -217,7 +217,7 @@ proc stackSize(stack: ptr GcStack): int {.noinline.} =
when nimCoroutines:
var pos = stack.pos
else:
var pos {.volatile.}: pointer
var pos {.volatile, noinit.}: pointer
pos = addr(pos)
if pos != nil:
@ -229,6 +229,7 @@ proc stackSize(stack: ptr GcStack): int {.noinline.} =
result = 0
proc stackSize(): int {.noinline.} =
result = 0
for stack in gch.stack.items():
result = result + stack.stackSize()
@ -303,7 +304,7 @@ when not defined(useNimRtl):
{.pop.}
proc isOnStack(p: pointer): bool =
var stackTop {.volatile.}: pointer
var stackTop {.volatile, noinit.}: pointer
stackTop = addr(stackTop)
var a = cast[ByteAddress](gch.getActiveStack().bottom)
var b = cast[ByteAddress](stackTop)

View file

@ -424,12 +424,12 @@ proc write*(f: File, b: bool) {.tags: [WriteIOEffect], benign.} =
else: write(f, "false")
proc write*(f: File, r: float32) {.tags: [WriteIOEffect], benign.} =
var buffer: array[65, char]
var buffer {.noinit.}: array[65, char]
discard writeFloatToBuffer(buffer, r)
if c_fprintf(f, "%s", buffer[0].addr) < 0: checkErr(f)
proc write*(f: File, r: BiggestFloat) {.tags: [WriteIOEffect], benign.} =
var buffer: array[65, char]
var buffer {.noinit.}: array[65, char]
discard writeFloatToBuffer(buffer, r)
if c_fprintf(f, "%s", buffer[0].addr) < 0: checkErr(f)
@ -591,7 +591,7 @@ when defined(posix) and not defined(nimscript):
proc open*(f: var File, filename: string,
mode: FileMode = fmRead,
bufSize: int = -1): bool {.tags: [], raises: [], benign.} =
bufSize: int = -1): bool {.tags: [], raises: [], benign.} =
## Opens a file named `filename` with given `mode`.
##
## Default mode is readonly. Returns true if the file could be opened.
@ -605,7 +605,7 @@ proc open*(f: var File, filename: string,
# How `fopen` handles opening a directory is not specified in ISO C and
# POSIX. We do not want to handle directories as regular files that can
# be opened.
var res: Stat
var res {.noinit.}: Stat
if c_fstat(getFileHandle(f2), res) >= 0'i32 and modeIsDir(res.st_mode):
close(f2)
return false
@ -759,7 +759,7 @@ proc readFile*(filename: string): TaintedString {.tags: [ReadIOEffect], benign.}
## Raises an IO exception in case of an error. If you need to call
## this inside a compile time macro you can use `staticRead
## <system.html#staticRead,string>`_.
var f: File
var f: File = nil
if open(f, filename):
try:
result = readAll(f)
@ -772,7 +772,7 @@ proc writeFile*(filename, content: string) {.tags: [WriteIOEffect], benign.} =
## Opens a file named `filename` for writing. Then writes the
## `content` completely to the file and closes the file afterwards.
## Raises an IO exception in case of an error.
var f: File
var f: File = nil
if open(f, filename, fmWrite):
try:
f.write(content)
@ -785,7 +785,7 @@ proc writeFile*(filename: string, content: openArray[byte]) {.since: (1, 1).} =
## Opens a file named `filename` for writing. Then writes the
## `content` completely to the file and closes the file afterwards.
## Raises an IO exception in case of an error.
var f: File
var f: File = nil
if open(f, filename, fmWrite):
try:
f.writeBuffer(unsafeAddr content[0], content.len)
@ -799,7 +799,7 @@ proc readLines*(filename: string, n: Natural): seq[TaintedString] =
## in case of an error. Raises EOF if file does not contain at least `n` lines.
## Available at compile time. A line of text may be delimited by ``LF`` or ``CRLF``.
## The newline character(s) are not part of the returned strings.
var f: File
var f: File = nil
if open(f, filename):
try:
result = newSeq[TaintedString](n)

View file

@ -102,6 +102,7 @@ proc reprSetAux(result: var string, p: pointer, typ: PNimType) =
of 4: u = cast[ptr uint32](p)[]
of 8: u = cast[ptr uint64](p)[]
else:
u = uint64(0)
var a = cast[PByteArray](p)
for i in 0 .. typ.size*8-1:
if (uint(a[i shr 3]) and (1'u shl (i and 7))) != 0:

View file

@ -31,6 +31,7 @@ proc countBits64(n: uint64): int {.compilerproc, inline.} =
proc cardSet(s: NimSet, len: int): int {.compilerproc, inline.} =
var i = 0
result = 0
when defined(x86) or defined(amd64):
while i < len - 8:
inc(result, countBits64((cast[ptr uint64](s[i].unsafeAddr))[]))

View file

@ -94,7 +94,7 @@ proc addFloat*(result: var string; x: float) =
when nimvm:
result.add $x
else:
var buffer: array[65, char]
var buffer {.noinit.}: array[65, char]
let n = writeFloatToBuffer(buffer, x)
result.addCstringN(cstring(buffer[0].addr), n)
@ -131,8 +131,8 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
i = start
sign = 1.0
kdigits, fdigits = 0
exponent: int
integer: uint64
exponent = 0
integer = uint64(0)
fracExponent = 0
expSign = 1
firstDigit = -1

View file

@ -63,6 +63,7 @@ proc ord(arg: Utf16Char): int = int(cast[uint16](arg))
proc len*(w: WideCString): int =
## returns the length of a widestring. This traverses the whole string to
## find the binary zero end marker!
result = 0
while int16(w[result]) != 0'i16: inc result
const