# # # 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 must not be listed ## explicitly. Because of this there cannot be a user-defined module named ## ``system``. ## ## System module ## ============= ## ## .. include:: ./system_overview.rst type float* {.magic: Float.} ## Default floating point type. float32* {.magic: Float32.} ## 32 bit floating point type. float64* {.magic: Float.} ## 64 bit floating point type. # 'float64' is now an alias to 'float'; this solves many problems 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, use the ``addr`` ## operator to get a pointer to a variable. typedesc* {.magic: TypeDesc.} ## Meta type to denote a type description. type `ptr`*[T] {.magic: Pointer.} ## Built-in generic untraced pointer type. `ref`*[T] {.magic: Pointer.} ## Built-in generic traced pointer type. `nil` {.magic: "Nil".} void* {.magic: "VoidType".} ## Meta type to denote the absence of any type. auto* {.magic: Expr.} ## Meta type for automatic type determination. any* = distinct auto ## Meta type for any supported type. untyped* {.magic: Expr.} ## Meta type to denote an expression that ## is not resolved (for templates). typed* {.magic: Stmt.} ## Meta type to denote an expression that ## is resolved (for templates). include "system/basic_types" proc compileOption*(option: string): bool {. magic: "CompileOption", noSideEffect.} ## Can be used to determine an `on|off` compile-time option. Example: ## ## .. code-block:: Nim ## when compileOption("floatchecks"): ## echo "compiled with floating point NaN and Inf checks" proc compileOption*(option, arg: string): bool {. magic: "CompileOptionArg", noSideEffect.} ## Can be used to determine an enum compile-time option. Example: ## ## .. code-block:: Nim ## when compileOption("opt", "size") and compileOption("gc", "boehm"): ## echo "compiled with optimization for size and uses Boehm's GC" {.push warning[GcMem]: off, warning[Uninit]: off.} {.push hints: off.} 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. type SomeFloat* = float|float32|float64 ## Type class matching all floating point number types. SomeNumber* = SomeInteger|SomeFloat ## Type class matching all number types. proc defined*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.} ## Special compile-time procedure that checks whether `x` is ## defined. ## ## `x` is an external symbol introduced through the compiler's ## `-d:x switch `_ to enable ## build time conditionals: ## ## .. code-block:: Nim ## when not defined(release): ## # Do here programmer friendly expensive sanity checks. ## # Put here the normal code when defined(nimHashOrdinalFixed): type Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer, ## bool, character, and enumeration types ## as well as their subtypes. See also ## `SomeOrdinal`. else: # bootstrap <= 0.20.0 type OrdinalImpl[T] {.magic: Ordinal.} Ordinal* = OrdinalImpl | uint | uint64 when defined(nimHasRunnableExamples): proc runnableExamples*(body: untyped) {.magic: "RunnableExamples".} ## A section you should use to mark `runnable example`:idx: code with. ## ## - In normal debug and release builds code within ## a ``runnableExamples`` section is ignored. ## - The documentation generator is aware of these examples and considers them ## part of the ``##`` doc comment. As the last step of documentation ## generation each runnableExample is put in its own file ``$file_examples$i.nim``, ## compiled and tested. The collected examples are ## put into their own module to ensure the examples do not refer to ## non-exported symbols. ## ## Usage: ## ## .. code-block:: Nim ## proc double*(x: int): int = ## ## This proc doubles a number. ## runnableExamples: ## ## at module scope ## assert double(5) == 10 ## block: ## at block scope ## defer: echo "done" ## ## result = 2 * x else: template runnableExamples*(body: untyped) = discard proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.} ## Special compile-time procedure that checks whether `x` is ## declared. `x` has to be an identifier or a qualified identifier. ## ## See also: ## * `declaredInScope <#declaredInScope,untyped>`_ ## ## This can be used to check whether a library provides a certain ## feature or not: ## ## .. code-block:: Nim ## when not declared(strutils.toUpper): ## # provide our own toUpper proc here, because strutils is ## # missing it. proc declaredInScope*(x: untyped): bool {. magic: "DefinedInScope", noSideEffect, compileTime.} ## Special compile-time procedure that checks whether `x` is ## declared in the current scope. `x` has to be an identifier. proc `addr`*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} = ## Builtin `addr` operator for taking the address of a memory location. ## Cannot be overloaded. ## ## See also: ## * `unsafeAddr <#unsafeAddr,T>`_ ## ## .. code-block:: 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.} = ## Builtin `addr` operator for taking the address of a memory ## location. This works even for ``let`` variables or parameters ## for better interop with C and so it is considered even more ## unsafe than the ordinary `addr <#addr,T>`_. ## ## **Note**: When you use it to write a wrapper for a C library, 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. discard when defined(nimNewTypedesc): type `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``. else: proc `type`*(x: untyped): typedesc {.magic: "TypeOf", noSideEffect, compileTime.} = ## Builtin `type` operator for accessing the type of an expression. ## Cannot be overloaded. discard when defined(nimHasTypeof): type 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. discard const ThisIsSystem = true proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.} ## Leaked implementation detail. Do not use. when 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 ## 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! proc wasMoved*[T](obj: var T) {.magic: "WasMoved", 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. discard proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} = result = x wasMoved(x) 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. when defined(nimUncheckedArrayTyp): type UncheckedArray*[T]{.magic: "UncheckedArray".} ## Array with no bounds checking. else: type UncheckedArray*[T]{.unchecked.} = array[0,T] ## Array with no bounds checking. type sink*[T]{.magic: "BuiltinType".} type lent*[T]{.magic: "BuiltinType".} proc high*[T: Ordinal|enum|range](x: T): T {.magic: "High", noSideEffect.} ## Returns the highest possible value of an ordinal value `x`. ## ## As a special semantic rule, `x` may also be a type identifier. ## ## See also: ## * `low(T) <#low,T>`_ ## ## .. code-block:: 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:. ## ## See also: ## * `low(typedesc) <#low,typedesc[T]>`_ ## ## .. code-block:: Nim ## high(int) # => 9223372036854775807 proc high*[T](x: openArray[T]): int {.magic: "High", noSideEffect.} ## Returns the highest possible index of a sequence `x`. ## ## See also: ## * `low(openArray) <#low,openArray[T]>`_ ## ## .. code-block:: Nim ## var s = @[1, 2, 3, 4, 5, 6, 7] ## high(s) # => 6 ## for i in low(s)..high(s): ## echo s[i] proc high*[I, T](x: array[I, T]): I {.magic: "High", noSideEffect.} ## Returns the highest possible index of an array `x`. ## ## See also: ## * `low(array) <#low,array[I,T]>`_ ## ## .. code-block:: Nim ## var arr = [1, 2, 3, 4, 5, 6, 7] ## high(arr) # => 6 ## for i in low(arr)..high(arr): ## echo arr[i] proc high*[I, T](x: typedesc[array[I, T]]): I {.magic: "High", noSideEffect.} ## Returns the highest possible index of an array type. ## ## See also: ## * `low(typedesc[array]) <#low,typedesc[array[I,T]]>`_ ## ## .. code-block:: Nim ## high(array[7, int]) # => 6 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`. ## ## See also: ## * `low(string) <#low,string>`_ ## ## .. code-block:: Nim ## var str = "Hello world!" ## high(str) # => 11 proc low*[T: Ordinal|enum|range](x: T): T {.magic: "Low", noSideEffect.} ## Returns the lowest possible value of an ordinal value `x`. As a special ## semantic rule, `x` may also be a type identifier. ## ## See also: ## * `high(T) <#high,T>`_ ## ## .. code-block:: 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:. ## ## See also: ## * `high(typedesc) <#high,typedesc[T]>`_ ## ## .. code-block:: Nim ## low(int) # => -9223372036854775808 proc low*[T](x: openArray[T]): int {.magic: "Low", noSideEffect.} ## Returns the lowest possible index of a sequence `x`. ## ## See also: ## * `high(openArray) <#high,openArray[T]>`_ ## ## .. code-block:: Nim ## var s = @[1, 2, 3, 4, 5, 6, 7] ## low(s) # => 0 ## for i in low(s)..high(s): ## echo s[i] proc low*[I, T](x: array[I, T]): I {.magic: "Low", noSideEffect.} ## Returns the lowest possible index of an array `x`. ## ## See also: ## * `high(array) <#high,array[I,T]>`_ ## ## .. code-block:: Nim ## var arr = [1, 2, 3, 4, 5, 6, 7] ## low(arr) # => 0 ## for i in low(arr)..high(arr): ## echo arr[i] proc low*[I, T](x: typedesc[array[I, T]]): I {.magic: "Low", noSideEffect.} ## Returns the lowest possible index of an array type. ## ## See also: ## * `high(typedesc[array]) <#high,typedesc[array[I,T]]>`_ ## ## .. code-block:: Nim ## low(array[7, int]) # => 0 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`. ## ## See also: ## * `high(string) <#high,string>`_ ## ## .. code-block:: Nim ## var str = "Hello world!" ## low(str) # => 0 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. when defined(nimArrIdx): # :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 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".} proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = ## Generic `destructor`:idx: implementation that can be overridden. discard proc `=sink`*[T](x: var T; y: T) {.inline, magic: "Asgn".} = ## Generic `sink`:idx: implementation that can be overridden. shallowCopy(x, y) type 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. ## ## .. code-block:: 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".} = ## Unary `slice`:idx: operator that constructs an interval ``[default(int), b]``. ## ## .. code-block:: Nim ## let a = [10, 20, 30, 40, 50] ## echo a[.. 2] # @[10, 20, 30] result = HSlice[int, T](a: 0, b: b) when not defined(niminheritable): {.pragma: inheritable.} when not defined(nimunion): {.pragma: unchecked.} when not defined(nimHasHotCodeReloading): {.pragma: nonReloadable.} when defined(hotCodeReloading): {.pragma: hcrInline, inline.} else: {.pragma: hcrInline.} {.push profiler: off.} let nimvm* {.magic: "Nimvm", compileTime.}: bool = false ## May be used only in `when` expression. ## It is true in Nim VM context and false otherwise. {.pop.} 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, 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: UncheckedArray[char] NimString = ptr NimStringDesc when notJSnotNims and not defined(nimSeqsV2): template space(s: PGenericSeq): int {.dirty.} = s.reserved and not (seqShallowFlag or strlitFlag) when notJSnotNims and not defined(nimV2): include "system/hti" type 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. 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. 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`. include "system/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. ## ## .. code-block:: Nim ## sizeof('A') # => 1 ## sizeof(2) # => 8 when defined(nimHasalignOf): 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.} when defined(nimtypedescfixed): 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: ## ## .. code-block:: 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. ## ## See also: ## * `newSeqOfCap <#newSeqOfCap,Natural>`_ ## * `newSeqUninitialized <#newSeqUninitialized,Natural>`_ ## ## .. code-block:: 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" 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``. ## ## .. code-block:: Nim ## var x = newSeqOfCap[int](5) ## assert len(x) == 0 ## x.add(10) ## assert len(x) == 1 discard when not defined(js): proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] = ## 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. ## ## .. code-block:: 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 proc len*[TOpenArray: openArray|varargs](x: TOpenArray): int {. magic: "LengthOpenArray", noSideEffect.} ## Returns the length of an openArray. ## ## .. code-block:: Nim ## var s = [1, 1, 1, 1, 1] ## echo len(s) # => 5 proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} ## Returns the length of a string. ## ## .. code-block:: Nim ## var str = "Hello world!" ## echo len(str) # => 12 proc len*(x: cstring): int {.magic: "LengthStr", noSideEffect.} ## Returns the length of a compatible string. This is sometimes ## an O(n) operation. ## ## .. code-block:: Nim ## var str: cstring = "Hello world!" ## len(str) # => 12 proc len*(x: (type array)|array): int {.magic: "LengthArray", noSideEffect.} ## Returns the length of an array or an array type. ## This is roughly the same as ``high(T)-low(T)+1``. ## ## .. code-block:: Nim ## var arr = [1, 1, 1, 1, 1] ## echo len(arr) # => 5 ## echo len(array[3..8, int]) # => 6 proc len*[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.} ## Returns the length of a sequence. ## ## .. code-block:: Nim ## var s = @[1, 1, 1, 1, 1] ## echo len(s) # => 5 proc ord*[T: Ordinal|enum](x: T): int {.magic: "Ord", noSideEffect.} ## Returns the internal `int` value of an ordinal value ``x``. ## ## .. code-block:: Nim ## echo ord('A') # => 65 ## echo ord('a') # => 97 proc chr*(u: range[0..255]): char {.magic: "Chr", noSideEffect.} ## Converts an `int` in the range `0..255` to a character. ## ## .. code-block:: Nim ## echo chr(65) # => A ## echo chr(97) # => a # floating point operations: proc `+`*(x: float32): float32 {.magic: "UnaryPlusF64", noSideEffect.} proc `-`*(x: float32): float32 {.magic: "UnaryMinusF64", noSideEffect.} proc `+`*(x, y: float32): float32 {.magic: "AddF64", noSideEffect.} proc `-`*(x, y: float32): float32 {.magic: "SubF64", noSideEffect.} proc `*`*(x, y: float32): float32 {.magic: "MulF64", noSideEffect.} proc `/`*(x, y: float32): float32 {.magic: "DivF64", noSideEffect.} 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.} proc `==`*(x, y: float32): bool {.magic: "EqF64", noSideEffect.} proc `<=`*(x, y: float32): bool {.magic: "LeF64", noSideEffect.} proc `<` *(x, y: float32): bool {.magic: "LtF64", noSideEffect.} proc `==`*(x, y: float): bool {.magic: "EqF64", noSideEffect.} proc `<=`*(x, y: float): bool {.magic: "LeF64", noSideEffect.} proc `<`*(x, y: float): bool {.magic: "LtF64", noSideEffect.} 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` ## ## .. code-block:: 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 template `in`*(x, y: untyped): untyped {.dirty.} = contains(y, x) ## Sugar for `contains`. ## ## .. code-block:: Nim ## assert(1 in (1..3) == true) ## assert(5 in (1..3) == false) template `notin`*(x, y: untyped): untyped {.dirty.} = not contains(y, x) ## Sugar for `not contains`. ## ## .. code-block:: 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>`_. ## ## .. code-block:: 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 = not (x is y) ## Negated version of `is <#is,T,S>`_. Equivalent to ``not(x is y)``. ## ## .. code-block:: 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 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. # This is only required to make 0.20 compile with the 0.19 line. template ``*(t: untyped): untyped = owned(t) 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 # This is only required to make 0.20 compile with the 0.19 line. template ``*(t: untyped): untyped = t template disarm*(x: typed) = ## Useful for ``disarming`` dangling pointers explicitly for the ## --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: typedesc[T], y: typedesc[S]): bool {.magic: "Of", noSideEffect.} proc `of`*[T, S](x: T, y: typedesc[S]): bool {.magic: "Of", noSideEffect.} proc `of`*[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.} ## Checks if `x` has a type of `y`. ## ## .. code-block:: Nim ## assert(FloatingPointDefect of Exception) ## assert(DivByZeroDefect of Exception) proc cmp*[T](x, y: T): int {.procvar.} = ## 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. ## ## .. code-block:: Nim ## import 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, procvar.} ## 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! when defined(nimHasDefault): 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]``. ## ## .. code-block:: Nim ## let ## a = [1, 3, 5] ## b = "foo" ## ## echo @a # => @[1, 3, 5] ## echo @b # => @['f', 'o', 'o'] proc default*(T: typedesc): T {.magic: "Default", noSideEffect.} ## returns the default value of the type ``T``. proc reset*[T](obj: var T) {.noSideEffect.} = ## Resets an object `obj` to its default value. obj = default(typeof(obj)) else: proc `@`* [IDX, T](a: array[IDX, T]): seq[T] {. magic: "ArrToSeq", noSideEffect.} when defined(nimV2): proc reset*[T](obj: var T) {.magic: "Destroy", noSideEffect.} else: proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.} proc setLen*[T](s: var seq[T], newlen: Natural) {. magic: "SetLengthSeq", noSideEffect.} ## 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. ## ## .. code-block:: 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 string `s` to `newlen`. ## ## If the current length is greater than the new length, ## ``s`` will be truncated. ## ## .. code-block:: 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 or with ``add``. 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, merge.} ## Concatenates `x` with `y`. ## ## .. code-block:: Nim ## assert("ab" & 'c' == "abc") proc `&`*(x, y: char): string {. magic: "ConStrStr", noSideEffect, merge.} ## Concatenates characters `x` and `y` into a string. ## ## .. code-block:: Nim ## assert('a' & 'b' == "ab") proc `&`*(x, y: string): string {. magic: "ConStrStr", noSideEffect, merge.} ## Concatenates strings `x` and `y`. ## ## .. code-block:: Nim ## assert("ab" & "cd" == "abcd") proc `&`*(x: char, y: string): string {. magic: "ConStrStr", noSideEffect, merge.} ## Concatenates `x` with `y`. ## ## .. code-block:: Nim ## assert('a' & "bc" == "abc") # implementation note: These must all have the same magic value "ConStrStr" so # that the merge optimization works properly. proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.} ## Appends `y` to `x` in place. ## ## .. code-block:: 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. ## ## .. code-block:: Nim ## var tmp = "" ## tmp.add("ab") ## tmp.add("cd") ## assert(tmp == "abcd") type Endianness* = enum ## Type describing the endianness of a processor. littleEndian, bigEndian const isMainModule* {.magic: "IsMainModule".}: bool = false ## 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" ## The date (in UTC) of compilation as a string of the form ## ``YYYY-MM-DD``. This works thanks to compiler magic. CompileTime* {.magic: "CompileTime"}: string = "00:00:00" ## The time (in UTC) of compilation as a string of the form ## ``HH:MM:SS``. This works thanks to compiler magic. 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"`, `"riscv64"`. 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 hasThreadSupport = compileOption("threads") and not defined(nimscript) hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own taintMode = compileOption("taintmode") nimEnableCovariance* = defined(nimEnableCovariance) # or true 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".} 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.0" elif defined(freebsd): const boehmLib = "libgc-threaded.so.1" else: const boehmLib = "libgc.so.1" {.pragma: boehmGC, noconv, dynlib: boehmLib.} when taintMode: type TaintedString* = distinct string ## A distinct string type that ## is `tainted`:idx:, see `taint mode ## `_ ## for details. It is an alias for ## ``string`` if the taint mode is not ## turned on. proc len*(s: TaintedString): int {.borrow.} else: type TaintedString* = string ## A distinct string type that ## is `tainted`:idx:, see `taint mode ## `_ ## for details. It is an alias for ## ``string`` if the taint mode is not ## turned on. when defined(profiler) and not defined(nimscript): proc nimProfile() {.compilerproc, noinline.} when hasThreadSupport: {.pragma: rtlThreadVar, threadvar.} else: {.pragma: rtlThreadVar.} const QuitSuccess* = 0 ## is the value that should be passed to `quit <#quit,int>`_ to indicate ## success. QuitFailure* = 1 ## is the value that should be passed to `quit <#quit,int>`_ to indicate ## failure. when defined(js) and defined(nodejs) and not defined(nimscript): var programResult* {.importc: "process.exitCode".}: int programResult = 0 elif hostOS != "standalone": var programResult* {.compilerproc, exportc: "nim_program_result".}: int ## deprecated, prefer ``quit`` 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) when defined(nimdoc): proc quit*(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.} ## Stops the program immediately with an exit code. ## ## Before stopping the program the "quit procedures" are called in the ## opposite order they were added with `addQuitProc <#addQuitProc,proc>`_. ## ``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_fullCollect ## <#GC_fullCollect>`_. ## ## 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 `_ or `fatal ## `_ pragmas. elif defined(genode): include genode/env var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr type GenodeEnv* = GenodeEnvPtr ## Opaque type representing Genode environment. proc quit*(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "".} proc quit*(errorcode: int = QuitSuccess) = systemEnv.quit(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) {. magic: "Exit", importc: "exit", header: "", noreturn.} template sysAssert(cond: bool, msg: string) = when defined(useSysAssert): if not cond: cstderr.rawWrite "[SYSASSERT] " cstderr.rawWrite msg cstderr.rawWrite "\n" quit 1 const hasAlloc = (hostOS != "standalone" or not defined(nogc)) and not defined(nimscript) when notJSnotNims and hostOS != "standalone" and hostOS != "any": include "system/cgprocs" when notJSnotNims and hasAlloc and not defined(nimSeqsV2): proc addChar(s: NimString, c: char): NimString {.compilerproc, benign.} when defined(nimscript) or not defined(nimSeqsV2): proc add*[T](x: var seq[T], y: 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. 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][T],seq[T][T]>`_ ## ## .. code-block:: Nim ## var s: seq[string] = @["test2","test2"] ## s.add("test") # s <- @[test2, test2, test] 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) = a = move(b) else: template movingCopy(a, b) = 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][T],Natural>`_ for preserving the order ## ## .. code-block:: Nim ## var i = @[1, 2, 3, 4, 5] ## i.del(2) # => @[1, 2, 5, 4] let xl = x.len - 1 movingCopy(x[i], x[xl]) setLen(x, xl) proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect.} = ## Deletes the item at index `i` by moving all ``x[i+1..]`` items by one position. ## ## This is an `O(n)` operation. ## ## See also: ## * `del <#delete,seq[T][T],Natural>`_ for O(1) operation ## ## .. code-block:: Nim ## var i = @[1, 2, 3, 4, 5] ## i.delete(2) # => @[1, 2, 4, 5] 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() proc insert*[T](x: var seq[T], item: sink T, i = 0.Natural) {.noSideEffect.} = ## Inserts `item` into `x` at position `i`. ## ## .. code-block:: Nim ## var i = @[1, 3, 5] ## i.insert(99, 0) # i <- @[99, 1, 3, 5] 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. ## ## It works even for complex data graphs with cycles. This is a great ## debugging tool. ## ## .. code-block:: 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] type ByteAddress* = int ## is the signed integer type that should be used for converting ## pointers to integer addresses for readability. BiggestFloat* = float64 ## is an alias for the biggest floating point type the Nim ## compiler supports. Currently this is ``float64``, but it is ## platform-dependent in general. when defined(js): type BiggestUInt* = uint32 ## is an alias for the biggest unsigned integer type the Nim compiler ## supports. Currently this is ``uint32`` for JS and ``uint64`` for other ## targets. else: type BiggestUInt* = uint64 ## is an alias for the biggest unsigned integer type the Nim compiler ## supports. Currently this is ``uint32`` for JS and ``uint64`` for other ## targets. when defined(windows): type clong* {.importc: "long", nodecl.} = int32 ## This is the same as the type ``long`` in *C*. culong* {.importc: "unsigned long", nodecl.} = uint32 ## This is the same as the type ``unsigned long`` in *C*. else: type clong* {.importc: "long", nodecl.} = int ## This is the same as the type ``long`` in *C*. culong* {.importc: "unsigned long", nodecl.} = uint ## This is the same as the type ``unsigned long`` in *C*. 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.} = int8 ## 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*. 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. csize_t* {.importc: "size_t", nodecl.} = uint ## This is the same as the type ``size_t`` 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 Nim's code generator. cuchar* {.importc: "unsigned char", nodecl.} = char ## This is the same as the type ``unsigned char`` in *C*. cushort* {.importc: "unsigned short", nodecl.} = uint16 ## This is the same as the type ``unsigned short`` in *C*. cuint* {.importc: "unsigned int", nodecl.} = uint32 ## This is the same as the type ``unsigned int`` in *C*. culonglong* {.importc: "unsigned long long", nodecl.} = uint64 ## This is the same as the type ``unsigned long long`` in *C*. cstringArray* {.importc: "char**", nodecl.} = ptr UncheckedArray[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 proc <#cstringArrayToSeq,cstringArray,Natural>`_ ## to convert it into a ``seq[string]``. 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``. proc toFloat*(i: int): float {.noSideEffect, inline.} = ## Converts an integer `i` into a ``float``. ## ## If the conversion fails, `ValueError` is raised. ## However, on most platforms the conversion cannot fail. ## ## .. code-block:: 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 ## `_. ## ## Note that some floating point numbers (e.g. infinity or even 1e19) ## cannot be accurately converted. ## ## .. code-block:: 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 addQuitProc*(quitProc: proc() {.noconv.}) {. importc: "atexit", header: "".} ## 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. 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. ## ## .. code-block:: 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])[]) const 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 `classify` procedure ## in the `math module `_ for checking for NaN. include "system/memalloc" proc `|`*(a, b: typedesc): typedesc = discard include "system/iterators_1" {.push stackTrace: off.} proc abs*(x: float64): float64 {.noSideEffect, inline.} = if x < 0.0: -x else: x proc abs*(x: float32): float32 {.noSideEffect, inline.} = if x < 0.0: -x else: x proc min*(x, y: float32): float32 {.noSideEffect, inline.} = if x <= y or y != y: x else: y proc min*(x, y: float64): float64 {.noSideEffect, inline.} = if x <= y or y != y: x else: y proc max*(x, y: float32): float32 {.noSideEffect, inline.} = if y <= x or y != y: x else: y proc max*(x, y: float64): float64 {.noSideEffect, inline.} = if y <= x or y != y: x else: y proc min*[T: not SomeFloat](x, y: T): T {.inline.} = if x <= y: x else: y proc max*[T: not SomeFloat](x, y: T): T {.inline.} = if y <= x: x else: y {.pop.} # stackTrace: off proc high*(T: typedesc[SomeFloat]): T = Inf proc low*(T: typedesc[SomeFloat]): T = NegInf 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. ## ## .. code-block:: Nim ## assert((0..5).len == 6) ## assert((5..2).len == 0) result = max(0, ord(x.b) - ord(x.a) + 1) when defined(nimNoNilSeqs2): when not compileOption("nilseqs"): {.pragma: nilError, error.} else: {.pragma: nilError.} else: {.pragma: nilError.} proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil", nilError.} ## Requires `--nilseqs:on` since 0.19. ## ## Seqs are no longer nil by default, but set and empty. ## Check for zero length instead. ## ## See also: ## * `isNil(string) <#isNil,string>`_ proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".} proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil", nilError.} ## Requires `--nilseqs:on`. ## ## See also: ## * `isNil(seq[T]) <#isNil,seq[T][T]>`_ 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](x: T): bool {.noSideEffect, magic: "IsNil".} ## Fast check whether `x` is nil. This is sometimes more efficient than ## ``== nil``. 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. ## ## See also: ## * `add(var seq[T], openArray[T]) <#add,seq[T][T],openArray[T]>`_ ## ## .. code-block:: Nim ## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6]) 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. ## ## See also: ## * `add(var seq[T], T) <#add,seq[T][T],T>`_ ## ## .. code-block:: Nim ## assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4]) 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. ## ## .. code-block:: 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. ## ## See also: ## * `add(var seq[T], openArray[T]) <#add,seq[T][T],openArray[T]>`_ ## ## .. code-block:: Nim ## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6]) 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. ## ## See also: ## * `add(var seq[T], T) <#add,seq[T][T],T>`_ ## ## .. code-block:: Nim ## assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4]) 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. ## ## .. code-block:: 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 astToStr*[T](x: T): string {.magic: "AstToStr", noSideEffect.} ## Converts the AST of `x` into a string representation. This is very useful ## for debugging. 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: ## ## .. code-block:: nim ## import 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)' proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime.} = ## Special compile-time procedure that checks whether `x` can be compiled ## without any semantic error. ## This can be used to check whether a type supports some operation: ## ## .. code-block:: Nim ## when compiles(3 + 4): ## echo "'+' for integers is available" discard when notJSnotNims: import "system/ansi_c" import "system/memory" {.push stackTrace: off.} when not defined(js) and hasThreadSupport and hostOS != "standalone": const insideRLocksModule = false include "system/syslocks" include "system/threadlocalstorage" when not defined(js) and defined(nimV2): type TNimNode {.compilerproc.} = object # to keep the code generator simple DestructorProc = proc (p: pointer) {.nimcall, benign, raises: [].} TNimType {.compilerproc.} = object destructor: pointer size: int align: int name: cstring traceImpl: pointer disposeImpl: pointer PNimType = ptr TNimType when notJSnotNims and defined(nimSeqsV2): include "system/strs_v2" include "system/seqs_v2" {.pop.} when notJSnotNims: 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" when notJSnotNims: {.push stackTrace: off, profiler: off.} proc atomicInc*(memLoc: var int, x: int = 1): int {.inline, discardable, benign.} ## Atomic increment of `memLoc`. Returns the value after the operation. proc atomicDec*(memLoc: var int, x: int = 1): int {.inline, discardable, benign.} ## Atomic decrement of `memLoc`. Returns the value after the operation. include "system/atomics" {.pop.} when defined(nimV2): include system/refs_v2 import system/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 `==` operations to work. for i in items(a): if i == item: return inc(result) result = -1 proc contains*[T](a: openArray[T], item: T): bool {.inline.}= ## Returns true if `item` is in `a` or false if not found. This is a shortcut ## for ``find(a, item) >= 0``. ## ## This allows the `in` operator: `a.contains(item)` is the same as ## `item in a`. ## ## .. code-block:: 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 ## `s` as a stack and implements the common *pop* operation. runnableExamples: var a = @[1, 3, 5, 7] let b = pop(a) assert b == 7 assert a == @[1, 3, 5] var L = s.len-1 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") template coroutinesSupportedPlatform(): bool = when defined(sparc) or defined(ELATE) or compileOption("gc", "v2") or defined(boehmgc) or defined(gogc) or defined(nogc) or defined(gcRegions) or defined(gcMarkAndSweep): false else: true when defined(nimCoroutines): # Explicit opt-in. when not coroutinesSupportedPlatform(): {.error: "Coroutines are not supported on this architecture and/or garbage collector.".} const nimCoroutines* = true elif defined(noNimCoroutines): # Explicit opt-out. const nimCoroutines* = false else: # Autodetect coroutine support. const nimCoroutines* = false {.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 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. 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: ## ## .. code-block:: 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` 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(js): proc add*(x: var string, y: cstring) {.asmNoStackFrame.} = asm """ 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".} 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.} when defined(nimvarargstyped): proc echo*(x: varargs[typed, `$`]) {.magic: "Echo", tags: [WriteIOEffect], 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 ## `_ 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 ## `_. else: proc echo*(x: varargs[untyped, `$`]) {.magic: "Echo", tags: [WriteIOEffect], benign, sideEffect.} proc debugEcho*(x: varargs[untyped, `$`]) {.magic: "Echo", noSideEffect, tags: [], raises: [].} 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 hostOS == "standalone" and defined(nogc): proc nimToCStringConv(s: NimString): cstring {.compilerproc, inline.} = if s == nil or s.len == 0: result = cstring"" else: result = 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 ## `_ instead. {.push stackTrace: off.} proc abs*(x: int): int {.magic: "AbsI", noSideEffect.} = if x < 0: -x else: x proc abs*(x: int8): int8 {.magic: "AbsI", noSideEffect.} = if x < 0: -x else: x proc abs*(x: int16): int16 {.magic: "AbsI", noSideEffect.} = if x < 0: -x else: x proc abs*(x: int32): int32 {.magic: "AbsI", noSideEffect.} = if x < 0: -x else: x proc abs*(x: int64): int64 {.magic: "AbsI", 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). result = if x < 0: -x else: x {.pop.} when not defined(js): proc likelyProc(val: bool): bool {.importc: "NIM_LIKELY", nodecl, noSideEffect.} proc unlikelyProc(val: bool): bool {.importc: "NIM_UNLIKELY", nodecl, noSideEffect.} 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: ## ## .. code-block:: 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) 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: ## ## .. code-block:: 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) const NimMajor* {.intdefine.}: int = 1 ## is the major number of Nim's version. Example: ## ## .. code-block:: Nim ## when (NimMajor, NimMinor, NimPatch) >= (1, 3, 1): discard # See also private symbol `since: (1, 3)` reserved for stdlib NimMinor* {.intdefine.}: int = 3 ## is the minor number of Nim's version. ## Odd for devel, even for releases. NimPatch* {.intdefine.}: int = 1 ## is the patch number of Nim's version. import system/dollars export dollars const NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch ## is the version of Nim as a string. type FileSeekPos* = enum ## Position relative to which seek should happen. # The values are ordered so that they match with stdio # SEEK_SET, SEEK_CUR and SEEK_END respectively. fspSet ## Seek to absolute value fspCur ## Seek relative to current position fspEnd ## Seek relative to end when not defined(js): {.push stackTrace: off, profiler: off.} when hasAlloc: when not defined(gcRegions) and not usesDestructors: proc initGC() {.gcsafe.} 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.}: 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.} {.pop.} 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 when not defined(js): proc cmp(x, y: string): int = when defined(nimscript): if x < y: result = -1 elif x > y: result = 1 else: result = 0 else: when nimvm: if x < y: result = -1 elif x > y: result = 1 else: result = 0 else: 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``. 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) 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 notJSnotNims: 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/threads" 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. when not defined(noSignalHandler) and not defined(useNimRtl): proc unsetControlCHook*() ## Reverts a call to setControlCHook. when hostOS != "standalone": proc getStackTrace*(): string {.gcsafe.} ## Gets the current stack trace. This only works for debug builds. 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 stackTrace: off, profiler: off.} when defined(memtracker): include "system/memtracker" when hostOS == "standalone": include "system/embedded" else: include "system/excpt" include "system/chcks" # we cannot compile this with stack tracing on # as it would recurse endlessly! when defined(nimNewIntegerOps): include "system/integerops" else: include "system/arithm" {.pop.} 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 notJSnotNims: when hostOS != "standalone" and hostOS != "any": include "system/dyncalls" include "system/sets" when defined(gogc): const GenericSeqSize = (3 * sizeof(int)) else: const GenericSeqSize = (2 * sizeof(int)) when not defined(nimV2): 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 = 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: sysAssert(false, "getDiscriminant: invalid n.typ.size") return d proc selectBranch(aa: pointer, n: ptr TNimNode): ptr TNimNode = var discr = getDiscriminant(aa, n) 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) else: result = n.sons[n.len] 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" when not usesDestructors: include "system/assign" when not defined(nimV2): include "system/repr" when notJSnotNims and hasThreadSupport and hostOS != "standalone": include "system/channels" 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 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 when notJSnotNims: {.push stackTrace: off, profiler: off.} when (defined(profiler) or defined(memProfiler)): include "system/profiler" {.pop.} proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} = ## Retrieves the raw proc pointer of the closure `x`. This is ## useful for interfacing closures with C. {.emit: """ `result` = `x`.ClP_0; """.} proc rawEnv*[T: proc](x: T): pointer {.noSideEffect, inline.} = ## Retrieves the raw environment pointer of the closure `x`. This is ## useful for interfacing closures with C. {.emit: """ `result` = `x`.ClE_0; """.} proc finished*[T: proc](x: T): bool {.noSideEffect, inline.} = ## can be used to determine if a first class iterator has finished. {.emit: """ `result` = ((NI*) `x`.ClE_0)[1] < 0; """.} when defined(js): when not defined(nimscript): include "system/jssys" include "system/reprjs" else: proc cmp(x, y: string): int = if x == y: return 0 if x < y: return -1 return 1 when defined(js) or defined(nimscript): proc addInt*(result: var string; x: int64) = result.add $x proc addFloat*(result: var string; x: float) = result.add $x 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 proc `/`*(x, y: int): float {.inline, noSideEffect.} = ## Division of integers that results in a float. ## ## See also: ## * `div <#div,int,int>`_ ## * `mod <#mod,int,int>`_ ## ## .. code-block:: Nim ## echo 7 / 5 # => 1.4 result = toFloat(x) / toFloat(y) type BackwardsIndex* = distinct int ## Type that is constructed by ``^`` for ## reversed array accesses. ## (See `^ template <#^.t,int>`_) template `^`*(x: int): BackwardsIndex = BackwardsIndex(x) ## Builtin `roof`:idx: operator that can be used for convenient array access. ## ``a[^x]`` is a shortcut for ``a[a.len-x]``. ## ## .. code-block:: Nim ## let ## a = [1, 3, 5, 7, 9] ## b = "abcdefgh" ## ## echo a[^1] # => 9 ## echo b[^2] # => g template `..^`*(a, b: untyped): untyped = ## A shortcut for `.. ^` to avoid the common gotcha that a space between ## '..' and '^' is required. a .. ^b template `..<`*(a, b: untyped): untyped = ## A shortcut for `a .. pred(b)`. ## ## .. code-block:: Nim ## for i in 5 ..< 9: ## echo i # => 5; 6; 7; 8 a .. (when b is BackwardsIndex: succ(b) else: pred(b)) template spliceImpl(s, a, L, b: untyped): untyped = # make room for additional elements or cut: var shift = b.len - max(0,L) # ignore negative slice size var newLen = s.len + shift if shift > 0: # enlarge: setLen(s, newLen) for i in countdown(newLen-1, a+b.len): movingCopy(s[i], s[i-shift]) else: for i in countup(a+b.len, newLen-1): movingCopy(s[i], s[i-shift]) # cut down: setLen(s, newLen) # fill the hole: for i in 0 ..< b.len: s[a+i] = b[i] template `^^`(s, i: untyped): untyped = (when i is BackwardsIndex: s.len - int(i) else: int(i)) template `[]`*(s: string; i: int): char = arrGet(s, i) template `[]=`*(s: string; i: int; val: char) = arrPut(s, i, val) proc `[]`*[T, U](s: string, x: HSlice[T, U]): string {.inline.} = ## Slice operation for strings. ## Returns the inclusive range `[s[x.a], s[x.b]]`: ## ## .. code-block:: Nim ## var s = "abcdef" ## assert s[1..3] == "bcd" let a = s ^^ x.a let L = (s ^^ x.b) - a + 1 result = newString(L) for i in 0 ..< L: result[i] = s[i + a] proc `[]=`*[T, U](s: var string, x: HSlice[T, U], b: string) = ## Slice assignment for strings. ## ## If ``b.len`` is not exactly the number of elements that are referred to ## by `x`, a `splice`:idx: is performed: ## runnableExamples: var s = "abcdefgh" s[1 .. ^2] = "xyz" assert s == "axyzh" var a = s ^^ x.a var L = (s ^^ x.b) - a + 1 if L == b.len: for i in 0..`_. proc staticRead*(filename: string): string {.magic: "Slurp".} ## Compile-time `readFile `_ proc for easy ## `resource`:idx: embedding: ## ## The maximum file size limit that ``staticRead`` and ``slurp`` can read is ## near or equal to the *free* memory of the device you are using to compile. ## ## .. code-block:: Nim ## const myResource = staticRead"mydatafile.bin" ## ## `slurp <#slurp,string>`_ is an alias for ``staticRead``. proc gorge*(command: string, input = "", cache = ""): string {. magic: "StaticExec".} = discard ## This is an alias for `staticExec <#staticExec,string,string,string>`_. proc staticExec*(command: string, input = "", cache = ""): string {. magic: "StaticExec".} = discard ## Executes an external process at compile-time and returns its text output ## (stdout + stderr). ## ## If `input` is not an empty string, it will be passed as a standard input ## to the executed program. ## ## .. code-block:: Nim ## const buildInfo = "Revision " & staticExec("git rev-parse HEAD") & ## "\nCompiled on " & staticExec("uname -v") ## ## `gorge <#gorge,string,string,string>`_ is an alias for ``staticExec``. ## ## Note that you can use this proc inside a pragma like ## `passc `_ or ## `passl `_. ## ## If ``cache`` is not empty, the results of ``staticExec`` are cached within ## the ``nimcache`` directory. Use ``--forceBuild`` to get rid of this caching ## behaviour then. ``command & input & cache`` (the concatenated string) is ## used to determine whether the entry in the cache is still valid. You can ## use versioning information for ``cache``: ## ## .. code-block:: Nim ## const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0") proc gorgeEx*(command: string, input = "", cache = ""): tuple[output: string, exitCode: int] = ## Similar to `gorge <#gorge,string,string,string>`_ but also returns the ## precious exit code. discard proc `+=`*[T: float|float32|float64] (x: var T, y: T) {. inline, noSideEffect.} = ## Increments in place a floating point number. x = x + y proc `-=`*[T: float|float32|float64] (x: var T, y: T) {. inline, noSideEffect.} = ## Decrements in place a floating point number. x = x - y proc `*=`*[T: float|float32|float64] (x: var T, y: T) {. inline, noSideEffect.} = ## Multiplies in place a floating point number. x = x * y proc `/=`*(x: var float64, y: float64) {.inline, noSideEffect.} = ## Divides in place a floating point number. x = x / y proc `/=`*[T: float|float32](x: var T, y: T) {.inline, noSideEffect.} = ## Divides in place a floating point number. x = x / y proc `&=`*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} ## Appends in place to a string. ## ## .. code-block:: Nim ## var a = "abc" ## a &= "de" # a <- "abcde" template `&=`*(x, y: typed) = ## Generic 'sink' operator for Nim. ## ## For files an alias for ``write``. ## If not specialized further, an alias for ``add``. add(x, y) when declared(File): template `&=`*(f: File, x: typed) = write(f, x) template currentSourcePath*: string = instantiationInfo(-1, true).filename ## Returns the full file-system path of the current source. ## ## To get the directory containing the current source, use it with ## `os.parentDir() `_ as ``currentSourcePath.parentDir()``. ## ## The path returned by this template is set at compile time. ## ## See the docstring of `macros.getProjectPath() `_ ## for an example to see the distinction between the ``currentSourcePath`` ## and ``getProjectPath``. ## ## See also: ## * `getCurrentDir proc `_ 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(nimhygiene): {.pragma: inject.} 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) 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: s.reserved = s.reserved or seqShallowFlag type NimNodeObj = object NimNode* {.magic: "PNimrodNode".} = ref NimNodeObj ## Represents a Nim AST node. Macros operate on this type. when defined(nimV2): import system/repr_v2 export repr_v2 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 false: template eval*(blk: typed): typed = ## Executes a block of code at compile time just as if it was a macro. ## ## Optionally, the block can return an AST tree that will replace the ## eval expression. macro payload: typed {.gensym.} = blk payload() when hasAlloc or defined(nimscript): proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} = ## Inserts `item` into `x` at position `i`. ## ## .. code-block:: Nim ## var a = "abc" ## a.insert("zz", 0) # a <- "zzabc" var xl = x.len setLen(x, xl+item.len) var j = xl-1 while j >= i: 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 ``\c`` by ``\\c`` ## * 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. ## ## **Note**: 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 '\L': s.add "\\n" # \x0A of '\v': s.add "\\v" # \x0B of '\f': s.add "\\f" # \x0C of '\c': s.add "\\c" # \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. ## ## .. code-block:: 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 SomeSignedInt: 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: ## ## .. code-block:: 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 and not usesDestructors: # 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``. 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. ## ## .. code-block:: 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: "".} if pointer(x) == pointer(y): result = true elif x.isNil or y.isNil: result = false else: result = strcmp(x, y) == 0 when defined(nimNoNilSeqs2) and not compileOption("nilseqs"): when defined(nimHasUserErrors): # bug #9149; ensure that 'type(nil)' does not match *too* well by using 'type(nil) | type(nil)'. # Eventually (in 0.20?) we will be able to remove this hack completely. proc `==`*(x: string; y: type(nil) | type(nil)): bool {. error: "'nil' is now invalid for 'string'; compile with --nilseqs:on for a migration period".} = discard proc `==`*(x: type(nil) | type(nil); y: string): bool {. error: "'nil' is now invalid for 'string'; compile with --nilseqs:on for a migration period".} = discard else: proc `==`*(x: string; y: type(nil) | type(nil)): bool {.error.} = discard proc `==`*(x: type(nil) | type(nil); y: string): bool {.error.} = discard 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 `_ instead. ## ## Example: ## ## .. code-block:: 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). ## ## .. code-block:: 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: string, first, last: int): string = ## 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".} when defined(nimToOpenArrayCString): 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".} 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".} type ForLoopStmt* {.compilerproc.} = object ## \ ## A special type that marks a macro as a `for-loop macro`:idx:. ## See `"For Loop Macro" `_. 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.quit(programResult) # No native Genode application initialization, # exit as would POSIX. else: componentConstructHook(env) # Perform application initialization # and return to thread entrypoint. import system/widestrs export widestrs import system/io export io when not defined(createNimHcr): include nimhcr