Documentation menu
Built-ins

Data & math

Numbers, text and bytes: the namespaces you reach for inside a program, before it touches anything outside itself. None of these need a permission.

Math

All math functions are called as Math.functionName(args):

out Math.PI    // → 3.141592653589793
out Math.E     // → 2.718281828459045

// Rounding
out Math.floor(3.9)    // → 3
out Math.ceil(3.1)     // → 4
out Math.round(3.5)    // → 4
out Math.trunc(-3.9)   // → -3  (toward zero)

// Basic
out Math.abs(-7)       // → 7
out Math.sqrt(16.0)    // → 4.0
out Math.pow(2.0, 10.0)  // → 1024.0

// Min / max / clamp
out Math.min(3, 1, 4, 1, 5)    // → 1
out Math.max(3, 1, 4, 1, 5)    // → 5
out Math.clamp(15, 0, 10)      // → 10

// Logarithms
out Math.log(Math.E)   // → 1.0
out Math.log2(8.0)     // → 3.0
out Math.log10(1000.0) // → 3.0

// Random — decimal in [0, 1)
out Math.random()

Trigonometry

All trig functions use radians:

out Math.sin(Math.PI / 2.0)   // → 1.0
out Math.cos(0.0)              // → 1.0
out Math.tan(Math.PI / 4.0)   // → ~1.0

out Math.atan2(1.0, 1.0)      // → 0.785...  (π/4)

// Degrees → radians helper
let deg = 90.0
let rad = deg * Math.PI / 180.0
out Math.sin(rad)   // → 1.0

Random

A seedable pseudo-random generator for games, simulations and model initialization. It is an LCG: seed it and the sequence repeats exactly, which is what you want for reproducible runs — and exactly what you do not want for anything secret.

Random.seed(42)             // reproducible sequence

out Random.decimal()        // [0, 1)
out Random.int(1, 6)        // [1, 6] inclusive
out Random.uniform(-1.0, 1.0)
out Random.normal(0.0, 1.0) // gaussian
out Random.bernoulli(0.3)   // true 30% of the time

let deck = [1, 2, 3, 4, 5]
out Random.shuffle(deck)    // Fisher-Yates copy — deck is untouched
out Random.choice(deck)     // one random element

// Tensor initializers (for neural nets)
let w = Random.normalTensor([64, 32], 0.0, 0.1)
let u = Random.uniformTensor([8], -0.5, 0.5)
MethodReturnsDescription
Random.seed(n)nullSets the generator seed
Random.decimal()decimalUniform in [0, 1)
Random.int(min, max)intUniform integer in [min, max], both inclusive
Random.uniform(lo, hi)decimalUniform in [lo, hi)
Random.normal(mean, std)decimalNormal distribution N(mean, std)
Random.bernoulli(p)booltrue with probability p
Random.shuffle(array)[any]Fisher-Yates shuffled copy — the original is untouched
Random.choice(array)anyOne random element
Random.normalTensor([shape], mean, std)TensorTensor filled with N(mean, std)
Random.uniformTensor([shape], lo, hi)TensorTensor filled with U[lo, hi)

JSON

Serialize any value to JSON and parse it back:

// Stringify — works with any value
out JSON.stringify(42)          // → "42"
out JSON.stringify(true)        // → "true"
out JSON.stringify([1, 2, 3])   // → "[1,2,3]"

let user <string, any> = ({"name", "Sergio"}, {"age", 28})
out JSON.stringify(user)
// → {"name":"Sergio","age":28}

// Parse — returns the equivalent Serez value
let json = '{"x": 10, "y": 20}'
let obj = JSON.parse(json)
out obj["x"]   // → 10

// Round-trip
let original = [1, "hello", true, null]
let json_str = JSON.stringify(original)
let parsed   = JSON.parse(json_str)
out parsed[1]   // → hello

Use JSON.pretty(value, [indent]) for indented, human-readable output — great for inspecting a fetch response in the console. The indent (spaces per level) defaults to 2; an indent of 0 falls back to compact. If the value is a raw JSON string (such as a fetch body), it is parsed first and then re-indented.

native fn string fetch(string url)

let body = fetch("https://api.example.com/data")

// Pretty-print the raw response body (2-space indent by default)
out JSON.pretty(body)
// → {
//     "name": "Sergio",
//     "age": 28
//   }

out JSON.pretty(body, 4)   // 4-space indent

// Works on structured values too
out JSON.pretty(user)

Regex

A dependency-free regular-expression engine written for this runtime. It is a backtracking engine compiled to a small bytecode, with a bounded step budget: a pathological pattern can never hang the program or blow the stack — it returns "no match" instead.

out Regex.test("^\\d+$", "12345")            // true

// match → [whole, group1, group2, …] or null
let m = Regex.match("(\\w+)@(\\w+)\\.com", "hi [email protected]")
out m[0]   // [email protected]
out m[1]   // bob
out m[2]   // mail

out Regex.findAll("\\d+", "a1 b22 c333")       // ["1", "22", "333"]
out Regex.split("\\s*,\\s*", "a , b,c")        // ["a", "b", "c"]

