Contents


docs.std

std.core

std.core.convert
read
convert

std.core.err
assert_ok
print
fail
assert

std.core.num
ok
print
printin
le
ge
lt
gt
leq
geq
eq
neq
not
exists
add
mod
sub
mul
div
negative

std.core.range
range
next

std.core.str
next
CString
String
IndependentString
is
print
str
nstr
printin
eq
neq
slice
strip
len
at
Split
key
getch
is_left
is_right
is_up
is_down
is_tab
is_delete
is_backspace
is_char
to_char

std.file
next_chunk
open
to_end
next_line
ReadFile
WriteFile
File
print
to_start
temp
len
ended
is_file
is_dir
remove_file
create_dir
console

std.map

std.math
cos
acos
sin
asin
exp
pi
tan
atan
atan2
is_nan
is_inf
sqrt
pow
log

std.mem

std.mem.arena
Region
read
Arena
Circular
clear
BoundMemory
Buffer
is
Dynamic
allocate
dynamic
used
Memory
fixed
arena
circular
len

std.mem.device
Stack
Heap
MemoryDevice
ContiguousMemory
allocate
file_end

std.mem.grid

std.mem.str
copy
str
nstr
add

std.os
Process
open
to_end
next_chunk
next_line
system

std.rand
__rotl
splitmix64
Rand
next

std.time
sleep
exact_sleep
time

std.vec
Vec
vector
print
dot
put
slice
add
sub
mul
len
div
at

docs.std 🔝

This the documentation of smoλ's standard library. It is automatically kept up to date by periodically running the following command. That pulls from code annotations and overloaded implementations.
./smol docs/std.s --task doc
You 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.

The following functionality that is ready to use without -or with minimal- external dependencies. It is organized into top-level files residing directly under 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

std.core 🔝

Contains basic numeric functionalities and string types.

std.core.convert unsafe 🔝

Standard library wrapping and simplification of C console commands.

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.

read 🔝

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) → i64
read(@access u64) → u64
read(@access f64) → f64

convert 🔝

Converts 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)

convert(@access i64,cstr _s) → i64
convert(@access i64,nstr _s) → i64
convert(@access i64,str _s) → i64
convert(@access u64,cstr _s) → u64
convert(@access u64,nstr _s) → u64
convert(@access u64,str _s) → u64
convert(@access f64,cstr _s) → f64
convert(@access f64,nstr _s) → f64
convert(@access f64,str _s) → f64

std.core.err unsafe 🔝

Standard library implementations of error utilities.

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.

assert_ok 🔝

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) → ()

assert 🔝

assert(bool condition,cstr error) → ()

print 🔝

Prints a string interpretation of an error code.

print(errcode error) → ()

fail 🔝

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) → ()
fail(nstr error) → ()
fail(str error) → ()

std.core.num unsafe 🔝

Standard library wrapping of C basic arithmetics and printing.

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.

ok 🔝

ok() → ()

not 🔝

Negation of a boolean. There is no equivalent operator, and currying-based 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) → bool

exists 🔝

Checks 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) → bool

print 🔝

Prints a primitive number, character, or boolean to the console.

print(@access f64 message) → ()
print(@access i64 message) → ()
print(@access u64 message) → ()
print(@access bool message) → ()
print(@access char message) → ()
print() → ()

printin 🔝

Prints a primitive number, character, or boolean to the console without changing line.

printin(@access f64 message) → ()
printin(@access i64 message) → ()
printin(@access u64 message) → ()
printin(@access bool message) → ()
printin(@access char message) → ()

le 🔝

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) → bool
le(@access f64 x,f64 y) → bool
le(@access i64 x,i64 y) → bool

ge 🔝

Checks 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) → bool
ge(@access f64 x,f64 y) → bool
ge(@access i64 x,i64 y) → bool

lt 🔝

Checks if the first number is less than the second and overloads the corresponding operator. Example:

print(1>=2)

lt(@access u64 x,u64 y) → bool
lt(@access f64 x,f64 y) → bool
lt(@access i64 x,i64 y) → bool

gt 🔝

Checks if the first number is greater than the second and overloads the corresponding operator. Example:

print(1>=2)

gt(@access u64 x,u64 y) → bool
gt(@access f64 x,f64 y) → bool
gt(@access i64 x,i64 y) → bool

leq 🔝

Checks if the first number is less than or equal to the second.

