System

The runtime and the outside world: processes, files, paths and standard I/O, plus the codecs, the conversions between types, and randomness.

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.

Runtime

CLASS System

Abstract base class for executable-module entry points.

Every executable Envzn module has exactly one class that EXTENDS System and overrides start(String[] argv) — that's the program's main entry point. The compiler resolves "which class is the entry point" by finding the unique subclass of System in the executable target.

Beyond the entry-point pattern, System exposes runtime services every program tends to want: stdout / stderr printing, env-var lookup, stdin line read, exit-code propagation. These are instance methods on System (the entry-point class inherits them); they are available to any code that has access to the module's entry-point instance via the implicit machinery that drives start().

EXTENDS System resolves through the standard parent-method walk (no hardcoded shortcut).

────────────────────────────────────────────────────────────────── ENTRY-POINT CONTRACT ──────────────────────────────────────────────────────────────────

The entry-point class must:

  1. Extend System (CLASS Main EXTENDS System { ... }).
  2. Provide a no-arg INIT.
  3. Override start(String[] argv) RETURNS int32. The returned value becomes the process exit code.

Example shape:

CLASS Main EXTENDS System {
    INIT() { }
    OVERRIDE METHOD start(String[] argv) RETURNS int32 {
        SELF->print("Hello, world!")
        RETURN (0)
    }
}

The compiler synthesises a small int main(int argc, char** argv) shim that constructs the Main class and invokes start(). That shim lives in the compiler's emit path, not in this file.

kernel/src/System.ev:87

Methods

METHOD getenv(REFERENCE String key) RETURNS | String

Look up an environment variable. Pipe-XOR: SUCCESS populates value with the variable's value (empty String if set to the empty value); FAILURE if the variable is unset.

METHOD exit(int32 code) RETURNS void

Exit the process immediately with the given code. Does NOT return. CLEANUP on stack frames is skipped — call only when the program genuinely cannot continue. For normal termination, RETURN from start() instead and let the entry-point shim propagate the exit code.

METHOD cloneCount() RETURNS int64

Deep copies performed so far. See the note above on enabling.

METHOD resetCloneCount() RETURNS void

Zero the counter, so a test can bracket one sequence.

METHOD memoryCompare(REFERENCE binary[] a, int64 aOff, REFERENCE binary[] b, int64 bOff, int64 n) RETURNS int32

Lexicographic byte comparison of the n-byte run a[aOff .. aOff+n) against b[bOff .. bOff+n). Returns a negative int32 when the first differing byte is smaller in a, positive when larger, and 0 when the two runs are byte-equal — the std::memcmp result contract, so one primitive serves both equality (== 0) and ordering. Each offset+run is bounds-checked once against its array's length.

METHOD memoryCopy(MUTABLE REFERENCE binary[] dst, int64 dstOff, REFERENCE binary[] src, int64 srcOff, int64 n) RETURNS void

Copy the n-byte run src[srcOff .. srcOff+n) into dst[dstOff .. dstOff+n) in place. PRECONDITION: both ranges are live — dstOff+n must not exceed dst.length (this is an in-place copy into existing slots, never a growing append) and srcOff+n must not exceed src.length; the compiler enforces both with one bounds check per run (IndexOutOfBoundsError on violation). The source and destination runs must not overlap. The compiler lowers each call site to one std::memcpy.

METHOD memoryWord(REFERENCE binary[] a, int64 off) RETURNS uint64

Read the 8 consecutive bytes a[off .. off+8) as one uint64 — a WIDE load, for word-wise hashing/scanning that processes eight bytes per operation instead of one. PRECONDITION: off+8 must not exceed a.length (the compiler checks it once and throws IndexOutOfBoundsError otherwise). The compiler lowers each call site to a single native-endian 8-byte load; this body is the readable little-endian spec, which coincides with the load on the little-endian V1 targets. Byte order is an internal detail — a word-wise hash only needs the same bytes to map to the same word, which both forms guarantee.

CLASS Stdio

The console: standard output, standard error, standard input. stdio-spec.md §2.

Stdio is a singleton. Twelve methods in three groups:

stdout — print · printline · formatPrint · formatPrintline · printBytes stderr — the same five, each with an Err suffix stdin — read(int32 length) · readline()

print writes its text verbatim; printline appends a newline. The formatPrint* pair render a $1..$9 template (stdio-spec.md §4) before writing. printBytes* write raw bytes with no formatting.

Writes return the pipe-XOR shape (int64 written | STATUS status) — written is the byte count. Reads return the comma shape (value, boolean atEof) — both slots are always populated, so an end-of-input read still delivers the bytes it managed to read.

The I/O layer is pure Envzn: write / read are bound directly from libc via FOREIGN BIND (no inline C++). <unistd.h> is listed in the ENVZN manifest's foreign block. A ByteBuffer argument crosses the boundary as a (pointer, length) pair (bind-spec §4); the C side of read writes through it.

V1 scope: a write is a single write(2) call (a rare short write under-reports the count, never corrupts); read / readline go one byte at a time, and a line ends at \n (0x0A). Buffered I/O, the full splitLines delimiter set, and EPIPE→FAILURE are V2.

kernel/src/Stdio.ev:50

Methods

METHOD print(REFERENCE String text) RETURNS | int64

Write text to stdout verbatim — no trailing newline.

METHOD printline(REFERENCE String text) RETURNS | int64

Write text to stdout followed by a newline.

METHOD formatPrint(REFERENCE String tmpl, opaque args...) RETURNS | int64

Render tmpl against args (stdio-spec.md §4) and write the result to stdout — no trailing newline.

METHOD formatPrintline(REFERENCE String tmpl, opaque args...) RETURNS | int64

Render tmpl against args and write the result to stdout followed by a newline.

METHOD printBytes(REFERENCE ByteBuffer data) RETURNS | int64

Write the raw bytes of data to stdout — no formatting.

METHOD printErr(REFERENCE String text) RETURNS | int64

Write text to stderr verbatim — no trailing newline.

METHOD printlineErr(REFERENCE String text) RETURNS | int64

Write text to stderr followed by a newline.

METHOD formatPrintErr(REFERENCE String tmpl, opaque args...) RETURNS | int64

Render tmpl against args and write the result to stderr.

METHOD formatPrintlineErr(REFERENCE String tmpl, opaque args...) RETURNS | int64

Render tmpl against args and write the result to stderr followed by a newline.

METHOD printBytesErr(REFERENCE ByteBuffer data) RETURNS | int64

Write the raw bytes of data to stderr — no formatting.

METHOD read(int32 length) RETURNS ByteBuffer

Read from stdin. length > 0 reads up to that many bytes; length == 0 reads one line, the \n delimiter included. Comma shape: loaded always holds what was read; atEof is TRUE when end-of-input was reached before the request was met.

METHOD readline() RETURNS String

Read one line from stdin, the trailing \n stripped. Comma shape: at end-of-input line is empty and atEof is TRUE, distinguishing EOF from a genuine blank line.

CLASS CommandLineArguments

Declare, parse and read a program's command-line arguments.

The input-side counterpart of Formatter: where format turns values into text on the way out, CommandLineArguments turns the argv a program was launched with into typed, validated values on the way in. It is the standard way to read arguments, so no program has to hand-roll its own loop.

A program declares what it accepts, parses once, then reads typed values:

INIT(String[] argv) {
    .args := CREATE CommandLineArguments(argv)
}

METHOD start() RETURNS STATUS {
    .args->addFlag("verbose", "v", "print each step")
    .args->addIntegerOption("jobs", "j", 1, "how many builds to run at once")
    .args->addTextOption("output", "o", "", "where to write the result")
    .args->require("output")
    .args->addPositional("input", "the file to read")
    IF .args->parse() IS FAILURE THEN { ... print $! and .args->usage() ... }
    IF .args->helpRequested() THEN { Stdio->printline(.args->usage()) ... }
    int64 jobs = .args->integerValue("jobs")
    String input := .args->positional("input")
}

Accepted spellings: --name value, --name=value, -n value (a declared short name), a bare flag --verbose / -v, and --, after which every word is positional. --help and -h are reserved: they set helpRequested().

