Skip to content

Commit

Permalink
System cleanup, part 2 (#13155)
Browse files Browse the repository at this point in the history
* create basic_types, arithmetics, exceptions, comparisons
* create setops.nim
* create memalloc.nim
* create gc_interface.nim
* create iterators_1.nim
  • Loading branch information
narimiran authored and Araq committed Jan 15, 2020
1 parent 79a3267 commit e708d5d
Show file tree
Hide file tree
Showing 9 changed files with 1,700 additions and 1,649 deletions.
1,678 changes: 29 additions & 1,649 deletions lib/system.nim

Large diffs are not rendered by default.

486 changes: 486 additions & 0 deletions lib/system/arithmetics.nim

Large diffs are not rendered by default.

67 changes: 67 additions & 0 deletions lib/system/basic_types.nim
Original file line number Diff line number Diff line change
@@ -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 changes: 311 additions & 0 deletions lib/system/comparisons.nim
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit e708d5d

Please sign in to comment.