right shift is now by default sign preserving (#11322)
* right shift is now by default sign preserving * fix hashString and semfold * enable arithmetic shift right globally for CI * fix typo * remove xxx * use oldShiftRight as flag * apply feedback * add changelog entry
This commit is contained in:
parent
897e7c90ac
commit
88b5dd3362
18 changed files with 211 additions and 187 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -82,3 +82,4 @@ megatest.nim
|
|||
/outputExpected.txt
|
||||
/outputGotten.txt
|
||||
|
||||
/lib/pure/*.js
|
||||
|
|
|
|||
|
|
@ -46,9 +46,13 @@
|
|||
- A bug allowed `macro foo(): int = 123` to compile even though a
|
||||
macros has to return a `NimNode`. This has been fixed.
|
||||
|
||||
- `shr` is now sign preserving. Use `-d:oldShiftRight` to enable old
|
||||
behavior globally.
|
||||
|
||||
- With the exception of `uint` and `uint64`, conversion to unsigned types
|
||||
are now range checked during runtime.
|
||||
|
||||
|
||||
#### Breaking changes in the standard library
|
||||
|
||||
- `osproc.execProcess` now also takes a `workingDir` parameter.
|
||||
|
|
|
|||
|
|
@ -75,20 +75,20 @@ proc bitSetContains(x, y: TBitSet): bool =
|
|||
const populationCount: array[low(int8)..high(int8), int8] = block:
|
||||
var arr: array[low(int8)..high(int8), int8]
|
||||
|
||||
proc countSetBits(x: int8): int8 =
|
||||
proc countSetBits(x: uint8): uint8 =
|
||||
return
|
||||
( x and 0b00000001'i8) +
|
||||
((x and 0b00000010'i8) shr 1) +
|
||||
((x and 0b00000100'i8) shr 2) +
|
||||
((x and 0b00001000'i8) shr 3) +
|
||||
((x and 0b00010000'i8) shr 4) +
|
||||
((x and 0b00100000'i8) shr 5) +
|
||||
((x and 0b01000000'i8) shr 6) +
|
||||
((x and 0b10000000'i8) shr 7)
|
||||
( x and 0b00000001'u8) +
|
||||
((x and 0b00000010'u8) shr 1) +
|
||||
((x and 0b00000100'u8) shr 2) +
|
||||
((x and 0b00001000'u8) shr 3) +
|
||||
((x and 0b00010000'u8) shr 4) +
|
||||
((x and 0b00100000'u8) shr 5) +
|
||||
((x and 0b01000000'u8) shr 6) +
|
||||
((x and 0b10000000'u8) shr 7)
|
||||
|
||||
|
||||
for it in low(int8)..high(int8):
|
||||
arr[it] = countSetBits(it)
|
||||
arr[it] = cast[int8](countSetBits(cast[uint8](it)))
|
||||
|
||||
arr
|
||||
|
||||
|
|
|
|||
|
|
@ -28,29 +28,29 @@ proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool =
|
|||
result = getPragmaStmt(n, w) != nil
|
||||
|
||||
proc hashString*(conf: ConfigRef; s: string): BiggestInt =
|
||||
# has to be the same algorithm as system.hashString!
|
||||
# has to be the same algorithm as strmantle.hashString!
|
||||
if CPU[conf.target.targetCPU].bit == 64:
|
||||
# we have to use the same bitwidth
|
||||
# as the target CPU
|
||||
var b = 0'i64
|
||||
var b = 0'u64
|
||||
for i in 0 ..< len(s):
|
||||
b = b +% ord(s[i])
|
||||
b = b +% `shl`(b, 10)
|
||||
b = b xor `shr`(b, 6)
|
||||
b = b +% `shl`(b, 3)
|
||||
b = b xor `shr`(b, 11)
|
||||
b = b +% `shl`(b, 15)
|
||||
result = b
|
||||
b = b + uint(s[i])
|
||||
b = b + (b shl 10)
|
||||
b = b xor (b shr 6)
|
||||
b = b + (b shl 3)
|
||||
b = b xor (b shr 11)
|
||||
b = b + (b shl 15)
|
||||
result = cast[Hash](b)
|
||||
else:
|
||||
var a = 0'i32
|
||||
var a = 0'u32
|
||||
for i in 0 ..< len(s):
|
||||
a = a +% ord(s[i]).int32
|
||||
a = a +% `shl`(a, 10'i32)
|
||||
a = a xor `shr`(a, 6'i32)
|
||||
a = a +% `shl`(a, 3'i32)
|
||||
a = a xor `shr`(a, 11'i32)
|
||||
a = a +% `shl`(a, 15'i32)
|
||||
result = a
|
||||
a = a + uint32(s[i])
|
||||
a = a + (a shl 10)
|
||||
a = a xor (a shr 6)
|
||||
a = a + (a shl 3)
|
||||
a = a xor (a shr 11)
|
||||
a = a + (a shl 15)
|
||||
result = cast[Hash](a)
|
||||
|
||||
template getUniqueType*(key: PType): PType = key
|
||||
|
||||
|
|
|
|||
|
|
@ -647,34 +647,35 @@ proc handleDecChars(L: var TLexer, xi: var int) =
|
|||
inc(L.bufpos)
|
||||
|
||||
proc addUnicodeCodePoint(s: var string, i: int) =
|
||||
let i = cast[uint](i)
|
||||
# inlined toUTF-8 to avoid unicode and strutils dependencies.
|
||||
let pos = s.len
|
||||
if i <=% 127:
|
||||
if i <= 127:
|
||||
s.setLen(pos+1)
|
||||
s[pos+0] = chr(i)
|
||||
elif i <=% 0x07FF:
|
||||
elif i <= 0x07FF:
|
||||
s.setLen(pos+2)
|
||||
s[pos+0] = chr((i shr 6) or 0b110_00000)
|
||||
s[pos+1] = chr((i and ones(6)) or 0b10_0000_00)
|
||||
elif i <=% 0xFFFF:
|
||||
elif i <= 0xFFFF:
|
||||
s.setLen(pos+3)
|
||||
s[pos+0] = chr(i shr 12 or 0b1110_0000)
|
||||
s[pos+1] = chr(i shr 6 and ones(6) or 0b10_0000_00)
|
||||
s[pos+2] = chr(i and ones(6) or 0b10_0000_00)
|
||||
elif i <=% 0x001FFFFF:
|
||||
elif i <= 0x001FFFFF:
|
||||
s.setLen(pos+4)
|
||||
s[pos+0] = chr(i shr 18 or 0b1111_0000)
|
||||
s[pos+1] = chr(i shr 12 and ones(6) or 0b10_0000_00)
|
||||
s[pos+2] = chr(i shr 6 and ones(6) or 0b10_0000_00)
|
||||
s[pos+3] = chr(i and ones(6) or 0b10_0000_00)
|
||||
elif i <=% 0x03FFFFFF:
|
||||
elif i <= 0x03FFFFFF:
|
||||
s.setLen(pos+5)
|
||||
s[pos+0] = chr(i shr 24 or 0b111110_00)
|
||||
s[pos+1] = chr(i shr 18 and ones(6) or 0b10_0000_00)
|
||||
s[pos+2] = chr(i shr 12 and ones(6) or 0b10_0000_00)
|
||||
s[pos+3] = chr(i shr 6 and ones(6) or 0b10_0000_00)
|
||||
s[pos+4] = chr(i and ones(6) or 0b10_0000_00)
|
||||
elif i <=% 0x7FFFFFFF:
|
||||
elif i <= 0x7FFFFFFF:
|
||||
s.setLen(pos+6)
|
||||
s[pos+0] = chr(i shr 30 or 0b1111110_0)
|
||||
s[pos+1] = chr(i shr 24 and ones(6) or 0b10_0000_00)
|
||||
|
|
|
|||
|
|
@ -248,13 +248,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
|
|||
result = doAndFit(newIntNodeT(`shl`(getInt(a), getInt(b)), n, g))
|
||||
else: internalError(g.config, n.info, "constant folding for shl")
|
||||
of mShrI:
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(int8(getInt(a)) shr int8(getInt(b)), n, g)
|
||||
of tyInt16: result = newIntNodeT(int16(getInt(a)) shr int16(getInt(b)), n, g)
|
||||
of tyInt32: result = newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n, g)
|
||||
of tyInt64, tyInt, tyUInt..tyUInt64:
|
||||
result = newIntNodeT(`shr`(getInt(a), getInt(b)), n, g)
|
||||
else: internalError(g.config, n.info, "constant folding for shr")
|
||||
let a = cast[uint64](getInt(a))
|
||||
let b = cast[uint64](getInt(b))
|
||||
let c = cast[BiggestInt](a shr b)
|
||||
result = newIntNodeT(c, n, g)
|
||||
of mAshrI:
|
||||
case skipTypes(n.typ, abstractRange).kind
|
||||
of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g)
|
||||
|
|
|
|||
|
|
@ -421,12 +421,15 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
|
|||
else:
|
||||
let srcDist = (sizeof(src.intVal) - srctyp.size) * 8
|
||||
let destDist = (sizeof(dest.intVal) - desttyp.size) * 8
|
||||
|
||||
var value = cast[BiggestUInt](src.intVal)
|
||||
when system.cpuEndian == bigEndian:
|
||||
dest.intVal = (src.intVal shr srcDist) shl srcDist
|
||||
dest.intVal = (dest.intVal shr destDist) shl destDist
|
||||
value = (value shr srcDist) shl srcDist
|
||||
value = (value shr destDist) shl destDist
|
||||
else:
|
||||
dest.intVal = (src.intVal shl srcDist) shr srcDist
|
||||
dest.intVal = (dest.intVal shl destDist) shr destDist
|
||||
value = (value shl srcDist) shr srcDist
|
||||
value = (value shl destDist) shr destDist
|
||||
dest.intVal = cast[BiggestInt](value)
|
||||
of tyFloat..tyFloat64:
|
||||
if dest.kind != rkFloat:
|
||||
myreset(dest); dest.kind = rkFloat
|
||||
|
|
@ -818,7 +821,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
|
|||
regs[ra].floatVal = regs[rb].floatVal / regs[rc].floatVal
|
||||
of opcShrInt:
|
||||
decodeBC(rkInt)
|
||||
regs[ra].intVal = regs[rb].intVal shr regs[rc].intVal
|
||||
let b = cast[uint64](regs[rb].intVal)
|
||||
let c = cast[uint64](regs[rc].intVal)
|
||||
let a = cast[int64](b shr c)
|
||||
regs[ra].intVal = a
|
||||
of opcShlInt:
|
||||
decodeBC(rkInt)
|
||||
regs[ra].intVal = regs[rb].intVal shl regs[rc].intVal
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import
|
|||
hashes, math
|
||||
|
||||
type
|
||||
BitScalar = int
|
||||
BitScalar = uint
|
||||
|
||||
const
|
||||
InitIntSetSize = 8 # must be a power of two!
|
||||
|
|
@ -102,8 +102,8 @@ proc intSetPut(t: var IntSet, key: int): PTrunk =
|
|||
proc bitincl(s: var IntSet, key: int) {.inline.} =
|
||||
var t = intSetPut(s, `shr`(key, TrunkShift))
|
||||
var u = key and TrunkMask
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
||||
`shl`(1, u and IntMask)
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or
|
||||
(BitScalar(1) shl (u and IntMask))
|
||||
|
||||
proc exclImpl(s: var IntSet, key: int) =
|
||||
if s.elems <= s.a.len:
|
||||
|
|
@ -113,11 +113,11 @@ proc exclImpl(s: var IntSet, key: int) =
|
|||
dec s.elems
|
||||
return
|
||||
else:
|
||||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
var t = intSetGet(s, key shr TrunkShift)
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and
|
||||
not `shl`(1, u and IntMask)
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] and
|
||||
not(BitScalar(1) shl (u and IntMask))
|
||||
|
||||
template dollarImpl(): untyped =
|
||||
result = "{"
|
||||
|
|
@ -137,7 +137,7 @@ iterator items*(s: IntSet): int {.inline.} =
|
|||
while r != nil:
|
||||
var i = 0
|
||||
while i <= high(r.bits):
|
||||
var w = r.bits[i]
|
||||
var w: uint = r.bits[i]
|
||||
# taking a copy of r.bits[i] here is correct, because
|
||||
# modifying operations are not allowed during traversation
|
||||
var j = 0
|
||||
|
|
@ -186,7 +186,7 @@ proc contains*(s: IntSet, key: int): bool =
|
|||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||
result = (t.bits[u shr IntShift] and (BitScalar(1) shl (u and IntMask))) != 0
|
||||
else:
|
||||
result = false
|
||||
|
||||
|
|
@ -268,10 +268,10 @@ proc containsOrIncl*(s: var IntSet, key: int): bool =
|
|||
var t = intSetGet(s, `shr`(key, TrunkShift))
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0
|
||||
result = (t.bits[u shr IntShift] and BitScalar(1) shl (u and IntMask)) != 0
|
||||
if not result:
|
||||
t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or
|
||||
`shl`(1, u and IntMask)
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or
|
||||
(BitScalar(1) shl (u and IntMask))
|
||||
else:
|
||||
incl(s, key)
|
||||
result = false
|
||||
|
|
|
|||
|
|
@ -60,17 +60,22 @@ proc `!&`*(h: Hash, val: int): Hash {.inline.} =
|
|||
## Mixes a hash value `h` with `val` to produce a new hash value.
|
||||
##
|
||||
## This is only needed if you need to implement a hash proc for a new datatype.
|
||||
result = h +% val
|
||||
result = result +% result shl 10
|
||||
result = result xor (result shr 6)
|
||||
let h = cast[uint](h)
|
||||
let val = cast[uint](val)
|
||||
var res = h + val
|
||||
res = res + res shl 10
|
||||
res = res xor (res shr 6)
|
||||
result = cast[Hash](res)
|
||||
|
||||
proc `!$`*(h: Hash): Hash {.inline.} =
|
||||
## Finishes the computation of the hash value.
|
||||
##
|
||||
## This is only needed if you need to implement a hash proc for a new datatype.
|
||||
result = h +% h shl 3
|
||||
result = result xor (result shr 11)
|
||||
result = result +% result shl 15
|
||||
let h = cast[uint](h) # Hash is practically unsigned.
|
||||
var res = h + h shl 3
|
||||
res = res xor (res shr 11)
|
||||
res = res + res shl 15
|
||||
result = cast[Hash](res)
|
||||
|
||||
proc hashData*(data: pointer, size: int): Hash =
|
||||
## Hashes an array of bytes of size `size`.
|
||||
|
|
@ -105,7 +110,7 @@ proc hash*(x: pointer): Hash {.inline.} =
|
|||
}
|
||||
"""
|
||||
else:
|
||||
result = (cast[Hash](x)) shr 3 # skip the alignment
|
||||
result = cast[Hash](cast[uint](x) shr 3) # skip the alignment
|
||||
|
||||
when not defined(booting):
|
||||
proc hash*[T: proc](x: T): Hash {.inline.} =
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ proc runeLen*(s: string): int {.rtl, extern: "nuc$1".} =
|
|||
|
||||
var i = 0
|
||||
while i < len(s):
|
||||
if ord(s[i]) <=% 127: inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110: inc(i, 2)
|
||||
elif ord(s[i]) shr 4 == 0b1110: inc(i, 3)
|
||||
elif ord(s[i]) shr 3 == 0b11110: inc(i, 4)
|
||||
elif ord(s[i]) shr 2 == 0b111110: inc(i, 5)
|
||||
elif ord(s[i]) shr 1 == 0b1111110: inc(i, 6)
|
||||
if uint(s[i]) <= 127: inc(i)
|
||||
elif uint(s[i]) shr 5 == 0b110: inc(i, 2)
|
||||
elif uint(s[i]) shr 4 == 0b1110: inc(i, 3)
|
||||
elif uint(s[i]) shr 3 == 0b11110: inc(i, 4)
|
||||
elif uint(s[i]) shr 2 == 0b111110: inc(i, 5)
|
||||
elif uint(s[i]) shr 1 == 0b1111110: inc(i, 6)
|
||||
else: inc i
|
||||
inc(result)
|
||||
|
||||
|
|
@ -67,12 +67,12 @@ proc runeLenAt*(s: string, i: Natural): int =
|
|||
doAssert a.runeLenAt(0) == 1
|
||||
doAssert a.runeLenAt(1) == 2
|
||||
|
||||
if ord(s[i]) <=% 127: result = 1
|
||||
elif ord(s[i]) shr 5 == 0b110: result = 2
|
||||
elif ord(s[i]) shr 4 == 0b1110: result = 3
|
||||
elif ord(s[i]) shr 3 == 0b11110: result = 4
|
||||
elif ord(s[i]) shr 2 == 0b111110: result = 5
|
||||
elif ord(s[i]) shr 1 == 0b1111110: result = 6
|
||||
if uint(s[i]) <= 127: result = 1
|
||||
elif uint(s[i]) shr 5 == 0b110: result = 2
|
||||
elif uint(s[i]) shr 4 == 0b1110: result = 3
|
||||
elif uint(s[i]) shr 3 == 0b11110: result = 4
|
||||
elif uint(s[i]) shr 2 == 0b111110: result = 5
|
||||
elif uint(s[i]) shr 1 == 0b1111110: result = 6
|
||||
else: result = 1
|
||||
|
||||
const replRune = Rune(0xFFFD)
|
||||
|
|
@ -83,76 +83,76 @@ template fastRuneAt*(s: string, i: int, result: untyped, doInc = true) =
|
|||
## If ``doInc == true`` (default), ``i`` is incremented by the number
|
||||
## of bytes that have been processed.
|
||||
bind ones
|
||||
if ord(s[i]) <=% 127:
|
||||
result = Rune(ord(s[i]))
|
||||
if uint(s[i]) <= 127:
|
||||
result = Rune(uint(s[i]))
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
# assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
elif uint(s[i]) shr 5 == 0b110:
|
||||
# assert(uint(s[i+1]) shr 6 == 0b10)
|
||||
if i <= s.len - 2:
|
||||
result = Rune((ord(s[i]) and (ones(5))) shl 6 or
|
||||
(ord(s[i+1]) and ones(6)))
|
||||
result = Rune((uint(s[i]) and (ones(5))) shl 6 or
|
||||
(uint(s[i+1]) and ones(6)))
|
||||
when doInc: inc(i, 2)
|
||||
else:
|
||||
result = replRune
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
# assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
elif uint(s[i]) shr 4 == 0b1110:
|
||||
# assert(uint(s[i+1]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+2]) shr 6 == 0b10)
|
||||
if i <= s.len - 3:
|
||||
result = Rune((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)))
|
||||
result = Rune((uint(s[i]) and ones(4)) shl 12 or
|
||||
(uint(s[i+1]) and ones(6)) shl 6 or
|
||||
(uint(s[i+2]) and ones(6)))
|
||||
when doInc: inc(i, 3)
|
||||
else:
|
||||
result = replRune
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
# assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
elif uint(s[i]) shr 3 == 0b11110:
|
||||
# assert(uint(s[i+1]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+2]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+3]) shr 6 == 0b10)
|
||||
if i <= s.len - 4:
|
||||
result = Rune((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)))
|
||||
result = Rune((uint(s[i]) and ones(3)) shl 18 or
|
||||
(uint(s[i+1]) and ones(6)) shl 12 or
|
||||
(uint(s[i+2]) and ones(6)) shl 6 or
|
||||
(uint(s[i+3]) and ones(6)))
|
||||
when doInc: inc(i, 4)
|
||||
else:
|
||||
result = replRune
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 2 == 0b111110:
|
||||
# assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+4]) shr 6 == 0b10)
|
||||
elif uint(s[i]) shr 2 == 0b111110:
|
||||
# assert(uint(s[i+1]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+2]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+3]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+4]) shr 6 == 0b10)
|
||||
if i <= s.len - 5:
|
||||
result = Rune((ord(s[i]) and ones(2)) shl 24 or
|
||||
(ord(s[i+1]) and ones(6)) shl 18 or
|
||||
(ord(s[i+2]) and ones(6)) shl 12 or
|
||||
(ord(s[i+3]) and ones(6)) shl 6 or
|
||||
(ord(s[i+4]) and ones(6)))
|
||||
result = Rune((uint(s[i]) and ones(2)) shl 24 or
|
||||
(uint(s[i+1]) and ones(6)) shl 18 or
|
||||
(uint(s[i+2]) and ones(6)) shl 12 or
|
||||
(uint(s[i+3]) and ones(6)) shl 6 or
|
||||
(uint(s[i+4]) and ones(6)))
|
||||
when doInc: inc(i, 5)
|
||||
else:
|
||||
result = replRune
|
||||
when doInc: inc(i)
|
||||
elif ord(s[i]) shr 1 == 0b1111110:
|
||||
# assert(ord(s[i+1]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+2]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+3]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+4]) shr 6 == 0b10)
|
||||
# assert(ord(s[i+5]) shr 6 == 0b10)
|
||||
elif uint(s[i]) shr 1 == 0b1111110:
|
||||
# assert(uint(s[i+1]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+2]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+3]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+4]) shr 6 == 0b10)
|
||||
# assert(uint(s[i+5]) shr 6 == 0b10)
|
||||
if i <= s.len - 6:
|
||||
result = Rune((ord(s[i]) and ones(1)) shl 30 or
|
||||
(ord(s[i+1]) and ones(6)) shl 24 or
|
||||
(ord(s[i+2]) and ones(6)) shl 18 or
|
||||
(ord(s[i+3]) and ones(6)) shl 12 or
|
||||
(ord(s[i+4]) and ones(6)) shl 6 or
|
||||
(ord(s[i+5]) and ones(6)))
|
||||
result = Rune((uint(s[i]) and ones(1)) shl 30 or
|
||||
(uint(s[i+1]) and ones(6)) shl 24 or
|
||||
(uint(s[i+2]) and ones(6)) shl 18 or
|
||||
(uint(s[i+3]) and ones(6)) shl 12 or
|
||||
(uint(s[i+4]) and ones(6)) shl 6 or
|
||||
(uint(s[i+5]) and ones(6)))
|
||||
when doInc: inc(i, 6)
|
||||
else:
|
||||
result = replRune
|
||||
when doInc: inc(i)
|
||||
else:
|
||||
result = Rune(ord(s[i]))
|
||||
result = Rune(uint(s[i]))
|
||||
when doInc: inc(i)
|
||||
|
||||
proc runeAt*(s: string, i: Natural): Rune =
|
||||
|
|
@ -180,20 +180,20 @@ proc validateUTF8*(s: string): int =
|
|||
var i = 0
|
||||
let L = s.len
|
||||
while i < L:
|
||||
if ord(s[i]) <=% 127:
|
||||
if uint(s[i]) <= 127:
|
||||
inc(i)
|
||||
elif ord(s[i]) shr 5 == 0b110:
|
||||
if ord(s[i]) < 0xc2: return i # Catch overlong ascii representations.
|
||||
if i+1 < L and ord(s[i+1]) shr 6 == 0b10: inc(i, 2)
|
||||
elif uint(s[i]) shr 5 == 0b110:
|
||||
if uint(s[i]) < 0xc2: return i # Catch overlong ascii representations.
|
||||
if i+1 < L and uint(s[i+1]) shr 6 == 0b10: inc(i, 2)
|
||||
else: return i
|
||||
elif ord(s[i]) shr 4 == 0b1110:
|
||||
if i+2 < L and ord(s[i+1]) shr 6 == 0b10 and ord(s[i+2]) shr 6 == 0b10:
|
||||
elif uint(s[i]) shr 4 == 0b1110:
|
||||
if i+2 < L and uint(s[i+1]) shr 6 == 0b10 and uint(s[i+2]) shr 6 == 0b10:
|
||||
inc i, 3
|
||||
else: return i
|
||||
elif ord(s[i]) shr 3 == 0b11110:
|
||||
if i+3 < L and ord(s[i+1]) shr 6 == 0b10 and
|
||||
ord(s[i+2]) shr 6 == 0b10 and
|
||||
ord(s[i+3]) shr 6 == 0b10:
|
||||
elif uint(s[i]) shr 3 == 0b11110:
|
||||
if i+3 < L and uint(s[i+1]) shr 6 == 0b10 and
|
||||
uint(s[i+2]) shr 6 == 0b10 and
|
||||
uint(s[i+3]) shr 6 == 0b10:
|
||||
inc i, 4
|
||||
else: return i
|
||||
else:
|
||||
|
|
@ -906,7 +906,7 @@ proc lastRune*(s: string; last: int): (Rune, int) =
|
|||
result = (Rune(s[last]), 1)
|
||||
else:
|
||||
var L = 0
|
||||
while last-L >= 0 and ord(s[last-L]) shr 6 == 0b10: inc(L)
|
||||
while last-L >= 0 and uint(s[last-L]) shr 6 == 0b10: inc(L)
|
||||
var r: Rune
|
||||
fastRuneAt(s, last-L, r, false)
|
||||
result = (r, L+1)
|
||||
|
|
|
|||
|
|
@ -1270,24 +1270,34 @@ else:
|
|||
proc `mod`*(x, y: int64): int64 {.magic: "ModI64", noSideEffect.}
|
||||
|
||||
when defined(nimNewShiftOps):
|
||||
proc `shr`*(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect.}
|
||||
## Computes the `shift right` operation of `x` and `y`, filling
|
||||
## vacant bit positions with zeros.
|
||||
##
|
||||
## **Note**: `Operator precedence <manual.html#syntax-precedence>`_
|
||||
## is different than in *C*.
|
||||
##
|
||||
## See also:
|
||||
## * `ashr proc <#ashr,int,SomeInteger>`_ for arithmetic shift right
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8
|
||||
## 0b1000_0000'i8 shr 8 == 0b0000_0000'i8
|
||||
## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8
|
||||
proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect.}
|
||||
proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect.}
|
||||
proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect.}
|
||||
proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect.}
|
||||
|
||||
when defined(oldShiftRight) or not defined(nimAshr):
|
||||
const shrDepMessage = "`shr` will become sign preserving."
|
||||
proc `shr`*(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
|
||||
proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
|
||||
proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
|
||||
proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
|
||||
proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
|
||||
else:
|
||||
proc `shr`*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.}
|
||||
## Computes the `shift right` operation of `x` and `y`, filling
|
||||
## vacant bit positions with the sign bit.
|
||||
##
|
||||
## **Note**: `Operator precedence <manual.html#syntax-precedence>`_
|
||||
## is different than in *C*.
|
||||
##
|
||||
## See also:
|
||||
## * `ashr proc <#ashr,int,SomeInteger>`_ for arithmetic shift right
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8
|
||||
## 0b1000_0000'i8 shr 8 == 0b0000_0000'i8
|
||||
## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8
|
||||
proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "AshrI", noSideEffect.}
|
||||
proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "AshrI", noSideEffect.}
|
||||
proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "AshrI", noSideEffect.}
|
||||
proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "AshrI", noSideEffect.}
|
||||
|
||||
|
||||
proc `shl`*(x: int, y: SomeInteger): int {.magic: "ShlI", noSideEffect.}
|
||||
## Computes the `shift left` operation of `x` and `y`.
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ type
|
|||
Trunk = object
|
||||
next: PTrunk # all nodes are connected with this pointer
|
||||
key: int # start address at bit 0
|
||||
bits: array[0..IntsPerTrunk-1, int] # a bit vector
|
||||
bits: array[0..IntsPerTrunk-1, uint] # a bit vector
|
||||
|
||||
TrunkBuckets = array[0..255, PTrunk]
|
||||
IntSet = object
|
||||
|
|
@ -332,21 +332,21 @@ proc contains(s: IntSet, key: int): bool =
|
|||
var t = intSetGet(s, key shr TrunkShift)
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
|
||||
result = (t.bits[u shr IntShift] and (uint(1) shl (u and IntMask))) != 0
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc incl(a: var MemRegion, s: var IntSet, key: int) =
|
||||
var t = intSetPut(a, s, key shr TrunkShift)
|
||||
var u = key and TrunkMask
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or (uint(1) shl (u and IntMask))
|
||||
|
||||
proc excl(s: var IntSet, key: int) =
|
||||
var t = intSetGet(s, key shr TrunkShift)
|
||||
if t != nil:
|
||||
var u = key and TrunkMask
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] and not
|
||||
(1 shl (u and IntMask))
|
||||
(uint(1) shl (u and IntMask))
|
||||
|
||||
iterator elements(t: IntSet): int {.inline.} =
|
||||
# while traversing it is forbidden to change the set!
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ type
|
|||
BitIndex = range[0..UnitsPerPage-1]
|
||||
PageDesc {.final, pure.} = object
|
||||
next: PPageDesc # all nodes are connected with this pointer
|
||||
key: ByteAddress # start address at bit 0
|
||||
key: uint # start address at bit 0
|
||||
bits: array[BitIndex, int] # a bit vector
|
||||
|
||||
PPageDescArray = ptr UncheckedArray[PPageDesc]
|
||||
|
|
@ -97,7 +97,7 @@ proc nextTry(h, maxHash: int): int {.inline.} =
|
|||
# generates each int in range(maxHash) exactly once (see any text on
|
||||
# random-number generation for proof).
|
||||
|
||||
proc cellSetGet(t: CellSet, key: ByteAddress): PPageDesc =
|
||||
proc cellSetGet(t: CellSet, key: uint): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while t.data[h] != nil:
|
||||
if t.data[h].key == key: return t.data[h]
|
||||
|
|
@ -122,7 +122,7 @@ proc cellSetEnlarge(t: var CellSet) =
|
|||
dealloc(t.data)
|
||||
t.data = n
|
||||
|
||||
proc cellSetPut(t: var CellSet, key: ByteAddress): PPageDesc =
|
||||
proc cellSetPut(t: var CellSet, key: uint): PPageDesc =
|
||||
var h = cast[int](key) and t.max
|
||||
while true:
|
||||
var x = t.data[h]
|
||||
|
|
@ -146,33 +146,33 @@ proc cellSetPut(t: var CellSet, key: ByteAddress): PPageDesc =
|
|||
# ---------- slightly higher level procs --------------------------------------
|
||||
|
||||
proc contains(s: CellSet, cell: PCell): bool =
|
||||
var u = cast[ByteAddress](cell)
|
||||
var u = cast[uint](cell)
|
||||
var t = cellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
u = (u mod PageSize) div MemAlign
|
||||
result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
|
||||
else:
|
||||
result = false
|
||||
|
||||
proc incl(s: var CellSet, cell: PCell) {.noinline.} =
|
||||
var u = cast[ByteAddress](cell)
|
||||
var u = cast[uint](cell)
|
||||
var t = cellSetPut(s, u shr PageShift)
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
u = (u mod PageSize) div MemAlign
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask))
|
||||
|
||||
proc excl(s: var CellSet, cell: PCell) =
|
||||
var u = cast[ByteAddress](cell)
|
||||
var u = cast[uint](cell)
|
||||
var t = cellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
u = (u mod PageSize) div MemAlign
|
||||
t.bits[u shr IntShift] = (t.bits[u shr IntShift] and
|
||||
not (1 shl (u and IntMask)))
|
||||
|
||||
proc containsOrIncl(s: var CellSet, cell: PCell): bool =
|
||||
var u = cast[ByteAddress](cell)
|
||||
var u = cast[uint](cell)
|
||||
var t = cellSetGet(s, u shr PageShift)
|
||||
if t != nil:
|
||||
u = (u %% PageSize) /% MemAlign
|
||||
u = (u mod PageSize) div MemAlign
|
||||
result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0
|
||||
if not result:
|
||||
t.bits[u shr IntShift] = t.bits[u shr IntShift] or
|
||||
|
|
@ -185,15 +185,15 @@ iterator elements(t: CellSet): PCell {.inline.} =
|
|||
# while traversing it is forbidden to add pointers to the tree!
|
||||
var r = t.head
|
||||
while r != nil:
|
||||
var i = 0
|
||||
while i <= high(r.bits):
|
||||
var i: uint = 0
|
||||
while int(i) <= high(r.bits):
|
||||
var w = r.bits[i] # taking a copy of r.bits[i] here is correct, because
|
||||
# modifying operations are not allowed during traversation
|
||||
var j = 0
|
||||
var j: uint = 0
|
||||
while w != 0: # test all remaining bits for zero
|
||||
if (w and 1) != 0: # the bit is set!
|
||||
yield cast[PCell]((r.key shl PageShift) or
|
||||
(i shl IntShift +% j) *% MemAlign)
|
||||
(i shl IntShift + j) * MemAlign)
|
||||
inc(j)
|
||||
w = w shr 1
|
||||
inc(i)
|
||||
|
|
@ -238,16 +238,16 @@ iterator elementsExcept(t, s: CellSet): PCell {.inline.} =
|
|||
var r = t.head
|
||||
while r != nil:
|
||||
let ss = cellSetGet(s, r.key)
|
||||
var i = 0
|
||||
while i <= high(r.bits):
|
||||
var i:uint = 0
|
||||
while int(i) <= high(r.bits):
|
||||
var w = r.bits[i]
|
||||
if ss != nil:
|
||||
w = w and not ss.bits[i]
|
||||
var j = 0
|
||||
var j:uint = 0
|
||||
while w != 0:
|
||||
if (w and 1) != 0:
|
||||
yield cast[PCell]((r.key shl PageShift) or
|
||||
(i shl IntShift +% j) *% MemAlign)
|
||||
(i shl IntShift + j) * MemAlign)
|
||||
inc(j)
|
||||
w = w shr 1
|
||||
inc(i)
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ proc extGetCellType(c: pointer): PNimType {.compilerproc.} =
|
|||
result = usrToCell(c).typ
|
||||
|
||||
proc internRefcount(p: pointer): int {.exportc: "getRefcount".} =
|
||||
result = int(usrToCell(p).refcount) shr rcShift
|
||||
result = usrToCell(p).refcount shr rcShift
|
||||
|
||||
# this that has to equals zero, otherwise we have to round up UnitsPerPage:
|
||||
when BitsPerPage mod (sizeof(int)*8) != 0:
|
||||
|
|
|
|||
|
|
@ -30,15 +30,15 @@ proc eqStrings(a, b: string): bool {.inline, compilerProc.} =
|
|||
proc hashString(s: string): int {.compilerproc.} =
|
||||
# the compiler needs exactly the same hash function!
|
||||
# this used to be used for efficient generation of string case statements
|
||||
var h = 0
|
||||
var h : uint = 0
|
||||
for i in 0..len(s)-1:
|
||||
h = h +% ord(s[i])
|
||||
h = h +% h shl 10
|
||||
h = h + uint(s[i])
|
||||
h = h + h shl 10
|
||||
h = h xor (h shr 6)
|
||||
h = h +% h shl 3
|
||||
h = h + h shl 3
|
||||
h = h xor (h shr 11)
|
||||
h = h +% h shl 15
|
||||
result = h
|
||||
h = h + h shl 15
|
||||
result = cast[int](h)
|
||||
|
||||
proc addInt*(result: var string; x: int64) =
|
||||
## Converts integer to its string representation and appends it to `result`.
|
||||
|
|
|
|||
|
|
@ -150,10 +150,10 @@ block tshr:
|
|||
let VI16 = -8'i16
|
||||
let VI8 = -8'i8
|
||||
# doAssert( (VI shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI shr 1))
|
||||
doAssert( (VI64 shr 1) == 9_223_372_036_854_775_804, "Actual: " & $(VI64 shr 1))
|
||||
doAssert( (VI32 shr 1) == 2_147_483_644, "Actual: " & $(VI32 shr 1))
|
||||
doAssert( (VI16 shr 1) == 32_764, "Actual: " & $(VI16 shr 1))
|
||||
doAssert( (VI8 shr 1) == 124, "Actual: " & $(VI8 shr 1))
|
||||
doAssert( (VI64 shr 1) == -4, "Actual: " & $(VI64 shr 1))
|
||||
doAssert( (VI32 shr 1) == -4, "Actual: " & $(VI32 shr 1))
|
||||
doAssert( (VI16 shr 1) == -4, "Actual: " & $(VI16 shr 1))
|
||||
doAssert( (VI8 shr 1) == -4, "Actual: " & $(VI8 shr 1))
|
||||
|
||||
T()
|
||||
static:
|
||||
|
|
|
|||
|
|
@ -31,13 +31,13 @@ test(`or`, 0xf0f0'i16, 0x0d0d'i16, 0xfdfd'i16)
|
|||
test(`and`, 0xf0f0'i16, 0xfdfd'i16, 0xf0f0'i16)
|
||||
|
||||
when not defined(js):
|
||||
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0x0fffffffffffffff'i64)
|
||||
test(`shr`, 0xffff'i16, 0x4'i16, 0x0fff'i16)
|
||||
test(`shr`, 0xff'i8, 0x4'i8, 0x0f'i8)
|
||||
test(`shr`, 0xffffffffffffffff'i64, 0x4'i64, 0xffffffffffffffff'i64)
|
||||
test(`shr`, 0xffff'i16, 0x4'i16, 0xffff'i16)
|
||||
test(`shr`, 0xff'i8, 0x4'i8, 0xff'i8)
|
||||
|
||||
when not defined(js):
|
||||
test(`shr`, 0xffffffff'i64, 0x4'i64, 0x0fffffff'i64)
|
||||
test(`shr`, 0xffffffff'i32, 0x4'i32, 0x0fffffff'i32)
|
||||
test(`shr`, 0xffffffff'i32, 0x4'i32, 0xffffffff'i32)
|
||||
|
||||
when not defined(js):
|
||||
test(`shl`, 0xffffffffffffffff'i64, 0x4'i64, 0xfffffffffffffff0'i64)
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ proc toVarNum(x: int32, b: var TBuffer) =
|
|||
a = abs(x)
|
||||
# first 6 bits:
|
||||
b[0] = toU8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63))
|
||||
a = a shr 6'i32 # skip first 6 bits
|
||||
a = (a shr 6'i32) and 0x03ffffff # skip first 6 bits
|
||||
var i = 1
|
||||
while a != 0'i32:
|
||||
b[i] = toU8(ord(a >% 127'i32) shl 7 or (int(a) and 127))
|
||||
|
|
@ -42,7 +42,7 @@ proc toVarNum64(x: int64, b: var TBuffer) =
|
|||
a = abs(x)
|
||||
# first 6 bits:
|
||||
b[0] = toU8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63))
|
||||
a = a shr 6 # skip first 6 bits
|
||||
a = (a shr 6) and 0x03ffffffffffffff # skip first 6 bits
|
||||
var i = 1
|
||||
while a != 0'i64:
|
||||
b[i] = toU8(ord(a >% 127'i64) shl 7 or int(a and 127))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue