@std/prelude

API Reference

implicit scope
Symbols in @std/prelude are available in every Rasmalai source file out-of-the-box without an explicit import. Explicit imports are supported for disambiguation.

class Any

Untyped escape hatch. Nothing on an Any is resolved statically, so cast before use with v as Int or v as String.

class Array

Dense growable sequence with Int indexes.

Methods, all compiler builtins needing no import: length(): Int, len(): Int, isEmpty(): Bool, push(item), pop(), map(closure), filter(closure). length and len also read as properties. map builds a new array from the closure's return value; filter keeps the elements the closure accepts and keeps their original type.

pop() takes the last element and gives null on an empty array. Reading an index past the end throws index out of bounds, so check the length first.

Search and fold helpers (find, findIndex, some, every, reduce, join, reversed) are extension methods below.

fn every(predicate: fn(T): Bool): Bool

Whether every element satisfies predicate.

predicate — called once per element, in index order.

returns — false on the first rejection, true for an empty array.

print([4, 9, 16].every((x: Int): Bool => x > 0));
Run in Playground
fn find(predicate: fn(T): Bool): T?

First element satisfying predicate.

predicate — called once per element, in index order.

returns — the first match, or `null` when the array is empty or nothing matches.

let xs = [4, 9, 16];
print(xs.find((x: Int): Bool => x > 5) ?? -1);
Run in Playground
fn findIndex(predicate: fn(T): Bool): Int

Where the first matching element sits.

predicate — called once per element, in index order.

returns — the zero-based index of the first match, or -1 when the array is empty or nothing matches.

let xs = [4, 9, 16];
print(xs.findIndex((x: Int): Bool => x > 5));
Run in Playground
fn join(separator: String): String

Render every element and glue the pieces with separator.

separator — text between elements; `""` when omitted.

returns — the joined text, `""` for an empty array.

print([4, 9, 16].join(" | "));
Run in Playground
fn reduce(initial: U, reducer: fn(U, T): U): U

Left fold: thread initial through reducer over each element.

initial — value handed to the first `reducer` call.

reducer — called with the accumulator and the next element.

returns — the last accumulator, which is `initial` for an empty array.

print([4, 9, 16].reduce<Int>(0, (acc: Int, x: Int): Int => acc + x));
Run in Playground
fn reversed(): Array<T>

Reverse this array into a copy.

returns — a new array holding the same elements back to front.

print([4, 9, 16].reversed().join(","));
Run in Playground
fn some(predicate: fn(T): Bool): Bool

Whether any element satisfies predicate.

predicate — called once per element, in index order.

returns — true on the first match, false for an empty array.

print([4, 9, 16].some((x: Int): Bool => x == 9));
Run in Playground
class ArrayIter

Index-based iterator over an array. It holds the array and a cursor, walks the array in place, and yields null once the cursor passes the end. for..in accepts it directly.

init(arr: Array<T>)

fields

  • arr: Array<T>
  • i: Int
fn next(): T?

Take the next element and step the cursor on.

returns — the element at the cursor, or `null` past the end.

class Bool

Foundation boolean type: true or false.

Methods: toString(): String, which prints true or false.

class Char

Single scalar view into a String. The checker treats a Char as a String, and charCodeAt is how you read the scalar value.

class Date

Calendar view over the wall clock. Catalog stub: @std/time owns the clocks, and none of them report calendar dates.

class Error

Error value. Catalog stub: throw raises a String message and catch (e) binds it, so an Error carries nothing on its own.

class FastFloat

Relaxed float type.

Produced by Float.asFast() and read back with asStrict(). It mixes with Float only after an explicit conversion, and comparing one with the other needs 82.5.asFast()-style literals.

class Float

Foundation float type: an IEEE-754 double.

Methods: toString(): String, toBits(): Int, asFast(): FastFloat, asStrict(): Float. Statics: Float.nan(), Float.isNaN(x), Float.fma(a, b, c), Float.fromBits(bits).

A Float and a FastFloat never mix in one expression; the mix is E305, so name the conversion you mean.

class GenRef

Generational reference for cyclic edges. GenRef.of(x) takes a reference without raising the owner's retain count, and .get() gives null once the owner is gone, so a back edge never keeps a graph alive. ARC owns, GenRef points back; use #[Allow(CyclicReference)] on a field for a strong cycle you mean to break yourself.

class Int

Foundation integer type: a signed 64-bit whole number.

Methods: toString(): String. Convert a float with Int(x), which truncates toward zero, and render a number with x.toString().

class Map

Insertion-ordered key-value table. Catalog stub: Map and its methods live in @std/collections.

class Promise

One-shot eventual value: Pending (0), Fulfilled (1), Rejected (2). Combinators attach continuations; wait() parks the OS thread until settlement. The first settlement wins and later calls are ignored. A rejection carries a String reason.