leq(@access u64 x,u64 y) → bool
leq(@access f64 x,f64 y) → bool
leq(@access i64 x,i64 y) → bool

geq 🔝

Checks if the first number is greater than or equal to the second.

geq(@access u64 x,u64 y) → bool
geq(@access f64 x,f64 y) → bool
geq(@access i64 x,i64 y) → bool

eq 🔝

Checks 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) → bool
eq(@access f64 x,f64 y) → bool
eq(@access i64 x,i64 y) → bool
eq(@access ptr x,ptr y) → bool
eq(@access bool x,bool y) → bool
eq(@access tag x,tag y) → bool

neq 🔝

Checks 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) → bool
neq(@access f64 x,f64 y) → bool
neq(@access i64 x,i64 y) → bool
neq(@access ptr x,ptr y) → bool
neq(@access bool x,bool y) → bool
neq(@access tag x,tag y) → bool

add 🔝

Addition of two numbers of the same type and overloads the corresponding operator. Example:

print(1+2)

add(@access u64 x,u64 y) → u64
add(@access i64 x,i64 y) → i64
add(@access f64 x,f64 y) → f64

mod 🔝

Modulo operation for signed or unsigned integers. For i64, only positive divisors are allowed. Fails on zero divisor. Overloads the corresponding operator. Here is an example:

print(1%2)

mod(@access u64 x,u64 y) → u64
mod(@access i64 x,i64 y) → i64

sub 🔝

Subtraction 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.

print(1-2)

sub(@access u64 x,u64 y) → u64
sub(@access i64 x,i64 y) → i64
sub(@access f64 x,f64 y) → f64

mul 🔝

Multiplication of two numbers of the same type and overloads the corresponding operator. Example:

print(3*2)

mul(@access u64 x,u64 y) → u64
mul(@access i64 x,i64 y) → i64
mul(@access f64 x,f64 y) → f64

div 🔝

Division 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) → u64
div(@access i64 x,i64 y) → i64
div(@access f64 x,f64 y) → f64

negative 🔝

Returns 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.

print(0.i64-1.i64)
print(1.i64.negative)

negative(@access i64 x) → i64
negative(@access f64 x) → f64

std.core.range 🔝

Standard library implementation of u64 ranges.

next 🔝

Obtains 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) → bool

range 🔝

Defines a u64 range as a structural type (instead of nominal 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)
range(u64 start,u64 sup) → range(u64 start,u64 sup,u64 step)
range(u64 sup) → range(u64 start,u64 sup,u64 step)

std.core.str unsafe 🔝

Standard library implementation of the extensible string model based on C pointers and an implementation for const char arrays.

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.

next 🔝

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) → bool

key 🔝

key(nominal,i64 data) → (nominal,i64 data)

getch 🔝

getch() → key

is_left 🔝

is_left(key input) → bool

is_right 🔝

is_right(key input) → bool

is_up 🔝

is_up(key input) → bool

is_down 🔝

is_down(key input) → bool

is_tab 🔝

is_tab(key input) → bool

is_delete 🔝

is_delete(key input) → bool

is_backspace 🔝

is_backspace(key input) → bool

is_char 🔝

is_char(key input) → bool

to_char 🔝

to_char(key input) → char

CString 🔝

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. Here is an example:

def foo(CString _s)
    s = _s.nstr()
    ...
    end

nstr(nominal,ptr contents,u64 length,char first,ptr memory) → (nominal,ptr contents,u64 length,char first,ptr memory)

String 🔝

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. Here is an example:

def foo(String _s)
    s = _s.str()
    ...
    end

nstr(nominal,ptr contents,u64 length,char first,ptr memory) → (nominal,ptr contents,u64 length,char first,ptr memory)
str(nominal,ptr contents,u64 length,char first,ptr memory) → (nominal,ptr contents,u64 length,char first,ptr memory)

IndependentString 🔝

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(nominal,ptr contents,u64 length,char first,ptr memory) → (nominal,ptr contents,u64 length,char first,ptr memory)
str(nominal,ptr contents,u64 length,char first,ptr memory) → (nominal,ptr contents,u64 length,char first,ptr memory)

is 🔝

Compile-time check of a String exact type matching compared to an arbitrary type.
Example usage.

def foo(String s)
    with s.is(str)
        ...
        end else
        ...
    end end

is(@access cstr self,cstr) → cstr
is(nstr self,nstr) → nstr
is(str self,str) → str

print 🔝

