diff options
Diffstat (limited to 'lib/system.nim')
-rw-r--r--[-rwxr-xr-x] | lib/system.nim | 4267 |
1 files changed, 2810 insertions, 1457 deletions
diff --git a/lib/system.nim b/lib/system.nim index a83812ed0..2f9cdc5f9 100755..100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -1,1169 +1,1745 @@ # # -# Nimrod's Runtime Library -# (c) Copyright 2010 Andreas Rumpf +# Nim's Runtime Library +# (c) Copyright 2015 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 +## +## Each module implicitly imports the System module; it must not be listed ## explicitly. Because of this there cannot be a user-defined module named -## ``system``. +## `system`. +## +## System module +## ============= +## +## .. include:: ./system_overview.rst + -{.push hints: off.} +include "system/basic_types" + +func zeroDefault*[T](_: typedesc[T]): T {.magic: "ZeroDefault".} = + ## Returns the binary zeros representation of the type `T`. It ignores + ## default fields of an object. + ## + ## See also: + ## * `default <#default,typedesc[T]>`_ + +include "system/compilation" + +{.push warning[GcMem]: off, warning[Uninit]: off.} +# {.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 + `static`*[T] {.magic: "Static".} + ## Meta type representing all values that can be evaluated at compile-time. + ## + ## The type coercion `static(x)` can be used to force the compile-time + ## evaluation of the given expression `x`. + + `type`*[T] {.magic: "Type".} + ## Meta type representing the type of all type values. + ## + ## The coercion `type(x)` can be used to obtain the type of the given + ## expression `x`. 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] + TypeOfMode* = enum ## Possible modes of `typeof`. + typeOfProc, ## Prefer the interpretation that means `x` is a proc call. + typeOfIter ## Prefer the interpretation that means `x` is an iterator call. + +proc typeof*(x: untyped; mode = typeOfIter): typedesc {. + magic: "TypeOf", noSideEffect, compileTime.} = + ## Builtin `typeof` operation for accessing the type of an expression. + ## Since version 0.20.0. + runnableExamples: + proc myFoo(): float = 0.0 + iterator myFoo(): string = yield "abc" + iterator myFoo2(): string = yield "abc" + iterator myFoo3(): string {.closure.} = yield "abc" + doAssert type(myFoo()) is string + doAssert typeof(myFoo()) is string + doAssert typeof(myFoo(), typeOfIter) is string + doAssert typeof(myFoo3) is iterator + + doAssert typeof(myFoo(), typeOfProc) is float + doAssert typeof(0.0, typeOfProc) is float + doAssert typeof(myFoo3, typeOfProc) is iterator + doAssert not compiles(typeof(myFoo2(), typeOfProc)) + # this would give: Error: attempting to call routine: 'myFoo2' + # since `typeOfProc` expects a typed expression and `myFoo2()` can + # only be used in a `for` context. + +proc `or`*(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.} + ## Constructs an `or` meta class. + +proc `and`*(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.} + ## Constructs an `and` meta class. + +proc `not`*(a: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.} + ## Constructs an `not` meta class. + +when defined(nimHasIterable): + type + iterable*[T] {.magic: IterableType.} ## Represents an expression that yields `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. - -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)) {. + Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer, + ## bool, character, and enumeration types + ## as well as their subtypes. See also + ## `SomeOrdinal`. + + +proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = + ## Builtin `addr` operator for taking the address of a memory location. + ## + ## .. note:: This works for `let` variables or parameters + ## for better interop with C. When you use it to write a wrapper + ## for a C library and take the address of `let` variables or parameters, + ## you should always check that the original library + ## does never write to data behind the pointer that is returned from + ## this procedure. + ## + ## Cannot be overloaded. + ## + ## ```nim + ## var + ## buf: seq[char] = @['a','b','c'] + ## p = buf[1].addr + ## echo p.repr # ref 0x7faa35c40059 --> 'b' + ## echo p[] # b + ## ``` + discard + +proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = + ## .. warning:: `unsafeAddr` is a deprecated alias for `addr`, + ## use `addr` instead. + discard + + +const ThisIsSystem = true + +proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. 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 + ## 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. + ## 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! + +proc `=wasMoved`*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = + ## Generic `wasMoved`:idx: implementation that can be overridden. + +proc wasMoved*[T](obj: var T) {.inline, noSideEffect.} = + ## Resets an object `obj` to its initial (binary zero) value to signify + ## it was "moved" and to signify its destructor should do nothing and + ## ideally be optimized away. + {.cast(raises: []), cast(tags: []).}: + `=wasMoved`(obj) + +proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} = + result = x + {.cast(raises: []), cast(tags: []).}: + `=wasMoved`(x) + +when defined(nimHasEnsureMove): + proc ensureMove*[T](x: T): T {.magic: "EnsureMove", noSideEffect.} = + ## Ensures that `x` is moved to the new location, otherwise it gives + ## an error at the compile time. + runnableExamples: + proc foo = + var x = "Hello" + let y = ensureMove(x) + doAssert y == "Hello" + foo() + discard "implemented in injectdestructors" + +type + range*[T]{.magic: "Range".} ## Generic type to construct range types. + array*[I, T]{.magic: "Array".} ## Generic type to construct + ## fixed-length arrays. + openArray*[T]{.magic: "OpenArray".} ## Generic type to construct open arrays. + ## Open arrays are implemented as a + ## pointer to the array data and a + ## length field. + varargs*[T]{.magic: "Varargs".} ## Generic type to construct a varargs type. + seq*[T]{.magic: "Seq".} ## Generic type to construct sequences. + set*[T]{.magic: "Set".} ## Generic type to construct bit sets. + +type + UncheckedArray*[T]{.magic: "UncheckedArray".} + ## Array with no bounds checking. + +type sink*[T]{.magic: "BuiltinType".} +type lent*[T]{.magic: "BuiltinType".} -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 +proc high*[T: Ordinal|enum|range](x: T): T {.magic: "High", noSideEffect, + deprecated: "Deprecated since v1.4; there should not be `high(value)`. Use `high(type)`.".} + ## Returns the highest possible value of an ordinal value `x`. + ## + ## As a special semantic rule, `x` may also be a type identifier. + ## + ## **This proc is deprecated**, use this one instead: + ## * `high(typedesc) <#high,typedesc[T]>`_ + ## + ## ```nim + ## high(2) # => 9223372036854775807 + ## ``` + +proc high*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "High", noSideEffect.} + ## Returns the highest possible value of an ordinal or enum type. + ## + ## `high(int)` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:. + ## ```nim + ## high(int) # => 9223372036854775807 + ## ``` + ## + ## See also: + ## * `low(typedesc) <#low,typedesc[T]>`_ + +proc high*[T](x: openArray[T]): int {.magic: "High", noSideEffect.} + ## Returns the highest possible index of a sequence `x`. + ## ```nim + ## var s = @[1, 2, 3, 4, 5, 6, 7] + ## high(s) # => 6 + ## for i in low(s)..high(s): + ## echo s[i] + ## ``` + ## + ## See also: + ## * `low(openArray) <#low,openArray[T]>`_ + +proc high*[I, T](x: array[I, T]): I {.magic: "High", noSideEffect.} + ## Returns the highest possible index of an array `x`. + ## + ## For empty arrays, the return type is `int`. + ## ```nim + ## var arr = [1, 2, 3, 4, 5, 6, 7] + ## high(arr) # => 6 + ## for i in low(arr)..high(arr): + ## echo arr[i] + ## ``` + ## + ## See also: + ## * `low(array) <#low,array[I,T]>`_ + +proc high*[I, T](x: typedesc[array[I, T]]): I {.magic: "High", noSideEffect.} + ## Returns the highest possible index of an array type. + ## + ## For empty arrays, the return type is `int`. + ## ```nim + ## high(array[7, int]) # => 6 + ## ``` + ## + ## See also: + ## * `low(typedesc[array]) <#low,typedesc[array[I,T]]>`_ + +proc high*(x: cstring): int {.magic: "High", noSideEffect.} + ## Returns the highest possible index of a compatible string `x`. + ## This is sometimes an O(n) operation. + ## + ## See also: + ## * `low(cstring) <#low,cstring>`_ + +proc high*(x: string): int {.magic: "High", noSideEffect.} + ## Returns the highest possible index of a string `x`. + ## ```nim + ## var str = "Hello world!" + ## high(str) # => 11 + ## ``` + ## + ## See also: + ## * `low(string) <#low,string>`_ + +proc low*[T: Ordinal|enum|range](x: T): T {.magic: "Low", noSideEffect, + deprecated: "Deprecated since v1.4; there should not be `low(value)`. Use `low(type)`.".} + ## Returns the lowest possible value of an ordinal value `x`. As a special ## semantic rule, `x` may also be a type identifier. + ## + ## **This proc is deprecated**, use this one instead: + ## * `low(typedesc) <#low,typedesc[T]>`_ + ## + ## ```nim + ## low(2) # => -9223372036854775808 + ## ``` + +proc low*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "Low", noSideEffect.} + ## Returns the lowest possible value of an ordinal or enum type. + ## + ## `low(int)` is Nim's way of writing `INT_MIN`:idx: or `MIN_INT`:idx:. + ## ```nim + ## low(int) # => -9223372036854775808 + ## ``` + ## + ## See also: + ## * `high(typedesc) <#high,typedesc[T]>`_ + +proc low*[T](x: openArray[T]): int {.magic: "Low", noSideEffect.} + ## Returns the lowest possible index of a sequence `x`. + ## ```nim + ## var s = @[1, 2, 3, 4, 5, 6, 7] + ## low(s) # => 0 + ## for i in low(s)..high(s): + ## echo s[i] + ## ``` + ## + ## See also: + ## * `high(openArray) <#high,openArray[T]>`_ + +proc low*[I, T](x: array[I, T]): I {.magic: "Low", noSideEffect.} + ## Returns the lowest possible index of an array `x`. + ## + ## For empty arrays, the return type is `int`. + ## ```nim + ## var arr = [1, 2, 3, 4, 5, 6, 7] + ## low(arr) # => 0 + ## for i in low(arr)..high(arr): + ## echo arr[i] + ## ``` + ## + ## See also: + ## * `high(array) <#high,array[I,T]>`_ + +proc low*[I, T](x: typedesc[array[I, T]]): I {.magic: "Low", noSideEffect.} + ## Returns the lowest possible index of an array type. + ## + ## For empty arrays, the return type is `int`. + ## ```nim + ## low(array[7, int]) # => 0 + ## ``` + ## + ## See also: + ## * `high(typedesc[array]) <#high,typedesc[array[I,T]]>`_ + +proc low*(x: cstring): int {.magic: "Low", noSideEffect.} + ## Returns the lowest possible index of a compatible string `x`. + ## + ## See also: + ## * `high(cstring) <#high,cstring>`_ + +proc low*(x: string): int {.magic: "Low", noSideEffect.} + ## Returns the lowest possible index of a string `x`. + ## ```nim + ## var str = "Hello world!" + ## low(str) # => 0 + ## ``` + ## + ## See also: + ## * `high(string) <#high,string>`_ + +when not defined(gcArc) and not defined(gcOrc) and not defined(gcAtomicArc): + proc shallowCopy*[T](x: var T, y: T) {.noSideEffect, magic: "ShallowCopy".} + ## Use this instead of `=` for a `shallow copy`:idx:. + ## + ## The shallow copy only changes the semantics for sequences and strings + ## (and types which contain those). + ## + ## Be careful with the changed semantics though! + ## There is a reason why the default assignment does a deep copy of sequences + ## and strings. + +# :array|openArray|string|seq|cstring|tuple +proc `[]`*[I: Ordinal;T](a: T; i: I): T {. + noSideEffect, magic: "ArrGet".} +proc `[]=`*[I: Ordinal;T,S](a: T; i: I; + x: sink S) {.noSideEffect, magic: "ArrPut".} +proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".} +proc `=copy`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".} + +proc arrGet[I: Ordinal;T](a: T; i: I): T {. + noSideEffect, magic: "ArrGet".} +proc arrPut[I: Ordinal;T,S](a: T; i: I; + x: S) {.noSideEffect, magic: "ArrPut".} + +const arcLikeMem = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc) + + +when defined(nimAllowNonVarDestructor) and arcLikeMem and defined(nimPreviewNonVarDestructor): + proc `=destroy`*[T](x: T) {.inline, magic: "Destroy".} = + ## Generic `destructor`:idx: implementation that can be overridden. + discard +else: + proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = + ## Generic `destructor`:idx: implementation that can be overridden. + discard + + when defined(nimAllowNonVarDestructor) and arcLikeMem: + proc `=destroy`*(x: string) {.inline, magic: "Destroy", enforceNoRaises.} = + discard + + proc `=destroy`*[T](x: seq[T]) {.inline, magic: "Destroy".} = + discard + + proc `=destroy`*[T](x: ref T) {.inline, magic: "Destroy".} = + discard + +when defined(nimHasDup): + proc `=dup`*[T](x: T): T {.inline, magic: "Dup".} = + ## Generic `dup`:idx: implementation that can be overridden. + discard + +proc `=sink`*[T](x: var T; y: T) {.inline, nodestroy, magic: "Asgn".} = + ## Generic `sink`:idx: implementation that can be overridden. + when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc): + x = y + else: + shallowCopy(x, y) + +when defined(nimHasTrace): + proc `=trace`*[T](x: var T; env: pointer) {.inline, magic: "Trace".} = + ## Generic `trace`:idx: implementation that can be overridden. + discard 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): + HSlice*[T, U] = object ## "Heterogeneous" slice type. + a*: T ## The lower bound (inclusive). + b*: U ## The upper bound (inclusive). + Slice*[T] = HSlice[T, T] ## An alias for `HSlice[T, T]`. + +proc `..`*[T, U](a: sink T, b: sink U): HSlice[T, U] {.noSideEffect, inline, magic: "DotDot".} = + ## Binary `slice`:idx: operator that constructs an interval `[a, b]`, both `a` + ## and `b` are inclusive. + ## + ## Slices can also be used in the set constructor and in ordinal case + ## statements, but then they are special-cased by the compiler. + ## ```nim + ## let a = [10, 20, 30, 40, 50] + ## echo a[2 .. 3] # @[30, 40] + ## ``` + result = HSlice[T, U](a: a, b: b) + +proc `..`*[T](b: sink T): HSlice[int, T] + {.noSideEffect, inline, magic: "DotDot", deprecated: "replace `..b` with `0..b`".} = + ## Unary `slice`:idx: operator that constructs an interval `[default(int), b]`. + ## ```nim + ## let a = [10, 20, 30, 40, 50] + ## echo a[.. 2] # @[10, 20, 30] + ## ``` + result = HSlice[int, T](a: 0, b: b) + +when defined(hotCodeReloading): + {.pragma: hcrInline, inline.} +else: + {.pragma: hcrInline.} + +include "system/arithmetics" +include "system/comparisons" + +const + appType* {.magic: "AppType".}: string = "" + ## A string that describes the application type. Possible values: + ## `"console"`, `"gui"`, `"lib"`. + +include "system/inclrtl" + +const NoFakeVars = defined(nimscript) ## `true` if the backend doesn't support \ + ## "fake variables" like `var EBADF {.importc.}: cint`. + +const notJSnotNims = not defined(js) and not defined(nimscript) + +when not defined(js) and not defined(nimSeqsV2): type - TGenericSeq {.compilerproc, pure.} = object - len, space: int + TGenericSeq {.compilerproc, pure, inheritable.} = object + len, reserved: int + when defined(gogc): + elemSize: int + elemAlign: 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] + data: UncheckedArray[char] NimString = ptr NimStringDesc +when notJSnotNims: include "system/hti" type - Byte* = Int8 ## this is an alias for ``int8``, that is a signed - ## int 8 bits wide. + byte* = uint8 ## This is an alias for `uint8`, that is an unsigned + ## integer, 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. + ## 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".}: string ## the exception's message. Not - ## providing an exception message + ## is an `int` type ranging from one to the maximum value + ## of an `int`. This type is often useful for documentation and debugging. + +type + RootObj* {.compilerproc, inheritable.} = + object ## The root of Nim's object hierarchy. + ## + ## Objects should inherit from `RootObj` or one of its descendants. + ## However, objects that have no ancestor are also allowed. + RootRef* = ref RootObj ## Reference to `RootObj`. + +const NimStackTraceMsgs = compileOption("stacktraceMsgs") + +type + RootEffect* {.compilerproc.} = object of RootObj ## \ + ## Base effect class. + ## + ## Each effect should inherit from `RootEffect` unless you know what + ## you're doing. + +type + 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. + when NimStackTraceMsgs: + frameMsg*: string ## When a stacktrace is generated in a given frame and + ## rendered at a later time, we should ensure the stacktrace + ## data isn't invalidated; any pointer into PFrame is + ## subject to being invalidated so shouldn't be stored. + when defined(nimStackTraceOverride): + programCounter*: uint ## Program counter - will be used to get the rest of the info, + ## when `$` is called on this type. We can't use + ## "cuintptr_t" in here. + procnameStr*, filenameStr*: string ## GC-ed alternatives to "procname" and "filename" + + 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] + 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. + +when defined(nimIcIntegrityChecks): + include "system/exceptions" +else: + import system/exceptions + export exceptions + +when defined(js) or defined(nimdoc): + type + JsRoot* = ref object of RootObj + ## Root type of the JavaScript object hierarchy + +proc unsafeNew*[T](a: var ref T, size: Natural) {.magic: "New", noSideEffect.} + ## Creates a new object of type `T` and returns a safe (traced) + ## reference to it in `a`. + ## + ## This is **unsafe** as it allocates an object of the passed `size`. + ## This should only be used for optimization purposes when you know + ## what you're doing! + ## + ## See also: + ## * `new <#new,ref.T,proc(ref.T)>`_ + +proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.} + ## Returns the size of `x` in bytes. + ## + ## Since this is a low-level proc, + ## its usage is discouraged - using `new <#new,ref.T,proc(ref.T)>`_ 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). + ## + ## Limitations: If used for types that are imported from C or C++, + ## sizeof should fallback to the `sizeof` in the C compiler. The + ## result isn't available for the Nim compiler and therefore can't + ## be used inside of macros. + ## ```nim + ## sizeof('A') # => 1 + ## sizeof(2) # => 8 + ## ``` + +proc alignof*[T](x: T): int {.magic: "AlignOf", noSideEffect.} +proc alignof*(x: typedesc): int {.magic: "AlignOf", noSideEffect.} + +proc offsetOfDotExpr(typeAccess: typed): int {.magic: "OffsetOf", noSideEffect, compileTime.} + +template offsetOf*[T](t: typedesc[T]; member: untyped): int = + var tmp {.noinit.}: ptr T + offsetOfDotExpr(tmp[].member) + +template offsetOf*[T](value: T; member: untyped): int = + offsetOfDotExpr(value.member) + +#proc offsetOf*(memberaccess: typed): int {.magic: "OffsetOf", noSideEffect.} - 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. - - EFloatingPoint* = object of ESynch ## base class for floating point exceptions - EFloatInvalidOp* {.compilerproc.} = - object of EFloatingPoint ## Invalid operation according to IEEE: Raised by - ## 0.0/0.0, for example. - EFloatDivByZero* {.compilerproc.} = - object of EFloatingPoint ## Division by zero. Divisor is zero and dividend - ## is a finite nonzero number. - EFloatOverflow* {.compilerproc.} = - object of EFloatingPoint ## Overflow. Operation produces a result - ## that exceeds the range of the exponent - EFloatUnderflow* {.compilerproc.} = - object of EFloatingPoint ## Underflow. Operation produces a result - ## that is too small to be represented as - ## a normal number - EFloatInexact* {.compilerproc.} = - object of EFloatingPoint ## Inexact. Operation produces a result - ## that cannot be represented with infinite - ## precision -- for example, 2.0 / 3.0, log(1.1) - ## NOTE: Nimrod currently does not detect these! - - 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 +proc sizeof*(x: typedesc): int {.magic: "SizeOf", noSideEffect.} + + +proc newSeq*[T](s: var seq[T], len: Natural) {.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. + ## + ## Note that the sequence will be filled with zeroed entries. + ## After the creation of the sequence you should assign entries to + ## the sequence instead of adding them. Example: + ## ```nim + ## var inputStrings: seq[string] + ## newSeq(inputStrings, 3) + ## assert len(inputStrings) == 3 + ## inputStrings[0] = "The fourth" + ## inputStrings[1] = "assignment" + ## inputStrings[2] = "would crash" + ## #inputStrings[3] = "out of bounds" + ## ``` + +proc newSeq*[T](len = 0.Natural): seq[T] = + ## Creates a new sequence of type `seq[T]` with length `len`. + ## + ## Note that the sequence will be filled with zeroed entries. + ## After the creation of the sequence you should assign entries to + ## the sequence instead of adding them. + ## ```nim + ## var inputStrings = newSeq[string](3) + ## assert len(inputStrings) == 3 + ## inputStrings[0] = "The fourth" + ## inputStrings[1] = "assignment" + ## inputStrings[2] = "would crash" + ## #inputStrings[3] = "out of bounds" + ## ``` + ## + ## See also: + ## * `newSeqOfCap <#newSeqOfCap,Natural>`_ + ## * `newSeqUninit <#newSeqUninit,Natural>`_ + newSeq(result, len) + +proc newSeqOfCap*[T](cap: Natural): seq[T] {. + magic: "NewSeqOfCap", noSideEffect.} = + ## Creates a new sequence of type `seq[T]` with length zero and capacity + ## `cap`. Example: + ## ```nim + ## var x = newSeqOfCap[int](5) + ## assert len(x) == 0 + ## x.add(10) + ## assert len(x) == 1 + ## ``` + discard + +func len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.magic: "LengthOpenArray".} = + ## Returns the length of an openArray. + runnableExamples: + proc bar[T](a: openArray[T]): int = len(a) + assert bar([1,2]) == 2 + assert [1,2].len == 2 + +func len*(x: string): int {.magic: "LengthStr".} = + ## Returns the length of a string. + runnableExamples: + assert "abc".len == 3 + assert "".len == 0 + assert string.default.len == 0 + +proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.} = + ## Returns the length of a compatible string. This is an O(n) operation except + ## in js at runtime. + ## + ## **Note:** On the JS backend this currently counts UTF-16 code points + ## instead of bytes at runtime (not at compile time). For now, if you + ## need the byte length of the UTF-8 encoding, convert to string with + ## `$` first then call `len`. + runnableExamples: + doAssert len(cstring"abc") == 3 + doAssert len(cstring r"ab\0c") == 5 # \0 is escaped + doAssert len(cstring"ab\0c") == 5 # ditto + var a: cstring = "ab\0c" + when defined(js): doAssert a.len == 4 # len ignores \0 for js + else: doAssert a.len == 2 # \0 is a null terminator + static: + var a2: cstring = "ab\0c" + doAssert a2.len == 2 # \0 is a null terminator, even in js vm + +func len*(x: (type array)|array): int {.magic: "LengthArray".} = + ## Returns the length of an array or an array type. + ## This is roughly the same as `high(T)-low(T)+1`. + runnableExamples: + var a = [1, 1, 1] + assert a.len == 3 + assert array[0, float].len == 0 + static: assert array[-2..2, float].len == 5 + +func len*[T](x: seq[T]): int {.magic: "LengthSeq".} = + ## Returns the length of `x`. + runnableExamples: + assert @[0, 1].len == 2 + assert seq[int].default.len == 0 + assert newSeq[int](3).len == 3 + let s = newSeqOfCap[int](3) + assert s.len == 0 + # xxx this gives cgen error: assert newSeqOfCap[int](3).len == 0 + +func ord*[T: Ordinal|enum](x: T): int {.magic: "Ord".} = + ## Returns the internal `int` value of `x`, including for enum with holes + ## and distinct ordinal types. + runnableExamples: + assert ord('A') == 65 + type Foo = enum + f0 = 0, f1 = 3 + assert f1.ord == 3 + type Bar = distinct int + assert 3.Bar.ord == 3 + +func chr*(u: range[0..255]): char {.magic: "Chr".} = + ## Converts `u` to a `char`, same as `char(u)`. + runnableExamples: + doAssert chr(65) == 'A' + doAssert chr(255) == '\255' + doAssert chr(255) == char(255) + doAssert not compiles chr(256) + doAssert not compiles char(256) + var x = 256 + doAssertRaises(RangeDefect): discard chr(x) + doAssertRaises(RangeDefect): discard char(x) + + +include "system/setops" + + +proc contains*[U, V, W](s: HSlice[U, V], value: W): bool {.noSideEffect, inline.} = + ## Checks if `value` is within the range of `s`; returns true if + ## `value >= s.a and value <= s.b`. + ## ```nim + ## assert((1..3).contains(1) == true) + ## assert((1..3).contains(2) == true) + ## assert((1..3).contains(4) == false) + ## ``` + result = s.a <= value and value <= s.b + +when not defined(nimHasCallsitePragma): + {.pragma: callsite.} + +template `in`*(x, y: untyped): untyped {.dirty, callsite.} = contains(y, x) + ## Sugar for `contains`. + ## ```nim + ## assert(1 in (1..3) == true) + ## assert(5 in (1..3) == false) + ## ``` +template `notin`*(x, y: untyped): untyped {.dirty, callsite.} = not contains(y, x) + ## Sugar for `not contains`. + ## ```nim + ## assert(1 notin (1..3) == false) + ## assert(5 notin (1..3) == true) + ## ``` + +proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} + ## Checks if `T` is of the same type as `S`. + ## + ## For a negated version, use `isnot <#isnot.t,untyped,untyped>`_. + ## + ## ```nim + ## assert 42 is int + ## assert @[1, 2] is seq + ## + ## proc test[T](a: T): int = + ## when (T is int): + ## return a + ## else: + ## return 0 + ## + ## assert(test[int](3) == 3) + ## assert(test[string]("xyz") == 0) + ## ``` +template `isnot`*(x, y: untyped): untyped {.callsite.} = not (x is y) + ## Negated version of `is <#is,T,S>`_. Equivalent to `not(x is y)`. + ## ```nim + ## assert 42 isnot float + ## assert @[1, 2] isnot enum + ## ``` + +when (defined(nimOwnedEnabled) and not defined(nimscript)) or defined(nimFixedOwned): + type owned*[T]{.magic: "BuiltinType".} ## type constructor to mark a ref/ptr or a closure as `owned`. +else: + template owned*(t: typedesc): typedesc = t + +when defined(nimOwnedEnabled) and not defined(nimscript): + proc new*[T](a: var owned(ref T)) {.magic: "New", noSideEffect.} + ## Creates a new object of type `T` and returns a safe (traced) + ## reference to it in `a`. -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. + proc new*(t: typedesc): auto = + ## Creates a new object of type `T` and returns a safe (traced) + ## reference to it as result value. + ## + ## When `T` is a ref type then the resulting type will be `T`, + ## otherwise it will be `ref T`. + when (t is ref): + var r: owned t + else: + var r: owned(ref t) + new(r) + return r + + proc unown*[T](x: T): T {.magic: "Unown", noSideEffect.} + ## Use the expression `x` ignoring its ownership attribute. + + +else: + template unown*(x: typed): untyped = x + + 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: typedesc): auto = + ## Creates a new object of type `T` and returns a safe (traced) + ## reference to it as result value. + ## + ## When `T` is a ref type then the resulting type will be `T`, + ## otherwise it will be `ref T`. + when (t is ref): + var r: t + else: + var r: ref t + new(r) + return r + + +template disarm*(x: typed) = + ## Useful for `disarming` dangling pointers explicitly for `--newruntime`. + ## Regardless of whether `--newruntime` is used or not + ## this sets the pointer or callback `x` to `nil`. This is an + ## experimental API! + x = nil + +proc `of`*[T, S](x: T, y: typedesc[S]): bool {.magic: "Of", noSideEffect.} = + ## Checks if `x` is an instance of `y`. + runnableExamples: + type + Base = ref object of RootObj + Sub1 = ref object of Base + Sub2 = ref object of Base + Unrelated = ref object + + var base: Base = Sub1() # downcast + doAssert base of Base # generates `CondTrue` (statically true) + doAssert base of Sub1 + doAssert base isnot Sub1 + doAssert not (base of Sub2) + + base = Sub2() # re-assign + doAssert base of Sub2 + doAssert Sub2(base) != nil # upcast + doAssertRaises(ObjectConversionDefect): discard Sub1(base) + + var sub1 = Sub1() + doAssert sub1 of Base + doAssert sub1.Base of Sub1 + + doAssert not compiles(base of Unrelated) + +proc cmp*[T](x, y: T): int = + ## Generic compare proc. + ## + ## Returns: + ## * a value less than zero, if `x < y` + ## * a value greater than zero, if `x > y` + ## * zero, if `x == y` + ## + ## This is useful for writing generic algorithms without performance loss. + ## This generic implementation uses the `==` and `<` operators. + ## ```nim + ## import std/algorithm + ## echo sorted(@[4, 2, 6, 5, 8, 7], cmp[int]) + ## ``` 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. + ## + ## **Note**: The precise result values depend on the used C runtime library and + ## can differ between operating systems! + +proc `@`* [IDX, T](a: sink 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]`. + ## + ## ```nim + ## let + ## a = [1, 3, 5] + ## b = "foo" + ## + ## echo @a # => @[1, 3, 5] + ## echo @b # => @['f', 'o', 'o'] + ## ``` -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 default*[T](_: typedesc[T]): T {.magic: "Default", noSideEffect.} = + ## Returns the default value of the type `T`. Contrary to `zeroDefault`, it takes default fields + ## of an object into consideration. + ## + ## See also: + ## * `zeroDefault <#zeroDefault,typedesc[T]>`_ + ## + runnableExamples("-d:nimPreviewRangeDefault"): + assert (int, float).default == (0, 0.0) + type Foo = object + a: range[2..6] + var x = Foo.default + assert x.a == 2 + + +proc reset*[T](obj: var T) {.noSideEffect.} = + ## Resets an object `obj` to its default value. + when nimvm: + obj = default(typeof(obj)) + else: + when defined(gcDestructors): + {.cast(noSideEffect), cast(raises: []), cast(tags: []).}: + `=destroy`(obj) + `=wasMoved`(obj) + else: + obj = default(typeof(obj)) -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. +proc setLen*[T](s: var seq[T], newlen: Natural) {. + magic: "SetLengthSeq", noSideEffect, nodestroy.} + ## Sets the length of seq `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) {. + ## `s` will be truncated. + ## ```nim + ## var x = @[10, 20] + ## x.setLen(5) + ## x[4] = 50 + ## assert x == @[10, 20, 0, 0, 50] + ## x.setLen(1) + ## assert x == @[10] + ## ``` + +proc setLen*(s: var string, newlen: Natural) {. magic: "SetLengthStr", noSideEffect.} - ## sets the length of `s` to `newlen`. + ## Sets the length of string `s` to `newlen`. + ## ## If the current length is greater than the new length, - ## ``s`` will be truncated. - -proc newString*(len: int): string {. + ## `s` will be truncated. + ## ```nim + ## var myS = "Nim is great!!" + ## myS.setLen(3) # myS <- "Nim" + ## echo myS, " is fantastic!!" + ## ``` + +proc newString*(len: Natural): 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.} + ## Returns a new string of length `len`. + ## 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 or with `add`. -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 del* [T](x: var seq[T], i: int) {.noSideEffect.} = - ## deletes the item at index `i` by putting ``x[high(x)]`` into position `i`. - ## This is an O(1) operation. - var xl = x.len - x[i] = x[xl-1] - setLen(x, xl-1) - -proc delete*[T](x: var seq[T], i: int) {.noSideEffect.} = - ## deletes the item at index `i` by moving ``x[i+1..]`` by one position. - ## This is an O(n) operation. - var xl = x.len - for j in i..xl-2: x[j] = x[j+1] - setLen(x, xl-1) - -proc insert*[T](x: var seq[T], item: T, i = 0) {.noSideEffect.} = - ## inserts `item` into `x` at position `i`. - var xl = x.len - setLen(x, xl+1) - var j = xl-1 - while j >= i: - x[j+1] = x[j] - dec(j) - x[i] = item - - -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. +proc newStringOfCap*(cap: Natural): string {. + magic: "NewStringOfCap", importc: "rawNewString", noSideEffect.} + ## Returns a new string of length `0` but with capacity `cap`. + ## + ## This procedure exists only for optimization purposes; the same effect can + ## be achieved with the `&` operator or with `add`. + +proc `&`*(x: string, y: char): string {. + magic: "ConStrStr", noSideEffect.} + ## Concatenates `x` with `y`. + ## ```nim + ## assert("ab" & 'c' == "abc") + ## ``` +proc `&`*(x, y: char): string {. + magic: "ConStrStr", noSideEffect.} + ## Concatenates characters `x` and `y` into a string. + ## ```nim + ## assert('a' & 'b' == "ab") + ## ``` +proc `&`*(x, y: string): string {. + magic: "ConStrStr", noSideEffect.} + ## Concatenates strings `x` and `y`. + ## ```nim + ## assert("ab" & "cd" == "abcd") + ## ``` +proc `&`*(x: char, y: string): string {. + magic: "ConStrStr", noSideEffect.} + ## Concatenates `x` with `y`. + ## ```nim + ## assert('a' & "bc" == "abc") + ## ``` + +# implementation note: These must all have the same magic value "ConStrStr" so +# that the merge optimization works properly. -type - TAddress* = int - ## is the signed integer type that should be used for converting - ## pointers to integer addresses for readability. +proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.} + ## Appends `y` to `x` in place. + ## ```nim + ## var tmp = "" + ## tmp.add('a') + ## tmp.add('b') + ## assert(tmp == "ab") + ## ``` + +proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} = + ## Concatenates `x` and `y` in place. + ## + ## See also `strbasics.add`. + runnableExamples: + var tmp = "" + tmp.add("ab") + tmp.add("cd") + assert tmp == "abcd" 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. - ## Use cstringArrayToSeq to convert it into a ``seq[string]``. - - TEndian* = enum ## is a type describing the endianness of a processor. + Endianness* = enum ## 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 + cpuEndian* {.magic: "CpuEndian".}: Endianness = littleEndian + ## 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"`, `"haiku"`, `"standalone"`. + + hostCPU* {.magic: "HostCPU".}: string = "" + ## A string that describes the host CPU. + ## + ## Possible values: + ## `"i386"`, `"alpha"`, `"powerpc"`, `"powerpc64"`, `"powerpc64el"`, + ## `"sparc"`, `"amd64"`, `"mips"`, `"mipsel"`, `"arm"`, `"arm64"`, + ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, `"loongarch64"`. + + seqShallowFlag = low(int) + strlitFlag = 1 shl (sizeof(int)*8 - 2) # later versions of the codegen \ + # emit this flag + # for string literals, it allows for some optimizations. 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. + hasThreadSupport = compileOption("threads") and not defined(nimscript) + hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own -proc `/`*(x, y: int): float {.inline, noSideEffect.} = - ## integer division that results in a float. - result = toFloat(x) / toFloat(y) +when notJSnotNims and not defined(nimSeqsV2): + template space(s: PGenericSeq): int = + s.reserved and not (seqShallowFlag or strlitFlag) -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. +when hasThreadSupport and defined(tcc) and not compileOption("tlsEmulation"): + # tcc doesn't support TLS + {.error: "`--tlsEmulation:on` must be used when using threads with tcc backend".} -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. +when defined(boehmgc): + when defined(windows): + when sizeof(int) == 8: + const boehmLib = "boehmgc64.dll" + else: + const boehmLib = "boehmgc.dll" + elif defined(macosx): + const boehmLib = "libgc.dylib" + elif defined(openbsd): + const boehmLib = "libgc.so.(4|5).0" + elif defined(freebsd): + const boehmLib = "libgc-threaded.so.1" + else: + const boehmLib = "libgc.so.1" + {.pragma: boehmGC, noconv, dynlib: boehmLib.} -template `>=%` *(x, y: expr): expr = y <=% x - ## treats `x` and `y` as unsigned and compares them. - ## Returns true iff ``unsigned(x) >= unsigned(y)``. +when not defined(nimPreviewSlimSystem): + type TaintedString* {.deprecated: "Deprecated since 1.5".} = string -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. +when defined(profiler) and not defined(nimscript): + proc nimProfile() {.compilerproc, noinline.} +when hasThreadSupport: + {.pragma: rtlThreadVar, threadvar.} +else: + {.pragma: rtlThreadVar.} -proc `$` *(x: int64): string {.magic: "Int64ToStr", noSideEffect.} - ## The stingify operator for an integer argument. Returns `x` - ## converted to a decimal string. +const + QuitSuccess* = 0 + ## is the value that should be passed to `quit <#quit,int>`_ to indicate + ## success. -proc `$` *(x: float): string {.magic: "FloatToStr", noSideEffect.} - ## The stingify operator for a float argument. Returns `x` - ## converted to a decimal string. + QuitFailure* = 1 + ## is the value that should be passed to `quit <#quit,int>`_ to indicate + ## failure. -proc `$` *(x: bool): string {.magic: "BoolToStr", noSideEffect.} - ## The stingify operator for a boolean argument. Returns `x` - ## converted to the string "false" or "true". +when not defined(js) and hostOS != "standalone": + var programResult* {.compilerproc, exportc: "nim_program_result".}: int + ## deprecated, prefer `quit` or `exitprocs.getProgramResult`, `exitprocs.setProgramResult`. -proc `$` *(x: char): string {.magic: "CharToStr", noSideEffect.} - ## The stingify operator for a character argument. Returns `x` - ## converted to a string. +import std/private/since +import system/ctypes +export ctypes -proc `$` *(x: Cstring): string {.magic: "CStrToStr", noSideEffect.} - ## The stingify operator for a CString argument. Returns `x` - ## converted to a string. +proc align(address, alignment: int): int = + if alignment == 0: # Actually, this is illegal. This branch exists to actively + # hide problems. + result = address + else: + result = (address + (alignment - 1)) and not (alignment - 1) -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`` already is a string. +include system/rawquits +when defined(genode): + export GenodeEnv -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.) +template sysAssert(cond: bool, msg: string) = + when defined(useSysAssert): + if not cond: + cstderr.rawWrite "[SYSASSERT] " + cstderr.rawWrite msg + cstderr.rawWrite "\n" + rawQuit 1 -# 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. +const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) -#proc writeStackTrace() {.export: "writeStackTrace".} +when notJSnotNims and hasAlloc and not defined(nimSeqsV2): + proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.} -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. +when defined(nimscript) or not defined(nimSeqsV2): + proc add*[T](x: var seq[T], y: sink T) {.magic: "AppendSeqElem", 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 Nim naming scheme is + ## respected. + ## ```nim + ## var s: seq[string] = @["test2","test2"] + ## s.add("test") + ## assert s == @["test2", "test2", "test"] + ## ``` + +when false: # defined(gcDestructors): + proc add*[T](x: var seq[T], y: sink openArray[T]) {.noSideEffect.} = + ## Generic proc for adding a container `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 Nim naming scheme is + ## respected. + ## ```nim + ## var s: seq[string] = @["test2","test2"] + ## s.add("test") # s <- @[test2, test2, test] + ## ``` + ## + ## See also: + ## * `& proc <#&,seq[T],seq[T]>`_ + {.noSideEffect.}: + let xl = x.len + setLen(x, xl + y.len) + for i in 0..high(y): + when nimvm: + # workaround the fact that the VM does not yet + # handle sink parameters properly: + x[xl+i] = y[i] + else: + x[xl+i] = move y[i] +else: + proc add*[T](x: var seq[T], y: openArray[T]) {.noSideEffect.} = + ## Generic proc for adding a container `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 Nim naming scheme is + ## respected. + ## + ## See also: + ## * `& proc <#&,seq[T],seq[T]>`_ + runnableExamples: + var a = @["a1", "a2"] + a.add(["b1", "b2"]) + assert a == @["a1", "a2", "b1", "b2"] + var c = @["c0", "c1", "c2", "c3"] + a.add(c.toOpenArray(1, 2)) + assert a == @["a1", "a2", "b1", "b2", "c1", "c2"] + + {.noSideEffect.}: + let xl = x.len + setLen(x, xl + y.len) + for i in 0..high(y): x[xl+i] = y[i] + + +when defined(nimSeqsV2): + template movingCopy(a, b: typed) = + a = move(b) +else: + template movingCopy(a, b: typed) = + shallowCopy(a, b) + +proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} = + ## Deletes the item at index `i` by putting `x[high(x)]` into position `i`. + ## + ## This is an `O(1)` operation. + ## + ## See also: + ## * `delete <#delete,seq[T],Natural>`_ for preserving the order + runnableExamples: + var a = @[10, 11, 12, 13, 14] + a.del(2) + assert a == @[10, 11, 14, 13] + let xl = x.len - 1 + movingCopy(x[i], x[xl]) + setLen(x, xl) + +proc insert*[T](x: var seq[T], item: sink T, i = 0.Natural) {.noSideEffect.} = + ## Inserts `item` into `x` at position `i`. + ## ```nim + ## var i = @[1, 3, 5] + ## i.insert(99, 0) # i <- @[99, 1, 3, 5] + ## ``` + {.noSideEffect.}: + template defaultImpl = + let xl = x.len + setLen(x, xl+1) + var j = xl-1 + while j >= i: + movingCopy(x[j+1], x[j]) + dec(j) + when nimvm: + defaultImpl() + else: + when defined(js): + var it : T + {.emit: "`x` = `x` || []; `x`.splice(`i`, 0, `it`);".} + else: + defaultImpl() + x[i] = item + +when not defined(nimV2): + proc repr*[T](x: T): string {.magic: "Repr", noSideEffect.} + ## Takes any Nim variable and returns its string representation. + ## No trailing newline is inserted (so `echo` won't add an empty newline). + ## Use `-d:nimLegacyReprWithNewline` to revert to old behavior where newlines + ## were added in some cases. + ## + ## It works even for complex data graphs with cycles. This is a great + ## debugging tool. + ## ```nim + ## var s: seq[string] = @["test2", "test2"] + ## var i = @[1, 2, 3, 4, 5] + ## echo repr(s) # => 0x1055eb050[0x1055ec050"test2", 0x1055ec078"test2"] + ## echo repr(i) # => 0x1055ed050[1, 2, 3, 4, 5] + ## ``` + +when not defined(nimPreviewSlimSystem): + type + csize* {.importc: "size_t", nodecl, deprecated: "use `csize_t` instead".} = int + ## This isn't the same as `size_t` in *C*. Don't use it. -# 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) + Inf* = 0x7FF0000000000000'f64 + ## Contains the IEEE floating point value of positive infinity. + NegInf* = 0xFFF0000000000000'f64 + ## Contains the IEEE floating point value of negative infinity. + NaN* = 0x7FF7FFFFFFFFFFFF'f64 + ## 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 `isNaN` or `classify` procedure + ## in the `math module <math.html>`_ for checking for NaN. -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) +proc high*(T: typedesc[SomeFloat]): T = Inf +proc low*(T: typedesc[SomeFloat]): T = NegInf + +proc toFloat*(i: int): float {.noSideEffect, inline.} = + ## Converts an integer `i` into a `float`. Same as `float(i)`. + ## + ## If the conversion fails, `ValueError` is raised. + ## However, on most platforms the conversion cannot fail. + ## + ## ```nim + ## let + ## a = 2 + ## b = 3.7 + ## + ## echo a.toFloat + b # => 5.7 + ## ``` + float(i) + +proc toBiggestFloat*(i: BiggestInt): BiggestFloat {.noSideEffect, inline.} = + ## Same as `toFloat <#toFloat,int>`_ but for `BiggestInt` to `BiggestFloat`. + BiggestFloat(i) + +proc toInt*(f: float): int {.noSideEffect.} = + ## Converts a floating point number `f` into an `int`. + ## + ## Conversion rounds `f` half away from 0, see + ## `Round half away from zero + ## <https://en.wikipedia.org/wiki/Rounding#Round_half_away_from_zero>`_, + ## as opposed to a type conversion which rounds towards zero. + ## + ## Note that some floating point numbers (e.g. infinity or even 1e19) + ## cannot be accurately converted. + ## ```nim + ## doAssert toInt(0.49) == 0 + ## doAssert toInt(0.5) == 1 + ## doAssert toInt(-0.5) == -1 # rounding is symmetrical + ## ``` + if f >= 0: int(f+0.5) else: int(f-0.5) + +proc toBiggestInt*(f: BiggestFloat): BiggestInt {.noSideEffect.} = + ## Same as `toInt <#toInt,float>`_ but for `BiggestFloat` to `BiggestInt`. + if f >= 0: BiggestInt(f+0.5) else: BiggestInt(f-0.5) + +proc `/`*(x, y: int): float {.inline, noSideEffect.} = + ## Division of integers that results in a float. + ## ```nim + ## echo 7 / 5 # => 1.4 + ## ``` + ## + ## See also: + ## * `div <system.html#div,int,int>`_ + ## * `mod <system.html#mod,int,int>`_ + result = toFloat(x) / toFloat(y) + +{.push stackTrace: off.} + +when defined(js): + proc js_abs[T: SomeNumber](x: T): T {.importc: "Math.abs".} +else: + proc c_fabs(x: cdouble): cdouble {.importc: "fabs", header: "<math.h>".} + proc c_fabsf(x: cfloat): cfloat {.importc: "fabsf", header: "<math.h>".} + +proc abs*[T: float64 | float32](x: T): T {.noSideEffect, inline.} = + when nimvm: + if x < 0.0: result = -x + elif x == 0.0: result = 0.0 # handle 0.0, -0.0 + else: result = x # handle NaN, > 0 + else: + when defined(js): result = js_abs(x) + else: + when T is float64: + result = c_fabs(x) + else: + result = c_fabsf(x) + +func abs*(x: int): int {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int8): int8 {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int16): int16 {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int32): int32 {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int64): int64 {.magic: "AbsI", inline.} = + ## 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). + result = if x < 0: -x else: x + +{.pop.} # stackTrace: off + +when not defined(nimPreviewSlimSystem): + proc addQuitProc*(quitProc: proc() {.noconv.}) {. + importc: "atexit", header: "<stdlib.h>", deprecated: "use exitprocs.addExitProc".} + ## 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 exception if `quitProc` cannot be + ## registered. + # Support for addQuitProc() is done by Ansi C's facilities here. + # In case of an unhandled exception the exit handlers should + # not be called explicitly! The user may decide to do this manually though. -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 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. + ## + ## ```nim + ## var + ## a = 5 + ## b = 9 + ## + ## swap(a, b) + ## + ## assert a == 9 + ## assert b == 5 + ## ``` + +when not defined(js) and not defined(booting) and defined(nimTrMacros): + template swapRefsInArray*{swap(arr[a], arr[b])}(arr: openArray[ref], a, b: int) = + # Optimize swapping of array elements if they are refs. Default swap + # implementation will cause unsureAsgnRef to be emitted which causes + # unnecessary slow down in this case. + swap(cast[ptr pointer](addr arr[a])[], cast[ptr pointer](addr arr[b])[]) + +when not defined(nimscript): + {.push stackTrace: off, profiler: off.} + + when not defined(nimPreviewSlimSystem): + import std/sysatomics + export sysatomics + else: + import std/sysatomics + + {.pop.} + +include "system/memalloc" + + +proc `|`*(a, b: typedesc): typedesc = discard + +include "system/iterators_1" + + +proc len*[U: Ordinal; V: Ordinal](x: HSlice[U, V]): int {.noSideEffect, inline.} = + ## Length of ordinal slice. When x.b < x.a returns zero length. + ## ```nim + ## assert((0..5).len == 6) + ## assert((5..2).len == 0) + ## ``` + result = max(0, ord(x.b) - ord(x.a) + 1) -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".} +proc isNil*[T: proc | iterator {.closure.}](x: T): 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.}= + ## `== nil`. + +when defined(nimHasTopDownInference): + # magic used for seq type inference + proc `@`*[T](a: openArray[T]): seq[T] {.magic: "OpenArrayToSeq".} = + ## Turns an *openArray* into a sequence. + ## + ## This is not as efficient as turning a fixed length array into a sequence + ## as it always copies every element of `a`. + newSeq(result, a.len) + for i in 0..a.len-1: result[i] = a[i] +else: + proc `@`*[T](a: openArray[T]): seq[T] = + ## Turns an *openArray* into a sequence. + ## + ## This is not as efficient as turning a fixed length array into a sequence + ## as it always copies every element of `a`. + newSeq(result, a.len) + for i in 0..a.len-1: result[i] = a[i] + + +when defined(nimSeqsV2): + + proc `&`*[T](x, y: sink seq[T]): seq[T] {.noSideEffect.} = + ## Concatenates two sequences. + ## + ## Requires copying of the sequences. + ## ```nim + ## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6]) + ## ``` + ## + ## See also: + ## * `add(var seq[T], openArray[T]) <#add,seq[T],openArray[T]>`_ + newSeq(result, x.len + y.len) + for i in 0..x.len-1: + result[i] = move(x[i]) + for i in 0..y.len-1: + result[i+x.len] = move(y[i]) + + proc `&`*[T](x: sink seq[T], y: sink T): seq[T] {.noSideEffect.} = + ## Appends element y to the end of the sequence. + ## + ## Requires copying of the sequence. + ## ```nim + ## assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4]) + ## ``` + ## + ## See also: + ## * `add(var seq[T], T) <#add,seq[T],sinkT>`_ + newSeq(result, x.len + 1) + for i in 0..x.len-1: + result[i] = move(x[i]) + result[x.len] = move(y) + + proc `&`*[T](x: sink T, y: sink seq[T]): seq[T] {.noSideEffect.} = + ## Prepends the element x to the beginning of the sequence. + ## + ## Requires copying of the sequence. + ## ```nim + ## assert(1 & @[2, 3, 4] == @[1, 2, 3, 4]) + ## ``` + newSeq(result, y.len + 1) + result[0] = move(x) + for i in 0..y.len-1: + result[i+1] = move(y[i]) + +else: + + proc `&`*[T](x, y: seq[T]): seq[T] {.noSideEffect.} = + ## Concatenates two sequences. + ## + ## Requires copying of the sequences. + ## ```nim + ## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6]) + ## ``` + ## + ## See also: + ## * `add(var seq[T], openArray[T]) <#add,seq[T],openArray[T]>`_ + 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: seq[T], y: T): seq[T] {.noSideEffect.} = + ## Appends element y to the end of the sequence. + ## + ## Requires copying of the sequence. + ## ```nim + ## assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4]) + ## ``` + ## + ## See also: + ## * `add(var seq[T], T) <#add,seq[T],sinkT>`_ + 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: seq[T]): seq[T] {.noSideEffect.} = + ## Prepends the element x to the beginning of the sequence. + ## + ## Requires copying of the sequence. + ## ```nim + ## assert(1 & @[2, 3, 4] == @[1, 2, 3, 4]) + ## ``` + newSeq(result, y.len + 1) + result[0] = x + for i in 0..y.len-1: + result[i+1] = y[i] + + +proc instantiationInfo*(index = -1, fullPaths = false): tuple[ + filename: string, line: int, column: int] {.magic: "InstantiationInfo", noSideEffect.} + ## Provides access to the compiler's instantiation stack line information + ## of a template. + ## + ## While similar to the `caller info`:idx: of other languages, it is determined + ## at compile time. + ## + ## This proc is mostly useful for meta programming (eg. `assert` template) + ## to retrieve information about the current filename and line number. + ## Example: + ## + ## ```nim + ## import std/strutils + ## + ## template testException(exception, code: untyped): typed = + ## try: + ## let pos = instantiationInfo() + ## discard(code) + ## echo "Test failure at $1:$2 with '$3'" % [pos.filename, + ## $pos.line, astToStr(code)] + ## assert false, "A test expecting failure succeeded?" + ## except exception: + ## discard + ## + ## proc tester(pos: int): int = + ## let + ## a = @[1, 2, 3] + ## result = a[pos] + ## + ## when isMainModule: + ## testException(IndexDefect, tester(30)) + ## testException(IndexDefect, tester(1)) + ## # --> Test failure at example.nim:20 with 'tester(1)' + ## ``` + + +when notJSnotNims: + import system/ansi_c + import system/memory + + +{.push stackTrace: off.} + +when not defined(js) and hasThreadSupport and hostOS != "standalone": + import std/private/syslocks + include "system/threadlocalstorage" + +when not defined(js) and defined(nimV2): + type + DestructorProc = proc (p: pointer) {.nimcall, benign, raises: [].} + TNimTypeV2 {.compilerproc.} = object + destructor: pointer + size: int + align: int16 + depth: int16 + display: ptr UncheckedArray[uint32] # classToken + when defined(nimTypeNames) or defined(nimArcIds): + name: cstring + traceImpl: pointer + typeInfoV1: pointer # for backwards compat, usually nil + flags: int + when defined(gcDestructors): + when defined(cpp): + vTable: ptr UncheckedArray[pointer] # vtable for types + else: + vTable: UncheckedArray[pointer] # vtable for types + PNimTypeV2 = ptr TNimTypeV2 + +proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".} + +when notJSnotNims and defined(nimSeqsV2): + include "system/strs_v2" + include "system/seqs_v2" + +when not defined(js): + template newSeqImpl(T, len) = + result = newSeqOfCap[T](len) + {.cast(noSideEffect).}: + when defined(nimSeqsV2): + cast[ptr int](addr result)[] = len + else: + var s = cast[PGenericSeq](result) + s.len = len + + proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] {.deprecated: "Use `newSeqUninit` instead".} = + ## Creates a new sequence of type `seq[T]` with length `len`. + ## + ## Only available for numbers types. Note that the sequence will be + ## uninitialized. After the creation of the sequence you should assign + ## entries to the sequence instead of adding them. + ## Example: + ## ```nim + ## var x = newSeqUninitialized[int](3) + ## assert len(x) == 3 + ## x[0] = 10 + ## ``` + result = newSeqOfCap[T](len) + when defined(nimSeqsV2): + cast[ptr int](addr result)[] = len + else: + var s = cast[PGenericSeq](result) + s.len = len + + func newSeqUninit*[T](len: Natural): seq[T] = + ## Creates a new sequence of type `seq[T]` with length `len`. + ## + ## Only available for types, which don't contain + ## managed memory or have destructors. + ## Note that the sequence will be uninitialized. + ## After the creation of the sequence you should assign + ## entries to the sequence instead of adding them. + runnableExamples: + var x = newSeqUninit[int](3) + assert len(x) == 3 + x[0] = 10 + when supportsCopyMem(T): + when nimvm: + result = newSeq[T](len) + else: + newSeqImpl(T, len) + else: + {.error: "The type T cannot contain managed memory or have destructors".} + + proc newStringUninit*(len: Natural): string = + ## 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 or with `add`. + when nimvm: + result = newString(len) + else: + result = newStringOfCap(len) + when defined(nimSeqsV2): + let s = cast[ptr NimStringV2](addr result) + if len > 0: + s.len = len + s.p.data[len] = '\0' + else: + let s = cast[NimString](result) + s.len = len + s.data[len] = '\0' +else: + proc newStringUninit*(len: Natural): string {. + magic: "NewString", importc: "mnewString", noSideEffect.} + +{.pop.} + +when not defined(nimscript): + proc writeStackTrace*() {.tags: [], gcsafe, raises: [].} + ## Writes the current stack trace to `stderr`. This is only works + ## for debug builds. Since it's usually used for debugging, this + ## is proclaimed to have no IO effect! + +when not declared(sysFatal): + include "system/fatal" + +type + PFrame* = ptr TFrame ## Represents a runtime frame of the call stack; + ## part of the debugger API. + # keep in sync with nimbase.h `struct TFrame_` + TFrame* {.importc, nodecl, final.} = object ## The frame itself. + prev*: PFrame ## Previous frame; used for chaining the call stack. + 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. + len*: int16 ## Length of the inspectable slots. + calldepth*: int16 ## Used for max call depth checking. + when NimStackTraceMsgs: + frameMsgLen*: int ## end position in frameMsgBuf for this frame. + +when defined(nimV2): + var + framePtr {.threadvar.}: PFrame + + include system/arc + +template newException*(exceptn: typedesc, message: string; + parentException: ref Exception = nil): untyped = + ## Creates an exception object of type `exceptn` and sets its `msg` field + ## to `message`. Returns the new exception object. + (ref exceptn)(msg: message, parent: parentException) + +when not defined(nimPreviewSlimSystem): + import std/assertions + export assertions + +import system/iterators +export iterators + + +proc find*[T, S](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. + ## appropriate `items` and `==` operations to work. + result = 0 for i in items(a): if i == item: return inc(result) @@ -1171,432 +1747,1209 @@ proc find*[T, S: typeDesc](a: T, item: S): int {.inline.}= 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``. + ## for `find(a, item) >= 0`. + ## + ## This allows the `in` operator: `a.contains(item)` is the same as + ## `item in a`. + ## ```nim + ## var a = @[1, 3, 5] + ## assert a.contains(5) + ## assert 3 in a + ## assert 99 notin a + ## ``` 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 +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. + ## + ## Raises `IndexDefect` if `s` is empty. + runnableExamples: + var a = @[1, 3, 5, 7] + let b = pop(a) + assert b == 7 + assert a == @[1, 3, 5] + var L = s.len-1 - result = s[L] - setLen(s, L) + when defined(nimV2): + result = move s[L] + shrink(s, L) + else: + result = s[L] + setLen(s, L) + +proc `==`*[T: tuple|object](x, y: T): bool = + ## Generic `==` operator for tuples that is lifted from the components. + ## of `x` and `y`. + for a, b in fields(x, y): + if a != b: return false + return true + +proc `<=`*[T: tuple](x, y: T): bool = + ## Generic lexicographic `<=` operator for tuples that is lifted from the + ## components of `x` and `y`. This implementation uses `cmp`. + for a, b in fields(x, y): + var c = cmp(a, b) + if c < 0: return true + if c > 0: return false + return true + +proc `<`*[T: tuple](x, y: T): bool = + ## Generic lexicographic `<` operator for tuples that is lifted from the + ## components of `x` and `y`. This implementation uses `cmp`. + for a, b in fields(x, y): + var c = cmp(a, b) + if c < 0: return true + if c > 0: return false + return false + + +include "system/gc_interface" + +# we have to compute this here before turning it off in except.nim anyway ... +const NimStackTrace = compileOption("stacktrace") + +import system/coro_detection + +{.push checks: 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 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]) +when notJSnotNims: + var + globalRaiseHook*: proc (e: ref Exception): bool {.nimcall, benign.} + ## With this hook you can influence exception handling on a global level. + ## If not nil, every 'raise' statement ends up calling this hook. + ## + ## .. warning:: Ordinary application code should never set this hook! You better know what you do when setting this. + ## + ## If `globalRaiseHook` returns false, the exception is caught and does + ## not propagate further through the call stack. + localRaiseHook* {.threadvar.}: proc (e: ref Exception): bool {.nimcall, benign.} + ## With this hook you can influence exception handling on a + ## thread local level. + ## If not nil, every 'raise' statement ends up calling this hook. + ## + ## .. warning:: Ordinary application code should never set this hook! You better know what you do when setting this. + ## + ## If `localRaiseHook` returns false, the exception + ## is caught and does not propagate further through the call stack. -# ----------------- FPU ------------------------------------------------------ + outOfMemHook*: proc () {.nimcall, tags: [], benign, raises: [].} + ## Set this variable to provide a procedure that should be called + ## in case of an `out of memory`:idx: event. The standard handler + ## writes an error message and terminates the program. + ## + ## `outOfMemHook` can be used to raise an exception in case of OOM like so: + ## + ## ```nim + ## var gOutOfMem: ref EOutOfMemory + ## new(gOutOfMem) # need to be allocated *before* OOM really happened! + ## gOutOfMem.msg = "out of memory" + ## + ## proc handleOOM() = + ## raise gOutOfMem + ## + ## system.outOfMemHook = handleOOM + ## ``` + ## + ## If the handler does not raise an exception, ordinary control flow + ## continues and the program is terminated. + unhandledExceptionHook*: proc (e: ref Exception) {.nimcall, tags: [], benign, raises: [].} + ## Set this variable to provide a procedure that should be called + ## in case of an `unhandle exception` event. The standard handler + ## writes an error message and terminates the program, except when + ## using `--os:any` + +when defined(js) or defined(nimdoc): + proc add*(x: var string, y: cstring) {.asmNoStackFrame.} = + ## Appends `y` to `x` in place. + runnableExamples: + var tmp = "" + tmp.add(cstring("ab")) + tmp.add(cstring("cd")) + doAssert tmp == "abcd" + {.emit: """ + if (`x` === null) { `x` = []; } + var off = `x`.length; + `x`.length += `y`.length; + for (var i = 0; i < `y`.length; ++i) { + `x`[off+i] = `y`.charCodeAt(i); + } + """.} + proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".} = + ## Appends `y` to `x` in place. + ## Only implemented for JS backend. + runnableExamples: + when defined(js): + var tmp: cstring = "" + tmp.add(cstring("ab")) + tmp.add(cstring("cd")) + doAssert tmp == cstring("abcd") + +elif hasAlloc: + {.push stackTrace: off, profiler: off.} + proc add*(x: var string, y: cstring) = + var i = 0 + if y != nil: + while y[i] != '\0': + add(x, y[i]) + inc(i) + {.pop.} -#proc disableFPUExceptions*() -# disables all floating point unit exceptions +proc echo*(x: varargs[typed, `$`]) {.magic: "Echo", benign, sideEffect.} + ## Writes and flushes the parameters to the standard output. + ## + ## Special built-in that takes a variable number of arguments. Each argument + ## is converted to a string via `$`, so it works for user-defined + ## types that have an overloaded `$` operator. + ## It is roughly equivalent to `writeLine(stdout, x); flushFile(stdout)`, but + ## available for the JavaScript target too. + ## + ## Unlike other IO operations this is guaranteed to be thread-safe as + ## `echo` is very often used for debugging convenience. If you want to use + ## `echo` inside a `proc without side effects + ## <manual.html#pragmas-nosideeffect-pragma>`_ you can use `debugEcho + ## <#debugEcho,varargs[typed,]>`_ instead. + +proc debugEcho*(x: varargs[typed, `$`]) {.magic: "Echo", noSideEffect, + tags: [], raises: [].} + ## Same as `echo <#echo,varargs[typed,]>`_, but as a special semantic rule, + ## `debugEcho` pretends to be free of side effects, so that it can be used + ## for debugging routines marked as `noSideEffect + ## <manual.html#pragmas-nosideeffect-pragma>`_. + +when hostOS == "standalone" and defined(nogc): + proc nimToCStringConv(s: NimString): cstring {.compilerproc, inline.} = + if s == nil or s.len == 0: result = cstring"" + else: result = cast[cstring](addr s.data) + +proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", benign.} + ## Get type information for `x`. + ## + ## Ordinary code should not use this, but the `typeinfo module + ## <typeinfo.html>`_ instead. -#proc enableFPUExceptions*() -# enables all floating point unit exceptions -# ----------------- GC interface --------------------------------------------- +when not defined(js): -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 likelyProc(val: bool): bool {.importc: "NIM_LIKELY", nodecl, noSideEffect.} + proc unlikelyProc(val: bool): bool {.importc: "NIM_UNLIKELY", nodecl, noSideEffect.} -proc GC_enable*() - ## enables the GC again. +template likely*(val: bool): bool = + ## Hints the optimizer that `val` is likely going to be true. + ## + ## You can use this template to decorate a branch condition. On certain + ## platforms this can help the processor predict better which branch is + ## going to be run. Example: + ## ```nim + ## for value in inputValues: + ## if likely(value <= 100): + ## process(value) + ## else: + ## echo "Value too big!" + ## ``` + ## + ## On backends without branch prediction (JS and the nimscript VM), this + ## template will not affect code execution. + when nimvm: + val + else: + when defined(js): + val + else: + likelyProc(val) -proc GC_fullCollect*() - ## forces a full garbage collection pass. - ## Ordinary code does not need to call this (and should not). +template unlikely*(val: bool): bool = + ## Hints the optimizer that `val` is likely going to be false. + ## + ## You can use this proc to decorate a branch condition. On certain + ## platforms this can help the processor predict better which branch is + ## going to be run. Example: + ## ```nim + ## for value in inputValues: + ## if unlikely(value > 100): + ## echo "Value too big!" + ## else: + ## process(value) + ## ``` + ## + ## On backends without branch prediction (JS and the nimscript VM), this + ## template will not affect code execution. + when nimvm: + val + else: + when defined(js): + val + else: + unlikelyProc(val) -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 +import system/dollars +export dollars + +when defined(nimAuditDelete): + {.pragma: auditDelete, deprecated: "review this call for out of bounds behavior".} +else: + {.pragma: auditDelete.} -proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo".} - ## equivalent to ``writeln(stdout, x); flush(stdout)``. BUT: This is - ## available for the ECMAScript target too! +proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, systemRaisesDefect, auditDelete.} = + ## Deletes the item at index `i` by moving all `x[i+1..^1]` items by one position. + ## + ## This is an `O(n)` operation. + ## + ## See also: + ## * `del <#del,seq[T],Natural>`_ for O(1) operation + ## + runnableExamples: + var s = @[1, 2, 3, 4, 5] + s.delete(2) + doAssert s == @[1, 2, 4, 5] + + when not defined(nimAuditDelete): + if i > high(x): + # xxx this should call `raiseIndexError2(i, high(x))` after some refactoring + raise (ref IndexDefect)(msg: "index out of bounds: '" & $i & "' < '" & $x.len & "' failed") + + template defaultImpl = + let xl = x.len + for j in i.int..xl-2: movingCopy(x[j], x[j+1]) + setLen(x, xl-1) + + when nimvm: + defaultImpl() + else: + when defined(js): + {.emit: "`x`.splice(`i`, 1);".} + else: + defaultImpl() -template newException*(exceptn, message: expr): expr = - ## creates an exception object of type "exceptn" and sets its ``msg`` field - ## to `message`. Returns the new exception object. - 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. + NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch + ## is the version of Nim as a string. + +when not defined(js): + {.push stackTrace: off, profiler: off.} + + when hasAlloc: + when not defined(gcRegions) and not usesDestructors: + proc initGC() {.gcsafe, raises: [].} + + proc initStackBottom() {.inline, compilerproc.} = + # WARNING: This is very fragile! An array size of 8 does not work on my + # Linux 64bit system. -- That's because the stack direction is the other + # way around. + when declared(nimGC_setStackBottom): + var locals {.volatile, noinit.}: pointer + locals = addr(locals) + nimGC_setStackBottom(locals) + + proc initStackBottomWith(locals: pointer) {.inline, compilerproc.} = + # We need to keep initStackBottom around for now to avoid + # bootstrapping problems. + when declared(nimGC_setStackBottom): + nimGC_setStackBottom(locals) + + when not usesDestructors: + {.push profiler: off.} + var + strDesc = TNimType(size: sizeof(string), kind: tyString, flags: {ntfAcyclic}) + {.pop.} - QuitFailure* = 1 - ## is the value that should be passed to ``quit`` to indicate - ## failure. + {.pop.} -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(js): + # ugly hack, see the accompanying .pop for + # the mysterious error message + {.push stackTrace: off, profiler: off.} + +when notJSnotNims: + proc zeroMem(p: pointer, size: Natural) = + nimZeroMem(p, size) + when declared(memTrackerOp): + memTrackerOp("zeroMem", p, size) + proc copyMem(dest, source: pointer, size: Natural) = + nimCopyMem(dest, source, size) + when declared(memTrackerOp): + memTrackerOp("copyMem", dest, size) + proc moveMem(dest, source: pointer, size: Natural) = + c_memmove(dest, source, csize_t(size)) + when declared(memTrackerOp): + memTrackerOp("moveMem", dest, size) + proc equalMem(a, b: pointer, size: Natural): bool = + nimCmpMem(a, b, size) == 0 + proc cmpMem(a, b: pointer, size: Natural): int = + nimCmpMem(a, b, size).int + +when not defined(js) or defined(nimscript): + # nimscript can be defined if config file for js compilation + proc cmp(x, y: string): int = + when nimvm: + if x < y: result = -1 + elif x > y: result = 1 + else: result = 0 + else: + when not defined(nimscript): # avoid semantic checking + let minlen = min(x.len, y.len) + result = int(nimCmpMem(x.cstring, y.cstring, cast[csize_t](minlen))) + if result == 0: + result = x.len - y.len + + when declared(newSeq): + proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] = + ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be + ## of length `len`. + if a == nil: return @[] + newSeq(result, len) + for i in 0..len-1: result[i] = $a[i] + + proc cstringArrayToSeq*(a: cstringArray): seq[string] = + ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be + ## terminated by `nil`. + if a == nil: return @[] + var L = 0 + while a[L] != nil: inc(L) + result = cstringArrayToSeq(a, L) + + +when not defined(js) and declared(alloc0) and declared(dealloc): + proc allocCStringArray*(a: openArray[string]): cstringArray = + ## Creates a NULL terminated cstringArray from `a`. The result has to + ## be freed with `deallocCStringArray` after it's not needed anymore. + result = cast[cstringArray](alloc0((a.len+1) * sizeof(cstring))) + + let x = cast[ptr UncheckedArray[string]](a) + for i in 0 .. a.high: + result[i] = cast[cstring](alloc0(x[i].len+1)) + copyMem(result[i], addr(x[i][0]), x[i].len) + + proc deallocCStringArray*(a: cstringArray) = + ## Frees a NULL terminated cstringArray. + var i = 0 + while a[i] != nil: + dealloc(a[i]) + inc(i) + dealloc(a) -when not defined(EcmaScript) and not defined(NimrodVM): +when notJSnotNims and not gotoBasedExceptions: + type + PSafePoint = ptr TSafePoint + TSafePoint {.compilerproc, final.} = object + prev: PSafePoint # points to next safe point ON THE STACK + status: int + context: C_JmpBuf + SafePoint = TSafePoint + +when not defined(js): + when declared(initAllocator): + initAllocator() + when hasThreadSupport: + when hostOS != "standalone": + include system/threadimpl + when not defined(nimPreviewSlimSystem): + import std/typedthreads + export typedthreads + + elif not defined(nogc) and not defined(nimscript): + when not defined(useNimRtl) and not defined(createNimRtl): initStackBottom() + when declared(initGC): initGC() + +when notJSnotNims: + proc setControlCHook*(hook: proc () {.noconv.}) + ## Allows you to override the behaviour of your application when CTRL+C + ## is pressed. Only one such hook is supported. + ## Example: + ## + ## ```nim + ## proc ctrlc() {.noconv.} = + ## echo "Ctrl+C fired!" + ## # do clean up stuff + ## quit() + ## + ## setControlCHook(ctrlc) + ## ``` - proc initGC() + when not defined(noSignalHandler) and not defined(useNimRtl): + proc unsetControlCHook*() + ## Reverts a call to setControlCHook. - var - strDesc: TNimType + when hostOS != "standalone": + proc getStackTrace*(): string {.gcsafe.} + ## Gets the current stack trace. This only works for debug builds. - strDesc.size = sizeof(string) - strDesc.kind = tyString - strDesc.flags = {ntfAcyclic} - initGC() # BUGFIX: need to be called here! + proc getStackTrace*(e: ref Exception): string {.gcsafe.} + ## Gets the stack trace associated with `e`, which is the stack that + ## lead to the `raise` statement. This only works for debug builds. - {.push stack_trace: off.} + {.push stackTrace: off, profiler: off.} + when defined(memtracker): + include "system/memtracker" - include "system/ansi_c" + when hostOS == "standalone": + include "system/embedded" + else: + include "system/excpt" + include "system/chcks" - proc cmp(x, y: string): int = - return int(c_strcmp(x, y)) + # we cannot compile this with stack tracing on + # as it would recurse endlessly! + include "system/integerops" + {.pop.} - 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 not defined(js): + # this is a hack: without this when statement, you would get: + # Error: system module needs: nimGCvisit + {.pop.} # stackTrace: off, profiler: off - 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) - - iterator lines*(f: TFile): string = - ## Iterate over any line in the file `f`. - var res = "" - while not endOfFile(f): - rawReadLine(f, res) - yield res - - 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) - - proc cstringArrayToSeq*(a: cstringArray, len: int): seq[string] = - ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be - ## of length ``len``. - newSeq(result, len) - for i in 0..len-1: result[i] = $a[i] - - proc cstringArrayToSeq*(a: cstringArray): seq[string] = - ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be - ## terminated by ``nil``. - var L = 0 - while a[L] != nil: inc(L) - result = cstringArrayToSeq(a, L) - - # ---------------------------------------------------------------------------- - - 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" +when notJSnotNims: + when hostOS != "standalone" and hostOS != "any": + type + LibHandle = pointer # private type + ProcAddr = pointer # library loading and loading of procs: + + proc nimLoadLibrary(path: string): LibHandle {.compilerproc, hcrInline, nonReloadable.} + proc nimUnloadLibrary(lib: LibHandle) {.compilerproc, hcrInline, nonReloadable.} + proc nimGetProcAddr(lib: LibHandle, name: cstring): ProcAddr {.compilerproc, hcrInline, nonReloadable.} + + proc nimLoadLibraryError(path: string) {.compilerproc, hcrInline, nonReloadable.} + + include "system/dyncalls" + + import system/countbits_impl include "system/sets" - const - GenericSeqSize = (2 * sizeof(int)) - - proc reprAny(p: pointer, typ: PNimType): string {.compilerproc.} + when defined(gogc): + const GenericSeqSize = (3 * sizeof(int)) + else: + const GenericSeqSize = (2 * sizeof(int)) - proc getDiscriminant(aa: Pointer, n: ptr TNimNode): int = - assert(n.kind == nkCase) - var d: int - var a = cast[TAddress](aa) + proc getDiscriminant(aa: pointer, n: ptr TNimNode): uint = + sysAssert(n.kind == nkCase, "getDiscriminant: node != nkCase") + var d: uint + var a = cast[uint](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) + of 1: d = uint(cast[ptr uint8](a + uint(n.offset))[]) + of 2: d = uint(cast[ptr uint16](a + uint(n.offset))[]) + of 4: d = uint(cast[ptr uint32](a + uint(n.offset))[]) + of 8: d = uint(cast[ptr uint64](a + uint(n.offset))[]) + else: + d = 0'u + sysAssert(false, "getDiscriminant: invalid n.typ.size") return d - proc selectBranch(aa: Pointer, n: ptr TNimNode): ptr TNimNode = + proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode = var discr = getDiscriminant(aa, n) - if discr <% n.len: + if discr < cast[uint](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) + # n.sons[n.len] contains the `else` part (but may be nil) else: result = n.sons[n.len] - include "system/mm" - include "system/sysstr" +when notJSnotNims and hasAlloc: + {.push profiler: off.} + include "system/mmdisp" + {.pop.} + {.push stackTrace: off, profiler: off.} + when not defined(nimSeqsV2): + include "system/sysstr" + {.pop.} + + include "system/strmantle" 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 + when not defined(nimV2): + include "system/repr" + +when notJSnotNims and hasThreadSupport and hostOS != "standalone": + when not defined(nimPreviewSlimSystem): + include "system/channels_builtin" + - {.push stack_trace: off.} - when defined(endb): - include "system/debugger" +when notJSnotNims and hostOS != "standalone": + proc getCurrentException*(): ref Exception {.compilerRtl, inl, benign.} = + ## Retrieves the current exception; if there is none, `nil` is returned. + result = currException - when defined(profiler): + proc nimBorrowCurrentException(): ref Exception {.compilerRtl, inl, benign, nodestroy.} = + # .nodestroy here so that we do not produce a write barrier as the + # C codegen only uses it in a borrowed way: + result = currException + + proc getCurrentExceptionMsg*(): string {.inline, benign.} = + ## Retrieves the error message that was attached to the current + ## exception; if there is none, `""` is returned. + return if currException == nil: "" else: currException.msg + + proc setCurrentException*(exc: ref Exception) {.inline, benign.} = + ## Sets the current exception. + ## + ## .. warning:: Only use this if you know what you are doing. + currException = exc +elif defined(nimscript): + proc getCurrentException*(): ref Exception {.compilerRtl.} = discard + +when notJSnotNims: + {.push stackTrace: off, profiler: off.} + when (defined(profiler) or defined(memProfiler)): 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 + {.pop.} + + proc rawProc*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} = + ## Retrieves the raw proc pointer of the closure `x`. This is + ## useful for interfacing closures with C/C++, hash computations, etc. + ## If `rawEnv(x)` returns `nil`, the proc which the result points to + ## takes as many parameters as `x`, but with `{.nimcall.}` as its calling + ## convention instead of `{.closure.}`, otherwise it takes one more parameter + ## which is a `pointer`, and it still has `{.nimcall.}` as its calling convention. + ## To invoke the resulted proc, what this returns has to be casted into a `proc`, + ## not a `ptr proc`, and, in a case where `rawEnv(x)` returns non-`nil`, + ## the last and additional argument has to be the result of `rawEnv(x)`. + ## This is not available for the JS target. + #[ + The conversion from function pointer to `void*` is a tricky topic, but this + should work at least for c++ >= c++11, e.g. for `dlsym` support. + refs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57869, + https://stackoverflow.com/questions/14125474/casts-between-pointer-to-function-and-pointer-to-object-in-c-and-c + ]# + runnableExamples: + proc makeClosure(x: int): (proc(y: int): int) = + var n = x + result = ( + proc(y: int): int = + n += y + return n + ) + + var + c1 = makeClosure(10) + e = c1.rawEnv() + p = c1.rawProc() + + if e.isNil(): + let c2 = cast[proc(y: int): int {.nimcall.}](p) + echo c2(2) + else: + let c3 = cast[proc(y: int; env: pointer): int {.nimcall.}](p) + echo c3(3, e) + + {.emit: """ + `result` = (void*)`x`.ClP_0; + """.} + + proc rawEnv*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} = + ## Retrieves the raw environment pointer of the closure `x`. See also `rawProc`. + ## This is not available for the JS target. + {.emit: """ + `result` = `x`.ClE_0; + """.} + +proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} = + ## It can be used to determine if a first class iterator has finished. + when defined(js): + # TODO: mangle `:state` + {.emit: """ + `result` = (`x`.ClE_0).HEX3Astate < 0; + """.} + else: + {.emit: """ + `result` = ((NI*) `x`.ClE_0)[1] < 0; + """.} + +from std/private/digitsutils import addInt +export addInt + +when defined(js) and not defined(nimscript): + # nimscript can be defined if config file for js compilation + include "system/jssys" + include "system/reprjs" + + +when defined(nimNoQuit): + proc quit*(errorcode: int = QuitSuccess) = discard "ignoring quit" + +elif defined(nimdoc): + proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.} + ## Stops the program immediately with an exit code. + ## + ## Before stopping the program the "exit procedures" are called in the + ## opposite order they were added with `addExitProc <exitprocs.html#addExitProc,proc)>`_. + ## + ## The proc `quit(QuitSuccess)` is called implicitly when your nim + ## program finishes without incident for platforms where this is the + ## expected behavior. A raised unhandled exception is + ## equivalent to calling `quit(QuitFailure)`. + ## + ## Note that this is a *runtime* call and using `quit` inside a macro won't + ## have any compile time effect. If you need to stop the compiler inside a + ## macro, use the `error <manual.html#pragmas-error-pragma>`_ or `fatal + ## <manual.html#pragmas-fatal-pragma>`_ pragmas. + ## + ## .. warning:: `errorcode` gets saturated when it exceeds the valid range + ## on the specific platform. On Posix, the valid range is `low(int8)..high(int8)`. + ## On Windows, the valid range is `low(int32)..high(int32)`. For instance, + ## `quit(int(0x100000000))` is equal to `quit(127)` on Linux. + ## + ## .. danger:: In almost all cases, in particular in library code, prefer + ## alternatives, e.g. `raiseAssert` or raise a `Defect`. + ## `quit` bypasses regular control flow in particular `defer`, + ## `try`, `catch`, `finally` and `destructors`, and exceptions that may have been + ## raised by an `addExitProc` proc, as well as cleanup code in other threads. + ## It does *not* call the garbage collector to free all the memory, + ## unless an `addExitProc` proc calls `GC_fullCollect <#GC_fullCollect>`_. + +elif defined(genode): + proc quit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = + rawQuit(errorcode) + +elif defined(js) and defined(nodejs) and not defined(nimscript): + proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", + importc: "process.exit", noreturn.} + +else: + proc quit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = + when defined(posix): # posix uses low 8 bits + type ExitCodeRange = int8 + else: # win32 uses low 32 bits + type ExitCodeRange = cint + when sizeof(errorcode) > sizeof(ExitCodeRange): + if errorcode < low(ExitCodeRange): + rawQuit(low(ExitCodeRange).cint) + elif errorcode > high(ExitCodeRange): + rawQuit(high(ExitCodeRange).cint) + else: + rawQuit(errorcode.cint) + else: + rawQuit(errorcode.cint) + +proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} = + ## A shorthand for `echo(errormsg); quit(errorcode)`. + when defined(nimscript) or defined(js) or (hostOS == "standalone"): + echo errormsg + else: + when nimvm: + echo errormsg + else: + cstderr.rawWrite(errormsg) + cstderr.rawWrite("\n") + quit(errorcode) + +{.pop.} # checks: off +# {.pop.} # hints: off + +include "system/indices" + +proc `&=`*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} + ## Appends in place to a string. + ## ```nim + ## var a = "abc" + ## a &= "de" # a <- "abcde" + ## ``` + +template `&=`*(x, y: typed) = + ## Generic 'sink' operator for Nim. + ## + ## If not specialized further, an alias for `add`. + add(x, y) + +when compileOption("rangechecks"): + template rangeCheck*(cond) = + ## Helper for performing user-defined range checks. + ## Such checks will be performed only when the `rangechecks` + ## compile-time option is enabled. + if not cond: sysFatal(RangeDefect, "range check failed") +else: + template rangeCheck*(cond) = discard + +when not defined(gcArc) and not defined(gcOrc) and not defined(gcAtomicArc): + proc shallow*[T](s: var seq[T]) {.noSideEffect, inline.} = + ## Marks a sequence `s` as `shallow`:idx:. Subsequent assignments will not + ## perform deep copies of `s`. + ## + ## This is only useful for optimization purposes. + if s.len == 0: return + when not defined(js) and not defined(nimscript) and not defined(nimSeqsV2): + var s = cast[PGenericSeq](s) + {.noSideEffect.}: + s.reserved = s.reserved or seqShallowFlag + + proc shallow*(s: var string) {.noSideEffect, inline.} = + ## Marks a string `s` as `shallow`:idx:. Subsequent assignments will not + ## perform deep copies of `s`. + ## + ## This is only useful for optimization purposes. + when not defined(js) and not defined(nimscript) and not defined(nimSeqsV2): + var s = cast[PGenericSeq](s) + if s == nil: + s = cast[PGenericSeq](newString(0)) + # string literals cannot become 'shallow': + if (s.reserved and strlitFlag) == 0: + {.noSideEffect.}: + s.reserved = s.reserved or seqShallowFlag + +type + NimNodeObj = object + + NimNode* {.magic: "PNimrodNode".} = ref NimNodeObj + ## Represents a Nim AST node. Macros operate on this type. + +type + ForLoopStmt* {.compilerproc.} = object ## \ + ## A special type that marks a macro as a `for-loop macro`:idx:. + ## See `"For Loop Macro" <manual.html#macros-for-loop-macro>`_. + +macro varargsLen*(x: varargs[untyped]): int {.since: (1, 1).} = + ## returns number of variadic arguments in `x` + proc varargsLenImpl(x: NimNode): NimNode {.magic: "LengthOpenArray", noSideEffect.} + varargsLenImpl(x) + +when defined(nimV2): + import system/repr_v2 + export repr_v2 + +proc repr*[T, U](x: HSlice[T, U]): string = + ## Generic `repr` operator for slices that is lifted from the components + ## of `x`. Example: + ## ```Nim + ## $(1 .. 5) == "1 .. 5" + ## ``` + result = repr(x.a) + result.add(" .. ") + result.add(repr(x.b)) + +when hasAlloc or defined(nimscript): + proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} = + ## Inserts `item` into `x` at position `i`. + ## ```nim + ## var a = "abc" + ## a.insert("zz", 0) # a <- "zzabc" + ## ``` + if item.len == 0: # prevents self-assignment + return + var xl = x.len + setLen(x, xl+item.len) + var j = xl-1 + while j >= i: + when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc): + x[j+item.len] = move x[j] + else: + shallowCopy(x[j+item.len], x[j]) + dec(j) + j = 0 + while j < item.len: + x[j+i] = item[j] + inc(j) + +when declared(initDebugger): + initDebugger() + +proc addEscapedChar*(s: var string, c: char) {.noSideEffect, inline.} = + ## Adds a char to string `s` and applies the following escaping: + ## + ## * replaces any ``\`` by `\\` + ## * replaces any `'` by `\'` + ## * replaces any `"` by `\"` + ## * replaces any `\a` by `\\a` + ## * replaces any `\b` by `\\b` + ## * replaces any `\t` by `\\t` + ## * replaces any `\n` by `\\n` + ## * replaces any `\v` by `\\v` + ## * replaces any `\f` by `\\f` + ## * replaces any `\r` by `\\r` + ## * replaces any `\e` by `\\e` + ## * replaces any other character not in the set `{\21..\126}` + ## by `\xHH` where `HH` is its hexadecimal value + ## + ## The procedure has been designed so that its output is usable for many + ## different common syntaxes. + ## + ## .. warning:: This is **not correct** for producing ANSI C code! + ## + case c + of '\a': s.add "\\a" # \x07 + of '\b': s.add "\\b" # \x08 + of '\t': s.add "\\t" # \x09 + of '\n': s.add "\\n" # \x0A + of '\v': s.add "\\v" # \x0B + of '\f': s.add "\\f" # \x0C + of '\r': (when defined(nimLegacyAddEscapedCharx0D): s.add "\\c" else: s.add "\\r") # \x0D + of '\e': s.add "\\e" # \x1B + of '\\': s.add("\\\\") + of '\'': s.add("\\'") + of '\"': s.add("\\\"") + of {'\32'..'\126'} - {'\\', '\'', '\"'}: s.add(c) + else: + s.add("\\x") + const HexChars = "0123456789ABCDEF" + let n = ord(c) + s.add(HexChars[int((n and 0xF0) shr 4)]) + s.add(HexChars[int(n and 0xF)]) + +proc addQuoted*[T](s: var string, x: T) = + ## Appends `x` to string `s` in place, applying quoting and escaping + ## if `x` is a string or char. + ## + ## See `addEscapedChar <#addEscapedChar,string,char>`_ + ## for the escaping scheme. When `x` is a string, characters in the + ## range `{\128..\255}` are never escaped so that multibyte UTF-8 + ## characters are untouched (note that this behavior is different from + ## `addEscapedChar`). + ## + ## The Nim standard library uses this function on the elements of + ## collections when producing a string representation of a collection. + ## It is recommended to use this function as well for user-side collections. + ## Users may overload `addQuoted` for custom (string-like) types if + ## they want to implement a customized element representation. + ## + ## ```nim + ## var tmp = "" + ## tmp.addQuoted(1) + ## tmp.add(", ") + ## tmp.addQuoted("string") + ## tmp.add(", ") + ## tmp.addQuoted('c') + ## assert(tmp == """1, "string", 'c'""") + ## ``` + when T is string or T is cstring: + s.add("\"") + for c in x: + # Only ASCII chars are escaped to avoid butchering + # multibyte UTF-8 characters. + if c <= 127.char: + s.addEscapedChar(c) + else: + s.add c + s.add("\"") + elif T is char: + s.add("'") + s.addEscapedChar(x) + s.add("'") + # prevent temporary string allocation + elif T is SomeInteger: + s.addInt(x) + elif T is SomeFloat: + s.addFloat(x) + elif compiles(s.add(x)): + s.add(x) + else: + s.add($x) + +proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} = + ## Generates a tuple constructor expression listing all the local variables + ## in the current scope. + ## + ## This is quite fast as it does not rely + ## on any debug or runtime information. Note that in contrast to what + ## the official signature says, the return type is *not* `RootObj` but a + ## tuple of a structure that depends on the current scope. Example: + ## + ## ```nim + ## proc testLocals() = + ## var + ## a = "something" + ## b = 4 + ## c = locals() + ## d = "super!" + ## + ## b = 1 + ## for name, value in fieldPairs(c): + ## echo "name ", name, " with value ", value + ## echo "B is ", b + ## # -> name a with value something + ## # -> name b with value 4 + ## # -> B is 1 + ## ``` + discard + +when hasAlloc and notJSnotNims: + # XXX how to implement 'deepCopy' is an open problem. + proc deepCopy*[T](x: var T, y: T) {.noSideEffect, magic: "DeepCopy".} = + ## Performs a deep copy of `y` and copies it into `x`. + ## + ## This is also used by the code generator + ## for the implementation of `spawn`. + ## + ## For `--mm:arc` or `--mm:orc` deepcopy support has to be enabled + ## via `--deepcopy:on`. + discard + + proc deepCopy*[T](y: T): T = + ## Convenience wrapper around `deepCopy` overload. + deepCopy(result, y) + + include "system/deepcopy" + +proc procCall*(x: untyped) {.magic: "ProcCall", compileTime.} = + ## Special magic to prohibit dynamic binding for `method`:idx: calls. + ## This is similar to `super`:idx: in ordinary OO languages. + ## ```nim + ## # 'someMethod' will be resolved fully statically: + ## procCall someMethod(a, b) + ## ``` + discard + + +proc `==`*(x, y: cstring): bool {.magic: "EqCString", noSideEffect, + inline.} = + ## Checks for equality between two `cstring` variables. + proc strcmp(a, b: cstring): cint {.noSideEffect, + importc, header: "<string.h>".} + if pointer(x) == pointer(y): result = true + elif pointer(x) == nil or pointer(y) == nil: result = false + else: result = strcmp(x, y) == 0 + +template closureScope*(body: untyped): untyped = + ## Useful when creating a closure in a loop to capture local loop variables by + ## their current iteration values. + ## + ## Note: This template may not work in some cases, use + ## `capture <sugar.html#capture.m,varargs[typed],untyped>`_ instead. + ## + ## Example: + ## + ## ```nim + ## var myClosure : proc() + ## # without closureScope: + ## for i in 0 .. 5: + ## let j = i + ## if j == 3: + ## myClosure = proc() = echo j + ## myClosure() # outputs 5. `j` is changed after closure creation + ## # with closureScope: + ## for i in 0 .. 5: + ## closureScope: # Everything in this scope is locked after closure creation + ## let j = i + ## if j == 3: + ## myClosure = proc() = echo j + ## myClosure() # outputs 3 + ## ``` + (proc() = body)() + +template once*(body: untyped): untyped = + ## Executes a block of code only once (the first time the block is reached). + ## ```nim + ## proc draw(t: Triangle) = + ## once: + ## graphicsInit() + ## line(t.p1, t.p2) + ## line(t.p2, t.p3) + ## line(t.p3, t.p1) + ## ``` + var alreadyExecuted {.global.} = false + if not alreadyExecuted: + alreadyExecuted = true + body + +{.pop.} # warning[GcMem]: off, warning[Uninit]: off + +proc substr*(s: openArray[char]): string = + ## Copies a slice of `s` into a new string and returns this new + ## string. + runnableExamples: + let a = "abcdefgh" + assert a.substr(2, 5) == "cdef" + assert a.substr(2) == "cdefgh" + assert a.substr(5, 99) == "fgh" + result = newString(s.len) + for i, ch in s: + result[i] = ch + +proc substr*(s: string, first, last: int): string = # A bug with `magic: Slice` requires this to exist this way + ## 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)`. If `last >= s.len`, `s.len` + ## is used instead: This means `substr` can also be used to `cut`:idx: + ## or `limit`:idx: a string's length. + runnableExamples: + let a = "abcdefgh" + assert a.substr(2, 5) == "cdef" + assert a.substr(2) == "cdefgh" + assert a.substr(5, 99) == "fgh" + + let first = max(first, 0) + let L = max(min(last, high(s)) - first + 1, 0) + result = newString(L) + for i in 0 .. L-1: + result[i] = s[i+first] + +proc substr*(s: string, first = 0): string = + result = substr(s, first, high(s)) + +when defined(nimconfig): + include "system/nimscript" + +when not defined(js): + proc toOpenArray*[T](x: ptr UncheckedArray[T]; first, last: int): openArray[T] {. + magic: "Slice".} + proc toOpenArray*(x: cstring; first, last: int): openArray[char] {. + magic: "Slice".} + proc toOpenArrayByte*(x: cstring; first, last: int): openArray[byte] {. + magic: "Slice".} + +proc toOpenArray*[T](x: seq[T]; first, last: int): openArray[T] {. + magic: "Slice".} + ## Allows passing the slice of `x` from the element at `first` to the element + ## at `last` to `openArray[T]` parameters without copying it. + ## + ## Example: + ## ```nim + ## proc test(x: openArray[int]) = + ## doAssert x == [1, 2, 3] + ## + ## let s = @[0, 1, 2, 3, 4] + ## s.toOpenArray(1, 3).test + ## ``` + +proc toOpenArray*[T](x: openArray[T]; first, last: int): openArray[T] {. + magic: "Slice".} +proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openArray[T] {. + magic: "Slice".} +proc toOpenArray*(x: string; first, last: int): openArray[char] {. + magic: "Slice".} + +proc toOpenArrayByte*(x: string; first, last: int): openArray[byte] {. + magic: "Slice".} +proc toOpenArrayByte*(x: openArray[char]; first, last: int): openArray[byte] {. + magic: "Slice".} +proc toOpenArrayByte*(x: seq[char]; first, last: int): openArray[byte] {. + magic: "Slice".} + +proc toOpenArrayChar*(x: openArray[byte]; first, last: int): openArray[char] {. + magic: "Slice".} + +when defined(genode): + var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.} + ## Hook into the Genode component bootstrap process. + ## + ## This hook is called after all globals are initialized. + ## When this hook is set the component will not automatically exit, + ## call `quit` explicitly to do so. This is the only available method + ## of accessing the initial Genode environment. + + proc nim_component_construct(env: GenodeEnv) {.exportc.} = + ## Procedure called during `Component::construct` by the loader. + if componentConstructHook.isNil: + env.rawQuit(programResult) + # No native Genode application initialization, + # exit as would POSIX. + else: + componentConstructHook(env) + # Perform application initialization + # and return to thread entrypoint. + + +when not defined(nimPreviewSlimSystem): + import std/widestrs + export widestrs + +when notJSnotNims: + when defined(windows) and compileOption("threads"): + when not declared(addSysExitProc): + proc addSysExitProc(quitProc: proc() {.noconv.}) {.importc: "atexit", header: "<stdlib.h>".} + var echoLock: SysLock + initSysLock echoLock + addSysExitProc(proc() {.noconv.} = deinitSys(echoLock)) + + const stdOutLock = compileOption("threads") and + not defined(windows) and + not defined(android) and + not defined(nintendoswitch) and + not defined(freertos) and + not defined(zephyr) and + not defined(nuttx) and + hostOS != "any" + + proc raiseEIO(msg: string) {.noinline, noreturn.} = + raise newException(IOError, msg) + + proc echoBinSafe(args: openArray[string]) {.compilerproc.} = + when defined(androidNDK): + # When running nim in android app, stdout goes nowhere, so echo gets ignored + # To redirect echo to the android logcat, use -d:androidNDK + const ANDROID_LOG_VERBOSE = 2.cint + proc android_log_print(prio: cint, tag: cstring, fmt: cstring): cint + {.importc: "__android_log_print", header: "<android/log.h>", varargs, discardable.} + var s = "" + for arg in args: + s.add arg + android_log_print(ANDROID_LOG_VERBOSE, "nim", s) + else: + # flockfile deadlocks some versions of Android 5.x.x + when stdOutLock: + proc flockfile(f: CFilePtr) {.importc, nodecl.} + proc funlockfile(f: CFilePtr) {.importc, nodecl.} + flockfile(cstdout) + when defined(windows) and compileOption("threads"): + acquireSys echoLock + for s in args: + when defined(windows): + # equivalent to syncio.writeWindows + proc writeWindows(f: CFilePtr; s: string; doRaise = false) = + # Don't ask why but the 'printf' family of function is the only thing + # that writes utf-8 strings reliably on Windows. At least on my Win 10 + # machine. We also enable `setConsoleOutputCP(65001)` now by default. + # But we cannot call printf directly as the string might contain \0. + # So we have to loop over all the sections separated by potential \0s. + var i = int c_fprintf(f, "%s", s) + while i < s.len: + if s[i] == '\0': + let w = c_fputc('\0', f) + if w != 0: + if doRaise: raiseEIO("cannot write string to file") + break + inc i + else: + let w = c_fprintf(f, "%s", unsafeAddr s[i]) + if w <= 0: + if doRaise: raiseEIO("cannot write string to file") + break + inc i, w + writeWindows(cstdout, s) + else: + discard c_fwrite(s.cstring, cast[csize_t](s.len), 1, cstdout) + const linefeed = "\n" + discard c_fwrite(linefeed.cstring, linefeed.len, 1, cstdout) + discard c_fflush(cstdout) + when stdOutLock: + funlockfile(cstdout) + when defined(windows) and compileOption("threads"): + releaseSys echoLock + +when not defined(nimPreviewSlimSystem): + import std/syncio + export syncio + +when not defined(createNimHcr) and not defined(nimscript): + include nimhcr + +when notJSnotNims and not defined(nimSeqsV2): + proc prepareMutation*(s: var string) {.inline.} = + ## String literals (e.g. "abc", etc) in the ARC/ORC mode are "copy on write", + ## therefore you should call `prepareMutation` before modifying the strings + ## via `addr`. + runnableExamples: + var x = "abc" + var y = "defgh" + prepareMutation(y) # without this, you may get a `SIGBUS` or `SIGSEGV` + moveMem(addr y[0], addr x[0], x.len) + assert y == "abcgh" + discard + +proc arrayWith*[T](y: T, size: static int): array[size, T] {.raises: [].} = + ## Creates a new array filled with `y`. + for i in 0..size-1: + when nimvm: + result[i] = y + else: + # TODO: fixme it should be `=dup` + result[i] = y |