diff options
Diffstat (limited to 'nimlib/system.nim')
-rwxr-xr-x | nimlib/system.nim | 1531 |
1 files changed, 0 insertions, 1531 deletions
diff --git a/nimlib/system.nim b/nimlib/system.nim deleted file mode 100755 index 174d739cd..000000000 --- a/nimlib/system.nim +++ /dev/null @@ -1,1531 +0,0 @@ -# -# -# Nimrod's Runtime Library -# (c) Copyright 2009 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## The compiler depends on the System module to work properly and the System -## module depends on the compiler. Most of the routines listed here use -## special compiler magic. -## Each module implicitly imports the System module; it may not be listed -## explicitly. Because of this there cannot be a user-defined module named -## ``system``. - -{.push hints: off.} - -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 - float* {.magic: Float.} ## default floating point type - float32* {.magic: Float32.} ## 32 bit floating point type - float64* {.magic: Float64.} ## 64 bit floating point 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 - -type - char* {.magic: Char.} ## built-in 8 bit character type (unsigned) - string* {.magic: String.} ## built-in string type - cstring* {.magic: Cstring.} ## built-in cstring (*compatible string*) type - pointer* {.magic: Pointer.} ## built-in pointer type - Ordinal* {.magic: Ordinal.}[T] - -type - `nil` {.magic: "Nil".} - expr* {.magic: Expr.} ## meta type to denote an expression (for templates) - stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates) - typeDesc* {.magic: TypeDesc.} ## meta type to denote - ## a type description (for templates) - -proc defined*[T](x: T): bool {.magic: "Defined", noSideEffect.} - ## Special comile-time procedure that checks whether `x` is - ## defined. `x` has to be an identifier or a qualified identifier. - ## This can be used to check whether a library provides a certain - ## feature or not: - ## - ## .. code-block:: Nimrod - ## when not defined(strutils.toUpper): - ## # provide our own toUpper proc here, because strutils is - ## # missing it. - -proc definedInScope*[T](x: T): bool {. - magic: "DefinedInScope", noSideEffect.} - ## Special comile-time procedure that checks whether `x` is - ## defined in the current scope. `x` has to be an identifier. - -# these require compiler magic: -proc `not` *(x: bool): bool {.magic: "Not", noSideEffect.} - ## Boolean not; returns true iff ``x == false``. - -proc `and`*(x, y: bool): bool {.magic: "And", noSideEffect.} - ## Boolean ``and``; returns true iff ``x == y == true``. - ## Evaluation is short-circuited: This means that if ``x`` is false, - ## ``y`` will not even be evaluated. -proc `or`*(x, y: bool): bool {.magic: "Or", noSideEffect.} - ## Boolean ``or``; returns true iff ``not (not x and not y)``. - ## Evaluation is short-circuited: This means that if ``x`` is true, - ## ``y`` will not even be evaluated. -proc `xor`*(x, y: bool): bool {.magic: "Xor", noSideEffect.} - ## Boolean `exclusive or`; returns true iff ``x != y``. - -proc new*[T](a: var ref T) {.magic: "New", noSideEffect.} - ## creates a new object of type ``T`` and returns a safe (traced) - ## reference to it in ``a``. - -proc new*[T](a: var ref T, finalizer: proc (x: ref T)) {. - magic: "NewFinalize", noSideEffect.} - ## creates a new object of type ``T`` and returns a safe (traced) - ## reference to it in ``a``. When the garbage collector frees the object, - ## `finalizer` is called. The `finalizer` may not keep a reference to the - ## object pointed to by `x`. The `finalizer` cannot prevent the GC from - ## freeing the object. Note: The `finalizer` refers to the type `T`, not to - ## the object! This means that for each object of type `T` the finalizer - ## will be called! - -# for low and high the return type T may not be correct, but -# we handle that with compiler magic in SemLowHigh() -proc high*[T](x: T): T {.magic: "High", noSideEffect.} - ## returns the highest possible index of an array, a sequence, a string or - ## the highest possible value of an ordinal value `x`. As a special - ## semantic rule, `x` may also be a type identifier. - -proc low*[T](x: T): T {.magic: "Low", noSideEffect.} - ## returns the lowest possible index of an array, a sequence, a string or - ## the lowest possible value of an ordinal value `x`. As a special - ## semantic rule, `x` may also be a type identifier. - -type - range*{.magic: "Range".} [T] ## Generic type to construct range types. - array*{.magic: "Array".}[I, T] ## Generic type to construct - ## fixed-length arrays. - openarray*{.magic: "OpenArray".}[T] ## Generic type to construct open arrays. - ## Open arrays are implemented as a - ## pointer to the array data and a - ## length field. - seq*{.magic: "Seq".}[T] ## Generic type to construct sequences. - set*{.magic: "Set".}[T] ## Generic type to construct bit sets. - -when not defined(EcmaScript) and not defined(NimrodVM): - type - TGenericSeq {.compilerproc, pure.} = object - len, space: int - PGenericSeq {.exportc.} = ptr TGenericSeq - # len and space without counting the terminating zero: - NimStringDesc {.compilerproc, final.} = object of TGenericSeq - data: array[0..100_000_000, char] - NimString = ptr NimStringDesc - - include "system/hti" - -type - Byte* = Int8 ## this is an alias for ``int8``, that is a signed - ## int 8 bits wide. - - Natural* = range[0..high(int)] - ## is an int type ranging from zero to the maximum value - ## of an int. This type is often useful for documentation and debugging. - - Positive* = range[1..high(int)] - ## is an int type ranging from one to the maximum value - ## of an int. This type is often useful for documentation and debugging. - - TObject* {.exportc: "TNimObject".} = - object ## the root of Nimrod's object hierarchy. Objects should - ## inherit from TObject or one of its descendants. However, - ## objects that have no ancestor are allowed. - PObject* = ref TObject ## reference to TObject - - E_Base* {.compilerproc.} = object of TObject ## base exception class; - ## each exception has to - ## inherit from `E_Base`. - name*: cstring ## The exception's name is its Nimrod identifier. - ## This field is filled automatically in the - ## ``raise`` statement. - msg* {.exportc: "message".}: cstring ## the exception's message. Not - ## providing an - ## exception message is bad style. - - EAsynch* = object of E_Base ## Abstract exception class for - ## *asynchronous exceptions* (interrupts). - ## This is rarely needed: Most - ## exception types inherit from `ESynch` - ESynch* = object of E_Base ## Abstract exception class for - ## *synchronous exceptions*. Most exceptions - ## should be inherited (directly or indirectly) - ## from ESynch. - ESystem* = object of ESynch ## Abstract class for exceptions that the runtime - ## system raises. - EIO* = object of ESystem ## raised if an IO error occured. - EOS* = object of ESystem ## raised if an operating system service failed. - EInvalidLibrary* = object of EOS ## raised if a dynamic library - ## could not be loaded. - ERessourceExhausted* = object of ESystem ## raised if a ressource request - ## could not be fullfilled. - EArithmetic* = object of ESynch ## raised if any kind of arithmetic - ## error occured. - EDivByZero* {.compilerproc.} = - object of EArithmetic ## is the exception class for integer divide-by-zero - ## errors. - EOverflow* {.compilerproc.} = - object of EArithmetic ## is the exception class for integer calculations - ## whose results are too large to fit in the - ## provided bits. - - EAccessViolation* {.compilerproc.} = - object of ESynch ## the exception class for invalid memory access errors - - EAssertionFailed* {.compilerproc.} = - object of ESynch ## is the exception class for Assert - ## procedures that is raised if the - ## assertion proves wrong - - EControlC* = object of EAsynch ## is the exception class for Ctrl+C - ## key presses in console applications. - - EInvalidValue* = object of ESynch ## is the exception class for string - ## and object conversion errors. - - EOutOfMemory* = object of ESystem ## is the exception class for - ## unsuccessful attempts to allocate - ## memory. - - EInvalidIndex* = object of ESynch ## is raised if an array index is out - ## of bounds. - EInvalidField* = object of ESynch ## is raised if a record field is not - ## accessible because its dicriminant's - ## value does not fit. - - EOutOfRange* = object of ESynch ## is raised if a range check error - ## occured. - - EStackOverflow* = object of ESystem ## is raised if the hardware stack - ## used for subroutine calls overflowed. - - ENoExceptionToReraise* = object of ESynch ## is raised if there is no - ## exception to reraise. - - EInvalidObjectAssignment* = - object of ESynch ## is raised if an object gets assigned to its - ## farther's object. - - EInvalidObjectConversion* = - object of ESynch ## is raised if an object is converted to an incompatible - ## object type. - - TResult* = enum Failure, Success - -proc sizeof*[T](x: T): natural {.magic: "SizeOf", noSideEffect.} - ## returns the size of ``x`` in bytes. Since this is a low-level proc, - ## its usage is discouraged - using ``new`` for the most cases suffices - ## that one never needs to know ``x``'s size. As a special semantic rule, - ## ``x`` may also be a type identifier (``sizeof(int)`` is valid). - -proc succ*[T](x: ordinal[T], y = 1): T {.magic: "Succ", noSideEffect.} - ## returns the ``y``-th successor of the value ``x``. ``T`` has to be - ## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised - ## or a compile time error occurs. - -proc pred*[T](x: ordinal[T], y = 1): T {.magic: "Pred", noSideEffect.} - ## returns the ``y``-th predecessor of the value ``x``. ``T`` has to be - ## an ordinal type. If such a value does not exist, ``EOutOfRange`` is raised - ## or a compile time error occurs. - -proc inc*[T](x: var ordinal[T], y = 1) {.magic: "Inc", noSideEffect.} - ## increments the ordinal ``x`` by ``y``. If such a value does not - ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a - ## short notation for: ``x = succ(x, y)``. - -proc dec*[T](x: var ordinal[T], y = 1) {.magic: "Dec", noSideEffect.} - ## decrements the ordinal ``x`` by ``y``. If such a value does not - ## exist, ``EOutOfRange`` is raised or a compile time error occurs. This is a - ## short notation for: ``x = pred(x, y)``. - -proc newSeq*[T](s: var seq[T], len: int) {.magic: "NewSeq", noSideEffect.} - ## creates a new sequence of type ``seq[T]`` with length ``len``. - ## This is equivalent to ``s = @[]; setlen(s, len)``, but more - ## efficient since no reallocation is needed. - -proc len*[T](x: openarray[T]): int {.magic: "LengthOpenArray", noSideEffect.} -proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} -proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.} -proc len*[I, T](x: array[I, T]): int {.magic: "LengthArray", noSideEffect.} -proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.} - ## returns the length of an array, a sequence or a string. - ## This is rougly the same as ``high(T)-low(T)+1``, but its resulting type is - ## always an int. - -# set routines: -proc incl*[T](x: var set[T], y: T) {.magic: "Incl", noSideEffect.} - ## includes element ``y`` to the set ``x``. This is the same as - ## ``x = x + {y}``, but it might be more efficient. - -proc excl*[T](x: var set[T], y: T) {.magic: "Excl", noSideEffect.} - ## excludes element ``y`` to the set ``x``. This is the same as - ## ``x = x - {y}``, but it might be more efficient. - -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. - -proc ord*[T](x: T): int {.magic: "Ord", noSideEffect.} - ## returns the internal int value of an ordinal value ``x``. - -proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.} - ## converts an int in the range 0..255 to a character. - -# -------------------------------------------------------------------------- -# built-in operators - -proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect.} - ## zero extends a smaller integer type to ``int``. This treats `x` as - ## unsigned. -proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect.} - ## zero extends a smaller integer type to ``int``. This treats `x` as - ## unsigned. - -proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.} - ## zero extends a smaller integer type to ``int64``. This treats `x` as - ## unsigned. -proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.} - ## zero extends a smaller integer type to ``int64``. This treats `x` as - ## unsigned. - -proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.} - ## zero extends a smaller integer type to ``int64``. This treats `x` as - ## unsigned. -proc ze64*(x: int): int64 {.magic: "ZeIToI64", noDecl, noSideEffect.} - ## 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.) - -proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect.} - ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits - ## from `x`. -proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect.} - ## treats `x` as unsigned and converts it to an ``int16`` by taking the last - ## 16 bits from `x`. -proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect.} - ## treats `x` as unsigned and converts it to an ``int32`` by taking the - ## last 32 bits from `x`. - - -# integer calculations: -proc `+` *(x: int): int {.magic: "UnaryPlusI", noSideEffect.} -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: "UnaryPlusI64", noSideEffect.} - ## Unary `+` operator for an integer. Has no effect. - -proc `-` *(x: int): int {.magic: "UnaryMinusI", noSideEffect.} -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.} - ## Unary `-` operator for an integer. Negates `x`. - -proc `not` *(x: int): int {.magic: "BitnotI", noSideEffect.} -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: "BitnotI64", noSideEffect.} - ## computes the `bitwise complement` of the integer `x`. - -proc `+` *(x, y: int): int {.magic: "AddI", noSideEffect.} -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: "AddI64", noSideEffect.} - ## Binary `+` operator for an integer. - -proc `-` *(x, y: int): int {.magic: "SubI", noSideEffect.} -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: "SubI64", noSideEffect.} - ## Binary `-` operator for an integer. - -proc `*` *(x, y: int): int {.magic: "MulI", noSideEffect.} -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: "MulI64", noSideEffect.} - ## Binary `*` operator for an integer. - -proc `div` *(x, y: int): int {.magic: "DivI", noSideEffect.} -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: "DivI64", noSideEffect.} - ## computes the integer division. This is roughly the same as - ## ``floor(x/y)``. - -proc `mod` *(x, y: int): int {.magic: "ModI", noSideEffect.} -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: "ModI64", noSideEffect.} - ## computes the integer modulo operation. This is the same as - ## ``x - (x div y) * y``. - -proc `shr` *(x, y: int): int {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int8): int8 {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int16): int16 {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int32): int32 {.magic: "ShrI", noSideEffect.} -proc `shr` *(x, y: int64): int64 {.magic: "ShrI64", noSideEffect.} - ## computes the `shift right` operation of `x` and `y`. - -proc `shl` *(x, y: int): int {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int8): int8 {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int16): int16 {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int32): int32 {.magic: "ShlI", noSideEffect.} -proc `shl` *(x, y: int64): int64 {.magic: "ShlI64", noSideEffect.} - ## computes the `shift left` operation of `x` and `y`. - -proc `and` *(x, y: int): int {.magic: "BitandI", noSideEffect.} -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: "BitandI64", noSideEffect.} - ## computes the `bitwise and` of numbers `x` and `y`. - -proc `or` *(x, y: int): int {.magic: "BitorI", noSideEffect.} -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: "BitorI64", noSideEffect.} - ## computes the `bitwise or` of numbers `x` and `y`. - -proc `xor` *(x, y: int): int {.magic: "BitxorI", noSideEffect.} -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: "BitxorI64", noSideEffect.} - ## computes the `bitwise xor` of numbers `x` and `y`. - -proc `==` *(x, y: int): bool {.magic: "EqI", noSideEffect.} -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: "EqI64", noSideEffect.} - ## Compares two integers for equality. - -proc `<=` *(x, y: int): bool {.magic: "LeI", noSideEffect.} -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: "LeI64", noSideEffect.} - ## Returns true iff `x` is less than or equal to `y`. - -proc `<` *(x, y: int): bool {.magic: "LtI", noSideEffect.} -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: "LtI64", noSideEffect.} - ## Returns true iff `x` is less than `y`. - -proc abs*(x: int): int {.magic: "AbsI", noSideEffect.} -proc abs*(x: int8): int8 {.magic: "AbsI", noSideEffect.} -proc abs*(x: int16): int16 {.magic: "AbsI", noSideEffect.} -proc abs*(x: int32): int32 {.magic: "AbsI", noSideEffect.} -proc abs*(x: int64): int64 {.magic: "AbsI64", noSideEffect.} - ## returns the absolute value of `x`. If `x` is ``low(x)`` (that - ## is -MININT for its type), an overflow exception is thrown (if overflow - ## checking is turned on). - -proc `+%` *(x, y: int): int {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int8): int8 {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int16): int16 {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int32): int32 {.magic: "AddU", noSideEffect.} -proc `+%` *(x, y: int64): int64 {.magic: "AddU64", 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: int): int {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int8): int8 {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int16): int16 {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int32): int32 {.magic: "SubU", noSideEffect.} -proc `-%` *(x, y: int64): int64 {.magic: "SubU64", 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: int): int {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int8): int8 {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int16): int16 {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int32): int32 {.magic: "MulU", noSideEffect.} -proc `*%` *(x, y: int64): int64 {.magic: "MulU64", 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: int): int {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int8): int8 {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int16): int16 {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int32): int32 {.magic: "DivU", noSideEffect.} -proc `/%` *(x, y: int64): int64 {.magic: "DivU64", 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: int): int {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int8): int8 {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int16): int16 {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int32): int32 {.magic: "ModU", noSideEffect.} -proc `%%` *(x, y: int64): int64 {.magic: "ModU64", 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. - -proc `<=%` *(x, y: int): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int8): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int16): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int32): bool {.magic: "LeU", noSideEffect.} -proc `<=%` *(x, y: int64): bool {.magic: "LeU64", noSideEffect.} - ## treats `x` and `y` as unsigned and compares them. - ## Returns true iff ``unsigned(x) <= unsigned(y)``. - -proc `<%` *(x, y: int): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int8): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int16): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int32): bool {.magic: "LtU", noSideEffect.} -proc `<%` *(x, y: int64): bool {.magic: "LtU64", noSideEffect.} - ## treats `x` and `y` as unsigned and compares them. - ## Returns true iff ``unsigned(x) < unsigned(y)``. - - -# floating point operations: -proc `+` *(x: float): float {.magic: "UnaryPlusF64", noSideEffect.} -proc `-` *(x: float): float {.magic: "UnaryMinusF64", noSideEffect.} -proc `+` *(x, y: float): float {.magic: "AddF64", noSideEffect.} -proc `-` *(x, y: float): float {.magic: "SubF64", noSideEffect.} -proc `*` *(x, y: float): float {.magic: "MulF64", noSideEffect.} -proc `/` *(x, y: float): float {.magic: "DivF64", noSideEffect.} - ## computes the floating point division - -proc `==` *(x, y: float): bool {.magic: "EqF64", noSideEffect.} -proc `<=` *(x, y: float): bool {.magic: "LeF64", noSideEffect.} -proc `<` *(x, y: float): bool {.magic: "LtF64", noSideEffect.} -proc abs*(x: float): float {.magic: "AbsF64", noSideEffect.} -proc min*(x, y: float): float {.magic: "MinF64", noSideEffect.} -proc max*(x, y: float): float {.magic: "MaxF64", noSideEffect.} - -# set operators -proc `*` *[T](x, y: set[T]): set[T] {.magic: "MulSet", noSideEffect.} - ## This operator computes the intersection of two sets. -proc `+` *[T](x, y: set[T]): set[T] {.magic: "PlusSet", noSideEffect.} - ## This operator computes the union of two sets. -proc `-` *[T](x, y: set[T]): set[T] {.magic: "MinusSet", noSideEffect.} - ## This operator computes the difference of two sets. -proc `-+-` *[T](x, y: set[T]): set[T] {.magic: "SymDiffSet", noSideEffect.} - ## computes the symmetric set difference. This is the same as - ## ``(A - B) + (B - A)``, but more efficient. - -# comparison operators: -proc `==` *[T](x, y: ordinal[T]): bool {.magic: "EqEnum", noSideEffect.} -proc `==` *(x, y: pointer): bool {.magic: "EqRef", noSideEffect.} -proc `==` *(x, y: string): bool {.magic: "EqStr", noSideEffect.} -proc `==` *(x, y: cstring): bool {.magic: "EqCString", noSideEffect.} -proc `==` *(x, y: char): bool {.magic: "EqCh", noSideEffect.} -proc `==` *(x, y: bool): bool {.magic: "EqB", noSideEffect.} -proc `==` *[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.} -proc `==` *[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.} -proc `==` *[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.} - -proc `<=` *[T](x, y: ordinal[T]): bool {.magic: "LeEnum", noSideEffect.} -proc `<=` *(x, y: string): bool {.magic: "LeStr", noSideEffect.} -proc `<=` *(x, y: char): bool {.magic: "LeCh", noSideEffect.} -proc `<=` *[T](x, y: set[T]): bool {.magic: "LeSet", noSideEffect.} -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 `<` *[T](x, y: ordinal[T]): bool {.magic: "LtEnum", noSideEffect.} -proc `<` *(x, y: string): bool {.magic: "LtStr", noSideEffect.} -proc `<` *(x, y: char): bool {.magic: "LtCh", noSideEffect.} -proc `<` *[T](x, y: set[T]): bool {.magic: "LtSet", noSideEffect.} -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: expr): expr = - ## unequals operator. This is a shorthand for ``not (x == y)``. - not (x == y) - -template `>=` * (x, y: expr): expr = - ## "is greater or equals" operator. This is the same as ``y <= x``. - y <= x - -template `>` * (x, y: expr): expr = - ## "is greater" operator. This is the same as ``y < x``. - y < x - -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 Nimrod 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:: Nimrod - ## var s: set[range['a'..'z']] = {'a'..'c'} - ## writeln(stdout, '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. - -template `in` * (x, y: expr): expr = contains(y, x) -template `not_in` * (x, y: expr): expr = not contains(y, x) - -proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} -template `is_not` *(x, y: expr): expr = not (x is y) - -proc cmp*[T, S: typeDesc](x: T, y: S): int = - ## Generic compare proc. Returns a value < 0 iff x < y, a value > 0 iff x > y - ## and 0 iff x == y. This is useful for writing generic algorithms without - ## performance loss. This generic implementation uses the `==` and `<` - ## operators. - if x == y: return 0 - if x < y: return -1 - return 1 - -proc cmp*(x, y: string): int {.noSideEffect.} - ## Compare proc for strings. More efficient than the generic version. - -proc `@` * [IDX, T](a: array[IDX, T]): seq[T] {. - magic: "ArrToSeq", nosideeffect.} - ## turns an array into a sequence. This most often useful for constructing - ## sequences with the array constructor: ``@[1, 2, 3]`` has the type - ## ``seq[int]``, while ``[1, 2, 3]`` has the type ``array[0..2, int]``. - -proc setLen*[T](s: var seq[T], newlen: int) {. - magic: "SetLengthSeq", noSideEffect.} - ## sets the length of `s` to `newlen`. - ## ``T`` may be any sequence type. - ## If the current length is greater than the new length, - ## ``s`` will be truncated. - -proc setLen*(s: var string, newlen: int) {. - magic: "SetLengthStr", noSideEffect.} - ## sets the length of `s` to `newlen`. - ## If the current length is greater than the new length, - ## ``s`` will be truncated. - -proc newString*(len: int): string {. - magic: "NewString", importc: "mnewString", noSideEffect.} - ## returns a new string of length ``len`` but with uninitialized - ## content. One needs to fill the string character after character - ## with the index operator ``s[i]``. This procedure exists only for - ## optimization purposes; the same effect can be achieved with the - ## ``&`` operator. - -# concat operator: -proc `&` * (x: string, y: char): string {. - magic: "ConStrStr", noSideEffect, merge.} -proc `&` * (x: char, y: char): string {. - magic: "ConStrStr", noSideEffect, merge.} -proc `&` * (x, y: string): string {. - magic: "ConStrStr", noSideEffect, merge.} -proc `&` * (x: char, y: string): string {. - magic: "ConStrStr", noSideEffect, merge.} - ## is the `concatenation operator`. It concatenates `x` and `y`. - -proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.} -proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} - -when not defined(ECMAScript): - {.push overflow_checks:off} - proc add* (x: var string, y: cstring) = - var i = 0 - while y[i] != '\0': - add(x, y[i]) - inc(i) - {.pop.} -else: - proc add* (x: var string, y: cstring) {.pure.} = - asm """ - var len = `x`[0].length-1; - for (var i = 0; i < `y`.length; ++i) { - `x`[0][len] = `y`.charCodeAt(i); - ++len; - } - `x`[0][len] = 0 - """ - -proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.} -proc add *[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} = - ## Generic proc for adding a data item `y` to a container `x`. - ## For containers that have an order, `add` means *append*. New generic - ## containers should also call their adding proc `add` for consistency. - ## Generic code becomes much easier to write if the Nimrod naming scheme is - ## respected. - var xl = x.len - setLen(x, xl + y.len) - for i in 0..high(y): x[xl+i] = y[i] - -proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.} - ## takes any Nimrod variable and returns its string representation. It - ## works even for complex data graphs with cycles. This is a great - ## debugging tool. - -type - TAddress* = int - ## is the signed integer type that should be used for converting - ## pointers to integer addresses for readability. - -type - BiggestInt* = int64 - ## is an alias for the biggest signed integer type the Nimrod compiler - ## supports. Currently this is ``int64``, but it is platform-dependant - ## in general. - - BiggestFloat* = float64 - ## is an alias for the biggest floating point type the Nimrod - ## compiler supports. Currently this is ``float64``, but it is - ## platform-dependant in general. - -type # these work for most platforms: - cchar* {.importc: "char", nodecl.} = char - ## This is the same as the type ``char`` in *C*. - cschar* {.importc: "signed char", nodecl.} = byte - ## This is the same as the type ``signed char`` in *C*. - cshort* {.importc: "short", nodecl.} = int16 - ## This is the same as the type ``short`` in *C*. - cint* {.importc: "int", nodecl.} = int32 - ## This is the same as the type ``int`` in *C*. - clong* {.importc: "long", nodecl.} = int - ## This is the same as the type ``long`` in *C*. - clonglong* {.importc: "long long", nodecl.} = int64 - ## This is the same as the type ``long long`` in *C*. - cfloat* {.importc: "float", nodecl.} = float32 - ## This is the same as the type ``float`` in *C*. - cdouble* {.importc: "double", nodecl.} = float64 - ## This is the same as the type ``double`` in *C*. - clongdouble* {.importc: "long double", nodecl.} = BiggestFloat - ## This is the same as the type ``long double`` in *C*. - ## This C type is not supported by Nimrod's code generator - - cstringArray* {.importc: "char**", nodecl.} = ptr array [0..50_000, cstring] - ## This is binary compatible to the type ``char**`` in *C*. The array's - ## high value is large enough to disable bounds checking in practice. - - TEndian* = enum ## is a type describing the endianness of a processor. - littleEndian, bigEndian - - PFloat32* = ptr Float32 ## an alias for ``ptr float32`` - PFloat64* = ptr Float64 ## an alias for ``ptr float64`` - PInt64* = ptr Int64 ## an alias for ``ptr int64`` - PInt32* = ptr Int32 ## an alias for ``ptr int32`` - -const - isMainModule* {.magic: "IsMainModule".}: bool = false - ## is true only when accessed in the main module. This works thanks to - ## compiler magic. It is useful to embed testing code in a module. - - CompileDate* {.magic: "CompileDate"}: string = "0000-00-00" - ## is the date of compilation as a string of the form - ## ``YYYY-MM-DD``. This works thanks to compiler magic. - - CompileTime* {.magic: "CompileTime"}: string = "00:00:00" - ## is the time of compilation as a string of the form - ## ``HH:MM:SS``. This works thanks to compiler magic. - - NimrodVersion* {.magic: "NimrodVersion"}: string = "0.0.0" - ## is the version of Nimrod as a string. - ## This works thanks to compiler magic. - - NimrodMajor* {.magic: "NimrodMajor"}: int = 0 - ## is the major number of Nimrod's version. - ## This works thanks to compiler magic. - - NimrodMinor* {.magic: "NimrodMinor"}: int = 0 - ## is the minor number of Nimrod's version. - ## This works thanks to compiler magic. - - NimrodPatch* {.magic: "NimrodPatch"}: int = 0 - ## is the patch number of Nimrod's version. - ## This works thanks to compiler magic. - - cpuEndian* {.magic: "CpuEndian"}: TEndian = littleEndian - ## is the endianness of the target CPU. This is a valuable piece of - ## information for low-level code only. This works thanks to compiler magic. - - hostOS* {.magic: "HostOS"}: string = "" - ## a string that describes the host operating system. Possible values: - ## "windows", "macosx", "linux", "netbsd", "freebsd", "openbsd", "solaris", - ## "aix" - - hostCPU* {.magic: "HostCPU"}: string = "" - ## a string that describes the host CPU. Possible values: - ## "i386", "alpha", "powerpc", "sparc", "amd64", "mips", "arm" - -proc toFloat*(i: int): float {. - magic: "ToFloat", noSideEffect, importc: "toFloat".} - ## converts an integer `i` into a ``float``. If the conversion - ## fails, `EInvalidValue` is raised. However, on most platforms the - ## conversion cannot fail. - -proc toBiggestFloat*(i: biggestint): biggestfloat {. - magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".} - ## converts an biggestint `i` into a ``biggestfloat``. If the conversion - ## fails, `EInvalidValue` is raised. However, on most platforms the - ## conversion cannot fail. - -proc toInt*(f: float): int {. - magic: "ToInt", noSideEffect, importc: "toInt".} - ## converts a floating point number `f` into an ``int``. Conversion - ## rounds `f` if it does not contain an integer value. If the conversion - ## fails (because `f` is infinite for example), `EInvalidValue` is raised. - -proc toBiggestInt*(f: biggestfloat): biggestint {. - magic: "ToBiggestInt", noSideEffect, importc: "toBiggestInt".} - ## converts a biggestfloat `f` into a ``biggestint``. Conversion - ## rounds `f` if it does not contain an integer value. If the conversion - ## fails (because `f` is infinite for example), `EInvalidValue` is raised. - -proc addQuitProc*(QuitProc: proc {.noconv.}) {.importc: "atexit", nodecl.} - ## adds/registers a quit procedure. Each call to ``addQuitProc`` - ## registers another quit procedure. Up to 30 procedures can be - ## registered. They are executed on a last-in, first-out basis - ## (that is, the last function registered is the first to be executed). - ## ``addQuitProc`` raises an EOutOfIndex if ``quitProc`` cannot be - ## registered. - -# Support for addQuitProc() is done by Ansi C's facilities here. -# In case of an unhandled exeption the exit handlers should -# not be called explicitly! The user may decide to do this manually though. - -proc copy*(s: string, first = 0): string {. - magic: "CopyStr", importc: "copyStr", noSideEffect.} -proc copy*(s: string, first, last: int): string {. - magic: "CopyStrLast", importc: "copyStrLast", noSideEffect.} - ## copies a slice of `s` into a new string and returns this new - ## string. The bounds `first` and `last` denote the indices of - ## the first and last characters that shall be copied. If ``last`` - ## is omitted, it is treated as ``high(s)``. - -proc zeroMem*(p: Pointer, size: int) {.importc, noDecl.} - ## 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: int) {.importc: "memcpy", noDecl.} - ## 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: int) {.importc: "memmove", noDecl.} - ## 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: int): bool {. - importc: "equalMem", noDecl, noSideEffect.} - ## 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*. - -proc alloc*(size: int): pointer {.noconv.} - ## allocates a new memory block with at least ``size`` bytes. The - ## block has to be freed with ``realloc(block, 0)`` or - ## ``dealloc(block)``. The block is not initialized, so reading - ## from it before writing to it is undefined behaviour! -proc alloc0*(size: int): pointer {.noconv.} - ## allocates a new memory block with at least ``size`` bytes. The - ## block has to be freed with ``realloc(block, 0)`` or - ## ``dealloc(block)``. The block is initialized with all bytes - ## containing zero, so it is somewhat safer than ``alloc``. -proc realloc*(p: Pointer, newsize: int): pointer {.noconv.} - ## 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``. -proc dealloc*(p: Pointer) {.noconv.} - ## 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. - -proc assert*(cond: bool) {.magic: "Assert", noSideEffect.} - ## provides a means to implement `programming by contracts`:idx: in Nimrod. - ## ``assert`` evaluates expression ``cond`` and if ``cond`` is false, it - ## raises an ``EAssertionFailure`` exception. However, the compiler may - ## not generate any code at all for ``assert`` if it is advised to do so. - ## Use ``assert`` for debugging purposes only. - -proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.} - ## swaps the values `a` and `b`. This is often more efficient than - ## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms. - -template `>=%` *(x, y: expr): expr = y <=% x - ## treats `x` and `y` as unsigned and compares them. - ## Returns true iff ``unsigned(x) >= unsigned(y)``. - -template `>%` *(x, y: expr): expr = y <% x - ## treats `x` and `y` as unsigned and compares them. - ## Returns true iff ``unsigned(x) > unsigned(y)``. - -proc `$` *(x: int): string {.magic: "IntToStr", noSideEffect.} - ## The stingify operator for an integer argument. Returns `x` - ## converted to a decimal string. - -proc `$` *(x: int64): string {.magic: "Int64ToStr", noSideEffect.} - ## The stingify operator for an integer argument. Returns `x` - ## converted to a decimal string. - -proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.} - ## The stingify operator for a float argument. Returns `x` - ## converted to a decimal string. - -proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.} - ## The stingify operator for a boolean argument. Returns `x` - ## converted to the string "false" or "true". - -proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.} - ## The stingify operator for a character argument. Returns `x` - ## converted to a string. - -proc `$` *(x: Cstring): string {.magic: "CStrToStr", noSideEffect.} - ## The stingify operator for a CString argument. Returns `x` - ## converted to a string. - -proc `$` *(x: string): string {.magic: "StrToStr", noSideEffect.} - ## The stingify operator for a string argument. Returns `x` - ## as it is. This operator is useful for generic code, so - ## that ``$expr`` also works if ``expr`` is already a string. - -proc `$` *[T](x: ordinal[T]): string {.magic: "EnumToStr", noSideEffect.} - ## The stingify operator for an enumeration argument. This works for - ## any enumeration type thanks to compiler magic. If a - ## a ``$`` operator for a concrete enumeration is provided, this is - ## used instead. (In other words: *Overwriting* is possible.) - -# undocumented: -proc getRefcount*[T](x: ref T): int {.importc: "getRefcount", noSideEffect.} - ## retrieves the reference count of an heap-allocated object. The - ## value is implementation-dependant. - -#proc writeStackTrace() {.export: "writeStackTrace".} - -when not defined(NimrodVM): - proc getCurrentExceptionMsg*(): string {.exportc.} - ## retrieves the error message that was attached to the current - ## exception; if there is none, "" is returned. - -# new constants: -const - inf* {.magic: "Inf".} = 1.0 / 0.0 - ## contains the IEEE floating point value of positive infinity. - neginf* {.magic: "NegInf".} = -inf - ## contains the IEEE floating point value of negative infinity. - nan* {.magic: "NaN".} = 0.0 / 0.0 - ## contains an IEEE floating point value of *Not A Number*. Note - ## that you cannot compare a floating point value to this value - ## and expect a reasonable result - use the `classify` procedure - ## in the module ``math`` for checking for NaN. - -var - dbgLineHook*: proc = nil - ## set this variable to provide a procedure that should be called before - ## each executed instruction. This should only be used by debuggers! - ## Only code compiled with the ``debugger:on`` switch calls this hook. - -# GC interface: - -proc getOccupiedMem*(): int - ## returns the number of bytes that are owned by the process and hold data. - -proc getFreeMem*(): int - ## returns the number of bytes that are owned by the process, but do not - ## hold any meaningful data. - -proc getTotalMem*(): int - ## returns the number of bytes that are owned by the process. - - -iterator countdown*[T](a, b: T, step = 1): T {.inline.} = - ## Counts from ordinal value `a` down to `b` with the given - ## step count. `T` may be any ordinal type, `step` may only - ## be positive. - var res = a - while res >= b: - yield res - dec(res, step) - -iterator countup*[T](a, b: T, step = 1): T {.inline.} = - ## Counts from ordinal value `a` up to `b` with the given - ## step count. `T` may be any ordinal type, `step` may only - ## be positive. - var res = a - while res <= b: - yield res - inc(res, step) - # we cannot use ``for x in a..b: `` here, because that is not - # known in the System module - - -proc min*(x, y: int): int {.magic: "MinI", noSideEffect.} -proc min*(x, y: int8): int8 {.magic: "MinI", noSideEffect.} -proc min*(x, y: int16): int16 {.magic: "MinI", noSideEffect.} -proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.} -proc min*(x, y: int64): int64 {.magic: "MinI64", noSideEffect.} - ## The minimum value of two integers. - -proc min*[T](x: openarray[T]): T = - ## The minimum value of an openarray. - result = x[0] - for i in 1..high(x): result = min(result, x[i]) - -proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.} -proc max*(x, y: int8): int8 {.magic: "MaxI", noSideEffect.} -proc max*(x, y: int16): int16 {.magic: "MaxI", noSideEffect.} -proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.} -proc max*(x, y: int64): int64 {.magic: "MaxI64", noSideEffect.} - ## The maximum value of two integers. - -proc max*[T](x: openarray[T]): T = - ## The maximum value of an openarray. - result = x[0] - for i in 1..high(x): result = max(result, x[i]) - - -iterator items*[T](a: openarray[T]): T {.inline.} = - ## iterates over each item of `a`. - var i = 0 - while i < len(a): - yield a[i] - inc(i) - -iterator items*[IX, T](a: array[IX, T]): T {.inline.} = - ## iterates over each item of `a`. - var i = low(IX) - if i <= high(IX): - while true: - yield a[i] - if i >= high(IX): break - inc(i) - -iterator items*[T](a: seq[T]): T {.inline.} = - ## iterates over each item of `a`. - var i = 0 - while i < len(a): - yield a[i] - inc(i) - -iterator items*(a: string): char {.inline.} = - ## iterates over each item of `a`. - var i = 0 - while i < len(a): - yield a[i] - inc(i) - -iterator items*[T](a: set[T]): T {.inline.} = - ## iterates over each element of `a`. `items` iterates only over the - ## elements that are really in the set (and not over the ones the set is - ## able to hold). - var i = low(T) - if i <= high(T): - while true: - if i in a: yield i - if i >= high(T): break - inc(i) - -iterator items*(a: cstring): char {.inline.} = - ## iterates over each item of `a`. - var i = 0 - while a[i] != '\0': - yield a[i] - inc(i) - -proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".} -proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".} -proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil".} -proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".} -proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".} -proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".} - ## Fast check whether `x` is nil. This is sometimes more efficient than - ## ``== nil``. - - -# Fixup some magic symbols here: -#{.fixup_system.} -# This is an undocumented pragma that can only be used -# once in the system module. - -proc `&` *[T](x, y: openArray[T]): seq[T] {.noSideEffect.} = - newSeq(result, x.len + y.len) - for i in 0..x.len-1: - result[i] = x[i] - for i in 0..y.len-1: - result[i+x.len] = y[i] - -proc `&` *[T](x: openArray[T], y: T): seq[T] {.noSideEffect.} = - newSeq(result, x.len + 1) - for i in 0..x.len-1: - result[i] = x[i] - result[x.len] = y - -proc `&` *[T](x: T, y: openArray[T]): seq[T] {.noSideEffect.} = - newSeq(result, y.len + 1) - for i in 0..y.len-1: - result[i] = y[i] - result[y.len] = x - -when not defined(NimrodVM): - when not defined(ECMAScript): - proc seqToPtr[T](x: seq[T]): pointer {.inline, nosideeffect.} = - result = cast[pointer](x) - else: - proc seqToPtr[T](x: seq[T]): pointer {.pure, nosideeffect.} = - asm """return `x`""" - - proc `==` *[T: typeDesc](x, y: seq[T]): bool {.noSideEffect.} = - ## Generic equals operator for sequences: relies on a equals operator for - ## the element type `T`. - if seqToPtr(x) == seqToPtr(y): - result = true - elif seqToPtr(x) == nil or seqToPtr(y) == nil: - result = false - elif x.len == y.len: - for i in 0..x.len-1: - if x[i] != y[i]: return false - result = true - -proc find*[T, S: typeDesc](a: T, item: S): int {.inline.}= - ## Returns the first index of `item` in `a` or -1 if not found. This requires - ## appropriate `items` and `==` procs to work. - for i in items(a): - if i == item: return - inc(result) - result = -1 - -proc contains*[T](a: openArray[T], item: T): bool {.inline.}= - ## Returns true if `item` is in `a` or false if not found. This is a shortcut - ## for ``find(a, item) >= 0``. - return find(a, item) >= 0 - -proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} = - ## returns the last item of `s` and decreases ``s.len`` by one. This treats - ## `s` as a stack and implements the common *pop* operation. - var L = s.len-1 - result = s[L] - setLen(s, L) - -proc each*[T, S](data: openArray[T], op: proc (x: T): S): seq[S] {. - noSideEffect.} = - ## The well-known ``map`` operation from functional programming. Applies - ## `op` to every item in `data` and returns the result as a sequence. - newSeq(result, data.len) - for i in 0..data.len-1: result[i] = op(data[i]) - - -# ----------------- FPU ------------------------------------------------------ - -#proc disableFPUExceptions*() -# disables all floating point unit exceptions - -#proc enableFPUExceptions*() -# enables all floating point unit exceptions - -# ----------------- GC interface --------------------------------------------- - -proc GC_disable*() - ## 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`. - -proc GC_enable*() - ## enables the GC again. - -proc GC_fullCollect*() - ## forces a full garbage collection pass. - ## Ordinary code does not need to call this (and should not). - -type - TGC_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 - -proc GC_setStrategy*(strategy: TGC_Strategy) - ## tells the GC the desired strategy for the application. - -proc GC_enableMarkAndSweep*() -proc GC_disableMarkAndSweep*() - ## 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 - ## returns an informative string about the GC's activity. This may be useful - ## for tweaking. - -proc GC_ref*[T](x: ref T) {.magic: "GCref".} -proc GC_ref*[T](x: seq[T]) {.magic: "GCref".} -proc GC_ref*(x: string) {.magic: "GCref".} - ## 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".} -proc GC_unref*[T](x: seq[T]) {.magic: "GCunref".} -proc GC_unref*(x: string) {.magic: "GCunref".} - ## see the documentation of `GC_ref`. - -template accumulateResult*(iter: expr) = - ## helps to convert an iterator to a proc. - result = @[] - for x in iter: add(result, x) - -{.push checks: off, line_dir: off, debugger: off.} -# obviously we cannot generate checking operations here :-) -# because it would yield into an endless recursion -# however, stack-traces are available for most parts -# of the code - -proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo".} - ## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is - ## available for the ECMAScript target too! - -template newException(exceptn, message: expr): expr = - block: # open a new scope - var - e: ref exceptn - new(e) - e.msg = message - e - -const - QuitSuccess* = 0 - ## is the value that should be passed to ``quit`` to indicate - ## success. - - QuitFailure* = 1 - ## is the value that should be passed to ``quit`` to indicate - ## failure. - -proc quit*(errorcode: int = QuitSuccess) {. - magic: "Exit", importc: "exit", noDecl, noReturn.} - ## stops the program immediately; before stopping the program the - ## "quit procedures" are called in the opposite order they were added - ## with ``addQuitProc``. ``quit`` never returns and ignores any - ## exception that may have been raised by the quit procedures. - ## It does *not* call the garbage collector to free all the memory, - ## unless a quit procedure calls ``GC_collect``. - -when not defined(EcmaScript) and not defined(NimrodVM): - proc quit*(errormsg: string) {.noReturn.} - ## a shorthand for ``echo(errormsg); quit(quitFailure)``. - -when not defined(EcmaScript) and not defined(NimrodVM): - - proc initGC() - - var - strDesc: TNimType - - strDesc.size = sizeof(string) - strDesc.kind = tyString - strDesc.flags = {ntfAcyclic} - initGC() # BUGFIX: need to be called here! - - {.push stack_trace: off.} - - include "system/ansi_c" - - proc cmp(x, y: string): int = - return int(c_strcmp(x, y)) - - const pccHack = if defined(pcc): "_" else: "" # Hack for PCC - when defined(windows): - # work-around C's sucking abstraction: - # BUGFIX: stdin and stdout should be binary files! - proc setmode(handle, mode: int) {.importc: pccHack & "setmode", - header: "<io.h>".} - proc fileno(f: C_TextFileStar): int {.importc: pccHack & "fileno", - header: "<fcntl.h>".} - var - O_BINARY {.importc: pccHack & "O_BINARY", nodecl.}: int - - # we use binary mode in Windows: - setmode(fileno(c_stdin), O_BINARY) - setmode(fileno(c_stdout), O_BINARY) - - when defined(endb): - proc endbStep() - - # ----------------- IO Part -------------------------------------------------- - - type - CFile {.importc: "FILE", nodecl, final.} = object # empty record for - # data hiding - TFile* = ptr CFile ## The type representing a file handle. - - TFileMode* = enum ## The file mode when opening a file. - fmRead, ## Open the file for read access only. - fmWrite, ## Open the file for write access only. - fmReadWrite, ## Open the file for read and write access. - ## If the file does not exist, it will be - ## created. - fmReadWriteExisting, ## Open the file for read and write access. - ## If the file does not exist, it will not be - ## created. - fmAppend ## Open the file for writing only; append data - ## at the end. - - TFileHandle* = cint ## type that represents an OS file handle; this is - ## useful for low-level file access - - # text file handling: - var - stdin* {.importc: "stdin", noDecl.}: TFile ## The standard input stream. - stdout* {.importc: "stdout", noDecl.}: TFile ## The standard output stream. - stderr* {.importc: "stderr", noDecl.}: TFile - ## The standard error stream. - ## - ## Note: In my opinion, this should not be used -- the concept of a - ## separate error stream is a design flaw of UNIX. A seperate *message - ## stream* is a good idea, but since it is named ``stderr`` there are few - ## programs out there that distinguish properly between ``stdout`` and - ## ``stderr``. So, that's what you get if you don't name your variables - ## appropriately. It also annoys people if redirection via ``>output.txt`` - ## does not work because the program writes to ``stderr``. - - proc OpenFile*(f: var TFile, filename: string, - mode: TFileMode = fmRead, - bufSize: int = -1): Bool {.deprecated.} - ## **Deprecated since version 0.8.0**: Use `open` instead. - - proc OpenFile*(f: var TFile, filehandle: TFileHandle, - mode: TFileMode = fmRead): Bool {.deprecated.} - ## **Deprecated since version 0.8.0**: Use `open` instead. - - proc Open*(f: var TFile, filename: string, - mode: TFileMode = fmRead, bufSize: int = -1): Bool - ## Opens a file named `filename` with given `mode`. - ## - ## Default mode is readonly. Returns true iff the file could be opened. - ## This throws no exception if the file could not be opened. The reason is - ## that the programmer needs to provide an appropriate error message anyway - ## (yes, even in scripts). - - proc Open*(f: var TFile, filehandle: TFileHandle, - mode: TFileMode = fmRead): Bool - ## Creates a ``TFile`` from a `filehandle` with given `mode`. - ## - ## Default mode is readonly. Returns true iff the file could be opened. - - proc CloseFile*(f: TFile) {.importc: "fclose", nodecl, deprecated.} - ## Closes the file. - ## **Deprecated since version 0.8.0**: Use `close` instead. - - proc Close*(f: TFile) {.importc: "fclose", nodecl.} - ## Closes the file. - - proc EndOfFile*(f: TFile): Bool - ## Returns true iff `f` is at the end. - proc readChar*(f: TFile): char {.importc: "fgetc", nodecl.} - ## Reads a single character from the stream `f`. If the stream - ## has no more characters, `EEndOfFile` is raised. - proc FlushFile*(f: TFile) {.importc: "fflush", noDecl.} - ## Flushes `f`'s buffer. - - proc readFile*(filename: string): string - ## Opens a file name `filename` for reading. Then reads the - ## file's content completely into a string and - ## closes the file afterwards. Returns the string. Returns nil if there was - ## an error. Does not throw an IO exception. - - proc write*(f: TFile, r: float) - proc write*(f: TFile, i: int) - proc write*(f: TFile, s: string) - proc write*(f: TFile, b: Bool) - proc write*(f: TFile, c: char) - proc write*(f: TFile, c: cstring) - proc write*(f: TFile, a: openArray[string]) - ## Writes a value to the file `f`. May throw an IO exception. - - proc readLine*(f: TFile): string - ## reads a line of text from the file `f`. May throw an IO exception. - ## Reading from an empty file buffer, does not throw an exception, but - ## returns nil. A line of text may be delimited by ``CR``, ``LF`` or - ## ``CRLF``. The newline character(s) are not part of the returned string. - - proc writeln*[Ty](f: TFile, x: Ty) {.inline.} - ## writes a value `x` to `f` and then writes "\n". - ## May throw an IO exception. - - proc writeln*[Ty](f: TFile, x: openArray[Ty]) {.inline.} - ## writes a value `x` to `f` and then writes "\n". - ## May throw an IO exception. - - proc getFileSize*(f: TFile): int64 - ## retrieves the file size (in bytes) of `f`. - - proc ReadBytes*(f: TFile, a: var openarray[byte], start, len: int): int - ## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns - ## the actual number of bytes that have been read which may be less than - ## `len` (if not as many bytes are remaining), but not greater. - - proc ReadChars*(f: TFile, a: var openarray[char], start, len: int): int - ## reads `len` bytes into the buffer `a` starting at ``a[start]``. Returns - ## the actual number of bytes that have been read which may be less than - ## `len` (if not as many bytes are remaining), but not greater. - - proc readBuffer*(f: TFile, buffer: pointer, len: int): int - ## reads `len` bytes into the buffer pointed to by `buffer`. Returns - ## the actual number of bytes that have been read which may be less than - ## `len` (if not as many bytes are remaining), but not greater. - - proc writeBytes*(f: TFile, a: openarray[byte], start, len: int): int - ## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns - ## the number of actual written bytes, which may be less than `len` in case - ## of an error. - - proc writeChars*(f: tFile, a: openarray[char], start, len: int): int - ## writes the bytes of ``a[start..start+len-1]`` to the file `f`. Returns - ## the number of actual written bytes, which may be less than `len` in case - ## of an error. - - proc writeBuffer*(f: TFile, buffer: pointer, len: int): int - ## writes the bytes of buffer pointed to by the parameter `buffer` to the - ## file `f`. Returns the number of actual written bytes, which may be less - ## than `len` in case of an error. - - proc setFilePos*(f: TFile, pos: int64) - ## sets the position of the file pointer that is used for read/write - ## operations. The file's first byte has the index zero. - - proc getFilePos*(f: TFile): int64 - ## retrieves the current position of the file pointer that is used to - ## read from the file `f`. The file's first byte has the index zero. - - include "system/sysio" - - iterator lines*(filename: string): string = - ## Iterate over any line in the file named `filename`. - ## If the file does not exist `EIO` is raised. - var - f: TFile - if not open(f, filename): - raise newException(EIO, "cannot open: " & filename) - var res = "" - while not endOfFile(f): - rawReadLine(f, res) - yield res - Close(f) - - proc fileHandle*(f: TFile): TFileHandle {.importc: "fileno", - header: "<stdio.h>"} - ## returns the OS file handle of the file ``f``. This is only useful for - ## platform specific programming. - - proc quit(errormsg: string) = - echo(errormsg) - quit(quitFailure) - - # ---------------------------------------------------------------------------- - - include "system/excpt" - # we cannot compile this with stack tracing on - # as it would recurse endlessly! - include "system/arithm" - {.pop.} # stack trace - include "system/dyncalls" - include "system/sets" - - const - GenericSeqSize = (2 * sizeof(int)) - - proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.} - - proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int = - assert(n.kind == nkCase) - var d: int - var a = cast[TAddress](aa) - case n.typ.size - of 1: d = ze(cast[ptr int8](a +% n.offset)^) - of 2: d = ze(cast[ptr int16](a +% n.offset)^) - of 4: d = int(cast[ptr int32](a +% n.offset)^) - else: assert(false) - return d - - proc selectBranch(aa: Pointer, n: ptr TNimNode): ptr TNimNode = - var discr = getDiscriminant(aa, n) - if discr <% n.len: - result = n.sons[discr] - if result == nil: result = n.sons[n.len] - # n.sons[n.len] contains the ``else`` part (but may be nil) - else: - result = n.sons[n.len] - - include "system/mm" - include "system/sysstr" - include "system/assign" - include "system/repr" - - # we have to implement it here after gentostr for the cstrToNimStrDummy proc - proc getCurrentExceptionMsg(): string = - if excHandler == nil: return "" - return $excHandler.exc.msg - - {.push stack_trace: off.} - when defined(endb): - include "system/debugger" - - when defined(profiler): - include "system/profiler" - {.pop.} # stacktrace - -elif defined(ecmaScript): - include "system/ecmasys" -elif defined(NimrodVM): - # Stubs for the GC interface: - proc GC_disable() = nil - proc GC_enable() = nil - proc GC_fullCollect() = nil - proc GC_setStrategy(strategy: TGC_Strategy) = nil - proc GC_enableMarkAndSweep() = nil - proc GC_disableMarkAndSweep() = nil - proc GC_getStatistics(): string = return "" - - proc getOccupiedMem(): int = return -1 - proc getFreeMem(): int = return -1 - proc getTotalMem(): int = return -1 - - proc cmp(x, y: string): int = - if x == y: return 0 - if x < y: return -1 - return 1 - - proc dealloc(p: pointer) = nil - proc alloc(size: int): pointer = nil - proc alloc0(size: int): pointer = nil - proc realloc(p: Pointer, newsize: int): pointer = nil - -{.pop.} # checks -{.pop.} # hints |