Rules: * Every declared positional is required and filled in declaration order; an extra positional word is a parse FAILURE, as is an undeclared option. * An option's value is checked against its kind at parse(): --jobs abc fails there, so the typed getters never have to. * Reading a name that was never declared is a programmer error, not a runtime condition, and halts with UNREACHABLE!.

Storage is index-aligned parallel arrays rather than an option record: one slot per declared option in names, shortNames, helps, kinds, required, seen, texts, integers and floats.

kernel/src/CommandLineArguments.ev:52

Constructors

INIT(REFERENCE String[] argv)

argv exactly as the program received it: argv[0] is the program itself (used in usage()), the rest are the words to parse.

Methods

MODIFY METHOD addFlag(REFERENCE String name, REFERENCE String shortName, REFERENCE String help) RETURNS void

A switch that is either present or absent: --verbose / -v. shortName is one letter, or "" for none.

MODIFY METHOD addTextOption(REFERENCE String name, REFERENCE String shortName, REFERENCE String defaultValue, REFERENCE String help) RETURNS void

An option carrying text: --output out.csv.

MODIFY METHOD addIntegerOption(REFERENCE String name, REFERENCE String shortName, int64 defaultValue, REFERENCE String help) RETURNS void

An option carrying a whole number: --jobs 8.

MODIFY METHOD addFloatOption(REFERENCE String name, REFERENCE String shortName, float64 defaultValue, REFERENCE String help) RETURNS void

An option carrying a floating-point number: --rate 0.25.

MODIFY METHOD require(REFERENCE String name) RETURNS void

Make a declared option mandatory: parse() fails if it is absent.

MODIFY METHOD addPositional(REFERENCE String name, REFERENCE String help) RETURNS void

A required word that is not an option, filled in declaration order.

MODIFY METHOD parse() RETURNS STATUS

Read every word against the declarations. SUCCESS means every value is present and has the right kind; FAILURE's message names the first problem. After --help, parsing succeeds without enforcing required values.

METHOD helpRequested() RETURNS boolean

TRUE if --help or -h was given.

METHOD isSet(REFERENCE String name) RETURNS boolean

TRUE if the flag or option appeared on the command line.

METHOD textValue(REFERENCE String name) RETURNS String

The option's text: what was given, or its default.

METHOD integerValue(REFERENCE String name) RETURNS int64

An integer option's value: what was given, or its default.

METHOD floatValue(REFERENCE String name) RETURNS float64

A float option's value: what was given, or its default.

METHOD positional(REFERENCE String name) RETURNS String

A positional argument's word, by its declared name.

METHOD usage() RETURNS String

The help text, generated from the declarations so it cannot drift from them.

CLASS Process

Process — kernel singleton for synchronous shell-out.

Stateless; never instantiated by user code. Always accessed via Process->run(...).

kernel/src/Process.ev:46

Methods

METHOD run(REFERENCE String command, REFERENCE String[] args) RETURNS ProcessResult

Run command with args, capturing stdout, stderr, and the exit code into a ProcessResult.

Blocks until the child process exits. PATH lookup follows the standard execvp rules — passing a bare program name (e.g. "tar") searches $PATH; an absolute or directory-relative path (e.g. "/bin/sh", "./build") is used directly.

Failure surfaces as exitCode == -1 (signal-killed); a pipe() / fork() / waitpid() failure PANICs an Error. execvp failure inside the child writes "execvp failed: ..." to stderr and exits with code 127.

CLASS File

IMPLEMENTS Readable, Writable

Full file-interaction class over the POSIX byte-I/O surface.

Pure Envzn making C system calls (no C++ shim). Two fd lifecycle modes on ONE class via an optional fd field:

• Persistent — open() (or a named opener) stores the fd; subsequent reads/writes/append/seek reuse it; close() releases it (CLEANUP closes any still-open fd on scope exit). • Per-operation — never call open(): the convenience methods open their own fd, do the op, and close. They are ADAPTIVE: if a persistent fd is open they use it, otherwise they open-and-close.

Thread safety: a per-File Lock (gate) guards the shared OS fd offset in persistent mode via raw acquire/release around the critical section (SYNCHRONIZED cannot be used inside pipe-shaped methods — E6051). Positioned I/O (readAt/writeAt → pread/pwrite) is offset-stable and needs no lock.

Failure model: open and every File-UNIQUE syscall carry SETS_ERRNO(-1), so failures return a STATUS with the real strerror message + errno code. read/write are co-bound (identically) in Stdio.ev, so they keep the plain signature — their errors are detected by the (<0) return.

Pipe-XOR idioms (kernel-first use of SETS_ERRNO): a pipe-shaped (X | STATUS status) method returns via the NAMED slot (status = FAILURE(…) RETURN (status); slot = local RETURN (slot)), binds $RETURNED to a LOCAL in the THEN arm (never slot = $RETURNED), and uses $!/$# only inside the ELSE arm.

Text I/O is UTF-8: String is the decoded char32 form; bytes on disk are UTF-8, transcoded at the boundary via TextConverter (String↔ByteBuffer). Byte I/O is binary[] (Readable/Writable contract).

kernel/src/File.ev:85

Fields

Constructors

INIT(REFERENCE String path)

Methods

MODIFY METHOD openRead() RETURNS STATUS

Open read-only (O_RDONLY).

MODIFY METHOD openWrite() RETURNS STATUS

Open for writing, creating + truncating (O_WRONLY|O_CREAT|O_TRUNC, 0644).

MODIFY METHOD openAppend() RETURNS STATUS

Open for appending, creating if absent (O_WRONLY|O_CREAT|O_APPEND, 0644).

MODIFY METHOD openReadWrite() RETURNS STATUS

Open for reading + writing, creating if absent (O_RDWR|O_CREAT, 0644).

MODIFY METHOD openExclusive() RETURNS STATUS

Open exclusively — fails if the file exists (O_WRONLY|O_CREAT|O_EXCL).

METHOD isOpen() RETURNS boolean

TRUE while a persistent fd is open.

MODIFY METHOD close() RETURNS STATUS

Close the persistent fd (no-op if not open).

MODIFY METHOD read() RETURNS | binary[]

Read the entire file's bytes (Readable). Adaptive: persistent fd (gate-guarded) if open, else opens O_RDONLY, drains, closes.

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