Every combinator hands back a new promise and leaves this one as it is, so a chain of them settles independently at each link. Handlers added after settlement run at once on the calling thread.

init(state: Int, value: T, reason: String, syncId: Int)

fields

  • _handlers: Array<fn(T): Void>
  • _reason: String
  • _rejectHandlers: Array<fn(String): Void>
  • _state: Int
  • _syncId: Int
  • _value: T
fn all(promises: Array<Promise<T>>): Promise<Array<T>>

Wait for every promise and fulfill with the payloads in input order, whatever order they settle in. The first rejection wins and rejects the result; later settlements are ignored. An empty array fulfills with [].

promises — promises to wait on.

returns — a promise for the payloads, or the first rejection.

let ps: Array<Promise<Int>> = [Promise.resolve(1), Promise.resolve(2)];
let all: Result<Array<Int>, String> = Promise.all<Int>(ps).wait();
let got: Array<Int> = all.unwrap();
print(got.join(","));
Run in Playground
fn allRej(out: Promise<Array<U>>): fn(String): Void

Build the rejection continuation Promise.all hands each input. Internal: one of these rejects out and settles the combinator.

out — promise the first rejection rejects.

returns — a continuation taking the reason.

fn allSettled(promises: Array<Promise<T>>): Promise<Array<PromiseResult<T>>>

Wait for every promise and never reject. Each input turns into a PromiseResult in input order holding either the payload or the rejection message. An empty array fulfills with [].

promises — promises to wait on.

returns — a promise for one settlement record per input.

let ps: Array<Promise<Int>> = [Promise.resolve(5), Promise.reject<Int>("bad")];
let all: Result<Array<PromiseResult<Int>>, String> = Promise.allSettled<Int>(ps).wait();
let got: Array<PromiseResult<Int>> = all.unwrap();
print(got[0].status);
print(got[1].reason);
Run in Playground
fn allSlot(slots: Array<U>, out: Promise<Array<U>>, counterId: Int, n: Int, idx: Int): fn(U): Void

Build the fulfillment continuation Promise.all hands each input. Internal: one of these writes its slot, and the last one to finish fulfills out with the slots in input order.

slots — scratch array holding one payload per input.

out — promise the last input fulfills.

counterId — registry id of the remaining-count atomic.

n — how many inputs there are.

idx — this input's index.

returns — a continuation taking the payload.

fn any(promises: Array<Promise<T>>): Promise<T>

Fulfill with the first payload to arrive. Only once every input has rejected does the result reject, and then with "AggregateError: all promises rejected". An empty array rejects at once with "AggregateError: no promises".

promises — promises to try.

returns — a promise for the first payload, or the aggregate rejection.

let mixed: Array<Promise<Int>> = [Promise.reject<Int>("no"), Promise.resolve(5)];
print(Promise.any<Int>(mixed).wait().unwrap());
Run in Playground
fn anyFwd(out: Promise<U>): fn(U): Void

Build the fulfillment continuation Promise.any hands each input. Internal: one of these fulfills out, and only the first to arrive has any effect.

out — promise the winner fulfills.

returns — a continuation taking the payload.

fn anyRej(out: Promise<U>, counterId: Int): fn(String): Void

Build the rejection continuation Promise.any hands each input. Internal: one of these decrements the count, and the one that finds nothing left rejects out with the aggregate message.

out — promise the aggregate rejection settles.

counterId — registry id of the remaining-count atomic.

returns — a continuation taking the reason.

fn attach(onF: fn(T): Void, onR: fn(String): Void): Void

Register both continuations. A pending promise queues one pair per call; a settled promise runs the matching continuation at once on the calling thread and queues nothing. Only one of the two ever runs for a given promise.

onF — called with the payload on fulfillment.

onR — called with the message on rejection.

let wr = Promise.withResolvers<Int>();
wr.promise.attach((v: Int): Void => print("got", v), (e: String): Void => print("bad", e));
wr.resolve(7);
Run in Playground
fn catchReject(onRejected: fn(String): U): Promise<U>

Chain a rejection handler. A fulfillment passes through with its payload untouched; a rejection runs the closure and the new promise fulfills with the closure's result, so the chain recovers instead of staying rejected.

onRejected — runs with the reason and produces the new payload.

returns — a promise that turns this rejection into a fulfillment.

let r: Result<Int, String> = Promise.reject<Int>("x").catchReject<Int>((e: String): Int => 99).wait();
print(r.unwrap());
Run in Playground
fn finallyDo(onFinally: fn(): Void): Promise<T>

Chain a handler that runs on either outcome and leaves it alone. The closure runs before the new promise settles, so what it prints lands before the value read from wait().

onFinally — runs once the promise settles, either way.

returns — a promise carrying the original outcome.

