The compiler depends on the System module to work properly and the System module depends on the compiler. Most of the routines listed here use special compiler magic. Each module implicitly imports the System module; it must not be listed explicitly. Because of this there cannot be a user-defined module named system
.
int
int8
int16
int32
int64
uint
uint8
uint16
uint32
uint64
float
float32
float64
bool = enum false = 0, true = 1
char
string
cstring
pointer
addr
operator to get a pointer to a variable typedesc
Ordinal[T]
ptr[T]
ref[T]
expr
untyped
instead. stmt
typed
instead. void
auto
any = distinct auto
untyped
typed
SomeSignedInt = int | int8 | int16 | int32 | int64
SomeUnsignedInt = uint | uint8 | uint16 | uint32 | uint64
SomeInteger = SomeSignedInt | SomeUnsignedInt
SomeOrdinal = int | int8 | int16 | int32 | int64 | bool | enum | uint8 | uint16 | uint32
SomeReal = float | float32 | float64
SomeNumber = SomeInteger | SomeReal
range[T]
array[I; T]
openArray[T]
varargs[T]
seq[T]
set[T]
UncheckedArray[T] = array[0, T]
Slice[T] = object a*, b*: T ## the bounds
byte = uint8
uint8
, that is an unsigned int 8 bits wide. Natural = range[0 .. high(int)]
Positive = range[1 .. high(int)]
RootObj = object
RootRef = ref RootObj
RootEffect = object of RootObj
TimeEffect = object of RootEffect
IOEffect = object of RootEffect
ReadIOEffect = object of IOEffect
WriteIOEffect = object of IOEffect
ExecIOEffect = object of IOEffect
Exception = object of RootObj 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. trace: string up: ref Exception
Base exception class.
Each exception has to inherit from Exception. See the full exception hierarchy.
SystemError = object of Exception
Abstract class for exceptions that the runtime system raises.
See the full exception hierarchy.
IOError = object of SystemError
Raised if an IO error occurred.
See the full exception hierarchy.
EOFError = object of IOError
Raised if an IO "end of file" error occurred.
See the full exception hierarchy.
OSError = object of SystemError errorCode*: int32 ## OS-defined error code describing this error.
Raised if an operating system service failed.
See the full exception hierarchy.
LibraryError = object of OSError
Raised if a dynamic library could not be loaded.
See the full exception hierarchy.
ResourceExhaustedError = object of SystemError
Raised if a resource request could not be fulfilled.
See the full exception hierarchy.
ArithmeticError = object of Exception
Raised if any kind of arithmetic error occurred.
See the full exception hierarchy.
DivByZeroError = object of ArithmeticError
Raised for runtime integer divide-by-zero errors.
See the full exception hierarchy.
OverflowError = object of ArithmeticError
Raised for runtime integer overflows.
This happens for calculations whose results are too large to fit in the provided bits. See the full exception hierarchy.
AccessViolationError = object of Exception
Raised for invalid memory access errors
See the full exception hierarchy.
AssertionError = object of Exception
Raised when assertion is proved wrong.
Usually the result of using the assert() template. See the full exception hierarchy.
ValueError = object of Exception
KeyError = object of ValueError
Raised if a key cannot be found in a table.
Mostly used by the tables module, it can also be raised by other collection modules like sets or strtabs. See the full exception hierarchy.
OutOfMemError = object of SystemError
Raised for unsuccessful attempts to allocate memory.
See the full exception hierarchy.
IndexError = object of Exception
Raised if an array index is out of bounds.
See the full exception hierarchy.
FieldError = object of Exception
Raised if a record field is not accessible because its dicriminant's value does not fit.
See the full exception hierarchy.
RangeError = object of Exception
Raised if a range check error occurred.
See the full exception hierarchy.
StackOverflowError = object of SystemError
Raised if the hardware stack used for subroutine calls overflowed.
See the full exception hierarchy.
ReraiseError = object of Exception
Raised if there is no exception to reraise.
See the full exception hierarchy.
ObjectAssignmentError = object of Exception
Raised if an object gets assigned to its parent's object.
See the full exception hierarchy.
ObjectConversionError = object of Exception
Raised if an object is converted to an incompatible object type. You can use of
operator to check if conversion will succeed.
See the full exception hierarchy.
FloatingPointError = object of Exception
Base class for floating point exceptions.
See the full exception hierarchy.
FloatInvalidOpError = object of FloatingPointError
Raised by invalid operations according to IEEE.
Raised by 0.0/0.0
, for example. See the full exception hierarchy.
FloatDivByZeroError = object of FloatingPointError
Raised by division by zero.
Divisor is zero and dividend is a finite nonzero number. See the full exception hierarchy.
FloatOverflowError = object of FloatingPointError
Raised for overflows.
The operation produced a result that exceeds the range of the exponent. See the full exception hierarchy.
FloatUnderflowError = object of FloatingPointError
Raised for underflows.
The operation produced a result that is too small to be represented as a normal number. See the full exception hierarchy.
FloatInexactError = object of FloatingPointError
Raised for inexact results.
The operation produced a result that cannot be represented with infinite precision -- for example: 2.0 / 3.0, log(1.1)
NOTE: Nim currently does not detect these! See the full exception hierarchy.
DeadThreadError = object of Exception
Raised if it is attempted to send a message to a dead thread.
See the full exception hierarchy.
NilAccessError = object of SystemError
Raised on dereferences of nil
pointers.
This is only raised if the segfaults.nim
module was imported!
Endianness = enum littleEndian, bigEndian
TaintedString = string
string
if the taint mode is not turned on. ByteAddress = int
BiggestInt = int64
int64
, but it is platform-dependant in general. BiggestFloat = float64
float64
, but it is platform-dependant in general. BiggestUInt = uint64
uint32
for JS and uint64
for other targets. clong = int32
long
in C. culong = uint32
unsigned long
in C. cchar = char
char
in C. cschar = int8
signed char
in C. cshort = int16
short
in C. cint = int32
int
in C. csize = int
size_t
in C. clonglong = int64
long long
in C. cfloat = float32
float
in C. cdouble = float64
double
in C. clongdouble = BiggestFloat
long double
in C. This C type is not supported by Nim's code generator. cuchar = char
unsigned char
in C. cushort = uint16
unsigned short
in C. cuint = uint32
unsigned int
in C. culonglong = uint64
unsigned long long
in C. cstringArray = ptr UncheckedArray[cstring]
char**
in C. The array's high value is large enough to disable bounds checking in practice. Use cstringArrayToSeq to convert it into a seq[string]
. PFloat32 = ptr float32
ptr float32
PFloat64 = ptr float64
ptr float64
PInt64 = ptr int64
ptr int64
PInt32 = ptr int32
ptr int32
GC_Strategy = enum gcThroughput, ## optimize for throughput gcResponsiveness, ## optimize for responsiveness (default) gcOptimizeTime, ## optimize for speed gcOptimizeSpace ## optimize for memory footprint
PFrame = ptr TFrame
TFrame = object prev*: PFrame ## previous frame; used for chaining the call stack procname*: cstring ## name of the proc that is currently executing line*: int ## line number of the proc that is currently executing filename*: cstring ## filename of the proc that is currently executing len*: int16 ## length of the inspectable slots calldepth*: int16 ## used for max call depth checking
FileSeekPos = enum fspSet, ## Seek to absolute value fspCur, ## Seek relative to current position fspEnd ## Seek relative to end
File = ptr CFile
FileMode = enum fmRead, ## Open the file for read access only. fmWrite, ## Open the file for write access only. ## If the file does not exist, it will be ## created. fmReadWrite, ## Open the file for read and write access. ## If the file does not exist, it will be ## created. Existing files will be cleared! fmReadWriteExisting, ## Open the file for read and write access. ## If the file does not exist, it will not be ## created. The existing file will not be cleared. fmAppend ## Open the file for writing only; append data ## at the end.
FileHandle = cint
ForeignCell = object data*: pointer owner: ptr GcHeap
Utf16Char = distinct int16
WideCString = ref UncheckedArray[Utf16Char]
NimNode = ref NimNodeObj
programResult: int
quit
, this value is ignored. globalRaiseHook: proc (e: ref Exception): bool {.nimcall, gcsafe, locks: 0.}
globalRaiseHook
returns false, the exception is caught and does not propagate further through the call stack. localRaiseHook: proc (e: ref Exception): bool {.nimcall, gcsafe, locks: 0.}
localRaiseHook
returns false, the exception is caught and does not propagate further through the call stack. outOfMemHook: proc () {.nimcall, tags: [], gcsafe, locks: 0.}
var gOutOfMem: ref EOutOfMemory new(gOutOfMem) # need to be allocated *before* OOM really happened! gOutOfMem.msg = "out of memory" proc handleOOM() = raise gOutOfMem system.outOfMemHook = handleOOM
If the handler does not raise an exception, ordinary control flow continues and the program is terminated.
stdin: File
stdout: File
stderr: File
errorMessageWriter: (proc (msg: string) {.tags: [WriteIOEffect], gcsafe, locks: 0, nimcall.})
onUnhandledException: (proc (errorMsg: string) {.nimcall.})
stderr
and then call quit(1)
. Unstable API. nimvm: bool = false
on = true
true
off = false
false
appType: string = ""
NoFakeVars = false
isMainModule: bool = false
CompileDate: string = "0000-00-00"
YYYY-MM-DD
. This works thanks to compiler magic. CompileTime: string = "00:00:00"
HH:MM:SS
. This works thanks to compiler magic. cpuEndian: Endianness = littleEndian
hostOS: string = ""
hostCPU: string = ""
nimEnableCovariance = false
QuitSuccess = 0
QuitFailure = 1
Inf = inf
NegInf = -inf
NaN = nan
math
for checking for NaN. NimMajor: int = 0
NimMinor: int = 17
NimPatch: int = 2
NimVersion: string = "0.17.2"
nimCoroutines = false
nativeStackTraceSupported = false
proc `or`(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
proc `and`(a, b: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
proc `not`(a: typedesc): typedesc {.magic: "TypeTrait", noSideEffect.}
proc defined(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
when not defined(release): # Do here programmer friendly expensive sanity checks. # Put here the normal code
proc declared(x: untyped): bool {.magic: "Defined", noSideEffect, compileTime.}
when not declared(strutils.toUpper): # provide our own toUpper proc here, because strutils is # missing it.
proc definedInScope(x: untyped): bool {.magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
declaredInScope
instead. proc declaredInScope(x: untyped): bool {.magic: "DefinedInScope", noSideEffect, compileTime.}
proc `addr`[T](x: var T): ptr T {.magic: "Addr", noSideEffect.}
var buf: seq[char] = @['a','b','c'] p: pointer = buf[1].addr echo cast[ptr char](p)[] # b
proc unsafeAddr[T](x: T): ptr T {.magic: "Addr", noSideEffect.}
let
variables or parameters for better interop with C and so it is considered even more unsafe than the ordinary addr
. When you use it to write a wrapper for a C library, you should always check that the original library does never write to data behind the pointer that is returned from this procedure. Cannot be overloaded. proc `type`(x: untyped): typedesc {.magic: "TypeOf", noSideEffect, compileTime.}
proc `not`(x: bool): bool {.magic: "Not", noSideEffect.}
x == false
. proc `and`(x, y: bool): bool {.magic: "And", noSideEffect.}
and
; returns true iff x == y == true
. Evaluation is lazy: if x
is false, y
will not even be evaluated. proc `or`(x, y: bool): bool {.magic: "Or", noSideEffect.}
or
; returns true iff not (not x and not y)
. Evaluation is lazy: if x
is true, y
will not even be evaluated. proc `xor`(x, y: bool): bool {.magic: "Xor", noSideEffect.}
x != y
. proc new[T](a: var ref T) {.magic: "New", noSideEffect.}
T
and returns a safe (traced) reference to it in a
. proc new(T: typedesc): auto
creates a new object of type T
and returns a safe (traced) reference to it as result value.
When T
is a ref type then the resulting type will be T
, otherwise it will be ref T
.
proc internalNew[T](a: var ref T) {.magic: "New", noSideEffect.}
proc new[T](a: var ref T; finalizer: proc (x: ref T) {.nimcall.}) {.magic: "NewFinalize", noSideEffect.}
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 reset[T](obj: var T) {.magic: "Reset", noSideEffect.}
proc high[T: Ordinal](x: T): T {.magic: "High", noSideEffect.}
high(int)
is Nim's way of writing INT_MAX or MAX_INT.var arr = [1,2,3,4,5,6,7] high(arr) #=> 6 high(2) #=> 9223372036854775807 high(int) #=> 9223372036854775807
proc high[T: Ordinal](x: typedesc[T]): T {.magic: "High", noSideEffect.}
proc high[T](x: openArray[T]): int {.magic: "High", noSideEffect.}
proc high[I, T](x: array[I, T]): I {.magic: "High", noSideEffect.}
proc high[I, T](x: typedesc[array[I, T]]): I {.magic: "High", noSideEffect.}
proc high(x: cstring): int {.magic: "High", noSideEffect.}
proc high(x: string): int {.magic: "High", noSideEffect.}
proc low[T: Ordinal](x: typedesc[T]): T {.magic: "Low", noSideEffect.}
proc low[T](x: openArray[T]): int {.magic: "Low", noSideEffect.}
proc low[I, T](x: array[I, T]): I {.magic: "Low", noSideEffect.}
proc low[T](x: T): T {.magic: "Low", noSideEffect.}
proc low[I, T](x: typedesc[array[I, T]]): I {.magic: "Low", noSideEffect.}
proc low(x: cstring): int {.magic: "Low", noSideEffect.}
proc low(x: string): int {.magic: "Low", noSideEffect.}
var arr = [1,2,3,4,5,6,7] low(arr) #=> 0 low(2) #=> -9223372036854775808 low(int) #=> -9223372036854775808
proc `[]`[I: Ordinal; T](a: T; i: I): T {.noSideEffect, magic: "ArrGet".}
proc `[]=`[I: Ordinal; T, S](a: T; i: I; x: S) {.noSideEffect, magic: "ArrPut".}
proc `=`[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
proc `..`[T](a, b: T): Slice[T] {.noSideEffect, inline, magic: "DotDot".}
[a, b]
, both a and b are inclusive. Slices can also be used in the set constructor and in ordinal case statements, but then they are special-cased by the compiler. proc `..`[T](b: T): Slice[T] {.noSideEffect, inline, magic: "DotDot".}
[default(T), b]
proc `==`[Enum: enum](x, y: Enum): bool {.magic: "EqEnum", noSideEffect.}
type Enum1 = enum Field1 = 3, Field2 Enum2 = enum Place1, Place2 = 3 var e1 = Field1 e2 = Enum1(Place2) echo (e1 == e2) # true echo (e1 == Place2) # raises error
proc `==`(x, y: pointer): bool {.magic: "EqRef", noSideEffect.}
var # this is a wildly dangerous example a = cast[pointer](0) b = cast[pointer](nil) echo (a == b) # true due to the special meaning of `nil`/0 as a pointer
proc `==`(x, y: string): bool {.magic: "EqStr", noSideEffect.}
proc `==`(x, y: char): bool {.magic: "EqCh", noSideEffect.}
proc `==`(x, y: bool): bool {.magic: "EqB", noSideEffect.}
proc `==`[T](x, y: set[T]): bool {.magic: "EqSet", noSideEffect.}
var a = {1, 2, 2, 3} # duplication in sets is ignored var b = {1, 2, 3} echo (a == b) # true
proc `==`[T](x, y: ref T): bool {.magic: "EqRef", noSideEffect.}
proc `==`[T](x, y: ptr T): bool {.magic: "EqRef", noSideEffect.}
proc `==`[T: proc](x, y: T): bool {.magic: "EqProc", noSideEffect.}
proc `<=`[Enum: enum](x, y: Enum): bool {.magic: "LeEnum", noSideEffect.}
proc `<=`(x, y: string): bool {.magic: "LeStr", noSideEffect.}
proc `<=`(x, y: char): bool {.magic: "LeCh", noSideEffect.}
proc `<=`[T](x, y: set[T]): bool {.magic: "LeSet", noSideEffect.}
proc `<=`(x, y: bool): bool {.magic: "LeB", noSideEffect.}
proc `<=`[T](x, y: ref T): bool {.magic: "LePtr", noSideEffect.}
proc `<=`(x, y: pointer): bool {.magic: "LePtr", noSideEffect.}
proc `<`[Enum: enum](x, y: Enum): bool {.magic: "LtEnum", noSideEffect.}
proc `<`(x, y: string): bool {.magic: "LtStr", noSideEffect.}
proc `<`(x, y: char): bool {.magic: "LtCh", noSideEffect.}
proc `<`[T](x, y: set[T]): bool {.magic: "LtSet", noSideEffect.}
proc `<`(x, y: bool): bool {.magic: "LtB", noSideEffect.}
proc `<`[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.}
proc `<`[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.}
proc `<`(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.}
proc unsafeNew[T](a: var ref T; size: Natural) {.magic: "New", noSideEffect.}
T
and returns a safe (traced) reference to it in a
. This is unsafe as it allocates an object of the passed size
. This should only be used for optimization purposes when you know what you're doing! proc sizeof[T](x: T): int {.magic: "SizeOf", noSideEffect.}
returns the size of x
in bytes. Since this is a low-level proc, its usage is discouraged - using new
for the most cases suffices that one never needs to know x
's size. As a special semantic rule, x
may also be a type identifier (sizeof(int)
is valid).
Limitations: If used within nim VM context sizeof
will only work for simple types.
sizeof('A') #=> 1 sizeof(2) #=> 8
proc sizeof(x: typedesc): int {.magic: "SizeOf", noSideEffect.}
proc `<`[T](x: Ordinal[T]): T {.magic: "UnaryLt", noSideEffect.}
<
that can be used for nice looking excluding ranges:for i in 0 .. <10: echo i #=> 0 1 2 3 4 5 6 7 8 9
Semantically this is the same as pred
.
proc succ[T](x: Ordinal[T]; y = 1): T {.magic: "Succ", noSideEffect.}
y
-th successor of the value x
. T
has to be an ordinal type. If such a value does not exist, EOutOfRange
is raised or a compile time error occurs. proc pred[T](x: Ordinal[T]; y = 1): T {.magic: "Pred", noSideEffect.}
y
-th predecessor of the value x
. T
has to be an ordinal type. If such a value does not exist, EOutOfRange
is raised or a compile time error occurs. proc inc[T: Ordinal | uint | uint64](x: var T; y = 1) {.magic: "Inc", noSideEffect.}
x
by y
. If such a value does not exist, EOutOfRange
is raised or a compile time error occurs. This is a short notation for: x = succ(x, y)
.var i = 2 inc(i) #=> 3 inc(i, 3) #=> 6
proc dec[T: Ordinal | uint | uint64](x: var T; y = 1) {.magic: "Dec", noSideEffect.}
x
by y
. If such a value does not exist, EOutOfRange
is raised or a compile time error occurs. This is a short notation for: x = pred(x, y)
.var i = 2 dec(i) #=> 1 dec(i, 3) #=> -2
proc newSeq[T](s: var seq[T]; len: Natural) {.magic: "NewSeq", noSideEffect.}
creates a new sequence of type seq[T]
with length len
. This is equivalent to s = @[]; setlen(s, len)
, but more efficient since no reallocation is needed.
Note that the sequence will be filled with zeroed entries, which can be a problem for sequences containing strings since their value will be nil
. After the creation of the sequence you should assign entries to the sequence instead of adding them. Example:
var inputStrings : seq[string] newSeq(inputStrings, 3) inputStrings[0] = "The fourth" inputStrings[1] = "assignment" inputStrings[2] = "would crash" #inputStrings[3] = "out of bounds"
proc newSeq[T](len = 0.Natural): seq[T]
creates a new sequence of type seq[T]
with length len
.
Note that the sequence will be filled with zeroed entries, which can be a problem for sequences containing strings since their value will be nil
. After the creation of the sequence you should assign entries to the sequence instead of adding them. Example:
var inputStrings = newSeq[string](3) inputStrings[0] = "The fourth" inputStrings[1] = "assignment" inputStrings[2] = "would crash" #inputStrings[3] = "out of bounds"
proc newSeqOfCap[T](cap: Natural): seq[T] {.magic: "NewSeqOfCap", noSideEffect.}
seq[T]
with length 0 and capacity cap
. proc len[TOpenArray: openArray | varargs](x: TOpenArray): int {. magic: "LengthOpenArray", noSideEffect.}
proc len(x: string): int {.magic: "LengthStr", noSideEffect.}
proc len(x: cstring): int {.magic: "LengthStr", noSideEffect.}
proc len(x: (type array) | array): int {.magic: "LengthArray", noSideEffect.}
proc len[T](x: seq[T]): int {.magic: "LengthSeq", noSideEffect.}
high(T)-low(T)+1
, but its resulting type is always an int.var arr = [1,1,1,1,1] len(arr) #=> 5 for i in 0..<arr.len: echo arr[i] #=> 1,1,1,1,1
proc incl[T](x: var set[T]; y: T) {.magic: "Incl", noSideEffect.}
y
to the set x
. This is the same as x = x + {y}
, but it might be more efficient.var a = initSet[int](4) a.incl(2) #=> {2} a.incl(3) #=> {2, 3}
proc excl[T](x: var set[T]; y: T) {.magic: "Excl", noSideEffect.}
y
to the set x
. This is the same as x = x - {y}
, but it might be more efficient.var b = {2,3,5,6,12,545} b.excl(5) #=> {2,3,6,12,545}
proc card[T](x: set[T]): int {.magic: "Card", noSideEffect.}
x
, i.e. the number of elements in the set.var i = {1,2,3,4} card(i) #=> 4
proc ord[T](x: T): int {.magic: "Ord", noSideEffect.}
x
.ord('A') #=> 65
proc chr(u: range[0 .. 255]): char {.magic: "Chr", noSideEffect.}
chr(65) #=> A
proc ze(x: int8): int {.magic: "Ze8ToI", noSideEffect.}
int
. This treats x as unsigned. proc ze(x: int16): int {.magic: "Ze16ToI", noSideEffect.}
int
. This treats x as unsigned. proc ze64(x: int8): int64 {.magic: "Ze8ToI64", noSideEffect.}
int64
. This treats x as unsigned. proc ze64(x: int16): int64 {.magic: "Ze16ToI64", noSideEffect.}
int64
. This treats x as unsigned. proc ze64(x: int32): int64 {.magic: "Ze32ToI64", noSideEffect.}
int64
. This treats x as unsigned. proc ze64(x: int): int64 {.magic: "ZeIToI64", noSideEffect.}
int64
. This treats x as unsigned. Does nothing if the size of an int
is the same as int64
. (This is the case on 64 bit processors.) proc toU8(x: int): int8 {.magic: "ToU8", noSideEffect.}
proc toU16(x: int): int16 {.magic: "ToU16", noSideEffect.}
int16
by taking the last 16 bits from x. proc toU32(x: int64): int32 {.magic: "ToU32", noSideEffect.}
int32
by taking the last 32 bits from x. proc `+`(x: int): int {.magic: "UnaryPlusI", noSideEffect.}
proc `+`(x: int8): int8 {.magic: "UnaryPlusI", noSideEffect.}
proc `+`(x: int16): int16 {.magic: "UnaryPlusI", noSideEffect.}
proc `+`(x: int32): int32 {.magic: "UnaryPlusI", noSideEffect.}
proc `+`(x: int64): int64 {.magic: "UnaryPlusI", noSideEffect.}
proc `-`(x: int): int {.magic: "UnaryMinusI", noSideEffect.}
proc `-`(x: int8): int8 {.magic: "UnaryMinusI", noSideEffect.}
proc `-`(x: int16): int16 {.magic: "UnaryMinusI", noSideEffect.}
proc `-`(x: int32): int32 {.magic: "UnaryMinusI", noSideEffect.}
proc `-`(x: int64): int64 {.magic: "UnaryMinusI64", noSideEffect.}
proc `not`(x: int): int {.magic: "BitnotI", noSideEffect.}
proc `not`(x: int8): int8 {.magic: "BitnotI", noSideEffect.}
proc `not`(x: int16): int16 {.magic: "BitnotI", noSideEffect.}
proc `not`(x: int32): int32 {.magic: "BitnotI", noSideEffect.}
proc `not`(x: int64): int64 {.magic: "BitnotI", noSideEffect.}
proc `+`(x, y: int): int {.magic: "AddI", noSideEffect.}
proc `+`(x, y: int8): int8 {.magic: "AddI", noSideEffect.}
proc `+`(x, y: int16): int16 {.magic: "AddI", noSideEffect.}
proc `+`(x, y: int32): int32 {.magic: "AddI", noSideEffect.}
proc `+`(x, y: int64): int64 {.magic: "AddI", noSideEffect.}
proc `-`(x, y: int): int {.magic: "SubI", noSideEffect.}
proc `-`(x, y: int8): int8 {.magic: "SubI", noSideEffect.}
proc `-`(x, y: int16): int16 {.magic: "SubI", noSideEffect.}
proc `-`(x, y: int32): int32 {.magic: "SubI", noSideEffect.}
proc `-`(x, y: int64): int64 {.magic: "SubI", noSideEffect.}
proc `*`(x, y: int): int {.magic: "MulI", noSideEffect.}
proc `*`(x, y: int8): int8 {.magic: "MulI", noSideEffect.}
proc `*`(x, y: int16): int16 {.magic: "MulI", noSideEffect.}
proc `*`(x, y: int32): int32 {.magic: "MulI", noSideEffect.}
proc `*`(x, y: int64): int64 {.magic: "MulI", noSideEffect.}
proc `div`(x, y: int): int {.magic: "DivI", noSideEffect.}
proc `div`(x, y: int8): int8 {.magic: "DivI", noSideEffect.}
proc `div`(x, y: int16): int16 {.magic: "DivI", noSideEffect.}
proc `div`(x, y: int32): int32 {.magic: "DivI", noSideEffect.}
floor(x/y)
.1 div 2 == 0 2 div 2 == 1 3 div 2 == 1 7 div 5 == 1
proc `div`(x, y: int64): int64 {.magic: "DivI", noSideEffect.}
proc `mod`(x, y: int): int {.magic: "ModI", noSideEffect.}
proc `mod`(x, y: int8): int8 {.magic: "ModI", noSideEffect.}
proc `mod`(x, y: int16): int16 {.magic: "ModI", noSideEffect.}
proc `mod`(x, y: int32): int32 {.magic: "ModI", noSideEffect.}
x - (x div y) * y
.(7 mod 5) == 2
proc `mod`(x, y: int64): int64 {.magic: "ModI", noSideEffect.}
proc `shr`(x: int; y: SomeInteger): int {.magic: "ShrI", noSideEffect.}
proc `shr`(x: int8; y: SomeInteger): int8 {.magic: "ShrI", noSideEffect.}
proc `shr`(x: int16; y: SomeInteger): int16 {.magic: "ShrI", noSideEffect.}
proc `shr`(x: int32; y: SomeInteger): int32 {.magic: "ShrI", noSideEffect.}
proc `shr`(x: int64; y: SomeInteger): int64 {.magic: "ShrI", noSideEffect.}
0b0001_0000'i8 shr 2 == 0b0000_0100'i8 0b1000_0000'i8 shr 8 == 0b0000_0000'i8 0b0000_0001'i8 shr 1 == 0b0000_0000'i8
proc `shl`(x: int; y: SomeInteger): int {.magic: "ShlI", noSideEffect.}
proc `shl`(x: int8; y: SomeInteger): int8 {.magic: "ShlI", noSideEffect.}
proc `shl`(x: int16; y: SomeInteger): int16 {.magic: "ShlI", noSideEffect.}
proc `shl`(x: int32; y: SomeInteger): int32 {.magic: "ShlI", noSideEffect.}
proc `shl`(x: int64; y: SomeInteger): int64 {.magic: "ShlI", noSideEffect.}
1'i32 shl 4 == 0x0000_0010 1'i64 shl 4 == 0x0000_0000_0000_0010
proc `and`(x, y: int): int {.magic: "BitandI", noSideEffect.}
proc `and`(x, y: int8): int8 {.magic: "BitandI", noSideEffect.}
proc `and`(x, y: int16): int16 {.magic: "BitandI", noSideEffect.}
proc `and`(x, y: int32): int32 {.magic: "BitandI", noSideEffect.}
proc `and`(x, y: int64): int64 {.magic: "BitandI", noSideEffect.}
(0xffff'i16 and 0x0010'i16) == 0x0010
proc `or`(x, y: int): int {.magic: "BitorI", noSideEffect.}
proc `or`(x, y: int8): int8 {.magic: "BitorI", noSideEffect.}
proc `or`(x, y: int16): int16 {.magic: "BitorI", noSideEffect.}
proc `or`(x, y: int32): int32 {.magic: "BitorI", noSideEffect.}
proc `or`(x, y: int64): int64 {.magic: "BitorI", noSideEffect.}
(0x0005'i16 or 0x0010'i16) == 0x0015
proc `xor`(x, y: int): int {.magic: "BitxorI", noSideEffect.}
proc `xor`(x, y: int8): int8 {.magic: "BitxorI", noSideEffect.}
proc `xor`(x, y: int16): int16 {.magic: "BitxorI", noSideEffect.}
proc `xor`(x, y: int32): int32 {.magic: "BitxorI", noSideEffect.}
proc `xor`(x, y: int64): int64 {.magic: "BitxorI", noSideEffect.}
(0x1011'i16 xor 0x0101'i16) == 0x1110
proc `==`(x, y: int): bool {.magic: "EqI", noSideEffect.}
proc `==`(x, y: int8): bool {.magic: "EqI", noSideEffect.}
proc `==`(x, y: int16): bool {.magic: "EqI", noSideEffect.}
proc `==`(x, y: int32): bool {.magic: "EqI", noSideEffect.}
proc `==`(x, y: int64): bool {.magic: "EqI", noSideEffect.}
proc `<=`(x, y: int): bool {.magic: "LeI", noSideEffect.}
proc `<=`(x, y: int8): bool {.magic: "LeI", noSideEffect.}
proc `<=`(x, y: int16): bool {.magic: "LeI", noSideEffect.}
proc `<=`(x, y: int32): bool {.magic: "LeI", noSideEffect.}
proc `<=`(x, y: int64): bool {.magic: "LeI", noSideEffect.}
proc `<`(x, y: int): bool {.magic: "LtI", noSideEffect.}
proc `<`(x, y: int8): bool {.magic: "LtI", noSideEffect.}
proc `<`(x, y: int16): bool {.magic: "LtI", noSideEffect.}
proc `<`(x, y: int32): bool {.magic: "LtI", noSideEffect.}
proc `<`(x, y: int64): bool {.magic: "LtI", noSideEffect.}
proc `+%`(x, y: IntMax32): IntMax32 {.magic: "AddU", noSideEffect.}
proc `+%`(x, y: int64): int64 {.magic: "AddU", noSideEffect.}
proc `-%`(x, y: IntMax32): IntMax32 {.magic: "SubU", noSideEffect.}
proc `-%`(x, y: int64): int64 {.magic: "SubU", noSideEffect.}
proc `*%`(x, y: IntMax32): IntMax32 {.magic: "MulU", noSideEffect.}
proc `*%`(x, y: int64): int64 {.magic: "MulU", noSideEffect.}
proc `/%`(x, y: IntMax32): IntMax32 {.magic: "DivU", noSideEffect.}
proc `/%`(x, y: int64): int64 {.magic: "DivU", noSideEffect.}
proc `%%`(x, y: IntMax32): IntMax32 {.magic: "ModU", noSideEffect.}
proc `%%`(x, y: int64): int64 {.magic: "ModU", noSideEffect.}
proc `<=%`(x, y: IntMax32): bool {.magic: "LeU", noSideEffect.}
proc `<=%`(x, y: int64): bool {.magic: "LeU64", noSideEffect.}
unsigned(x) <= unsigned(y)
. proc `<%`(x, y: IntMax32): bool {.magic: "LtU", noSideEffect.}
proc `<%`(x, y: int64): bool {.magic: "LtU64", noSideEffect.}
unsigned(x) < unsigned(y)
. proc `not`[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.}
proc `shr`[T: SomeUnsignedInt](x: T; y: SomeInteger): T {.magic: "ShrI", noSideEffect.}
proc `shl`[T: SomeUnsignedInt](x: T; y: SomeInteger): T {.magic: "ShlI", noSideEffect.}
proc `and`[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.}
proc `or`[T: SomeUnsignedInt](x, y: T): T {.magic: "BitorI", noSideEffect.}
proc `xor`[T: SomeUnsignedInt](x, y: T): T {.magic: "BitxorI", noSideEffect.}
proc `==`[T: SomeUnsignedInt](x, y: T): bool {.magic: "EqI", noSideEffect.}
proc `+`[T: SomeUnsignedInt](x, y: T): T {.magic: "AddU", noSideEffect.}
proc `-`[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.}
proc `*`[T: SomeUnsignedInt](x, y: T): T {.magic: "MulU", noSideEffect.}
proc `div`[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
floor(x/y)
.(7 div 5) == 1
proc `mod`[T: SomeUnsignedInt](x, y: T): T {.magic: "ModU", noSideEffect.}
x - (x div y) * y
.(7 mod 5) == 2
proc `<=`[T: SomeUnsignedInt](x, y: T): bool {.magic: "LeU", noSideEffect.}
x <= y
. proc `<`[T: SomeUnsignedInt](x, y: T): bool {.magic: "LtU", noSideEffect.}
unsigned(x) < unsigned(y)
. 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.}
proc `*`[T](x, y: set[T]): set[T] {.magic: "MulSet", noSideEffect.}
proc `+`[T](x, y: set[T]): set[T] {.magic: "PlusSet", noSideEffect.}
proc `-`[T](x, y: set[T]): set[T] {.magic: "MinusSet", noSideEffect.}
proc contains[T](x: set[T]; y: T): bool {.magic: "InSet", noSideEffect.}
in
operator. The parameters are in reverse order! a in b
is a template for contains(b, a)
. This is because the unification algorithm that Nim uses for overload resolution works from left to right. But for the in
operator that would be the wrong direction for this piece of code:var s: set[range['a'..'z']] = {'a'..'c'} writeLine(stdout, 'b' in s)
If in
had been declared as [T](elem: T, s: set[T])
then T
would have been bound to char
. But s
is not compatible to type set[char]
! The solution is to bind T
to range['a'..'z']
. This is achieved by reversing the parameters for contains
; in
then passes its arguments in reverse order.
proc contains[T](s: Slice[T]; value: T): bool {.noSideEffect, inline.}
assert((1..3).contains(1) == true) assert((1..3).contains(2) == true) assert((1..3).contains(4) == false)
proc `is`[T, S](x: T; y: S): bool {.magic: "Is", noSideEffect.}
proc test[T](a: T): int = when (T is int): return a else: return 0 assert(test[int](3) == 3) assert(test[string]("xyz") == 0)
proc `of`[T, S](x: typedesc[T]; y: typedesc[S]): bool {.magic: "Of", noSideEffect.}
proc `of`[T, S](x: T; y: typedesc[S]): bool {.magic: "Of", noSideEffect.}
proc `of`[T, S](x: T; y: S): bool {.magic: "Of", noSideEffect.}
assert(FloatingPointError of Exception) assert(DivByZeroError of Exception)
proc cmp[T](x, y: T): int {.procvar.}
import algorithm echo sorted(@[4,2,6,5,8,7], cmp[int])
proc `@`[IDX, T](a: array[IDX, T]): seq[T] {.magic: "ArrToSeq", nosideeffect.}
@[1, 2, 3]
has the type seq[int]
, while [1, 2, 3]
has the type array[0..2, int]
. proc setLen[T](s: var seq[T]; newlen: Natural) {.magic: "SetLengthSeq", noSideEffect.}
T
may be any sequence type. If the current length is greater than the new length, s
will be truncated. s cannot be nil! To initialize a sequence with a size, use newSeq
instead. proc setLen(s: var string; newlen: Natural) {.magic: "SetLengthStr", noSideEffect.}
s
will be truncated. s cannot be nil! To initialize a string with a size, use newString
instead.var myS = "Nim is great!!" myS.setLen(3) echo myS, " is fantastic!!"
proc newString(len: Natural): string {.magic: "NewString", importc: "mnewString", noSideEffect.}
len
but with uninitialized content. One needs to fill the string character after character with the index operator s[i]
. This procedure exists only for optimization purposes; the same effect can be achieved with the &
operator or with add
. proc newStringOfCap(cap: Natural): string {.magic: "NewStringOfCap", importc: "rawNewString", noSideEffect.}
0
but with capacity cap.This procedure exists only for optimization purposes; the same effect can be achieved with the &
operator or with add
. proc `&`(x: string; y: char): string {.magic: "ConStrStr", noSideEffect, merge.}
assert("ab" & 'c' == "abc")
proc `&`(x, y: char): string {.magic: "ConStrStr", noSideEffect, merge.}
assert('a' & 'b' == "ab")
proc `&`(x, y: string): string {.magic: "ConStrStr", noSideEffect, merge.}
assert("ab" & "cd" == "abcd")
proc `&`(x: char; y: string): string {.magic: "ConStrStr", noSideEffect, merge.}
assert('a' & "bc" == "abc")
proc add(x: var string; y: char) {.magic: "AppendStrCh", noSideEffect.}
var tmp = "" tmp.add('a') tmp.add('b') assert(tmp == "ab")
proc add(x: var string; y: string) {.magic: "AppendStrStr", noSideEffect.}
var tmp = "" tmp.add("ab") tmp.add("cd") assert(tmp == "abcd")
proc compileOption(option: string): bool {.magic: "CompileOption", noSideEffect.}
when compileOption("floatchecks"): echo "compiled with floating point NaN and Inf checks"
proc compileOption(option, arg: string): bool {.magic: "CompileOptionArg", noSideEffect.}
when compileOption("opt", "size") and compileOption("gc", "boehm"): echo "compiled with optimization for size and uses Boehm's GC"
proc quit(errorcode: int = QuitSuccess) {.magic: "Exit", noreturn.}
Stops the program immediately with an exit code.
Before stopping the program the "quit procedures" are called in the opposite order they were added with addQuitProc. quit
never returns and ignores any exception that may have been raised by the quit procedures. It does not call the garbage collector to free all the memory, unless a quit procedure calls GC_fullCollect.
The proc quit(QuitSuccess)
is called implicitly when your nim program finishes without incident. A raised unhandled exception is equivalent to calling quit(QuitFailure)
.
Note that this is a runtime call and using quit
inside a macro won't have any compile time effect. If you need to stop the compiler inside a macro, use the error or fatal pragmas.
proc add[T](x: var seq[T]; y: T) {.magic: "AppendSeqElem", noSideEffect.}
proc add[T](x: var seq[T]; y: openArray[T]) {.noSideEffect.}
var s: seq[string] = @["test2","test2"] s.add("test") #=> @[test2, test2, test]
proc shallowCopy[T](x: var T; y: T) {.noSideEffect, magic: "ShallowCopy".}
proc del[T](x: var seq[T]; i: Natural) {.noSideEffect.}
x[high(x)]
into position i. This is an O(1) operation.var i = @[1, 2, 3, 4, 5] i.del(2) #=> @[1, 2, 5, 4]
proc delete[T](x: var seq[T]; i: Natural) {.noSideEffect.}
x[i+1..]
by one position. This is an O(n) operation.var i = @[1, 2, 3, 4, 5] i.delete(2) #=> @[1, 2, 4, 5]
proc insert[T](x: var seq[T]; item: T; i = 0.Natural) {.noSideEffect.}
var i = @[1, 2, 3, 4, 5] i.insert(2, 4) #=> @[1, 2, 3, 4, 2, 5]
proc repr[T](x: T): string {.magic: "Repr", noSideEffect.}
var s: seq[string] = @["test2", "test2"] var i = @[1, 2, 3, 4, 5] repr(s) #=> 0x1055eb050[0x1055ec050"test2", 0x1055ec078"test2"] repr(i) #=> 0x1055ed050[1, 2, 3, 4, 5]
proc toFloat(i: int): float {.magic: "ToFloat", noSideEffect, importc: "toFloat".}
float
. If the conversion fails, EInvalidValue is raised. However, on most platforms the conversion cannot fail. proc toBiggestFloat(i: BiggestInt): BiggestFloat {.magic: "ToBiggestFloat", noSideEffect, importc: "toBiggestFloat".}
biggestfloat
. If the conversion fails, EInvalidValue is raised. However, on most platforms the conversion cannot fail. proc toInt(f: float): int {.magic: "ToInt", noSideEffect, importc: "toInt".}
int
. Conversion rounds f if it does not contain an integer value. If the conversion fails (because f is infinite for example), EInvalidValue is raised. proc toBiggestInt(f: BiggestFloat): BiggestInt {.magic: "ToBiggestInt", noSideEffect, importc: "toBiggestInt".}
biggestint
. Conversion rounds f if it does not contain an integer value. If the conversion fails (because f is infinite for example), EInvalidValue is raised. proc addQuitProc(QuitProc: proc () {.noconv.}) {.importc: "atexit", header: "<stdlib.h>".}
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.
proc copy(s: string; first = 0): string {.magic: "CopyStr", importc: "copyStr", noSideEffect, deprecated.}
proc copy(s: string; first, last: int): string {.magic: "CopyStrLast", importc: "copyStrLast", noSideEffect, deprecated.}
last
is omitted, it is treated as high(s)
. Deprecated since version 0.8.12: Use substr
instead. proc substr(s: string; first = 0): string {.magic: "CopyStr", importc: "copyStr", noSideEffect.}
proc substr(s: string; first, last: int): string {.magic: "CopyStrLast", importc: "copyStrLast", noSideEffect.}
last
is omitted, it is treated as high(s)
. If last >= s.len
, s.len
is used instead: This means substr
can also be used to cut or limit a string's length. proc createU(T: typedesc; size = 1.Positive): ptr T:type {.inline, gcsafe, locks: 0.}
T.sizeof * size
bytes. The block has to be freed with resize(block, 0)
or free(block)
. The block is not initialized, so reading from it before writing to it is undefined behaviour! The allocated memory belongs to its allocating thread! Use createSharedU to allocate from a shared heap. proc create(T: typedesc; size = 1.Positive): ptr T:type {.inline, gcsafe, locks: 0.}
T.sizeof * size
bytes. The block has to be freed with resize(block, 0)
or free(block)
. The block is initialized with all bytes containing zero, so it is somewhat safer than createU
. The allocated memory belongs to its allocating thread! Use createShared to allocate from a shared heap. proc resize[T](p: ptr T; newSize: Natural): ptr T {.inline, gcsafe, locks: 0.}
T.sizeof * newSize
bytes. If newSize == 0
and p is not nil resize
calls free(p)
. In other cases the block has to be freed with free
. The allocated memory belongs to its allocating thread! Use resizeShared to reallocate from a shared heap. T.sizeof * size
bytes. The block has to be freed with resizeShared(block, 0)
or freeShared(block)
. The block is not initialized, so reading from it before writing to it is undefined behaviour! T.sizeof * size
bytes. The block has to be freed with resizeShared(block, 0)
or freeShared(block)
. The block is initialized with all bytes containing zero, so it is somewhat safer than createSharedU
. T.sizeof * newSize
bytes. If newSize == 0
and p is not nil resizeShared
calls freeShared(p)
. In other cases the block has to be freed with freeShared
. createShared
, createSharedU
or resizeShared
. This procedure is dangerous! If one forgets to free the memory a leak occurs; if one tries to access freed memory (or just freeing it twice!) a core dump may happen or other memory may be corrupted. proc swap[T](a, b: var T) {.magic: "Swap", noSideEffect.}
tmp = a; a = b; b = tmp
. Particularly useful for sorting algorithms. proc `$`(x: int): string {.magic: "IntToStr", noSideEffect.}
$
is Nim's general way of spelling toString. proc `$`(x: int64): string {.magic: "Int64ToStr", noSideEffect.}
proc `$`(x: float): string {.magic: "FloatToStr", noSideEffect.}
proc `$`(x: bool): string {.magic: "BoolToStr", noSideEffect.}
proc `$`(x: char): string {.magic: "CharToStr", noSideEffect.}
proc `$`(x: cstring): string {.magic: "CStrToStr", noSideEffect.}
proc `$`(x: string): string {.magic: "StrToStr", noSideEffect.}
$expr
also works if expr
is already a string. proc `$`[Enum: enum](x: Enum): string {.magic: "EnumToStr", noSideEffect.}
$
operator for a concrete enumeration is provided, this is used instead. (In other words: Overwriting is possible.) proc getRefcount[T](x: ref T): int {.importc: "getRefcount", noSideEffect.}
proc getRefcount(x: string): int {.importc: "getRefcount", noSideEffect.}
proc getRefcount[T](x: seq[T]): int {.importc: "getRefcount", noSideEffect.}
proc min(x, y: int): int {.magic: "MinI", noSideEffect, raises: [], tags: [].}
proc min(x, y: int8): int8 {.magic: "MinI", noSideEffect, raises: [], tags: [].}
proc min(x, y: int16): int16 {.magic: "MinI", noSideEffect, raises: [], tags: [].}
proc min(x, y: int32): int32 {.magic: "MinI", noSideEffect, raises: [], tags: [].}
proc min(x, y: int64): int64 {.magic: "MinI", noSideEffect, raises: [], tags: [].}
proc min[T](x: openArray[T]): T
T
needs to have a <
operator. proc max(x, y: int): int {.magic: "MaxI", noSideEffect, raises: [], tags: [].}
proc max(x, y: int8): int8 {.magic: "MaxI", noSideEffect, raises: [], tags: [].}
proc max(x, y: int16): int16 {.magic: "MaxI", noSideEffect, raises: [], tags: [].}
proc max(x, y: int32): int32 {.magic: "MaxI", noSideEffect, raises: [], tags: [].}
proc max(x, y: int64): int64 {.magic: "MaxI", noSideEffect, raises: [], tags: [].}
proc max[T](x: openArray[T]): T
T
needs to have a <
operator. proc abs(x: float): float {.magic: "AbsF64", noSideEffect, raises: [], tags: [].}
proc min(x, y: float): float {.magic: "MinF64", noSideEffect, raises: [], tags: [].}
proc max(x, y: float): float {.magic: "MaxF64", noSideEffect, raises: [], tags: [].}
proc min[T](x, y: T): T
proc max[T](x, y: T): T
proc clamp[T](x, a, b: T): T
x
within the interval [a, b]assert((1.4).clamp(0.0, 1.0) == 1.0) assert((0.5).clamp(0.0, 1.0) == 0.5)
proc len[T: Ordinal](x: Slice[T]): int {.noSideEffect, inline.}
assert((0..5).len == 6) assert((5..2).len == 0)
proc isNil[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil".}
proc isNil[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil(x: string): bool {.noSideEffect, magic: "IsNil".}
proc isNil[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
proc isNil(x: pointer): bool {.noSideEffect, magic: "IsNil".}
proc isNil(x: cstring): bool {.noSideEffect, magic: "IsNil".}
proc isNil[T: proc](x: T): bool {.noSideEffect, magic: "IsNil".}
== nil
. proc `==`[I, T](x, y: array[I, T]): bool
proc `@`[T](a: openArray[T]): seq[T]
proc `&`[T](x, y: seq[T]): seq[T] {.noSideEffect.}
assert(@[1, 2, 3, 4] & @[5, 6] == @[1, 2, 3, 4, 5, 6])
proc `&`[T](x: seq[T]; y: T): seq[T] {.noSideEffect.}
assert(@[1, 2, 3] & 4 == @[1, 2, 3, 4])
proc `&`[T](x: T; y: seq[T]): seq[T] {.noSideEffect.}
assert(1 & @[2, 3, 4] == @[1, 2, 3, 4])
proc `==`[T](x, y: seq[T]): bool {.noSideEffect.}
proc find[T, S](a: T; item: S): int {.inline.}
proc contains[T](a: openArray[T]; item: T): bool {.inline.}
find(a, item) >= 0
. proc pop[T](s: var seq[T]): T {.inline, noSideEffect.}
s.len
by one. This treats s as a stack and implements the common pop operation. proc `==`[T: tuple | object](x, y: T): bool
==
operator for tuples that is lifted from the components of x and y. proc `<=`[T: tuple](x, y: T): bool
<=
operator for tuples that is lifted from the components of x and y. This implementation uses cmp. proc `<`[T: tuple](x, y: T): bool
<
operator for tuples that is lifted from the components of x and y. This implementation uses cmp. proc `$`[T: tuple | object](x: T): string
$
operator for tuples that is lifted from the components of x. Example:$(23, 45) == "(23, 45)" $() == "()"
proc `$`[T](x: set[T]): string
$
operator for sets that is lifted from the components of x. Example:${23, 45} == "{23, 45}"
proc `$`[T](x: seq[T]): string
$
operator for seqs that is lifted from the components of x. Example:$(@[23, 45]) == "@[23, 45]"
proc GC_ref[T](x: ref T) {.magic: "GCref", gcsafe, locks: 0.}
proc GC_ref[T](x: seq[T]) {.magic: "GCref", gcsafe, locks: 0.}
proc GC_ref(x: string) {.magic: "GCref", gcsafe, locks: 0.}
proc GC_unref[T](x: ref T) {.magic: "GCunref", gcsafe, locks: 0.}
proc GC_unref[T](x: seq[T]) {.magic: "GCunref", gcsafe, locks: 0.}
proc GC_unref(x: string) {.magic: "GCunref", gcsafe, locks: 0.}
proc add(x: var string; y: cstring) {.raises: [], tags: [].}
proc echo(x: varargs[typed, `$`]) {.magic: "Echo", tags: [WriteIOEffect], gcsafe, locks: 0, sideEffect.}
Writes and flushes the parameters to the standard output.
Special built-in that takes a variable number of arguments. Each argument is converted to a string via $
, so it works for user-defined types that have an overloaded $
operator. It is roughly equivalent to writeLine(stdout, x); flushFile(stdout)
, but available for the JavaScript target too.
Unlike other IO operations this is guaranteed to be thread-safe as echo
is very often used for debugging convenience. If you want to use echo
inside a proc without side effects you can use debugEcho instead.
proc debugEcho(x: varargs[typed, `$`]) {.magic: "Echo", noSideEffect, tags: [], raises: [].}
debugEcho
pretends to be free of side effects, so that it can be used for debugging routines marked as noSideEffect. proc getTypeInfo[T](x: T): pointer {.magic: "GetTypeInfo", gcsafe, locks: 0.}
proc abs(x: int): int {.magic: "AbsI", noSideEffect, raises: [], tags: [].}
proc abs(x: int8): int8 {.magic: "AbsI", noSideEffect, raises: [], tags: [].}
proc abs(x: int16): int16 {.magic: "AbsI", noSideEffect, raises: [], tags: [].}
proc abs(x: int32): int32 {.magic: "AbsI", noSideEffect, raises: [], tags: [].}
proc abs(x: int64): int64 {.magic: "AbsI", noSideEffect, raises: [], tags: [].}
low(x)
(that is -MININT for its type), an overflow exception is thrown (if overflow checking is turned on). proc cmp(x, y: string): int {.noSideEffect, procvar, raises: [], tags: [].}
proc open(f: var File; filename: string; mode: FileMode = fmRead; bufSize: int = -1): bool {. tags: [], gcsafe, locks: 0, raises: [].}
Opens a file named filename with given mode.
Default mode is readonly. Returns true iff the file could be opened. This throws no exception if the file could not be opened.
proc open(f: var File; filehandle: FileHandle; mode: FileMode = fmRead): bool {.tags: [], gcsafe, locks: 0, raises: [].}
Creates a File
from a filehandle with given mode.
Default mode is readonly. Returns true iff the file could be opened.
proc open(filename: string; mode: FileMode = fmRead; bufSize: int = -1): File {. raises: [Exception, IOError], tags: [].}
Opens a file named filename with given mode.
Default mode is readonly. Raises an IO
exception if the file could not be opened.
proc reopen(f: File; filename: string; mode: FileMode = fmRead): bool {.tags: [], gcsafe, locks: 0, raises: [].}
reopens the file f with given filename and mode. This is often used to redirect the stdin, stdout or stderr file variables.
Default mode is readonly. Returns true iff the file could be reopened.
proc setStdIoUnbuffered() {.tags: [], gcsafe, locks: 0, raises: [].}
proc close(f: File) {.tags: [], gcsafe, raises: [].}
proc endOfFile(f: File): bool {.tags: [], gcsafe, locks: 0, raises: [].}
proc readChar(f: File): char {.tags: [ReadIOEffect], deprecated, raises: [IOError, EOFError].}
readBuffer
instead. proc flushFile(f: File) {.tags: [WriteIOEffect], raises: [].}
proc readAll(file: File): TaintedString {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
Reads all data from the stream file.
Raises an IO exception in case of an error. It is an error if the current file position is not at the beginning of the file.
proc readFile(filename: string): TaintedString {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
Opens a file named filename for reading.
Then calls readAll and closes the file afterwards. Returns the string. Raises an IO exception in case of an error. If you need to call this inside a compile time macro you can use staticRead.
proc writeFile(filename, content: string) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; r: float32) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; i: int) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; i: BiggestInt) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; r: BiggestFloat) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; s: string) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; b: bool) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; c: char) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [].}
proc write(f: File; c: cstring) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; a: varargs[string, `$`]) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc readLine(f: File): TaintedString {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError, EOFError].}
LF
or CRLF
. The newline character(s) are not part of the returned string. proc readLine(f: File; line: var TaintedString): bool {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
nil
! May throw an IO exception. A line of text may be delimited by LF
or CRLF
. The newline character(s) are not part of the returned string. Returns false
if the end of the file has been reached, true
otherwise. If false
is returned line contains no new data. proc writeLn[Ty](f: File; x: varargs[Ty, `$`]) {.inline, tags: [WriteIOEffect], gcsafe, locks: 0, deprecated.}
proc writeLine[Ty](f: File; x: varargs[Ty, `$`]) {.inline, tags: [WriteIOEffect], gcsafe, locks: 0.}
proc getFileSize(f: File): int64 {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc readBytes(f: File; a: var openArray[int8 | uint8]; start, len: Natural): int {. tags: [ReadIOEffect], gcsafe, locks: 0.}
a[start]
. Returns the actual number of bytes that have been read which may be less than len (if not as many bytes are remaining), but not greater. proc readChars(f: File; a: var openArray[char]; start, len: Natural): int {. tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
reads len bytes into the buffer a starting at a[start]
. Returns the actual number of bytes that have been read which may be less than len (if not as many bytes are remaining), but not greater.
Warning: The buffer a must be pre-allocated. This can be done using, for example, newString
.
proc readBuffer(f: File; buffer: pointer; len: Natural): int {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc writeBytes(f: File; a: openArray[int8 | uint8]; start, len: Natural): int {. tags: [WriteIOEffect], gcsafe, locks: 0.}
a[start..start+len-1]
to the file f. Returns the number of actual written bytes, which may be less than len in case of an error. proc writeChars(f: File; a: openArray[char]; start, len: Natural): int {. tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
a[start..start+len-1]
to the file f. Returns the number of actual written bytes, which may be less than len in case of an error. proc writeBuffer(f: File; buffer: pointer; len: Natural): int {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc setFilePos(f: File; pos: int64; relativeTo: FileSeekPos = fspSet) {. gcsafe, locks: 0, raises: [IOError], tags: [].}
proc getFilePos(f: File): int64 {.gcsafe, locks: 0, raises: [IOError], tags: [].}
proc getFileHandle(f: File): FileHandle {.raises: [], tags: [].}
f
. This is only useful for platform specific programming. proc cstringArrayToSeq(a: cstringArray; len: Natural): seq[string] {.raises: [], tags: [].}
cstringArray
to a seq[string]
. a is supposed to be of length len
. proc cstringArrayToSeq(a: cstringArray): seq[string] {.raises: [], tags: [].}
cstringArray
to a seq[string]
. a is supposed to be terminated by nil
. proc allocCStringArray(a: openArray[string]): cstringArray {.raises: [Exception], tags: [].}
proc deallocCStringArray(a: cstringArray) {.raises: [Exception], tags: [].}
proc atomicInc(memLoc: var int; x: int = 1): int {.inline, discardable, gcsafe, locks: 0, raises: [], tags: [].}
proc atomicDec(memLoc: var int; x: int = 1): int {.inline, discardable, gcsafe, locks: 0, raises: [], tags: [].}
proc addAndFetch(p: ptr int; val: int): int {.inline, raises: [], tags: [].}
proc atomicInc(memLoc: var int; x: int = 1): int {.inline, discardable, gcsafe, locks: 0, raises: [], tags: [].}
proc atomicDec(memLoc: var int; x: int = 1): int {.inline, discardable, gcsafe, locks: 0, raises: [], tags: [].}
proc cas[T: bool | int | ptr](p: ptr T; oldValue, newValue: T): bool {. importc: "__sync_bool_compare_and_swap", nodecl.}
proc cpuRelax() {.inline, raises: [], tags: [].}
proc setControlCHook(hook: proc () {.noconv.} not nil) {.raises: [Exception], tags: [RootEffect].}
proc writeStackTrace() {.tags: [WriteIOEffect], gcsafe, raises: [Exception].}
stderr
. This is only works for debug builds. proc getStackTrace(): string {.gcsafe, raises: [], tags: [].}
proc getStackTrace(e: ref Exception): string {.gcsafe, raises: [], tags: [].}
raise
statement. This only works for debug builds. proc zeroMem(p: pointer; size: Natural) {.inline, gcsafe, locks: 0, raises: [], tags: [].}
p
with the value 0. Exactly size
bytes will be overwritten. Like any procedure dealing with raw memory this is unsafe. proc copyMem(dest, source: pointer; size: Natural) {.inline, gcsafe, locks: 0, tags: [], locks: 0, raises: [].}
source
to the memory at dest
. Exactly size
bytes will be copied. The memory regions may not overlap. Like any procedure dealing with raw memory this is unsafe. proc moveMem(dest, source: pointer; size: Natural) {.inline, gcsafe, locks: 0, tags: [], locks: 0, raises: [].}
source
to the memory at dest
. Exactly size
bytes will be copied. The memory regions may overlap, moveMem
handles this case appropriately and is thus somewhat more safe than copyMem
. Like any procedure dealing with raw memory this is still unsafe, though. proc equalMem(a, b: pointer; size: Natural): bool {.inline, noSideEffect, tags: [], locks: 0, raises: [].}
a
and b
. size
bytes will be compared. If the blocks are equal, true is returned, false otherwise. Like any procedure dealing with raw memory this is unsafe. proc getFrameState(): FrameState {.compilerproc, inline, raises: [], tags: [].}
proc setFrameState(state: FrameState) {.compilerproc, inline, raises: [], tags: [].}
proc getFrame(): PFrame {.compilerproc, inline, raises: [], tags: [].}
proc setFrame(s: PFrame) {.compilerproc, inline, raises: [], tags: [].}
proc stackTraceAvailable(): bool {.raises: [], tags: [].}
proc stackTraceAvailable(): bool {.raises: [], tags: [].}
proc writeStackTrace() {.tags: [WriteIOEffect], gcsafe, raises: [Exception].}
stderr
. This is only works for debug builds. proc getStackTrace(): string {.gcsafe, raises: [], tags: [].}
proc getStackTrace(e: ref Exception): string {.gcsafe, raises: [], tags: [].}
raise
statement. This only works for debug builds. proc setControlCHook(hook: proc () {.noconv.} not nil) {.raises: [Exception], tags: [RootEffect].}
proc iterToProc(iter: typed; envType: typedesc; procName: untyped) {.magic: "Plugin", compileTime.}
proc alloc(size: Natural): pointer {.noconv, gcsafe, tags: [], gcsafe, locks: 0, raises: [Exception].}
size
bytes. The block has to be freed with realloc(block, 0)
or dealloc(block)
. The block is not initialized, so reading from it before writing to it is undefined behaviour! The allocated memory belongs to its allocating thread! Use allocShared to allocate from a shared heap. proc alloc0(size: Natural): pointer {.noconv, gcsafe, tags: [], gcsafe, locks: 0, raises: [Exception].}
size
bytes. The block has to be freed with realloc(block, 0)
or dealloc(block)
. The block is initialized with all bytes containing zero, so it is somewhat safer than alloc
. The allocated memory belongs to its allocating thread! Use allocShared0 to allocate from a shared heap. proc dealloc(p: pointer) {.noconv, gcsafe, tags: [], gcsafe, locks: 0, raises: [Exception].}
alloc
, alloc0
or realloc
. This procedure is dangerous! If one forgets to free the memory a leak occurs; if one tries to access freed memory (or just freeing it twice!) a core dump may happen or other memory may be corrupted. The freed memory must belong to its allocating thread! Use deallocShared to deallocate from a shared heap. proc realloc(p: pointer; newSize: Natural): pointer {.noconv, gcsafe, tags: [], gcsafe, locks: 0, raises: [Exception].}
newSize
bytes. If newSize == 0
and p is not nil realloc
calls dealloc(p)
. In other cases the block has to be freed with dealloc
. The allocated memory belongs to its allocating thread! Use reallocShared to reallocate from a shared heap. proc getFreeMem(): int {.gcsafe, raises: [], tags: [].}
proc getTotalMem(): int {.gcsafe, raises: [], tags: [].}
proc getOccupiedMem(): int {.gcsafe, raises: [], tags: [].}
proc getMaxMem(): int {.raises: [], tags: [].}
size
bytes. The block has to be freed with reallocShared(block, 0)
or deallocShared(block)
. The block is not initialized, so reading from it before writing to it is undefined behaviour! size
bytes. The block has to be freed with reallocShared(block, 0)
or deallocShared(block)
. The block is initialized with all bytes containing zero, so it is somewhat safer than allocShared
. allocShared
, allocShared0
or reallocShared
. This procedure is dangerous! If one forgets to free the memory a leak occurs; if one tries to access freed memory (or just freeing it twice!) a core dump may happen or other memory may be corrupted. newSize
bytes. If newSize == 0
and p is not nil reallocShared
calls deallocShared(p)
. In other cases the block has to be freed with deallocShared
. proc protect(x: pointer): ForeignCell {.raises: [Exception], tags: [].}
proc dispose(x: ForeignCell) {.raises: [Exception], tags: [].}
proc isNotForeign(x: ForeignCell): bool {.raises: [], tags: [].}
proc deallocHeap(runFinalizers = true; allowGcAfterwards = true) {.raises: [Exception], tags: [RootEffect].}
runFinalizers``` is true. If ``allowGcAfterwards
is true, a minimal amount of allocation happens to ensure the GC can continue to work after the call to deallocHeap
. proc GC_addCycleRoot[T](p: ref T) {.inline.}
proc gcInvariant() {.raises: [], tags: [].}
proc GC_disable() {.gcsafe, inline, gcsafe, locks: 0, raises: [], tags: [].}
proc GC_enable() {.gcsafe, inline, gcsafe, locks: 0, raises: [AssertionError], tags: [].}
proc GC_setStrategy(strategy: GC_Strategy) {.gcsafe, deprecated, gcsafe, locks: 0, raises: [], tags: [].}
proc GC_enableMarkAndSweep() {.gcsafe, gcsafe, locks: 0, raises: [], tags: [].}
proc GC_disableMarkAndSweep() {.gcsafe, gcsafe, locks: 0, raises: [], tags: [].}
proc GC_fullCollect() {.gcsafe, gcsafe, locks: 0, raises: [Exception], tags: [RootEffect].}
proc GC_getStatistics(): string {.gcsafe, gcsafe, locks: 0, raises: [], tags: [].}
proc add(result: var string; x: int64) {.raises: [], tags: [].}
proc add(result: var string; x: float) {.raises: [], tags: [].}
proc readBuffer(f: File; buffer: pointer; len: Natural): int {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc readBytes(f: File; a: var openArray[int8 | uint8]; start, len: Natural): int {. tags: [ReadIOEffect], gcsafe, locks: 0.}
a[start]
. Returns the actual number of bytes that have been read which may be less than len (if not as many bytes are remaining), but not greater. proc readChars(f: File; a: var openArray[char]; start, len: Natural): int {. tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
reads len bytes into the buffer a starting at a[start]
. Returns the actual number of bytes that have been read which may be less than len (if not as many bytes are remaining), but not greater.
Warning: The buffer a must be pre-allocated. This can be done using, for example, newString
.
proc write(f: File; c: cstring) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc writeBuffer(f: File; buffer: pointer; len: Natural): int {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc writeBytes(f: File; a: openArray[int8 | uint8]; start, len: Natural): int {. tags: [WriteIOEffect], gcsafe, locks: 0.}
a[start..start+len-1]
to the file f. Returns the number of actual written bytes, which may be less than len in case of an error. proc writeChars(f: File; a: openArray[char]; start, len: Natural): int {. tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
a[start..start+len-1]
to the file f. Returns the number of actual written bytes, which may be less than len in case of an error. proc write(f: File; s: string) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc close(f: File) {.tags: [], gcsafe, raises: [].}
proc readChar(f: File): char {.tags: [ReadIOEffect], deprecated, raises: [IOError, EOFError].}
readBuffer
instead. proc flushFile(f: File) {.tags: [WriteIOEffect], raises: [].}
proc getFileHandle(f: File): FileHandle {.raises: [], tags: [].}
f
. This is only useful for platform specific programming. proc readLine(f: File; line: var TaintedString): bool {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
nil
! May throw an IO exception. A line of text may be delimited by LF
or CRLF
. The newline character(s) are not part of the returned string. Returns false
if the end of the file has been reached, true
otherwise. If false
is returned line contains no new data. proc readLine(f: File): TaintedString {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError, EOFError].}
LF
or CRLF
. The newline character(s) are not part of the returned string. proc write(f: File; i: int) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; i: BiggestInt) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; b: bool) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; r: float32) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; r: BiggestFloat) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc write(f: File; c: char) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [].}
proc write(f: File; a: varargs[string, `$`]) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc endOfFile(f: File): bool {.tags: [], gcsafe, locks: 0, raises: [].}
proc readAll(file: File): TaintedString {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
Reads all data from the stream file.
Raises an IO exception in case of an error. It is an error if the current file position is not at the beginning of the file.
proc writeLn[Ty](f: File; x: varargs[Ty, `$`]) {.inline, tags: [WriteIOEffect], gcsafe, locks: 0, deprecated.}
proc writeLine[Ty](f: File; x: varargs[Ty, `$`]) {.inline, tags: [WriteIOEffect], gcsafe, locks: 0.}
proc len(w: WideCString): int {.raises: [], tags: [].}
proc newWideCString(source: cstring; L: int): WideCString {.raises: [], tags: [].}
s[i]
in result. If doInc == true
i is incremented by the number of bytes that have been processed. proc newWideCString(s: cstring): WideCString {.raises: [], tags: [].}
proc newWideCString(s: string): WideCString {.raises: [], tags: [].}
proc `$`(w: WideCString; estimate: int; replacement: int = 0x0000FFFD): string {. raises: [], tags: [].}
proc `$`(s: WideCString): string {.raises: [], tags: [].}
proc open(f: var File; filename: string; mode: FileMode = fmRead; bufSize: int = -1): bool {. tags: [], gcsafe, locks: 0, raises: [].}
Opens a file named filename with given mode.
Default mode is readonly. Returns true iff the file could be opened. This throws no exception if the file could not be opened.
proc reopen(f: File; filename: string; mode: FileMode = fmRead): bool {.tags: [], gcsafe, locks: 0, raises: [].}
reopens the file f with given filename and mode. This is often used to redirect the stdin, stdout or stderr file variables.
Default mode is readonly. Returns true iff the file could be reopened.
proc open(f: var File; filehandle: FileHandle; mode: FileMode = fmRead): bool {.tags: [], gcsafe, locks: 0, raises: [].}
Creates a File
from a filehandle with given mode.
Default mode is readonly. Returns true iff the file could be opened.
proc setFilePos(f: File; pos: int64; relativeTo: FileSeekPos = fspSet) {. gcsafe, locks: 0, raises: [IOError], tags: [].}
proc getFilePos(f: File): int64 {.gcsafe, locks: 0, raises: [IOError], tags: [].}
proc getFileSize(f: File): int64 {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc readFile(filename: string): TaintedString {.tags: [ReadIOEffect], gcsafe, locks: 0, raises: [IOError].}
Opens a file named filename for reading.
Then calls readAll and closes the file afterwards. Returns the string. Raises an IO exception in case of an error. If you need to call this inside a compile time macro you can use staticRead.
proc writeFile(filename, content: string) {.tags: [WriteIOEffect], gcsafe, locks: 0, raises: [IOError].}
proc setStdIoUnbuffered() {.tags: [], gcsafe, locks: 0, raises: [].}
proc `$`(x: uint64): string {.noSideEffect, raises: [], tags: [].}
proc getCurrentException(): ref Exception {.compilerproc, inline, gcsafe, locks: 0, raises: [], tags: [].}
proc getCurrentExceptionMsg(): string {.inline, gcsafe, locks: 0, raises: [], tags: [].}
proc onRaise(action: proc (e: ref Exception): bool {.closure.}) {.raises: [], tags: [].}
try
statement to setup a Lisp-like condition system: This prevents the 'raise' statement to raise an exception but instead calls action
. If action
returns false, the exception has been handled and does not propagate further through the call stack. proc setCurrentException(exc: ref Exception) {.inline, gcsafe, locks: 0, raises: [], tags: [].}
sets the current exception.
Warning: Only use this if you know what you are doing.
proc rawProc[T: proc](x: T): pointer {.noSideEffect, inline.}
proc rawEnv[T: proc](x: T): pointer {.noSideEffect, inline.}
proc finished[T: proc](x: T): bool {.noSideEffect, inline.}
proc `$`[T, IDX](x: array[IDX, T]): string
$
operator for arrays that is lifted from the components proc quit(errormsg: string; errorcode = QuitFailure) {.noReturn, raises: [], tags: [].}
echo(errormsg); quit(errorcode)
. proc `/`(x, y: int): float {.inline, noSideEffect, raises: [], tags: [].}
proc `[]`(s: string; x: Slice[int]): string {.inline, raises: [], tags: [].}
var s = "abcdef" assert s[1..3] == "bcd"
proc `[]=`(s: var string; x: Slice[int]; b: string) {.raises: [], tags: [].}
b.len
is not exactly the number of elements that are referred to by x, a splice is performed:var s = "abcdef" s[1 .. ^2] = "xyz" assert s == "axyzf"
proc `[]`[Idx, T](a: array[Idx, T]; x: Slice[int]): seq[T]
var a = [1,2,3,4] assert a[0..2] == @[1,2,3]
proc `[]=`[Idx, T](a: var array[Idx, T]; x: Slice[int]; b: openArray[T])
proc `[]`[Idx, T](a: array[Idx, T]; x: Slice[Idx]): seq[T]
proc `[]=`[Idx, T](a: var array[Idx, T]; x: Slice[Idx]; b: openArray[T])
proc `[]`[T](s: seq[T]; x: Slice[int]): seq[T]
var s = @[1,2,3,4] assert s[0..2] == @[1,2,3]
proc `[]=`[T](s: var seq[T]; x: Slice[int]; b: openArray[T])
b.len
is not exactly the number of elements that are referred to by x, a splice is performed. proc slurp(filename: string): string {.magic: "Slurp".}
proc staticRead(filename: string): string {.magic: "Slurp".}
const myResource = staticRead"mydatafile.bin"
slurp is an alias for staticRead
.
proc gorge(command: string; input = ""; cache = ""): string {.magic: "StaticExec", raises: [], tags: [].}
proc staticExec(command: string; input = ""; cache = ""): string {.magic: "StaticExec", raises: [], tags: [].}
const buildInfo = "Revision " & staticExec("git rev-parse HEAD") & "\nCompiled on " & staticExec("uname -v")
gorge is an alias for staticExec
. Note that you can use this proc inside a pragma like passC or passL.
If cache
is not empty, the results of staticExec
are cached within the nimcache
directory. Use --forceBuild
to get rid of this caching behaviour then. command & input & cache
(the concatenated string) is used to determine whether the entry in the cache is still valid. You can use versioning information for cache
:
const stateMachine = staticExec("dfaoptimizer", "input", "0.8.0")
proc gorgeEx(command: string; input = ""; cache = ""): tuple[output: string, exitCode: int] {. raises: [], tags: [].}
proc `+=`[T: SomeOrdinal | uint | uint64](x: var T; y: T) {.magic: "Inc", noSideEffect.}
proc `-=`[T: SomeOrdinal | uint | uint64](x: var T; y: T) {.magic: "Dec", noSideEffect.}
proc `*=`[T: SomeOrdinal | uint | uint64](x: var T; y: T) {.inline, noSideEffect.}
proc `+=`[T: float | float32 | float64](x: var T; y: T) {.inline, noSideEffect.}
proc `-=`[T: float | float32 | float64](x: var T; y: T) {.inline, noSideEffect.}
proc `*=`[T: float | float32 | float64](x: var T; y: T) {.inline, noSideEffect.}
proc `/=`(x: var float64; y: float64) {.inline, noSideEffect, raises: [], tags: [].}
proc `/=`[T: float | float32](x: var T; y: T) {.inline, noSideEffect.}
proc `&=`(x: var string; y: string) {.magic: "AppendStrStr", noSideEffect.}
proc astToStr[T](x: T): string {.magic: "AstToStr", noSideEffect.}
proc instantiationInfo(index = -1; fullPaths = false): tuple[filename: string, line: int] {. magic: "InstantiationInfo", noSideEffect.}
provides access to the compiler's instantiation stack line information of a template.
While similar to the caller info of other languages, it is determined at compile time.
This proc is mostly useful for meta programming (eg. assert
template) to retrieve information about the current filename and line number. Example:
import strutils template testException(exception, code: expr): stmt = try: let pos = instantiationInfo() discard(code) echo "Test failure at $1:$2 with '$3'" % [pos.filename, $pos.line, astToStr(code)] assert false, "A test expecting failure succeeded?" except exception: discard proc tester(pos: int): int = let a = @[1, 2, 3] result = a[pos] when isMainModule: testException(IndexError, tester(30)) testException(IndexError, tester(1)) # --> Test failure at example.nim:20 with 'tester(1)'
proc raiseAssert(msg: string) {.noinline, raises: [AssertionError], tags: [].}
proc failedAssertImpl(msg: string) {.raises: [], tags: [].}
proc shallow[T](s: var seq[T]) {.noSideEffect, inline.}
proc shallow(s: var string) {.noSideEffect, inline, raises: [], tags: [].}
proc insert(x: var string; item: string; i = 0.Natural) {.noSideEffect, raises: [], tags: [].}
proc compiles(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime, raises: [], tags: [].}
when compiles(3 + 4): echo "'+' for integers is available"
proc safeAdd[T](x: var seq[T]; y: T) {.noSideEffect.}
y
to x
unless x
is not yet initialized; in that case, x
becomes @[y]
proc safeAdd(x: var string; y: char) {.raises: [], tags: [].}
y
to x
. If x
is nil
it is initialized to ""
proc safeAdd(x: var string; y: string) {.raises: [], tags: [].}
y
to x
unless x
is not yet initalized; in that case, x
becomes y
proc locals(): RootObj {.magic: "Plugin", noSideEffect, raises: [], tags: [].}
RootObj
but a tuple of a structure that depends on the current scope. Example:proc testLocals() = var a = "something" b = 4 c = locals() d = "super!" b = 1 for name, value in fieldPairs(c): echo "name ", name, " with value ", value echo "B is ", b # -> name a with value something # -> name b with value 4 # -> B is 1
proc deepCopy[T](x: var T; y: T) {.noSideEffect, magic: "DeepCopy".}
spawn
. proc procCall(x: untyped) {.magic: "ProcCall", compileTime, raises: [], tags: [].}
# 'someMethod' will be resolved fully statically: procCall someMethod(a, b)
proc `^`[T](x: int; y: openArray[T]): int {.noSideEffect, magic: "Roof".}
proc `^`(x: int): int {.noSideEffect, magic: "Roof", raises: [], tags: [].}
a[^x]
is rewritten to a[a.len-x]
. However currently the a
expression must not have side effects for this to compile. Note that since this is a builtin, it automatically works for all kinds of overloaded []
or []=
accessors. proc xlen(x: string): int {.magic: "XLenStr", noSideEffect, raises: [], tags: [].}
proc xlen[T](x: seq[T]): int {.magic: "XLenSeq", noSideEffect.}
proc `==`(x, y: cstring): bool {.magic: "EqCString", noSideEffect, inline, raises: [], tags: [].}
iterator countdown[T](a, b: T; step = 1): T {.inline.}
low(int)
if T = int for efficiency reasons. iterator countup[S, T](a: S; b: T; step = 1): T {.inline.}
high(int)
if T = int for efficiency reasons. iterator `..`[S, T](a: S; b: T): T {.inline.}
iterator `||`[S, T](a: S; b: T; annotation = ""): T {.inline, magic: "OmpParFor", sideEffect.}
#pragma omp parallel for
construct of OpenMP and as such isn't aware of the parallelism in your code! Be careful! Later versions of ||
will get proper support by Nim's code generator and GC. iterator items[T](a: openArray[T]): T {.inline.}
iterator mitems[T](a: var openArray[T]): var T {.inline.}
iterator items[IX, T](a: array[IX, T]): T {.inline.}
iterator mitems[IX, T](a: var array[IX, T]): var T {.inline.}
iterator items[T](a: set[T]): T {.inline.}
iterator items(a: cstring): char {.inline, raises: [], tags: [].}
iterator mitems(a: var cstring): var char {.inline, raises: [], tags: [].}
iterator items(E: typedesc[enum]): E:type
E
. iterator items[T](s: Slice[T]): T
iterator pairs[T](a: openArray[T]): tuple[key: int, val: T] {.inline.}
(index, a[index])
pairs. iterator mpairs[T](a: var openArray[T]): tuple[key: int, val: var T] {.inline.}
(index, a[index])
pairs. a[index]
can be modified. iterator pairs[IX, T](a: array[IX, T]): tuple[key: IX, val: T] {.inline.}
(index, a[index])
pairs. iterator mpairs[IX, T](a: var array[IX, T]): tuple[key: IX, val: var T] {.inline.}
(index, a[index])
pairs. a[index]
can be modified. iterator pairs[T](a: seq[T]): tuple[key: int, val: T] {.inline.}
(index, a[index])
pairs. iterator mpairs[T](a: var seq[T]): tuple[key: int, val: var T] {.inline.}
(index, a[index])
pairs. a[index]
can be modified. iterator pairs(a: string): tuple[key: int, val: char] {.inline, raises: [], tags: [].}
(index, a[index])
pairs. iterator mpairs(a: var string): tuple[key: int, val: var char] {.inline, raises: [], tags: [].}
(index, a[index])
pairs. a[index]
can be modified. iterator pairs(a: cstring): tuple[key: int, val: char] {.inline, raises: [], tags: [].}
(index, a[index])
pairs. iterator mpairs(a: var cstring): tuple[key: int, val: var char] {.inline, raises: [], tags: [].}
(index, a[index])
pairs. a[index]
can be modified. iterator fields[T: tuple | object](x: T): RootObj {.magic: "Fields", noSideEffect.}
iterator fields[S: tuple | object; T: tuple | object](x: S; y: T): tuple[a, b: untyped] {.magic: "Fields", noSideEffect.}
iterator fieldPairs[T: tuple | object](x: T): RootObj {.magic: "FieldPairs", noSideEffect.}
Iterates over every field of x returning their name and value.
When you iterate over objects with different field types you have to use the compile time when
instead of a runtime if
to select the code you want to run for each type. To perform the comparison use the is operator. Example:
type Custom = object foo: string bar: bool proc `$`(x: Custom): string = result = "Custom:" for name, value in x.fieldPairs: when value is bool: result.add("\n\t" & name & " is " & $value) else: if value.isNil: result.add("\n\t" & name & " (nil)") else: result.add("\n\t" & name & " '" & value & "'")
Another way to do the same without when
is to leave the task of picking the appropriate code to a secondary proc which you overload for each field type and pass the value to.
Warning: This really transforms the 'for' and unrolls the loop. The current implementation also has a bug that affects symbol binding in the loop body.
iterator fieldPairs[S: tuple | object; T: tuple | object](x: S; y: T): tuple[a, b: untyped] {.magic: "FieldPairs", noSideEffect.}
iterator lines(filename: string): TaintedString {.tags: [ReadIOEffect], raises: [Exception, IOError, IOError].}
Iterates over any line in the file named filename.
If the file does not exist EIO is raised. The trailing newline character(s) are removed from the iterated lines. Example:
import strutils proc transformLetters(filename: string) = var buffer = "" for line in filename.lines: buffer.add(line.replace("a", "0") & '\x0A') writeFile(filename, buffer)
iterator lines(f: File): TaintedString {.tags: [ReadIOEffect], raises: [IOError].}
Iterate over any line in the file f.
The trailing newline character(s) are removed from the iterated lines. Example:
proc countZeros(filename: File): tuple[lines, zeros: int] = for line in filename.lines: for letter in line: if letter == '0': result.zeros += 1 result.lines += 1
iterator items[T](a: seq[T]): T {.inline.}
iterator mitems[T](a: var seq[T]): var T {.inline.}
iterator items(a: string): char {.inline, raises: [], tags: [].}
iterator mitems(a: var string): var char {.inline, raises: [], tags: [].}
iterator `..<`[S, T](a: S; b: T): T
template `!=`(x, y: untyped): untyped
not (x == y)
. template `>=`(x, y: untyped): untyped
y <= x
. template `>`(x, y: untyped): untyped
y < x
. template incl[T](s: var set[T]; flags: set[T])
x
. template excl[T](s: var set[T]; flags: set[T])
x
. template `in`(x, y: untyped): untyped {.dirty.}
assert(1 in (1..3) == true) assert(5 in (1..3) == false)
template `notin`(x, y: untyped): untyped {.dirty.}
assert(1 notin (1..3) == false) assert(5 notin (1..3) == true)
template `isnot`(x, y: untyped): untyped
not(x is y)
. template `>=%`(x, y: untyped): untyped
unsigned(x) >= unsigned(y)
. template `>%`(x, y: untyped): untyped
unsigned(x) > unsigned(y)
. template accumulateResult(iter: untyped)
template newException(exceptn: typedesc; message: string; parentException: ref Exception = nil): untyped
exceptn
and sets its msg
field to message. Returns the new exception object. template stdmsg(): File
template setupForeignThreadGc()
template tearDownForeignThreadGc()
template likely(val: bool): bool
Hints the optimizer that val is likely going to be true.
You can use this template to decorate a branch condition. On certain platforms this can help the processor predict better which branch is going to be run. Example:
for value in inputValues: if likely(value <= 100): process(value) else: echo "Value too big!"
On backends without branch prediction (JS and the nimscript VM), this template will not affect code execution.
template unlikely(val: bool): bool
Hints the optimizer that val is likely going to be false.
You can use this proc to decorate a branch condition. On certain platforms this can help the processor predict better which branch is going to be run. Example:
for value in inputValues: if unlikely(value > 100): echo "Value too big!" else: process(value)
On backends without branch prediction (JS and the nimscript VM), this template will not affect code execution.
template `&=`(x, y: typed)
write
. If not specialized further an alias for add
. template `&=`(f: File; x: typed)
template currentSourcePath(): string
template assert(cond: bool; msg = "")
AssertionError
with msg if cond is false. Note that AssertionError
is hidden from the effect system, so it doesn't produce {.raises: [AssertionError].}
. This exception is only supposed to be caught by unit testing frameworks. The compiler may not generate any code at all for assert
if it is advised to do so through the -d:release
or --assertions:off
command line switches. template doAssert(cond: bool; msg = "")
--assertions
command line switch. template onFailedAssert(msg, code: untyped): untyped {.dirty.}
# module-wide policy to change the failed assert # exception type in order to include a lineinfo onFailedAssert(msg): var e = new(TMyError) e.msg = msg e.lineinfo = instantiationInfo(-2) raise e
template `..^`(a, b: untyped): untyped
template `..<`(a, b: untyped): untyped {.dirty.}
template closureScope(body: untyped): untyped
var myClosure : proc() # without closureScope: for i in 0 .. 5: let j = i if j == 3: myClosure = proc() = echo j myClosure() # outputs 5. `j` is changed after closure creation # with closureScope: for i in 0 .. 5: closureScope: # Everything in this scope is locked after closure creation let j = i if j == 3: myClosure = proc() = echo j myClosure() # outputs 3
© 2006–2017 Andreas Rumpf
Licensed under the MIT License.
https://nim-lang.org/docs/system.html