zena:core

zena
import {…} from 'zena:core';

Foundational language types and utilities: strings, errors, options, results, boxes, ranges, arrays, iterators, and byte buffers.

Many declarations here are available automatically in the language prelude.

Evolving String Internals

String representation and low-level byte access methods are undergoing active redesign. See the Strings guide for current details.

Classes

String

zena
final class String implements Hashable, Stringable, Iterable<String>
Re-exported from zena:core/string.zena

An immutable sequence of characters with value equality.

Strings are created from string literals, template literals, concatenation, slicing, and StringBuilder.

Indexing and slicing operate on StringIndex values (str[i], str[start..end], str[start..], str[..end], str[..]), which are guaranteed to lie on Unicode scalar boundaries. Iteration (for (let ch in str)) yields grapheme clusters as String slices by default. Use str.codePoints to iterate Unicode scalar values (i32), str.utf8 for a UTF-8 byte view (u8), or str.utf16 for a UTF-16 code unit view (u16).

Properties
zena
encoding: Encoding { get; }
#

The encoding of the backing bytes. Encoding is deliberately an internal detail almost everywhere; this exists for boundary code — canonical-ABI marshaling, host interop — that copies the bytes verbatim and must assert what it is copying rather than assume.

zena
isEmpty: boolean { get; }
#

True when this string contains zero bytes.

zena
length: i32 { get; }
#

The length of the string in bytes of its own encoding.

Deprecated.

The byte length depends on the encoding. Use isEmpty, utf8.length, utf16.length, or graphemes.count() instead.

zena
startIndex: StringIndex { get; }
#

The index of the first character in this string (always byte offset 0).

zena
endIndex: StringIndex { get; }
#

The "past the end" index of this string.

zena
graphemes: StringGraphemes { get; }
#

View of this string's extended grapheme clusters as String slices. Zero heap allocation.

zena
codePoints: StringCodePoints { get; }
#

View of this string's decoded Unicode scalar values as i32. Zero heap allocation.

zena
utf8: StringUtf8View { get; }
#

Contiguous UTF-8 / WTF-8 byte view (u8) of this string.

Zero-copy when this.encoding == Encoding.WTF8; transcodes to a fresh UTF-8 ByteArray when this.encoding == Encoding.WTF16.

zena
utf16: StringUtf16View { get; }
#

Contiguous UTF-16 / WTF-16 code unit view (u16) of this string.

Zero-copy when this.encoding == Encoding.WTF16; transcodes to a fresh little-endian UTF-16 ByteArray when this.encoding == Encoding.WTF8.

Methods
zena
static fromByteArray(data: ByteArray, start: i32, end: i32, encoding: Encoding): String
#

Creates a String from a ByteArray with given bounds and encoding. This is used by StringBuilder and other internal operations.

zena
static fromBytes(bytes: FixedArray<u8>): String
#

A String over a copy of bytes, taken as WTF-8 — the bytes a response body or a file arrives as. Zena strings are views over byte arrays, so nothing is re-encoded; the copy is what turns a fixed array into the backing store a view needs.

zena
static fromCodePoint(code: i32): String
#

Creates a String containing a single Unicode code point code. Throws IndexOutOfBoundsError if code is outside 0..0x10FFFF.

zena
static fromCodePoints<A extends Array<i32>>(codes: A): String
#

Creates a String from a sequence of Unicode code points. Throws IndexOutOfBoundsError if any code point is outside 0..0x10FFFF.

zena
toBytes(): FixedArray<u8>
#

A copy of this string's UTF-8 / WTF-8 bytes. The inverse of fromBytes: what a list<u8> position wants, a header value or a body.

zena
static fromParts<A extends Array<String>>(parts: A): String
#

Creates a new string by concatenating all parts. This is more efficient than chained + operators for multiple strings, as it allocates the result array only once.

Generic over the array representation: element access resolves through the bound, so each specialization reads its receiver directly with no interface dispatch.

zena
static fromRawParts(parts: array<String>): String
#

The raw-array entry the compiler's synthesized string joins call — template-literal lowering resolves it by name against a one-parameter raw-array signature. Its body is also the call site that keeps the FixedArray specialization of fromParts reachable. User code calls fromParts.

zena
indexAfter(i: StringIndex): StringIndex
#

Returns the StringIndex immediately following the extended grapheme cluster at i. Throws IndexOutOfBoundsError if i is at endIndex or is not a valid boundary of this string.

zena
indexBefore(i: StringIndex): StringIndex
#

Returns the StringIndex at the start of the extended grapheme cluster immediately preceding i. Throws IndexOutOfBoundsError if i is at startIndex or is not a valid boundary of this string.

zena
scalarIndexAfter(i: StringIndex): StringIndex
#

Returns the StringIndex immediately following the Unicode scalar value at i. Throws IndexOutOfBoundsError if i is at endIndex or is not a valid boundary of this string.

zena
scalarIndexBefore(i: StringIndex): StringIndex
#

Returns the StringIndex of the Unicode scalar value immediately preceding i. Throws IndexOutOfBoundsError if i is at startIndex or is not a valid boundary of this string.

zena
indexOffsetBy(from: StringIndex, count: i32): inline (true, StringIndex) | inline (false, _)
#

Advances from by count grapheme clusters (count >= 0 moves forward, count < 0 moves backward). Returns (true, index) if within bounds, or (false, _) if stepping past startIndex or endIndex.

zena
slice(start: StringIndex, end: StringIndex): String
#

O(1) zero-copy slice from start to end (exclusive). Throws IndexOutOfBoundsError if start or end is not a valid boundary of this string or if start > end.

zena
slice(start: StringIndex): String
#

O(1) zero-copy slice from start to endIndex.

zena
reverse(): String
#

Returns a new String with its extended grapheme clusters in reverse order. Preserves combining mark sequences and multi-code-point emojis.

zena
getByteAt(index: i32): i32
#

Returns the byte at index of the string's own encoding.

Deprecated.

Which bytes a string has depends on its encoding. Use utf8[index] or utf16[index] instead.

zena
codePointAt(index: StringIndex): i32
#

Returns the Unicode scalar value at index. Throws IndexOutOfBoundsError if index is at endIndex or is not a valid boundary of this string.

zena
codePointAt(index: i32): i32
#

Returns the Unicode code point at byte offset index. For multi-byte UTF-8 sequences, decodes the full code point. Returns -1 if index is out of bounds or points to an invalid sequence.

Deprecated.

Use codePointAt(StringIndex) or codePoints instead.

zena
getI32At(index: i32): i32
#

Returns 4 bytes starting at index packed as a little-endian 32-bit integer.

zena
sliceBytes(start: i32, end: i32): String
#

O(1) zero-copy slice by byte offsets of the string's own encoding, clamped to the string. Returns a new String sharing the backing array.

SAFETY: Offsets are byte indices, not Unicode boundaries. Slicing inside a multi-byte UTF-8 sequence produces an ill-formed string.

Deprecated.

Use str[start..end] with indices from utf8.indexAt or utf16.indexAt, or slice(start, end).

zena
copy(): String
#

Force a copy - creates a new String with its own backing array. Use this when you need to release the parent string's memory.

zena
copyBytesTo(target: ByteArray, targetOffset: i32, start: i32 = 0, length: i32 = -1): void
#

Copies bytes from this string to a target ByteArray.

target

The target ByteArray to copy to.

targetOffset

The offset in target to start writing.

start

Start byte offset in this string (default: 0).

length

Number of bytes to copy (default: rest of string from start).

zena
regionEqualsBytes(other: String, start: i32, end: i32): boolean
#

True if this string's bytes are exactly the bytes of other in [start, end).

For matching against a range of a larger string without slicing it out first — the inner loop of a string table, which asks "is the text I just scanned the string already in this slot?" once per probe. Going through sliceBytes and == instead would allocate a view per probe and re-do the bounds and hash checks that the caller has already settled.

A range falling outside other does not match, rather than reading out of bounds — unlike sliceBytes, which clamps. Clamping would be wrong here: it would silently compare against a shorter range and could report a match the caller never asked about.

SAFETY: as with sliceBytes, the offsets are bytes and are not required to fall on code point boundaries — this compares encoded bytes, so a range that splits a multi-byte sequence simply will not match any whole string.

zena
startsWith(prefix: String): boolean
#

Returns true if this string starts with the given prefix.

zena
endsWith(suffix: String): boolean
#

Returns true if this string ends with the given suffix.

zena
split(separator: String): FixedArray<String>
#

Splits the string into an array of substrings separated by the given separator.

zena
indexOf(needle: String): inline (true, StringIndex) | inline (false, _)
#

Finds the first occurrence of needle in this string. Returns (true, index) if found, or (false, _) if not found.

zena
indexOf(needle: String, from: StringIndex): inline (true, StringIndex) | inline (false, _)
#

Finds the first occurrence of needle at or after from. Throws IndexOutOfBoundsError if from is not a valid boundary of this string. Returns (true, index) if found, or (false, _) if not found.

zena
contains(needle: String): boolean
#

Returns true if needle occurs anywhere in this string. Overrides IterableUtils<String>.contains to perform a substring search.

zena
getBackingArrayIfFull(): ByteArray | null
#

Returns the backing ByteArray if the String spans the entire array (i.e. not a slice). Used for optimization by StringBuilder.

zena
compareTo(other: String): i32
#

Compares this string with other in lexicographical code point order.

Returns:

  • < 0 if this < other
  • 0 if this == other
  • > 0 if this > other

In UTF-8, lexicographical byte comparison matches Unicode code point order.

zena
asciiLowerCase(): String
#

Returns this string with every ASCII letter lowercased; every other byte is left alone. See asciiLowerByte for why this is deliberately not Unicode-aware.

Byte-wise, which is exactly right for WTF-8: an ASCII byte is always a whole code point, and no continuation byte falls in 0x41..0x5A, so no multi-byte sequence can be corrupted. A WTF-16 string would instead need code-unit stepping — and that branch belongs here, on #encoding, rather than in every caller, which is the reason this lives on String at all. No String method supports WTF-16 yet and nothing constructs one today.

Returns this when there is nothing to change, so the common already-lowercase case does not allocate.

zena
asciiUpperCase(): String
#

Returns this string with every ASCII letter uppercased.

zena
toLowerCase(): String
#

