diff --git a/compiler/ast.nim b/compiler/ast.nim index 43ea2b39c44fb..b82002b06e535 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -617,7 +617,6 @@ type mEqI, mLeI, mLtI, mEqF64, mLeF64, mLtF64, mLeU, mLtU, - mLeU64, mLtU64, mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, @@ -687,7 +686,6 @@ const mEqI, mLeI, mLtI, mEqF64, mLeF64, mLtF64, mLeU, mLtU, - mLeU64, mLtU64, mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, mEqB, mLeB, mLtB, diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 277913b177bde..f133b97a2d456 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -605,8 +605,6 @@ proc binaryArith(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mLtF64: applyFormat("($1 < $2)") of mLeU: applyFormat("((NU$3)($1) <= (NU$3)($2))") of mLtU: applyFormat("((NU$3)($1) < (NU$3)($2))") - of mLeU64: applyFormat("((NU64)($1) <= (NU64)($2))") - of mLtU64: applyFormat("((NU64)($1) < (NU64)($2))") of mEqEnum: applyFormat("($1 == $2)") of mLeEnum: applyFormat("($1 <= $2)") of mLtEnum: applyFormat("($1 < $2)") diff --git a/compiler/forloops.nim b/compiler/forloops.nim index 729afb92054b8..ee91000d4b858 100644 --- a/compiler/forloops.nim +++ b/compiler/forloops.nim @@ -13,8 +13,8 @@ import ast, astalgo const someCmp = {mEqI, mEqF64, mEqEnum, mEqCh, mEqB, mEqRef, mEqProc, - mLeI, mLeF64, mLeU, mLeU64, mLeEnum, - mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtU64, mLtEnum, + mLeI, mLeF64, mLeU, mLeEnum, + mLeCh, mLeB, mLePtr, mLtI, mLtF64, mLtU, mLtEnum, mLtCh, mLtB, mLtPtr} proc isCounter(s: PSym): bool {.inline.} = diff --git a/compiler/guards.nim b/compiler/guards.nim index 97dc4f418d0c8..5d0fa64ebdc4d 100644 --- a/compiler/guards.nim +++ b/compiler/guards.nim @@ -17,9 +17,9 @@ const mEqStr, mEqSet, mEqCString} # set excluded here as the semantics are vastly different: - someLe = {mLeI, mLeF64, mLeU, mLeU64, mLeEnum, + someLe = {mLeI, mLeF64, mLeU, mLeEnum, mLeCh, mLeB, mLePtr, mLeStr} - someLt = {mLtI, mLtF64, mLtU, mLtU64, mLtEnum, + someLt = {mLtI, mLtF64, mLtU, mLtEnum, mLtCh, mLtB, mLtPtr, mLtStr} someLen = {mLengthOpenArray, mLengthStr, mLengthArray, mLengthSeq} diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 1130e35f8191a..e63ce74895de8 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -371,69 +371,67 @@ type const # magic checked op; magic unchecked op; jsMagics: TMagicOps = [ mAddI: ["addInt", ""], - ["subInt", ""], # SubI - ["mulInt", ""], # MulI - ["divInt", ""], # DivI - ["modInt", ""], # ModI - ["addInt", ""], # Succ - ["subInt", ""], # Pred - ["", ""], # AddF64 - ["", ""], # SubF64 - ["", ""], # MulF64 - ["", ""], # DivF64 - ["", ""], # ShrI - ["", ""], # ShlI - ["", ""], # AshrI - ["", ""], # BitandI - ["", ""], # BitorI - ["", ""], # BitxorI - ["nimMin", "nimMin"], # MinI - ["nimMax", "nimMax"], # MaxI - ["", ""], # addU - ["", ""], # subU - ["", ""], # mulU - ["", ""], # divU - ["", ""], # modU - ["", ""], # EqI - ["", ""], # LeI - ["", ""], # LtI - ["", ""], # EqF64 - ["", ""], # LeF64 - ["", ""], # LtF64 - ["", ""], # leU - ["", ""], # ltU - ["", ""], # leU64 - ["", ""], # ltU64 - ["", ""], # EqEnum - ["", ""], # LeEnum - ["", ""], # LtEnum - ["", ""], # EqCh - ["", ""], # LeCh - ["", ""], # LtCh - ["", ""], # EqB - ["", ""], # LeB - ["", ""], # LtB - ["", ""], # EqRef - ["", ""], # LePtr - ["", ""], # LtPtr - ["", ""], # Xor - ["", ""], # EqCString - ["", ""], # EqProc - ["negInt", ""], # UnaryMinusI - ["negInt64", ""], # UnaryMinusI64 - ["absInt", ""], # AbsI - ["", ""], # Not - ["", ""], # UnaryPlusI - ["", ""], # BitnotI - ["", ""], # UnaryPlusF64 - ["", ""], # UnaryMinusF64 - ["nimCharToStr", "nimCharToStr"], - ["nimBoolToStr", "nimBoolToStr"], - ["cstrToNimstr", "cstrToNimstr"], - ["cstrToNimstr", "cstrToNimstr"], - ["cstrToNimstr", "cstrToNimstr"], - ["cstrToNimstr", "cstrToNimstr"], - ["", ""]] + mSubI: ["subInt", ""], + mMulI: ["mulInt", ""], + mDivI: ["divInt", ""], + mModI: ["modInt", ""], + mSucc: ["addInt", ""], + mPred: ["subInt", ""], + mAddF64: ["", ""], + mSubF64: ["", ""], + mMulF64: ["", ""], + mDivF64: ["", ""], + mShrI: ["", ""], + mShlI: ["", ""], + mAshrI: ["", ""], + mBitandI: ["", ""], + mBitorI: ["", ""], + mBitxorI: ["", ""], + mMinI: ["nimMin", "nimMin"], + mMaxI: ["nimMax", "nimMax"], + mAddU: ["", ""], + mSubU: ["", ""], + mMulU: ["", ""], + mDivU: ["", ""], + mModU: ["", ""], + mEqI: ["", ""], + mLeI: ["", ""], + mLtI: ["", ""], + mEqF64: ["", ""], + mLeF64: ["", ""], + mLtF64: ["", ""], + mLeU: ["", ""], + mLtU: ["", ""], + mEqEnum: ["", ""], + mLeEnum: ["", ""], + mLtEnum: ["", ""], + mEqCh: ["", ""], + mLeCh: ["", ""], + mLtCh: ["", ""], + mEqB: ["", ""], + mLeB: ["", ""], + mLtB: ["", ""], + mEqRef: ["", ""], + mLePtr: ["", ""], + mLtPtr: ["", ""], + mXor: ["", ""], + mEqCString: ["", ""], + mEqProc: ["", ""], + mUnaryMinusI: ["negInt", ""], + mUnaryMinusI64: ["negInt64", ""], + mAbsI: ["absInt", ""], + mNot: ["", ""], + mUnaryPlusI: ["", ""], + mBitnotI: ["", ""], + mUnaryPlusF64: ["", ""], + mUnaryMinusF64: ["", ""], + mCharToStr: ["nimCharToStr", "nimCharToStr"], + mBoolToStr: ["nimBoolToStr", "nimBoolToStr"], + mIntToStr: ["cstrToNimstr", "cstrToNimstr"], + mInt64ToStr: ["cstrToNimstr", "cstrToNimstr"], + mFloatToStr: ["cstrToNimstr", "cstrToNimstr"], + mCStrToStr: ["cstrToNimstr", "cstrToNimstr"], + mStrToStr: ["", ""]] proc needsTemp(p: PProc; n: PNode): bool = # check if n contains a call to determine @@ -575,8 +573,6 @@ proc arithAux(p: PProc, n: PNode, r: var TCompRes, op: TMagic) = of mLtF64: applyFormat("($1 < $2)", "($1 < $2)") of mLeU: applyFormat("($1 <= $2)", "($1 <= $2)") of mLtU: applyFormat("($1 < $2)", "($1 < $2)") - of mLeU64: applyFormat("($1 <= $2)", "($1 <= $2)") - of mLtU64: applyFormat("($1 < $2)", "($1 < $2)") of mEqEnum: applyFormat("($1 == $2)", "($1 == $2)") of mLeEnum: applyFormat("($1 <= $2)", "($1 <= $2)") of mLtEnum: applyFormat("($1 < $2)", "($1 < $2)") diff --git a/compiler/semfold.nim b/compiler/semfold.nim index b20616e1d366f..54850fcfed93d 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -288,9 +288,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode = of mLtStr: result = newIntNodeT(toInt128(ord(getStr(a) < getStr(b))), n, g) of mLeStr: result = newIntNodeT(toInt128(ord(getStr(a) <= getStr(b))), n, g) of mEqStr: result = newIntNodeT(toInt128(ord(getStr(a) == getStr(b))), n, g) - of mLtU, mLtU64: + of mLtU: result = newIntNodeT(toInt128(ord(`<%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, g) - of mLeU, mLeU64: + of mLeU: result = newIntNodeT(toInt128(ord(`<=%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, g) of mBitandI, mAnd: result = newIntNodeT(bitand(a.getInt, b.getInt), n, g) of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, g) diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 75f673c0b9468..5b355bcab8100 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -1071,8 +1071,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) = of mEqF64: genBinaryABC(c, n, dest, opcEqFloat) of mLeF64: genBinaryABC(c, n, dest, opcLeFloat) of mLtF64: genBinaryABC(c, n, dest, opcLtFloat) - of mLePtr, mLeU, mLeU64: genBinaryABC(c, n, dest, opcLeu) - of mLtPtr, mLtU, mLtU64: genBinaryABC(c, n, dest, opcLtu) + of mLePtr, mLeU: genBinaryABC(c, n, dest, opcLeu) + of mLtPtr, mLtU: genBinaryABC(c, n, dest, opcLtu) of mEqProc, mEqRef: genBinaryABC(c, n, dest, opcEqRef) of mXor: genBinaryABC(c, n, dest, opcXor) diff --git a/lib/system/arithmetics.nim b/lib/system/arithmetics.nim index 757a813e8619e..710566a6ddb54 100644 --- a/lib/system/arithmetics.nim +++ b/lib/system/arithmetics.nim @@ -342,45 +342,6 @@ proc `xor`*(x, y: int16): int16 {.magic: "BitxorI", noSideEffect.} proc `xor`*(x, y: int32): int32 {.magic: "BitxorI", noSideEffect.} proc `xor`*(x, y: int64): int64 {.magic: "BitxorI", noSideEffect.} -type - IntMax32 = int|int8|int16|int32 - -proc `+%`*(x, y: IntMax32): IntMax32 {.magic: "AddU", noSideEffect.} -proc `+%`*(x, y: int64): int64 {.magic: "AddU", noSideEffect.} - ## Treats `x` and `y` as unsigned and adds them. - ## - ## The result is truncated to fit into the result. - ## This implements modulo arithmetic. No overflow errors are possible. - -proc `-%`*(x, y: IntMax32): IntMax32 {.magic: "SubU", noSideEffect.} -proc `-%`*(x, y: int64): int64 {.magic: "SubU", noSideEffect.} - ## Treats `x` and `y` as unsigned and subtracts them. - ## - ## The result is truncated to fit into the result. - ## This implements modulo arithmetic. No overflow errors are possible. - -proc `*%`*(x, y: IntMax32): IntMax32 {.magic: "MulU", noSideEffect.} -proc `*%`*(x, y: int64): int64 {.magic: "MulU", noSideEffect.} - ## Treats `x` and `y` as unsigned and multiplies them. - ## - ## The result is truncated to fit into the result. - ## This implements modulo arithmetic. No overflow errors are possible. - -proc `/%`*(x, y: IntMax32): IntMax32 {.magic: "DivU", noSideEffect.} -proc `/%`*(x, y: int64): int64 {.magic: "DivU", noSideEffect.} - ## Treats `x` and `y` as unsigned and divides them. - ## - ## The result is truncated to fit into the result. - ## This implements modulo arithmetic. No overflow errors are possible. - -proc `%%`*(x, y: IntMax32): IntMax32 {.magic: "ModU", noSideEffect.} -proc `%%`*(x, y: int64): int64 {.magic: "ModU", noSideEffect.} - ## Treats `x` and `y` as unsigned and compute the modulo of `x` and `y`. - ## - ## The result is truncated to fit into the result. - ## This implements modulo arithmetic. No overflow errors are possible. - - # unsigned integer operations: proc `not`*(x: uint): uint {.magic: "BitnotI", noSideEffect.} ## Computes the `bitwise complement` of the integer `x`. @@ -461,8 +422,60 @@ 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 `+%`*(x, y: int): int {.inline.} = + ## Treats `x` and `y` as unsigned and adds them. + ## + ## The result is truncated to fit into the result. + ## This implements modulo arithmetic. No overflow errors are possible. + cast[int](cast[uint](x) + cast[uint](y)) +proc `+%`*(x, y: int8): int8 {.inline.} = cast[int8](cast[uint8](x) + cast[uint8](y)) +proc `+%`*(x, y: int16): int16 {.inline.} = cast[int16](cast[uint16](x) + cast[uint16](y)) +proc `+%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) + cast[uint32](y)) +proc `+%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) + cast[uint64](y)) + +proc `-%`*(x, y: int): int {.inline.} = + ## Treats `x` and `y` as unsigned and subtracts them. + ## + ## The result is truncated to fit into the result. + ## This implements modulo arithmetic. No overflow errors are possible. + cast[int](cast[uint](x) - cast[uint](y)) +proc `-%`*(x, y: int8): int8 {.inline.} = cast[int8](cast[uint8](x) - cast[uint8](y)) +proc `-%`*(x, y: int16): int16 {.inline.} = cast[int16](cast[uint16](x) - cast[uint16](y)) +proc `-%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) - cast[uint32](y)) +proc `-%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) - cast[uint64](y)) + +proc `*%`*(x, y: int): int {.inline.} = + ## Treats `x` and `y` as unsigned and multiplies them. + ## + ## The result is truncated to fit into the result. + ## This implements modulo arithmetic. No overflow errors are possible. + cast[int](cast[uint](x) * cast[uint](y)) +proc `*%`*(x, y: int8): int8 {.inline.} = cast[int8](cast[uint8](x) * cast[uint8](y)) +proc `*%`*(x, y: int16): int16 {.inline.} = cast[int16](cast[uint16](x) * cast[uint16](y)) +proc `*%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) * cast[uint32](y)) +proc `*%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) * cast[uint64](y)) +proc `/%`*(x, y: int): int {.inline.} = + ## Treats `x` and `y` as unsigned and divides them. + ## + ## The result is truncated to fit into the result. + ## This implements modulo arithmetic. No overflow errors are possible. + cast[int](cast[uint](x) div cast[uint](y)) +proc `/%`*(x, y: int8): int8 {.inline.} = cast[int8](cast[uint8](x) div cast[uint8](y)) +proc `/%`*(x, y: int16): int16 {.inline.} = cast[int16](cast[uint16](x) div cast[uint16](y)) +proc `/%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) div cast[uint32](y)) +proc `/%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) div cast[uint64](y)) +proc `%%`*(x, y: int): int {.inline.} = + ## Treats `x` and `y` as unsigned and compute the modulo of `x` and `y`. + ## + ## The result is truncated to fit into the result. + ## This implements modulo arithmetic. No overflow errors are possible. + cast[int](cast[uint](x) mod cast[uint](y)) +proc `%%`*(x, y: int8): int8 {.inline.} = cast[int8](cast[uint8](x) mod cast[uint8](y)) +proc `%%`*(x, y: int16): int16 {.inline.} = cast[int16](cast[uint16](x) mod cast[uint16](y)) +proc `%%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) mod cast[uint32](y)) +proc `%%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) mod cast[uint64](y)) proc `+=`*[T: SomeInteger](x: var T, y: T) {. magic: "Inc", noSideEffect.} diff --git a/lib/system/comparisons.nim b/lib/system/comparisons.nim index 787820989e93e..60ac554a624f4 100644 --- a/lib/system/comparisons.nim +++ b/lib/system/comparisons.nim @@ -161,16 +161,37 @@ proc `<`*(x, y: int16): bool {.magic: "LtI", noSideEffect.} proc `<`*(x, y: int32): bool {.magic: "LtI", noSideEffect.} proc `<`*(x, y: int64): bool {.magic: "LtI", 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 `<`*(x, y: uint): bool {.magic: "LtU", noSideEffect.} + ## Returns true if ``x < 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.} -proc `<=%`*(x, y: IntMax32): bool {.magic: "LeU", noSideEffect.} -proc `<=%`*(x, y: int64): bool {.magic: "LeU64", noSideEffect.} +proc `<=%`*(x, y: int): bool {.inline.} = ## Treats `x` and `y` as unsigned and compares them. ## Returns true if ``unsigned(x) <= unsigned(y)``. + cast[uint](x) <= cast[uint](y) +proc `<=%`*(x, y: int8): bool {.inline.} = cast[uint8](x) <= cast[uint8](y) +proc `<=%`*(x, y: int16): bool {.inline.} = cast[uint16](x) <= cast[uint16](y) +proc `<=%`*(x, y: int32): bool {.inline.} = cast[uint32](x) <= cast[uint32](y) +proc `<=%`*(x, y: int64): bool {.inline.} = cast[uint64](x) <= cast[uint64](y) -proc `<%`*(x, y: IntMax32): bool {.magic: "LtU", noSideEffect.} -proc `<%`*(x, y: int64): bool {.magic: "LtU64", noSideEffect.} +proc `<%`*(x, y: int): bool {.inline.} = ## Treats `x` and `y` as unsigned and compares them. ## Returns true if ``unsigned(x) < unsigned(y)``. + cast[uint](x) < cast[uint](y) +proc `<%`*(x, y: int8): bool {.inline.} = cast[uint8](x) < cast[uint8](y) +proc `<%`*(x, y: int16): bool {.inline.} = cast[uint16](x) < cast[uint16](y) +proc `<%`*(x, y: int32): bool {.inline.} = cast[uint32](x) < cast[uint32](y) +proc `<%`*(x, y: int64): bool {.inline.} = cast[uint64](x) < cast[uint64](y) template `>=%`*(x, y: untyped): untyped = y <=% x ## Treats `x` and `y` as unsigned and compares them. @@ -180,7 +201,6 @@ template `>%`*(x, y: untyped): untyped = y <% x ## Treats `x` and `y` as unsigned and compares them. ## Returns true if ``unsigned(x) > unsigned(y)``. - proc `==`*(x, y: uint): bool {.magic: "EqI", noSideEffect.} ## Compares two unsigned integers for equality. proc `==`*(x, y: uint8): bool {.magic: "EqI", noSideEffect.} @@ -189,21 +209,6 @@ proc `==`*(x, y: uint32): bool {.magic: "EqI", noSideEffect.} proc `==`*(x, y: uint64): bool {.magic: "EqI", 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 `<`*(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.} - - {.push stackTrace: off.} proc min*(x, y: int): int {.magic: "MinI", noSideEffect.} = diff --git a/tests/arithm/tarithm.nim b/tests/arithm/tarithm.nim index fcb78bd7a4b2c..99306b3e84dc8 100644 --- a/tests/arithm/tarithm.nim +++ b/tests/arithm/tarithm.nim @@ -12,7 +12,9 @@ int32 4294967295 2 0 +tUnsignedOps OK ''' +nimout: "tUnsignedOps OK" """ import typetraits @@ -167,3 +169,19 @@ block tissue12177: echo(a - b) echo(a * b) echo(a div b) + +block tUnsignedOps: + proc testUnsignedOps() = + let a: int8 = -128 + let b: int8 = 127 + + doAssert b +% 1 == -128 + doAssert b -% -1 == -128 + doAssert b *% 2 == -2 + doAssert a /% 4 == 32 + doAssert a %% 7 == 2 + echo "tUnsignedOps OK" + + testUnsignedOps() + static: + testUnsignedOps() diff --git a/tests/pragmas/t6448.nim b/tests/pragmas/t6448.nim index ab2e3811f9bba..6efb56e08ae38 100644 --- a/tests/pragmas/t6448.nim +++ b/tests/pragmas/t6448.nim @@ -1,5 +1,5 @@ discard """ - errormsg: '''ambiguous call; both foobar.async''' + errormsg: '''ambiguous call''' line: 10 disabled: "32bit" """