diff options
-rw-r--r-- | changelog.md | 1 | ||||
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | lib/system.nim | 193 | ||||
-rw-r--r-- | tests/arithm/tarithm.nim | 22 | ||||
-rw-r--r-- | tests/concepts/t3330.nim | 14 | ||||
-rw-r--r-- | tests/errmsgs/twrong_at_operator.nim | 8 | ||||
-rw-r--r-- | tests/generics/tgenerics_issues.nim | 8 | ||||
-rw-r--r-- | tests/pragmas/t6448.nim | 3 |
8 files changed, 151 insertions, 99 deletions
diff --git a/changelog.md b/changelog.md index 7381e6697..681d5166d 100644 --- a/changelog.md +++ b/changelog.md @@ -30,6 +30,7 @@ ## Language changes +- Unsigned integer operators have been fixed to allow promotion of the first operand. ### Tool changes diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index a4dd25045..dd4ad3b3a 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -53,7 +53,6 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimKnowsNimvm") defineSymbol("nimArrIdx") defineSymbol("nimHasalignOf") - defineSymbol("nimNewShiftOps") defineSymbol("nimDistros") defineSymbol("nimHasCppDefine") defineSymbol("nimGenericInOutFlags") diff --git a/lib/system.nim b/lib/system.nim index 9158b6153..fdbd91c2f 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1323,65 +1323,51 @@ proc `mod`*(x, y: int16): int16 {.magic: "ModI", noSideEffect.} proc `mod`*(x, y: int32): int32 {.magic: "ModI", noSideEffect.} proc `mod`*(x, y: int64): int64 {.magic: "ModI", noSideEffect.} -when defined(nimNewShiftOps): - - when defined(nimOldShiftRight) 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 - ## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8 - ## 0b1000_0000'i8 shr 4 == 0b1111_1000'i8 - ## -1 shr 5 == -1 - ## 1 shr 5 == 0 - ## 16 shr 2 == 4 - ## -16 shr 2 == -4 - 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`. +when defined(nimOldShiftRight) 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 - ## 1'i32 shl 4 == 0x0000_0010 - ## 1'i64 shl 4 == 0x0000_0000_0000_0010 - proc `shl`*(x: int8, y: SomeInteger): int8 {.magic: "ShlI", noSideEffect.} - proc `shl`*(x: int16, y: SomeInteger): int16 {.magic: "ShlI", noSideEffect.} - proc `shl`*(x: int32, y: SomeInteger): int32 {.magic: "ShlI", noSideEffect.} - proc `shl`*(x: int64, y: SomeInteger): int64 {.magic: "ShlI", noSideEffect.} -else: - proc `shr`*(x, y: int): int {.magic: "ShrI", noSideEffect.} - proc `shr`*(x, y: int8): int8 {.magic: "ShrI", noSideEffect.} - proc `shr`*(x, y: int16): int16 {.magic: "ShrI", noSideEffect.} - proc `shr`*(x, y: int32): int32 {.magic: "ShrI", noSideEffect.} - proc `shr`*(x, y: int64): int64 {.magic: "ShrI", noSideEffect.} - - proc `shl`*(x, y: int): int {.magic: "ShlI", noSideEffect.} - proc `shl`*(x, y: int8): int8 {.magic: "ShlI", noSideEffect.} - proc `shl`*(x, y: int16): int16 {.magic: "ShlI", noSideEffect.} - proc `shl`*(x, y: int32): int32 {.magic: "ShlI", noSideEffect.} - proc `shl`*(x, y: int64): int64 {.magic: "ShlI", noSideEffect.} + ## 0b0001_0000'i8 shr 2 == 0b0000_0100'i8 + ## 0b0000_0001'i8 shr 1 == 0b0000_0000'i8 + ## 0b1000_0000'i8 shr 4 == 0b1111_1000'i8 + ## -1 shr 5 == -1 + ## 1 shr 5 == 0 + ## 16 shr 2 == 4 + ## -16 shr 2 == -4 + 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`. + ## + ## **Note**: `Operator precedence <manual.html#syntax-precedence>`_ + ## is different than in *C*. + ## + ## .. code-block:: Nim + ## 1'i32 shl 4 == 0x0000_0010 + ## 1'i64 shl 4 == 0x0000_0000_0000_0010 +proc `shl`*(x: int8, y: SomeInteger): int8 {.magic: "ShlI", noSideEffect.} +proc `shl`*(x: int16, y: SomeInteger): int16 {.magic: "ShlI", noSideEffect.} +proc `shl`*(x: int32, y: SomeInteger): int32 {.magic: "ShlI", noSideEffect.} +proc `shl`*(x: int64, y: SomeInteger): int64 {.magic: "ShlI", noSideEffect.} when defined(nimAshr): proc ashr*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.} @@ -1518,54 +1504,105 @@ template `>%`*(x, y: untyped): untyped = y <% x # unsigned integer operations: -proc `not`*[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.} +proc `not`*(x: uint): uint {.magic: "BitnotI", noSideEffect.} ## Computes the `bitwise complement` of the integer `x`. - -when defined(nimNewShiftOps): - proc `shr`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShrI", noSideEffect.} - ## Computes the `shift right` operation of `x` and `y`. - proc `shl`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShlI", noSideEffect.} - ## Computes the `shift left` operation of `x` and `y`. -else: - proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.} - ## Computes the `shift right` operation of `x` and `y`. - proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.} - ## Computes the `shift left` operation of `x` and `y`. - -proc `and`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.} +proc `not`*(x: uint8): uint8 {.magic: "BitnotI", noSideEffect.} +proc `not`*(x: uint16): uint16 {.magic: "BitnotI", noSideEffect.} +proc `not`*(x: uint32): uint32 {.magic: "BitnotI", noSideEffect.} +proc `not`*(x: uint64): uint64 {.magic: "BitnotI", noSideEffect.} + +proc `shr`*(x: uint, y: SomeInteger): uint {.magic: "ShrI", noSideEffect.} + ## Computes the `shift right` operation of `x` and `y`. +proc `shr`*(x: uint8, y: SomeInteger): uint8 {.magic: "ShrI", noSideEffect.} +proc `shr`*(x: uint16, y: SomeInteger): uint16 {.magic: "ShrI", noSideEffect.} +proc `shr`*(x: uint32, y: SomeInteger): uint32 {.magic: "ShrI", noSideEffect.} +proc `shr`*(x: uint64, y: SomeInteger): uint64 {.magic: "ShrI", noSideEffect.} + +proc `shl`*(x: uint, y: SomeInteger): uint {.magic: "ShlI", noSideEffect.} + ## Computes the `shift left` operation of `x` and `y`. +proc `shl`*(x: uint8, y: SomeInteger): uint8 {.magic: "ShlI", noSideEffect.} +proc `shl`*(x: uint16, y: SomeInteger): uint16 {.magic: "ShlI", noSideEffect.} +proc `shl`*(x: uint32, y: SomeInteger): uint32 {.magic: "ShlI", noSideEffect.} +proc `shl`*(x: uint64, y: SomeInteger): uint64 {.magic: "ShlI", noSideEffect.} + +proc `and`*(x, y: uint): uint {.magic: "BitandI", noSideEffect.} ## Computes the `bitwise and` of numbers `x` and `y`. +proc `and`*(x, y: uint8): uint8 {.magic: "BitandI", noSideEffect.} +proc `and`*(x, y: uint16): uint16 {.magic: "BitandI", noSideEffect.} +proc `and`*(x, y: uint32): uint32 {.magic: "BitandI", noSideEffect.} +proc `and`*(x, y: uint64): uint64 {.magic: "BitandI", noSideEffect.} -proc `or`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitorI", noSideEffect.} +proc `or`*(x, y: uint): uint {.magic: "BitorI", noSideEffect.} ## Computes the `bitwise or` of numbers `x` and `y`. +proc `or`*(x, y: uint8): uint8 {.magic: "BitorI", noSideEffect.} +proc `or`*(x, y: uint16): uint16 {.magic: "BitorI", noSideEffect.} +proc `or`*(x, y: uint32): uint32 {.magic: "BitorI", noSideEffect.} +proc `or`*(x, y: uint64): uint64 {.magic: "BitorI", noSideEffect.} -proc `xor`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitxorI", noSideEffect.} +proc `xor`*(x, y: uint): uint {.magic: "BitxorI", noSideEffect.} ## Computes the `bitwise xor` of numbers `x` and `y`. +proc `xor`*(x, y: uint8): uint8 {.magic: "BitxorI", noSideEffect.} +proc `xor`*(x, y: uint16): uint16 {.magic: "BitxorI", noSideEffect.} +proc `xor`*(x, y: uint32): uint32 {.magic: "BitxorI", noSideEffect.} +proc `xor`*(x, y: uint64): uint64 {.magic: "BitxorI", noSideEffect.} -proc `==`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "EqI", noSideEffect.} +proc `==`*(x, y: uint): bool {.magic: "EqI", noSideEffect.} ## Compares two unsigned integers for equality. +proc `==`*(x, y: uint8): bool {.magic: "EqI", noSideEffect.} +proc `==`*(x, y: uint16): bool {.magic: "EqI", noSideEffect.} +proc `==`*(x, y: uint32): bool {.magic: "EqI", noSideEffect.} +proc `==`*(x, y: uint64): bool {.magic: "EqI", noSideEffect.} -proc `+`*[T: SomeUnsignedInt](x, y: T): T {.magic: "AddU", noSideEffect.} +proc `+`*(x, y: uint): uint {.magic: "AddU", noSideEffect.} ## Binary `+` operator for unsigned integers. +proc `+`*(x, y: uint8): uint8 {.magic: "AddU", noSideEffect.} +proc `+`*(x, y: uint16): uint16 {.magic: "AddU", noSideEffect.} +proc `+`*(x, y: uint32): uint32 {.magic: "AddU", noSideEffect.} +proc `+`*(x, y: uint64): uint64 {.magic: "AddU", noSideEffect.} -proc `-`*[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.} +proc `-`*(x, y: uint): uint {.magic: "SubU", noSideEffect.} ## Binary `-` operator for unsigned integers. +proc `-`*(x, y: uint8): uint8 {.magic: "SubU", noSideEffect.} +proc `-`*(x, y: uint16): uint16 {.magic: "SubU", noSideEffect.} +proc `-`*(x, y: uint32): uint32 {.magic: "SubU", noSideEffect.} +proc `-`*(x, y: uint64): uint64 {.magic: "SubU", noSideEffect.} -proc `*`*[T: SomeUnsignedInt](x, y: T): T {.magic: "MulU", noSideEffect.} +proc `*`*(x, y: uint): uint {.magic: "MulU", noSideEffect.} ## Binary `*` operator for unsigned integers. +proc `*`*(x, y: uint8): uint8 {.magic: "MulU", noSideEffect.} +proc `*`*(x, y: uint16): uint16 {.magic: "MulU", noSideEffect.} +proc `*`*(x, y: uint32): uint32 {.magic: "MulU", noSideEffect.} +proc `*`*(x, y: uint64): uint64 {.magic: "MulU", noSideEffect.} -proc `div`*[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.} +proc `div`*(x, y: uint): uint {.magic: "DivU", noSideEffect.} ## Computes the integer division for unsigned integers. ## This is roughly the same as ``trunc(x/y)``. +proc `div`*(x, y: uint8): uint8 {.magic: "DivU", noSideEffect.} +proc `div`*(x, y: uint16): uint16 {.magic: "DivU", noSideEffect.} +proc `div`*(x, y: uint32): uint32 {.magic: "DivU", noSideEffect.} +proc `div`*(x, y: uint64): uint64 {.magic: "DivU", noSideEffect.} -proc `mod`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ModU", noSideEffect.} +proc `mod`*(x, y: uint): uint {.magic: "ModU", noSideEffect.} ## Computes the integer modulo operation (remainder) for unsigned integers. ## This is the same as ``x - (x div y) * y``. +proc `mod`*(x, y: uint8): uint8 {.magic: "ModU", noSideEffect.} +proc `mod`*(x, y: uint16): uint16 {.magic: "ModU", noSideEffect.} +proc `mod`*(x, y: uint32): uint32 {.magic: "ModU", noSideEffect.} +proc `mod`*(x, y: uint64): uint64 {.magic: "ModU", noSideEffect.} -proc `<=`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LeU", noSideEffect.} +proc `<=`*(x, y: uint): bool {.magic: "LeU", noSideEffect.} ## Returns true if ``x <= y``. +proc `<=`*(x, y: uint8): bool {.magic: "LeU", noSideEffect.} +proc `<=`*(x, y: uint16): bool {.magic: "LeU", noSideEffect.} +proc `<=`*(x, y: uint32): bool {.magic: "LeU", noSideEffect.} +proc `<=`*(x, y: uint64): bool {.magic: "LeU", noSideEffect.} -proc `<`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LtU", noSideEffect.} +proc `<`*(x, y: uint): bool {.magic: "LtU", noSideEffect.} ## Returns true if ``unsigned(x) < unsigned(y)``. +proc `<`*(x, y: uint8): bool {.magic: "LtU", noSideEffect.} +proc `<`*(x, y: uint16): bool {.magic: "LtU", noSideEffect.} +proc `<`*(x, y: uint32): bool {.magic: "LtU", noSideEffect.} +proc `<`*(x, y: uint64): bool {.magic: "LtU", noSideEffect.} # floating point operations: proc `+`*(x: float32): float32 {.magic: "UnaryPlusF64", noSideEffect.} diff --git a/tests/arithm/tarithm.nim b/tests/arithm/tarithm.nim index 4625a5ecf..fcb78bd7a 100644 --- a/tests/arithm/tarithm.nim +++ b/tests/arithm/tarithm.nim @@ -4,6 +4,14 @@ int32 int32 1280 1280 +3 +1 +2 +2 +3 +4294967295 +2 +0 ''' """ @@ -145,3 +153,17 @@ block tsubrange: level = min(level + 2, maxLevel).n16 doAssert level == 1 + +block tissue12177: + var a: uint16 = 1 + var b: uint32 = 2 + + echo(b + a) + echo(b - a) + echo(b * a) + echo(b div a) + + echo(a + b) + echo(a - b) + echo(a * b) + echo(a div b) diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim index ed1590e16..ab77dd347 100644 --- a/tests/concepts/t3330.nim +++ b/tests/concepts/t3330.nim @@ -9,23 +9,23 @@ proc test(foo: Foo[int]) required type for foo: Foo[int] but expression 'bar' is of type: Bar[system.int] t3330.nim(63, 8) Hint: Non-matching candidates for add(k, string, T) -proc add[T](x: var seq[T]; y: openArray[T]) +proc add[T](x: var seq[T]; y: T) first type mismatch at position: 1 required type for x: var seq[T] but expression 'k' is of type: Alias -proc add[T](x: var seq[T]; y: T) +proc add(x: var string; y: string) first type mismatch at position: 1 - required type for x: var seq[T] + required type for x: var string but expression 'k' is of type: Alias proc add(result: var string; x: float) first type mismatch at position: 1 required type for result: var string but expression 'k' is of type: Alias -proc add(x: var string; y: cstring) +proc add(x: var string; y: char) first type mismatch at position: 1 required type for x: var string but expression 'k' is of type: Alias -proc add(x: var string; y: string) +proc add(x: var string; y: cstring) first type mismatch at position: 1 required type for x: var string but expression 'k' is of type: Alias @@ -33,9 +33,9 @@ proc add(result: var string; x: int64) first type mismatch at position: 1 required type for result: var string but expression 'k' is of type: Alias -proc add(x: var string; y: char) +proc add[T](x: var seq[T]; y: openArray[T]) first type mismatch at position: 1 - required type for x: var string + required type for x: var seq[T] but expression 'k' is of type: Alias t3330.nim(63, 8) template/generic instantiation of `add` from here diff --git a/tests/errmsgs/twrong_at_operator.nim b/tests/errmsgs/twrong_at_operator.nim index 9933b0f39..ebf6d966b 100644 --- a/tests/errmsgs/twrong_at_operator.nim +++ b/tests/errmsgs/twrong_at_operator.nim @@ -4,14 +4,14 @@ line: 22 nimout: ''' twrong_at_operator.nim(22, 30) Error: type mismatch: got <array[0..0, type int]> but expected one of: -proc `@`[T](a: openArray[T]): seq[T] - first type mismatch at position: 1 - required type for a: openArray[T] - but expression '[int]' is of type: array[0..0, type int] proc `@`[IDX, T](a: sink array[IDX, T]): seq[T] first type mismatch at position: 1 required type for a: sink array[IDX, T] but expression '[int]' is of type: array[0..0, type int] +proc `@`[T](a: openArray[T]): seq[T] + first type mismatch at position: 1 + required type for a: openArray[T] + but expression '[int]' is of type: array[0..0, type int] expression: @[int] ''' diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim index 3d5d65c75..af71a8938 100644 --- a/tests/generics/tgenerics_issues.nim +++ b/tests/generics/tgenerics_issues.nim @@ -762,11 +762,3 @@ block t3717: var f: Foo[Foo[int]] discard foo(f) - - - -block t5707: - proc foo[T]: seq[int] = - return lc[x | (x <- 1..10, x mod 2 == 0), int] - - doAssert foo[float32]() == @[2, 4, 6, 8, 10] diff --git a/tests/pragmas/t6448.nim b/tests/pragmas/t6448.nim index a1bd747a0..ab2e3811f 100644 --- a/tests/pragmas/t6448.nim +++ b/tests/pragmas/t6448.nim @@ -1,6 +1,7 @@ discard """ errormsg: '''ambiguous call; both foobar.async''' - line: 9 + line: 10 + disabled: "32bit" """ import foobar |