./smol docs/std.s --task docYou may notice that lot of dependencies are marked as unsafe; this is not worrying but only indicates that extra trust should be placed on both the person writing the implementations because some of the language's safety features are turned off to bring to you low-level functionality.
std/ and files under its subfolder. Do not import the latter by themselves to safe development speed. As a final remark, overloaded implementations are split per the file declaring them; foreign imports are not shown. @mut indicates mutability. If this is absent, the language promises to not modify values - the standard library promises to respect that too when considering whether it is allowed to modify pointer contents.@access indicates that arguments can view mutable fields, though not necessarily edit them. This marking also imports the function together with those that could result to arguments from the same import file. For example, the following snippet imports all numeric but not string operations from the standard library's core: @import std.core -> Number
This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Reads several string and primitive types from the console. The user needs to press enter after entering the input. Invalid inputs create service failures, including in the case where the number is too large to properly process. Example:
printin("Give a number.")
x = f64.read
printin("Rounded.")
print(i64(x+0.5))read(@access i64) → i64Converts a String representation to various numeric formats. This is lightweight and does not consume additional memory. The current service fails if the conversion is not possible. Example:
x = f64.convert("1.2")
print(x+1) // prints `2.2`convert(@access i64,cstr _s) → i64This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Checks if an error code corresponds to no error. If it does not, the service fails while printing the type of error. Error codes can be user errors, buffer errors, unknown errors, or no errors.
assert_ok(errcode error) → ()Prints a string interpretation of an error code.
print(errcode error) → ()Causes the current service to fail given a String message. This creates a user error code. Example:
printin("Give a number.")
x = i64.read()
if x==0.0
return fail("Cannot compute the inverse of zero")
printin("Its inverse is.")
print(1.0/x)fail(cstr error) → ()This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Negation of a boolean. There is no equivalent operator, currying notation should be used for manipulating single values. Here is a simple example, though this is often used in conditional statements.
print(true.not())not(@access bool x) → boolChecks if a pointer is non-null. Pointer access and manipulation is inherently unsafe and you should not encounter that in normal code writing. For those aiming to extend the standard library or who dabble with inherently unsafe use cases, this can be used to check for memory allocation failures and trigger a service failure to safely collapse the current execution state.
exists(@access ptr x) → boolPrints a primitive number, character, or boolean to the console.
print(@access f64 message) → ()Prints a primitive number, character, or boolean to the console without changing line.
printin(@access f64 message) → ()Checks if the first number is less than or equal to the second and overloads the corresponding operator. Only the same number types can be compared, and explicit casts are required otherwise. Example demonstrating the need to use an f64 zero (0.0 and not 0) to compare with another read value of the same type:
x = f64.read()
if x<0.0
return print("negative")
else
return print("non-negative")le(@access u64 x,u64 y) → boolChecks if the first number is greater than or equal to the second and overloads the corresponding operator. Only the same number types can be compared, and explicit casts are required otherwise. Example demonstrating the need to use an f64 zero (0.0 and not 0) to compare with another read value of the same type:
x = f64.read()
if x>0.0
return print("positive")
else
return print("non-positive")ge(@access u64 x,u64 y) → boolChecks if the first number is less than the second and overloads the corresponding operator. Example:
print(1>=2)lt(@access u64 x,u64 y) → boolChecks if the first number is greater than the second and overloads the corresponding operator. Example:
print(1>=2)gt(@access u64 x,u64 y) → boolChecks if the first number is less than or equal to the second.
leq(@access u64 x,u64 y) → boolChecks if the first number is greater than or equal to the second.
geq(@access u64 x,u64 y) → boolChecks if two primitives are equal and overloads the corresponding operator. Equality can be checked for all primitives, and is also defined for other types in the standard library, such as strings. Example:
print(1==2)eq(@access u64 x,u64 y) → boolChecks if two primitives are not equal and overloads the corresponding operator. Non-equality can be checked for all primitives, and is also defined for other types in the standard library, such as strings. Example:
print(1!=2)neq(@access u64 x,u64 y) → boolPerforms a left shift on a signed or unsigned integer given an unsigned number of shifted bits. Example:
print(1.lshift(2))lshift(@access u64 x,u64 y) → u64Performs a right shift on a signed or unsigned integer given an unsigned number of shifted bits. Example:
print(8.rshift(2))rshift(@access u64 x,u64 y) → u64Addition of two numbers of the same type and overloads the corresponding operator. Example:
print(1+2)add(@access u64 x,u64 y) → u64Modulo operation for signed or unsigned integers. For i64, only positive divisors are allowed. Fails on zero divisor. Overloads the corresponding operator. Example:
print(1%2)mod(@access u64 x,u64 y) → u64Subtraction of two numbers of the same type: Doing so for u64 will create a service failure if the result would be negative. Overloads the corresponding operator for numbers. Example that FAILS because the default integer type is u64. Example:
print(1-2)sub(@access u64 x,u64 y) → u64Multiplication of two numbers of the same type and overloads the corresponding operator. Example:
print(3*2)mul(@access u64 x,u64 y) → u64Division of two numbers of the same type: Division by zero for i64 or u64 creates a service failure, but for f64 it yields NaN. Overloads the corresponding operator. Here is an example that yields zero by performing integer division.
print(1/2)div(@access u64 x,u64 y) → u64Returns the additive inverse (negation) of an i64 or f64. Does NOT overload any operation. Having u64 as the default type helps avoid many spurious negation errors, especially when memory handling is concerned.
Both examples below print -1. Example:
print(0.i64()-1.i64())
print(1.i64)_.negative())negative(@access i64 x) → i64Obtains the next element in the range. Using a combination of a range and next element traversal is safer than manually checking bounds.
Below is the main usage pattern. Notice that next's argument is an in-place constructed u64 number that is mutable to obtain the next value. The function sets the next value, progresses the range's state, and returns whether the iteration ended. The first retrieved value is the starting element of the range. Example:
range(10)
.while next(@mut u64 i)
then print(i)next(@mut u64 self.start,@mut u64 self.sup,@mut u64 self.step,@mut u64 self.pos,@mut u64 value) → boolDefines a u64 range as a structural type (instead of new type). When directly using variables as ranges, the position should be mutable. A couple of calling conventions are provided for default values of 0 for start and 1 for step.
range(u64 start,u64 sup,u64 step) → (u64 start,u64 sup,u64 step,@mut u64 pos)This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Retrieves the next element over a Split string iteration. Example:
Split("I like bananas", " ")
.while next(@mut str word)
then print(word)next(@mut Split self,@mut str value) → boolRepresents a keyboard key input captured through getch. Encodes the key's integer representation in data.
Retrieves a character from the terminal without printing it. The result is a character encoded in i64 format. This is not stored as a char due to extra symbols, but can be converted to an one-byte character. Example:
s = getch()
if s.is_char()
print(s.to_char())getch() → keyChecks if a captured key represents the enter key.
is_enter(key input) → boolChecks if a captured key represents the left arrow key.
is_left(key input) → boolChecks if a captured key represents the right arrow key.
is_right(key input) → boolChecks if a captured key represents the up arrow key.
is_up(key input) → boolChecks if a captured key represents the down arrow key.
is_down(key input) → boolChecks if a captured key represents the tab key.
is_tab(key input) → boolChecks if a captured key represents the delete key.
is_delete(key input) → boolChecks if a captured key represents the backspace key.
is_backspace(key input) → boolChecks if a key press corresponds to a printable ASCII character.
is_char(key input) → boolConverts a key object representing a printable ASCII character to its char value. Fails if the key is not a character.
Checks if a captured key represents a printable ASCII character.
is_printable(key input) → boolPrints strings or bools to the console.
print(@access cstr message) → ()A union between nstr and constant strings cstr.
Main usage is to abstract an argument's type by converting it to nstr. The conversion is a zero cost abstraction in that needless operations will be removed. But it still augments constant strings with length and first element inform if these are needed. Example:
def foo(CString _s)
s = _s.nstr()
...nstr(new,ptr contents,u64 length,char first,ptr memory) → (new,ptr contents,u64 length,char first,ptr memory)A union between str, nstr, and constant strings cstr. Constant strings are those that generated by default when enclosing some text in quotients and are stored in the program memory.
Main usage is to abstract an argument's type by converting it to str. The conversion is a zero cost abstraction in that needless operations will be removed. But it still augments constant strings with length and first element inform if these are needed. Example:
def foo(String _s)
s = _s.str()
...nstr(new,ptr contents,u64 length,char first,ptr memory) → (new,ptr contents,u64 length,char first,ptr memory)A copy of the String union that can be used when a second argument is needed for a string of a potentially different variation.
nstr(new,ptr contents,u64 length,char first,ptr memory) → (new,ptr contents,u64 length,char first,ptr memory)Compile-time check of a String exact type matching compared to an arbitrary type.
Example:
def foo(String s)
case s.is(str)
...
case s.is(cstr)
...
qedis(@access cstr self,cstr) → cstrA memory allocated string and converters from constant strings and booleans to the type. Other standard library implementations provide more converters.
str(new,ptr contents,u64 length,char first,ptr memory) → (new,ptr contents,u64 length,char first,ptr memory)Prints strings or bools to the console without evoking a new line at the end.
printin(@access cstr message) → ()A null-terminated variation of str. Many operation produce this string version, as it can be readily converted to str at no cost (for the inverse, you need to copy the string)
nstr(new,ptr contents,u64 length,char first,ptr memory) → (new,ptr contents,u64 length,char first,ptr memory)Checks for equality between String types when considering their contents. Implementation of this operation varies, ensuring that the cached first element of strings (not available for cstr) is compared first and then the lengths are taken into account to compare memory bytes. Example:
if "me"=="me"
return print("me!")eq(@access char x,char y) → boolEquivalent to logical inversion of String eq. It is faster to write and run. Example:
if "to be"!="not to be"
return print("dobedobedoo!")neq(@access char x,char y) → boolObtains a substring slice out of a String, producing a str result. Null termination cannot be guaranteed for most results - and is dropped even in cases it could be guaranteed to reduce checks. This overloads the slicing operator. Example:
s = "I like bananas!"
print(s[7 upto 14]) // prints `bananas`
print(s[7 to 14]) // prints `banana`slice(@access cstr self,u64 from,u64 to) → strRemoves leading and trailing whitespace characters from a String, including spaces, tabs, carriage returns, and newlines. Returns a substring without allocating new memory. Example:
print(" hi! ".strip()) // prints `hi!`strip(@access cstr _s) → strReturns the length of a string. Works for str, nstr, and cstr. Example:
print(len("banana")) // prints 6len(str x) → u64Retrieves a character from a string at a given position. Fails if the position is out of bounds. Example:
print("abc".at(1)) // prints `b`at(str x,u64 pos) → charAn iterator structure that splits a String by a separator. The split is lazy and does not allocate memory, returning slices of the original string. Use next to retrieve each part.
This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Go to the end of a WriteFile. This is not implemented for ReadFile, as it makes more sense to just close the latter. Returns a boolean indicating a successful operation.
to_end(@mut WriteFile f) → boolAn opened file that is meant to be read only.
ReadFile(new,ptr contents) → (new,ptr contents)An opened file that is meant to be read or written.
WriteFile(new,ptr contents) → (new,ptr contents)Opens a File given a String path. There might be service failure due to external factors. Opening a WriteFile, may also cause failure if it already exists - in that case remove it first and it will be created. On the other hand, a ReadFile must already exist to be opened. Files must be set as mutable variables to allow reads and writes. Otherwise, only a few operations become available. Example for overwriting a file:
if is_file("hi.txt")
then remove_file("hi.txt")
@mut file = WriteFile.open("tmp.txt")
file:print("Hello world!")
@release file // early release closes the file
open(@mut ReadFile,cstr _path) → ReadFileReads the next line of a file while using it as an iterator. It accommodates Arena, Circular, and Volatile memories. Here is an example where volatile memory is used to avoid repeated or large allocations:
endl="n".str().first // optimized to just setting the new line character
@on Heap:volatile(1024)
ReadFile("README.md")
.open("README.md")
.while next_line(@mut str line)
if line[line:len-1]==endl
then line = line[0 to line:len-1]
then print(line)next_line(@mut Circular reader,@mut ReadFile f,@mut nstr value) → boolReads the next chunk of a file while using it as an iterator. It accommodates Arena, Circular, and Volatile memories. Here is an example where volatile memory is used to avoid repeated or large allocations:
@on Heap:volatile(1024)
ReadFile
.open("README.md")
.while next_chunk(@mut str chunk)
then print(chunk)next_chunk(@mut Circular reader,@mut ReadFile f,@mut nstr value) → boolA union between file types that allows common reading and positioning operations.
ReadFile(new,ptr contents) → (new,ptr contents)Writes a string on a WriteFile.
print(@mut WriteFile f,cstr _s) → ()Go to the beginning of a File. You can continue reading or writing from there. This may cause service failure due to external factors.
to_start(@mut ReadFile f) → ()Creates a WriteFile of a given size that is constrained to fixed memory provided by a Memory allocator. Due to safety mechanisms provided by operating systems, operations on this file may be slower than simple memory read and writes. If the operating system does not properly support memory mapped files, this may even end up consuming disk storage space of up to the given size by being stored as a temporary file. In general, reads and writes (with print) will be at most as slow as a normal file, with the contract that data cannot be recovered after termination. Some operating systems require manual deletion of temporary file folders if systems are abruptly powered off. This type of file should be mostly used to store temporary data or for testing purposes. Example:
@on Heap.dynamic() // allocator for the file
@mut f = WrteFile.temp(1024)
f.print("hello from withing a temp file!")
f.to_start()
f.next_line(@mut u64 line)
print(line)temp(@mut Stack memory,@mut WriteFile,u64 size) → WriteFileComputes the size of a File in bytes. This tries to leverage operating system metadata first, but if it fails it explicitly reads through the file once.
len(@mut ReadFile f) → u64Checks if the ending of the file has been reached. This is normal to be true for WriteFile.
ended(@mut ReadFile f) → boolChecks if a String path is a file system file.
is_file(cstr _path) → existsChecks if a String path is a file system directory.
is_dir(cstr _path) → boolDeletes a file from the system. May cause service failure due to external factors, or if the file is already open.
remove_file(cstr _path) → ()Creates a directory given a String path. May cause service failure due to external factors, or if the directory already exists.
create_dir(cstr _path) → ()A container that converts String instances to integer indexes of a given range.
StringHash(new,u64 size) → (new,u64 size,@mut str[] entries.dynamic)A container that converts any Number to integer indexes of a given range.
NumberHash(new,u64 size) → (new,u64 size,@mut u64[] entries.dynamic)Converts and str or u64 to a u64 hash code.
hash(str k,u64 size) → u64Converts any String or Number to corresponding str or u64 for which is_zero and hash are called.
to_hash_base(cstr k) → strA union between StringHash and NumberHash
StringHash(new,u64 size) → (new,u64 size,@mut str[] entries.dynamic)Check that an str is non-empty or a u64 is non-zero
is_zero(str k) → boolSearches for corresponding contents in a Hash and returns whether they exist or not. The search also admits a mutable number that stores the found position. If the entry is not found, the index remain unchanged. Empty strings and zero numbers are always present at the 0 index. Example:
@include std.core
@include std.map
def my_map()
@mut keys = new.StringHash(100)
@mut values = u64[].expect(keys.size)
@on Heap.dynamic()
values.put(keys["a".copy()], 1)
values.put(keys["b"], 2)
values.put(keys[""], 3)
return keys, values
service main()
@access map = my_map()
if map.keys.find("a".str(), @mut u64 pos)
print(map.values[pos])find(@mut StringHash self,cstr _k,@mut u64 idx) → boolThis file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Computes the cosine of an angle given in radians. Example:
print(cos(0.0)) // prints 1.0
print(cos(0.5.pi())) // prints approximately 0.0cos(f64 x) → f64Computes the arc cosine (inverse cosine) of a value in the range [-1, 1]. Returns an angle in radians. Example:
print(acos(1.0)) // prints 0.0
print(acos(0.0)) // prints approximately 1.5708 (0.5.pi())acos(f64 x) → f64Computes the sine of an angle given in radians. Example:
print(sin(0.0)) // prints 0.0
print(sin(0.5.pi())) // prints approximately 1.0sin(f64 x) → f64Computes the arc sine (inverse sine) of a value in the range [-1, 1]. Returns an angle in radians. Example:
print(asin(0.0)) // prints 0.0
print(asin(1.0)) // prints approximately 1.5708 (0.5.pi())asin(f64 x) → f64Computes the exponential function e^x. Example:
print(exp(1.0)) // prints approximately 2.71828
print(exp(2.0)) // prints approximately 7.38906exp(f64 x) → f64Multiplies a given number by π (pi). This is often used for angle conversions. Example:
print(1.0.pi()) // prints approximately 3.14159
print(0.5.pi()) // prints approximately 1.5708 (π/2)pi(f64 x) → f64Computes the tangent of an angle given in radians. Example:
print(tan(0.0)) // prints 0.0
print(tan(0.25.pi())) // prints approximately 1.0tan(f64 x) → f64Computes the arc tangent (inverse tangent) of a value, returning an angle in radians. Example:
print(atan(1.0)) // prints approximately 0.785398 (0.25.pi())
print(atan(0.0)) // prints 0.0atan(f64 x) → f64Computes the arc tangent of y/x using the signs of both arguments to determine the correct quadrant of the result. Returns an angle in radians. Example:
print(atan2(1.0, 1.0)) // prints approximately 0.785398 (0.25.pi())
print(atan2(1.0, -1.0)) // prints approximately 2.35619 (0.75.pi())atan2(f64 y,f64 x) → f64Checks if a floating-point number is 'not a number' (NaN). Example:
x = 0.0/0.0
if is_nan(x)
print("x is NaN")is_nan(f64 x) → boolChecks if a floating-point number represents infinity (positive or negative). Example:
x = 1.0/0.0
if is_inf(x)
print("x is infinite")is_inf(f64 x) → boolComputes the square root of a number. Requires a non-negative input. Example:
print(sqrt(9.0)) // prints 3.0
print(sqrt(2.0)) // prints approximately 1.41421sqrt(f64 x) → f64Computes the result of raising a base to an exponent (base^exponent). Yields NaN if the base is negative. Example:
print(pow(2.0, 3.0)) // prints 8.0
print(pow(9.0, 0.5)) // prints 3.0pow(f64 base,f64 exponent) → f64Computes the natural logarithm (base e) of a number. Yields NaN on non-positive input. Example:
print(log(exp(1.0))) // prints 1.0
print(log(10.0)) // prints approximately 2.30259log(f64 x) → f64This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
A fixed-sized arena that can be cleared. Data stored on this could be zero-initialized.
Arena(new,ContiguousMemory contents) → (new,ContiguousMemory contents,u64 length)A fixed-sized arena that can be cleared and circularly corrupted. Data stored on this could be zero-initialized.
Circular(new,ContiguousMemory contents) → (new,ContiguousMemory contents,u64 length)Allocates an Arena buffer of given size on the given Memory. Allocations on this can be shared and corrupted.
arena(@mut ContiguousMemory self) → ArenaAllocates a Circular buffer a of given size on the given Memory. Allocations on this can be shared and corrupted.
circular(@mut ContiguousMemory self) → (Circular)Clears an Arena or Circular arena by resetting its occupied length to zero. This can lead to overwriting previous data.
clear(@mut Circular self) → ()This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Represents call stack memory. Allocating on this is near-zero cost by being just an arithmetic addition. But its total size is limited - typically up to a few megabytes. Prefer this for small localized data that need to be processed exceedingly fast. Arena allocators are a close second in terms in performance.
Stack(new) → newRandom access memory (RAM) that can be allocated with __runtime_alloc. Writing to it and reading from it can be slow for programs that keep. Modern processors optimize heap usage by prefetching and caching nearby areas as the ones you access. For this reason, prefer creating Arena regions when you have a sense of the exact amount of data you will need. Allocating on the heap can leak memory under certain conditions, but the language's safety mechanism prevents this. Use other allocators in those cases. The standard library provides a Dynamic type that also accesses several heap allocations, though with an additional level of indirection.
Heap(new) → newRepresents allocated memory management. It keeps track of both currently used pointer addresses, for example if these are offsets of allocated base pointers with finally segments calling __runtime_free on those, and the underlying pointer addresses. Importantly, not all this information is retained after compilation, as most of it -perhaps all- is optimized away. But this structure still helps the compiler organize where to place memory releases, if needed. Users of the standard library will not generally work with this type, as it is highly unsafe to get its pointer fields and requires annotation for the language to allow that.
ContiguousMemory(new,u64 size,ptr mem,ptr underlying) → (new,u64 size,ptr mem,ptr underlying)Refers to either stack or heap memory.
Stack(new) → newAllocates memory on a predetermined device given a number of entries. Other standard library overloads implement allocation for more memory types, derived from the devices. Allocations throughout the standard library track the raw allocated memory so that usage is finally released only when the last dependent variable (e.g., the last string allocated on a heap arena) is no longer used. See ContiguousMemory.
allocate(Heap,u64 size) → ContiguousMemoryThis file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Copies a string on a given Memory allocator. The result is nstr, that is, a string variation is null-terminated. This operation may fail if the allocation fails.
copy(@mut Stack allocator,cstr _s) → nstrProvides methods for converting numbers to strings that are stored on provided Memory allocators. These are not necessarily null-terminated, so use nstr if that is important.
str(ContiguousMemory region) → str(new,ptr contents,u64 length,char first,ptr memory)Provides methods for converting numbers to strings that are stored on provided Memory allocators. The result is a null-terminated nstr.
nstr(@mut Stack allocator,i64 number) → nstr(new,ptr contents,u64 length,char first,ptr memory)Overloads the + operator to concatenate two strings. The result is nstr, that is, a string variation that is null-terminated. Example:
name = "Mario"
@on Heap.arena(1024)
message = "It's a me, "+name+"!"
print(message)add(@mut Stack allocator,cstr _x,cstr _y) → nstrThis file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
A running process whose stdout can be read as a file-like object.
Process(new,ptr contents) → (new,ptr contents)Reads all remaining output from the process without storing it.
to_end(@mut Process p) → ()Opens a Process given a command string. This starts the process and lets you read its output.When the process is eventually released, services fail if there is pending output or if the exit code is non-zero. Here is an example:
service run(String command)
@mut process = Process.open(command)
process.to_end()
@release process // explicitly release here
service main()
run("invalid command").err.assert_ok() // synchronizeopen(@mut Process,cstr _command) → ProcessReads the next chunk of process output into a provided buffer.
next_chunk(@mut Arena reader,@mut Process p,@mut nstr value) → boolReads the next line of process output into a provided buffer.
next_line(@mut Arena reader,@mut Process p,@mut nstr value) → boolThis file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Computes the next random number of a Rand sequence. Example:
@mut rnd = Rand()
range(10)
.while next(@mut u64 i)
print(rnd.next())next(@mut u64 self.s0,@mut u64 self.s1,@mut u64 self.s2,@mut u64 self.s3) → f64Computes the next random number of a splitmix64 sequence using the mutable unsigned int argument as state to be updated. This is NOT cryptographically secure and also has small period of 2^64 so usage is not recommended for long-running sequences. It is, however, faster than computing a next Rand state with next. If you do not provide a seed, a number obtained from the current time is provided. That can only be the start of a sequence, and marked as a leaking resource to prevent time-based randomization (which is not random). Example:
@mut rnd = splitmix64()
range(10)
.while next(@mut u64 i)
print(rnd.splitmix64()) // rnd is the state, the result is f64splitmix64(@mut u64 x) → u64This a structural type for storing the progress of random number generators on four u64 state fields. It can be initialized with an optional seed, which defaults to a time-based initialization if not provided. Its period is 2^256-1.
For safety against sharing random implementations between services or repeatedly initializing them, state variables are marked as a leaking resource. The whole data type is marked as @noborrow too, to prevent sharing mutable random states across different services. These safety mechanisms help safeguard speed and prevent common mistakes, for example by making impossible to directly re-initialize Rand in each loop to get a next number.
This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Make the current service wait for AT LEAST a number of f64 seconds. While yielding, other services may be called asynchronously to fill in the missing time. There is no guarantee for this, though. Sleeping for 0.0 duration does not incur delays, but may still run other services. Negative durations skip over this. Use exact_slepp to sleep without yielding and thus get a guarantee on the sleep duration. This method's exact implementation is ported from the runtime. Example:
sleep(1.0) // yields for at least 1 sec sleep(f64 duration) → ()Make the current service wait for exactly a specified number of f64 seconds. Control flow is not transferred to other services, so use sparingly (e.g., in main game loops). Example:
sleep(1.0) // waits for 1 sec of inactivity exact_sleep(f64 duration) → okRetrieve time elapsed from the start of the program in f64 seconds.
time() → f64This file is marked with the unsafe keyword. This means that its internal implementation (only) could be subject to bugs that the language's design otherwise eliminates. By using this file as a direct or indirect dependency you are trusting its implementation. Given this trust, consider other non-unsafe files using it as safe.
Represents a vector stored on contiguous memory. Prefer using the vector initializer, which can also generate vectors from random number generators. Vectors always hold f64 to ensure that invalid computations are stored as NaNs. They are also tailored for scientific use, so implementations aim to cut even the smallest corners without compromising safety. Use buffers to work with collections of u64 data instead.
Initializes a vector by using a provided memory allocator. The generated vector is zero-initialized. You can also provide a Rand random state imported from std.rand to initialize with uniformly random values in [0,1]. Example of generating a vector of 10 zero elements:
vec = Heap.dynamic().vector(10)vector(@mut Stack memory,u64 size) → VecPrints a vector to the console. To avoid large prints, at most the first 10 elements are printed.
print(Vec v) → ()Slices a vector from a given to an ending position. This is a transparent view of vector data.
slice(Vec v,u64 from,u64 to) → VecAdds two vectors element-by-element and stores the result on either a third mutable vector also of the same size, or on a newly allocated one in the provided memory. This fails if vector sizes are incompatible, or if the provided Memory cannot allocate the required space. Example where an on context is used to allow operator overloading:
@mut rnd = Rand()
@on Heap.dynamic()
v1 = rnd.vector(10)
v2 = rnd.vector(10)
v3 = v1+v2add(@mut Stack memory,Vec x1,Vec x2) → VecRetrieves the length of a vector.
len(Vec v) → u64Subtracts two vectors element-by-element and stores the result on either a third mutable vector also of the same size, or on a newly allocated one in the provided memory. This fails if vector sizes are incompatible, or if the provided Memory cannot allocate the required space. Example where an on context is used to allow operator overloading:
@mut rnd = Rand()
@on Heap.dynamic()
v1 = rnd.vector(10)
v2 = rnd.vector(10)
v3 = v1-v2sub(@mut Stack memory,Vec x1,Vec x2) → VecMultiplies two vectors element-by-element and stores the result on either a third mutable vector also of the same size, or on a newly allocated one in the provided memory. This fails if vector sizes are incompatible, or if the provided Memory cannot allocate the required space. Example where an on context is used to allow operator overloading:
@mut rnd = Rand()
@on Heap.dynamic()
v1 = rnd.vector(10)
v2 = rnd.vector(10)
v3 = v1*v2mul(@mut Stack memory,Vec x1,Vec x2) → VecRetrieves a specific f64 element from a vector. This overloads the element access operation like this:
vec = Rand().vector(Heap.dynamic(), 10)
print(vev[0])at(Vec v,u64 pos) → f64Divides two vectors element-by-element and stores the result on either a third mutable vector also of the same size, or on a newly allocated one in the provided memory. This fails if vector sizes are incompatible, or if the provided Memory cannot allocate the required space. Division may create NaN values. Example where an on context is used to allow operator overloading:
@mut rnd = Rand()
@on Heap.dynamic()
v1 = rnd.vector(10)
v2 = rnd.vector(10)
v3 = v1/v2div(@mut Stack memory,Vec x1,Vec x2) → Vec