# Built-Ins

This document defines the currently implemented Masterbelt built-in types, values, functions, and operators.

The built-in set is intentionally minimal at this stage. Future built-in additions must extend this document before or together with implementation changes.

## Built-In Types

The implemented built-in primitive types are:

- `null`: the type of the null literal.
- `bool`: the type of boolean literals.
- `string`: the type of string literals.

The implemented built-in numeric types are:

| Masterbelt | Signedness | Width                                  |
|------------|------------|----------------------------------------|
| `int`      | signed     | native (host language's natural width) |
| `int8`     | signed     | 8 bits                                 |
| `int16`    | signed     | 16 bits                                |
| `int32`    | signed     | 32 bits                                |
| `int64`    | signed     | 64 bits                                |
| `uint`     | unsigned   | native (host language's natural width) |
| `uint8`    | unsigned   | 8 bits                                 |
| `uint16`   | unsigned   | 16 bits                                |
| `uint32`   | unsigned   | 32 bits                                |
| `uint64`   | unsigned   | 64 bits                                |

The default type of an integer literal that has no type annotation, pushdown target, or cast prefix is `int`.

Built-in type names are written in lowercase.

### Numeric Type Classes

The language distinguishes three internal numeric type classes. These classes are not types in their own right: they cannot appear in a type expression position and they do not name a binding. They exist to let the checker describe operations that require a numeric operand or target.

- `numeric`: the union of every built-in numeric type listed above.
- `snumeric`: the union of every signed built-in numeric type (`int`, `int8`, `int16`, `int32`, `int64`).
- `unumeric`: the union of every unsigned built-in numeric type (`uint`, `uint8`, `uint16`, `uint32`, `uint64`).

An alias whose target resolves to a numeric type belongs to the same class as the resolved target.

The implemented built-in generic type constructors are:

- `list<T>`: a homogeneous sequence of values of element type `T`.
- `map<K, V>`: an associative mapping from key type `K` to value type `V`.

Generic type constructors take their type arguments between `<` and `>` separated by `,`. Each type argument is itself a type expression.

The number of type arguments must match the constructor:

- `list` takes exactly one type argument.
- `map` takes exactly two type arguments.

Built-in type names and generic type constructor names are available only in type expression positions. They do not introduce value bindings.

## Built-In Product Types

`Error` is the built-in product type used to represent a recoverable failure produced by a `failable` function.

```mst
type Error = { message: string }
```

The `Error` name is reserved at the type binding space: declaring a type, enum, or master named `Error` is a type checking error reported through the standard reserved-name diagnostic. The only surface use of `Error` is as the argument to `fail` (`fail Error { message: "..." }`); it does not appear in function return types or in user-visible unions. See [syntax.md](syntax.md#failable-handling) and [semantics.md](semantics.md#failable-handling) for the integration with `fail`.

## Built-In Values

The implemented built-in values are the literal words `null`, `true`, and `false`.

## Built-In Functions and Operators

The implemented built-in free functions are:

- `fn range(start: int, end: int): list<int>` — yields the integers `start, start + 1, ..., end - 1` in ascending order. When `start >= end` the result is empty. The function is total: every input produces a value of `list<int>` without effects.

`range` is exposed as a value binding in the same module-scope name space as user-declared functions. The name `range` cannot be redeclared (a user declaration of `const range = ...` or `fn range(...)` is rejected through the [reserved built-in names](#reserved-built-in-names) rule extended to value-position built-ins).

Although `range(start, end)` returns a `list<int>` at the type level, every supported codegen target recognises a `for i in range(a, b) { ... }` source form and emits a counted loop instead of materializing the list (see [codegen/golang.md](../codegen/golang.md), [codegen/typescript.md](../codegen/typescript.md), and [codegen/csharp.md](../codegen/csharp.md)). The optimization is a target-emission concern; the language semantics treat `range` as returning a regular list.

### Operator Methods

Every unary or binary operator in [syntax.md](syntax.md) is defined as a method on the operand (for unary) or the left operand (for binary). The surface form `a OP b` is equivalent to the method call `a.METHOD(b)`; the unary form `OP a` is equivalent to `a.METHOD()`.

The complete operator-to-method mapping is:

| Surface | Method   | Arity  |
|---------|----------|--------|
| `!a`    | `not`    | unary  |
| `+a`    | `plus`   | unary  |
| `-a`    | `minus`  | unary  |
| `a + b` | `add`    | binary |
| `a - b` | `sub`    | binary |
| `a * b` | `mul`    | binary |
| `a / b` | `div`    | binary |
| `a % b` | `mod`    | binary |
| `a == b`| `eql`    | binary |
| `a != b`| `neq`    | binary |
| `a < b` | `lt`     | binary |
| `a <= b`| `lteq`   | binary |
| `a > b` | `gt`     | binary |
| `a >= b`| `gteq`   | binary |
| `a & b` | `and`    | binary |
| `a | b` | `or`     | binary |
| `a ^ b` | `xor`    | binary |
| `a << b`| `lshift` | binary |
| `a >> b`| `rshift` | binary |

The method must exist on the operand's type. Type checking of an operator expression follows the same overload resolution rules used for any other method call (see [types.md](types.md)). A user product type may declare any subset of these methods to opt that operator in; declaring a method whose name is not in this table is permitted but has no operator interpretation.

### Built-In Fields on Primitive and Generic Types

A few built-in types expose `readonly` fields that record a side-effect-free property of the value. The fields are not method calls — they participate in the regular `value.field` member-access form defined in [syntax.md](syntax.md) — so the surface form has no parentheses.

- `string.length: int` — the number of Unicode codepoints in the string (rune count, not byte count). The value matches Go's `utf8.RuneCountInString`; each codepoint counts as one regardless of its UTF-8 byte size.
- `list<T>.size: int` — the number of elements in the list.
- `map<K, V>.size: int` — the number of entries in the map.

The fields are not visible as free identifiers and cannot be redefined; they exist on every value of the corresponding type. An alias whose target resolves to one of these types inherits the same fields.

### Built-In Operator Methods on Primitive Types

For every built-in primitive type listed earlier in this document, the language exposes a fixed set of operator methods as if the type carried them in its method list. These methods are not visible as free identifiers and cannot be redefined; they exist only to make operator expressions on primitive operands type-check.

The intrinsic operator methods provided for each primitive type are:

- Every numeric type `N` (`int`, `int8`, ..., `uint64`):
  - `fn add(other: N): N`, `fn sub(other: N): N`, `fn mul(other: N): N`, `fn div(other: N): N`, `fn mod(other: N): N`
  - `fn eql(other: N): bool`, `fn neq(other: N): bool`, `fn lt(other: N): bool`, `fn lteq(other: N): bool`, `fn gt(other: N): bool`, `fn gteq(other: N): bool`
  - `fn and(other: N): N`, `fn or(other: N): N`, `fn xor(other: N): N`
  - `fn lshift(other: N): N`, `fn rshift(other: N): N`
  - `fn plus(): N` (unary `+`)
  - `fn minus(): N` (unary `-`; provided on signed numeric types only)
- `bool`:
  - `fn eql(other: bool): bool`, `fn neq(other: bool): bool`
  - `fn and(other: bool): bool`, `fn or(other: bool): bool`, `fn xor(other: bool): bool`
  - `fn not(): bool` (unary `!`)
- `string`:
  - `fn eql(other: string): bool`, `fn neq(other: string): bool`
  - `fn lt(other: string): bool`, `fn lteq(other: string): bool`, `fn gt(other: string): bool`, `fn gteq(other: string): bool`
  - `fn add(other: string): string` (concatenation)
- `null`:
  - `fn eql(other: null): bool`, `fn neq(other: null): bool`

The built-in generic constructors expose operator methods as well:

- `list<T>`:
  - `fn add(other: list<T>): list<T>` — element-wise concatenation; the result lists the receiver's elements followed by the argument's elements.
- `map<K, V>`:
  - `fn add(other: map<K, V>): map<K, V>` — last-wins merge; the result contains every entry of the receiver and every entry of the argument, with a key present in both taking the argument's value.

An alias whose target resolves to a primitive type or a built-in generic application inherits the corresponding intrinsic operator method set.

Operator method calls on primitive operands are emitted by every supported target as that target's native operator. Operator method calls on built-in generic operands (list, map) are emitted as a call into the target's runtime helper file; see each target's specification for the surface translation and runtime file emission.
