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.pyfrom the kernel sources. Do not edit by hand: change the generator, or the doc comments inkernel/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:
- Extend System (
CLASS Main EXTENDS System { ... }). - Provide a no-arg INIT.
- 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
String pathint32 fdLock gate
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
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 ──────────────────────────────────────────────────────────────────
- I/O failures (resolve, listFiles, makeDir, remove) surface as a
FAILURESTATUS in the method's multi-return — never throw. Per the kernel-wide error-handling convention, callers inspect the STATUS slot (IF p->resolve() THEN { ... $RETURNED ... } ELSE { ... $! }). - Pure-string operations (parent, basename, stem, extension, join, withExtension, toString) never fail — they manipulate the path String, not the filesystem.
- Existence checks (exists, isDirectory, isFile) return boolean; they do not fail on absence (that's the whole point of asking).
kernel/src/Path.ev:64
Fields
String value
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
BinaryMode binaryMode
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.
- HEX_SPACED — uppercase hex, byte pairs space-separated: "DE AD BE EF". The default.
- HEX_PACKED — uppercase hex, no separators: "DEADBEEF".
- BASE64 — standard base64 with
=padding: "3q2+7w==".
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
}
- DEBUG — assertions on, optimizations relaxed, debug output enabled.
- RELEASE — assertions stripped, optimizations on.
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).
- UTF8 — Unicode 8-bit variable-length, the standard text encoding for new files / network payloads / source code. The kernel's String class stores text as UTF-8 internally; UTF8 is the natural round-trip.
- UTF16LE — Unicode 16-bit little-endian (Windows native, .NET).
- UTF16BE — Unicode 16-bit big-endian (Java DataOutput, BMP).
- ASCII — 7-bit ASCII subset; bytes ≥ 0x80 fail decode.
- LATIN1 — ISO-8859-1; round-trips all byte values 0–255 to code points 0–255 without failure.
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).
- LITTLE — least-significant byte first. x86 / ARM64 native; the dominant choice for new wire formats.
- BIG — most-significant byte first. Network byte order (RFC 1700), JVM / .NET BinaryWriter big-endian methods, many older protocols.
- NATIVE — host CPU's native order; resolved at call site. Use only when the bytes will not leave the process — otherwise always specify LITTLE or BIG.
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
String name— The case name — "HIGH".int32 value— The case value — the ordinal (Envzn enums are ordinal).
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
boolean present— Has anything been parsed? When FALSE,Formatter.renderArguses its default-rendering path; when TRUE, the spec fields drive the formatted output.char32 fill— Single fill char. ASCII space (0x20) by default.char32 align— Alignment marker: '<' / '>' / '^', or 0x0 for "type default".char32 sign— Sign marker: '+' (force on positives) / '-' (default — only on negatives), or 0x0 (treated as '-').uint32 width— Minimum render width in code points. 0 means "no minimum".char32 typeLetter— Type letter: 'd' / 'x' / 'X' / 'o' / 'b' / 's', or 0x0 for "no type override (use the arg's default render)".char32 groupSep— Digit-group separator: ',' or '_', or 0x0 for "no grouping" (I.F.iii(d), DESIGN_QUEUE #7 Feature 2). Group size is fixed by the TYPE, not the spec: 3 for decimal, 4 for the radix letters x/X/o/b — nibble-aligned, so a grouped hex value reads by byte pairs. The separator is counted WITHIN the field, so it sits inside zero-padding.
STRUCT Identity
Field order is load-bearing: it is the synthesized-constructor argument order the IDENTITY lowering emits.
kernel/src/structs.ev:161
Fields
String name— Bare head of the type name — "Person", "Array", "int32".String home— Declaring module; primitives report "ENVZN".String fullname— Fully-parameterized spelling — "Array[Person]" (== name for non-generics).String modifier— The binding's declared qualifier — constant / mutable / reference / mutable reference / shared mutable reference; blank for a type subject.String type— The type kind — Primitive / Enum / Group / Struct / Class / Value Class / Hidden Class / Shared Class / Abstract Class / Interface / View Class.boolean generic— True when the type has type-parameters (Array[T], Comparable[T]).boolean internal— True when the type is declared INTERNAL (module-private, §17).String currentLens— The subject's static/declared type when viewed through an ancestor lens (differs from the concrete type); blank otherwise.String[] lenses— Ancestors in order: classes -> abstract classes, then implemented interfaces.boolean blittable— True when a flat byte-copy DUPLICATES the value — both copies then live, both destroyed (C++ trivially-copyable). FALSE for anything owning a heap buffer or handle: String, ByteBuffer, every container.boolean relocatable— True when a flat byte-copy MOVES the value — the source is abandoned with NO destructor run, so only one copy is ever live (trivially-relocatable). The WEAKER and far more common property: an owning handle is notblittable(two owners would double-free) but ISrelocatable, which is why a growing container may memcpy its slots yet must clone() when copied. The one shape that is neither is a SELF-REFERENTIAL value — the value-arrayT[N+], whose backing points into its own inline buffer, so byte-moving it would dangle: DynamicString, DynamicByteBuffer.EnumKind[] cases— For an ENUM type subject: one EnumKind (name + value) per case, in declaration order — the enum's "instances". Empty for every non-enum subject. The generic name<->value logic over this table lives in EnumReflection (EnumReflection.ev).
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.
- exitCode — the child process's exit status (0 on clean
exit, the value passed to
exit(N)otherwise, or -1 if the process was killed by a signal). - out — captured stdout, complete (all bytes drained before this struct is returned).
- err — captured stderr, same drain semantics as
out.
kernel/src/structs.ev:40
Fields
int32 exitCodeString outString err
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
int32 MAX_DIGITS
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
int32 MAX_LIMBS
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
uint32 mantissaint32 exponent
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
uint64 mantissaint32 exponent
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
uint64 louint64 hi
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.