Before any user code is elaborated, an environment already exists: a collection of classes and values that the Definition presupposes and every program may use. This appendix records that standard environment, \(E_0\). It is not a complete library reference—for that, see the Nex Reference—but the part of the standard environment on which the semantics of earlier chapters depends.
B.1The Root and the Foundational Classes
Every class conforms ultimately to Any, the root of the class
hierarchy and the elaborated form of the type \(\mathsf{Any}\)
(Section 4.1). A user class may write inherit Any explicitly,
but does so implicitly in any case.
| Class | Routine | Signature | Meaning |
|---|---|---|---|
Any | to_string | \(\to\) String | user-facing rendering |
equals | Any \(\to\) Boolean | value equality, used by =; overridable | |
clone | \(\to\) Any | copy; collections override with deep copy |
Four further foundational classes are present in \(E_0\):
Function—the base class of all closures, and the elaborated form of the bare type \(\mathsf{Fun}\). It supplies the invocation protocolcall0,call1, …, by which a closure of any arity up to a fixed bound is applied.Cursor—the abstract iteration interface, with routinesstart,item,next, andat_end. Theacrossloop is defined in terms of this protocol (Appendix C).Comparable(deferred)—withcompare:Any\(\to\)Integer, returning a negative, zero, or positive ordering result, the basis of the comparison operators on ordered values.Hashable(deferred)—withhash\(\to\)Integer, returning a stable hash code, on which theMapandSetclasses rely.
B.2Scalar Classes
The lexically reserved type names denote classes of the standard environment. They
are Comparable and Hashable, and support the arithmetic
and comparison through which the operators of Section 2.6 are given
meaning.
| Type | Values | Notes |
|---|---|---|
Integer | 64-bit integers | literals of int form; default numeric type |
Real | floating-point | literals of real form; Real / Integer yields Real |
Char | characters | literals of char form |
Boolean | true, false | operand and result of the logical operators |
String | text | literals of string form; iterates by character |
The arithmetic operators apply to numeric operands, returning the wider type
(Section 4.4); an integer operand is admitted where a real is required, so
that total / count with total of type Real
yields a Real. The comparison operators apply to
Comparable operands through compare. Scalars are
immutable and unstored, so identity equality == coincides with value
equality = upon them (Section 5.3).
B.3Scalar Value Spaces
The previous section names the scalar classes; this one fixes the
value spaces they denote—their ranges, their numeric formats, and
the character model of Char and String. The
guiding decision of the Definition here is deliberate and worth stating plainly:
the numeric tower is pinned down exactly and identically on every
platform. The width of an integer, the behaviour of arithmetic on
overflow, the format of a floating-point number, and the result of division are
fixed by this Definition, not left to the host. Nex compiles to more than one
platform—the Java virtual machine and JavaScript at present—and an
earlier edition left the integer width and overflow behaviour host-defined, so
that the same program could denote different values on different back ends. That
latitude is withdrawn: a program’s arithmetic now means one thing on every
conforming implementation, and a program may rely on it. What remains
host-defined is only what is genuinely internal and unobservable through the
language—how a host stores a string, and the relation between a character
index and any underlying code unit—never the result of an arithmetic
operation.
Integer
Integer is a signed two’s-complement integer of exactly
64 bits, with range \([-2^{63},\, 2^{63}-1]\), on every
platform. Its arithmetic is checked: an operation
(+, -, *, unary
-, or ^) whose mathematical result lies outside that
range does not wrap, widen, or lose precision—it
raises an Arithmetic_Overflow exception. Integer
division / truncates toward zero, and the remainder
% is the truncated remainder, taking the sign of the
dividend, so that a = (a / b) * b + (a % b) holds whenever the
quotient exists: -7 / 2 is -3, -7 % 3 is
-1, and 7 % -3 is 1. (This is the
convention of C and Java, not the floored convention of Python.) Division and
remainder by zero have no integer
result and raise a Division_by_Zero exception; the
one division whose mathematical result lies outside the range,
\(-2^{63}\) / -1, raises Arithmetic_Overflow like
any other overflow. This
is uniform across back ends: where a host’s native integers are wider or
narrower than 64 bits, the implementation carries Integer as a
64-bit value and checks each operation, so that a program’s integer
arithmetic denotes the same value, or raises the same exception, everywhere.
The bitwise operations of Integer
(bitwise_left_shift and its companions) operate on the low
32 bits, with bit 0 the least significant; they are the one
part of the integer model that is not 64-bit, and they too behave identically on
every platform. An integer literal that does not fit the 64-bit range is rejected
(Section 2.2).
Real
Real is an IEEE 754 double-precision binary
floating-point value on every platform, in both its representation and
its arithmetic. A real literal denotes the nearest representable double, which may
not be the decimal written, so that 0.1 + 0.2 evaluates to
0.30000000000000004 and not to 0.3.
Division follows IEEE 754: 1.0 / 0.0 yields \(+\infty\),
-1.0 / 0.0 yields \(-\infty\), and 0.0 / 0.0 yields
NaN; none of these raises. The remainder % on reals
is likewise truncated (the fmod of C): the result has the sign of
the dividend, so -7.5 % 2.0 is -1.5, and a real
remainder by zero is NaN, not an exception. Every ordering
comparison (<, <=, >,
>=) against NaN is false, as IEEE 754
prescribes. The special values \(\pm\infty\) and
NaN are ordinary Real values, produced by arithmetic
and compared by the IEEE rules—NaN is unequal to every value
including itself—and the standard environment provides
is_nan, is_infinite, and is_finite to
inspect them.
This is the deliberate asymmetry of the numeric tower: integer division by zero raises, because there is no integer to return, while real division by zero is the IEEE value. It is the split drawn by most languages that carry both an integral and a binary floating type, and it is fixed here on every platform rather than left to the host.
Boolean and the character model
Boolean has exactly the two values true and
false.
A Char is a single Unicode code point. A
character constant may be written as a literal character, as one of the named
characters of Section 2.2, or as a decimal code point after #,
so that #65 denotes the same character as #A. A
String is a finite sequence of characters; its length
is the number of characters, it iterates character by character
(Section 2.8), and char_at and chars address it by
character position. The encoding of a string is exposed only through
to_bytes, which yields the UTF-8 bytes of the
string as integers in the range \([0, 255]\), on every platform; the internal
representation by which a host stores a string, and the relation between a
character index and any underlying code-unit index, are host-defined and not
observable except through to_bytes. A double-quoted string literal
interprets the standard backslash escapes (Section 2.2)—so
"\n" is a newline and \u{h} a code point—
while a single-quoted literal is raw; a control character may also be written
with its character constant or obtained from the standard environment.
| Type | Guaranteed by the Definition | Host-defined |
|---|---|---|
Integer | signed 64-bit two’s-complement, range \([-2^{63}, 2^{63}-1]\), on every platform; checked—overflow and division by zero raise; bitwise on low 32 bits | — |
Real | IEEE 754 double, in representation and arithmetic; division by zero yields \(\pm\infty\) / NaN per IEEE | — |
Char | a Unicode code point | internal representation |
String | sequence of characters; length in characters; to_bytes is UTF-8 in \([0,255]\) | internal encoding; character-to-code-unit mapping |
B.4Collection Classes
Three generic collection classes are present in \(E_0\), each a
Cursor source so that across may traverse it.
Array[T]
An ordered, growable sequence. The display [e₁, …, eₙ] is a
derived form constructing an Array (Appendix C). Representative
routines: get(i) \(\to\) T, add(x) to
append, length \(\to\) Integer.
Map[K, V]
An association of keys to values. The display
{k₁: v₁, …} is a derived form; {} is the empty map.
Representative routines: get(k) \(\to\) V,
put(k, v), iteration yielding [key, value] pairs.
Set[T]
An unordered collection of distinct values. The display
#{e₁, …} is a derived form; #{} is the empty set, which
must be written with the explicit set-display syntax to distinguish it from the
empty map. The constructor from_array builds a set from an array,
discarding duplicates; the routines union, intersection,
difference, contains, and size provide the
usual set algebra.
B.5Concurrency Classes
The classes underlying Chapter 6 are part of the standard environment.
| Class | Routine | Meaning |
|---|---|---|
Task[T] | await | block until done; yield result of type T |
await(ms) | timed await; nil on timeout | |
is_done, is_cancelled | completion and cancellation state | |
cancel | request cancellation | |
await_any, await_all | (class methods) wait on a collection of tasks | |
Channel[T] | send(v), receive | blocking communication (Section 6.2) |
try_send, try_receive | non-blocking variants used by select | |
with_capacity(n) | (constructor) a buffered channel | |
close, is_closed, size, capacity | channel state |
A spawn whose block assigns result of type \(T\)
yields a Task[T]; one that does not yields a plain
Task.
B.6Built-in Values and Effects
A handful of values are bound in the top-level bindings of \(E_0\). Chief
among them is print, which renders its argument (via
to_string) and writes it to the standard output—a host effect,
and the principal observable behaviour of many programs. The Console
class provides finer output control, including new_line. A line
break in output may be written as the \n escape in a double-quoted
string (Section 2.2), or produced with Console.new_line or the
character constant #newline.
The exception values raised by the language itself—on a nil
dereference, a failed contract, a failed runtime argument check, an out-of-range
collection access—are also part of the environment, and are the values a
rescue block receives in exception (Section 5.7).