// $0/$& is the whole match, $1..$9 the groups, $$ a literal $
out Regex.replace("(\\w+) (\\w+)", "hello world", "$2 $1")   // world hello

Supported syntax: literals, . (any character except newline), the classes \d \D \w \W \s \S and escapes (\. \\ \n \t \r), character classes [abc] [a-z] [^…], the anchors ^ and $, groups ( … ) and non-capturing (?: … ), alternation |, and the quantifiers * + ? {n} {n,} {n,m}, each optionally lazy (*?).

MethodReturnsDescription
Regex.test(pattern, text)boolWhether the pattern matches anywhere in the text
Regex.match(pattern, text)[any]?[whole, group1, …] for the first match, or null
Regex.findAll(pattern, text)[string]Every non-overlapping match
Regex.split(pattern, text)[string]Splits the text on each match
Regex.replace(pattern, text, repl)stringReplaces every match; $0/$& = whole, $1..$9 = groups, $$ = literal $

Binary

Byte-array utilities for binary data. Every operation works on plain Serez integer arrays whose values are bytes (0–255), so they compose with File.read_asBinary, sockets and Crypto without any special type.

let bytes = Binary.fromUtf8("héllo")   // UTF-8 bytes
out Binary.toUtf8(bytes)               // héllo
out Binary.toHex(bytes)                // 68c3a96c6c6f
out Binary.fromHex("6869")             // [104, 105]

// Fixed-width integers, little- and big-endian
let le = Binary.packInt32Le(1000)      // [232, 3, 0, 0]
out Binary.unpackInt32Le(le)           // 1000
out Binary.unpackInt32Be(Binary.packInt32Be(1000))
out Binary.unpackInt64Le(Binary.packInt64Le(9000000000))

out Binary.concat([1, 2], [3, 4])      // [1, 2, 3, 4]
MethodReturnsDescription
Binary.fromHex(hex)[int]Decodes a hex string into a byte array
Binary.toHex(bytes)stringEncodes a byte array as lowercase hex
Binary.fromUtf8(s)[int]UTF-8 bytes of a string
Binary.toUtf8(bytes)stringDecodes a UTF-8 byte array into a string
Binary.packInt32Le(n)[int]4-byte little-endian encoding
Binary.packInt32Be(n)[int]4-byte big-endian encoding
Binary.packInt64Le(n)[int]8-byte little-endian encoding
Binary.unpackInt32Le(bytes)intReads a 4-byte little-endian integer
Binary.unpackInt32Be(bytes)intReads a 4-byte big-endian integer
Binary.unpackInt64Le(bytes)intReads an 8-byte little-endian integer
Binary.concat(a, b)[int]Concatenates two byte arrays

Crypto

Hashing, encodings, a real CSPRNG and Ed25519 signatures. Pure compute — no permission declaration required. Random bytes come from the operating system's entropy source, and signatures use a vetted, audited implementation rather than a hand-rolled one.

// Hashes → lowercase hex
out Crypto.sha256("hello")            // 2cf24dba5fb0a30e...
out Crypto.md5("hello")               // 5d41402abc4b2a76...
out Crypto.hmacSha256("key", "data")  // signed digest, hex

// Encodings
let b64 = Crypto.base64encode("hello")   // aGVsbG8=
out Crypto.base64decode(b64)             // hello
out Crypto.hexEncode([104, 105])         // 6869
out Crypto.hexDecode("6869")             // [104, 105]

// Cryptographically secure random bytes (OS entropy)
let salt = Crypto.randomBytes(16)        // [int] — up to 1 MiB per call

// Ed25519 signatures
let keys = Crypto.ed25519Keypair()       // { private: hex, public: hex }
let sig  = Crypto.ed25519Sign(keys["private"], "message")
out Crypto.ed25519Verify(keys["public"], "message", sig)   // true

Never use Random.* for anything secret. It is a seedable LCG and therefore predictable. Tokens, salts and keys come from Crypto.randomBytes.

MethodReturnsDescription
Crypto.sha256(text)stringSHA-256 digest as lowercase hex
Crypto.sha1(text)stringSHA-1 digest as lowercase hex
Crypto.sha1base64(text)stringSHA-1 digest, base64 encoded (WebSocket handshake)
Crypto.md5(text)stringMD5 digest as lowercase hex — for checksums, not for security
Crypto.hmacSha256(key, data)stringHMAC-SHA256 as lowercase hex
Crypto.base64encode(text)stringBase64 encoding of the text
Crypto.base64decode(b64)stringDecodes base64; throws if the result is not valid UTF-8
Crypto.hexEncode(bytes)stringByte array → lowercase hex string
Crypto.hexDecode(hex)[int]Hex string → byte array
Crypto.randomBytes(n)[int]n cryptographically secure random bytes (OS entropy, max 1 MiB)
Crypto.ed25519Keypair()dictNew keypair as { private, public } hex strings
Crypto.ed25519Sign(privateHex, message)stringSignature as hex
Crypto.ed25519Verify(publicHex, message, signatureHex)boolVerifies a signature