diff options
author | metagn <metagngn@gmail.com> | 2023-04-11 22:20:20 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-11 21:20:20 +0200 |
commit | f05387045df55bf7123ee68002238e943716815e (patch) | |
tree | 9ba7959434162830612e31351eadbae79cf3bc37 /lib | |
parent | be06446ffecd7665651a25d6b07fade5cc019296 (diff) | |
download | Nim-f05387045df55bf7123ee68002238e943716815e.tar.gz |
int64/uint64 as bigint in JS (#21613)
* int64/uint64 as bigint in JS * fix CI * convert to compile option * fix lie * smaller diff, changelog entry
Diffstat (limited to 'lib')
-rw-r--r-- | lib/js/jscore.nim | 11 | ||||
-rw-r--r-- | lib/pure/json.nim | 2 | ||||
-rw-r--r-- | lib/pure/random.nim | 19 | ||||
-rw-r--r-- | lib/pure/strutils.nim | 10 | ||||
-rw-r--r-- | lib/pure/times.nim | 2 | ||||
-rw-r--r-- | lib/std/exitprocs.nim | 2 | ||||
-rw-r--r-- | lib/std/jsbigints.nim | 4 | ||||
-rw-r--r-- | lib/std/private/jsutils.nim | 17 | ||||
-rw-r--r-- | lib/system/ctypes.nim | 12 | ||||
-rw-r--r-- | lib/system/jssys.nim | 26 | ||||
-rw-r--r-- | lib/system/reprjs.nim | 8 |
11 files changed, 69 insertions, 44 deletions
diff --git a/lib/js/jscore.nim b/lib/js/jscore.nim index 781e8fd57..5147b550d 100644 --- a/lib/js/jscore.nim +++ b/lib/js/jscore.nim @@ -13,7 +13,7 @@ ## specific requirements and solely targets JavaScript, you should be using ## the relevant functions in the `math`, `json`, and `times` stdlib ## modules instead. -import std/private/since +import std/private/[since, jsutils] when not defined(js): {.error: "This module only works on the JavaScript platform".} @@ -74,9 +74,16 @@ proc parse*(d: DateLib, s: cstring): int {.importcpp.} proc newDate*(): DateTime {. importcpp: "new Date()".} -proc newDate*(date: int|int64|string): DateTime {. +proc newDate*(date: int|string): DateTime {. importcpp: "new Date(#)".} +whenJsNoBigInt64: + proc newDate*(date: int64): DateTime {. + importcpp: "new Date(#)".} +do: + proc newDate*(date: int64): DateTime {. + importcpp: "new Date(Number(#))".} + proc newDate*(year, month, day, hours, minutes, seconds, milliseconds: int): DateTime {. importcpp: "new Date(#,#,#,#,#,#,#)".} diff --git a/lib/pure/json.nim b/lib/pure/json.nim index d91da3545..45b22cea5 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1110,7 +1110,7 @@ proc initFromJson(dst: var JsonNode; jsonNode: JsonNode; jsonPath: var string) = dst = jsonNode.copy proc initFromJson[T: SomeInteger](dst: var T; jsonNode: JsonNode, jsonPath: var string) = - when T is uint|uint64 or (not defined(js) and int.sizeof == 4): + when T is uint|uint64 or int.sizeof == 4: verifyJsonKind(jsonNode, {JInt, JString}, jsonPath) case jsonNode.kind of JString: diff --git a/lib/pure/random.nim b/lib/pure/random.nim index c36ab445b..422f42a8b 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -72,7 +72,7 @@ runnableExamples: ## in the standard library import algorithm, math -import std/private/since +import std/private/[since, jsutils] when defined(nimPreviewSlimSystem): import std/[assertions] @@ -231,11 +231,14 @@ proc rand[T: uint | uint64](r: var Rand; max: T): T = let max = uint64(max) when T.high.uint64 == uint64.high: if max == uint64.high: return T(next(r)) + var iters = 0 while true: let x = next(r) # avoid `mod` bias - if x <= randMax - (randMax mod max): + if x <= randMax - (randMax mod max) or iters > 20: return T(x mod (max + 1)) + else: + inc iters proc rand*(r: var Rand; max: Natural): int {.benign.} = ## Returns a random integer in the range `0..max` using the given state. @@ -337,9 +340,9 @@ proc rand*[T: Ordinal or SomeFloat](r: var Rand; x: HSlice[T, T]): T = when T is SomeFloat: result = rand(r, x.b - x.a) + x.a else: # Integers and Enum types - when defined(js): + whenJsNoBigInt64: result = cast[T](rand(r, cast[uint](x.b) - cast[uint](x.a)) + cast[uint](x.a)) - else: + do: result = cast[T](rand(r, cast[uint64](x.b) - cast[uint64](x.a)) + cast[uint64](x.a)) proc rand*[T: Ordinal or SomeFloat](x: HSlice[T, T]): T = @@ -378,14 +381,14 @@ proc rand*[T: Ordinal](r: var Rand; t: typedesc[T]): T {.since: (1, 7, 1).} = when T is range or T is enum: result = rand(r, low(T)..high(T)) elif T is bool: - when defined(js): + whenJsNoBigInt64: result = (r.next or 0) < 0 - else: + do: result = cast[int64](r.next) < 0 else: - when defined(js): + whenJsNoBigInt64: result = cast[T](r.next shr (sizeof(uint)*8 - sizeof(T)*8)) - else: + do: result = cast[T](r.next shr (sizeof(uint64)*8 - sizeof(T)*8)) proc rand*[T: Ordinal](t: typedesc[T]): T = diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index c458d605e..0a77e8bf6 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -79,7 +79,7 @@ from unicode import toLower, toUpper export toLower, toUpper include "system/inclrtl" -import std/private/since +import std/private/[since, jsutils] from std/private/strimpl import cmpIgnoreStyleImpl, cmpIgnoreCaseImpl, startsWithImpl, endsWithImpl @@ -944,9 +944,9 @@ func toHex*[T: SomeInteger](x: T, len: Positive): string = doAssert b.toHex(4) == "1001" doAssert toHex(62, 3) == "03E" doAssert toHex(-8, 6) == "FFFFF8" - when defined(js): + whenJsNoBigInt64: toHexImpl(cast[BiggestUInt](x), len, x < 0) - else: + do: when T is SomeSignedInt: toHexImpl(cast[BiggestUInt](BiggestInt(x)), len, x < 0) else: @@ -957,9 +957,9 @@ func toHex*[T: SomeInteger](x: T): string = runnableExamples: doAssert toHex(1984'i64) == "00000000000007C0" doAssert toHex(1984'i16) == "07C0" - when defined(js): + whenJsNoBigInt64: toHexImpl(cast[BiggestUInt](x), 2*sizeof(T), x < 0) - else: + do: when T is SomeSignedInt: toHexImpl(cast[BiggestUInt](BiggestInt(x)), 2*sizeof(T), x < 0) else: diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 138f2d9ec..3d644d361 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -537,7 +537,7 @@ proc getDayOfWeek*(monthday: MonthdayRange, month: Month, year: int): WeekDay assertValidDate monthday, month, year # 1970-01-01 is a Thursday, we adjust to the previous Monday let days = toEpochDay(monthday, month, year) - 3 - let weeks = floorDiv(days, 7) + let weeks = floorDiv(days, 7'i64) let wd = days - weeks * 7 # The value of d is 0 for a Sunday, 1 for a Monday, 2 for a Tuesday, etc. # so we must correct for the WeekDay type. diff --git a/lib/std/exitprocs.nim b/lib/std/exitprocs.nim index 48b4fca7f..36f22a5d1 100644 --- a/lib/std/exitprocs.nim +++ b/lib/std/exitprocs.nim @@ -10,6 +10,8 @@ ## This module allows adding hooks to program exit. import locks +when defined(js) and not defined(nodejs): + import std/assertions type FunKind = enum kClosure, kNoconv # extend as needed diff --git a/lib/std/jsbigints.nim b/lib/std/jsbigints.nim index 04578fc87..fda299e7b 100644 --- a/lib/std/jsbigints.nim +++ b/lib/std/jsbigints.nim @@ -64,10 +64,10 @@ func wrapToUint*(this: JsBigInt; bits: Natural): JsBigInt {.importjs: runnableExamples: doAssert (big("3") + big("2") ** big("66")).wrapToUint(66) == big("3") -func toNumber*(this: JsBigInt): BiggestInt {.importjs: "Number(#)".} = +func toNumber*(this: JsBigInt): int {.importjs: "Number(#)".} = ## Does not do any bounds check and may or may not return an inexact representation. runnableExamples: - doAssert toNumber(big"2147483647") == 2147483647.BiggestInt + doAssert toNumber(big"2147483647") == 2147483647.int func `+`*(x, y: JsBigInt): JsBigInt {.importjs: "(# $1 #)".} = runnableExamples: diff --git a/lib/std/private/jsutils.nim b/lib/std/private/jsutils.nim index 836b3512a..fd1f395f3 100644 --- a/lib/std/private/jsutils.nim +++ b/lib/std/private/jsutils.nim @@ -79,5 +79,18 @@ when defined(js): assert not "123".toJs.isSafeInteger assert 123.isSafeInteger assert 123.toJs.isSafeInteger - assert 9007199254740991.toJs.isSafeInteger - assert not 9007199254740992.toJs.isSafeInteger + when false: + assert 9007199254740991.toJs.isSafeInteger + assert not 9007199254740992.toJs.isSafeInteger + +template whenJsNoBigInt64*(no64, yes64): untyped = + when defined(js): + when compiles(compileOption("jsbigint64")): + when compileOption("jsbigint64"): + yes64 + else: + no64 + else: + no64 + else: + no64 diff --git a/lib/system/ctypes.nim b/lib/system/ctypes.nim index f6a341477..b788274bd 100644 --- a/lib/system/ctypes.nim +++ b/lib/system/ctypes.nim @@ -12,16 +12,10 @@ type ## compiler supports. Currently this is `float64`, but it is ## platform-dependent in general. -when defined(js): - type BiggestUInt* = uint32 + BiggestUInt* = uint64 ## is an alias for the biggest unsigned integer type the Nim compiler - ## supports. Currently this is `uint32` for JS and `uint64` for other - ## targets. -else: - type BiggestUInt* = uint64 - ## is an alias for the biggest unsigned integer type the Nim compiler - ## supports. Currently this is `uint32` for JS and `uint64` for other - ## targets. + ## supports. Currently this is `uint64`, but it is platform-dependent + ## in general. when defined(windows): type diff --git a/lib/system/jssys.nim b/lib/system/jssys.nim index 4f64403fe..3bf506e1e 100644 --- a/lib/system/jssys.nim +++ b/lib/system/jssys.nim @@ -451,44 +451,44 @@ proc modInt(a, b: int): int {.asmNoStackFrame, compilerproc.} = return Math.trunc(`a` % `b`); """ -proc checkOverflowInt64(a: int) {.asmNoStackFrame, compilerproc.} = +proc checkOverflowInt64(a: int64) {.asmNoStackFrame, compilerproc.} = asm """ - if (`a` > 9223372036854775807 || `a` < -9223372036854775808) `raiseOverflow`(); + if (`a` > 9223372036854775807n || `a` < -9223372036854775808n) `raiseOverflow`(); """ -proc addInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = +proc addInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = asm """ var result = `a` + `b`; `checkOverflowInt64`(result); return result; """ -proc subInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = +proc subInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = asm """ var result = `a` - `b`; `checkOverflowInt64`(result); return result; """ -proc mulInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = +proc mulInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = asm """ var result = `a` * `b`; `checkOverflowInt64`(result); return result; """ -proc divInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = +proc divInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = asm """ - if (`b` == 0) `raiseDivByZero`(); - if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`(); - return Math.trunc(`a` / `b`); + if (`b` == 0n) `raiseDivByZero`(); + if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`(); + return `a` / `b`; """ -proc modInt64(a, b: int): int {.asmNoStackFrame, compilerproc.} = +proc modInt64(a, b: int64): int64 {.asmNoStackFrame, compilerproc.} = asm """ - if (`b` == 0) `raiseDivByZero`(); - if (`b` == -1 && `a` == 9223372036854775807) `raiseOverflow`(); - return Math.trunc(`a` % `b`); + if (`b` == 0n) `raiseDivByZero`(); + if (`b` == -1n && `a` == 9223372036854775807n) `raiseOverflow`(); + return `a` % `b`; """ proc negInt(a: int): int {.compilerproc.} = diff --git a/lib/system/reprjs.nim b/lib/system/reprjs.nim index 0818f9cc9..30e84ebee 100644 --- a/lib/system/reprjs.nim +++ b/lib/system/reprjs.nim @@ -12,6 +12,8 @@ when defined(nimPreviewSlimSystem): import std/formatfloat proc reprInt(x: int64): string {.compilerproc.} = $x +proc reprInt(x: uint64): string {.compilerproc.} = $x +proc reprInt(x: int): string {.compilerproc.} = $x proc reprFloat(x: float): string {.compilerproc.} = $x proc reprPointer(p: pointer): string {.compilerproc.} = @@ -192,8 +194,12 @@ proc reprAux(result: var string, p: pointer, typ: PNimType, return dec(cl.recDepth) case typ.kind - of tyInt..tyInt64, tyUInt..tyUInt64: + of tyInt..tyInt32, tyUInt..tyUInt32: add(result, reprInt(cast[int](p))) + of tyInt64: + add(result, reprInt(cast[int64](p))) + of tyUInt64: + add(result, reprInt(cast[uint64](p))) of tyChar: add(result, reprChar(cast[char](p))) of tyBool: |