Core interfaces

The contracts every other family is built on: copying, equality, ordering, hashing, iteration, views, and reading and writing text.

Generated by bin/build_library_doc.py from the kernel sources. Do not edit by hand: change the generator, or the doc comments in kernel/src/, and re-run it.

Collections and iteration

INTERFACE BidirectionalIterator

BidirectionalIterator OF T — extends ReferenceIterator OF T with reverse traversal. Used by Array, LinkedList, SortedList, Deque per spec L763-768.

kernel/src/interfaces.ev:429

Methods

METHOD hasPrevious() RETURNS boolean
MODIFY METHOD previous() RETURNS | REFERENCE T
MODIFY METHOD skipBack(uint64 n) RETURNS | REFERENCE T

GROUP Collectable

kernel/src/interfaces.ev:145

INTERFACE Collection

The minimum definition of a Collection container — what every container in the standard library can answer, so that membership of this interface is what marks a type AS a collection.

3 METHODS: iterator() declared here size() and isEmpty() inherited from Countable

contains() is deliberately NOT here, and the reason is the whole shape of the interface. Containment needs EQUALITY on T, and Array[T] requires only Cloneable of its elements — so putting contains in the minimum would force Equatable onto every element type in the language the moment Array joined. That is the split the industry already divides on: where equality is UNIVERSAL (Java's Object.equals, Python's eq) a Collection can require contains, and where equality is OPT-IN (Rust, Swift, C++) it cannot — Swift's Collection requires iteration and offers contains only as an extension where Element: Equatable. Envzn is the second kind. Containment belongs with Searchable OF T, whose find needs exactly the same equality and of which contains is the boolean shadow.

ITERATION is also the more primitive notion: contains is DERIVABLE from iterating and comparing, while iteration cannot be derived from containment. A minimum should be the irreducible core. The qualifier is deliberately the WIDEST of any container's: iterator(), size() and isEmpty() ask NOTHING of T, so nothing here should either. Shareable is listed beside Cloneable because the OwnedList family constrains its element that way, and refusing it would exclude a container from the interface over a contract the interface never uses.

kernel/src/interfaces.ev:492

Methods

METHOD iterator() RETURNS ReferenceIterator[T]

GROUP Collectors

kernel/src/interfaces.ev:133

INTERFACE Countable

Countable is an opt-in interface for any class that enumerates how many elements it holds.

kernel/src/interfaces.ev:221

Methods

METHOD size() RETURNS int64
METHOD isEmpty() RETURNS boolean

INTERFACE Iterator

Iterator OF T — forward-traversal cursor over a collection. Per spec §Iterator (L730+).

kernel/src/interfaces.ev:255

Methods

METHOD hasNext() RETURNS boolean

INTERFACE ObjectIterator

ObjectIterator OF T — extends Iterator with by-reference navigation over a HEAP-CLASS element type. The object peer of ReferenceIterator: where ReferenceIterator's bound admits only Cloneable primitives, ObjectIterator admits any class, so a collection whose logical element is a synthesized class instance (a per-position VIEW — e.g. a DataFrame yielding a Row built from its stored columns) can be FOR e IN coll-iterable. Because the source may not STORE the element (it synthesizes it), the concrete iterator OWNS the current element in an internal slot and hands back a non-owning REFERENCE into that slot; the reference is valid until the next advance, on which the slot is refreshed. The FOR-IN loop borrows it for the iteration exactly as it borrows a ReferenceIterator's referent — so next() lowers to REFERENCE T (a T*) on both this interface and its implementers, with none of the value-form covariance seam.

kernel/src/interfaces.ev:405

Methods

MODIFY METHOD next() RETURNS | REFERENCE T

2.0 pipe-XOR shape: a successful navigation refreshes the iterator's owned slot and populates value with a non-owning reference into it; end-of-iteration populates s with FAILURE.

METHOD peek() RETURNS | REFERENCE T

peek is non-consuming: the reference to the current slot without advancing. Same pipe-XOR shape as next().

INTERFACE ReferenceIterator

