correct comparisons for nil strings/seqs
This commit is contained in:
parent
13a380bca6
commit
f64f9e50cc
7 changed files with 91 additions and 23 deletions
|
|
@ -980,10 +980,10 @@ proc genEcho(p: BProc, n: PNode) =
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
for it in n.sons:
|
for it in n.sons:
|
||||||
if it.skipConv.kind == nkNilLit:
|
if it.skipConv.kind == nkNilLit:
|
||||||
add(args, ", \"nil\"")
|
add(args, ", \"\"")
|
||||||
else:
|
else:
|
||||||
initLocExpr(p, it, a)
|
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>")
|
p.module.includeHeader("<base/log.h>")
|
||||||
linefmt(p, cpsStmts, """Genode::log(""$1);$n""", args)
|
linefmt(p, cpsStmts, """Genode::log(""$1);$n""", args)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1755,16 +1755,14 @@ proc genStrEquals(p: BProc, e: PNode, d: var TLoc) =
|
||||||
var x: TLoc
|
var x: TLoc
|
||||||
var a = e.sons[1]
|
var a = e.sons[1]
|
||||||
var b = e.sons[2]
|
var b = e.sons[2]
|
||||||
if (a.kind == nkNilLit) or (b.kind == nkNilLit):
|
if a.kind in {nkStrLit..nkTripleStrLit} and a.strVal == "":
|
||||||
binaryExpr(p, e, d, "($1 == $2)")
|
|
||||||
elif (a.kind in {nkStrLit..nkTripleStrLit}) and (a.strVal == ""):
|
|
||||||
initLocExpr(p, e.sons[2], x)
|
initLocExpr(p, e.sons[2], x)
|
||||||
putIntoDest(p, d, e,
|
putIntoDest(p, d, e,
|
||||||
rfmt(nil, "(($1) && ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
rfmt(nil, "(!($1) || ($1)->$2 == 0)", rdLoc(x), lenField(p)))
|
||||||
elif (b.kind in {nkStrLit..nkTripleStrLit}) and (b.strVal == ""):
|
elif b.kind in {nkStrLit..nkTripleStrLit} and b.strVal == "":
|
||||||
initLocExpr(p, e.sons[1], x)
|
initLocExpr(p, e.sons[1], x)
|
||||||
putIntoDest(p, d, e,
|
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:
|
else:
|
||||||
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
binaryExpr(p, e, d, "#eqStrings($1, $2)")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,6 @@ proc countDefinedSymbols*(): int =
|
||||||
|
|
||||||
proc initDefines*() =
|
proc initDefines*() =
|
||||||
gSymbols = newStringTable(modeStyleInsensitive)
|
gSymbols = newStringTable(modeStyleInsensitive)
|
||||||
defineSymbol("nimrod") # 'nimrod' is always defined
|
|
||||||
# for bootstrapping purposes and old code:
|
# for bootstrapping purposes and old code:
|
||||||
defineSymbol("nimhygiene")
|
defineSymbol("nimhygiene")
|
||||||
defineSymbol("niminheritable")
|
defineSymbol("niminheritable")
|
||||||
|
|
@ -115,3 +114,4 @@ proc initDefines*() =
|
||||||
defineSymbol("nimHasNilChecks")
|
defineSymbol("nimHasNilChecks")
|
||||||
defineSymbol("nimSymKind")
|
defineSymbol("nimSymKind")
|
||||||
defineSymbol("nimVmEqIdent")
|
defineSymbol("nimVmEqIdent")
|
||||||
|
defineSymbol("nimNoNil")
|
||||||
|
|
|
||||||
|
|
@ -1553,6 +1553,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||||
result = newNodeIT(nkFloatLit, info, t)
|
result = newNodeIT(nkFloatLit, info, t)
|
||||||
of tyCString, tyString:
|
of tyCString, tyString:
|
||||||
result = newNodeIT(nkStrLit, info, t)
|
result = newNodeIT(nkStrLit, info, t)
|
||||||
|
result.strVal = ""
|
||||||
of tyVar, tyLent, tyPointer, tyPtr, tySequence, tyExpr,
|
of tyVar, tyLent, tyPointer, tyPtr, tySequence, tyExpr,
|
||||||
tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
|
tyStmt, tyTypeDesc, tyStatic, tyRef, tyNil:
|
||||||
result = newNodeIT(nkNilLit, info, t)
|
result = newNodeIT(nkNilLit, info, t)
|
||||||
|
|
|
||||||
|
|
@ -645,7 +645,6 @@ template replaceImpl(str: string, pattern: Regex,
|
||||||
let bounds = match.matchBounds
|
let bounds = match.matchBounds
|
||||||
result.add(str.substr(lastIdx, bounds.a - 1))
|
result.add(str.substr(lastIdx, bounds.a - 1))
|
||||||
let nextVal = replacement
|
let nextVal = replacement
|
||||||
assert(nextVal != nil)
|
|
||||||
result.add(nextVal)
|
result.add(nextVal)
|
||||||
|
|
||||||
lastIdx = bounds.b + 1
|
lastIdx = bounds.b + 1
|
||||||
|
|
|
||||||
|
|
@ -2412,6 +2412,7 @@ proc `==` *[T](x, y: seq[T]): bool {.noSideEffect.} =
|
||||||
if seqToPtr(x) == seqToPtr(y):
|
if seqToPtr(x) == seqToPtr(y):
|
||||||
return true
|
return true
|
||||||
|
|
||||||
|
when not defined(nimNoNil):
|
||||||
if x.isNil or y.isNil:
|
if x.isNil or y.isNil:
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
|
@ -4010,18 +4011,18 @@ proc addQuoted*[T](s: var string, x: T) =
|
||||||
|
|
||||||
when hasAlloc:
|
when hasAlloc:
|
||||||
# XXX: make these the default (or implement the NilObject optimization)
|
# 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,
|
## Adds ``y`` to ``x`` unless ``x`` is not yet initialized; in that case,
|
||||||
## ``x`` becomes ``@[y]``
|
## ``x`` becomes ``@[y]``
|
||||||
if x == nil: x = @[y]
|
if x == nil: x = @[y]
|
||||||
else: x.add(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 ``""``
|
## Adds ``y`` to ``x``. If ``x`` is ``nil`` it is initialized to ``""``
|
||||||
if x == nil: x = ""
|
if x == nil: x = ""
|
||||||
x.add(y)
|
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
|
## Adds ``y`` to ``x`` unless ``x`` is not yet initalized; in that
|
||||||
## case, ``x`` becomes ``y``
|
## case, ``x`` becomes ``y``
|
||||||
if x == nil: x = y
|
if x == nil: x = y
|
||||||
|
|
|
||||||
|
|
@ -22,21 +22,34 @@ proc resize(old: int): int {.inline.} =
|
||||||
|
|
||||||
proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
|
proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
|
||||||
if a == b: return 0
|
if a == b: return 0
|
||||||
|
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 a == nil: return -1
|
||||||
if b == nil: return 1
|
if b == nil: return 1
|
||||||
let minlen = min(a.len, b.len)
|
let alen = a.len
|
||||||
|
let blen = b.len
|
||||||
|
let minlen = min(alen, blen)
|
||||||
if minlen > 0:
|
if minlen > 0:
|
||||||
result = c_memcmp(addr a.data, addr b.data, minlen.csize)
|
result = c_memcmp(addr a.data, addr b.data, minlen.csize)
|
||||||
if result == 0:
|
if result == 0:
|
||||||
result = a.len - b.len
|
result = alen - blen
|
||||||
else:
|
else:
|
||||||
result = a.len - b.len
|
result = alen - blen
|
||||||
|
|
||||||
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
|
||||||
if a == b: return true
|
if a == b: return true
|
||||||
|
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
|
if a == nil or b == nil: return false
|
||||||
return a.len == b.len and
|
let alen = a.len
|
||||||
equalMem(addr(a.data), addr(b.data), 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):
|
when declared(allocAtomic):
|
||||||
template allocStr(size: untyped): untyped =
|
template allocStr(size: untyped): untyped =
|
||||||
|
|
|
||||||
|
|
@ -51,3 +51,59 @@ import strutils
|
||||||
let arr = ['H','e','l','l','o',' ','W','o','r','l','d','!','\0']
|
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 $arr == "['H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '!', '\\x00']"
|
||||||
doAssert $cstring(unsafeAddr arr) == "Hello World!"
|
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()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue