Перейти к содержанию

Выражения и типы

Приоритет операторов (от низшего)

  1. Тернарник cond ? a : b
  2. or, ||
  3. and, &&
  4. Сравнения == != < > <= >= contains is (is = ==)
  5. Сложение + - и конкатенация <<< >>>
  6. Умножение * / % (деление на ноль — ошибка, а не NaN)
  7. Унарные - ! not ++ --
  8. Постфикс: .свойство, [ключ], x++ / x--
  9. Первичные: литералы, переменные, f(...), ( ... )

+ — это и сложение, и конкатенация: если хоть один операнд текст — результат текст ("n: " + 5 → "n: 5"). and/or — с коротким замыканием.

Сравнения и членство

if n < 2:
    return n
if box contains "sword":
    message "Armed!"
if victim is null:
    stop

contains работает для списков (через looseEquals), мап (ключ) и текста (подстрока). Числа сравниваются численно, всё остальное — как текст.

Вызовы, свойства, индексы

let victim = player(target)   # вызов функции/builtin
message victim.name           # свойство игрока
message box[0]                # индекс списка/мапы/строки

Цепочки комбинируются: player(target).health, args[0]. Неизвестная функция — ошибка компиляции unknown function '...'.

Приведение типов

Значения — обычные JDK-типы (Double, String, Boolean, List, Map), при необходимости приводятся:

  • в число: Boolean → 1/0, текст — парсинг (пустой/мусор — ошибка);
  • в логику: Boolean как есть, число — != 0, текст — непустой и не "false";
  • в текст: null → "", целые double — без .0 (5, а не 5.0), списки — [a, b].

Как работает вывод типов (для любопытных)

Compiler.kindOf доверяет только надёжным листьям: литералам, локалам с непротиворечивым Storage.kind и вызовам с известной сигнатурой.

  • number + number → примитивные DADD/DCMPL, без боксинга;
  • text + text в сравнениях → String.equals/concat;
  • остальное боксится сразу после вычисления операнда и уходит в Values.*;
  • + с неизвестным операндом даёт kind ANY (не NUMBER), иначе цепочка a + b + "x" потеряла бы текстовость;
  • бокс — ровно в одном месте: повторный бокс уже-объекта запрещён (проверяется фактически произведённое представление), иначе VerifyError;
  • конструкторы в генерируемом коде — только INVOKESPECIAL.