ReferenceIterator OF T — extends Iterator with by-reference navigation. Implemented by the collection iterators, whose backing storage is referenceable: next() / peek() / skip() hand back a non-owning reference into the source rather than a copy. Buffer iterators (over by-value _cxx* storage) implement only the value-form Iterator. next/peek/skip hand back a REFERENCE and never clone, so Cloneable was never used; Shareable joins it so the OwnedList family qualifies.

kernel/src/interfaces.ev:355

Methods

MODIFY METHOD next() RETURNS | REFERENCE T

2.0 pipe-XOR shape: a successful navigation populates value with a non-owning reference into the source; end-of-iteration or invariant violation populates s with FAILURE. The caller's IF iter->next() THEN { use($RETURNED) } ELSE { ... } consumes the populated slot.

METHOD peek() RETURNS | REFERENCE T

peek is non-throwing and non-consuming: returns the reference at the current cursor without advancing. Same pipe-XOR shape as next().

MODIFY METHOD skip(uint64 n) RETURNS | REFERENCE T

INTERFACE Searchable

Searchable OF T — contents can be searched for a needle of the same Text kind. find returns the match position; pipe-XOR FAILURE means no match. Implemented by String and StringView — the view holds the one canonical scan, and String forwards through a full-span view.

kernel/src/interfaces.ev:292

Methods

METHOD find(REFERENCE T needle) RETURNS | int64

INTERFACE ValueIterator

ValueIterator OF T — extends Iterator OF T with by-value navigation. Implemented by the buffer iterators, whose backing storage yields elements by value, not by reference: nextValue() / peekValue() / skipValue() hand back a copy of the element. The value-form mirror of ReferenceIterator.

kernel/src/interfaces.ev:377

Methods

MODIFY METHOD nextValue() RETURNS | T

2.0 pipe-XOR shape: a successful navigation populates value with a copy of the element at the new cursor; end-of-iteration populates s with FAILURE.

METHOD peekValue() RETURNS | T

peekValue is non-consuming: the value at the current cursor without advancing. Same pipe-XOR shape as nextValue().

MODIFY METHOD skipValue(uint64 n) RETURNS | T

Copying and ownership

INTERFACE Cloneable

Cloneable — per Bug #23. A class implementing Cloneable opts in to deep-copy semantics: := on instances calls clone(); the *Copy family of collection methods clones each class-typed element through this interface.

Implementations declare their own concrete return type — Envzn's interface satisfaction rule accepts any return type that itself implements Cloneable (covariant-return-via-subtype), so:

CLASS Person IMPLEMENTS Cloneable { METHOD clone() RETURNS Person { Person p := CREATE Person(.age) RETURN (p) } }

...satisfies the contract without any cast.

An AUTO clone is the other form, and it declares NO return type: the compiler supplies the body AND the concrete return type, so writing RETURNS on one is E7029 (auto-clone-with-returns).