Prints strings or bools to the console.

print(@access cstr message) → ()
print(nstr message) → ()
print(str message) → ()
print(str[] messages.dynamic) → ()

str 🔝

A memory allocated string and converters from constant strings and booleans to the type. Other standard library implementations provide more converters.

str(nominal,ptr contents,u64 length,char first,ptr memory) → (nominal,ptr contents,u64 length,char first,ptr memory)
str(nstr other) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@access cstr raw) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@access bool value) → str(nominal,ptr contents,u64 length,char first,ptr memory)

nstr 🔝

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(nominal,ptr contents,u64 length,char first,ptr memory) → (nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@access cstr raw) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@access bool value) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)

printin 🔝

Prints strings or bools to the console without evoking a new line at the end.

printin(@access cstr message) → ()
printin(nstr message) → ()
printin(str message) → ()

eq 🔝

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) → bool
eq(@access cstr _x,cstr _y) → bool
eq(nstr _x,cstr _y) → bool
eq(str _x,cstr _y) → bool
eq(@access cstr _x,nstr _y) → bool
eq(nstr _x,nstr _y) → bool
eq(str _x,nstr _y) → bool
eq(@access cstr _x,str _y) → bool
eq(nstr _x,str _y) → bool
eq(str _x,str _y) → bool

neq 🔝

Equivalent to logical inversion of String eq. It is faster to write and run.

neq(@access char x,char y) → bool
neq(@access cstr _x,cstr _y) → bool
neq(nstr _x,cstr _y) → bool
neq(str _x,cstr _y) → bool
neq(@access cstr _x,nstr _y) → bool
neq(nstr _x,nstr _y) → bool
neq(str _x,nstr _y) → bool
neq(@access cstr _x,str _y) → bool
neq(nstr _x,str _y) → bool
neq(str _x,str _y) → bool

slice 🔝

Obtains a substring slice out of a String. This always produces a str results, because null termination cannot be guaranteed for most results - and is dropped even if it could be guaranteed to save computations.

slice(@access cstr self,u64 from,u64 to) → str
slice(nstr self,u64 from,u64 to) → str
slice(str self,u64 from,u64 to) → str
slice(@access cstr self,u64 from) → str
slice(nstr self,u64 from) → str
slice(str self,u64 from) → str

strip 🔝

strip(@access cstr _s) → str
strip(nstr _s) → str
strip(str _s) → str

len 🔝

len(str x) → u64
len(nstr x) → u64
len(@access cstr x) → u64

at 🔝

at(str x,u64 pos) → char
at(nstr x,u64 pos) → char

Split 🔝

Splits a String given a query String. Optionally, you may also provide a starting position, where the default is 0. The result of the split can be iterated through with next. This does not allocate memory in that a substring is retrieved, so you might consider copying the splits - or store them on data structures like maps that automatically copy data if needed.

