diff options
Diffstat (limited to 'lib/system.nim')
-rw-r--r-- | lib/system.nim | 3010 |
1 files changed, 1464 insertions, 1546 deletions
diff --git a/lib/system.nim b/lib/system.nim index 822454626..2f9cdc5f9 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -14,7 +14,7 @@ ## ## 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 ## ============= @@ -22,57 +22,59 @@ ## .. 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. +include "system/basic_types" -# 'float64' is now an alias to 'float'; this solves many problems +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]>`_ -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. +include "system/compilation" - typedesc* {.magic: TypeDesc.} ## Meta type to denote a type description. +{.push warning[GcMem]: off, warning[Uninit]: off.} +# {.push hints: off.} 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" + `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`. -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" + `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`. -{.push warning[GcMem]: off, warning[Uninit]: off.} -{.push hints: off.} +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. + 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. @@ -83,181 +85,85 @@ proc `and`*(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.} 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 - 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 <nimc.html#compiler-usage-compile-time-symbols>`_ 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 + Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer, + ## bool, character, and enumeration types + ## as well as their subtypes. See also + ## `SomeOrdinal`. -when defined(nimHasRunnableExamples): - proc runnableExamples*(rdoccmd = "", 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 - ## runnableExamples "-d:foo -b:cpp": - ## import std/compilesettings - ## doAssert querySetting(backend) == "cpp" - ## runnableExamples "-r:off": ## this one is only compiled - ## import std/browsers - ## openDefaultBrowser "https://forum.nim-lang.org/" -else: - template runnableExamples*(doccmd = "", 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>`_ +proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = + ## Builtin `addr` operator for taking the address of a memory location. ## - ## This can be used to check whether a library provides a certain - ## feature or not: + ## .. 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. ## - ## .. 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 + ## ```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. + ## .. warning:: `unsafeAddr` is a deprecated alias for `addr`, + ## use `addr` instead. 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. +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! -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.} = + ## Generic `wasMoved`:idx: implementation that can be overridden. -proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = +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. - discard + {.cast(raises: []), cast(tags: []).}: + `=wasMoved`(obj) proc move*[T](x: var T): T {.magic: "Move", noSideEffect.} = result = x - wasMoved(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. @@ -271,72 +177,73 @@ 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 + UncheckedArray*[T]{.magic: "UncheckedArray".} + ## 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.} +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. ## - ## See also: - ## * `low(T) <#low,T>`_ + ## **This proc is deprecated**, use this one instead: + ## * `high(typedesc) <#high,typedesc[T]>`_ ## - ## .. code-block:: Nim - ## high(2) # => 9223372036854775807 + ## ```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:. + ## `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]>`_ - ## - ## .. 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`. + ## ```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]>`_ - ## - ## .. 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`. ## + ## 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]>`_ - ## - ## .. 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. ## + ## For empty arrays, the return type is `int`. + ## ```nim + ## high(array[7, int]) # => 6 + ## ``` + ## ## 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`. @@ -347,67 +254,73 @@ proc high*(x: cstring): int {.magic: "High", noSideEffect.} 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>`_ - ## - ## .. code-block:: Nim - ## var str = "Hello world!" - ## high(str) # => 11 -proc low*[T: Ordinal|enum|range](x: T): T {.magic: "Low", noSideEffect.} +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. ## - ## See also: - ## * `high(T) <#high,T>`_ + ## **This proc is deprecated**, use this one instead: + ## * `low(typedesc) <#low,typedesc[T]>`_ ## - ## .. code-block:: Nim - ## low(2) # => -9223372036854775808 + ## ```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:. + ## `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]>`_ - ## - ## .. 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`. + ## ```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]>`_ - ## - ## .. 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`. ## + ## 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]>`_ - ## - ## .. 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. ## + ## For empty arrays, the return type is `int`. + ## ```nim + ## low(array[7, int]) # => 0 + ## ``` + ## ## 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`. @@ -417,98 +330,120 @@ proc low*(x: cstring): int {.magic: "Low", noSideEffect.} 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>`_ - ## - ## .. 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 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".} -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".} +const arcLikeMem = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc) - 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".} +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 - proc `=sink`*[T](x: var T; y: T) {.inline, magic: "Asgn".} = - ## Generic `sink`:idx: implementation that can be overridden. + + 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 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]``. + 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` + ## 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 + ## ```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 +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 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 = "" + 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 \ +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) @@ -526,15 +461,11 @@ when not defined(js) and not defined(nimSeqsV2): 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): +when notJSnotNims: include "system/hti" type - byte* = uint8 ## This is an alias for ``uint8``, that is an unsigned + byte* = uint8 ## This is an alias for `uint8`, that is an unsigned ## integer, 8 bits wide. Natural* = range[0..high(int)] @@ -545,6 +476,7 @@ type ## 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. ## @@ -552,8 +484,64 @@ type ## However, objects that have no ancestor are also allowed. RootRef* = ref RootObj ## Reference to `RootObj`. +const NimStackTraceMsgs = compileOption("stacktraceMsgs") -include "system/exceptions" +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 @@ -561,10 +549,10 @@ when defined(js) or defined(nimdoc): ## 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``. + ## 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 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! ## @@ -572,195 +560,166 @@ proc unsafeNew*[T](a: var ref T, size: Natural) {.magic: "New", noSideEffect.} ## * `new <#new,ref.T,proc(ref.T)>`_ proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.} - ## Returns the size of ``x`` in bytes. + ## 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. + ## 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). + ## 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 + ## 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 + ## ```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 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.} +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](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) +template offsetOf*[T](value: T; member: untyped): int = + offsetOfDotExpr(value.member) - #proc offsetOf*(memberaccess: typed): int {.magic: "OffsetOf", noSideEffect.} +#proc offsetOf*(memberaccess: typed): int {.magic: "OffsetOf", noSideEffect.} -when defined(nimtypedescfixed): - proc sizeof*(x: typedesc): int {.magic: "SizeOf", noSideEffect.} +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``. + ## Creates a new sequence of type `seq[T]` with length `len`. ## - ## This is equivalent to ``s = @[]; setlen(s, len)``, but more + ## 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] + ## ```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``. + ## 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 + ## ```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``. - ## - ## .. code-block:: Nim + ## 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 -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.} +func len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.magic: "LengthOpenArray".} = ## Returns the length of an openArray. - ## - ## .. code-block:: Nim - ## var s = [1, 1, 1, 1, 1] - ## echo len(s) # => 5 + runnableExamples: + proc bar[T](a: openArray[T]): int = len(a) + assert bar([1,2]) == 2 + assert [1,2].len == 2 -proc len*(x: string): int {.magic: "LengthStr", noSideEffect.} +func len*(x: string): int {.magic: "LengthStr".} = ## Returns the length of a string. - ## - ## .. code-block:: Nim - ## var str = "Hello world!" - ## echo len(str) # => 12 + 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 sometimes - ## an O(n) operation. +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`. - ## - ## .. code-block:: Nim - ## var str: cstring = "Hello world!" - ## len(str) # => 12 - -proc len*(x: (type array)|array): int {.magic: "LengthArray", noSideEffect.} + 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``. - ## - ## .. 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.} + ## 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 -proc `==`*(x, y: float): bool {.magic: "EqF64", noSideEffect.} -proc `<=`*(x, y: float): bool {.magic: "LeF64", noSideEffect.} -proc `<`*(x, y: float): bool {.magic: "LtF64", noSideEffect.} +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" @@ -768,33 +727,36 @@ 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 + ## `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 -template `in`*(x, y: untyped): untyped {.dirty.} = contains(y, x) +when not defined(nimHasCallsitePragma): + {.pragma: callsite.} + +template `in`*(x, y: untyped): untyped {.dirty, callsite.} = contains(y, x) ## Sugar for `contains`. - ## - ## .. code-block:: Nim + ## ```nim ## assert(1 in (1..3) == true) ## assert(5 in (1..3) == false) -template `notin`*(x, y: untyped): untyped {.dirty.} = not contains(y, x) + ## ``` +template `notin`*(x, y: untyped): untyped {.dirty, callsite.} = not contains(y, x) ## Sugar for `not contains`. - ## - ## .. code-block:: Nim + ## ```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 + ## ```nim ## assert 42 is int ## assert @[1, 2] is seq ## @@ -806,12 +768,13 @@ proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} ## ## 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 + ## ``` +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`. @@ -820,15 +783,15 @@ else: 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``. + ## 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) + ## 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 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: @@ -837,24 +800,22 @@ when defined(nimOwnedEnabled) and not defined(nimscript): return r proc unown*[T](x: T): T {.magic: "Unown", noSideEffect.} - ## Use the expression ``x`` ignoring its ownership attribute. + ## 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``. + ## 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) + ## 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 a ref type then the resulting type will be `T`, + ## otherwise it will be `ref T`. when (t is ref): var r: t else: @@ -862,24 +823,39 @@ else: 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 + ## 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: 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 `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. @@ -891,10 +867,10 @@ proc cmp*[T](x, y: T): int = ## ## 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]) + ## ```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 @@ -905,145 +881,145 @@ proc cmp*(x, y: string): int {.noSideEffect.} ## **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 `@`* [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 default*(T: typedesc): T {.magic: "Default", noSideEffect.} - ## returns the default value of the type ``T``. +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. - 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.} +proc reset*[T](obj: var T) {.noSideEffect.} = + ## Resets an object `obj` to its default value. + when nimvm: + obj = default(typeof(obj)) else: - proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.} + 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: Natural) {. - magic: "SetLengthSeq", noSideEffect.} - ## Sets the length of seq `s` to `newlen`. ``T`` may be any sequence type. + 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. - ## - ## .. code-block:: Nim + ## `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 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!!" + ## `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]``. + ## 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``. + ## 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`. + ## 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``. + ## be achieved with the `&` operator or with `add`. proc `&`*(x: string, y: char): string {. - magic: "ConStrStr", noSideEffect, merge.} + magic: "ConStrStr", noSideEffect.} ## Concatenates `x` with `y`. - ## - ## .. code-block:: Nim + ## ```nim ## assert("ab" & 'c' == "abc") + ## ``` proc `&`*(x, y: char): string {. - magic: "ConStrStr", noSideEffect, merge.} + magic: "ConStrStr", noSideEffect.} ## Concatenates characters `x` and `y` into a string. - ## - ## .. code-block:: Nim + ## ```nim ## assert('a' & 'b' == "ab") + ## ``` proc `&`*(x, y: string): string {. - magic: "ConStrStr", noSideEffect, merge.} + magic: "ConStrStr", noSideEffect.} ## Concatenates strings `x` and `y`. - ## - ## .. code-block:: Nim + ## ```nim ## assert("ab" & "cd" == "abcd") + ## ``` proc `&`*(x: char, y: string): string {. - magic: "ConStrStr", noSideEffect, merge.} + magic: "ConStrStr", noSideEffect.} ## Concatenates `x` with `y`. - ## - ## .. code-block:: Nim + ## ```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 + ## ```nim ## var tmp = "" ## tmp.add('a') ## tmp.add('b') ## assert(tmp == "ab") -proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} + ## ``` + +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") - + ## See also `strbasics.add`. + runnableExamples: + 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 + 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. @@ -1061,7 +1037,7 @@ const ## Possible values: ## `"i386"`, `"alpha"`, `"powerpc"`, `"powerpc64"`, `"powerpc64el"`, ## `"sparc"`, `"amd64"`, `"mips"`, `"mipsel"`, `"arm"`, `"arm64"`, - ## `"mips64"`, `"mips64el"`, `"riscv64"`. + ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, `"loongarch64"`. seqShallowFlag = low(int) strlitFlag = 1 shl (sizeof(int)*8 - 2) # later versions of the codegen \ @@ -1071,12 +1047,14 @@ const 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 notJSnotNims and not defined(nimSeqsV2): + template space(s: PGenericSeq): int = + s.reserved and not (seqShallowFlag or strlitFlag) 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".} + {.error: "`--tlsEmulation:on` must be used when using threads with tcc backend".} when defined(boehmgc): when defined(windows): @@ -1087,29 +1065,16 @@ when defined(boehmgc): elif defined(macosx): const boehmLib = "libgc.dylib" elif defined(openbsd): - const boehmLib = "libgc.so.4.0" + 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.} -when taintMode: - type TaintedString* = distinct string ## A distinct string type that - ## is `tainted`:idx:, see `taint mode - ## <manual_experimental.html#taint-mode>`_ - ## for details. It is an alias for - ## ``string`` if the taint mode is not - ## turned on. +when not defined(nimPreviewSlimSystem): + type TaintedString* {.deprecated: "Deprecated since 1.5".} = string - proc len*(s: TaintedString): int {.borrow.} -else: - type TaintedString* = string ## A distinct string type that - ## is `tainted`:idx:, see `taint mode - ## <manual_experimental.html#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.} @@ -1127,14 +1092,13 @@ const ## 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": +when not defined(js) and hostOS != "standalone": var programResult* {.compilerproc, exportc: "nim_program_result".}: int - ## deprecated, prefer ``quit`` + ## deprecated, prefer `quit` or `exitprocs.getProgramResult`, `exitprocs.setProgramResult`. import std/private/since +import system/ctypes +export ctypes proc align(address, alignment: int): int = if alignment == 0: # Actually, this is illegal. This branch exists to actively @@ -1143,49 +1107,9 @@ proc align(address, alignment: int): int = 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 "exit procedures" are called in the - ## opposite order they were added with `addExitProc <exitprocs.html#addExitProc,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 <manual.html#pragmas-error-pragma>`_ or `fatal - ## <manual.html#pragmas-fatal-pragma>`_ 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: "<base/sleep.h>".} - - 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: "<stdlib.h>", noreturn.} - +include system/rawquits +when defined(genode): + export GenodeEnv template sysAssert(cond: bool, msg: string) = when defined(useSysAssert): @@ -1193,12 +1117,10 @@ template sysAssert(cond: bool, msg: string) = cstderr.rawWrite "[SYSASSERT] " cstderr.rawWrite msg cstderr.rawWrite "\n" - quit 1 + rawQuit 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.} @@ -1210,243 +1132,254 @@ when defined(nimscript) or not defined(nimSeqsV2): ## 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] -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) = + template movingCopy(a, b: typed) = a = move(b) else: - template movingCopy(a, b) = + 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`. + ## 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] + ## * `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 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: + ## ```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() - x[i] = item + 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. - ## - ## .. 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. + ## ```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. -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. +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 `isNaN` or `classify` procedure + ## in the `math module <math.html>`_ for checking for NaN. -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 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``. + ## 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. ## - ## .. code-block:: Nim + ## ```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``. + ## 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``. + ## 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>`_. + ## <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. - ## - ## .. code-block:: Nim + ## ```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``. + ## 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: "<stdlib.h>", deprecated: "use exitprocs.addExitProc".} - ## Adds/registers a quit procedure. +proc `/`*(x, y: int): float {.inline, noSideEffect.} = + ## Division of integers that results in a float. + ## ```nim + ## echo 7 / 5 # => 1.4 + ## ``` ## - ## 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. + ## See also: + ## * `div <system.html#div,int,int>`_ + ## * `mod <system.html#mod,int,int>`_ + result = toFloat(x) / toFloat(y) -# 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. +{.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. 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``. + ## This is often more efficient than `tmp = a; a = b; b = tmp`. ## Particularly useful for sorting algorithms. ## - ## .. code-block:: Nim + ## ```nim ## var ## a = 5 ## b = 9 @@ -1455,6 +1388,7 @@ proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.} ## ## 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) = @@ -1463,18 +1397,16 @@ when not defined(js) and not defined(booting) and defined(nimTrMacros): # 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 <math.html>`_ for checking for NaN. +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" @@ -1484,78 +1416,40 @@ 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 + ## ```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".} +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``. - + ## `== 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(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): @@ -1564,12 +1458,12 @@ when defined(nimSeqsV2): ## 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][T],openArray[T]>`_ - ## - ## .. code-block:: Nim - ## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6]) + ## * `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]) @@ -1580,12 +1474,12 @@ when defined(nimSeqsV2): ## 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][T],T>`_ - ## - ## .. code-block:: Nim - ## assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4]) + ## * `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]) @@ -1595,9 +1489,9 @@ when defined(nimSeqsV2): ## Prepends the element x to the beginning of the sequence. ## ## Requires copying of the sequence. - ## - ## .. code-block:: Nim + ## ```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: @@ -1609,12 +1503,12 @@ else: ## 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][T],openArray[T]>`_ - ## - ## .. code-block:: Nim - ## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6]) + ## * `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] @@ -1625,12 +1519,12 @@ else: ## 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][T],T>`_ - ## - ## .. code-block:: Nim - ## assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4]) + ## * `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] @@ -1640,19 +1534,15 @@ else: ## Prepends the element x to the beginning of the sequence. ## ## Requires copying of the sequence. - ## - ## .. code-block:: Nim + ## ```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 @@ -1661,12 +1551,12 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[ ## 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) + ## 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 + ## ```nim + ## import std/strutils ## ## template testException(exception, code: untyped): typed = ## try: @@ -1687,78 +1577,160 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[ ## 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" + 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" + import std/private/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 + TNimTypeV2 {.compilerproc.} = object destructor: pointer size: int - align: int - name: cstring + align: int16 + depth: int16 + display: ptr UncheckedArray[uint32] # classToken + when defined(nimTypeNames) or defined(nimArcIds): + name: cstring traceImpl: pointer - disposeImpl: pointer - PNimType = ptr TNimType + 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 notJSnotNims: +when not defined(nimscript): proc writeStackTrace*() {.tags: [], gcsafe, raises: [].} - ## Writes the current stack trace to ``stderr``. This is only works + ## 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" +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. - {.pop.} +when defined(nimV2): + var + framePtr {.threadvar.}: PFrame + include system/arc -when defined(nimV2): - include system/refs_v2 +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) -import system/assertions -export assertions +when not defined(nimPreviewSlimSystem): + import std/assertions + export assertions import system/iterators export iterators @@ -1775,21 +1747,23 @@ proc find*[T, S](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`. - ## - ## .. code-block:: Nim + ## ```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 + ## 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) @@ -1805,14 +1779,14 @@ proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} = setLen(s, L) proc `==`*[T: tuple|object](x, y: T): bool = - ## Generic ``==`` operator for tuples that is lifted from the components. + ## 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 + ## 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) @@ -1821,7 +1795,7 @@ proc `<=`*[T: tuple](x, y: T): bool = return true proc `<`*[T: tuple](x, y: T): bool = - ## Generic lexicographic ``<`` operator for tuples that is lifted from the + ## 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) @@ -1835,25 +1809,7 @@ 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 +import system/coro_detection {.push checks: off.} # obviously we cannot generate checking operations here :-) @@ -1861,79 +1817,78 @@ else: # 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. +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. - 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` + 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. -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. + 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): +when defined(js) or defined(nimdoc): proc add*(x: var string, y: cstring) {.asmNoStackFrame.} = - asm """ + ## 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".} + """.} + 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.} @@ -1945,45 +1900,32 @@ elif hasAlloc: 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 - ## <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>`_. -else: - proc echo*(x: varargs[untyped, `$`]) {.magic: "Echo", tags: [WriteIOEffect], - benign, sideEffect.} - proc debugEcho*(x: varargs[untyped, `$`]) {.magic: "Echo", noSideEffect, - tags: [], raises: [].} +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. -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) +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 = cstring(addr s.data) + else: result = cast[cstring](addr s.data) proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", benign.} ## Get type information for `x`. @@ -1991,22 +1933,6 @@ proc getTypeInfo*[T](x: T): pointer {.magic: "GetTypeInfo", benign.} ## Ordinary code should not use this, but the `typeinfo module ## <typeinfo.html>`_ 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): @@ -2019,13 +1945,13 @@ template likely*(val: bool): bool = ## 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 + ## ```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. @@ -2043,13 +1969,13 @@ template unlikely*(val: bool): bool = ## 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 + ## ```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. @@ -2061,38 +1987,49 @@ template unlikely*(val: bool): bool = 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 std/private/since +import system/dollars +export dollars - NimMinor* {.intdefine.}: int = 3 - ## is the minor number of Nim's version. - ## Odd for devel, even for releases. +when defined(nimAuditDelete): + {.pragma: auditDelete, deprecated: "review this call for out of bounds behavior".} +else: + {.pragma: auditDelete.} - NimPatch* {.intdefine.}: int = 5 - ## is the patch number of Nim's version. - ## Odd for devel, even for releases. +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] -import system/dollars -export dollars + 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") -const - NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch - ## is the version of Nim as a string. + 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() -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 +const + NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch + ## is the version of Nim as a string. when not defined(js): {.push stackTrace: off, profiler: off.} @@ -2145,8 +2082,11 @@ when notJSnotNims: 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): +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 @@ -2161,14 +2101,16 @@ when not defined(js): 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``. + ## 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``. + ## 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) @@ -2193,7 +2135,7 @@ when not defined(js) and declared(alloc0) and declared(dealloc): inc(i) dealloc(a) -when notJSnotNims: +when notJSnotNims and not gotoBasedExceptions: type PSafePoint = ptr TSafePoint TSafePoint {.compilerproc, final.} = object @@ -2206,7 +2148,12 @@ when not defined(js): when declared(initAllocator): initAllocator() when hasThreadSupport: - when hostOS != "standalone": include "system/threads" + 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() @@ -2215,6 +2162,16 @@ 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) + ## ``` when not defined(noSignalHandler) and not defined(useNimRtl): proc unsetControlCHook*() @@ -2226,7 +2183,7 @@ when notJSnotNims: 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. + ## lead to the `raise` statement. This only works for debug builds. {.push stackTrace: off, profiler: off.} when defined(memtracker): @@ -2240,10 +2197,7 @@ when notJSnotNims: # we cannot compile this with stack tracing on # as it would recurse endlessly! - when defined(nimNewIntegerOps): - include "system/integerops" - else: - include "system/arithm" + include "system/integerops" {.pop.} @@ -2256,8 +2210,19 @@ when not defined(js): 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" when defined(gogc): @@ -2265,29 +2230,28 @@ when notJSnotNims: 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: - d = 0'u - 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] + 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: + d = 0'u + 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.} @@ -2299,13 +2263,14 @@ when notJSnotNims and hasAlloc: {.pop.} include "system/strmantle" - when not usesDestructors: - include "system/assign" + include "system/assign" + when not defined(nimV2): include "system/repr" when notJSnotNims and hasThreadSupport and hostOS != "standalone": - include "system/channels" + when not defined(nimPreviewSlimSystem): + include "system/channels_builtin" when notJSnotNims and hostOS != "standalone": @@ -2326,9 +2291,10 @@ when notJSnotNims and hostOS != "standalone": proc setCurrentException*(exc: ref Exception) {.inline, benign.} = ## Sets the current exception. ## - ## **Warning**: Only use this if you know what you are doing. + ## .. 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.} @@ -2336,45 +2302,135 @@ when notJSnotNims: include "system/profiler" {.pop.} - proc rawProc*[T: proc](x: T): pointer {.noSideEffect, inline.} = + 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. + ## 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` = `x`.ClP_0; + `result` = (void*)`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. + 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: proc](x: T): bool {.noSideEffect, inline.} = - ## can be used to determine if a first class iterator has finished. +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; """.} -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 +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>`_. -when defined(js) or defined(nimscript): - proc addInt*(result: var string; x: int64) = - result.add $x +elif defined(genode): + proc quit*(errorcode: int = QuitSuccess) {.inline, noreturn.} = + rawQuit(errorcode) - proc addFloat*(result: var string; x: float) = - result.add $x +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)``. + ## A shorthand for `echo(errormsg); quit(errorcode)`. when defined(nimscript) or defined(js) or (hostOS == "standalone"): echo errormsg else: @@ -2386,315 +2442,57 @@ proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} = 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..<L: s[i+a] = b[i] - else: - spliceImpl(s, a, L, b) - -proc `[]`*[Idx, T, U, V](a: array[Idx, T], x: HSlice[U, V]): seq[T] = - ## Slice operation for arrays. - ## Returns the inclusive range `[a[x.a], a[x.b]]`: - ## - ## .. code-block:: Nim - ## var a = [1, 2, 3, 4] - ## assert a[0..2] == @[1, 2, 3] - let xa = a ^^ x.a - let L = (a ^^ x.b) - xa + 1 - result = newSeq[T](L) - for i in 0..<L: result[i] = a[Idx(i + xa)] - -proc `[]=`*[Idx, T, U, V](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) = - ## Slice assignment for arrays. - ## - ## .. code-block:: Nim - ## var a = [10, 20, 30, 40, 50] - ## a[1..2] = @[99, 88] - ## assert a == [10, 99, 88, 40, 50] - let xa = a ^^ x.a - let L = (a ^^ x.b) - xa + 1 - if L == b.len: - for i in 0..<L: a[Idx(i + xa)] = b[i] - else: - sysFatal(RangeDefect, "different lengths for slice assignment") - -proc `[]`*[T, U, V](s: openArray[T], x: HSlice[U, V]): seq[T] = - ## Slice operation for sequences. - ## Returns the inclusive range `[s[x.a], s[x.b]]`: - ## - ## .. code-block:: Nim - ## var s = @[1, 2, 3, 4] - ## assert s[0..2] == @[1, 2, 3] - let a = s ^^ x.a - let L = (s ^^ x.b) - a + 1 - newSeq(result, L) - for i in 0 ..< L: result[i] = s[i + a] - -proc `[]=`*[T, U, V](s: var seq[T], x: HSlice[U, V], b: openArray[T]) = - ## Slice assignment for sequences. - ## - ## 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" - - let a = s ^^ x.a - let L = (s ^^ x.b) - a + 1 - if L == b.len: - for i in 0 ..< L: s[i+a] = b[i] - else: - spliceImpl(s, a, L, b) - -proc `[]`*[T](s: openArray[T]; i: BackwardsIndex): T {.inline.} = - system.`[]`(s, s.len - int(i)) - -proc `[]`*[Idx, T](a: array[Idx, T]; i: BackwardsIndex): T {.inline.} = - a[Idx(a.len - int(i) + int low(a))] -proc `[]`*(s: string; i: BackwardsIndex): char {.inline.} = s[s.len - int(i)] - -proc `[]`*[T](s: var openArray[T]; i: BackwardsIndex): var T {.inline.} = - system.`[]`(s, s.len - int(i)) -proc `[]`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex): var T {.inline.} = - a[Idx(a.len - int(i) + int low(a))] - -proc `[]=`*[T](s: var openArray[T]; i: BackwardsIndex; x: T) {.inline.} = - system.`[]=`(s, s.len - int(i), x) -proc `[]=`*[Idx, T](a: var array[Idx, T]; i: BackwardsIndex; x: T) {.inline.} = - a[Idx(a.len - int(i) + int low(a))] = x -proc `[]=`*(s: var string; i: BackwardsIndex; x: char) {.inline.} = - s[s.len - int(i)] = x - -proc slurp*(filename: string): string {.magic: "Slurp".} - ## This is an alias for `staticRead <#staticRead,string>`_. - -proc staticRead*(filename: string): string {.magic: "Slurp".} - ## Compile-time `readFile <io.html#readFile,string>`_ 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 <manual.html#implementation-specific-pragmas-passc-pragma>`_ or - ## `passl <manual.html#implementation-specific-pragmas-passl-pragma>`_. - ## - ## 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 +# {.pop.} # hints: off -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 +include "system/indices" proc `&=`*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} ## Appends in place to a string. - ## - ## .. code-block:: Nim + ## ```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``. + ## 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() <os.html#parentDir%2Cstring>`_ as ``currentSourcePath.parentDir()``. - ## - ## The path returned by this template is set at compile time. - ## - ## See the docstring of `macros.getProjectPath() <macros.html#getProjectPath>`_ - ## for an example to see the distinction between the ``currentSourcePath`` - ## and ``getProjectPath``. - ## - ## See also: - ## * `getCurrentDir proc <os.html#getCurrentDir>`_ when compileOption("rangechecks"): template rangeCheck*(cond) = ## Helper for performing user-defined range checks. - ## Such checks will be performed only when the ``rangechecks`` + ## 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 +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 @@ -2702,36 +2500,47 @@ type 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 +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 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 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`. - ## - ## .. code-block:: Nim + ## ```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: - shallowCopy(x[j+item.len], x[j]) + 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: @@ -2744,32 +2553,33 @@ when declared(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. + ## * 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. ## - ## **Note**: This is **not correct** for producing Ansi C code! + ## .. 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 '\L': s.add "\\n" # \x0A + of '\n': s.add "\\n" # \x0A of '\v': s.add "\\v" # \x0B of '\f': s.add "\\f" # \x0C - of '\c': s.add "\\c" # \x0D + 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("\\'") @@ -2788,9 +2598,9 @@ proc addQuoted*[T](s: var string, x: T) = ## ## 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 + ## range `{\128..\255}` are never escaped so that multibyte UTF-8 ## characters are untouched (note that this behavior is different from - ## ``addEscapedChar``). + ## `addEscapedChar`). ## ## The Nim standard library uses this function on the elements of ## collections when producing a string representation of a collection. @@ -2798,7 +2608,7 @@ proc addQuoted*[T](s: var string, x: T) = ## Users may overload `addQuoted` for custom (string-like) types if ## they want to implement a customized element representation. ## - ## .. code-block:: Nim + ## ```nim ## var tmp = "" ## tmp.addQuoted(1) ## tmp.add(", ") @@ -2806,6 +2616,7 @@ proc addQuoted*[T](s: var string, x: T) = ## tmp.add(", ") ## tmp.addQuoted('c') ## assert(tmp == """1, "string", 'c'""") + ## ``` when T is string or T is cstring: s.add("\"") for c in x: @@ -2821,7 +2632,7 @@ proc addQuoted*[T](s: var string, x: T) = s.addEscapedChar(x) s.add("'") # prevent temporary string allocation - elif T is SomeSignedInt: + elif T is SomeInteger: s.addInt(x) elif T is SomeFloat: s.addFloat(x) @@ -2836,10 +2647,10 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} = ## ## 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 + ## 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 + ## ```nim ## proc testLocals() = ## var ## a = "something" @@ -2854,15 +2665,19 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} = ## # -> name a with value something ## # -> name b with value 4 ## # -> B is 1 + ## ``` discard -when hasAlloc and notJSnotNims and not usesDestructors: +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 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 = @@ -2874,10 +2689,10 @@ when hasAlloc and notJSnotNims and not usesDestructors: 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 + ## ```nim ## # 'someMethod' will be resolved fully statically: ## procCall someMethod(a, b) + ## ``` discard @@ -2887,33 +2702,19 @@ proc `==`*(x, y: cstring): bool {.magic: "EqCString", noSideEffect, proc strcmp(a, b: cstring): cint {.noSideEffect, importc, header: "<string.h>".} if pointer(x) == pointer(y): result = true - elif x.isNil or y.isNil: result = false + elif pointer(x) == nil or pointer(y) == nil: 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 <sugar.html#capture.m,openArray[typed],untyped>`_ instead. + ## `capture <sugar.html#capture.m,varargs[typed],untyped>`_ instead. ## ## Example: ## - ## .. code-block:: Nim + ## ```nim ## var myClosure : proc() ## # without closureScope: ## for i in 0 .. 5: @@ -2928,20 +2729,19 @@ template closureScope*(body: untyped): untyped = ## 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) - ## + ## ```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 @@ -2949,14 +2749,26 @@ template once*(body: untyped): untyped = {.pop.} # warning[GcMem]: off, warning[Uninit]: off -proc substr*(s: string, first, last: int): string = +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: + ## 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" @@ -2979,14 +2791,25 @@ when defined(nimconfig): 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*(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] {. @@ -3001,10 +2824,8 @@ proc toOpenArrayByte*(x: openArray[char]; first, last: int): openArray[byte] {. 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" <manual.html#macros-for-loop-macro>`_. +proc toOpenArrayChar*(x: openArray[byte]; first, last: int): openArray[char] {. + magic: "Slice".} when defined(genode): var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.} @@ -3012,13 +2833,13 @@ when defined(genode): ## ## 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 + ## 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. + ## Procedure called during `Component::construct` by the loader. if componentConstructHook.isNil: - env.quit(programResult) + env.rawQuit(programResult) # No native Genode application initialization, # exit as would POSIX. else: @@ -3027,11 +2848,108 @@ when defined(genode): # and return to thread entrypoint. -import system/widestrs -export widestrs +when not defined(nimPreviewSlimSystem): + import std/widestrs + export widestrs -import system/io -export io +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 |