Type system

ezc is dynamically typed. Every value carries its type at runtime and operators check types when popping.

Value types

typedescription
intarbitrary-precision integer (BigInt)
u8u256fixed-width unsigned (8/16/32/64/128/256-bit)
i8i256fixed-width signed
f16/f32/f64IEEE-754 floating point
strimmutable, interned UTF-8 string
binimmutable, interned byte buffer
listheterogeneous sequence of values
blockdeferred code (sequence of expressions)

Numeric families

Arithmetic operators only work between values in the same family:

  • Integer familyint
  • Unsigned familyu8, u16, ..., u256
  • Signed familyi8, i16, ..., i256
  • Float familyf16, f32, f64

Within a family, operations promote to the wider type:

3u8 4u32 +    # → 7u32 (u8 promoted)

Cross-family is an error — int, unsigned, signed, and float are separate families. Convert explicitly:

3 4u8 +        # error: int and u8 are different families
3 u8 4u8 +     # → 7u8  (convert 3 to u8 first)

int (BigInt) is its own family. Within int, all ops are exact:

2 100 ^        # 2^100 as int (no overflow)

Fixed-width types overflow (and error) when results exceed their range:

2u8 7u8 ^      # 128u8 — fits
2u8 8u8 ^      # error: overflow in u8

Truthiness

Used by ?, ??, & and the higher-order ops:

typefalsy when
numberzero
strempty
binempty
listempty
blocknever (always truthy)

Interning

str, bin, and int (BigInt) values are interned per engine instance. Equality is constant-time pointer comparison; copying is shared via Arc. This makes large strings and integers cheap to pass around.

Spans

Every value on the stack carries a source span — the byte range of the expression that pushed it. The DAP debugger and ariadne error reports use these spans to highlight the exact token responsible for a mismatch, not just a line number.