Split(nominal,str query,str sep,@mut u64 pos) → (nominal,str query,str sep,@mut u64 pos)
Split(@access cstr _query,@access cstr _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(nstr _query,@access cstr _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(str _query,@access cstr _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(@access cstr _query,nstr _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(nstr _query,nstr _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(str _query,nstr _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(@access cstr _query,str _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(nstr _query,str _sep) → Split(nominal,str query,str sep,@mut u64 pos)
Split(str _query,str _sep) → Split(nominal,str query,str sep,@mut u64 pos)

std.file unsafe 🔝

Standard library implementation of file management that uses the C filesystem.

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.

to_end 🔝

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) → bool

ReadFile 🔝

An opened file that is meant to be read only.

ReadFile(nominal,ptr contents) → (nominal,ptr contents)

WriteFile 🔝

An opened file that is meant to be read or written.

WriteFile(nominal,ptr contents) → (nominal,ptr contents)

console 🔝

console(@mut WriteFile) → (WriteFile)

next_chunk 🔝

Reads the next chunk of a file while using it as an iterator. It accomodates Arena 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) → bool
next_chunk(@mut Circular reader,@mut WriteFile f,@mut nstr value) → bool
next_chunk(@mut Region reader,@mut ReadFile f,@mut nstr value) → bool
next_chunk(@mut Arena reader,@mut ReadFile f,@mut nstr value) → bool
next_chunk(@mut Region reader,@mut WriteFile f,@mut nstr value) → bool
next_chunk(@mut Arena reader,@mut WriteFile f,@mut nstr value) → bool
next_chunk(@mut Region reader,@mut ReadFile f,@mut str value) → bool
next_chunk(@mut Arena reader,@mut ReadFile f,@mut str value) → bool
next_chunk(@mut Circular reader,@mut ReadFile f,@mut str value) → bool
next_chunk(@mut Region reader,@mut WriteFile f,@mut str value) → bool
next_chunk(@mut Arena reader,@mut WriteFile f,@mut str value) → bool
next_chunk(@mut Circular reader,@mut WriteFile f,@mut str value) → bool

open 🔝

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) → ReadFile
open(@mut ReadFile,nstr _path) → ReadFile
open(@mut ReadFile,str _path) → ReadFile
open(@mut WriteFile,cstr _path) → WriteFile
open(@mut WriteFile,nstr _path) → WriteFile
open(@mut WriteFile,str _path) → WriteFile

next_line 🔝

Reads the next line of a file while using it as an iterator. It accomodates Arena 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) → bool
next_line(@mut Circular reader,@mut WriteFile f,@mut nstr value) → bool
next_line(@mut Region reader,@mut ReadFile f,@mut nstr value) → bool
next_line(@mut Arena reader,@mut ReadFile f,@mut nstr value) → bool
next_line(@mut Region reader,@mut WriteFile f,@mut nstr value) → bool
next_line(@mut Arena reader,@mut WriteFile f,@mut nstr value) → bool
next_line(@mut Region reader,@mut ReadFile f,@mut str value) → bool
next_line(@mut Arena reader,@mut ReadFile f,@mut str value) → bool
next_line(@mut Circular reader,@mut ReadFile f,@mut str value) → bool
next_line(@mut Region reader,@mut WriteFile f,@mut str value) → bool
next_line(@mut Arena reader,@mut WriteFile f,@mut str value) → bool
next_line(@mut Circular reader,@mut WriteFile f,@mut str value) → bool

File 🔝

A union between file types that allows common reading and positioning operations.

ReadFile(nominal,ptr contents) → (nominal,ptr contents)
WriteFile(nominal,ptr contents) → (nominal,ptr contents)

print 🔝

Writes a string on a WriteFile.

print(@mut WriteFile f,cstr _s) → ()
print(@mut WriteFile f,nstr _s) → ()
print(@mut WriteFile f,str _s) → ()

to_start 🔝

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) → ()
to_start(@mut WriteFile f) → ()

temp 🔝

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 usage:

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) → WriteFile
temp(@mut Heap memory,@mut WriteFile,u64 size) → WriteFile
temp(@mut Region memory,@mut WriteFile,u64 size) → WriteFile
temp(@mut Arena memory,@mut WriteFile,u64 size) → WriteFile
temp(@mut Circular memory,@mut WriteFile,u64 size) → WriteFile
temp(@mut Dynamic memory,@mut WriteFile,u64 size) → WriteFile

len 🔝

Computes 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) → u64
len(@mut WriteFile f) → u64

ended 🔝

Checks if the ending of the file has been reached. This is normal to be true for WriteFile.

ended(@mut ReadFile f) → bool
ended(@mut WriteFile f) → bool

is_file 🔝

Checks if a String path is a file system file.

is_file(cstr _path) → exists
is_file(nstr _path) → exists

is_dir 🔝

Checks if a String path is a file system directory.

is_dir(cstr _path) → bool
is_dir(nstr _path) → bool

remove_file 🔝

Deletes a file from the system. May cause service failure due to external factors, or if the file is already open.

remove_file(cstr _path) → ()
remove_file(nstr _path) → ()
remove_file(str _path) → ()

create_dir 🔝

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) → ()
create_dir(nstr _path) → ()
create_dir(str _path) → ()

std.map 🔝

std/map.s

std.math unsafe 🔝

Standard library wrapping of C math operations.

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.

cos 🔝

cos(f64 x) → f64

acos 🔝

acos(f64 x) → f64

sin 🔝

sin(f64 x) → f64

asin 🔝

asin(f64 x) → f64

exp 🔝

exp(f64 x) → f64

pi 🔝

pi(f64 x) → f64

tan 🔝

tan(f64 x) → f64

atan 🔝

atan(f64 x) → f64

atan2 🔝

atan2(f64 y,f64 x) → f64

is_nan 🔝

is_nan(f64 x) → bool

is_inf 🔝

is_inf(f64 x) → bool

sqrt 🔝

