From 7707a4b40f148743682dcb098cf184f4024fef56 Mon Sep 17 00:00:00 2001 From: Mamy Ratsimbazafy Date: Thu, 31 May 2018 14:31:27 +0200 Subject: [PATCH] Add overloads for literals only (#50) --- stint.nim | 4 +- stint/literals_stint.nim | 87 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 stint/literals_stint.nim diff --git a/stint.nim b/stint.nim index 007e08d..c38335e 100644 --- a/stint.nim +++ b/stint.nim @@ -7,8 +7,8 @@ # # at your option. This file may not be copied, modified, or distributed except according to those terms. -import stint/[uint_public, int_public, io, modular_arithmetic] -export uint_public, int_public, io, modular_arithmetic +import stint/[uint_public, int_public, io, modular_arithmetic, literals_stint] +export uint_public, int_public, io, modular_arithmetic, literals_stint type Int128* = Stint[128] diff --git a/stint/literals_stint.nim b/stint/literals_stint.nim new file mode 100644 index 0000000..437b48c --- /dev/null +++ b/stint/literals_stint.nim @@ -0,0 +1,87 @@ +# Stint +# Copyright 2018 Status Research & Development GmbH +# Licensed under either of +# +# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) +# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT) +# +# at your option. This file may not be copied, modified, or distributed except according to those terms. + +## This file provides syntactic sugar to work with literals + +import ./int_public, ./uint_public, macros + +type Signedness = enum + BothSigned, IntOnly, UintOnly + +macro make_mixed_types_ops(op: untyped, ResultTy: untyped, sign: static[Signedness], switchInputs: static[bool]): untyped = + # ResultTy must be "InputType" or a real type like bool + + let isInputType = eqIdent(ResultTy, "InputType") + result = newStmtList() + + # Workaround for int{lit} in quote do block + let intLit = nnkCurlyExpr.newTree( + newIdentNode("int"), + newIdentNode("lit") + ) + + if sign != IntOnly: + let ResultTy = if not isInputType: ResultTy + else: nnkBracketExpr.newTree( + newIdentNode("StUint"), + newIdentNode("bits") + ) + + result.add quote do: + proc `op`*[bits: static[int]](a: Stuint[bits], b: `intLit`): `ResultTy` {.inline.}= + `op`(a, b.stuint(bits)) + + if switchInputs: + result.add quote do: + proc `op`*[bits: static[int]](a: `intLit`, b: Stuint[bits]): `ResultTy` {.inline.}= + `op`(a.stuint(bits), b) + + if sign != UintOnly: + let ResultTy = if not isInputType: ResultTy + else: nnkBracketExpr.newTree( + newIdentNode("StInt"), + newIdentNode("bits") + ) + + result.add quote do: + proc `op`*[bits: static[int]](a: Stint[bits], b: `intLit`): `ResultTy` {.inline.}= + `op`(a, b.stuint(bits)) + + if switchInputs: + result.add quote do: + proc `op`*[bits: static[int]](a: `intLit`, b: Stint[bits]): `ResultTy` {.inline.}= + `op`(a.stuint(bits), b) + +make_mixed_types_ops(`+`, InputType, BothSigned, switchInputs = true) +make_mixed_types_ops(`+=`, InputType, BothSigned, switchInputs = false) +make_mixed_types_ops(`-`, InputType, BothSigned, switchInputs = true) +make_mixed_types_ops(`-=`, InputType, BothSigned, switchInputs = false) +make_mixed_types_ops(`*`, InputType, BothSigned, switchInputs = true) +make_mixed_types_ops(`div`, InputType, BothSigned, switchInputs = false) +make_mixed_types_ops(`mod`, InputType, BothSigned, switchInputs = false) +make_mixed_types_ops(divmod, InputType, BothSigned, switchInputs = false) + +make_mixed_types_ops(`<`, bool, BothSigned, switchInputs = true) +make_mixed_types_ops(`<=`, bool, BothSigned, switchInputs = true) +make_mixed_types_ops(`==`, bool, BothSigned, switchInputs = true) + +make_mixed_types_ops(`or`, InputType, BothSigned, switchInputs = true) +make_mixed_types_ops(`and`, InputType, BothSigned, switchInputs = true) +make_mixed_types_ops(`xor`, InputType, BothSigned, switchInputs = true) + +# Specialization / fast path for comparison to zero +# Note system.nim has templates to transform > and >= into <= and < +template mtoIsZero*{a == 0}(a: StUint or Stint): bool = a.isZero +template mtoIsZero*{0 == a}(a: StUint or Stint): bool = a.isZero + +template mtoIsNeg*{a < 0}(a: Stint): bool = a.isNegative +template mtoIsNegOrZero*{a <= 0}(a: Stint): bool = a.isZero or a.isNegative + +template mtoIsPos*{0 < a}(a: Stint): bool = not(a.isZero or a.isNegative) +template mtoIsPosOrZero*{0 <= a}(a: Stint): bool = not a.isNegative