The language

Integer tensors, static shapes, rank 1 or 2, no control flow. Statements end at a newline (newlines inside (...) and [...] do not end a statement). # starts a comment.

input  A : i8[4, 8]                 # declare an input
const  W : i8[2, 2] = [[1, -2],     # declare a constant (shape and range are checked)
                       [3,  4]]
C = relu(A @ B + b)                 # define a value (names are single-assignment)
output C, D                         # one or more outputs (at least one is required)

Reserved words: input const output relu i8 i32.

Types

i8 or i32, with 1 or 2 positive dimensions: i8[4, 8], i32[6].

Expressions

@ binds tighter than +; both are left-associative; parentheses group.

Expression Rule Result
a @ b both rank 2, a is [M,K] and b is [K,N]; operand types may be i8 or i32 i32[M,N]
a + b same shape, or [M,N] + [N] in either order (the row is broadcast); i8 operands are widened i32, the larger shape
relu(a) any same shape and type as a

Semantics

All arithmetic is exact (widened); every op result must fit in i32, otherwise evaluation fails with RangeError, because tiny-gpu raises on overflow rather than wrapping. Inputs must fit their declared type.

Errors

The first problem stops compilation and is shown with the source line and a caret:

matmul_inner_mismatch.tiny:3:5: error: matmul inner dimensions differ: 8 vs 4 (i8[4,8] @ i8[4,4])
3 | C = A @ B
  |     ^^^^^

Every message is snapshot-tested (tests/golden/errors/).

Target legality (checked later, Phase 2)

Whether a program can run on a chip is not a language rule: tiny-tpu needs i8 matmul operands, and tiny-gpu has a memory budget. See docs/PLAN.md §3.3.