sqrt(f64 x) → f64

pow 🔝

pow(f64 base,f64 exponent) → f64

log 🔝

log(f64 x) → f64

std.mem 🔝

std/mem.s

std.mem.arena unsafe 🔝

Standard library implementation of arena allocation, marked as @noborrow but unsafely returned from constructors. Pointer arithmetics yield offsets within arenas.

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.

Region 🔝

Region(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)

read 🔝

read(@mut Arena self) → str

Arena 🔝

Arena(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)

Circular 🔝

Circular(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)

Dynamic 🔝

Dynamic(nominal) → (nominal,ptr acquired,u64 size,u64 allocated,u64)

clear 🔝

clear(@mut Circular self) → ()
clear(@mut Arena self) → ()

BoundMemory 🔝

Region(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)
Arena(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)

Buffer 🔝

Region(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)
Arena(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)
Circular(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)

is 🔝

is(@mut Stack self,@mut Stack) → Stack
is(@mut Heap self,@mut Heap) → Heap
is(@mut Region self,@mut Region) → Region
is(@mut Arena self,@mut Arena) → Arena
is(@mut Circular self,@mut Circular) → Circular
is(@mut Dynamic self,@mut Dynamic) → Dynamic

allocate 🔝

allocate(@mut Dynamic self,u64 size) → ContiguousMemory
allocate(@mut Region self,u64 size) → ContiguousMemory
allocate(@mut Arena self,u64 size) → ContiguousMemory
allocate(@mut Circular self,u64 size) → ContiguousMemory

dynamic 🔝

dynamic(Heap) → Dynamic
dynamic(Stack) → nominal

used 🔝

used(@mut Region self) → u64
used(@mut Arena self) → u64
used(@mut Circular self) → u64

Memory 🔝

Region(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)
Arena(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)
Circular(nominal,ContiguousMemory contents) → (nominal,ContiguousMemory contents,u64 length)
Dynamic(nominal) → (nominal,ptr acquired,u64 size,u64 allocated,u64)

fixed 🔝

fixed(@mut Stack self,u64 size) → Circular
fixed(@mut Heap self,u64 size) → Circular
fixed(@mut Region self,u64 size) → Circular
fixed(@mut Arena self,u64 size) → Circular
fixed(@mut Circular self,u64 size) → Circular
fixed(@mut Dynamic self,u64 size) → Circular

arena 🔝

arena(@mut Stack self,u64 size) → Arena
arena(@mut Heap self,u64 size) → Arena
arena(@mut Region self,u64 size) → Arena
arena(@mut Arena self,u64 size) → Arena
arena(@mut Circular self,u64 size) → Arena
arena(@mut Dynamic self,u64 size) → Arena
arena(@mut Circular mem) → (Arena)

circular 🔝

circular(@mut Stack self,u64 size) → Circular
circular(@mut Heap self,u64 size) → Circular
circular(@mut Region self,u64 size) → Circular
circular(@mut Arena self,u64 size) → Circular
circular(@mut Circular self,u64 size) → Circular
circular(@mut Dynamic self,u64 size) → Circular

len 🔝

len(@mut Region self) → u64
len(@mut Arena self) → u64
len(@mut Circular self) → u64

std.mem.device unsafe 🔝

Standard library implementation of memory management that accounts for the stack and heap and depends on the runtime.h implementation of heap memory, and GCC implementation of alloca. Stack allocations cannot be returned from services, as the stack is pruned when programming function calls end. Def-based functions are inlined within services, so it is fine to return stack allocations from them.

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.

Stack 🔝

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.

Stack(nominal) → nominal

Heap 🔝

Random 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(nominal) → nominal

ContiguousMemory 🔝

Represents 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(nominal,u64 size,ptr mem,ptr underlying) → (nominal,u64 size,ptr mem,ptr underlying)

file_end 🔝

file_end() → ()

MemoryDevice 🔝

Refers to either stack or heap memory.

Stack(nominal) → nominal
Heap(nominal) → nominal

allocate 🔝

Allocates 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) → ContiguousMemory
allocate(Stack,u64 size) → ContiguousMemory

std.mem.grid 🔝

std/mem/grid.s

std.mem.str unsafe 🔝

Standard library implementation of string operations using its own allocators and C memory operations.

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.

