summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorflywind <43030857+xflywind@users.noreply.github.com>2021-02-18 13:13:52 -0600
committerGitHub <noreply@github.com>2021-02-18 20:13:52 +0100
commitcd274a5ac90edec6edccb5b8772bd34b4d1cd993 (patch)
tree0ab3bf0d4b757c438f31532c4ac221946fb95790
parent8fd1ed6dfe68c98bee7f69d26946df8003f930c5 (diff)
downloadNim-cd274a5ac90edec6edccb5b8772bd34b4d1cd993.tar.gz
fix stringify unsigned integer in JS and JS VM (#17086)
* fix js unsigned integer

* better
-rw-r--r--lib/system/dollars.nim47
-rw-r--r--tests/system/tdollars.nim28
2 files changed, 57 insertions, 18 deletions
diff --git a/lib/system/dollars.nim b/lib/system/dollars.nim
index 4c72c2901..238c59837 100644
--- a/lib/system/dollars.nim
+++ b/lib/system/dollars.nim
@@ -3,6 +3,26 @@ proc `$`*(x: int): string {.magic: "IntToStr", noSideEffect.}
   ## converted to a decimal string. ``$`` is Nim's general way of
   ## spelling `toString`:idx:.
 
+template dollarImpl(x: uint | uint64, result: var string) =
+  type destTyp = typeof(x)
+  if x == 0:
+    result = "0"
+  else:
+    result = newString(60)
+    var i = 0
+    var n = x
+    while n != 0:
+      let nn = n div destTyp(10)
+      result[i] = char(n - destTyp(10) * nn + ord('0'))
+      inc i
+      n = nn
+    result.setLen i
+
+    let half = i div 2
+    # Reverse
+    for t in 0 .. half-1: swap(result[t], result[i-t-1])
+
+
 when defined(js):
   import std/private/since
   since (1, 3):
@@ -10,34 +30,25 @@ when defined(js):
       ## Caveat: currently implemented as $(cast[int](x)), tied to current
       ## semantics of js' Number type.
       # for c, see strmantle.`$`
-      $(cast[int](x))
+      when nimvm:
+        dollarImpl(x, result)
+      else:
+        result = $(int(x))
 
     proc `$`*(x: uint64): string =
       ## Compatibility note:
       ## the results may change in future releases if/when js target implements
       ## 64bit ints.
       # pending https://github.com/nim-lang/RFCs/issues/187
-      $(cast[int](x))
+      when nimvm:
+        dollarImpl(x, result)
+      else:
+        result = $(cast[int](x))
 else:
   proc `$`*(x: uint64): string {.noSideEffect, raises: [].} =
     ## The stringify operator for an unsigned integer argument. Returns `x`
     ## converted to a decimal string.
-    if x == 0:
-      result = "0"
-    else:
-      result = newString(60)
-      var i = 0
-      var n = x
-      while n != 0:
-        let nn = n div 10'u64
-        result[i] = char(n - 10'u64 * nn + ord('0'))
-        inc i
-        n = nn
-      result.setLen i
-
-      let half = i div 2
-      # Reverse
-      for t in 0 .. half-1: swap(result[t], result[i-t-1])
+    dollarImpl(x, result)
 
 proc `$`*(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
   ## The stringify operator for an integer argument. Returns `x`
diff --git a/tests/system/tdollars.nim b/tests/system/tdollars.nim
index 62f77c857..04595c93c 100644
--- a/tests/system/tdollars.nim
+++ b/tests/system/tdollars.nim
@@ -101,6 +101,31 @@ block: # #14350, #16674, #16686 for JS
     doAssert nil1 == cstring("")
     doAssert nil2 == cstring("")
 
+block:
+  block:
+    let x = -1'i8
+    let y = uint32(x)
+
+    doAssert $y == "4294967295"
+
+  block:
+    let x = -1'i16
+    let y = uint32(x)
+
+    doAssert $y == "4294967295"
+
+  block:
+    let x = -1'i32
+    let y = uint32(x)
+
+    doAssert $y == "4294967295"
+
+  block:
+    let x = 4294967295'u32
+    doAssert $x == "4294967295"
+
+  block:
+    doAssert $(4294967295'u32) == "4294967295"
 
 proc main()=
   block:
@@ -124,5 +149,8 @@ proc main()=
     doAssert $(0) == "0"
 
 
+  doAssert $uint32.high == "4294967295"
+
+
 static: main()
 main()