diff options
author | Timothee Cour <timothee.cour2@gmail.com> | 2021-02-24 05:01:06 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-24 14:01:06 +0100 |
commit | 11a7fa68f646777214a81cddaf3043d642c94c6b (patch) | |
tree | 16c56f6cf4bf1cdfc8d4b22cb37f7504145bf789 | |
parent | 3021252ad44b60a35a58deb4abe4e001146dd09d (diff) | |
download | Nim-11a7fa68f646777214a81cddaf3043d642c94c6b.tar.gz |
fix #17159 items(cstring) works in VM (#17160)
* fix #17159 items(cstring) works in VM * improve test coverage tests/stdlib/tcstring.nim; add helpers: whenRuntimeJs, whenVMorJs * document items(cstring) * address comments
-rw-r--r-- | lib/system/iterators.nim | 59 | ||||
-rw-r--r-- | testament/lib/stdtest/testutils.nim | 24 | ||||
-rw-r--r-- | tests/arc/tcstring.nim | 16 | ||||
-rw-r--r-- | tests/stdlib/tcstring.nim | 101 |
4 files changed, 156 insertions, 44 deletions
diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim index 7f0076a44..7dac4ec77 100644 --- a/lib/system/iterators.nim +++ b/lib/system/iterators.nim @@ -56,31 +56,62 @@ iterator items*[T](a: set[T]): T {.inline.} = iterator items*(a: cstring): char {.inline.} = ## Iterates over each item of `a`. - when defined(js): + runnableExamples: + from std/sequtils import toSeq + assert toSeq("abc\0def".cstring) == @['a', 'b', 'c'] + assert toSeq("abc".cstring) == @['a', 'b', 'c'] + #[ + assert toSeq(nil.cstring) == @[] # xxx fails with SIGSEGV + this fails with SIGSEGV; unclear whether we want to instead yield nothing + or pay a small price to check for `nil`, a benchmark is needed. Note that + other procs support `nil`. + ]# + template impl() = var i = 0 - var L = len(a) - while i < L: + let n = len(a) + while i < n: yield a[i] inc(i) + when defined(js): impl() else: - var i = 0 - while a[i] != '\0': - yield a[i] - inc(i) + when nimvm: + # xxx `cstring` should behave like c backend instead. + impl() + else: + var i = 0 + while a[i] != '\0': + yield a[i] + inc(i) iterator mitems*(a: var cstring): var char {.inline.} = ## Iterates over each item of `a` so that you can modify the yielded value. - when defined(js): + # xxx this should give CT error in js RT. + runnableExamples: + from std/sugar import collect + var a = "abc\0def" + var b = a.cstring + let s = collect: + for bi in mitems(b): + if bi == 'b': bi = 'B' + bi + assert s == @['a', 'B', 'c'] + assert b == "aBc" + assert a == "aBc\0def" + + template impl() = var i = 0 - var L = len(a) - while i < L: + let n = len(a) + while i < n: yield a[i] inc(i) + when defined(js): impl() else: - var i = 0 - while a[i] != '\0': - yield a[i] - inc(i) + when nimvm: impl() + else: + var i = 0 + while a[i] != '\0': + yield a[i] + inc(i) iterator items*[T: enum and Ordinal](E: typedesc[T]): T = ## Iterates over the values of `E`. diff --git a/testament/lib/stdtest/testutils.nim b/testament/lib/stdtest/testutils.nim index 50dda22e2..36f951272 100644 --- a/testament/lib/stdtest/testutils.nim +++ b/testament/lib/stdtest/testutils.nim @@ -42,3 +42,27 @@ template enableRemoteNetworking*: bool = ## process calls, e.g. `testament all` calls itself, which in turns invokes ## a `nim` invocation (possibly via additional intermediate processes). getEnv("NIM_TESTAMENT_REMOTE_NETWORKING") == "1" + +template whenRuntimeJs*(bodyIf, bodyElse) = + ##[ + Behaves as `when defined(js) and not nimvm` (which isn't legal yet). + pending improvements to `nimvm`, this sugar helps; use as follows: + + whenRuntimeJs: + doAssert defined(js) + when nimvm: doAssert false + else: discard + do: + discard + ]## + when nimvm: bodyElse + else: + when defined(js): bodyIf + else: bodyElse + +template whenVMorJs*(bodyIf, bodyElse) = + ## Behaves as: `when defined(js) or nimvm` + when nimvm: bodyIf + else: + when defined(js): bodyIf + else: bodyElse diff --git a/tests/arc/tcstring.nim b/tests/arc/tcstring.nim deleted file mode 100644 index 79c8a7fcf..000000000 --- a/tests/arc/tcstring.nim +++ /dev/null @@ -1,16 +0,0 @@ -discard """ - cmd: "nim c --gc:arc -r $file" - nimout: '''hello -h -o -''' -""" - -# Issue #13321: [codegen] --gc:arc does not properly emit cstring, results in SIGSEGV - -let a = "hello".cstring -echo a -echo a[0] -echo a[4] -doAssert a[a.len] == '\0' - diff --git a/tests/stdlib/tcstring.nim b/tests/stdlib/tcstring.nim index 299925119..98da5d5c4 100644 --- a/tests/stdlib/tcstring.nim +++ b/tests/stdlib/tcstring.nim @@ -1,19 +1,92 @@ discard """ targets: "c cpp js" + matrix: "; --gc:arc" """ +from std/sugar import collect +from stdtest/testutils import whenRuntimeJs, whenVMorJs -block: # bug #13859 - let str = "abc".cstring - doAssert len(str).int8 == 3 - doAssert len(str).int16 == 3 - doAssert len(str).int32 == 3 - var str2 = "cde".cstring - doAssert len(str2).int8 == 3 - doAssert len(str2).int16 == 3 - doAssert len(str2).int32 == 3 - - const str3 = "abc".cstring - doAssert len(str3).int32 == 3 - doAssert len("abc".cstring).int16 == 3 - doAssert len("abc".cstring).float32 == 3.0 +template testMitems() = + block: + var a = "abc" + var b = a.cstring + let s = collect: + for bi in mitems(b): + if bi == 'b': bi = 'B' + bi + whenRuntimeJs: + discard # xxx mitems should give CT error instead of @['\x00', '\x00', '\x00'] + do: + doAssert s == @['a', 'B', 'c'] + + block: + var a = "abc\0def" + var b = a.cstring + let s = collect: + for bi in mitems(b): + if bi == 'b': bi = 'B' + bi + whenRuntimeJs: + discard # ditto + do: + doAssert s == @['a', 'B', 'c'] + +proc mainProc() = + testMitems() + +template main() = + block: # bug #13859 + let str = "abc".cstring + doAssert len(str).int8 == 3 + doAssert len(str).int16 == 3 + doAssert len(str).int32 == 3 + var str2 = "cde".cstring + doAssert len(str2).int8 == 3 + doAssert len(str2).int16 == 3 + doAssert len(str2).int32 == 3 + + const str3 = "abc".cstring + doAssert len(str3).int32 == 3 + doAssert len("abc".cstring).int16 == 3 + doAssert len("abc".cstring).float32 == 3.0 + + block: # bug #17159 + block: + var a = "abc" + var b = a.cstring + doAssert $(b, ) == """("abc",)""" + let s = collect: + for bi in b: bi + doAssert s == @['a', 'b', 'c'] + + block: + var a = "abc\0def" + var b = a.cstring + let s = collect: + for bi in b: bi + whenRuntimeJs: + doAssert $(b, ) == """("abc\x00def",)""" + doAssert s == @['a', 'b', 'c', '\x00', 'd', 'e', 'f'] + do: + doAssert $(b, ) == """("abc",)""" + doAssert s == @['a', 'b', 'c'] + + block: + when defined(gcArc): # xxx SIGBUS + discard + else: + mainProc() + when false: # xxx bug vm: Error: unhandled exception: 'node' is not accessible using discriminant 'kind' of type 'TFullReg' [FieldDefect] + testMitems() + + block: # bug #13321: [codegen] --gc:arc does not properly emit cstring, results in SIGSEGV + let a = "hello".cstring + doAssert $a == "hello" + doAssert $a[0] == "h" + doAssert $a[4] == "o" + whenVMorJs: discard # xxx this should work in vm, refs https://github.com/timotheecour/Nim/issues/619 + do: + doAssert a[a.len] == '\0' + +static: main() +main() |