fixes #24941; missing < (less than), cmp for cstring (#24942)

fixes #24941

now `cmp` can select the correct version of cstring comparsions

(cherry picked from commit 42a4adb4a5)
This commit is contained in:
ringabout
2025-05-10 14:26:21 +08:00
committed by narimiran
parent d89fd45b9e
commit ee916f051b
4 changed files with 86 additions and 3 deletions

View File

@@ -335,6 +335,12 @@ proc registerAdditionalOps*(c: PCtx) =
registerCallback c, "stdlib.hashes.hashVmImplByte", hashVmImplByte
registerCallback c, "stdlib.hashes.hashVmImplChar", hashVmImplByte
registerCallback c, "stdlib.system.ltCStringVm", proc (a: VmArgs) =
setResult(a, getString(a, 0) < getString(a, 1))
registerCallback c, "stdlib.system.leCStringVm", proc (a: VmArgs) =
setResult(a, getString(a, 0) <= getString(a, 1))
if optBenchmarkVM in c.config.globalOptions or vmopsDanger in c.config.features:
wrap0(cpuTime, timesop)
else:

View File

@@ -2720,16 +2720,53 @@ proc procCall*(x: untyped) {.magic: "ProcCall", compileTime.} =
## ```
discard
proc strcmp(a, b: cstring): cint {.noSideEffect,
importc, header: "<string.h>".}
proc `==`*(x, y: cstring): bool {.magic: "EqCString", noSideEffect,
inline.} =
## Checks for equality between two `cstring` variables.
proc strcmp(a, b: cstring): cint {.noSideEffect,
importc, header: "<string.h>".}
if pointer(x) == pointer(y): result = true
elif pointer(x) == nil or pointer(y) == nil: result = false
else: result = strcmp(x, y) == 0
func ltCStringVm(x, y: cstring): bool {.inline.} =
discard "implemented in the vm ops"
func leCStringVm(x, y: cstring): bool {.inline.} =
discard "implemented in the vm ops"
func `<`*(x, y: cstring): bool {.inline.} =
if x == y:
result = false
elif x == nil:
result = true
elif y == nil:
result = false
else:
when nimvm:
result = ltCStringVm(x, y)
else:
when defined(js):
result = pointer(x) < pointer(y)
else:
result = strcmp(x, y) < 0
func `<=`*(x, y: cstring): bool {.inline.} =
if x == y: result = true
elif x == nil:
result = true
elif y == nil:
result = false
else:
when nimvm:
result = leCStringVm(x, y)
else:
when defined(js):
result = pointer(x) <= pointer(y)
else:
result = strcmp(x, y) <= 0
template closureScope*(body: untyped): untyped =
## Useful when creating a closure in a loop to capture local loop variables by
## their current iteration values.

View File

@@ -7,7 +7,7 @@ proc `<`[T](x, y: set[T]): bool
first type mismatch at position: 2
required type for y: set[T]
but expression 'x' is of type: set[range 1..5(uint8)]
20 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
21 other mismatching symbols have been suppressed; compile with --showAllMismatches:on to see them
expression: {1'u8, 5} < x'''
"""

View File

@@ -198,3 +198,43 @@ block: # bug #6549
doAssert $v == "18446744073709551615"
doAssert $float32(v) == "1.8446744e+19"
doAssert $float64(v) == "1.8446744073709552e+19"
proc bar2() =
var a = cstring"1233"
var b = cstring"1233"
if a == b: doAssert not(a<b)
doAssert not (a != b)
doAssert a <= b
doAssert not (a > b)
doAssert a >= b
doAssert not (a < b)
var c = cstring"a1345"
var d = cstring"hwr"
doAssert c < d
doAssert c <= d
doAssert not (c > d)
doAssert not (c > d)
doAssert c != d
doAssert not (c == d)
when not defined(js):
doAssert cstring(nil) < cstring""
doAssert cstring(nil) <= cstring""
doAssert not (cstring"" < cstring(nil))
doAssert not (cstring"" <= cstring(nil))
doAssert not (cstring(nil) > cstring"")
doAssert not (cstring(nil) >= cstring"")
doAssert cstring"" > cstring(nil)
doAssert cstring"" >= cstring(nil)
doAssert not (cstring"" == cstring(nil))
doAssert cstring(nil) != cstring""
doAssert cstring(nil) == cstring(nil)
doAssert cstring(nil) >= cstring(nil)
doAssert cstring("") >= cstring("")
doAssert cstring(nil) <= cstring(nil)
doAssert cstring("") <= cstring("")
static: bar2()
bar2()