Types

EZ is a statically-typed language with strong typing. Types are checked at compile time, and there is no implicit type coercion.

Primitive Types

int

Integer numbers (whole numbers):

temp age int = 25
temp count int = -100
temp zero int = 0

float

Floating-point numbers (decimals):

temp pi float = 3.14159
temp temperature float = -40.5
temp percentage float = 0.85

string

Text values:

temp name string = "Alice"
temp empty string = ""
temp sentence string = "Hello, World!"

char

Single characters:

temp letter char = 'A'
temp digit char = '5'
temp newline char = '\n'

bool

Boolean values (can only be true or false):

temp isActive bool = true
temp hasError bool = false

byte

A single unsigned 8-bit value representing raw binary data (0-255):

temp myByte byte = 255
temp zeroByte byte = 0
temp asciiA byte = 65  // ASCII value for 'A'

Sized Integers

EZ provides explicitly sized integers for when you need precise control:

Signed Integers

Can hold positive and negative values:

TypeSizeRange
i88 bits-128 to 127
i1616 bits-32,768 to 32,767
i3232 bits-2.1 billion to 2.1 billion
i6464 bits-9.2 quintillion to 9.2 quintillion
i128128 bitsVery large range
i256256 bitsExtremely large range
temp small i8 = -128
temp medium i32 = -100000
temp large i64 = -9223372036854775808

Unsigned Integers

Only positive values (and zero):

TypeSizeRange
u88 bits0 to 255
u1616 bits0 to 65,535
u3232 bits0 to 4.2 billion
u6464 bits0 to 18.4 quintillion
u128128 bitsVery large range
u256256 bitsExtremely large range
uintPlatform-dependent0 to platform max
temp byte u8 = 255
temp word u32 = 4294967295
temp big u64 = 18446744073709551615

Arrays

Ordered collections of values of the same type:

Dynamic Arrays

temp numbers [int] = {1, 2, 3, 4, 5}
temp names [string] = {"Alice", "Bob"}
temp empty [float] = {}

Fixed-Size Arrays

Must be declared with const:

const DAYS [string, 7] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}
const MATRIX [int, 9] = {1, 2, 3, 4, 5, 6, 7, 8, 9}

See @arrays for array manipulation functions.

Byte Arrays

Byte arrays are specialized arrays for binary data, buffers, or raw file contents.

Dynamic Byte Arrays

temp buffer [byte] = {0, 128, 255}
temp empty [byte] = {}
temp fileData [byte] = io.read_bytes("image.png")

Fixed-Size Byte Arrays

temp header [byte, 4] = {137, 80, 78, 71}  // PNG magic bytes
temp smallBuffer [byte, 16] = {0, 16}      // 16 zero-initialized bytes

Note: Byte values can be written as decimal (0-255) or hexadecimal (0x00-0xFF). Negative values are never valid for bytes.

Note: Fixed-size byte arrays require careful memory management and bounds awareness. For most use cases, the dynamic [byte] type is recommended as it handles resizing automatically and reduces the risk of buffer-related errors.

TypeSizeRange
byte8 bits0-255
[byte]dynamicN/A

See @bytes for byte manipulation functions.

Multi-dimensional Arrays

EZ supports multi-dimensional arrays (matrices) through nested array syntax.

Note: Fixed-size multi-dimensional arrays are not currently supported. Use temp for all multi-dimensional array declarations.

Syntax

[[type]]    // 2D array (matrix)
[[[type]]]  // 3D array

EZ supports any number of dimensions (tested up to 10D).

Declaration

// 2D array (3x2 matrix)
temp matrix [[int]] = {{1, 2}, {3, 4}, {5, 6}}

// 2D string array
temp grid [[string]] = {{"a", "b", "c"}, {"d", "e", "f"}}

// 3D array
temp cube [[[int]]] = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}}

// Empty 2D array
temp empty [[int]] = {}

Accessing Elements

temp matrix [[int]] = {{1, 2, 3}, {4, 5, 6}}

temp row [int] = matrix[0]       // {1, 2, 3}
temp value int = matrix[1][2]    // 6
matrix[0][1] = 99                // modify element

Iteration

temp matrix [[int]] = {{1, 2}, {3, 4}, {5, 6}}

