diff options
author | Bung <crc32@qq.com> | 2022-12-01 20:34:00 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-01 13:34:00 +0100 |
commit | 658b28dc5707601b39d9aad4b6bf79a9afff1e92 (patch) | |
tree | b8e10d4d1f2666c45c3b1dec23e7c03d5ba23be9 | |
parent | a70d3abd37819e7562f80f0c808788c3f5c62c55 (diff) | |
download | Nim-658b28dc5707601b39d9aad4b6bf79a9afff1e92.tar.gz |
tyInt tyUint fit target int bit width (#20829)
-rw-r--r-- | compiler/sigmatch.nim | 47 | ||||
-rw-r--r-- | compiler/types.nim | 40 | ||||
-rw-r--r-- | lib/std/formatfloat.nim | 6 | ||||
-rw-r--r-- | lib/std/private/digitsutils.nim | 6 | ||||
-rw-r--r-- | lib/std/private/dragonbox.nim | 38 | ||||
-rw-r--r-- | lib/std/private/schubfach.nim | 16 | ||||
-rw-r--r-- | lib/std/syncio.nim | 6 | ||||
-rw-r--r-- | lib/std/typedthreads.nim | 2 | ||||
-rw-r--r-- | lib/std/widestrs.nim | 379 | ||||
-rw-r--r-- | lib/system.nim | 14 | ||||
-rw-r--r-- | lib/system/alloc.nim | 10 | ||||
-rw-r--r-- | lib/system/arithmetics.nim | 8 | ||||
-rw-r--r-- | lib/system/bitmasks.nim | 2 | ||||
-rw-r--r-- | lib/system/strmantle.nim | 2 | ||||
-rw-r--r-- | lib/system/strs_v2.nim | 2 | ||||
-rw-r--r-- | tests/arithm/t1.nim | 2 | ||||
-rw-r--r-- | tests/varres/tprevent_forloopvar_mutations.nim | 9 |
17 files changed, 314 insertions, 275 deletions
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index 2c4f5d2ea..591a7c2a2 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -373,14 +373,16 @@ proc concreteType(c: TCandidate, t: PType; f: PType = nil): PType = else: result = t # Note: empty is valid here -proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = +proc handleRange(c: PContext, f, a: PType, min, max: TTypeKind): TTypeRelation = if a.kind == f.kind: result = isEqual else: let ab = skipTypes(a, {tyRange}) let k = ab.kind + let nf = c.config.normalizeKind(f.kind) + let na = c.config.normalizeKind(k) if k == f.kind: result = isSubrange - elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64, + elif k == tyInt and f.kind in {tyRange, tyInt..tyInt64, tyUInt..tyUInt64} and isIntLit(ab) and getInt(ab.n) >= firstOrd(nil, f) and getInt(ab.n) <= lastOrd(nil, f): @@ -389,9 +391,13 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = # integer literal in the proper range; we want ``i16 + 4`` to stay an # ``int16`` operation so we declare the ``4`` pseudo-equal to int16 result = isFromIntLit - elif f.kind == tyInt and k in {tyInt8..tyInt32}: + elif a.kind == tyInt and nf == c.config.targetSizeSignedToKind: result = isIntConv - elif f.kind == tyUInt and k in {tyUInt8..tyUInt32}: + elif a.kind == tyUInt and nf == c.config.targetSizeUnsignedToKind: + result = isIntConv + elif f.kind == tyInt and na in {tyInt8 .. c.config.targetSizeSignedToKind}: + result = isIntConv + elif f.kind == tyUInt and na in {tyUInt8 .. c.config.targetSizeUnsignedToKind}: result = isIntConv elif k >= min and k <= max: result = isConvertible @@ -405,7 +411,7 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = result = isConvertible else: result = isNone -proc isConvertibleToRange(f, a: PType): bool = +proc isConvertibleToRange(c: PContext, f, a: PType): bool = if f.kind in {tyInt..tyInt64, tyUInt..tyUInt64} and a.kind in {tyInt..tyInt64, tyUInt..tyUInt64}: case f.kind @@ -413,13 +419,14 @@ proc isConvertibleToRange(f, a: PType): bool = of tyInt16: result = isIntLit(a) or a.kind in {tyInt8, tyInt16} of tyInt32: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32} # This is wrong, but seems like there's a lot of code that relies on it :( - of tyInt, tyUInt, tyUInt64: result = true + of tyInt, tyUInt: result = true + # of tyInt: result = isIntLit(a) or a.kind in {tyInt8 .. c.config.targetSizeSignedToKind} of tyInt64: result = isIntLit(a) or a.kind in {tyInt8, tyInt16, tyInt32, tyInt, tyInt64} of tyUInt8: result = isIntLit(a) or a.kind in {tyUInt8} of tyUInt16: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16} of tyUInt32: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32} - #of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt} - #of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt, tyUInt64} + # of tyUInt: result = isIntLit(a) or a.kind in {tyUInt8 .. c.config.targetSizeUnsignedToKind} + of tyUInt64: result = isIntLit(a) or a.kind in {tyUInt8, tyUInt16, tyUInt32, tyUInt64} else: result = false elif f.kind in {tyFloat..tyFloat128}: # `isIntLit` is correct and should be used above as well, see PR: @@ -1148,18 +1155,18 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, let f = skipTypes(f, {tyRange}) if f.kind == a.kind and (f.kind != tyEnum or sameEnumTypes(f, a)): result = isIntConv - elif isConvertibleToRange(f, a): + elif isConvertibleToRange(c.c, f, a): result = isConvertible # a convertible to f - of tyInt: result = handleRange(f, a, tyInt8, tyInt32) - of tyInt8: result = handleRange(f, a, tyInt8, tyInt8) - of tyInt16: result = handleRange(f, a, tyInt8, tyInt16) - of tyInt32: result = handleRange(f, a, tyInt8, tyInt32) - of tyInt64: result = handleRange(f, a, tyInt, tyInt64) - of tyUInt: result = handleRange(f, a, tyUInt8, tyUInt32) - of tyUInt8: result = handleRange(f, a, tyUInt8, tyUInt8) - of tyUInt16: result = handleRange(f, a, tyUInt8, tyUInt16) - of tyUInt32: result = handleRange(f, a, tyUInt8, tyUInt32) - of tyUInt64: result = handleRange(f, a, tyUInt, tyUInt64) + of tyInt: result = handleRange(c.c, f, a, tyInt8, c.c.config.targetSizeSignedToKind) + of tyInt8: result = handleRange(c.c, f, a, tyInt8, tyInt8) + of tyInt16: result = handleRange(c.c, f, a, tyInt8, tyInt16) + of tyInt32: result = handleRange(c.c, f, a, tyInt8, tyInt32) + of tyInt64: result = handleRange(c.c, f, a, tyInt, tyInt64) + of tyUInt: result = handleRange(c.c, f, a, tyUInt8, c.c.config.targetSizeUnsignedToKind) + of tyUInt8: result = handleRange(c.c, f, a, tyUInt8, tyUInt8) + of tyUInt16: result = handleRange(c.c, f, a, tyUInt8, tyUInt16) + of tyUInt32: result = handleRange(c.c, f, a, tyUInt8, tyUInt32) + of tyUInt64: result = handleRange(c.c, f, a, tyUInt, tyUInt64) of tyFloat: result = handleFloatRange(f, a) of tyFloat32: result = handleFloatRange(f, a) of tyFloat64: result = handleFloatRange(f, a) @@ -2114,6 +2121,8 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, of isIntConv: # I'm too lazy to introduce another ``*matches`` field, so we conflate # ``isIntConv`` and ``isIntLit`` here: + if f.skipTypes({tyRange}).kind notin {tyInt, tyUInt}: + inc(m.intConvMatches) inc(m.intConvMatches) result = implicitConv(nkHiddenStdConv, f, arg, m, c) of isSubtype: diff --git a/compiler/types.nim b/compiler/types.nim index 0ade59fd0..4bbbaf13c 100644 --- a/compiler/types.nim +++ b/compiler/types.nim @@ -753,8 +753,13 @@ proc firstOrd*(conf: ConfigRef; t: PType): Int128 = assert(t.n.kind == nkRange) result = getOrdValue(t.n[0]) of tyInt: - if conf != nil and conf.target.intSize == 4: - result = toInt128(-2147483648) + if conf != nil: + case conf.target.intSize + of 8: result = toInt128(0x8000000000000000'i64) + of 4: result = toInt128(-2147483648) + of 2: result = toInt128(-32768) + of 1: result = toInt128(-128) + else: discard else: result = toInt128(0x8000000000000000'i64) of tyInt8: result = toInt128(-128) @@ -797,6 +802,29 @@ proc firstFloat*(t: PType): BiggestFloat = internalError(newPartialConfigRef(), "invalid kind for firstFloat(" & $t.kind & ')') NaN +proc targetSizeSignedToKind*(conf: ConfigRef): TTypeKind = + case conf.target.intSize + of 8: result = tyInt64 + of 4: result = tyInt32 + of 2: result = tyInt16 + else: discard + +proc targetSizeUnsignedToKind*(conf: ConfigRef): TTypeKind = + case conf.target.intSize + of 8: result = tyUInt64 + of 4: result = tyUInt32 + of 2: result = tyUInt16 + else: discard + +proc normalizeKind*(conf: ConfigRef, k: TTypeKind): TTypeKind = + case k + of tyInt: + result = conf.targetSizeSignedToKind() + of tyUInt: + result = conf.targetSizeUnsignedToKind() + else: + result = k + proc lastOrd*(conf: ConfigRef; t: PType): Int128 = case t.kind of tyBool: result = toInt128(1'u) @@ -808,7 +836,13 @@ proc lastOrd*(conf: ConfigRef; t: PType): Int128 = assert(t.n.kind == nkRange) result = getOrdValue(t.n[1]) of tyInt: - if conf != nil and conf.target.intSize == 4: result = toInt128(0x7FFFFFFF) + if conf != nil: + case conf.target.intSize + of 8: result = toInt128(0x7FFFFFFFFFFFFFFF'u64) + of 4: result = toInt128(0x7FFFFFFF) + of 2: result = toInt128(0x00007FFF) + of 1: result = toInt128(0x0000007F) + else: discard else: result = toInt128(0x7FFFFFFFFFFFFFFF'u64) of tyInt8: result = toInt128(0x0000007F) of tyInt16: result = toInt128(0x00007FFF) diff --git a/lib/std/formatfloat.nim b/lib/std/formatfloat.nim index 2850f7021..01b88d813 100644 --- a/lib/std/formatfloat.nim +++ b/lib/std/formatfloat.nim @@ -28,11 +28,11 @@ proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: BiggestFloat) ## ## returns the amount of bytes written to `buf` not counting the ## terminating '\0' character. - result = toChars(buf, value, forceTrailingDotZero=true) + result = toChars(buf, value, forceTrailingDotZero=true).int buf[result] = '\0' proc writeFloatToBufferRoundtrip*(buf: var array[65, char]; value: float32): int = - result = float32ToChars(buf, value, forceTrailingDotZero=true) + result = float32ToChars(buf, value, forceTrailingDotZero=true).int buf[result] = '\0' proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", @@ -49,7 +49,7 @@ proc writeFloatToBufferSprintf*(buf: var array[65, char]; value: BiggestFloat): ## ## returns the amount of bytes written to `buf` not counting the ## terminating '\0' character. - var n: int = c_sprintf(cast[cstring](addr buf), "%.16g", value) + var n = c_sprintf(cast[cstring](addr buf), "%.16g", value).int var hasDot = false for i in 0..n-1: if buf[i] == ',': diff --git a/lib/std/private/digitsutils.nim b/lib/std/private/digitsutils.nim index 588bcaec0..b3dc5d14f 100644 --- a/lib/std/private/digitsutils.nim +++ b/lib/std/private/digitsutils.nim @@ -34,7 +34,7 @@ proc utoa2Digits*(buf: var openArray[char]; pos: int; digits: uint32) {.inline.} #copyMem(buf, unsafeAddr(digits100[2 * digits]), 2 * sizeof((char))) proc trailingZeros2Digits*(digits: uint32): int32 {.inline.} = - return trailingZeros100[digits] + return trailingZeros100[digits.int8] when defined(js): proc numToString(a: SomeInteger): cstring {.importjs: "((#) + \"\")".} @@ -63,14 +63,14 @@ func addIntImpl(result: var string, x: uint64) {.inline.} = while num >= nbatch: let originNum = num num = num div nbatch - let index = (originNum - num * nbatch) shl 1 + let index = int16((originNum - num * nbatch) shl 1) tmp[next] = digits100[index + 1] tmp[next - 1] = digits100[index] dec(next, 2) # process last 1-2 digits if num < 10: - tmp[next] = chr(ord('0') + num) + tmp[next] = chr(ord('0') + num.uint8) else: let index = num * 2 tmp[next] = digits100[index + 1] diff --git a/lib/std/private/dragonbox.nim b/lib/std/private/dragonbox.nim index 23adff385..2ba22a751 100644 --- a/lib/std/private/dragonbox.nim +++ b/lib/std/private/dragonbox.nim @@ -1146,7 +1146,7 @@ proc printDecimalDigitsBackwards*(buf: var openArray[char]; pos: int; output64: buf[pos] = chr(ord('0') + q) return tz -proc decimalLength*(v: uint64): int32 {.inline.} = +proc decimalLength*(v: uint64): int {.inline.} = dragonbox_Assert(v >= 1) dragonbox_Assert(v <= 99999999999999999'u64) if cast[uint32](v shr 32) != 0: @@ -1166,48 +1166,48 @@ proc decimalLength*(v: uint64): int32 {.inline.} = return 11 return 10 let v32: uint32 = cast[uint32](v) - if v32 >= 1000000000'u: + if v32 >= 1000000000'u32: return 10 - if v32 >= 100000000'u: + if v32 >= 100000000'u32: return 9 - if v32 >= 10000000'u: + if v32 >= 10000000'u32: return 8 - if v32 >= 1000000'u: + if v32 >= 1000000'u32: return 7 - if v32 >= 100000'u: + if v32 >= 100000'u32: return 6 - if v32 >= 10000'u: + if v32 >= 10000'u32: return 5 - if v32 >= 1000'u: + if v32 >= 1000'u32: return 4 - if v32 >= 100'u: + if v32 >= 100'u32: return 3 - if v32 >= 10'u: + if v32 >= 10'u32: return 2 return 1 -proc formatDigits*(buffer: var openArray[char]; pos: int; digits: uint64; decimalExponent: int32; +proc formatDigits*[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint64; decimalExponent: int; forceTrailingDotZero = false): int {.inline.} = const - minFixedDecimalPoint: int32 = -6 + minFixedDecimalPoint = -6 const - maxFixedDecimalPoint: int32 = 17 - var pos = pos + maxFixedDecimalPoint = 17 + var pos:int = pos.int assert(minFixedDecimalPoint <= -1, "internal error") assert(maxFixedDecimalPoint >= 17, "internal error") dragonbox_Assert(digits >= 1) dragonbox_Assert(digits <= 99999999999999999'u64) dragonbox_Assert(decimalExponent >= -999) dragonbox_Assert(decimalExponent <= 999) - var numDigits: int32 = decimalLength(digits) - let decimalPoint: int32 = numDigits + decimalExponent + var numDigits = decimalLength(digits) + let decimalPoint = numDigits + decimalExponent let useFixed: bool = minFixedDecimalPoint <= decimalPoint and decimalPoint <= maxFixedDecimalPoint ## Prepare the buffer. for i in 0..<32: buffer[pos+i] = '0' assert(minFixedDecimalPoint >= -30, "internal error") assert(maxFixedDecimalPoint <= 32, "internal error") - var decimalDigitsPosition: int32 + var decimalDigitsPosition: int if useFixed: if decimalPoint <= 0: ## 0.[000]digits @@ -1258,7 +1258,7 @@ proc formatDigits*(buffer: var openArray[char]; pos: int; digits: uint64; decima ## d.igitsE+123 buffer[pos+1] = '.' pos = digitsEnd - let scientificExponent: int32 = decimalPoint - 1 + let scientificExponent: int = decimalPoint - 1 ## SF_ASSERT(scientific_exponent != 0); buffer[pos] = 'e' buffer[pos+1] = if scientificExponent < 0: '-' else: '+' @@ -1291,7 +1291,7 @@ proc toChars*(buffer: var openArray[char]; v: float; forceTrailingDotZero = fals if exponent != 0 or significand != 0: ## != 0 let dec = toDecimal64(significand, exponent) - return formatDigits(buffer, pos, dec.significand, dec.exponent, + return formatDigits(buffer, pos, dec.significand, dec.exponent.int, forceTrailingDotZero) else: buffer[pos] = '0' diff --git a/lib/std/private/schubfach.nim b/lib/std/private/schubfach.nim index 872317ebf..dad8363ba 100644 --- a/lib/std/private/schubfach.nim +++ b/lib/std/private/schubfach.nim @@ -244,7 +244,7 @@ proc toDecimal32(ieeeSignificand: uint32; ieeeExponent: uint32): FloatingDecimal ## ToChars ## ================================================================================================== -proc printDecimalDigitsBackwards(buf: var openArray[char]; pos: int; output: uint32): int32 {.inline.} = +proc printDecimalDigitsBackwards[T: Ordinal](buf: var openArray[char]; pos: T; output: uint32): int32 {.inline.} = var output = output var pos = pos var tz: int32 = 0 @@ -300,7 +300,7 @@ proc printDecimalDigitsBackwards(buf: var openArray[char]; pos: int; output: uin buf[pos] = chr(uint32('0') + q) return tz -proc decimalLength(v: uint32): int32 {.inline.} = +proc decimalLength(v: uint32): int {.inline.} = sf_Assert(v >= 1) sf_Assert(v <= 999999999'u) if v >= 100000000'u: @@ -321,7 +321,7 @@ proc decimalLength(v: uint32): int32 {.inline.} = return 2 return 1 -proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimalExponent: int32; +proc formatDigits[T: Ordinal](buffer: var openArray[char]; pos: T; digits: uint32; decimalExponent: int; forceTrailingDotZero: bool = false): int {.inline.} = const minFixedDecimalPoint: int32 = -4 @@ -333,8 +333,8 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal sf_Assert(digits <= 999999999'u) sf_Assert(decimalExponent >= -99) sf_Assert(decimalExponent <= 99) - var numDigits: int32 = decimalLength(digits) - let decimalPoint: int32 = numDigits + decimalExponent + var numDigits = decimalLength(digits) + let decimalPoint = numDigits + decimalExponent let useFixed: bool = minFixedDecimalPoint <= decimalPoint and decimalPoint <= maxFixedDecimalPoint ## Prepare the buffer. @@ -342,7 +342,7 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal for i in 0..<32: buffer[pos+i] = '0' assert(minFixedDecimalPoint >= -30, "internal error") assert(maxFixedDecimalPoint <= 32, "internal error") - var decimalDigitsPosition: int32 + var decimalDigitsPosition: int if useFixed: if decimalPoint <= 0: ## 0.[000]digits @@ -386,7 +386,7 @@ proc formatDigits(buffer: var openArray[char]; pos: int; digits: uint32; decimal ## d.igitsE+123 buffer[pos+1] = '.' pos = digitsEnd - let scientificExponent: int32 = decimalPoint - 1 + let scientificExponent = decimalPoint - 1 ## SF_ASSERT(scientific_exponent != 0); buffer[pos] = 'e' buffer[pos+1] = if scientificExponent < 0: '-' else: '+' @@ -412,7 +412,7 @@ proc float32ToChars*(buffer: var openArray[char]; v: float32; forceTrailingDotZe if exponent != 0 or significand != 0: ## != 0 let dec: auto = toDecimal32(significand, exponent) - return formatDigits(buffer, pos, dec.digits, dec.exponent, forceTrailingDotZero) + return formatDigits(buffer, pos, dec.digits, dec.exponent.int, forceTrailingDotZero) else: buffer[pos] = '0' buffer[pos+1] = '.' diff --git a/lib/std/syncio.nim b/lib/std/syncio.nim index dcbed9cdd..2b5ea6a3c 100644 --- a/lib/std/syncio.nim +++ b/lib/std/syncio.nim @@ -573,7 +573,7 @@ proc readAllFile(file: File, len: int64): string = result = newString(len) let bytes = readBuffer(file, addr(result[0]), len) if endOfFile(file): - if bytes < len: + if bytes.int64 < len: result.setLen(bytes) else: # We read all the bytes but did not reach the EOF @@ -717,7 +717,7 @@ proc open*(f: var File, filename: string, result = true f = cast[File](p) - if bufSize > 0 and bufSize <= high(cint).int: + if bufSize > 0 and bufSize.uint <= high(uint): discard c_setvbuf(f, nil, IOFBF, cast[csize_t](bufSize)) elif bufSize == 0: discard c_setvbuf(f, nil, IONBF, 0) @@ -821,7 +821,7 @@ when defined(windows) and appType == "console" and proc getConsoleCP(): cuint {.stdcall, dynlib: "kernel32", importc: "GetConsoleCP".} - const Utf8codepage = 65001 + const Utf8codepage = 65001'u32 let consoleOutputCP = getConsoleOutputCP() diff --git a/lib/std/typedthreads.nim b/lib/std/typedthreads.nim index 358ff0d9e..53b18d01e 100644 --- a/lib/std/typedthreads.nim +++ b/lib/std/typedthreads.nim @@ -52,7 +52,7 @@ when defined(genode): import genode/env -when hasAllocStack or defined(zephyr) or defined(freertos): +when hasAllocStack or defined(zephyr) or defined(freertos) or defined(cpu16) or defined(cpu8): const nimThreadStackSize {.intdefine.} = 8192 nimThreadStackGuard {.intdefine.} = 128 diff --git a/lib/std/widestrs.nim b/lib/std/widestrs.nim index 7df4004d1..f0f648c8d 100644 --- a/lib/std/widestrs.nim +++ b/lib/std/widestrs.nim @@ -15,214 +15,215 @@ type Utf16Char* = distinct int16 -when defined(nimv2): +when not (defined(cpu16) or defined(cpu8)): + when defined(nimv2): - type - WideCString* = ptr UncheckedArray[Utf16Char] + type + WideCString* = ptr UncheckedArray[Utf16Char] - WideCStringObj* = object - bytes: int - data: WideCString + WideCStringObj* = object + bytes: int + data: WideCString - proc `=destroy`(a: var WideCStringObj) = - if a.data != nil: + proc `=destroy`(a: var WideCStringObj) = + if a.data != nil: + when compileOption("threads"): + deallocShared(a.data) + else: + dealloc(a.data) + + proc `=copy`(a: var WideCStringObj; b: WideCStringObj) {.error.} + + proc `=sink`(a: var WideCStringObj; b: WideCStringObj) = + a.bytes = b.bytes + a.data = b.data + + proc createWide(a: var WideCStringObj; bytes: int) = + a.bytes = bytes when compileOption("threads"): - deallocShared(a.data) + a.data = cast[typeof(a.data)](allocShared0(bytes)) else: - dealloc(a.data) + a.data = cast[typeof(a.data)](alloc0(bytes)) - proc `=copy`(a: var WideCStringObj; b: WideCStringObj) {.error.} + template `[]`*(a: WideCStringObj; idx: int): Utf16Char = a.data[idx] + template `[]=`*(a: WideCStringObj; idx: int; val: Utf16Char) = a.data[idx] = val - proc `=sink`(a: var WideCStringObj; b: WideCStringObj) = - a.bytes = b.bytes - a.data = b.data + template nullWide(): untyped = WideCStringObj(bytes: 0, data: nil) + + converter toWideCString*(x: WideCStringObj): WideCString {.inline.} = + result = x.data - proc createWide(a: var WideCStringObj; bytes: int) = - a.bytes = bytes - when compileOption("threads"): - a.data = cast[typeof(a.data)](allocShared0(bytes)) - else: - a.data = cast[typeof(a.data)](alloc0(bytes)) - - template `[]`*(a: WideCStringObj; idx: int): Utf16Char = a.data[idx] - template `[]=`*(a: WideCStringObj; idx: int; val: Utf16Char) = a.data[idx] = val - - template nullWide(): untyped = WideCStringObj(bytes: 0, data: nil) - - converter toWideCString*(x: WideCStringObj): WideCString {.inline.} = - result = x.data - -else: - template nullWide(): untyped = nil - - type - WideCString* = ref UncheckedArray[Utf16Char] - WideCStringObj* = WideCString - - template createWide(a; L) = - unsafeNew(a, L) - -proc ord(arg: Utf16Char): int = int(cast[uint16](arg)) - -proc len*(w: WideCString): int = - ## returns the length of a widestring. This traverses the whole string to - ## find the binary zero end marker! - result = 0 - while int16(w[result]) != 0'i16: inc result - -const - UNI_REPLACEMENT_CHAR = Utf16Char(0xFFFD'i16) - UNI_MAX_BMP = 0x0000FFFF - UNI_MAX_UTF16 = 0x0010FFFF - # UNI_MAX_UTF32 = 0x7FFFFFFF - # UNI_MAX_LEGAL_UTF32 = 0x0010FFFF - - halfShift = 10 - halfBase = 0x0010000 - halfMask = 0x3FF - - UNI_SUR_HIGH_START = 0xD800 - UNI_SUR_HIGH_END = 0xDBFF - UNI_SUR_LOW_START = 0xDC00 - UNI_SUR_LOW_END = 0xDFFF - UNI_REPL = 0xFFFD - -template ones(n: untyped): untyped = ((1 shl n)-1) - -template fastRuneAt(s: cstring, i, L: int, result: untyped, doInc = true) = - ## Returns the unicode character `s[i]` in `result`. If `doInc == true` - ## `i` is incremented by the number of bytes that have been processed. - bind ones - - if ord(s[i]) <= 127: - result = ord(s[i]) - when doInc: inc(i) - elif ord(s[i]) shr 5 == 0b110: - #assert(ord(s[i+1]) shr 6 == 0b10) - if i <= L - 2: - result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6)) - when doInc: inc(i, 2) - else: - result = UNI_REPL - when doInc: inc(i) - elif ord(s[i]) shr 4 == 0b1110: - if i <= L - 3: - #assert(ord(s[i+1]) shr 6 == 0b10) - #assert(ord(s[i+2]) shr 6 == 0b10) - result = (ord(s[i]) and ones(4)) shl 12 or - (ord(s[i+1]) and ones(6)) shl 6 or - (ord(s[i+2]) and ones(6)) - when doInc: inc(i, 3) - else: - result = UNI_REPL - when doInc: inc(i) - elif ord(s[i]) shr 3 == 0b11110: - if i <= L - 4: - #assert(ord(s[i+1]) shr 6 == 0b10) - #assert(ord(s[i+2]) shr 6 == 0b10) - #assert(ord(s[i+3]) shr 6 == 0b10) - result = (ord(s[i]) and ones(3)) shl 18 or - (ord(s[i+1]) and ones(6)) shl 12 or - (ord(s[i+2]) and ones(6)) shl 6 or - (ord(s[i+3]) and ones(6)) - when doInc: inc(i, 4) - else: - result = UNI_REPL - when doInc: inc(i) else: - result = 0xFFFD - when doInc: inc(i) - -iterator runes(s: cstring, L: int): int = - var - i = 0 - result: int - while i < L: - fastRuneAt(s, i, L, result, true) - yield result - -proc newWideCString*(size: int): WideCStringObj = - createWide(result, size * 2 + 2) - -proc newWideCString*(source: cstring, L: int): WideCStringObj = - createWide(result, L * 2 + 2) - var d = 0 - for ch in runes(source, L): - - if ch <= UNI_MAX_BMP: - if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_LOW_END: - result[d] = UNI_REPLACEMENT_CHAR - else: - result[d] = cast[Utf16Char](uint16(ch)) - elif ch > UNI_MAX_UTF16: - result[d] = UNI_REPLACEMENT_CHAR - else: - let ch = ch - halfBase - result[d] = cast[Utf16Char](uint16((ch shr halfShift) + UNI_SUR_HIGH_START)) - inc d - result[d] = cast[Utf16Char](uint16((ch and halfMask) + UNI_SUR_LOW_START)) - inc d - result[d] = Utf16Char(0) + template nullWide(): untyped = nil -proc newWideCString*(s: cstring): WideCStringObj = - if s.isNil: return nullWide + type + WideCString* = ref UncheckedArray[Utf16Char] + WideCStringObj* = WideCString - result = newWideCString(s, s.len) + template createWide(a; L) = + unsafeNew(a, L) -proc newWideCString*(s: string): WideCStringObj = - result = newWideCString(cstring s, s.len) + proc ord(arg: Utf16Char): int = int(cast[uint16](arg)) -proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string = - result = newStringOfCap(estimate + estimate shr 2) + proc len*(w: WideCString): int = + ## returns the length of a widestring. This traverses the whole string to + ## find the binary zero end marker! + result = 0 + while int16(w[result]) != 0'i16: inc result - var i = 0 - while w[i].int16 != 0'i16: - var ch = ord(w[i]) - inc i - if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_HIGH_END: - # If the 16 bits following the high surrogate are in the source buffer... - let ch2 = ord(w[i]) + const + UNI_REPLACEMENT_CHAR = Utf16Char(0xFFFD'i16) + UNI_MAX_BMP = 0x0000FFFF + UNI_MAX_UTF16 = 0x0010FFFF + # UNI_MAX_UTF32 = 0x7FFFFFFF + # UNI_MAX_LEGAL_UTF32 = 0x0010FFFF - # If it's a low surrogate, convert to UTF32: - if ch2 >= UNI_SUR_LOW_START and ch2 <= UNI_SUR_LOW_END: - ch = (((ch and halfMask) shl halfShift) + (ch2 and halfMask)) + halfBase - inc i + halfShift = 10 + halfBase = 0x0010000 + halfMask = 0x3FF + + UNI_SUR_HIGH_START = 0xD800 + UNI_SUR_HIGH_END = 0xDBFF + UNI_SUR_LOW_START = 0xDC00 + UNI_SUR_LOW_END = 0xDFFF + UNI_REPL = 0xFFFD + + template ones(n: untyped): untyped = ((1 shl n)-1) + + template fastRuneAt(s: cstring, i, L: int, result: untyped, doInc = true) = + ## Returns the unicode character `s[i]` in `result`. If `doInc == true` + ## `i` is incremented by the number of bytes that have been processed. + bind ones + + if ord(s[i]) <= 127: + result = ord(s[i]) + when doInc: inc(i) + elif ord(s[i]) shr 5 == 0b110: + #assert(ord(s[i+1]) shr 6 == 0b10) + if i <= L - 2: + result = (ord(s[i]) and (ones(5))) shl 6 or (ord(s[i+1]) and ones(6)) + when doInc: inc(i, 2) + else: + result = UNI_REPL + when doInc: inc(i) + elif ord(s[i]) shr 4 == 0b1110: + if i <= L - 3: + #assert(ord(s[i+1]) shr 6 == 0b10) + #assert(ord(s[i+2]) shr 6 == 0b10) + result = (ord(s[i]) and ones(4)) shl 12 or + (ord(s[i+1]) and ones(6)) shl 6 or + (ord(s[i+2]) and ones(6)) + when doInc: inc(i, 3) else: + result = UNI_REPL + when doInc: inc(i) + elif ord(s[i]) shr 3 == 0b11110: + if i <= L - 4: + #assert(ord(s[i+1]) shr 6 == 0b10) + #assert(ord(s[i+2]) shr 6 == 0b10) + #assert(ord(s[i+3]) shr 6 == 0b10) + result = (ord(s[i]) and ones(3)) shl 18 or + (ord(s[i+1]) and ones(6)) shl 12 or + (ord(s[i+2]) and ones(6)) shl 6 or + (ord(s[i+3]) and ones(6)) + when doInc: inc(i, 4) + else: + result = UNI_REPL + when doInc: inc(i) + else: + result = 0xFFFD + when doInc: inc(i) + + iterator runes(s: cstring, L: int): int = + var + i = 0 + result: int + while i < L: + fastRuneAt(s, i, L, result, true) + yield result + + proc newWideCString*(size: int): WideCStringObj = + createWide(result, size * 2 + 2) + + proc newWideCString*(source: cstring, L: int): WideCStringObj = + createWide(result, L * 2 + 2) + var d = 0 + for ch in runes(source, L): + + if ch <= UNI_MAX_BMP: + if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_LOW_END: + result[d] = UNI_REPLACEMENT_CHAR + else: + result[d] = cast[Utf16Char](uint16(ch)) + elif ch > UNI_MAX_UTF16: + result[d] = UNI_REPLACEMENT_CHAR + else: + let ch = ch - halfBase + result[d] = cast[Utf16Char](uint16((ch shr halfShift) + UNI_SUR_HIGH_START)) + inc d + result[d] = cast[Utf16Char](uint16((ch and halfMask) + UNI_SUR_LOW_START)) + inc d + result[d] = Utf16Char(0) + + proc newWideCString*(s: cstring): WideCStringObj = + if s.isNil: return nullWide + + result = newWideCString(s, s.len) + + proc newWideCString*(s: string): WideCStringObj = + result = newWideCString(cstring s, s.len) + + proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string = + result = newStringOfCap(estimate + estimate shr 2) + + var i = 0 + while w[i].int16 != 0'i16: + var ch = ord(w[i]) + inc i + if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_HIGH_END: + # If the 16 bits following the high surrogate are in the source buffer... + let ch2 = ord(w[i]) + + # If it's a low surrogate, convert to UTF32: + if ch2 >= UNI_SUR_LOW_START and ch2 <= UNI_SUR_LOW_END: + ch = (((ch and halfMask) shl halfShift) + (ch2 and halfMask)) + halfBase + inc i + else: + #invalid UTF-16 + ch = replacement + elif ch >= UNI_SUR_LOW_START and ch <= UNI_SUR_LOW_END: #invalid UTF-16 ch = replacement - elif ch >= UNI_SUR_LOW_START and ch <= UNI_SUR_LOW_END: - #invalid UTF-16 - ch = replacement - - if ch < 0x80: - result.add chr(ch) - elif ch < 0x800: - result.add chr((ch shr 6) or 0xc0) - result.add chr((ch and 0x3f) or 0x80) - elif ch < 0x10000: - result.add chr((ch shr 12) or 0xe0) - result.add chr(((ch shr 6) and 0x3f) or 0x80) - result.add chr((ch and 0x3f) or 0x80) - elif ch <= 0x10FFFF: - result.add chr((ch shr 18) or 0xf0) - result.add chr(((ch shr 12) and 0x3f) or 0x80) - result.add chr(((ch shr 6) and 0x3f) or 0x80) - result.add chr((ch and 0x3f) or 0x80) - else: - # replacement char(in case user give very large number): - result.add chr(0xFFFD shr 12 or 0b1110_0000) - result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00) - result.add chr(0xFFFD and ones(6) or 0b10_0000_00) -proc `$`*(s: WideCString): string = - result = s $ 80 + if ch < 0x80: + result.add chr(ch) + elif ch < 0x800: + result.add chr((ch shr 6) or 0xc0) + result.add chr((ch and 0x3f) or 0x80) + elif ch < 0x10000: + result.add chr((ch shr 12) or 0xe0) + result.add chr(((ch shr 6) and 0x3f) or 0x80) + result.add chr((ch and 0x3f) or 0x80) + elif ch <= 0x10FFFF: + result.add chr((ch shr 18) or 0xf0) + result.add chr(((ch shr 12) and 0x3f) or 0x80) + result.add chr(((ch shr 6) and 0x3f) or 0x80) + result.add chr((ch and 0x3f) or 0x80) + else: + # replacement char(in case user give very large number): + result.add chr(0xFFFD shr 12 or 0b1110_0000) + result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00) + result.add chr(0xFFFD and ones(6) or 0b10_0000_00) + + proc `$`*(s: WideCString): string = + result = s $ 80 -when defined(nimv2): - proc `$`*(s: WideCStringObj, estimate: int, replacement: int = 0xFFFD): string = - `$`(s.data, estimate, replacement) + when defined(nimv2): + proc `$`*(s: WideCStringObj, estimate: int, replacement: int = 0xFFFD): string = + `$`(s.data, estimate, replacement) - proc `$`*(s: WideCStringObj): string = - $(s.data) + proc `$`*(s: WideCStringObj): string = + $(s.data) - proc len*(w: WideCStringObj): int {.inline.} = - len(w.data) + proc len*(w: WideCStringObj): int {.inline.} = + len(w.data) diff --git a/lib/system.nim b/lib/system.nim index c41b3cb9d..ac806759c 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -2001,7 +2001,7 @@ when notJSnotNims: proc equalMem(a, b: pointer, size: Natural): bool = nimCmpMem(a, b, size) == 0 proc cmpMem(a, b: pointer, size: Natural): int = - nimCmpMem(a, b, size) + nimCmpMem(a, b, size).int when not defined(js): proc cmp(x, y: string): int = @@ -2300,11 +2300,13 @@ else: type ExitCodeRange = int8 else: # win32 uses low 32 bits type ExitCodeRange = cint - - if errorcode < low(ExitCodeRange): - rawQuit(low(ExitCodeRange).cint) - elif errorcode > high(ExitCodeRange): - rawQuit(high(ExitCodeRange).cint) + when sizeof(errorcode) > sizeof(ExitCodeRange): + if errorcode < low(ExitCodeRange): + rawQuit(low(ExitCodeRange).cint) + elif errorcode > high(ExitCodeRange): + rawQuit(high(ExitCodeRange).cint) + else: + rawQuit(errorcode.cint) else: rawQuit(errorcode.cint) diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 04cbb9e3e..9c8f70c11 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -24,7 +24,7 @@ template track(op, address, size) = const nimMinHeapPages {.intdefine.} = 128 # 0.5 MB SmallChunkSize = PageSize - MaxFli = 30 + MaxFli = when sizeof(int) > 2: 30 else: 14 MaxLog2Sli = 5 # 32, this cannot be increased without changing 'uint32' # everywhere! MaxSli = 1 shl MaxLog2Sli @@ -32,7 +32,7 @@ const RealFli = MaxFli - FliOffset # size of chunks in last matrix bin - MaxBigChunkSize = 1 shl MaxFli - 1 shl (MaxFli-MaxLog2Sli-1) + MaxBigChunkSize = int(1'i32 shl MaxFli - 1'i32 shl (MaxFli-MaxLog2Sli-1)) HugeChunkSize = MaxBigChunkSize + 1 type @@ -115,7 +115,7 @@ type MemRegion = object when not defined(gcDestructors): minLargeObj, maxLargeObj: int - freeSmallChunks: array[0..SmallChunkSize div MemAlign-1, PSmallChunk] + freeSmallChunks: array[0..max(1,SmallChunkSize div MemAlign-1), PSmallChunk] flBitmap: uint32 slBitmap: array[RealFli, uint32] matrix: array[RealFli, array[MaxSli, PBigChunk]] @@ -196,7 +196,7 @@ proc mappingSearch(r, fl, sl: var int) {.inline.} = let t = roundup((1 shl (msbit(uint32 r) - MaxLog2Sli)), PageSize) - 1 r = r + t r = r and not t - r = min(r, MaxBigChunkSize) + r = min(r, MaxBigChunkSize).int fl = msbit(uint32 r) sl = (r shr (fl - MaxLog2Sli)) - MaxSli dec fl, FliOffset @@ -472,7 +472,7 @@ proc requestOsChunks(a: var MemRegion, size: int): PBigChunk = a.nextChunkSize = PageSize*4 else: a.nextChunkSize = min(roundup(usedMem shr 2, PageSize), a.nextChunkSize * 2) - a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize) + a.nextChunkSize = min(a.nextChunkSize, MaxBigChunkSize).int var size = size if size > a.nextChunkSize: diff --git a/lib/system/arithmetics.nim b/lib/system/arithmetics.nim index 910e73507..d05aaaa5b 100644 --- a/lib/system/arithmetics.nim +++ b/lib/system/arithmetics.nim @@ -1,4 +1,4 @@ -proc succ*[T: Ordinal](x: T, y = 1): T {.magic: "Succ", noSideEffect.} = +proc succ*[T, V: Ordinal](x: T, y: V = 1): T {.magic: "Succ", noSideEffect.} = ## Returns the `y`-th successor (default: 1) of the value `x`. ## ## If such a value does not exist, `OverflowDefect` is raised @@ -7,7 +7,7 @@ proc succ*[T: Ordinal](x: T, y = 1): T {.magic: "Succ", noSideEffect.} = assert succ(5) == 6 assert succ(5, 3) == 8 -proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.} = +proc pred*[T, V: Ordinal](x: T, y: V = 1): T {.magic: "Pred", noSideEffect.} = ## Returns the `y`-th predecessor (default: 1) of the value `x`. ## ## If such a value does not exist, `OverflowDefect` is raised @@ -16,7 +16,7 @@ proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.} = assert pred(5) == 4 assert pred(5, 3) == 2 -proc inc*[T: Ordinal](x: var T, y = 1) {.magic: "Inc", noSideEffect.} = +proc inc*[T, V: Ordinal](x: var T, y: V = 1) {.magic: "Inc", noSideEffect.} = ## Increments the ordinal `x` by `y`. ## ## If such a value does not exist, `OverflowDefect` is raised or a compile @@ -28,7 +28,7 @@ proc inc*[T: Ordinal](x: var T, y = 1) {.magic: "Inc", noSideEffect.} = inc(i, 3) assert i == 6 -proc dec*[T: Ordinal](x: var T, y = 1) {.magic: "Dec", noSideEffect.} = +proc dec*[T, V: Ordinal](x: var T, y: V = 1) {.magic: "Dec", noSideEffect.} = ## Decrements the ordinal `x` by `y`. ## ## If such a value does not exist, `OverflowDefect` is raised or a compile diff --git a/lib/system/bitmasks.nim b/lib/system/bitmasks.nim index 9cb57bc45..0663247c2 100644 --- a/lib/system/bitmasks.nim +++ b/lib/system/bitmasks.nim @@ -10,7 +10,7 @@ # Page size of the system; in most cases 4096 bytes. For exotic OS or # CPU this needs to be changed: const - PageShift = when defined(nimPage256) or defined(cpu16): 8 + PageShift = when defined(nimPage256) or defined(cpu16): 3 elif defined(nimPage512): 9 elif defined(nimPage1k): 10 else: 12 # \ # my tests showed no improvements for using larger page sizes. diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim index 3c6ac718b..0b2578280 100644 --- a/lib/system/strmantle.nim +++ b/lib/system/strmantle.nim @@ -17,7 +17,7 @@ proc cmpStrings(a, b: string): int {.inline, compilerproc.} = let blen = b.len let minlen = min(alen, blen) if minlen > 0: - result = c_memcmp(unsafeAddr a[0], unsafeAddr b[0], cast[csize_t](minlen)) + result = c_memcmp(unsafeAddr a[0], unsafeAddr b[0], cast[csize_t](minlen)).int if result == 0: result = alen - blen else: diff --git a/lib/system/strs_v2.nim b/lib/system/strs_v2.nim index e5ab236d2..429724dab 100644 --- a/lib/system/strs_v2.nim +++ b/lib/system/strs_v2.nim @@ -36,7 +36,7 @@ template frees(s) = proc resize(old: int): int {.inline.} = if old <= 0: result = 4 - elif old < 65536: result = old * 2 + elif old <= high(int16): result = old * 2 else: result = old * 3 div 2 # for large arrays * 3/2 is better proc prepareAdd(s: var NimStringV2; addlen: int) {.compilerRtl.} = diff --git a/tests/arithm/t1.nim b/tests/arithm/t1.nim new file mode 100644 index 000000000..f9a87684e --- /dev/null +++ b/tests/arithm/t1.nim @@ -0,0 +1,2 @@ +doAssert typeOf(1.int64 + 1.int) is int64 +doAssert typeOf(1.uint64 + 1.uint) is uint64 diff --git a/tests/varres/tprevent_forloopvar_mutations.nim b/tests/varres/tprevent_forloopvar_mutations.nim index 96bb208c2..aae23d8b1 100644 --- a/tests/varres/tprevent_forloopvar_mutations.nim +++ b/tests/varres/tprevent_forloopvar_mutations.nim @@ -1,14 +1,5 @@ discard """ errormsg: "type mismatch: got <int>" - nimout: '''tprevent_forloopvar_mutations.nim(16, 7) Error: type mismatch: got <int> -but expected one of: -proc inc[T: Ordinal](x: var T; y = 1) - first type mismatch at position: 1 - required type for x: var T: Ordinal - but expression 'i' is immutable, not 'var' - -expression: inc i -''' """ for i in 0..10: |