CLASS Point IMPLEMENTS Cloneable { AUTO METHOD clone() { } // generated; never RETURNS Point }

kernel/src/interfaces.ev:175

Methods

METHOD clone() RETURNS Cloneable

INTERFACE Inoperative

Inoperative — marker for types whose values can't be operated on in generic code. Today's sole member is the Part-G opaque primitive: type-erased payload whose static type is opaque to callers, so no method dispatch is well-defined. Generic kernel containers (Array, Dictionary, Set, etc.) use WHEN T IMPLEMENTS Inoperative { /* no-op stub */ } ELSE { ... } to opt out of clone, copy, and iteration paths that would instantiate to deleted-ctor / dangling-handle errors for opaque.

The inoperativeReason() method is the sole operation valid on an Inoperative value — it returns a fixed-text human-readable description of why this type is opaque. Used by debug printers, error formatters, and kernel logs that need to render "what is this thing I got" without unwrapping.

Compile-time WHEN T IMPLEMENTS Inoperative lowers to a special _is_inoperative_v<T> trait check (see EV_handles.hpp) rather than the usual std::is_base_of_v<> path, because opaque is a runtime struct (not a class that can inherit from an interface). The dispatch of inoperativeReason() itself is hardcoded in the emitter for the opaque keyword type.

kernel/src/interfaces.ev:339

Methods

METHOD inoperativeReason() RETURNS String

Equality, ordering and hashing

INTERFACE Comparable

Comparable[T] — type defines a strict less-than ordering. Extends Equatable[T]: a type that is comparable is necessarily equatable (otherwise sorted-and-equal-to checks can't compose).

Required for any T used in: - SortedList[T] (insert position determined by isLessThan) - Array[T]->sort() (insertion-sort or quicksort comparator) - any future ordered collection

The implementation MUST satisfy a strict total order: - Irreflexive — a.isLessThan(a) is always FALSE. - Antisymmetric — if a.isLessThan(b) then NOT b.isLessThan(a). - Transitive — if a.isLessThan(b) and b.isLessThan(c), then a.isLessThan(c). - Trichotomous (consistent with Equatable) — for every pair, exactly one of a.isLessThan(b), b.isLessThan(a), or a.isEqualTo(b) is TRUE.

The kernel provides built-in Comparable behaviour for primitive numerics (int8..int64, uint8..uint64, float32, float64, byte, char) and String (lexicographic). boolean is also comparable (FALSE < TRUE). Class types must declare IMPLEMENTS Comparable[K] and provide isLessThan(K) and isEqualTo(K) methods explicitly.

isLessThanOrEqual, isGreaterThan, isGreaterThanOrEqual are derivable and not part of this interface; the canonical method is isLessThan. Callers compose: NOT a.isLessThan(b) is "a >= b", b.isLessThan(a) is "a > b", etc.

kernel/src/interfaces.ev:528

Methods

METHOD isLessThan(REFERENCE T other) RETURNS boolean

INTERFACE Equatable

Equatable[T] — type can compare itself to another instance of the same type for value equality. Parameterised over T to pin the comparison type at the implementation site:

CLASS Token IMPLEMENTS Equatable[Token] {
    METHOD isEqualTo(Token other) RETURNS boolean { ... }
}

Equatable is the contract Dictionary uses to resolve hash collisions and Set uses for membership. Required alongside Hashable for any class type used as a Dictionary key.

Implementations must be: - Reflexive — a.isEqualTo(a) is always TRUE. - Symmetric — a.isEqualTo(b) iff b.isEqualTo(a). - Transitive — if a.isEqualTo(b) and b.isEqualTo(c), then a.isEqualTo(c). - Consistent with Hashable — if a.isEqualTo(b), then a.hash() == b.hash(). (The reverse need not hold; hash collisions on equal-by-isEqualTo objects break Dictionary.)

Built-in for primitives and String, same as Hashable.

kernel/src/interfaces.ev:283

Methods

METHOD equals(REFERENCE T other) RETURNS boolean

GROUP HashKey

kernel/src/interfaces.ev:128

INTERFACE Hashable

Hashable — type can produce a stable hash code of itself. Returned value is uint64 per spec §Hashable and KeyHasher (CONSTITUTION L3611). Implementing classes are eligible for use as Dictionary[K: V] keys (paired with Equatable[K], below) and Set[T] elements.

The hash MUST be: - Deterministic — equal objects (per Equatable.isEqualTo) must produce equal hashes. Calling hash() on the same value twice must yield the same result. - Pure — no observable side effects, no I/O, no mutation of SELF or any reachable state.

The kernel provides built-in Hashable behaviour for primitives (int8..int64, uint8..uint64, float32, float64, byte, char, boolean) and String — those types do not need to declare IMPLEMENTS Hashable explicitly. Dictionary[K: V] uses the built-in path automatically when K is one of those.

kernel/src/interfaces.ev:455

Methods

METHOD hash() RETURNS uint64

GROUP WordKey

GROUP WordKey — a primitive whose value IS an integer bit-pattern, so a hasher body may reduce it to its hash word with uint64 v = #key (I.F.ii(a): the value mod 2^64) and nothing about the value domain changes. It is exactly the operand set # accepts (E2153).

FastIntHasher and InlineIntHasher were qualified PRIMITIVE(EXCEPT opaque, boolean, number, complex) while their bodies are a bare uint64 v = key — which TRUNCATES for float32/float64, is forbidden outright for decimal128 (E2121 — decimal never mixes), and names a FOREIGN-only type for the C.* four. The constraint admitted types the body could not honour. This is the set it can.

int128/uint128 ARE members, and they are the one case where the reduction is lossy: the high 64 bits are dropped, so two keys differing only above bit 63 hash alike. That is a WEAK hash, not a wrong one — Equatable still separates them on lookup, and taking low bits is an ordinary hash fold. A float is excluded for the different reason that its bits are not a value: the same number has several encodings, so # on it would not be a fold but a reinterpretation. (Brian, 2026-08-24.)

kernel/src/interfaces.ev:107

Text I/O

INTERFACE Printable

Printable — type can render itself directly to stdout.

Distinct from Readable — Readable produces a String for the caller to do something with; Printable is the convenience for types that own their own output side effects (e.g. a complex renderer that writes structured output to multiple lines).

Most types should implement Readable and let callers route the output. Printable is for cases where producing the intermediate String would be wasteful (e.g. large structured dumps).

kernel/src/interfaces.ev:615

Methods

METHOD print() RETURNS void

INTERFACE Readable

Readable — a byte source: the counterpart of Writable. The single operation is read — drain the source into an storage char8[512+] of whatever it had. File, Socket, and the Stdio stdin source implement it, so code can ask of any of them "can I read this?" the same way Writable answers "can I write it?".

read returns the bytes it managed to produce as a char8[512+] storage value — empty when the source has none, populated through to end-of-input otherwise. The FAILURE status is reserved for a genuine read error, not for a short or empty read. The caller can build a ByteBuffer or DynamicByteBuffer from the returned storage when a wrapper is needed (§21).

Spec reference: stdio-spec.md §6.

kernel/src/interfaces.ev:598

Methods

MODIFY METHOD read() RETURNS | binary[]

GROUP Text

kernel/src/interfaces.ev:137

INTERFACE Writable

Writable — a byte sink. The single operation is write: hand it a ByteBuffer and it delivers every byte or fails. Implemented by the Stdio stdout/stderr sinks, by File, and by Socket — so a rendered String (from a Formatter) can reach any of them through one uniform call.

All-or-nothing: a short OS write is retried internally, so the outcome is SUCCESS — every byte written, count returned — or a FAILURE status. There is no partial write.

THE EXTENT IS THE ARRAY'S OWN LENGTH — there is deliberately no length parameter (gh #195, removed 2026-08-12). The old shape write(content, length) passed the caller's integer straight to POSIX write, which reads that many bytes from the base pointer: write(twoByteBuffer, 65536) wrote 64 KB of live heap — including a pointer — to disk, with no diagnostic at any phase. CWE-126, and severity 10 against I.A's memory-safe floor.

It was also redundant. read/readAt already return a char8[] whose .length IS the valid extent, so the class conveyed extent by array length in one direction and by a separate integer in the other. Three of the four call sites in the whole corpus passed a value equal to the array's length anyway.

To write PART of a buffer, take a view (ByteBufferView is REFERENCE char8[] source + start + length) or pass a right-sized array. A lone length could only ever express a prefix — it has no offset — so it was never the right tool for a slice.

Spec reference: stdio-spec.md §6.

kernel/src/interfaces.ev:747

Methods

MODIFY METHOD write(REFERENCE binary[] content) RETURNS | int64

Views

INTERFACE View

View — the non-owning window itself. Minimal base contract; the element-typed operations (operator[], iterator, find via Searchable, copy) live on the concrete view (StringView). Kept deliberately minimal so a future N-D view tier is not constrained by 1-D shape. Declared before Viewable because Viewable.view() references it.

kernel/src/interfaces.ev:301

Methods

METHOD length() RETURNS int64

INTERFACE Viewable

Viewable — a source that yields a non-owning, bounded View into its own storage without copying. view(start, length) windows over [start, start+length). The return type is the base View; an implementer narrows it covariantly to its concrete view (String returns StringView). This is the 1-D / linear tier (String now; ArrayView / byte-buffer views later) — the N-D strided views the Data module needs are a separate, related contract.

kernel/src/interfaces.ev:312

Methods

METHOD view(int64 start, int64 length) RETURNS View