# Цілі числа
Від одного байта до 128 байт. Знакові та беззнакові. Переповнення, насичення, затискання — все під контролем на рівні синтаксису.
Terra використовує тег-систему типів: розмір закодований прямо в імені тегу (число = байти).
| Тег (беззнаковий) | Розмір | Байти | Діапазон | Тег (знаковий) | Діапазон знаковий |
|---|---|---|---|---|---|
| /intbyte | 8-bit | 1 | 0 … 255 | /intbyte- | −128 … 127 |
| /int2 | 16-bit | 2 | 0 … 65,535 | /int2- | −32,768 … 32,767 |
| /int4 | 32-bit | 4 | 0 … ≈4.29×10⁹ | /int4- | ≈−2.14×10⁹ … ≈2.14×10⁹ |
| /int8 | 64-bit | 8 | 0 … ≈1.84×10¹⁹ | /int8- | ≈−9.22×10¹⁸ … ≈9.22×10¹⁸ |
| /int16 | 128-bit | 16 | 0 … ≈3.40×10³⁸ | /int16- | ≈−1.70×10³⁸ … ≈1.70×10³⁸ |
| /int64 | 512-bit | 64 | 0 … ≈1.34×10¹⁵⁴ | /int64- | ≈−6.70×10¹⁵³ … ≈6.70×10¹⁵³ |
| — | 1024-bit | 128 | — | /intlong | ≈−8.98×10³⁰⁷ … ≈8.98×10³⁰⁷ |
- робить тип знаковим.
Всі змінні оголошуються через ключове слово app. Теги — це не зарезервовані слова, а маркери для токенізатора.
! Оголошення змінної /intbyte app (/intbyte, /var) intbyte = 12 ::start:: intbyte + (12) /display(intbyte)
app (/intbyte, /const) MAX_VAL = 200
intbyte, Intbyte та INTBYTE — одна й та сама змінна.
Порядок виконання — суворо зліва направо. Немає пріоритету операторів. Дужки — єдиний спосіб змінити порядок. Всі операції — тільки всередині ::start::.
Стандартна поведінка при переповненні — wrap: 255 + 1 = 0 для /intbyte.
app (/intbyte, /var) intbyte = 12 intbyte + (5) ! помилка: немає ::start::
Модифікатори прив'язані до конкретної операції, а не до змінної. Дозволяють контролювати поведінку при переповненні.
| Модифікатор | Для операцій | Поведінка |
|---|---|---|
| &st | +, -, *, / | Насичення до максимуму типу (для /intbyte: 255) |
| &max(N) | +, -, *, / | Затиснути результат зверху: результат ≤ N |
| &min(N) | +, -, *, / | Затиснути результат знизу: результат ≥ N |
| &min(A)&max(B) | +, -, *, / | Затиснути в діапазоні [A, B] одночасно |
app (/intbyte, /var) intbyte = 200 ::start:: intbyte + (100)&st ! 200+100=300 → насичується до 255 /display(intbyte)
app (/intbyte, /var) intbyte = 1 ::start:: ! 1 + 495 = 496, але затискаємо в [12, 142] intbyte + (495)&min(12)&max(142) /display(intbyte)
llvm.umax + llvm.umin — нативні SIMD-інструкції без розгалужень.
i8, i16...) — без розширення до i64. uadd.sat / usub.sat + umax / umin. Zero branches, runtime overflow неможливий.
Якщо змінна оголошується без значення — вона отримує .None..
.None. — постійна властивість оголошення, а не поточне значення.
.None. ніколи не може бути дільником — навіть після присвоєння нового значення.Перевіряється на етапі парсингу → E600 DIVISION_BY_NONE
app (/intbyte, /var) counter ! = .None. (store i8 0) ::start:: counter (18) ! присвоєння — ОК /display(counter) ! виводить 18
.None. в пам'яті — store i8 0. Display показує 0 до присвоєння.
app (/intbyte, /var) x = 84 app (/intbyte, /var) divisor ! = .None. ::start:: divisor (18) ! присвоєння — ОК x / (divisor) ! .None. назавжди → E600
Вивід значення змінної. Детальна документація — в окремому розділі Display.
app (/intbyte, /var) intbyte = 12 ::start:: /display(intbyte(F, O, B))
Живі приклади з тестового пакету. Повна таблиця — у розділі Коди помилок.
app (/intbyte) CaseA = 12 ! немає /var або /const
app (/var, /intbyte) CaseB = 12 ! /var перед типом
(/intbyte, /var)
app (/intbyte, /const) CaseE ! константа без = значення
app (/intbyte, /var) APP = 14 ! APP — зарезервоване