copy 🔝

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) → nstr
copy(@mut Heap allocator,cstr _s) → nstr
copy(@mut Region allocator,cstr _s) → nstr
copy(@mut Arena allocator,cstr _s) → nstr
copy(@mut Circular allocator,cstr _s) → nstr
copy(@mut Dynamic allocator,cstr _s) → nstr
copy(@mut Stack allocator,nstr _s) → nstr
copy(@mut Heap allocator,nstr _s) → nstr
copy(@mut Region allocator,nstr _s) → nstr
copy(@mut Arena allocator,nstr _s) → nstr
copy(@mut Circular allocator,nstr _s) → nstr
copy(@mut Dynamic allocator,nstr _s) → nstr
copy(@mut Stack allocator,str _s) → nstr
copy(@mut Heap allocator,str _s) → nstr
copy(@mut Region allocator,str _s) → nstr
copy(@mut Arena allocator,str _s) → nstr
copy(@mut Circular allocator,str _s) → nstr
copy(@mut Dynamic allocator,str _s) → nstr

str 🔝

Provides methods for converting numbers to strings that are stored on provided Memory allocators. The result is a null-terminated nstr.

str(ContiguousMemory region) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(ContiguousMemory region,u64 size) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Stack allocator,u64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Heap allocator,u64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Region allocator,u64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Arena allocator,u64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Circular allocator,u64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Dynamic allocator,u64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Stack allocator,i64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Heap allocator,i64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Region allocator,i64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Arena allocator,i64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Circular allocator,i64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Dynamic allocator,i64 number) → str(nominal,ptr contents,u64 length,char first,ptr memory)
str(@mut Stack allocator,f64 number) → (str)
str(@mut Heap allocator,f64 number) → (str)
str(@mut Region allocator,f64 number) → (str)
str(@mut Arena allocator,f64 number) → (str)
str(@mut Circular allocator,f64 number) → (str)
str(@mut Dynamic allocator,f64 number) → (str)

nstr 🔝

nstr(@mut Stack allocator,i64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Heap allocator,i64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Region allocator,i64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Arena allocator,i64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Circular allocator,i64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Dynamic allocator,i64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Stack allocator,u64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Heap allocator,u64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Region allocator,u64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Arena allocator,u64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Circular allocator,u64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Dynamic allocator,u64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Stack allocator,f64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Heap allocator,f64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Region allocator,f64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Arena allocator,f64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Circular allocator,f64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)
nstr(@mut Dynamic allocator,f64 number) → nstr(nominal,ptr contents,u64 length,char first,ptr memory)

add 🔝

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+"!"
    end
print(message)

add(@mut Stack allocator,cstr _x,cstr _y) → nstr
add(@mut Heap allocator,cstr _x,cstr _y) → nstr
add(@mut Region allocator,cstr _x,cstr _y) → nstr
add(@mut Arena allocator,cstr _x,cstr _y) → nstr
add(@mut Circular allocator,cstr _x,cstr _y) → nstr
add(@mut Dynamic allocator,cstr _x,cstr _y) → nstr
add(@mut Stack allocator,nstr _x,cstr _y) → nstr
add(@mut Heap allocator,nstr _x,cstr _y) → nstr
add(@mut Region allocator,nstr _x,cstr _y) → nstr
add(@mut Arena allocator,nstr _x,cstr _y) → nstr
add(@mut Circular allocator,nstr _x,cstr _y) → nstr
add(@mut Dynamic allocator,nstr _x,cstr _y) → nstr
add(@mut Stack allocator,str _x,cstr _y) → nstr
add(@mut Heap allocator,str _x,cstr _y) → nstr
add(@mut Region allocator,str _x,cstr _y) → nstr
add(@mut Arena allocator,str _x,cstr _y) → nstr
add(@mut Circular allocator,str _x,cstr _y) → nstr
add(@mut Dynamic allocator,str _x,cstr _y) → nstr
add(@mut Stack allocator,cstr _x,nstr _y) → nstr
add(@mut Heap allocator,cstr _x,nstr _y) → nstr
add(@mut Region allocator,cstr _x,nstr _y) → nstr
add(@mut Arena allocator,cstr _x,nstr _y) → nstr
add(@mut Circular allocator,cstr _x,nstr _y) → nstr
add(@mut Dynamic allocator,cstr _x,nstr _y) → nstr
add(@mut Stack allocator,nstr _x,nstr _y) → nstr
add(@mut Heap allocator,nstr _x,nstr _y) → nstr
add(@mut Region allocator,nstr _x,nstr _y) → nstr
add(@mut Arena allocator,nstr _x,nstr _y) → nstr
add(@mut Circular allocator,nstr _x,nstr _y) → nstr
add(@mut Dynamic allocator,nstr _x,nstr _y) → nstr
add(@mut Stack allocator,str _x,nstr _y) → nstr
add(@mut Heap allocator,str _x,nstr _y) → nstr
add(@mut Region allocator,str _x,nstr _y) → nstr
add(@mut Arena allocator,str _x,nstr _y) → nstr
add(@mut Circular allocator,str _x,nstr _y) → nstr
add(@mut Dynamic allocator,str _x,nstr _y) → nstr
add(@mut Stack allocator,cstr _x,str _y) → nstr
add(@mut Heap allocator,cstr _x,str _y) → nstr
add(@mut Region allocator,cstr _x,str _y) → nstr
add(@mut Arena allocator,cstr _x,str _y) → nstr
add(@mut Circular allocator,cstr _x,str _y) → nstr
add(@mut Dynamic allocator,cstr _x,str _y) → nstr
add(@mut Stack allocator,nstr _x,str _y) → nstr
add(@mut Heap allocator,nstr _x,str _y) → nstr
add(@mut Region allocator,nstr _x,str _y) → nstr
add(@mut Arena allocator,nstr _x,str _y) → nstr
add(@mut Circular allocator,nstr _x,str _y) → nstr
add(@mut Dynamic allocator,nstr _x,str _y) → nstr
add(@mut Stack allocator,str _x,str _y) → nstr
add(@mut Heap allocator,str _x,str _y) → nstr
add(@mut Region allocator,str _x,str _y) → nstr
add(@mut Arena allocator,str _x,str _y) → nstr
add(@mut Circular allocator,str _x,str _y) → nstr
add(@mut Dynamic allocator,str _x,str _y) → nstr