// Iterate over rows
for_each row in matrix {
    std.println(row)
}

// Iterate over all elements
for_each row in matrix {
    for_each value in row {
        std.println(value)
    }
}

Jagged Arrays

Inner arrays can have different lengths:

temp jagged [[int]] = {{1, 2, 3}, {4, 5}, {6}}
// jagged[0] has 3 elements
// jagged[1] has 2 elements
// jagged[2] has 1 element

Maps

Key-value pairs:

temp ages map = {
    {"Alice", 25},
    {"Bob", 30}
}

// With explicit types
temp scores map[string:int] = {"math": 95, "english": 88}

See @maps for map manipulation functions.

Structs

User-defined composite types:

const Person struct {
    name string
    age int
}

temp p Person = Person{name: "Alice", age: 30}

See Structs for more details.

Enums

Named constants:

const Status enum {
    PENDING
    ACTIVE
    DONE
}

temp s int = Status.ACTIVE

See Enums for more details.

Type Checking

EZ enforces types at compile time:

temp x int = 10
// x = "hello"  // Error! Cannot assign string to int

temp name string = "Alice"
// temp age int = name  // Error! Type mismatch

Type Conversion

Explicit conversion between compatible types:

int()

temp s string = "42"
temp n int = int(s)  // 42

temp f float = 3.14
temp i int = int(f)  // 3 (truncates)

float()

temp s string = "3.14"
temp f float = float(s)  // 3.14

temp i int = 42
temp f2 float = float(i)  // 42.0

string()

temp n int = 42
temp s string = string(n)  // "42"

temp f float = 3.14
temp s2 string = string(f)  // "3.14"

temp b bool = true
temp s3 string = string(b)  // "true"

byte()

Explicit conversion to the byte type (unsigned 8-bit integer, range 0-255).

temp n int = 65
temp b byte = byte(n)  // 65

temp f float = 97.8
temp b2 byte = byte(f)  // 97 (truncates)

temp s string = "200"
temp b3 byte = byte(s)  // 200

temp c char = 'A'
temp b4 byte = byte(c)  // 65 (ASCII value)

char()

Converts an integer (ASCII/Unicode code point) to a character.

temp x int = 65
temp y char = char(x)  // 'A' (ASCII value 65)
println(y)             // Output: A

temp emoji int = 128512
temp face char = char(emoji)  // Unicode smiley

typeof()

Get the type of a value at runtime:

temp x int = 42
std.println(typeof(x))  // "int"

temp arr [string] = {"a", "b"}
std.println(typeof(arr))  // "array"

temp m map = {{"key", "value"}}
std.println(typeof(m))  // "map"

Default Values

Uninitialized temp variables get default values:

TypeDefault
int0
float0.0
string""
char'\0'
boolfalse
byte0
[T]{}
[byte]{}
temp count int      // 0
temp price float    // 0.0
temp name string    // ""
temp flag bool      // false
temp items [int]    // {}

Numeric Separators

Use underscores for readability:

temp million int = 1_000_000
temp binary int = 0b1010_1010
temp hex int = 0xFF_FF
temp pi float = 3.141_592_653

Type Inference

EZ does not support type inference. Types must always be declared:

// This is required:
temp x int = 10

// This won't work:
// temp x = 10  // Error! Missing type

Why require explicit types? It makes code clearer and easier to read. You always know exactly what type a variable is without having to guess or trace through the code.

Example Program

import @std

do main() {
    // Primitives
    temp count int = 0
    temp price float = 19.99
    temp name string = "Product"
    temp inStock bool = true

    // Sized integers
    temp smallNum i8 = 127
    temp largeNum u64 = 1_000_000_000_000

    // Arrays
    temp scores [int] = {85, 92, 78, 95}
    const GRADES [string, 5] = {"A", "B", "C", "D", "F"}

    // Type checking
    std.println("count type:", typeof(count))   // int
    std.println("price type:", typeof(price))   // float
    std.println("scores type:", typeof(scores)) // array

    // Type conversion
    temp priceStr string = string(price)
    temp scoreSum int = 0
    for_each s in scores {
        scoreSum += s
    }
    temp average float = float(scoreSum) / float(len(scores))

    std.println("Average score:", average)
}