Returns this string lowercased by Unicode's default case mapping, as JavaScript's toLowerCase does: 'ÀB' becomes 'àb', 'İ' becomes 'i̇' (two code points), and a Σ that ends a word becomes ς. Language-specific mappings, such as the Turkish dotless ı, are not applied. Returns this when nothing changes. For ASCII letters only, use asciiLowerCase.

Whether a Σ ends a word is decided more cheaply than JavaScript decides it, so the two can differ beside an uncommon character (#isFinalSigma).

zena
toUpperCase(): String
#

Returns this string uppercased by Unicode's default case mapping, as JavaScript's toUpperCase does: 'àb' becomes 'ÀB' and 'ß' becomes 'SS'. Returns this when nothing changes. For ASCII letters only, use asciiUpperCase.

zena
trim(): String
#

Returns this string without the ASCII whitespace at either end: spaces, tabs, line feeds, form feeds and carriage returns. Other whitespace, like a no-break space, is kept.

zena
'  Content-Length: 12\r\n'.trim(); // 'Content-Length: 12'
zena
filter(predicate: (item: String) => boolean): Iterable<String>
#
zena
all(predicate: (item: String) => boolean): boolean
#
zena
some(predicate: (item: String) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: String) => R): R
#
zena
find(predicate: (item: String) => boolean): inline (true, String) | inline (false, _)
#
zena
hashCode(): i32
#
Operators
zena
operator [](index: StringIndex): String
#

Returns the single extended grapheme cluster starting at index as a zero-copy String slice. Throws IndexOutOfBoundsError if index is at endIndex or is not a valid boundary of this string.

zena
operator [](r: Range<StringIndex>): String
#

Returns the substring covered by r (start..end, start.., or ..end) as a zero-copy String slice. Throws IndexOutOfBoundsError if the bounds are invalid or out of order.

zena
operator [](_r: FullRange): String
#

Returns the full string slice for str[..].

zena
operator +(other: String): String
#

Concatenates two strings and returns a new string.

zena
operator ==(other: String): boolean
#

Equality operator - compares the bytes in each view.

StringGraphemes

zena
final extension class StringGraphemes implements Iterable<String>
Implements Iterable<String>
Re-exported from zena:core/string.zena

Zero-allocation view of a String's extended grapheme clusters.

Methods
zena
filter(predicate: (item: String) => boolean): Iterable<String>
#
zena
contains(value: String): boolean
#
zena
all(predicate: (item: String) => boolean): boolean
#
zena
some(predicate: (item: String) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: String) => R): R
#
zena
find(predicate: (item: String) => boolean): inline (true, String) | inline (false, _)
#
zena
count(): i32
#

Counts the number of extended grapheme clusters in this string in $O(n)$ time.

zena
toArray(): FixedArray<String>
#

Collects all extended grapheme clusters into a FixedArray<String>.

StringCodePoints

zena
final extension class StringCodePoints implements Iterable<i32>
Implements Iterable<i32>
Re-exported from zena:core/string.zena

Zero-allocation view of a String's decoded Unicode scalar values (i32).

Methods
zena
filter(predicate: (item: i32) => boolean): Iterable<i32>
#
zena
contains(value: i32): boolean
#
zena
all(predicate: (item: i32) => boolean): boolean
#
zena
some(predicate: (item: i32) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: i32) => R): R
#
zena
find(predicate: (item: i32) => boolean): inline (true, i32) | inline (false, _)
#
zena
count(): i32
#

Counts the number of Unicode scalar values in this string in $O(n)$ time.

zena
toArray(): FixedArray<i32>
#

Collects all decoded Unicode scalar values into a FixedArray<i32>.

StringUtf8View

zena
final class StringUtf8View implements Iterable<u8>
Implements Iterable<u8>
Re-exported from zena:core/string.zena

Contiguous view of a String's UTF-8 / WTF-8 encoded bytes (u8).

When created from a WTF8 string, this view shares the string's backing ByteArray without copying. When created from a WTF16 string, the string's contents are transcoded to a fresh UTF-8 ByteArray.

Constructors
zena
new(data: ByteArray, start: i32, end: i32, origin: i32, native: boolean)
#
Properties
zena
length: i32 { get; }
#

The number of UTF-8 bytes in this view.

zena
isEmpty: boolean { get; }
#

True when this view contains zero bytes.

Methods
zena
indexAt(offset: i32): inline (true, StringIndex) | inline (false, _)
#

The string's index for the UTF-8 offset offset into this view: (true, index) when the offset is within [0, length] and on a Unicode scalar boundary, else (false, _). O(1) for a WTF-8 string, whose storage this view shares; for a WTF-16 string it counts the code units of the scalars before the offset.

zena
slice(start: i32, end: i32): StringUtf8View
#

Returns a zero-copy sub-view of [start, end), clamped to [0, length].

zena
filter(predicate: (item: u8) => boolean): Iterable<u8>
#
zena
contains(value: u8): boolean
#
zena
all(predicate: (item: u8) => boolean): boolean
#
zena
some(predicate: (item: u8) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: u8) => R): R
#
zena
find(predicate: (item: u8) => boolean): inline (true, u8) | inline (false, _)
#
zena
copyTo(target: ByteArray, targetOffset: i32 = 0, start: i32 = 0, length: i32 = -1): void
#

Copies UTF-8 bytes from this view into target starting at targetOffset.

zena
toArray(): FixedArray<u8>
#

Returns a copy of this view's UTF-8 bytes as a FixedArray<u8>.

Operators
zena
operator [](index: i32): u8
#

Returns the UTF-8 byte at index as a u8. Throws IndexOutOfBoundsError if index is out of bounds.

StringUtf16View

zena
final class StringUtf16View implements Iterable<u16>
Implements Iterable<u16>
Re-exported from zena:core/string.zena

Contiguous view of a String's UTF-16 / WTF-16 code units (u16).

When created from a WTF16 string, this view shares the string's backing ByteArray without copying. When created from a WTF8 string, the string's contents are transcoded to a fresh little-endian UTF-16 ByteArray.

Constructors
zena
new(data: ByteArray, start: i32, end: i32, origin: i32, native: boolean)
#
Properties
zena
length: i32 { get; }
#

The number of 16-bit code units in this view.

zena
isEmpty: boolean { get; }
#

True when this view contains zero code units.

Methods
zena
indexAt(offset: i32): inline (true, StringIndex) | inline (false, _)
#

The string's index for the code unit offset offset into this view: (true, index) when the offset is within [0, length] and does not split a surrogate pair, else (false, _). O(1) for a WTF-16 string, whose storage this view shares; for a WTF-8 string it counts the bytes of the scalars before the offset.

zena
slice(start: i32, end: i32): StringUtf16View
#

Returns a zero-copy sub-view of code units [start, end), clamped to [0, length].

zena
filter(predicate: (item: u16) => boolean): Iterable<u16>
#
zena
contains(value: u16): boolean
#
zena
all(predicate: (item: u16) => boolean): boolean
#
zena
some(predicate: (item: u16) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: u16) => R): R
#
zena
find(predicate: (item: u16) => boolean): inline (true, u16) | inline (false, _)
#
zena
toArray(): FixedArray<u16>
#

Returns a copy of this view's UTF-16 code units as a FixedArray<u16>.

Operators
zena
operator [](index: i32): u16
#

Returns the 16-bit code unit at index as a u16. Throws IndexOutOfBoundsError if index is out of bounds.

Error

zena
class Error
Re-exported from zena:core/error.zena
Constructors
zena
new(message: String)
#
Properties
zena
message: String
#
Methods
zena
getStackTrace(): String | null
#

LookupError

zena
class LookupError extends Error
Extends Error
Re-exported from zena:core/error.zena

Base class for errors when a lookup operation fails.

Constructors
zena
new(message: String)
#
2 inherited members
From Error
Properties
zena
message: String
#
Methods
zena
getStackTrace(): String | null
#

IndexOutOfBoundsError

zena
class IndexOutOfBoundsError extends LookupError
Extends LookupError
Re-exported from zena:core/error.zena

Thrown when an array/sequence index is out of bounds.

Constructors
zena
new(index: i32, length: i32)
#
Properties
zena
index: i32
#
zena
length: i32
#
2 inherited members
From Error
Properties
zena
message: String
#
Methods
zena
getStackTrace(): String | null
#

KeyNotFoundError

zena
class KeyNotFoundError extends LookupError
Extends LookupError
Re-exported from zena:core/error.zena

Thrown when a key is not found in a map or similar collection.

Constructors
zena
new()
#
2 inherited members
From Error
Properties
zena
message: String
#
Methods
zena
getStackTrace(): String | null
#

AsyncInSyncIteration

zena
class AsyncInSyncIteration extends Error
Extends Error
Re-exported from zena:core/error.zena

Thrown by requireSync/requireSyncIterator (zena:async) when the asynchronous iterator they wrap reports a Pending step — a value that is not available synchronously. Consume such an iterator with for await instead (docs/design/async-iteration.md).

Constructors
zena
new()
#
2 inherited members
From Error
Properties
zena
message: String
#
Methods
zena
getStackTrace(): String | null
#

ContractError

zena
class ContractError extends Error
Extends Error
Re-exported from zena:core/error.zena

Thrown when a contract clause does not hold: a requires or ensures clause of a function, or an invariant clause of a loop. The message is the clause as it was written.

Constructors
zena
new(message: String)
#
2 inherited members
From Error
Properties
zena
message: String
#
Methods
zena
getStackTrace(): String | null
#

Some

zena
class Some<T>
Re-exported from zena:core/option.zena

Represents a present value.

T is scoped, so a Some may hold an owner: a Some<Own<R>> moves like the owner, a pattern that takes it apart moves the owner out (if (let Some {value} = o)), and one nobody takes apart releases it where it is dropped.

Constructors
zena
new(value: T)
#
Properties
zena
value: T
#

None

zena
class None
Re-exported from zena:core/option.zena

Represents an absent value.

Box

zena
class Box<T>
Re-exported from zena:core/box.zena
Constructors
zena
new(value: T)
#
Properties
zena
var value: T
#

Range

zena
sealed class Range<T = i32>
Re-exported from zena:core/range.zena

Any range: a..b, a.., ..b or ...

Each form is its own class, so a range literal has the type of its form, and a parameter typed Range accepts all four.

Methods
zena
abstract bounds(length: T): inline (T, T)
#

