mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-19 17:38:34 +00:00
System cleanup, part 2 (#13155)
* create basic_types, arithmetics, exceptions, comparisons * create setops.nim * create memalloc.nim * create gc_interface.nim * create iterators_1.nim
This commit is contained in:
1674
lib/system.nim
1674
lib/system.nim
File diff suppressed because it is too large
Load Diff
486
lib/system/arithmetics.nim
Normal file
486
lib/system/arithmetics.nim
Normal file
@@ -0,0 +1,486 @@
|
||||
proc succ*[T: Ordinal](x: T, y = 1): T {.magic: "Succ", noSideEffect.}
|
||||
## Returns the ``y``-th successor (default: 1) of the value ``x``.
|
||||
## ``T`` has to be an `ordinal type <#Ordinal>`_.
|
||||
##
|
||||
## If such a value does not exist, ``OverflowError`` is raised
|
||||
## or a compile time error occurs.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let x = 5
|
||||
## echo succ(5) # => 6
|
||||
## echo succ(5, 3) # => 8
|
||||
|
||||
proc pred*[T: Ordinal](x: T, y = 1): T {.magic: "Pred", noSideEffect.}
|
||||
## Returns the ``y``-th predecessor (default: 1) of the value ``x``.
|
||||
## ``T`` has to be an `ordinal type <#Ordinal>`_.
|
||||
##
|
||||
## If such a value does not exist, ``OverflowError`` is raised
|
||||
## or a compile time error occurs.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let x = 5
|
||||
## echo pred(5) # => 4
|
||||
## echo pred(5, 3) # => 2
|
||||
|
||||
proc inc*[T: Ordinal|uint|uint64](x: var T, y = 1) {.magic: "Inc", noSideEffect.}
|
||||
## Increments the ordinal ``x`` by ``y``.
|
||||
##
|
||||
## If such a value does not exist, ``OverflowError`` is raised or a compile
|
||||
## time error occurs. This is a short notation for: ``x = succ(x, y)``.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var i = 2
|
||||
## inc(i) # i <- 3
|
||||
## inc(i, 3) # i <- 6
|
||||
|
||||
proc dec*[T: Ordinal|uint|uint64](x: var T, y = 1) {.magic: "Dec", noSideEffect.}
|
||||
## Decrements the ordinal ``x`` by ``y``.
|
||||
##
|
||||
## If such a value does not exist, ``OverflowError`` is raised or a compile
|
||||
## time error occurs. This is a short notation for: ``x = pred(x, y)``.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var i = 2
|
||||
## dec(i) # i <- 1
|
||||
## dec(i, 3) # i <- -2
|
||||
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------
|
||||
# built-in operators
|
||||
|
||||
when defined(nimNoZeroExtendMagic):
|
||||
proc ze*(x: int8): int {.deprecated.} =
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int](uint(cast[uint8](x)))
|
||||
|
||||
proc ze*(x: int16): int {.deprecated.} =
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int](uint(cast[uint16](x)))
|
||||
|
||||
proc ze64*(x: int8): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint8](x)))
|
||||
|
||||
proc ze64*(x: int16): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint16](x)))
|
||||
|
||||
proc ze64*(x: int32): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint32](x)))
|
||||
|
||||
proc ze64*(x: int): int64 {.deprecated.} =
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
|
||||
## (This is the case on 64 bit processors.)
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int64](uint64(cast[uint](x)))
|
||||
|
||||
proc toU8*(x: int): int8 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
|
||||
## from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int8](x)
|
||||
|
||||
proc toU16*(x: int): int16 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to an ``int16`` by taking the last
|
||||
## 16 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int16](x)
|
||||
|
||||
proc toU32*(x: int64): int32 {.deprecated.} =
|
||||
## treats `x` as unsigned and converts it to an ``int32`` by taking the
|
||||
## last 32 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
cast[int32](x)
|
||||
|
||||
elif not defined(JS):
|
||||
proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to ``int``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect, deprecated.}
|
||||
## zero extends a smaller integer type to ``int64``. This treats `x` as
|
||||
## unsigned. Does nothing if the size of an ``int`` is the same as ``int64``.
|
||||
## (This is the case on 64 bit processors.)
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect, deprecated.}
|
||||
## treats `x` as unsigned and converts it to a byte by taking the last 8 bits
|
||||
## from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect, deprecated.}
|
||||
## treats `x` as unsigned and converts it to an ``int16`` by taking the last
|
||||
## 16 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect, deprecated.}
|
||||
## treats `x` as unsigned and converts it to an ``int32`` by taking the
|
||||
## last 32 bits from `x`.
|
||||
## **Deprecated since version 0.19.9**: Use unsigned integers instead.
|
||||
|
||||
# integer calculations:
|
||||
proc `+`*(x: int): int {.magic: "UnaryPlusI", noSideEffect.}
|
||||
## Unary `+` operator for an integer. Has no effect.
|
||||
proc `+`*(x: int8): int8 {.magic: "UnaryPlusI", noSideEffect.}
|
||||
proc `+`*(x: int16): int16 {.magic: "UnaryPlusI", noSideEffect.}
|
||||
proc `+`*(x: int32): int32 {.magic: "UnaryPlusI", noSideEffect.}
|
||||
proc `+`*(x: int64): int64 {.magic: "UnaryPlusI", noSideEffect.}
|
||||
|
||||
proc `-`*(x: int): int {.magic: "UnaryMinusI", noSideEffect.}
|
||||
## Unary `-` operator for an integer. Negates `x`.
|
||||
proc `-`*(x: int8): int8 {.magic: "UnaryMinusI", noSideEffect.}
|
||||
proc `-`*(x: int16): int16 {.magic: "UnaryMinusI", noSideEffect.}
|
||||
proc `-`*(x: int32): int32 {.magic: "UnaryMinusI", noSideEffect.}
|
||||
proc `-`*(x: int64): int64 {.magic: "UnaryMinusI64", noSideEffect.}
|
||||
|
||||
proc `not`*(x: int): int {.magic: "BitnotI", noSideEffect.}
|
||||
## Computes the `bitwise complement` of the integer `x`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var
|
||||
## a = 0'u8
|
||||
## b = 0'i8
|
||||
## c = 1000'u16
|
||||
## d = 1000'i16
|
||||
##
|
||||
## echo not a # => 255
|
||||
## echo not b # => -1
|
||||
## echo not c # => 64535
|
||||
## echo not d # => -1001
|
||||
proc `not`*(x: int8): int8 {.magic: "BitnotI", noSideEffect.}
|
||||
proc `not`*(x: int16): int16 {.magic: "BitnotI", noSideEffect.}
|
||||
proc `not`*(x: int32): int32 {.magic: "BitnotI", noSideEffect.}
|
||||
proc `not`*(x: int64): int64 {.magic: "BitnotI", noSideEffect.}
|
||||
|
||||
proc `+`*(x, y: int): int {.magic: "AddI", noSideEffect.}
|
||||
## Binary `+` operator for an integer.
|
||||
proc `+`*(x, y: int8): int8 {.magic: "AddI", noSideEffect.}
|
||||
proc `+`*(x, y: int16): int16 {.magic: "AddI", noSideEffect.}
|
||||
proc `+`*(x, y: int32): int32 {.magic: "AddI", noSideEffect.}
|
||||
proc `+`*(x, y: int64): int64 {.magic: "AddI", noSideEffect.}
|
||||
|
||||
proc `-`*(x, y: int): int {.magic: "SubI", noSideEffect.}
|
||||
## Binary `-` operator for an integer.
|
||||
proc `-`*(x, y: int8): int8 {.magic: "SubI", noSideEffect.}
|
||||
proc `-`*(x, y: int16): int16 {.magic: "SubI", noSideEffect.}
|
||||
proc `-`*(x, y: int32): int32 {.magic: "SubI", noSideEffect.}
|
||||
proc `-`*(x, y: int64): int64 {.magic: "SubI", noSideEffect.}
|
||||
|
||||
proc `*`*(x, y: int): int {.magic: "MulI", noSideEffect.}
|
||||
## Binary `*` operator for an integer.
|
||||
proc `*`*(x, y: int8): int8 {.magic: "MulI", noSideEffect.}
|
||||
proc `*`*(x, y: int16): int16 {.magic: "MulI", noSideEffect.}
|
||||
proc `*`*(x, y: int32): int32 {.magic: "MulI", noSideEffect.}
|
||||
proc `*`*(x, y: int64): int64 {.magic: "MulI", noSideEffect.}
|
||||
|
||||
proc `div`*(x, y: int): int {.magic: "DivI", noSideEffect.}
|
||||
## Computes the integer division.
|
||||
##
|
||||
## This is roughly the same as ``trunc(x/y)``.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ( 1 div 2) == 0
|
||||
## ( 2 div 2) == 1
|
||||
## ( 3 div 2) == 1
|
||||
## ( 7 div 3) == 2
|
||||
## (-7 div 3) == -2
|
||||
## ( 7 div -3) == -2
|
||||
## (-7 div -3) == 2
|
||||
proc `div`*(x, y: int8): int8 {.magic: "DivI", noSideEffect.}
|
||||
proc `div`*(x, y: int16): int16 {.magic: "DivI", noSideEffect.}
|
||||
proc `div`*(x, y: int32): int32 {.magic: "DivI", noSideEffect.}
|
||||
proc `div`*(x, y: int64): int64 {.magic: "DivI", noSideEffect.}
|
||||
|
||||
proc `mod`*(x, y: int): int {.magic: "ModI", noSideEffect.}
|
||||
## Computes the integer modulo operation (remainder).
|
||||
##
|
||||
## This is the same as ``x - (x div y) * y``.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ( 7 mod 5) == 2
|
||||
## (-7 mod 5) == -2
|
||||
## ( 7 mod -5) == 2
|
||||
## (-7 mod -5) == -2
|
||||
proc `mod`*(x, y: int8): int8 {.magic: "ModI", noSideEffect.}
|
||||
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(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`.
|
||||
##
|
||||
## **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.}
|
||||
## Shifts right by pushing copies of the leftmost bit in from the left,
|
||||
## and let the rightmost bits fall off.
|
||||
##
|
||||
## Note that `ashr` is not an operator so use the normal function
|
||||
## call syntax for it.
|
||||
##
|
||||
## See also:
|
||||
## * `shr proc <#shr,int,SomeInteger>`_
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## ashr(0b0001_0000'i8, 2) == 0b0000_0100'i8
|
||||
## ashr(0b1000_0000'i8, 8) == 0b1111_1111'i8
|
||||
## ashr(0b1000_0000'i8, 1) == 0b1100_0000'i8
|
||||
proc ashr*(x: int8, y: SomeInteger): int8 {.magic: "AshrI", noSideEffect.}
|
||||
proc ashr*(x: int16, y: SomeInteger): int16 {.magic: "AshrI", noSideEffect.}
|
||||
proc ashr*(x: int32, y: SomeInteger): int32 {.magic: "AshrI", noSideEffect.}
|
||||
proc ashr*(x: int64, y: SomeInteger): int64 {.magic: "AshrI", noSideEffect.}
|
||||
else:
|
||||
# used for bootstrapping the compiler
|
||||
proc ashr*[T](x: T, y: SomeInteger): T = discard
|
||||
|
||||
proc `and`*(x, y: int): int {.magic: "BitandI", noSideEffect.}
|
||||
## Computes the `bitwise and` of numbers `x` and `y`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## (0b0011 and 0b0101) == 0b0001
|
||||
## (0b0111 and 0b1100) == 0b0100
|
||||
proc `and`*(x, y: int8): int8 {.magic: "BitandI", noSideEffect.}
|
||||
proc `and`*(x, y: int16): int16 {.magic: "BitandI", noSideEffect.}
|
||||
proc `and`*(x, y: int32): int32 {.magic: "BitandI", noSideEffect.}
|
||||
proc `and`*(x, y: int64): int64 {.magic: "BitandI", noSideEffect.}
|
||||
|
||||
proc `or`*(x, y: int): int {.magic: "BitorI", noSideEffect.}
|
||||
## Computes the `bitwise or` of numbers `x` and `y`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## (0b0011 or 0b0101) == 0b0111
|
||||
## (0b0111 or 0b1100) == 0b1111
|
||||
proc `or`*(x, y: int8): int8 {.magic: "BitorI", noSideEffect.}
|
||||
proc `or`*(x, y: int16): int16 {.magic: "BitorI", noSideEffect.}
|
||||
proc `or`*(x, y: int32): int32 {.magic: "BitorI", noSideEffect.}
|
||||
proc `or`*(x, y: int64): int64 {.magic: "BitorI", noSideEffect.}
|
||||
|
||||
proc `xor`*(x, y: int): int {.magic: "BitxorI", noSideEffect.}
|
||||
## Computes the `bitwise xor` of numbers `x` and `y`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## (0b0011 xor 0b0101) == 0b0110
|
||||
## (0b0111 xor 0b1100) == 0b1011
|
||||
proc `xor`*(x, y: int8): int8 {.magic: "BitxorI", noSideEffect.}
|
||||
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`.
|
||||
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`*(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`*(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 `+`*(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 `-`*(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 `*`*(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`*(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`*(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: SomeInteger](x: var T, y: T) {.
|
||||
magic: "Inc", noSideEffect.}
|
||||
## Increments an integer.
|
||||
|
||||
proc `+=`*[T: enum|bool](x: var T, y: T) {.
|
||||
magic: "Inc", noSideEffect, deprecated: "use `inc` instead".}
|
||||
## **Deprecated since v0.20**: use `inc` instead.
|
||||
|
||||
proc `-=`*[T: SomeInteger](x: var T, y: T) {.
|
||||
magic: "Dec", noSideEffect.}
|
||||
## Decrements an integer.
|
||||
|
||||
proc `-=`*[T: enum|bool](x: var T, y: T) {.
|
||||
magic: "Dec", noSideEffect, deprecated: "0.20.0, use `dec` instead".}
|
||||
## **Deprecated since v0.20**: use `dec` instead.
|
||||
|
||||
proc `*=`*[T: SomeInteger](x: var T, y: T) {.
|
||||
inline, noSideEffect.} =
|
||||
## Binary `*=` operator for integers.
|
||||
x = x * y
|
||||
67
lib/system/basic_types.nim
Normal file
67
lib/system/basic_types.nim
Normal file
@@ -0,0 +1,67 @@
|
||||
type
|
||||
int* {.magic: Int.} ## Default integer type; bitwidth depends on
|
||||
## architecture, but is always the same as a pointer.
|
||||
int8* {.magic: Int8.} ## Signed 8 bit integer type.
|
||||
int16* {.magic: Int16.} ## Signed 16 bit integer type.
|
||||
int32* {.magic: Int32.} ## Signed 32 bit integer type.
|
||||
int64* {.magic: Int64.} ## Signed 64 bit integer type.
|
||||
uint* {.magic: UInt.} ## Unsigned default integer type.
|
||||
uint8* {.magic: UInt8.} ## Unsigned 8 bit integer type.
|
||||
uint16* {.magic: UInt16.} ## Unsigned 16 bit integer type.
|
||||
uint32* {.magic: UInt32.} ## Unsigned 32 bit integer type.
|
||||
uint64* {.magic: UInt64.} ## Unsigned 64 bit integer type.
|
||||
|
||||
type # we need to start a new type section here, so that ``0`` can have a type
|
||||
bool* {.magic: Bool.} = enum ## Built-in boolean type.
|
||||
false = 0, true = 1
|
||||
|
||||
const
|
||||
on* = true ## Alias for ``true``.
|
||||
off* = false ## Alias for ``false``.
|
||||
|
||||
type
|
||||
Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer,
|
||||
## bool, character, and enumeration types
|
||||
## as well as their subtypes.
|
||||
|
||||
SomeSignedInt* = int|int8|int16|int32|int64
|
||||
## Type class matching all signed integer types.
|
||||
|
||||
SomeUnsignedInt* = uint|uint8|uint16|uint32|uint64
|
||||
## Type class matching all unsigned integer types.
|
||||
|
||||
SomeInteger* = SomeSignedInt|SomeUnsignedInt
|
||||
## Type class matching all integer types.
|
||||
|
||||
SomeOrdinal* = int|int8|int16|int32|int64|bool|enum|uint|uint8|uint16|uint32|uint64
|
||||
## Type class matching all ordinal types; however this includes enums with
|
||||
## holes.
|
||||
|
||||
BiggestInt* = int64
|
||||
## is an alias for the biggest signed integer type the Nim compiler
|
||||
## supports. Currently this is ``int64``, but it is platform-dependent
|
||||
## in general.
|
||||
|
||||
|
||||
{.push warning[GcMem]: off, warning[Uninit]: off.}
|
||||
{.push hints: off.}
|
||||
|
||||
proc `not`*(x: bool): bool {.magic: "Not", noSideEffect.}
|
||||
## Boolean not; returns true if ``x == false``.
|
||||
|
||||
proc `and`*(x, y: bool): bool {.magic: "And", noSideEffect.}
|
||||
## Boolean ``and``; returns true if ``x == y == true`` (if both arguments
|
||||
## are true).
|
||||
##
|
||||
## Evaluation is lazy: if ``x`` is false, ``y`` will not even be evaluated.
|
||||
proc `or`*(x, y: bool): bool {.magic: "Or", noSideEffect.}
|
||||
## Boolean ``or``; returns true if ``not (not x and not y)`` (if any of
|
||||
## the arguments is true).
|
||||
##
|
||||
## Evaluation is lazy: if ``x`` is true, ``y`` will not even be evaluated.
|
||||
proc `xor`*(x, y: bool): bool {.magic: "Xor", noSideEffect.}
|
||||
## Boolean `exclusive or`; returns true if ``x != y`` (if either argument
|
||||
## is true while the other is false).
|
||||
|
||||
{.pop.}
|
||||
{.pop.}
|
||||
311
lib/system/comparisons.nim
Normal file
311
lib/system/comparisons.nim
Normal file
@@ -0,0 +1,311 @@
|
||||
# comparison operators:
|
||||
proc `==`*[Enum: enum](x, y: Enum): bool {.magic: "EqEnum", noSideEffect.}
|
||||
## Checks whether values within the *same enum* have the same underlying value.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## type
|
||||
## Enum1 = enum
|
||||
## Field1 = 3, Field2
|
||||
## Enum2 = enum
|
||||
## Place1, Place2 = 3
|
||||
## var
|
||||
## e1 = Field1
|
||||
## e2 = Enum1(Place2)
|
||||
## echo (e1 == e2) # true
|
||||
## echo (e1 == Place2) # raises error
|
||||
proc `==`*(x, y: pointer): bool {.magic: "EqRef", noSideEffect.}
|
||||
## .. code-block:: Nim
|
||||
## var # this is a wildly dangerous example
|
||||
## a = cast[pointer](0)
|
||||
## b = cast[pointer](nil)
|
||||
## echo (a == b) # true due to the special meaning of `nil`/0 as a pointer
|
||||
proc `==`*(x, y: string): bool {.magic: "EqStr", noSideEffect.}
|
||||
## Checks for equality between two `string` variables.
|
||||
|
||||
proc `==`*(x, y: char): bool {.magic: "EqCh", noSideEffect.}
|
||||
## Checks for equality between two `char` variables.
|
||||
proc `==`*(x, y: bool): bool {.magic: "EqB", noSideEffect.}
|
||||
## Checks for equality between two `bool` variables.
|
||||
proc `==`*[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.}
|
||||
## Checks for equality between two variables of type `set`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var a = {1, 2, 2, 3} # duplication in sets is ignored
|
||||
## var b = {1, 2, 3}
|
||||
## echo (a == b) # true
|
||||
proc `==`*[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
|
||||
## Checks that two `ref` variables refer to the same item.
|
||||
proc `==`*[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
|
||||
## Checks that two `ptr` variables refer to the same item.
|
||||
proc `==`*[T: proc](x, y: T): bool {.magic: "EqProc", noSideEffect.}
|
||||
## Checks that two `proc` variables refer to the same procedure.
|
||||
|
||||
proc `<=`*[Enum: enum](x, y: Enum): bool {.magic: "LeEnum", noSideEffect.}
|
||||
proc `<=`*(x, y: string): bool {.magic: "LeStr", noSideEffect.}
|
||||
## Compares two strings and returns true if `x` is lexicographically
|
||||
## before `y` (uppercase letters come before lowercase letters).
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = "abc"
|
||||
## b = "abd"
|
||||
## c = "ZZZ"
|
||||
## assert a <= b
|
||||
## assert a <= a
|
||||
## assert (a <= c) == false
|
||||
proc `<=`*(x, y: char): bool {.magic: "LeCh", noSideEffect.}
|
||||
## Compares two chars and returns true if `x` is lexicographically
|
||||
## before `y` (uppercase letters come before lowercase letters).
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = 'a'
|
||||
## b = 'b'
|
||||
## c = 'Z'
|
||||
## assert a <= b
|
||||
## assert a <= a
|
||||
## assert (a <= c) == false
|
||||
proc `<=`*[T](x, y: set[T]): bool {.magic: "LeSet", noSideEffect.}
|
||||
## Returns true if `x` is a subset of `y`.
|
||||
##
|
||||
## A subset `x` has all of its members in `y` and `y` doesn't necessarily
|
||||
## have more members than `x`. That is, `x` can be equal to `y`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = {3, 5}
|
||||
## b = {1, 3, 5, 7}
|
||||
## c = {2}
|
||||
## assert a <= b
|
||||
## assert a <= a
|
||||
## assert (a <= c) == false
|
||||
proc `<=`*(x, y: bool): bool {.magic: "LeB", noSideEffect.}
|
||||
proc `<=`*[T](x, y: ref T): bool {.magic: "LePtr", noSideEffect.}
|
||||
proc `<=`*(x, y: pointer): bool {.magic: "LePtr", noSideEffect.}
|
||||
|
||||
proc `<`*[Enum: enum](x, y: Enum): bool {.magic: "LtEnum", noSideEffect.}
|
||||
proc `<`*(x, y: string): bool {.magic: "LtStr", noSideEffect.}
|
||||
## Compares two strings and returns true if `x` is lexicographically
|
||||
## before `y` (uppercase letters come before lowercase letters).
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = "abc"
|
||||
## b = "abd"
|
||||
## c = "ZZZ"
|
||||
## assert a < b
|
||||
## assert (a < a) == false
|
||||
## assert (a < c) == false
|
||||
proc `<`*(x, y: char): bool {.magic: "LtCh", noSideEffect.}
|
||||
## Compares two chars and returns true if `x` is lexicographically
|
||||
## before `y` (uppercase letters come before lowercase letters).
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = 'a'
|
||||
## b = 'b'
|
||||
## c = 'Z'
|
||||
## assert a < b
|
||||
## assert (a < a) == false
|
||||
## assert (a < c) == false
|
||||
proc `<`*[T](x, y: set[T]): bool {.magic: "LtSet", noSideEffect.}
|
||||
## Returns true if `x` is a strict or proper subset of `y`.
|
||||
##
|
||||
## A strict or proper subset `x` has all of its members in `y` but `y` has
|
||||
## more elements than `y`.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = {3, 5}
|
||||
## b = {1, 3, 5, 7}
|
||||
## c = {2}
|
||||
## assert a < b
|
||||
## assert (a < a) == false
|
||||
## assert (a < c) == false
|
||||
proc `<`*(x, y: bool): bool {.magic: "LtB", noSideEffect.}
|
||||
proc `<`*[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.}
|
||||
proc `<`*[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.}
|
||||
proc `<`*(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.}
|
||||
|
||||
template `!=`*(x, y: untyped): untyped =
|
||||
## Unequals operator. This is a shorthand for ``not (x == y)``.
|
||||
not (x == y)
|
||||
|
||||
template `>=`*(x, y: untyped): untyped =
|
||||
## "is greater or equals" operator. This is the same as ``y <= x``.
|
||||
y <= x
|
||||
|
||||
template `>`*(x, y: untyped): untyped =
|
||||
## "is greater" operator. This is the same as ``y < x``.
|
||||
y < x
|
||||
|
||||
|
||||
proc `==`*(x, y: int): bool {.magic: "EqI", noSideEffect.}
|
||||
## Compares two integers for equality.
|
||||
proc `==`*(x, y: int8): bool {.magic: "EqI", noSideEffect.}
|
||||
proc `==`*(x, y: int16): bool {.magic: "EqI", noSideEffect.}
|
||||
proc `==`*(x, y: int32): bool {.magic: "EqI", noSideEffect.}
|
||||
proc `==`*(x, y: int64): bool {.magic: "EqI", noSideEffect.}
|
||||
|
||||
proc `<=`*(x, y: int): bool {.magic: "LeI", noSideEffect.}
|
||||
## Returns true if `x` is less than or equal to `y`.
|
||||
proc `<=`*(x, y: int8): bool {.magic: "LeI", noSideEffect.}
|
||||
proc `<=`*(x, y: int16): bool {.magic: "LeI", noSideEffect.}
|
||||
proc `<=`*(x, y: int32): bool {.magic: "LeI", noSideEffect.}
|
||||
proc `<=`*(x, y: int64): bool {.magic: "LeI", noSideEffect.}
|
||||
|
||||
proc `<`*(x, y: int): bool {.magic: "LtI", noSideEffect.}
|
||||
## Returns true if `x` is less than `y`.
|
||||
proc `<`*(x, y: int8): bool {.magic: "LtI", noSideEffect.}
|
||||
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: IntMax32): bool {.magic: "LeU", noSideEffect.}
|
||||
proc `<=%`*(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
|
||||
## Treats `x` and `y` as unsigned and compares them.
|
||||
## Returns true if ``unsigned(x) <= unsigned(y)``.
|
||||
|
||||
proc `<%`*(x, y: IntMax32): bool {.magic: "LtU", noSideEffect.}
|
||||
proc `<%`*(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
|
||||
## Treats `x` and `y` as unsigned and compares them.
|
||||
## Returns true if ``unsigned(x) < unsigned(y)``.
|
||||
|
||||
template `>=%`*(x, y: untyped): untyped = y <=% x
|
||||
## Treats `x` and `y` as unsigned and compares them.
|
||||
## Returns true if ``unsigned(x) >= unsigned(y)``.
|
||||
|
||||
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.}
|
||||
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 `<=`*(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.} =
|
||||
if x <= y: x else: y
|
||||
proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.} =
|
||||
if x <= y: x else: y
|
||||
proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.} =
|
||||
if x <= y: x else: y
|
||||
proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.} =
|
||||
if x <= y: x else: y
|
||||
proc min*(x, y: int64): int64 {.magic: "MinI", noSideEffect.} =
|
||||
## The minimum value of two integers.
|
||||
if x <= y: x else: y
|
||||
|
||||
proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.} =
|
||||
if y <= x: x else: y
|
||||
proc max*(x, y: int8): int8 {.magic: "MaxI", noSideEffect.} =
|
||||
if y <= x: x else: y
|
||||
proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.} =
|
||||
if y <= x: x else: y
|
||||
proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.} =
|
||||
if y <= x: x else: y
|
||||
proc max*(x, y: int64): int64 {.magic: "MaxI", noSideEffect.} =
|
||||
## The maximum value of two integers.
|
||||
if y <= x: x else: y
|
||||
|
||||
|
||||
proc min*[T](x: openArray[T]): T =
|
||||
## The minimum value of `x`. ``T`` needs to have a ``<`` operator.
|
||||
result = x[0]
|
||||
for i in 1..high(x):
|
||||
if x[i] < result: result = x[i]
|
||||
|
||||
proc max*[T](x: openArray[T]): T =
|
||||
## The maximum value of `x`. ``T`` needs to have a ``<`` operator.
|
||||
result = x[0]
|
||||
for i in 1..high(x):
|
||||
if result < x[i]: result = x[i]
|
||||
|
||||
{.pop.} # stackTrace: off
|
||||
|
||||
|
||||
proc clamp*[T](x, a, b: T): T =
|
||||
## Limits the value ``x`` within the interval [a, b].
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## assert((1.4).clamp(0.0, 1.0) == 1.0)
|
||||
## assert((0.5).clamp(0.0, 1.0) == 0.5)
|
||||
if x < a: return a
|
||||
if x > b: return b
|
||||
return x
|
||||
|
||||
|
||||
proc `==`*[I, T](x, y: array[I, T]): bool =
|
||||
for f in low(x)..high(x):
|
||||
if x[f] != y[f]:
|
||||
return
|
||||
result = true
|
||||
|
||||
proc `==`*[T](x, y: openArray[T]): bool =
|
||||
if x.len != y.len:
|
||||
return false
|
||||
for f in low(x)..high(x):
|
||||
if x[f] != y[f]:
|
||||
return false
|
||||
result = true
|
||||
|
||||
|
||||
proc `==`*[T](x, y: seq[T]): bool {.noSideEffect.} =
|
||||
## Generic equals operator for sequences: relies on a equals operator for
|
||||
## the element type `T`.
|
||||
when nimvm:
|
||||
when not defined(nimNoNil):
|
||||
if x.isNil and y.isNil:
|
||||
return true
|
||||
else:
|
||||
if x.len == 0 and y.len == 0:
|
||||
return true
|
||||
else:
|
||||
when not defined(JS):
|
||||
proc seqToPtr[T](x: seq[T]): pointer {.inline, noSideEffect.} =
|
||||
when defined(nimSeqsV2):
|
||||
result = cast[NimSeqV2[T]](x).p
|
||||
else:
|
||||
result = cast[pointer](x)
|
||||
|
||||
if seqToPtr(x) == seqToPtr(y):
|
||||
return true
|
||||
else:
|
||||
var sameObject = false
|
||||
asm """`sameObject` = `x` === `y`"""
|
||||
if sameObject: return true
|
||||
|
||||
when not defined(nimNoNil):
|
||||
if x.isNil or y.isNil:
|
||||
return false
|
||||
|
||||
if x.len != y.len:
|
||||
return false
|
||||
|
||||
for i in 0..x.len-1:
|
||||
if x[i] != y[i]:
|
||||
return false
|
||||
|
||||
return true
|
||||
137
lib/system/exceptions.nim
Normal file
137
lib/system/exceptions.nim
Normal file
@@ -0,0 +1,137 @@
|
||||
type
|
||||
RootEffect* {.compilerproc.} = object of RootObj ## \
|
||||
## Base effect class.
|
||||
##
|
||||
## Each effect should inherit from `RootEffect` unless you know what
|
||||
## you're doing.
|
||||
TimeEffect* = object of RootEffect ## Time effect.
|
||||
IOEffect* = object of RootEffect ## IO effect.
|
||||
ReadIOEffect* = object of IOEffect ## Effect describing a read IO operation.
|
||||
WriteIOEffect* = object of IOEffect ## Effect describing a write IO operation.
|
||||
ExecIOEffect* = object of IOEffect ## Effect describing an executing IO operation.
|
||||
|
||||
StackTraceEntry* = object ## In debug mode exceptions store the stack trace that led
|
||||
## to them. A `StackTraceEntry` is a single entry of the
|
||||
## stack trace.
|
||||
procname*: cstring ## Name of the proc that is currently executing.
|
||||
line*: int ## Line number of the proc that is currently executing.
|
||||
filename*: cstring ## Filename of the proc that is currently executing.
|
||||
|
||||
Exception* {.compilerproc, magic: "Exception".} = object of RootObj ## \
|
||||
## Base exception class.
|
||||
##
|
||||
## Each exception has to inherit from `Exception`. See the full `exception
|
||||
## hierarchy <manual.html#exception-handling-exception-hierarchy>`_.
|
||||
parent*: ref Exception ## Parent exception (can be used as a stack).
|
||||
name*: cstring ## The exception's name is its Nim identifier.
|
||||
## This field is filled automatically in the
|
||||
## ``raise`` statement.
|
||||
msg* {.exportc: "message".}: string ## The exception's message. Not
|
||||
## providing an exception message
|
||||
## is bad style.
|
||||
when defined(js):
|
||||
trace: string
|
||||
else:
|
||||
trace: seq[StackTraceEntry]
|
||||
when defined(nimBoostrapCsources0_19_0):
|
||||
# see #10315, bootstrap with `nim cpp` from csources gave error:
|
||||
# error: no member named 'raise_id' in 'Exception'
|
||||
raise_id: uint # set when exception is raised
|
||||
else:
|
||||
raiseId: uint # set when exception is raised
|
||||
up: ref Exception # used for stacking exceptions. Not exported!
|
||||
|
||||
Defect* = object of Exception ## \
|
||||
## Abstract base class for all exceptions that Nim's runtime raises
|
||||
## but that are strictly uncatchable as they can also be mapped to
|
||||
## a ``quit`` / ``trap`` / ``exit`` operation.
|
||||
|
||||
CatchableError* = object of Exception ## \
|
||||
## Abstract class for all exceptions that are catchable.
|
||||
IOError* = object of CatchableError ## \
|
||||
## Raised if an IO error occurred.
|
||||
EOFError* = object of IOError ## \
|
||||
## Raised if an IO "end of file" error occurred.
|
||||
OSError* = object of CatchableError ## \
|
||||
## Raised if an operating system service failed.
|
||||
errorCode*: int32 ## OS-defined error code describing this error.
|
||||
LibraryError* = object of OSError ## \
|
||||
## Raised if a dynamic library could not be loaded.
|
||||
ResourceExhaustedError* = object of CatchableError ## \
|
||||
## Raised if a resource request could not be fulfilled.
|
||||
ArithmeticError* = object of Defect ## \
|
||||
## Raised if any kind of arithmetic error occurred.
|
||||
DivByZeroError* = object of ArithmeticError ## \
|
||||
## Raised for runtime integer divide-by-zero errors.
|
||||
|
||||
OverflowError* = object of ArithmeticError ## \
|
||||
## Raised for runtime integer overflows.
|
||||
##
|
||||
## This happens for calculations whose results are too large to fit in the
|
||||
## provided bits.
|
||||
AccessViolationError* = object of Defect ## \
|
||||
## Raised for invalid memory access errors
|
||||
AssertionError* = object of Defect ## \
|
||||
## Raised when assertion is proved wrong.
|
||||
##
|
||||
## Usually the result of using the `assert() template
|
||||
## <assertions.html#assert.t,untyped,string>`_.
|
||||
ValueError* = object of CatchableError ## \
|
||||
## Raised for string and object conversion errors.
|
||||
KeyError* = object of ValueError ## \
|
||||
## Raised if a key cannot be found in a table.
|
||||
##
|
||||
## Mostly used by the `tables <tables.html>`_ module, it can also be raised
|
||||
## by other collection modules like `sets <sets.html>`_ or `strtabs
|
||||
## <strtabs.html>`_.
|
||||
OutOfMemError* = object of Defect ## \
|
||||
## Raised for unsuccessful attempts to allocate memory.
|
||||
IndexError* = object of Defect ## \
|
||||
## Raised if an array index is out of bounds.
|
||||
|
||||
FieldError* = object of Defect ## \
|
||||
## Raised if a record field is not accessible because its discriminant's
|
||||
## value does not fit.
|
||||
RangeError* = object of Defect ## \
|
||||
## Raised if a range check error occurred.
|
||||
StackOverflowError* = object of Defect ## \
|
||||
## Raised if the hardware stack used for subroutine calls overflowed.
|
||||
ReraiseError* = object of Defect ## \
|
||||
## Raised if there is no exception to reraise.
|
||||
ObjectAssignmentError* = object of Defect ## \
|
||||
## Raised if an object gets assigned to its parent's object.
|
||||
ObjectConversionError* = object of Defect ## \
|
||||
## Raised if an object is converted to an incompatible object type.
|
||||
## You can use ``of`` operator to check if conversion will succeed.
|
||||
FloatingPointError* = object of Defect ## \
|
||||
## Base class for floating point exceptions.
|
||||
FloatInvalidOpError* = object of FloatingPointError ## \
|
||||
## Raised by invalid operations according to IEEE.
|
||||
##
|
||||
## Raised by ``0.0/0.0``, for example.
|
||||
FloatDivByZeroError* = object of FloatingPointError ## \
|
||||
## Raised by division by zero.
|
||||
##
|
||||
## Divisor is zero and dividend is a finite nonzero number.
|
||||
FloatOverflowError* = object of FloatingPointError ## \
|
||||
## Raised for overflows.
|
||||
##
|
||||
## The operation produced a result that exceeds the range of the exponent.
|
||||
FloatUnderflowError* = object of FloatingPointError ## \
|
||||
## Raised for underflows.
|
||||
##
|
||||
## The operation produced a result that is too small to be represented as a
|
||||
## normal number.
|
||||
FloatInexactError* = object of FloatingPointError ## \
|
||||
## Raised for inexact results.
|
||||
##
|
||||
## The operation produced a result that cannot be represented with infinite
|
||||
## precision -- for example: ``2.0 / 3.0, log(1.1)``
|
||||
##
|
||||
## **Note**: Nim currently does not detect these!
|
||||
DeadThreadError* = object of Defect ## \
|
||||
## Raised if it is attempted to send a message to a dead thread.
|
||||
NilAccessError* = object of Defect ## \
|
||||
## Raised on dereferences of ``nil`` pointers.
|
||||
##
|
||||
## This is only raised if the `segfaults module <segfaults.html>`_ was imported!
|
||||
100
lib/system/gc_interface.nim
Normal file
100
lib/system/gc_interface.nim
Normal file
@@ -0,0 +1,100 @@
|
||||
# ----------------- GC interface ---------------------------------------------
|
||||
const
|
||||
usesDestructors = defined(gcDestructors) or defined(gcHooks)
|
||||
|
||||
when not usesDestructors:
|
||||
{.pragma: nodestroy.}
|
||||
|
||||
when hasAlloc:
|
||||
type
|
||||
GC_Strategy* = enum ## The strategy the GC should use for the application.
|
||||
gcThroughput, ## optimize for throughput
|
||||
gcResponsiveness, ## optimize for responsiveness (default)
|
||||
gcOptimizeTime, ## optimize for speed
|
||||
gcOptimizeSpace ## optimize for memory footprint
|
||||
|
||||
when hasAlloc and not defined(JS) and not usesDestructors:
|
||||
proc GC_disable*() {.rtl, inl, benign.}
|
||||
## Disables the GC. If called `n` times, `n` calls to `GC_enable`
|
||||
## are needed to reactivate the GC.
|
||||
##
|
||||
## Note that in most circumstances one should only disable
|
||||
## the mark and sweep phase with
|
||||
## `GC_disableMarkAndSweep <#GC_disableMarkAndSweep>`_.
|
||||
|
||||
proc GC_enable*() {.rtl, inl, benign.}
|
||||
## Enables the GC again.
|
||||
|
||||
proc GC_fullCollect*() {.rtl, benign.}
|
||||
## Forces a full garbage collection pass.
|
||||
## Ordinary code does not need to call this (and should not).
|
||||
|
||||
proc GC_enableMarkAndSweep*() {.rtl, benign.}
|
||||
proc GC_disableMarkAndSweep*() {.rtl, benign.}
|
||||
## The current implementation uses a reference counting garbage collector
|
||||
## with a seldomly run mark and sweep phase to free cycles. The mark and
|
||||
## sweep phase may take a long time and is not needed if the application
|
||||
## does not create cycles. Thus the mark and sweep phase can be deactivated
|
||||
## and activated separately from the rest of the GC.
|
||||
|
||||
proc GC_getStatistics*(): string {.rtl, benign.}
|
||||
## Returns an informative string about the GC's activity. This may be useful
|
||||
## for tweaking.
|
||||
|
||||
proc GC_ref*[T](x: ref T) {.magic: "GCref", benign.}
|
||||
proc GC_ref*[T](x: seq[T]) {.magic: "GCref", benign.}
|
||||
proc GC_ref*(x: string) {.magic: "GCref", benign.}
|
||||
## Marks the object `x` as referenced, so that it will not be freed until
|
||||
## it is unmarked via `GC_unref`.
|
||||
## If called n-times for the same object `x`,
|
||||
## n calls to `GC_unref` are needed to unmark `x`.
|
||||
|
||||
proc GC_unref*[T](x: ref T) {.magic: "GCunref", benign.}
|
||||
proc GC_unref*[T](x: seq[T]) {.magic: "GCunref", benign.}
|
||||
proc GC_unref*(x: string) {.magic: "GCunref", benign.}
|
||||
## See the documentation of `GC_ref <#GC_ref,string>`_.
|
||||
|
||||
proc nimGC_setStackBottom*(theStackBottom: pointer) {.compilerRtl, noinline, benign.}
|
||||
## Expands operating GC stack range to `theStackBottom`. Does nothing
|
||||
## if current stack bottom is already lower than `theStackBottom`.
|
||||
|
||||
when hasAlloc and defined(JS):
|
||||
template GC_disable* =
|
||||
{.warning: "GC_disable is a no-op in JavaScript".}
|
||||
|
||||
template GC_enable* =
|
||||
{.warning: "GC_enable is a no-op in JavaScript".}
|
||||
|
||||
template GC_fullCollect* =
|
||||
{.warning: "GC_fullCollect is a no-op in JavaScript".}
|
||||
|
||||
template GC_setStrategy* =
|
||||
{.warning: "GC_setStrategy is a no-op in JavaScript".}
|
||||
|
||||
template GC_enableMarkAndSweep* =
|
||||
{.warning: "GC_enableMarkAndSweep is a no-op in JavaScript".}
|
||||
|
||||
template GC_disableMarkAndSweep* =
|
||||
{.warning: "GC_disableMarkAndSweep is a no-op in JavaScript".}
|
||||
|
||||
template GC_ref*[T](x: ref T) =
|
||||
{.warning: "GC_ref is a no-op in JavaScript".}
|
||||
|
||||
template GC_ref*[T](x: seq[T]) =
|
||||
{.warning: "GC_ref is a no-op in JavaScript".}
|
||||
|
||||
template GC_ref*(x: string) =
|
||||
{.warning: "GC_ref is a no-op in JavaScript".}
|
||||
|
||||
template GC_unref*[T](x: ref T) =
|
||||
{.warning: "GC_unref is a no-op in JavaScript".}
|
||||
|
||||
template GC_unref*[T](x: seq[T]) =
|
||||
{.warning: "GC_unref is a no-op in JavaScript".}
|
||||
|
||||
template GC_unref*(x: string) =
|
||||
{.warning: "GC_unref is a no-op in JavaScript".}
|
||||
|
||||
template GC_getStatistics*(): string =
|
||||
{.warning: "GC_getStatistics is a no-op in JavaScript".}
|
||||
""
|
||||
214
lib/system/iterators_1.nim
Normal file
214
lib/system/iterators_1.nim
Normal file
@@ -0,0 +1,214 @@
|
||||
when sizeof(int) <= 2:
|
||||
type IntLikeForCount = int|int8|int16|char|bool|uint8|enum
|
||||
else:
|
||||
type IntLikeForCount = int|int8|int16|int32|char|bool|uint8|uint16|enum
|
||||
|
||||
iterator countdown*[T](a, b: T, step: Positive = 1): T {.inline.} =
|
||||
## Counts from ordinal value `a` down to `b` (inclusive) with the given
|
||||
## step count.
|
||||
##
|
||||
## `T` may be any ordinal type, `step` may only be positive.
|
||||
##
|
||||
## **Note**: This fails to count to ``low(int)`` if T = int for
|
||||
## efficiency reasons.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## for i in countdown(7, 3):
|
||||
## echo i # => 7; 6; 5; 4; 3
|
||||
##
|
||||
## for i in countdown(9, 2, 3):
|
||||
## echo i # => 9; 6; 3
|
||||
when T is (uint|uint64):
|
||||
var res = a
|
||||
while res >= b:
|
||||
yield res
|
||||
if res == b: break
|
||||
dec(res, step)
|
||||
elif T is IntLikeForCount:
|
||||
var res = int(a)
|
||||
while res >= int(b):
|
||||
yield T(res)
|
||||
dec(res, step)
|
||||
else:
|
||||
var res = a
|
||||
while res >= b:
|
||||
yield res
|
||||
dec(res, step)
|
||||
|
||||
when defined(nimNewRoof):
|
||||
iterator countup*[T](a, b: T, step: Positive = 1): T {.inline.} =
|
||||
## Counts from ordinal value `a` to `b` (inclusive) with the given
|
||||
## step count.
|
||||
##
|
||||
## `T` may be any ordinal type, `step` may only be positive.
|
||||
##
|
||||
## **Note**: This fails to count to ``high(int)`` if T = int for
|
||||
## efficiency reasons.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## for i in countup(3, 7):
|
||||
## echo i # => 3; 4; 5; 6; 7
|
||||
##
|
||||
## for i in countup(2, 9, 3):
|
||||
## echo i # => 2; 5; 8
|
||||
mixin inc
|
||||
when T is IntLikeForCount:
|
||||
var res = int(a)
|
||||
while res <= int(b):
|
||||
yield T(res)
|
||||
inc(res, step)
|
||||
else:
|
||||
var res = a
|
||||
while res <= b:
|
||||
yield res
|
||||
inc(res, step)
|
||||
|
||||
iterator `..`*[T](a, b: T): T {.inline.} =
|
||||
## An alias for `countup(a, b, 1)`.
|
||||
##
|
||||
## See also:
|
||||
## * [..<](#..<.i,T,T)
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## for i in 3 .. 7:
|
||||
## echo i # => 3; 4; 5; 6; 7
|
||||
mixin inc
|
||||
when T is IntLikeForCount:
|
||||
var res = int(a)
|
||||
while res <= int(b):
|
||||
yield T(res)
|
||||
inc(res)
|
||||
else:
|
||||
var res = a
|
||||
while res <= b:
|
||||
yield res
|
||||
inc(res)
|
||||
|
||||
template dotdotImpl(t) {.dirty.} =
|
||||
iterator `..`*(a, b: t): t {.inline.} =
|
||||
## A type specialized version of ``..`` for convenience so that
|
||||
## mixing integer types works better.
|
||||
##
|
||||
## See also:
|
||||
## * [..<](#..<.i,T,T)
|
||||
var res = a
|
||||
while res <= b:
|
||||
yield res
|
||||
inc(res)
|
||||
|
||||
dotdotImpl(int64)
|
||||
dotdotImpl(int32)
|
||||
dotdotImpl(uint64)
|
||||
dotdotImpl(uint32)
|
||||
|
||||
iterator `..<`*[T](a, b: T): T {.inline.} =
|
||||
mixin inc
|
||||
var i = a
|
||||
while i < b:
|
||||
yield i
|
||||
inc i
|
||||
|
||||
template dotdotLessImpl(t) {.dirty.} =
|
||||
iterator `..<`*(a, b: t): t {.inline.} =
|
||||
## A type specialized version of ``..<`` for convenience so that
|
||||
## mixing integer types works better.
|
||||
var res = a
|
||||
while res < b:
|
||||
yield res
|
||||
inc(res)
|
||||
|
||||
dotdotLessImpl(int64)
|
||||
dotdotLessImpl(int32)
|
||||
dotdotLessImpl(uint64)
|
||||
dotdotLessImpl(uint32)
|
||||
|
||||
else: # not defined(nimNewRoof)
|
||||
iterator countup*[S, T](a: S, b: T, step = 1): T {.inline.} =
|
||||
## Counts from ordinal value `a` up to `b` (inclusive) with the given
|
||||
## step count.
|
||||
##
|
||||
## `S`, `T` may be any ordinal type, `step` may only be positive.
|
||||
##
|
||||
## **Note**: This fails to count to ``high(int)`` if T = int for
|
||||
## efficiency reasons.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## for i in countup(3, 7):
|
||||
## echo i # => 3; 4; 5; 6; 7
|
||||
##
|
||||
## for i in countup(2, 9, 3):
|
||||
## echo i # => 2; 5; 8
|
||||
when T is IntLikeForCount:
|
||||
var res = int(a)
|
||||
while res <= int(b):
|
||||
yield T(res)
|
||||
inc(res, step)
|
||||
else:
|
||||
var res = T(a)
|
||||
while res <= b:
|
||||
yield res
|
||||
inc(res, step)
|
||||
|
||||
iterator `..`*[S, T](a: S, b: T): T {.inline.} =
|
||||
## An alias for `countup(a, b, 1)`.
|
||||
##
|
||||
## See also:
|
||||
## * [..<](#..<.i,T,T)
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## for i in 3 .. 7:
|
||||
## echo i # => 3; 4; 5; 6; 7
|
||||
mixin inc
|
||||
when T is IntLikeForCount:
|
||||
var res = int(a)
|
||||
while res <= int(b):
|
||||
yield T(res)
|
||||
inc(res)
|
||||
else:
|
||||
var res = T(a)
|
||||
while res <= b:
|
||||
yield res
|
||||
inc(res)
|
||||
|
||||
iterator `..<`*[S, T](a: S, b: T): T {.inline.} =
|
||||
mixin inc
|
||||
var i = T(a)
|
||||
while i < b:
|
||||
yield i
|
||||
inc i
|
||||
|
||||
|
||||
iterator `||`*[S, T](a: S, b: T, annotation: static string = "parallel for"): T {.
|
||||
inline, magic: "OmpParFor", sideEffect.} =
|
||||
## OpenMP parallel loop iterator. Same as `..` but the loop may run in parallel.
|
||||
##
|
||||
## `annotation` is an additional annotation for the code generator to use.
|
||||
## The default annotation is `parallel for`.
|
||||
## Please refer to the `OpenMP Syntax Reference
|
||||
## <https://www.openmp.org/wp-content/uploads/OpenMP-4.5-1115-CPP-web.pdf>`_
|
||||
## for further information.
|
||||
##
|
||||
## Note that the compiler maps that to
|
||||
## the ``#pragma omp parallel for`` construct of `OpenMP`:idx: and as
|
||||
## such isn't aware of the parallelism in your code! Be careful! Later
|
||||
## versions of ``||`` will get proper support by Nim's code generator
|
||||
## and GC.
|
||||
discard
|
||||
|
||||
iterator `||`*[S, T](a: S, b: T, step: Positive, annotation: static string = "parallel for"): T {.
|
||||
inline, magic: "OmpParFor", sideEffect.} =
|
||||
## OpenMP parallel loop iterator with stepping.
|
||||
## Same as `countup` but the loop may run in parallel.
|
||||
##
|
||||
## `annotation` is an additional annotation for the code generator to use.
|
||||
## The default annotation is `parallel for`.
|
||||
## Please refer to the `OpenMP Syntax Reference
|
||||
## <https://www.openmp.org/wp-content/uploads/OpenMP-4.5-1115-CPP-web.pdf>`_
|
||||
## for further information.
|
||||
##
|
||||
## Note that the compiler maps that to
|
||||
## the ``#pragma omp parallel for`` construct of `OpenMP`:idx: and as
|
||||
## such isn't aware of the parallelism in your code! Be careful! Later
|
||||
## versions of ``||`` will get proper support by Nim's code generator
|
||||
## and GC.
|
||||
discard
|
||||
262
lib/system/memalloc.nim
Normal file
262
lib/system/memalloc.nim
Normal file
@@ -0,0 +1,262 @@
|
||||
when notJSnotNims:
|
||||
proc zeroMem*(p: pointer, size: Natural) {.inline, noSideEffect,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
## Overwrites the contents of the memory at ``p`` with the value 0.
|
||||
##
|
||||
## Exactly ``size`` bytes will be overwritten. Like any procedure
|
||||
## dealing with raw memory this is **unsafe**.
|
||||
|
||||
proc copyMem*(dest, source: pointer, size: Natural) {.inline, benign,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
## Copies the contents from the memory at ``source`` to the memory
|
||||
## at ``dest``.
|
||||
## Exactly ``size`` bytes will be copied. The memory
|
||||
## regions may not overlap. Like any procedure dealing with raw
|
||||
## memory this is **unsafe**.
|
||||
|
||||
proc moveMem*(dest, source: pointer, size: Natural) {.inline, benign,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
## Copies the contents from the memory at ``source`` to the memory
|
||||
## at ``dest``.
|
||||
##
|
||||
## Exactly ``size`` bytes will be copied. The memory
|
||||
## regions may overlap, ``moveMem`` handles this case appropriately
|
||||
## and is thus somewhat more safe than ``copyMem``. Like any procedure
|
||||
## dealing with raw memory this is still **unsafe**, though.
|
||||
|
||||
proc equalMem*(a, b: pointer, size: Natural): bool {.inline, noSideEffect,
|
||||
tags: [], locks: 0, raises: [].}
|
||||
## Compares the memory blocks ``a`` and ``b``. ``size`` bytes will
|
||||
## be compared.
|
||||
##
|
||||
## If the blocks are equal, `true` is returned, `false`
|
||||
## otherwise. Like any procedure dealing with raw memory this is
|
||||
## **unsafe**.
|
||||
|
||||
when hasAlloc:
|
||||
proc alloc*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
|
||||
## Allocates a new memory block with at least ``size`` bytes.
|
||||
##
|
||||
## The block has to be freed with `realloc(block, 0) <#realloc,pointer,Natural>`_
|
||||
## or `dealloc(block) <#dealloc,pointer>`_.
|
||||
## The block is not initialized, so reading
|
||||
## from it before writing to it is undefined behaviour!
|
||||
##
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `allocShared <#allocShared,Natural>`_ to allocate from a shared heap.
|
||||
##
|
||||
## See also:
|
||||
## * `alloc0 <#alloc0,Natural>`_
|
||||
proc createU*(T: typedesc, size = 1.Positive): ptr T {.inline, benign, raises: [].} =
|
||||
## Allocates a new memory block with at least ``T.sizeof * size`` bytes.
|
||||
##
|
||||
## The block has to be freed with `resize(block, 0) <#resize,ptr.T,Natural>`_
|
||||
## or `dealloc(block) <#dealloc,pointer>`_.
|
||||
## The block is not initialized, so reading
|
||||
## from it before writing to it is undefined behaviour!
|
||||
##
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `createSharedU <#createSharedU,typedesc>`_ to allocate from a shared heap.
|
||||
##
|
||||
## See also:
|
||||
## * `create <#create,typedesc>`_
|
||||
cast[ptr T](alloc(T.sizeof * size))
|
||||
|
||||
proc alloc0*(size: Natural): pointer {.noconv, rtl, tags: [], benign, raises: [].}
|
||||
## Allocates a new memory block with at least ``size`` bytes.
|
||||
##
|
||||
## The block has to be freed with `realloc(block, 0) <#realloc,pointer,Natural>`_
|
||||
## or `dealloc(block) <#dealloc,pointer>`_.
|
||||
## The block is initialized with all bytes containing zero, so it is
|
||||
## somewhat safer than `alloc <#alloc,Natural>`_.
|
||||
##
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `allocShared0 <#allocShared0,Natural>`_ to allocate from a shared heap.
|
||||
proc create*(T: typedesc, size = 1.Positive): ptr T {.inline, benign, raises: [].} =
|
||||
## Allocates a new memory block with at least ``T.sizeof * size`` bytes.
|
||||
##
|
||||
## The block has to be freed with `resize(block, 0) <#resize,ptr.T,Natural>`_
|
||||
## or `dealloc(block) <#dealloc,pointer>`_.
|
||||
## The block is initialized with all bytes containing zero, so it is
|
||||
## somewhat safer than `createU <#createU,typedesc>`_.
|
||||
##
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `createShared <#createShared,typedesc>`_ to allocate from a shared heap.
|
||||
cast[ptr T](alloc0(sizeof(T) * size))
|
||||
|
||||
proc realloc*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [],
|
||||
benign, raises: [].}
|
||||
## Grows or shrinks a given memory block.
|
||||
##
|
||||
## If `p` is **nil** then a new memory block is returned.
|
||||
## In either way the block has at least ``newSize`` bytes.
|
||||
## If ``newSize == 0`` and `p` is not **nil** ``realloc`` calls ``dealloc(p)``.
|
||||
## In other cases the block has to be freed with
|
||||
## `dealloc(block) <#dealloc,pointer>`_.
|
||||
##
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `reallocShared <#reallocShared,pointer,Natural>`_ to reallocate
|
||||
## from a shared heap.
|
||||
proc resize*[T](p: ptr T, newSize: Natural): ptr T {.inline, benign, raises: [].} =
|
||||
## Grows or shrinks a given memory block.
|
||||
##
|
||||
## If `p` is **nil** then a new memory block is returned.
|
||||
## In either way the block has at least ``T.sizeof * newSize`` bytes.
|
||||
## If ``newSize == 0`` and `p` is not **nil** ``resize`` calls ``dealloc(p)``.
|
||||
## In other cases the block has to be freed with ``free``.
|
||||
##
|
||||
## The allocated memory belongs to its allocating thread!
|
||||
## Use `resizeShared <#resizeShared,ptr.T,Natural>`_ to reallocate
|
||||
## from a shared heap.
|
||||
cast[ptr T](realloc(p, T.sizeof * newSize))
|
||||
|
||||
proc dealloc*(p: pointer) {.noconv, rtl, tags: [], benign, raises: [].}
|
||||
## Frees the memory allocated with ``alloc``, ``alloc0`` or
|
||||
## ``realloc``.
|
||||
##
|
||||
## **This procedure is dangerous!**
|
||||
## If one forgets to free the memory a leak occurs; if one tries to
|
||||
## access freed memory (or just freeing it twice!) a core dump may happen
|
||||
## or other memory may be corrupted.
|
||||
##
|
||||
## The freed memory must belong to its allocating thread!
|
||||
## Use `deallocShared <#deallocShared,pointer>`_ to deallocate from a shared heap.
|
||||
|
||||
proc allocShared*(size: Natural): pointer {.noconv, rtl, benign, raises: [], tags: [].}
|
||||
## Allocates a new memory block on the shared heap with at
|
||||
## least ``size`` bytes.
|
||||
##
|
||||
## The block has to be freed with
|
||||
## `reallocShared(block, 0) <#reallocShared,pointer,Natural>`_
|
||||
## or `deallocShared(block) <#deallocShared,pointer>`_.
|
||||
##
|
||||
## The block is not initialized, so reading from it before writing
|
||||
## to it is undefined behaviour!
|
||||
##
|
||||
## See also:
|
||||
## `allocShared0 <#allocShared0,Natural>`_.
|
||||
proc createSharedU*(T: typedesc, size = 1.Positive): ptr T {.inline, tags: [],
|
||||
benign, raises: [].} =
|
||||
## Allocates a new memory block on the shared heap with at
|
||||
## least ``T.sizeof * size`` bytes.
|
||||
##
|
||||
## The block has to be freed with
|
||||
## `resizeShared(block, 0) <#resizeShared,ptr.T,Natural>`_ or
|
||||
## `freeShared(block) <#freeShared,ptr.T>`_.
|
||||
##
|
||||
## The block is not initialized, so reading from it before writing
|
||||
## to it is undefined behaviour!
|
||||
##
|
||||
## See also:
|
||||
## * `createShared <#createShared,typedesc>`_
|
||||
cast[ptr T](allocShared(T.sizeof * size))
|
||||
|
||||
proc allocShared0*(size: Natural): pointer {.noconv, rtl, benign, raises: [], tags: [].}
|
||||
## Allocates a new memory block on the shared heap with at
|
||||
## least ``size`` bytes.
|
||||
##
|
||||
## The block has to be freed with
|
||||
## `reallocShared(block, 0) <#reallocShared,pointer,Natural>`_
|
||||
## or `deallocShared(block) <#deallocShared,pointer>`_.
|
||||
##
|
||||
## The block is initialized with all bytes
|
||||
## containing zero, so it is somewhat safer than
|
||||
## `allocShared <#allocShared,Natural>`_.
|
||||
proc createShared*(T: typedesc, size = 1.Positive): ptr T {.inline.} =
|
||||
## Allocates a new memory block on the shared heap with at
|
||||
## least ``T.sizeof * size`` bytes.
|
||||
##
|
||||
## The block has to be freed with
|
||||
## `resizeShared(block, 0) <#resizeShared,ptr.T,Natural>`_ or
|
||||
## `freeShared(block) <#freeShared,ptr.T>`_.
|
||||
##
|
||||
## The block is initialized with all bytes
|
||||
## containing zero, so it is somewhat safer than
|
||||
## `createSharedU <#createSharedU,typedesc>`_.
|
||||
cast[ptr T](allocShared0(T.sizeof * size))
|
||||
|
||||
proc reallocShared*(p: pointer, newSize: Natural): pointer {.noconv, rtl, tags: [],
|
||||
benign, raises: [].}
|
||||
## Grows or shrinks a given memory block on the heap.
|
||||
##
|
||||
## If `p` is **nil** then a new memory block is returned.
|
||||
## In either way the block has at least ``newSize`` bytes.
|
||||
## If ``newSize == 0`` and `p` is not **nil** ``reallocShared`` calls
|
||||
## ``deallocShared(p)``.
|
||||
## In other cases the block has to be freed with
|
||||
## `deallocShared <#deallocShared,pointer>`_.
|
||||
proc resizeShared*[T](p: ptr T, newSize: Natural): ptr T {.inline, raises: [].} =
|
||||
## Grows or shrinks a given memory block on the heap.
|
||||
##
|
||||
## If `p` is **nil** then a new memory block is returned.
|
||||
## In either way the block has at least ``T.sizeof * newSize`` bytes.
|
||||
## If ``newSize == 0`` and `p` is not **nil** ``resizeShared`` calls
|
||||
## ``freeShared(p)``.
|
||||
## In other cases the block has to be freed with
|
||||
## `freeShared <#freeShared,ptr.T>`_.
|
||||
cast[ptr T](reallocShared(p, T.sizeof * newSize))
|
||||
|
||||
proc deallocShared*(p: pointer) {.noconv, rtl, benign, raises: [], tags: [].}
|
||||
## Frees the memory allocated with ``allocShared``, ``allocShared0`` or
|
||||
## ``reallocShared``.
|
||||
##
|
||||
## **This procedure is dangerous!**
|
||||
## If one forgets to free the memory a leak occurs; if one tries to
|
||||
## access freed memory (or just freeing it twice!) a core dump may happen
|
||||
## or other memory may be corrupted.
|
||||
proc freeShared*[T](p: ptr T) {.inline, benign, raises: [].} =
|
||||
## Frees the memory allocated with ``createShared``, ``createSharedU`` or
|
||||
## ``resizeShared``.
|
||||
##
|
||||
## **This procedure is dangerous!**
|
||||
## If one forgets to free the memory a leak occurs; if one tries to
|
||||
## access freed memory (or just freeing it twice!) a core dump may happen
|
||||
## or other memory may be corrupted.
|
||||
deallocShared(p)
|
||||
|
||||
|
||||
# GC interface:
|
||||
|
||||
when hasAlloc:
|
||||
proc getOccupiedMem*(): int {.rtl.}
|
||||
## Returns the number of bytes that are owned by the process and hold data.
|
||||
|
||||
proc getFreeMem*(): int {.rtl.}
|
||||
## Returns the number of bytes that are owned by the process, but do not
|
||||
## hold any meaningful data.
|
||||
|
||||
proc getTotalMem*(): int {.rtl.}
|
||||
## Returns the number of bytes that are owned by the process.
|
||||
|
||||
|
||||
when defined(JS):
|
||||
# Stubs:
|
||||
proc getOccupiedMem(): int = return -1
|
||||
proc getFreeMem(): int = return -1
|
||||
proc getTotalMem(): int = return -1
|
||||
|
||||
proc dealloc(p: pointer) = discard
|
||||
proc alloc(size: Natural): pointer = discard
|
||||
proc alloc0(size: Natural): pointer = discard
|
||||
proc realloc(p: pointer, newsize: Natural): pointer = discard
|
||||
|
||||
proc allocShared(size: Natural): pointer = discard
|
||||
proc allocShared0(size: Natural): pointer = discard
|
||||
proc deallocShared(p: pointer) = discard
|
||||
proc reallocShared(p: pointer, newsize: Natural): pointer = discard
|
||||
|
||||
|
||||
when hasAlloc and hasThreadSupport:
|
||||
proc getOccupiedSharedMem*(): int {.rtl.}
|
||||
## Returns the number of bytes that are owned by the process
|
||||
## on the shared heap and hold data. This is only available when
|
||||
## threads are enabled.
|
||||
|
||||
proc getFreeSharedMem*(): int {.rtl.}
|
||||
## Returns the number of bytes that are owned by the
|
||||
## process on the shared heap, but do not hold any meaningful data.
|
||||
## This is only available when threads are enabled.
|
||||
|
||||
proc getTotalSharedMem*(): int {.rtl.}
|
||||
## Returns the number of bytes on the shared heap that are owned by the
|
||||
## process. This is only available when threads are enabled.
|
||||
94
lib/system/setops.nim
Normal file
94
lib/system/setops.nim
Normal file
@@ -0,0 +1,94 @@
|
||||
proc incl*[T](x: var set[T], y: T) {.magic: "Incl", noSideEffect.}
|
||||
## Includes element ``y`` in the set ``x``.
|
||||
##
|
||||
## This is the same as ``x = x + {y}``, but it might be more efficient.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var a = {1, 3, 5}
|
||||
## a.incl(2) # a <- {1, 2, 3, 5}
|
||||
## a.incl(4) # a <- {1, 2, 3, 4, 5}
|
||||
|
||||
template incl*[T](x: var set[T], y: set[T]) =
|
||||
## Includes the set ``y`` in the set ``x``.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var a = {1, 3, 5, 7}
|
||||
## var b = {4, 5, 6}
|
||||
## a.incl(b) # a <- {1, 3, 4, 5, 6, 7}
|
||||
x = x + y
|
||||
|
||||
proc excl*[T](x: var set[T], y: T) {.magic: "Excl", noSideEffect.}
|
||||
## Excludes element ``y`` from the set ``x``.
|
||||
##
|
||||
## This is the same as ``x = x - {y}``, but it might be more efficient.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var b = {2, 3, 5, 6, 12, 545}
|
||||
## b.excl(5) # b <- {2, 3, 6, 12, 545}
|
||||
|
||||
template excl*[T](x: var set[T], y: set[T]) =
|
||||
## Excludes the set ``y`` from the set ``x``.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var a = {1, 3, 5, 7}
|
||||
## var b = {3, 4, 5}
|
||||
## a.excl(b) # a <- {1, 7}
|
||||
x = x - y
|
||||
|
||||
proc card*[T](x: set[T]): int {.magic: "Card", noSideEffect.}
|
||||
## Returns the cardinality of the set ``x``, i.e. the number of elements
|
||||
## in the set.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var a = {1, 3, 5, 7}
|
||||
## echo card(a) # => 4
|
||||
|
||||
proc len*[T](x: set[T]): int {.magic: "Card", noSideEffect.}
|
||||
## An alias for `card(x)`.
|
||||
|
||||
|
||||
proc `*`*[T](x, y: set[T]): set[T] {.magic: "MulSet", noSideEffect.}
|
||||
## This operator computes the intersection of two sets.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = {1, 2, 3}
|
||||
## b = {2, 3, 4}
|
||||
## echo a * b # => {2, 3}
|
||||
proc `+`*[T](x, y: set[T]): set[T] {.magic: "PlusSet", noSideEffect.}
|
||||
## This operator computes the union of two sets.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = {1, 2, 3}
|
||||
## b = {2, 3, 4}
|
||||
## echo a + b # => {1, 2, 3, 4}
|
||||
proc `-`*[T](x, y: set[T]): set[T] {.magic: "MinusSet", noSideEffect.}
|
||||
## This operator computes the difference of two sets.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## let
|
||||
## a = {1, 2, 3}
|
||||
## b = {2, 3, 4}
|
||||
## echo a - b # => {1}
|
||||
|
||||
proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.}
|
||||
## One should overload this proc if one wants to overload the ``in`` operator.
|
||||
##
|
||||
## The parameters are in reverse order! ``a in b`` is a template for
|
||||
## ``contains(b, a)``.
|
||||
## This is because the unification algorithm that Nim uses for overload
|
||||
## resolution works from left to right.
|
||||
## But for the ``in`` operator that would be the wrong direction for this
|
||||
## piece of code:
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var s: set[range['a'..'z']] = {'a'..'c'}
|
||||
## assert s.contains('c')
|
||||
## assert 'b' in s
|
||||
##
|
||||
## If ``in`` had been declared as ``[T](elem: T, s: set[T])`` then ``T`` would
|
||||
## have been bound to ``char``. But ``s`` is not compatible to type
|
||||
## ``set[char]``! The solution is to bind ``T`` to ``range['a'..'z']``. This
|
||||
## is achieved by reversing the parameters for ``contains``; ``in`` then
|
||||
## passes its arguments in reverse order.
|
||||
Reference in New Issue
Block a user