Write every byte of content, replacing contents (Writable). Adaptive. The extent is content.length — see the Writable contract (gh #195).

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

Append length bytes to the end (creating if absent). Adaptive.

METHOD readAt(int64 offset, int32 max) RETURNS | binary[]

Read up to max bytes at absolute offset (pread). Persistent fd.

MODIFY METHOD writeAt(int64 offset, REFERENCE binary[] content) RETURNS | int64

Write length bytes at absolute offset (pwrite). Persistent fd.

MODIFY METHOD readText() RETURNS | String

Read the whole file as UTF-8 text. Invalid UTF-8 → FAILURE.

MODIFY METHOD writeText(REFERENCE String content) RETURNS STATUS

Write content as UTF-8 text, replacing the file's contents.

MODIFY METHOD appendText(REFERENCE String content) RETURNS STATUS

Append content as UTF-8 text to the end of the file.

MODIFY METHOD seekFromStart(int64 offset) RETURNS | int64

Move the cursor to offset bytes from the START of the file. Returns the resulting absolute position.

MODIFY METHOD seekFromCurrent(int64 offset) RETURNS | int64

Move the cursor offset bytes from where it currently sits — negative moves backward. Returns the resulting absolute position.

MODIFY METHOD seekFromEnd(int64 offset) RETURNS | int64

Move the cursor offset bytes from the END of the file — 0 is the end itself and negative moves back into the content. Returns the resulting absolute position. (A POSITIVE offset here is legal and seeks PAST the end; writing there creates a hole. That is lseek's behaviour and this wrapper does not change it.)

MODIFY METHOD tell() RETURNS | int64

Current cursor position (lseek SEEK_CUR, no move).

MODIFY METHOD size() RETURNS | int64

File size in bytes — seek to end then restore the cursor (no stat). Nested so no top-level statement follows a pipe consume.

MODIFY METHOD truncateTo(int64 length) RETURNS STATUS

Truncate (or extend) the file to length bytes (ftruncate).

MODIFY METHOD flush() RETURNS STATUS

Flush buffered writes to disk (fsync).

MODIFY METHOD lockExclusive(boolean blocking) RETURNS STATUS

Acquire an exclusive advisory lock. blocking FALSE → non-blocking.

MODIFY METHOD lockShared(boolean blocking) RETURNS STATUS

Acquire a shared advisory lock.

MODIFY METHOD unlockFile() RETURNS STATUS

Release any advisory lock held on the file (LOCK_UN).

METHOD exists() RETURNS boolean

TRUE if the path exists (access F_OK).

METHOD isReadable() RETURNS boolean

TRUE if readable by the caller (access R_OK).

METHOD isWritable() RETURNS boolean

TRUE if writable by the caller (access W_OK).

METHOD isExecutable() RETURNS boolean

TRUE if executable by the caller (access X_OK).

MODIFY METHOD deleteFile() RETURNS STATUS

Delete the file (unlink). Named deleteFile — delete is a C++ keyword.

MODIFY METHOD renameTo(REFERENCE String dest) RETURNS STATUS

Rename / move the file to dest (rename).

MODIFY METHOD setPermissions(int32 mode) RETURNS STATUS

Change the file's permission bits (chmod); mode is an octal value.

CLASS Path

IMPLEMENTS Cloneable, Comparable, Equatable

Instance class wrapping a filesystem path with rich operations.

Path is the comprehensive filesystem-path API in the kernel. Where File (File.ev) is minimal — just a path String + read/write — Path layers existence checks, directory operations, manipulation (parent, basename, stem, extension, join, withExtension, resolve), and tree traversal (listFiles, makeDir, remove).

Internally a Path is a value-type wrapper around a String. Path instances are cheap to construct and hand around; they don't hold OS resources beyond the String itself.

The filesystem-touching methods (exists / isDirectory / isFile / resolve / listFiles / makeDir / remove) are backed by the native shims in EV_path_native.hpp via FOREIGN BIND. The manipulation methods (parent / basename / stem / extension / join / withExtension / toString) are pure Envzn — they never touch the filesystem.

────────────────────────────────────────────────────────────────── ERROR HANDLING ──────────────────────────────────────────────────────────────────

kernel/src/Path.ev:64

Fields

Constructors

INIT(REFERENCE String value)

Methods

METHOD clone() RETURNS Cloneable
METHOD exists() RETURNS boolean

EXISTENCE CHECKS — never fail TRUE iff something exists at this path (file, directory, or other).

METHOD isDirectory() RETURNS boolean

TRUE iff this path exists and is a directory.

METHOD isFile() RETURNS boolean

TRUE iff this path exists and is a regular file.

METHOD parent() RETURNS Path

PURE-ENVZN PATH MANIPULATION

The six methods below — parent / basename / stem / extension / withExtension / join — perform byte-level string manipulation around the / separator. The filesystem is never touched, so they are pure Envzn: cross-platform-consistent semantics (forward-slash only), demagic-plan-aligned scrutability, and one fewer dependency for the future LLVM-IR self-host.

Paths are treated as code-point strings: / is 0x2F and . is 0x2E (both ASCII, one code point each). Multi-byte codepoints inside path segments pass through unchanged. Returns the parent directory. For "/a/b/c" returns "/a/b". For "/a/b/c/" returns "/a/b/c" (the trailing slash makes the filename empty). For a relative single-segment path ("a"), returns the empty path. For "/" returns "/" (root's own parent — fixed point).

METHOD basename() RETURNS String

Filename including extension. For "/a/b/file.txt" returns "file.txt". For a path ending in "/" returns the empty String.

METHOD stem() RETURNS String

Filename without extension. For "/a/b/file.txt" returns "file". For "file.tar.gz" returns "file.tar" (only the last extension is stripped). For dotfiles like ".bashrc" returns ".bashrc" (no leading-dot extension stripped).

METHOD extension() RETURNS String

The file's extension including the leading dot. For "file.txt" returns ".txt". For an extensionless filename returns the empty String. For a leading-dot dotfile (".bashrc") returns the empty String — the leading dot is part of the stem, not an extension.

METHOD withExtension(REFERENCE String ext) RETURNS Path

Returns a new Path with the extension replaced. ext may include or omit the leading dot. For withExtension(".cpp") on "file.txt" returns Path "file.cpp". For withExtension("") strips the extension entirely (returning the stem-form path).

METHOD join(REFERENCE String segment) RETURNS Path

Append segment as a child path component. The result is value + "/" + segment, normalised so a trailing slash on value or a leading slash on segment doesn't produce a double "//". If segment is absolute (starts with '/') it replaces value entirely — matches std::filesystem::path's operator/ semantics.

METHOD resolve() RETURNS | Path

Resolve the path: if relative, prepend CWD; resolve any symbolic links; canonicalise '.' and '..' segments. Canonical resolution requires existence, so a missing path is FAILURE. Pipe-XOR: SUCCESS populates the resolved Path; FAILURE the STATUS.

METHOD listFiles() RETURNS | Array[Path]

DIRECTORY OPERATIONS — STATUS multi-return on failure List the immediate children of this directory as Paths. Each child is this joined with the entry's filename (forward-slash semantics via join()). FAILURE if this path is not an existing directory. An empty directory yields an empty Array (SUCCESS).

METHOD makeDir() RETURNS STATUS

Create the directory (and any missing parents). No-op if it already exists. FAILURE on permission error.

METHOD remove() RETURNS STATUS

Remove the file or directory tree. FAILURE on permission error or unreachable entries during traversal.

METHOD readText() RETURNS String

I/O — delegates to File

Convenience wrappers — for callers that already have a Path, it's natural to read/write directly without constructing a separate File instance. These are equivalent to: File f := CREATE File(.value); f->readText() / writeText

METHOD writeText(REFERENCE String content) RETURNS STATUS
METHOD modifiedAt() RETURNS | int64

Last modification time, in NANOSECONDS since the Unix epoch. FAILURE when the path cannot be stat'd — it does not exist, or a component of it is not searchable.

Nanoseconds rather than whole seconds because the caller is a build tool: a source edited in the same second as the build that consumed it must still read as newer, or the rebuild is silently skipped. An int64 of nanoseconds since the epoch runs to the year 2262.

IF p->modifiedAt() THEN { int64 ns := $= }
METHOD toString() RETURNS String

STRING REPRESENTATION

METHOD equals(REFERENCE Path other) RETURNS boolean
METHOD isLessThan(REFERENCE Path other) RETURNS boolean

CLASS BuildInfo

Build-provenance runtime API.

Surfaces the AUTO-GENERATED EV_buildinfo_data.hpp constants (version, git describe / commit / branch, build counter, dirty flag, build timestamp) to an Envzn program. The data is computed at build time by the compiler (compiler/buildinfo.py) and written to the OUTPUT side every build — never to source — so a program can report its own provenance.

char8[], not String: the data header is #included early (global scope, before namespace ENVZN), so this surface deliberately deals in char8[] byte arrays (UTF-8) and primitives, and never touches String — a caller that wants text converts the bytes itself (bytes INTO String, once String is in scope) at the call site. A NAMESPACE (not a SINGLETON): BuildInfo is a stateless provider of constants, it performs no behaviour.

The strings cross the FFI via the LOAD fill-buffer idiom — RETURNS char8[] is not a legal FFI return (bind-spec), so each accessor fills a caller-owned char8[] and returns the byte count.

kernel/src/BuildInfo.ev:37

Methods

METHOD version() RETURNS char8[]
METHOD gitDescribe() RETURNS char8[]
METHOD commit() RETURNS char8[]
METHOD branch() RETURNS char8[]
METHOD builtAt() RETURNS char8[]
METHOD isDirty() RETURNS boolean
METHOD buildCounter() RETURNS uint64

CLASS EnumReflection

The generic enum name<->value capability.

An enum's case names are per-enum compile-time data the compiler alone knows, so the compiler emits them: IDENTITY(SomeEnum).cases yields an EnumKind[], one pair per case (the "cases as instances" model). This namespace is the generic LOGIC over that table — written once, reused by anything that needs an enum's name<->value mapping (serde, logging, config/UI, round-tripping through any format). No feature synthesizes its own per-enum lookups; they all call here.

EnumKind (a case's name + value) lives in structs.ev next to Identity: it is referenced by both Identity.cases and this namespace, and a STRUCT may not share a file with a NAMESPACE (E9008) — so the ">1 consumer -> structs.ev" rule applies.

The lookups walk cases by index (FOR i = 0 UNTIL cases.length): FOR/IN over a T[] value-array PARAM mis-emits cases->iterator() (arrow on a value) today, so the index form is the working idiom here.

kernel/src/EnumReflection.ev:28

Methods

METHOD name(REFERENCE EnumKind[] cases, int32 value) RETURNS String

value -> case name; the empty String when no case has that value.

METHOD valueForName(REFERENCE EnumKind[] cases, REFERENCE String target) RETURNS | int32

case name -> value; FAILURE when no case carries that name.

METHOD checkValue(REFERENCE EnumKind[] cases, int32 candidate) RETURNS | int32

Validate a value names a live case; echoes it back, else FAILURE.

CLASS Formatter

Auto-conversion text formatter (stdio-spec.md §4).

Formatter is the kernel surface that powers the user-facing ("...$1")->format(args) form. The compiler rewrites that call to Formatter->format(template, args) whenever at least one arg's static type is not String — see stdio-spec.md §4.3.

A Formatter carries one piece of configuration: how it renders a binary / ByteBuffer / DynamicByteBuffer placeholder. Construct a Formatter once and reuse it — as a local, a CONSTANT field, or held by a Writable for consistent output. The compiler's default rewrite uses Formatter() (HEX_SPACED); call Formatter explicitly to choose a different BinaryMode.

Architecture note: the template-walking + type cascade live here, not on String. String is upstream of every renderable type's conversion (the Converter and Codec classes, FloatFormat) in the kernel .hpp DAG; placing the cascade on String would create a cycle. Formatter is downstream of both and can freely call into them. The compiler-rewrite from stringExpr->format(args) to Formatter->format(stringExpr, args) is what lets users keep the natural call shape while preserving the topological invariant.

Format specifiers: a placeholder may carry a Python-style :spec suffix (stdio-spec.md §4.4). The spec governs width / fill / align and — for select types — base override and sign. The spec grammar lives in parseSpec below; the rendering side dispatches in renderArg / applyWidth.

kernel/src/Formatter.ev:47

Fields

Constructors

INIT()

Default Formatter — binary args render as spaced hex.

INIT(BinaryMode mode)

Formatter with an explicit binary-rendering mode.

Methods

METHOD format(REFERENCE String tmpl, REFERENCE opaque[] args) RETURNS String

Render tmpl against args, substituting $1..$9 and $$ per stdio-spec.md §4.1. A placeholder may carry a format spec :<spec> (§4.4) — width / fill / align / sign / type-letter — that is parsed and applied to the rendered value.

ENUM BinaryMode

BinaryMode — how a Formatter renders a binary placeholder argument. Selected at Formatter construction; the default Formatter uses HEX_SPACED.

Spec reference: stdio-spec.md §4.

kernel/src/enums.ev:171

Case Description
? —
? —
? —

ENUM Build

Build — compile-time build flavor. Available to user code via the WHEN Build IS DEBUG/RELEASE conditional-compilation construct (analogous to #ifdef DEBUG in C/C++; #5, shipped 2026-06-26 — the unmatched arm is removed before semantic analysis, never emitted):

WHEN Build IS DEBUG {
    log("debug-only state: $1")->format(detail)
} ELSE {
    // release path
}

Spec reference: §Control Flow > Conditional Compilation.

kernel/src/enums.ev:64

Case Description
? —
? —

ENUM Encoding

Encoding — text-encoding tag used by Convert text↔bytes bridges. Consumed by the four-form String/ByteBuffer type system (added 2026-05-03 in the String/Binary rework).

Used by: - Convert.toBytes(String, Encoding) → ByteBuffer - Convert.toString(ByteBuffer, Encoding) → (String, STATUS)

V1 implementation: UTF-8 round-trip is end-to-end; the other four variants are stubbed as STATUS-FAILURE returns until needed.

kernel/src/enums.ev:91

Case Description
? —
? —
? —
? —
? —
? —

ENUM Endianness

Endianness — byte-order tag used by Convert numeric↔binary bridges. Consumed by the four-form String/ByteBuffer type system (added 2026-05-03 in the String/Binary rework).

Used by: - Convert.toBytes(int32, Endianness) → ByteBuffer - Convert.toInt32(ByteBuffer, Endianness) → (int32, STATUS) - …and every other Convert numeric↔binary bridge.

kernel/src/enums.ev:119

Case Description
? —
? —
? —

STRUCT EnumKind

Identity — the compile-time reflection / RTTI carrier produced by the IDENTITY(subject) keyword intrinsic. Every field is computed by the compiler from static type + binding knowledge; the developer cannot construct an Identity directly (the keyword is the only producer). See docs/specifications-drafted/identity-reflection-design.md for the field semantics and the closed class / modifier vocabularies.

EnumKind — one enum case as a (name, value) pair; the element type of Identity.cases. Referenced by both Identity and EnumReflection, so it lives here per the ">1 consumer -> structs.ev" rule. Declared before Identity because Identity holds an EnumKind[].

kernel/src/structs.ev:150

Fields

STRUCT FormatSpec

FormatSpec — parsed $N:<spec> directive carried into Formatter's per-arg renderer. See stdio-spec.md §4.4 for the grammar and per- type semantics. Default-constructed values mean "absent" — align of 0x0 means "type default" (right for numbers, left for everything else); typeLetter of 0x0 means "render via the type's default"; width of 0 means "no minimum width".

kernel/src/structs.ev:106

Fields

STRUCT Identity

Field order is load-bearing: it is the synthesized-constructor argument order the IDENTITY lowering emits.

kernel/src/structs.ev:161

Fields

STRUCT ProcessResult

Mirrors enums.ev / interfaces.ev: a single file collecting the small reserved STRUCTs that the constitution recognises as part of the kernel surface but that don't merit their own per- class file. ProcessResult — the output of a Process->run(...) call.

kernel/src/structs.ev:40

Fields

Codecs

CLASS Base64Codec

Base64Codec.ev — base64 text<->bytes encoding (RFC 4648 standard alphabet). Parameterized, multi-form transforms — NOT AS/INTO operators — hosted in a NAMESPACE of free functions (no instance), called as Base64Codec.toBase64(bb).

kernel/src/Base64Codec.ev:14

Methods

METHOD toBase64(REFERENCE ByteBuffer bb) RETURNS String

ByteBuffer -> base64 String (RFC 4648 standard alphabet). Padding ('=') is included so the output is always a multiple of 4 characters. No line wrapping.

METHOD fromBase64(REFERENCE String s) RETURNS | ByteBuffer

Base64 String -> ByteBuffer (RFC 4648 standard alphabet). Standard '+/' alphabet only (no URL-safe variant in V1). Padding required. Skips ASCII whitespace. Pipe-XOR — FAILURE on any invalid character or wrong padding.

CLASS ByteOrderCodec

kernel/src/ByteOrderCodec.ev:32

Methods

METHOD toBytes(int32 n, Endianness endian) RETURNS ByteBuffer
METHOD toBytes(int64 n, Endianness endian) RETURNS ByteBuffer
METHOD toBytes(uint32 n, Endianness endian) RETURNS ByteBuffer
METHOD toBytes(uint64 n, Endianness endian) RETURNS ByteBuffer
METHOD toBytes(float32 n, Endianness endian) RETURNS ByteBuffer

Float -> bytes: IEEE-754 bit pattern via a bound shim, then packed by the same pure-Envzn endian helper the integer overloads use.

METHOD toBytes(float64 n, Endianness endian) RETURNS ByteBuffer
METHOD toInt32(REFERENCE ByteBuffer bb, Endianness endian) RETURNS | int32
METHOD toInt64(REFERENCE ByteBuffer bb, Endianness endian) RETURNS | int64
METHOD toUInt32(REFERENCE ByteBuffer bb, Endianness endian) RETURNS | uint32
METHOD toUInt64(REFERENCE ByteBuffer bb, Endianness endian) RETURNS | uint64
METHOD toFloat32(REFERENCE ByteBuffer bb, Endianness endian) RETURNS | float32

Bytes -> float: integer bit pattern assembled in pure Envzn, then a bound shim reinterprets it as IEEE-754.

METHOD toFloat64(REFERENCE ByteBuffer bb, Endianness endian) RETURNS | float64

CLASS DecimalCodec

The inbound half of the decimal128 IEEE 754-2008 BID (Binary Integer Decimal) 128-bit wire codec.

bidToParts decodes 16 big-endian BID bytes into a (coefficient, exponent) DecimalParts — it returns only the PARTS, never a decimal128: the kernel cannot construct a value-class-backed primitive, so the compiler's ByteBuffer INTO decimal128 lowering calls this helper and assembles Decimal128(coeff, exp) on success (the same parts→value pattern as DecimalText.parseDecimalParts for String INTO decimal128). The outbound encode is decimal128 INTO ByteBuffer (DecimalConversions, a plain total OPERATOR INTO).

Simple form only: a canonical decimal128 holds ≤ 34 digits (< 10^34 < 2^113), so the coefficient always fits the 113-bit field and the "11" combination branch (large coefficient / Infinity / NaN) is never PRODUCED — but a hostile or foreign 16 bytes can present it, so decode REJECTS it (and any out-of-range exponent or > 34-digit coefficient) with a FAILURE: that is the fallible path.

Layout (big-endian): bit 127 = sign, bits 126..113 = biased exponent (exponent + 6176), bits 112..0 = the unsigned coefficient.

Pure Envzn, zero deps beyond ByteBuffer / DecimalParts / NumericUtilities. See decimal128-design.md §"IEEE BID wire codec".

kernel/src/DecimalCodec.ev:34

Methods

METHOD bidToParts(REFERENCE ByteBuffer bb) RETURNS | DecimalParts

Decode 16 big-endian IEEE BID bytes into (coefficient, exponent). Fallible: wrong length, the non-canonical "11" combination form, an out-of-range biased exponent, or a coefficient of more than 34 digits.

CLASS HexCodec

kernel/src/HexCodec.ev:13

Methods

METHOD toHex(REFERENCE ByteBuffer bb) RETURNS String

ByteBuffer -> hex string with " " between bytes. Empty buffer returns "". Each byte becomes two uppercase hex digits.

METHOD toHex(REFERENCE ByteBuffer bb, REFERENCE String separator) RETURNS String

ByteBuffer -> hex string with caller-chosen separator. Pass "" for compact ("3F406A"), " " for canonical ("3F 40 6A"), ":" for MAC-style.

METHOD toHex(binary b) RETURNS String

Single-byte hex form. Used by the kernel print/stringify dispatch as the default formatter for the binary primitive (Bug #56). Returns exactly two uppercase characters (e.g. "3F" for 0x3F, "00" for zero).

METHOD fromHex(REFERENCE String s) RETURNS | ByteBuffer

Hex string -> ByteBuffer. Accepts upper/lowercase hex digits; ignores ASCII whitespace and standard separators (" ", ":", "-") so canonical / MAC / UUID formats round-trip. Pipe-XOR — FAILURE on any non-hex non-separator character or an odd digit count.

CLASS UTFCodec

Unicode Transformation Format codec + scalar validity.

UTFCodec is a stateless NAMESPACE: never instantiated, reached via UTFCodec.methodName(args). It hosts free functions plus the private CONSTANT lookup tables (and the CharClass / State enums + FirstUnitInfo struct they are built from) the transcoders walk.

PURPOSE The single home for transcoding between the three UTF encodings (UTF-8 / UTF-16 / UTF-32), plus the predicates that decide whether a code point is a legal Unicode scalar and whether it is admissible as text. The Converter and Codec classes and DynamicString (via DynamicString.append) are the user-facing bridges to the String / ByteBuffer types; they marshal char[] arrays in/out and call UTFCodec for the actual transcoding. UTFCodec itself has no dependency on String, DynamicString, ByteBuffer, or DynamicByteBuffer — it works purely in terms of char8[] / char16[] / char32[] and the two scalar-validity predicates over char. That keeps UTFCodec below every text/byte class in the kernel dependency order.

The class is named for the UTF family (UTF-8 / UTF-16 / UTF-32). Every transcoder is named encodeTo<TARGET>(<SOURCE>[] source) -> (<TARGET>[] | STATUS) — the destination encoding is in the method name; the source is in the argument width. The full 3×3 matrix minus the identity diagonal is implemented (6 methods).

CODE POINT vs CODE UNIT char32 is a Unicode code point (U+0000..U+10FFFF, lowering to char32_t). char8 is a UTF-8 code unit (8-bit, char8_t). char16 is a UTF-16 code unit (16-bit, char16_t). Code-unit arrays in char8[] / char16[] form may need multi-unit grouping to recover a code point — UTF-8 lead+continuation bytes for encodeToUTF32(char8[]), surrogate pairs for encodeToUTF32(char16[]).

LOOKUP TABLES (utf_utils-style DFA) Four PRIVATE CONSTANT tables back a single-table DFA decoder (currently dormant — the linear decode below is what runs today). The DFA shape follows Bob Steagall's utf_utils paper:

firstUnitTable[256] — for each possible first byte, the masked code-point bits + the next DFA state. octetCategory[256] — CharClass tag for every byte value, used by continuation-byte transition lookup. transitions[108] — 9 states × 12 CharClass categories → next State. Index = (state + category). firstOctetMask[12] — per-CharClass mask of the first byte's code-point bits (e.g. 0x1F for the 5-bit lead in a 2-byte sequence).

VALIDITY — TWO PREDICATES - isValid(char) — is the code point a legal Unicode scalar value (<= U+10FFFF, not a UTF-16 surrogate). - isStringSafeCodePoint(char) — stricter: a scalar that is also admissible as text. Rejects the 66 noncharacters and the non-whitespace C0/C1 control bytes. This is the invariant DynamicString enforces on every append, so a text value can never accumulate non-text content.

STATUS: first version, written 2026-05-18 as part of the four-form text/binary dig-out. Carries the UTF-8 encode/decode that previously lived on Convert (encodeUtf8 / decodeUtf8), now with the scalar- validity checks (overlong / surrogate / out-of-range) folded into decode. The DFA lookup tables landed 2026-05-25 — they are dormant storage until a DFA-based decode rewrite replaces the current linear form.

kernel/src/UTFCodec.ev:84

Methods

METHOD encodeToUTF32(REFERENCE char8[] source) RETURNS | char32[]

DFA-BASED BULK DECODE — UTF-8 code units -> UTF-32 code points Decode a full UTF-8 buffer (char8[] code units) into a char32[] of code points using the four LOOKUP TABLES above (utf_utils- style single-DFA decoder). Pipe-XOR: SUCCESS yields the codepoints buffer; FAILURE on the first malformed lead unit, truncated sequence, bad continuation unit, or DFA-detected illegal form (overlong, surrogate, beyond U+10FFFF — all baked into the transitions[] mapping).

Input / output are both bare value-array storage shorthand — no String / ByteBuffer / DynamicString / Array[T] dependency. UTFCodec sits below the String family in the kernel dependency order.

Algorithm: 1. firstUnitTable[u] -> (firstOctet bits, nextState). ASCII units (0x00..0x7F) return nextState=BEGIN with cp == u, so the ASCII path is one table read + one write. 2. For multi-unit leads, nextState moves into a CONTINUEn / PARTIAL_SEQUENCE state. The continuation loop reads successive code units, accumulates 6 bits per unit into cp, and advances state via transitions[currentState + octetCategory[contUnit]]. Loop exits when state returns to BEGIN/END (= 0; code point complete) or ERROR (malformed). 3. Result built via the value-array HWM-write proxy — result[outCount] = cp grows the buffer when outCount equals result.length.

METHOD encodeToUTF8(REFERENCE char32[] source) RETURNS | char8[]

BULK TRANSCODE — char32[] → char8[] (codepoints → UTF-8 bytes) Encode an array of UTF-32 codepoints into a UTF-8 byte stream. Pipe-XOR: SUCCESS yields the byte buffer; FAILURE on the first codepoint that's beyond U+10FFFF or in the UTF-16 surrogate block. The byte width per codepoint follows RFC 3629: < 0x80 → 1 byte (0xxxxxxx) < 0x800 → 2 bytes (110xxxxx 10xxxxxx) < 0x10000 → 3 bytes (1110xxxx 10xxxxxx 10xxxxxx) else → 4 bytes (11110xxx 10xxxxxx 10xxxxxx 10xxxxxx)

METHOD encodeToUTF16(REFERENCE char32[] source) RETURNS | char16[]

BULK TRANSCODE — char32[] → char16[] (codepoints → UTF-16 units) Encode an array of UTF-32 codepoints into a UTF-16 code unit stream. BMP codepoints (< U+10000) emit one char16. Supplementary plane codepoints (U+10000..U+10FFFF) emit a surrogate pair — high in [0xD800, 0xDBFF], low in [0xDC00, 0xDFFF]. Pipe-XOR: FAILURE on a codepoint that's beyond U+10FFFF or in the surrogate block (raw surrogate codepoints are not legal scalar values).

METHOD encodeToUTF32(REFERENCE char16[] source) RETURNS | char32[]

BULK TRANSCODE — char16[] → char32[] (UTF-16 units → codepoints) Decode a UTF-16 code unit stream into UTF-32 codepoints, pairing surrogate halves into supplementary-plane codepoints. Pipe-XOR: FAILURE on an unpaired surrogate (low surrogate without a preceding high, or high surrogate without a following low).

METHOD encodeToUTF8(REFERENCE char16[] source) RETURNS | char8[]

BULK TRANSCODE — char16[] → char8[] (UTF-16 → UTF-8)

Composition: decode UTF-16 → codepoints → encode codepoints as UTF-8. The chain propagates STATUS from either step.

METHOD encodeToUTF16(REFERENCE char8[] source) RETURNS | char16[]

BULK TRANSCODE — char8[] → char16[] (UTF-8 → UTF-16)

Composition: decode UTF-8 → codepoints → encode codepoints as UTF-16. The chain propagates STATUS from either step.

METHOD isValid(char32 c) RETURNS boolean

VALIDITY PREDICATES TRUE when c is a legal Unicode scalar value: in range U+0000..U+10FFFF and not a UTF-16 surrogate half.

METHOD isStringSafeCodePoint(char32 c) RETURNS boolean

TRUE when c is admissible as text — a legal scalar value that is also not a noncharacter and not a junk control byte. This is the Tier-1 text rule: DynamicString.append(char) rejects every code point that fails it, so no text value can carry non-text content.

Allowed control bytes are the text whitespace set only — tab (U+0009), LF (U+000A), VT (U+000B), FF (U+000C), CR (U+000D), and NEL (U+0085); every other C0/C1 control and U+007F (DEL) is rejected. VT/FF/NEL are kept because they are line separators (see splitLines).

Conversions

CLASS PrimitiveConversions

CONVERSIONS host for primitive↔primitive numeric and character conversions. The AS/INTO surface over the number/char conversion matrix.

widening → OPERATOR INTO (lossless, total) e.g. int32 INTO int64 narrowing / → OPERATOR AS (lossy, fallible) e.g. int64 AS int32 sign-cross (range-checked → STATUS)

No class dependencies (only primitives + STATUS), so this host orders early in the kernel include topology and is reachable from every kernel class.

NOT here (they live on NumericUtilities): the deliberate UNCHECKED bit operations (truncateTo*, the saturating toInt32(uint32), the reinterpreting toUint64(int32)) — they would collide with the checked AS for the same type pair; the char-transcoding narrowings (char16/char32 → char8, char32 → char16) — they route through UTFCodec; and the character classifiers (isAlpha/isDigit/…) — predicates, not conversions.

kernel/src/PrimitiveConversions.ev:28

CLASS NumberConversions

CONVERSIONS host for the number primitive's narrow-OUT surface. Widening INTO number (int / float -> number) is the implicit lattice edge handled by the compiler; this host owns the explicit, fallible extraction back to a fixed scalar.

number AS int8/16/32/64, uint8/16/32, uint64, char8 — lossy, fallible (T | STATUS) Per CONVERSIONS.md: AS is lossy and RANGE-CHECKED at runtime — it fails into the IF/ELSE pipe-XOR, it is NOT a silent truncation. Succeeds IFF the number holds an integer subtype (INTEGER or the overflow-arm UNSIGNED, #38) whose value fits the target (in range, ≥ 0 for unsigned). The UNSIGNED arm is exactly a uint64, so AS uint64 on it is total; but UNSIGNED > int64_max, so AS int64 (and any narrower signed/unsigned) FAILS its range check. A float-subtype number always FAILS an integer extraction.

number INTO float64 — lossless-ish, total Every subtype lowers to float64 by the widening model (INTEGER via int64, UNSIGNED via uint64, both registered edges; float64 is identity), so this is a plain-value INTO, not a fallible AS (large magnitudes round, as any float).

The held value is read off the tagged union behind the value-class surface (v.tag / v.store.i / v.store.u / v.store.f). The range-checked assignment to the value slot is the sanctioned narrowing site (mirrors the int64 AS int32 row in PrimitiveConversions). number AS float32 is deferred (see its note below — blocked on a writable float32-max bound).

kernel/src/NumberConversions.ev:35

CLASS ComplexConversions

kernel/src/ComplexConversions.ev:12

CLASS DecimalConversions

The AS/INTO conversion host for decimal128 (DESIGN_QUEUE #40, Phase 5). Mirrors NumberConversions / ComplexConversions.

Surface (decimal128-design.md §Conversions): - decimal128 INTO String — EXACT decimal text (total). The headline display feature: a decimal128 renders the precise value it holds, no float artifacts. - decimal128 AS int8…int64 / uint8…uint64 — fallible (non-integral or out-of-range → FAILURE). - decimal128 AS float32 / float64 — lossy, fallible. String → decimal128 (parse) and number ↔ decimal128 land alongside.

Widening INTO decimal128 (int* → decimal128) is implicit (no operator) — the compiler lowers it at the widen-in site (build_ir).

kernel/src/DecimalConversions.ev:25

CLASS TextConverter

CONVERSIONS host for the String ↔ ByteBuffer hard line. The AS/INTO surface over the kernel's text/binary boundary, and its implementation — the UTF-8 encode/decode logic lives here in the operators (and the shared encoder helper), not delegated elsewhere.

Asymmetry (by design): String INTO ByteBuffer — lossless, total (every code point UTF-8 encodes) ByteBuffer INTO String — lossless, fallible (arbitrary bytes may not be valid UTF-8 → FAILURE; each decoded code point also passes the Tier-1 text check)

INTO here assumes UTF-8 — the canonical text encoding. Other encodings, and the hex/base64 transforms, are parameterized and stay as named functions on the Converter and Codec classes (out of scope for single-source/single-target AS/INTO operators).

kernel/src/TextConverter.ev:26

CLASS CharConverter

CONVERSIONS host for char→String.

A single code point rendered as a one-character String. char8/char16 widen to a char32 code point (via PrimitiveConversions) before encoding; char32 is already a code point. DynamicString.append(char32) UTF-8-encodes it and runs the Tier-1 text check — a non-text code point yields an empty String (the append FAILURE is benign here, matching the legacy behavior).

char8/char16/char32 INTO String — lossless, total char32[] INTO String — lossless, total String INTO char32 — exact-or-FAILURE (one code point)

Depends only on String + DynamicString, so it orders early. The char32[]→String operator backs the compiler-inserted error-message auto-conversion (args.py wraps a char[]-typed print/format argument as arg INTO String); the conversion registry is array-aware so it coexists with the scalar char32→String above rather than colliding on the key.

kernel/src/CharConverter.ev:28

CLASS CharWidthConverter

CONVERSIONS host for cross-char-width NARROWING. The AS surface over char16/char32 → a narrower char, and its implementation — the single-code-unit narrowing decision lives here, delegating only to UTFCodec's bulk transcoders (the UTF authority).

char16/char32 AS char8 — lossy, fallible (multi-byte UTF-8 → FAILURE) char32 AS char16 — lossy, fallible (UTF-16 surrogate pair → FAILURE)

UTFCodec emits the full encoded sequence; the narrowing succeeds only when the result is exactly one code unit. UTF validation (scalar range, surrogate rejection) is owned by UTFCodec — an invalid source scalar surfaces as STATUS.

Char-width WIDENING (char8 INTO char16/char32, char16 INTO char32) is lossless and lives in PrimitiveConversions; only the fallible narrowing direction needs UTFCodec, so this host depends on UTFCodec and orders AFTER it (later than the early PrimitiveConversions / CharConverter hosts).

kernel/src/CharWidthConverter.ev:27

CLASS NumberConverter

CONVERSIONS host for number↔text conversions The AS/INTO surface over the kernel's numeric conversions, and their implementation — the digit/parse logic lives here in the operators (and their shared helpers), not delegated elsewhere.

integer/boolean INTO String — lossless, total (every value has a text form) String INTO number — lossless, fallible (parse; bad text → FAILURE)

Scoped to depend on only String + DynamicString (NOT FloatFormat), so this host orders EARLY — before foundational classes like Array — letting them use x INTO String. The float→String path is the one piece that needs the Ryu engine (FloatFormat); it lives in the separate FloatConverter host, which orders later. Float PARSING (String→float) stays here — it uses the strtod/ strtof native shim, not FloatFormat (FOREIGN scope is per-file, §17, so the parse binds are redeclared below).

kernel/src/NumberConverter.ev:26

CLASS FloatConverter

CONVERSIONS host for float→String (V1 Part F piece 4).

Split out of NumberConverter so that NumberConverter (integer/boolean→String + all String→number parsing) depends only on String/DynamicString and can be ordered EARLY — before foundational classes like Array — letting them use x INTO String. The float→decimal path is the one piece that needs the Ryu engine (FloatFormat), so it lives here and orders after FloatFormat; its users (Formatter, Math, MeasuringTimer) are all later classes.

float32 INTO String — lossless, total float64 INTO String — lossless, total

The float→bits reinterpret crosses the FOREIGN boundary (no pure-Envzn expression); everything past that is integer-only arithmetic in FloatFormat.

kernel/src/FloatConverter.ev:28

CLASS FloatParseConverter

kernel/src/FloatParseConverter.ev:21

CLASS FloatParse

kernel/src/FloatParse.ev:14

Methods

METHOD parseF64(REFERENCE String s) RETURNS | float64
METHOD parseF32(REFERENCE String s) RETURNS | float32

CLASS FloatParseResult

kernel/src/FloatParseResult.ev:27

Fields

Constructors

INIT()

Methods

MODIFY METHOD pushDigit64(uint32 d) RETURNS void

Accumulate one decimal digit into the uint64 fast-path significand, flipping sig64Ovf the moment sig64·10+d would exceed uint64.

METHOD isValid() RETURNS boolean

Whether the last parse() produced a well-formed value (the FloatParse surface reads this to choose the success vs FAILURE arm).

METHOD charEqCI(char32 c, char32 lower) RETURNS boolean

ASCII case-insensitive char compare (lower is the lowercase letter).

METHOD isInfinityWord(REFERENCE String s, int64 start, int64 endp) RETURNS boolean

TRUE iff s[start, endp) spells "inf" or "infinity" (case-insensitive).

METHOD computeBitsN(int32 mantBits, int32 eMin, int32 biasAdd, int32 maxBiased, int32 signPos) RETURNS uint64

L4 — the exact float driver, generalized over target width. Produce the correctly-rounded IEEE-754 bit pattern for the parsed (significand, exp10, sign) via big-integer AlgorithmM: form V = sig·10^exp10 = N/D, scale to [2^mantBits, 2^(mantBits+1)) tracking the binary exponent e2 (subnormal floor at eMin), extract the mantissa by binary long-division, round-to- nearest-even (with the truncated sticky bit), then handle rounding overflow and the subnormal/normal/inf encodings. Parameters: float64 → (52, -1074, 1075, 2047, 63) float32 → (23, -149, 150, 255, 31) where biasAdd = mantBits + exponent-bias, maxBiased = 2^expBits − 1.

METHOD computeBits() RETURNS uint64

Correctly-rounded IEEE-754 binary64 / binary32 bit patterns (exact path).

METHOD computeBits32() RETURNS uint64
METHOD clingerEligible() RETURNS boolean

TRUE iff the Clinger fast path applies to the parsed value at float64.

METHOD eiselLemire64() RETURNS | uint64

Eisel-Lemire tier-2 fast path — value = sig64 · 10^exp10 with sig64 known exact (fits uint64). Returns the float64 MAGNITUDE bit pattern on a confidently-correct rounding, or FAILURE to fall back to the exact path. A faithful port of Rust dec2flt lemire.rs, validated in Python (0 mismatches over ~200k cases). It NEVER commits a wrong result — the only outcomes are the correctly-rounded value or a fall-back signal.

METHOD toFloat64() RETURNS float64

The parsed value as a real float64. Tiered: (L8) Clinger for the common exactly-representable case; then Eisel-Lemire for the wider fits-in-uint64 case; then the exact bignum computeBits() for everything else / EL fall-back.

METHOD clingerEligible32() RETURNS boolean

Clinger applies at float32 when sig ≤ 2^24 and |exp10| ≤ 10 (10^10 = 5^10· 2^10, 5^10 < 2^24, so it is an exact float32).

METHOD toFloat32() RETURNS float32
MODIFY METHOD parse(REFERENCE String s) RETURNS void

Parse s into this result's fields. Sets valid = FALSE (and stops) on any character outside the strict finite-number grammar or on non-consumption.

CLASS FloatBigInt

kernel/src/FloatBigInt.ev:25

Fields

Constructors

INIT()

Methods

METHOD isZero() RETURNS boolean
MODIFY METHOD setSmall(uint64 v) RETURNS void

Set to a value that fits in 64 bits.

MODIFY METHOD mulAddSmall(uint32 mul, uint32 add) RETURNS void

self := self * mul + add (mul, add each fit in 32 bits; mul >= 1).

METHOD pow10Small(int32 e) RETURNS uint32

10^e for e in 0..8 (fits uint32; e<=8 keeps it under 10^9 < 2^32).

MODIFY METHOD mulPow10(int32 k) RETURNS void

self := self * 10^k (k >= 0). Chunked by 10^9 per pass (the largest power of ten a uint32 multiplier holds), then a final <10^9 remainder.

MODIFY METHOD setPow10(int32 k) RETURNS void

self := 10^k (k >= 0). The denominator-construction path.

MODIFY METHOD shiftLeftBits(int32 n) RETURNS void

self := self * 2^n

MODIFY METHOD appendLimbHi(uint32 v) RETURNS void

Append a limb as the new most-significant limb (internal builder for cloning self into a scratch value without passing SELF).

METHOD bitLength() RETURNS int32

Number of significant bits (0 for zero). floor(log2(self)) + 1.

METHOD cloneBig() RETURNS FloatBigInt

A fresh independent copy of self (reads own limbs, builds the copy through its own appendLimbHi — never passes SELF).

METHOD cmp(REFERENCE FloatBigInt other) RETURNS int32

Ordering vs another big int: -1 (self < other), 0 (equal), 1 (self > other).

MODIFY METHOD addBig(REFERENCE FloatBigInt other) RETURNS void

self := self + other

MODIFY METHOD subBig(REFERENCE FloatBigInt other) RETURNS void

self := self - other (precondition: self >= other)

CLASS FloatToDecimal

kernel/src/FloatToDecimal.ev:22

Methods

METHOD float64Parts(float64 v) RETURNS | DecimalParts
METHOD float32Parts(float32 v) RETURNS | DecimalParts

CLASS NumberToDecimal

kernel/src/NumberToDecimal.ev:15

Methods

METHOD numberParts(number v) RETURNS | DecimalParts

number → decimal parts. An INTEGER subtype is exact (coefficient = store.i, exponent 0); a FLOAT subtype takes the Ryu shortest-decimal route (and so inherits its only failure mode — a non-finite float).

METHOD int128Parts(int128 v) RETURNS | DecimalParts

int128 → decimal parts (Bug #269). Exact when the value fits decimal128's 34 significant digits (|v| < 10^34); a wider value FAILS rather than silently rounding — the exact-or-fail INTO contract that keeps decimal128 from ever losing precision. coefficient = v directly (int128 → int128).

METHOD uint128Parts(uint128 v) RETURNS | DecimalParts

uint128 → decimal parts (Bug #269). Exact when < 10^34; wider FAILS. The magnitude (< 2^113, so it fits a positive int128) is reassembled into the signed coefficient from its 64-bit halves — there is no uint128→int128 operator, and the low half is halved-then-doubled so the int64 reinterpret never goes negative (the DecimalCodec.bidToParts shape).

METHOD complexParts(complex v) RETURNS | DecimalParts

complex → decimal parts. A complex projects onto a real decimal128 only when its imaginary part is zero (there is no ordering or real embedding of a genuinely-complex value); otherwise FAILURE. The real part is a number, so it routes through numberParts.

CLASS CharClassifier

kernel/src/CharClassifier.ev:17

Methods

METHOD isAlpha(char32 c) RETURNS boolean
METHOD isDigit(char32 c) RETURNS boolean
METHOD isAlnum(char32 c) RETURNS boolean
METHOD isSpace(char32 c) RETURNS boolean
METHOD isUpper(char32 c) RETURNS boolean
METHOD isLower(char32 c) RETURNS boolean

STRUCT FloatingDecimal32

kernel/src/structs.ev:57

Fields

STRUCT FloatingDecimal64

FloatingDecimal64 / FloatingDecimal32 — the shortest-decimal carriers produced by FloatFormat's d2d / f2d core methods. Each holds the decimal mantissa as an unsigned integer plus the decimal exponent (so the represented value is mantissa * 10^exponent). Reserved exponent sentinels in the 0x7FFFxxxx range encode IEEE-754 special cases (nan / ±inf / -0) — see FloatFormat.float64toDecimal.

kernel/src/structs.ev:52

Fields

STRUCT Pow5Entry

Pow5Entry — one 128-bit fixed-point pow5 magic constant, split into its low and high 64-bit halves. Used by FloatFormat's small-table Ryu path: DOUBLE_POW5_SPLIT2 and DOUBLE_POW5_INV_SPLIT2 are sequences of these, and double_computePow5 / double_computeInvPow5 build one on demand for arbitrary indices. Order matches Ryu's uint64_t mul[2] convention — .lo is the low half, .hi is the high half.

kernel/src/structs.ev:78

Fields

Randomness

CLASS CasualRandom

IMPLEMENTS Random

A fast, OS-seeded Random for games, sampling, jitter, and other non-reproducible, non-security uses. Seeds an xoshiro256** engine once at construction from operating-system entropy; thereafter it is a pure (fast) PRNG. NOT reproducible (the seed is fresh each time) and NOT for secrets — use SecureRandom for tokens/keys.

Thread-affine (see the Random interface note): not a SHARED CLASS.

kernel/src/CasualRandom.ev:26

Constructors

INIT()

Methods

MODIFY METHOD nextInt(int64 bound) RETURNS int64
MODIFY METHOD nextUInt128() RETURNS uint128
MODIFY METHOD nextFloat() RETURNS float64
MODIFY METHOD nextBoolean() RETURNS boolean

CLASS SecureRandom

IMPLEMENTS Random

A cryptographically-secure Random drawing fresh operating-system entropy on every call (getentropy via the native shim). For tokens, session identifiers, salts, and keys. Not a PRNG: there is no seed and no reproducibility. INIT throws RandomError if the OS entropy source is unavailable.

Thread-affine (see the Random interface note): not a SHARED CLASS.

kernel/src/SecureRandom.ev:23

Constructors

INIT()

Methods

METHOD boundedSecure(uint64 bound) RETURNS uint64

Uniform unsigned in [0, bound) over fresh entropy — the same 128-bit Lemire rejection as the PRNG path, but each draw pulls new OS entropy rather than advancing a seeded engine. Assumes bound >= 1.

MODIFY METHOD nextInt(int64 bound) RETURNS int64

Uniform in [0, bound) over fresh entropy. bound <= 0 throws.

The former nextLong; see Xoshiro256.nextInt for why the two collapsed.

A checked r AS int64 was tried here and its ELSE branch had nothing to put in it, because the draw cannot reach the upper half of uint64: bound > 0 by the guard, so b <= INT64_MAX, and boundedSecure returns Lemire-uniform in [0, b) — the value is bounded BY an int64 and is therefore always one. An UNREACHABLE! in that branch would be honest but would still be a branch written for a statically-impossible case, which is what the unchecked, NAMED helper exists to avoid. toInt64 states the crossing in one line and is exact for every value this can produce.

MODIFY METHOD nextUInt128() RETURNS uint128
MODIFY METHOD nextFloat() RETURNS float64
MODIFY METHOD nextBoolean() RETURNS boolean

CLASS SeededRandom

IMPLEMENTS Random

A deterministic Random seeded from a developer-supplied int64. Same seed → same sequence, across runs and platforms (xoshiro256** + splitmix64 are fixed algorithms). For reproducible simulations, tests, and property-based testing.

Thread-affine (see the Random interface note): not a SHARED CLASS, so it cannot be shared across threads; move it if a task needs sole ownership.

kernel/src/SeededRandom.ev:19

Constructors

INIT(int64 seed)

Methods

MODIFY METHOD nextInt(int64 bound) RETURNS int64
MODIFY METHOD nextUInt128() RETURNS uint128
MODIFY METHOD nextFloat() RETURNS float64
MODIFY METHOD nextBoolean() RETURNS boolean

INTERFACE Shuffleable

The interface a shuffleable collection implements. shuffle(rng) reorders the collection in place into a uniformly-random permutation, drawing index choices from the supplied Shuffler. Array[T] implements it (Fisher-Yates); any future ordered collection can too.

Same element bound as Array: T is a Cloneable class or a non-boolean primitive (the swap clones / moves elements through the backing storage).

kernel/src/Shuffleable.ev:20

Methods

MODIFY METHOD shuffle(MUTABLE REFERENCE Shuffler rng) RETURNS void

Reorder in place into a uniformly-random permutation, drawing from rng. MODIFY — mutates the collection; rng is a MUTABLE REFERENCE because every draw advances its state.

INTERFACE Random

Random — the full random / pseudo-random surface, extending Shuffler with wider-range, 128-bit, float, and boolean draws. Implemented by CasualRandom (fast, OS-seeded), SeededRandom (deterministic from a developer seed), and SecureRandom (OS entropy). A Random instance is thread-affine: it is not a SHARED CLASS, so it cannot be shared across a thread boundary — a non-owning capture into a PARALLEL body is rejected, while a sole-ownership move is permitted and data-race-safe.

kernel/src/interfaces.ev:771

Methods

MODIFY METHOD nextUInt128() RETURNS uint128

A full-width 128-bit random value (two engine draws).

MODIFY METHOD nextFloat() RETURNS float64

Uniform random float64 in [0, 1) (53-bit mantissa).

MODIFY METHOD nextBoolean() RETURNS boolean

Uniform random boolean (the engine's top bit).

INTERFACE Shuffler

Shuffler — the narrow random-source capability: a single bounded integer draw. Consumers that only need to pick an index (e.g. Array.shuffle) depend on this, not the full Random surface.

kernel/src/interfaces.ev:755

Methods

MODIFY METHOD nextInt(int64 bound) RETURNS int64

Uniform random integer in [0, bound). bound <= 0 throws RandomError. MODIFY because drawing advances generator state.