std.os unsafe 🔝

Standard library wrapping of C system calls and of process management using C popen.

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.

Process 🔝

A running process whose stdout can be read as a file-like object.

Process(nominal,ptr contents) → (nominal,ptr contents)

to_end 🔝

Reads all remaining output from the process without storing it.

to_end(@mut Process p) → ()

open 🔝

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() // synchronize

open(@mut Process,cstr _command) → Process
open(@mut Process,nstr _command) → Process
open(@mut Process,str command) → (Process)

next_chunk 🔝

Reads the next chunk of process output into a provided buffer.

next_chunk(@mut Region reader,@mut Process p,@mut nstr value) → bool
next_chunk(@mut Arena reader,@mut Process p,@mut nstr value) → bool
next_chunk(@mut Circular reader,@mut Process p,@mut nstr value) → bool
next_chunk(@mut Region memory,@mut Process p,@mut str value) → bool
next_chunk(@mut Arena memory,@mut Process p,@mut str value) → bool
next_chunk(@mut Circular memory,@mut Process p,@mut str value) → bool

next_line 🔝

Reads the next line of process output into a provided buffer.

next_line(@mut Region reader,@mut Process p,@mut nstr value) → bool
next_line(@mut Arena reader,@mut Process p,@mut nstr value) → bool
next_line(@mut Circular reader,@mut Process p,@mut nstr value) → bool
next_line(@mut Region memory,@mut Process p,@mut str value) → bool
next_line(@mut Arena memory,@mut Process p,@mut str value) → bool
next_line(@mut Circular memory,@mut Process p,@mut str value) → bool

system 🔝

system(cstr command) → ()
system(str command) → ()

std.rand unsafe 🔝

Standard library porting Xoshiro256plus random numbers from https://prng.di.unimi.it/. These and are NOT cryptographically secure.

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.

__rotl 🔝

__rotl(u64 x,u64 k) → u64

next 🔝

Computes the next random number of a Rand sequence.Example:

@mut rnd = Rand()
range(10)
:while next(@mut u64 i)
    print(rnd:next)
    end

next(@mut u64 self.s0,@mut u64 self.s1,@mut u64 self.s2,@mut u64 self.s3) → f64

splitmix64 🔝

Computes 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 f64
    end

splitmix64(@mut u64 x) → u64
splitmix64() → u64

Rand 🔝

This 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.

Rand(u64 seed) → (@mut u64 s0,@mut u64 s1,@mut u64 s2,@mut u64 s3)
Rand() → Rand(u64 seed)

std.time unsafe 🔝