let r: Result<Int, String> = Promise.resolve(7).finallyDo(() => print("done")).wait();
print(r.unwrap());
Run in Playground
fn freshId(): Int

Take the next id from the shared counter. Internal: every promise needs its own mutex and condvar id.

returns — a fresh registry id.

fn fulfill(val: T): Void

Settle as fulfilled with val. Ignored unless the promise is still pending, so the first settlement wins. Queued handlers run after the guard is released, never while holding it.

val — payload for the fulfillment.

fn race(promises: Array<Promise<T>>): Promise<T>

Settle with whichever input settles first, fulfillment or rejection alike; the first settlement copies across and later ones are ignored. The losing inputs keep running, so avoid handing race work that must not continue. An empty array never settles, and wait() on the result gives back Err after its 5s timeout.

promises — promises to race.

returns — a promise carrying the first settlement.

let ps: Array<Promise<Int>> = [Promise.resolve(1), Promise.resolve(2)];
print(Promise.race<Int>(ps).wait().unwrap());
Run in Playground
fn raceFwd(out: Promise<U>): fn(U): Void

Build the fulfillment continuation Promise.race hands each input. Internal: one of these fulfills out, and only the first to arrive has any effect.

out — promise the winner fulfills.

returns — a continuation taking the payload.

fn raceRej(out: Promise<U>): fn(String): Void

Build the rejection continuation Promise.race hands each input. Internal: one of these rejects out, and only the first to arrive has any effect.

out — promise the first rejection rejects.

returns — a continuation taking the reason.

fn reject(reason: String): Promise<T>

A promise that is already rejected.

reason — message the rejection carries.

returns — a rejected promise; `wait()` gives back `Result.Err` holding the same message.

fn rejectWith(reason: String): Void

Settle as rejected with reason. Ignored unless the promise is still pending, so the first settlement wins. Queued handlers run after the guard is released, never while holding it.

reason — message for the rejection.

fn resolve(val: T): Promise<T>

A promise that is already fulfilled.

val — payload carried by the promise.

returns — a fulfilled promise; handlers attached later run at once.

fn settledRej(slots: Array<PromiseResult<U>>, out: Promise<Array<PromiseResult<U>>>, counterId: Int, n: Int, idx: Int): fn(String): Void

Build the rejection continuation Promise.allSettled hands each input. Internal: one of these writes a "rejected" record and decrements the count, and the last one fulfills out with every record in input order.

slots — scratch array holding one record per input.

out — promise the last input fulfills.

counterId — registry id of the remaining-count atomic.

n — how many inputs there are.

idx — this input's index.

returns — a continuation taking the reason.

fn settledSlot(slots: Array<PromiseResult<U>>, out: Promise<Array<PromiseResult<U>>>, counterId: Int, n: Int, idx: Int, ok: Bool): fn(U): Void

Build the fulfillment continuation Promise.allSettled hands each input. Internal: one of these writes a "fulfilled" record and decrements the count, and the last one fulfills out with every record in input order.

slots — scratch array holding one record per input.

out — promise the last input fulfills.

counterId — registry id of the remaining-count atomic.

n — how many inputs there are.

idx — this input's index.

ok — true for the fulfillment continuation.

returns — a continuation taking the payload.

fn then(onFulfilled: fn(T): U): Promise<U>

Chain a fulfillment handler. A rejection skips the closure and reaches the new promise unchanged, so catchReject is what recovers from one. The closure's return value becomes the payload the new promise settles with.

onFulfilled — runs with the payload and produces the new payload.

returns — a promise for the closure's result.

let a: Result<Int, String> = Promise.resolve(20).then<Int>((v: Int): Int => v + 1).wait();
print(a.unwrap());
let b: Result<Int, String> = Promise.reject<Int>("bad").then<Int>((v: Int): Int => v + 1).wait();
print(b.isErr());
Run in Playground
fn wait(): Result<T, String>

Park the calling OS thread until the promise settles, without spinning: it sleeps on a condvar in 1s slices and gives up after 5s. Fine in a plain function or a Thread.spawn body; inside an async fn it is a compile error, because parking an event-loop task deadlocks.

returns — `Ok(val)` on fulfillment and `Err(reason)` on rejection, and `Err` with a timeout message when nothing settles in 5s.

let r: Result<Int, String> = Promise.resolve(41).wait();
print(r.unwrap());
Run in Playground
fn waitAny(p: Promise<Any>): Result<Any, String>

Park until p settles. This is the bridge await lowers to, so user code should reach for await or wait() instead.

p — promise to wait on.

returns — `Ok(val)` on fulfillment, `Err(reason)` on rejection.

fn withResolvers(): PromiseWithResolvers<T>

A pending promise together with the handles that settle it. Use it when the value arrives from somewhere the promise cannot own, such as a worker thread or an OS callback.

returns — a pending promise wrapped with `resolve` and `reject`.

