01 · Арифметичні оператори #arithmetic
+
Додавання
-
Віднімання
*
Множення
/
Ділення
^
Степінь
Дужки — це ланцюг над лівим операндом: x + (5) — взяти x, виконати + 5, результат назад у x. Операції всередині дужок продовжують ланцюг зліва направо — лівий операнд завжди x.
Ланцюг у дужках
приклад
app (/intbyte, /var) x = 12

::start::
x + (5 * 5 + 4)
! x+5=17 → 17*5=85 → 85+4=89
/display(x)
output89
Дужки не ізолюють підвираз — вони продовжують ланцюг операцій над x.
Вкладені дужки
приклад
app (/intbyte, /var) x = 12

::start::
x + (5 * (5 + 4))
! (5+4)=9 спочатку → x+5=17 → 17*9=153
/display(x)
output153
Внутрішні дужки рахуються першими — потім включаються в ланцюг.
Вкладені дужки ✓ test B
math_test_B_double_nested.terra
app (/intbyte, /var) x = 2

::start::
x + ((3 * (2 + 2)) * 2 + 1)
! парсер: (2+2)=4 → (3*4)=12
! ланцюг: x+12=14 → 14*2=28 → 28+1=29
/display(x)
output29
Парсер згортає від найглибшого рівня. Кодген отримує спрощений ланцюг.
Ланцюг з константами — SSA захищає ✓ test C
math_test_C_llvm_trap.terra
app (/intbyte, /var) x = 1

::start::
x + (2 * 3 + 10 * 2)
! ланцюг: x+2=3 → 3*3=9 → 9+10=19 → 19*2=38
! НЕ математика: 2*3+10*2=26, x+26=27
/display(x)
output38
SSA-ланцюг: кожен %tN залежить від попереднього. LLVM не може переоптимізувати.
Інлайн перерахунок змінної
приклад
app (/intbyte, /var) x = 12

::start::
x (x + (5 * 2))
! 5*2=10 → 12+10=22 → x = 22 (старе 12 затирається)
/display(x)
output22
x як початковий операнд нового ланцюга. Результат замінює старе значення x.
x + 5 поза функцією — паніка ✗ E100
приклад
app (/intbyte, /var) x = 12

::start::
x + 5
! Немає акумулятора @. Немає виділеного регістру.
! Memory layout x не передбачає куди писати.
! Паніка парсера — не runtime.
error E100 · Очікувалась '(' після оператора
Всередині функції x + 5 легально — @ вже виділений. В ::start:: без функції — немає куди писати.
Стандартне переповнення — wrap: для /intbyte: 255 + 1 = 0. Для контролю — &-модифікатори.
02 · &-модифікатори #amp-modifiers

&-модифікатори — це окрема категорія синтаксису Terra. Ключова відмінність від звичайних умов: вони описують правило конкретної операції, а не стан змінної. Компілятор перетворює їх у нативні LLVM-інструкції без жодних умовних переходів у runtime.

Кільце vs відрізок: Без модифікатора /intbyte — кільце від 0 до 255: 255+1=0, 0-1=255.
&-модифікатор перетворює кільце у відрізок з двома стелями — вийти за межі неможливо.
Маска на кожен крок ланцюга: Модифікатор застосовується після кожної операції в ланцюгу, не тільки до фінального результату.
x + (a * 76 - 12 + 7)&max(212) — кожен проміжний результат затискається в [0..212].
Compile-time гарантія: Компілюється у llvm.uadd.sat / llvm.usub.sat (насичення) + llvm.umax / llvm.umin (затискання).
Все в рідному типі (i8, i16...) — без розширення до i64. Zero branches, zero overhead.
&st
saturation — насичення до межі типу
Операції:
+ - * /

Насичення до максимуму типу. Для /intbyte: результат > 255 стає 255.
Може використовуватись самостійно або разом з &min.

✓ basics_test
basics_test.terra
app (/intbyte, /var) x = 1

::start::
x + (300)&st   ! 1+300=301 → 255
/display(x)
output255
llvm IR: call i8 @llvm.uadd.sat.i8(i8 %x, i8 %val)
&max(N)
верхня стеля результату
Операції:
+ - * /

Якщо результат > N — він стає N.
Неявно включає насичення — переповнення неможливе до застосування межі.
Може використовуватись без &min.

✓ clamp_sat_test
clamp_sat_test.terra
app (/intbyte, /var) x = 12

::start::
x + (200)&max(150)   ! sat(12+200)=212 → umin(212,150)=150
/display(x)
output150
llvm IR: call i8 @llvm.uadd.sat.i8call i8 @llvm.umin.i8(i8 %sat, i8 150)
&min(N)
нижня стеля результату
Операції:
+ - * /

Якщо результат < N — він стає N.
Неявно включає насичення знизу.
Може використовуватись без &max.

✓ clamp_sat_test
clamp_sat_test.terra
app (/intbyte, /var) x = 12

::start::
x - (200)&min(10)   ! sat(12-200)=0 → umax(0,10)=10
/display(x)
output10
llvm IR: call i8 @llvm.usub.sat.i8call i8 @llvm.umax.i8(i8 %sat, i8 10)
&min(A)&max(B)
відрізок [A, B] — обидві стелі
Операції:
+ - * /

Повний відрізок — результат завжди в [A, B].
Еквівалентний синтаксис: &min&max(A, B)
Маска застосовується до кожного кроку ланцюга.

✓ clamp_sat_test
clamp_sat_test.terra
app (/intbyte, /var) x = 12

::start::
! sat(12+50)=62 → umax(62,10)=62 → umin(62,100)=62
x + (50)&min(10)&max(100)
/display(x)

! Еквівалентний запис:
! x + (50)&min&max(10, 100)
output62
llvm IR: uadd.sat.i8umax.i8(_, 10)umin.i8(_, 100) — все в i8
03 · <<! — обнулення #reset-op

Оператор <<! скидає змінну до нуля. Працює тільки з беззнаковими типами — для знакових типів виникає помилка парсера.

беззнаковий
приклад
app (/intbyte, /var) x = 200

::start::
<<! (x)          ! x стає 0
/display(x)
output0
знаковий — помилка
приклад
app (/intbyte-, /var) y = 100

::start::
<<! (y)   ! помилка: знаковий тип
error Оператор <<! працює тільки з беззнаковими типами
04 · Числові літерали #prefixes

Terra підтримує числа в різних системах числення прямо в коді. Компілятор перетворює їх у десяткові значення на етапі лексингу — жодних runtime перетворень.

Префікс База Приклад Десяткове значення
0b двійкова (2) 0b1100 = 12
0o вісімкова (8) 0o14 = 12
0x шістнадцяткова (16) 0xC = 12
(без префіксу) десяткова (10) 12 = 12
всі чотири записи еквівалентні
приклад
app (/intbyte, /const) a = 12
app (/intbyte, /const) b = 0b1100
app (/intbyte, /const) c = 0o14
app (/intbyte, /const) d = 0xC

! a == b == c == d == 12
05 · Математичні функції #precomp

Математичні функції Terra — /sum, /sqrt, /median, /min, /max — окрема категорія синтаксису.
Більшість обробляється парсером до LLVM IR і компілюється у звичайну константу.

Повна документація — ∑ Математичні функції