Standard library wrapping of C time (provided by posix time.h or windows.h).

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.

sleep 🔝

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) → ()

exact_sleep 🔝

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) → ok

time 🔝

Retrieve time elapsed from the start of the program in f64 seconds.

time() → f64

std.vec unsafe 🔝

Standard library implementation of vectors that are allocated with safe memory management but use C pointers for element access.

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.

Vec 🔝

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.

Vec(nominal,ptr contents,u64 size,ptr surface) → (nominal,ptr contents,u64 size,ptr surface)

dot 🔝

dot(Vec x1,Vec x2) → f64

vector 🔝

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) → Vec
vector(@mut Heap memory,u64 size) → Vec
vector(@mut Region memory,u64 size) → Vec
vector(@mut Arena memory,u64 size) → Vec
vector(@mut Circular memory,u64 size) → Vec
vector(@mut Dynamic memory,u64 size) → Vec
vector(@mut Stack memory,@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,u64 size) → Vec
vector(@mut Heap memory,@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,u64 size) → Vec
vector(@mut Region memory,@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,u64 size) → Vec
vector(@mut Arena memory,@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,u64 size) → Vec
vector(@mut Circular memory,@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,u64 size) → Vec
vector(@mut Dynamic memory,@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,u64 size) → Vec
vector(@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,@mut Stack memory,u64 size) → Vec
vector(@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,@mut Heap memory,u64 size) → Vec
vector(@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,@mut Region memory,u64 size) → Vec
vector(@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,@mut Arena memory,u64 size) → Vec
vector(@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,@mut Circular memory,u64 size) → Vec
vector(@mut u64 rand.s0,@mut u64 rand.s1,@mut u64 rand.s2,@mut u64 rand.s3,@mut Dynamic memory,u64 size) → Vec

print 🔝

Prints a vector to the console. To avoid large prints, at most the first 10 elements are printed.

print(Vec v) → ()

put 🔝

put(@mut Vec v,u64 pos,f64 value) → Vec
put(@mut Vec x1,Vec x2) → ()

slice 🔝

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) → Vec

add 🔝

Adds 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+v2
    end

add(@mut Stack memory,Vec x1,Vec x2) → Vec
add(@mut Heap memory,Vec x1,Vec x2) → Vec
add(@mut Region memory,Vec x1,Vec x2) → Vec
add(@mut Arena memory,Vec x1,Vec x2) → Vec
add(@mut Circular memory,Vec x1,Vec x2) → Vec
add(@mut Dynamic memory,Vec x1,Vec x2) → Vec
add(@mut Vec result,Vec x1,Vec x2) → Vec

sub 🔝

Subtracts 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-v2
    end

sub(@mut Stack memory,Vec x1,Vec x2) → Vec
sub(@mut Heap memory,Vec x1,Vec x2) → Vec
sub(@mut Region memory,Vec x1,Vec x2) → Vec
sub(@mut Arena memory,Vec x1,Vec x2) → Vec
sub(@mut Circular memory,Vec x1,Vec x2) → Vec
sub(@mut Dynamic memory,Vec x1,Vec x2) → Vec
sub(@mut Vec result,Vec x1,Vec x2) → Vec

mul 🔝

Multiplies 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*v2
    end

mul(@mut Stack memory,Vec x1,Vec x2) → Vec
mul(@mut Heap memory,Vec x1,Vec x2) → Vec
mul(@mut Region memory,Vec x1,Vec x2) → Vec
mul(@mut Arena memory,Vec x1,Vec x2) → Vec
mul(@mut Circular memory,Vec x1,Vec x2) → Vec
mul(@mut Dynamic memory,Vec x1,Vec x2) → Vec
mul(@mut Vec result,Vec x1,Vec x2) → Vec

len 🔝

Retrieves the length of a vector.

len(Vec v) → u64

div 🔝

Divides 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/v2
    end

div(@mut Stack memory,Vec x1,Vec x2) → Vec
div(@mut Heap memory,Vec x1,Vec x2) → Vec
div(@mut Region memory,Vec x1,Vec x2) → Vec
div(@mut Arena memory,Vec x1,Vec x2) → Vec
div(@mut Circular memory,Vec x1,Vec x2) → Vec
div(@mut Dynamic memory,Vec x1,Vec x2) → Vec
div(@mut Vec result,Vec x1,Vec x2) → Vec

at 🔝

Retrieves 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) → f64