let wr = Promise.withResolvers<Int>();
wr.resolve(42);
let r: Result<Int, String> = wr.promise.wait();
print(r.unwrap());
Run in Playground
class PromiseResult

Settlement record for Promise.allSettled. One per input promise, in input order: status is "fulfilled" or "rejected", value holds the payload of a fulfillment, and reason the message of a rejection.

init(status: String, value: T, reason: String)

fields

  • reason: String
  • status: String
  • value: T
class PromiseWithResolvers

Manual settlement handles from Promise.withResolvers. It holds the pending promise plus the two calls that settle it, which is how a worker thread, an OS callback, or an I/O handler hands a value back into the promise chain.

init(promise: Promise<T>)

fields

  • promise: Promise<T>
fn reject(reason: String): Void

Reject the promise with reason. Ignored once the promise has settled; the first settlement wins.

reason — message carried by the rejection.

fn resolve(val: T): Void

Fulfill the promise with val. Ignored once the promise has settled; the first settlement wins.

val — payload for the fulfillment.

class RnxHost

Host metadata: rnx is ambient in every module with no import. version is the compiler version string, args holds the CLI arguments after the script path, cwd() reads the working directory, and exit(code) terminates immediately.

init()

fields

  • args: Array<String>
  • version: String
fn cwd(): String

Read the working directory of the process.

returns — the path the process was started in.

fn exit(code: Int)

Stop the process now. Nothing after the call runs and the exit status is the code given.

code — exit status handed to the host.

class Set

Distinct-member collection. Catalog stub: Set and its methods live in @std/collections.

class String

Canonical UTF-8 string type.

Every index counts characters, not bytes, so a multi-byte character is one step like any other.

Methods, all compiler builtins needing no import: length(): Int, len(): Int, slice(start: Int, end: Int): String, indexOf(needle: String): Int, indexOf(needle: String, from: Int): Int, trim(): String, concat(other: String): String, charCodeAt(index: Int): Int. length and len also read as properties.

slice clamps both bounds to the length and gives "" once the start reaches the end. Both indexOf forms give the index of the first match at or after their start, or -1 when there is none; an empty needle answers with the start it was given. trim strips leading and trailing whitespace. charCodeAt gives the Unicode code point of the character at that index, or -1 past the end.

Search and transform helpers (contains, startsWith, endsWith, split, replace, replaceAll, repeat, toUpperCase, toLowerCase) are extension methods below.

fn contains(search: String): Bool

Whether search occurs anywhere in this string.

search — text to look for; `""` is always contained.

returns — true on a hit, false otherwise.

print("rasmalai/compiler".contains("compiler"));
Run in Playground
fn endsWith(suffix: String): Bool

Whether this string ends with suffix.

suffix — text to compare; `""` always matches.

returns — true on a match, false otherwise.

print("rasmalai".endsWith("ai"));
Run in Playground
fn repeat(count: Int): String

Copy this string back to back.

count — how many copies; `0` or less gives `""`.

returns — the repeated text.

print("ab".repeat(3));
Run in Playground
fn replace(target: String, replacement: String): String

Swap the first occurrence of target for replacement.

target — text to look for.

replacement — text to put in its place.

returns — a new string, or this one unchanged when `target` is absent.

print("rasmalai/compiler".replace("/", "-"));
Run in Playground
fn replaceAll(target: String, replacement: String): String

Swap every occurrence of target for replacement.

target — text to look for; `""` leaves the string unchanged.

replacement — text to put in place of each hit.

returns — a new string with every occurrence replaced.

print("a-b-c".replaceAll("-", "+"));
Run in Playground
fn split(delimiter: String): Array<String>

Cut this string around every delimiter.

delimiter — text to cut on; `""` gives one element per character.

returns — the pieces in order, one element when there is no delimiter.

print("rasmalai/compiler".split("/").length());
Run in Playground
fn startsWith(prefix: String): Bool

Whether this string begins with prefix.

prefix — text to compare; `""` always matches.

returns — true on a match, false otherwise.

print("rasmalai".startsWith("ras"));
Run in Playground
fn toLowerCase(): String

Fold this string to lower case. Only ASCII A to Z change; every other character, accented Latin included, passes through untouched, so "HÉLLO" gives "hÉllo".

returns — a new string with the ASCII letters lower-cased.

print("HeLLo".toLowerCase());
Run in Playground
fn toUpperCase(): String

Fold this string to upper case. Only ASCII a to z change; every other character, accented Latin included, passes through untouched, so "héllo" gives "HéLLO".

returns — a new string with the ASCII letters upper-cased.

print("hello".toUpperCase());
Run in Playground
class Void

Absence of a return value. Void marks a function that only has effects; null is the absent value itself, of type Null.

enum Result
  • Err(E)
  • Ok(T)