diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/core/typeinfo.nim | 28 | ||||
-rw-r--r-- | lib/posix/posix_haiku.nim | 4 | ||||
-rw-r--r-- | lib/posix/posix_nintendoswitch.nim | 10 | ||||
-rw-r--r-- | lib/pure/memfiles.nim | 8 | ||||
-rw-r--r-- | lib/pure/nativesockets.nim | 6 | ||||
-rw-r--r-- | lib/pure/os.nim | 2 | ||||
-rw-r--r-- | lib/pure/ssl_certs.nim | 4 | ||||
-rw-r--r-- | lib/pure/terminal.nim | 8 | ||||
-rw-r--r-- | lib/std/syncio.nim | 64 | ||||
-rw-r--r-- | lib/system.nim | 969 | ||||
-rw-r--r-- | lib/system/ansi_c.nim | 4 | ||||
-rw-r--r-- | lib/system/arithmetics.nim | 271 | ||||
-rw-r--r-- | lib/system/basic_types.nim | 61 | ||||
-rw-r--r-- | lib/system/chcks.nim | 4 | ||||
-rw-r--r-- | lib/system/comparisons.nim | 22 | ||||
-rw-r--r-- | lib/system/compilation.nim | 214 | ||||
-rw-r--r-- | lib/system/ctypes.nim | 90 | ||||
-rw-r--r-- | lib/system/exceptions.nim | 96 | ||||
-rw-r--r-- | lib/system/indices.nim | 156 | ||||
-rw-r--r-- | lib/system/iterators.nim | 2 | ||||
-rw-r--r-- | lib/system_overview.rst | 2 | ||||
-rw-r--r-- | lib/windows/winlean.nim | 4 |
22 files changed, 1036 insertions, 993 deletions
diff --git a/lib/core/typeinfo.nim b/lib/core/typeinfo.nim index df2e66226..89b1deb31 100644 --- a/lib/core/typeinfo.nim +++ b/lib/core/typeinfo.nim @@ -91,7 +91,7 @@ type rawTypePtr: pointer ppointer = ptr pointer - pbyteArray = ptr array[0xffff, int8] + pbyteArray = ptr array[0xffff, uint8] when not defined(gcDestructors): type @@ -139,10 +139,10 @@ proc getDiscriminant(aa: pointer, n: ptr TNimNode): int = var d: int let a = cast[ByteAddress](aa) case n.typ.size - of 1: d = ze(cast[ptr int8](a +% n.offset)[]) - of 2: d = ze(cast[ptr int16](a +% n.offset)[]) - of 4: d = int(cast[ptr int32](a +% n.offset)[]) - of 8: d = int(cast[ptr int64](a +% n.offset)[]) + of 1: d = int(cast[ptr uint8](a +% n.offset)[]) + of 2: d = int(cast[ptr uint16](a +% n.offset)[]) + of 4: d = int(cast[ptr uint32](a +% n.offset)[]) + of 8: d = int(cast[ptr uint64](a +% n.offset)[]) else: assert(false) return d @@ -484,8 +484,8 @@ proc getBiggestInt*(x: Any): BiggestInt = of tyChar: result = BiggestInt(cast[ptr char](x.value)[]) of tyEnum, tySet: case t.size - of 1: result = ze64(cast[ptr int8](x.value)[]) - of 2: result = ze64(cast[ptr int16](x.value)[]) + of 1: result = int64(cast[ptr uint8](x.value)[]) + of 2: result = int64(cast[ptr uint16](x.value)[]) of 4: result = BiggestInt(cast[ptr int32](x.value)[]) of 8: result = BiggestInt(cast[ptr int64](x.value)[]) else: assert false @@ -509,8 +509,8 @@ proc setBiggestInt*(x: Any, y: BiggestInt) = of tyChar: cast[ptr char](x.value)[] = chr(y.int) of tyEnum, tySet: case t.size - of 1: cast[ptr int8](x.value)[] = toU8(y.int) - of 2: cast[ptr int16](x.value)[] = toU16(y.int) + of 1: cast[ptr uint8](x.value)[] = uint8(y.int) + of 2: cast[ptr uint16](x.value)[] = uint16(y.int) of 4: cast[ptr int32](x.value)[] = int32(y) of 8: cast[ptr int64](x.value)[] = y else: assert false @@ -691,14 +691,14 @@ iterator elements*(x: Any): int = # "typ.slots.len" field is for sets the "first" field var u: int64 case typ.size - of 1: u = ze64(cast[ptr int8](p)[]) - of 2: u = ze64(cast[ptr int16](p)[]) - of 4: u = ze64(cast[ptr int32](p)[]) + of 1: u = int64(cast[ptr uint8](p)[]) + of 2: u = int64(cast[ptr uint16](p)[]) + of 4: u = int64(cast[ptr uint32](p)[]) of 8: u = cast[ptr int64](p)[] else: let a = cast[pbyteArray](p) for i in 0 .. typ.size*8-1: - if (ze(a[i div 8]) and (1 shl (i mod 8))) != 0: + if (int(a[i div 8]) and (1 shl (i mod 8))) != 0: yield i + typ.node.len if typ.size <= 8: for i in 0..sizeof(int64)*8-1: @@ -727,4 +727,4 @@ proc inclSetElement*(x: Any, elem: int) = a[] = a[] or (1'i64 shl e) else: var a = cast[pbyteArray](p) - a[e shr 3] = toU8(a[e shr 3] or (1 shl (e and 7))) + a[e shr 3] = a[e shr 3] or uint8(1 shl (e and 7)) diff --git a/lib/posix/posix_haiku.nim b/lib/posix/posix_haiku.nim index d626b2106..32a6d24e2 100644 --- a/lib/posix/posix_haiku.nim +++ b/lib/posix/posix_haiku.nim @@ -304,7 +304,7 @@ type Stack* {.importc: "stack_t", header: "<signal.h>", final, pure.} = object ## stack_t ss_sp*: pointer ## Stack base or pointer. - ss_size*: csize ## Stack size. + ss_size*: csize_t ## Stack size. ss_flags*: cint ## Flags. SigInfo* {.importc: "siginfo_t", @@ -404,7 +404,7 @@ type IOVec* {.importc: "struct iovec", pure, final, header: "<sys/uio.h>".} = object ## struct iovec iov_base*: pointer ## Base address of a memory region for input or output. - iov_len*: csize ## The size of the memory pointed to by iov_base. + iov_len*: csize_t ## The size of the memory pointed to by iov_base. Tmsghdr* {.importc: "struct msghdr", pure, final, header: "<sys/socket.h>".} = object ## struct msghdr diff --git a/lib/posix/posix_nintendoswitch.nim b/lib/posix/posix_nintendoswitch.nim index 4cef80bb7..b66563695 100644 --- a/lib/posix/posix_nintendoswitch.nim +++ b/lib/posix/posix_nintendoswitch.nim @@ -286,7 +286,7 @@ type header: "<signal.h>", final, pure.} = object ## stack_t ss_sp*: pointer ## Stack base or pointer. ss_flags*: cint ## Flags. - ss_size*: csize ## Stack size. + ss_size*: csize_t ## Stack size. SigInfo* {.importc: "siginfo_t", header: "<signal.h>", final, pure.} = object ## siginfo_t @@ -321,7 +321,7 @@ type aio_lio_opcode*: cint ## Operation to be performed. aio_reqprio*: cint ## Request priority offset. aio_buf*: pointer ## Location of buffer. - aio_nbytes*: csize ## Length of transfer. + aio_nbytes*: csize_t ## Length of transfer. aio_sigevent*: SigEvent ## Signal number and value. next_prio: pointer abs_prio: cint @@ -378,15 +378,15 @@ type msg_name*: pointer ## Optional address. msg_namelen*: SockLen ## Size of address. msg_iov*: ptr IOVec ## Scatter/gather array. - msg_iovlen*: csize ## Members in msg_iov. + msg_iovlen*: csize_t ## Members in msg_iov. msg_control*: pointer ## Ancillary data; see below. - msg_controllen*: csize ## Ancillary data buffer len. + msg_controllen*: csize_t ## Ancillary data buffer len. msg_flags*: cint ## Flags on received message. Tcmsghdr* {.importc: "struct cmsghdr", pure, final, header: "<sys/socket.h>".} = object ## struct cmsghdr - cmsg_len*: csize ## Data byte count, including the cmsghdr. + cmsg_len*: csize_t ## Data byte count, including the cmsghdr. cmsg_level*: cint ## Originating protocol. cmsg_type*: cint ## Protocol-specific type. diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 28563b6fe..a952933ed 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -317,9 +317,9 @@ when defined(posix) or defined(nimdoc): raiseOSError(osLastError()) when defined(linux): #Maybe NetBSD, too? #On Linux this can be over 100 times faster than a munmap,mmap cycle. - proc mremap(old: pointer; oldSize, newSize: csize; flags: cint): + proc mremap(old: pointer; oldSize, newSize: csize_t; flags: cint): pointer {.importc: "mremap", header: "<sys/mman.h>".} - let newAddr = mremap(f.mem, csize(f.size), csize(newFileSize), cint(1)) + let newAddr = mremap(f.mem, csize_t(f.size), csize_t(newFileSize), cint(1)) if newAddr == cast[pointer](MAP_FAILED): raiseOSError(osLastError()) else: @@ -412,7 +412,7 @@ iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline ## inc(count) ## echo count - proc c_memchr(cstr: pointer, c: char, n: csize): pointer {. + proc c_memchr(cstr: pointer, c: char, n: csize_t): pointer {. importc: "memchr", header: "<string.h>".} proc `-!`(p, q: pointer): int {.inline.} = return cast[int](p) -% cast[int](q) var ms: MemSlice @@ -420,7 +420,7 @@ iterator memSlices*(mfile: MemFile, delim = '\l', eat = '\r'): MemSlice {.inline ms.data = mfile.mem var remaining = mfile.size while remaining > 0: - ending = c_memchr(ms.data, delim, remaining) + ending = c_memchr(ms.data, delim, csize_t(remaining)) if ending == nil: # unterminated final slice ms.size = remaining # Weird case..check eat? yield ms diff --git a/lib/pure/nativesockets.nim b/lib/pure/nativesockets.nim index dcba996a4..2599a8acc 100644 --- a/lib/pure/nativesockets.nim +++ b/lib/pure/nativesockets.nim @@ -169,7 +169,7 @@ when not useWinVersion: else: proc toInt(domain: Domain): cint = - result = toU32(ord(domain)).cint + result = cast[cint](uint32(ord(domain))) proc toKnownDomain*(family: cint): Option[Domain] = ## Converts the platform-dependent `cint` to the Domain or none(), @@ -375,9 +375,9 @@ when not useNimNetLite: ## ## On posix this will search through the `/etc/services` file. when useWinVersion: - var s = winlean.getservbyport(ze(int16(port)).cint, proto) + var s = winlean.getservbyport(uint16(port).cint, proto) else: - var s = posix.getservbyport(ze(int16(port)).cint, proto) + var s = posix.getservbyport(uint16(port).cint, proto) if s == nil: raiseOSError(osLastError(), "Service not found.") result.name = $s.s_name result.aliases = cstringArrayToSeq(s.s_aliases) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 5c387ec03..b240a23ff 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -3121,7 +3121,7 @@ when defined(haiku): B_FIND_PATH_IMAGE_PATH = 1000 proc find_path(codePointer: pointer, baseDirectory: cint, subPath: cstring, - pathBuffer: cstring, bufferSize: csize): int32 + pathBuffer: cstring, bufferSize: csize_t): int32 {.importc, header: "<FindDirectory.h>".} proc getApplHaiku(): string = diff --git a/lib/pure/ssl_certs.nim b/lib/pure/ssl_certs.nim index c40eadf04..dd09848be 100644 --- a/lib/pure/ssl_certs.nim +++ b/lib/pure/ssl_certs.nim @@ -88,7 +88,7 @@ when defined(haiku): proc find_paths_etc(architecture: cstring, baseDirectory: cint, subPath: cstring, flags: uint32, paths: var ptr UncheckedArray[cstring], - pathCount: var csize): int32 + pathCount: var csize_t): int32 {.importc, header: "<FindDirectory.h>".} proc free(p: pointer) {.importc, header: "<stdlib.h>".} @@ -137,7 +137,7 @@ iterator scanSSLCertificates*(useEnvVars = false): string = else: var paths: ptr UncheckedArray[cstring] - size: csize + size: csize_t let err = find_paths_etc( nil, B_FIND_PATH_DATA_DIRECTORY, "ssl/CARootCertificates.pem", B_FIND_PATH_EXISTING_ONLY, paths, size diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 571c9b13c..daf470b09 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -644,9 +644,9 @@ proc setForegroundColor*(f: File, fg: ForegroundColor, bright = false) = 0, # fg8Bit not supported, see `enableTrueColors` instead. 0] # unused if fg == fgDefault: - discard setConsoleTextAttribute(h, toU16(old or defaultForegroundColor)) + discard setConsoleTextAttribute(h, cast[int16](cast[uint16](old) or cast[uint16](defaultForegroundColor))) else: - discard setConsoleTextAttribute(h, toU16(old or lookup[fg])) + discard setConsoleTextAttribute(h, cast[int16](cast[uint16](old) or cast[uint16](lookup[fg]))) else: gFG = ord(fg) if bright: inc(gFG, 60) @@ -673,9 +673,9 @@ proc setBackgroundColor*(f: File, bg: BackgroundColor, bright = false) = 0, # bg8Bit not supported, see `enableTrueColors` instead. 0] # unused if bg == bgDefault: - discard setConsoleTextAttribute(h, toU16(old or defaultBackgroundColor)) + discard setConsoleTextAttribute(h, cast[int16](cast[uint16](old) or cast[uint16](defaultBackgroundColor))) else: - discard setConsoleTextAttribute(h, toU16(old or lookup[bg])) + discard setConsoleTextAttribute(h, cast[int16](cast[uint16](old) or cast[uint16](lookup[bg]))) else: gBG = ord(bg) if bright: inc(gBG, 60) diff --git a/lib/std/syncio.nim b/lib/std/syncio.nim index 22e981198..fc132bba7 100644 --- a/lib/std/syncio.nim +++ b/lib/std/syncio.nim @@ -39,6 +39,13 @@ type FileHandle* = cint ## type that represents an OS file handle; this is ## useful for low-level file access + 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 + # text file handling: when not defined(nimscript) and not defined(js): # duplicated between io and ansi_c @@ -142,13 +149,6 @@ proc c_fprintf(f: File, frmt: cstring): cint {. proc c_fputc(c: char, f: File): cint {. importc: "fputc", header: "<stdio.h>".} -# When running nim in android app, stdout goes nowhere, so echo gets ignored -# To redirect echo to the android logcat, use -d:androidNDK -when defined(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.} - template sysFatal(exc, msg) = raise newException(exc, msg) @@ -791,52 +791,6 @@ proc setStdIoUnbuffered*() {.tags: [], benign.} = when declared(stdin): discard c_setvbuf(stdin, nil, IONBF, 0) -when declared(stdout): - when defined(windows) and compileOption("threads"): - proc addSysExitProc(quitProc: proc() {.noconv.}) {.importc: "atexit", header: "<stdlib.h>".} - - const insideRLocksModule = false - include "system/syslocks" - - - var echoLock: SysLock - initSysLock echoLock - addSysExitProc(proc() {.noconv.} = deinitSys(echoLock)) - - const stdOutLock = not defined(windows) and - not defined(android) and - not defined(nintendoswitch) and - not defined(freertos) and - not defined(zephyr) and - hostOS != "any" - - proc echoBinSafe(args: openArray[string]) {.compilerproc.} = - when defined(androidNDK): - 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: File) {.importc, nodecl.} - proc funlockfile(f: File) {.importc, nodecl.} - flockfile(stdout) - when defined(windows) and compileOption("threads"): - acquireSys echoLock - for s in args: - when defined(windows): - writeWindows(stdout, s) - else: - discard c_fwrite(s.cstring, cast[csize_t](s.len), 1, stdout) - const linefeed = "\n" - discard c_fwrite(linefeed.cstring, linefeed.len, 1, stdout) - discard c_fflush(stdout) - when stdOutLock: - funlockfile(stdout) - when defined(windows) and compileOption("threads"): - releaseSys echoLock - when defined(windows) and not defined(nimscript) and not defined(js): # work-around C's sucking abstraction: @@ -960,3 +914,7 @@ iterator lines*(f: File): string {.tags: [ReadIOEffect].} = result.lines += 1 var res = newStringOfCap(80) while f.readLine(res): yield res + +template `&=`*(f: File, x: typed) = + ## An alias for `write`. + write(f, x) diff --git a/lib/system.nim b/lib/system.nim index 5b191f1e9..2de70ecad 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -22,97 +22,52 @@ ## .. include:: ./system_overview.rst -type - float* {.magic: Float.} ## Default floating point type. - float32* {.magic: Float32.} ## 32 bit floating point type. - float64* {.magic: Float.} ## 64 bit floating point type. - -# 'float64' is now an alias to 'float'; this solves many problems +include "system/basic_types" -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* {.deprecated: "Deprecated since v1.5; Use auto instead.".} = distinct auto ## Deprecated; Use `auto` instead. See https://github.com/nim-lang/RFCs/issues/281 - 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). + `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`. -include "system/basic_types" + `type`*[T] {.magic: "Type".} + ## Meta type representing the type of all type values. + ## + ## The coercion `type(x)` can be used to obtain the type of the given + ## expression `x`. +type + 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 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. - runnableExamples: - proc timesTwo*(x: int): int = - ## This proc doubles a number. - runnableExamples: - # at module scope - const exported* = 123 - assert timesTwo(5) == 10 - block: # at block scope - defer: echo "done" - runnableExamples "-d:foo -b:cpp": - import std/compilesettings - assert querySetting(backend) == "cpp" - assert defined(foo) - runnableExamples "-r:off": ## this one is only compiled - import std/browsers - openDefaultBrowser "https://forum.nim-lang.org/" - 2 * x - -proc compileOption*(option: string): bool {. - magic: "CompileOption", noSideEffect.} = - ## Can be used to determine an `on|off` compile-time option. - ## - ## See also: - ## * `compileOption <#compileOption,string,string>`_ for enum options - ## * `defined <#defined,untyped>`_ - ## * `std/compilesettings module <compilesettings.html>`_ - runnableExamples("--floatChecks:off"): - static: doAssert not compileOption("floatchecks") - {.push floatChecks: on.} - static: doAssert compileOption("floatchecks") - # floating point NaN and Inf checks enabled in this scope - {.pop.} - -proc compileOption*(option, arg: string): bool {. - magic: "CompileOptionArg", noSideEffect.} = - ## Can be used to determine an enum compile-time option. - ## - ## See also: - ## * `compileOption <#compileOption,string>`_ for `on|off` options - ## * `defined <#defined,untyped>`_ - ## * `std/compilesettings module <compilesettings.html>`_ +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: - when compileOption("opt", "size") and compileOption("gc", "boehm"): - discard "compiled with optimization for size and uses Boehm's GC" + 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" -{.push warning[GcMem]: off, warning[Uninit]: off.} -# {.push hints: off.} + 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. @@ -123,32 +78,6 @@ proc `and`*(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.} proc `not`*(a: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.} ## Constructs an `not` meta class. - -type - SomeFloat* = float|float32|float64 - ## Type class matching all floating point number types. - - SomeNumber* = SomeInteger|SomeFloat - ## Type class matching all number types. - -proc defined*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.} - ## Special compile-time procedure that checks whether `x` is - ## defined. - ## - ## `x` is an external symbol introduced through the compiler's - ## `-d:x switch <nimc.html#compiler-usage-compileminustime-symbols>`_ to enable - ## build time conditionals: - ## ``` - ## when not defined(release): - ## # Do here programmer friendly expensive sanity checks. - ## # Put here the normal code - ## ``` - ## - ## See also: - ## * `compileOption <#compileOption,string>`_ for `on|off` options - ## * `compileOption <#compileOption,string,string>`_ for enum options - ## * `define pragmas <manual.html#implementation-specific-pragmas-compileminustime-define-pragmas>`_ - when defined(nimHasIterable): type iterable*[T] {.magic: IterableType.} ## Represents an expression that yields `T` @@ -165,31 +94,6 @@ else: OrdinalImpl[T] {.magic: Ordinal.} Ordinal* = OrdinalImpl | uint | uint64 -when defined(nimHasDeclaredMagic): - proc declared*(x: untyped): bool {.magic: "Declared", noSideEffect, compileTime.} - ## Special compile-time procedure that checks whether `x` is - ## declared. `x` has to be an identifier or a qualified identifier. - ## - ## This can be used to check whether a library provides a certain - ## feature or not: - ## ``` - ## when not declared(strutils.toUpper): - ## # provide our own toUpper proc here, because strutils is - ## # missing it. - ## ``` - ## - ## See also: - ## * `declaredInScope <#declaredInScope,untyped>`_ -else: - proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.} - -when defined(nimHasDeclaredMagic): - proc declaredInScope*(x: untyped): bool {.magic: "DeclaredInScope", noSideEffect, compileTime.} - ## Special compile-time procedure that checks whether `x` is - ## declared in the current scope. `x` has to be an identifier. -else: - proc declaredInScope*(x: untyped): bool {.magic: "DefinedInScope", noSideEffect, compileTime.} - proc `addr`*[T](x: T): ptr T {.magic: "Addr", noSideEffect.} = ## Builtin `addr` operator for taking the address of a memory location. ## @@ -226,64 +130,24 @@ proc unsafeAddr*[T](x: T): ptr T {.magic: "Addr", noSideEffect, ## Cannot be overloaded. discard -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`. - -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. const ThisIsSystem = true proc internalNew*[T](a: var ref T) {.magic: "New", noSideEffect.} ## Leaked implementation detail. Do not use. -when true: - proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. - magic: "NewFinalize", noSideEffect.} - ## Creates a new object of type `T` and returns a safe (traced) - ## reference to it in `a`. - ## - ## When the garbage collector frees the object, `finalizer` is called. - ## The `finalizer` may not keep a reference to the - ## object pointed to by `x`. The `finalizer` cannot prevent the GC from - ## freeing the object. - ## - ## **Note**: The `finalizer` refers to the type `T`, not to the object! - ## This means that for each object of type `T` the finalizer will be called! +proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. + magic: "NewFinalize", noSideEffect.} + ## Creates a new object of type `T` and returns a safe (traced) + ## reference to it in `a`. + ## + ## When the garbage collector frees the object, `finalizer` is called. + ## The `finalizer` may not keep a reference to the + ## object pointed to by `x`. The `finalizer` cannot prevent the GC from + ## freeing the object. + ## + ## **Note**: The `finalizer` refers to the type `T`, not to the object! + ## This means that for each object of type `T` the finalizer will be called! proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = ## Resets an object `obj` to its initial (binary zero) value to signify @@ -539,12 +403,6 @@ when defined(hotCodeReloading): 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" @@ -592,6 +450,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. ## @@ -599,8 +458,66 @@ 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 + +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. -include "system/exceptions" + 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 @@ -800,29 +717,6 @@ func chr*(u: range[0..255]): char {.magic: "Chr".} = doAssertRaises(RangeDefect): discard chr(x) doAssertRaises(RangeDefect): discard char(x) -# floating point operations: -proc `+`*(x: float32): float32 {.magic: "UnaryPlusF64", noSideEffect.} -proc `-`*(x: float32): float32 {.magic: "UnaryMinusF64", noSideEffect.} -proc `+`*(x, y: float32): float32 {.magic: "AddF64", noSideEffect.} -proc `-`*(x, y: float32): float32 {.magic: "SubF64", noSideEffect.} -proc `*`*(x, y: float32): float32 {.magic: "MulF64", noSideEffect.} -proc `/`*(x, y: float32): float32 {.magic: "DivF64", noSideEffect.} - -proc `+`*(x: float): float {.magic: "UnaryPlusF64", noSideEffect.} -proc `-`*(x: float): float {.magic: "UnaryMinusF64", noSideEffect.} -proc `+`*(x, y: float): float {.magic: "AddF64", noSideEffect.} -proc `-`*(x, y: float): float {.magic: "SubF64", noSideEffect.} -proc `*`*(x, y: float): float {.magic: "MulF64", noSideEffect.} -proc `/`*(x, y: float): float {.magic: "DivF64", noSideEffect.} - -proc `==`*(x, y: float32): bool {.magic: "EqF64", noSideEffect.} -proc `<=`*(x, y: float32): bool {.magic: "LeF64", noSideEffect.} -proc `<` *(x, y: float32): bool {.magic: "LtF64", noSideEffect.} - -proc `==`*(x, y: float): bool {.magic: "EqF64", noSideEffect.} -proc `<=`*(x, y: float): bool {.magic: "LeF64", noSideEffect.} -proc `<`*(x, y: float): bool {.magic: "LtF64", noSideEffect.} - include "system/setops" @@ -1113,18 +1007,6 @@ type littleEndian, bigEndian const - isMainModule* {.magic: "IsMainModule".}: bool = false - ## True only when accessed in the main module. This works thanks to - ## compiler magic. It is useful to embed testing code in a module. - - CompileDate* {.magic: "CompileDate".}: string = "0000-00-00" - ## The date (in UTC) of compilation as a string of the form - ## `YYYY-MM-DD`. This works thanks to compiler magic. - - CompileTime* {.magic: "CompileTime".}: string = "00:00:00" - ## The time (in UTC) of compilation as a string of the form - ## `HH:MM:SS`. This works thanks to compiler magic. - cpuEndian* {.magic: "CpuEndian".}: Endianness = littleEndian ## The endianness of the target CPU. This is a valuable piece of ## information for low-level code only. This works thanks to compiler @@ -1174,7 +1056,8 @@ when defined(boehmgc): const boehmLib = "libgc.so.1" {.pragma: boehmGC, noconv, dynlib: boehmLib.} -type TaintedString* {.deprecated: "Deprecated since 1.5".} = string +when not defined(nimPreviewSlimSystem): + type TaintedString* {.deprecated: "Deprecated since 1.5".} = string when defined(profiler) and not defined(nimscript): @@ -1389,82 +1272,28 @@ when not defined(nimV2): ## 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. +import system/ctypes +export ctypes - BiggestFloat* = float64 - ## is an alias for the biggest floating point type the Nim - ## compiler supports. Currently this is `float64`, but it is - ## platform-dependent in general. +when 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, deprecated: "use `char` or `uint8` instead".} = char - ## Deprecated: Use `uint8` instead. - 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`. Same as `float(i)`. @@ -1506,18 +1335,68 @@ proc toBiggestInt*(f: BiggestFloat): BiggestInt {.noSideEffect.} = ## Same as `toInt <#toInt,float>`_ but for `BiggestFloat` to `BiggestInt`. if f >= 0: BiggestInt(f+0.5) else: BiggestInt(f-0.5) -proc addQuitProc*(quitProc: proc() {.noconv.}) {. - importc: "atexit", header: "<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. + ## ``` + ## echo 7 / 5 # => 1.4 + ## ``` + ## + ## See also: + ## * `div <system.html#div,int,int>`_ + ## * `mod <system.html#mod,int,int>`_ + result = toFloat(x) / toFloat(y) + +{.push stackTrace: off.} + +when defined(js): + proc js_abs[T: SomeNumber](x: T): T {.importc: "Math.abs".} +else: + proc c_fabs(x: cdouble): cdouble {.importc: "fabs", header: "<math.h>".} + proc c_fabsf(x: cfloat): cfloat {.importc: "fabsf", header: "<math.h>".} + +proc abs*[T: float64 | float32](x: T): T {.noSideEffect, inline.} = + when nimvm: + if x < 0.0: result = -x + elif x == 0.0: result = 0.0 # handle 0.0, -0.0 + else: result = x # handle NaN, > 0 + else: + when defined(js): result = js_abs(x) + else: + when T is float64: + result = c_fabs(x) + else: + result = c_fabsf(x) + +func abs*(x: int): int {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int8): int8 {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int16): int16 {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int32): int32 {.magic: "AbsI", inline.} = + if x < 0: -x else: x +func abs*(x: int64): int64 {.magic: "AbsI", inline.} = + ## Returns the absolute value of `x`. ## - ## 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. + ## 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`. @@ -1543,18 +1422,6 @@ 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 `isNaN` or `classify` procedure - ## in the `math module <math.html>`_ for checking for NaN. - include "system/memalloc" @@ -1564,47 +1431,6 @@ proc `|`*(a, b: typedesc): typedesc = discard include "system/iterators_1" -{.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) - -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. ## ``` @@ -1733,10 +1559,6 @@ else: 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 @@ -1773,15 +1595,6 @@ proc instantiationInfo*(index = -1, fullPaths = false): tuple[ ## # --> 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: - ## ``` - ## when compiles(3 + 4): - ## echo "'+' for integers is available" - ## ``` - discard when notJSnotNims: import system/ansi_c @@ -2066,22 +1879,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.} -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.} when not defined(js): @@ -2136,22 +1933,6 @@ template unlikely*(val: bool): bool = else: unlikelyProc(val) -const - NimMajor* {.intdefine.}: int = 1 - ## is the major number of Nim's version. Example: - ## ``` - ## when (NimMajor, NimMinor, NimPatch) >= (1, 3, 1): discard - ## ``` - # see also std/private/since - - NimMinor* {.intdefine.}: int = 7 - ## is the minor number of Nim's version. - ## Odd for devel, even for releases. - - NimPatch* {.intdefine.}: int = 3 - ## is the patch number of Nim's version. - ## Odd for devel, even for releases. - import system/dollars export dollars @@ -2200,16 +1981,6 @@ const NimVersion*: string = $NimMajor & "." & $NimMinor & "." & $NimPatch ## is the version of Nim as a string. - -type - FileSeekPos* = enum ## Position relative to which seek should happen. - # The values are ordered so that they match with stdio - # SEEK_SET, SEEK_CUR and SEEK_END respectively. - fspSet ## Seek to absolute value - fspCur ## Seek relative to current position - fspEnd ## Seek relative to end - - when not defined(js): {.push stackTrace: off, profiler: off.} @@ -2521,249 +2292,7 @@ proc quit*(errormsg: string, errorcode = QuitFailure) {.noreturn.} = {.pop.} # checks: off # {.pop.} # hints: off -proc `/`*(x, y: int): float {.inline, noSideEffect.} = - ## Division of integers that results in a float. - ## ``` - ## echo 7 / 5 # => 1.4 - ## ``` - ## - ## See also: - ## * `div <#div,int,int>`_ - ## * `mod <#mod,int,int>`_ - 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]`. - ## - ## ``` - ## 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)`. - ## ``` - ## 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: Ordinal](s: string, x: HSlice[T, U]): string {.inline.} = - ## Slice operation for strings. - ## Returns the inclusive range `[s[x.a], s[x.b]]`: - ## ``` - ## 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: Ordinal](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: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] = - ## Slice operation for arrays. - ## Returns the inclusive range `[a[x.a], a[x.b]]`: - ## ``` - ## 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: Ordinal](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) = - ## Slice assignment for arrays. - ## ``` - ## 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: Ordinal](s: openArray[T], x: HSlice[U, V]): seq[T] = - ## Slice operation for sequences. - ## Returns the inclusive range `[s[x.a], s[x.b]]`: - ## ``` - ## 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: Ordinal](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 `[]`*(s: var string; i: BackwardsIndex): var char {.inline.} = s[s.len - int(i)] - -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 <syncio.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. - ## ``` - ## 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. - ## ``` - ## 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`: - ## ``` - ## const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0") - ## ``` - -proc gorgeEx*(command: string, input = "", cache = ""): tuple[output: string, - exitCode: int] = - ## Similar to `gorge <#gorge,string,string,string>`_ but also returns the - ## precious exit code. - discard - - -proc `+=`*[T: float|float32|float64] (x: var T, y: T) {. - inline, noSideEffect.} = - ## Increments in place a floating point number. - x = x + y - -proc `-=`*[T: float|float32|float64] (x: var T, y: T) {. - inline, noSideEffect.} = - ## Decrements in place a floating point number. - x = x - y - -proc `*=`*[T: float|float32|float64] (x: var T, y: T) {. - inline, noSideEffect.} = - ## Multiplies in place a floating point number. - x = x * y - -proc `/=`*(x: var float64, y: float64) {.inline, noSideEffect.} = - ## Divides in place a floating point number. - x = x / y - -proc `/=`*[T: float|float32](x: var T, y: T) {.inline, noSideEffect.} = - ## Divides in place a floating point number. - x = x / y +include "system/indices" proc `&=`*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} ## Appends in place to a string. @@ -2775,26 +2304,8 @@ proc `&=`*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.} template `&=`*(x, y: typed) = ## Generic 'sink' operator for Nim. ## - ## For files an alias for `write`. ## If not specialized further, an alias for `add`. add(x, y) -when declared(File): - template `&=`*(f: File, x: typed) = write(f, x) - -template currentSourcePath*: string = instantiationInfo(-1, true).filename - ## Returns the full file-system path of the current source. - ## - ## To get the directory containing the current source, use it with - ## `os.parentDir() <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) = @@ -2834,23 +2345,19 @@ 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 when hasAlloc or defined(nimscript): proc insert*(x: var string, item: string, i = 0.Natural) {.noSideEffect.} = @@ -3127,11 +2634,6 @@ 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>`_. - when defined(genode): var componentConstructHook*: proc (env: GenodeEnv) {.nimcall.} ## Hook into the Genode component bootstrap process. @@ -3156,12 +2658,81 @@ when defined(genode): import system/widestrs export widestrs +when notJSnotNims: + when defined(windows) and compileOption("threads"): + when not declared(addSysExitProc): + proc addSysExitProc(quitProc: proc() {.noconv.}) {.importc: "atexit", header: "<stdlib.h>".} + var echoLock: SysLock + initSysLock echoLock + addSysExitProc(proc() {.noconv.} = deinitSys(echoLock)) + + const stdOutLock = not defined(windows) and + not defined(android) and + not defined(nintendoswitch) and + not defined(freertos) and + not defined(zephyr) and + hostOS != "any" + + proc raiseEIO(msg: string) {.noinline, noreturn.} = + sysFatal(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 = 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): {.deprecated: "io is about to move out of system; use `-d:nimPreviewSlimSystem` and import `std/syncio`".} import std/syncio export syncio -else: - import std/syncio when not defined(createNimHcr) and not defined(nimscript): include nimhcr diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 0dbded126..ae4b90504 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -180,6 +180,8 @@ proc c_printf*(frmt: cstring): cint {. proc c_fputs*(c: cstring, f: CFilePtr): cint {. importc: "fputs", header: "<stdio.h>", discardable.} +proc c_fputc*(c: char, f: CFilePtr): cint {. + importc: "fputc", header: "<stdio.h>", discardable.} proc c_sprintf*(buf, frmt: cstring): cint {. importc: "sprintf", header: "<stdio.h>", varargs, noSideEffect.} @@ -212,7 +214,7 @@ else: proc c_fwrite*(buf: pointer, size, n: csize_t, f: CFilePtr): cint {. importc: "fwrite", header: "<stdio.h>".} -proc c_fflush(f: CFilePtr): cint {. +proc c_fflush*(f: CFilePtr): cint {. importc: "fflush", header: "<stdio.h>".} proc rawWriteString*(f: CFilePtr, s: cstring, length: int) {.compilerproc, nonReloadable, inline.} = diff --git a/lib/system/arithmetics.nim b/lib/system/arithmetics.nim index 0dd329495..910e73507 100644 --- a/lib/system/arithmetics.nim +++ b/lib/system/arithmetics.nim @@ -45,109 +45,6 @@ proc dec*[T: Ordinal](x: var T, y = 1) {.magic: "Dec", noSideEffect.} = # -------------------------------------------------------------------------- # built-in operators -when defined(nimNoZeroExtendMagic): - proc ze*(x: int8): int {.deprecated.} = - ## zero extends a smaller integer type to `int`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int](uint(cast[uint8](x))) - - proc ze*(x: int16): int {.deprecated.} = - ## zero extends a smaller integer type to `int`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int](uint(cast[uint16](x))) - - proc ze64*(x: int8): int64 {.deprecated.} = - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int64](uint64(cast[uint8](x))) - - proc ze64*(x: int16): int64 {.deprecated.} = - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int64](uint64(cast[uint16](x))) - - proc ze64*(x: int32): int64 {.deprecated.} = - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int64](uint64(cast[uint32](x))) - - proc ze64*(x: int): int64 {.deprecated.} = - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. Does nothing if the size of an `int` is the same as `int64`. - ## (This is the case on 64 bit processors.) - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int64](uint64(cast[uint](x))) - - proc toU8*(x: int): int8 {.deprecated.} = - ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits - ## from `x`. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int8](x) - - proc toU16*(x: int): int16 {.deprecated.} = - ## treats `x` as unsigned and converts it to an `int16` by taking the last - ## 16 bits from `x`. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int16](x) - - proc toU32*(x: int64): int32 {.deprecated.} = - ## treats `x` as unsigned and converts it to an `int32` by taking the - ## last 32 bits from `x`. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - cast[int32](x) - -elif not defined(js): - proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect, deprecated.} - ## zero extends a smaller integer type to `int`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect, deprecated.} - ## zero extends a smaller integer type to `int`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect, deprecated.} - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect, deprecated.} - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect, deprecated.} - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect, deprecated.} - ## zero extends a smaller integer type to `int64`. This treats `x` as - ## unsigned. Does nothing if the size of an `int` is the same as `int64`. - ## (This is the case on 64 bit processors.) - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect, deprecated.} - ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits - ## from `x`. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect, deprecated.} - ## treats `x` as unsigned and converts it to an `int16` by taking the last - ## 16 bits from `x`. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - - proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect, deprecated.} - ## treats `x` as unsigned and converts it to an `int32` by taking the - ## last 32 bits from `x`. - ## **Deprecated since version 0.19.9**: Use unsigned integers instead. - # integer calculations: proc `+`*(x: int): int {.magic: "UnaryPlusI", noSideEffect.} ## Unary `+` operator for an integer. Has no effect. @@ -399,6 +296,59 @@ proc `mod`*(x, y: uint16): uint16 {.magic: "ModU", noSideEffect.} proc `mod`*(x, y: uint32): uint32 {.magic: "ModU", noSideEffect.} proc `mod`*(x, y: uint64): uint64 {.magic: "ModU", noSideEffect.} +proc `+=`*[T: SomeInteger](x: var T, y: T) {. + magic: "Inc", noSideEffect.} + ## Increments an integer. + +proc `-=`*[T: SomeInteger](x: var T, y: T) {. + magic: "Dec", noSideEffect.} + ## Decrements an integer. + +proc `*=`*[T: SomeInteger](x: var T, y: T) {. + inline, noSideEffect.} = + ## Binary `*=` operator for integers. + x = x * y + +# 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 `+=`*[T: float|float32|float64] (x: var T, y: T) {. + inline, noSideEffect.} = + ## Increments in place a floating point number. + x = x + y + +proc `-=`*[T: float|float32|float64] (x: var T, y: T) {. + inline, noSideEffect.} = + ## Decrements in place a floating point number. + x = x - y + +proc `*=`*[T: float|float32|float64] (x: var T, y: T) {. + inline, noSideEffect.} = + ## Multiplies in place a floating point number. + x = x * y + +proc `/=`*(x: var float64, y: float64) {.inline, noSideEffect.} = + ## Divides in place a floating point number. + x = x / y + +proc `/=`*[T: float|float32](x: var T, y: T) {.inline, noSideEffect.} = + ## Divides in place a floating point number. + x = x / y + +# the following have to be included in system, not imported for some reason: + proc `+%`*(x, y: int): int {.inline.} = ## Treats `x` and `y` as unsigned and adds them. ## @@ -454,15 +404,106 @@ proc `%%`*(x, y: int16): int16 {.inline.} = cast[int16](cast[uint16](x) mod cast proc `%%`*(x, y: int32): int32 {.inline.} = cast[int32](cast[uint32](x) mod cast[uint32](y)) proc `%%`*(x, y: int64): int64 {.inline.} = cast[int64](cast[uint64](x) mod cast[uint64](y)) -proc `+=`*[T: SomeInteger](x: var T, y: T) {. - magic: "Inc", noSideEffect.} - ## Increments an integer. - -proc `-=`*[T: SomeInteger](x: var T, y: T) {. - magic: "Dec", noSideEffect.} - ## Decrements an integer. - -proc `*=`*[T: SomeInteger](x: var T, y: T) {. - inline, noSideEffect.} = - ## Binary `*=` operator for integers. - x = x * y +when not defined(nimPreviewSlimSystem): + when defined(nimNoZeroExtendMagic): + proc ze*(x: int8): int {.deprecated.} = + ## zero extends a smaller integer type to `int`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int](uint(cast[uint8](x))) + + proc ze*(x: int16): int {.deprecated.} = + ## zero extends a smaller integer type to `int`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int](uint(cast[uint16](x))) + + proc ze64*(x: int8): int64 {.deprecated.} = + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int64](uint64(cast[uint8](x))) + + proc ze64*(x: int16): int64 {.deprecated.} = + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int64](uint64(cast[uint16](x))) + + proc ze64*(x: int32): int64 {.deprecated.} = + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int64](uint64(cast[uint32](x))) + + proc ze64*(x: int): int64 {.deprecated.} = + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. Does nothing if the size of an `int` is the same as `int64`. + ## (This is the case on 64 bit processors.) + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int64](uint64(cast[uint](x))) + + proc toU8*(x: int): int8 {.deprecated.} = + ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits + ## from `x`. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int8](x) + + proc toU16*(x: int): int16 {.deprecated.} = + ## treats `x` as unsigned and converts it to an `int16` by taking the last + ## 16 bits from `x`. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int16](x) + + proc toU32*(x: int64): int32 {.deprecated.} = + ## treats `x` as unsigned and converts it to an `int32` by taking the + ## last 32 bits from `x`. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + cast[int32](x) + + elif not defined(js): + proc ze*(x: int8): int {.magic: "Ze8ToI", noSideEffect, deprecated.} + ## zero extends a smaller integer type to `int`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc ze*(x: int16): int {.magic: "Ze16ToI", noSideEffect, deprecated.} + ## zero extends a smaller integer type to `int`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc ze64*(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect, deprecated.} + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc ze64*(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect, deprecated.} + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc ze64*(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect, deprecated.} + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc ze64*(x: int): int64 {.magic: "ZeIToI64", noSideEffect, deprecated.} + ## zero extends a smaller integer type to `int64`. This treats `x` as + ## unsigned. Does nothing if the size of an `int` is the same as `int64`. + ## (This is the case on 64 bit processors.) + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc toU8*(x: int): int8 {.magic: "ToU8", noSideEffect, deprecated.} + ## treats `x` as unsigned and converts it to a byte by taking the last 8 bits + ## from `x`. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc toU16*(x: int): int16 {.magic: "ToU16", noSideEffect, deprecated.} + ## treats `x` as unsigned and converts it to an `int16` by taking the last + ## 16 bits from `x`. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. + + proc toU32*(x: int64): int32 {.magic: "ToU32", noSideEffect, deprecated.} + ## treats `x` as unsigned and converts it to an `int32` by taking the + ## last 32 bits from `x`. + ## **Deprecated since version 0.19.9**: Use unsigned integers instead. diff --git a/lib/system/basic_types.nim b/lib/system/basic_types.nim index 7779e1ce9..bf81b9b6a 100644 --- a/lib/system/basic_types.nim +++ b/lib/system/basic_types.nim @@ -1,15 +1,45 @@ type - int* {.magic: "Int".} ## Default integer type; bitwidth depends on + int* {.magic: Int.} ## Default integer type; bitwidth depends on ## architecture, but is always the same as a pointer. - int8* {.magic: "Int8".} ## Signed 8 bit integer type. - int16* {.magic: "Int16".} ## Signed 16 bit integer type. - int32* {.magic: "Int32".} ## Signed 32 bit integer type. - int64* {.magic: "Int64".} ## Signed 64 bit integer type. - uint* {.magic: "UInt".} ## Unsigned default integer type. - uint8* {.magic: "UInt8".} ## Unsigned 8 bit integer type. - uint16* {.magic: "UInt16".} ## Unsigned 16 bit integer type. - uint32* {.magic: "UInt32".} ## Unsigned 32 bit integer type. - uint64* {.magic: "UInt64".} ## Unsigned 64 bit integer type. + int8* {.magic: Int8.} ## Signed 8 bit integer type. + int16* {.magic: Int16.} ## Signed 16 bit integer type. + int32* {.magic: Int32.} ## Signed 32 bit integer type. + int64* {.magic: Int64.} ## Signed 64 bit integer type. + uint* {.magic: UInt.} ## Unsigned default integer type. + uint8* {.magic: UInt8.} ## Unsigned 8 bit integer type. + uint16* {.magic: UInt16.} ## Unsigned 16 bit integer type. + uint32* {.magic: UInt32.} ## Unsigned 32 bit integer type. + uint64* {.magic: UInt64.} ## Unsigned 64 bit integer type. + +type + float* {.magic: Float.} ## Default floating point type. + float32* {.magic: Float32.} ## 32 bit floating point type. + float64* {.magic: Float.} ## 64 bit floating point type. + +# 'float64' is now an alias to 'float'; this solves many problems + +type + char* {.magic: Char.} ## Built-in 8 bit character type (unsigned). + string* {.magic: String.} ## Built-in string type. + cstring* {.magic: Cstring.} ## Built-in cstring (*compatible string*) type. + pointer* {.magic: Pointer.} ## Built-in pointer type, use the `addr` + ## operator to get a pointer to a variable. + + typedesc* {.magic: TypeDesc.} ## Meta type to denote a type description. + +type + `ptr`*[T] {.magic: Pointer.} ## Built-in generic untraced pointer type. + `ref`*[T] {.magic: Pointer.} ## Built-in generic traced pointer type. + + `nil` {.magic: "Nil".} + + void* {.magic: "VoidType".} ## Meta type to denote the absence of any type. + auto* {.magic: Expr.} ## Meta type for automatic type determination. + any* {.deprecated: "Deprecated since v1.5; Use auto instead.".} = distinct auto ## Deprecated; Use `auto` instead. See https://github.com/nim-lang/RFCs/issues/281 + 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). type # we need to start a new type section here, so that ``0`` can have a type bool* {.magic: "Bool".} = enum ## Built-in boolean type. @@ -29,15 +59,16 @@ type SomeInteger* = SomeSignedInt|SomeUnsignedInt ## Type class matching all integer types. + SomeFloat* = float|float32|float64 + ## Type class matching all floating point number types. + + SomeNumber* = SomeInteger|SomeFloat + ## Type class matching all number types. + SomeOrdinal* = int|int8|int16|int32|int64|bool|enum|uint|uint8|uint16|uint32|uint64 ## Type class matching all ordinal types; however this includes enums with ## holes. See also `Ordinal` - BiggestInt* = int64 - ## is an alias for the biggest signed integer type the Nim compiler - ## supports. Currently this is `int64`, but it is platform-dependent - ## in general. - {.push warning[GcMem]: off, warning[Uninit]: off.} {.push hints: off.} diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim index bdf2903d2..dd26d140d 100644 --- a/lib/system/chcks.nim +++ b/lib/system/chcks.nim @@ -37,11 +37,11 @@ proc raiseFieldError(f: string) {.compilerproc, noinline.} = when defined(nimV2): proc raiseFieldError2(f: string, discVal: int) {.compilerproc, noinline.} = ## raised when field is inaccessible given runtime value of discriminant - sysFatal(FieldError, f & $discVal & "'") + sysFatal(FieldDefect, f & $discVal & "'") else: proc raiseFieldError2(f: string, discVal: string) {.compilerproc, noinline.} = ## raised when field is inaccessible given runtime value of discriminant - sysFatal(FieldError, formatFieldDefect(f, discVal)) + sysFatal(FieldDefect, formatFieldDefect(f, discVal)) proc raiseRangeErrorI(i, a, b: BiggestInt) {.compilerproc, noinline.} = when defined(standalone): diff --git a/lib/system/comparisons.nim b/lib/system/comparisons.nim index daa47fa59..eedac9d84 100644 --- a/lib/system/comparisons.nim +++ b/lib/system/comparisons.nim @@ -206,6 +206,14 @@ proc `==`*(x, y: uint16): bool {.magic: "EqI", noSideEffect.} proc `==`*(x, y: uint32): bool {.magic: "EqI", noSideEffect.} proc `==`*(x, y: uint64): bool {.magic: "EqI", noSideEffect.} +proc `<=`*(x, y: float32): bool {.magic: "LeF64", noSideEffect.} +proc `<=`*(x, y: float): bool {.magic: "LeF64", noSideEffect.} + +proc `<`*(x, y: float32): bool {.magic: "LtF64", noSideEffect.} +proc `<`*(x, y: float): bool {.magic: "LtF64", noSideEffect.} + +proc `==`*(x, y: float32): bool {.magic: "EqF64", noSideEffect.} +proc `==`*(x, y: float): bool {.magic: "EqF64", noSideEffect.} {.push stackTrace: off.} @@ -220,6 +228,13 @@ proc min*(x, y: int32): int32 {.magic: "MinI", noSideEffect.} = proc min*(x, y: int64): int64 {.magic: "MinI", noSideEffect.} = ## The minimum value of two integers. if x <= y: x else: y +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 min*[T: not SomeFloat](x, y: T): T {.inline.} = + ## Generic minimum operator of 2 values based on `<=`. + if x <= y: x else: y proc max*(x, y: int): int {.magic: "MaxI", noSideEffect.} = if y <= x: x else: y @@ -232,6 +247,13 @@ proc max*(x, y: int32): int32 {.magic: "MaxI", noSideEffect.} = proc max*(x, y: int64): int64 {.magic: "MaxI", noSideEffect.} = ## The maximum value of two integers. if y <= x: 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 max*[T: not SomeFloat](x, y: T): T {.inline.} = + ## Generic maximum operator of 2 values based on `<=`. + if y <= x: x else: y proc min*[T](x: openArray[T]): T = diff --git a/lib/system/compilation.nim b/lib/system/compilation.nim new file mode 100644 index 000000000..6109e9874 --- /dev/null +++ b/lib/system/compilation.nim @@ -0,0 +1,214 @@ +const + NimMajor* {.intdefine.}: int = 1 + ## is the major number of Nim's version. Example: + ## ``` + ## when (NimMajor, NimMinor, NimPatch) >= (1, 3, 1): discard + ## ``` + # see also std/private/since + + NimMinor* {.intdefine.}: int = 7 + ## is the minor number of Nim's version. + ## Odd for devel, even for releases. + + NimPatch* {.intdefine.}: int = 3 + ## is the patch number of Nim's version. + ## Odd for devel, even for releases. + +{.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.} + +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. + +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-compileminustime-symbols>`_ to enable + ## build time conditionals: + ## ``` + ## when not defined(release): + ## # Do here programmer friendly expensive sanity checks. + ## # Put here the normal code + ## ``` + ## + ## See also: + ## * `compileOption <#compileOption,string>`_ for `on|off` options + ## * `compileOption <#compileOption,string,string>`_ for enum options + ## * `define pragmas <manual.html#implementation-specific-pragmas-compileminustime-define-pragmas>`_ + +when defined(nimHasDeclaredMagic): + proc declared*(x: untyped): bool {.magic: "Declared", noSideEffect, compileTime.} + ## Special compile-time procedure that checks whether `x` is + ## declared. `x` has to be an identifier or a qualified identifier. + ## + ## This can be used to check whether a library provides a certain + ## feature or not: + ## ``` + ## when not declared(strutils.toUpper): + ## # provide our own toUpper proc here, because strutils is + ## # missing it. + ## ``` + ## + ## See also: + ## * `declaredInScope <#declaredInScope,untyped>`_ +else: + proc declared*(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.} + +when defined(nimHasDeclaredMagic): + proc declaredInScope*(x: untyped): bool {.magic: "DeclaredInScope", noSideEffect, compileTime.} + ## Special compile-time procedure that checks whether `x` is + ## declared in the current scope. `x` has to be an identifier. +else: + proc declaredInScope*(x: untyped): bool {.magic: "DefinedInScope", noSideEffect, compileTime.} + +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: + ## ``` + ## when compiles(3 + 4): + ## echo "'+' for integers is available" + ## ``` + discard + +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 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. + runnableExamples: + proc timesTwo*(x: int): int = + ## This proc doubles a number. + runnableExamples: + # at module scope + const exported* = 123 + assert timesTwo(5) == 10 + block: # at block scope + defer: echo "done" + runnableExamples "-d:foo -b:cpp": + import std/compilesettings + assert querySetting(backend) == "cpp" + assert defined(foo) + runnableExamples "-r:off": ## this one is only compiled + import std/browsers + openDefaultBrowser "https://forum.nim-lang.org/" + 2 * x + +proc compileOption*(option: string): bool {. + magic: "CompileOption", noSideEffect.} = + ## Can be used to determine an `on|off` compile-time option. + ## + ## See also: + ## * `compileOption <#compileOption,string,string>`_ for enum options + ## * `defined <#defined,untyped>`_ + ## * `std/compilesettings module <compilesettings.html>`_ + runnableExamples("--floatChecks:off"): + static: doAssert not compileOption("floatchecks") + {.push floatChecks: on.} + static: doAssert compileOption("floatchecks") + # floating point NaN and Inf checks enabled in this scope + {.pop.} + +proc compileOption*(option, arg: string): bool {. + magic: "CompileOptionArg", noSideEffect.} = + ## Can be used to determine an enum compile-time option. + ## + ## See also: + ## * `compileOption <#compileOption,string>`_ for `on|off` options + ## * `defined <#defined,untyped>`_ + ## * `std/compilesettings module <compilesettings.html>`_ + runnableExamples: + when compileOption("opt", "size") and compileOption("gc", "boehm"): + discard "compiled with optimization for size and uses Boehm's GC" + +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>`_ + +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 <syncio.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. + ## ``` + ## 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. + ## ``` + ## 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`: + ## ``` + ## 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 diff --git a/lib/system/ctypes.nim b/lib/system/ctypes.nim new file mode 100644 index 000000000..6ba28ed49 --- /dev/null +++ b/lib/system/ctypes.nim @@ -0,0 +1,90 @@ +## Some type definitions for compatibility between different +## backends and platforms. + +type + BiggestInt* = int64 + ## is an alias for the biggest signed integer type the Nim compiler + ## supports. Currently this is `int64`, but it is platform-dependent + ## in general. + + BiggestFloat* = float64 + ## is an alias for the biggest floating point type the Nim + ## compiler supports. Currently this is `float64`, but it is + ## platform-dependent in general. + +when defined(js): + type BiggestUInt* = uint32 + ## is an alias for the biggest unsigned integer type the Nim compiler + ## supports. Currently this is `uint32` for JS and `uint64` for other + ## targets. +else: + type BiggestUInt* = uint64 + ## is an alias for the biggest unsigned integer type the Nim compiler + ## supports. Currently this is `uint32` for JS and `uint64` for other + ## targets. + +when defined(windows): + type + clong* {.importc: "long", nodecl.} = int32 + ## This is the same as the type `long` in *C*. + culong* {.importc: "unsigned long", nodecl.} = uint32 + ## This is the same as the type `unsigned long` in *C*. +else: + type + clong* {.importc: "long", nodecl.} = int + ## This is the same as the type `long` in *C*. + culong* {.importc: "unsigned long", nodecl.} = uint + ## This is the same as the type `unsigned long` in *C*. + +type # these work for most platforms: + cchar* {.importc: "char", nodecl.} = char + ## This is the same as the type `char` in *C*. + cschar* {.importc: "signed char", nodecl.} = int8 + ## This is the same as the type `signed char` in *C*. + cshort* {.importc: "short", nodecl.} = int16 + ## This is the same as the type `short` in *C*. + cint* {.importc: "int", nodecl.} = int32 + ## This is the same as the type `int` in *C*. + csize_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, deprecated: "use `char` or `uint8` instead".} = char + ## Deprecated: Use `uint8` instead. + 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*. + +type + ByteAddress* = int + ## is the signed integer type that should be used for converting + ## pointers to integer addresses for readability. + + 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]`. + +when not defined(nimPreviewSlimSystem): + # pollutes namespace + type + PFloat32* {.deprecated: "use `ptr float32`".} = ptr float32 + ## An alias for `ptr float32`. + PFloat64* {.deprecated: "use `ptr float64`".} = ptr float64 + ## An alias for `ptr float64`. + PInt64* {.deprecated: "use `ptr int64`".} = ptr int64 + ## An alias for `ptr int64`. + PInt32* {.deprecated: "use `ptr int32`".} = ptr int32 + ## An alias for `ptr int32`. diff --git a/lib/system/exceptions.nim b/lib/system/exceptions.nim index 5dcd77bd0..63588f858 100644 --- a/lib/system/exceptions.nim +++ b/lib/system/exceptions.nim @@ -1,61 +1,13 @@ -const NimStackTraceMsgs = - when defined(nimHasStacktraceMsgs): compileOption("stacktraceMsgs") - else: false +## Exception and effect types used in Nim code. type - RootEffect* {.compilerproc.} = object of RootObj ## \ - ## Base effect class. - ## - ## Each effect should inherit from `RootEffect` unless you know what - ## you're doing. TimeEffect* = object of RootEffect ## Time effect. IOEffect* = object of RootEffect ## IO effect. ReadIOEffect* = object of IOEffect ## Effect describing a read IO operation. WriteIOEffect* = object of IOEffect ## Effect describing a write IO operation. ExecIOEffect* = object of IOEffect ## Effect describing an executing IO operation. - 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. +type IOError* = object of CatchableError ## \ ## Raised if an IO error occurred. EOFError* = object of IOError ## \ @@ -144,25 +96,27 @@ type ## ## This is only raised if the `segfaults module <segfaults.html>`_ was imported! - ArithmeticError* {.deprecated: "See corresponding Defect".} = ArithmeticDefect - DivByZeroError* {.deprecated: "See corresponding Defect".} = DivByZeroDefect - OverflowError* {.deprecated: "See corresponding Defect".} = OverflowDefect - AccessViolationError* {.deprecated: "See corresponding Defect".} = AccessViolationDefect - AssertionError* {.deprecated: "See corresponding Defect".} = AssertionDefect - OutOfMemError* {.deprecated: "See corresponding Defect".} = OutOfMemDefect - IndexError* {.deprecated: "See corresponding Defect".} = IndexDefect +when not defined(nimPreviewSlimSystem): + type + ArithmeticError* {.deprecated: "See corresponding Defect".} = ArithmeticDefect + DivByZeroError* {.deprecated: "See corresponding Defect".} = DivByZeroDefect + OverflowError* {.deprecated: "See corresponding Defect".} = OverflowDefect + AccessViolationError* {.deprecated: "See corresponding Defect".} = AccessViolationDefect + AssertionError* {.deprecated: "See corresponding Defect".} = AssertionDefect + OutOfMemError* {.deprecated: "See corresponding Defect".} = OutOfMemDefect + IndexError* {.deprecated: "See corresponding Defect".} = IndexDefect - FieldError* {.deprecated: "See corresponding Defect".} = FieldDefect - RangeError* {.deprecated: "See corresponding Defect".} = RangeDefect - StackOverflowError* {.deprecated: "See corresponding Defect".} = StackOverflowDefect - ReraiseError* {.deprecated: "See corresponding Defect".} = ReraiseDefect - ObjectAssignmentError* {.deprecated: "See corresponding Defect".} = ObjectAssignmentDefect - ObjectConversionError* {.deprecated: "See corresponding Defect".} = ObjectConversionDefect - FloatingPointError* {.deprecated: "See corresponding Defect".} = FloatingPointDefect - FloatInvalidOpError* {.deprecated: "See corresponding Defect".} = FloatInvalidOpDefect - FloatDivByZeroError* {.deprecated: "See corresponding Defect".} = FloatDivByZeroDefect - FloatOverflowError* {.deprecated: "See corresponding Defect".} = FloatOverflowDefect - FloatUnderflowError* {.deprecated: "See corresponding Defect".} = FloatUnderflowDefect - FloatInexactError* {.deprecated: "See corresponding Defect".} = FloatInexactDefect - DeadThreadError* {.deprecated: "See corresponding Defect".} = DeadThreadDefect - NilAccessError* {.deprecated: "See corresponding Defect".} = NilAccessDefect + FieldError* {.deprecated: "See corresponding Defect".} = FieldDefect + RangeError* {.deprecated: "See corresponding Defect".} = RangeDefect + StackOverflowError* {.deprecated: "See corresponding Defect".} = StackOverflowDefect + ReraiseError* {.deprecated: "See corresponding Defect".} = ReraiseDefect + ObjectAssignmentError* {.deprecated: "See corresponding Defect".} = ObjectAssignmentDefect + ObjectConversionError* {.deprecated: "See corresponding Defect".} = ObjectConversionDefect + FloatingPointError* {.deprecated: "See corresponding Defect".} = FloatingPointDefect + FloatInvalidOpError* {.deprecated: "See corresponding Defect".} = FloatInvalidOpDefect + FloatDivByZeroError* {.deprecated: "See corresponding Defect".} = FloatDivByZeroDefect + FloatOverflowError* {.deprecated: "See corresponding Defect".} = FloatOverflowDefect + FloatUnderflowError* {.deprecated: "See corresponding Defect".} = FloatUnderflowDefect + FloatInexactError* {.deprecated: "See corresponding Defect".} = FloatInexactDefect + DeadThreadError* {.deprecated: "See corresponding Defect".} = DeadThreadDefect + NilAccessError* {.deprecated: "See corresponding Defect".} = NilAccessDefect diff --git a/lib/system/indices.nim b/lib/system/indices.nim new file mode 100644 index 000000000..40e7419f6 --- /dev/null +++ b/lib/system/indices.nim @@ -0,0 +1,156 @@ +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]`. + ## + ## ``` + ## let + ## a = [1, 3, 5, 7, 9] + ## b = "abcdefgh" + ## + ## echo a[^1] # => 9 + ## echo b[^2] # => g + ## ``` + +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 `[]`*(s: var string; i: BackwardsIndex): var char {.inline.} = s[s.len - int(i)] + +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 + +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)`. + ## ``` + ## for i in 5 ..< 9: + ## echo i # => 5; 6; 7; 8 + ## ``` + a .. (when b is BackwardsIndex: succ(b) else: pred(b)) + +template `[]`*(s: string; i: int): char = arrGet(s, i) +template `[]=`*(s: string; i: int; val: char) = arrPut(s, i, val) + +template `^^`(s, i: untyped): untyped = + (when i is BackwardsIndex: s.len - int(i) else: int(i)) + +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] + +proc `[]`*[T, U: Ordinal](s: string, x: HSlice[T, U]): string {.inline.} = + ## Slice operation for strings. + ## Returns the inclusive range `[s[x.a], s[x.b]]`: + ## ``` + ## 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: Ordinal](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: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] = + ## Slice operation for arrays. + ## Returns the inclusive range `[a[x.a], a[x.b]]`: + ## ``` + ## 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: Ordinal](a: var array[Idx, T], x: HSlice[U, V], b: openArray[T]) = + ## Slice assignment for arrays. + ## ``` + ## 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: Ordinal](s: openArray[T], x: HSlice[U, V]): seq[T] = + ## Slice operation for sequences. + ## Returns the inclusive range `[s[x.a], s[x.b]]`: + ## ``` + ## 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: Ordinal](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) diff --git a/lib/system/iterators.nim b/lib/system/iterators.nim index 220e341b3..b16a605b7 100644 --- a/lib/system/iterators.nim +++ b/lib/system/iterators.nim @@ -1,3 +1,5 @@ +## Default iterators for some Nim types. + when defined(nimPreviewSlimSystem): import std/assertions diff --git a/lib/system_overview.rst b/lib/system_overview.rst index 768fdcd6d..158069375 100644 --- a/lib/system_overview.rst +++ b/lib/system_overview.rst @@ -5,9 +5,11 @@ The System module imports several separate modules, and their documentation is in separate files: * `iterators <iterators.html>`_ +* `exceptions <exceptions.html>`_ * `assertions <assertions.html>`_ * `dollars <dollars.html>`_ * `widestrs <widestrs.html>`_ +* `ctypes <ctypes.html>`_ Here is a short overview of the most commonly used functions from the diff --git a/lib/windows/winlean.nim b/lib/windows/winlean.nim index 97dc537be..91b0d18c1 100644 --- a/lib/windows/winlean.nim +++ b/lib/windows/winlean.nim @@ -422,10 +422,10 @@ else: importc: "GetCommandLineA", stdcall, dynlib: "kernel32", sideEffect.} proc rdFileTime*(f: FILETIME): int64 = - result = ze64(f.dwLowDateTime) or (ze64(f.dwHighDateTime) shl 32) + result = int64(cast[uint32](f.dwLowDateTime)) or (int64(cast[uint32](f.dwHighDateTime)) shl 32) proc rdFileSize*(f: WIN32_FIND_DATA): int64 = - result = ze64(f.nFileSizeLow) or (ze64(f.nFileSizeHigh) shl 32) + result = int64(cast[uint32](f.nFileSizeLow)) or (int64(cast[uint32](f.nFileSizeHigh)) shl 32) proc getSystemTimeAsFileTime*(lpSystemTimeAsFileTime: var FILETIME) {. importc: "GetSystemTimeAsFileTime", dynlib: "kernel32", stdcall, sideEffect.} |