Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Types and values

NEX currently has four first-class value categories:

  • int
  • str
  • bool
  • array<int> / array<str>

Variables are declared with an explicit type and keep that type for their lifetime. That makes NEX an explicitly typed language core with strong runtime type checks. A variable is not just a name; it is a name bound to a value of a particular type, and later assignments must respect that binding.

This design keeps the language small while still illustrating an important concept in language implementation: values have kinds, and the interpreter must enforce the rules that say which operations are valid for which kinds of values.

Integers

int values are arbitrary-precision whole numbers. In other words, they are not limited to a fixed 32-bit or 64-bit range.

int a = 10;
int b = -3;
print(a + b);

Integers support the usual arithmetic operators. In the current core, -, *, /, and % are integer-only operators, while + also has a second meaning for string concatenation. That split is intentional: it keeps the operator set small while showing that the same surface symbol can have different meanings depending on operand types.

Strings

str values are double-quoted text literals.

str left = "he";
str right = "llo";
print(left + right);

Strings can be concatenated with +, compared for equality, and also compared with the ordering operators. This is a useful teaching choice because it shows that not all comparisons are numeric: some values can be ordered lexicographically.

Booleans

bool values are either true or false.

bool ready = true;

if (!ready) {
    print("wait");
} else {
    print("go");
}

Conditions in if, while, and for must evaluate to bool. NEX does not use implicit truthiness. In other words, NEX does not silently treat integers or strings as conditions. A condition must really be boolean, which keeps the rules easy to explain and easy to check.

Arrays

NEX also supports typed arrays of integers and strings.

array<int> numbers;
array<str> names;

Array creation is currently always empty. Arrays therefore use declaration syntax without an initializer expression. This makes array declarations a small special case in the current language: unlike scalar declarations, they create a valid value directly without needing an explicit initializer.

Supported array types are:

  • array<int>
  • array<str>

Elements are accessed with indexing syntax:

int first = numbers[0];
str last = names[-1];

Negative indices count from the back of the array. For example, arr[-1] refers to the last element and arr[-2] to the second-to-last element.

Elements can also be updated with indexed assignment:

numbers[0] = 10;
names[-1] = "Ada";

Arrays also support resizing, resetting, and length queries:

numbers.resize(10);
numbers.reset();
int count = numbers.length();

These method-style calls are surface syntax for ordinary function calls. In other words, numbers.resize(10) behaves like resize(numbers, 10), and numbers.length() behaves like length(numbers). Likewise, numbers.reset() behaves like reset(numbers).

Variable declarations

Scalar variables are introduced with an explicit type, a name, and an initializer.

int count = 0;
str name = "nex";
bool ok = true;

The initializer expression must evaluate to a value that matches the declared type. Redeclaring a variable in the same scope is a runtime error. Together, these rules make declarations do two things at once: they create a new binding and they immediately give it a valid initial value.

In other words, scalar declarations without an initializer are not part of the current language. Forms such as int x;, str name;, and bool ok; are rejected.

Array declarations are the exception:

array<int> arr;

They create an empty array value directly and do not use an initializer.

Assignment

Assignment updates an existing variable.

int x = 1;
x = x + 2;
print(x);

Compound assignment is also supported:

x += 2;
x *= 3;
x /= 2;
x -= 1;
x ^= 2;

These forms update the current value in place using the corresponding operator. For example, x += 2; behaves like x = x + 2;.

Assignments must preserve the declared variable type. Assigning a str to an int variable, for example, is a runtime error. Assigning to a variable name that has not been declared is also a runtime error. This means NEX does not allow assignment to invent new bindings implicitly; declarations and assignments have separate roles.

Arrays extend assignment with indexed element updates:

arr[0] = 10;
arr[-1] = 99;

Compound assignment works with indexed targets too:

arr[0] += 10;
arr[-1] *= 2;

This syntax updates a slot inside an existing array rather than rebinding the array variable itself.