The start and end (exclusive) of this range in a sequence of length elements: a range with no start starts at 0, and one with no end ends at length. The bounds are not clamped to the sequence.

zena
abstract contains(value: T): boolean
#

Returns true if value falls within this range.

Variants
zena
case BoundedRange
#
zena
case FromRange
#
zena
case ToRange
#
zena
case FullRange
#

BoundedRange

zena
final class BoundedRange<T = i32> extends Range<T> implements Iterable<T>
Extends Range<T>
Implements Iterable<T>
Re-exported from zena:core/range.zena

A bounded range with both start and end (exclusive). Represents [start, end) - includes start, excludes end. A range whose end is at or before its start is empty.

Constructors
zena
new(start: T, end: T)
#
Properties
zena
start: T
#
zena
end: T
#
Methods
zena
bounds(_length: T): inline (T, T)
#
zena
contains(value: T): boolean
#

Returns true if value is in [start, end).

zena
filter(predicate: (item: T) => boolean): Iterable<T>
#
zena
all(predicate: (item: T) => boolean): boolean
#
zena
some(predicate: (item: T) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#
zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#
4 inherited members
From Range
zena
case BoundedRange
#
zena
case FromRange
#
zena
case ToRange
#
zena
case FullRange
#

FromRange

zena
final class FromRange<T = i32> extends Range<T> implements Iterable<T>
Extends Range<T>
Implements Iterable<T>
Re-exported from zena:core/range.zena

A range from a start point to infinity/length. Represents [start, ∞) or [start, length).

Iterating a FromRange counts up from start and stops after the largest i32, 2147483647, instead of wrapping around to negative numbers.

Constructors
zena
new(start: T)
#
Properties
zena
start: T
#
Methods
zena
bounds(length: T): inline (T, T)
#
zena
contains(value: T): boolean
#

Returns true if value is at least start.

zena
filter(predicate: (item: T) => boolean): Iterable<T>
#
zena
all(predicate: (item: T) => boolean): boolean
#
zena
some(predicate: (item: T) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#
zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#
4 inherited members
From Range
zena
case BoundedRange
#
zena
case FromRange
#
zena
case ToRange
#
zena
case FullRange
#

ToRange

zena
final class ToRange<T = i32> extends Range<T>
Extends Range<T>
Re-exported from zena:core/range.zena

A range from zero to an end point (exclusive). Represents [0, end) for indexing or (-∞, end) for membership.

Constructors
zena
new(end: T)
#
Properties
zena
end: T
#
Methods
zena
bounds(_length: T): inline (T, T)
#
zena
contains(value: T): boolean
#
4 inherited members
From Range
zena
case BoundedRange
#
zena
case FromRange
#
zena
case ToRange
#
zena
case FullRange
#

FullRange

zena
final class FullRange<T = i32> extends Range<T>
Extends Range<T>
Re-exported from zena:core/range.zena

A full range representing all elements. Represents [0, length) for indexing or (-∞, ∞) for membership.

Methods
zena
bounds(length: T): inline (T, T)
#
zena
contains(_value: T): boolean
#
4 inherited members
From Range
zena
case BoundedRange
#
zena
case FromRange
#
zena
case ToRange
#
zena
case FullRange
#

Resource

zena
abstract resource class Resource implements OwnState
Implements OwnState
Re-exported from zena:core/ownership.zena

The classes declared with the resource modifier — those holding something the garbage collector cannot reclaim, and therefore carrying a release obligation.

resource class R satisfies this without an implements clause, the way a case class satisfies Hashable. It exists to be bounded against: disown and adopt take a T extends Resource rather than any T, because moving a value between the affine and manually-managed regimes is only meaningful for something that has a disposal obligation to move.

There is deliberately no way to hold one. Nothing is assignable to Resource, because the only reference to a resource a program can name is a handle — Own<R>, Borrow<R>, Unmanaged<R> — and those are nominally distinct types that assign to no supertype at all. That is what keeps a widening conversion from dropping the permissions the handle carries, and it is a property of the handles rather than of this interface: the same applies to every supertype, Resource or otherwise.

Resource-ness is what this names; affineness is what Own<T> declares. They are separate properties — see ownership.md §"Resource-ness and affineness are different properties" — so this bound restricts neither Own<T> itself nor the ordinary classes it will eventually wrap.

The root of every resource hierarchy. A resource class with no explicit superclass extends this one, so the lifecycle flag has an ordinary in-language home rather than a field codegen injects, and disown/adopt read it with an ordinary method call rather than an intrinsic. Being the root is also what makes ownership.md §"Resource-ness is inherited" cheap to satisfy: single inheritance means a resource cannot also extend an ordinary class, so the rule that its chain is all resources is structural rather than a check.

Declaring no method that returns this is load-bearing, not incidental. That is the whole reason an arbitrary superclass is unsafe for a resource and this one is not.

ResourceStateError

zena
class ResourceStateError extends Error
Extends Error
Re-exported from zena:core/ownership.zena

Raised when a regime change is handed a resource in the wrong state: adopting one that was never disowned, or disowning one twice.

Both are programming errors rather than expected conditions — the resource was already claimed by someone else, or already released — so they throw rather than returning a Result. A tryAdopt handing back the branch can be added if a caller ever wants it.

Constructors
zena
new(operation: String, actual: String, expected: String)
#
2 inherited members
From Error
Properties
zena
message: String
#
Methods
zena
getStackTrace(): String | null
#

TemplateStringsArray

zena
final class TemplateStringsArray
Re-exported from zena:core/template-strings-array.zena

Represents the string literals in a tagged template expression.

When you write tag\Hello ${name}!`` the tag function receives:

  • strings: TemplateStringsArray containing ["Hello ", "!"]
  • values: array containing [name]

Key properties:

  • Immutable: The strings array cannot be modified.
  • Cached: The same TemplateStringsArray instance is reused across invocations of the same tagged template expression.
  • Interleaved: Strings and values alternate, with strings on both ends. For \a${x}b${y}c`: strings = ["a", "b", "c"], values = [x, y]. This means there is always strings.length == values.length + 1`.

The raw property provides access to the raw (unescaped) string literals, where escape sequences like \\n appear as two characters (\ and n) rather than being interpreted as a newline.

Example:

text
let tag = (strings: TemplateStringsArray, values: FixedArray<anyref>): String => {
  // strings[0] = "Line 1\nLine 2" (newline interpreted)
  // strings.raw[0] = "Line 1\\nLine 2" (backslash-n literal)
  return strings[0];
};
tag\`Line 1\\nLine 2\`;
Constructors
zena
new(strings: ImmutableArray<String>, raw: ImmutableArray<String>)
#
Properties
zena
raw: ImmutableArray<String> { get; }
#

The raw string literals with escape sequences preserved.

zena
length: i32 { get; }
#

The number of string literals. This is always one more than the number of interpolated values.

Operators
zena
operator [](index: i32): String
#

Access a cooked string literal by index.

FilterIterator

zena
final class FilterIterator<T> implements Iterator<T>
Implements Iterator<T>
Re-exported from zena:core/iterable-utils.zena

An Iterator that yields elements matching a predicate.

Constructors
zena
new(iter: Iterator<T>, predicate: (item: T) => boolean)
#
Methods
zena
next(): Step<T>
#

FilteredIterable

zena
final class FilteredIterable<T> implements Iterable<T>
Implements Iterable<T>
Re-exported from zena:core/iterable-utils.zena

An Iterable that lazily filters elements using a predicate.

Constructors
zena
new(source: Iterable<T>, predicate: (item: T) => boolean)
#
Methods
zena
filter(predicate: (item: T) => boolean): Iterable<T>
#
zena
contains(value: T): boolean
#
zena
all(predicate: (item: T) => boolean): boolean
#
zena
some(predicate: (item: T) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#
zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#

ArrayIterator

zena
final class ArrayIterator<T> implements Iterator<T>
Implements Iterator<T>
Re-exported from zena:core/array-iterator.zena

Iterator over a FixedArray. Holds a reference to the array and tracks position.

Constructors
zena
new(arr: array<T>)
#
Methods
zena
next(): Step<T>
#

GrowableArrayIterator

zena
final class GrowableArrayIterator<T> implements Iterator<T>
Implements Iterator<T>
Re-exported from zena:core/growable-array-iterator.zena
Constructors
zena
new(buffer: FixedArray<T>, length: i32)
#
Methods
zena
next(): Step<T>
#

FixedArray

zena
final extension class FixedArray<T> with IterableUtils<T> implements MutableArray<T>, Iterable<T>
Implements MutableArray<T>, Iterable<T>
Mixes in IterableUtils<T>
Re-exported from zena:core/fixed-array.zena
Constructors
zena
new(length: i32, value: T)
#
Properties
zena
length: i32
#
Methods
zena
static from<A>(seq: Array<A>): FixedArray<A>
#
zena
map<U>(f: (item: T, index: i32, seq: FixedArray<T>) => U): FixedArray<U>
#
zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#
zena
reverse(): FixedArray<T>
#
zena
slice(start: i32, end: i32): FixedArray<T>
#

Returns a shallow copy of a portion of the array. The start index is inclusive, the end index is exclusive. Negative indices are not supported.

zena
contentEquals(other: Array<T>): boolean
#

Whether other has the same length and == elements in the same order, whatever array class it is. == on two arrays compares identity; this compares contents, as two byte strings are compared.

Operators
zena
operator [](index: i32): T
#
zena
operator []=(index: i32, value: T): void
#
zena
operator [](r: Range): FixedArray<T>
#

A copy of the elements whose indices are in the range: a..b, a.., ..b or ... Bounds outside the array are clamped to it.

7 inherited members
From Array
zena
new growable(capacity: i32 = 8): GrowableArray<T>
#

The same as new Array(), named for symmetry with fixed.

zena
new fixed(length: i32, value: T): FixedArray<T>
#

A fixed-length array of length copies of value.

From Iterable
zena
contains(value: T): boolean
#

Returns true if the collection contains the specified value.

zena
all(predicate: (item: T) => boolean): boolean
#

Returns true if all elements match the given predicate. Returns true if the collection is empty.

zena
some(predicate: (item: T) => boolean): boolean
#

Returns true if at least one element matches the given predicate. Returns false if the collection is empty.

zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#

Finds the first element that matches the predicate. Returns an inline tuple (true, item) if found, or (false, _) if not.

zena
filter(predicate: (item: T) => boolean): Iterable<T>
#

Returns a new iterable containing only the elements that match the predicate.

GrowableArray

zena
final class GrowableArray<T> implements MutableArray<T>, Iterable<T>
Implements MutableArray<T>, Iterable<T>
Re-exported from zena:core/growable-array.zena
Constructors
zena
new(capacity: i32 = 8, adopting: FixedArray<T> | null = null)
#

adopting, when given, becomes the backing storage, full: length starts at its length, no copy is made, and capacity is ignored. The caller must hand the buffer over — writes through either alias would be visible through the other. from copies; this adopts. (A constructor parameter rather than a static so it works from generic bodies — see the issue linked from growable below.)

Properties
zena
length: i32 { get; }
#
Methods
zena
static from<A>(seq: Array<A>): GrowableArray<A>
#
zena
push(value: T): void
#
zena
pop(): T
#
zena
clear(): void
#

Empties the array in place, keeping its buffer for reuse. The cleared slots are not overwritten, so references they held stay reachable until a later push replaces them.

zena
slice(start: i32, end: i32): GrowableArray<T>
#

A copy of the elements from start up to but not including end. Bounds outside the array are clamped to it.

zena
map<U>(f: (item: T, index: i32, seq: GrowableArray<T>) => U): GrowableArray<U>
#
zena
contains(value: T): boolean
#
zena
all(predicate: (item: T) => boolean): boolean
#
zena
some(predicate: (item: T) => boolean): boolean
#
zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#
zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#
zena
filter(predicate: (item: T) => boolean): Iterable<T>
#
zena
contentEquals(other: Array<T>): boolean
#

Whether other has the same length and == elements in the same order, whatever array class it is. == on two arrays compares identity; this compares contents.

Operators
zena
operator [](index: i32): T
#
zena
operator []=(index: i32, value: T): void
#
zena
operator [](r: Range): GrowableArray<T>
#

A copy of the elements whose indices are in the range: a..b, a.., ..b or ... Bounds outside the array are clamped to it.

2 inherited members
From Array
zena
new growable(capacity: i32 = 8): GrowableArray<T>
#

The same as new Array(), named for symmetry with fixed.

zena
new fixed(length: i32, value: T): FixedArray<T>
#

A fixed-length array of length copies of value.

ImmutableArray

zena
final extension class ImmutableArray<T> with IterableUtils<T> implements Array<T>
Implements Array<T>
Mixes in IterableUtils<T>
Re-exported from zena:core/immutable-array.zena
Properties
zena
length: i32
#
Methods
zena
slice(start: i32, end: i32): FixedArray<T>
#

A copy of the elements from start up to but not including end. Bounds outside the array are clamped to it.

zena
map<U>(f: (item: T, index: i32, seq: ImmutableArray<T>) => U): FixedArray<U>
#
zena
contentEquals(other: Array<T>): boolean
#

Whether other has the same length and == elements in the same order, whatever array class it is. == on two arrays compares identity; this compares contents.

Operators
zena
operator [](index: i32): T
#
zena
operator [](r: Range): FixedArray<T>
#

A copy of the elements whose indices are in the range: a..b, a.., ..b or ... Bounds outside the array are clamped to it.

9 inherited members
From Array
zena
new(capacity: i32 = 8): GrowableArray<T>
#

An empty growable array, with room for capacity items before it grows.

zena
new growable(capacity: i32 = 8): GrowableArray<T>
#

The same as new Array(), named for symmetry with fixed.

zena
new fixed(length: i32, value: T): FixedArray<T>
#

A fixed-length array of length copies of value.

From Iterable
zena
contains(value: T): boolean
#

Returns true if the collection contains the specified value.

zena
all(predicate: (item: T) => boolean): boolean
#

Returns true if all elements match the given predicate. Returns true if the collection is empty.

zena
some(predicate: (item: T) => boolean): boolean
#

Returns true if at least one element matches the given predicate. Returns false if the collection is empty.

zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#

Reduces the collection to a single value by accumulating state.

zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#

Finds the first element that matches the predicate. Returns an inline tuple (true, item) if found, or (false, _) if not.

zena
filter(predicate: (item: T) => boolean): Iterable<T>
#

Returns a new iterable containing only the elements that match the predicate.

ByteBuffer

zena
final class ByteBuffer
Re-exported from zena:core/byte-buffer.zena

A growable buffer for efficiently constructing binary data.

Constructors
zena
new(capacity: i32 = 256)
#

Creates a new ByteBuffer with the specified initial chunk capacity.

capacity

Initial capacity for the first chunk (default: 256).

Properties
zena
length: i32 { get; }
#

Total number of bytes written to the buffer.

zena
capacity: i32 { get; }
#

Total allocated capacity across all chunks.

Methods
zena
writeByte(b: i32): ByteBuffer
#

Write a single byte.

zena
writeBytes(src: ByteArray): ByteBuffer
#

Write all bytes from a ByteArray.

zena
writeBytesSlice(src: ByteArray, offset: i32, len: i32): ByteBuffer
#

Write a slice of bytes from a ByteArray.

src

Source byte array

offset

Starting offset in source

len

Number of bytes to write

zena
writeBufferRange(other: ByteBuffer, start: i32, end: i32): ByteBuffer
#

Write the byte range [start, end) of another ByteBuffer's contents.

zena
writeBuffer(other: ByteBuffer): ByteBuffer
#

Write another ByteBuffer's contents.

zena
writeU16(value: i32): ByteBuffer
#

Write a 16-bit unsigned integer (little-endian).

zena
writeU32(value: i32): ByteBuffer
#

Write a 32-bit unsigned integer (little-endian).

zena
writeU64(value: i64): ByteBuffer
#

Write a 64-bit integer (little-endian).

zena
writeF32(value: f32): ByteBuffer
#

Write a 32-bit float (little-endian).

zena
writeF64(value: f64): ByteBuffer
#

Write a 64-bit float (little-endian).

zena
writeULEB128(value: i32): ByteBuffer
#

Write an unsigned LEB128 encoded integer.

zena
writeSLEB128(value: i32): ByteBuffer
#

Write a signed LEB128 encoded integer.

zena
writeULEB128_64(value: i64): ByteBuffer
#

Write a 64-bit unsigned LEB128.

zena
writeSLEB128_64(value: i64): ByteBuffer
#

Write a 64-bit signed LEB128.

zena
getByte(index: i32): i32
#

Read a byte at an absolute position.

zena
setByte(index: i32, value: i32): void
#

Write a byte at an absolute position (for patching).

zena
patchU32(index: i32, value: i32): void
#

Patch a U32 at an absolute position (little-endian).

zena
toByteArray(): ByteArray
#

Convert to a single contiguous ByteArray.

zena
clear(): void
#

Clear the buffer, reusing the first chunk.

DataView

zena
final class DataView
Re-exported from zena:core/data-view.zena

Typed reads from a range of a ByteArray. Offsets are relative to the start of the range, and a read that would leave it throws IndexOutOfBoundsError. The array is shared, not copied.

Constructors
zena
new(bytes: ByteArray, start: i32 = 0, length: i32 = -1)
#

A view of bytes[start..start + length]; with no length, to the end of the array.

Properties
zena
buffer: ByteArray { get; }
#

The array the view reads from.

zena
byteOffset: i32 { get; }
#

Where the view starts in buffer.

zena
byteLength: i32 { get; }
#

The number of bytes in the view.

Methods
zena
getU8(offset: i32): i32
#
zena
getU16(offset: i32): i32
#
zena
getU32(offset: i32): i32
#
zena
getU64(offset: i32): i64
#
zena
getF32(offset: i32): f32
#
zena
getF64(offset: i32): f64
#
zena
getULEB128(offset: i32): inline (i32, i32)
#

The unsigned LEB128 value at offset, and the offset after it.

zena
getULEB128_64(offset: i32): inline (i64, i32)
#

The 64-bit unsigned LEB128 value at offset, and the offset after it.

zena
getSLEB128(offset: i32): inline (i32, i32)
#

The signed LEB128 value at offset, and the offset after it.

zena
getSLEB128_64(offset: i32): inline (i64, i32)
#

The 64-bit signed LEB128 value at offset, and the offset after it.

StringBuilder

zena
final class StringBuilder
Re-exported from zena:core/string-builder.zena

An append-only sequence of characters for efficient string construction.

Constructors
zena
new(capacity: i32 = 16)
#

Creates a new StringBuilder with the specified initial capacity.

capacity

Initial capacity for the first chunk.

Properties
zena
length: i32 { get; }
#

Current length of the built string in bytes.

zena
capacity: i32 { get; }
#

Current capacity (total allocated size).

Methods
zena
append(s: String): StringBuilder
#

Appends a string to the builder.

zena
appendSlice(s: String, start: i32, end: i32): StringBuilder
#

Appends a byte slice [start, end) of s directly without allocating an intermediate String view.

zena
appendByte(b: i32): StringBuilder
#

Appends a single byte.

zena
appendByte2(b0: i32, b1: i32): StringBuilder
#

Appends two bytes (such as a two-byte escape sequence).

zena
appendI32(n: i32): StringBuilder
#

Appends a signed 32-bit integer as decimal. Uses shared conversion from zena:string-convert.

zena
appendU32(n: u32): StringBuilder
#

Appends an unsigned 32-bit integer as decimal. Uses shared conversion from zena:string-convert.

zena
appendI64(n: i64): StringBuilder
#

Appends a signed 64-bit integer as decimal. Uses shared conversion from zena:string-convert.

zena
appendU64(n: u64): StringBuilder
#

Appends an unsigned 64-bit integer as decimal. Uses shared conversion from zena:string-convert.

zena
appendF32(n: f32): StringBuilder
#

Appends a 32-bit float as decimal. Uses shared conversion from zena:string-convert.

zena
appendF64(n: f64): StringBuilder
#

Appends a 64-bit float as decimal. Uses shared conversion from zena:string-convert.

zena
toString(): String
#

Returns the string content.

zena
clear(): void
#

Clears the builder.

zena
static fromString(s: String): StringBuilder
#

Creates a new StringBuilder initialized with the content of the given String. If the string uses its entire backing ByteArray, the builder will adopt the array directly (zero-copy).

IterableJoin

zena
extension class IterableJoin<T>
Re-exported from zena:core/string-join.zena
Methods
zena
join(stringify: (item: T) => String, separator: String = ', '): String
#

StringReader

zena
final class StringReader
Re-exported from zena:core/string-reader.zena

StringReader - A cursor-based string parser that tracks byte positions.

Use StringReader for parsing to ensure slices are always at valid UTF-8 code point boundaries. Positions from mark() are safe to use with sliceBytes().

Example usage:

text
let r = new StringReader(input);
r.skipWhitespace();
let start = r.mark();
while (!r.isAtEnd && r.peekByte() != 34) {  // 34 = '"'
  r.advance();  // Move by code point (safe for Unicode)
}
let token = r.sliceFrom(start);  // Safe: positions from mark()

A reader may be given a StringTable, in which case internFrom and internRange return canonical instances for the text they cover — see StringTable, exported from this module. Several readers can share one table, so a parser run over many files reuses the identifiers it has already seen. Passing no table is not a special case to handle: the intern methods then behave exactly like sliceFrom/sliceRange, because strings have value semantics either way.

Constructors
zena
new(source: String, table: StringTable | null = null)
#
Properties
zena
table: StringTable | null { get; }
#

The string table this reader interns into, if any.

zena
position: i32 { get; }
#

Current byte position in the string.

zena
isAtEnd: boolean { get; }
#

True if at end of string.

zena
source: String { get; }
#

The source string being read.

zena
remaining: i32 { get; }
#

Remaining length in bytes.

Methods
zena
peekByte(): i32
#

Peek at the current byte without consuming it. Returns -1 if at end of string. Use for ASCII characters (< 128) like delimiters: { } [ ] , : " etc.

zena
peekByteAt(offset: i32): i32
#

Peek at a byte at offset from current position. Returns -1 if out of bounds.

zena
advanceByte(): i32
#

Consume and return the current byte. Returns -1 if at end. WARNING: Only use for ASCII (< 128). For Unicode text, use advance().

zena
peek(): i32
#

Peek at the current Unicode code point without consuming it. Returns -1 if at end of string. Decodes UTF-8 sequences properly.

TODO: Use shift operators (<< 6, << 12, << 18) when available in Zena. Currently using multiplication as a workaround.

zena
advance(): i32
#

Consume and return the current Unicode code point. Returns -1 if at end. Advances by the correct number of bytes (1-4 for UTF-8).

TODO: Use shift operators (<< 6, << 12, << 18) when available in Zena. Currently using multiplication as a workaround.

zena
skip(count: i32): void
#

Skip N code points (not bytes). Properly handles multi-byte UTF-8 sequences.

zena
mark(): i32
#

Mark the current position for later slicing. Returns an opaque position value safe to use with sliceFrom/sliceRange.

zena
reset(pos: i32): void
#

Reset to a previously marked position.

zena
sliceFrom(start: i32): String
#

Extract a slice from a marked position to current position. This is SAFE because both positions are at code point boundaries.

zena
sliceRange(start: i32, end: i32): String
#

Extract a slice between two marked positions. This is SAFE because both positions are at code point boundaries.

zena
internFrom(start: i32): String
#

Like sliceFrom, but returns the canonical instance from this reader's string table — or the plain slice if the reader has no table.

Prefer this over sliceFrom for text a parser will compare or use as a map key later: identifiers, member names, object keys. It is worth nothing for text used once, such as a numeric literal, and worse than nothing for text that is nearly always distinct, such as string literal contents, which would fill the table with single-use entries.

zena
internRange(start: i32, end: i32): String
#

Like sliceRange, but interned. See internFrom.

zena
matchByte(expected: i32): boolean
#

Check if current byte matches, and advance if it does. Returns true if matched.

zena
skipWhitespace(): void
#

Skip ASCII whitespace (space, tab, newline, carriage return).

zena
skipBytes(n: i32): void
#

Skip N bytes (not code points). Use with caution - only when you know the bytes are at valid boundaries.

zena
skipBytesWhile(predicate: (byte: i32) => boolean): void
#

Skip bytes while predicate returns true. Predicate receives byte value (not code point). Useful for ASCII character classes: digits, letters, etc.

zena
readUntil(needle: String): String | null
#

Reads a substring up to the next occurrence of needle. If needle is found, returns the substring before it and advances the cursor past needle. If needle is not found, returns null and does not advance the cursor.

zena
readToEnd(): String
#

Reads the remaining substring from current position to the end of the string, advancing the cursor to the end.

StringTable

zena
final class StringTable
Re-exported from zena:core/string-table.zena

A set of unique strings: interning one returns the single canonical instance for its bytes, so equal strings become the same object.

Strings have value semantics whether or not they are interned, so interning never changes what a program computes. What it changes is cost, and the costs it removes are mostly downstream of the parser rather than in it:

  • String caches its FNV hash in a field on first use. An interned identifier is therefore hashed once for the life of the table, not once per HashMap<String, V> probe — and a compiler probes scope and symbol tables with the same identifier over and over.
  • operator == returns early on reference equality, so comparing two interned strings is a pointer compare instead of a byte loop.
  • One live String per distinct identifier instead of one per token.

Interning is deliberately not perfect: intern is the only way in, and nothing stops an equal string from being produced by other means. Code may treat === as a fast path for equality, never as the definition of it.

Sharing a table ​

A table is an ordinary object, so several StringReaders — several whole parses — can share one and get cross-file reuse: the second file's let costs a lookup and no allocation. That is also why intern copies (see below): a table outliving the text it was filled from must not pin it.

Constructors
zena
new(capacity: i32 = 512, maxLength: i32 = 128)
#
Properties
zena
maxLength: i32 { get; }
#

The longest string, in bytes, this table will intern.

Interning is a bet that a string will be seen again, and it is paid for up front with a copy that then lives as long as the table. The bet is a good one for identifiers and keys, which are short and repeat constantly. It is a bad one for the long strings in the same input — a JSON document's text values, a Zena string literal, a WIT doc comment — which are mostly distinct, so each one interned is a permanent copy of bytes that will never be looked up again, and a byte compare on every collision with it.

So the table simply declines. Over-long strings are returned equal but uninterned, which callers must already tolerate: interning is best-effort and === is only ever a fast path for equality, never the definition of it. prime declines too, so no key in the table is longer than this and intern can never miss one that is.

zena
size: i32 { get; }
#

The number of distinct strings held.

Methods
zena
intern(s: String): String
#

Returns the canonical instance equal to s, adding a copy of it if this is the first sighting.

The copy is what makes a long-lived table safe. Zena strings are views into a shared backing array, so interning a three-byte identifier sliced out of a source file would otherwise keep that whole file alive for as long as the table — and a table shared across a compilation would accumulate every file it ever saw. The copy costs one allocation per distinct string, never per occurrence, and leaves the canonical instance on tight storage that its own byte loops then walk.

Use prime for strings that already own their storage permanently.

zena
internRange(source: String, start: i32, end: i32): String
#

Returns the canonical instance for source's bytes in [start, end), without slicing that range out first.

This is the form a scanner wants, and the reason it exists is that intern turns out to be dominated by neither hashing nor probing. Its cost is the per-probe candidate == s: a virtual call to String.operator == that re-derives the length and consults the hash cache before reaching the byte compare, plus the throwaway view allocated to have something to pass it. Matching against the source range in place removes all of that from the hit path, which is every occurrence after the first.

zena
prime(s: String): String
#

Interns s without copying it, making s itself canonical if it is new.

For strings that already own their storage for the life of the program — literals, above all — where intern's defensive copy would allocate a second permanent copy of bytes that were never going to be freed.

Priming a table with a language's keywords before parsing is the motivating case, and it buys more than the avoided copies: a keyword lexed out of source then interns to the very object the keyword table is keyed by, so the keyword lookup that follows hits =='s reference-equal fast path against an already-hashed key.

Declines over-long strings exactly as intern does; see maxLength.

zena
primeAll(words: Array<String>): void
#

Primes every string in words. See prime.

zena
has(s: String): boolean
#

True if a string equal to s has been interned.

Interfaces

Equatable

zena
interface Equatable
Re-exported from zena:core/hashable.zena

A type that declares its own equality: an operator == taking another value of the same type.

Every class has an equality, so == does not need this bound to compile. What it says is that the class wrote one down, rather than relying on reference equality. Every hash key is one, since Hashable extends it. Primitives, enums, and case classes that derive their equality satisfy it without an implements clause.

The parameter is typed this, which makes == a binary method: Equatable works as a bound on a type parameter (<T extends Equatable>), where both operands are the same T. Two values that are each some Equatable may be different classes, and cannot be compared through it.

Operators
zena
operator ==(other: this): boolean
#

Hashable

zena
interface Hashable extends Equatable
Extends Equatable
Re-exported from zena:core/hashable.zena

A type that can be used as a key in hash-based collections like HashMap and HashSet.

A hash key declares its equality, so Hashable extends Equatable, and the two must agree: if two values are equal (per operator ==), they must return the same hashCode. The reverse is not required — unequal values may share a hash code, though fewer collisions means better performance.

A class whose equality is identity says so, and returns an identity hash: a value that is unique per instance and stable for its lifetime, such as a counter assigned in the constructor.

zena
class Session implements Hashable {
  #id: i32 = nextSessionId();
  operator ==(other: Session): boolean { return this === other; }
  hashCode(): i32 { return this.#id; }
}

Case classes automatically satisfy Hashable: the compiler derives a structural hashCode() and operator == from their parameters, unless the class inherits either one from its base, whose pair is then the hierarchy's equality. Primitives (i32, boolean, enums, and distinct types over them) also satisfy the Hashable constraint; they hash to their own value. Strings hash with FNV-1a, cached after the first computation.

Methods
zena
hashCode(): i32
#
1 inherited member
From Equatable
zena
operator ==(other: this): boolean
#

Stringable

zena
interface Stringable
Re-exported from zena:core/stringable.zena

A type that provides a custom string representation for template literals and toString().

Stringable is not required to pass a value to toString() or interpolate it into a template literal — non-Stringable classes format as <ClassName>, records as <record>, and tuples as <tuple>. Implementing Stringable opts a class into custom formatting via [Stringable.toString]().

zena
class Point implements Stringable {
  x: i32;
  y: i32;
  new(this.x, this.y);
  [Stringable.toString](): String {
    return `(${this.x}, ${this.y})`;
  }
}

Disposable

zena
interface Disposable
Re-exported from zena:core/ownership.zena

A value holding something the garbage collector cannot reclaim.

dispose is symbol-keyed rather than name-keyed. dispose is a common enough method name that a class may already have one meaning something unrelated, and this is a protocol the language itself invokes implicitly — a silent collision would be a resource released at the wrong time. Call it as value.[Disposable.dispose]().

zena
import { Disposable } from './ownership.zena';

class Descriptor implements Disposable {
  #handle: i32;
  new(this.#handle);
  [Disposable.dispose](): void { descriptorDrop(this.#handle); }
}

Disposal must be idempotent: dispose() may be called on an already disposed value and must not release the underlying resource twice. Until affine checking lands in O2, nothing statically prevents a double call, and a resource wrapper's state flag is what makes the second one a no-op.

Iterator

zena
interface Iterator<T> extends AsyncIterator<T>
Extends AsyncIterator<T>
Re-exported from zena:core/iterator.zena
Methods
zena
next(): Step<T>
#

Advances the iterator and returns the next element as a Step<T>: Ready with a value, or Done when exhausted. Never Pending: that is what makes this iterator synchronous, and what lets a plain for consume it (async-iteration.md).

Iterable

zena
interface Iterable<T>
Re-exported from zena:core/iterator.zena

A collection that can produce an Iterator.

Methods
zena
contains(value: T): boolean
#

Returns true if the collection contains the specified value.

zena
all(predicate: (item: T) => boolean): boolean
#

Returns true if all elements match the given predicate. Returns true if the collection is empty.

zena
some(predicate: (item: T) => boolean): boolean
#

Returns true if at least one element matches the given predicate. Returns false if the collection is empty.

zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#

Reduces the collection to a single value by accumulating state.

zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#

Finds the first element that matches the predicate. Returns an inline tuple (true, item) if found, or (false, _) if not.

zena
filter(predicate: (item: T) => boolean): Iterable<T>
#

Returns a new iterable containing only the elements that match the predicate.

Array

zena
interface Array<T> extends Iterable<T>
Extends Iterable<T>
Re-exported from zena:core/array.zena

A sequence with a length and indexed reads.

This is the read-only view; MutableArray adds indexed writes. The constructors build the standard implementations — new Array() is a GrowableArray and new Array.fixed(n, value) a FixedArray — and are typed as those classes, so the result has the class's full API. (The modules declaring those classes import this one back; classes and interfaces may cross an import cycle.)

Constructors
zena
new(capacity: i32 = 8): GrowableArray<T>
#

An empty growable array, with room for capacity items before it grows.

zena
new growable(capacity: i32 = 8): GrowableArray<T>
#

The same as new Array(), named for symmetry with fixed.

zena
new fixed(length: i32, value: T): FixedArray<T>
#

A fixed-length array of length copies of value.

Properties
zena
length: i32 { get; }
#
Methods
zena
map<U>(f: (item: T, index: i32, seq: this) => U): Array<U>
#
zena
contentEquals(other: Array<T>): boolean
#

Whether other has the same length and == elements in the same order, whatever array class it is. == on two arrays compares identity; this compares contents, as two byte strings are compared.

Operators
zena
operator [](index: i32): T
#
zena
operator [](r: Range): Array<T>
#

A copy of the elements whose indices are in the range: a..b (from a up to but not including b), a.. (from a to the end), ..b (from the start up to b) or .. (all of them). Bounds outside the array are clamped to it, and a range with no elements gives an empty array.

6 inherited members
From Iterable
zena
contains(value: T): boolean
#

Returns true if the collection contains the specified value.

zena
all(predicate: (item: T) => boolean): boolean
#

Returns true if all elements match the given predicate. Returns true if the collection is empty.

zena
some(predicate: (item: T) => boolean): boolean
#

Returns true if at least one element matches the given predicate. Returns false if the collection is empty.

zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#

Reduces the collection to a single value by accumulating state.

zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#

Finds the first element that matches the predicate. Returns an inline tuple (true, item) if found, or (false, _) if not.

zena
filter(predicate: (item: T) => boolean): Iterable<T>
#

Returns a new iterable containing only the elements that match the predicate.

MutableArray

zena
interface MutableArray<T> extends Array<T>
Extends Array<T>
Re-exported from zena:core/array.zena
Operators
zena
operator []=(index: i32, value: T): void
#
13 inherited members
From Array
Constructors
zena
new(capacity: i32 = 8): GrowableArray<T>
#

An empty growable array, with room for capacity items before it grows.

zena
new growable(capacity: i32 = 8): GrowableArray<T>
#

The same as new Array(), named for symmetry with fixed.

zena
new fixed(length: i32, value: T): FixedArray<T>
#

A fixed-length array of length copies of value.

Properties
zena
length: i32 { get; }
#
Methods
zena
map<U>(f: (item: T, index: i32, seq: this) => U): Array<U>
#
zena
contentEquals(other: Array<T>): boolean
#

Whether other has the same length and == elements in the same order, whatever array class it is. == on two arrays compares identity; this compares contents, as two byte strings are compared.

Operators
zena
operator [](index: i32): T
#
From Iterable
zena
contains(value: T): boolean
#

Returns true if the collection contains the specified value.

zena
all(predicate: (item: T) => boolean): boolean
#

Returns true if all elements match the given predicate. Returns true if the collection is empty.

zena
some(predicate: (item: T) => boolean): boolean
#

Returns true if at least one element matches the given predicate. Returns false if the collection is empty.

zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#

Reduces the collection to a single value by accumulating state.

zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#

Finds the first element that matches the predicate. Returns an inline tuple (true, item) if found, or (false, _) if not.

zena
filter(predicate: (item: T) => boolean): Iterable<T>
#

Returns a new iterable containing only the elements that match the predicate.

Mixins

IterableUtils

zena
mixin IterableUtils<T> on Iterable<T>
Extends Iterable<T>
Re-exported from zena:core/iterable-utils.zena

Common iteration utilities for any collection that implements Iterable.

Methods
zena
filter(predicate: (item: T) => boolean): Iterable<T>
#

Returns a new iterable containing only the elements that match the predicate.

zena
contains(value: T): boolean
#

Checks if the collection contains the specified value using equality.

zena
all(predicate: (item: T) => boolean): boolean
#

Returns true if all elements match the given predicate. Returns true if the collection is empty.

zena
some(predicate: (item: T) => boolean): boolean
#

Returns true if at least one element matches the given predicate. Returns false if the collection is empty.

zena
fold<R>(initial: R, combine: (acc: R, item: T) => R): R
#

Reduces the collection to a single value by accumulating state.

zena
find(predicate: (item: T) => boolean): inline (true, T) | inline (false, _)
#

Finds the first element that matches the predicate. Returns an inline tuple (true, item) if found, or (false, _) if not.

Enums

Encoding

zena
enum Encoding
Re-exported from zena:core/encoding.zena

String encodings supported by Zena strings and byte conversion.

Members
zena
WTF8
#
zena
WTF16
#

Type aliases

StringIndex

zena
type StringIndex = i32
Re-exported from zena:core/string.zena

A position within a String that has been validated to lie on a Unicode boundary: an offset in the string's own encoding, which an i32 read of it exposes.

StringIndex values are produced by String methods (startIndex, endIndex, indexAfter, indexBefore, scalarIndexAfter, scalarIndexBefore, indexOffsetBy, indexOf) and by the views' indexAt (utf8.indexAt, utf16.indexAt), and cannot be forged by casting an arbitrary i32 outside zena:core. Reading the underlying offset with idx as i32 is always legal.

StackRef

zena
type StackRef = anyref
Re-exported from zena:core/error/stack-ref.zena

Opaque host-side stack-trace handle.

Option

zena
type Option<T> = Some<T> | None
Re-exported from zena:core/option.zena

A value that is either present (Some) or absent (None).

Result

zena
type Result<T, E> = (true, T) | (false, E)
Re-exported from zena:core/result.zena

Result<T, E> — a value that is either an ok payload or an error payload.

A value union of two tuples, told apart by the literal in front: (true, value) or (false, error). Returned as inline Result<T, E>, it is a WebAssembly multi-value return and costs no allocation; stored in a variable, field or collection, it is a boxed tuple. The two forms convert implicitly. See docs/design/result-option.md.

zena
import { Result } from 'zena:core';

let checkedSub = (a: i32, b: i32): inline Result<i32, String> => {
  if (b > a) {
    return (false, "underflow");
  }
  return (true, a - b);
};

if (let (true, v) = checkedSub(10, 4)) {
  // v is 6
}
let kept: Array<Result<i32, String>> = [checkedSub(1, 2)];

WithDefault

zena
type WithDefault<T>
Re-exported from zena:core/box.zena

A slot for a T that may be empty: T itself at a primitive, and T | null at a reference. A generic class keeps a value it may not have yet in one, without a Box. defaultValue<T>() is its empty value, a T fills it, and slot as T reads it back; at a non-null reference T, reading an empty slot fails the cast.

zena
class Cell<T> {
  var #value: WithDefault<T> = defaultValue<T>();
  set(value: T): void { this.#value = value; }
  get(): T { return this.#value as T; }
}

Own

zena
type Own<T> = T
Re-exported from zena:core/ownership.zena

The owning reference to a resource. Affine: it may be moved, returned or stored, but not duplicated, and it is released when it leaves scope unmoved.

Erased at codegen: a distinct type is nominally distinct for checking but shares its target's representation, so a handle costs no allocation and no indirection. The three differ in permissions, not data.

Own<T> is what declares affineness; resource class declares resource-ness. The two are separate on purpose — see ownership.md §"Resource-ness and affineness are different properties" — which is why Own<T> will also apply to ordinary classes (from a provably exclusive source) once layer 4 needs it.

Borrow

zena
type Borrow<T> = T
Re-exported from zena:core/ownership.zena

A borrowed reference. Freely copied, but second-class: it may not be returned (except derived from a single borrow parameter), stored in a field or array, or captured by a closure. Never releases what it points at.

At unrestricted instantiations Borrow<T> is the identity — Borrow<i32> is i32 — which is what keeps container APIs from forking.

Unmanaged

zena
type Unmanaged<T> = T
Re-exported from zena:core/ownership.zena

A disowned resource: aliasable like an ordinary reference, and never implicitly dropped. You must dispose() it yourself or adopt() it back into the affine world.

This is the population using was designed for. Entering it costs leak-freedom and compile-time use-after-dispose detection; it costs neither type soundness nor memory safety, because the state flag turns a bad adopt into a clean error rather than a double free.

Scoped

zena
type Scoped<T> = T
Re-exported from zena:core/ownership.zena

A value that may not be duplicated and may not outlive the extent it derives from — the corner of the universe table where both restrictions bind (ownership.md §"Scoped: the fourth corner"). The population is borrow-derived futures and iterators: an async function that holds a Borrow across await returns Scoped<Future<T>>, so the frame holding the borrow cannot escape the borrow's extent.

A scoped value must be consumed exactly once on every path: a scoped future by await or a move, a scoped iterator by for/in. It may not be stored in a field, container, record, or tuple, and may not be captured by a closure. A first-class Future<T> coerces to Scoped<Future<T>>; there is no way back.

ScopedFrom

zena
type ScopedFrom<T, R>
Re-exported from zena:core/ownership.zena

Scoped<R> when T carries a second-class type — a scoped value, a restricted borrow, or a scoped type parameter — and R otherwise (ownership.md §"Combinator audit", docs/design/type-operators.md). For a generic whose result must be scoped exactly when an input is: Future.allSettled<scoped T> returns ScopedFrom<T, Future<Array<Result<Awaited<T>, Error>>>>, so a call over scoped futures yields a scoped result the caller must consume, and a call over ordinary futures yields the ordinary future it always did. Inside the generic body the operator reads as Scoped<R>; substitution collapses it once T is known.

TemplateTag

zena
type TemplateTag<T> = (strings: TemplateStringsArray, values: FixedArray<anyref>) => T
Re-exported from zena:core/template-strings-array.zena

Type alias for template tag functions.

Example usage:

text
const html: TemplateTag<String> = (strings, values) => {
  // strings[0], strings[1], etc. are the literal parts
  // values[0], values[1], etc. are the interpolated expressions
  // strings.raw gives access to raw (unescaped) strings
  return '...';
};

const result = html`<div>${name}</div>`;

Step

zena
type Step<T> = inline (0, _, _) | inline (1, inline? T, _)
Re-exported from zena:core/iterator.zena

Step — one result of a synchronous iterator's next() (docs/design/async-iteration.md). It is an inline multi-value, so it travels in stack slots and allocates nothing.

  • Done (discriminant 0): no more items.
  • Ready (discriminant 1): a value, available now.

A tuple value is unboxed too (inline? T): Step<(K, V)> returns the key and the value as results of their own, so zip and similar iterators allocate nothing per step.

The third position is always empty. It is there so that every Step is also an AsyncStep (zena:async), whose third arm carries a future: a synchronous iterator can stand wherever an asynchronous one is expected, and a for await drives both.

Functions

asciiLowerByte

zena
function asciiLowerByte(b: i32): i32
Re-exported from zena:core/string.zena

Returns the ASCII lowercase of b, leaving every other byte or code point unchanged.

asciiUpperByte

zena
function asciiUpperByte(b: i32): i32
Re-exported from zena:core/string.zena

Returns the ASCII uppercase of b.

$contractFailed

zena
function $contractFailed(message: String): never
Re-exported from zena:core/error.zena

What compiled code calls when a contract clause does not hold. The compiler emits the call, with a message naming the clause, so what a violated contract does is decided here.

unreachable

zena
declare function unreachable(): never
Re-exported from zena:core/error.zena

installStackTraceHooks

zena
function installStackTraceHooks(capture: () => StackRef | null, format: (stack: StackRef | null) => String | null): void
Re-exported from zena:core/error/stack-hooked.zena

Install the host's capture and format.

captureStackTrace

zena
function captureStackTrace(): StackRef | null
Re-exported from zena:core/error/stack-hooked.zena

formatStackTrace

zena
function formatStackTrace(stack: StackRef | null): String | null
Re-exported from zena:core/error/stack-hooked.zena

some

zena
function some<T>(value: T): Option<T>
Re-exported from zena:core/option.zena

Creates a Some containing the given value.

unit

zena
function unit(): void
Re-exported from zena:core/result.zena

The void value, for a tuple's void member: (true, unit()) is a Result<void, E> that succeeded.

defaultValue

zena
declare function defaultValue<T>(): WithDefault<T>
Re-exported from zena:core/box.zena

The value of an empty WithDefault<T>: zero at a primitive, null at a reference.

hash

zena
declare function hash<T>(value: T): i32
Re-exported from zena:core/hashable.zena

The hash code of a value, dispatched on its static type: primitives hash by value, Strings by content, and classes through hashCode().

This is what hash-based collections call. Prefer it over hashCode() — it works for primitives, which have no methods.

equals

zena
declare function equals<T>(a: T, b: T): boolean
Re-exported from zena:core/hashable.zena

Whether two values of the same type are equal, dispatched on their static type: primitives compare by value, Strings by content, and classes through operator == when the class defines one and by reference otherwise.

toString

zena
declare function toString<T>(value: T): String
Re-exported from zena:core/stringable.zena

Converts any value to a String, dispatched on its static type: primitives format by value, null as 'null', Stringable types via [Stringable.toString](), and other classes, records, and tuples with a type-tag fallback (<ClassName>, <record>, <tuple>).

isFirstClass

zena
declare function isFirstClass<T>(): boolean
Re-exported from zena:core/ownership.zena

Whether T is first-class in this specialization: false where it may be an owner, a borrow or a value holding one, true elsewhere. A constant, so a scoped T body branches on what only one kind of instantiation needs and the other branch folds away. It answers for the body a specialization shares, so it is false at Unmanaged<R>, which shares Own<R>'s, and true at Scoped<F>, which shares F's (ownership.md §"Scoped type arguments").

disown

zena
function disown<T extends Resource>(value: Own<T>): Unmanaged<T>
Re-exported from zena:core/ownership.zena

Leaves the affine regime: takes the owning handle and hands back an aliasable one that is never implicitly dropped.

zena
let raw: Unmanaged<Descriptor> = disown(f);   // f is consumed
// … alias it, store it in a field, put it in an ordinary Array …
let f2: Own<Descriptor> = adopt(raw);         // back under implicit drop

The handles are erased, so this re-types the object rather than allocating anything: Own<T> and Unmanaged<T> lower to the same wasm type, and the body compiles to an identity function returning its argument. The call itself is not yet inlined away.

Requires the resource to be owned and leaves it disowned, so disowning the same resource twice throws rather than handing out two unmanaged aliases with one disposal obligation between them.

disown consumes its argument. Otherwise an Own that will implicitly drop would coexist with an Unmanaged alias to the same resource, and the drop would run under an alias that outlives it. Move checking enforces the consumption for local bindings — a caller that keeps using the original Own after disowning it gets a compile error, through the ordinary rule that an argument to an Own parameter is a move. The flag still guards the routes the checker does not track, such as an Own read out of a field.

The cast is legal here and nowhere else: Own<T> and Unmanaged<T> are opaque types declared in this file, and both erase to T, so re-labelling one as the other mints nothing. See ownership.md §"Handles are not forgeable" — outside this file the same cast is a diagnostic, which is what makes disown and adopt the only doors between the two regimes.

adopt

zena
function adopt<T extends Resource>(value: Unmanaged<T>): Own<T>
Re-exported from zena:core/ownership.zena

Re-enters the affine regime: takes a disowned handle back under implicit drop, so it is released at scope exit again.

The inverse of disown, and the only way back — Unmanaged<R> has no user-callable dispose, since it is not an owner and cannot call the consuming form. A disowned resource is either scoped with using or adopted back.

Throws when the resource is not in the disowned state: owned means something else adopted it first, so two racing adopters do not both succeed — the loser gets a clear error rather than a second owner and, once implicit drop lands, a double free.

dropped throws too: every consuming dispose sets it, so adopting an already-released resource is reported as exactly that.

adopt cannot retract aliases. Aliasability is the point of the disowned state, so the flag is the only defence here, by design.

map

zena
function map<T, U>(it: Scoped<Iterator<T>>, f: (v: T) => U): Scoped<Iterator<U>>
Re-exported from zena:core/ownership.zena

The elements of a scoped iterator mapped through f. Driving the result drives it, inside the same extent — the input is consumed (a scoped iterator is driven exactly once), and the result derives from the same borrow, so it is scoped too.

filter

zena
function filter<T>(it: Scoped<Iterator<T>>, keep: (v: T) => boolean): Scoped<Iterator<T>>
Re-exported from zena:core/ownership.zena

The elements of a scoped iterator for which keep answers true.

take

zena
function take<T>(it: Scoped<Iterator<T>>, count: i32): Scoped<Iterator<T>>
Re-exported from zena:core/ownership.zena

At most the first count elements of a scoped iterator. The loop is always entered — every path out of this body must consume it — so with count <= 0 one element is still pulled from the source before the frame is disposed.

dedent

zena
function dedent(strings: TemplateStringsArray, values: FixedArray<String>): String
Re-exported from zena:core/template-strings-array.zena

A template tag that strips the source indentation from a multi-line template literal, so a block of text can be written at the indentation of the code around it and still come out flush left:

text
let usage = dedent`
  zena build <entry>
    -o <path>   where to write the module
`;
// "zena build <entry>\n  -o <path>   where to write the module"

The rules:

  • The opening line is dropped, along with its line break, when it is blank — which it is in the form above, where the content starts on the line after the backtick. The closing line is dropped the same way. Neither is dropped when it has content on it: a line with content is a line, and it takes part in the rule below like any other.
  • The indentation removed from every remaining line is the longest common prefix of the indentation of the lines that have content on them. It is compared byte for byte, so a file that mixes tabs and spaces dedents by what its lines actually share rather than by a count that assumes a tab width.
  • Blank lines are ignored when computing that prefix and come out empty, so a line of leftover trailing spaces is not what decides the result.
  • Interpolated values are inserted verbatim. A value containing newlines is not re-indented, and its newlines do not start lines that participate in the computation: only indentation written in the literal counts. A line that starts with a value is a content line, and the whitespace before the value is its indentation.

Interpolations must be Strings — a tag receives its values without the conversion ${} performs in an untagged template literal, so write dedent`count: ${`${n}`}` (or i32ToString(n)) for a number.

The text dedented is the cooked strings, so an escape is processed before the indentation is measured: a \n written as an escape breaks a line here exactly as a real newline does, and the line it opens takes part in the common-indent computation like any other. Use dedentRaw to dedent text whose escapes are meant to stay as written.

dedentRaw

zena
function dedentRaw(strings: TemplateStringsArray, values: FixedArray<String>): String
Re-exported from zena:core/template-strings-array.zena

dedent over the raw literals, keeping the trailing line break: the tag for embedding source code in a test.

It differs from dedent in two ways, both of which matter when the text being embedded is itself code:

  • The text dedented is strings.raw, so an escape stays the characters that were written. dedentRaw`let s = 'a\\nb';` yields a backslash followed by an n, which is the source line someone typed. Under dedent the same literal yields a real line break, which splits that Zena string literal across two lines, and because the second of them has no indentation it also drops the common indent to nothing.
  • The line break that ends the last content line survives the closing line being dropped, so the result ends in a newline when the closing backtick sits on its own line. Source files end in a newline, and so does the output of a formatter, so a round-trip comparison needs one here.
text
let source = dedentRaw`
  let f = () => {
    x += 2;
  };
`;
// "let f = () => {\n  x += 2;\n};\n"

Nothing is added that was not written: a template whose closing backtick follows the last line's content has no trailing break to keep, and the result has none. Every other rule — which lines the common indent is taken from, how blank lines are treated, how interpolations are spliced in — is dedent's, described above.

fixed

zena
function fixed<T>(items: FixedArray<T>): FixedArray<T>
Re-exported from zena:core/fixed-array.zena

Its argument, unchanged: fixed([1, 2, 3]).

The parameter supplies the mutable context, so a literal argument builds directly as a FixedArray — a mutable literal in expression position, where no annotation can say so. The identity body inlines away, leaving the bare allocation.

growable

zena
function growable<T>(items: FixedArray<T>): GrowableArray<T>
Re-exported from zena:core/growable-array.zena

A growable array from an array literal: growable([1, 2, 3]).

The parameter supplies the mutable context, so the literal builds directly as a FixedArray and is adopted as the backing storage — no copy, unlike GrowableArray.from over an interface-typed source. Until literal decorators land, this is the concise spelling for a growable array with initial contents.

newByteArray

zena
function newByteArray(size: i32): ByteArray
Re-exported from zena:core/byte-array.zena

Create a new ByteArray of the specified size, filled with zeros.

copyBytes

zena
function copyBytes(dest: ByteArray, destOffset: i32, src: ByteArray, srcOffset: i32, length: i32): void
Re-exported from zena:core/byte-array.zena

Copy bytes from source to destination.

dest

Destination array

destOffset

Starting index in destination

src

Source array

srcOffset

Starting index in source

length

Number of bytes to copy

readU8

zena
function readU8(bytes: ByteArray, offset: i32): i32
Re-exported from zena:core/data-view.zena

The byte at offset, from 0 to 255.

readU16

zena
function readU16(bytes: ByteArray, offset: i32): i32
Re-exported from zena:core/data-view.zena

The two bytes at offset, little-endian, from 0 to 65535.

readU32

zena
function readU32(bytes: ByteArray, offset: i32): i32
Re-exported from zena:core/data-view.zena

The four bytes at offset, little-endian. Read as u32 for the unsigned value.

readU64

zena
function readU64(bytes: ByteArray, offset: i32): i64
Re-exported from zena:core/data-view.zena

The eight bytes at offset, little-endian. Read as u64 for the unsigned value.

readF32

zena
function readF32(bytes: ByteArray, offset: i32): f32
Re-exported from zena:core/data-view.zena

The f32 whose bits are the four bytes at offset, little-endian.

readF64

zena
function readF64(bytes: ByteArray, offset: i32): f64
Re-exported from zena:core/data-view.zena

The f64 whose bits are the eight bytes at offset, little-endian.

readULEB128

zena
function readULEB128(bytes: ByteArray, offset: i32, end: i32): inline (i32, i32)
Re-exported from zena:core/data-view.zena

The unsigned LEB128 value at offset, of at most 5 bytes, and the offset after it; that offset is -1 when the value does not end before end. Bits past the 32nd are dropped.

readULEB128_64

zena
function readULEB128_64(bytes: ByteArray, offset: i32, end: i32): inline (i64, i32)
Re-exported from zena:core/data-view.zena

The unsigned LEB128 value at offset, of at most 10 bytes, and the offset after it; that offset is -1 when the value does not end before end. Read as u64 for values of 2^63 and above.

readSLEB128

zena
function readSLEB128(bytes: ByteArray, offset: i32, end: i32): inline (i32, i32)
Re-exported from zena:core/data-view.zena

The signed LEB128 value at offset, of at most 5 bytes, and the offset after it, or -1 as for readULEB128.

readSLEB128_64

zena
function readSLEB128_64(bytes: ByteArray, offset: i32, end: i32): inline (i64, i32)
Re-exported from zena:core/data-view.zena

The signed LEB128 value at offset, of at most 10 bytes, and the offset after it, or -1 as for readULEB128_64.

join

zena
function join(items: Iterable<String>, separator: String = ''): String
Re-exported from zena:core/string-join.zena

Concatenates the strings in items with separator between adjacent elements.

writeI32

zena
function writeI32(value: i32, buffer: ByteArray, bufferEnd: i32): inline (i32, i32)
Re-exported from zena:core/string-convert.zena

Writes an i32 to a buffer. Buffer must have at least 11 bytes. Returns (startPos, endPos) where the digits are in buffer[startPos..endPos).

writeU32

zena
function writeU32(value: u32, buffer: ByteArray, bufferEnd: i32): inline (i32, i32)
Re-exported from zena:core/string-convert.zena

Writes a u32 to a buffer. Buffer must have at least 10 bytes. Returns (startPos, endPos).

writeI64

zena
function writeI64(value: i64, buffer: ByteArray, bufferEnd: i32): inline (i32, i32)
Re-exported from zena:core/string-convert.zena

Writes an i64 to a buffer. Buffer must have at least 20 bytes. Returns (startPos, endPos).

writeU64

zena
function writeU64(value: u64, buffer: ByteArray, bufferEnd: i32): inline (i32, i32)
Re-exported from zena:core/string-convert.zena

Writes a u64 to a buffer. Buffer must have at least 20 bytes. Returns (startPos, endPos).

boolToString

zena
function boolToString(value: boolean): String
Re-exported from zena:core/string-convert.zena

Converts a bool to "true" or "false".

parseI32

zena
function parseI32(s: String): inline (true, i32) | inline (false, _)
Re-exported from zena:core/string-convert.zena

Parse a decimal integer from a string, with optional leading sign. Returns inline (true, value) on success, inline (false, _) on failure. Fails if the string is empty or contains non-digit characters (after optional sign).

parseI64

zena
function parseI64(s: String): inline (true, i64) | inline (false, _)
Re-exported from zena:core/string-convert.zena

Parse an i64 integer from a string, supporting optional leading sign, optional hex prefix (0x or 0X), and optional underscores (_). Returns inline (true, value) on success, inline (false, _) on failure.

decimalToF64

zena
function decimalToF64(d: u64, p: i32, negative: boolean, inexact: boolean, tail: u64): f64
Re-exported from zena:core/string-convert.zena

The f64 nearest to d * 10^p, correctly rounded. d is the decimal significand as an integer below 2^64 and p its decimal exponent. inexact says the true value lies strictly between d and d + 1 — the caller had more digits than it could keep — and tail is that leftover fraction scaled by 2^11.

With 19 or fewer significant digits inexact is false and the result is the correctly rounded one, always. Beyond that the significand no longer fits: normalizing d to 64 bits leaves only 64 - bits(d) low bits for the remainder, so the value is placed to within half of the last of them and can land on the wrong side of a rounding boundary that falls inside that gap. Measured against a correctly-rounded implementation this is about one input in five thousand of more than 19 significant digits, always by one ulp (dev/fp-difftest.js measures it). Closing it needs an exact-arithmetic fallback, which the algorithm this comes from also leaves to its caller.

i32ToString

zena
function i32ToString(value: i32): String
Re-exported from zena:core/number-format.zena

Converts an i32 to its decimal string representation.

u32ToString

zena
function u32ToString(value: u32): String
Re-exported from zena:core/number-format.zena

Converts a u32 to its decimal string representation.

i64ToString

zena
function i64ToString(value: i64): String
Re-exported from zena:core/number-format.zena

Converts an i64 to its decimal string representation.

u64ToString

zena
function u64ToString(value: u64): String
Re-exported from zena:core/number-format.zena

Converts a u64 to its decimal string representation.

f32ToString

zena
function f32ToString(value: f32): String
Re-exported from zena:core/number-format.zena

The shortest decimal string that reads back as this f32. The f32 interval is used, not the f64 one the promoted value would have, so 0.1 as f32 prints "0.1" rather than "0.10000000149011612".

f64ToString

zena
function f64ToString(value: f64): String
Re-exported from zena:core/number-format.zena

The shortest decimal string that reads back as this f64.

f64ToPrecision

zena
function f64ToPrecision(value: f64, sigDigits: i32): String
Re-exported from zena:core/number-format.zena

value rounded to sigDigits significant decimal digits, in the same format f64ToString uses. sigDigits is clamped to [1, 17].

parseF64

zena
function parseF64(s: String): f64
Re-exported from zena:core/string-convert.zena

Parses the number at the start of s to the NEAREST f64, correctly rounded: an optional sign, then Infinity, 0x and hex digits, or a decimal with an optional fraction and exponent. Anything after the number is ignored, and a string that does not start with one is NaN.

Apart from hex, which the compiler uses for a hex literal typed as a float, this is JavaScript's parseFloat on a string that does not start with whitespace. parseFloat skips leading whitespace, where this reads no number; JavaScript's whitespace includes a dozen non-ASCII spaces, and recognizing them would cost every module that parses a float.

The significand is accumulated as an integer and the exponent tracked alongside, so no rounding happens until the single decimalToF64 at the end. Digits beyond the nineteenth cannot change the result except through the tie they might break, so they are folded into a sticky low digit rather than dropped.

Variables

none

zena
let none: None
Re-exported from zena:core/option.zena

The singleton None instance.