diff options
Diffstat (limited to 'lib/system.nim')
-rw-r--r-- | lib/system.nim | 639 |
1 files changed, 395 insertions, 244 deletions
diff --git a/lib/system.nim b/lib/system.nim index 8faf8f4ce..2f9cdc5f9 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -25,7 +25,11 @@ include "system/basic_types" func zeroDefault*[T](_: typedesc[T]): T {.magic: "ZeroDefault".} = - ## returns the default value of the type `T`. + ## Returns the binary zeros representation of the type `T`. It ignores + ## default fields of an object. + ## + ## See also: + ## * `default <#default,typedesc[T]>`_ include "system/compilation" @@ -62,11 +66,11 @@ proc typeof*(x: untyped; mode = typeOfIter): typedesc {. doAssert type(myFoo()) is string doAssert typeof(myFoo()) is string doAssert typeof(myFoo(), typeOfIter) is string - doAssert typeof(myFoo3) is "iterator" + 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 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 @@ -85,17 +89,12 @@ when defined(nimHasIterable): type iterable*[T] {.magic: IterableType.} ## Represents an expression that yields `T` -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 < 1.2.0 - type - OrdinalImpl[T] {.magic: Ordinal.} - Ordinal* = OrdinalImpl | uint | uint64 +type + Ordinal*[T] {.magic: Ordinal.} ## Generic ordinal type. Includes integer, + ## bool, character, and enumeration types + ## as well as their subtypes. See also + ## `SomeOrdinal`. + proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = ## Builtin `addr` operator for taking the address of a memory location. @@ -109,7 +108,7 @@ proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = ## ## Cannot be overloaded. ## - ## ``` + ## ```nim ## var ## buf: seq[char] = @['a','b','c'] ## p = buf[1].addr @@ -126,9 +125,6 @@ proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = 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) @@ -142,15 +138,32 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. ## **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.} = +proc `=wasMoved`*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = + ## Generic `wasMoved`:idx: implementation that can be overridden. + +proc wasMoved*[T](obj: var T) {.inline, noSideEffect.} = ## Resets an object `obj` to its initial (binary zero) value to signify ## it was "moved" and to signify its destructor should do nothing and ## ideally be optimized away. - 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. @@ -180,7 +193,7 @@ proc high*[T: Ordinal|enum|range](x: T): T {.magic: "High", noSideEffect, ## **This proc is deprecated**, use this one instead: ## * `high(typedesc) <#high,typedesc[T]>`_ ## - ## ``` + ## ```nim ## high(2) # => 9223372036854775807 ## ``` @@ -188,7 +201,7 @@ proc high*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "High", noSideEffe ## Returns the highest possible value of an ordinal or enum type. ## ## `high(int)` is Nim's way of writing `INT_MAX`:idx: or `MAX_INT`:idx:. - ## ``` + ## ```nim ## high(int) # => 9223372036854775807 ## ``` ## @@ -197,7 +210,7 @@ proc high*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "High", noSideEffe 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): @@ -211,7 +224,7 @@ 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): @@ -225,7 +238,7 @@ 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 ## ``` ## @@ -241,7 +254,7 @@ 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 ## ``` @@ -257,7 +270,7 @@ proc low*[T: Ordinal|enum|range](x: T): T {.magic: "Low", noSideEffect, ## **This proc is deprecated**, use this one instead: ## * `low(typedesc) <#low,typedesc[T]>`_ ## - ## ``` + ## ```nim ## low(2) # => -9223372036854775808 ## ``` @@ -265,7 +278,7 @@ proc low*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "Low", noSideEffect ## Returns the lowest possible value of an ordinal or enum type. ## ## `low(int)` is Nim's way of writing `INT_MIN`:idx: or `MIN_INT`:idx:. - ## ``` + ## ```nim ## low(int) # => -9223372036854775808 ## ``` ## @@ -274,7 +287,7 @@ proc low*[T: Ordinal|enum|range](x: typedesc[T]): T {.magic: "Low", noSideEffect 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): @@ -288,7 +301,7 @@ 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): @@ -302,7 +315,7 @@ 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 ## ``` ## @@ -317,7 +330,7 @@ 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 ## ``` @@ -325,7 +338,7 @@ proc low*(x: string): int {.magic: "Low", noSideEffect.} ## See also: ## * `high(string) <#high,string>`_ -when not defined(gcArc) and not defined(gcOrc): +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:. ## @@ -349,12 +362,36 @@ proc arrGet[I: Ordinal;T](a: T; i: I): T {. proc arrPut[I: Ordinal;T,S](a: T; i: I; x: S) {.noSideEffect, magic: "ArrPut".} -proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = - ## Generic `destructor`:idx: implementation that can be overridden. - discard +const arcLikeMem = defined(gcArc) or defined(gcAtomicArc) or defined(gcOrc) + + +when defined(nimAllowNonVarDestructor) and arcLikeMem and defined(nimPreviewNonVarDestructor): + proc `=destroy`*[T](x: T) {.inline, magic: "Destroy".} = + ## Generic `destructor`:idx: implementation that can be overridden. + discard +else: + proc `=destroy`*[T](x: var T) {.inline, magic: "Destroy".} = + ## Generic `destructor`:idx: implementation that can be overridden. + discard + + when defined(nimAllowNonVarDestructor) and arcLikeMem: + proc `=destroy`*(x: string) {.inline, magic: "Destroy", enforceNoRaises.} = + discard + + proc `=destroy`*[T](x: seq[T]) {.inline, magic: "Destroy".} = + discard + + proc `=destroy`*[T](x: ref T) {.inline, magic: "Destroy".} = + discard + +when defined(nimHasDup): + proc `=dup`*[T](x: T): T {.inline, magic: "Dup".} = + ## Generic `dup`:idx: implementation that can be overridden. + discard + proc `=sink`*[T](x: var T; y: T) {.inline, nodestroy, magic: "Asgn".} = ## Generic `sink`:idx: implementation that can be overridden. - when defined(gcArc) or defined(gcOrc): + when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc): x = y else: shallowCopy(x, y) @@ -376,7 +413,7 @@ proc `..`*[T, U](a: sink T, b: sink U): HSlice[T, U] {.noSideEffect, inline, mag ## ## Slices can also be used in the set constructor and in ordinal case ## statements, but then they are special-cased by the compiler. - ## ``` + ## ```nim ## let a = [10, 20, 30, 40, 50] ## echo a[2 .. 3] # @[30, 40] ## ``` @@ -385,7 +422,7 @@ proc `..`*[T, U](a: sink T, b: sink U): HSlice[T, U] {.noSideEffect, inline, mag 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] ## ``` @@ -424,10 +461,6 @@ 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: include "system/hti" @@ -451,9 +484,7 @@ type ## However, objects that have no ancestor are also allowed. RootRef* = ref RootObj ## Reference to `RootObj`. -const NimStackTraceMsgs = - when defined(nimHasStacktraceMsgs): compileOption("stacktraceMsgs") - else: false +const NimStackTraceMsgs = compileOption("stacktraceMsgs") type RootEffect* {.compilerproc.} = object of RootObj ## \ @@ -542,7 +573,7 @@ proc sizeof*[T](x: T): int {.magic: "SizeOf", noSideEffect.} ## sizeof should fallback to the `sizeof` in the C compiler. The ## result isn't available for the Nim compiler and therefore can't ## be used inside of macros. - ## ``` + ## ```nim ## sizeof('A') # => 1 ## sizeof(2) # => 8 ## ``` @@ -573,7 +604,7 @@ proc newSeq*[T](s: var seq[T], len: Natural) {.magic: "NewSeq", noSideEffect.} ## Note that the sequence will be filled with zeroed entries. ## After the creation of the sequence you should assign entries to ## the sequence instead of adding them. Example: - ## ``` + ## ```nim ## var inputStrings: seq[string] ## newSeq(inputStrings, 3) ## assert len(inputStrings) == 3 @@ -589,7 +620,7 @@ proc newSeq*[T](len = 0.Natural): seq[T] = ## Note that the sequence will be filled with zeroed entries. ## After the creation of the sequence you should assign entries to ## the sequence instead of adding them. - ## ``` + ## ```nim ## var inputStrings = newSeq[string](3) ## assert len(inputStrings) == 3 ## inputStrings[0] = "The fourth" @@ -600,14 +631,14 @@ proc newSeq*[T](len = 0.Natural): seq[T] = ## ## See also: ## * `newSeqOfCap <#newSeqOfCap,Natural>`_ - ## * `newSeqUninitialized <#newSeqUninitialized,Natural>`_ + ## * `newSeqUninit <#newSeqUninit,Natural>`_ newSeq(result, len) proc newSeqOfCap*[T](cap: Natural): seq[T] {. magic: "NewSeqOfCap", noSideEffect.} = ## Creates a new sequence of type `seq[T]` with length zero and capacity ## `cap`. Example: - ## ``` + ## ```nim ## var x = newSeqOfCap[int](5) ## assert len(x) == 0 ## x.add(10) @@ -615,26 +646,6 @@ proc newSeqOfCap*[T](cap: Natural): seq[T] {. ## ``` 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. - ## Example: - ## ``` - ## 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 len*[TOpenArray: openArray|varargs](x: TOpenArray): int {.magic: "LengthOpenArray".} = ## Returns the length of an openArray. runnableExamples: @@ -717,7 +728,7 @@ include "system/setops" proc contains*[U, V, W](s: HSlice[U, V], value: W): bool {.noSideEffect, inline.} = ## Checks if `value` is within the range of `s`; returns true if ## `value >= s.a and value <= s.b`. - ## ``` + ## ```nim ## assert((1..3).contains(1) == true) ## assert((1..3).contains(2) == true) ## assert((1..3).contains(4) == false) @@ -729,13 +740,13 @@ when not defined(nimHasCallsitePragma): template `in`*(x, y: untyped): untyped {.dirty, callsite.} = contains(y, x) ## Sugar for `contains`. - ## ``` + ## ```nim ## assert(1 in (1..3) == true) ## assert(5 in (1..3) == false) ## ``` template `notin`*(x, y: untyped): untyped {.dirty, callsite.} = not contains(y, x) ## Sugar for `not contains`. - ## ``` + ## ```nim ## assert(1 notin (1..3) == false) ## assert(5 notin (1..3) == true) ## ``` @@ -745,7 +756,7 @@ proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} ## ## For a negated version, use `isnot <#isnot.t,untyped,untyped>`_. ## - ## ``` + ## ```nim ## assert 42 is int ## assert @[1, 2] is seq ## @@ -760,7 +771,7 @@ proc `is`*[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} ## ``` 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 ## ``` @@ -856,7 +867,7 @@ proc cmp*[T](x, y: T): int = ## ## This is useful for writing generic algorithms without performance loss. ## This generic implementation uses the `==` and `<` operators. - ## ``` + ## ```nim ## import std/algorithm ## echo sorted(@[4, 2, 6, 5, 8, 7], cmp[int]) ## ``` @@ -877,7 +888,7 @@ proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {.magic: "ArrToSeq", noSideEff ## 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" @@ -887,35 +898,39 @@ proc `@`* [IDX, T](a: sink array[IDX, T]): seq[T] {.magic: "ArrToSeq", noSideEff ## ``` proc default*[T](_: typedesc[T]): T {.magic: "Default", noSideEffect.} = - ## returns the default value of the type `T`. - runnableExamples: + ## 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) - # note: `var a = default(T)` is usually the same as `var a: T` and (currently) generates - # a value whose binary representation is all 0, regardless of whether this - # would violate type constraints such as `range`, `not nil`, etc. This - # property is required to implement certain algorithms efficiently which - # may require intermediate invalid states. type Foo = object a: range[2..6] - var a1: range[2..6] # currently, this compiles - # var a2: Foo # currently, this errors: Error: The Foo type doesn't have a default value. - # var a3 = Foo() # ditto - var a3 = Foo.default # this works, but generates a `UnsafeDefault` warning. - # note: the doc comment also explains why `default` can't be implemented - # via: `template default*[T](t: typedesc[T]): T = (var v: T; v)` + 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)) + when nimvm: + obj = default(typeof(obj)) + else: + when defined(gcDestructors): + {.cast(noSideEffect), cast(raises: []), cast(tags: []).}: + `=destroy`(obj) + `=wasMoved`(obj) + else: + obj = default(typeof(obj)) proc setLen*[T](s: var seq[T], newlen: Natural) {. - magic: "SetLengthSeq", noSideEffect.} + 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. - ## ``` + ## ```nim ## var x = @[10, 20] ## x.setLen(5) ## x[4] = 50 @@ -930,7 +945,7 @@ proc setLen*(s: var string, newlen: Natural) {. ## ## If the current length is greater than the new length, ## `s` will be truncated. - ## ``` + ## ```nim ## var myS = "Nim is great!!" ## myS.setLen(3) # myS <- "Nim" ## echo myS, " is fantastic!!" @@ -938,8 +953,8 @@ proc setLen*(s: var string, newlen: Natural) {. 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 + ## 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; @@ -955,25 +970,25 @@ proc newStringOfCap*(cap: Natural): string {. proc `&`*(x: string, y: char): string {. magic: "ConStrStr", noSideEffect.} ## Concatenates `x` with `y`. - ## ``` + ## ```nim ## assert("ab" & 'c' == "abc") ## ``` proc `&`*(x, y: char): string {. magic: "ConStrStr", noSideEffect.} ## Concatenates characters `x` and `y` into a string. - ## ``` + ## ```nim ## assert('a' & 'b' == "ab") ## ``` proc `&`*(x, y: string): string {. magic: "ConStrStr", noSideEffect.} ## Concatenates strings `x` and `y`. - ## ``` + ## ```nim ## assert("ab" & "cd" == "abcd") ## ``` proc `&`*(x: char, y: string): string {. magic: "ConStrStr", noSideEffect.} ## Concatenates `x` with `y`. - ## ``` + ## ```nim ## assert('a' & "bc" == "abc") ## ``` @@ -982,7 +997,7 @@ proc `&`*(x: char, y: string): string {. proc add*(x: var string, y: char) {.magic: "AppendStrCh", noSideEffect.} ## Appends `y` to `x` in place. - ## ``` + ## ```nim ## var tmp = "" ## tmp.add('a') ## tmp.add('b') @@ -1022,7 +1037,7 @@ const ## Possible values: ## `"i386"`, `"alpha"`, `"powerpc"`, `"powerpc64"`, `"powerpc64el"`, ## `"sparc"`, `"amd64"`, `"mips"`, `"mipsel"`, `"arm"`, `"arm64"`, - ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, '"loongarch64"'. + ## `"mips64"`, `"mips64el"`, `"riscv32"`, `"riscv64"`, `"loongarch64"`. seqShallowFlag = low(int) strlitFlag = 1 shl (sizeof(int)*8 - 2) # later versions of the codegen \ @@ -1033,6 +1048,10 @@ const hasThreadSupport = compileOption("threads") and not defined(nimscript) hasSharedHeap = defined(boehmgc) or defined(gogc) # don't share heaps; every thread has its own +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".} @@ -1088,31 +1107,9 @@ proc align(address, alignment: int): int = else: result = (address + (alignment - 1)) and not (alignment - 1) -when defined(nimNoQuit): - proc rawQuit(errorcode: int = QuitSuccess) = discard "ignoring quit" - -elif defined(genode): - import genode/env - - var systemEnv {.exportc: runtimeEnvSym.}: GenodeEnvPtr - - type GenodeEnv* = GenodeEnvPtr - ## Opaque type representing Genode environment. - - proc rawQuit(env: GenodeEnv; errorcode: int) {.magic: "Exit", noreturn, - importcpp: "#->parent().exit(@); Genode::sleep_forever()", header: "<base/sleep.h>".} - - proc rawQuit(errorcode: int = QuitSuccess) {.inline, noreturn.} = - systemEnv.rawQuit(errorcode) - - -elif defined(js) and defined(nodejs) and not defined(nimscript): - proc rawQuit(errorcode: int = QuitSuccess) {.magic: "Exit", - importc: "process.exit", noreturn.} - -else: - proc rawQuit(errorcode: cint) {. - 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): @@ -1124,8 +1121,6 @@ template sysAssert(cond: bool, msg: string) = 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.} @@ -1137,6 +1132,11 @@ 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.} = @@ -1146,7 +1146,7 @@ when false: # defined(gcDestructors): ## 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] ## ``` @@ -1171,13 +1171,17 @@ else: ## containers should also call their adding proc `add` for consistency. ## Generic code becomes much easier to write if the Nim naming scheme is ## respected. - ## ``` - ## var s: seq[string] = @["test2","test2"] - ## s.add("test") # s <- @[test2, test2, test] - ## ``` ## ## 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) @@ -1208,7 +1212,7 @@ proc del*[T](x: var seq[T], i: Natural) {.noSideEffect.} = proc insert*[T](x: var seq[T], item: sink T, i = 0.Natural) {.noSideEffect.} = ## Inserts `item` into `x` at position `i`. - ## ``` + ## ```nim ## var i = @[1, 3, 5] ## i.insert(99, 0) # i <- @[99, 1, 3, 5] ## ``` @@ -1239,7 +1243,7 @@ when not defined(nimV2): ## ## It works even for complex data graphs with cycles. This is a great ## debugging tool. - ## ``` + ## ```nim ## var s: seq[string] = @["test2", "test2"] ## var i = @[1, 2, 3, 4, 5] ## echo repr(s) # => 0x1055eb050[0x1055ec050"test2", 0x1055ec078"test2"] @@ -1272,7 +1276,7 @@ proc toFloat*(i: int): float {.noSideEffect, inline.} = ## If the conversion fails, `ValueError` is raised. ## However, on most platforms the conversion cannot fail. ## - ## ``` + ## ```nim ## let ## a = 2 ## b = 3.7 @@ -1295,7 +1299,7 @@ proc toInt*(f: float): int {.noSideEffect.} = ## ## Note that some floating point numbers (e.g. infinity or even 1e19) ## cannot be accurately converted. - ## ``` + ## ```nim ## doAssert toInt(0.49) == 0 ## doAssert toInt(0.5) == 1 ## doAssert toInt(-0.5) == -1 # rounding is symmetrical @@ -1308,7 +1312,7 @@ proc toBiggestInt*(f: BiggestFloat): BiggestInt {.noSideEffect.} = proc `/`*(x, y: int): float {.inline, noSideEffect.} = ## Division of integers that results in a float. - ## ``` + ## ```nim ## echo 7 / 5 # => 1.4 ## ``` ## @@ -1375,7 +1379,7 @@ proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.} ## This is often more efficient than `tmp = a; a = b; b = tmp`. ## Particularly useful for sorting algorithms. ## - ## ``` + ## ```nim ## var ## a = 5 ## b = 9 @@ -1414,7 +1418,7 @@ include "system/iterators_1" proc len*[U: Ordinal; V: Ordinal](x: HSlice[U, V]): int {.noSideEffect, inline.} = ## Length of ordinal slice. When x.b < x.a returns zero length. - ## ``` + ## ```nim ## assert((0..5).len == 6) ## assert((5..2).len == 0) ## ``` @@ -1425,11 +1429,10 @@ proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".} proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".} proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".} proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".} -proc isNil*[T: proc](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`. - when defined(nimHasTopDownInference): # magic used for seq type inference proc `@`*[T](a: openArray[T]): seq[T] {.magic: "OpenArrayToSeq".} = @@ -1455,7 +1458,7 @@ 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]) ## ``` ## @@ -1471,7 +1474,7 @@ 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]) ## ``` ## @@ -1486,7 +1489,7 @@ when defined(nimSeqsV2): ## Prepends the element x to the beginning of the sequence. ## ## Requires copying of the sequence. - ## ``` + ## ```nim ## assert(1 & @[2, 3, 4] == @[1, 2, 3, 4]) ## ``` newSeq(result, y.len + 1) @@ -1500,7 +1503,7 @@ else: ## Concatenates two sequences. ## ## Requires copying of the sequences. - ## ``` + ## ```nim ## assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6]) ## ``` ## @@ -1516,7 +1519,7 @@ 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]) ## ``` ## @@ -1531,7 +1534,7 @@ else: ## Prepends the element x to the beginning of the sequence. ## ## Requires copying of the sequence. - ## ``` + ## ```nim ## assert(1 & @[2, 3, 4] == @[1, 2, 3, 4]) ## ``` newSeq(result, y.len + 1) @@ -1552,7 +1555,7 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[ ## to retrieve information about the current filename and line number. ## Example: ## - ## ``` + ## ```nim ## import std/strutils ## ## template testException(exception, code: untyped): typed = @@ -1597,17 +1600,97 @@ when not defined(js) and defined(nimV2): align: int16 depth: int16 display: ptr UncheckedArray[uint32] # classToken - when defined(nimTypeNames): + when defined(nimTypeNames) or defined(nimArcIds): name: cstring traceImpl: pointer typeInfoV1: pointer # for backwards compat, usually nil flags: int + when defined(gcDestructors): + when defined(cpp): + vTable: ptr UncheckedArray[pointer] # vtable for types + else: + vTable: UncheckedArray[pointer] # vtable for types PNimTypeV2 = ptr TNimTypeV2 +proc supportsCopyMem(t: typedesc): bool {.magic: "TypeTrait".} + when notJSnotNims and defined(nimSeqsV2): include "system/strs_v2" include "system/seqs_v2" +when not defined(js): + template newSeqImpl(T, len) = + result = newSeqOfCap[T](len) + {.cast(noSideEffect).}: + when defined(nimSeqsV2): + cast[ptr int](addr result)[] = len + else: + var s = cast[PGenericSeq](result) + s.len = len + + proc newSeqUninitialized*[T: SomeNumber](len: Natural): seq[T] {.deprecated: "Use `newSeqUninit` instead".} = + ## Creates a new sequence of type `seq[T]` with length `len`. + ## + ## Only available for numbers types. Note that the sequence will be + ## uninitialized. After the creation of the sequence you should assign + ## entries to the sequence instead of adding them. + ## Example: + ## ```nim + ## var x = newSeqUninitialized[int](3) + ## assert len(x) == 3 + ## x[0] = 10 + ## ``` + result = newSeqOfCap[T](len) + when defined(nimSeqsV2): + cast[ptr int](addr result)[] = len + else: + var s = cast[PGenericSeq](result) + s.len = len + + func newSeqUninit*[T](len: Natural): seq[T] = + ## Creates a new sequence of type `seq[T]` with length `len`. + ## + ## Only available for types, which don't contain + ## managed memory or have destructors. + ## Note that the sequence will be uninitialized. + ## After the creation of the sequence you should assign + ## entries to the sequence instead of adding them. + runnableExamples: + var x = newSeqUninit[int](3) + assert len(x) == 3 + x[0] = 10 + when supportsCopyMem(T): + when nimvm: + result = newSeq[T](len) + else: + newSeqImpl(T, len) + else: + {.error: "The type T cannot contain managed memory or have destructors".} + + proc newStringUninit*(len: Natural): string = + ## Returns a new string of length `len` but with uninitialized + ## content. One needs to fill the string character after character + ## with the index operator `s[i]`. + ## + ## This procedure exists only for optimization purposes; + ## the same effect can be achieved with the `&` operator or with `add`. + when nimvm: + result = newString(len) + else: + result = newStringOfCap(len) + when defined(nimSeqsV2): + let s = cast[ptr NimStringV2](addr result) + if len > 0: + s.len = len + s.p.data[len] = '\0' + else: + let s = cast[NimString](result) + s.len = len + s.data[len] = '\0' +else: + proc newStringUninit*(len: Natural): string {. + magic: "NewString", importc: "mnewString", noSideEffect.} + {.pop.} when not defined(nimscript): @@ -1619,8 +1702,24 @@ when not defined(nimscript): when not declared(sysFatal): include "system/fatal" +type + PFrame* = ptr TFrame ## Represents a runtime frame of the call stack; + ## part of the debugger API. + # keep in sync with nimbase.h `struct TFrame_` + TFrame* {.importc, nodecl, final.} = object ## The frame itself. + prev*: PFrame ## Previous frame; used for chaining the call stack. + procname*: cstring ## Name of the proc that is currently executing. + line*: int ## Line number of the proc that is currently executing. + filename*: cstring ## Filename of the proc that is currently executing. + len*: int16 ## Length of the inspectable slots. + calldepth*: int16 ## Used for max call depth checking. + when NimStackTraceMsgs: + frameMsgLen*: int ## end position in frameMsgBuf for this frame. when defined(nimV2): + var + framePtr {.threadvar.}: PFrame + include system/arc template newException*(exceptn: typedesc, message: string; @@ -1630,7 +1729,6 @@ template newException*(exceptn: typedesc, message: string; (ref exceptn)(msg: message, parent: parentException) when not defined(nimPreviewSlimSystem): - {.deprecated: "assertions is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/assertions`".} import std/assertions export assertions @@ -1653,7 +1751,7 @@ proc contains*[T](a: openArray[T], item: T): bool {.inline.}= ## ## This allows the `in` operator: `a.contains(item)` is the same as ## `item in a`. - ## ``` + ## ```nim ## var a = @[1, 3, 5] ## assert a.contains(5) ## assert 3 in a @@ -1664,6 +1762,8 @@ proc contains*[T](a: openArray[T], item: T): bool {.inline.}= proc pop*[T](s: var seq[T]): T {.inline, noSideEffect.} = ## Returns the last item of `s` and decreases `s.len` by one. This treats ## `s` as a stack and implements the common *pop* operation. + ## + ## Raises `IndexDefect` if `s` is empty. runnableExamples: var a = @[1, 3, 5, 7] let b = pop(a) @@ -1745,7 +1845,7 @@ when notJSnotNims: ## ## `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" @@ -1764,20 +1864,6 @@ when notJSnotNims: ## writes an error message and terminates the program, except when ## using `--os:any` -type - PFrame* = ptr TFrame ## Represents a runtime frame of the call stack; - ## part of the debugger API. - # keep in sync with nimbase.h `struct TFrame_` - TFrame* {.importc, nodecl, final.} = object ## The frame itself. - prev*: PFrame ## Previous frame; used for chaining the call stack. - procname*: cstring ## Name of the proc that is currently executing. - line*: int ## Line number of the proc that is currently executing. - filename*: cstring ## Filename of the proc that is currently executing. - len*: int16 ## Length of the inspectable slots. - calldepth*: int16 ## Used for max call depth checking. - when NimStackTraceMsgs: - frameMsgLen*: int ## end position in frameMsgBuf for this frame. - when defined(js) or defined(nimdoc): proc add*(x: var string, y: cstring) {.asmNoStackFrame.} = ## Appends `y` to `x` in place. @@ -1786,14 +1872,14 @@ when defined(js) or defined(nimdoc): tmp.add(cstring("ab")) tmp.add(cstring("cd")) doAssert tmp == "abcd" - asm """ + {.emit: """ if (`x` === null) { `x` = []; } var off = `x`.length; `x`.length += `y`.length; for (var i = 0; i < `y`.length; ++i) { `x`[off+i] = `y`.charCodeAt(i); } - """ + """.} proc add*(x: var cstring, y: cstring) {.magic: "AppendStrStr".} = ## Appends `y` to `x` in place. ## Only implemented for JS backend. @@ -1859,7 +1945,7 @@ 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: - ## ``` + ## ```nim ## for value in inputValues: ## if likely(value <= 100): ## process(value) @@ -1883,7 +1969,7 @@ 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: - ## ``` + ## ```nim ## for value in inputValues: ## if unlikely(value > 100): ## echo "Value too big!" @@ -1909,15 +1995,11 @@ when defined(nimAuditDelete): else: {.pragma: auditDelete.} -proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, auditDelete.} = +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. ## - ## .. note:: With `-d:nimStrictDelete`, an index error is produced when the index passed - ## to it was out of bounds. `-d:nimStrictDelete` will become the default - ## in upcoming versions. - ## ## See also: ## * `del <#del,seq[T],Natural>`_ for O(1) operation ## @@ -1926,7 +2008,7 @@ proc delete*[T](x: var seq[T], i: Natural) {.noSideEffect, auditDelete.} = s.delete(2) doAssert s == @[1, 2, 4, 5] - when defined(nimStrictDelete): + 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") @@ -2003,7 +2085,8 @@ when notJSnotNims: 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 @@ -2020,12 +2103,14 @@ when not defined(js): proc cstringArrayToSeq*(a: cstringArray, len: Natural): seq[string] = ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be ## of length `len`. + if a == nil: return @[] newSeq(result, len) for i in 0..len-1: result[i] = $a[i] proc cstringArrayToSeq*(a: cstringArray): seq[string] = ## Converts a `cstringArray` to a `seq[string]`. `a` is supposed to be ## terminated by `nil`. + if a == nil: return @[] var L = 0 while a[L] != nil: inc(L) result = cstringArrayToSeq(a, L) @@ -2050,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 @@ -2066,7 +2151,6 @@ when not defined(js): when hostOS != "standalone": include system/threadimpl when not defined(nimPreviewSlimSystem): - {.deprecated: "threads is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/typedthreads`".} import std/typedthreads export typedthreads @@ -2080,7 +2164,7 @@ when notJSnotNims: ## is pressed. Only one such hook is supported. ## Example: ## - ## ``` + ## ```nim ## proc ctrlc() {.noconv.} = ## echo "Ctrl+C fired!" ## # do clean up stuff @@ -2113,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.} @@ -2129,6 +2210,16 @@ 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 @@ -2211,44 +2302,72 @@ 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/C++, hash compuations, etc. - when T is "closure": - #[ - 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 - ]# - {.emit: """ - `result` = (void*)`x`.ClP_0; - """.} - else: - {.error: "Only closure function and iterator are allowed!".} + ## 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() - proc rawEnv*[T: proc](x: T): pointer {.noSideEffect, inline.} = + if e.isNil(): + let c2 = cast[proc(y: int): int {.nimcall.}](p) + echo c2(2) + else: + let c3 = cast[proc(y: int; env: pointer): int {.nimcall.}](p) + echo c3(3, e) + + {.emit: """ + `result` = (void*)`x`.ClP_0; + """.} + + proc rawEnv*[T: proc {.closure.} | iterator {.closure.}](x: T): pointer {.noSideEffect, inline.} = ## Retrieves the raw environment pointer of the closure `x`. See also `rawProc`. - when T is "closure": - {.emit: """ - `result` = `x`.ClE_0; - """.} - else: - {.error: "Only closure function and iterator are allowed!".} - - proc finished*[T: proc](x: T): bool {.noSideEffect, inline, magic: "Finished".} = - ## It can be used to determine if a first class iterator has finished. - when T is "iterator": - {.emit: """ - `result` = ((NI*) `x`.ClE_0)[1] < 0; - """.} - else: - {.error: "Only closure iterator is allowed!".} + ## This is not available for the JS target. + {.emit: """ + `result` = `x`.ClE_0; + """.} + +proc finished*[T: iterator {.closure.}](x: T): bool {.noSideEffect, inline, magic: "Finished".} = + ## It can be used to determine if a first class iterator has finished. + when defined(js): + # TODO: mangle `:state` + {.emit: """ + `result` = (`x`.ClE_0).HEX3Astate < 0; + """.} + else: + {.emit: """ + `result` = ((NI*) `x`.ClE_0)[1] < 0; + """.} from std/private/digitsutils import addInt export addInt -when defined(js): +when defined(js) and not defined(nimscript): + # nimscript can be defined if config file for js compilation include "system/jssys" include "system/reprjs" @@ -2279,7 +2398,7 @@ elif defined(nimdoc): ## `quit(int(0x100000000))` is equal to `quit(127)` on Linux. ## ## .. danger:: In almost all cases, in particular in library code, prefer - ## alternatives, e.g. `doAssert false` or raise a `Defect`. + ## 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. @@ -2329,7 +2448,7 @@ include "system/indices" proc `&=`*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} ## Appends in place to a string. - ## ``` + ## ```nim ## var a = "abc" ## a &= "de" # a <- "abcde" ## ``` @@ -2349,7 +2468,7 @@ when compileOption("rangechecks"): else: template rangeCheck*(cond) = discard -when not defined(gcArc) and not defined(gcOrc): +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`. @@ -2358,7 +2477,8 @@ when not defined(gcArc) and not defined(gcOrc): 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 + {.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 @@ -2371,7 +2491,8 @@ when not defined(gcArc) and not defined(gcOrc): s = cast[PGenericSeq](newString(0)) # string literals cannot become 'shallow': if (s.reserved and strlitFlag) == 0: - s.reserved = s.reserved or seqShallowFlag + {.noSideEffect.}: + s.reserved = s.reserved or seqShallowFlag type NimNodeObj = object @@ -2393,18 +2514,30 @@ when defined(nimV2): import system/repr_v2 export repr_v2 +proc repr*[T, U](x: HSlice[T, U]): string = + ## Generic `repr` operator for slices that is lifted from the components + ## of `x`. Example: + ## ```Nim + ## $(1 .. 5) == "1 .. 5" + ## ``` + result = repr(x.a) + result.add(" .. ") + result.add(repr(x.b)) + when hasAlloc or defined(nimscript): proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} = ## Inserts `item` into `x` at position `i`. - ## ``` + ## ```nim ## var a = "abc" ## a.insert("zz", 0) # a <- "zzabc" ## ``` + if item.len == 0: # prevents self-assignment + return var xl = x.len setLen(x, xl+item.len) var j = xl-1 while j >= i: - when defined(gcArc) or defined(gcOrc): + when defined(gcArc) or defined(gcOrc) or defined(gcAtomicArc): x[j+item.len] = move x[j] else: shallowCopy(x[j+item.len], x[j]) @@ -2475,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. ## - ## ``` + ## ```nim ## var tmp = "" ## tmp.addQuoted(1) ## tmp.add(", ") @@ -2517,7 +2650,7 @@ proc locals*(): RootObj {.magic: "Plugin", noSideEffect.} = ## the official signature says, the return type is *not* `RootObj` but a ## tuple of a structure that depends on the current scope. Example: ## - ## ``` + ## ```nim ## proc testLocals() = ## var ## a = "something" @@ -2543,7 +2676,7 @@ when hasAlloc and notJSnotNims: ## This is also used by the code generator ## for the implementation of `spawn`. ## - ## For `--gc:arc` or `--gc:orc` deepcopy support has to be enabled + ## For `--mm:arc` or `--mm:orc` deepcopy support has to be enabled ## via `--deepcopy:on`. discard @@ -2556,7 +2689,7 @@ when hasAlloc and notJSnotNims: proc procCall*(x: untyped) {.magic: "ProcCall", compileTime.} = ## Special magic to prohibit dynamic binding for `method`:idx: calls. ## This is similar to `super`:idx: in ordinary OO languages. - ## ``` + ## ```nim ## # 'someMethod' will be resolved fully statically: ## procCall someMethod(a, b) ## ``` @@ -2569,7 +2702,7 @@ 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 template closureScope*(body: untyped): untyped = @@ -2581,7 +2714,7 @@ template closureScope*(body: untyped): untyped = ## ## Example: ## - ## ``` + ## ```nim ## var myClosure : proc() ## # without closureScope: ## for i in 0 .. 5: @@ -2601,7 +2734,7 @@ template closureScope*(body: untyped): untyped = template once*(body: untyped): untyped = ## Executes a block of code only once (the first time the block is reached). - ## ``` + ## ```nim ## proc draw(t: Triangle) = ## once: ## graphicsInit() @@ -2658,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] {. @@ -2680,6 +2824,9 @@ proc toOpenArrayByte*(x: openArray[char]; first, last: int): openArray[byte] {. proc toOpenArrayByte*(x: seq[char]; first, last: int): openArray[byte] {. magic: "Slice".} +proc toOpenArrayChar*(x: openArray[byte]; first, last: int): openArray[char] {. + magic: "Slice".} + when defined(genode): var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.} ## Hook into the Genode component bootstrap process. @@ -2719,10 +2866,11 @@ when notJSnotNims: not defined(nintendoswitch) and not defined(freertos) and not defined(zephyr) and + not defined(nuttx) and hostOS != "any" proc raiseEIO(msg: string) {.noinline, noreturn.} = - sysFatal(IOError, msg) + raise newException(IOError, msg) proc echoBinSafe(args: openArray[string]) {.compilerproc.} = when defined(androidNDK): @@ -2752,7 +2900,7 @@ when notJSnotNims: # 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 = c_fprintf(f, "%s", s) + var i = int c_fprintf(f, "%s", s) while i < s.len: if s[i] == '\0': let w = c_fputc('\0', f) @@ -2778,7 +2926,6 @@ when notJSnotNims: releaseSys echoLock when not defined(nimPreviewSlimSystem): - {.deprecated: "io is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/syncio`".} import std/syncio export syncio @@ -2790,7 +2937,7 @@ when notJSnotNims and not defined(nimSeqsV2): ## 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("--gc:arc"): + runnableExamples: var x = "abc" var y = "defgh" prepareMutation(y) # without this, you may get a `SIGBUS` or `SIGSEGV` @@ -2798,7 +2945,11 @@ when notJSnotNims and not defined(nimSeqsV2): assert y == "abcgh" discard -proc nimArrayWith[T](y: T, size: static int): array[size, T] {.compilerRtl, raises: [].} = +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: - result[i] = y + when nimvm: + result[i] = y + else: + # TODO: fixme it should be `=dup` + result[i] = y |