mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-22 00:41:28 +00:00
correct comparisons for nil strings/seqs
This commit is contained in:
@@ -980,10 +980,10 @@ proc genEcho(p: BProc, n: PNode) =
|
||||
var a: TLoc
|
||||
for it in n.sons:
|
||||
if it.skipConv.kind == nkNilLit:
|
||||
add(args, ", \"nil\"")
|
||||
add(args, ", \"\"")
|
||||
else:
|
||||
initLocExpr(p, it, a)
|
||||
addf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
|
||||
addf(args, ", $1? ($1)->data:\"\"", [rdLoc(a)])
|
||||
p.module.includeHeader("<base/log.h>")
|
||||
linefmt(p, cpsStmts, """Genode::log(""$1);$n""", args)
|
||||
else:
|
||||
@@ -1755,16 +1755,14 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||
var x: TLoc
|
||||
var a = e.sons[1]
|
||||
var b = e.sons[2]
|
||||
if (a.kind == nkNilLit) or (b.kind == nkNilLit):
|
||||
binaryExpr(p, e, d, "($1 == $2)")
|
||||
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
|
||||
if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
|
||||
initLocExpr(p, e.sons[2], x)
|
||||
putIntoDest(p, d, e,
|
||||
rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
||||
elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""):
|
||||
rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
||||
elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
|
||||
initLocExpr(p, e.sons[1], x)
|
||||
putIntoDest(p, d, e,
|
||||
rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
||||
rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
||||
else:
|
||||
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
||||
|
||||
|
||||
@@ -82,7 +82,6 @@ proc countDefinedSymbols*(): int =
|
||||
|
||||
proc initDefines*() =
|
||||
gSymbols = newStringTable(modeStyleInsensitive)
|
||||
defineSymbol("nimrod") # 'nimrod' is always defined
|
||||
# for bootstrapping purposes and old code:
|
||||
defineSymbol("nimhygiene")
|
||||
defineSymbol("niminheritable")
|
||||
@@ -115,3 +114,4 @@ proc initDefines*() =
|
||||
defineSymbol("nimHasNilChecks")
|
||||
defineSymbol("nimSymKind")
|
||||
defineSymbol("nimVmEqIdent")
|
||||
defineSymbol("nimNoNil")
|
||||
|
||||
@@ -1553,6 +1553,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||
result = newNodeIT(nkFloatLit, info, t)
|
||||
of tyCString, tyString:
|
||||
result = newNodeIT(nkStrLit, info, t)
|
||||
result.strVal = ""
|
||||
of tyVar, tyLent, tyPointer, tyPtr, tySequence, tyExpr,
|
||||
tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
|
||||
result = newNodeIT(nkNilLit, info, t)
|
||||
|
||||
@@ -645,7 +645,6 @@ template replaceImpl(str: string, pattern: Regex,
|
||||
let bounds = match.matchBounds
|
||||
result.add(str.substr(lastIdx, bounds.a - 1))
|
||||
let nextVal = replacement
|
||||
assert(nextVal != nil)
|
||||
result.add(nextVal)
|
||||
|
||||
lastIdx = bounds.b + 1
|
||||
|
||||
@@ -2412,8 +2412,9 @@ proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
|
||||
if seqToPtr(x) == seqToPtr(y):
|
||||
return true
|
||||
|
||||
if x.isNil or y.isNil:
|
||||
return false
|
||||
when not defined(nimNoNil):
|
||||
if x.isNil or y.isNil:
|
||||
return false
|
||||
|
||||
if x.len != y.len:
|
||||
return false
|
||||
@@ -4010,18 +4011,18 @@ proc addQuoted*[T](s: var string, x: T) =
|
||||
|
||||
when hasAlloc:
|
||||
# XXX: make these the default (or implement the NilObject optimization)
|
||||
proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} =
|
||||
proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect, deprecated.} =
|
||||
## Adds ``y`` to ``x`` unless ``x`` is not yet initialized; in that case,
|
||||
## ``x`` becomes ``@[y]``
|
||||
if x == nil: x = @[y]
|
||||
else: x.add(y)
|
||||
|
||||
proc safeAdd*(x: var string, y: char) =
|
||||
proc safeAdd*(x: var string, y: char) {.noSideEffect, deprecated.} =
|
||||
## Adds ``y`` to ``x``. If ``x`` is ``nil`` it is initialized to ``""``
|
||||
if x == nil: x = ""
|
||||
x.add(y)
|
||||
|
||||
proc safeAdd*(x: var string, y: string) =
|
||||
proc safeAdd*(x: var string, y: string) {.noSideEffect, deprecated.} =
|
||||
## Adds ``y`` to ``x`` unless ``x`` is not yet initalized; in that
|
||||
## case, ``x`` becomes ``y``
|
||||
if x == nil: x = y
|
||||
|
||||
@@ -22,21 +22,34 @@ proc resize(old: int): int {.inline.} =
|
||||
|
||||
proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
|
||||
if a == b: return 0
|
||||
if a == nil: return -1
|
||||
if b == nil: return 1
|
||||
let minlen = min(a.len, b.len)
|
||||
when defined(nimNoNil):
|
||||
let alen = if a == nil: 0 else: a.len
|
||||
let blen = if b == nil: 0 else: b.len
|
||||
else:
|
||||
if a == nil: return -1
|
||||
if b == nil: return 1
|
||||
let alen = a.len
|
||||
let blen = b.len
|
||||
let minlen = min(alen, blen)
|
||||
if minlen > 0:
|
||||
result = c_memcmp(addr a.data, addr b.data, minlen.csize)
|
||||
if result == 0:
|
||||
result = a.len - b.len
|
||||
result = alen - blen
|
||||
else:
|
||||
result = a.len - b.len
|
||||
result = alen - blen
|
||||
|
||||
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
||||
if a == b: return true
|
||||
if a == nil or b == nil: return false
|
||||
return a.len == b.len and
|
||||
equalMem(addr(a.data), addr(b.data), a.len)
|
||||
when defined(nimNoNil):
|
||||
let alen = if a == nil: 0 else: a.len
|
||||
let blen = if b == nil: 0 else: b.len
|
||||
else:
|
||||
if a == nil or b == nil: return false
|
||||
let alen = a.len
|
||||
let blen = b.len
|
||||
if alen == blen:
|
||||
if alen == 0: return true
|
||||
return equalMem(addr(a.data), addr(b.data), alen)
|
||||
|
||||
when declared(allocAtomic):
|
||||
template allocStr(size: untyped): untyped =
|
||||
|
||||
@@ -51,3 +51,59 @@ import strutils
|
||||
let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0']
|
||||
doAssert $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\\x00']"
|
||||
doAssert $cstring(unsafeAddr arr) == "Hello World!"
|
||||
|
||||
proc takes(c: cstring) =
|
||||
doAssert c == ""
|
||||
|
||||
proc testm() =
|
||||
var x: string
|
||||
# nil is mapped to "":
|
||||
takes(x)
|
||||
|
||||
testm()
|
||||
|
||||
# nil tests
|
||||
var xx: seq[string]
|
||||
var yy: string
|
||||
doAssert xx == @[]
|
||||
doAssert yy == ""
|
||||
|
||||
proc bar(arg: cstring): void =
|
||||
doAssert arg[0] == '\0'
|
||||
|
||||
proc baz(arg: openarray[char]): void =
|
||||
doAssert arg.len == 0
|
||||
|
||||
proc stringCompare(): void =
|
||||
var a,b,c,d,e,f,g: string
|
||||
a.add 'a'
|
||||
doAssert a == "a"
|
||||
b.add "bee"
|
||||
doAssert b == "bee"
|
||||
b.add g
|
||||
doAssert b == "bee"
|
||||
c.add 123.456
|
||||
doAssert c == "123.456"
|
||||
d.add 123456
|
||||
doAssert d == "123456"
|
||||
|
||||
doAssert e == ""
|
||||
doAssert "" == e
|
||||
doAssert nil == e
|
||||
doAssert e == nil
|
||||
doAssert f == g
|
||||
doAssert "" == ""
|
||||
doAssert "" == nil
|
||||
doAssert nil == ""
|
||||
|
||||
g.setLen(10)
|
||||
doAssert g == "\0\0\0\0\0\0\0\0\0\0"
|
||||
doAssert "" != "\0\0\0\0\0\0\0\0\0\0"
|
||||
|
||||
var nilstring: string
|
||||
bar(nilstring)
|
||||
baz(nilstring)
|
||||
|
||||
stringCompare()
|
||||
static:
|
||||
stringCompare()
|
||||
Reference in New Issue
Block a user